[
  {
    "path": ".dockerignore",
    "content": "*\n!*.go\n!pkg\n!go.mod\n!go.sum\n!Makefile\n!po\n!doc\n!completions\n"
  },
  {
    "path": ".github/CODEOWNERS",
    "content": "*       @Jguer\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "github: [Jguer]\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Report a malfunction to help us improve\ntitle: \"\"\nlabels: \"Status: Triage, Type: Bug\"\nassignees: \"\"\n---\n\n### Affected Version\n\n<!-- Please ensure you are using the latest yay-git package\nUse `yay -V` to get installed version\nExample: `yay v8.1139.r0.g9ac4ab6 - libalpm v11.0.1` -->\n\n### Describe the bug\n\n<!-- A clear and concise description of the bug. -->\n\n### Reproduction Steps\n\n1.\n2.\n3.\n\n### Expected behavior\n\n<!-- A clear and concise description of what you expected to happen. -->\n\n### Output\n\n<!--\nInclude the FULL output of any relevant commands/configs\nThe current yay config can be printed with `yay -Pg`\nPaste services are only needed for excessive output (>500 lines)\nUse --debug to add pacman and yay debug logs \nor add the following key to your ~/.config/yay/config.json to only get yay debug logs\n{\n  \"debug\": true\n}\n-->\n\n```sh\n\n```\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: \"\"\nlabels: \"Type: Feature Request, Status: Discussion Open\"\nassignees: \"\"\n---\n\n### Is your feature request related to a problem? Please describe.\n\n<!-- A clear and concise description of the problem, e.g. I'm always frustrated when ... -->\n\n### Describe the solution you'd like\n\n<!-- A clear and concise description of what you want to happen. -->\n\n### Describe alternatives you've considered\n\n<!-- A clear and concise description of any alternative solutions or features you've considered. -->\n\n### Additional context\n\n<!-- Add any other context or screenshots about the feature request here. -->\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "# To get started with Dependabot version updates, you'll need to specify which\n# package ecosystems to update and where the package manifests are located.\n# Please see the documentation for all configuration options:\n# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file\n\nversion: 2\nupdates:\n  - package-ecosystem: \"gomod\" # See documentation for possible values\n    directory: \"/\" # Location of package manifests\n    schedule:\n      interval: \"weekly\"\n    groups:\n      go-all:\n        patterns:\n          - '*'\n"
  },
  {
    "path": ".github/workflows/builder-image.yml",
    "content": "name: Builder Image\n\non:\n  schedule:\n    - cron: \"0 3 * * 1\"  # Every Monday at 3 AM\n  push:\n    paths:\n      - \"ci.Dockerfile\"\n      - \".github/workflows/builder-image.yml\"\n\nenv:\n  REGISTRY_IMAGE: jguer/yay-builder\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        platform:\n          - linux/amd64\n          - linux/arm/v7\n          - linux/arm64\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v4\n\n      - name: Set up QEMU\n        uses: docker/setup-qemu-action@v3\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n\n      - name: Login to GitHub Container Registry\n        uses: docker/login-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ github.repository_owner }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Extract metadata for Docker\n        id: meta\n        uses: docker/metadata-action@v5\n        with:\n          images: |\n            ghcr.io/${{ env.REGISTRY_IMAGE }}\n          tags: |\n            type=raw,value=latest\n            type=sha,format=long\n\n      - name: Build and push by digest\n        id: build\n        uses: docker/build-push-action@v5\n        with:\n          context: .\n          file: ci.Dockerfile\n          platforms: ${{ matrix.platform }}\n          labels: ${{ steps.meta.outputs.labels }}\n          outputs: type=image,name=ghcr.io/${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true\n\n      - name: Export digest\n        run: |\n          mkdir -p /tmp/digests\n          digest=\"${{ steps.build.outputs.digest }}\"\n          echo -n \"$digest\" > \"/tmp/digests/$(echo \"${{ matrix.platform }}\" | tr '/' '_')\"\n\n      - name: Upload digest\n        uses: actions/upload-artifact@v4\n        with:\n          name: digest-${{ matrix.platform == 'linux/amd64' && 'amd64' || matrix.platform == 'linux/arm/v7' && 'armv7' || 'arm64' }}\n          path: /tmp/digests/*\n          if-no-files-found: error\n          retention-days: 1\n\n  merge:\n    needs: [build]\n    runs-on: ubuntu-latest\n    steps:\n      - name: Download digests\n        uses: actions/download-artifact@v4\n        with:\n          pattern: digest-*\n          merge-multiple: true\n          path: /tmp/digests\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n\n      - name: Login to GitHub Container Registry\n        uses: docker/login-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ github.repository_owner }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Extract metadata for Docker\n        id: meta\n        uses: docker/metadata-action@v5\n        with:\n          images: |\n            ghcr.io/${{ env.REGISTRY_IMAGE }}\n          tags: |\n            type=raw,value=latest\n            type=sha,format=short\n\n      - name: Create and push manifest list\n        env:\n          DOCKER_CLI_EXPERIMENTAL: enabled\n        run: |\n          # Extract GitHub Container Registry tags\n          GHCR_TAGS=$(echo '${{ steps.meta.outputs.tags }}' | xargs -I {} echo \"-t {}\")\n          \n          # Create a manifest list using the image digests from /tmp/digests/*\n          DIGESTS=$(for file in /tmp/digests/*; do\n            echo -n \"ghcr.io/${{ env.REGISTRY_IMAGE }}@$(cat $file) \"\n          done)\n          \n          # Create the manifest list for GitHub Container Registry\n          docker buildx imagetools create $GHCR_TAGS $DIGESTS\n\n      - name: Inspect image\n        run: |\n          docker buildx imagetools inspect ghcr.io/${{ env.REGISTRY_IMAGE }}:latest"
  },
  {
    "path": ".github/workflows/multiarch-build.yml",
    "content": "name: Build Release\n\non:\n  push:\n    tags:\n      - v*\n\njobs:\n  build-releases:\n    strategy:\n      matrix:\n        arch: [\"linux/amd64 x86_64\", \"linux/arm/v7 armv7h\", \"linux/arm64 aarch64\"]\n    name: Build ${{ matrix.arch }}\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n\n      - name: Set up QEMU\n        uses: docker/setup-qemu-action@v3\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n\n      - name: Login to Docker Hub\n        uses: docker/login-action@v3\n        with:\n          username: ${{ secrets.DOCKERHUB_USERNAME }}\n          password: ${{ secrets.DOCKERHUB_TOKEN }}\n\n      - name: Read info\n        id: tags\n        run: |\n          echo \"VERSION=${GITHUB_REF#refs/tags/v}\" >> $GITHUB_OUTPUT\n          echo \"TAG=${GITHUB_REF#refs/tags/}\" >> $GITHUB_OUTPUT\n          arch=\"${{ matrix.arch }}\"\n          echo \"PLATFORM=${arch%% *}\" >> $GITHUB_OUTPUT\n          echo \"ARCH=${arch##* }\" >> $GITHUB_OUTPUT\n\n      - name: Build ${{ matrix.arch }} release\n        run: |\n          mkdir artifacts\n          docker buildx build --platform ${{ steps.tags.outputs.platform }} \\\n            --build-arg VERSION=${{ steps.tags.outputs.version }} \\\n            --build-arg ARCH=${{ steps.tags.outputs.arch }} \\\n            --build-arg PREFIX=\"/usr\" \\\n            -t yay:${{ steps.tags.outputs.arch }} . --load\n          make docker-release ARCH=${{ steps.tags.outputs.arch }} VERSION=${{ steps.tags.outputs.version }} PREFIX=\"/usr\"\n          mv *.tar.gz artifacts\n\n      - uses: actions/upload-artifact@v4\n        with:\n          name: yay_${{ steps.tags.outputs.arch }}\n          path: artifacts\n\n  create_release:\n    name: Create release from this build\n    needs: [build-releases]\n    runs-on: ubuntu-latest\n    permissions:\n      contents: write\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n\n      - name: Read info\n        id: tags\n        run: |\n          echo \"VERSION=${GITHUB_REF#refs/tags/v}\" >> $GITHUB_OUTPUT\n          echo \"TAG=${GITHUB_REF#refs/tags/}\" >> $GITHUB_OUTPUT\n\n      - uses: actions/download-artifact@v4\n        with:\n          pattern: yay_*\n          merge-multiple: true\n\n      - name: Create Release\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        run: |\n          gh release create ${{ steps.tags.outputs.tag }} \\\n            --title \"${{ steps.tags.outputs.tag }}\" \\\n            --generate-notes \\\n            ./yay_${{ steps.tags.outputs.version }}_*.tar.gz\n\n      - name: Release Notary Action\n        uses: docker://aevea/release-notary:latest\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}"
  },
  {
    "path": ".github/workflows/testing-git.yml",
    "content": "name: Test against pacman-git\non:\n  pull_request:\n    paths-ignore:\n      - \"doc/**\"\n      - \"**/*.po\"\n      - \"README.md\"\n      - \".gitignore\"\n\njobs:\n  build:\n    name: Lint and test yay (-git)\n    runs-on: ubuntu-latest\n    container:\n      image: ghcr.io/jguer/yay-builder:latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/cache@v3\n        with:\n          path: ~/go/pkg/mod\n          key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}\n          restore-keys: |\n            ${{ runner.os }}-go-\n      - uses: actions/cache@v3\n        with:\n          path: /home/runner/work/yay/yay/pacman-git\n          key: ${{ runner.os }}-pacman-${{ hashFiles('/home/runner/work/yay/yay/pacman-git/PKGBUILD') }}\n          restore-keys: |\n            ${{ runner.os }}-pacman-\n      - name: checkout pacman-git\n        run: |\n          git -C ./pacman-git pull || git clone https://aur.archlinux.org/pacman-git\n          useradd github\n          echo 'github ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers\n          chmod -R 777 pacman-git\n          su github -c 'cd pacman-git; yes | makepkg -si --nocheck'\n      - name: Run Build and Tests with pacman-git\n        run: |\n          make test\n"
  },
  {
    "path": ".github/workflows/testing.yml",
    "content": "name: Test against pacman\non:\n  pull_request:\n\njobs:\n  build:\n    name: Lint and test yay\n    runs-on: ubuntu-latest\n    container:\n      image: ghcr.io/jguer/yay-builder:latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/cache@v3\n        with:\n          path: ~/go/pkg/mod\n          key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}\n          restore-keys: |\n            ${{ runner.os }}-go-\n      - name: Lint\n        env:\n          GOFLAGS: -buildvcs=false -tags=next\n        run: /app/bin/golangci-lint run -v ./...\n      - name: Run Build and Tests\n        run: make test\n\n      - name: Run Integration Tests\n        continue-on-error: true\n        run: |\n          useradd -m yay &&\n          chown -R yay:yay . &&\n          cp -r ~/go/ /home/yay/go/ &&\n          chown -R yay:yay /home/yay/go/ &&\n            su yay -c \"make test-integration\"\n      - name: Build yay Artifact\n        env:\n          GOFLAGS: -buildvcs=false -tags=next\n        run: make\n      - name: Upload yay Artifact\n        uses: actions/upload-artifact@v4\n        with:\n          name: yay\n          path: ./yay\n          if-no-files-found: error\n          overwrite: true"
  },
  {
    "path": ".gitignore",
    "content": "# Compiled Object files, Static and Dynamic libs (Shared Objects)\n*.o\n*.a\n*.so\n\n# Folders\n_obj\n_test\n.vscode\n\n*.cgo1.go\n*.cgo2.c\n_cgo_defun.c\n_cgo_gotypes.go\n_cgo_export.*\n\n*.exe\n*.test\n*.prof\nyay\nyay_*/\n*.tar.gz\nqemu-*\n.go\n\n# Locale\n*.mo\n*.pot\n*.po~\n*.pprof\n\nnode_modules/\nxgotext\n.devcontainer/"
  },
  {
    "path": ".golangci.yml",
    "content": "version: \"2\"\nrun:\n  go: \"1.26\"\nlinters:\n  default: none\n  enable:\n    - bodyclose\n    - dogsled\n    - dupl\n    - errcheck\n    - errorlint\n    - gochecknoinits\n    - gocritic\n    - goprintffuncname\n    - gosec\n    - govet\n    - ineffassign\n    - lll\n    - misspell\n    - nakedret\n    - noctx\n    - nolintlint\n    - staticcheck\n    - unconvert\n    - unparam\n    - unused\n    - whitespace\n  settings:\n    dupl:\n      threshold: 100\n    funlen:\n      lines: 100\n      statements: 50\n    goconst:\n      min-len: 3\n      min-occurrences: 4\n    gocritic:\n      enabled-tags:\n        - diagnostic\n        - experimental\n        - opinionated\n        - performance\n        - style\n    gocyclo:\n      min-complexity: 15\n    lll:\n      line-length: 140\n    misspell:\n      locale: US\n    nolintlint:\n      require-explanation: false\n      require-specific: false\n      allow-unused: false\n  exclusions:\n    generated: lax\n    presets:\n      - comments\n      - common-false-positives\n      - legacy\n      - std-error-handling\n    rules:\n      - linters:\n          - dupl\n          - errcheck\n          - errorlint\n          - gochecknoinits\n          - gocritic\n          - godot\n          - gosec\n          - govet\n          - lll\n          - revive\n          - staticcheck\n          - wsl\n        path: (.+)_test.go\n      - path: (.+)\\.go$\n        text: G204\n      - path: (.+)\\.go$\n        text: G115\n      - path: (.+)\\.go$\n        text: G703\n      - path: (.+)\\.go$\n        text: G705\n      - path: (.+)\\.go$\n        text: QF1012\n    paths:\n      - third_party$\n      - builtin$\n      - examples$\nformatters:\n  enable:\n    - gofmt\n    - goimports\n  settings:\n    goimports:\n      local-prefixes:\n        - github.com/Jguer/yay/v12\n  exclusions:\n    generated: lax\n    paths:\n      - third_party$\n      - builtin$\n      - examples$\n"
  },
  {
    "path": ".pre-commit-config.yaml",
    "content": "default_stages: [commit]\n\nrepos:\n  - repo: https://github.com/dnephin/pre-commit-golang\n    rev: v0.5.1\n    hooks:\n      - id: go-fmt\n      - id: golangci-lint\n      - id: go-unit-tests\n      - id: go-build\n\n  - repo: https://github.com/pre-commit/mirrors-prettier\n    rev: v4.0.0-alpha.8 # Use the sha or tag you want to point at\n    hooks:\n      - id: prettier\n\n  - repo: https://github.com/pre-commit/pre-commit-hooks\n    rev: v4.5.0 # Use the ref you want to point at\n    hooks:\n      - id: trailing-whitespace\n      - id: check-json\n      - id: check-yaml\n      - id: check-added-large-files\n\n  - repo: https://github.com/commitizen-tools/commitizen\n    rev: v3.15.0\n    hooks:\n      - id: commitizen\n        stages: [commit-msg]\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to yay\n\n## Translation\n\n[Transifex](https://www.transifex.com/yay-1/yay/)\n\n## Quality Assurance\n\n```sh\npacman -S --needed git base-devel\ngit clone https://aur.archlinux.org/yay-git.git\ncd yay-git\nmakepkg -si\n```\n\nInstalling `yay-git` and using issues to help determine what's broken is already\na very big help.\n\n## Development\n\nContributors are always welcome!\n\nIf you plan to make any large changes or changes that may not be 100% agreed\non, we suggest opening an issue detailing your ideas first.\n\nOtherwise send us a pull request and we will be happy to review it.\n\n### Vision\n\nYay is based on the design of [yaourt](https://github.com/archlinuxfr/yaourt), [apacman](https://github.com/oshazard/apacman) and [pacaur](https://github.com/rmarquis/pacaur). It is developed with these objectives in mind:\n\n- Provide an interface for pacman\n- Yaourt-style interactive search/install\n- Minimal dependencies\n- Minimize user input\n\n### Dependencies\n\nYay depends on:\n\n- go (make only)\n- git\n- base-devel\n- pacman\n\nNote: Yay also depends on a few other projects, these are pulled as go modules.\n\n### Building\n\nRun `make` to build Yay. This command will generate a binary called `yay` in\nthe same directory as the Makefile.\n\n#### Docker Release\n\n`make docker-release` will build the release packages for `aarch64` and for `x86_64`.\n\nFor `aarch64` to run on a `x86_64` platform `qemu-user-static(-bin)` must be\ninstalled.\n\n```\ndocker run --rm --privileged multiarch/qemu-user-static:register --reset\n```\n\nwill register QEMU in the build agent. ARM builds tend to crash sometimes but\nrepeated runs tend to succeed.\n\n### Code Style\n\nAll code should be formatted through `go fmt`. This tool will automatically\nformat code for you. We recommend, however, that you write code in the proper\nstyle and use `go fmt` only to catch mistakes.\n\nUse [pre-commit](https://pre-commit.com/) to validate your commits against the various\nlinters configured for this repository.\n\n### Testing\n\nRun `make test` to test Yay. This command will verify that the code is\nformatted correctly, run the code through `go vet`, and run unit tests.\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM ghcr.io/jguer/yay-builder:latest\nLABEL maintainer=\"Jguer,docker@jguer.space\"\n\nARG VERSION\nARG PREFIX\nARG ARCH\n\nWORKDIR /app\n\nCOPY . .\n\nRUN pacman -Syu --overwrite=* --noconfirm\n\nRUN make release VERSION=${VERSION} PREFIX=${PREFIX} ARCH=${ARCH}"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    {one line to give the program's name and a brief idea of what it does.}\n    Copyright (C) {year}  {name of author}\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    {project}  Copyright (C) {year}  {fullname}\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n"
  },
  {
    "path": "Makefile",
    "content": "export GO111MODULE=on\nGOPROXY ?= https://proxy.golang.org,direct\nexport GOPROXY\n\nBUILD_TAG = devel\nARCH ?= $(shell uname -m)\nBIN := yay\nDESTDIR :=\nGO ?= go\nPKGNAME := yay\nPREFIX := /usr/local\n\nMAJORVERSION := 13\nMINORVERSION := 0\nPATCHVERSION := 0\nVERSION ?= ${MAJORVERSION}.${MINORVERSION}.${PATCHVERSION}\n\nLOCALEDIR := po\nSYSTEMLOCALEPATH := $(PREFIX)/share/locale/\n\n# ls -1 po | sed -e 's/\\.po$//' | paste -sd \" \"\nLANGS := ca cs de en es eu fr_FR he hu id it_IT ja ko nl pl_PL pt_BR pt ru_RU ru sk sv tr uk vi vi_VN zh_CN zh_TW\nPOTFILE := default.pot\nPOFILES := $(addprefix $(LOCALEDIR)/,$(addsuffix .po,$(LANGS)))\nMOFILES := $(POFILES:.po=.mo)\n\nFLAGS ?= -trimpath -mod=readonly -modcacherw\nEXTRA_FLAGS ?= -buildmode=pie\nLDFLAGS := -X \"main.yayVersion=${VERSION}\" -X \"main.localePath=${SYSTEMLOCALEPATH}\" -linkmode=external -compressdwarf=false\n\nRELEASE_DIR := ${PKGNAME}_${VERSION}_${ARCH}\nPACKAGE := $(RELEASE_DIR).tar.gz\nSOURCES ?= $(shell find . -name \"*.go\" -type f)\n\n.PRECIOUS: ${LOCALEDIR}/%.po\n\n.PHONY: default\ndefault: build\n\n.PHONY: all\nall: | clean release\n\n.PHONY: clean\nclean:\n\t$(GO) clean $(FLAGS) -i ./...\n\trm -rf $(BIN) $(PKGNAME)_*\n\n.PHONY: test_lint\ntest_lint: test lint\n\n.PHONY: test\ntest:\n\t$(GO) test -race -covermode=atomic $(FLAGS) ./...\n\n.PHONY: test-integration\ntest-integration:\n\t$(GO) test -tags=integration $(FLAGS) ./...\n\n.PHONY: build\nbuild: $(BIN)\n\n.PHONY: release\nrelease: $(PACKAGE)\n\n.PHONY: docker-release-all\ndocker-release-all:\n\tmake docker-release-armv7h ARCH=armv7h\n\tmake docker-release-x86_64 ARCH=x86_64\n\tmake docker-release-aarch64 ARCH=aarch64\n\ndocker-release:\n\tdocker create --name yay-$(ARCH) yay:${ARCH} /bin/sh\n\tdocker cp yay-$(ARCH):/app/${PACKAGE} $(PACKAGE)\n\tdocker container rm yay-$(ARCH)\n\n.PHONY: docker-build\ndocker-build:\n\tdocker build -t yay-$(ARCH):${VERSION} .\n\tdocker run -e=\"ARCH=$(ARCH)\" --name yay-$(ARCH) yay-$(ARCH):${VERSION} make build VERSION=${VERSION} PREFIX=${PREFIX}\n\tdocker cp yay-$(ARCH):/app/${BIN} $(BIN)\n\tdocker container rm yay-$(ARCH)\n\n.PHONY: lint\nlint:\n\tGOFLAGS=\"$(FLAGS)\" golangci-lint run ./...\n\n.PHONY: fmt\nfmt:\n\tgo fmt ./...\n\n.PHONY: install\ninstall: build ${MOFILES}\n\tinstall -Dm755 ${BIN} $(DESTDIR)$(PREFIX)/bin/${BIN}\n\tinstall -Dm644 doc/${PKGNAME}.8 $(DESTDIR)$(PREFIX)/share/man/man8/${PKGNAME}.8\n\tinstall -Dm644 completions/bash $(DESTDIR)$(PREFIX)/share/bash-completion/completions/${PKGNAME}\n\tinstall -Dm644 completions/zsh $(DESTDIR)$(PREFIX)/share/zsh/site-functions/_${PKGNAME}\n\tinstall -Dm644 completions/fish $(DESTDIR)$(PREFIX)/share/fish/vendor_completions.d/${PKGNAME}.fish\n\tfor lang in ${LANGS}; do \\\n\t\tinstall -Dm644 ${LOCALEDIR}/$${lang}.mo $(DESTDIR)$(PREFIX)/share/locale/$$lang/LC_MESSAGES/${PKGNAME}.mo; \\\n\tdone\n\n.PHONY: uninstall\nuninstall:\n\trm -f $(DESTDIR)$(PREFIX)/bin/${BIN}\n\trm -f $(DESTDIR)$(PREFIX)/share/man/man8/${PKGNAME}.8\n\trm -f $(DESTDIR)$(PREFIX)/share/bash-completion/completions/${PKGNAME}\n\trm -f $(DESTDIR)$(PREFIX)/share/zsh/site-functions/_${PKGNAME}\n\trm -f $(DESTDIR)$(PREFIX)/share/fish/vendor_completions.d/${PKGNAME}.fish\n\tfor lang in ${LANGS}; do \\\n\t\trm -f $(DESTDIR)$(PREFIX)/share/locale/$$lang/LC_MESSAGES/${PKGNAME}.mo; \\\n\tdone\n\n$(BIN): $(SOURCES)\n\t$(GO) build $(FLAGS) -ldflags '$(LDFLAGS)' $(EXTRA_FLAGS) -o $@\n\n$(RELEASE_DIR):\n\tmkdir $(RELEASE_DIR)\n\n$(PACKAGE): $(BIN) $(RELEASE_DIR) ${MOFILES}\n\tstrip ${BIN}\n\tcp -t $(RELEASE_DIR) ${BIN} doc/${PKGNAME}.8 completions/* ${MOFILES}\n\ttar -czvf $(PACKAGE) $(RELEASE_DIR)\n\nlocale:\n\txgotext -in . -out po\n\tmv po/default.pot po/en.po\n\tfor lang in ${LANGS}; do \\\n\t\ttest -f po/$$lang.po || msginit --no-translator -l po/$$lang.po -i po/${POTFILE} -o po/$$lang.po; \\\n\t\tmsgmerge -U po/$$lang.po po/${POTFILE}; \\\n\t\ttouch po/$$lang.po; \\\n\tdone\n\n${LOCALEDIR}/%.mo: ${LOCALEDIR}/%.po\n\tmsgfmt -o $@ $<\n"
  },
  {
    "path": "README.md",
    "content": "[![yay](https://img.shields.io/aur/version/yay?color=1793d1&label=yay&logo=arch-linux&style=for-the-badge)](https://aur.archlinux.org/packages/yay/)\n[![yay-bin](https://img.shields.io/aur/version/yay-bin?color=1793d1&label=yay-bin&logo=arch-linux&style=for-the-badge)](https://aur.archlinux.org/packages/yay-bin/)\n[![yay-git](https://img.shields.io/aur/version/yay-git?color=1793d1&label=yay-git&logo=arch-linux&style=for-the-badge)](https://aur.archlinux.org/packages/yay-git/)\n![AUR votes](https://img.shields.io/aur/votes/yay?color=333333&style=for-the-badge)\n[![GitHub license](https://img.shields.io/github/license/jguer/yay?color=333333&style=for-the-badge)](https://github.com/Jguer/yay/blob/master/LICENSE)\n\n# yay\n\nYet Another Yogurt - An AUR Helper Written in Go\n\n### Help translate yay: [Transifex](https://app.transifex.com/yay-1/yay/)\n\n## Features\n\n- Advanced dependency solving\n- PKGBUILD downloading from ABS or AUR\n- Completions for AUR packages\n- Query user up-front for all input (prior to starting builds)\n- Narrow search (`yay linux header` will first search `linux` and then narrow on `header`)\n- Find matching package providers during search and allow selection\n- Remove make dependencies at the end of the build process\n- Build local PKGBUILDs with AUR dependencies\n- Un/Vote for packages\n\n[![asciicast](https://asciinema.org/a/399431.svg)](https://asciinema.org/a/399431)\n\n[![asciicast](https://asciinema.org/a/399433.svg)](https://asciinema.org/a/399433)\n\n## Installation\n\nIf you are migrating from another AUR helper, you can simply install yay with that helper.\n\n> [!WARNING]  \n> We are using `sudo` in these examples. You can switch that out for a different privilege escalation tool.\n\n### Source\n\nThe initial installation of yay can be done by cloning the PKGBUILD and\nbuilding with makepkg:\n\nWe make sure we have the `base-devel` package group installed.\n\n```sh\nsudo pacman -S --needed git base-devel\ngit clone https://aur.archlinux.org/yay.git\ncd yay\nmakepkg -si\n```\n\nIf you want to do all of this at once, we can chain the commands like so:\n\n```sh\nsudo pacman -S --needed git base-devel && git clone https://aur.archlinux.org/yay.git && cd yay && makepkg -si\n```\n\n### Binary\n\nIf you do not want to compile yay yourself you can use the builds generated by\nGitHub Actions.\n\n```sh\nsudo pacman -S --needed git base-devel\ngit clone https://aur.archlinux.org/yay-bin.git\ncd yay-bin\nmakepkg -si\n```\n\nIf you want to do all of this at once, we can chain the commands like so:\n\n```sh\nsudo pacman -S --needed git base-devel && git clone https://aur.archlinux.org/yay-bin.git && cd yay-bin && makepkg -si\n```\n\n### Other distributions\n\nIf you're using Manjaro or [another distribution that packages `yay`](https://repology.org/project/yay/versions)\nyou can simply install yay using pacman (as root):\n\n```sh\npacman -S --needed git base-devel yay\n```\n> [!WARNING]\n> distributions sometimes lag updating yay on their repositories.\n\n## First Use\n\n#### Development packages upgrade\n\n- Use `yay -Y --gendb` to generate a development package database for `*-git`\n  packages that were installed without yay.\n  This command should only be run once.\n\n- `yay -Syu --devel` will then check for development package updates\n\n- Use `yay -Y --devel --save` to make development package updates permanently\n  enabled (`yay` and `yay -Syu` will then always check dev packages)\n\n## Examples of Custom Operations\n\n| Command                           | Description                                                                                                |\n| --------------------------------- | ---------------------------------------------------------------------------------------------------------- |\n| `yay`                             | Alias to `yay -Syu`.                                                                                       |\n| `yay <Search Term>`               | Present package-installation selection menu.                                                               |\n| `yay -Bi <dir>`                   | Install dependencies and build a local PKGBUILD.                                                           |\n| `yay -G <AUR Package>`            | Download PKGBUILD from ABS or AUR. (yay v12.0+)                                                            |\n| `yay -Gp <AUR Package>`           | Print to stdout PKGBUILD from ABS or AUR.                                                                  |\n| `yay -Ps`                         | Print system statistics.                                                                                   |\n| `yay -Syu --devel`                | Perform system upgrade, but also check for development package updates.                                    |\n| `yay -Wu <AUR Package>`           | Unvote for package (Requires setting `AUR_USERNAME` and `AUR_PASSWORD` environment variables) (yay v11.3+) |\n| `yay -Wv <AUR Package>`           | Vote for package (Requires setting `AUR_USERNAME` and `AUR_PASSWORD` environment variables). (yay v11.3+)  |\n| `yay -Y --combinedupgrade --save` | Make combined upgrade the default mode.                                                                    |\n| `yay -Y --gendb`                  | Generate development package database used for devel update.                                               |\n| `yay -Yc`                         | Clean unneeded dependencies.                                                                               |\n\n## Frequently Asked Questions\n\n- **yay does not display colored output. How do I fix it?**\n\n  Make sure you have the `Color` option in your `/etc/pacman.conf`\n  (see issue [#123](https://github.com/Jguer/yay/issues/123)).\n\n- **Sometimes diffs are printed to the terminal, and other times they are paged via less. How do I fix this?**\n\n  yay uses `git diff` to display diffs, which by default tells less not to\n  page if the output can fit into one terminal length. This behavior can be\n  overridden by exporting your own flags (`export LESS=SRX`).\n\n- **yay is not asking me to edit PKGBUILDS, and I don't like the diff menu! What can I do?**\n\n  `yay --editmenu --diffmenu=false --save`\n\n- **How can I tell yay to act only on AUR packages, or only on repo packages?**\n\n  `yay -{OPERATION} --aur`\n  `yay -{OPERATION} --repo`\n\n- **A `Flagged Out Of Date AUR Packages` message is displayed. Why doesn't yay update them?**\n\n  This message does not mean that updated AUR packages are available. It means\n  the packages have been flagged out of date on the AUR, but\n  their maintainers have not yet updated the `PKGBUILD`s\n  (see [outdated AUR packages](https://wiki.archlinux.org/index.php/Arch_User_Repository#Foo_in_the_AUR_is_outdated.3B_what_should_I_do.3F)).\n\n- **yay doesn't install dependencies added to a PKGBUILD during installation.**\n\n  yay resolves all dependencies ahead of time. You are free to edit the\n  PKGBUILD in any way, but any problems you cause are your own and should not be\n  reported unless they can be reproduced with the original PKGBUILD.\n\n- **I know my `-git` package has updates but yay doesn't offer to update it**\n\n  yay uses a hash cache for development packages. Normally it is updated at the end of the package install with the message `Found git repo`.\n  If you transition between aur helpers and did not install the devel package using yay at some point, it is possible it never got added to the cache. `yay -Y --gendb` will fix the current version of every devel package and start checking from there.\n\n- **I want to help out!**\n\n  Check [CONTRIBUTING.md](./CONTRIBUTING.md) for more information.\n\n## Support\n\nAll support related to yay should be requested via GitHub issues. Since yay is not\nofficially supported by Arch Linux, support should not be sought out on the\nforums, AUR comments or other official channels.\n\nA broken AUR package should be reported as a comment on the package's AUR page.\nA package may only be considered broken if it fails to build with makepkg.\n\nReports should be made using makepkg and include the full output as well as any\nother relevant information. Never make reports using yay or any other external\ntools.\n\n## Images\n\n<p align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/Jguer/jguer.github.io/refs/heads/master/yay/yay.png\" width=\"42%\">\n  <img src=\"https://raw.githubusercontent.com/Jguer/jguer.github.io/refs/heads/master/yay/yay-s.png\" width=\"42%\">\n</p>\n\n<p align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/Jguer/jguer.github.io/refs/heads/master/yay/yay-y.png\" width=\"42%\">\n  <img src=\"https://raw.githubusercontent.com/Jguer/jguer.github.io/refs/heads/master/yay/yay-ps.png\" width=\"42%\">\n</p>\n\n### Other AUR helpers/tools\n\n- [paru](https://github.com/morganamilo/paru)\n- [aurutils](https://github.com/AladW/aurutils)\n- [pikaur](https://github.com/actionless/pikaur)\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Policy\n\nThank you for helping keep yay secure!\n\n## Supported Versions\n\nWe only provide security updates and support for the latest released version of yay. Please ensure you are using the most up-to-date version before reporting vulnerabilities.\n\n## Reporting a Vulnerability\n\nIf you discover a security vulnerability, please email us at [security@jguer.space](mailto:security@jguer.space). We will respond as quickly as possible and coordinate a fix.\n\nWe appreciate responsible disclosure and your help in making this project safe for everyone. "
  },
  {
    "path": "ci.Dockerfile",
    "content": "FROM quay.io/gmanka/archlinuxarm:base-devel\nLABEL maintainer=\"Jguer,docker@jguer.space\"\n\nENV GO111MODULE=on\nWORKDIR /app\n\nCOPY go.mod .\n\n# asciidoc, doxygen, meson needed for pacman-git\nRUN set -eux; \\\n    pacman-key --init; \\\n    sed -i 's/^#DisableSandboxFilesystem/DisableSandboxFilesystem/' /etc/pacman.conf; \\\n    sed -i 's/^#DisableSandboxSyscalls/DisableSandboxSyscalls/' /etc/pacman.conf; \\\n    pacman -Syu --noconfirm --needed archlinux-keyring pacman go git gcc make base-devel sudo asciidoc doxygen meson; \\\n    curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v2.10.1; \\\n    go mod download; \\\n    rm -rf /var/lib/pacman/sync/* /var/cache/pacman/* /tmp/* /var/tmp/*; \\\n    rm -rf /usr/share/man/* /usr/share/doc/* || true; \\\n    yes | pacman -Scc >/dev/null 2>&1 || true\n"
  },
  {
    "path": "clean.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"github.com/Jguer/aur\"\n\tmapset \"github.com/deckarep/golang-set/v2\"\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n)\n\n// CleanDependencies removes all dangling dependencies in system.\nfunc cleanDependencies(ctx context.Context, cfg *settings.Configuration,\n\tcmdBuilder exe.ICmdBuilder, cmdArgs *parser.Arguments, dbExecutor db.Executor,\n\tremoveOptional bool,\n) error {\n\thanging := hangingPackages(removeOptional, dbExecutor)\n\tif len(hanging) != 0 {\n\t\treturn cleanRemove(ctx, cfg, cmdBuilder, cmdArgs, hanging)\n\t}\n\n\treturn nil\n}\n\n// CleanRemove sends a full removal command to pacman with the pkgName slice.\nfunc cleanRemove(ctx context.Context, cfg *settings.Configuration,\n\tcmdBuilder exe.ICmdBuilder, cmdArgs *parser.Arguments, pkgNames []string,\n) error {\n\tif len(pkgNames) == 0 {\n\t\treturn nil\n\t}\n\n\targuments := cmdArgs.CopyGlobal()\n\tif err := arguments.AddArg(\"R\", \"s\", \"u\"); err != nil {\n\t\treturn err\n\t}\n\targuments.AddTarget(pkgNames...)\n\n\treturn cmdBuilder.Show(\n\t\tcmdBuilder.BuildPacmanCmd(ctx,\n\t\t\targuments, cfg.Mode, settings.NoConfirm))\n}\n\nfunc syncClean(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {\n\tkeepInstalled := false\n\tkeepCurrent := false\n\n\t_, removeAll, _ := cmdArgs.GetArg(\"c\", \"clean\")\n\n\tfor _, v := range run.PacmanConf.CleanMethod {\n\t\tswitch v {\n\t\tcase \"KeepInstalled\":\n\t\t\tkeepInstalled = true\n\t\tcase \"KeepCurrent\":\n\t\t\tkeepCurrent = true\n\t\t}\n\t}\n\n\tif run.Cfg.Mode.AtLeastRepo() {\n\t\tif err := run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,\n\t\t\tcmdArgs, run.Cfg.Mode, settings.NoConfirm)); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif !run.Cfg.Mode.AtLeastAUR() {\n\t\treturn nil\n\t}\n\n\tvar question string\n\tif removeAll {\n\t\tquestion = gotext.Get(\"Do you want to remove ALL AUR packages from cache?\")\n\t} else {\n\t\tquestion = gotext.Get(\"Do you want to remove all other AUR packages from cache?\")\n\t}\n\n\trun.Logger.Println(gotext.Get(\"\\nBuild directory:\"), run.Cfg.BuildDir)\n\n\tif run.Logger.ContinueTask(question, true, settings.NoConfirm) {\n\t\tif err := cleanAUR(ctx, run, keepInstalled, keepCurrent, removeAll, dbExecutor); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif removeAll {\n\t\treturn nil\n\t}\n\n\tif run.Logger.ContinueTask(gotext.Get(\"Do you want to remove ALL untracked AUR files?\"), true, settings.NoConfirm) {\n\t\treturn cleanUntracked(ctx, run)\n\t}\n\n\treturn nil\n}\n\nfunc cleanAUR(ctx context.Context, run *runtime.Runtime,\n\tkeepInstalled, keepCurrent, removeAll bool, dbExecutor db.Executor,\n) error {\n\trun.Logger.Println(gotext.Get(\"removing AUR packages from cache...\"))\n\n\tinstalledBases := mapset.NewThreadUnsafeSet[string]()\n\tinAURBases := mapset.NewThreadUnsafeSet[string]()\n\n\tremotePackages := dbExecutor.InstalledRemotePackages()\n\n\tfiles, err := os.ReadDir(run.Cfg.BuildDir)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tcachedPackages := make([]string, 0, len(files))\n\n\tfor _, file := range files {\n\t\tif !file.IsDir() {\n\t\t\tcontinue\n\t\t}\n\n\t\tcachedPackages = append(cachedPackages, file.Name())\n\t}\n\n\t// Most people probably don't use keep current and that is the only\n\t// case where this is needed.\n\t// Querying the AUR is slow and needs internet so don't do it if we\n\t// don't need to.\n\tif keepCurrent {\n\t\tinfo, errInfo := run.AURClient.Get(ctx, &aur.Query{\n\t\t\tNeedles: cachedPackages,\n\t\t})\n\t\tif errInfo != nil {\n\t\t\treturn errInfo\n\t\t}\n\n\t\tfor i := range info {\n\t\t\tinAURBases.Add(info[i].PackageBase)\n\t\t}\n\t}\n\n\tfor _, pkg := range remotePackages {\n\t\tif pkg.Base() != \"\" {\n\t\t\tinstalledBases.Add(pkg.Base())\n\t\t} else {\n\t\t\tinstalledBases.Add(pkg.Name())\n\t\t}\n\t}\n\n\tfor _, file := range files {\n\t\tif !file.IsDir() {\n\t\t\tcontinue\n\t\t}\n\n\t\tif !removeAll {\n\t\t\tif keepInstalled && installedBases.Contains(file.Name()) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif keepCurrent && inAURBases.Contains(file.Name()) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\tdir := filepath.Join(run.Cfg.BuildDir, file.Name())\n\t\trun.Logger.Debugln(\"removing\", dir)\n\t\tif err = os.RemoveAll(dir); err != nil {\n\t\t\trun.Logger.Warnln(gotext.Get(\"Unable to remove %s: %s\", dir, err))\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc cleanUntracked(ctx context.Context, run *runtime.Runtime) error {\n\trun.Logger.Println(gotext.Get(\"removing untracked AUR files from cache...\"))\n\n\tfiles, err := os.ReadDir(run.Cfg.BuildDir)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, file := range files {\n\t\tif !file.IsDir() {\n\t\t\tcontinue\n\t\t}\n\n\t\tdir := filepath.Join(run.Cfg.BuildDir, file.Name())\n\t\trun.Logger.Debugln(\"cleaning\", dir)\n\t\tif isGitRepository(dir) {\n\t\t\tif err := run.CmdBuilder.Show(run.CmdBuilder.BuildGitCmd(ctx, dir, \"clean\", \"-fx\")); err != nil {\n\t\t\t\trun.Logger.Warnln(gotext.Get(\"Unable to clean:\"), dir)\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc isGitRepository(dir string) bool {\n\t_, err := os.Stat(filepath.Join(dir, \".git\"))\n\treturn !os.IsNotExist(err)\n}\n"
  },
  {
    "path": "clean_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\n\talpm \"github.com/Jguer/dyalpm\"\n\tpacmanconf \"github.com/Morganamilo/go-pacmanconf\"\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db/mock\"\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n)\n\nfunc TestCleanHanging(t *testing.T) {\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\n\tt.Parallel()\n\n\ttestCases := []struct {\n\t\tname     string\n\t\targs     []string\n\t\twantShow []string\n\t}{\n\t\t{\n\t\t\tname:     \"clean\",\n\t\t\targs:     []string{\"Y\", \"c\"},\n\t\t\twantShow: []string{\"pacman\", \"-R\", \"-s\", \"-u\", \"--config\", \"/etc/pacman.conf\", \"--\", \"lsp-plugins\"},\n\t\t},\n\t\t{\n\t\t\tname:     \"clean double\",\n\t\t\targs:     []string{\"Y\", \"c\", \"c\"},\n\t\t\twantShow: []string{\"pacman\", \"-R\", \"-s\", \"-u\", \"--config\", \"/etc/pacman.conf\", \"--\", \"lsp-plugins\", \"linux-headers\"},\n\t\t},\n\t}\n\n\tdbExc := &mock.DBExecutor{\n\t\tPackageOptionalDependsFn: func(i alpm.Package) []alpm.Depend {\n\t\t\tif i.Name() == \"linux\" {\n\t\t\t\treturn []alpm.Depend{\n\t\t\t\t\t{\n\t\t\t\t\t\tName: \"linux-headers\",\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn []alpm.Depend{}\n\t\t},\n\t\tPackageProvidesFn: func(p alpm.Package) []alpm.Depend { return []alpm.Depend{} },\n\t\tPackageDependsFn:  func(p alpm.Package) []alpm.Depend { return []alpm.Depend{} },\n\t\tLocalPackagesFn: func() []mock.IPackage {\n\t\t\treturn []mock.IPackage{\n\t\t\t\t&mock.Package{\n\t\t\t\t\tPReason: alpm.PkgReasonExplicit,\n\t\t\t\t\tPName:   \"linux\",\n\t\t\t\t},\n\t\t\t\t&mock.Package{\n\t\t\t\t\tPReason: alpm.PkgReasonDepend,\n\t\t\t\t\tPName:   \"lsp-plugins\",\n\t\t\t\t},\n\t\t\t\t&mock.Package{\n\t\t\t\t\tPReason: alpm.PkgReasonDepend,\n\t\t\t\t\tPName:   \"linux-headers\",\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tmockRunner := &exe.MockRunner{\n\t\t\t\tCaptureFn: func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\t\t\t\treturn \"\", \"\", nil\n\t\t\t\t},\n\t\t\t\tShowFn: func(cmd *exec.Cmd) error { return nil },\n\t\t\t}\n\t\t\tcmdBuilder := &exe.CmdBuilder{\n\t\t\t\tSudoBin:          \"su\",\n\t\t\t\tPacmanBin:        pacmanBin,\n\t\t\t\tPacmanConfigPath: \"/etc/pacman.conf\",\n\t\t\t\tGitBin:           \"git\",\n\t\t\t\tRunner:           mockRunner,\n\t\t\t\tSudoLoopEnabled:  false,\n\t\t\t}\n\n\t\t\trun := &runtime.Runtime{CmdBuilder: cmdBuilder, Cfg: &settings.Configuration{}}\n\t\t\tcmdArgs := parser.MakeArguments()\n\t\t\tcmdArgs.AddArg(tc.args...)\n\n\t\t\terr := handleCmd(context.Background(),\n\t\t\t\trun, cmdArgs, dbExc,\n\t\t\t)\n\n\t\t\trequire.NoError(t, err)\n\n\t\t\tfor i, call := range mockRunner.ShowCalls {\n\t\t\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\t\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\n\t\t\t\t// options are in a different order on different systems and on CI root user is used\n\t\t\t\tassert.Subset(t, strings.Split(show, \" \"),\n\t\t\t\t\tstrings.Split(tc.wantShow[i], \" \"),\n\t\t\t\t\tfmt.Sprintf(\"%d - %s\", i, show))\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestIntegrationCleanAUR(t *testing.T) {\n\tbuildDir := filepath.Join(t.TempDir(), \"build\")\n\tyayGitDir := filepath.Join(buildDir, \"yay-git\")\n\tzoomDir := filepath.Join(buildDir, \"zoom\")\n\n\tt.Parallel()\n\n\ttestCases := []struct {\n\t\tname     string\n\t\targs     []string\n\t\twantDirs []string\n\t}{\n\t\t{\n\t\t\tname:     \"Sync clean AUR\",\n\t\t\targs:     []string{\"S\", \"c\", \"a\"},\n\t\t\twantDirs: []string{\"zoom\"},\n\t\t},\n\t\t{\n\t\t\tname:     \"Sync clean double AUR\",\n\t\t\targs:     []string{\"S\", \"c\", \"c\", \"a\"},\n\t\t\twantDirs: []string{},\n\t\t},\n\t}\n\n\tdbExc := &mock.DBExecutor{\n\t\tPackageOptionalDependsFn: func(i alpm.Package) []alpm.Depend {\n\t\t\tif i.Name() == \"linux\" {\n\t\t\t\treturn []alpm.Depend{\n\t\t\t\t\t{\n\t\t\t\t\t\tName: \"linux-headers\",\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn []alpm.Depend{}\n\t\t},\n\t\tPackageProvidesFn: func(p alpm.Package) []alpm.Depend { return []alpm.Depend{} },\n\t\tPackageDependsFn:  func(p alpm.Package) []alpm.Depend { return []alpm.Depend{} },\n\t\tInstalledRemotePackagesFn: func() map[string]alpm.Package {\n\t\t\treturn map[string]alpm.Package{\n\t\t\t\t\"zoom\": &mock.Package{\n\t\t\t\t\tPName:    \"zoom\",\n\t\t\t\t\tPVersion: \"6.5.8-1\",\n\t\t\t\t\tPBase:    \"zoom\",\n\t\t\t\t\tPReason:  alpm.PkgReasonExplicit,\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tmockRunner := &exe.MockRunner{}\n\n\t\t\tcfg := &settings.Configuration{\n\t\t\t\tBuildDir: buildDir,\n\t\t\t\tMode:     parser.ModeAUR,\n\t\t\t}\n\t\t\tpacmanConf := &pacmanconf.Config{\n\t\t\t\t// Only testing the keep installed clean method right now\n\t\t\t\tCleanMethod: []string{\"KeepInstalled\"},\n\t\t\t}\n\t\t\trun := &runtime.Runtime{\n\t\t\t\tCfg:        cfg,\n\t\t\t\tPacmanConf: pacmanConf,\n\t\t\t\tLogger:     newTestLogger(),\n\t\t\t}\n\t\t\tcmdArgs := parser.MakeArguments()\n\t\t\tcmdArgs.AddArg(tc.args...)\n\n\t\t\t// Create the package directories to be cleaned\n\t\t\terr := os.MkdirAll(yayGitDir, 0o755)\n\t\t\trequire.NoError(t, err)\n\t\t\terr = os.MkdirAll(zoomDir, 0o755)\n\t\t\trequire.NoError(t, err)\n\n\t\t\terr = handleCmd(context.Background(),\n\t\t\t\trun, cmdArgs, dbExc,\n\t\t\t)\n\t\t\trequire.NoError(t, err)\n\n\t\t\t// This should only test AUR cleaning, so no calls to an external command should be made\n\t\t\tassert.Len(t, mockRunner.ShowCalls, 0)\n\n\t\t\t// Make sure the directories left after cleaning are the only ones we expect\n\t\t\tpackageDirs, err := os.ReadDir(buildDir)\n\t\t\trequire.NoError(t, err)\n\n\t\t\tvar packageDirNames []string\n\t\t\tfor _, dir := range packageDirs {\n\t\t\t\tpackageDirNames = append(packageDirNames, dir.Name())\n\t\t\t}\n\n\t\t\tassert.ElementsMatch(t, tc.wantDirs, packageDirNames)\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "cmd.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strings\"\n\n\talpm \"github.com/Jguer/dyalpm\"\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/completion\"\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/download\"\n\t\"github.com/Jguer/yay/v12/pkg/intrange\"\n\t\"github.com/Jguer/yay/v12/pkg/news\"\n\t\"github.com/Jguer/yay/v12/pkg/query\"\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\t\"github.com/Jguer/yay/v12/pkg/upgrade\"\n\t\"github.com/Jguer/yay/v12/pkg/vcs\"\n)\n\nfunc usage(logger *text.Logger) {\n\tlogger.Println(`Usage:\n    yay\n    yay <operation> [...]\n    yay <package(s)>\n\noperations:\n    yay {-h --help}\n    yay {-V --version}\n    yay {-D --database}    <options> <package(s)>\n    yay {-F --files}       [options] [package(s)]\n    yay {-Q --query}       [options] [package(s)]\n    yay {-R --remove}      [options] <package(s)>\n    yay {-S --sync}        [options] [package(s)]\n    yay {-T --deptest}     [options] [package(s)]\n    yay {-U --upgrade}     [options] <file(s)>\n\nNew operations:\n    yay {-B --build}       [options] [dir]\n    yay {-G --getpkgbuild} [options] [package(s)]\n    yay {-P --show}        [options]\n    yay {-W --web}         [options] [package(s)]\n    yay {-Y --yay}         [options] [package(s)]\n\nIf no operation is specified 'yay -Syu' will be performed\nIf no operation is specified and targets are provided, -Y will be assumed\n\nNew options:\n    -N --repo             Assume targets are from the repositories\n    -a --aur              Assume targets are from the AUR\n\nPermanent configuration options:\n    --save                Causes the following options to be saved back to the\n                          config file when used\n\n    --aururl      <url>   Set an alternative AUR URL\n    --aurrpcurl   <url>   Set an alternative URL for the AUR /rpc endpoint\n    --builddir    <dir>   Directory used to download and run PKGBUILDS\n    --editor      <file>  Editor to use when editing PKGBUILDs\n    --editorflags <flags> Pass arguments to editor\n    --makepkg     <file>  makepkg command to use\n    --mflags      <flags> Pass arguments to makepkg\n    --pacman      <file>  pacman command to use\n    --git         <file>  git command to use\n    --gitflags    <flags> Pass arguments to git\n    --gpg         <file>  gpg command to use\n    --gpgflags    <flags> Pass arguments to gpg\n    --config      <file>  pacman.conf file to use\n    --makepkgconf <file>  makepkg.conf file to use\n    --nomakepkgconf       Use the default makepkg.conf\n\n    --requestsplitn <n>   Max amount of packages to query per AUR request\n    --completioninterval  <n> Time in days to refresh completion cache\n    --sortby    <field>   Sort AUR results by a specific field during search\n    --searchby  <field>   Search for packages using a specified field\n    --answerclean   <a>   Set a predetermined answer for the clean build menu\n    --answerdiff    <a>   Set a predetermined answer for the diff menu\n    --answeredit    <a>   Set a predetermined answer for the edit pkgbuild menu\n    --answerupgrade <a>   Set a predetermined answer for the upgrade menu\n    --noanswerclean       Unset the answer for the clean build menu\n    --noanswerdiff        Unset the answer for the edit diff menu\n    --noansweredit        Unset the answer for the edit pkgbuild menu\n    --noanswerupgrade     Unset the answer for the upgrade menu\n    --cleanmenu           Give the option to clean build PKGBUILDS\n    --diffmenu            Give the option to show diffs for build files\n    --editmenu            Give the option to edit/view PKGBUILDS\n    --askremovemake       Ask to remove makedepends after install\n    --askyesremovemake    Ask to remove makedepends after install(\"Y\" as default)\n    --removemake          Remove makedepends after install\n    --noremovemake        Don't remove makedepends after install\n\n    --cleanafter          Remove package sources after successful install\n    --keepsrc             Keep pkg/ and src/ after building packages\n    --bottomup            Shows AUR's packages first and then repository's\n    --topdown             Shows repository's packages first and then AUR's\n    --singlelineresults   List each search result on its own line\n    --doublelineresults   List each search result on two lines, like pacman\n\n    --devel               Check development packages during sysupgrade\n    --rebuild             Always build target packages\n    --rebuildall          Always build all AUR packages\n    --norebuild           Skip package build if in cache and up to date\n    --rebuildtree         Always build all AUR packages even if installed\n    --redownload          Always download pkgbuilds of targets\n    --noredownload        Skip pkgbuild download if in cache and up to date\n    --redownloadall       Always download pkgbuilds of all AUR packages\n    --provides            Look for matching providers when searching for packages\n    --pgpfetch            Prompt to import PGP keys from PKGBUILDs\n    --useask              Automatically resolve conflicts using pacman's ask flag\n\n    --sudo                <file>  sudo command to use\n    --sudoflags           <flags> Pass arguments to sudo\n    --sudoloop            Loop sudo calls in the background to avoid timeout\n\nshow specific options (used with -P):\n    -c --complete         Used for completions\n    -d --defaultconfig    Print default yay configuration\n    -g --currentconfig    Print current yay configuration\n    -s --stats            Display system package statistics\n    -w --news             Print arch news\n\nyay specific options (used with -Y):\n    -c --clean            Remove unneeded dependencies (-cc to ignore optdepends)\n       --gendb            Generates development package DB used for updating\n\ngetpkgbuild specific options (used with -G):\n    -f --force            Force download for existing ABS packages\n    -p --print            Print pkgbuild of packages`)\n}\n\nfunc handleCmd(ctx context.Context, run *runtime.Runtime,\n\tcmdArgs *parser.Arguments, dbExecutor db.Executor,\n) error {\n\tif cmdArgs.ExistsArg(\"h\", \"help\") {\n\t\treturn handleHelp(ctx, run, cmdArgs)\n\t}\n\n\tif run.Cfg.SudoLoop && cmdArgs.NeedRoot(run.Cfg.Mode) {\n\t\trun.CmdBuilder.SudoLoop()\n\t}\n\n\tswitch cmdArgs.Op {\n\tcase \"V\", \"version\":\n\t\thandleVersion(run.Logger)\n\t\treturn nil\n\tcase \"D\", \"database\":\n\t\treturn run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,\n\t\t\tcmdArgs, run.Cfg.Mode, settings.NoConfirm))\n\tcase \"F\", \"files\":\n\t\treturn run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,\n\t\t\tcmdArgs, run.Cfg.Mode, settings.NoConfirm))\n\tcase \"Q\", \"query\":\n\t\treturn handleQuery(ctx, run, cmdArgs, dbExecutor)\n\tcase \"R\", \"remove\":\n\t\treturn handleRemove(ctx, run, cmdArgs, run.VCSStore)\n\tcase \"S\", \"sync\":\n\t\treturn handleSync(ctx, run, cmdArgs, dbExecutor)\n\tcase \"T\", \"deptest\":\n\t\treturn run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,\n\t\t\tcmdArgs, run.Cfg.Mode, settings.NoConfirm))\n\tcase \"U\", \"upgrade\":\n\t\treturn handleUpgrade(ctx, run, cmdArgs)\n\tcase \"B\", \"build\":\n\t\treturn handleBuild(ctx, run, dbExecutor, cmdArgs)\n\tcase \"G\", \"getpkgbuild\":\n\t\treturn handleGetpkgbuild(ctx, run, cmdArgs, dbExecutor)\n\tcase \"P\", \"show\":\n\t\treturn handlePrint(ctx, run, cmdArgs, dbExecutor)\n\tcase \"Y\", \"yay\":\n\t\treturn handleYay(ctx, run, cmdArgs, run.CmdBuilder,\n\t\t\tdbExecutor, run.QueryBuilder)\n\tcase \"W\", \"web\":\n\t\treturn handleWeb(ctx, run, cmdArgs)\n\t}\n\n\treturn errors.New(gotext.Get(\"unhandled operation\"))\n}\n\n// getFilter returns filter function which can keep packages which were only\n// explicitly installed or ones installed as dependencies for showing available\n// updates or their count.\nfunc getFilter(cmdArgs *parser.Arguments) (upgrade.Filter, error) {\n\tdeps, explicit := cmdArgs.ExistsArg(\"d\", \"deps\"), cmdArgs.ExistsArg(\"e\", \"explicit\")\n\n\tswitch {\n\tcase deps && explicit:\n\t\treturn nil, errors.New(gotext.Get(\"invalid option: '--deps' and '--explicit' may not be used together\"))\n\tcase deps:\n\t\treturn func(pkg *upgrade.Upgrade) bool {\n\t\t\treturn pkg.Reason == alpm.PkgReasonDepend\n\t\t}, nil\n\tcase explicit:\n\t\treturn func(pkg *upgrade.Upgrade) bool {\n\t\t\treturn pkg.Reason == alpm.PkgReasonExplicit\n\t\t}, nil\n\t}\n\n\treturn func(pkg *upgrade.Upgrade) bool {\n\t\treturn true\n\t}, nil\n}\n\nfunc handleQuery(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {\n\tif cmdArgs.ExistsArg(\"u\", \"upgrades\") {\n\t\tfilter, err := getFilter(cmdArgs)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\treturn printUpdateList(ctx, run, cmdArgs, dbExecutor,\n\t\t\tcmdArgs.ExistsDouble(\"u\", \"sysupgrade\"), filter)\n\t}\n\n\tif err := run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,\n\t\tcmdArgs, run.Cfg.Mode, settings.NoConfirm)); err != nil {\n\t\tif str := err.Error(); strings.Contains(str, \"exit status\") {\n\t\t\t// yay -Qdt should not output anything in case of error\n\t\t\treturn fmt.Errorf(\"\")\n\t\t}\n\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc handleHelp(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments) error {\n\tusage(run.Logger)\n\tswitch cmdArgs.Op {\n\tcase \"Y\", \"yay\", \"G\", \"getpkgbuild\", \"P\", \"show\", \"W\", \"web\", \"B\", \"build\":\n\t\treturn nil\n\t}\n\n\trun.Logger.Println(\"\\npacman operation specific options:\")\n\treturn run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,\n\t\tcmdArgs, run.Cfg.Mode, settings.NoConfirm))\n}\n\nfunc handleVersion(logger *text.Logger) {\n\tlogger.Printf(\"yay v%s - libalpm v%s\\n\", yayVersion, alpm.Version())\n}\n\nfunc handlePrint(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {\n\tswitch {\n\tcase cmdArgs.ExistsArg(\"d\", \"defaultconfig\"):\n\t\ttmpConfig := settings.DefaultConfig(yayVersion)\n\t\trun.Logger.Printf(\"%v\", tmpConfig)\n\n\t\treturn nil\n\tcase cmdArgs.ExistsArg(\"g\", \"currentconfig\"):\n\t\trun.Logger.Printf(\"%v\", run.Cfg)\n\n\t\treturn nil\n\tcase cmdArgs.ExistsArg(\"w\", \"news\"):\n\t\tdouble := cmdArgs.ExistsDouble(\"w\", \"news\")\n\t\tquiet := cmdArgs.ExistsArg(\"q\", \"quiet\")\n\n\t\treturn news.PrintNewsFeed(ctx, run.HTTPClient, run.Logger,\n\t\t\tdbExecutor.LastBuildTime(), run.Cfg.BottomUp, double, quiet)\n\tcase cmdArgs.ExistsArg(\"c\", \"complete\"):\n\t\treturn completion.Show(ctx, run.HTTPClient, dbExecutor,\n\t\t\trun.Cfg.AURURL, run.Cfg.CompletionPath, run.Cfg.CompletionInterval, cmdArgs.ExistsDouble(\"c\", \"complete\"), run.Logger)\n\tcase cmdArgs.ExistsArg(\"s\", \"stats\"):\n\t\treturn localStatistics(ctx, run, dbExecutor)\n\t}\n\n\treturn nil\n}\n\nfunc handleYay(ctx context.Context, run *runtime.Runtime,\n\tcmdArgs *parser.Arguments, cmdBuilder exe.ICmdBuilder,\n\tdbExecutor db.Executor, queryBuilder query.Builder,\n) error {\n\tswitch {\n\tcase cmdArgs.ExistsArg(\"gendb\"):\n\t\treturn createDevelDB(ctx, run, dbExecutor)\n\tcase cmdArgs.ExistsDouble(\"c\"):\n\t\treturn cleanDependencies(ctx, run.Cfg, cmdBuilder, cmdArgs, dbExecutor, true)\n\tcase cmdArgs.ExistsArg(\"c\", \"clean\"):\n\t\treturn cleanDependencies(ctx, run.Cfg, cmdBuilder, cmdArgs, dbExecutor, false)\n\tcase len(cmdArgs.Targets) > 0:\n\t\treturn displayNumberMenu(ctx, run, cmdArgs.Targets, dbExecutor, queryBuilder, cmdArgs)\n\t}\n\n\treturn nil\n}\n\nfunc handleWeb(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments) error {\n\tswitch {\n\tcase cmdArgs.ExistsArg(\"v\", \"vote\"):\n\t\treturn handlePackageVote(ctx, cmdArgs.Targets, run.AURClient, run.Logger,\n\t\t\trun.VoteClient, true)\n\tcase cmdArgs.ExistsArg(\"u\", \"unvote\"):\n\t\treturn handlePackageVote(ctx, cmdArgs.Targets, run.AURClient, run.Logger,\n\t\t\trun.VoteClient, false)\n\t}\n\n\treturn nil\n}\n\nfunc handleGetpkgbuild(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments, dbExecutor download.DBSearcher) error {\n\tif cmdArgs.ExistsArg(\"p\", \"print\") {\n\t\treturn printPkgbuilds(dbExecutor, run.AURClient,\n\t\t\trun.HTTPClient, run.Logger, cmdArgs.Targets, run.Cfg.Mode, run.Cfg.AURURL)\n\t}\n\n\treturn getPkgbuilds(ctx, dbExecutor, run.AURClient, run,\n\t\tcmdArgs.Targets, cmdArgs.ExistsArg(\"f\", \"force\"))\n}\n\nfunc handleUpgrade(ctx context.Context,\n\trun *runtime.Runtime, cmdArgs *parser.Arguments,\n) error {\n\treturn run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,\n\t\tcmdArgs, run.Cfg.Mode, settings.NoConfirm))\n}\n\n// -B* options\nfunc handleBuild(ctx context.Context,\n\trun *runtime.Runtime, dbExecutor db.Executor, cmdArgs *parser.Arguments,\n) error {\n\treturn installLocalPKGBUILD(ctx, run, cmdArgs, dbExecutor)\n}\n\nfunc handleSync(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {\n\ttargets := cmdArgs.Targets\n\n\tswitch {\n\tcase cmdArgs.ExistsArg(\"s\", \"search\"):\n\t\treturn syncSearch(ctx, targets, dbExecutor, run.QueryBuilder, !cmdArgs.ExistsArg(\"q\", \"quiet\"))\n\tcase cmdArgs.ExistsArg(\"p\", \"print\", \"print-format\"):\n\t\treturn run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,\n\t\t\tcmdArgs, run.Cfg.Mode, settings.NoConfirm))\n\tcase cmdArgs.ExistsArg(\"c\", \"clean\"):\n\t\treturn syncClean(ctx, run, cmdArgs, dbExecutor)\n\tcase cmdArgs.ExistsArg(\"l\", \"list\"):\n\t\treturn syncList(ctx, run, run.HTTPClient, cmdArgs, dbExecutor)\n\tcase cmdArgs.ExistsArg(\"g\", \"groups\"):\n\t\treturn run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,\n\t\t\tcmdArgs, run.Cfg.Mode, settings.NoConfirm))\n\tcase cmdArgs.ExistsArg(\"i\", \"info\"):\n\t\treturn syncInfo(ctx, run, cmdArgs, targets, dbExecutor)\n\tcase cmdArgs.ExistsArg(\"u\", \"sysupgrade\") || len(cmdArgs.Targets) > 0:\n\t\treturn syncInstall(ctx, run, cmdArgs, dbExecutor)\n\tcase cmdArgs.ExistsArg(\"y\", \"refresh\"):\n\t\treturn run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,\n\t\t\tcmdArgs, run.Cfg.Mode, settings.NoConfirm))\n\t}\n\n\treturn nil\n}\n\nfunc handleRemove(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments, localCache vcs.Store) error {\n\terr := run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,\n\t\tcmdArgs, run.Cfg.Mode, settings.NoConfirm))\n\tif err == nil {\n\t\tlocalCache.RemovePackages(cmdArgs.Targets)\n\t}\n\n\treturn err\n}\n\n// NumberMenu presents a CLI for selecting packages to install.\nfunc displayNumberMenu(ctx context.Context, run *runtime.Runtime, pkgS []string, dbExecutor db.Executor,\n\tqueryBuilder query.Builder, cmdArgs *parser.Arguments,\n) error {\n\tqueryBuilder.Execute(ctx, dbExecutor, pkgS)\n\n\tif err := queryBuilder.Results(dbExecutor, query.NumberMenu); err != nil {\n\t\treturn err\n\t}\n\n\tif queryBuilder.Len() == 0 {\n\t\t// no results were found\n\t\treturn nil\n\t}\n\n\trun.Logger.Infoln(gotext.Get(\"Packages to install (eg: 1 2 3, 1-3 or ^4)\"))\n\n\tnumberBuf, err := run.Logger.GetInput(\"\", false)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tinclude, exclude, _, otherExclude := intrange.ParseNumberMenu(numberBuf)\n\n\ttargets, err := queryBuilder.GetTargets(include, exclude, otherExclude)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// modify the arguments to pass for the install\n\tcmdArgs.Targets = targets\n\n\tif len(cmdArgs.Targets) == 0 {\n\t\trun.Logger.Println(gotext.Get(\" there is nothing to do\"))\n\t\treturn nil\n\t}\n\n\treturn syncInstall(ctx, run, cmdArgs, dbExecutor)\n}\n\nfunc syncList(ctx context.Context, run *runtime.Runtime,\n\thttpClient *http.Client, cmdArgs *parser.Arguments, dbExecutor db.Executor,\n) error {\n\taur := false\n\n\tfor i := len(cmdArgs.Targets) - 1; i >= 0; i-- {\n\t\tif cmdArgs.Targets[i] == \"aur\" && run.Cfg.Mode.AtLeastAUR() {\n\t\t\tcmdArgs.Targets = append(cmdArgs.Targets[:i], cmdArgs.Targets[i+1:]...)\n\t\t\taur = true\n\t\t}\n\t}\n\n\tif run.Cfg.Mode.AtLeastAUR() && (len(cmdArgs.Targets) == 0 || aur) {\n\t\tscanner, err := download.GetPackageScanner(ctx, httpClient, run.Cfg.AURURL, run.Logger)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer scanner.Close()\n\n\t\tfor scanner.Scan() {\n\t\t\tname := scanner.Text()\n\t\t\tif cmdArgs.ExistsArg(\"q\", \"quiet\") {\n\t\t\t\trun.Logger.Println(name)\n\t\t\t} else {\n\t\t\t\trun.Logger.Printf(\"%s %s %s\", text.Magenta(\"aur\"), text.Bold(name), text.Bold(text.Green(gotext.Get(\"unknown-version\"))))\n\n\t\t\t\tif dbExecutor.LocalPackage(name) != nil {\n\t\t\t\t\trun.Logger.Print(text.Bold(text.Blue(gotext.Get(\" [Installed]\"))))\n\t\t\t\t}\n\n\t\t\t\trun.Logger.Println()\n\t\t\t}\n\t\t}\n\t}\n\n\tif run.Cfg.Mode.AtLeastRepo() && (len(cmdArgs.Targets) != 0 || !aur) {\n\t\treturn run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,\n\t\t\tcmdArgs, run.Cfg.Mode, settings.NoConfirm))\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "cmd_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/Jguer/aur\"\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db/mock\"\n\tmockaur \"github.com/Jguer/yay/v12/pkg/dep/mock\"\n\t\"github.com/Jguer/yay/v12/pkg/query\"\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\t\"github.com/Jguer/yay/v12/pkg/vcs\"\n)\n\nfunc TestYogurtMenuAURDB(t *testing.T) {\n\tt.Skip(\"skip until Operation service is an interface\")\n\tt.Parallel()\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tgitBin := t.TempDir() + \"/git\"\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(gitBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\treturn \"\", \"\", nil\n\t}\n\n\tshowOverride := func(cmd *exec.Cmd) error {\n\t\treturn nil\n\t}\n\n\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\tcmdBuilder := &exe.CmdBuilder{\n\t\tMakepkgBin:       makepkgBin,\n\t\tSudoBin:          \"su\",\n\t\tPacmanBin:        pacmanBin,\n\t\tPacmanConfigPath: \"/etc/pacman.conf\",\n\t\tGitBin:           \"git\",\n\t\tRunner:           mockRunner,\n\t\tSudoLoopEnabled:  false,\n\t}\n\n\tcmdArgs := parser.MakeArguments()\n\tcmdArgs.AddArg(\"Y\")\n\tcmdArgs.AddTarget(\"yay\")\n\n\tdb := &mock.DBExecutor{\n\t\tAlpmArchitecturesFn: func() ([]string, error) {\n\t\t\treturn []string{\"x86_64\"}, nil\n\t\t},\n\t\tRefreshHandleFn: func() error {\n\t\t\treturn nil\n\t\t},\n\t\tReposFn: func() []string {\n\t\t\treturn []string{\"aur\"}\n\t\t},\n\t\tSyncPackagesFn: func(s ...string) []mock.IPackage {\n\t\t\treturn []mock.IPackage{\n\t\t\t\t&mock.Package{\n\t\t\t\t\tPName:    \"yay\",\n\t\t\t\t\tPBase:    \"yay\",\n\t\t\t\t\tPVersion: \"10.0.0\",\n\t\t\t\t\tPDB:      mock.NewDB(\"aur\"),\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t\tLocalPackageFn: func(s string) mock.IPackage {\n\t\t\treturn nil\n\t\t},\n\t}\n\taurCache := &mockaur.MockAUR{\n\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\treturn []aur.Pkg{\n\t\t\t\t{\n\t\t\t\t\tName:        \"yay\",\n\t\t\t\t\tPackageBase: \"yay\",\n\t\t\t\t\tVersion:     \"10.0.0\",\n\t\t\t\t},\n\t\t\t}, nil\n\t\t},\n\t}\n\tlogger := text.NewLogger(io.Discard, os.Stderr, strings.NewReader(\"1\\n\"), true, \"test\")\n\n\trun := &runtime.Runtime{\n\t\tCfg: &settings.Configuration{\n\t\t\tRemoveMake: \"no\",\n\t\t},\n\t\tLogger:     logger,\n\t\tCmdBuilder: cmdBuilder,\n\t\tVCSStore:   &vcs.Mock{},\n\t\tQueryBuilder: query.NewSourceQueryBuilder(aurCache, logger, \"votes\", parser.ModeAny, \"name\",\n\t\t\ttrue, false, true),\n\t\tAURClient: aurCache,\n\t}\n\terr = handleCmd(context.Background(), run, cmdArgs, db)\n\trequire.NoError(t, err)\n\n\twantCapture := []string{}\n\twantShow := []string{\n\t\t\"pacman -S -y --config /etc/pacman.conf --\",\n\t\t\"pacman -S -y -u --config /etc/pacman.conf --\",\n\t}\n\n\trequire.Len(t, mockRunner.ShowCalls, len(wantShow))\n\trequire.Len(t, mockRunner.CaptureCalls, len(wantCapture))\n\n\tfor i, call := range mockRunner.ShowCalls {\n\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\t\tshow = strings.ReplaceAll(show, gitBin, \"git\")\n\n\t\t// options are in a different order on different systems and on CI root user is used\n\t\tassert.Subset(t, strings.Split(show, \" \"), strings.Split(wantShow[i], \" \"), fmt.Sprintf(\"%d - %s\", i, show))\n\t}\n}\n"
  },
  {
    "path": "completions/bash",
    "content": "# This file is in the public domain.\n\n_arch_compgen() {\n  local i r\n  COMPREPLY=($(compgen -W '$*' -- \"$cur\"))\n  for ((i = 1; i < ${#COMP_WORDS[@]} - 1; i++)); do\n    for r in ${!COMPREPLY[@]}; do\n      if [[ ${COMP_WORDS[i]} == ${COMPREPLY[r]} ]]; then\n        unset 'COMPREPLY[r]'\n        break\n      fi\n    done\n  done\n}\n\n_arch_ptr2comp() {\n  local list= x y\n  for x; do\n    for y in '0 --' '1 -'; do\n      eval 'set -- ${'$x'[${y% *}]}'\n      list+=\\ ${@/#/${y#* }}\n    done\n  done\n  _arch_compgen $list\n}\n\n_arch_incomp() {\n  local r=\"[[:space:]]-(-${1#* }[[:space:]]|[[:alnum:]_]*${1% *})\"\n  [[ $COMP_LINE =~ $r ]]\n}\n\n_pacman_pkg() {\n  _arch_compgen \"$(\n    if [[ $2 ]]; then\n      \\pacman -$1 2>/dev/null | \\cut -d' ' -f1 | \\sort -u\n    else\n      \\pacman -$1 2>/dev/null\n    fi\n  )\"\n}\n\n_yay_pkg() {\n  [ -z \"$cur\" ] && _pacman_pkg Slq && return\n  _arch_compgen \"$(yay -Pc)\"\n}\n\n_pacman_repo_list() {\n  _arch_compgen \"$(pacman-conf --repo-list)\"\n}\n\n_yay() {\n  compopt -o default\n  local common core cur database files prev query remove sync upgrade o\n  local yays show getpkgbuild web\n  local cur prev words cword\n\n  _init_completion || return\n  database=('asdeps asexplicit')\n  files=('list machinereadable refresh regex' 'l x y')\n  query=('changelog check deps explicit file foreign groups info list native owns\n          search unrequired upgrades' 'c e g i k l m n o p s t u')\n  remove=('cascade dbonly nodeps assume-installed nosave print recursive unneeded' 'c n p s u')\n  sync=('asdeps asexplicit clean dbonly downloadonly overwrite groups ignore ignoregroup\n         info list needed nodeps assume-installed print refresh recursive search sysupgrade aur repo'\n    'c g i l p s u w y a N')\n  upgrade=('asdeps asexplicit overwrite needed nodeps assume-installed print recursive' 'p')\n  core=('database files help query remove sync upgrade version' 'D F Q R S U V h')\n\n  ##yay stuff\n  common=('arch cachedir color config confirm dbpath debug gpgdir help hookdir logfile\n          noconfirm noprogressbar noscriptlet quiet root verbose\n          makepkg pacman git gpg gpgflags config requestsplitn sudoloop\n          redownload noredownload redownloadall rebuild rebuildall rebuildtree norebuild sortby\n          singlelineresults doublelineresults answerclean answerdiff answeredit answerupgrade noanswerclean noanswerdiff\n          noansweredit noanswerupgrade cleanmenu diffmenu editmenu cleanafter keepsrc\n          provides pgpfetch\n          useask combinedupgrade aur repo makepkgconf\n          nomakepkgconf askremovemake askyesremovemake removemake noremovemake completioninterval aururl aurrpcurl\n          searchby batchinstall'\n    'b d h q r v')\n  yays=('clean gendb' 'c')\n  show=('complete defaultconfig currentconfig stats news' 'c d g s w')\n  getpkgbuild=('force print' 'f p')\n  web=('vote unvote' 'v u')\n\n  for o in 'D database' 'F files' 'Q query' 'R remove' 'S sync' 'U upgrade' 'Y yays' 'P show' 'G getpkgbuild' 'W web'; do\n    _arch_incomp \"$o\" && break\n  done\n\n  if [[ $? != 0 ]]; then\n    _arch_ptr2comp core\n  elif [[ ! $prev =~ ^-[[:alnum:]_]*[Vbhr] && ! $prev == --@(cachedir|color|config|dbpath|help|hookdir|gpgdir|logfile|root|version) ]]; then\n    [[ $cur == -* ]] && _arch_ptr2comp ${o#* } common ||\n      case ${o% *} in\n      D | R)\n        _pacman_pkg Qq\n        ;;\n      F)\n        { _arch_incomp 'l list' && _pacman_pkg Slq; } ||\n          _arch_incomp 'o owns' ||\n          compopt +o default\n        ;;\n      Q)\n        { _arch_incomp 'g groups' && _pacman_pkg Qg sort; } ||\n          { _arch_incomp 'p file' && _pacman_file; } ||\n          { _arch_incomp 's search' && compopt +o default; } ||\n          { _arch_incomp 'u upgrades' && compopt +o default; } ||\n          _arch_incomp 'o owns' ||\n          _pacman_pkg Qq\n        ;;\n      S)\n        { _arch_incomp 'g groups' && _pacman_pkg Sg; } ||\n          { _arch_incomp 'l list' && _pacman_repo_list; } ||\n          { _arch_incomp 's search' && compopt +o default; } ||\n          _yay_pkg\n        ;;\n      U)\n        _pacman_file\n        ;;\n      G)\n        _yay_pkg\n        ;;\n      W)\n        _yay_pkg\n        ;;\n      esac\n  fi\n  true\n}\n\n_pacman_file() {\n  compopt -o filenames\n  _filedir 'pkg.*'\n}\n\ncomplete -F _yay yay\n\n# ex:et ts=2 sw=2 ft=sh\n"
  },
  {
    "path": "completions/fish",
    "content": "# vim:fdm=marker foldlevel=0 tabstop=2 shiftwidth=2 filetype=fish\n# Original Author for pacman: Giorgio Lando <patroclo7@gmail.com>\n# Updated for yay by jguer\n\nset -l progname yay\n\n# Yay constants\nset -l listall \"(yay -Pc)\"\nset -l listpacman \"(__fish_print_packages)\"\nset -l yayspecific '__fish_contains_opt -s Y yay'\nset -l webspecific '__fish_contains_opt -s W web'\nset -l show '__fish_contains_opt -s P show'\nset -l getpkgbuild '__fish_contains_opt -s G getpkgbuild'\n\n# Pacman constants\nset -l listinstalled \"(pacman -Q | string replace ' ' \\t)\"\nset -l listrepos \"(__fish_print_pacman_repos)\"\nset -l listgroups \"(pacman -Sg)\\t'Package Group'\"\n\nset -l noopt 'not __fish_contains_opt -s S -s D -s Q -s R -s U -s T -s F -s Y -s W -s P -s G database query sync remove upgrade deptest files show getpkgbuild web yay'\nset -l database '__fish_contains_opt -s D database'\nset -l query '__fish_contains_opt -s Q query'\nset -l remove '__fish_contains_opt -s R remove'\nset -l sync '__fish_contains_opt -s S sync'\nset -l upgrade '__fish_contains_opt -s U upgrade'\nset -l files '__fish_contains_opt -s F files'\n\n\n\ncomplete -c $progname -e\ncomplete -c $progname -f\n# HACK: We only need these two to coerce fish to stop file completion and complete options\ncomplete -c $progname -n \"$noopt\" -a \"-D\" -d \"Modify the package database\"\ncomplete -c $progname -n \"$noopt\" -a \"-Q\" -d \"Query the package database\"\n\n# Primary operations\ncomplete -c $progname -s D -f -l database -n \"$noopt\" -d 'Modify the package database'\ncomplete -c $progname -s Q -f -l query -n \"$noopt\" -d 'Query the package database'\ncomplete -c $progname -s R -f -l remove -n \"$noopt\" -d 'Remove packages from the system'\ncomplete -c $progname -s S -f -l sync -n \"$noopt\" -d 'Synchronize packages'\ncomplete -c $progname -s T -f -l deptest -n \"$noopt\" -d 'Check dependencies'\ncomplete -c $progname -s U -l upgrade -n \"$noopt\" -d 'Upgrade or add a local package'\ncomplete -c $progname -s F -f -l files -n \"$noopt\" -d 'Query the files database'\ncomplete -c $progname -s V -f -l version -d 'Display version and exit'\ncomplete -c $progname -s h -f -l help -d 'Display help'\n\n# General options\n# Only offer these once a command has been given so they get prominent display\ncomplete -c $progname -n \"not $noopt\" -s b -l dbpath -d 'Alternate database location' -xa \"(__fish_complete_directories)\"\ncomplete -c $progname -n \"not $noopt\" -s r -l root -d 'Alternate installation root' -xa \"(__fish_complete_directories)\"\ncomplete -c $progname -n \"not $noopt\" -s v -l verbose -d 'Output more status messages' -f\ncomplete -c $progname -n \"not $noopt\" -l arch -d 'Alternate architecture' -f\ncomplete -c $progname -n \"not $noopt\" -l cachedir -d 'Alternate package cache location' -xa \"(__fish_complete_directories)\"\ncomplete -c $progname -n \"not $noopt\" -l color -d 'Colorize the output' -fa '{auto,always,never}'\ncomplete -c $progname -n \"not $noopt\" -l config -d 'Alternate config file' -rF\ncomplete -c $progname -n \"not $noopt\" -l confirm -d 'Always ask for confirmation' -f\ncomplete -c $progname -n \"not $noopt\" -l debug -d 'Display debug messages' -f\ncomplete -c $progname -n \"not $noopt\" -l disable-download-timeout -d 'Use relaxed timeouts for download' -f\ncomplete -c $progname -n \"not $noopt\" -l gpgdir -d 'Alternate home directory for GnuPG' -xa \"(__fish_complete_directories)\"\ncomplete -c $progname -n \"not $noopt\" -l hookdir -d 'Alternate hook location' -xa \"(__fish_complete_directories)\"\ncomplete -c $progname -n \"not $noopt\" -l logfile -d 'Alternate log file'\ncomplete -c $progname -n \"not $noopt\" -l noconfirm -d 'Bypass any confirmation' -f\ncomplete -c $progname -n \"not $noopt\" -l sysroot -d 'Operate on a mounted guest system (root-only)' -xa \"(__fish_complete_directories)\"\n\n# File, query, sync options (files, query, sync)\nfor condition in files query sync\n    complete -c $progname -n \"$$condition\" -s q -l quiet -d 'Show less information' -f\nend\n\n# Transaction options (sync, remove, upgrade)\nfor condition in sync remove upgrade\n    complete -c $progname -n \"$$condition\" -s d -l nodeps -d 'Skip [all] dependency checks' -f\n    complete -c $progname -n \"$$condition\" -s p -l print -d 'Dry run, only print targets' -f\n    complete -c $progname -n \"$$condition\" -l assume-installed -d 'Add a virtual package to satisfy dependencies' -f\n    complete -c $progname -n \"$$condition\" -l dbonly -d 'Modify database entry only' -f\n    complete -c $progname -n \"$$condition\" -l noprogressbar -d 'Do not display progress bar' -f\n    complete -c $progname -n \"$$condition\" -l noscriptlet -d 'Do not execute install script' -f\n    complete -c $progname -n \"$$condition\" -l print-format -d 'Specify printf-like format' -x\nend\n\n# File and query options (files, query)\nfor condition in files query\n    complete -c $progname -n \"$$condition\" -s l -l list -d 'List the files owned by PACKAGE' -f\nend\n\n# File and sync options (files, sync)\nfor condition in files sync\n    complete -c $progname -n \"$$condition\" -s y -l refresh -d 'Download fresh package databases [force]' -f\nend\n\n# Query and sync options (query, sync)\nfor condition in query sync\n    complete -c $progname -n \"$$condition\" -s g -l groups -d 'Display members of [all] package GROUP' -xa \"$listgroups\"\nend\n\n# Sync and upgrade options (sync, upgrade)\nfor condition in sync upgrade\n    complete -c $progname -n \"$$condition\" -l asdeps -d 'Install packages as non-explicitly installed' -f\n    complete -c $progname -n \"$$condition\" -l asexplicit -d 'Install packages as explicitly installed' -f\n    complete -c $progname -n \"$$condition\" -l ignore -d 'Ignore a package upgrade (can be used more than once)' -xa \"$listall\"\n    complete -c $progname -n \"$$condition\" -l ignoregroup -d 'Ignore a group upgrade (can be used more than once)' -xa \"$listgroups\"\n    complete -c $progname -n \"$$condition\" -l needed -d 'Do not reinstall up to date packages' -f\n    complete -c $progname -n \"$$condition\" -l overwrite -d 'Overwrite conflicting files (can be used more than once)' -rF\nend\n\n# Database options\nset -l has_db_opt '__fish_contains_opt asdeps asexplicit check -s k'\ncomplete -c $progname -n \"$database; and not $has_db_opt\" -s k -l check -d 'Check database validity'\ncomplete -c $progname -n \"$database\" -s q -l quite -d 'Suppress output of success messages' -f\ncomplete -c $progname -n \"$database; and not $has_db_opt\" -l asdeps -d 'Mark PACKAGE as dependency' -x\ncomplete -c $progname -n \"$database; and not $has_db_opt\" -l asexplicit -d 'Mark PACKAGE as explicitly installed' -x\ncomplete -c $progname -n \"$has_db_opt; and $database\" -xa \"$listinstalled\"\n\n# File options - since pacman 5\ncomplete -c $progname -n \"$files\" -s x -l regex -d 'Interpret each query as a regular expression' -f\ncomplete -c $progname -n \"$files\" -l machinereadable -d 'Print each match in a machine readable output format' -f\ncomplete -c $progname -n \"$files\" -d Package -xa \"$listpacman\"\n\n# Query options\ncomplete -c $progname -n \"$query\" -s c -l changelog -d 'View the change log of PACKAGE' -f\ncomplete -c $progname -n \"$query\" -s d -l deps -d 'List only non-explicit packages (dependencies)' -f\ncomplete -c $progname -n \"$query\" -s e -l explicit -d 'List only explicitly installed packages' -f\ncomplete -c $progname -n \"$query\" -s i -l info -d 'View PACKAGE [backup files] information' -f\ncomplete -c $progname -n \"$query\" -s k -l check -d 'Check that PACKAGE files exist' -f\ncomplete -c $progname -n \"$query\" -s m -l foreign -d 'List installed packages not found in sync database' -f\ncomplete -c $progname -n \"$query\" -s n -l native -d 'list installed packages only found in sync database' -f\ncomplete -c $progname -n \"$query\" -s o -l owns -d 'Query the package that owns FILE' -rF\ncomplete -c $progname -n \"$query\" -s p -l file -d 'Query a package file instead of the database' -rF\ncomplete -c $progname -n \"$query\" -s s -l search -d 'Search locally-installed packages for regexp' -f\ncomplete -c $progname -n \"$query\" -s t -l unrequired -d 'List only unrequired packages [and optdepends]' -f\ncomplete -c $progname -n \"$query\" -s u -l upgrades -d 'List only out-of-date packages' -f\ncomplete -c $progname -n \"$query\" -d 'Installed package' -xa \"$listinstalled\"\n\n# Remove options\ncomplete -c $progname -n \"$remove\" -s c -l cascade -d 'Also remove packages depending on PACKAGE' -f\ncomplete -c $progname -n \"$remove\" -s n -l nosave -d 'Ignore file backup designations' -f\ncomplete -c $progname -n \"$remove\" -s s -l recursive -d 'Also remove dependencies of PACKAGE' -f\ncomplete -c $progname -n \"$remove\" -s u -l unneeded -d 'Only remove targets not required by PACKAGE' -f\ncomplete -c $progname -n \"$remove\" -d 'Installed package' -xa \"$listinstalled\"\n\n# Sync options\ncomplete -c $progname -n \"$sync\" -s c -l clean -d 'Remove [all] packages from cache' -f\ncomplete -c $progname -n \"$sync\" -s i -l info -d 'View PACKAGE [extended] information' -f\ncomplete -c $progname -n \"$sync\" -s l -l list -d 'List all packages in REPOSITORY' -xa \"$listrepos\"\ncomplete -c $progname -n \"$sync\" -s s -l search -d 'Search remote repositories for regexp' -f\ncomplete -c $progname -n \"$sync\" -s u -l sysupgrade -d 'Upgrade all packages that are out of date'\ncomplete -c $progname -n \"$sync\" -s w -l downloadonly -d 'Only download the target packages'\ncomplete -c $progname -n \"$sync\" -xa \"$listall $listgroups\"\n\n# Upgrade options\n# Theoretically, pacman reads packages in all formats that libarchive supports\n# In practice, it's going to be tar.xz, tar.gz, tar.zst, or just pkg.tar (uncompressed pkg)\ncomplete -c $progname -n \"$upgrade\" -xa '(__fish_complete_suffix pkg.tar.zst; __fish_complete_suffix pkg.tar.xz; __fish_complete_suffix pkg.tar.gz; __fish_complete_suffix pkg.tar;)' -d 'Package file'\n\n\n# Yay operations\ncomplete -c $progname -s Y -f -l yay -n \"$noopt\" -d 'Yay specific operations'\ncomplete -c $progname -s P -f -l show -n \"$noopt\" -d 'Print information'\ncomplete -c $progname -s G -f -l getpkgbuild -n \"$noopt\" -d 'Get PKGBUILD from ABS or AUR'\ncomplete -c $progname -s W -f -l web -n \"$noopt\" -d 'Web operations'\n\n# Web options\ncomplete -c $progname -n \"$webspecific\" -s v -l vote -d 'Vote for AUR packages' -f\ncomplete -c $progname -n \"$webspecific\" -s u -l unvote -d 'Unvote for AUR packages' -f\ncomplete -c $progname -n \"$webspecific\" -xa \"$listall\"\n\n# New options\ncomplete -c $progname -n \"not $noopt\" -s a -l aur -d 'Assume targets are from the AUR' -f\ncomplete -c $progname -n \"not $noopt\" -s N -l repo -d 'Assume targets are from the repositories' -f\n\n# Yay options\ncomplete -c $progname -n \"$yayspecific\" -s c -l clean -d 'Remove unneeded dependencies' -f\ncomplete -c $progname -n \"$yayspecific\" -l gendb -d 'Generate development package DB' -f\n\n# Show options\ncomplete -c $progname -n \"$show\" -s c -l complete -d 'Print a list of all AUR and repo packages' -f\n#complete -c $progname -n \"$show\" -s f -l fish -d 'During complete adjust the output for the fish shell' -f\ncomplete -c $progname -n \"$show\" -s d -l defaultconfig -d 'Print default yay configuration' -f\ncomplete -c $progname -n \"$show\" -s g -l currentconfig -d 'Print current yay configuration' -f\ncomplete -c $progname -n \"$show\" -s s -l stats -d 'Display system package statistics' -f\ncomplete -c $progname -n \"$show\" -s w -l news -d 'Print arch news' -f\ncomplete -c $progname -n \"$show\" -s q -l quiet -d 'Do not print news description' -f\n\n# Getpkgbuild options\ncomplete -c $progname -n \"$getpkgbuild\" -s f -l force -d 'Force download for existing ABS packages' -f\ncomplete -c $progname -n \"$getpkgbuild\" -xa \"$listall\"\ncomplete -c $progname -n \"$getpkgbuild\" -s p -l print -d 'Print pkgbuild of packages' -f\n\n# Permanent configuration settings\ncomplete -c $progname -n \"not $noopt\" -l save -d 'Save current arguments to yay permanent configuration' -f\ncomplete -c $progname -n \"not $noopt\" -l aururl -d 'Set an alternative AUR URL' -f\ncomplete -c $progname -n \"not $noopt\" -l aurrpcurl -d 'Set an alternative URL for the AUR /rpc endpoint' -f\ncomplete -c $progname -n \"not $noopt\" -l builddir -d 'Directory to use for Building AUR Packages' -r\ncomplete -c $progname -n \"not $noopt\" -l editor -d 'Editor to use' -f\ncomplete -c $progname -n \"not $noopt\" -l editorflags -d 'Editor flags to use' -f\ncomplete -c $progname -n \"not $noopt\" -l makepkg -d 'Makepkg command to use' -f\ncomplete -c $progname -n \"not $noopt\" -l pacman -d 'Pacman command to use' -f\ncomplete -c $progname -n \"not $noopt\" -l tar -d 'Tar command to use' -f\ncomplete -c $progname -n \"not $noopt\" -l git -d 'Git command to use' -f\ncomplete -c $progname -n \"not $noopt\" -l gpg -d 'Gpg command to use' -f\ncomplete -c $progname -n \"not $noopt\" -l config -d 'The pacman config file to use' -r\ncomplete -c $progname -n \"not $noopt\" -l makepkgconf -d 'Use custom makepkg.conf location' -r\ncomplete -c $progname -n \"not $noopt\" -l nomakepkgconf -d 'Use default makepkg.conf' -f\ncomplete -c $progname -n \"not $noopt\" -l requestsplitn -d 'Max amount of packages to query per AUR request' -f\ncomplete -c $progname -n \"not $noopt\" -l completioninterval -d 'Refresh interval for completion cache' -f\ncomplete -c $progname -n \"not $noopt\" -l sortby -d 'Sort AUR results by a specific field during search' -xa \"{votes,popularity,name,base,submitted,modified}\"\ncomplete -c $progname -n \"not $noopt\" -l searchby -d 'Search for AUR packages by querying the specified field' -xa \"{name,name-desc,maintainer,depends,checkdepends,makedepends,optdepends}\"\ncomplete -c $progname -n \"not $noopt\" -l answerclean -d 'Set a predetermined answer for the clean build menu' -xa \"{All,None,Installed,NotInstalled}\"\ncomplete -c $progname -n \"not $noopt\" -l answerdiff -d 'Set a predetermined answer for the edit diff menu' -xa \"{All,None,Installed,NotInstalled}\"\ncomplete -c $progname -n \"not $noopt\" -l answeredit -d 'Set a predetermined answer for the edit pkgbuild menu' -xa \"{All,None,Installed,NotInstalled}\"\ncomplete -c $progname -n \"not $noopt\" -l answerupgrade -d 'Set a predetermined answer for the upgrade menu' -f\ncomplete -c $progname -n \"not $noopt\" -l noanswerclean -d 'Unset the answer for the clean build menu' -f\ncomplete -c $progname -n \"not $noopt\" -l noanswerdiff -d 'Unset the answer for the diff menu' -f\ncomplete -c $progname -n \"not $noopt\" -l noansweredit -d 'Unset the answer for the edit pkgbuild menu' -f\ncomplete -c $progname -n \"not $noopt\" -l noanswerupgrade -d 'Unset the answer for the upgrade menu' -f\ncomplete -c $progname -n \"not $noopt\" -l cleanmenu -d 'Give the option to clean build PKGBUILDS' -f\ncomplete -c $progname -n \"not $noopt\" -l diffmenu -d 'Give the option to show diffs for build files' -f\ncomplete -c $progname -n \"not $noopt\" -l editmenu -d 'Give the option to edit/view PKGBUILDS' -f\ncomplete -c $progname -n \"not $noopt\" -l askremovemake -d 'Ask to remove make deps after install' -f\ncomplete -c $progname -n \"not $noopt\" -l askyesremovemake -d 'Ask to remove make deps after install(with \"Y\" as default)' -f\ncomplete -c $progname -n \"not $noopt\" -l removemake -d 'Remove make deps after install' -f\ncomplete -c $progname -n \"not $noopt\" -l noremovemake -d 'Do not remove make deps after install' -f\ncomplete -c $progname -n \"not $noopt\" -l topdown -d 'Shows repository packages first and then aur' -f\ncomplete -c $progname -n \"not $noopt\" -l bottomup -d 'Shows aur packages first and then repository' -f\ncomplete -c $progname -n \"not $noopt\" -l singlelineresults -d 'List each search result on its own line' -f\ncomplete -c $progname -n \"not $noopt\" -l doublelineresults -d 'List each search result on two lines, like pacman' -f\ncomplete -c $progname -n \"not $noopt\" -l devel -d 'Check -git/-svn/-hg development version' -f\ncomplete -c $progname -n \"not $noopt\" -l cleanafter -d 'Clean package sources after successful build' -f\ncomplete -c $progname -n \"not $noopt\" -l keepsrc -d 'Keep pkg/ and src/ after building packages' -f\ncomplete -c $progname -n \"not $noopt\" -l redownload -d 'Redownload PKGBUILD of package even if up-to-date' -f\ncomplete -c $progname -n \"not $noopt\" -l redownloadall -d 'Redownload PKGBUILD of package and deps even if up-to-date' -f\ncomplete -c $progname -n \"not $noopt\" -l noredownload -d 'Do not redownload up-to-date PKGBUILDs' -f\ncomplete -c $progname -n \"not $noopt\" -l provides -d 'Look for matching providers when searching for packages' -f\ncomplete -c $progname -n \"not $noopt\" -l pgpfetch -d 'Prompt to import PGP keys from PKGBUILDs' -f\ncomplete -c $progname -n \"not $noopt\" -l useask -d 'Automatically resolve conflicts using pacmans ask flag' -f\ncomplete -c $progname -n \"not $noopt\" -l combinedupgrade -d 'Refresh then perform the repo and AUR upgrade together' -f\ncomplete -c $progname -n \"not $noopt\" -l batchinstall -d 'Build multiple AUR packages then install them together' -f\ncomplete -c $progname -n \"not $noopt\" -l rebuild -d 'Always build target packages' -f\ncomplete -c $progname -n \"not $noopt\" -l rebuildall -d 'Always build all AUR packages' -f\ncomplete -c $progname -n \"not $noopt\" -l rebuildtree -d 'Always build all AUR packages even if installed' -f\ncomplete -c $progname -n \"not $noopt\" -l norebuild -d 'Skip package build if in cache and up to date' -f\ncomplete -c $progname -n \"not $noopt\" -l mflags -d 'Pass the following options to makepkg' -f\ncomplete -c $progname -n \"not $noopt\" -l gpgflags -d 'Pass the following options to gpg' -f\ncomplete -c $progname -n \"not $noopt\" -l sudoloop -d 'Loop sudo calls in the background to avoid timeout' -f\n"
  },
  {
    "path": "completions/zsh",
    "content": "#compdef yay\n# vim:noexpandtab tabstop=2 shiftwidth=2 filetype=zsh\n\ntypeset -A opt_args\nsetopt extendedglob\n\n# options for passing to _arguments: main pacman commands\n_pacman_opts_commands=(\n\t{-D,--database}'[Modify database]'\n\t{-F,--files}'[Query the files database]'\n\t{-G,--getpkgbuild}'[Get PKGBUILD from ABS or AUR]'\n\t{-Q,--query}'[Query the package database]'\n\t{-R,--remove}'[Remove a package from the system]'\n\t{-P,--show}'[Print yay information]'\n\t{-S,--sync}'[Synchronize packages]'\n\t{-T,--deptest}'[Check if dependencies are installed]'\n\t{-U,--upgrade}'[Upgrade a package]'\n\t{-Y,--yay}'[Yay specific options]'\n\t{-W,--web}'[web options]'\n\t{-V,--version}'[Display version and exit]'\n\t'(-h --help)'{-h,--help}'[Display usage]'\n)\n\n# options for passing to _arguments: options common to all commands\n_pacman_opts_common=(\n\t'(-N --repo)'{-N,--repo}'[Assume targets are from the repositories]'\n\t'(-a --aur)'{-a,--aur}'[Assume targets are from the AUR]'\n\t'--aururl[Set an alternative AUR URL]:url'\n\t'--aurrpcurl[Set an alternative URL for the AUR /rpc endpoint]:url'\n\t'--arch[Set an alternate architecture]'\n\t'(-b --dbpath)'{-b,--dbpath}'[Alternate database location]:database_location:_files -/'\n\t'--color[colorize the output]:color options:(always never auto)'\n\t'(- *)'{-h,--help}'[Display syntax for the given operation]'\n\t'(-r --root)'{-r,--root}'[Set alternate installation root]:installation root:_files -/'\n\t'(-v --verbose)'{-v,--verbose}'[Be more verbose]'\n\t'--cachedir[Alternate package cache location]:cache_location:_files -/'\n\t'--config[An alternate configuration file]:config file:_files'\n\t'(--nomakepkgconf)--makepkgconf[makepkg.conf file to use]:config file:_files'\n\t'(--makepkgconf)--nomakepkgconf[Use the default makepkg.conf]'\n\t'--requestsplitn[Max amount of packages to query per AUR request]:number'\n\t'--completioninterval[Time in days to refresh completion cache]:number'\n\t'--confirm[Always ask for confirmation]'\n\t'--debug[Display debug messages]'\n\t'--gpgdir[Set an alternate directory for GnuPG (instead of /etc/pacman.d/gnupg)]: :_files -/'\n\t'--hookdir[Set an alternate hook location]: :_files -/'\n\t'--logfile[An alternate log file]:config file:_files'\n\t'--noconfirm[Do not ask for confirmation]'\n\t'--noprogressbar[Do not show a progress bar when downloading files]'\n\t'--noscriptlet[Do not execute the install scriptlet if one exists]'\n\n\t'--save[Causes config options to be saved back to the config file]'\n\n\t'--builddir[Directory to use for building AUR Packages]:build dir:_files -/'\n\t'--editor[Editor to use when editing PKGBUILDs]:editor:_files'\n\t'--editorflags[Flags to pass to editor]'\n\t'--makepkg[makepkg command to use]:makepkg:_files'\n\t'--pacman[pacman command to use]:pacman:_files'\n\t'--git[git command to use]:git:_files'\n\t'--gpg[gpg command to use]:gpg:_files'\n\n\t'--sortby[Sort AUR results by a specific field during search]:sortby options:(votes popularity name base submitted modified)'\n\t'--searchby[Search for packages using a specified field]:query'\n\t'(--noanswerclean)--answerclean[Set a predetermined answer for the clean build menu]:answer'\n\t'(--noanswerdiff)--answerdiff[Set a predetermined answer for the diff menu]:answer'\n\t'(--noansweredit)--answeredit[Set a predetermined answer for the edit pkgbuild menu]:answer'\n\t'(--noanswerupgrade)--answerupgrade[Set a predetermined answer for the upgrade menu]:answer'\n\t'(--answerclean)--noanswerclean[Unset the answer for the clean build menu]'\n\t'(--answerdiff)--noanswerdiff[Unset the answer for the diff menu]'\n\t'(--answeredit)--noansweredit[Unset the answer for the edit pkgbuild menu]'\n\t'(--answerupgrade)--noanswerupgrade[Unset the answer for the upgrade menu]'\n\t'--cleanmenu[Give the option to clean build PKGBUILDS]'\n\t'--diffmenu[Give the option to show diffs for build files]'\n\t'--editmenu[Give the option to edit/view PKGBUILDS]'\n\t'(--askyesremovemake --removemake --noremovemake)--askremovemake[Ask to remove makedepends after install]'\n\t'(--askremovemake --removemake --noremovemake)--askyesremovemake[Ask to remove makedepends after install(with \"Y\" as default)]'\n\t'(--askremovemake --askyesremovemake --noremovemake)--removemake[Remove makedepends after install]'\n\t\"(--askremovemake --askyesremovemake --removemake)--noremovemake[Don't remove makedepends after install]\"\n\n\t'(--bottomup)--topdown[Show repository packages first]'\n\t'(--topdown)--bottomup[Show AUR packages first]'\n\t'(--doublelineresults)--singlelineresults[List each search result on its own line]'\n\t'(--singlelineresults)--doublelineresults[List each search result on two lines, like pacman]'\n\t'--devel[Check -git/-svn/-hg development version]'\n\t'--cleanafter[Clean package sources after successful build]'\n\t'--keepsrc[Keep pkg/ and src/ after building packages]'\n\t'--separatesources[Separate query results by source, AUR and sync]'\n\t'(--redownloadall --noredownload)--redownload[Always download pkgbuilds of targets]'\n\t'(--redownload --noredownload)--redownloadall[Always download pkgbuilds of all AUR packages]'\n\t'(--redownload --redownloadall)--noredownload[Skip pkgbuild download if in cache and up to date]'\n\t'--provides[Look for matching providers when searching for packages]'\n\t'--pgpfetch[Prompt to import PGP keys from PKGBUILDs]'\n\t\"--useask[Automatically resolve conflicts using pacman's ask flag]\"\n\t'--combinedupgrade[Refresh then perform the repo and AUR upgrade together]'\n\t'--batchinstall[Build multiple AUR packages then install them together]'\n\t'(--rebuildall --rebuildtree --norebuild)--rebuild[Always build target packages]'\n\t'(--rebuild --rebuildtree --norebuild)--rebuildall[Always build all AUR packages]'\n\t'(--rebuild --rebuildall --norebuild)--rebuildtree[Always build all AUR packages even if installed]'\n\t'(--rebuild --rebuildall --rebuildtree)--norebuild[Skip package build if in cache and up to date]'\n\t'--mflags[Pass arguments to makepkg]:mflags'\n\t'--gpgflags[Pass arguments to gpg]:gpgflags'\n\t'--sudo[The command to use for sudo calls]:command'\n\t'--sudoflags[Passes arguments to sudo]:flag'\n\t'--sudoloop[Loop sudo calls in the background to avoid timeout]'\n)\n\n# options for passing to _arguments: options for --upgrade commands\n_pacman_opts_pkgfile=(\n\t'*-d[Skip dependency checks]'\n\t'*--nodeps[Skip dependency checks]'\n\t'*--assume-installed[Add virtual package to satisfy dependencies]'\n\t'--dbonly[Only remove database entry, do not remove files]'\n\t'--overwrite[Overwrite conflicting files]:file:_files -g \"*\"'\n\t'--needed[Do not reinstall up to date packages]'\n\t'(--asexplicit)--asdeps[mark packages as non-explicitly installed]'\n\t'(--asdeps)--asexplicit[mark packages as explicitly installed]'\n\t'(-p --print)'{-p,--print}'[Only print the targets instead of performing the operation]'\n\t'*--ignore[Ignore a package upgrade]:package: _pacman_completions_all_packages'\n\t'*--ignoregroup[Ignore a group upgrade]:package group:_pacman_completions_all_groups'\n\t'--print-format[Specify how the targets should be printed]'\n\t'*:package file:_files -g \"*.pkg.tar*~*.sig(.,@)\"'\n)\n\n# options for passing to _arguments: subactions for --query command\n_pacman_opts_query_actions=(\n\t'(-Q --query)'{-Q,--query}\n\t{-g,--groups}'[View all members of a package group]:*:package groups:->query_group'\n\t{-o,--owns}'[Query the package that owns a file]:file:_files'\n\t{-p,--file}'[Package file to query]:*:package file:->query_file'\n\t{-s,--search}'[Search package names and descriptions]:*:search text:->query_search'\n)\n\n# options for passing to _arguments: options for --query and subcommands\n_pacman_opts_query_modifiers=(\n\t'(-c --changelog)'{-c,--changelog}'[List package changelog]'\n\t'(-d --deps)'{-d,--deps}'[List packages installed as dependencies]'\n\t'(-e --explicit)'{-e,--explicit}'[List packages explicitly installed]'\n\t{\\*-i,\\*--info}'[View package information]'\n\t{\\*-k,\\*--check}'[Check package files]'\n\t'(-l --list)'{-l,--list}'[List package contents]'\n\t'(-m --foreign)'{-m,--foreign}'[List installed packages not found in sync db(s)]'\n\t'(-n --native)'{-n,--native}'[List installed packages found in sync db(s)]'\n\t'(-q --quiet)'{-q,--quiet}'[Show less information for query and search]'\n\t'(-t --unrequired)'{-t,--unrequired}'[List packages not required by any package]'\n\t'(-u --upgrades)'{-u,--upgrades}'[List packages that can be upgraded]'\n)\n\n# -Y\n_pacman_opts_yay_modifiers=(\n\t'(-c --clean)'{-c,--clean}'[Remove unneeded dependencies]'\n\t'--gendb[Generates development package DB used for updating]'\n)\n\n# -G\n_pacman_opts_getpkgbuild_modifiers=(\n\t'(-f --force)'{-f,--force}'[Force download for existing ABS packages]'\n\t'(-p --print)'{-p,--print}'[Print PKGBUILDs]:package:_pacman_completions_all_packages'\n)\n\n# -W\n_pacman_opts_web_modifiers=(\n\t'(-u --unvote)'{-u,--unvote}'[Unvote AUR package]:package:_pacman_completions_all_packages'\n\t'(-v --vote)'{-v,--vote}'[Vote AUR package]:package:_pacman_completions_all_packages'\n)\n\n# -P\n_pacman_opts_print_modifiers=(\n\t\t'(-c --complete)'{-c,--complete}'[Used for completions]'\n\t\t'(-d --defaultconfig)'{-d,--defaultconfig}'[Print default yay configuration]'\n\t\t'(-g --config)'{-g,--config}'[Print current yay configuration]'\n\t\t'(-n --numberupgrades)'{-n,--numberupgrades}'[Print number of updates]'\n\t\t'(-s --stats)'{-s,--stats}'[Display system package statistics]'\n\t\t'(-u --upgrades)'{-u,--upgrades}'[Print update list]'\n\t\t'(-w --news)'{-w,--news}'[Print arch news]'\n)\n# options for passing to _arguments: options for --remove command\n_pacman_opts_remove=(\n\t'(-c --cascade)'{-c,--cascade}'[Remove all dependent packages]'\n\t'(-d --nodeps)'{-d,--nodeps}'[Skip dependency checks]'\n\t'*--assume-installed[Add virtual package to satisfy dependencies]'\n\t'(-n --nosave)'{-n,--nosave}'[Remove protected configuration files]'\n\t'(-p --print)'{-p,--print}'[Only print the targets instead of performing the operation]'\n\t{\\*-s,\\*--recursive}'[Remove dependencies not required by other packages]'\n\t'(-u --unneeded)'{-u,--unneeded}'[Remove unneeded packages]'\n\t'--dbonly[Only remove database entry, do not remove files]'\n\t'--print-format[Specify how the targets should be printed]'\n\t'*:installed package:_pacman_completions_installed_packages'\n)\n\n_pacman_opts_database=(\n\t'(--asexplicit)--asdeps[mark packages as non-explicitly installed]'\n\t'(--asdeps)--asexplicit[mark packages as explicitly installed]'\n\t'*:installed package:_pacman_completions_installed_packages'\n)\n\n_pacman_opts_files=(\n\t'(-l --list)'{-l,--list}'[List the files owned by the queried package]:package:_pacman_completions_all_packages'\n\t'(-x --regex)'{-x,--regex}'[Enable searching using regular expressions]:regex:'\n\t'(-y --refresh)'{-y,--refresh}'[Download fresh files databases from the server]'\n\t'--machinereadable[Produce machine-readable output]'\n\t'(-q --quiet)'{-q,--quiet}'[Show less information for query and search]'\n)\n\n# options for passing to _arguments: options for --sync command\n_pacman_opts_sync_actions=(\n\t'(-S --sync)'{-S,--sync}\n\t{\\*-c,\\*--clean}'[Remove old packages from cache]:\\*:clean:->sync_clean'\n\t{-g,--groups}'[View all members of a package group]:*:package groups:->sync_group'\n\t{-s,--search}'[Search package names and descriptions]:*:search text:->sync_search'\n\t'--dbonly[Only remove database entry, do not remove files]'\n\t'--needed[Do not reinstall up to date packages]'\n\t'--recursive[Reinstall all dependencies of target packages]'\n)\n\n# options for passing to _arguments: options for --sync command\n_pacman_opts_sync_modifiers=(\n\t{\\*-d,\\*--nodeps}'[Skip dependency checks]'\n\t'*--assume-installed[Add virtual package to satisfy dependencies]'\n\t{\\*-i,\\*--info}'[View package information]'\n\t'(-l --list)'{-l,--list}'[List all packages in a repository]'\n\t'(-p --print)'{-p,--print}'[Print download URIs for each package to be installed]'\n\t'(-q --quiet)'{-q,--quiet}'[Show less information for query and search]'\n\t{\\*-u,\\*--sysupgrade}'[Upgrade all out-of-date packages]'\n\t'(-w --downloadonly)'{-w,--downloadonly}'[Download packages only]'\n\t{\\*-y,\\*--refresh}'[Download fresh package databases]'\n\t'*--ignore[Ignore a package upgrade]:package: _pacman_completions_all_packages'\n\t'*--ignoregroup[Ignore a group upgrade]:package group:_pacman_completions_all_groups'\n\t'(--asexplicit)--asdeps[Install packages as non-explicitly installed]'\n\t'(--asdeps)--asexplicit[Install packages as explicitly installed]'\n\t'--overwrite[Overwrite conflicting files]:files:_files'\n\t'--print-format[Specify how the targets should be printed]'\n)\n\n# handles --help subcommand\n_pacman_action_help() {\n\t_arguments -s : \\\n\t\t\"$_pacman_opts_commands[@]\"\n}\n\n# handles cases where no subcommand has yet been given\n_pacman_action_none() {\n\t_arguments -s : \\\n\t\t\"$_pacman_opts_commands[@]\"\n}\n\n# handles --query subcommand\n_pacman_action_query() {\n\tlocal context state line\n\ttypeset -A opt_args\n\n\tcase $state in\n\t\tquery_file)\n\t\t\t_arguments -s : \\\n\t\t\t\t\"$_pacman_opts_common[@]\" \\\n\t\t\t\t\"$_pacman_opts_query_modifiers[@]\" \\\n\t\t\t\t'*:package file:_files -g \"*.pkg.tar*~*.sig(.,@)\"'\n\t\t\t;;\n\t\tquery_group)\n\t\t\t_arguments -s : \\\n\t\t\t\t\"$_pacman_opts_common[@]\" \\\n\t\t\t\t\"$_pacman_opts_query_modifiers[@]\" \\\n\t\t\t\t'*:groups:_pacman_completions_installed_groups'\n\t\t\t;;\n\t\tquery_owner)\n\t\t\t_arguments -s : \\\n\t\t\t\t\"$_pacman_opts_common[@]\" \\\n\t\t\t\t\"$_pacman_opts_query_modifiers[@]\" \\\n\t\t\t\t'*:file:_files'\n\t\t\t;;\n\t\tquery_search)\n\t\t\t_arguments -s : \\\n\t\t\t\t\"$_pacman_opts_common[@]\" \\\n\t\t\t\t\"$_pacman_opts_query_modifiers[@]\" \\\n\t\t\t\t'*:search text: '\n\t\t\t;;\n\t\t*)\n\t\t\t_arguments -s : \\\n\t\t\t\t\"$_pacman_opts_common[@]\" \\\n\t\t\t\t\"$_pacman_opts_query_actions[@]\" \\\n\t\t\t\t\"$_pacman_opts_query_modifiers[@]\" \\\n\t\t\t\t'*:package:_pacman_completions_installed_packages'\n\t\t\t;;\n\tesac\n}\n\n# handles --remove subcommand\n_pacman_action_remove() {\n\t_arguments -s : \\\n\t\t'(--remove -R)'{-R,--remove} \\\n\t\t\"$_pacman_opts_common[@]\" \\\n\t\t\"$_pacman_opts_remove[@]\"\n}\n\n# handles --database subcommand\n_pacman_action_database() {\n\t_arguments -s : \\\n\t\t'(--database -D)'{-D,--database} \\\n\t\t\"$_pacman_opts_common[@]\" \\\n\t\t\"$_pacman_opts_database[@]\"\n}\n\n# handles --files subcommand\n_pacman_action_files() {\n\t_arguments -s : \\\n\t\t'(--files -F)'{-F,--files} \\\n\t\t\"$_pacman_opts_common[@]\" \\\n\t\t\"$_pacman_opts_files[@]\"\n}\n\n_pacman_action_deptest () {\n\t_arguments -s : \\\n\t\t'(--deptest)-T' \\\n\t\t\"$_pacman_opts_common[@]\" \\\n\t\t\":packages:_pacman_all_packages\"\n}\n\n\n# handles --sync subcommand\n_pacman_action_sync() {\n\tlocal context state line\n\ttypeset -A opt_args\n\tif (( $+words[(r)--clean] )); then\n\t\tstate=sync_clean\n\telif (( $+words[(r)--groups] )); then\n\t\tstate=sync_group\n\telif (( $+words[(r)--search] )); then\n\t\tstate=sync_search\n\tfi\n\n\tcase $state in\n\t\tsync_clean)\n\t\t\t_arguments -s : \\\n\t\t\t\t{\\*-c,\\*--clean}'[Remove old packages from cache]' \\\n\t\t\t\t\"$_pacman_opts_common[@]\" \\\n\t\t\t\t\"$_pacman_opts_sync_modifiers[@]\"\n\t\t\t\t;;\n\t\tsync_group)\n\t\t\t_arguments -s : \\\n\t\t\t\t\"$_pacman_opts_common[@]\" \\\n\t\t\t\t\"$_pacman_opts_sync_modifiers[@]\" \\\n\t\t\t\t'(-g --group)'{-g,--groups} \\\n\t\t\t\t'*:package group:_pacman_completions_all_groups'\n\t\t\t;;\n\t\tsync_search)\n\t\t\t_arguments -s : \\\n\t\t\t\t\"$_pacman_opts_common[@]\" \\\n\t\t\t\t\"$_pacman_opts_sync_modifiers[@]\" \\\n\t\t\t\t'*:search text: '\n\t\t\t;;\n\t\t*)\n\t\t\t_arguments -s : \\\n\t\t\t\t\"$_pacman_opts_common[@]\" \\\n\t\t\t\t\"$_pacman_opts_sync_actions[@]\" \\\n\t\t\t\t\"$_pacman_opts_sync_modifiers[@]\" \\\n\t\t\t\t'*:package:_pacman_completions_all_packages'\n\t\t\t;;\n\tesac\n}\n\n# handles --upgrade subcommand\n_pacman_action_upgrade() {\n\t_arguments -s : \\\n\t\t'(-U --upgrade)'{-U,--upgrade} \\\n\t\t\"$_pacman_opts_common[@]\" \\\n\t\t\"$_pacman_opts_pkgfile[@]\"\n}\n\n# handles --version subcommand\n_pacman_action_version() {\n\t# no further arguments\n\treturn 0\n}\n\n# provides completions for package groups\n_pacman_completions_all_groups() {\n\tlocal -a cmd groups\n\t_pacman_get_command\n\tgroups=( $(_call_program groups $cmd[@] -Sg) )\n\ttypeset -U groups\n\n\tif [[ ${words[CURRENT-1]} == '--ignoregroup' ]]; then\n\t\t_sequence compadd -S ',' \"$@\" -a groups\n\telse\n\t\tcompadd \"$@\" -a groups\n\tfi\n}\n\n# provides completions for packages available from repositories\n# these can be specified as either 'package' or 'repository/package'\n_pacman_completions_all_packages() {\n\tlocal -a seq sep cmd packages repositories packages_long\n\n\tif [[ ${words[CURRENT-1]} == '--ignore' ]]; then\n\t\tseq='_sequence'\n\t\tsep=(-S ',')\n\telse\n\t\tseq=\n\t\tsep=()\n\tfi\n\n\tif compset -P1 '*/*'; then\n\t\tpackages=( $(_call_program packages yay -Pc ${words[CURRENT]%/*}) )\n\t\ttypeset -U packages\n\t\t${seq} _wanted repo_packages expl \"repository/package\" compadd ${sep[@]} ${(@)packages}\n\telse\n\t\tpackages=( $(_call_program packages yay -Pc ) )\n\t\ttypeset -U packages\n\t\t${seq} _wanted packages expl \"packages\" compadd ${sep[@]} - \"${(@)packages}\"\n\n\t\trepositories=($(pacman-conf --repo-list))\n\t\ttypeset -U repositories\n\t\t_wanted repo_packages expl \"repository/package\" compadd -S \"/\" $repositories\n\tfi\n}\n\n# provides completions for package groups\n_pacman_completions_installed_groups() {\n\tlocal -a cmd groups\n\t_pacman_get_command\n\tgroups=(${(o)${(f)\"$(_call_program groups $cmd[@] -Qg)\"}% *})\n\ttypeset -U groups\n\tcompadd \"$@\" -a groups\n}\n\n# provides completions for installed packages\n_pacman_completions_installed_packages() {\n\tlocal -a cmd packages packages_long\n\tpackages_long=(/var/lib/pacman/local/*(/))\n\tpackages=( ${${packages_long#/var/lib/pacman/local/}%-*-*} )\n\tcompadd \"$@\" -a packages\n}\n\n_pacman_all_packages() {\n\t_alternative : \\\n\t\t'localpkgs:local packages:_pacman_completions_installed_packages' \\\n\t\t'repopkgs:repository packages:_pacman_completions_all_packages'\n}\n\n# provides completions for repository names\n_pacman_completions_repositories() {\n\tlocal -a cmd repositories\n\trepositories=($(pacman-conf --repo-list))\n\t# Uniq the array\n\ttypeset -U repositories\n\tcompadd \"$@\" -a repositories\n}\n\n# builds command for invoking pacman in a _call_program command - extracts\n# relevant options already specified (config file, etc)\n# $cmd must be declared by calling function\n_pacman_get_command() {\n\t# this is mostly nicked from _perforce\n\tcmd=( \"pacman\" \"2>/dev/null\")\n\tinteger i\n\tfor (( i = 2; i < CURRENT - 1; i++ )); do\n\t\tif [[ ${words[i]} = \"--config\" || ${words[i]} = \"--root\" ]]; then\n\t\t\tcmd+=( ${words[i,i+1]} )\n\t\tfi\n\tdone\n}\n\n# main dispatcher\n_pacman_zsh_comp() {\n\tlocal -a args cmds;\n\tlocal tmp\n\targs=( ${${${(M)words:#-*}#-}:#-*} )\n\tfor tmp in $words; do\n\t\tcmds+=(\"${${_pacman_opts_commands[(r)*$tmp\\[*]%%\\[*}#*\\)}\")\n\tdone\n\tcase $args in #$words[2] in\n\t\th*)\n\t\t\tif (( ${(c)#args} <= 1 && ${(w)#cmds} <= 1 )); then\n\t\t\t\t_pacman_action_help\n\t\t\telse\n\t\t\t\t_message \"no more arguments\"\n\t\t\tfi\n\t\t\t;;\n\t\t*h*)\n\t\t\t_message \"no more arguments\"\n\t\t\t;;\n\t\tD*)\n\t\t\t_pacman_action_database\n\t\t\t;;\n\t\tF*)\n\t\t\t_pacman_action_files\n\t\t\t;;\n\t\tQ*g*) # ipkg groups\n\t\t\t_arguments -s : \\\n\t\t\t\t\"$_pacman_opts_common[@]\" \\\n\t\t\t\t\"$_pacman_opts_query_modifiers[@]\" \\\n\t\t\t\t'*:groups:_pacman_completions_installed_groups'\n\t\t\t;;\n\t\tQ*o*) # file\n\t\t\t_arguments -s : \\\n\t\t\t\t\"$_pacman_opts_common[@]\" \\\n\t\t\t\t\"$_pacman_opts_query_modifiers[@]\" \\\n\t\t\t\t'*:package file:_files'\n\t\t\t;;\n\t\tQ*p*) # file *.pkg.tar*\n\t\t\t_arguments -s : \\\n\t\t\t\t\"$_pacman_opts_common[@]\" \\\n\t\t\t\t\"$_pacman_opts_query_modifiers[@]\" \\\n\t\t\t\t'*:package file:_files -g \"*.pkg.tar*~*.sig(.,@)\"'\n\t\t\t;;\n\t\tQ*)\n\t\t\t_pacman_action_query\n\t\t\t;;\n\t\tP*)\n\t\t\t _arguments -s : \\\n\t\t\t\t'-P' \\\n\t\t\t\t\"$_pacman_opts_print_modifiers[@]\"\n\t\t\t;;\n\t\tW*)\n\t\t\t _arguments -s : \\\n\t\t\t\t'-W' \\\n\t\t\t\t\"$_pacman_opts_web_modifiers[@]\"\n\t\t\t;;\n\t\tR*)\n\t\t\t_pacman_action_remove\n\t\t\t;;\n\t\tS*c*) # no completion\n\t\t\t_arguments -s : \\\n\t\t\t\t'(-c --clean)'{\\*-c,\\*--clean}'[Remove all files from the cache]' \\\n\t\t\t\t\"$_pacman_opts_common[@]\"\n\t\t\t;;\n\t\tS*l*) # repos\n\t\t\t_arguments -s : \\\n\t\t\t\t\"$_pacman_opts_common[@]\" \\\n\t\t\t\t\"$_pacman_opts_sync_modifiers[@]\" \\\n\t\t\t\t'*:package repo:_pacman_completions_repositories' \\\n\t\t\t;;\n\t\tS*g*) # pkg groups\n\t\t\t_arguments -s : \\\n\t\t\t\t\"$_pacman_opts_common[@]\" \\\n\t\t\t\t\"$_pacman_opts_sync_modifiers[@]\" \\\n\t\t\t\t'*:package group:_pacman_completions_all_groups'\n\t\t\t;;\n\t\tS*s*)\n\t\t\t_arguments -s : \\\n\t\t\t\t\"$_pacman_opts_common[@]\" \\\n\t\t\t\t\"$_pacman_opts_sync_modifiers[@]\" \\\n\t\t\t\t'*:search text: '\n\t\t\t\t;;\n\t\tS*)\n\t\t\t_pacman_action_sync\n\t\t\t;;\n\t\tT*)\n\t\t\t_pacman_action_deptest\n\t\t\t;;\n\t\tU*)\n\t\t\t_pacman_action_upgrade\n\t\t\t;;\n\t\tV*)\n\t\t\t_pacman_action_version\n\t\t\t;;\n\t\tY*)\n\t\t\t_arguments -s : \\\n\t\t\t\t'-Y' \\\n\t\t\t\t\"$_pacman_opts_yay_modifiers[@]\"\n\t\t\t;;\n\t\tG*)\n\t\t\t_arguments -s : \\\n\t\t\t\t'-G' \\\n\t\t\t\t\"$_pacman_opts_getpkgbuild_modifiers[@]\"\n\t\t\t;;\n\n\t\t*)\n\n\t\t\tcase ${(M)words:#--*} in\n\t\t\t\t*--help*)\n\t\t\t\t\tif (( ${(w)#cmds} == 1 )); then\n\t\t\t\t\t\t_pacman_action_help\n\t\t\t\t\telse\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\tfi\n\t\t\t\t\t;;\n\t\t\t\t*--sync*)\n\t\t\t\t\t_pacman_action_sync\n\t\t\t\t\t;;\n\t\t\t\t*--query*)\n\t\t\t\t\t_pacman_action_query\n\t\t\t\t\t;;\n\t\t\t\t*--remove*)\n\t\t\t\t\t_pacman_action_remove\n\t\t\t\t\t;;\n\t\t\t\t*--deptest*)\n\t\t\t\t\t_pacman_action_deptest\n\t\t\t\t\t;;\n\t\t\t\t*--database*)\n\t\t\t\t\t_pacman_action_database\n\t\t\t\t\t;;\n\t\t\t\t*--files*)\n\t\t\t\t\t_pacman_action_files\n\t\t\t\t\t;;\n\t\t\t\t*--version*)\n\t\t\t\t\t_pacman_action_version\n\t\t\t\t\t;;\n\t\t\t\t*--upgrade*)\n\t\t\t\t\t_pacman_action_upgrade\n\t\t\t\t\t;;\n\t\t\t\t*)\n\t\t\t\t\t_pacman_action_none\n\t\t\t\t\t;;\n\t\t\tesac\n\t\t\t;;\n\tesac\n}\n_pacman_comp() {\n\tcase \"$service\" in\n\t\tyay)\n\t\t\t_pacman_zsh_comp \"$@\"\n\t\t\t;;\n\t\t*)\n\t\t\t_message \"Error\"\n\t\t\t;;\n\tesac\n}\n\n_pacman_comp \"$@\"\n"
  },
  {
    "path": "doc/yay.8",
    "content": ".TH \"YAY\" \"8\" \"2019\\-10\\-21\" \"Yay v12.0+\" \"Yay Manual\"\n.nh\n.ad l\n.SH NAME\nyay \\- AUR Helper written in go\n\n.SH SYNOPSIS\n\\fIyay\\fR <operation> [options] [targets]\n.sp\n\\fIyay\\fR <search terms>\n.sp\n\\fIyay\\fR\n\n.SH DESCRIPTION\nYay is a Pacman wrapper with AUR support. It passes options to Makepkg and\nPacman after resolving packages to install/upgrade.\n\nThis manpage only covers options unique to Yay. For other options see\n\\fBpacman(8)\\fR.\n\n.SH YAY OPERATIONS\n\n.TP\n.B \\-Y, \\-\\-yay\nPerform yay specific operations. This is the default if no other operation is\nselected and targets are defined.\n\n.TP\n.B \\-B, \\-\\-build\nBuild a PKGBUILD in a given directory.\n\n.TP\n.B \\-P, \\-\\-show\nPerform yay specific print operations.\n\n.TP\n.B \\-G, \\-\\-getpkgbuild\nDownloads PKGBUILD from ABS or AUR. The ABS can only be used for Arch Linux repositories.\n\n.TP\n.B \\-W, \\-\\-web\nWeb related operations such as voting for AUR packages.\n\n.RE\nIf no operation is specified 'yay \\-Syu' will be performed\n\nIf no operation is specified and targets are provided \\-Y will be assumed\n\n.SH EXTENDED PACMAN OPERATIONS\n.TP\n.B \\-S, \\-Si, \\-Sl, \\-Ss, \\-Su, \\-Sc, \\-Qu\nThese operations are extended to support both AUR and repo packages.\n\n.TP\n.B \\-Sc\nYay will also clean cached AUR package and any untracked Files in the\ncache. Cleaning untracked files will wipe any downloaded sources or\nbuilt packages but will keep already downloaded vcs sources.\n\n.TP\n.B \\-R\nYay will also remove cached data about devel packages.\n\n.SH NEW OPTIONS\n.TP\n.B \\-N, \\-\\-repo\nAssume all targets are from the repositories. Additionally Actions such as\nsysupgrade will only act on repository packages.\n\n.TP\n.B \\-a, \\-\\-aur\nAssume all targets are from the AUR. Additionally Actions such as\nsysupgrade will only act on AUR packages.\n\nNote that dependency resolving will still act normally and include repository\npackages.\n\n.SH YAY OPTIONS (APPLY TO \\-Y AND \\-\\-YAY)\n\n.TP\n.B <NO OPTION>\nDisplays a list of packages matching the search terms and prompts the user on\nwhich packages to install (yogurt mode).\n\nThe first search term is used to query the different sources and\nthe following search terms are used to narrow the search results\nthrough exact matching.\n\n.TP\n.B \\-\\-gendb\nGenerate development package database. Tracks the latest commit for each\ndevelopment package, when there is a new commit Yay will know to update. This\nis done per package whenever a package is synced. This option should only be\nused when migrating to Yay from another AUR helper.\n\n.TP\n.B \\-c, \\-\\-clean\nRemove unneeded dependencies.\n\n.TP\n.B \\-cc\nRemove unneeded dependencies, including packages optionally required by any other package.\n\n.SH SHOW OPTIONS (APPLY TO \\-P AND \\-\\-show)\n.TP\n.B \\-c, \\-\\-complete\nPrint a list of all AUR and repo packages. This allows shell completion\nand is not intended to be used directly by the user.\n\n.TP\n.B \\-d, \\-\\-defaultconfig\nPrint default yay configuration.\n\n.TP\n.B \\-g, \\-\\-currentconfig\nPrint current yay configuration.\n\n.TP\n.B \\-s, \\-\\-stats\nDisplays information about installed packages and system health. If there are\norphaned, or out\\-of\\-date packages, or packages that no longer exist on the\nAUR; warnings will be displayed.\n\n.TP\n.B \\-w, \\-\\-news\nPrint new news from the Archlinux homepage. News is considered new if it is\nnewer than the build date of all native packages. Pass this twice to show all\navailable news.\n\n.TP\n.B \\-q, \\-\\-quiet\nOnly show titles when printing news.\n\n.SH BUILD OPTIONS (APPLY TO \\-B AND \\-\\-build)\n.TP\n.B \\-i, \\-\\-install\nBuild and install a PKGBUILD in a given directory\n\n.SH GETPKGBUILD OPTIONS (APPLY TO \\-G AND \\-\\-getpkgbuild)\n.TP\n.B \\-f, \\-\\-force\nForce download for ABS packages that already exist in the current directory. This\nensures directories are not accidentally overwritten.\n\n.TP\n.B \\-p, \\-\\-print\nPrints the PKGBUILD of the given packages to stdout.\n\n.SH WEB OPTIONS (APPLY TO \\-W AND \\-\\-web)\n\n.TP\nWeb related operations such as voting for AUR packages.\nRequires setting AUR_USERNAME and AUR_PASSWORD environment variables.\n\n.TP\n.B \\-u, \\-\\-unvote\nRemove vote from AUR package(s)\n\n.TP\n.B \\-v, \\-\\-vote\nVote for AUR package(s)\n\n.SH PERMANENT CONFIGURATION SETTINGS\n.TP\n.B \\-\\-save\nCauses the following options to be saved back to the config file. This\nprovides an easy way to change config options without directly editing the\nfile.\n\n.TP\n.B \\-\\-aururl\nSet an alternative AUR URL.\n\n.TP\n.B \\-\\-aurrpcurl\nSet an alternative URL for the AUR /rpc endpoint.\n\n.TP\n.B \\-\\-builddir <dir>\nDirectory to use for Building AUR Packages. This directory is also used as\nthe AUR cache when deciding if Yay should skip builds.\n\n.TP\n.B \\-\\-editor <command>\nEditor to use when editing PKGBUILDs. If this is not set the \\fBVISUAL\\fR\nenvironment variable will be checked, followed by \\fBEDITOR\\fR. If none of\nthese are set Yay will prompt the user for an editor.\n\n.TP\n.B \\-\\-editorflags <flags>\nPasses arguments to the editor. These flags get passed to every instance where\nthe editor is called by Yay. Arguments are split on whitespace before being\npassed to the editor. Multiple arguments may be passed by supplying a space\nseparated list that is quoted by the shell.\n\n.TP\n.B \\-\\-makepkg <command>\nThe command to use for \\fBmakepkg\\fR calls. This can be a command in\n\\fBPATH\\fR or an absolute path to the file.\n\n.TP\n.B \\-\\-pacman <command>\nThe command to use for \\fBpacman\\fR calls. This can be a command in\n\\fBPATH\\fR or an absolute path to the file.\n\n.TP\n.B \\-\\-git <command>\nThe command to use for \\fBgit\\fR calls. This can be a command in\n\\fBPATH\\fR or an absolute path to the file.\n\n.TP\n.B \\-\\-gitflags <flags>\nPasses arguments to git. These flags get passed to every instance where\ngit is called by yay. Arguments are split on whitespace before being\npassed to git. Multiple arguments may be passed by supplying a space\nseparated list that is quoted by the shell.\n\n.TP\n.B \\-\\-gpg <command>\nThe command to use for \\fBgpg\\fR calls. This can be a command in\n\\fBPATH\\fR or an absolute path to the file.\n\n.TP\n.B \\-\\-config <file>\nThe pacman config file to use.\n\n.TP\n.B \\-\\-makepkgconf <file>\nThe config file for makepkg to use\\%. If this is not set then the default\nconfig file will be used.\n\n.TP\n.B \\-\\-nomakepkgconf\nReset the makepkg config file back to its default.\n\n.TP\n.B \\-\\-requestsplitn <number>\nThe maximum amount of packages to request per AUR query. The higher the\nnumber the faster AUR requests will be. Requesting too many packages in one\nAUR query will cause an error. This should only make a noticeable difference\nwith very large requests (>500) packages.\n\n.TP\n.B \\-\\-completioninterval <days>\nTime in days to refresh the completion cache. Setting this to 0 will cause\nthe cache to be refreshed every time, while setting this to -1 will cause the\ncache to never be refreshed.\n\n.TP\n.B \\-\\-sortby <votes|popularity|name|base|submitted|modified>\nSort AUR results by a specific field during search.\n\n.TP\n.B \\-\\-searchby <name|name-desc|maintainer|depends|checkdepends|makedepends|optdepends|provides|conflicts|replaces|groups|keywords|comaintainers>\nSearch for AUR packages by querying the specified field.\n\n.TP\n.B \\-\\-answerclean <All|None|Installed|NotInstalled|...>\nSet a predetermined answer for the clean build menu question. This answer\nwill be used instead of reading from standard input but will be parsed exactly\nthe same.\n\n.TP\n.B \\-\\-answerdiff <All|None|Installed|NotInstalled|...>\nSet a predetermined answer for the edit diff menu question. This answer\nwill be used instead of reading from standard input but will be parsed exactly\nthe same.\n\n.TP\n.B \\-\\-answeredit <All|None|Installed|NotInstalled|...>\nSet a predetermined answer for the edit pkgbuild menu question. This answer\nwill be used instead of reading from standard input but will be parsed exactly\nthe same.\n\n.TP\n.B \\-\\-answerupgrade <Repo|^Repo|None|...>\nSet a predetermined answer for the upgrade menu question. Selects which package\nranges or repos to omit for updates. This answer will be used instead of\nreading from standard input but will be treated exactly the same.\n\n.TP\n.B \\-\\-noanswerclean\nUnset the answer for the clean build menu.\n\n.TP\n.B \\-\\-noanswerdiff\nUnset the answer for the diff menu.\n\n.TP\n.B \\-\\-noansweredit\nUnset the answer for the edit pkgbuild menu.\n\n.TP\n.B \\-\\-noanswerupgrade\nUnset the answer for the upgrade menu.\n\n.TP\n.B \\-\\-cleanmenu\nShow the clean menu. This menu gives you the chance to fully delete the\ndownloaded build files from Yay's cache before redownloading a fresh copy.\n\nIf 'cleanmenu' is enabled in the configuration file, you can temporarily disable it by\nusing '--cleanmenu=false' on the command line\n\n.TP\n.B \\-\\-diffmenu\nShow the diff menu. This menu gives you the option to view diffs from\nbuild files before building.\n\nDiffs are shown via \\fBgit diff\\fR which uses\nless by default. This behaviour can be changed via git's config, the\n\\fB$GIT_PAGER\\fR or \\fB$PAGER\\fR environment variables.\n\n.TP\n.B \\-\\-editmenu\nShow the edit menu. This menu gives you the option to edit or view PKGBUILDs\nbefore building.\n\n\\fBWarning\\fR: Yay resolves dependencies ahead of time via the RPC. It is not\nrecommended to edit pkgbuild variables unless you know what you are doing.\n\n.TP\n.B \\-\\-askremovemake\nAsk to remove makedepends after installing packages.\n\n.TP\n.B \\-\\-askyesremovemake\nAsk to remove makedepends after installing packages(with \"Y\" as default).\n\n.TP\n.B \\-\\-removemake\nRemove makedepends after installing packages.\n\n.TP\n.B \\-\\-noremovemake\nDo not remove makedepends after installing packages.\n\n.TP\n.B \\-\\-topdown\nDisplay repository packages first and then AUR packages.\n\n.TP\n.B \\-\\-bottomup\nShow AUR packages first and then repository packages.\n\n.TP\n.B \\-\\-singlelineresults\nOverride pacman's usual double-line search result format and list each result\non its own line.\n\n.TP\n.B \\-\\-doublelineresults\nFollow pacman's double-line search result format and list each result using\ntwo lines.\n\n.TP\n.B \\-\\-devel\nDuring sysupgrade also check AUR development packages for updates. Currently\nonly Git packages are supported.\n\nDevel checking is done using \\fBgit ls-remote\\fR. The newest commit hash is\ncompared against the hash at install time. This allows devel updates to be\nchecked almost instantly and not require the original pkgbuild to be downloaded.\n\nThe slower pacaur-like devel checks can be implemented manually by piping\na list of packages into yay (see \\fBexamples\\fR).\n\nIf 'devel' is enabled in the configuration file, you can temporarily disable it by\nusing '--devel=false' on the command line\n\n.TP\n.B \\-\\-cleanafter\nRemove untracked files after installation.\n\nUntracked files are removed with the exception of directories.\nThis allows VCS packages to easily pull an update\ninstead of having to reclone the entire repo.\n\n.TP\n.B \\-\\-keepsrc\nKeep pkg/ and src/ after building packages\n\n.TP\n.B \\-\\-separatesources\nSeparate query results by source, AUR and sync\n\n.TP\n.B \\-\\-redownload\nAlways download pkgbuilds of targets even when a copy is available in cache.\n\n.TP\n.B \\-\\-redownloadall\nAlways download pkgbuilds of all AUR packages even when a copy is available\nin cache.\n\n.TP\n.B \\-\\-noredownload\nWhen downloading pkgbuilds if the pkgbuild is found in cache and is equal or\nnewer than the AUR's version use that instead of downloading a new one.\n\n.TP\n.B \\-\\-provides\nLook for matching providers when searching for AUR packages. When multiple\nproviders are found a menu will appear prompting you to pick one. This\nincreases dependency resolve time although this should not be noticeable.\n\n.TP\n.B \\-\\-pgpfetch\nPrompt to import unknown PGP keys from the \\fBvalidpgpkeys\\fR field of each\nPKGBUILD.\n\n.TP\n.B \\-\\-useask\nUse pacman's --ask flag to automatically confirm package conflicts. Yay lists\nconflicts ahead of time. It is possible that Yay does not detect\na conflict, causing a package to be removed without the user's confirmation.\nHowever, this is very unlikely.\n\n.TP\n.B \\-\\-combinedupgrade\nDuring sysupgrade, Yay will first perform a refresh, then show\nits combined menu of repo and AUR packages that will be upgraded. Then after\nreviewing the pkgbuilds, the repo and AUR upgrade will start with no need\nfor manual intervention.\n\nIf Yay exits for any reason After the refresh without upgrading. It is then\nthe user's responsibility to either resolve the reason Yay exited or run\na sysupgrade through pacman directly.\n\n.TP\n.B \\-\\-batchinstall\nWhen building and installing AUR packages instead of installing each package\nafter building, queue each package for install. Then once either all packages\nare built or a package in the build queue is needed as a dependency to build\nanother package, install all the packages in the install queue.\n\n.TP\n.B \\-\\-rebuild\nAlways build target packages even when a copy is available in cache.\n\n.TP\n.B \\-\\-rebuildall\nAlways build all AUR packages even when a copy is available\nin cache.\n\n.TP\n.B \\-\\-rebuildtree\nWhen installing an AUR package rebuild and reinstall all of its AUR\ndependencies recursively, even the ones already installed. This flag allows\nyou to easily rebuild packages against your current system's libraries if they\nhave become incompatible.\n\n.TP\n.B \\-\\-norebuild\nWhen building packages if the package is found in cache and is an equal version\nto the one wanted skip the package build and use the existing package.\n\n.TP\n.B \\-\\-mflags <flags>\nPasses arguments to makepkg. These flags get passed to every instance where\nmakepkg is called by Yay. Arguments are split on whitespace before being\npassed to makepkg. Multiple arguments may be passed by supplying a space\nseparated list that is quoted by the shell.\n\n.TP\n.B \\-\\-gpgflags <flags>\nPasses arguments to gpg. These flags get passed to every instance where\ngpg is called by Yay. Arguments are split on whitespace before being\npassed to gpg. Multiple arguments may be passed by supplying a space\nseparated list that is quoted by the shell.\n\n.TP\n.B \\-\\-sudo <command>\nThe command to use for \\fBsudo\\fR calls. This can be a command in\n\\fBPATH\\fR or an absolute path to the file.\nThe sudoloop is not guaranteed to work with a custom \\fBsudo\\fR command.\n\n.TP\n.B \\-\\-sudoflags <flags>\nPasses arguments to sudo. These flags get passed to every instance where\nsudo is called by Yay. Arguments are split on whitespace before being\npassed to sudo. Multiple arguments may be passed by supplying a space\nseparated list that is quoted by the shell.\n\n.TP\n.B \\-\\-sudoloop\nLoop sudo calls in the background to prevent sudo from timing out during long\nbuilds.\n\n.SH EXAMPLES\n.TP\nyay \\fIfoo\\fR\nSearch and install from the repos and the \\fBAUR\\fR\\ using yogurt mode.\n\n.TP\nyay \\-Syu\nUpdate package list and upgrade all currently installed repo and \\fBAUR\\fR.\n\n.TP\nyay \\-Sua\nUpdate all currently installed \\fBAUR\\fR packages.\n\n.TP\nyay \\-S \\fIfoo\\fR\nInstalls package \\fIfoo\\fR from the repos or the \\fBAUR\\fR.\n\n.TP\nyay \\-Ss \\fIfoo\\fR\nSearches for package \\fIfoo\\fR on the repos or the \\fBAUR\\fR.\n\n.TP\nyay \\-Si \\fIfoo\\fR\nGets information about package \\fIfoo\\fR from the repos or the \\fBAUR\\fR.\n\n.TP\nyay \\-S \\fIfoo\\fR \\-\\-mflags \"\\-\\-skipchecksums \\-\\-skippgpcheck\"\nInstalls \\fIfoo\\fR while skipping checksums and pgp checks.\n\n.TP\nyay \\-\\-devel \\-\\-save\nSets devel to true in the config.\n\n.TP\nyay \\-P \\-\\-stats\nShows statistics for installed packages and system health.\n\n.TP\npacman -Qmq | grep -Ee '-(cvs|svn|git|hg|bzr|darcs)$' | yay -S --needed -\npacaur-like devel check.\n\n.SH ENVIRONMENT VARIABLES\n.TP\n.B AURDEST\nCan be set to configure the build directory.\n\nOverridden by \\-\\-builddir.\n\n.TP\n.B VISUAL, EDITOR\nWhen editor is not configured, use these variables to pick what editor\nto use when editing PKGBUILDS.\n\n.SH FILES\n.TP\n.B CONFIG DIRECTORY\nThe config directory is \\fI$XDG_CONFIG_HOME/yay/\\fR. If\n\\fB$XDG_CONFIG_HOME\\fR is unset, the config directory will fall back to\n\\fI$HOME/.config/yay\\fR.\n\n\\fIconfig.json\\fR Is used to store all of Yay's config options. Editing\nthis file should be done through Yay, using the options\nmentioned in \\fBPERMANENT CONFIGURATION SETTINGS\\fR.\n\n.TP\n.B CACHE DIRECTORY\nThe cache directory is \\fI$XDG_CACHE_HOME/yay/\\fR. If\n\\fB$XDG_CACHE_HOME\\fR is unset, the cache directory will fall back to\n\\fI$HOME/.cache/yay\\fR.\n\n\\fIcompletion.cache\\fR holds a list of of all packages, including the AUR,\nfor shell completion. By default the completion files are refreshed every\n7 days.\n\n\\fIvcs.json\\fR tracks VCS packages and the latest commit of each source. If\nany of these commits change the package will be upgraded during a devel update.\n\n.TP\n.B BUILD DIRECTORY\nUnless otherwise set this should be the same as \\fBCACHE DIRECTORY\\fR. This\ndirectory is used to store downloaded AUR Packages as well as any source files\nand built packages from those packages.\n\n.TP\n.B PACMAN.CONF\nYay uses Pacman's config file to set certain pacman options either through\ngo\\-alpm or Yay itself. Options inherited include most libalpm options and\npacman options.\n\nNotably: \\fBDatabases\\fR, \\fBColor\\fR and \\fB*Path/*Dir\\fR options are used.\n\n.SH SEE ALSO\n.BR makepkg (8),\n.BR makepkg.conf (5),\n.BR PKGBUILD (5),\n.BR pacman (8),\n.BR pacman.conf (5)\n\nSee the arch wiki at https://wiki.archlinux.org/index.php/Arch_User_Repository for more info on the \\fBAUR\\fR.\n\n.SH BUGS\nPlease report bugs to our GitHub page https://github.com/Jguer/yay\n\n.SH AUTHORS\nJguer <joguer@proton.me>\n.br\nMorgan <morganamilo@archlinux.org>\n"
  },
  {
    "path": "errors.go",
    "content": "package main\n\nimport (\n\t\"errors\"\n\n\t\"github.com/leonelquinteros/gotext\"\n)\n\nvar ErrPackagesNotFound = errors.New(gotext.Get(\"could not find all required packages\"))\n"
  },
  {
    "path": "get.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/Jguer/aur\"\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/download\"\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\n// yay -Gp.\nfunc printPkgbuilds(dbExecutor download.DBSearcher, aurClient aur.QueryClient,\n\thttpClient *http.Client, logger *text.Logger, targets []string,\n\tmode parser.TargetMode, aurURL string,\n) error {\n\tpkgbuilds, err := download.PKGBUILDs(dbExecutor, aurClient, httpClient, logger, targets, aurURL, mode)\n\tif err != nil {\n\t\tlogger.Errorln(err)\n\t}\n\n\tfor target, pkgbuild := range pkgbuilds {\n\t\tlogger.Printf(\"\\n\\n# %s\\n\\n%s\", target, string(pkgbuild))\n\t}\n\n\tif len(pkgbuilds) != len(targets) {\n\t\tmissing := []string{}\n\n\t\tfor _, target := range targets {\n\t\t\tif _, ok := pkgbuilds[target]; !ok {\n\t\t\t\tmissing = append(missing, target)\n\t\t\t}\n\t\t}\n\n\t\tlogger.Warnln(gotext.Get(\"Unable to find the following packages:\"), \" \", strings.Join(missing, \", \"))\n\n\t\treturn fmt.Errorf(\"\")\n\t}\n\n\treturn nil\n}\n\n// yay -G.\nfunc getPkgbuilds(ctx context.Context, dbExecutor download.DBSearcher, aurClient aur.QueryClient,\n\trun *runtime.Runtime, targets []string, force bool,\n) error {\n\twd, err := os.Getwd()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tcloned, errD := download.PKGBUILDRepos(ctx, dbExecutor, aurClient,\n\t\trun.CmdBuilder, run.Logger, targets, run.Cfg.Mode, run.Cfg.AURURL, wd, force)\n\tif errD != nil {\n\t\trun.Logger.Errorln(errD)\n\t}\n\n\tif len(targets) != len(cloned) {\n\t\tmissing := []string{}\n\n\t\tfor _, target := range targets {\n\t\t\tif _, ok := cloned[target]; !ok {\n\t\t\t\tmissing = append(missing, target)\n\t\t\t}\n\t\t}\n\n\t\trun.Logger.Warnln(gotext.Get(\"Unable to find the following packages:\"), \" \", strings.Join(missing, \", \"))\n\n\t\terr = fmt.Errorf(\"\")\n\t}\n\n\treturn err\n}\n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/Jguer/yay/v12\n\nrequire (\n\tgithub.com/Jguer/aur v1.3.0\n\tgithub.com/Jguer/dyalpm v0.1.1\n\tgithub.com/Jguer/votar v1.0.0\n\tgithub.com/Morganamilo/go-pacmanconf v0.0.0-20210502114700-cff030e927a5\n\tgithub.com/Morganamilo/go-srcinfo v1.0.0\n\tgithub.com/adrg/strutil v0.3.1\n\tgithub.com/bradleyjkemp/cupaloy v2.3.0+incompatible\n\tgithub.com/deckarep/golang-set/v2 v2.8.0\n\tgithub.com/hashicorp/go-multierror v1.1.1\n\tgithub.com/leonelquinteros/gotext v1.7.2\n\tgithub.com/stretchr/testify v1.11.1\n\tgolang.org/x/net v0.52.0\n\tgolang.org/x/sys v0.42.0\n\tgolang.org/x/term v0.41.0\n\tgopkg.in/h2non/gock.v1 v1.1.2\n\tgopkg.in/ini.v1 v1.67.1\n)\n\nrequire (\n\tgithub.com/davecgh/go-spew v1.1.1 // indirect\n\tgithub.com/ebitengine/purego v0.9.1 // indirect\n\tgithub.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect\n\tgithub.com/hashicorp/errwrap v1.1.0 // indirect\n\tgithub.com/itchyny/gojq v0.12.18 // indirect\n\tgithub.com/itchyny/timefmt-go v0.1.7 // indirect\n\tgithub.com/mitchellh/mapstructure v1.5.0 // indirect\n\tgithub.com/ohler55/ojg v1.28.0 // indirect\n\tgithub.com/pmezard/go-difflib v1.0.0 // indirect\n\tgopkg.in/yaml.v3 v3.0.1 // indirect\n)\n\ngo 1.26\n"
  },
  {
    "path": "go.sum",
    "content": "github.com/Jguer/aur v1.3.0 h1:skdjp/P9kB75TBaJmn9PKK/kCeA9QsgjdUrORZ3gldU=\ngithub.com/Jguer/aur v1.3.0/go.mod h1:F8Awo+WKzTxlXtNOO4pDQjMkePLZ+oMSbu+1fKLTTLo=\ngithub.com/Jguer/dyalpm v0.1.1 h1:38JkmJuHIGXVZedXIDGz/nhVcn8DtMk4zM+GRGipC7w=\ngithub.com/Jguer/dyalpm v0.1.1/go.mod h1:eUPJQ/zSclJKTxOPihpspulI+S8WQNsxHJoIBiBgogw=\ngithub.com/Jguer/votar v1.0.0 h1:drPYpV5Py5BeAQS8xezmT6uCEfLzotNjLf5yfmlHKTg=\ngithub.com/Jguer/votar v1.0.0/go.mod h1:rc6vgVlTqNjI4nAnPbDTbdxw/N7kXkbB8BcUDjeFbYQ=\ngithub.com/Morganamilo/go-pacmanconf v0.0.0-20210502114700-cff030e927a5 h1:TMscPjkb1ThXN32LuFY5bEYIcXZx3YlwzhS1GxNpn/c=\ngithub.com/Morganamilo/go-pacmanconf v0.0.0-20210502114700-cff030e927a5/go.mod h1:Hk55m330jNiwxRodIlMCvw5iEyoRUCIY64W1p9D+tHc=\ngithub.com/Morganamilo/go-srcinfo v1.0.0 h1:Wh4nEF+HJWo+29hnxM18Q2hi+DUf0GejS13+Wg+dzmI=\ngithub.com/Morganamilo/go-srcinfo v1.0.0/go.mod h1:MP6VGY1NNpVUmYIEgoM9acix95KQqIRyqQ0hCLsyYUY=\ngithub.com/adrg/strutil v0.3.1 h1:OLvSS7CSJO8lBii4YmBt8jiK9QOtB9CzCzwl4Ic/Fz4=\ngithub.com/adrg/strutil v0.3.1/go.mod h1:8h90y18QLrs11IBffcGX3NW/GFBXCMcNg4M7H6MspPA=\ngithub.com/alexflint/go-arg v1.4.3/go.mod h1:3PZ/wp/8HuqRZMUUgu7I+e1qcpUbvmS258mRXkFH4IA=\ngithub.com/alexflint/go-scalar v1.1.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o=\ngithub.com/bradleyjkemp/cupaloy v2.3.0+incompatible h1:UafIjBvWQmS9i/xRg+CamMrnLTKNzo+bdmT/oH34c2Y=\ngithub.com/bradleyjkemp/cupaloy v2.3.0+incompatible/go.mod h1:Au1Xw1sgaJ5iSFktEhYsS0dbQiS1B0/XMXl+42y9Ilk=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/deckarep/golang-set/v2 v2.8.0 h1:swm0rlPCmdWn9mESxKOjWk8hXSqoxOp+ZlfuyaAdFlQ=\ngithub.com/deckarep/golang-set/v2 v2.8.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=\ngithub.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A=\ngithub.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=\ngithub.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=\ngithub.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=\ngithub.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=\ngithub.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=\ngithub.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=\ngithub.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=\ngithub.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=\ngithub.com/itchyny/gojq v0.12.18 h1:gFGHyt/MLbG9n6dqnvlliiya2TaMMh6FFaR2b1H6Drc=\ngithub.com/itchyny/gojq v0.12.18/go.mod h1:4hPoZ/3lN9fDL1D+aK7DY1f39XZpY9+1Xpjz8atrEkg=\ngithub.com/itchyny/timefmt-go v0.1.7 h1:xyftit9Tbw+Dc/huSSPJaEmX1TVL8lw5vxjJLK4GMMA=\ngithub.com/itchyny/timefmt-go v0.1.7/go.mod h1:5E46Q+zj7vbTgWY8o5YkMeYb4I6GeWLFnetPy5oBrAI=\ngithub.com/leonelquinteros/gotext v1.7.2 h1:bDPndU8nt+/kRo1m4l/1OXiiy2v7Z7dfPQ9+YP7G1Mc=\ngithub.com/leonelquinteros/gotext v1.7.2/go.mod h1:9/haCkm5P7Jay1sxKDGJ5WIg4zkz8oZKw4ekNpALob8=\ngithub.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=\ngithub.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=\ngithub.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4=\ngithub.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=\ngithub.com/ohler55/ojg v1.28.0 h1:8xClBgMIRRJGDUC9xNe7NprP4kD2C3mQMeon3wY4KXA=\ngithub.com/ohler55/ojg v1.28.0/go.mod h1:/Y5dGWkekv9ocnUixuETqiL58f+5pAsUfg5P8e7Pa2o=\ngithub.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=\ngithub.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=\ngithub.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=\ngithub.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4=\ngithub.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0=\ngithub.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=\ngithub.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=\ngithub.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=\ngithub.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=\ngithub.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=\ngithub.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=\ngolang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=\ngolang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=\ngolang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=\ngolang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=\ngolang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU=\ngolang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY=\ngopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0=\ngopkg.in/ini.v1 v1.67.1 h1:tVBILHy0R6e4wkYOn3XmiITt/hEVH4TFMYvAX2Ytz6k=\ngopkg.in/ini.v1 v1.67.1/go.mod h1:x/cyOwCgZqOkJoDIJ3c1KNHMo10+nLGAhh+kn3Zizss=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\n"
  },
  {
    "path": "local_install.go",
    "content": "// Experimental code for install local with dependency refactoring\n// Not at feature parity with install.go\npackage main\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/dep\"\n\t\"github.com/Jguer/yay/v12/pkg/multierror\"\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/sync\"\n\n\tgosrc \"github.com/Morganamilo/go-srcinfo\"\n\t\"github.com/leonelquinteros/gotext\"\n)\n\nvar ErrNoBuildFiles = errors.New(gotext.Get(\"cannot find PKGBUILD and .SRCINFO in directory\"))\n\nfunc srcinfoExists(ctx context.Context,\n\tcmdBuilder exe.ICmdBuilder, targetDir string,\n) error {\n\tsrcInfoDir := filepath.Join(targetDir, \".SRCINFO\")\n\tpkgbuildDir := filepath.Join(targetDir, \"PKGBUILD\")\n\tif _, err := os.Stat(srcInfoDir); err == nil {\n\t\tif _, err := os.Stat(pkgbuildDir); err == nil {\n\t\t\treturn nil\n\t\t}\n\t}\n\n\tif _, err := os.Stat(pkgbuildDir); err == nil {\n\t\t// run makepkg to generate .SRCINFO\n\t\tsrcinfo, stderr, err := cmdBuilder.Capture(cmdBuilder.BuildMakepkgCmd(ctx, targetDir, \"--printsrcinfo\"))\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"unable to generate .SRCINFO: %w - %s\", err, stderr)\n\t\t}\n\n\t\tif srcinfo == \"\" {\n\t\t\treturn fmt.Errorf(\"generated .SRCINFO is empty, check your PKGBUILD for errors\")\n\t\t}\n\n\t\tif err := os.WriteFile(srcInfoDir, []byte(srcinfo), 0o600); err != nil {\n\t\t\treturn fmt.Errorf(\"unable to write .SRCINFO: %w\", err)\n\t\t}\n\n\t\treturn nil\n\t}\n\n\treturn fmt.Errorf(\"%w: %s\", ErrNoBuildFiles, targetDir)\n}\n\nfunc installLocalPKGBUILD(\n\tctx context.Context,\n\trun *runtime.Runtime,\n\tcmdArgs *parser.Arguments,\n\tdbExecutor db.Executor,\n) error {\n\taurCache := run.AURClient\n\tnoCheck := strings.Contains(run.Cfg.MFlags, \"--nocheck\")\n\n\tif len(cmdArgs.Targets) < 1 {\n\t\treturn errors.New(gotext.Get(\"no target directories specified\"))\n\t}\n\n\tsrcInfos := map[string]*gosrc.Srcinfo{}\n\tfor _, targetDir := range cmdArgs.Targets {\n\t\tif err := srcinfoExists(ctx, run.CmdBuilder, targetDir); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tpkgbuild, err := gosrc.ParseFile(filepath.Join(targetDir, \".SRCINFO\"))\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"%s: %w\", gotext.Get(\"failed to parse .SRCINFO\"), err)\n\t\t}\n\n\t\tsrcInfos[targetDir] = pkgbuild\n\t}\n\n\tgrapher := dep.NewGrapher(dbExecutor, aurCache, false, settings.NoConfirm,\n\t\tcmdArgs.ExistsDouble(\"d\", \"nodeps\"), noCheck, cmdArgs.ExistsArg(\"needed\"),\n\t\trun.Logger.Child(\"grapher\"))\n\tgraph, err := grapher.GraphFromSrcInfos(ctx, nil, srcInfos)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\topService := sync.NewOperationService(ctx, dbExecutor, run)\n\tmultiErr := &multierror.MultiError{}\n\ttargets := graph.TopoSortedLayers(func(name string, ii *dep.InstallInfo) error {\n\t\tif ii.Source == dep.Missing {\n\t\t\tmultiErr.Add(fmt.Errorf(\"%w: %s %s\", ErrPackagesNotFound, name, ii.Version))\n\t\t}\n\t\treturn nil\n\t})\n\n\tif err := multiErr.Return(); err != nil {\n\t\treturn err\n\t}\n\treturn opService.Run(ctx, run, cmdArgs, targets, []string{})\n}\n"
  },
  {
    "path": "local_install_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"slices\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n\n\taur \"github.com/Jguer/aur\"\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db/mock\"\n\tmockaur \"github.com/Jguer/yay/v12/pkg/dep/mock\"\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\t\"github.com/Jguer/yay/v12/pkg/vcs\"\n)\n\nfunc newTestLogger() *text.Logger {\n\treturn text.NewLogger(io.Discard, io.Discard, strings.NewReader(\"\"), true, \"test\")\n}\n\nfunc TestIntegrationLocalInstall(t *testing.T) {\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tgitBin := t.TempDir() + \"/git\"\n\ttmpDir := t.TempDir()\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(gitBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\ttars := []string{\n\t\ttmpDir + \"/jellyfin-10.8.4-1-x86_64.pkg.tar.zst\",\n\t\ttmpDir + \"/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst\",\n\t\ttmpDir + \"/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst\",\n\t}\n\n\twantShow := []string{\n\t\t\"makepkg --verifysource --skippgpcheck -f -Cc\",\n\t\t\"pacman -S --config /etc/pacman.conf -- community/dotnet-sdk-6.0 community/dotnet-runtime-6.0\",\n\t\t\"pacman -D -q --asdeps --config /etc/pacman.conf -- dotnet-runtime-6.0 dotnet-sdk-6.0\",\n\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\"makepkg -c --nobuild --noextract --ignorearch\",\n\t\t\"pacman -U --config /etc/pacman.conf -- /testdir/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst /testdir/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst\",\n\t\t\"pacman -D -q --asexplicit --config /etc/pacman.conf -- jellyfin-server jellyfin-web\",\n\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\"makepkg -c --nobuild --noextract --ignorearch\",\n\t\t\"pacman -U --config /etc/pacman.conf -- /testdir/jellyfin-10.8.4-1-x86_64.pkg.tar.zst\",\n\t\t\"pacman -D -q --asexplicit --config /etc/pacman.conf -- jellyfin\",\n\t}\n\n\twantCapture := []string{\n\t\t\"makepkg --packagelist\",\n\t\t\"git -C testdata/jfin git reset --hard HEAD\",\n\t\t\"git -C testdata/jfin git merge --no-edit --ff\",\n\t\t\"makepkg --packagelist\",\n\t}\n\n\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\treturn strings.Join(tars, \"\\n\"), \"\", nil\n\t}\n\n\tonce := sync.Once{}\n\n\tshowOverride := func(cmd *exec.Cmd) error {\n\t\tonce.Do(func() {\n\t\t\tfor _, tar := range tars {\n\t\t\t\tf, err := os.OpenFile(tar, os.O_RDONLY|os.O_CREATE, 0o666)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\trequire.NoError(t, f.Close())\n\t\t\t}\n\t\t})\n\t\treturn nil\n\t}\n\n\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\tcmdBuilder := &exe.CmdBuilder{\n\t\tMakepkgBin:       makepkgBin,\n\t\tSudoBin:          \"su\",\n\t\tPacmanBin:        pacmanBin,\n\t\tPacmanConfigPath: \"/etc/pacman.conf\",\n\t\tGitBin:           \"git\",\n\t\tRunner:           mockRunner,\n\t\tSudoLoopEnabled:  false,\n\t}\n\n\tcmdArgs := parser.MakeArguments()\n\tcmdArgs.AddArg(\"B\")\n\tcmdArgs.AddArg(\"i\")\n\tcmdArgs.AddTarget(\"testdata/jfin\")\n\tsettings.NoConfirm = true\n\tdefer func() { settings.NoConfirm = false }()\n\tdb := &mock.DBExecutor{\n\t\tAlpmArchitecturesFn: func() ([]string, error) {\n\t\t\treturn []string{\"x86_64\"}, nil\n\t\t},\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"dotnet-sdk>=6\", \"dotnet-sdk<7\", \"dotnet-runtime>=6\", \"dotnet-runtime<7\", \"jellyfin-server=10.8.4\", \"jellyfin-web=10.8.4\":\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\treturn true\n\t\t},\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"dotnet-runtime>=6\", \"dotnet-runtime<7\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"dotnet-runtime-6.0\",\n\t\t\t\t\tPBase:    \"dotnet-runtime-6.0\",\n\t\t\t\t\tPVersion: \"6.0.100-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"community\"),\n\t\t\t\t}\n\t\t\tcase \"dotnet-sdk>=6\", \"dotnet-sdk<7\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"dotnet-sdk-6.0\",\n\t\t\t\t\tPBase:    \"dotnet-sdk-6.0\",\n\t\t\t\t\tPVersion: \"6.0.100-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"community\"),\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn nil\n\t\t},\n\t\tLocalPackageFn:                func(s string) mock.IPackage { return nil },\n\t\tInstalledRemotePackageNamesFn: func() []string { return []string{} },\n\t}\n\n\trun := &runtime.Runtime{\n\t\tCfg: &settings.Configuration{\n\t\t\tRemoveMake: \"no\",\n\t\t},\n\t\tLogger:     newTestLogger(),\n\t\tCmdBuilder: cmdBuilder,\n\t\tVCSStore:   &vcs.Mock{},\n\t\tAURClient: &mockaur.MockAUR{\n\t\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\t\treturn []aur.Pkg{}, nil\n\t\t\t},\n\t\t},\n\t}\n\n\terr = handleCmd(context.Background(), run, cmdArgs, db)\n\trequire.NoError(t, err)\n\n\trequire.Len(t, mockRunner.ShowCalls, len(wantShow))\n\trequire.Len(t, mockRunner.CaptureCalls, len(wantCapture))\n\n\tfor i, call := range mockRunner.ShowCalls {\n\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\tshow = strings.ReplaceAll(show, tmpDir, \"/testdir\") // replace the temp dir with a static path\n\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\t\tshow = strings.ReplaceAll(show, gitBin, \"git\")\n\n\t\t// options are in a different order on different systems and on CI root user is used\n\t\tassert.Subset(t, strings.Split(show, \" \"), strings.Split(wantShow[i], \" \"), fmt.Sprintf(\"%d - %s\", i, show))\n\t}\n}\n\nfunc TestIntegrationLocalBuildOnly(t *testing.T) {\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tgitBin := t.TempDir() + \"/git\"\n\ttmpDir := t.TempDir()\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(gitBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\ttars := []string{\n\t\ttmpDir + \"/jellyfin-10.8.4-1-x86_64.pkg.tar.zst\",\n\t\ttmpDir + \"/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst\",\n\t\ttmpDir + \"/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst\",\n\t}\n\n\twantShow := []string{\n\t\t\"makepkg --verifysource --skippgpcheck -f -Cc\",\n\t\t\"pacman -S --config /etc/pacman.conf -- community/dotnet-sdk-6.0 community/dotnet-runtime-6.0\",\n\t\t\"pacman -D -q --asdeps --config /etc/pacman.conf -- dotnet-runtime-6.0 dotnet-sdk-6.0\",\n\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\"makepkg -c --nobuild --noextract --ignorearch\",\n\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\"makepkg -c --nobuild --noextract --ignorearch\",\n\t}\n\n\twantCapture := []string{\n\t\t\"makepkg --packagelist\",\n\t\t\"git -C testdata/jfin git reset --hard HEAD\",\n\t\t\"git -C testdata/jfin git merge --no-edit --ff\",\n\t\t\"makepkg --packagelist\",\n\t}\n\n\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\treturn strings.Join(tars, \"\\n\"), \"\", nil\n\t}\n\n\tonce := sync.Once{}\n\n\tshowOverride := func(cmd *exec.Cmd) error {\n\t\tonce.Do(func() {\n\t\t\tfor _, tar := range tars {\n\t\t\t\tf, err := os.OpenFile(tar, os.O_RDONLY|os.O_CREATE, 0o666)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\trequire.NoError(t, f.Close())\n\t\t\t}\n\t\t})\n\t\treturn nil\n\t}\n\n\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\tcmdBuilder := &exe.CmdBuilder{\n\t\tMakepkgBin:       makepkgBin,\n\t\tSudoBin:          \"su\",\n\t\tPacmanBin:        pacmanBin,\n\t\tPacmanConfigPath: \"/etc/pacman.conf\",\n\t\tGitBin:           \"git\",\n\t\tRunner:           mockRunner,\n\t\tSudoLoopEnabled:  false,\n\t}\n\n\tcmdArgs := parser.MakeArguments()\n\tcmdArgs.AddArg(\"B\")\n\tcmdArgs.AddTarget(\"testdata/jfin\")\n\tsettings.NoConfirm = true\n\tdefer func() { settings.NoConfirm = false }()\n\tdb := &mock.DBExecutor{\n\t\tAlpmArchitecturesFn: func() ([]string, error) {\n\t\t\treturn []string{\"x86_64\"}, nil\n\t\t},\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"dotnet-sdk>=6\", \"dotnet-sdk<7\", \"dotnet-runtime>=6\", \"dotnet-runtime<7\", \"jellyfin-server=10.8.4\", \"jellyfin-web=10.8.4\":\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\treturn true\n\t\t},\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"dotnet-runtime>=6\", \"dotnet-runtime<7\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"dotnet-runtime-6.0\",\n\t\t\t\t\tPBase:    \"dotnet-runtime-6.0\",\n\t\t\t\t\tPVersion: \"6.0.100-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"community\"),\n\t\t\t\t}\n\t\t\tcase \"dotnet-sdk>=6\", \"dotnet-sdk<7\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"dotnet-sdk-6.0\",\n\t\t\t\t\tPBase:    \"dotnet-sdk-6.0\",\n\t\t\t\t\tPVersion: \"6.0.100-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"community\"),\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn nil\n\t\t},\n\t\tLocalPackageFn:                func(s string) mock.IPackage { return nil },\n\t\tInstalledRemotePackageNamesFn: func() []string { return []string{} },\n\t}\n\n\trun := &runtime.Runtime{\n\t\tCfg: &settings.Configuration{\n\t\t\tRemoveMake: \"no\",\n\t\t},\n\t\tLogger:     newTestLogger(),\n\t\tCmdBuilder: cmdBuilder,\n\t\tVCSStore:   &vcs.Mock{},\n\t\tAURClient: &mockaur.MockAUR{\n\t\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\t\treturn []aur.Pkg{}, nil\n\t\t\t},\n\t\t},\n\t}\n\n\terr = handleCmd(context.Background(), run, cmdArgs, db)\n\trequire.NoError(t, err)\n\n\trequire.Len(t, mockRunner.ShowCalls, len(wantShow))\n\trequire.Len(t, mockRunner.CaptureCalls, len(wantCapture))\n\n\tfor i, call := range mockRunner.ShowCalls {\n\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\tshow = strings.ReplaceAll(show, tmpDir, \"/testdir\")\n\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\t\tshow = strings.ReplaceAll(show, gitBin, \"git\")\n\n\t\tassert.Subset(t, strings.Split(show, \" \"), strings.Split(wantShow[i], \" \"), fmt.Sprintf(\"%d - %s\", i, show))\n\t}\n}\n\nfunc TestIntegrationLocalInstallMissingDep(t *testing.T) {\n\twantErr := ErrPackagesNotFound\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tgitBin := t.TempDir() + \"/git\"\n\ttmpDir := t.TempDir()\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(gitBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\ttars := []string{\n\t\ttmpDir + \"/jellyfin-10.8.4-1-x86_64.pkg.tar.zst\",\n\t\ttmpDir + \"/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst\",\n\t\ttmpDir + \"/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst\",\n\t}\n\n\twantShow := []string{}\n\twantCapture := []string{}\n\n\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\treturn strings.Join(tars, \"\\n\"), \"\", nil\n\t}\n\n\tonce := sync.Once{}\n\n\tshowOverride := func(cmd *exec.Cmd) error {\n\t\tonce.Do(func() {\n\t\t\tfor _, tar := range tars {\n\t\t\t\tf, err := os.OpenFile(tar, os.O_RDONLY|os.O_CREATE, 0o666)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\trequire.NoError(t, f.Close())\n\t\t\t}\n\t\t})\n\t\treturn nil\n\t}\n\n\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\tcmdBuilder := &exe.CmdBuilder{\n\t\tMakepkgBin:       makepkgBin,\n\t\tSudoBin:          \"su\",\n\t\tPacmanBin:        pacmanBin,\n\t\tPacmanConfigPath: \"/etc/pacman.conf\",\n\t\tGitBin:           \"git\",\n\t\tRunner:           mockRunner,\n\t\tSudoLoopEnabled:  false,\n\t}\n\n\tcmdArgs := parser.MakeArguments()\n\tcmdArgs.AddArg(\"B\")\n\tcmdArgs.AddArg(\"i\")\n\tcmdArgs.AddTarget(\"testdata/jfin\")\n\tsettings.NoConfirm = true\n\tdefer func() { settings.NoConfirm = false }()\n\tdb := &mock.DBExecutor{\n\t\tAlpmArchitecturesFn: func() ([]string, error) {\n\t\t\treturn []string{\"x86_64\"}, nil\n\t\t},\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"dotnet-sdk>=6\", \"dotnet-sdk<7\", \"dotnet-runtime>=6\", \"dotnet-runtime<7\", \"jellyfin-server=10.8.4\", \"jellyfin-web=10.8.4\":\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\treturn true\n\t\t},\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"dotnet-runtime>=6\", \"dotnet-runtime<7\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"dotnet-runtime-6.0\",\n\t\t\t\t\tPBase:    \"dotnet-runtime-6.0\",\n\t\t\t\t\tPVersion: \"6.0.100-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"community\"),\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn nil\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage { return nil },\n\t}\n\n\trun := &runtime.Runtime{\n\t\tCfg:        &settings.Configuration{},\n\t\tLogger:     newTestLogger(),\n\t\tCmdBuilder: cmdBuilder,\n\t\tVCSStore:   &vcs.Mock{},\n\t\tAURClient: &mockaur.MockAUR{\n\t\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\t\treturn []aur.Pkg{}, nil\n\t\t\t},\n\t\t},\n\t}\n\n\terr = handleCmd(context.Background(), run, cmdArgs, db)\n\trequire.ErrorContains(t, err, wantErr.Error())\n\n\trequire.Len(t, mockRunner.ShowCalls, len(wantShow))\n\trequire.Len(t, mockRunner.CaptureCalls, len(wantCapture))\n\n\tfor i, call := range mockRunner.ShowCalls {\n\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\tshow = strings.ReplaceAll(show, tmpDir, \"/testdir\") // replace the temp dir with a static path\n\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\t\tshow = strings.ReplaceAll(show, gitBin, \"git\")\n\n\t\t// options are in a different order on different systems and on CI root user is used\n\t\tassert.Subset(t, strings.Split(show, \" \"), strings.Split(wantShow[i], \" \"), fmt.Sprintf(\"%d - %s\", i, show))\n\t}\n}\n\nfunc TestIntegrationLocalInstallNeeded(t *testing.T) {\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tgitBin := t.TempDir() + \"/git\"\n\ttmpDir := t.TempDir()\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(gitBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\ttars := []string{\n\t\ttmpDir + \"/jellyfin-10.8.4-1-x86_64.pkg.tar.zst\",\n\t\ttmpDir + \"/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst\",\n\t\ttmpDir + \"/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst\",\n\t}\n\n\twantShow := []string{\n\t\t\"makepkg --verifysource --skippgpcheck -f -Cc\",\n\t\t\"pacman -S --config /etc/pacman.conf -- community/dotnet-sdk-6.0 community/dotnet-runtime-6.0\",\n\t\t\"pacman -D -q --asdeps --config /etc/pacman.conf -- dotnet-runtime-6.0 dotnet-sdk-6.0\",\n\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\"makepkg -c --nobuild --noextract --ignorearch\",\n\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\"makepkg -c --nobuild --noextract --ignorearch\",\n\t}\n\n\twantCapture := []string{\n\t\t\"makepkg --packagelist\",\n\t\t\"git -C testdata/jfin git reset --hard HEAD\",\n\t\t\"git -C testdata/jfin git merge --no-edit --ff\",\n\t\t\"makepkg --packagelist\",\n\t}\n\n\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\treturn strings.Join(tars, \"\\n\"), \"\", nil\n\t}\n\n\tonce := sync.Once{}\n\n\tshowOverride := func(cmd *exec.Cmd) error {\n\t\tonce.Do(func() {\n\t\t\tfor _, tar := range tars {\n\t\t\t\tf, err := os.OpenFile(tar, os.O_RDONLY|os.O_CREATE, 0o666)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\trequire.NoError(t, f.Close())\n\t\t\t}\n\t\t})\n\t\treturn nil\n\t}\n\n\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\tcmdBuilder := &exe.CmdBuilder{\n\t\tMakepkgBin:       makepkgBin,\n\t\tSudoBin:          \"su\",\n\t\tPacmanBin:        pacmanBin,\n\t\tPacmanConfigPath: \"/etc/pacman.conf\",\n\t\tGitBin:           \"git\",\n\t\tRunner:           mockRunner,\n\t\tSudoLoopEnabled:  false,\n\t}\n\n\tcmdArgs := parser.MakeArguments()\n\tcmdArgs.AddArg(\"B\")\n\tcmdArgs.AddArg(\"i\")\n\tcmdArgs.AddArg(\"needed\")\n\tcmdArgs.AddTarget(\"testdata/jfin\")\n\tsettings.NoConfirm = true\n\tdefer func() { settings.NoConfirm = false }()\n\tdb := &mock.DBExecutor{\n\t\tAlpmArchitecturesFn: func() ([]string, error) {\n\t\t\treturn []string{\"x86_64\"}, nil\n\t\t},\n\t\tIsCorrectVersionInstalledFn: func(s1, s2 string) bool {\n\t\t\treturn true\n\t\t},\n\t\tLocalPackageFn: func(s string) mock.IPackage {\n\t\t\tif s == \"jellyfin-server\" {\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"jellyfin-server\",\n\t\t\t\t\tPBase:    \"jellyfin-server\",\n\t\t\t\t\tPVersion: \"10.8.4-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"community\"),\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"dotnet-sdk>=6\", \"dotnet-sdk<7\", \"dotnet-runtime>=6\", \"dotnet-runtime<7\", \"jellyfin-server=10.8.4\", \"jellyfin-web=10.8.4\":\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\treturn true\n\t\t},\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"dotnet-runtime>=6\", \"dotnet-runtime<7\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"dotnet-runtime-6.0\",\n\t\t\t\t\tPBase:    \"dotnet-runtime-6.0\",\n\t\t\t\t\tPVersion: \"6.0.100-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"community\"),\n\t\t\t\t}\n\t\t\tcase \"dotnet-sdk>=6\", \"dotnet-sdk<7\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"dotnet-sdk-6.0\",\n\t\t\t\t\tPBase:    \"dotnet-sdk-6.0\",\n\t\t\t\t\tPVersion: \"6.0.100-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"community\"),\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn nil\n\t\t},\n\t\tInstalledRemotePackageNamesFn: func() []string { return []string{} },\n\t}\n\n\trun := &runtime.Runtime{\n\t\tCfg: &settings.Configuration{\n\t\t\tRemoveMake: \"no\",\n\t\t},\n\t\tLogger:     newTestLogger(),\n\t\tCmdBuilder: cmdBuilder,\n\t\tVCSStore:   &vcs.Mock{},\n\t\tAURClient: &mockaur.MockAUR{\n\t\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\t\treturn []aur.Pkg{}, nil\n\t\t\t},\n\t\t},\n\t}\n\n\terr = handleCmd(context.Background(), run, cmdArgs, db)\n\trequire.NoError(t, err)\n\n\trequire.Len(t, mockRunner.ShowCalls, len(wantShow), \"show calls: %v\", mockRunner.ShowCalls)\n\trequire.Len(t, mockRunner.CaptureCalls, len(wantCapture))\n\n\tfor i, call := range mockRunner.ShowCalls {\n\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\tshow = strings.ReplaceAll(show, tmpDir, \"/testdir\") // replace the temp dir with a static path\n\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\t\tshow = strings.ReplaceAll(show, gitBin, \"git\")\n\n\t\t// options are in a different order on different systems and on CI root user is used\n\t\tassert.Subset(t, strings.Split(show, \" \"), strings.Split(wantShow[i], \" \"), fmt.Sprintf(\"%d - %s\", i, show))\n\t}\n}\n\nfunc TestIntegrationLocalInstallGenerateSRCINFO(t *testing.T) {\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tgitBin := t.TempDir() + \"/git\"\n\ttmpDir := t.TempDir()\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(gitBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tsrcinfo, err := os.ReadFile(\"testdata/jfin/.SRCINFO\")\n\trequire.NoError(t, err)\n\tassert.True(t, strings.HasPrefix(string(srcinfo), \"pkgbase = jellyfin\"), string(srcinfo))\n\n\ttargetDir := t.TempDir()\n\tf, err = os.OpenFile(filepath.Join(targetDir, \"PKGBUILD\"), os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\ttars := []string{\n\t\ttmpDir + \"/jellyfin-10.8.4-1-x86_64.pkg.tar.zst\",\n\t\ttmpDir + \"/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst\",\n\t\ttmpDir + \"/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst\",\n\t}\n\n\twantShow := []string{\n\t\t\"makepkg --verifysource --skippgpcheck -f -Cc\",\n\t\t\"pacman -S --config /etc/pacman.conf -- community/dotnet-sdk-6.0 community/dotnet-runtime-6.0\",\n\t\t\"pacman -D -q --asdeps --config /etc/pacman.conf -- dotnet-runtime-6.0 dotnet-sdk-6.0\",\n\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\"makepkg -c --nobuild --noextract --ignorearch\",\n\t\t\"pacman -U --config /etc/pacman.conf -- /testdir/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst /testdir/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst\",\n\t\t\"pacman -D -q --asexplicit --config /etc/pacman.conf -- jellyfin-server jellyfin-web\",\n\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\"makepkg -c --nobuild --noextract --ignorearch\",\n\t\t\"pacman -U --config /etc/pacman.conf -- /testdir/jellyfin-10.8.4-1-x86_64.pkg.tar.zst\",\n\t\t\"pacman -D -q --asexplicit --config /etc/pacman.conf -- jellyfin\",\n\t}\n\n\twantCapture := []string{\n\t\t\"makepkg --printsrcinfo\",\n\t\t\"makepkg --packagelist\",\n\t\t\"git -C testdata/jfin git reset --hard HEAD\",\n\t\t\"git -C testdata/jfin git merge --no-edit --ff\",\n\t\t\"makepkg --packagelist\",\n\t}\n\n\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\tif slices.Contains(cmd.Args, \"--printsrcinfo\") {\n\t\t\treturn string(srcinfo), \"\", nil\n\t\t}\n\t\treturn strings.Join(tars, \"\\n\"), \"\", nil\n\t}\n\n\tonce := sync.Once{}\n\n\tshowOverride := func(cmd *exec.Cmd) error {\n\t\tonce.Do(func() {\n\t\t\tfor _, tar := range tars {\n\t\t\t\tf, err := os.OpenFile(tar, os.O_RDONLY|os.O_CREATE, 0o666)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\trequire.NoError(t, f.Close())\n\t\t\t}\n\t\t})\n\t\treturn nil\n\t}\n\n\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\tcmdBuilder := &exe.CmdBuilder{\n\t\tMakepkgBin:       makepkgBin,\n\t\tSudoBin:          \"su\",\n\t\tPacmanBin:        pacmanBin,\n\t\tPacmanConfigPath: \"/etc/pacman.conf\",\n\t\tGitBin:           \"git\",\n\t\tRunner:           mockRunner,\n\t\tSudoLoopEnabled:  false,\n\t}\n\n\tcmdArgs := parser.MakeArguments()\n\tcmdArgs.AddArg(\"B\")\n\tcmdArgs.AddArg(\"i\")\n\tcmdArgs.AddTarget(targetDir)\n\tsettings.NoConfirm = true\n\tdefer func() { settings.NoConfirm = false }()\n\tdb := &mock.DBExecutor{\n\t\tAlpmArchitecturesFn: func() ([]string, error) {\n\t\t\treturn []string{\"x86_64\"}, nil\n\t\t},\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"dotnet-sdk>=6\", \"dotnet-sdk<7\", \"dotnet-runtime>=6\", \"dotnet-runtime<7\", \"jellyfin-server=10.8.4\", \"jellyfin-web=10.8.4\":\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\treturn true\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage { return nil },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"dotnet-runtime>=6\", \"dotnet-runtime<7\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"dotnet-runtime-6.0\",\n\t\t\t\t\tPBase:    \"dotnet-runtime-6.0\",\n\t\t\t\t\tPVersion: \"6.0.100-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"community\"),\n\t\t\t\t}\n\t\t\tcase \"dotnet-sdk>=6\", \"dotnet-sdk<7\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"dotnet-sdk-6.0\",\n\t\t\t\t\tPBase:    \"dotnet-sdk-6.0\",\n\t\t\t\t\tPVersion: \"6.0.100-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"community\"),\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn nil\n\t\t},\n\t\tInstalledRemotePackageNamesFn: func() []string { return []string{} },\n\t}\n\n\trun := &runtime.Runtime{\n\t\tCfg: &settings.Configuration{\n\t\t\tRemoveMake: \"no\",\n\t\t\tDebug:      false,\n\t\t},\n\t\tLogger:     newTestLogger(),\n\t\tCmdBuilder: cmdBuilder,\n\t\tVCSStore:   &vcs.Mock{},\n\t\tAURClient: &mockaur.MockAUR{\n\t\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\t\treturn []aur.Pkg{}, nil\n\t\t\t},\n\t\t},\n\t}\n\n\terr = handleCmd(context.Background(), run, cmdArgs, db)\n\trequire.NoError(t, err)\n\n\trequire.Len(t, mockRunner.ShowCalls, len(wantShow))\n\trequire.Len(t, mockRunner.CaptureCalls, len(wantCapture))\n\n\tfor i, call := range mockRunner.ShowCalls {\n\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\tshow = strings.ReplaceAll(show, tmpDir, \"/testdir\") // replace the temp dir with a static path\n\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\t\tshow = strings.ReplaceAll(show, gitBin, \"git\")\n\n\t\t// options are in a different order on different systems and on CI root user is used\n\t\tassert.Subset(t, strings.Split(show, \" \"), strings.Split(wantShow[i], \" \"), fmt.Sprintf(\"%d - %s\", i, show))\n\t}\n}\n\nfunc TestIntegrationLocalInstallMissingFiles(t *testing.T) {\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tgitBin := t.TempDir() + \"/git\"\n\ttmpDir := t.TempDir()\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(gitBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tsrcinfo, err := os.ReadFile(\"testdata/jfin/.SRCINFO\")\n\trequire.NoError(t, err)\n\n\ttargetDir := t.TempDir()\n\n\ttars := []string{\n\t\ttmpDir + \"/jellyfin-10.8.4-1-x86_64.pkg.tar.zst\",\n\t\ttmpDir + \"/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst\",\n\t\ttmpDir + \"/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst\",\n\t}\n\n\twantShow := []string{}\n\n\twantCapture := []string{}\n\n\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\tif cmd.Args[1] == \"--printsrcinfo\" {\n\t\t\treturn string(srcinfo), \"\", nil\n\t\t}\n\t\treturn strings.Join(tars, \"\\n\"), \"\", nil\n\t}\n\n\tonce := sync.Once{}\n\n\tshowOverride := func(cmd *exec.Cmd) error {\n\t\tonce.Do(func() {\n\t\t\tfor _, tar := range tars {\n\t\t\t\tf, err := os.OpenFile(tar, os.O_RDONLY|os.O_CREATE, 0o666)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\trequire.NoError(t, f.Close())\n\t\t\t}\n\t\t})\n\t\treturn nil\n\t}\n\n\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\tcmdBuilder := &exe.CmdBuilder{\n\t\tMakepkgBin:       makepkgBin,\n\t\tSudoBin:          \"su\",\n\t\tPacmanBin:        pacmanBin,\n\t\tPacmanConfigPath: \"/etc/pacman.conf\",\n\t\tGitBin:           \"git\",\n\t\tRunner:           mockRunner,\n\t\tSudoLoopEnabled:  false,\n\t}\n\n\tcmdArgs := parser.MakeArguments()\n\tcmdArgs.AddArg(\"B\")\n\tcmdArgs.AddArg(\"i\")\n\tcmdArgs.AddTarget(targetDir)\n\tsettings.NoConfirm = true\n\tdefer func() { settings.NoConfirm = false }()\n\tdb := &mock.DBExecutor{\n\t\tAlpmArchitecturesFn: func() ([]string, error) {\n\t\t\treturn []string{\"x86_64\"}, nil\n\t\t},\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"dotnet-sdk>=6\", \"dotnet-sdk<7\", \"dotnet-runtime>=6\", \"dotnet-runtime<7\", \"jellyfin-server=10.8.4\", \"jellyfin-web=10.8.4\":\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\treturn true\n\t\t},\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"dotnet-runtime>=6\", \"dotnet-runtime<7\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"dotnet-runtime-6.0\",\n\t\t\t\t\tPBase:    \"dotnet-runtime-6.0\",\n\t\t\t\t\tPVersion: \"6.0.100-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"community\"),\n\t\t\t\t}\n\t\t\tcase \"dotnet-sdk>=6\", \"dotnet-sdk<7\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"dotnet-sdk-6.0\",\n\t\t\t\t\tPBase:    \"dotnet-sdk-6.0\",\n\t\t\t\t\tPVersion: \"6.0.100-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"community\"),\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn nil\n\t\t},\n\t}\n\n\tconfig := &runtime.Runtime{\n\t\tCfg: &settings.Configuration{\n\t\t\tRemoveMake: \"no\",\n\t\t\tDebug:      false,\n\t\t},\n\t\tLogger:     newTestLogger(),\n\t\tCmdBuilder: cmdBuilder,\n\t\tVCSStore:   &vcs.Mock{},\n\t\tAURClient: &mockaur.MockAUR{\n\t\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\t\treturn []aur.Pkg{}, nil\n\t\t\t},\n\t\t},\n\t}\n\n\terr = handleCmd(context.Background(), config, cmdArgs, db)\n\trequire.ErrorIs(t, err, ErrNoBuildFiles)\n\n\trequire.Len(t, mockRunner.ShowCalls, len(wantShow))\n\trequire.Len(t, mockRunner.CaptureCalls, len(wantCapture))\n\n\tfor i, call := range mockRunner.ShowCalls {\n\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\tshow = strings.ReplaceAll(show, tmpDir, \"/testdir\") // replace the temp dir with a static path\n\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\t\tshow = strings.ReplaceAll(show, gitBin, \"git\")\n\n\t\t// options are in a different order on different systems and on CI root user is used\n\t\tassert.Subset(t, strings.Split(show, \" \"), strings.Split(wantShow[i], \" \"), fmt.Sprintf(\"%d - %s\", i, show))\n\t}\n}\n\nfunc TestIntegrationLocalInstallWithDepsProvides(t *testing.T) {\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tgitBin := t.TempDir() + \"/git\"\n\ttmpDir := t.TempDir()\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(gitBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\ttars := []string{\n\t\ttmpDir + \"/ceph-bin-17.2.6-2-x86_64.pkg.tar.zst\",\n\t\ttmpDir + \"/ceph-libs-bin-17.2.6-2-x86_64.pkg.tar.zst\",\n\t}\n\n\twantShow := []string{\n\t\t\"makepkg --verifysource --skippgpcheck -f -Cc\",\n\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\"makepkg -c --nobuild --noextract --ignorearch\",\n\t\t\"pacman -U --config /etc/pacman.conf -- /testdir/ceph-libs-bin-17.2.6-2-x86_64.pkg.tar.zst\",\n\t\t\"pacman -D -q --asexplicit --config /etc/pacman.conf -- ceph-libs-bin\",\n\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\"makepkg -c --nobuild --noextract --ignorearch\",\n\t\t\"pacman -U --config /etc/pacman.conf -- /testdir/ceph-bin-17.2.6-2-x86_64.pkg.tar.zst\",\n\t\t\"pacman -D -q --asexplicit --config /etc/pacman.conf -- ceph-bin\",\n\t}\n\n\twantCapture := []string{\n\t\t\"git -C testdata/cephbin git reset --hard HEAD\",\n\t\t\"git -C testdata/cephbin git merge --no-edit --ff\",\n\t\t\"makepkg --packagelist\",\n\t\t\"makepkg --packagelist\",\n\t}\n\n\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\treturn strings.Join(tars, \"\\n\"), \"\", nil\n\t}\n\n\tonce := sync.Once{}\n\n\tshowOverride := func(cmd *exec.Cmd) error {\n\t\tonce.Do(func() {\n\t\t\tfor _, tar := range tars {\n\t\t\t\tf, err := os.OpenFile(tar, os.O_RDONLY|os.O_CREATE, 0o666)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\trequire.NoError(t, f.Close())\n\t\t\t}\n\t\t})\n\t\treturn nil\n\t}\n\n\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\tcmdBuilder := &exe.CmdBuilder{\n\t\tMakepkgBin:       makepkgBin,\n\t\tSudoBin:          \"su\",\n\t\tPacmanBin:        pacmanBin,\n\t\tPacmanConfigPath: \"/etc/pacman.conf\",\n\t\tGitBin:           \"git\",\n\t\tRunner:           mockRunner,\n\t\tSudoLoopEnabled:  false,\n\t}\n\n\tcmdArgs := parser.MakeArguments()\n\tcmdArgs.AddArg(\"B\")\n\tcmdArgs.AddArg(\"i\")\n\tcmdArgs.AddTarget(\"testdata/cephbin\")\n\tsettings.NoConfirm = true\n\tdefer func() { settings.NoConfirm = false }()\n\tdb := &mock.DBExecutor{\n\t\tAlpmArchitecturesFn: func() ([]string, error) {\n\t\t\treturn []string{\"x86_64\"}, nil\n\t\t},\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"ceph=17.2.6-2\", \"ceph-libs=17.2.6-2\":\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\treturn true\n\t\t},\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\treturn nil\n\t\t},\n\t\tLocalPackageFn:                func(s string) mock.IPackage { return nil },\n\t\tInstalledRemotePackageNamesFn: func() []string { return []string{} },\n\t}\n\n\tconfig := &runtime.Runtime{\n\t\tCfg: &settings.Configuration{\n\t\t\tRemoveMake: \"no\",\n\t\t},\n\t\tLogger:     newTestLogger(),\n\t\tCmdBuilder: cmdBuilder,\n\t\tVCSStore:   &vcs.Mock{},\n\t\tAURClient: &mockaur.MockAUR{\n\t\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\t\treturn []aur.Pkg{}, nil\n\t\t\t},\n\t\t},\n\t}\n\n\terr = handleCmd(context.Background(), config, cmdArgs, db)\n\trequire.NoError(t, err)\n\n\trequire.Len(t, mockRunner.ShowCalls, len(wantShow))\n\trequire.Len(t, mockRunner.CaptureCalls, len(wantCapture))\n\n\tfor i, call := range mockRunner.ShowCalls {\n\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\tshow = strings.ReplaceAll(show, tmpDir, \"/testdir\") // replace the temp dir with a static path\n\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\t\tshow = strings.ReplaceAll(show, gitBin, \"git\")\n\n\t\t// options are in a different order on different systems and on CI root user is used\n\t\tassert.Subset(t, strings.Split(show, \" \"), strings.Split(wantShow[i], \" \"), fmt.Sprintf(\"%d - %s\", i, show))\n\t}\n}\n\nfunc TestIntegrationLocalInstallTwoSrcInfosWithDeps(t *testing.T) {\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tgitBin := t.TempDir() + \"/git\"\n\ttmpDir1 := t.TempDir()\n\ttmpDir2 := t.TempDir()\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(gitBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tpkgsTars := []string{\n\t\ttmpDir1 + \"/libzip-git-1.9.2.r166.gd2c47d0f-1-x86_64.pkg.tar.zst\",\n\t\ttmpDir2 + \"/gourou-0.8.1-4-x86_64.pkg.tar.zst\",\n\t}\n\n\twantShow := []string{\n\t\t\"makepkg --verifysource --skippgpcheck -f -Cc\",\n\t\t\"makepkg --verifysource --skippgpcheck -f -Cc\",\n\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\"makepkg -c --nobuild --noextract --ignorearch\",\n\t\t\"pacman -U --config /etc/pacman.conf -- /testdir1/libzip-git-1.9.2.r166.gd2c47d0f-1-x86_64.pkg.tar.zst\",\n\t\t\"pacman -D -q --asexplicit --config /etc/pacman.conf -- libzip-git\",\n\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\"makepkg -c --nobuild --noextract --ignorearch\",\n\t\t\"pacman -U --config /etc/pacman.conf -- /testdir2/gourou-0.8.1-4-x86_64.pkg.tar.zst\",\n\t\t\"pacman -D -q --asexplicit --config /etc/pacman.conf -- gourou\",\n\t}\n\n\twantCapture := []string{\n\t\t\"git -C testdata/gourou git reset --hard HEAD\",\n\t\t\"git -C testdata/gourou git merge --no-edit --ff\",\n\t\t\"git -C testdata/libzip-git git reset --hard HEAD\",\n\t\t\"git -C testdata/libzip-git git merge --no-edit --ff\",\n\t\t\"makepkg --packagelist\",\n\t\t\"makepkg --packagelist\",\n\t}\n\n\tcaptureCounter := 0\n\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\tcaptureCounter++\n\t\tswitch captureCounter {\n\t\tcase 5:\n\t\t\treturn pkgsTars[0] + \"\\n\", \"\", nil\n\t\tcase 6:\n\t\t\treturn pkgsTars[1] + \"\\n\", \"\", nil\n\t\tdefault:\n\t\t\treturn \"\", \"\", nil\n\t\t}\n\t}\n\n\tonce := sync.Once{}\n\n\tshowOverride := func(cmd *exec.Cmd) error {\n\t\tonce.Do(func() {\n\t\t\tfor _, tar := range pkgsTars {\n\t\t\t\tf, err := os.OpenFile(tar, os.O_RDONLY|os.O_CREATE, 0o666)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\trequire.NoError(t, f.Close())\n\t\t\t}\n\t\t})\n\t\treturn nil\n\t}\n\n\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\tcmdBuilder := &exe.CmdBuilder{\n\t\tMakepkgBin:       makepkgBin,\n\t\tSudoBin:          \"su\",\n\t\tPacmanBin:        pacmanBin,\n\t\tPacmanConfigPath: \"/etc/pacman.conf\",\n\t\tGitBin:           \"git\",\n\t\tRunner:           mockRunner,\n\t\tSudoLoopEnabled:  false,\n\t}\n\n\tcmdArgs := parser.MakeArguments()\n\tcmdArgs.AddArg(\"B\")\n\tcmdArgs.AddArg(\"i\")\n\tcmdArgs.AddTarget(\"testdata/gourou\")\n\tcmdArgs.AddTarget(\"testdata/libzip-git\")\n\tsettings.NoConfirm = true\n\tdefer func() { settings.NoConfirm = false }()\n\tdb := &mock.DBExecutor{\n\t\tAlpmArchitecturesFn: func() ([]string, error) {\n\t\t\treturn []string{\"x86_64\"}, nil\n\t\t},\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"gourou\", \"libzip\", \"libzip-git\":\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\treturn true\n\t\t},\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\treturn nil\n\t\t},\n\t\tLocalPackageFn:                func(s string) mock.IPackage { return nil },\n\t\tInstalledRemotePackageNamesFn: func() []string { return []string{} },\n\t}\n\n\trun := &runtime.Runtime{\n\t\tCfg: &settings.Configuration{\n\t\t\tRemoveMake: \"no\",\n\t\t},\n\t\tLogger:     newTestLogger(),\n\t\tCmdBuilder: cmdBuilder,\n\t\tVCSStore:   &vcs.Mock{},\n\t\tAURClient: &mockaur.MockAUR{\n\t\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\t\treturn []aur.Pkg{}, nil\n\t\t\t},\n\t\t},\n\t}\n\n\terr = handleCmd(context.Background(), run, cmdArgs, db)\n\trequire.NoError(t, err)\n\n\trequire.Len(t, mockRunner.ShowCalls, len(wantShow))\n\trequire.Len(t, mockRunner.CaptureCalls, len(wantCapture))\n\n\tfor i, call := range mockRunner.ShowCalls {\n\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\tshow = strings.ReplaceAll(show, tmpDir1, \"/testdir1\") // replace the temp dir with a static path\n\t\tshow = strings.ReplaceAll(show, tmpDir2, \"/testdir2\") // replace the temp dir with a static path\n\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\t\tshow = strings.ReplaceAll(show, gitBin, \"git\")\n\n\t\t// options are in a different order on different systems and on CI root user is used\n\t\tassert.Subset(t, strings.Split(show, \" \"), strings.Split(wantShow[i], \" \"), fmt.Sprintf(\"%d - %s\", i, show))\n\t}\n}\n"
  },
  {
    "path": "main.go",
    "content": "package main // import \"github.com/Jguer/yay\"\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"os\"\n\t\"os/exec\"\n\t\"runtime/debug\"\n\t\"strings\"\n\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db/ialpm\"\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\nvar (\n\tyayVersion = \"13.0.0\"            // To be set by compiler.\n\tlocalePath = \"/usr/share/locale\" // To be set by compiler.\n)\n\nfunc initGotext() {\n\tif envLocalePath := os.Getenv(\"LOCALE_PATH\"); envLocalePath != \"\" {\n\t\tlocalePath = envLocalePath\n\t}\n\n\tif lc := os.Getenv(\"LANGUAGE\"); lc != \"\" {\n\t\t// Split LANGUAGE by ':' and prioritize the first locale\n\t\t// Should fix in gotext to support this\n\t\tlocales := strings.Split(lc, \":\")\n\t\tif len(locales) > 0 && locales[0] != \"\" {\n\t\t\tgotext.Configure(localePath, locales[0], \"yay\")\n\t\t}\n\t} else if lc := os.Getenv(\"LC_ALL\"); lc != \"\" {\n\t\tgotext.Configure(localePath, lc, \"yay\")\n\t} else if lc := os.Getenv(\"LC_MESSAGES\"); lc != \"\" {\n\t\tgotext.Configure(localePath, lc, \"yay\")\n\t} else {\n\t\tgotext.Configure(localePath, os.Getenv(\"LANG\"), \"yay\")\n\t}\n}\n\nfunc main() {\n\tfallbackLog := text.NewLogger(os.Stdout, os.Stderr, os.Stdin, false, \"fallback\")\n\tvar (\n\t\terr error\n\t\tctx = context.Background()\n\t\tret = 0\n\t)\n\n\tdefer func() {\n\t\tif rec := recover(); rec != nil {\n\t\t\tfallbackLog.Errorln(\"Panic occurred:\", rec)\n\t\t\tfallbackLog.Errorln(\"Stack trace:\", string(debug.Stack()))\n\t\t\tret = 1\n\t\t}\n\n\t\tos.Exit(ret)\n\t}()\n\n\tinitGotext()\n\n\tif os.Geteuid() == 0 {\n\t\tfallbackLog.Warnln(gotext.Get(\"Avoid running yay as root/sudo.\"))\n\t}\n\n\tconfigPath := settings.GetConfigPath()\n\t// Parse config\n\tcfg, err := settings.NewConfig(fallbackLog, configPath, yayVersion)\n\tif err != nil {\n\t\tif str := err.Error(); str != \"\" {\n\t\t\tfallbackLog.Errorln(str)\n\t\t}\n\n\t\tret = 1\n\n\t\treturn\n\t}\n\n\tcmdArgs := parser.MakeArguments()\n\n\t// Parse command line\n\tif err = cfg.ParseCommandLine(cmdArgs); err != nil {\n\t\tif str := err.Error(); str != \"\" {\n\t\t\tfallbackLog.Errorln(str)\n\t\t}\n\n\t\tret = 1\n\n\t\treturn\n\t}\n\n\tif cfg.SaveConfig {\n\t\tif errS := cfg.Save(configPath, yayVersion); errS != nil {\n\t\t\tfallbackLog.Errorln(errS)\n\t\t}\n\t}\n\n\t// Build run\n\trun, err := runtime.NewRuntime(cfg, cmdArgs, yayVersion)\n\tif err != nil {\n\t\tif str := err.Error(); str != \"\" {\n\t\t\tfallbackLog.Errorln(str)\n\t\t}\n\n\t\tret = 1\n\n\t\treturn\n\t}\n\n\tdbExecutor, err := ialpm.NewExecutor(run.PacmanConf, run.Logger.Child(\"db\"))\n\tif err != nil {\n\t\tif str := err.Error(); str != \"\" {\n\t\t\tfallbackLog.Errorln(str)\n\t\t}\n\n\t\tret = 1\n\n\t\treturn\n\t}\n\n\tdefer func() {\n\t\tif rec := recover(); rec != nil {\n\t\t\tfallbackLog.Errorln(\"Panic occurred in DB operation:\", rec)\n\t\t\tfallbackLog.Errorln(\"Stack trace:\", string(debug.Stack()))\n\t\t}\n\n\t\tdbExecutor.Cleanup()\n\t}()\n\n\tif err = handleCmd(ctx, run, cmdArgs, dbExecutor); err != nil {\n\t\tif str := err.Error(); str != \"\" {\n\t\t\tfallbackLog.Errorln(str)\n\t\t}\n\n\t\texitError := &exec.ExitError{}\n\t\tif errors.As(err, &exitError) {\n\t\t\t// mirror pacman exit code when applicable\n\t\t\tret = exitError.ExitCode()\n\t\t\treturn\n\t\t}\n\n\t\t// fallback\n\t\tret = 1\n\t}\n}\n"
  },
  {
    "path": "pkg/cmd/graph/main.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db/ialpm\"\n\t\"github.com/Jguer/yay/v12/pkg/dep\"\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\n\t\"github.com/Jguer/aur/metadata\"\n\t\"github.com/leonelquinteros/gotext\"\n)\n\nfunc handleCmd(logger *text.Logger) error {\n\tcfg, err := settings.NewConfig(logger, settings.GetConfigPath(), \"\")\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tcmdArgs := parser.MakeArguments()\n\tif errP := cfg.ParseCommandLine(cmdArgs); errP != nil {\n\t\treturn errP\n\t}\n\n\trun, err := runtime.NewRuntime(cfg, cmdArgs, \"1.0.0\")\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tdbExecutor, err := ialpm.NewExecutor(run.PacmanConf, logger)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\taurCache, err := metadata.New(\n\t\tmetadata.WithCacheFilePath(\n\t\t\tfilepath.Join(cfg.BuildDir, \"aur.json\")))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%s: %w\", gotext.Get(\"failed to retrieve aur Cache\"), err)\n\t}\n\n\tgrapher := dep.NewGrapher(dbExecutor, aurCache, true, settings.NoConfirm,\n\t\tcmdArgs.ExistsDouble(\"d\", \"nodeps\"), false, false,\n\t\trun.Logger.Child(\"grapher\"))\n\n\treturn graphPackage(context.Background(), grapher, cmdArgs.Targets)\n}\n\nfunc main() {\n\tfallbackLog := text.NewLogger(os.Stdout, os.Stderr, os.Stdin, false, \"fallback\")\n\tif err := handleCmd(fallbackLog); err != nil {\n\t\tfallbackLog.Errorln(err)\n\t\tos.Exit(1)\n\t}\n}\n\nfunc graphPackage(\n\tctx context.Context,\n\tgrapher *dep.Grapher,\n\ttargets []string,\n) error {\n\tif len(targets) != 1 {\n\t\treturn errors.New(gotext.Get(\"only one target is allowed\"))\n\t}\n\n\tgraph, err := grapher.GraphFromAUR(ctx, nil, []string{targets[0]})\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfmt.Fprintln(os.Stdout, graph.String())\n\tfmt.Fprintln(os.Stdout, \"\\nlayers map\\n\", graph.TopoSortedLayers(nil))\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/completion/completion.go",
    "content": "package completion\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/download\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\n// NeedsUpdate checks if the completion cache needs to be regenerated.\n// Returns true if the file doesn't exist, is older than interval days, is empty, or force is true.\nfunc NeedsUpdate(completionPath string, interval int, force bool) bool {\n\tif force {\n\t\treturn true\n\t}\n\n\tinfo, err := os.Stat(completionPath)\n\tif os.IsNotExist(err) {\n\t\treturn true\n\t}\n\n\t// If the file is empty or invalid, regenerate it\n\tif info.Size() == 0 {\n\t\treturn true\n\t}\n\n\tif interval != -1 && time.Since(info.ModTime()).Hours() >= float64(interval*24) {\n\t\treturn true\n\t}\n\n\treturn false\n}\n\ntype PkgSynchronizer interface {\n\tSyncPackages(...string) []db.IPackage\n}\n\n// Show provides completion info for shells.\nfunc Show(ctx context.Context, httpClient download.HTTPRequestDoer,\n\tdbExecutor PkgSynchronizer, aurURL, completionPath string, interval int, force bool, logger *text.Logger,\n) error {\n\tif NeedsUpdate(completionPath, interval, force) {\n\t\tif err := UpdateCache(ctx, httpClient, dbExecutor, aurURL, completionPath, logger); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tin, err := os.OpenFile(completionPath, os.O_RDWR|os.O_CREATE, 0o644)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer in.Close()\n\n\t_, err = io.Copy(os.Stdout, in)\n\n\treturn err\n}\n\n// UpdateCache regenerates the completion cache file unconditionally.\nfunc UpdateCache(ctx context.Context, httpClient download.HTTPRequestDoer,\n\tdbExecutor PkgSynchronizer, aurURL, completionPath string, logger *text.Logger,\n) error {\n\tif err := os.MkdirAll(filepath.Dir(completionPath), 0o755); err != nil {\n\t\treturn err\n\t}\n\n\tout, err := os.Create(completionPath)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer out.Close()\n\n\tif err := createAURList(ctx, httpClient, aurURL, out, logger); err != nil {\n\t\tos.Remove(completionPath)\n\t\treturn err\n\t}\n\n\treturn createRepoList(dbExecutor, out)\n}\n\n// createAURList creates a new completion file.\nfunc createAURList(ctx context.Context, client download.HTTPRequestDoer, aurURL string, out io.Writer, logger *text.Logger) error {\n\tscanner, err := download.GetPackageScanner(ctx, client, aurURL, logger)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer scanner.Close()\n\n\tscanner.Scan()\n\n\tfor scanner.Scan() {\n\t\tpkgName := scanner.Text()\n\t\tif strings.HasPrefix(pkgName, \"#\") {\n\t\t\tcontinue\n\t\t}\n\n\t\tif _, err := io.WriteString(out, pkgName+\"\\tAUR\\n\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// createRepoList appends Repo packages to completion cache.\nfunc createRepoList(dbExecutor PkgSynchronizer, out io.Writer) error {\n\tfor _, pkg := range dbExecutor.SyncPackages() {\n\t\t_, err := io.WriteString(out, pkg.Name()+\"\\t\"+pkg.DB().Name()+\"\\n\")\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/completion/completion_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage completion\n\nimport (\n\t\"bytes\"\n\t\"compress/gzip\"\n\t\"context\"\n\t\"errors\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/db/mock\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n)\n\nconst samplePackageResp = `\n# AUR package list, generated on Fri, 24 Jul 2020 22:05:22 GMT\ncytadela\nbitefusion\nglobs-svn\nri-li\nglobs-benchmarks-svn\ndunelegacy\nlumina\neternallands-sound\n`\n\nconst expectPackageCompletion = `cytadela\tAUR\nbitefusion\tAUR\nglobs-svn\tAUR\nri-li\tAUR\nglobs-benchmarks-svn\tAUR\ndunelegacy\tAUR\nlumina\tAUR\neternallands-sound\tAUR\n`\n\ntype mockDoer struct {\n\tt                *testing.T\n\treturnBody       []byte\n\treturnStatusCode int\n\treturnErr        error\n\twantURL          string\n}\n\nfunc (m *mockDoer) Get(url string) (*http.Response, error) {\n\tassert.Equal(m.t, m.wantURL, url)\n\treturn &http.Response{\n\t\tStatusCode: m.returnStatusCode,\n\t\tBody:       io.NopCloser(bytes.NewReader(m.returnBody)),\n\t}, m.returnErr\n}\n\nfunc gzipString(s string) []byte {\n\tvar buf bytes.Buffer\n\tgz := gzip.NewWriter(&buf)\n\tgz.Write([]byte(s))\n\tgz.Close()\n\treturn buf.Bytes()\n}\n\nfunc Test_createAURList(t *testing.T) {\n\tt.Parallel()\n\tdoer := &mockDoer{\n\t\tt:                t,\n\t\twantURL:          \"https://aur.archlinux.org/packages.gz\",\n\t\treturnStatusCode: 200,\n\t\treturnBody:       []byte(samplePackageResp),\n\t\treturnErr:        nil,\n\t}\n\tout := &bytes.Buffer{}\n\terr := createAURList(context.Background(), doer, \"https://aur.archlinux.org\", out, nil)\n\tassert.NoError(t, err)\n\tgotOut := out.String()\n\tassert.Equal(t, expectPackageCompletion, gotOut)\n}\n\nfunc Test_createAURListGzip(t *testing.T) {\n\tt.Parallel()\n\tdoer := &mockDoer{\n\t\tt:                t,\n\t\twantURL:          \"https://aur.archlinux.org/packages.gz\",\n\t\treturnStatusCode: 200,\n\t\treturnBody:       gzipString(samplePackageResp),\n\t\treturnErr:        nil,\n\t}\n\tout := &bytes.Buffer{}\n\terr := createAURList(context.Background(), doer, \"https://aur.archlinux.org\", out, nil)\n\tassert.NoError(t, err)\n\tgotOut := out.String()\n\tassert.Equal(t, expectPackageCompletion, gotOut)\n}\n\nfunc Test_createAURListHTTPError(t *testing.T) {\n\tt.Parallel()\n\tdoer := &mockDoer{\n\t\tt:                t,\n\t\twantURL:          \"https://aur.archlinux.org/packages.gz\",\n\t\treturnStatusCode: 200,\n\t\treturnBody:       []byte(samplePackageResp),\n\t\treturnErr:        errors.New(\"Not available\"),\n\t}\n\n\tout := &bytes.Buffer{}\n\terr := createAURList(context.Background(), doer, \"https://aur.archlinux.org\", out, nil)\n\tassert.EqualError(t, err, \"Not available\")\n}\n\nfunc Test_createAURListStatusError(t *testing.T) {\n\tt.Parallel()\n\tdoer := &mockDoer{\n\t\tt:                t,\n\t\twantURL:          \"https://aur.archlinux.org/packages.gz\",\n\t\treturnStatusCode: 503,\n\t\treturnBody:       []byte(samplePackageResp),\n\t\treturnErr:        nil,\n\t}\n\n\tout := &bytes.Buffer{}\n\terr := createAURList(context.Background(), doer, \"https://aur.archlinux.org\", out, nil)\n\tassert.EqualError(t, err, \"invalid status code: 503\")\n}\n\nfunc TestNeedsUpdate(t *testing.T) {\n\tt.Parallel()\n\n\ttests := []struct {\n\t\tname           string\n\t\tsetupFile      func(t *testing.T, path string)\n\t\tinterval       int\n\t\tforce          bool\n\t\texpectedResult bool\n\t}{\n\t\t{\n\t\t\tname:           \"force returns true\",\n\t\t\tsetupFile:      nil,\n\t\t\tinterval:       7,\n\t\t\tforce:          true,\n\t\t\texpectedResult: true,\n\t\t},\n\t\t{\n\t\t\tname:           \"file does not exist returns true\",\n\t\t\tsetupFile:      nil,\n\t\t\tinterval:       7,\n\t\t\tforce:          false,\n\t\t\texpectedResult: true,\n\t\t},\n\t\t{\n\t\t\tname: \"fresh file returns false\",\n\t\t\tsetupFile: func(t *testing.T, path string) {\n\t\t\t\tt.Helper()\n\t\t\t\terr := os.WriteFile(path, []byte(\"test\"), 0o600)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t},\n\t\t\tinterval:       7,\n\t\t\tforce:          false,\n\t\t\texpectedResult: false,\n\t\t},\n\t\t{\n\t\t\tname: \"interval -1 never updates\",\n\t\t\tsetupFile: func(t *testing.T, path string) {\n\t\t\t\tt.Helper()\n\t\t\t\terr := os.WriteFile(path, []byte(\"test\"), 0o600)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\t// Set file time to 30 days ago\n\t\t\t\toldTime := time.Now().Add(-30 * 24 * time.Hour)\n\t\t\t\terr = os.Chtimes(path, oldTime, oldTime)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t},\n\t\t\tinterval:       -1,\n\t\t\tforce:          false,\n\t\t\texpectedResult: false,\n\t\t},\n\t\t{\n\t\t\tname: \"old file returns true\",\n\t\t\tsetupFile: func(t *testing.T, path string) {\n\t\t\t\tt.Helper()\n\t\t\t\terr := os.WriteFile(path, []byte(\"test\"), 0o600)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\t// Set file time to 10 days ago\n\t\t\t\toldTime := time.Now().Add(-10 * 24 * time.Hour)\n\t\t\t\terr = os.Chtimes(path, oldTime, oldTime)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t},\n\t\t\tinterval:       7,\n\t\t\tforce:          false,\n\t\t\texpectedResult: true,\n\t\t},\n\t\t{\n\t\t\tname: \"file within interval returns false\",\n\t\t\tsetupFile: func(t *testing.T, path string) {\n\t\t\t\tt.Helper()\n\t\t\t\terr := os.WriteFile(path, []byte(\"test\"), 0o600)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\t// Set file time to 3 days ago\n\t\t\t\toldTime := time.Now().Add(-3 * 24 * time.Hour)\n\t\t\t\terr = os.Chtimes(path, oldTime, oldTime)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t},\n\t\t\tinterval:       7,\n\t\t\tforce:          false,\n\t\t\texpectedResult: false,\n\t\t},\n\t\t{\n\t\t\tname: \"empty file returns true\",\n\t\t\tsetupFile: func(t *testing.T, path string) {\n\t\t\t\tt.Helper()\n\t\t\t\t// Create an empty file\n\t\t\t\terr := os.WriteFile(path, []byte(\"\"), 0o600)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t},\n\t\t\tinterval:       7,\n\t\t\tforce:          false,\n\t\t\texpectedResult: true,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\ttmpDir := t.TempDir()\n\t\t\tcompletionPath := filepath.Join(tmpDir, \"completion\")\n\n\t\t\tif tt.setupFile != nil {\n\t\t\t\ttt.setupFile(t, completionPath)\n\t\t\t}\n\n\t\t\tresult := NeedsUpdate(completionPath, tt.interval, tt.force)\n\t\t\tassert.Equal(t, tt.expectedResult, result)\n\t\t})\n\t}\n}\n\n// mockPkgSynchronizer implements PkgSynchronizer for testing.\ntype mockPkgSynchronizer struct {\n\tpackages []db.IPackage\n}\n\nfunc (m *mockPkgSynchronizer) SyncPackages(...string) []db.IPackage {\n\treturn m.packages\n}\n\nfunc Test_createRepoList(t *testing.T) {\n\tt.Parallel()\n\n\ttests := []struct {\n\t\tname           string\n\t\tpackages       []db.IPackage\n\t\texpectedOutput string\n\t\texpectedError  error\n\t}{\n\t\t{\n\t\t\tname:           \"empty package list\",\n\t\t\tpackages:       []db.IPackage{},\n\t\t\texpectedOutput: \"\",\n\t\t\texpectedError:  nil,\n\t\t},\n\t\t{\n\t\t\tname: \"single package\",\n\t\t\tpackages: []db.IPackage{\n\t\t\t\t&mock.Package{PName: \"vim\", PDB: mock.NewDB(\"extra\")},\n\t\t\t},\n\t\t\texpectedOutput: \"vim\\textra\\n\",\n\t\t\texpectedError:  nil,\n\t\t},\n\t\t{\n\t\t\tname: \"multiple packages\",\n\t\t\tpackages: []db.IPackage{\n\t\t\t\t&mock.Package{PName: \"vim\", PDB: mock.NewDB(\"extra\")},\n\t\t\t\t&mock.Package{PName: \"git\", PDB: mock.NewDB(\"extra\")},\n\t\t\t\t&mock.Package{PName: \"linux\", PDB: mock.NewDB(\"core\")},\n\t\t\t},\n\t\t\texpectedOutput: \"vim\\textra\\ngit\\textra\\nlinux\\tcore\\n\",\n\t\t\texpectedError:  nil,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tdbExecutor := &mockPkgSynchronizer{packages: tt.packages}\n\t\t\tout := &bytes.Buffer{}\n\n\t\t\terr := createRepoList(dbExecutor, out)\n\n\t\t\tif tt.expectedError != nil {\n\t\t\t\tassert.EqualError(t, err, tt.expectedError.Error())\n\t\t\t} else {\n\t\t\t\tassert.NoError(t, err)\n\t\t\t}\n\t\t\tassert.Equal(t, tt.expectedOutput, out.String())\n\t\t})\n\t}\n}\n\n// errorWriter is a writer that always returns an error.\ntype errorWriter struct{}\n\nfunc (e *errorWriter) Write(p []byte) (n int, err error) {\n\treturn 0, errors.New(\"write error\")\n}\n\nfunc Test_createRepoListWriteError(t *testing.T) {\n\tt.Parallel()\n\n\tdbExecutor := &mockPkgSynchronizer{\n\t\tpackages: []db.IPackage{\n\t\t\t&mock.Package{PName: \"vim\", PDB: mock.NewDB(\"extra\")},\n\t\t},\n\t}\n\n\terr := createRepoList(dbExecutor, &errorWriter{})\n\tassert.EqualError(t, err, \"write error\")\n}\n\nfunc TestUpdateCache(t *testing.T) {\n\tt.Parallel()\n\n\ttests := []struct {\n\t\tname           string\n\t\tdoer           *mockDoer\n\t\tpackages       []db.IPackage\n\t\texpectedOutput string\n\t\texpectError    bool\n\t}{\n\t\t{\n\t\t\tname: \"successful update\",\n\t\t\tdoer: &mockDoer{\n\t\t\t\treturnStatusCode: 200,\n\t\t\t\treturnBody:       []byte(\"# Comment\\npkg1\\npkg2\\n\"),\n\t\t\t\treturnErr:        nil,\n\t\t\t},\n\t\t\tpackages: []db.IPackage{\n\t\t\t\t&mock.Package{PName: \"vim\", PDB: mock.NewDB(\"extra\")},\n\t\t\t},\n\t\t\texpectedOutput: \"pkg1\\tAUR\\npkg2\\tAUR\\nvim\\textra\\n\",\n\t\t\texpectError:    false,\n\t\t},\n\t\t{\n\t\t\tname: \"AUR fetch error removes file\",\n\t\t\tdoer: &mockDoer{\n\t\t\t\treturnStatusCode: 500,\n\t\t\t\treturnBody:       []byte{},\n\t\t\t\treturnErr:        nil,\n\t\t\t},\n\t\t\tpackages:    []db.IPackage{},\n\t\t\texpectError: true,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\ttmpDir := t.TempDir()\n\t\t\tcompletionPath := filepath.Join(tmpDir, \"subdir\", \"completion\")\n\t\t\ttt.doer.t = t\n\t\t\ttt.doer.wantURL = \"https://aur.archlinux.org/packages.gz\"\n\n\t\t\tdbExecutor := &mockPkgSynchronizer{packages: tt.packages}\n\n\t\t\terr := UpdateCache(context.Background(), tt.doer, dbExecutor, \"https://aur.archlinux.org\", completionPath, nil)\n\n\t\t\tif tt.expectError {\n\t\t\t\tassert.Error(t, err)\n\t\t\t\t// File should be removed on error\n\t\t\t\t_, statErr := os.Stat(completionPath)\n\t\t\t\tassert.True(t, os.IsNotExist(statErr))\n\t\t\t} else {\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\tcontent, readErr := os.ReadFile(completionPath)\n\t\t\t\trequire.NoError(t, readErr)\n\t\t\t\tassert.Equal(t, tt.expectedOutput, string(content))\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestShow(t *testing.T) {\n\t// Note: Not running in parallel because we need to capture os.Stdout\n\ttests := []struct {\n\t\tname        string\n\t\tsetupFile   func(t *testing.T, path string)\n\t\tdoer        *mockDoer\n\t\tpackages    []db.IPackage\n\t\tinterval    int\n\t\tforce       bool\n\t\texpectError bool\n\t}{\n\t\t{\n\t\t\tname: \"existing fresh file\",\n\t\t\tsetupFile: func(t *testing.T, path string) {\n\t\t\t\tt.Helper()\n\t\t\t\terr := os.WriteFile(path, []byte(\"cached\\tdata\\n\"), 0o600)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t},\n\t\t\tdoer:        nil, // Should not be called\n\t\t\tpackages:    nil,\n\t\t\tinterval:    7,\n\t\t\tforce:       false,\n\t\t\texpectError: false,\n\t\t},\n\t\t{\n\t\t\tname:      \"file needs update\",\n\t\t\tsetupFile: nil,\n\t\t\tdoer: &mockDoer{\n\t\t\t\treturnStatusCode: 200,\n\t\t\t\treturnBody:       []byte(\"# Comment\\naur-pkg\\n\"),\n\t\t\t\treturnErr:        nil,\n\t\t\t},\n\t\t\tpackages: []db.IPackage{\n\t\t\t\t&mock.Package{PName: \"repo-pkg\", PDB: mock.NewDB(\"core\")},\n\t\t\t},\n\t\t\tinterval:    7,\n\t\t\tforce:       false,\n\t\t\texpectError: false,\n\t\t},\n\t\t{\n\t\t\tname:      \"force update\",\n\t\t\tsetupFile: nil,\n\t\t\tdoer: &mockDoer{\n\t\t\t\treturnStatusCode: 200,\n\t\t\t\treturnBody:       []byte(\"# Comment\\nforced-pkg\\n\"),\n\t\t\t\treturnErr:        nil,\n\t\t\t},\n\t\t\tpackages:    []db.IPackage{},\n\t\t\tinterval:    7,\n\t\t\tforce:       true,\n\t\t\texpectError: false,\n\t\t},\n\t\t{\n\t\t\tname:      \"update cache error\",\n\t\t\tsetupFile: nil,\n\t\t\tdoer: &mockDoer{\n\t\t\t\treturnStatusCode: 500,\n\t\t\t\treturnBody:       []byte{},\n\t\t\t\treturnErr:        nil,\n\t\t\t},\n\t\t\tpackages:    []db.IPackage{},\n\t\t\tinterval:    7,\n\t\t\tforce:       false,\n\t\t\texpectError: true,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\t// Not running in parallel because we capture os.Stdout\n\t\t\ttmpDir := t.TempDir()\n\t\t\tcompletionPath := filepath.Join(tmpDir, \"completion\")\n\n\t\t\tif tt.setupFile != nil {\n\t\t\t\ttt.setupFile(t, completionPath)\n\t\t\t}\n\n\t\t\tif tt.doer != nil {\n\t\t\t\ttt.doer.t = t\n\t\t\t\ttt.doer.wantURL = \"https://aur.archlinux.org/packages.gz\"\n\t\t\t}\n\n\t\t\tdbExecutor := &mockPkgSynchronizer{packages: tt.packages}\n\n\t\t\t// Capture stdout using a pipe\n\t\t\toldStdout := os.Stdout\n\t\t\tr, w, pipeErr := os.Pipe()\n\t\t\trequire.NoError(t, pipeErr)\n\t\t\tos.Stdout = w\n\n\t\t\terr := Show(context.Background(), tt.doer, dbExecutor, \"https://aur.archlinux.org\", completionPath, tt.interval, tt.force, nil)\n\n\t\t\t// Close writer first, then restore stdout, then read\n\t\t\tw.Close()\n\t\t\tos.Stdout = oldStdout\n\n\t\t\tvar buf bytes.Buffer\n\t\t\t_, copyErr := io.Copy(&buf, r)\n\t\t\tr.Close()\n\n\t\t\tif tt.expectError {\n\t\t\t\tassert.Error(t, err)\n\t\t\t} else {\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\trequire.NoError(t, copyErr)\n\t\t\t\t// Verify file exists and has content\n\t\t\t\tcontent, readErr := os.ReadFile(completionPath)\n\t\t\t\trequire.NoError(t, readErr)\n\t\t\t\tassert.NotEmpty(t, content)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestShowFileOpenError(t *testing.T) {\n\tt.Parallel()\n\n\ttmpDir := t.TempDir()\n\t// Use a path that can't be created (directory as file)\n\tcompletionPath := filepath.Join(tmpDir, \"completion\")\n\n\t// Create a directory where we expect a file - this will cause OpenFile to fail\n\terr := os.MkdirAll(completionPath, 0o755)\n\trequire.NoError(t, err)\n\n\tdoer := &mockDoer{\n\t\tt:                t,\n\t\twantURL:          \"https://aur.archlinux.org/packages.gz\",\n\t\treturnStatusCode: 200,\n\t\treturnBody:       []byte(\"# Comment\\npkg\\n\"),\n\t\treturnErr:        nil,\n\t}\n\n\tdbExecutor := &mockPkgSynchronizer{packages: []db.IPackage{}}\n\n\terr = Show(context.Background(), doer, dbExecutor, \"https://aur.archlinux.org\", completionPath, 7, true, nil)\n\tassert.Error(t, err)\n}\n\nfunc TestUpdateCacheMkdirError(t *testing.T) {\n\tt.Parallel()\n\n\t// Create a file where we expect a directory - this will cause MkdirAll to fail\n\ttmpDir := t.TempDir()\n\tblockingFile := filepath.Join(tmpDir, \"blocking\")\n\terr := os.WriteFile(blockingFile, []byte(\"block\"), 0o600)\n\trequire.NoError(t, err)\n\n\tcompletionPath := filepath.Join(blockingFile, \"subdir\", \"completion\")\n\n\tdoer := &mockDoer{\n\t\tt:                t,\n\t\twantURL:          \"https://aur.archlinux.org/packages.gz\",\n\t\treturnStatusCode: 200,\n\t\treturnBody:       []byte(\"# Comment\\npkg\\n\"),\n\t\treturnErr:        nil,\n\t}\n\n\tdbExecutor := &mockPkgSynchronizer{packages: []db.IPackage{}}\n\n\terr = UpdateCache(context.Background(), doer, dbExecutor, \"https://aur.archlinux.org\", completionPath, nil)\n\tassert.Error(t, err)\n}\n\nfunc Test_createAURListWriteError(t *testing.T) {\n\tt.Parallel()\n\n\tdoer := &mockDoer{\n\t\tt:                t,\n\t\twantURL:          \"https://aur.archlinux.org/packages.gz\",\n\t\treturnStatusCode: 200,\n\t\treturnBody:       []byte(\"# Comment\\npkg1\\npkg2\\n\"),\n\t\treturnErr:        nil,\n\t}\n\n\terr := createAURList(context.Background(), doer, \"https://aur.archlinux.org\", &errorWriter{}, nil)\n\tassert.EqualError(t, err, \"write error\")\n}\n"
  },
  {
    "path": "pkg/db/executor.go",
    "content": "package db\n\nimport (\n\t\"time\"\n\n\talpm \"github.com/Jguer/dyalpm\"\n\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\ntype (\n\tIPackage = alpm.Package\n\tDepend   = alpm.Depend\n)\n\n// VerCmp performs version comparison according to Pacman conventions. Return\n// value is <0 if and only if v1 is older than v2.\nfunc VerCmp(v1, v2 string) int {\n\treturn alpm.VerCmp(v1, v2)\n}\n\ntype Upgrade struct {\n\tName          string\n\tBase          string\n\tRepository    string\n\tLocalVersion  string\n\tRemoteVersion string\n\tReason        alpm.PkgReason\n\tExtra         string // Extra information to be displayed\n}\n\ntype SyncUpgrade struct {\n\tPackage      alpm.Package\n\tLocalVersion string\n\tReason       alpm.PkgReason\n}\n\ntype Executor interface {\n\tAlpmArchitectures() ([]string, error)\n\tBiggestPackages() []IPackage\n\tCleanup()\n\tInstalledRemotePackageNames() []string\n\tInstalledRemotePackages() map[string]IPackage\n\tInstalledSyncPackageNames() []string\n\tIsCorrectVersionInstalled(string, string) bool\n\tLastBuildTime() time.Time\n\tLocalPackage(string) IPackage\n\tLocalPackages() []IPackage\n\tLocalSatisfierExists(string) bool\n\tPackageDepends(IPackage) []Depend\n\tPackageGroups(IPackage) []string\n\tPackageOptionalDepends(IPackage) []Depend\n\tPackageProvides(IPackage) []Depend\n\tPackagesFromGroup(string) []IPackage\n\tPackagesFromGroupAndDB(string, string) ([]IPackage, error)\n\tRefreshHandle() error\n\tSyncUpgrades(enableDowngrade bool) (\n\t\tmap[string]SyncUpgrade, error)\n\tRepos() []string\n\tSatisfierFromDB(string, string) (IPackage, error)\n\tSyncPackage(string) IPackage\n\tSyncPackageFromDB(string, string) IPackage\n\tSyncPackages(...string) []IPackage\n\tSyncSatisfier(string) IPackage\n\tSyncSatisfierExists(string) bool\n\n\tSetLogger(logger *text.Logger)\n}\n"
  },
  {
    "path": "pkg/db/ialpm/alpm.go",
    "content": "package ialpm\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"strconv\"\n\t\"time\"\n\n\talpm \"github.com/Jguer/dyalpm\"\n\tpacmanconf \"github.com/Morganamilo/go-pacmanconf\"\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\ntype AlpmExecutor struct {\n\thandle       alpm.Handle\n\tlocalDB      alpm.Database\n\tsyncDB       []alpm.Database\n\tsyncDBsCache []alpm.Database\n\tconf         *pacmanconf.Config\n\tlog          *text.Logger\n\n\tinstalledRemotePkgNames []string\n\tinstalledRemotePkgMap   map[string]alpm.Package\n\tinstalledSyncPkgNames   []string\n}\n\nfunc NewExecutor(pacmanConf *pacmanconf.Config, logger *text.Logger) (*AlpmExecutor, error) {\n\tae := &AlpmExecutor{\n\t\thandle:                  nil,\n\t\tlocalDB:                 nil,\n\t\tsyncDB:                  nil,\n\t\tsyncDBsCache:            []alpm.Database{},\n\t\tconf:                    pacmanConf,\n\t\tlog:                     logger,\n\t\tinstalledRemotePkgNames: nil,\n\t\tinstalledRemotePkgMap:   nil,\n\t\tinstalledSyncPkgNames:   nil,\n\t}\n\n\tif err := ae.RefreshHandle(); err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar err error\n\tae.localDB, err = ae.handle.LocalDB()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tae.syncDB, err = ae.handle.SyncDBs()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn ae, nil\n}\n\nfunc toUsage(usages []string) alpm.Usage {\n\tif len(usages) == 0 {\n\t\treturn alpm.UsageAll\n\t}\n\n\tvar ret alpm.Usage\n\n\tfor _, usage := range usages {\n\t\tswitch usage {\n\t\tcase \"Sync\":\n\t\t\tret |= alpm.UsageSync\n\t\tcase \"Search\":\n\t\t\tret |= alpm.UsageSearch\n\t\tcase \"Install\":\n\t\t\tret |= alpm.UsageInstall\n\t\tcase \"Upgrade\":\n\t\t\tret |= alpm.UsageUpgrade\n\t\tcase \"All\":\n\t\t\tret |= alpm.UsageAll\n\t\t}\n\t}\n\n\treturn ret\n}\n\nfunc configureAlpm(pacmanConf *pacmanconf.Config, alpmHandle alpm.Handle) error {\n\tfor _, repo := range pacmanConf.Repos {\n\t\t// TODO: set SigLevel\n\t\talpmDB, err := alpmHandle.RegisterSyncDB(repo.Name, 0)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif err := alpmDB.SetServers(repo.Servers); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := alpmDB.SetUsage(int(toUsage(repo.Usage))); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif err := alpmHandle.SetCacheDirs(pacmanConf.CacheDir); err != nil {\n\t\treturn err\n\t}\n\n\t// add hook directories 1-by-1 to avoid overwriting the system directory\n\tfor _, dir := range pacmanConf.HookDir {\n\t\tif err := alpmHandle.AddHookDir(dir); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif err := alpmHandle.SetGPGDir(pacmanConf.GPGDir); err != nil {\n\t\treturn err\n\t}\n\n\tif err := alpmHandle.SetLogFile(pacmanConf.LogFile); err != nil {\n\t\treturn err\n\t}\n\n\tif err := alpmHandle.SetIgnorePkgs(pacmanConf.IgnorePkg); err != nil {\n\t\treturn err\n\t}\n\n\tif err := alpmHandle.SetIgnoreGroups(pacmanConf.IgnoreGroup); err != nil {\n\t\treturn err\n\t}\n\n\tif err := alpmSetArchitecture(alpmHandle, pacmanConf.Architecture); err != nil {\n\t\treturn err\n\t}\n\n\tif err := alpmHandle.SetNoUpgrades(pacmanConf.NoUpgrade); err != nil {\n\t\treturn err\n\t}\n\n\tif err := alpmHandle.SetNoExtracts(pacmanConf.NoExtract); err != nil {\n\t\treturn err\n\t}\n\n\tif err := alpmHandle.SetUseSyslog(pacmanConf.UseSyslog); err != nil {\n\t\treturn err\n\t}\n\n\treturn alpmHandle.SetCheckSpace(pacmanConf.CheckSpace)\n}\n\nfunc (ae *AlpmExecutor) logCallback() func(level alpm.LogLevel, str string) {\n\treturn func(level alpm.LogLevel, str string) {\n\t\tswitch level {\n\t\tcase alpm.LogWarning:\n\t\t\tae.log.Warn(str)\n\t\tcase alpm.LogError:\n\t\t\tae.log.Error(str)\n\t\t}\n\t}\n}\n\nfunc (ae *AlpmExecutor) questionCallback() func(question alpm.QuestionAny) {\n\treturn func(question alpm.QuestionAny) {\n\t\tif qi, err := question.QuestionInstallIgnorepkg(); err == nil {\n\t\t\tqi.SetInstall(true)\n\t\t}\n\n\t\tqp, err := question.QuestionSelectProvider()\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\n\t\tif settings.HideMenus {\n\t\t\treturn\n\t\t}\n\n\t\tsize := 0\n\n\t\t_ = qp.Providers(ae.handle).ForEach(func(pkg alpm.Package) error {\n\t\t\tsize++\n\t\t\treturn nil\n\t\t})\n\n\t\tstr := text.Bold(gotext.Get(\"There are %[1]d providers available for %[2]s:\", size, qp.Dep()))\n\n\t\tsize = 1\n\n\t\tvar dbName string\n\n\t\t_ = qp.Providers(ae.handle).ForEach(func(pkg alpm.Package) error {\n\t\t\tthisDB := pkg.DB().Name()\n\n\t\t\tif dbName != thisDB {\n\t\t\t\tdbName = thisDB\n\t\t\t\tstr += \"\\n\"\n\t\t\t\tstr += ae.log.SprintOperationInfo(gotext.Get(\"Repository\"), \" \", dbName, \"\\n    \")\n\t\t\t}\n\t\t\tstr += fmt.Sprintf(\"%d) %s \", size, pkg.Name())\n\t\t\tsize++\n\t\t\treturn nil\n\t\t})\n\n\t\tae.log.OperationInfoln(str)\n\n\t\tfor {\n\t\t\tae.log.Println(gotext.Get(\"\\nEnter a number (default=1): \"))\n\n\t\t\t// TODO: reenable noconfirm\n\t\t\tif settings.NoConfirm {\n\t\t\t\tae.log.Println()\n\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tnumberBuf, err := ae.log.GetInput(\"\", false)\n\t\t\tif err != nil {\n\t\t\t\tae.log.Errorln(err)\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tif numberBuf == \"\" {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tnum, err := strconv.Atoi(numberBuf)\n\t\t\tif err != nil {\n\t\t\t\tae.log.Errorln(gotext.Get(\"invalid number: %s\", numberBuf))\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif num < 1 || num > size {\n\t\t\t\tae.log.Errorln(gotext.Get(\"invalid value: %d is not between %d and %d\", num, 1, size))\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tqp.SetUseIndex(num - 1)\n\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nfunc (ae *AlpmExecutor) RefreshHandle() error {\n\tif ae.handle != nil {\n\t\tif errRelease := ae.handle.Release(); errRelease != nil {\n\t\t\treturn errRelease\n\t\t}\n\t}\n\n\talpmHandle, err := alpm.Initialize(ae.conf.RootDir, ae.conf.DBPath)\n\tif err != nil {\n\t\treturn errors.New(gotext.Get(\"unable to CreateHandle: %s\", err))\n\t}\n\n\tif errConf := configureAlpm(ae.conf, alpmHandle); errConf != nil {\n\t\treturn errConf\n\t}\n\n\tif err := alpmSetQuestionCallback(alpmHandle, ae.questionCallback()); err != nil {\n\t\treturn err\n\t}\n\talpmSetLogCallback(alpmHandle, ae.logCallback())\n\tae.handle = alpmHandle\n\tae.syncDBsCache = nil\n\n\tae.syncDB, err = alpmHandle.SyncDBs()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tae.localDB, err = alpmHandle.LocalDB()\n\n\treturn err\n}\n\nfunc (ae *AlpmExecutor) LocalSatisfierExists(pkgName string) bool {\n\tif _, err := ae.localDB.PkgCache().FindSatisfier(pkgName); err != nil {\n\t\treturn false\n\t}\n\n\treturn true\n}\n\nfunc (ae *AlpmExecutor) SyncSatisfierExists(pkgName string) bool {\n\treturn ae.SyncSatisfier(pkgName) != nil\n}\n\nfunc (ae *AlpmExecutor) IsCorrectVersionInstalled(pkgName, versionRequired string) bool {\n\talpmPackage := ae.localDB.Pkg(pkgName)\n\tif alpmPackage == nil {\n\t\treturn false\n\t}\n\n\treturn alpmPackage.Version() == versionRequired\n}\n\nfunc (ae *AlpmExecutor) SyncSatisfier(pkgName string) alpm.Package {\n\tdbs := ae.syncDBs()\n\tif len(dbs) == 0 {\n\t\treturn nil\n\t}\n\t// Use FindDBSatisfier across sync databases\n\tdbSlice := make([]alpm.Database, len(dbs))\n\tcopy(dbSlice, dbs)\n\treturn ae.handle.FindDBSatisfier(dbSlice, pkgName)\n}\n\nfunc (ae *AlpmExecutor) PackagesFromGroup(groupName string) []alpm.Package {\n\tpkgs, err := ae.handle.FindGroupPkgs(ae.syncDBs(), groupName)\n\tif err != nil {\n\t\treturn nil\n\t}\n\treturn pkgs\n}\n\nfunc (ae *AlpmExecutor) PackagesFromGroupAndDB(groupName, dbName string) ([]alpm.Package, error) {\n\tsingleDBs, err := ae.handle.SyncDBListByDBName(dbName)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn ae.handle.FindGroupPkgs(singleDBs, groupName)\n}\n\nfunc (ae *AlpmExecutor) LocalPackages() []alpm.Package {\n\tlocalPackages := []alpm.Package{}\n\t_ = ae.localDB.PkgCache().ForEach(func(pkg alpm.Package) error {\n\t\tlocalPackages = append(localPackages, pkg)\n\t\treturn nil\n\t})\n\treturn localPackages\n}\n\n// SyncPackages searches SyncDB for packages or returns all packages if no search param is given.\nfunc (ae *AlpmExecutor) SyncPackages(pkgNames ...string) []alpm.Package {\n\trepoPackages := []alpm.Package{}\n\tfor _, alpmDB := range ae.syncDBs() {\n\t\tif len(pkgNames) == 0 {\n\t\t\t_ = alpmDB.PkgCache().ForEach(func(pkg alpm.Package) error {\n\t\t\t\trepoPackages = append(repoPackages, pkg)\n\t\t\t\treturn nil\n\t\t\t})\n\t\t\tcontinue\n\t\t}\n\t\t_ = alpmDB.Search(pkgNames).ForEach(func(pkg alpm.Package) error {\n\t\t\trepoPackages = append(repoPackages, pkg)\n\t\t\treturn nil\n\t\t})\n\t}\n\n\treturn repoPackages\n}\n\nfunc (ae *AlpmExecutor) LocalPackage(pkgName string) alpm.Package {\n\tpkg := ae.localDB.Pkg(pkgName)\n\tif pkg == nil {\n\t\treturn nil\n\t}\n\n\treturn pkg\n}\n\nfunc (ae *AlpmExecutor) syncDBs() []alpm.Database {\n\tif ae.syncDBsCache == nil {\n\t\tae.syncDBsCache = ae.syncDB\n\t}\n\n\treturn ae.syncDBsCache\n}\n\nfunc (ae *AlpmExecutor) SyncPackage(pkgName string) alpm.Package {\n\tfor _, db := range ae.syncDBs() {\n\t\tif dbPkg := db.Pkg(pkgName); dbPkg != nil {\n\t\t\treturn dbPkg\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (ae *AlpmExecutor) SyncPackageFromDB(pkgName, dbName string) alpm.Package {\n\tsingleDB, err := ae.handle.SyncDBByName(dbName)\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn singleDB.Pkg(pkgName)\n}\n\nfunc (ae *AlpmExecutor) SatisfierFromDB(pkgName, dbName string) (alpm.Package, error) {\n\tsingleDBs, err := ae.handle.SyncDBListByDBName(dbName)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tfoundPkg := ae.handle.FindDBSatisfier(singleDBs, pkgName)\n\tif foundPkg == nil {\n\t\treturn nil, nil\n\t}\n\n\treturn foundPkg, nil\n}\n\nfunc (ae *AlpmExecutor) PackageDepends(pkg alpm.Package) []alpm.Depend {\n\treturn pkg.Depends()\n}\n\nfunc (ae *AlpmExecutor) PackageOptionalDepends(pkg alpm.Package) []alpm.Depend {\n\treturn pkg.OptionalDepends()\n}\n\nfunc (ae *AlpmExecutor) PackageProvides(pkg alpm.Package) []alpm.Depend {\n\treturn pkg.Provides()\n}\n\nfunc (ae *AlpmExecutor) PackageGroups(pkg alpm.Package) []string {\n\treturn pkg.Groups()\n}\n\n// upRepo gathers local packages and checks if they have new versions.\n// Output: Upgrade type package list.\nfunc (ae *AlpmExecutor) SyncUpgrades(enableDowngrade bool) (\n\tmap[string]db.SyncUpgrade, error,\n) {\n\tups := map[string]db.SyncUpgrade{}\n\tvar errReturn error\n\n\tlocalDB, errDB := ae.handle.LocalDB()\n\tif errDB != nil {\n\t\treturn ups, errDB\n\t}\n\n\tif err := ae.handle.TransInit(alpm.TransFlagNoLock); err != nil {\n\t\treturn ups, err\n\t}\n\n\tdefer func() {\n\t\terrReturn = ae.handle.TransRelease()\n\t}()\n\n\tif err := ae.handle.SyncSysupgrade(enableDowngrade); err != nil {\n\t\treturn ups, err\n\t}\n\n\t_ = ae.handle.TransGetAdd().ForEach(func(pkg alpm.Package) error {\n\t\tlocalVer := \"-\"\n\t\treason := alpm.PkgReasonExplicit\n\n\t\tif localPkg := localDB.Pkg(pkg.Name()); localPkg != nil {\n\t\t\tlocalVer = localPkg.Version()\n\t\t\treason = localPkg.Reason()\n\t\t}\n\n\t\tups[pkg.Name()] = db.SyncUpgrade{\n\t\t\tPackage:      pkg,\n\t\t\tReason:       reason,\n\t\t\tLocalVersion: localVer,\n\t\t}\n\n\t\treturn nil\n\t})\n\n\treturn ups, errReturn\n}\n\nfunc (ae *AlpmExecutor) BiggestPackages() []alpm.Package {\n\treturn append([]alpm.Package{}, ae.localDB.PkgCache().SortBySize()...)\n}\n\nfunc (ae *AlpmExecutor) LastBuildTime() time.Time {\n\tvar lastTime time.Time\n\n\tfor _, db := range ae.syncDBs() {\n\t\t_ = db.PkgCache().ForEach(func(pkg alpm.Package) error {\n\t\t\tthisTime := pkg.BuildDate()\n\t\t\tif thisTime.After(lastTime) {\n\t\t\t\tlastTime = thisTime\n\t\t\t}\n\t\t\treturn nil\n\t\t})\n\t}\n\n\treturn lastTime\n}\n\nfunc (ae *AlpmExecutor) Cleanup() {\n\tif ae.handle != nil {\n\t\tif err := ae.handle.Release(); err != nil {\n\t\t\tfmt.Fprintln(os.Stderr, err)\n\t\t}\n\t}\n}\n\nfunc (ae *AlpmExecutor) Repos() (repos []string) {\n\tfor _, db := range ae.syncDBs() {\n\t\trepos = append(repos, db.Name())\n\t}\n\n\treturn\n}\n\nfunc alpmSetArchitecture(alpmHandle alpm.Handle, arch []string) error {\n\treturn alpmHandle.SetArchitectures(arch)\n}\n\nfunc (ae *AlpmExecutor) AlpmArchitectures() ([]string, error) {\n\tarchitectures, err := ae.handle.Architectures()\n\n\treturn architectures, err\n}\n\nfunc alpmSetLogCallback(alpmHandle alpm.Handle, cb func(alpm.LogLevel, string)) {\n\t// dyalpm uses a different callback mechanism - log callback not easily supported\n\t// due to va_list in libalpm. Skip setting log callback.\n\t_ = alpmHandle\n\t_ = cb\n}\n\nfunc alpmSetQuestionCallback(alpmHandle alpm.Handle, cb func(alpm.QuestionAny)) error {\n\treturn alpmHandle.SetQuestionCallbackFunc(func(q alpm.Question) {\n\t\tcb(alpm.QuestionAny{Question: q})\n\t})\n}\n"
  },
  {
    "path": "pkg/db/ialpm/alpm_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage ialpm\n\nimport (\n\t\"io\"\n\t\"strings\"\n\t\"testing\"\n\n\talpm \"github.com/Jguer/dyalpm\"\n\t\"github.com/Morganamilo/go-pacmanconf\"\n\t\"github.com/stretchr/testify/assert\"\n\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\nfunc TestAlpmExecutor(t *testing.T) {\n\tt.Parallel()\n\tpacmanConf := &pacmanconf.Config{\n\t\tRootDir:                \"/\",\n\t\tDBPath:                 \"/var/lib/pacman/\",\n\t\tCacheDir:               []string{\"/cachedir/\", \"/another/\"},\n\t\tHookDir:                []string{\"/hookdir/\"},\n\t\tGPGDir:                 \"/gpgdir/\",\n\t\tLogFile:                \"/logfile\",\n\t\tHoldPkg:                []string(nil),\n\t\tIgnorePkg:              []string{\"ignore\", \"this\", \"package\"},\n\t\tIgnoreGroup:            []string{\"ignore\", \"this\", \"group\"},\n\t\tArchitecture:           []string{\"8086\"},\n\t\tXferCommand:            \"\",\n\t\tNoUpgrade:              []string{\"noupgrade\"},\n\t\tNoExtract:              []string{\"noextract\"},\n\t\tCleanMethod:            []string{\"KeepInstalled\"},\n\t\tSigLevel:               []string{\"PackageOptional\", \"PackageTrustedOnly\", \"DatabaseOptional\", \"DatabaseTrustedOnly\"},\n\t\tLocalFileSigLevel:      []string(nil),\n\t\tRemoteFileSigLevel:     []string(nil),\n\t\tUseSyslog:              false,\n\t\tColor:                  false,\n\t\tUseDelta:               0,\n\t\tTotalDownload:          true,\n\t\tCheckSpace:             true,\n\t\tVerbosePkgLists:        true,\n\t\tDisableDownloadTimeout: false,\n\t\tRepos: []pacmanconf.Repository{\n\t\t\t{Name: \"repo1\", Servers: []string{\"repo1\"}, SigLevel: []string(nil), Usage: []string{\"All\"}},\n\t\t\t{Name: \"repo2\", Servers: []string{\"repo2\"}, SigLevel: []string(nil), Usage: []string{\"All\"}},\n\t\t},\n\t}\n\n\taExec, err := NewExecutor(pacmanConf, text.NewLogger(io.Discard, io.Discard, strings.NewReader(\"\"), false, \"test\"))\n\tassert.NoError(t, err)\n\n\tassert.NotNil(t, aExec.conf)\n\tassert.EqualValues(t, pacmanConf, aExec.conf)\n\n\tassert.NotNil(t, aExec.localDB)\n\tassert.NotNil(t, aExec.syncDB)\n\tassert.NotNil(t, aExec.questionCallback)\n\th := aExec.handle\n\tassert.NotNil(t, h)\n\n\troot := h.Root()\n\tassert.Nil(t, err)\n\tassert.Equal(t, \"/\", root)\n\n\tdbPath := h.DBPath()\n\tassert.Nil(t, err)\n\tassert.Equal(t, \"/var/lib/pacman/\", dbPath)\n\n\tcache, err := h.CacheDirs()\n\tassert.Nil(t, err)\n\tassert.Equal(t, []string{\"/cachedir/\", \"/another/\"}, cache)\n\n\tlog := h.LogFile()\n\tassert.Nil(t, err)\n\tassert.Equal(t, \"/logfile\", log)\n\n\tgpg := h.GPGDir()\n\tassert.Nil(t, err)\n\tassert.Equal(t, \"/gpgdir/\", gpg)\n\n\thook, err := h.HookDirs()\n\tassert.Nil(t, err)\n\tassert.Equal(t, []string{\"/usr/share/libalpm/hooks/\", \"/hookdir/\"}, hook)\n\n\tarch, err := alpmTestGetArch(h)\n\tassert.Nil(t, err)\n\tassert.Equal(t, []string{\"8086\"}, arch)\n\n\tignorePkg, err := h.IgnorePkgs()\n\tassert.Nil(t, err)\n\tassert.Equal(t, []string{\"ignore\", \"this\", \"package\"}, ignorePkg)\n\n\tignoreGroup, err := h.IgnoreGroups()\n\tassert.Nil(t, err)\n\tassert.Equal(t, []string{\"ignore\", \"this\", \"group\"}, ignoreGroup)\n\n\tnoUp, err := h.NoUpgrades()\n\tassert.Nil(t, err)\n\tassert.Equal(t, []string{\"noupgrade\"}, noUp)\n\n\tnoEx, err := h.NoExtracts()\n\tassert.Nil(t, err)\n\tassert.Equal(t, []string{\"noextract\"}, noEx)\n\n\tcheck := h.CheckSpace()\n\tassert.Nil(t, err)\n\tassert.Equal(t, true, check)\n}\n\nfunc alpmTestGetArch(h alpm.Handle) ([]string, error) {\n\tarchitectures, err := h.Architectures()\n\n\treturn architectures, err\n}\n"
  },
  {
    "path": "pkg/db/ialpm/high_level.go",
    "content": "package ialpm\n\nimport (\n\talpm \"github.com/Jguer/dyalpm\"\n\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\n// GetPackageNamesBySource returns package names with and without correspondence in SyncDBS respectively.\nfunc (ae *AlpmExecutor) getPackageNamesBySource() {\n\tif ae.installedRemotePkgMap == nil {\n\t\tae.installedRemotePkgMap = map[string]alpm.Package{}\n\t}\n\tfor _, localpkg := range ae.LocalPackages() {\n\t\tpkgName := localpkg.Name()\n\t\tif ae.SyncPackage(pkgName) != nil {\n\t\t\tae.installedSyncPkgNames = append(ae.installedSyncPkgNames, pkgName)\n\t\t} else {\n\t\t\tae.installedRemotePkgNames = append(ae.installedRemotePkgNames, pkgName)\n\t\t\tae.installedRemotePkgMap[pkgName] = localpkg\n\t\t}\n\t}\n\n\tae.log.Debugln(\"populating db executor package caches.\",\n\t\t\"sync_len\", len(ae.installedSyncPkgNames), \"remote_len\", len(ae.installedRemotePkgNames))\n}\n\nfunc (ae *AlpmExecutor) InstalledRemotePackages() map[string]alpm.Package {\n\tif ae.installedRemotePkgMap == nil {\n\t\tae.getPackageNamesBySource()\n\t}\n\n\treturn ae.installedRemotePkgMap\n}\n\nfunc (ae *AlpmExecutor) InstalledRemotePackageNames() []string {\n\tif ae.installedRemotePkgNames == nil {\n\t\tae.getPackageNamesBySource()\n\t}\n\n\treturn ae.installedRemotePkgNames\n}\n\nfunc (ae *AlpmExecutor) InstalledSyncPackageNames() []string {\n\tif ae.installedSyncPkgNames == nil {\n\t\tae.getPackageNamesBySource()\n\t}\n\n\treturn ae.installedSyncPkgNames\n}\n\nfunc (ae *AlpmExecutor) SetLogger(logger *text.Logger) {\n\tae.log = logger\n}\n"
  },
  {
    "path": "pkg/db/mock/executor.go",
    "content": "package mock\n\nimport (\n\t\"time\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\n\talpm \"github.com/Jguer/dyalpm\"\n)\n\ntype (\n\tIPackage = alpm.Package\n\tDepend   = alpm.Depend\n\tUpgrade  = db.Upgrade\n)\n\ntype DBExecutor struct {\n\tdb.Executor\n\tAlpmArchitecturesFn           func() ([]string, error)\n\tInstalledRemotePackageNamesFn func() []string\n\tInstalledRemotePackagesFn     func() map[string]IPackage\n\tIsCorrectVersionInstalledFn   func(string, string) bool\n\tLocalPackageFn                func(string) IPackage\n\tLocalPackagesFn               func() []IPackage\n\tLocalSatisfierExistsFn        func(string) bool\n\tPackageDependsFn              func(IPackage) []Depend\n\tPackageOptionalDependsFn      func(alpm.Package) []alpm.Depend\n\tPackageProvidesFn             func(IPackage) []Depend\n\tPackagesFromGroupFn           func(string) []IPackage\n\tPackagesFromGroupAndDBFn      func(string, string) ([]IPackage, error)\n\tRefreshHandleFn               func() error\n\tReposFn                       func() []string\n\tSyncPackageFn                 func(string) IPackage\n\tSyncPackagesFn                func(...string) []IPackage\n\tSyncSatisfierFn               func(string) IPackage\n\tSatisfierFromDBFn             func(string, string) (IPackage, error)\n\tSyncUpgradesFn                func(bool) (map[string]db.SyncUpgrade, error)\n\tSetLoggerFn                   func(*text.Logger)\n}\n\nfunc (t *DBExecutor) InstalledRemotePackageNames() []string {\n\tif t.InstalledRemotePackageNamesFn != nil {\n\t\treturn t.InstalledRemotePackageNamesFn()\n\t}\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) InstalledRemotePackages() map[string]IPackage {\n\tif t.InstalledRemotePackagesFn != nil {\n\t\treturn t.InstalledRemotePackagesFn()\n\t}\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) AlpmArchitectures() ([]string, error) {\n\tif t.AlpmArchitecturesFn != nil {\n\t\treturn t.AlpmArchitecturesFn()\n\t}\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) BiggestPackages() []IPackage {\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) Cleanup() {\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) IsCorrectVersionInstalled(s, s2 string) bool {\n\tif t.IsCorrectVersionInstalledFn != nil {\n\t\treturn t.IsCorrectVersionInstalledFn(s, s2)\n\t}\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) LastBuildTime() time.Time {\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) LocalPackage(s string) IPackage {\n\tif t.LocalPackageFn != nil {\n\t\treturn t.LocalPackageFn(s)\n\t}\n\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) LocalPackages() []IPackage {\n\tif t.LocalPackagesFn != nil {\n\t\treturn t.LocalPackagesFn()\n\t}\n\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) LocalSatisfierExists(s string) bool {\n\tif t.LocalSatisfierExistsFn != nil {\n\t\treturn t.LocalSatisfierExistsFn(s)\n\t}\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) PackageConflicts(iPackage IPackage) []Depend {\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) PackageDepends(iPackage IPackage) []Depend {\n\tif t.PackageDependsFn != nil {\n\t\treturn t.PackageDependsFn(iPackage)\n\t}\n\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) PackageGroups(iPackage IPackage) []string {\n\treturn []string{}\n}\n\nfunc (t *DBExecutor) PackageOptionalDepends(iPackage IPackage) []Depend {\n\tif t.PackageOptionalDependsFn != nil {\n\t\treturn t.PackageOptionalDependsFn(iPackage)\n\t}\n\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) PackageProvides(iPackage IPackage) []Depend {\n\tif t.PackageProvidesFn != nil {\n\t\treturn t.PackageProvidesFn(iPackage)\n\t}\n\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) PackagesFromGroup(s string) []IPackage {\n\tif t.PackagesFromGroupFn != nil {\n\t\treturn t.PackagesFromGroupFn(s)\n\t}\n\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) PackagesFromGroupAndDB(s, s2 string) ([]IPackage, error) {\n\tif t.PackagesFromGroupAndDBFn != nil {\n\t\treturn t.PackagesFromGroupAndDBFn(s, s2)\n\t}\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) RefreshHandle() error {\n\tif t.RefreshHandleFn != nil {\n\t\treturn t.RefreshHandleFn()\n\t}\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) SyncUpgrades(b bool) (map[string]db.SyncUpgrade, error) {\n\tif t.SyncUpgradesFn != nil {\n\t\treturn t.SyncUpgradesFn(b)\n\t}\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) Repos() []string {\n\tif t.ReposFn != nil {\n\t\treturn t.ReposFn()\n\t}\n\t// Tests that don't care about repo ordering shouldn't need to stub this out.\n\treturn nil\n}\n\nfunc (t *DBExecutor) SatisfierFromDB(s, s2 string) (IPackage, error) {\n\tif t.SatisfierFromDBFn != nil {\n\t\treturn t.SatisfierFromDBFn(s, s2)\n\t}\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) SyncPackage(s string) IPackage {\n\tif t.SyncPackageFn != nil {\n\t\treturn t.SyncPackageFn(s)\n\t}\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) SyncPackages(s ...string) []IPackage {\n\tif t.SyncPackagesFn != nil {\n\t\treturn t.SyncPackagesFn(s...)\n\t}\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) SyncSatisfier(s string) IPackage {\n\tif t.SyncSatisfierFn != nil {\n\t\treturn t.SyncSatisfierFn(s)\n\t}\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) SyncSatisfierExists(s string) bool {\n\tif t.SyncSatisfierFn != nil {\n\t\treturn t.SyncSatisfierFn(s) != nil\n\t}\n\tpanic(\"implement me\")\n}\n\nfunc (t *DBExecutor) SetLogger(logger *text.Logger) {\n\tif t.SetLoggerFn != nil {\n\t\tt.SetLoggerFn(logger)\n\t\treturn\n\t}\n\tpanic(\"implement me\")\n}\n"
  },
  {
    "path": "pkg/db/mock/repo.go",
    "content": "package mock\n\nimport (\n\t\"io\"\n\t\"time\"\n\n\talpm \"github.com/Jguer/dyalpm\"\n)\n\n// DependList is a lightweight helper for test fixtures.\ntype DependList struct {\n\tDepends []alpm.Depend\n}\n\ntype Package struct {\n\tPBase         string\n\tPBuildDate    time.Time\n\tPDB           *DB\n\tPDescription  string\n\tPISize        int64\n\tPName         string\n\tPShouldIgnore bool\n\tPSize         int64\n\tPVersion      string\n\tPReason       alpm.PkgReason\n\tPDepends      DependList\n\tPProvides     DependList\n\tPArchitecture string\n}\n\nvar _ alpm.Package = (*Package)(nil)\n\nfunc (p *Package) Base() string {\n\treturn p.PBase\n}\n\nfunc (p *Package) BuildDate() time.Time {\n\treturn p.PBuildDate\n}\n\nfunc (p *Package) DB() alpm.Database {\n\treturn p.PDB\n}\n\nfunc (p *Package) Description() string {\n\treturn p.PDescription\n}\n\nfunc (p *Package) ISize() int64 {\n\treturn p.PISize\n}\n\nfunc (p *Package) Name() string {\n\treturn p.PName\n}\n\nfunc (p *Package) ShouldIgnore() bool {\n\treturn p.PShouldIgnore\n}\n\nfunc (p *Package) Size() int64 {\n\treturn p.PSize\n}\n\nfunc (p *Package) Version() string {\n\treturn p.PVersion\n}\n\nfunc (p *Package) Reason() alpm.PkgReason {\n\treturn p.PReason\n}\n\nfunc (p *Package) FileName() string {\n\tpanic(\"not implemented\")\n}\n\nfunc (p *Package) Base64Signature() string {\n\tpanic(\"not implemented\")\n}\n\nfunc (p *Package) Validation() alpm.Validation {\n\tpanic(\"not implemented\")\n}\n\n// Architecture returns the package target Architecture.\nfunc (p *Package) Architecture() string {\n\treturn p.PArchitecture\n}\n\n// Backup returns a list of package backups.\nfunc (p *Package) Backup() []alpm.Backup {\n\tpanic(\"not implemented\")\n}\n\n// Conflicts returns the conflicts of the package as a DependList.\nfunc (p *Package) Conflicts() []alpm.Depend {\n\tpanic(\"not implemented\")\n}\n\n// Depends returns the package's dependency list.\nfunc (p *Package) Depends() []alpm.Depend {\n\treturn p.PDepends.Depends\n}\n\n// Depends returns the package's optional dependency list.\nfunc (p *Package) OptionalDepends() []alpm.Depend {\n\tpanic(\"not implemented\")\n}\n\n// Depends returns the package's check dependency list.\nfunc (p *Package) CheckDepends() []alpm.Depend {\n\tpanic(\"not implemented\")\n}\n\n// Depends returns the package's make dependency list.\nfunc (p *Package) MakeDepends() []alpm.Depend {\n\tpanic(\"not implemented\")\n}\n\n// Files returns the file list of the package.\nfunc (p *Package) Files() []alpm.File {\n\tpanic(\"not implemented\")\n}\n\n// ContainsFile checks if the path is in the package filelist.\nfunc (p *Package) ContainsFile(path string) (alpm.File, error) {\n\tpanic(\"not implemented\")\n}\n\n// Groups returns the groups the package belongs to.\nfunc (p *Package) Groups() []string {\n\tpanic(\"not implemented\")\n}\n\n// InstallDate returns the package install date.\nfunc (p *Package) InstallDate() time.Time {\n\tpanic(\"not implemented\")\n}\n\n// Licenses returns the package license list.\nfunc (p *Package) Licenses() []string {\n\tpanic(\"not implemented\")\n}\n\n// SHA256Sum returns package SHA256Sum.\nfunc (p *Package) SHA256Sum() string {\n\tpanic(\"not implemented\")\n}\n\n// Packager returns package packager name.\nfunc (p *Package) Packager() string {\n\tpanic(\"not implemented\")\n}\n\n// Provides returns DependList of packages provides by package.\nfunc (p *Package) Provides() []alpm.Depend {\n\treturn p.PProvides.Depends\n}\n\n// Origin returns package origin.\nfunc (p *Package) Origin() alpm.PkgFrom {\n\tpanic(\"not implemented\")\n}\n\n// Replaces returns a DependList with the packages this package replaces.\nfunc (p *Package) Replaces() []alpm.Depend {\n\tpanic(\"not implemented\")\n}\n\n// URL returns the upstream URL of the package.\nfunc (p *Package) URL() string {\n\tpanic(\"not implemented\")\n}\n\n// ComputeRequiredBy returns the names of reverse dependencies of a package.\nfunc (p *Package) ComputeRequiredBy() ([]string, error) {\n\tpanic(\"not implemented\")\n}\n\n// ComputeOptionalFor returns the names of packages that optionally\n// require the given package.\nfunc (p *Package) ComputeOptionalFor() ([]string, error) {\n\tpanic(\"not implemented\")\n}\n\n// SyncNewVersion checks if there is a new version of the\n// package in a given DBlist.\nfunc (p *Package) SyncNewVersion(dbs []alpm.Database) alpm.Package {\n\tpanic(\"not implemented\")\n}\n\nfunc (p *Package) Type() string {\n\tpanic(\"not implemented\")\n}\n\nfunc (p *Package) CheckMD5Sum() error {\n\tpanic(\"not implemented\")\n}\n\nfunc (p *Package) CheckPGPSignature() (alpm.SigList, error) {\n\tpanic(\"not implemented\")\n}\n\nfunc (p *Package) Contains(path string) bool {\n\tpanic(\"not implemented\")\n}\n\nfunc (p *Package) Free() error {\n\treturn nil\n}\n\n// New methods required by dyalpm refactoring\nfunc (p *Package) HasScriptlet() bool {\n\treturn false\n}\n\nfunc (p *Package) DownloadSize() int64 {\n\treturn 0\n}\n\nfunc (p *Package) NativeHandle() alpm.Handle {\n\treturn nil\n}\n\nfunc (p *Package) Sig() string {\n\treturn \"\"\n}\n\nfunc (p *Package) PkgValidation() alpm.PkgValidation {\n\treturn alpm.PkgValidationUnknown\n}\n\nfunc (p *Package) XData() string {\n\treturn \"\"\n}\n\nfunc (p *Package) Changelog() (io.ReadCloser, error) {\n\treturn nil, nil\n}\n\nfunc (p *Package) SyncGetNewVersion(dbsSync []alpm.Database) alpm.Package {\n\treturn nil\n}\n\ntype DB struct {\n\talpm.Database\n\tname string\n}\n\nfunc NewDB(name string) *DB {\n\treturn &DB{name: name}\n}\n\nfunc (d *DB) Name() string {\n\treturn d.name\n}\n\nfunc (d *DB) Pkg(name string) alpm.Package {\n\treturn nil\n}\n\nfunc (d *DB) PkgCache() alpm.PackageIterator {\n\treturn alpm.PackageIterator{}\n}\n\nfunc (d *DB) Search(needles []string) alpm.PackageIterator {\n\treturn alpm.PackageIterator{}\n}\n\nfunc (d *DB) SetServers(servers []string) error {\n\treturn nil\n}\n\nfunc (d *DB) SetUsage(usage int) error {\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/db/types.go",
    "content": "package db\n\nimport \"slices\"\n\nfunc ArchIsSupported(alpmArch []string, arch string) bool {\n\tif arch == \"any\" {\n\t\treturn true\n\t}\n\n\treturn slices.Contains(alpmArch, arch)\n}\n"
  },
  {
    "path": "pkg/dep/dep.go",
    "content": "package dep\n\nimport (\n\t\"strings\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\taur \"github.com/Jguer/yay/v12/pkg/query\"\n)\n\nfunc splitDep(dep string) (pkg, mod, ver string) {\n\tsplit := strings.FieldsFunc(dep, func(c rune) bool {\n\t\tmatch := c == '>' || c == '<' || c == '='\n\n\t\tif match {\n\t\t\tmod += string(c)\n\t\t}\n\n\t\treturn match\n\t})\n\n\tif len(split) == 0 {\n\t\treturn \"\", \"\", \"\"\n\t}\n\n\tif len(split) == 1 {\n\t\treturn split[0], \"\", \"\"\n\t}\n\n\treturn split[0], mod, split[1]\n}\n\nfunc pkgSatisfies(name, version, dep string) bool {\n\tdepName, depMod, depVersion := splitDep(dep)\n\n\tif depName != name {\n\t\treturn false\n\t}\n\n\treturn verSatisfies(version, depMod, depVersion)\n}\n\nfunc provideSatisfies(provide, dep, pkgVersion string) bool {\n\tdepName, depMod, depVersion := splitDep(dep)\n\tprovideName, provideMod, provideVersion := splitDep(provide)\n\n\tif provideName != depName {\n\t\treturn false\n\t}\n\n\t// Unversioned provides can not satisfy a versioned dep\n\tif provideMod == \"\" && depMod != \"\" {\n\t\tprovideVersion = pkgVersion // Example package: pagure\n\t}\n\n\treturn verSatisfies(provideVersion, depMod, depVersion)\n}\n\nfunc verSatisfies(ver1, mod, ver2 string) bool {\n\tswitch mod {\n\tcase \"=\":\n\t\treturn db.VerCmp(ver1, ver2) == 0\n\tcase \"<\":\n\t\treturn db.VerCmp(ver1, ver2) < 0\n\tcase \"<=\":\n\t\treturn db.VerCmp(ver1, ver2) <= 0\n\tcase \">\":\n\t\treturn db.VerCmp(ver1, ver2) > 0\n\tcase \">=\":\n\t\treturn db.VerCmp(ver1, ver2) >= 0\n\t}\n\n\treturn true\n}\n\nfunc satisfiesAur(dep string, pkg *aur.Pkg) bool {\n\tif pkgSatisfies(pkg.Name, pkg.Version, dep) {\n\t\treturn true\n\t}\n\n\tfor _, provide := range pkg.Provides {\n\t\tif provideSatisfies(provide, dep, pkg.Version) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n"
  },
  {
    "path": "pkg/dep/dep_graph.go",
    "content": "package dep\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\n\taurc \"github.com/Jguer/aur\"\n\talpm \"github.com/Jguer/dyalpm\"\n\tgosrc \"github.com/Morganamilo/go-srcinfo\"\n\tmapset \"github.com/deckarep/golang-set/v2\"\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/dep/topo\"\n\t\"github.com/Jguer/yay/v12/pkg/intrange\"\n\taur \"github.com/Jguer/yay/v12/pkg/query\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\ntype InstallInfo struct {\n\tSource       Source\n\tReason       Reason\n\tVersion      string\n\tLocalVersion string\n\tSrcinfoPath  *string\n\tAURBase      *string\n\tSyncDBName   *string\n\n\tIsGroup bool\n\tUpgrade bool\n\tDevel   bool\n}\n\nfunc (i *InstallInfo) String() string {\n\treturn fmt.Sprintf(\"InstallInfo{Source: %v, Reason: %v}\", i.Source, i.Reason)\n}\n\ntype (\n\tReason int\n\tSource int\n)\n\nfunc (r Reason) String() string {\n\treturn ReasonNames[r]\n}\n\nfunc (s Source) String() string {\n\treturn SourceNames[s]\n}\n\nconst (\n\tExplicit Reason = iota // 0\n\tDep                    // 1\n\tMakeDep                // 2\n\tCheckDep               // 3\n)\n\nvar ReasonNames = map[Reason]string{\n\tExplicit: gotext.Get(\"Explicit\"),\n\tDep:      gotext.Get(\"Dependency\"),\n\tMakeDep:  gotext.Get(\"Make Dependency\"),\n\tCheckDep: gotext.Get(\"Check Dependency\"),\n}\n\nconst (\n\tAUR Source = iota\n\tSync\n\tLocal\n\tSrcInfo\n\tMissing\n)\n\nvar SourceNames = map[Source]string{\n\tAUR:     gotext.Get(\"AUR\"),\n\tSync:    gotext.Get(\"Sync\"),\n\tLocal:   gotext.Get(\"Local\"),\n\tSrcInfo: gotext.Get(\"SRCINFO\"),\n\tMissing: gotext.Get(\"Missing\"),\n}\n\nvar bgColorMap = map[Source]string{\n\tAUR:     \"lightblue\",\n\tSync:    \"lemonchiffon\",\n\tLocal:   \"darkolivegreen1\",\n\tMissing: \"tomato\",\n}\n\nvar colorMap = map[Reason]string{\n\tExplicit: \"black\",\n\tDep:      \"deeppink\",\n\tMakeDep:  \"navyblue\",\n\tCheckDep: \"forestgreen\",\n}\n\ntype Grapher struct {\n\tlogger        *text.Logger\n\tproviderCache map[string][]aur.Pkg\n\n\tdbExecutor  db.Executor\n\taurClient   aurc.QueryClient\n\tfullGraph   bool // If true, the graph will include all dependencies including already installed ones or repo\n\tnoConfirm   bool // If true, the graph will not prompt for confirmation\n\tnoDeps      bool // If true, the graph will not include dependencies\n\tnoCheckDeps bool // If true, the graph will not include check dependencies\n\tneeded      bool // If true, the graph will only include packages that are not installed\n}\n\nfunc NewGrapher(dbExecutor db.Executor, aurCache aurc.QueryClient,\n\tfullGraph, noConfirm, noDeps, noCheckDeps, needed bool,\n\tlogger *text.Logger,\n) *Grapher {\n\treturn &Grapher{\n\t\tdbExecutor:    dbExecutor,\n\t\taurClient:     aurCache,\n\t\tfullGraph:     fullGraph,\n\t\tnoConfirm:     noConfirm,\n\t\tnoDeps:        noDeps,\n\t\tnoCheckDeps:   noCheckDeps,\n\t\tneeded:        needed,\n\t\tproviderCache: make(map[string][]aurc.Pkg, 5),\n\t\tlogger:        logger,\n\t}\n}\n\nfunc NewGraph() *topo.Graph[string, *InstallInfo] {\n\treturn topo.New[string, *InstallInfo]()\n}\n\nfunc (g *Grapher) GraphFromTargets(ctx context.Context,\n\tgraph *topo.Graph[string, *InstallInfo], targets []string,\n) (*topo.Graph[string, *InstallInfo], error) {\n\tif graph == nil {\n\t\tgraph = NewGraph()\n\t}\n\n\taurTargets := make([]string, 0, len(targets))\n\n\tfor _, targetString := range targets {\n\t\ttarget := ToTarget(targetString)\n\n\t\tswitch target.DB {\n\t\tcase \"\": // unspecified db\n\t\t\tif pkg := g.dbExecutor.SyncSatisfier(target.Name); pkg != nil {\n\t\t\t\tg.GraphSyncPkg(ctx, graph, pkg, nil)\n\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tgroupPackages := g.dbExecutor.PackagesFromGroup(target.Name)\n\t\t\tif len(groupPackages) > 0 {\n\t\t\t\tdbName := groupPackages[0].DB().Name()\n\t\t\t\tg.GraphSyncGroup(ctx, graph, target.Name, dbName)\n\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tfallthrough\n\t\tcase \"aur\":\n\t\t\taurTargets = append(aurTargets, target.Name)\n\t\tdefault:\n\t\t\tpkg, err := g.dbExecutor.SatisfierFromDB(target.Name, target.DB)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tif pkg != nil {\n\t\t\t\tg.GraphSyncPkg(ctx, graph, pkg, nil)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tgroupPackages, err := g.dbExecutor.PackagesFromGroupAndDB(target.Name, target.DB)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tif len(groupPackages) > 0 {\n\t\t\t\tg.GraphSyncGroup(ctx, graph, target.Name, target.DB)\n\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tg.logger.Errorln(gotext.Get(\"No package found for\"), \" \", target)\n\t\t}\n\t}\n\n\tvar errA error\n\tgraph, errA = g.GraphFromAUR(ctx, graph, aurTargets)\n\tif errA != nil {\n\t\treturn nil, errA\n\t}\n\n\treturn graph, nil\n}\n\nfunc (g *Grapher) pickSrcInfoPkgs(pkgs []*aurc.Pkg) ([]*aurc.Pkg, error) {\n\tfinal := make([]*aurc.Pkg, 0, len(pkgs))\n\tfor i := range pkgs {\n\t\tg.logger.Println(text.Magenta(strconv.Itoa(i+1)+\" \") + text.Bold(pkgs[i].Name) +\n\t\t\t\" \" + text.Cyan(pkgs[i].Version))\n\t\tg.logger.Println(\"    \" + pkgs[i].Description)\n\t}\n\tg.logger.Infoln(gotext.Get(\"Packages to exclude\") + \" (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\"):\")\n\n\tnumberBuf, err := g.logger.GetInput(\"\", g.noConfirm)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tinclude, exclude, _, otherExclude := intrange.ParseNumberMenu(numberBuf)\n\tisInclude := len(exclude) == 0 && otherExclude.Cardinality() == 0\n\n\tfor i := 1; i <= len(pkgs); i++ {\n\t\ttarget := i - 1\n\n\t\tif isInclude && !include.Get(i) {\n\t\t\tfinal = append(final, pkgs[target])\n\t\t}\n\n\t\tif !isInclude && (exclude.Get(i)) {\n\t\t\tfinal = append(final, pkgs[target])\n\t\t}\n\t}\n\n\treturn final, nil\n}\n\nfunc (g *Grapher) addAurPkgProvides(pkg *aurc.Pkg, graph *topo.Graph[string, *InstallInfo]) {\n\tfor i := range pkg.Provides {\n\t\tdepName, mod, version := splitDep(pkg.Provides[i])\n\t\tg.logger.Debugln(pkg.String() + \" provides: \" + depName)\n\t\tgraph.AddProvides(depName, &alpm.Depend{\n\t\t\tName:    depName,\n\t\t\tVersion: version,\n\t\t\tMod:     aurDepModToAlpmDep(mod),\n\t\t}, pkg.Name)\n\t}\n}\n\nfunc (g *Grapher) GraphFromSrcInfos(ctx context.Context, graph *topo.Graph[string, *InstallInfo],\n\tsrcInfos map[string]*gosrc.Srcinfo,\n) (*topo.Graph[string, *InstallInfo], error) {\n\tif graph == nil {\n\t\tgraph = NewGraph()\n\t}\n\n\taurPkgsAdded := []*aurc.Pkg{}\n\tfor pkgBuildDir, pkgbuild := range srcInfos {\n\t\taurPkgs, err := makeAURPKGFromSrcinfo(g.dbExecutor, pkgbuild)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tif len(aurPkgs) > 1 {\n\t\t\tvar errPick error\n\t\t\taurPkgs, errPick = g.pickSrcInfoPkgs(aurPkgs)\n\t\t\tif errPick != nil {\n\t\t\t\treturn nil, errPick\n\t\t\t}\n\t\t}\n\n\t\tfor _, pkg := range aurPkgs {\n\t\t\treason := Explicit\n\t\t\tif pkg := g.dbExecutor.LocalPackage(pkg.Name); pkg != nil {\n\t\t\t\treason = Reason(pkg.Reason())\n\t\t\t}\n\n\t\t\tgraph.AddNode(pkg.Name)\n\n\t\t\tg.addAurPkgProvides(pkg, graph)\n\n\t\t\tg.ValidateAndSetNodeInfo(graph, pkg.Name, &topo.NodeInfo[*InstallInfo]{\n\t\t\t\tColor:      colorMap[reason],\n\t\t\t\tBackground: bgColorMap[AUR],\n\t\t\t\tValue: &InstallInfo{\n\t\t\t\t\tSource:      SrcInfo,\n\t\t\t\t\tReason:      reason,\n\t\t\t\t\tSrcinfoPath: &pkgBuildDir,\n\t\t\t\t\tAURBase:     &pkg.PackageBase,\n\t\t\t\t\tVersion:     pkg.Version,\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\n\t\taurPkgsAdded = append(aurPkgsAdded, aurPkgs...)\n\t}\n\n\tg.AddDepsForPkgs(ctx, aurPkgsAdded, graph)\n\n\treturn graph, nil\n}\n\nfunc (g *Grapher) AddDepsForPkgs(ctx context.Context, pkgs []*aur.Pkg, graph *topo.Graph[string, *InstallInfo]) {\n\tfor _, pkg := range pkgs {\n\t\tg.addDepNodes(ctx, pkg, graph)\n\t}\n}\n\nfunc (g *Grapher) addDepNodes(ctx context.Context, pkg *aur.Pkg, graph *topo.Graph[string, *InstallInfo]) {\n\tif len(pkg.MakeDepends) > 0 {\n\t\tg.addNodes(ctx, graph, pkg.Name, pkg.MakeDepends, MakeDep)\n\t}\n\n\tif !g.noDeps && len(pkg.Depends) > 0 {\n\t\tg.addNodes(ctx, graph, pkg.Name, pkg.Depends, Dep)\n\t}\n\n\tif !g.noCheckDeps && !g.noDeps && len(pkg.CheckDepends) > 0 {\n\t\tg.addNodes(ctx, graph, pkg.Name, pkg.CheckDepends, CheckDep)\n\t}\n}\n\nfunc (g *Grapher) GraphSyncPkg(ctx context.Context,\n\tgraph *topo.Graph[string, *InstallInfo],\n\tpkg alpm.Package, upgradeInfo *db.SyncUpgrade,\n) *topo.Graph[string, *InstallInfo] {\n\tif graph == nil {\n\t\tgraph = NewGraph()\n\t}\n\n\tgraph.AddNode(pkg.Name())\n\tprovides := pkg.Provides()\n\tfor i := range provides {\n\t\tp := &provides[i]\n\t\tg.logger.Debugln(pkg.Name() + \" provides: \" + p.String())\n\t\tgraph.AddProvides(p.Name, p, pkg.Name())\n\t}\n\n\tdbName := pkg.DB().Name()\n\tinfo := &InstallInfo{\n\t\tSource:     Sync,\n\t\tReason:     Explicit,\n\t\tVersion:    pkg.Version(),\n\t\tSyncDBName: &dbName,\n\t}\n\n\tif upgradeInfo == nil {\n\t\tif localPkg := g.dbExecutor.LocalPackage(pkg.Name()); localPkg != nil {\n\t\t\tinfo.Reason = Reason(localPkg.Reason())\n\t\t}\n\t} else {\n\t\tinfo.Upgrade = true\n\t\tinfo.Reason = Reason(upgradeInfo.Reason)\n\t\tinfo.LocalVersion = upgradeInfo.LocalVersion\n\t}\n\n\tg.ValidateAndSetNodeInfo(graph, pkg.Name(), &topo.NodeInfo[*InstallInfo]{\n\t\tColor:      colorMap[info.Reason],\n\t\tBackground: bgColorMap[info.Source],\n\t\tValue:      info,\n\t})\n\n\treturn graph\n}\n\nfunc (g *Grapher) GraphSyncGroup(ctx context.Context,\n\tgraph *topo.Graph[string, *InstallInfo],\n\tgroupName, dbName string,\n) *topo.Graph[string, *InstallInfo] {\n\tif graph == nil {\n\t\tgraph = NewGraph()\n\t}\n\n\tgraph.AddNode(groupName)\n\n\tg.ValidateAndSetNodeInfo(graph, groupName, &topo.NodeInfo[*InstallInfo]{\n\t\tColor:      colorMap[Explicit],\n\t\tBackground: bgColorMap[Sync],\n\t\tValue: &InstallInfo{\n\t\t\tSource:     Sync,\n\t\t\tReason:     Explicit,\n\t\t\tVersion:    \"\",\n\t\t\tSyncDBName: &dbName,\n\t\t\tIsGroup:    true,\n\t\t},\n\t})\n\n\treturn graph\n}\n\nfunc (g *Grapher) GraphAURTarget(ctx context.Context,\n\tgraph *topo.Graph[string, *InstallInfo],\n\tpkg *aurc.Pkg, instalInfo *InstallInfo,\n) *topo.Graph[string, *InstallInfo] {\n\tif graph == nil {\n\t\tgraph = NewGraph()\n\t}\n\n\tgraph.AddNode(pkg.Name)\n\n\tg.addAurPkgProvides(pkg, graph)\n\n\tg.ValidateAndSetNodeInfo(graph, pkg.Name, &topo.NodeInfo[*InstallInfo]{\n\t\tColor:      colorMap[instalInfo.Reason],\n\t\tBackground: bgColorMap[AUR],\n\t\tValue:      instalInfo,\n\t})\n\n\treturn graph\n}\n\nfunc (g *Grapher) GraphFromAUR(ctx context.Context,\n\tgraph *topo.Graph[string, *InstallInfo],\n\ttargets []string,\n) (*topo.Graph[string, *InstallInfo], error) {\n\tif graph == nil {\n\t\tgraph = NewGraph()\n\t}\n\n\tif len(targets) == 0 {\n\t\treturn graph, nil\n\t}\n\n\taurPkgs, errCache := g.aurClient.Get(ctx, &aurc.Query{By: aurc.Name, Needles: targets})\n\tif errCache != nil {\n\t\tg.logger.Errorln(errCache)\n\t}\n\n\tfor i := range aurPkgs {\n\t\tpkg := &aurPkgs[i]\n\t\tif _, ok := g.providerCache[pkg.Name]; !ok {\n\t\t\tg.providerCache[pkg.Name] = []aurc.Pkg{*pkg}\n\t\t}\n\t}\n\n\taurPkgsAdded := []*aurc.Pkg{}\n\n\tvar packagesNotFound int\n\n\tfor _, target := range targets {\n\t\tif cachedProvidePkg, ok := g.providerCache[target]; ok {\n\t\t\taurPkgs = cachedProvidePkg\n\t\t} else {\n\t\t\tvar errA error\n\t\t\taurPkgs, errA = g.aurClient.Get(ctx, &aurc.Query{By: aurc.Provides, Needles: []string{target}, Contains: true})\n\t\t\tif errA != nil {\n\t\t\t\tg.logger.Errorln(gotext.Get(\"Failed to find AUR package for\"), \" \", target, \":\", errA)\n\t\t\t}\n\t\t}\n\n\t\tif len(aurPkgs) == 0 {\n\t\t\tg.logger.Errorln(gotext.Get(\"No AUR package found for\"), \" \", target)\n\t\t\tpackagesNotFound++\n\n\t\t\tcontinue\n\t\t}\n\n\t\taurPkg := &aurPkgs[0]\n\t\tif len(aurPkgs) > 1 {\n\t\t\tchosen := g.provideMenu(target, aurPkgs)\n\t\t\taurPkg = chosen\n\t\t\tg.providerCache[target] = []aurc.Pkg{*aurPkg}\n\t\t}\n\n\t\treason := Explicit\n\t\tif pkg := g.dbExecutor.LocalPackage(aurPkg.Name); pkg != nil {\n\t\t\treason = Reason(pkg.Reason())\n\n\t\t\tif g.needed {\n\t\t\t\tif db.VerCmp(pkg.Version(), aurPkg.Version) >= 0 {\n\t\t\t\t\tg.logger.Warnln(gotext.Get(\"%s is up to date -- skipping\", text.Cyan(pkg.Name()+\"-\"+pkg.Version())))\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tgraph = g.GraphAURTarget(ctx, graph, aurPkg, &InstallInfo{\n\t\t\tAURBase: &aurPkg.PackageBase,\n\t\t\tReason:  reason,\n\t\t\tSource:  AUR,\n\t\t\tVersion: aurPkg.Version,\n\t\t})\n\t\taurPkgsAdded = append(aurPkgsAdded, aurPkg)\n\t}\n\n\tg.AddDepsForPkgs(ctx, aurPkgsAdded, graph)\n\n\tif packagesNotFound == len(targets) {\n\t\treturn graph, &aur.ErrTargetNotFound{}\n\t}\n\n\treturn graph, nil\n}\n\n// Removes found deps from the deps mapset and returns the found deps.\nfunc (g *Grapher) findDepsFromAUR(ctx context.Context,\n\tgraph *topo.Graph[string, *InstallInfo],\n\tparentPkgName string,\n\tdeps mapset.Set[string],\n) []aurc.Pkg {\n\tpkgsToAdd := make([]aurc.Pkg, 0, deps.Cardinality())\n\tif deps.Cardinality() == 0 {\n\t\treturn []aurc.Pkg{}\n\t}\n\n\tmissingNeedles := make([]string, 0, deps.Cardinality())\n\tfor _, depString := range deps.ToSlice() {\n\t\tif _, ok := g.providerCache[depString]; !ok {\n\t\t\tdepName, _, _ := splitDep(depString)\n\t\t\tmissingNeedles = append(missingNeedles, depName)\n\t\t}\n\t}\n\n\tif len(missingNeedles) != 0 {\n\t\tg.logger.Debugln(\"deps to find\", missingNeedles)\n\t\t// provider search is more demanding than a simple search\n\t\t// try to find name match if possible and then try to find provides.\n\t\taurPkgs, errCache := g.aurClient.Get(ctx, &aurc.Query{\n\t\t\tBy: aurc.Name, Needles: missingNeedles, Contains: false,\n\t\t})\n\t\tif errCache != nil {\n\t\t\tg.logger.Errorln(errCache)\n\t\t}\n\n\t\tfor i := range aurPkgs {\n\t\t\tpkg := &aurPkgs[i]\n\t\t\t// Cache by the full depString (including version) for each dep whose name matches\n\t\t\tfor _, depString := range deps.ToSlice() {\n\t\t\t\tdepName, _, _ := splitDep(depString)\n\t\t\t\tif depName == pkg.Name {\n\t\t\t\t\tg.providerCache[depString] = append(g.providerCache[depString], *pkg)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor _, val := range pkg.Provides {\n\t\t\t\tif val == pkg.Name {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// Also check provides against versioned deps\n\t\t\t\tprovideName, _, _ := splitDep(val)\n\t\t\t\tfor _, depString := range deps.ToSlice() {\n\t\t\t\t\tdepName, _, _ := splitDep(depString)\n\t\t\t\t\tif depName == provideName {\n\t\t\t\t\t\tg.providerCache[depString] = append(g.providerCache[depString], *pkg)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfor _, depString := range deps.ToSlice() {\n\t\tvar aurPkgs []aurc.Pkg\n\t\tdepName, _, _ := splitDep(depString)\n\n\t\tif cachedProvidePkg, ok := g.providerCache[depString]; ok {\n\t\t\taurPkgs = cachedProvidePkg\n\t\t} else {\n\t\t\tvar errA error\n\t\t\taurPkgs, errA = g.aurClient.Get(ctx, &aurc.Query{By: aurc.Provides, Needles: []string{depName}, Contains: true})\n\t\t\tif errA != nil {\n\t\t\t\tg.logger.Errorln(gotext.Get(\"Failed to find AUR package for\"), depString, \":\", errA)\n\t\t\t}\n\t\t}\n\n\t\t// remove packages that don't satisfy the dependency\n\t\tsatisfyingPkgs := make([]aurc.Pkg, 0, len(aurPkgs))\n\t\tfor i := range aurPkgs {\n\t\t\tif satisfiesAur(depString, &aurPkgs[i]) {\n\t\t\t\tsatisfyingPkgs = append(satisfyingPkgs, aurPkgs[i])\n\t\t\t}\n\t\t}\n\t\taurPkgs = satisfyingPkgs\n\n\t\tif len(aurPkgs) == 0 {\n\t\t\t// set of packages that require this dependency\n\t\t\trequiredBySet := mapset.NewThreadUnsafeSet[string]()\n\n\t\t\t// add current parent\n\t\t\trequiredBySet.Add(parentPkgName)\n\n\t\t\t// if dependency is already in graph, get all packages that require it\n\t\t\tif graph.Exists(depName) {\n\t\t\t\tif deps := graph.Dependents(depName); deps != nil {\n\t\t\t\t\tfor parent := range deps {\n\t\t\t\t\t\trequiredBySet.Add(parent)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trequiredBySlice := requiredBySet.ToSlice()\n\t\t\trequiredByStr := strings.Join(requiredBySlice, \", \")\n\t\t\tg.logger.Errorln(gotext.Get(\"No AUR package found for\"), \" \", depString, \" (\", gotext.Get(\"required by\"), \": \", requiredByStr, \")\")\n\n\t\t\tcontinue\n\t\t}\n\n\t\tpkg := aurPkgs[0]\n\t\tif len(aurPkgs) > 1 {\n\t\t\tchosen := g.provideMenu(depString, aurPkgs)\n\t\t\tpkg = *chosen\n\t\t}\n\n\t\tg.providerCache[depString] = []aurc.Pkg{pkg}\n\t\tdeps.Remove(depString)\n\t\tpkgsToAdd = append(pkgsToAdd, pkg)\n\t}\n\n\treturn pkgsToAdd\n}\n\nfunc (g *Grapher) ValidateAndSetNodeInfo(graph *topo.Graph[string, *InstallInfo],\n\tnode string, nodeInfo *topo.NodeInfo[*InstallInfo],\n) {\n\tinfo := graph.GetNodeInfo(node)\n\tif info != nil && info.Value != nil {\n\t\tif info.Value.Reason < nodeInfo.Value.Reason {\n\t\t\treturn // refuse to downgrade reason\n\t\t}\n\t\tif info.Value.Upgrade {\n\t\t\treturn // refuse to overwrite an upgrade\n\t\t}\n\t}\n\n\tgraph.SetNodeInfo(node, nodeInfo)\n}\n\nfunc (g *Grapher) addNodes(\n\tctx context.Context,\n\tgraph *topo.Graph[string, *InstallInfo],\n\tparentPkgName string,\n\tdeps []string,\n\tdepType Reason,\n) {\n\ttargetsToFind := mapset.NewThreadUnsafeSet(deps...)\n\t// Check if in graph already\n\tfor _, depString := range targetsToFind.ToSlice() {\n\t\tdepName, _, _ := splitDep(depString)\n\t\tif !graph.Exists(depName) && !graph.HasProvides(depName) {\n\t\t\tcontinue\n\t\t}\n\n\t\tif graph.Exists(depName) {\n\t\t\tif err := graph.DependOn(depName, parentPkgName); err != nil {\n\t\t\t\tg.logger.Warnln(depString, parentPkgName, err)\n\t\t\t}\n\n\t\t\ttargetsToFind.Remove(depString)\n\t\t}\n\n\t\tif p := graph.GetProviderInfo(depName); p != nil {\n\t\t\tif provideSatisfies(p.String(), depString, p.Version) {\n\t\t\t\tif err := graph.DependOn(p.Provider, parentPkgName); err != nil {\n\t\t\t\t\tg.logger.Warnln(p.Provider, parentPkgName, err)\n\t\t\t\t}\n\n\t\t\t\ttargetsToFind.Remove(depString)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check installed\n\tfor _, depString := range targetsToFind.ToSlice() {\n\t\tdepName, _, _ := splitDep(depString)\n\t\tif !g.dbExecutor.LocalSatisfierExists(depString) {\n\t\t\tcontinue\n\t\t}\n\n\t\tif g.fullGraph {\n\t\t\tg.ValidateAndSetNodeInfo(\n\t\t\t\tgraph,\n\t\t\t\tdepName,\n\t\t\t\t&topo.NodeInfo[*InstallInfo]{Color: colorMap[depType], Background: bgColorMap[Local]})\n\n\t\t\tif err := graph.DependOn(depName, parentPkgName); err != nil {\n\t\t\t\tg.logger.Warnln(depName, parentPkgName, err)\n\t\t\t}\n\t\t}\n\n\t\ttargetsToFind.Remove(depString)\n\t}\n\n\t// Check Sync\n\tfor _, depString := range targetsToFind.ToSlice() {\n\t\talpmPkg := g.dbExecutor.SyncSatisfier(depString)\n\t\tif alpmPkg == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\tif err := graph.DependOn(alpmPkg.Name(), parentPkgName); err != nil {\n\t\t\tg.logger.Warnln(\"repo dep warn:\", depString, parentPkgName, err)\n\t\t}\n\n\t\tdbName := alpmPkg.DB().Name()\n\t\tg.ValidateAndSetNodeInfo(\n\t\t\tgraph,\n\t\t\talpmPkg.Name(),\n\t\t\t&topo.NodeInfo[*InstallInfo]{\n\t\t\t\tColor:      colorMap[depType],\n\t\t\t\tBackground: bgColorMap[Sync],\n\t\t\t\tValue: &InstallInfo{\n\t\t\t\t\tSource:     Sync,\n\t\t\t\t\tReason:     depType,\n\t\t\t\t\tVersion:    alpmPkg.Version(),\n\t\t\t\t\tSyncDBName: &dbName,\n\t\t\t\t},\n\t\t\t})\n\n\t\tif newDeps := alpmPkg.Depends(); len(newDeps) != 0 && g.fullGraph {\n\t\t\tnewDepsSlice := make([]string, 0, len(newDeps))\n\t\t\tfor _, newDep := range newDeps {\n\t\t\t\tnewDepsSlice = append(newDepsSlice, newDep.Name)\n\t\t\t}\n\n\t\t\tg.addNodes(ctx, graph, alpmPkg.Name(), newDepsSlice, Dep)\n\t\t}\n\n\t\ttargetsToFind.Remove(depString)\n\t}\n\n\t// Check AUR\n\tpkgsToAdd := g.findDepsFromAUR(ctx, graph, parentPkgName, targetsToFind)\n\tfor i := range pkgsToAdd {\n\t\taurPkg := &pkgsToAdd[i]\n\t\tif err := graph.DependOn(aurPkg.Name, parentPkgName); err != nil {\n\t\t\tg.logger.Warnln(\"aur dep warn:\", aurPkg.Name, parentPkgName, err)\n\t\t}\n\n\t\tgraph.SetNodeInfo(\n\t\t\taurPkg.Name,\n\t\t\t&topo.NodeInfo[*InstallInfo]{\n\t\t\t\tColor:      colorMap[depType],\n\t\t\t\tBackground: bgColorMap[AUR],\n\t\t\t\tValue: &InstallInfo{\n\t\t\t\t\tSource:  AUR,\n\t\t\t\t\tReason:  depType,\n\t\t\t\t\tAURBase: &aurPkg.PackageBase,\n\t\t\t\t\tVersion: aurPkg.Version,\n\t\t\t\t},\n\t\t\t})\n\n\t\tg.addDepNodes(ctx, aurPkg, graph)\n\t}\n\n\t// Add missing to graph\n\tfor _, depString := range targetsToFind.ToSlice() {\n\t\tdepName, mod, ver := splitDep(depString)\n\t\t// no dep found. add as missing\n\t\tif err := graph.DependOn(depName, parentPkgName); err != nil {\n\t\t\tg.logger.Warnln(\"missing dep warn:\", depString, parentPkgName, err)\n\t\t}\n\t\tgraph.SetNodeInfo(depName, &topo.NodeInfo[*InstallInfo]{\n\t\t\tColor:      colorMap[depType],\n\t\t\tBackground: bgColorMap[Missing],\n\t\t\tValue: &InstallInfo{\n\t\t\t\tSource:  Missing,\n\t\t\t\tReason:  depType,\n\t\t\t\tVersion: fmt.Sprintf(\"%s%s\", mod, ver),\n\t\t\t},\n\t\t})\n\t}\n}\n\nfunc (g *Grapher) provideMenu(dep string, options []aur.Pkg) *aur.Pkg {\n\tsize := len(options)\n\tif size == 1 {\n\t\treturn &options[0]\n\t}\n\n\tstr := text.Bold(gotext.Get(\"There are %[1]d providers available for %[2]s:\", size, dep))\n\tstr += \"\\n\"\n\n\tsize = 1\n\tstr += g.logger.SprintOperationInfo(gotext.Get(\"Repository AUR\"), \"\\n    \")\n\n\tfor i := range options {\n\t\tstr += fmt.Sprintf(\"%d) %s \", size, options[i].Name)\n\t\tsize++\n\t}\n\n\tg.logger.OperationInfoln(str)\n\n\tfor {\n\t\tg.logger.Println(gotext.Get(\"\\nEnter a number (default=1): \"))\n\n\t\tif g.noConfirm {\n\t\t\tg.logger.Println(\"1\")\n\n\t\t\treturn &options[0]\n\t\t}\n\n\t\tnumberBuf, err := g.logger.GetInput(\"\", false)\n\t\tif err != nil {\n\t\t\tg.logger.Errorln(err)\n\n\t\t\treturn &options[0]\n\t\t}\n\n\t\tif numberBuf == \"\" {\n\t\t\treturn &options[0]\n\t\t}\n\n\t\tnum, err := strconv.Atoi(numberBuf)\n\t\tif err != nil {\n\t\t\tg.logger.Errorln(gotext.Get(\"invalid number: %s\", numberBuf))\n\n\t\t\tcontinue\n\t\t}\n\n\t\tif num < 1 || num >= size {\n\t\t\tg.logger.Errorln(gotext.Get(\"invalid value: %d is not between %d and %d\",\n\t\t\t\tnum, 1, size-1))\n\n\t\t\tcontinue\n\t\t}\n\n\t\treturn &options[num-1]\n\t}\n}\n\nfunc makeAURPKGFromSrcinfo(dbExecutor db.Executor, srcInfo *gosrc.Srcinfo) ([]*aur.Pkg, error) {\n\tpkgs := make([]*aur.Pkg, 0, 1)\n\n\talpmArch, err := dbExecutor.AlpmArchitectures()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\talpmArch = append(alpmArch, \"\") // srcinfo assumes no value as \"\"\n\n\tgetDesc := func(pkg *gosrc.Package) string {\n\t\tif pkg.Pkgdesc != \"\" {\n\t\t\treturn pkg.Pkgdesc\n\t\t}\n\n\t\treturn srcInfo.Pkgdesc\n\t}\n\n\tfor i := range srcInfo.Packages {\n\t\tpkg := &srcInfo.Packages[i]\n\n\t\tpkgs = append(pkgs, &aur.Pkg{\n\t\t\tID:            0,\n\t\t\tName:          pkg.Pkgname,\n\t\t\tPackageBaseID: 0,\n\t\t\tPackageBase:   srcInfo.Pkgbase,\n\t\t\tVersion:       srcInfo.Version(),\n\t\t\tDescription:   getDesc(pkg),\n\t\t\tURL:           pkg.URL,\n\t\t\tDepends: append(archStringToString(alpmArch, pkg.Depends),\n\t\t\t\tarchStringToString(alpmArch, srcInfo.Depends)...),\n\t\t\tMakeDepends:  archStringToString(alpmArch, srcInfo.MakeDepends),\n\t\t\tCheckDepends: archStringToString(alpmArch, srcInfo.CheckDepends),\n\t\t\tConflicts: append(archStringToString(alpmArch, pkg.Conflicts),\n\t\t\t\tarchStringToString(alpmArch, srcInfo.Conflicts)...),\n\t\t\tProvides: append(archStringToString(alpmArch, pkg.Provides),\n\t\t\t\tarchStringToString(alpmArch, srcInfo.Provides)...),\n\t\t\tReplaces: append(archStringToString(alpmArch, pkg.Replaces),\n\t\t\t\tarchStringToString(alpmArch, srcInfo.Replaces)...),\n\t\t\tOptDepends: append(archStringToString(alpmArch, pkg.OptDepends),\n\t\t\t\tarchStringToString(alpmArch, srcInfo.OptDepends)...),\n\t\t\tGroups:   pkg.Groups,\n\t\t\tLicense:  pkg.License,\n\t\t\tKeywords: []string{},\n\t\t})\n\t}\n\n\treturn pkgs, nil\n}\n\nfunc archStringToString(alpmArches []string, archString []gosrc.ArchString) []string {\n\tpkgs := make([]string, 0, len(archString))\n\n\tfor _, arch := range archString {\n\t\tif db.ArchIsSupported(alpmArches, arch.Arch) {\n\t\t\tpkgs = append(pkgs, arch.Value)\n\t\t}\n\t}\n\n\treturn pkgs\n}\n\nfunc aurDepModToAlpmDep(mod string) alpm.DepMod {\n\tswitch mod {\n\tcase \"=\":\n\t\treturn alpm.DepModEQ\n\tcase \">=\":\n\t\treturn alpm.DepModGE\n\tcase \"<=\":\n\t\treturn alpm.DepModLE\n\tcase \">\":\n\t\treturn alpm.DepModGT\n\tcase \"<\":\n\t\treturn alpm.DepModLT\n\t}\n\treturn alpm.DepModAny\n}\n"
  },
  {
    "path": "pkg/dep/dep_graph_bench_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage dep\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"os\"\n\t\"testing\"\n\n\taurc \"github.com/Jguer/aur\"\n\talpm \"github.com/Jguer/dyalpm\"\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db/mock\"\n\tmockaur \"github.com/Jguer/yay/v12/pkg/dep/mock\"\n\taur \"github.com/Jguer/yay/v12/pkg/query\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\n// benchCase represents a single benchmark scenario with expected results for validation.\ntype benchCase struct {\n\tname           string\n\ttargets        []string\n\texpectedLayers []map[string]*InstallInfo\n\tnoDeps         bool\n\tnoCheckDeps    bool\n}\n\n// newBenchMockDB creates a mock DB executor for benchmarking gstreamer-git scenarios.\nfunc newBenchMockDB() *mock.DBExecutor {\n\treturn &mock.DBExecutor{\n\t\tSyncPackageFn:       func(string) mock.IPackage { return nil },\n\t\tPackagesFromGroupFn: func(string) []mock.IPackage { return []mock.IPackage{} },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"gstreamer-git\", \"gst-plugins-base-libs-git\", \"gst-plugins-good-git\",\n\t\t\t\t\"gstreamer-git=1.24.0.r37-1\", \"gst-plugins-base-libs-git=1.24.0.r37-1\":\n\t\t\t\treturn nil\n\t\t\tcase \"libxml2\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"libxml2\",\n\t\t\t\t\tPVersion: \"2.12.0-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"core\"),\n\t\t\t\t}\n\t\t\tcase \"glib2\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"glib2\",\n\t\t\t\t\tPVersion: \"2.78.0-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"core\"),\n\t\t\t\t}\n\t\t\tcase \"orc\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"orc\",\n\t\t\t\t\tPVersion: \"0.4.34-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"extra\"),\n\t\t\t\t}\n\t\t\tcase \"libxv\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"libxv\",\n\t\t\t\t\tPVersion: \"1.0.12-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"extra\"),\n\t\t\t\t}\n\t\t\tcase \"iso-codes\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"iso-codes\",\n\t\t\t\t\tPVersion: \"4.15.0-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"extra\"),\n\t\t\t\t}\n\t\t\tcase \"libpulse\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"libpulse\",\n\t\t\t\t\tPVersion: \"16.1-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"extra\"),\n\t\t\t\t}\n\t\t\tcase \"wavpack\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"wavpack\",\n\t\t\t\t\tPVersion: \"5.6.0-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"extra\"),\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"gstreamer-git\", \"gstreamer-git=1.24.0.r37-1\",\n\t\t\t\t\"gst-plugins-base-libs-git\", \"gst-plugins-base-libs-git=1.24.0.r37-1\",\n\t\t\t\t\"gst-plugins-good-git\":\n\t\t\t\treturn false\n\t\t\tcase \"libxml2\", \"glib2\", \"orc\", \"libxv\", \"iso-codes\", \"libpulse\", \"wavpack\",\n\t\t\t\t\"git\", \"meson\", \"ninja\", \"llvm\", \"clang\":\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn true\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage { return nil },\n\t}\n}\n\n// newBenchMockAUR creates a mock AUR client for benchmarking gstreamer-git scenarios.\nfunc newBenchMockAUR(t testing.TB) *mockaur.MockAUR {\n\treturn &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\tif len(query.Needles) > 0 {\n\t\t\tfor _, needle := range query.Needles {\n\t\t\t\tif needle == \"gstreamer-git\" || needle == \"gst-plugins-base-libs-git\" || needle == \"gst-plugins-good-git\" {\n\t\t\t\t\tgstFn := getFromFile(t, \"testdata/gstreamer-git.json\")\n\t\t\t\t\treturn gstFn(ctx, query)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn []aur.Pkg{}, nil\n\t}}\n}\n\n// newJellyfinMockDB creates a mock DB for jellyfin scenarios.\nfunc newJellyfinMockDB() *mock.DBExecutor {\n\treturn &mock.DBExecutor{\n\t\tSyncPackageFn: func(string) mock.IPackage { return nil },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"jellyfin\":\n\t\t\t\treturn nil\n\t\t\tcase \"dotnet-runtime-6.0\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"dotnet-runtime-6.0\",\n\t\t\t\t\tPBase:    \"dotnet-runtime-6.0\",\n\t\t\t\t\tPVersion: \"6.0.100-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"community\"),\n\t\t\t\t}\n\t\t\tcase \"dotnet-sdk-6.0\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"dotnet-sdk-6.0\",\n\t\t\t\t\tPBase:    \"dotnet-sdk-6.0\",\n\t\t\t\t\tPVersion: \"6.0.100-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"community\"),\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t\tPackagesFromGroupFn: func(string) []mock.IPackage { return nil },\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"dotnet-sdk-6.0\", \"dotnet-runtime-6.0\", \"jellyfin-server=10.8.8\", \"jellyfin-web=10.8.8\":\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn true\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage { return nil },\n\t}\n}\n\n// newJellyfinMockAUR creates a mock AUR for jellyfin scenarios.\nfunc newJellyfinMockAUR(t testing.TB) *mockaur.MockAUR {\n\treturn &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\tif len(query.Needles) == 0 {\n\t\t\treturn []aur.Pkg{}, nil\n\t\t}\n\t\tswitch query.Needles[0] {\n\t\tcase \"jellyfin\":\n\t\t\treturn getFromFile(t, \"testdata/jellyfin.json\")(ctx, query)\n\t\tcase \"jellyfin-web\":\n\t\t\treturn getFromFile(t, \"testdata/jellyfin-web.json\")(ctx, query)\n\t\tcase \"jellyfin-server\":\n\t\t\treturn getFromFile(t, \"testdata/jellyfin-server.json\")(ctx, query)\n\t\t}\n\t\treturn []aur.Pkg{}, nil\n\t}}\n}\n\n// newCephMockDB creates a mock DB for ceph scenarios with providers.\nfunc newCephMockDB() *mock.DBExecutor {\n\treturn &mock.DBExecutor{\n\t\tSyncPackageFn:       func(string) mock.IPackage { return nil },\n\t\tPackagesFromGroupFn: func(string) []mock.IPackage { return []mock.IPackage{} },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"ceph-bin\", \"ceph-libs-bin\", \"ceph\", \"ceph-libs\", \"ceph-libs=17.2.6-2\":\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"ceph-libs\", \"ceph-libs=17.2.6-2\":\n\t\t\t\treturn false\n\t\t\tcase \"dep1\", \"dep2\", \"dep3\", \"makedep1\", \"makedep2\", \"checkdep1\":\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn true\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage { return nil },\n\t}\n}\n\n// newCephMockAUR creates a mock AUR for ceph scenarios.\nfunc newCephMockAUR() *mockaur.MockAUR {\n\tmockPkgs := map[string]aur.Pkg{\n\t\t\"ceph-bin\": {\n\t\t\tName:        \"ceph-bin\",\n\t\t\tPackageBase: \"ceph-bin\",\n\t\t\tVersion:     \"17.2.6-2\",\n\t\t\tDepends:     []string{\"ceph-libs=17.2.6-2\", \"dep1\"},\n\t\t\tProvides:    []string{\"ceph=17.2.6-2\"},\n\t\t},\n\t\t\"ceph-libs-bin\": {\n\t\t\tName:        \"ceph-libs-bin\",\n\t\t\tPackageBase: \"ceph-bin\",\n\t\t\tVersion:     \"17.2.6-2\",\n\t\t\tDepends:     []string{\"dep1\", \"dep2\"},\n\t\t\tProvides:    []string{\"ceph-libs=17.2.6-2\"},\n\t\t},\n\t\t\"ceph\": {\n\t\t\tName:         \"ceph\",\n\t\t\tPackageBase:  \"ceph\",\n\t\t\tVersion:      \"17.2.6-2\",\n\t\t\tDepends:      []string{\"ceph-libs=17.2.6-2\", \"dep1\"},\n\t\t\tMakeDepends:  []string{\"makedep1\"},\n\t\t\tCheckDepends: []string{\"checkdep1\"},\n\t\t\tProvides:     []string{\"ceph=17.2.6-2\"},\n\t\t},\n\t\t\"ceph-libs\": {\n\t\t\tName:         \"ceph-libs\",\n\t\t\tPackageBase:  \"ceph\",\n\t\t\tVersion:      \"17.2.6-2\",\n\t\t\tDepends:      []string{\"dep1\", \"dep2\", \"dep3\"},\n\t\t\tMakeDepends:  []string{\"makedep1\", \"makedep2\"},\n\t\t\tCheckDepends: []string{\"checkdep1\"},\n\t\t\tProvides:     []string{\"ceph-libs=17.2.6-2\"},\n\t\t},\n\t}\n\n\treturn &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\tpkgs := []aur.Pkg{}\n\t\tfor _, needle := range query.Needles {\n\t\t\tif pkg, ok := mockPkgs[needle]; ok {\n\t\t\t\tpkgs = append(pkgs, pkg)\n\t\t\t}\n\t\t}\n\t\treturn pkgs, nil\n\t}}\n}\n\n// newAndroidSDKMockDB creates a mock DB for android-sdk scenarios.\nfunc newAndroidSDKMockDB() *mock.DBExecutor {\n\treturn &mock.DBExecutor{\n\t\tSyncPackageFn: func(string) mock.IPackage { return nil },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"android-sdk\":\n\t\t\t\treturn nil\n\t\t\tcase \"jdk11-openjdk\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"jdk11-openjdk\",\n\t\t\t\t\tPVersion: \"11.0.12.u7-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"community\"),\n\t\t\t\t\tPProvides: mock.DependList{\n\t\t\t\t\t\tDepends: []alpm.Depend{\n\t\t\t\t\t\t\t{Name: \"java-environment\", Version: \"11\", Mod: alpm.DepModEQ},\n\t\t\t\t\t\t\t{Name: \"java-environment-openjdk\", Version: \"11\", Mod: alpm.DepModEQ},\n\t\t\t\t\t\t\t{Name: \"jdk11-openjdk\", Version: \"11.0.19.u7-1\", Mod: alpm.DepModEQ},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t\tPackagesFromGroupFn: func(string) []mock.IPackage { return nil },\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"java-environment\":\n\t\t\t\treturn false\n\t\t\tcase \"libxtst\", \"fontconfig\", \"freetype2\", \"lib32-gcc-libs\", \"lib32-glibc\",\n\t\t\t\t\"libx11\", \"libxext\", \"libxrender\", \"zlib\", \"gcc-libs\":\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn true\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage { return nil },\n\t}\n}\n\n// newAndroidSDKMockAUR creates a mock AUR for android-sdk scenarios.\nfunc newAndroidSDKMockAUR(t testing.TB) *mockaur.MockAUR {\n\treturn &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\tif len(query.Needles) > 0 && query.Needles[0] == \"android-sdk\" {\n\t\t\treturn getFromFile(t, \"testdata/android-sdk.json\")(ctx, query)\n\t\t}\n\t\treturn []aur.Pkg{}, nil\n\t}}\n}\n\n// verifyLayers checks that the actual layers match expected layers.\nfunc verifyLayers(t testing.TB, expected, actual []map[string]*InstallInfo) {\n\tt.Helper()\n\trequire.Equal(t, len(expected), len(actual), \"layer count mismatch\")\n\tfor i := range expected {\n\t\trequire.Equal(t, len(expected[i]), len(actual[i]), \"layer %d package count mismatch\", i)\n\t\tfor name, expectedInfo := range expected[i] {\n\t\t\tactualInfo, ok := actual[i][name]\n\t\t\trequire.True(t, ok, \"missing package %s in layer %d\", name, i)\n\t\t\trequire.Equal(t, expectedInfo.Source, actualInfo.Source, \"source mismatch for %s\", name)\n\t\t\trequire.Equal(t, expectedInfo.Reason, actualInfo.Reason, \"reason mismatch for %s\", name)\n\t\t\trequire.Equal(t, expectedInfo.Version, actualInfo.Version, \"version mismatch for %s\", name)\n\t\t\tif expectedInfo.AURBase != nil {\n\t\t\t\trequire.NotNil(t, actualInfo.AURBase, \"AURBase should not be nil for %s\", name)\n\t\t\t\trequire.Equal(t, *expectedInfo.AURBase, *actualInfo.AURBase, \"AURBase mismatch for %s\", name)\n\t\t\t}\n\t\t\tif expectedInfo.SyncDBName != nil {\n\t\t\t\trequire.NotNil(t, actualInfo.SyncDBName, \"SyncDBName should not be nil for %s\", name)\n\t\t\t\trequire.Equal(t, *expectedInfo.SyncDBName, *actualInfo.SyncDBName, \"SyncDBName mismatch for %s\", name)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// BenchmarkGraphFromTargets_GstreamerGit benchmarks dependency graph construction\n// for the gstreamer-git split package scenario.\nfunc BenchmarkGraphFromTargets_GstreamerGit(b *testing.B) {\n\tcases := []benchCase{\n\t\t{\n\t\t\tname:    \"SingleTarget\",\n\t\t\ttargets: []string{\"gst-plugins-good-git\"},\n\t\t\texpectedLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"gst-plugins-good-git\": {Source: AUR, Reason: Explicit, Version: \"1.24.0.r37-1\", AURBase: ptrString(\"gstreamer-git\")}},\n\t\t\t\t{\"gst-plugins-base-libs-git\": {Source: AUR, Reason: Dep, Version: \"1.24.0.r37-1\", AURBase: ptrString(\"gstreamer-git\")}},\n\t\t\t\t{\"gstreamer-git\": {Source: AUR, Reason: Dep, Version: \"1.24.0.r37-1\", AURBase: ptrString(\"gstreamer-git\")}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:    \"TwoTargets\",\n\t\t\ttargets: []string{\"gstreamer-git\", \"gst-plugins-good-git\"},\n\t\t\texpectedLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"gst-plugins-good-git\": {Source: AUR, Reason: Explicit, Version: \"1.24.0.r37-1\", AURBase: ptrString(\"gstreamer-git\")}},\n\t\t\t\t{\"gst-plugins-base-libs-git\": {Source: AUR, Reason: Dep, Version: \"1.24.0.r37-1\", AURBase: ptrString(\"gstreamer-git\")}},\n\t\t\t\t{\"gstreamer-git\": {Source: AUR, Reason: Explicit, Version: \"1.24.0.r37-1\", AURBase: ptrString(\"gstreamer-git\")}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:    \"AllThreeExplicit\",\n\t\t\ttargets: []string{\"gstreamer-git\", \"gst-plugins-base-libs-git\", \"gst-plugins-good-git\"},\n\t\t\texpectedLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"gst-plugins-good-git\": {Source: AUR, Reason: Explicit, Version: \"1.24.0.r37-1\", AURBase: ptrString(\"gstreamer-git\")}},\n\t\t\t\t{\"gst-plugins-base-libs-git\": {Source: AUR, Reason: Explicit, Version: \"1.24.0.r37-1\", AURBase: ptrString(\"gstreamer-git\")}},\n\t\t\t\t{\"gstreamer-git\": {Source: AUR, Reason: Explicit, Version: \"1.24.0.r37-1\", AURBase: ptrString(\"gstreamer-git\")}},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, tc := range cases {\n\t\tb.Run(tc.name, func(b *testing.B) {\n\t\t\tmockDB := newBenchMockDB()\n\t\t\tmockAUR := newBenchMockAUR(b)\n\t\t\tlogger := text.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\")\n\t\t\tg := NewGrapher(mockDB, mockAUR, false, true, tc.noDeps, tc.noCheckDeps, false, logger)\n\n\t\t\t// Verify correctness once before benchmarking\n\t\t\tgraph, err := g.GraphFromTargets(context.Background(), nil, tc.targets)\n\t\t\trequire.NoError(b, err)\n\t\t\tlayers := graph.TopoSortedLayers(nil)\n\t\t\tverifyLayers(b, tc.expectedLayers, layers)\n\n\t\t\tb.ResetTimer()\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _ = g.GraphFromTargets(context.Background(), nil, tc.targets)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// BenchmarkGraphFromTargets_Jellyfin benchmarks dependency graph construction\n// for the jellyfin package with mixed AUR/sync dependencies.\nfunc BenchmarkGraphFromTargets_Jellyfin(b *testing.B) {\n\tcases := []benchCase{\n\t\t{\n\t\t\tname:        \"NoDeps\",\n\t\t\ttargets:     []string{\"jellyfin\"},\n\t\t\tnoDeps:      true,\n\t\t\tnoCheckDeps: false,\n\t\t\texpectedLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"jellyfin\": {Source: AUR, Reason: Explicit, Version: \"10.8.8-1\", AURBase: ptrString(\"jellyfin\")}},\n\t\t\t\t{\"dotnet-sdk-6.0\": {Source: Sync, Reason: MakeDep, Version: \"6.0.100-1\", SyncDBName: ptrString(\"community\")}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:        \"WithDeps\",\n\t\t\ttargets:     []string{\"jellyfin\"},\n\t\t\tnoDeps:      false,\n\t\t\tnoCheckDeps: false,\n\t\t\texpectedLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"jellyfin\": {Source: AUR, Reason: Explicit, Version: \"10.8.8-1\", AURBase: ptrString(\"jellyfin\")}},\n\t\t\t\t{\n\t\t\t\t\t\"jellyfin-web\":    {Source: AUR, Reason: Dep, Version: \"10.8.8-1\", AURBase: ptrString(\"jellyfin\")},\n\t\t\t\t\t\"jellyfin-server\": {Source: AUR, Reason: Dep, Version: \"10.8.8-1\", AURBase: ptrString(\"jellyfin\")},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"dotnet-sdk-6.0\":     {Source: Sync, Reason: MakeDep, Version: \"6.0.100-1\", SyncDBName: ptrString(\"community\")},\n\t\t\t\t\t\"dotnet-runtime-6.0\": {Source: Sync, Reason: Dep, Version: \"6.0.100-1\", SyncDBName: ptrString(\"community\")},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, tc := range cases {\n\t\tb.Run(tc.name, func(b *testing.B) {\n\t\t\tmockDB := newJellyfinMockDB()\n\t\t\tmockAUR := newJellyfinMockAUR(b)\n\t\t\tlogger := text.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\")\n\t\t\tg := NewGrapher(mockDB, mockAUR, false, true, tc.noDeps, tc.noCheckDeps, false, logger)\n\n\t\t\t// Verify correctness once before benchmarking\n\t\t\tgraph, err := g.GraphFromTargets(context.Background(), nil, tc.targets)\n\t\t\trequire.NoError(b, err)\n\t\t\tlayers := graph.TopoSortedLayers(nil)\n\t\t\tverifyLayers(b, tc.expectedLayers, layers)\n\n\t\t\tb.ResetTimer()\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _ = g.GraphFromTargets(context.Background(), nil, tc.targets)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// BenchmarkGraphFromTargets_CephProvides benchmarks dependency graph construction\n// for packages with virtual provides (ceph-bin provides ceph-libs).\nfunc BenchmarkGraphFromTargets_CephProvides(b *testing.B) {\n\tcases := []benchCase{\n\t\t{\n\t\t\tname:    \"CephBinWithLibsBin\",\n\t\t\ttargets: []string{\"ceph-bin\", \"ceph-libs-bin\"},\n\t\t\texpectedLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"ceph-bin\": {Source: AUR, Reason: Explicit, Version: \"17.2.6-2\", AURBase: ptrString(\"ceph-bin\")}},\n\t\t\t\t{\"ceph-libs-bin\": {Source: AUR, Reason: Explicit, Version: \"17.2.6-2\", AURBase: ptrString(\"ceph-bin\")}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:    \"CephOnly\",\n\t\t\ttargets: []string{\"ceph\"},\n\t\t\texpectedLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"ceph\": {Source: AUR, Reason: Explicit, Version: \"17.2.6-2\", AURBase: ptrString(\"ceph\")}},\n\t\t\t\t{\"ceph-libs\": {Source: AUR, Reason: Dep, Version: \"17.2.6-2\", AURBase: ptrString(\"ceph\")}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:    \"CephBinOnly\",\n\t\t\ttargets: []string{\"ceph-bin\"},\n\t\t\texpectedLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"ceph-bin\": {Source: AUR, Reason: Explicit, Version: \"17.2.6-2\", AURBase: ptrString(\"ceph-bin\")}},\n\t\t\t\t{\"ceph-libs\": {Source: AUR, Reason: Dep, Version: \"17.2.6-2\", AURBase: ptrString(\"ceph\")}},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, tc := range cases {\n\t\tb.Run(tc.name, func(b *testing.B) {\n\t\t\tmockDB := newCephMockDB()\n\t\t\tmockAUR := newCephMockAUR()\n\t\t\tlogger := text.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\")\n\t\t\tg := NewGrapher(mockDB, mockAUR, false, true, tc.noDeps, tc.noCheckDeps, false, logger)\n\n\t\t\t// Verify correctness once before benchmarking\n\t\t\tgraph, err := g.GraphFromTargets(context.Background(), nil, tc.targets)\n\t\t\trequire.NoError(b, err)\n\t\t\tlayers := graph.TopoSortedLayers(nil)\n\t\t\tverifyLayers(b, tc.expectedLayers, layers)\n\n\t\t\tb.ResetTimer()\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _ = g.GraphFromTargets(context.Background(), nil, tc.targets)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// BenchmarkGraphFromTargets_AndroidSDK benchmarks dependency graph construction\n// for packages with explicit sync dependencies providing virtual packages.\nfunc BenchmarkGraphFromTargets_AndroidSDK(b *testing.B) {\n\ttc := benchCase{\n\t\tname:    \"WithJDK\",\n\t\ttargets: []string{\"android-sdk\", \"jdk11-openjdk\"},\n\t\texpectedLayers: []map[string]*InstallInfo{\n\t\t\t{\"android-sdk\": {Source: AUR, Reason: Explicit, Version: \"26.1.1-2\", AURBase: ptrString(\"android-sdk\")}},\n\t\t\t{\"jdk11-openjdk\": {Source: Sync, Reason: Explicit, Version: \"11.0.12.u7-1\", SyncDBName: ptrString(\"community\")}},\n\t\t},\n\t}\n\n\tmockDB := newAndroidSDKMockDB()\n\tmockAUR := newAndroidSDKMockAUR(b)\n\tlogger := text.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\")\n\tg := NewGrapher(mockDB, mockAUR, false, true, tc.noDeps, tc.noCheckDeps, false, logger)\n\n\t// Verify correctness once before benchmarking\n\tgraph, err := g.GraphFromTargets(context.Background(), nil, tc.targets)\n\trequire.NoError(b, err)\n\tlayers := graph.TopoSortedLayers(nil)\n\tverifyLayers(b, tc.expectedLayers, layers)\n\n\tb.ResetTimer()\n\tfor i := 0; i < b.N; i++ {\n\t\t_, _ = g.GraphFromTargets(context.Background(), nil, tc.targets)\n\t}\n}\n\n// BenchmarkTopoSortedLayers benchmarks the topological sort operation on pre-built graphs.\nfunc BenchmarkTopoSortedLayers(b *testing.B) {\n\tb.Run(\"GstreamerGit\", func(b *testing.B) {\n\t\tmockDB := newBenchMockDB()\n\t\tmockAUR := newBenchMockAUR(b)\n\t\tlogger := text.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\")\n\t\tg := NewGrapher(mockDB, mockAUR, false, true, false, false, false, logger)\n\n\t\tgraph, err := g.GraphFromTargets(context.Background(), nil, []string{\"gst-plugins-good-git\"})\n\t\trequire.NoError(b, err)\n\n\t\t// Verify correctness\n\t\tlayers := graph.TopoSortedLayers(nil)\n\t\trequire.Len(b, layers, 3)\n\n\t\tb.ResetTimer()\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\t_ = graph.TopoSortedLayers(nil)\n\t\t}\n\t})\n\n\tb.Run(\"Jellyfin\", func(b *testing.B) {\n\t\tmockDB := newJellyfinMockDB()\n\t\tmockAUR := newJellyfinMockAUR(b)\n\t\tlogger := text.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\")\n\t\tg := NewGrapher(mockDB, mockAUR, false, true, false, false, false, logger)\n\n\t\tgraph, err := g.GraphFromTargets(context.Background(), nil, []string{\"jellyfin\"})\n\t\trequire.NoError(b, err)\n\n\t\t// Verify correctness\n\t\tlayers := graph.TopoSortedLayers(nil)\n\t\trequire.Len(b, layers, 3)\n\n\t\tb.ResetTimer()\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\t_ = graph.TopoSortedLayers(nil)\n\t\t}\n\t})\n}\n\n// BenchmarkNewGraph benchmarks graph creation overhead.\nfunc BenchmarkNewGraph(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = NewGraph()\n\t}\n}\n\n// BenchmarkGraphDependOn benchmarks adding dependency edges.\nfunc BenchmarkGraphDependOn(b *testing.B) {\n\tb.Run(\"SmallGraph\", func(b *testing.B) {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\tgraph := NewGraph()\n\t\t\t_ = graph.DependOn(\"pkg1\", \"pkg2\")\n\t\t\t_ = graph.DependOn(\"pkg2\", \"pkg3\")\n\t\t\t_ = graph.DependOn(\"pkg3\", \"pkg4\")\n\t\t}\n\t})\n\n\tb.Run(\"MediumGraph\", func(b *testing.B) {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\tgraph := NewGraph()\n\t\t\t// Create a chain of 20 dependencies\n\t\t\tfor j := 0; j < 20; j++ {\n\t\t\t\t_ = graph.DependOn(\n\t\t\t\t\t\"pkg\"+string(rune('A'+j)),\n\t\t\t\t\t\"pkg\"+string(rune('A'+j+1)),\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "pkg/dep/dep_graph_rpc_test.go",
    "content": "//go:build !integration\n// +build !integration\n\n// Package dep provides tests for tree resolution and parsing using RPC/.SRCINFO metadata\n// instead of PKGBUILD parsing. These tests validate:\n// - Reliable parser: Ability to handle complex packages using provided metadata\n// - Reliable solver: Ability to correctly solve and build complex dependency chains\n// - Split packages: Ability to correctly build and install split packages\npackage dep\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"testing\"\n\n\taurc \"github.com/Jguer/aur\"\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db/mock\"\n\tmockaur \"github.com/Jguer/yay/v12/pkg/dep/mock\"\n\taur \"github.com/Jguer/yay/v12/pkg/query\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\n// TestGrapher_ReliableParser_AWSCliGit tests the reliable parsing capability\n// for complex packages like aws-cli-git that have many dependencies.\n// This validates that the RPC metadata is correctly parsed and dependencies\n// are properly resolved without needing PKGBUILD parsing.\nfunc TestGrapher_ReliableParser_AWSCliGit(t *testing.T) {\n\tmockDB := &mock.DBExecutor{\n\t\tSyncPackageFn:       func(string) mock.IPackage { return nil },\n\t\tPackagesFromGroupFn: func(string) []mock.IPackage { return []mock.IPackage{} },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"aws-cli-git\":\n\t\t\t\treturn nil\n\t\t\tcase \"python\":\n\t\t\t\treturn &mock.Package{PName: \"python\", PVersion: \"3.11.0-1\", PDB: mock.NewDB(\"core\")}\n\t\t\tcase \"python-botocore>=1.19.35\", \"python-botocore\":\n\t\t\t\treturn &mock.Package{PName: \"python-botocore\", PVersion: \"1.29.0-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"python-docutils>=0.10\", \"python-docutils\":\n\t\t\t\treturn &mock.Package{PName: \"python-docutils\", PVersion: \"0.19-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"python-rsa>=3.1.2\", \"python-rsa\":\n\t\t\t\treturn &mock.Package{PName: \"python-rsa\", PVersion: \"4.9-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"python-s3transfer>=0.3.0\", \"python-s3transfer\":\n\t\t\t\treturn &mock.Package{PName: \"python-s3transfer\", PVersion: \"0.6.0-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"python-yaml>=3.10\", \"python-yaml\":\n\t\t\t\treturn &mock.Package{PName: \"python-yaml\", PVersion: \"6.0-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"python-colorama>=0.2.5\", \"python-colorama\":\n\t\t\t\treturn &mock.Package{PName: \"python-colorama\", PVersion: \"0.4.6-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"python-tox>=2.3.1\", \"python-tox\":\n\t\t\t\treturn &mock.Package{PName: \"python-tox\", PVersion: \"4.0.0-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"python-nose>=1.3.7\", \"python-nose\":\n\t\t\t\treturn &mock.Package{PName: \"python-nose\", PVersion: \"1.3.7-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"python-mock>=1.3.0\", \"python-mock\":\n\t\t\t\treturn &mock.Package{PName: \"python-mock\", PVersion: \"5.0.0-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"python-wheel>=0.24.0\", \"python-wheel\":\n\t\t\t\treturn &mock.Package{PName: \"python-wheel\", PVersion: \"0.38.0-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"python-dateutil>=2.1\", \"python-dateutil\":\n\t\t\t\treturn &mock.Package{PName: \"python-dateutil\", PVersion: \"2.8.2-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"python-sphinx>=1.1.3\", \"python-sphinx\":\n\t\t\t\treturn &mock.Package{PName: \"python-sphinx\", PVersion: \"6.0.0-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"python-distribute\":\n\t\t\t\treturn &mock.Package{PName: \"python-distribute\", PVersion: \"0.7.3-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"git\":\n\t\t\t\treturn &mock.Package{PName: \"git\", PVersion: \"2.39.0-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\t}\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"aws-cli-git\":\n\t\t\t\treturn false\n\t\t\tcase \"python\", \"python-botocore>=1.19.35\", \"python-docutils>=0.10\",\n\t\t\t\t\"python-rsa>=3.1.2\", \"python-s3transfer>=0.3.0\", \"python-yaml>=3.10\",\n\t\t\t\t\"python-colorama>=0.2.5\", \"python-tox>=2.3.1\", \"python-nose>=1.3.7\",\n\t\t\t\t\"python-mock>=1.3.0\", \"python-wheel>=0.24.0\", \"python-dateutil>=2.1\",\n\t\t\t\t\"python-sphinx>=1.1.3\", \"python-distribute\", \"git\":\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage { return nil },\n\t}\n\n\tmockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\tif len(query.Needles) > 0 && query.Needles[0] == \"aws-cli-git\" {\n\t\t\tawsFn := getFromFile(t, \"testdata/aws-cli-git.json\")\n\t\t\treturn awsFn(ctx, query)\n\t\t}\n\t\treturn []aur.Pkg{}, nil\n\t}}\n\n\tt.Run(\"parses aws-cli-git with all its dependencies\", func(t *testing.T) {\n\t\tg := NewGrapher(mockDB, mockAUR, false, true, false, false, false,\n\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\t\tgot, err := g.GraphFromTargets(context.Background(), nil, []string{\"aws-cli-git\"})\n\t\trequire.NoError(t, err)\n\t\tlayers := got.TopoSortedLayers(nil)\n\n\t\trequire.NotEmpty(t, layers)\n\t\trequire.Contains(t, layers[0], \"aws-cli-git\")\n\t\trequire.Equal(t, \"1.27.145.r11217.g5885ee4dc-1\", layers[0][\"aws-cli-git\"].Version)\n\t\trequire.Equal(t, \"aws-cli-git\", *layers[0][\"aws-cli-git\"].AURBase)\n\t\trequire.Equal(t, Explicit, layers[0][\"aws-cli-git\"].Reason)\n\t\trequire.Equal(t, AUR, layers[0][\"aws-cli-git\"].Source)\n\t})\n\n\tt.Run(\"validates provides field for aws-cli\", func(t *testing.T) {\n\t\tg := NewGrapher(mockDB, mockAUR, false, true, false, false, false,\n\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\t\tgot, err := g.GraphFromTargets(context.Background(), nil, []string{\"aws-cli-git\"})\n\t\trequire.NoError(t, err)\n\t\tlayers := got.TopoSortedLayers(nil)\n\n\t\trequire.NotEmpty(t, layers)\n\t\trequire.Contains(t, layers[0], \"aws-cli-git\")\n\t})\n}\n\n// TestGrapher_ReliableSolver_LiriDesktopGit tests the dependency solver\n// with complex dependency chains like liri-desktop-git metapackage.\nfunc TestGrapher_ReliableSolver_LiriDesktopGit(t *testing.T) {\n\tmockDB := &mock.DBExecutor{\n\t\tSyncPackageFn:       func(string) mock.IPackage { return nil },\n\t\tPackagesFromGroupFn: func(string) []mock.IPackage { return []mock.IPackage{} },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"liri-desktop-git\", \"liri-shell-git\", \"liri-settings-git\",\n\t\t\t\t\"libliri-git\", \"fluid-git\", \"liri-cmake-shared-git\":\n\t\t\t\treturn nil\n\t\t\tcase \"qt5-declarative\":\n\t\t\t\treturn &mock.Package{PName: \"qt5-declarative\", PVersion: \"5.15.10-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"qt5-quickcontrols2\":\n\t\t\t\treturn &mock.Package{PName: \"qt5-quickcontrols2\", PVersion: \"5.15.10-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"qt5-svg\":\n\t\t\t\treturn &mock.Package{PName: \"qt5-svg\", PVersion: \"5.15.10-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"qt5-graphicaleffects\":\n\t\t\t\treturn &mock.Package{PName: \"qt5-graphicaleffects\", PVersion: \"5.15.10-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"qt5-wayland\":\n\t\t\t\treturn &mock.Package{PName: \"qt5-wayland\", PVersion: \"5.15.10-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"wayland\":\n\t\t\t\treturn &mock.Package{PName: \"wayland\", PVersion: \"1.22.0-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"cmake\":\n\t\t\t\treturn &mock.Package{PName: \"cmake\", PVersion: \"3.28.0-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"qt5-tools\":\n\t\t\t\treturn &mock.Package{PName: \"qt5-tools\", PVersion: \"5.15.10-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"git\":\n\t\t\t\treturn &mock.Package{PName: \"git\", PVersion: \"2.43.0-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\t}\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"liri-desktop-git\", \"liri-shell-git\", \"liri-settings-git\",\n\t\t\t\t\"libliri-git\", \"fluid-git\":\n\t\t\t\treturn false\n\t\t\tcase \"liri-cmake-shared-git\": // makedepend from AUR\n\t\t\t\treturn false\n\t\t\tcase \"qt5-declarative\", \"qt5-quickcontrols2\", \"qt5-svg\",\n\t\t\t\t\"qt5-graphicaleffects\", \"qt5-wayland\", \"wayland\",\n\t\t\t\t\"cmake\", \"qt5-tools\", \"git\":\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage { return nil },\n\t}\n\n\tmockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\tfor _, needle := range query.Needles {\n\t\t\tswitch needle {\n\t\t\tcase \"liri-desktop-git\", \"liri-shell-git\", \"liri-settings-git\",\n\t\t\t\t\"libliri-git\", \"fluid-git\", \"liri-cmake-shared-git\":\n\t\t\t\tliriFn := getFromFile(t, \"testdata/liri-desktop-git.json\")\n\t\t\t\treturn liriFn(ctx, query)\n\t\t\t}\n\t\t}\n\t\treturn []aur.Pkg{}, nil\n\t}}\n\n\tt.Run(\"liri-desktop-git pulls all dependencies\", func(t *testing.T) {\n\t\tg := NewGrapher(mockDB, mockAUR, false, true, false, false, false,\n\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\t\tgot, err := g.GraphFromTargets(context.Background(), nil, []string{\"liri-desktop-git\"})\n\t\trequire.NoError(t, err)\n\t\tlayers := got.TopoSortedLayers(nil)\n\n\t\ttotalPkgs := 0\n\t\tfor _, layer := range layers {\n\t\t\ttotalPkgs += len(layer)\n\t\t}\n\t\t// 6 packages: liri-desktop-git + 4 deps + liri-cmake-shared-git (makedep)\n\t\trequire.Equal(t, 6, totalPkgs)\n\t\trequire.Contains(t, layers[0], \"liri-desktop-git\")\n\t\trequire.Equal(t, Explicit, layers[0][\"liri-desktop-git\"].Reason)\n\t})\n\n\tt.Run(\"complex dependency chain resolves in correct order\", func(t *testing.T) {\n\t\tg := NewGrapher(mockDB, mockAUR, false, true, false, false, false,\n\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\t\tgot, err := g.GraphFromTargets(context.Background(), nil, []string{\"liri-desktop-git\"})\n\t\trequire.NoError(t, err)\n\t\tlayers := got.TopoSortedLayers(nil)\n\n\t\trequire.Contains(t, layers[0], \"liri-desktop-git\")\n\n\t\tallPkgs := make(map[string]bool)\n\t\tfor _, layer := range layers {\n\t\t\tfor pkg := range layer {\n\t\t\t\tallPkgs[pkg] = true\n\t\t\t}\n\t\t}\n\t\trequire.True(t, allPkgs[\"liri-desktop-git\"])\n\t\trequire.True(t, allPkgs[\"liri-shell-git\"])\n\t\trequire.True(t, allPkgs[\"liri-settings-git\"])\n\t\trequire.True(t, allPkgs[\"fluid-git\"])\n\t\trequire.True(t, allPkgs[\"libliri-git\"])\n\t\trequire.True(t, allPkgs[\"liri-cmake-shared-git\"]) // makedepend\n\t})\n}\n\n// TestGrapher_SplitPackages_Clion tests split packages where multiple packages\n// come from the same package base, ensuring no rebuilding or reinstalling multiple times.\nfunc TestGrapher_SplitPackages_Clion(t *testing.T) {\n\tmockDB := &mock.DBExecutor{\n\t\tSyncPackageFn:       func(string) mock.IPackage { return nil },\n\t\tPackagesFromGroupFn: func(string) []mock.IPackage { return []mock.IPackage{} },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"clion\", \"clion-jre\", \"clion-cmake\", \"clion-gdb\", \"clion-lldb\":\n\t\t\t\treturn nil\n\t\t\tcase \"libdbusmenu-glib\":\n\t\t\t\treturn &mock.Package{PName: \"libdbusmenu-glib\", PVersion: \"16.04.0-5\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"rsync\":\n\t\t\t\treturn &mock.Package{PName: \"rsync\", PVersion: \"3.2.7-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"glibc\":\n\t\t\t\treturn &mock.Package{PName: \"glibc\", PVersion: \"2.38-1\", PDB: mock.NewDB(\"core\")}\n\t\t\tcase \"gcc-libs\":\n\t\t\t\treturn &mock.Package{PName: \"gcc-libs\", PVersion: \"13.2.1-1\", PDB: mock.NewDB(\"core\")}\n\t\t\tcase \"python\":\n\t\t\t\treturn &mock.Package{PName: \"python\", PVersion: \"3.11.0-1\", PDB: mock.NewDB(\"core\")}\n\t\t\t}\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"clion\", \"clion-jre\", \"clion-cmake\", \"clion-gdb\", \"clion-lldb\":\n\t\t\t\treturn false\n\t\t\tcase \"libdbusmenu-glib\", \"rsync\", \"glibc\", \"gcc-libs\", \"python\":\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage { return nil },\n\t}\n\n\tmockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\tfor _, needle := range query.Needles {\n\t\t\tswitch needle {\n\t\t\tcase \"clion\", \"clion-jre\", \"clion-cmake\", \"clion-gdb\", \"clion-lldb\":\n\t\t\t\tclionFn := getFromFile(t, \"testdata/clion.json\")\n\t\t\t\treturn clionFn(ctx, query)\n\t\t\t}\n\t\t}\n\t\treturn []aur.Pkg{}, nil\n\t}}\n\n\tinstallInfos := map[string]*InstallInfo{\n\t\t\"clion exp\":       {Source: AUR, Reason: Explicit, Version: \"2025.3.1.1-1\", AURBase: ptrString(\"clion\")},\n\t\t\"clion-jre exp\":   {Source: AUR, Reason: Explicit, Version: \"2025.3.1.1-1\", AURBase: ptrString(\"clion\")},\n\t\t\"clion-cmake exp\": {Source: AUR, Reason: Explicit, Version: \"2025.3.1.1-1\", AURBase: ptrString(\"clion\")},\n\t\t\"clion-gdb exp\":   {Source: AUR, Reason: Explicit, Version: \"2025.3.1.1-1\", AURBase: ptrString(\"clion\")},\n\t\t\"clion-lldb exp\":  {Source: AUR, Reason: Explicit, Version: \"2025.3.1.1-1\", AURBase: ptrString(\"clion\")},\n\t}\n\n\ttests := []struct {\n\t\tname       string\n\t\ttargets    []string\n\t\twantLayers []map[string]*InstallInfo\n\t}{\n\t\t{\n\t\t\tname:    \"single clion package\",\n\t\t\ttargets: []string{\"clion\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"clion\": installInfos[\"clion exp\"]},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:    \"clion with clion-jre\",\n\t\t\ttargets: []string{\"clion\", \"clion-jre\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"clion\": installInfos[\"clion exp\"], \"clion-jre\": installInfos[\"clion-jre exp\"]},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:    \"all clion packages from same base\",\n\t\t\ttargets: []string{\"clion\", \"clion-jre\", \"clion-cmake\", \"clion-gdb\", \"clion-lldb\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\n\t\t\t\t\t\"clion\":       installInfos[\"clion exp\"],\n\t\t\t\t\t\"clion-jre\":   installInfos[\"clion-jre exp\"],\n\t\t\t\t\t\"clion-cmake\": installInfos[\"clion-cmake exp\"],\n\t\t\t\t\t\"clion-gdb\":   installInfos[\"clion-gdb exp\"],\n\t\t\t\t\t\"clion-lldb\":  installInfos[\"clion-lldb exp\"],\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tg := NewGrapher(mockDB, mockAUR, false, true, false, false, false,\n\t\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\t\t\tgot, err := g.GraphFromTargets(context.Background(), nil, tt.targets)\n\t\t\trequire.NoError(t, err)\n\t\t\tlayers := got.TopoSortedLayers(nil)\n\t\t\trequire.EqualValues(t, tt.wantLayers, layers, layers)\n\t\t})\n\t}\n\n\tt.Run(\"packages from same base share AURBase\", func(t *testing.T) {\n\t\tg := NewGrapher(mockDB, mockAUR, false, true, false, false, false,\n\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\t\tgot, err := g.GraphFromTargets(context.Background(), nil,\n\t\t\t[]string{\"clion\", \"clion-jre\", \"clion-cmake\"})\n\t\trequire.NoError(t, err)\n\t\tlayers := got.TopoSortedLayers(nil)\n\n\t\trequire.Len(t, layers, 1)\n\t\tfor _, info := range layers[0] {\n\t\t\trequire.NotNil(t, info.AURBase)\n\t\t\trequire.Equal(t, \"clion\", *info.AURBase)\n\t\t}\n\t})\n}\n\n// TestGrapher_SplitPackages_SamsungUnifiedDriver tests split packages where\n// packages depend on another package from the same package base.\nfunc TestGrapher_SplitPackages_SamsungUnifiedDriver(t *testing.T) {\n\tmockDB := &mock.DBExecutor{\n\t\tSyncPackageFn:       func(string) mock.IPackage { return nil },\n\t\tPackagesFromGroupFn: func(string) []mock.IPackage { return []mock.IPackage{} },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"samsung-unified-driver\", \"samsung-unified-driver-common\",\n\t\t\t\t\"samsung-unified-driver-printer\", \"samsung-unified-driver-scanner\":\n\t\t\t\treturn nil\n\t\t\tcase \"cups\":\n\t\t\t\treturn &mock.Package{PName: \"cups\", PVersion: \"2.4.2-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"ghostscript\":\n\t\t\t\treturn &mock.Package{PName: \"ghostscript\", PVersion: \"10.02.0-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"libxml2-legacy\":\n\t\t\t\treturn &mock.Package{PName: \"libxml2-legacy\", PVersion: \"2.10.3-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"libusb-compat\":\n\t\t\t\treturn &mock.Package{PName: \"libusb-compat\", PVersion: \"0.1.8-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"sane\":\n\t\t\t\treturn &mock.Package{PName: \"sane\", PVersion: \"1.2.1-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\t}\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"samsung-unified-driver\", \"samsung-unified-driver-common\",\n\t\t\t\t\"samsung-unified-driver-printer\", \"samsung-unified-driver-scanner\":\n\t\t\t\treturn false\n\t\t\tcase \"cups\", \"ghostscript\", \"libxml2-legacy\", \"libusb-compat\", \"sane\":\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage { return nil },\n\t}\n\n\tmockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\tfor _, needle := range query.Needles {\n\t\t\tswitch needle {\n\t\t\tcase \"samsung-unified-driver\", \"samsung-unified-driver-common\",\n\t\t\t\t\"samsung-unified-driver-printer\", \"samsung-unified-driver-scanner\":\n\t\t\t\tsamsungFn := getFromFile(t, \"testdata/samsung-unified-driver.json\")\n\t\t\t\treturn samsungFn(ctx, query)\n\t\t\t}\n\t\t}\n\t\treturn []aur.Pkg{}, nil\n\t}}\n\n\ttests := []struct {\n\t\tname           string\n\t\ttargets        []string\n\t\twantPkgCount   int\n\t\twantContains   []string\n\t\twantNotContain []string\n\t}{\n\t\t{\n\t\t\tname:         \"metapackage samsung-unified-driver pulls printer and scanner\",\n\t\t\ttargets:      []string{\"samsung-unified-driver\"},\n\t\t\twantPkgCount: 4,\n\t\t\twantContains: []string{\n\t\t\t\t\"samsung-unified-driver\",\n\t\t\t\t\"samsung-unified-driver-printer\",\n\t\t\t\t\"samsung-unified-driver-scanner\",\n\t\t\t\t\"samsung-unified-driver-common\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:           \"printer alone pulls common\",\n\t\t\ttargets:        []string{\"samsung-unified-driver-printer\"},\n\t\t\twantPkgCount:   2,\n\t\t\twantContains:   []string{\"samsung-unified-driver-printer\", \"samsung-unified-driver-common\"},\n\t\t\twantNotContain: []string{\"samsung-unified-driver-scanner\"},\n\t\t},\n\t\t{\n\t\t\tname:           \"scanner alone pulls common\",\n\t\t\ttargets:        []string{\"samsung-unified-driver-scanner\"},\n\t\t\twantPkgCount:   2,\n\t\t\twantContains:   []string{\"samsung-unified-driver-scanner\", \"samsung-unified-driver-common\"},\n\t\t\twantNotContain: []string{\"samsung-unified-driver-printer\"},\n\t\t},\n\t\t{\n\t\t\tname:         \"common alone\",\n\t\t\ttargets:      []string{\"samsung-unified-driver-common\"},\n\t\t\twantPkgCount: 1,\n\t\t\twantContains: []string{\"samsung-unified-driver-common\"},\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tg := NewGrapher(mockDB, mockAUR, false, true, false, false, false,\n\t\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\t\t\tgot, err := g.GraphFromTargets(context.Background(), nil, tt.targets)\n\t\t\trequire.NoError(t, err)\n\t\t\tlayers := got.TopoSortedLayers(nil)\n\n\t\t\tallPkgs := make(map[string]bool)\n\t\t\tfor _, layer := range layers {\n\t\t\t\tfor pkg := range layer {\n\t\t\t\t\tallPkgs[pkg] = true\n\t\t\t\t}\n\t\t\t}\n\t\t\trequire.Equal(t, tt.wantPkgCount, len(allPkgs))\n\n\t\t\tfor _, pkg := range tt.wantContains {\n\t\t\t\trequire.True(t, allPkgs[pkg], \"expected package %s not found\", pkg)\n\t\t\t}\n\n\t\t\tfor _, pkg := range tt.wantNotContain {\n\t\t\t\trequire.False(t, allPkgs[pkg], \"unexpected package %s found\", pkg)\n\t\t\t}\n\t\t})\n\t}\n\n\tt.Run(\"split package internal deps resolved correctly\", func(t *testing.T) {\n\t\tg := NewGrapher(mockDB, mockAUR, false, true, false, false, false,\n\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\t\tgot, err := g.GraphFromTargets(context.Background(), nil, []string{\"samsung-unified-driver\"})\n\t\trequire.NoError(t, err)\n\t\tlayers := got.TopoSortedLayers(nil)\n\n\t\tlastLayer := layers[len(layers)-1]\n\t\trequire.Contains(t, lastLayer, \"samsung-unified-driver-common\")\n\n\t\tfor _, layer := range layers {\n\t\t\tfor _, info := range layer {\n\t\t\t\trequire.NotNil(t, info.AURBase)\n\t\t\t\trequire.Equal(t, \"samsung-unified-driver\", *info.AURBase)\n\t\t\t}\n\t\t}\n\t})\n}\n\n// TestGrapher_SplitPackages_NX tests independent split packages like nxproxy and nxagent.\nfunc TestGrapher_SplitPackages_NX(t *testing.T) {\n\tmockDB := &mock.DBExecutor{\n\t\tSyncPackageFn:       func(string) mock.IPackage { return nil },\n\t\tPackagesFromGroupFn: func(string) []mock.IPackage { return []mock.IPackage{} },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"nxproxy\", \"nxagent\", \"nx-x11\", \"libxcomp\":\n\t\t\t\treturn nil\n\t\t\tcase \"libjpeg-turbo\":\n\t\t\t\treturn &mock.Package{PName: \"libjpeg-turbo\", PVersion: \"2.1.5-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"libpng\":\n\t\t\t\treturn &mock.Package{PName: \"libpng\", PVersion: \"1.6.39-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"gcc-libs\":\n\t\t\t\treturn &mock.Package{PName: \"gcc-libs\", PVersion: \"13.2.1-1\", PDB: mock.NewDB(\"core\")}\n\t\t\tcase \"libxml2\":\n\t\t\t\treturn &mock.Package{PName: \"libxml2\", PVersion: \"2.11.0-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"xkeyboard-config\":\n\t\t\t\treturn &mock.Package{PName: \"xkeyboard-config\", PVersion: \"2.38-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"xorg-xkbcomp\":\n\t\t\t\treturn &mock.Package{PName: \"xorg-xkbcomp\", PVersion: \"1.4.6-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"libxfont2\":\n\t\t\t\treturn &mock.Package{PName: \"libxfont2\", PVersion: \"2.0.6-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"libxinerama\":\n\t\t\t\treturn &mock.Package{PName: \"libxinerama\", PVersion: \"1.1.5-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"xorg-font-util\":\n\t\t\t\treturn &mock.Package{PName: \"xorg-font-util\", PVersion: \"1.4.0-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"pixman\":\n\t\t\t\treturn &mock.Package{PName: \"pixman\", PVersion: \"0.42.2-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"libxrandr\":\n\t\t\t\treturn &mock.Package{PName: \"libxrandr\", PVersion: \"1.5.3-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"libxtst\":\n\t\t\t\treturn &mock.Package{PName: \"libxtst\", PVersion: \"1.2.4-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"libxcomposite\":\n\t\t\t\treturn &mock.Package{PName: \"libxcomposite\", PVersion: \"0.4.6-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"libxpm\":\n\t\t\t\treturn &mock.Package{PName: \"libxpm\", PVersion: \"3.5.16-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"libxdamage\":\n\t\t\t\treturn &mock.Package{PName: \"libxdamage\", PVersion: \"1.1.6-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"libtirpc\":\n\t\t\t\treturn &mock.Package{PName: \"libtirpc\", PVersion: \"1.3.3-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"xorgproto\":\n\t\t\t\treturn &mock.Package{PName: \"xorgproto\", PVersion: \"2023.2-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\tcase \"imake\":\n\t\t\t\treturn &mock.Package{PName: \"imake\", PVersion: \"1.0.9-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\t}\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"nxproxy\", \"nxagent\", \"nx-x11\", \"libxcomp\":\n\t\t\t\treturn false\n\t\t\tcase \"libjpeg-turbo\", \"libpng\", \"gcc-libs\", \"libxml2\",\n\t\t\t\t\"xkeyboard-config\", \"xorg-xkbcomp\", \"libxfont2\", \"libxinerama\",\n\t\t\t\t\"xorg-font-util\", \"pixman\", \"libxrandr\", \"libxtst\",\n\t\t\t\t\"libxcomposite\", \"libxpm\", \"libxdamage\", \"libtirpc\",\n\t\t\t\t\"xorgproto\", \"imake\":\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage { return nil },\n\t}\n\n\tmockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\tfor _, needle := range query.Needles {\n\t\t\tswitch needle {\n\t\t\tcase \"nxproxy\", \"nxagent\", \"nx-x11\", \"libxcomp\":\n\t\t\t\tnxFn := getFromFile(t, \"testdata/nx.json\")\n\t\t\t\treturn nxFn(ctx, query)\n\t\t\t}\n\t\t}\n\t\treturn []aur.Pkg{}, nil\n\t}}\n\n\tinstallInfos := map[string]*InstallInfo{\n\t\t\"nxproxy exp\":  {Source: AUR, Reason: Explicit, Version: \"3.5.99.27-3\", AURBase: ptrString(\"nx\")},\n\t\t\"nxagent exp\":  {Source: AUR, Reason: Explicit, Version: \"3.5.99.27-3\", AURBase: ptrString(\"nx\")},\n\t\t\"nx-x11 dep\":   {Source: AUR, Reason: Dep, Version: \"3.5.99.27-3\", AURBase: ptrString(\"nx\")},\n\t\t\"libxcomp dep\": {Source: AUR, Reason: Dep, Version: \"3.5.99.27-3\", AURBase: ptrString(\"nx\")},\n\t\t\"libxcomp exp\": {Source: AUR, Reason: Explicit, Version: \"3.5.99.27-3\", AURBase: ptrString(\"nx\")},\n\t}\n\n\ttests := []struct {\n\t\tname       string\n\t\ttargets    []string\n\t\twantLayers []map[string]*InstallInfo\n\t}{\n\t\t{\n\t\t\tname:    \"nxproxy independently\",\n\t\t\ttargets: []string{\"nxproxy\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"nxproxy\": installInfos[\"nxproxy exp\"]},\n\t\t\t\t{\"libxcomp\": installInfos[\"libxcomp dep\"]},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:    \"nxagent independently - has more deps\",\n\t\t\ttargets: []string{\"nxagent\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"nxagent\": installInfos[\"nxagent exp\"]},\n\t\t\t\t{\"nx-x11\": installInfos[\"nx-x11 dep\"]},\n\t\t\t\t{\"libxcomp\": installInfos[\"libxcomp dep\"]},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:    \"both nxproxy and nxagent\",\n\t\t\ttargets: []string{\"nxproxy\", \"nxagent\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"nxproxy\": installInfos[\"nxproxy exp\"], \"nxagent\": installInfos[\"nxagent exp\"]},\n\t\t\t\t{\"nx-x11\": installInfos[\"nx-x11 dep\"]},\n\t\t\t\t{\"libxcomp\": installInfos[\"libxcomp dep\"]},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:    \"libxcomp independently\",\n\t\t\ttargets: []string{\"libxcomp\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"libxcomp\": installInfos[\"libxcomp exp\"]},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tg := NewGrapher(mockDB, mockAUR, false, true, false, false, false,\n\t\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\t\t\tgot, err := g.GraphFromTargets(context.Background(), nil, tt.targets)\n\t\t\trequire.NoError(t, err)\n\t\t\tlayers := got.TopoSortedLayers(nil)\n\t\t\trequire.EqualValues(t, tt.wantLayers, layers, layers)\n\t\t})\n\t}\n\n\tt.Run(\"split packages share AURBase but can be installed independently\", func(t *testing.T) {\n\t\tg := NewGrapher(mockDB, mockAUR, false, true, false, false, false,\n\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\n\t\tgot1, err := g.GraphFromTargets(context.Background(), nil, []string{\"nxproxy\"})\n\t\trequire.NoError(t, err)\n\t\tlayers1 := got1.TopoSortedLayers(nil)\n\n\t\tgot2, err := g.GraphFromTargets(context.Background(), nil, []string{\"nxagent\"})\n\t\trequire.NoError(t, err)\n\t\tlayers2 := got2.TopoSortedLayers(nil)\n\n\t\trequire.Equal(t, \"nx\", *layers1[0][\"nxproxy\"].AURBase)\n\t\trequire.Equal(t, \"nx\", *layers2[0][\"nxagent\"].AURBase)\n\n\t\ttotalPkgs1 := 0\n\t\tfor _, layer := range layers1 {\n\t\t\ttotalPkgs1 += len(layer)\n\t\t}\n\t\ttotalPkgs2 := 0\n\t\tfor _, layer := range layers2 {\n\t\t\ttotalPkgs2 += len(layer)\n\t\t}\n\n\t\trequire.Equal(t, 2, totalPkgs1)\n\t\trequire.Equal(t, 3, totalPkgs2)\n\t})\n}\n\n// TestGrapher_SplitPackages_ReversedOrder tests that split packages resolve\n// correctly regardless of the order they are specified in.\nfunc TestGrapher_SplitPackages_ReversedOrder(t *testing.T) {\n\tmockDB := &mock.DBExecutor{\n\t\tSyncPackageFn:       func(string) mock.IPackage { return nil },\n\t\tPackagesFromGroupFn: func(string) []mock.IPackage { return []mock.IPackage{} },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"nxproxy\", \"nxagent\", \"nx-x11\", \"libxcomp\":\n\t\t\t\treturn nil\n\t\t\tdefault:\n\t\t\t\treturn &mock.Package{PName: s, PVersion: \"1.0.0-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\t}\n\t\t},\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"nxproxy\", \"nxagent\", \"nx-x11\", \"libxcomp\":\n\t\t\t\treturn false\n\t\t\tdefault:\n\t\t\t\treturn true\n\t\t\t}\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage { return nil },\n\t}\n\n\tmockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\tfor _, needle := range query.Needles {\n\t\t\tswitch needle {\n\t\t\tcase \"nxproxy\", \"nxagent\", \"nx-x11\", \"libxcomp\":\n\t\t\t\tnxFn := getFromFile(t, \"testdata/nx.json\")\n\t\t\t\treturn nxFn(ctx, query)\n\t\t\t}\n\t\t}\n\t\treturn []aur.Pkg{}, nil\n\t}}\n\n\tt.Run(\"nxproxy nxagent order\", func(t *testing.T) {\n\t\tg := NewGrapher(mockDB, mockAUR, false, true, false, false, false,\n\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\t\tgot, err := g.GraphFromTargets(context.Background(), nil, []string{\"nxproxy\", \"nxagent\"})\n\t\trequire.NoError(t, err)\n\t\tlayers1 := got.TopoSortedLayers(nil)\n\n\t\trequire.Contains(t, layers1[0], \"nxproxy\")\n\t\trequire.Contains(t, layers1[0], \"nxagent\")\n\t})\n\n\tt.Run(\"nxagent nxproxy reversed order\", func(t *testing.T) {\n\t\tg := NewGrapher(mockDB, mockAUR, false, true, false, false, false,\n\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\t\tgot, err := g.GraphFromTargets(context.Background(), nil, []string{\"nxagent\", \"nxproxy\"})\n\t\trequire.NoError(t, err)\n\t\tlayers2 := got.TopoSortedLayers(nil)\n\n\t\trequire.Contains(t, layers2[0], \"nxproxy\")\n\t\trequire.Contains(t, layers2[0], \"nxagent\")\n\t})\n}\n\n// TestGrapher_MultipleInstallInfo ensures that when the same package appears as\n// both explicit target and dependency, the explicit reason takes precedence.\nfunc TestGrapher_MultipleInstallInfo(t *testing.T) {\n\tmockDB := &mock.DBExecutor{\n\t\tSyncPackageFn:       func(string) mock.IPackage { return nil },\n\t\tPackagesFromGroupFn: func(string) []mock.IPackage { return []mock.IPackage{} },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"samsung-unified-driver\", \"samsung-unified-driver-common\",\n\t\t\t\t\"samsung-unified-driver-printer\", \"samsung-unified-driver-scanner\":\n\t\t\t\treturn nil\n\t\t\tdefault:\n\t\t\t\treturn &mock.Package{PName: s, PVersion: \"1.0.0-1\", PDB: mock.NewDB(\"extra\")}\n\t\t\t}\n\t\t},\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"samsung-unified-driver\", \"samsung-unified-driver-common\",\n\t\t\t\t\"samsung-unified-driver-printer\", \"samsung-unified-driver-scanner\":\n\t\t\t\treturn false\n\t\t\tdefault:\n\t\t\t\treturn true\n\t\t\t}\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage { return nil },\n\t}\n\n\tmockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\tfor _, needle := range query.Needles {\n\t\t\tswitch needle {\n\t\t\tcase \"samsung-unified-driver\", \"samsung-unified-driver-common\",\n\t\t\t\t\"samsung-unified-driver-printer\", \"samsung-unified-driver-scanner\":\n\t\t\t\tsamsungFn := getFromFile(t, \"testdata/samsung-unified-driver.json\")\n\t\t\t\treturn samsungFn(ctx, query)\n\t\t\t}\n\t\t}\n\t\treturn []aur.Pkg{}, nil\n\t}}\n\n\tt.Run(\"explicit target takes precedence over dependency\", func(t *testing.T) {\n\t\tg := NewGrapher(mockDB, mockAUR, false, true, false, false, false,\n\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\n\t\tgot, err := g.GraphFromTargets(context.Background(), nil,\n\t\t\t[]string{\"samsung-unified-driver\", \"samsung-unified-driver-common\"})\n\t\trequire.NoError(t, err)\n\t\tlayers := got.TopoSortedLayers(nil)\n\n\t\tfound := false\n\t\tfor _, layer := range layers {\n\t\t\tif info, ok := layer[\"samsung-unified-driver-common\"]; ok {\n\t\t\t\tfound = true\n\t\t\t\trequire.Equal(t, Explicit, info.Reason,\n\t\t\t\t\t\"explicit target should have Explicit reason, not Dep\")\n\t\t\t}\n\t\t}\n\t\trequire.True(t, found, \"samsung-unified-driver-common should be in layers\")\n\t})\n}\n\n// TestGrapher_VersionedDependencies tests proper handling of versioned dependencies.\nfunc TestGrapher_VersionedDependencies(t *testing.T) {\n\tmockDB := &mock.DBExecutor{\n\t\tSyncPackageFn:       func(string) mock.IPackage { return nil },\n\t\tPackagesFromGroupFn: func(string) []mock.IPackage { return []mock.IPackage{} },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"versioned-pkg\", \"dep-pkg\", \"dep-pkg>=2.0.0\":\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tpanic(fmt.Sprintf(\"implement me: %s\", s))\n\t\t},\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"versioned-pkg\", \"dep-pkg\", \"dep-pkg>=2.0.0\":\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn true\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage { return nil },\n\t}\n\n\tmockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\tmockPkgs := map[string]aur.Pkg{\n\t\t\t\"versioned-pkg\": {\n\t\t\t\tName:        \"versioned-pkg\",\n\t\t\t\tPackageBase: \"versioned-pkg\",\n\t\t\t\tVersion:     \"1.0.0-1\",\n\t\t\t\tDepends:     []string{\"dep-pkg>=2.0.0\"},\n\t\t\t},\n\t\t\t\"dep-pkg\": {\n\t\t\t\tName:        \"dep-pkg\",\n\t\t\t\tPackageBase: \"dep-pkg\",\n\t\t\t\tVersion:     \"2.5.0-1\",\n\t\t\t},\n\t\t}\n\n\t\tpkgs := []aur.Pkg{}\n\t\tfor _, needle := range query.Needles {\n\t\t\tif pkg, ok := mockPkgs[needle]; ok {\n\t\t\t\tpkgs = append(pkgs, pkg)\n\t\t\t}\n\t\t}\n\t\treturn pkgs, nil\n\t}}\n\n\tt.Run(\"versioned dependency satisfied by higher version\", func(t *testing.T) {\n\t\tg := NewGrapher(mockDB, mockAUR, false, true, false, false, false,\n\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\t\tgot, err := g.GraphFromTargets(context.Background(), nil, []string{\"versioned-pkg\"})\n\t\trequire.NoError(t, err)\n\t\tlayers := got.TopoSortedLayers(nil)\n\n\t\trequire.Len(t, layers, 2)\n\t\trequire.Contains(t, layers[0], \"versioned-pkg\")\n\t\trequire.Contains(t, layers[1], \"dep-pkg\")\n\t\trequire.Equal(t, \"2.5.0-1\", layers[1][\"dep-pkg\"].Version)\n\t})\n}\n"
  },
  {
    "path": "pkg/dep/dep_graph_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage dep\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"strings\"\n\t\"testing\"\n\n\taurc \"github.com/Jguer/aur\"\n\talpm \"github.com/Jguer/dyalpm\"\n\tmapset \"github.com/deckarep/golang-set/v2\"\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/db/mock\"\n\tmockaur \"github.com/Jguer/yay/v12/pkg/dep/mock\"\n\taur \"github.com/Jguer/yay/v12/pkg/query\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\nfunc ptrString(s string) *string {\n\treturn &s\n}\n\nfunc getFromFile(t testing.TB, filePath string) mockaur.GetFunc {\n\tt.Helper()\n\tf, err := os.Open(filePath)\n\trequire.NoError(t, err)\n\n\tfBytes, err := io.ReadAll(f)\n\trequire.NoError(t, err)\n\n\tpkgs := []aur.Pkg{}\n\terr = json.Unmarshal(fBytes, &pkgs)\n\trequire.NoError(t, err)\n\n\treturn func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\treturn pkgs, nil\n\t}\n}\n\nfunc TestGrapher_findDepsFromAUR_logsRequiredByForMissingDep(t *testing.T) {\n\tmockDB := &mock.DBExecutor{}\n\tmockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\treturn []aur.Pkg{}, nil\n\t}}\n\n\tvar stderr bytes.Buffer\n\tlogger := text.NewLogger(io.Discard, &stderr, strings.NewReader(\"\"), true, \"test\")\n\n\tg := NewGrapher(mockDB, mockAUR, false, true, false, false, false, logger)\n\n\tgraph := NewGraph()\n\n\tdepString := \"missingdep>=1.0\"\n\tdepName := \"missingdep\"\n\trequire.NoError(t, graph.DependOn(\"existingNeeds\", depName))\n\n\ttoFind := mapset.NewThreadUnsafeSet(depString)\n\t_ = g.findDepsFromAUR(context.Background(), graph, \"currentNeeds\", toFind)\n\n\tout := stderr.String()\n\trequire.Contains(t, out, \"No AUR package found for \"+depString+\" (required by:\")\n\trequire.Contains(t, out, \"currentNeeds\")\n\trequire.Contains(t, out, \"existingNeeds\")\n}\n\nfunc TestGrapher_GraphFromTargets_jellyfin(t *testing.T) {\n\tmockDB := &mock.DBExecutor{\n\t\tSyncPackageFn: func(string) mock.IPackage { return nil },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"jellyfin\":\n\t\t\t\treturn nil\n\t\t\tcase \"dotnet-runtime-6.0\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"dotnet-runtime-6.0\",\n\t\t\t\t\tPBase:    \"dotnet-runtime-6.0\",\n\t\t\t\t\tPVersion: \"6.0.100-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"community\"),\n\t\t\t\t}\n\t\t\tcase \"dotnet-sdk-6.0\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"dotnet-sdk-6.0\",\n\t\t\t\t\tPBase:    \"dotnet-sdk-6.0\",\n\t\t\t\t\tPVersion: \"6.0.100-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"community\"),\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn nil\n\t\t},\n\t\tPackagesFromGroupFn: func(string) []mock.IPackage { return nil },\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"dotnet-sdk-6.0\", \"dotnet-runtime-6.0\", \"jellyfin-server=10.8.8\", \"jellyfin-web=10.8.8\":\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\treturn true\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage { return nil },\n\t}\n\n\tmockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\tif query.Needles[0] == \"jellyfin\" {\n\t\t\tjfinFn := getFromFile(t, \"testdata/jellyfin.json\")\n\t\t\treturn jfinFn(ctx, query)\n\t\t}\n\n\t\tif query.Needles[0] == \"jellyfin-web\" {\n\t\t\tjfinWebFn := getFromFile(t, \"testdata/jellyfin-web.json\")\n\t\t\treturn jfinWebFn(ctx, query)\n\t\t}\n\n\t\tif query.Needles[0] == \"jellyfin-server\" {\n\t\t\tjfinServerFn := getFromFile(t, \"testdata/jellyfin-server.json\")\n\t\t\treturn jfinServerFn(ctx, query)\n\t\t}\n\n\t\tpanic(fmt.Sprintf(\"implement me %v\", query.Needles))\n\t}}\n\n\ttype fields struct {\n\t\tdbExecutor  db.Executor\n\t\taurCache    aurc.QueryClient\n\t\tnoDeps      bool\n\t\tnoCheckDeps bool\n\t}\n\ttype args struct {\n\t\ttargets []string\n\t}\n\ttests := []struct {\n\t\tname    string\n\t\tfields  fields\n\t\targs    args\n\t\twant    []map[string]*InstallInfo\n\t\twantErr bool\n\t}{\n\t\t{\n\t\t\tname: \"noDeps\",\n\t\t\tfields: fields{\n\t\t\t\tdbExecutor:  mockDB,\n\t\t\t\taurCache:    mockAUR,\n\t\t\t\tnoDeps:      true,\n\t\t\t\tnoCheckDeps: false,\n\t\t\t},\n\t\t\targs: args{\n\t\t\t\ttargets: []string{\"jellyfin\"},\n\t\t\t},\n\t\t\twant: []map[string]*InstallInfo{\n\t\t\t\t{\n\t\t\t\t\t\"jellyfin\": {\n\t\t\t\t\t\tSource:  AUR,\n\t\t\t\t\t\tReason:  Explicit,\n\t\t\t\t\t\tVersion: \"10.8.8-1\",\n\t\t\t\t\t\tAURBase: ptrString(\"jellyfin\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"dotnet-sdk-6.0\": {\n\t\t\t\t\t\tSource:     Sync,\n\t\t\t\t\t\tReason:     MakeDep,\n\t\t\t\t\t\tVersion:    \"6.0.100-1\",\n\t\t\t\t\t\tSyncDBName: ptrString(\"community\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname: \"deps\",\n\t\t\tfields: fields{\n\t\t\t\tdbExecutor:  mockDB,\n\t\t\t\taurCache:    mockAUR,\n\t\t\t\tnoDeps:      false,\n\t\t\t\tnoCheckDeps: false,\n\t\t\t},\n\t\t\targs: args{\n\t\t\t\ttargets: []string{\"jellyfin\"},\n\t\t\t},\n\t\t\twant: []map[string]*InstallInfo{\n\t\t\t\t{\n\t\t\t\t\t\"jellyfin\": {\n\t\t\t\t\t\tSource:  AUR,\n\t\t\t\t\t\tReason:  Explicit,\n\t\t\t\t\t\tVersion: \"10.8.8-1\",\n\t\t\t\t\t\tAURBase: ptrString(\"jellyfin\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"jellyfin-web\": {\n\t\t\t\t\t\tSource:  AUR,\n\t\t\t\t\t\tReason:  Dep,\n\t\t\t\t\t\tVersion: \"10.8.8-1\",\n\t\t\t\t\t\tAURBase: ptrString(\"jellyfin\"),\n\t\t\t\t\t},\n\t\t\t\t\t\"jellyfin-server\": {\n\t\t\t\t\t\tSource:  AUR,\n\t\t\t\t\t\tReason:  Dep,\n\t\t\t\t\t\tVersion: \"10.8.8-1\",\n\t\t\t\t\t\tAURBase: ptrString(\"jellyfin\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"dotnet-sdk-6.0\": {\n\t\t\t\t\t\tSource:     Sync,\n\t\t\t\t\t\tReason:     MakeDep,\n\t\t\t\t\t\tVersion:    \"6.0.100-1\",\n\t\t\t\t\t\tSyncDBName: ptrString(\"community\"),\n\t\t\t\t\t},\n\t\t\t\t\t\"dotnet-runtime-6.0\": {\n\t\t\t\t\t\tSource:     Sync,\n\t\t\t\t\t\tReason:     Dep,\n\t\t\t\t\t\tVersion:    \"6.0.100-1\",\n\t\t\t\t\t\tSyncDBName: ptrString(\"community\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tg := NewGrapher(tt.fields.dbExecutor,\n\t\t\t\ttt.fields.aurCache, false, true,\n\t\t\t\ttt.fields.noDeps, tt.fields.noCheckDeps, false,\n\t\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\t\t\tgot, err := g.GraphFromTargets(context.Background(), nil, tt.args.targets)\n\t\t\trequire.NoError(t, err)\n\t\t\tlayers := got.TopoSortedLayers(nil)\n\t\t\trequire.EqualValues(t, tt.want, layers, layers)\n\t\t})\n\t}\n}\n\nfunc TestGrapher_GraphProvides_androidsdk(t *testing.T) {\n\tmockDB := &mock.DBExecutor{\n\t\tSyncPackageFn: func(string) mock.IPackage { return nil },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"android-sdk\":\n\t\t\t\treturn nil\n\t\t\tcase \"jdk11-openjdk\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"jdk11-openjdk\",\n\t\t\t\t\tPVersion: \"11.0.12.u7-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"community\"),\n\t\t\t\t\tPProvides: mock.DependList{\n\t\t\t\t\t\tDepends: []alpm.Depend{\n\t\t\t\t\t\t\t{Name: \"java-environment\", Version: \"11\", Mod: alpm.DepModEQ},\n\t\t\t\t\t\t\t{Name: \"java-environment-openjdk\", Version: \"11\", Mod: alpm.DepModEQ},\n\t\t\t\t\t\t\t{Name: \"jdk11-openjdk\", Version: \"11.0.19.u7-1\", Mod: alpm.DepModEQ},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\tcase \"java-environment\":\n\t\t\t\tpanic(\"not supposed to be called\")\n\t\t\t}\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\t\tPackagesFromGroupFn: func(string) []mock.IPackage { return nil },\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"java-environment\":\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tswitch s {\n\t\t\tcase \"libxtst\", \"fontconfig\", \"freetype2\", \"lib32-gcc-libs\", \"lib32-glibc\", \"libx11\", \"libxext\", \"libxrender\", \"zlib\", \"gcc-libs\":\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage { return nil },\n\t}\n\n\tmockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\tif query.Needles[0] == \"android-sdk\" {\n\t\t\tjfinFn := getFromFile(t, \"testdata/android-sdk.json\")\n\t\t\treturn jfinFn(ctx, query)\n\t\t}\n\n\t\tpanic(fmt.Sprintf(\"implement me %v\", query.Needles))\n\t}}\n\n\ttype fields struct {\n\t\tdbExecutor  db.Executor\n\t\taurCache    aurc.QueryClient\n\t\tnoDeps      bool\n\t\tnoCheckDeps bool\n\t}\n\ttype args struct {\n\t\ttargets []string\n\t}\n\ttests := []struct {\n\t\tname    string\n\t\tfields  fields\n\t\targs    args\n\t\twant    []map[string]*InstallInfo\n\t\twantErr bool\n\t}{\n\t\t{\n\t\t\tname: \"explicit dep\",\n\t\t\tfields: fields{\n\t\t\t\tdbExecutor:  mockDB,\n\t\t\t\taurCache:    mockAUR,\n\t\t\t\tnoDeps:      false,\n\t\t\t\tnoCheckDeps: false,\n\t\t\t},\n\t\t\targs: args{\n\t\t\t\ttargets: []string{\"android-sdk\", \"jdk11-openjdk\"},\n\t\t\t},\n\t\t\twant: []map[string]*InstallInfo{\n\t\t\t\t{\n\t\t\t\t\t\"android-sdk\": {\n\t\t\t\t\t\tSource:  AUR,\n\t\t\t\t\t\tReason:  Explicit,\n\t\t\t\t\t\tVersion: \"26.1.1-2\",\n\t\t\t\t\t\tAURBase: ptrString(\"android-sdk\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"jdk11-openjdk\": {\n\t\t\t\t\t\tSource:     Sync,\n\t\t\t\t\t\tReason:     Explicit,\n\t\t\t\t\t\tVersion:    \"11.0.12.u7-1\",\n\t\t\t\t\t\tSyncDBName: ptrString(\"community\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tg := NewGrapher(tt.fields.dbExecutor,\n\t\t\t\ttt.fields.aurCache, false, true,\n\t\t\t\ttt.fields.noDeps, tt.fields.noCheckDeps, false,\n\t\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\t\t\tgot, err := g.GraphFromTargets(context.Background(), nil, tt.args.targets)\n\t\t\trequire.NoError(t, err)\n\t\t\tlayers := got.TopoSortedLayers(nil)\n\t\t\trequire.EqualValues(t, tt.want, layers, layers)\n\t\t})\n\t}\n}\n\nfunc TestGrapher_GraphFromAUR_Deps_ceph_bin(t *testing.T) {\n\tmockDB := &mock.DBExecutor{\n\t\tSyncPackageFn:       func(string) mock.IPackage { return nil },\n\t\tPackagesFromGroupFn: func(string) []mock.IPackage { return []mock.IPackage{} },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"ceph-bin\", \"ceph-libs-bin\":\n\t\t\t\treturn nil\n\t\t\tcase \"ceph\", \"ceph-libs\", \"ceph-libs=17.2.6-2\":\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"ceph-libs\", \"ceph-libs=17.2.6-2\":\n\t\t\t\treturn false\n\t\t\tcase \"dep1\", \"dep2\", \"dep3\", \"makedep1\", \"makedep2\", \"checkdep1\":\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage { return nil },\n\t}\n\n\tmockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\tmockPkgs := map[string]aur.Pkg{\n\t\t\t\"ceph-bin\": {\n\t\t\t\tName:        \"ceph-bin\",\n\t\t\t\tPackageBase: \"ceph-bin\",\n\t\t\t\tVersion:     \"17.2.6-2\",\n\t\t\t\tDepends:     []string{\"ceph-libs=17.2.6-2\", \"dep1\"},\n\t\t\t\tProvides:    []string{\"ceph=17.2.6-2\"},\n\t\t\t},\n\t\t\t\"ceph-libs-bin\": {\n\t\t\t\tName:        \"ceph-libs-bin\",\n\t\t\t\tPackageBase: \"ceph-bin\",\n\t\t\t\tVersion:     \"17.2.6-2\",\n\t\t\t\tDepends:     []string{\"dep1\", \"dep2\"},\n\t\t\t\tProvides:    []string{\"ceph-libs=17.2.6-2\"},\n\t\t\t},\n\t\t\t\"ceph\": {\n\t\t\t\tName:         \"ceph\",\n\t\t\t\tPackageBase:  \"ceph\",\n\t\t\t\tVersion:      \"17.2.6-2\",\n\t\t\t\tDepends:      []string{\"ceph-libs=17.2.6-2\", \"dep1\"},\n\t\t\t\tMakeDepends:  []string{\"makedep1\"},\n\t\t\t\tCheckDepends: []string{\"checkdep1\"},\n\t\t\t\tProvides:     []string{\"ceph=17.2.6-2\"},\n\t\t\t},\n\t\t\t\"ceph-libs\": {\n\t\t\t\tName:         \"ceph-libs\",\n\t\t\t\tPackageBase:  \"ceph\",\n\t\t\t\tVersion:      \"17.2.6-2\",\n\t\t\t\tDepends:      []string{\"dep1\", \"dep2\", \"dep3\"},\n\t\t\t\tMakeDepends:  []string{\"makedep1\", \"makedep2\"},\n\t\t\t\tCheckDepends: []string{\"checkdep1\"},\n\t\t\t\tProvides:     []string{\"ceph-libs=17.2.6-2\"},\n\t\t\t},\n\t\t}\n\n\t\tpkgs := []aur.Pkg{}\n\t\tfor _, needle := range query.Needles {\n\t\t\tif pkg, ok := mockPkgs[needle]; ok {\n\t\t\t\tpkgs = append(pkgs, pkg)\n\t\t\t} else {\n\t\t\t\tpanic(fmt.Sprintf(\"implement me %v\", needle))\n\t\t\t}\n\t\t}\n\n\t\treturn pkgs, nil\n\t}}\n\n\tinstallInfos := map[string]*InstallInfo{\n\t\t\"ceph-bin exp\": {\n\t\t\tSource:  AUR,\n\t\t\tReason:  Explicit,\n\t\t\tVersion: \"17.2.6-2\",\n\t\t\tAURBase: ptrString(\"ceph-bin\"),\n\t\t},\n\t\t\"ceph-libs-bin exp\": {\n\t\t\tSource:  AUR,\n\t\t\tReason:  Explicit,\n\t\t\tVersion: \"17.2.6-2\",\n\t\t\tAURBase: ptrString(\"ceph-bin\"),\n\t\t},\n\t\t\"ceph exp\": {\n\t\t\tSource:  AUR,\n\t\t\tReason:  Explicit,\n\t\t\tVersion: \"17.2.6-2\",\n\t\t\tAURBase: ptrString(\"ceph\"),\n\t\t},\n\t\t\"ceph-libs exp\": {\n\t\t\tSource:  AUR,\n\t\t\tReason:  Explicit,\n\t\t\tVersion: \"17.2.6-2\",\n\t\t\tAURBase: ptrString(\"ceph\"),\n\t\t},\n\t\t\"ceph-libs dep\": {\n\t\t\tSource:  AUR,\n\t\t\tReason:  Dep,\n\t\t\tVersion: \"17.2.6-2\",\n\t\t\tAURBase: ptrString(\"ceph\"),\n\t\t},\n\t}\n\n\ttests := []struct {\n\t\tname       string\n\t\ttargets    []string\n\t\twantLayers []map[string]*InstallInfo\n\t\twantErr    bool\n\t}{\n\t\t{\n\t\t\tname:    \"ceph-bin ceph-libs-bin\",\n\t\t\ttargets: []string{\"ceph-bin\", \"ceph-libs-bin\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"ceph-bin\": installInfos[\"ceph-bin exp\"]},\n\t\t\t\t{\"ceph-libs-bin\": installInfos[\"ceph-libs-bin exp\"]},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:    \"ceph-libs-bin ceph-bin (reversed order)\",\n\t\t\ttargets: []string{\"ceph-libs-bin\", \"ceph-bin\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"ceph-bin\": installInfos[\"ceph-bin exp\"]},\n\t\t\t\t{\"ceph-libs-bin\": installInfos[\"ceph-libs-bin exp\"]},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:    \"ceph\",\n\t\t\ttargets: []string{\"ceph\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"ceph\": installInfos[\"ceph exp\"]},\n\t\t\t\t{\"ceph-libs\": installInfos[\"ceph-libs dep\"]},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:    \"ceph-bin\",\n\t\t\ttargets: []string{\"ceph-bin\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"ceph-bin\": installInfos[\"ceph-bin exp\"]},\n\t\t\t\t{\"ceph-libs\": installInfos[\"ceph-libs dep\"]},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:    \"ceph-bin ceph-libs\",\n\t\t\ttargets: []string{\"ceph-bin\", \"ceph-libs\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"ceph-bin\": installInfos[\"ceph-bin exp\"]},\n\t\t\t\t{\"ceph-libs\": installInfos[\"ceph-libs exp\"]},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:    \"ceph-libs ceph-bin (reversed order)\",\n\t\t\ttargets: []string{\"ceph-libs\", \"ceph-bin\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"ceph-bin\": installInfos[\"ceph-bin exp\"]},\n\t\t\t\t{\"ceph-libs\": installInfos[\"ceph-libs exp\"]},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:    \"ceph ceph-libs-bin\",\n\t\t\ttargets: []string{\"ceph\", \"ceph-libs-bin\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"ceph\": installInfos[\"ceph exp\"]},\n\t\t\t\t{\"ceph-libs-bin\": installInfos[\"ceph-libs-bin exp\"]},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:    \"ceph-libs-bin ceph (reversed order)\",\n\t\t\ttargets: []string{\"ceph-libs-bin\", \"ceph\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"ceph\": installInfos[\"ceph exp\"]},\n\t\t\t\t{\"ceph-libs-bin\": installInfos[\"ceph-libs-bin exp\"]},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tg := NewGrapher(mockDB, mockAUR,\n\t\t\t\tfalse, true, false, false, false,\n\t\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\t\t\tgot, err := g.GraphFromTargets(context.Background(), nil, tt.targets)\n\t\t\trequire.NoError(t, err)\n\t\t\tlayers := got.TopoSortedLayers(nil)\n\t\t\trequire.EqualValues(t, tt.wantLayers, layers, layers)\n\t\t})\n\t}\n}\n\nfunc TestGrapher_GraphFromAUR_Deps_gourou(t *testing.T) {\n\tmockDB := &mock.DBExecutor{\n\t\tSyncPackageFn:       func(string) mock.IPackage { return nil },\n\t\tPackagesFromGroupFn: func(string) []mock.IPackage { return []mock.IPackage{} },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"gourou\", \"libzip-git\":\n\t\t\t\treturn nil\n\t\t\tcase \"libzip\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"libzip\",\n\t\t\t\t\tPVersion: \"1.9.2-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"extra\"),\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"gourou\", \"libzip\", \"libzip-git\":\n\t\t\t\treturn false\n\t\t\tcase \"dep1\", \"dep2\":\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage { return nil },\n\t}\n\n\tmockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\tmockPkgs := map[string]aur.Pkg{\n\t\t\t\"gourou\": {\n\t\t\t\tName:        \"gourou\",\n\t\t\t\tPackageBase: \"gourou\",\n\t\t\t\tVersion:     \"0.8.1\",\n\t\t\t\tDepends:     []string{\"libzip\"},\n\t\t\t},\n\t\t\t\"libzip-git\": {\n\t\t\t\tName:        \"libzip-git\",\n\t\t\t\tPackageBase: \"libzip-git\",\n\t\t\t\tVersion:     \"1.9.2.r159.gb3ac716c-1\",\n\t\t\t\tDepends:     []string{\"dep1\", \"dep2\"},\n\t\t\t\tProvides:    []string{\"libzip=1.9.2.r159.gb3ac716c\"},\n\t\t\t},\n\t\t}\n\n\t\tpkgs := []aur.Pkg{}\n\t\tfor _, needle := range query.Needles {\n\t\t\tif pkg, ok := mockPkgs[needle]; ok {\n\t\t\t\tpkgs = append(pkgs, pkg)\n\t\t\t} else {\n\t\t\t\tpanic(fmt.Sprintf(\"implement me %v\", needle))\n\t\t\t}\n\t\t}\n\n\t\treturn pkgs, nil\n\t}}\n\n\tinstallInfos := map[string]*InstallInfo{\n\t\t\"gourou exp\": {\n\t\t\tSource:  AUR,\n\t\t\tReason:  Explicit,\n\t\t\tVersion: \"0.8.1\",\n\t\t\tAURBase: ptrString(\"gourou\"),\n\t\t},\n\t\t\"libzip dep\": {\n\t\t\tSource:     Sync,\n\t\t\tReason:     Dep,\n\t\t\tVersion:    \"1.9.2-1\",\n\t\t\tSyncDBName: ptrString(\"extra\"),\n\t\t},\n\t\t\"libzip exp\": {\n\t\t\tSource:     Sync,\n\t\t\tReason:     Explicit,\n\t\t\tVersion:    \"1.9.2-1\",\n\t\t\tSyncDBName: ptrString(\"extra\"),\n\t\t},\n\t\t\"libzip-git exp\": {\n\t\t\tSource:  AUR,\n\t\t\tReason:  Explicit,\n\t\t\tVersion: \"1.9.2.r159.gb3ac716c-1\",\n\t\t\tAURBase: ptrString(\"libzip-git\"),\n\t\t},\n\t}\n\n\ttests := []struct {\n\t\tname       string\n\t\ttargets    []string\n\t\twantLayers []map[string]*InstallInfo\n\t\twantErr    bool\n\t}{\n\t\t{\n\t\t\tname:    \"gourou\",\n\t\t\ttargets: []string{\"gourou\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"gourou\": installInfos[\"gourou exp\"]},\n\t\t\t\t{\"libzip\": installInfos[\"libzip dep\"]},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:    \"gourou libzip\",\n\t\t\ttargets: []string{\"gourou\", \"libzip\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"gourou\": installInfos[\"gourou exp\"]},\n\t\t\t\t{\"libzip\": installInfos[\"libzip exp\"]},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:    \"gourou libzip-git\",\n\t\t\ttargets: []string{\"gourou\", \"libzip-git\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"gourou\": installInfos[\"gourou exp\"]},\n\t\t\t\t{\"libzip-git\": installInfos[\"libzip-git exp\"]},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:    \"libzip-git gourou (reversed order)\",\n\t\t\ttargets: []string{\"libzip-git\", \"gourou\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"gourou\": installInfos[\"gourou exp\"]},\n\t\t\t\t{\"libzip-git\": installInfos[\"libzip-git exp\"]},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tg := NewGrapher(mockDB, mockAUR,\n\t\t\t\tfalse, true, false, false, false,\n\t\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\t\t\tgot, err := g.GraphFromTargets(context.Background(), nil, tt.targets)\n\t\t\trequire.NoError(t, err)\n\t\t\tlayers := got.TopoSortedLayers(nil)\n\t\t\trequire.EqualValues(t, tt.wantLayers, layers, layers)\n\t\t})\n\t}\n}\n\nfunc TestGrapher_GraphFromTargets_ReinstalledDeps(t *testing.T) {\n\tmockDB := &mock.DBExecutor{\n\t\tSyncPackageFn:       func(string) mock.IPackage { return nil },\n\t\tPackagesFromGroupFn: func(string) []mock.IPackage { return []mock.IPackage{} },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"gourou\":\n\t\t\t\treturn nil\n\t\t\tcase \"libzip\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"libzip\",\n\t\t\t\t\tPVersion: \"1.9.2-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"extra\"),\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\t\tSatisfierFromDBFn: func(s, s2 string) (mock.IPackage, error) {\n\t\t\tif s2 == \"extra\" {\n\t\t\t\tswitch s {\n\t\t\t\tcase \"libzip\":\n\t\t\t\t\treturn &mock.Package{\n\t\t\t\t\t\tPName:    \"libzip\",\n\t\t\t\t\t\tPVersion: \"1.9.2-1\",\n\t\t\t\t\t\tPDB:      mock.NewDB(\"extra\"),\n\t\t\t\t\t}, nil\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpanic(\"implement me \" + s2 + \"/\" + s)\n\t\t},\n\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"gourou\", \"libzip\":\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\t\tLocalPackageFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"libzip\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"libzip\",\n\t\t\t\t\tPVersion: \"1.9.2-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"extra\"),\n\t\t\t\t\tPReason:  alpm.PkgReasonDepend,\n\t\t\t\t}\n\t\t\tcase \"gourou\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"gourou\",\n\t\t\t\t\tPVersion: \"0.8.1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"aur\"),\n\t\t\t\t\tPReason:  alpm.PkgReasonDepend,\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t}\n\n\tmockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\tmockPkgs := map[string]aur.Pkg{\n\t\t\t\"gourou\": {\n\t\t\t\tName:        \"gourou\",\n\t\t\t\tPackageBase: \"gourou\",\n\t\t\t\tVersion:     \"0.8.1\",\n\t\t\t\tDepends:     []string{\"libzip\"},\n\t\t\t},\n\t\t}\n\n\t\tpkgs := []aur.Pkg{}\n\t\tfor _, needle := range query.Needles {\n\t\t\tif pkg, ok := mockPkgs[needle]; ok {\n\t\t\t\tpkgs = append(pkgs, pkg)\n\t\t\t} else {\n\t\t\t\tpanic(fmt.Sprintf(\"implement me %v\", needle))\n\t\t\t}\n\t\t}\n\n\t\treturn pkgs, nil\n\t}}\n\n\tinstallInfos := map[string]*InstallInfo{\n\t\t\"gourou dep\": {\n\t\t\tSource:  AUR,\n\t\t\tReason:  Dep,\n\t\t\tVersion: \"0.8.1\",\n\t\t\tAURBase: ptrString(\"gourou\"),\n\t\t},\n\t\t\"libzip dep\": {\n\t\t\tSource:     Sync,\n\t\t\tReason:     Dep,\n\t\t\tVersion:    \"1.9.2-1\",\n\t\t\tSyncDBName: ptrString(\"extra\"),\n\t\t},\n\t}\n\n\ttests := []struct {\n\t\tname       string\n\t\ttargets    []string\n\t\twantLayers []map[string]*InstallInfo\n\t\twantErr    bool\n\t}{\n\t\t{\n\t\t\tname:    \"gourou libzip\",\n\t\t\ttargets: []string{\"gourou\", \"libzip\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"gourou\": installInfos[\"gourou dep\"]},\n\t\t\t\t{\"libzip\": installInfos[\"libzip dep\"]},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:    \"aur/gourou extra/libzip\",\n\t\t\ttargets: []string{\"aur/gourou\", \"extra/libzip\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"gourou\": installInfos[\"gourou dep\"]},\n\t\t\t\t{\"libzip\": installInfos[\"libzip dep\"]},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tg := NewGrapher(mockDB, mockAUR,\n\t\t\t\tfalse, true, false, false, false,\n\t\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\t\t\tgot, err := g.GraphFromTargets(context.Background(), nil, tt.targets)\n\t\t\trequire.NoError(t, err)\n\t\t\tlayers := got.TopoSortedLayers(nil)\n\t\t\trequire.EqualValues(t, tt.wantLayers, layers, layers)\n\t\t})\n\t}\n}\n\nfunc TestGrapher_GraphFromTargets_TargetNotFound(t *testing.T) {\n\tmockDB := &mock.DBExecutor{\n\t\tSyncSatisfierFn:        func(string) mock.IPackage { return nil },\n\t\tPackagesFromGroupFn:    func(string) []mock.IPackage { return nil },\n\t\tLocalPackageFn:         func(string) mock.IPackage { return nil },\n\t\tLocalSatisfierExistsFn: func(string) bool { return false },\n\t}\n\n\tmockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\tok := aur.Pkg{\n\t\t\tName:        \"okpkg\",\n\t\t\tPackageBase: \"okpkg\",\n\t\t\tVersion:     \"1.0.0\",\n\t\t}\n\n\t\tswitch query.By {\n\t\tcase aurc.Name:\n\t\t\t// Return only packages that exist.\n\t\t\tpkgs := make([]aur.Pkg, 0, len(query.Needles))\n\t\t\tfor _, needle := range query.Needles {\n\t\t\t\tif needle == ok.Name {\n\t\t\t\t\tpkgs = append(pkgs, ok)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn pkgs, nil\n\t\tcase aurc.Provides:\n\t\t\t// Provider lookup is done per-target.\n\t\t\tif len(query.Needles) > 0 && query.Needles[0] == ok.Name {\n\t\t\t\treturn []aur.Pkg{ok}, nil\n\t\t\t}\n\t\t\treturn []aur.Pkg{}, nil\n\t\tdefault:\n\t\t\treturn []aur.Pkg{}, nil\n\t\t}\n\t}}\n\n\tg := NewGrapher(mockDB, mockAUR,\n\t\tfalse, true, true, true, false,\n\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\n\tt.Run(\"returns error when all targets are missing\", func(t *testing.T) {\n\t\t_, err := g.GraphFromTargets(context.Background(), nil, []string{\"missing1\", \"missing2\"})\n\t\trequire.Error(t, err)\n\n\t\tvar targetNotFound *aur.ErrTargetNotFound\n\t\trequire.ErrorAs(t, err, &targetNotFound)\n\t})\n\n\tt.Run(\"does not error when at least one target is found\", func(t *testing.T) {\n\t\tgot, err := g.GraphFromTargets(context.Background(), nil, []string{\"missing1\", \"okpkg\"})\n\t\trequire.NoError(t, err)\n\n\t\tlayers := got.TopoSortedLayers(nil)\n\t\trequire.EqualValues(t, []map[string]*InstallInfo{\n\t\t\t{\n\t\t\t\t\"okpkg\": {\n\t\t\t\t\tSource:  AUR,\n\t\t\t\t\tReason:  Explicit,\n\t\t\t\t\tVersion: \"1.0.0\",\n\t\t\t\t\tAURBase: ptrString(\"okpkg\"),\n\t\t\t\t},\n\t\t\t},\n\t\t}, layers, layers)\n\t})\n}\n\n// TestGrapher_GraphFromAUR_SplitPkgInternalDeps tests split packages where\n// packages from the same base depend on each other (like gstreamer-git).\nfunc TestGrapher_GraphFromAUR_SplitPkgInternalDeps(t *testing.T) {\n\tmockDB := &mock.DBExecutor{\n\t\tSyncPackageFn:       func(string) mock.IPackage { return nil },\n\t\tPackagesFromGroupFn: func(string) []mock.IPackage { return []mock.IPackage{} },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\t// AUR packages and versioned AUR deps return nil\n\t\t\tcase \"gstreamer-git\", \"gst-plugins-base-libs-git\", \"gst-plugins-good-git\",\n\t\t\t\t\"gstreamer-git=1.24.0.r37-1\", \"gst-plugins-base-libs-git=1.24.0.r37-1\":\n\t\t\t\treturn nil\n\t\t\tcase \"libxml2\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"libxml2\",\n\t\t\t\t\tPVersion: \"2.12.0-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"core\"),\n\t\t\t\t}\n\t\t\tcase \"glib2\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"glib2\",\n\t\t\t\t\tPVersion: \"2.78.0-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"core\"),\n\t\t\t\t}\n\t\t\tcase \"orc\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"orc\",\n\t\t\t\t\tPVersion: \"0.4.34-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"extra\"),\n\t\t\t\t}\n\t\t\tcase \"libxv\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"libxv\",\n\t\t\t\t\tPVersion: \"1.0.12-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"extra\"),\n\t\t\t\t}\n\t\t\tcase \"iso-codes\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"iso-codes\",\n\t\t\t\t\tPVersion: \"4.15.0-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"extra\"),\n\t\t\t\t}\n\t\t\tcase \"libpulse\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"libpulse\",\n\t\t\t\t\tPVersion: \"16.1-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"extra\"),\n\t\t\t\t}\n\t\t\tcase \"wavpack\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"wavpack\",\n\t\t\t\t\tPVersion: \"5.6.0-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"extra\"),\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"gstreamer-git\", \"gstreamer-git=1.24.0.r37-1\",\n\t\t\t\t\"gst-plugins-base-libs-git\", \"gst-plugins-base-libs-git=1.24.0.r37-1\",\n\t\t\t\t\"gst-plugins-good-git\":\n\t\t\t\treturn false\n\t\t\tcase \"libxml2\", \"glib2\", \"orc\", \"libxv\", \"iso-codes\", \"libpulse\", \"wavpack\",\n\t\t\t\t\"git\", \"meson\", \"ninja\": // makedepends\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage { return nil },\n\t}\n\n\tmockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\tif len(query.Needles) > 0 {\n\t\t\tfor _, needle := range query.Needles {\n\t\t\t\tif needle == \"gstreamer-git\" || needle == \"gst-plugins-base-libs-git\" || needle == \"gst-plugins-good-git\" {\n\t\t\t\t\tgstFn := getFromFile(t, \"testdata/gstreamer-git.json\")\n\t\t\t\t\treturn gstFn(ctx, query)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn []aur.Pkg{}, nil // Return empty for unknown packages\n\t}}\n\n\tinstallInfos := map[string]*InstallInfo{\n\t\t\"gstreamer-git exp\": {\n\t\t\tSource:  AUR,\n\t\t\tReason:  Explicit,\n\t\t\tVersion: \"1.24.0.r37-1\",\n\t\t\tAURBase: ptrString(\"gstreamer-git\"),\n\t\t},\n\t\t\"gstreamer-git dep\": {\n\t\t\tSource:  AUR,\n\t\t\tReason:  Dep,\n\t\t\tVersion: \"1.24.0.r37-1\",\n\t\t\tAURBase: ptrString(\"gstreamer-git\"),\n\t\t},\n\t\t\"gst-plugins-base-libs-git exp\": {\n\t\t\tSource:  AUR,\n\t\t\tReason:  Explicit,\n\t\t\tVersion: \"1.24.0.r37-1\",\n\t\t\tAURBase: ptrString(\"gstreamer-git\"),\n\t\t},\n\t\t\"gst-plugins-base-libs-git dep\": {\n\t\t\tSource:  AUR,\n\t\t\tReason:  Dep,\n\t\t\tVersion: \"1.24.0.r37-1\",\n\t\t\tAURBase: ptrString(\"gstreamer-git\"),\n\t\t},\n\t\t\"gst-plugins-good-git exp\": {\n\t\t\tSource:  AUR,\n\t\t\tReason:  Explicit,\n\t\t\tVersion: \"1.24.0.r37-1\",\n\t\t\tAURBase: ptrString(\"gstreamer-git\"),\n\t\t},\n\t}\n\n\ttests := []struct {\n\t\tname       string\n\t\ttargets    []string\n\t\twantLayers []map[string]*InstallInfo\n\t\twantErr    bool\n\t}{\n\t\t{\n\t\t\tname:    \"gst-plugins-good-git pulls in base libs and gstreamer\",\n\t\t\ttargets: []string{\"gst-plugins-good-git\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"gst-plugins-good-git\": installInfos[\"gst-plugins-good-git exp\"]},\n\t\t\t\t{\"gst-plugins-base-libs-git\": installInfos[\"gst-plugins-base-libs-git dep\"]},\n\t\t\t\t{\"gstreamer-git\": installInfos[\"gstreamer-git dep\"]},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:    \"gst-plugins-base-libs-git pulls in gstreamer\",\n\t\t\ttargets: []string{\"gst-plugins-base-libs-git\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"gst-plugins-base-libs-git\": installInfos[\"gst-plugins-base-libs-git exp\"]},\n\t\t\t\t{\"gstreamer-git\": installInfos[\"gstreamer-git dep\"]},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:    \"explicit gstreamer-git with gst-plugins-good-git\",\n\t\t\ttargets: []string{\"gstreamer-git\", \"gst-plugins-good-git\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"gst-plugins-good-git\": installInfos[\"gst-plugins-good-git exp\"]},\n\t\t\t\t{\"gst-plugins-base-libs-git\": installInfos[\"gst-plugins-base-libs-git dep\"]},\n\t\t\t\t{\"gstreamer-git\": installInfos[\"gstreamer-git exp\"]},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:    \"all three packages explicitly\",\n\t\t\ttargets: []string{\"gstreamer-git\", \"gst-plugins-base-libs-git\", \"gst-plugins-good-git\"},\n\t\t\twantLayers: []map[string]*InstallInfo{\n\t\t\t\t{\"gst-plugins-good-git\": installInfos[\"gst-plugins-good-git exp\"]},\n\t\t\t\t{\"gst-plugins-base-libs-git\": installInfos[\"gst-plugins-base-libs-git exp\"]},\n\t\t\t\t{\"gstreamer-git\": installInfos[\"gstreamer-git exp\"]},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tg := NewGrapher(mockDB, mockAUR,\n\t\t\t\tfalse, true, false, false, false,\n\t\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\t\t\tgot, err := g.GraphFromTargets(context.Background(), nil, tt.targets)\n\t\t\trequire.NoError(t, err)\n\t\t\tlayers := got.TopoSortedLayers(nil)\n\t\t\trequire.EqualValues(t, tt.wantLayers, layers, layers)\n\t\t})\n\t}\n}\n\n// TestGrapher_GraphFromAUR_CheckDeps tests packages with CheckDepends.\nfunc TestGrapher_GraphFromAUR_CheckDeps(t *testing.T) {\n\tmockDB := &mock.DBExecutor{\n\t\tSyncPackageFn:       func(string) mock.IPackage { return nil },\n\t\tPackagesFromGroupFn: func(string) []mock.IPackage { return []mock.IPackage{} },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"python-pydantic\":\n\t\t\t\treturn nil\n\t\t\tcase \"python\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"python\",\n\t\t\t\t\tPVersion: \"3.11.0-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"core\"),\n\t\t\t\t}\n\t\t\tcase \"python-typing-extensions\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"python-typing-extensions\",\n\t\t\t\t\tPVersion: \"4.8.0-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"extra\"),\n\t\t\t\t}\n\t\t\tcase \"python-build\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"python-build\",\n\t\t\t\t\tPVersion: \"1.0.0-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"extra\"),\n\t\t\t\t}\n\t\t\tcase \"python-installer\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"python-installer\",\n\t\t\t\t\tPVersion: \"0.7.0-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"extra\"),\n\t\t\t\t}\n\t\t\tcase \"python-pytest\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"python-pytest\",\n\t\t\t\t\tPVersion: \"7.4.0-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"extra\"),\n\t\t\t\t}\n\t\t\tcase \"python-pytest-mock\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"python-pytest-mock\",\n\t\t\t\t\tPVersion: \"3.11.0-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"extra\"),\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"python-pydantic\",\n\t\t\t\t\"python-pytest\", \"python-pytest-mock\": // check deps not installed\n\t\t\t\treturn false\n\t\t\tcase \"python\", \"python-typing-extensions\", \"python-build\", \"python-installer\":\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage { return nil },\n\t}\n\n\tmockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\tif len(query.Needles) > 0 && query.Needles[0] == \"python-pydantic\" {\n\t\t\tpydanticFn := getFromFile(t, \"testdata/python-pydantic.json\")\n\t\t\treturn pydanticFn(ctx, query)\n\t\t}\n\n\t\treturn []aur.Pkg{}, nil // Return empty for unknown packages\n\t}}\n\n\tt.Run(\"with check deps enabled\", func(t *testing.T) {\n\t\tg := NewGrapher(mockDB, mockAUR,\n\t\t\tfalse, true, false, false, false,\n\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\t\tgot, err := g.GraphFromTargets(context.Background(), nil, []string{\"python-pydantic\"})\n\t\trequire.NoError(t, err)\n\t\tlayers := got.TopoSortedLayers(nil)\n\n\t\t// Should have the main package and its check deps\n\t\trequire.Len(t, layers, 2)\n\t\trequire.Contains(t, layers[0], \"python-pydantic\")\n\t\t// Check deps should be in the second layer\n\t\trequire.Contains(t, layers[1], \"python-pytest\")\n\t\trequire.Contains(t, layers[1], \"python-pytest-mock\")\n\t})\n\n\tt.Run(\"with check deps disabled\", func(t *testing.T) {\n\t\tg := NewGrapher(mockDB, mockAUR,\n\t\t\tfalse, true, false, true, false, // noCheckDeps = true\n\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\t\tgot, err := g.GraphFromTargets(context.Background(), nil, []string{\"python-pydantic\"})\n\t\trequire.NoError(t, err)\n\t\tlayers := got.TopoSortedLayers(nil)\n\n\t\t// Should only have the main package (no check deps)\n\t\trequire.Len(t, layers, 1)\n\t\trequire.Contains(t, layers[0], \"python-pydantic\")\n\t})\n}\n\n// TestGrapher_GraphFromAUR_VirtualProvides tests packages that provide virtual packages\n// (like mesa-git providing vulkan-driver, opengl-driver).\nfunc TestGrapher_GraphFromAUR_VirtualProvides(t *testing.T) {\n\tmockDB := &mock.DBExecutor{\n\t\tSyncPackageFn:       func(string) mock.IPackage { return nil },\n\t\tPackagesFromGroupFn: func(string) []mock.IPackage { return []mock.IPackage{} },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tswitch s {\n\t\t\tcase \"mesa-git\":\n\t\t\t\treturn nil\n\t\t\tcase \"libdrm\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"libdrm\",\n\t\t\t\t\tPVersion: \"2.4.117-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"core\"),\n\t\t\t\t}\n\t\t\tcase \"vulkan-icd-loader\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"vulkan-icd-loader\",\n\t\t\t\t\tPVersion: \"1.3.268-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"extra\"),\n\t\t\t\t}\n\t\t\tcase \"vulkan-radeon\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"vulkan-radeon\",\n\t\t\t\t\tPVersion: \"23.3.0-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"extra\"),\n\t\t\t\t\tPProvides: mock.DependList{\n\t\t\t\t\t\tDepends: []alpm.Depend{\n\t\t\t\t\t\t\t{Name: \"vulkan-driver\", Version: \"\", Mod: alpm.DepModAny},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Most mesa deps are already installed\n\t\t\tswitch s {\n\t\t\tcase \"libxxf86vm\", \"libxdamage\", \"libxshmfence\", \"libelf\", \"libunwind\",\n\t\t\t\t\"libglvnd\", \"wayland\", \"lm_sensors\", \"zstd\", \"expat\":\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    s,\n\t\t\t\t\tPVersion: \"1.0.0-1\",\n\t\t\t\t\tPDB:      mock.NewDB(\"extra\"),\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\tswitch s {\n\t\t\tcase \"mesa-git\", \"vulkan-driver\", \"opengl-driver\":\n\t\t\t\treturn false\n\t\t\tcase \"libdrm\", \"libxxf86vm\", \"libxdamage\", \"libxshmfence\", \"libelf\",\n\t\t\t\t\"libunwind\", \"libglvnd\", \"wayland\", \"lm_sensors\", \"vulkan-icd-loader\",\n\t\t\t\t\"zstd\", \"expat\",\n\t\t\t\t\"git\", \"meson\", \"ninja\", \"llvm\", \"clang\": // makedepends\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\tpanic(\"implement me \" + s)\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage { return nil },\n\t}\n\n\tmockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aurc.Query) ([]aur.Pkg, error) {\n\t\tif len(query.Needles) > 0 && query.Needles[0] == \"mesa-git\" {\n\t\t\tmesaFn := getFromFile(t, \"testdata/mesa-git.json\")\n\t\t\treturn mesaFn(ctx, query)\n\t\t}\n\n\t\treturn []aur.Pkg{}, nil // Return empty for unknown packages\n\t}}\n\n\tt.Run(\"mesa-git provides vulkan-driver and opengl-driver\", func(t *testing.T) {\n\t\tg := NewGrapher(mockDB, mockAUR,\n\t\t\tfalse, true, false, false, false,\n\t\t\ttext.NewLogger(io.Discard, io.Discard, &os.File{}, true, \"test\"))\n\t\tgot, err := g.GraphFromTargets(context.Background(), nil, []string{\"mesa-git\"})\n\t\trequire.NoError(t, err)\n\t\tlayers := got.TopoSortedLayers(nil)\n\n\t\trequire.Len(t, layers, 1)\n\t\trequire.Contains(t, layers[0], \"mesa-git\")\n\t\trequire.Equal(t, \"24.0.0.r1234-1\", layers[0][\"mesa-git\"].Version)\n\t\trequire.Equal(t, \"mesa-git\", *layers[0][\"mesa-git\"].AURBase)\n\t})\n}\n"
  },
  {
    "path": "pkg/dep/mock/aur.go",
    "content": "package mock\n\nimport (\n\t\"context\"\n\n\t\"github.com/Jguer/aur\"\n)\n\ntype GetFunc func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error)\n\ntype MockAUR struct {\n\tGetFn GetFunc\n}\n\nfunc (m *MockAUR) Get(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\tif m.GetFn != nil {\n\t\treturn m.GetFn(ctx, query)\n\t}\n\n\tpanic(\"implement me\")\n}\n"
  },
  {
    "path": "pkg/dep/target_handler.go",
    "content": "package dep\n\nimport \"github.com/Jguer/yay/v12/pkg/text\"\n\ntype Target struct {\n\tDB      string\n\tName    string\n\tMod     string\n\tVersion string\n}\n\nfunc ToTarget(pkg string) Target {\n\tdbName, depString := text.SplitDBFromName(pkg)\n\tname, mod, depVersion := splitDep(depString)\n\n\treturn Target{\n\t\tDB:      dbName,\n\t\tName:    name,\n\t\tMod:     mod,\n\t\tVersion: depVersion,\n\t}\n}\n\nfunc (t Target) DepString() string {\n\treturn t.Name + t.Mod + t.Version\n}\n\nfunc (t Target) String() string {\n\tif t.DB != \"\" {\n\t\treturn t.DB + \"/\" + t.DepString()\n\t}\n\n\treturn t.DepString()\n}\n"
  },
  {
    "path": "pkg/dep/testdata/android-sdk.json",
    "content": "[\n{\"ID\":1055234,\"Name\":\"android-sdk\",\"PackageBaseID\":13751,\"PackageBase\":\"android-sdk\",\"Version\":\"26.1.1-2\",\"Description\":\"Google Android SDK\",\"URL\":\"https://developer.android.com/studio/releases/sdk-tools.html\",\"NumVotes\":1487,\"Popularity\":0.802316,\"OutOfDate\":null,\"Maintainer\":\"dreamingincode\",\"Submitter\":null,\"FirstSubmitted\":1194895596,\"LastModified\":1647982720,\"URLPath\":\"/cgit/aur.git/snapshot/android-sdk.tar.gz\",\"Depends\":[\"java-environment\",\"libxtst\",\"fontconfig\",\"freetype2\",\"lib32-gcc-libs\",\"lib32-glibc\",\"libx11\",\"libxext\",\"libxrender\",\"zlib\",\"gcc-libs\"],\"OptDepends\":[\"android-emulator\",\"android-sdk-platform-tools\",\"android-udev\"],\"License\":[\"custom\"],\"Keywords\":[\"android\",\"development\"]}\n]"
  },
  {
    "path": "pkg/dep/testdata/aws-cli-git.json",
    "content": "[\n    {\"ID\":1266542,\"Name\":\"aws-cli-git\",\"PackageBaseID\":75029,\"PackageBase\":\"aws-cli-git\",\"Version\":\"1.27.145.r11217.g5885ee4dc-1\",\"Description\":\"Universal Command Line Interface for Amazon Web Services awscli\",\"URL\":\"https://github.com/aws/aws-cli\",\"NumVotes\":8,\"Popularity\":0.0,\"OutOfDate\":1710077383,\"Maintainer\":null,\"Submitter\":\"flaccid\",\"FirstSubmitted\":1383449501,\"LastModified\":1685666227,\"URLPath\":\"/cgit/aur.git/snapshot/aws-cli-git.tar.gz\",\"Depends\":[\"python\",\"python-botocore>=1.19.35\",\"python-docutils>=0.10\",\"python-rsa>=3.1.2\",\"python-s3transfer>=0.3.0\",\"python-yaml>=3.10\",\"python-colorama>=0.2.5\",\"python-tox>=2.3.1\",\"python-nose>=1.3.7\",\"python-mock>=1.3.0\",\"python-wheel>=0.24.0\",\"python-dateutil>=2.1\",\"python-sphinx>=1.1.3\"],\"MakeDepends\":[\"python\",\"python-distribute\",\"git\"],\"Conflicts\":[\"python2-aws-cli\",\"python-aws-cli\",\"aws-cli\"],\"Provides\":[\"aws-cli=1.27.145\"],\"License\":[\"Apache\"]}\n]\n"
  },
  {
    "path": "pkg/dep/testdata/clion.json",
    "content": "[\n    {\"ID\":1937213,\"Name\":\"clion\",\"PackageBaseID\":92202,\"PackageBase\":\"clion\",\"Version\":\"2025.3.1.1-1\",\"Description\":\"Cross-platform IDE for C and C++ from JetBrains.\",\"URL\":\"http://www.jetbrains.com/clion\",\"NumVotes\":239,\"Popularity\":1.760009,\"OutOfDate\":null,\"Maintainer\":\"Zrax\",\"Submitter\":\"rdoursenaud\",\"FirstSubmitted\":1429046635,\"LastModified\":1768325120,\"URLPath\":\"/cgit/aur.git/snapshot/clion.tar.gz\",\"Depends\":[\"libdbusmenu-glib\"],\"MakeDepends\":[\"rsync\"],\"OptDepends\":[\"clion-jre\",\"clion-cmake\",\"clion-gdb\",\"clion-lldb\",\"java-runtime\",\"cmake\",\"gdb\",\"lldb\",\"gcc\",\"clang\",\"gtest\",\"python\",\"doxygen\"],\"License\":[\"custom\"]},\n    {\"ID\":1937214,\"Name\":\"clion-jre\",\"PackageBaseID\":92202,\"PackageBase\":\"clion\",\"Version\":\"2025.3.1.1-1\",\"Description\":\"JBR (JetBrains Runtime) for CLion - aass/JVM bundle based on OpenJDK\",\"URL\":\"http://www.jetbrains.com/clion\",\"NumVotes\":50,\"Popularity\":0.5,\"OutOfDate\":null,\"Maintainer\":\"Zrax\",\"Submitter\":\"rdoursenaud\",\"FirstSubmitted\":1429046635,\"LastModified\":1768325120,\"URLPath\":\"/cgit/aur.git/snapshot/clion.tar.gz\",\"Depends\":[\"glibc\",\"gcc-libs\"],\"MakeDepends\":[\"rsync\"],\"Provides\":[\"java-runtime\"],\"License\":[\"custom\"]},\n    {\"ID\":1937215,\"Name\":\"clion-cmake\",\"PackageBaseID\":92202,\"PackageBase\":\"clion\",\"Version\":\"2025.3.1.1-1\",\"Description\":\"CMake for CLion IDE\",\"URL\":\"http://www.jetbrains.com/clion\",\"NumVotes\":30,\"Popularity\":0.3,\"OutOfDate\":null,\"Maintainer\":\"Zrax\",\"Submitter\":\"rdoursenaud\",\"FirstSubmitted\":1429046635,\"LastModified\":1768325120,\"URLPath\":\"/cgit/aur.git/snapshot/clion.tar.gz\",\"Depends\":[\"glibc\"],\"MakeDepends\":[\"rsync\"],\"Provides\":[\"cmake\"],\"Conflicts\":[\"cmake\"],\"License\":[\"custom\"]},\n    {\"ID\":1937216,\"Name\":\"clion-gdb\",\"PackageBaseID\":92202,\"PackageBase\":\"clion\",\"Version\":\"2025.3.1.1-1\",\"Description\":\"GDB for CLion IDE\",\"URL\":\"http://www.jetbrains.com/clion\",\"NumVotes\":25,\"Popularity\":0.25,\"OutOfDate\":null,\"Maintainer\":\"Zrax\",\"Submitter\":\"rdoursenaud\",\"FirstSubmitted\":1429046635,\"LastModified\":1768325120,\"URLPath\":\"/cgit/aur.git/snapshot/clion.tar.gz\",\"Depends\":[\"glibc\",\"python\"],\"MakeDepends\":[\"rsync\"],\"Provides\":[\"gdb\"],\"Conflicts\":[\"gdb\"],\"License\":[\"custom\"]},\n    {\"ID\":1937217,\"Name\":\"clion-lldb\",\"PackageBaseID\":92202,\"PackageBase\":\"clion\",\"Version\":\"2025.3.1.1-1\",\"Description\":\"LLDB for CLion IDE\",\"URL\":\"http://www.jetbrains.com/clion\",\"NumVotes\":20,\"Popularity\":0.2,\"OutOfDate\":null,\"Maintainer\":\"Zrax\",\"Submitter\":\"rdoursenaud\",\"FirstSubmitted\":1429046635,\"LastModified\":1768325120,\"URLPath\":\"/cgit/aur.git/snapshot/clion.tar.gz\",\"Depends\":[\"glibc\",\"python\"],\"MakeDepends\":[\"rsync\"],\"Provides\":[\"lldb\"],\"Conflicts\":[\"lldb\"],\"License\":[\"custom\"]}\n]\n"
  },
  {
    "path": "pkg/dep/testdata/gstreamer-git.json",
    "content": "[\n    {\"ID\":1000001,\"Name\":\"gstreamer-git\",\"PackageBaseID\":100001,\"PackageBase\":\"gstreamer-git\",\"Version\":\"1.24.0.r37-1\",\"Description\":\"GStreamer open-source multimedia framework core library (git version)\",\"URL\":\"https://gstreamer.freedesktop.org/\",\"NumVotes\":10,\"Popularity\":0.5,\"OutOfDate\":null,\"Maintainer\":\"testmaint\",\"Submitter\":\"testmaint\",\"FirstSubmitted\":1600000000,\"LastModified\":1700000000,\"URLPath\":\"/cgit/aur.git/snapshot/gstreamer-git.tar.gz\",\"Depends\":[\"libxml2\",\"glib2\"],\"MakeDepends\":[\"git\",\"meson\",\"ninja\"],\"Provides\":[\"gstreamer=1.24.0\"],\"Conflicts\":[\"gstreamer\"],\"License\":[\"LGPL\"]},\n    {\"ID\":1000002,\"Name\":\"gst-plugins-base-libs-git\",\"PackageBaseID\":100001,\"PackageBase\":\"gstreamer-git\",\"Version\":\"1.24.0.r37-1\",\"Description\":\"GStreamer base plugins libraries (git version)\",\"URL\":\"https://gstreamer.freedesktop.org/\",\"NumVotes\":10,\"Popularity\":0.5,\"OutOfDate\":null,\"Maintainer\":\"testmaint\",\"Submitter\":\"testmaint\",\"FirstSubmitted\":1600000000,\"LastModified\":1700000000,\"URLPath\":\"/cgit/aur.git/snapshot/gstreamer-git.tar.gz\",\"Depends\":[\"gstreamer-git=1.24.0.r37-1\",\"orc\",\"libxv\",\"iso-codes\"],\"MakeDepends\":[\"git\",\"meson\",\"ninja\"],\"Provides\":[\"gst-plugins-base-libs=1.24.0\"],\"Conflicts\":[\"gst-plugins-base-libs\"],\"License\":[\"LGPL\"]},\n    {\"ID\":1000003,\"Name\":\"gst-plugins-good-git\",\"PackageBaseID\":100001,\"PackageBase\":\"gstreamer-git\",\"Version\":\"1.24.0.r37-1\",\"Description\":\"GStreamer good plugins (git version)\",\"URL\":\"https://gstreamer.freedesktop.org/\",\"NumVotes\":10,\"Popularity\":0.5,\"OutOfDate\":null,\"Maintainer\":\"testmaint\",\"Submitter\":\"testmaint\",\"FirstSubmitted\":1600000000,\"LastModified\":1700000000,\"URLPath\":\"/cgit/aur.git/snapshot/gstreamer-git.tar.gz\",\"Depends\":[\"gst-plugins-base-libs-git=1.24.0.r37-1\",\"libpulse\",\"wavpack\"],\"MakeDepends\":[\"git\",\"meson\",\"ninja\"],\"Provides\":[\"gst-plugins-good=1.24.0\"],\"Conflicts\":[\"gst-plugins-good\"],\"License\":[\"LGPL\"]}\n]\n"
  },
  {
    "path": "pkg/dep/testdata/jellyfin-server.json",
    "content": "[\n    {\"ID\":1176791,\"Name\":\"jellyfin-server\",\"PackageBaseID\":138631,\"PackageBase\":\"jellyfin\",\"Version\":\"10.8.8-1\",\"Description\":\"Jellyfin server component\",\"URL\":\"https://github.com/jellyfin/jellyfin\",\"NumVotes\":84,\"Popularity\":1.272964,\"OutOfDate\":null,\"Maintainer\":\"z3ntu\",\"Submitter\":\"z3ntu\",\"FirstSubmitted\":1547053171,\"LastModified\":1669830147,\"URLPath\":\"/cgit/aur.git/snapshot/jellyfin-server.tar.gz\",\"Depends\":[\"dotnet-runtime-6.0\",\"aspnet-runtime-6.0\",\"ffmpeg\",\"sqlite\"],\"MakeDepends\":[\"dotnet-sdk-6.0\",\"nodejs\",\"npm\",\"git\"],\"License\":[\"GPL2\"]}\n]"
  },
  {
    "path": "pkg/dep/testdata/jellyfin-web.json",
    "content": "[\n{\"ID\":1176790,\"Name\":\"jellyfin-web\",\"PackageBaseID\":138631,\"PackageBase\":\"jellyfin\",\"Version\":\"10.8.8-1\",\"Description\":\"Jellyfin web client\",\"URL\":\"https://github.com/jellyfin/jellyfin\",\"NumVotes\":84,\"Popularity\":1.272964,\"OutOfDate\":null,\"Maintainer\":\"z3ntu\",\"Submitter\":\"z3ntu\",\"FirstSubmitted\":1547053171,\"LastModified\":1669830147,\"URLPath\":\"/cgit/aur.git/snapshot/jellyfin-web.tar.gz\",\"MakeDepends\":[\"dotnet-sdk-6.0\",\"nodejs\",\"npm\",\"git\"],\"License\":[\"GPL2\"]}\n]"
  },
  {
    "path": "pkg/dep/testdata/jellyfin.json",
    "content": "[\n    {\"ID\":1176789,\"Name\":\"jellyfin\",\"PackageBaseID\":138631,\"PackageBase\":\"jellyfin\",\"Version\":\"10.8.8-1\",\"Description\":\"The Free Software Media System\",\"URL\":\"https://github.com/jellyfin/jellyfin\",\"NumVotes\":84,\"Popularity\":1.272964,\"OutOfDate\":null,\"Maintainer\":\"z3ntu\",\"Submitter\":\"z3ntu\",\"FirstSubmitted\":1547053171,\"LastModified\":1669830147,\"URLPath\":\"/cgit/aur.git/snapshot/jellyfin.tar.gz\",\"Depends\":[\"jellyfin-web=10.8.8\",\"jellyfin-server=10.8.8\"],\"MakeDepends\":[\"dotnet-sdk-6.0\",\"nodejs\",\"npm\",\"git\"],\"License\":[\"GPL2\"]}\n]"
  },
  {
    "path": "pkg/dep/testdata/liri-desktop-git.json",
    "content": "[\n    {\"ID\":2000001,\"Name\":\"liri-desktop-git\",\"PackageBaseID\":200001,\"PackageBase\":\"liri-desktop-git\",\"Version\":\"0.1.0.r50-1\",\"Description\":\"Liri Desktop metapackage\",\"URL\":\"https://liri.io\",\"NumVotes\":10,\"Popularity\":0.1,\"OutOfDate\":null,\"Maintainer\":\"plfiorini\",\"Submitter\":\"plfiorini\",\"FirstSubmitted\":1494775706,\"LastModified\":1672746933,\"URLPath\":\"/cgit/aur.git/snapshot/liri-desktop-git.tar.gz\",\"Depends\":[\"liri-shell-git\",\"liri-settings-git\",\"fluid-git\",\"libliri-git\"],\"MakeDepends\":[\"git\"],\"License\":[\"GPL3\"]},\n    {\"ID\":2000002,\"Name\":\"liri-shell-git\",\"PackageBaseID\":200002,\"PackageBase\":\"liri-shell-git\",\"Version\":\"0.9.0.r100-1\",\"Description\":\"Liri Shell - Wayland compositor\",\"URL\":\"https://liri.io\",\"NumVotes\":8,\"Popularity\":0.08,\"OutOfDate\":null,\"Maintainer\":\"plfiorini\",\"Submitter\":\"plfiorini\",\"FirstSubmitted\":1494775706,\"LastModified\":1672746933,\"URLPath\":\"/cgit/aur.git/snapshot/liri-shell-git.tar.gz\",\"Depends\":[\"fluid-git\",\"libliri-git\",\"qt5-wayland\",\"wayland\"],\"MakeDepends\":[\"git\",\"liri-cmake-shared-git\",\"qt5-tools\"],\"License\":[\"GPL3\"]},\n    {\"ID\":2000003,\"Name\":\"liri-settings-git\",\"PackageBaseID\":200003,\"PackageBase\":\"liri-settings-git\",\"Version\":\"0.9.0.r50-1\",\"Description\":\"Liri Settings\",\"URL\":\"https://liri.io\",\"NumVotes\":6,\"Popularity\":0.06,\"OutOfDate\":null,\"Maintainer\":\"plfiorini\",\"Submitter\":\"plfiorini\",\"FirstSubmitted\":1494775706,\"LastModified\":1672746933,\"URLPath\":\"/cgit/aur.git/snapshot/liri-settings-git.tar.gz\",\"Depends\":[\"fluid-git\",\"libliri-git\",\"qt5-declarative\"],\"MakeDepends\":[\"git\",\"liri-cmake-shared-git\",\"qt5-tools\"],\"License\":[\"GPL3\"]},\n    {\"ID\":1191231,\"Name\":\"libliri-git\",\"PackageBaseID\":122343,\"PackageBase\":\"libliri-git\",\"Version\":\"r183.5ebe982-1\",\"Description\":\"Utilities for Liri Quick applications\",\"URL\":\"https://liri.io\",\"NumVotes\":3,\"Popularity\":0.0,\"OutOfDate\":1751932023,\"Maintainer\":\"plfiorini\",\"Submitter\":\"plfiorini\",\"FirstSubmitted\":1494775706,\"LastModified\":1672746933,\"URLPath\":\"/cgit/aur.git/snapshot/libliri-git.tar.gz\",\"Depends\":[\"qt5-declarative\"],\"MakeDepends\":[\"git\",\"liri-cmake-shared-git\"],\"Conflicts\":[\"libliri\"],\"Provides\":[\"libliri\"],\"Replaces\":[\"libliri\"],\"License\":[\"LGPL3\"]},\n    {\"ID\":2000004,\"Name\":\"fluid-git\",\"PackageBaseID\":200004,\"PackageBase\":\"fluid-git\",\"Version\":\"1.3.0.r50-1\",\"Description\":\"Fluid - Material Design for Qt Quick\",\"URL\":\"https://liri.io\",\"NumVotes\":15,\"Popularity\":0.15,\"OutOfDate\":null,\"Maintainer\":\"plfiorini\",\"Submitter\":\"plfiorini\",\"FirstSubmitted\":1494775706,\"LastModified\":1672746933,\"URLPath\":\"/cgit/aur.git/snapshot/fluid-git.tar.gz\",\"Depends\":[\"qt5-declarative\",\"qt5-quickcontrols2\",\"qt5-svg\",\"qt5-graphicaleffects\"],\"MakeDepends\":[\"git\",\"liri-cmake-shared-git\",\"qt5-tools\"],\"Conflicts\":[\"fluid\"],\"Provides\":[\"fluid\"],\"License\":[\"MPL2\"]},\n    {\"ID\":2000005,\"Name\":\"liri-cmake-shared-git\",\"PackageBaseID\":200005,\"PackageBase\":\"liri-cmake-shared-git\",\"Version\":\"1.0.0.r20-1\",\"Description\":\"Shared CMake functions and macros for Liri\",\"URL\":\"https://liri.io\",\"NumVotes\":5,\"Popularity\":0.05,\"OutOfDate\":null,\"Maintainer\":\"plfiorini\",\"Submitter\":\"plfiorini\",\"FirstSubmitted\":1494775706,\"LastModified\":1672746933,\"URLPath\":\"/cgit/aur.git/snapshot/liri-cmake-shared-git.tar.gz\",\"Depends\":[\"cmake\"],\"MakeDepends\":[\"git\"],\"Conflicts\":[\"liri-cmake-shared\"],\"Provides\":[\"liri-cmake-shared\"],\"License\":[\"BSD\"]}\n]\n"
  },
  {
    "path": "pkg/dep/testdata/mesa-git.json",
    "content": "[\n    {\"ID\":3000001,\"Name\":\"mesa-git\",\"PackageBaseID\":300001,\"PackageBase\":\"mesa-git\",\"Version\":\"24.0.0.r1234-1\",\"Description\":\"Open-source implementation of the OpenGL specification (git version)\",\"URL\":\"https://www.mesa3d.org/\",\"NumVotes\":100,\"Popularity\":3.0,\"OutOfDate\":null,\"Maintainer\":\"testmaint\",\"Submitter\":\"testmaint\",\"FirstSubmitted\":1600000000,\"LastModified\":1700000000,\"URLPath\":\"/cgit/aur.git/snapshot/mesa-git.tar.gz\",\"Depends\":[\"libdrm\",\"libxxf86vm\",\"libxdamage\",\"libxshmfence\",\"libelf\",\"libunwind\",\"libglvnd\",\"wayland\",\"lm_sensors\",\"vulkan-icd-loader\",\"zstd\",\"expat\"],\"MakeDepends\":[\"git\",\"meson\",\"ninja\",\"llvm\",\"clang\"],\"Provides\":[\"mesa=24.0.0\",\"vulkan-intel=24.0.0\",\"vulkan-radeon=24.0.0\",\"vulkan-driver\",\"opengl-driver\",\"mesa-libgl\"],\"Conflicts\":[\"mesa\",\"vulkan-intel\",\"vulkan-radeon\",\"mesa-libgl\"],\"License\":[\"MIT\"]}\n]\n"
  },
  {
    "path": "pkg/dep/testdata/nx.json",
    "content": "[\n    {\"ID\":1313798,\"Name\":\"libxcomp\",\"PackageBaseID\":177611,\"PackageBase\":\"nx\",\"Version\":\"3.5.99.27-3\",\"Description\":\"NX X compression library\",\"URL\":\"https://arctica-project.org\",\"NumVotes\":4,\"Popularity\":1e-6,\"OutOfDate\":null,\"Maintainer\":\"harrietobrien\",\"Submitter\":\"arojas\",\"FirstSubmitted\":1648839853,\"LastModified\":1693834449,\"URLPath\":\"/cgit/aur.git/snapshot/nx.tar.gz\",\"Depends\":[\"libjpeg-turbo\",\"libpng\",\"gcc-libs\"],\"MakeDepends\":[\"libjpeg-turbo\",\"libpng\",\"gcc-libs\",\"libxml2\",\"xkeyboard-config\",\"xorg-xkbcomp\",\"libxfont2\",\"libxinerama\",\"xorg-font-util\",\"pixman\",\"libxrandr\",\"libxtst\",\"libxcomposite\",\"libxpm\",\"libxdamage\",\"xorgproto\",\"imake\"],\"License\":[\"GPL\"]},\n    {\"ID\":1313799,\"Name\":\"nxproxy\",\"PackageBaseID\":177611,\"PackageBase\":\"nx\",\"Version\":\"3.5.99.27-3\",\"Description\":\"NX proxy\",\"URL\":\"https://arctica-project.org\",\"NumVotes\":4,\"Popularity\":1e-6,\"OutOfDate\":null,\"Maintainer\":\"harrietobrien\",\"Submitter\":\"arojas\",\"FirstSubmitted\":1648839853,\"LastModified\":1693834449,\"URLPath\":\"/cgit/aur.git/snapshot/nx.tar.gz\",\"Depends\":[\"libxcomp\"],\"MakeDepends\":[\"libjpeg-turbo\",\"libpng\",\"gcc-libs\",\"libxml2\",\"xkeyboard-config\",\"xorg-xkbcomp\",\"libxfont2\",\"libxinerama\",\"xorg-font-util\",\"pixman\",\"libxrandr\",\"libxtst\",\"libxcomposite\",\"libxpm\",\"libxdamage\",\"xorgproto\",\"imake\"],\"License\":[\"GPL\"]},\n    {\"ID\":1313800,\"Name\":\"nx-x11\",\"PackageBaseID\":177611,\"PackageBase\":\"nx\",\"Version\":\"3.5.99.27-3\",\"Description\":\"NX-X11 lib for the NX framework\",\"URL\":\"https://arctica-project.org\",\"NumVotes\":4,\"Popularity\":1e-6,\"OutOfDate\":null,\"Maintainer\":\"harrietobrien\",\"Submitter\":\"arojas\",\"FirstSubmitted\":1648839853,\"LastModified\":1693834449,\"URLPath\":\"/cgit/aur.git/snapshot/nx.tar.gz\",\"Depends\":[\"libxcomp\"],\"MakeDepends\":[\"libjpeg-turbo\",\"libpng\",\"gcc-libs\",\"libxml2\",\"xkeyboard-config\",\"xorg-xkbcomp\",\"libxfont2\",\"libxinerama\",\"xorg-font-util\",\"pixman\",\"libxrandr\",\"libxtst\",\"libxcomposite\",\"libxpm\",\"libxdamage\",\"xorgproto\",\"imake\"],\"License\":[\"GPL\"]},\n    {\"ID\":1313801,\"Name\":\"nxagent\",\"PackageBaseID\":177611,\"PackageBase\":\"nx\",\"Version\":\"3.5.99.27-3\",\"Description\":\"NX X server based on Xnest\",\"URL\":\"https://arctica-project.org\",\"NumVotes\":4,\"Popularity\":1e-6,\"OutOfDate\":null,\"Maintainer\":\"harrietobrien\",\"Submitter\":\"arojas\",\"FirstSubmitted\":1648839853,\"LastModified\":1693834449,\"URLPath\":\"/cgit/aur.git/snapshot/nx.tar.gz\",\"Depends\":[\"nx-x11\",\"libxcomp\",\"libxml2\",\"xkeyboard-config\",\"xorg-xkbcomp\",\"libxfont2\",\"libxinerama\",\"xorg-font-util\",\"pixman\",\"libxrandr\",\"libxtst\",\"libxcomposite\",\"libxpm\",\"libxdamage\",\"libtirpc\"],\"MakeDepends\":[\"libjpeg-turbo\",\"libpng\",\"gcc-libs\",\"libxml2\",\"xkeyboard-config\",\"xorg-xkbcomp\",\"libxfont2\",\"libxinerama\",\"xorg-font-util\",\"pixman\",\"libxrandr\",\"libxtst\",\"libxcomposite\",\"libxpm\",\"libxdamage\",\"xorgproto\",\"imake\"],\"Conflicts\":[\"nx-xcompext\"],\"License\":[\"GPL\"]}\n]\n"
  },
  {
    "path": "pkg/dep/testdata/python-pydantic.json",
    "content": "[\n    {\"ID\":2000001,\"Name\":\"python-pydantic\",\"PackageBaseID\":200001,\"PackageBase\":\"python-pydantic\",\"Version\":\"2.5.0-1\",\"Description\":\"Data validation using Python type hints\",\"URL\":\"https://github.com/pydantic/pydantic\",\"NumVotes\":50,\"Popularity\":2.0,\"OutOfDate\":null,\"Maintainer\":\"testmaint\",\"Submitter\":\"testmaint\",\"FirstSubmitted\":1600000000,\"LastModified\":1700000000,\"URLPath\":\"/cgit/aur.git/snapshot/python-pydantic.tar.gz\",\"Depends\":[\"python\",\"python-typing-extensions\"],\"MakeDepends\":[\"python-build\",\"python-installer\"],\"CheckDepends\":[\"python-pytest\",\"python-pytest-mock\"],\"License\":[\"MIT\"]}\n]\n"
  },
  {
    "path": "pkg/dep/testdata/samsung-unified-driver.json",
    "content": "[\n    {\"ID\":1734381,\"Name\":\"samsung-unified-driver\",\"PackageBaseID\":44188,\"PackageBase\":\"samsung-unified-driver\",\"Version\":\"1.00.39-11\",\"Description\":\"Samsung Unified Linux Driver for printers and scanners.\",\"URL\":\"http://www.samsung.com\",\"NumVotes\":227,\"Popularity\":0.119974,\"OutOfDate\":null,\"Maintainer\":\"christoph.gysin\",\"Submitter\":\"ptb\",\"FirstSubmitted\":1291593695,\"LastModified\":1747833725,\"URLPath\":\"/cgit/aur.git/snapshot/samsung-unified-driver.tar.gz\",\"Depends\":[\"samsung-unified-driver-printer\",\"samsung-unified-driver-scanner\"],\"License\":[\"custom:samsung\"]},\n    {\"ID\":1734378,\"Name\":\"samsung-unified-driver-common\",\"PackageBaseID\":44188,\"PackageBase\":\"samsung-unified-driver\",\"Version\":\"1.00.39-11\",\"Description\":\"Samsung Unified Linux Driver (common files)\",\"URL\":\"http://www.samsung.com\",\"NumVotes\":227,\"Popularity\":0.119974,\"OutOfDate\":null,\"Maintainer\":\"christoph.gysin\",\"Submitter\":\"ptb\",\"FirstSubmitted\":1291593695,\"LastModified\":1747833725,\"URLPath\":\"/cgit/aur.git/snapshot/samsung-unified-driver-common.tar.gz\",\"License\":[\"custom:samsung\"]},\n    {\"ID\":1734379,\"Name\":\"samsung-unified-driver-printer\",\"PackageBaseID\":44188,\"PackageBase\":\"samsung-unified-driver\",\"Version\":\"1.00.39-11\",\"Description\":\"Samsung Unified Linux Driver for printers.\",\"URL\":\"http://www.samsung.com\",\"NumVotes\":227,\"Popularity\":0.119974,\"OutOfDate\":null,\"Maintainer\":\"christoph.gysin\",\"Submitter\":\"ptb\",\"FirstSubmitted\":1291593695,\"LastModified\":1747833725,\"URLPath\":\"/cgit/aur.git/snapshot/samsung-unified-driver-printer.tar.gz\",\"Depends\":[\"samsung-unified-driver-common\",\"cups\",\"ghostscript\"],\"License\":[\"custom:samsung\"]},\n    {\"ID\":1734380,\"Name\":\"samsung-unified-driver-scanner\",\"PackageBaseID\":44188,\"PackageBase\":\"samsung-unified-driver\",\"Version\":\"1.00.39-11\",\"Description\":\"Samsung Unified Linux Driver for scanners.\",\"URL\":\"http://www.samsung.com\",\"NumVotes\":227,\"Popularity\":0.119974,\"OutOfDate\":null,\"Maintainer\":\"christoph.gysin\",\"Submitter\":\"ptb\",\"FirstSubmitted\":1291593695,\"LastModified\":1747833725,\"URLPath\":\"/cgit/aur.git/snapshot/samsung-unified-driver-scanner.tar.gz\",\"Depends\":[\"samsung-unified-driver-common\",\"libxml2-legacy\",\"libusb-compat\",\"sane\"],\"License\":[\"custom:samsung\"]}\n]\n"
  },
  {
    "path": "pkg/dep/topo/dep.go",
    "content": "package topo\n\nimport (\n\t\"fmt\"\n\t\"maps\"\n\t\"strings\"\n\n\talpm \"github.com/Jguer/dyalpm\"\n)\n\ntype (\n\t// NodeSet is a set of nodes represented as a map for O(1) membership checks.\n\t// The boolean value is not meaningful; presence of the key indicates membership.\n\tNodeSet[T comparable] map[T]bool\n\n\t// ProvidesMap maps a \"provides\" key (an alias/satisfier name) to information about the\n\t// node that provides it.\n\tProvidesMap[T comparable] map[T]*DependencyInfo[T]\n\n\t// DepMap maps a node to a set of nodes. In Graph this is used for adjacency:\n\t// - dependencies: node -> its direct dependencies\n\t// - dependents:   node -> its direct dependents\n\tDepMap[T comparable] map[T]NodeSet[T]\n)\n\n// Slice returns the set contents as a slice in unspecified order.\nfunc (n NodeSet[T]) Slice() []T {\n\tvar slice []T\n\n\tfor node := range n {\n\t\tslice = append(slice, node)\n\t}\n\n\treturn slice\n}\n\n// NodeInfo carries optional rendering metadata (Color/Background) plus the node's value.\ntype NodeInfo[V any] struct {\n\tColor      string\n\tBackground string\n\tValue      V\n}\n\n// DependencyInfo describes which node provides a given dependency/satisfier, along with the\n// original dependency metadata (alpm.Depend).\ntype DependencyInfo[T comparable] struct {\n\tProvider T\n\talpm.Depend\n}\n\n// CheckFn is a callback used by traversal helpers. It receives the node id plus the node's value.\ntype CheckFn[T comparable, V any] func(T, V) error\n\n// Graph is a directed dependency graph.\n//\n// Edge direction:\n// - An edge is added with DependOn(child, parent), meaning \"child depends on parent\".\n// - Internally, dependencies maps child -> parents (direct dependencies).\n// - Internally, dependents maps parent -> children (direct dependents).\ntype Graph[T comparable, V any] struct {\n\tnodes NodeSet[T]\n\n\t// node info map\n\tnodeInfo map[T]*NodeInfo[V]\n\n\t// `provides` tracks provides -> node.\n\tprovides ProvidesMap[T]\n\n\t// `dependencies` tracks child -> parents.\n\tdependencies DepMap[T]\n\t// `dependents` tracks parent -> children.\n\tdependents DepMap[T]\n}\n\n// New returns an empty Graph.\nfunc New[T comparable, V any]() *Graph[T, V] {\n\treturn &Graph[T, V]{\n\t\tnodes:        make(NodeSet[T]),\n\t\tdependencies: make(DepMap[T]),\n\t\tdependents:   make(DepMap[T]),\n\t\tnodeInfo:     make(map[T]*NodeInfo[V]),\n\t\tprovides:     make(ProvidesMap[T]),\n\t}\n}\n\n// Len returns the number of nodes currently present in the graph.\nfunc (g *Graph[T, V]) Len() int {\n\treturn len(g.nodes)\n}\n\n// Exists reports whether node exists in the graph's node set.\nfunc (g *Graph[T, V]) Exists(node T) bool {\n\t_, ok := g.nodes[node]\n\n\treturn ok\n}\n\n// AddNode adds node to the graph. It is safe to call multiple times.\nfunc (g *Graph[T, V]) AddNode(node T) {\n\tg.nodes[node] = true\n}\n\n// HasProvides reports whether the given provides key is registered.\nfunc (g *Graph[T, V]) HasProvides(provides T) bool {\n\t_, ok := g.provides[provides]\n\n\treturn ok\n}\n\n// GetProviderInfo returns the dependency info for a provider.\nfunc (g *Graph[T, V]) GetProviderInfo(provides T) *DependencyInfo[T] {\n\treturn g.provides[provides]\n}\n\n// AddProvides registers that node provides the given provides key.\n//\n// Note: despite the \"Add\" name, this is a single mapping; calling it again with the same\n// provides key overwrites the previous entry.\nfunc (g *Graph[T, V]) AddProvides(provides T, depInfo *alpm.Depend, node T) {\n\tg.provides[provides] = &DependencyInfo[T]{\n\t\tProvider: node,\n\t\tDepend:   *depInfo,\n\t}\n}\n\n// ForEach calls f for every node in the graph.\n//\n// The value passed to f is the node's NodeInfo.Value if set via SetNodeInfo; otherwise it is\n// the zero value of V.\nfunc (g *Graph[T, V]) ForEach(f CheckFn[T, V]) error {\n\tfor node := range g.nodes {\n\t\tvar v V\n\t\tif info := g.nodeInfo[node]; info != nil {\n\t\t\tv = info.Value\n\t\t}\n\t\tif err := f(node, v); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// SetNodeInfo sets metadata and value for node. Node does not need to already exist in the graph.\nfunc (g *Graph[T, V]) SetNodeInfo(node T, nodeInfo *NodeInfo[V]) {\n\tg.nodeInfo[node] = nodeInfo\n}\n\n// GetNodeInfo returns metadata/value for node, or nil if none was set.\nfunc (g *Graph[T, V]) GetNodeInfo(node T) *NodeInfo[V] {\n\treturn g.nodeInfo[node]\n}\n\n// DependOn adds an edge meaning \"child depends on parent\".\n//\n// This ensures both nodes exist in the graph and rejects:\n// - self edges (ErrSelfReferential)\n// - edges that would introduce a cycle (ErrCircular)\nfunc (g *Graph[T, V]) DependOn(child, parent T) error {\n\tif child == parent {\n\t\treturn ErrSelfReferential\n\t}\n\n\tif g.DependsOn(parent, child) {\n\t\treturn ErrCircular\n\t}\n\n\tg.AddNode(parent)\n\tg.AddNode(child)\n\n\t// Add edges.\n\tg.dependents.add(parent, child)\n\tg.dependencies.add(child, parent)\n\n\treturn nil\n}\n\n// String renders the graph in GraphViz DOT format.\n//\n// Nodes are emitted as `\"node\"` entries with optional color metadata from NodeInfo.\n// Edges are emitted in the direction: dependent -> dependency (child -> parent).\nfunc (g *Graph[T, V]) String() string {\n\tvar sb strings.Builder\n\n\tsb.WriteString(\"digraph {\\n\")\n\tsb.WriteString(\"compound=true;\\n\")\n\tsb.WriteString(\"concentrate=true;\\n\")\n\tsb.WriteString(\"node [shape = record, ordering=out];\\n\")\n\n\tfor node := range g.nodes {\n\t\textra := \"\"\n\n\t\tif info, ok := g.nodeInfo[node]; ok {\n\t\t\tif info.Background != \"\" || info.Color != \"\" {\n\t\t\t\textra = fmt.Sprintf(\"[color = %s, style = filled, fillcolor = %s]\", info.Color, info.Background)\n\t\t\t}\n\t\t}\n\n\t\tsb.WriteString(fmt.Sprintf(\"\\t\\\"%v\\\"%s;\\n\", node, extra))\n\t}\n\n\tfor parent, children := range g.dependencies {\n\t\tfor child := range children {\n\t\t\tsb.WriteString(fmt.Sprintf(\"\\t\\\"%v\\\" -> \\\"%v\\\";\\n\", parent, child))\n\t\t}\n\t}\n\n\tsb.WriteString(\"}\")\n\n\treturn sb.String()\n}\n\n// DependsOn reports whether child depends (transitively) on parent.\nfunc (g *Graph[T, V]) DependsOn(child, parent T) bool {\n\tdeps := g.Dependencies(child)\n\t_, ok := deps[parent]\n\n\treturn ok\n}\n\n// HasDependent reports whether parent has dependent as a (transitive) dependent.\nfunc (g *Graph[T, V]) HasDependent(parent, dependent T) bool {\n\tdeps := g.Dependents(parent)\n\t_, ok := deps[dependent]\n\n\treturn ok\n}\n\n// leavesMap returns a map of leaves with the node as key and the node info value as value.\nfunc (g *Graph[T, V]) leavesMap() map[T]V {\n\tleaves := make(map[T]V, 0)\n\n\tfor node := range g.nodes {\n\t\tif _, ok := g.dependencies[node]; !ok {\n\t\t\tnodeInfo := g.GetNodeInfo(node)\n\t\t\tif nodeInfo == nil {\n\t\t\t\tnodeInfo = &NodeInfo[V]{}\n\t\t\t}\n\n\t\t\tleaves[node] = nodeInfo.Value\n\t\t}\n\t}\n\n\treturn leaves\n}\n\n// TopoSortedLayers returns a slice of all of the graph nodes in topological sort order with their node info.\n//\n// The returned slice is layered: each element is a \"layer\" of nodes that have no remaining\n// dependencies at that stage of the process.\n//\n// Practical meaning with this graph's edge direction (DependOn(child, parent)):\n// - Earlier layers contain nodes with fewer/zero dependencies (i.e. dependencies-first order).\n// - A node appears only after all of its dependencies have appeared in earlier layers.\n//\n// If checkFn is non-nil, it is called once per node when it is emitted in a layer. Returning an\n// error causes TopoSortedLayers to return nil.\nfunc (g *Graph[T, V]) TopoSortedLayers(checkFn CheckFn[T, V]) []map[T]V {\n\tlayers := []map[T]V{}\n\n\t// Copy the graph\n\tshrinkingGraph := g.clone()\n\n\tfor {\n\t\tleaves := shrinkingGraph.leavesMap()\n\t\tif len(leaves) == 0 {\n\t\t\tbreak\n\t\t}\n\n\t\tlayers = append(layers, leaves)\n\n\t\tfor leafNode := range leaves {\n\t\t\tif checkFn != nil {\n\t\t\t\tif err := checkFn(leafNode, leaves[leafNode]); err != nil {\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t}\n\t\t\tshrinkingGraph.remove(leafNode)\n\t\t}\n\t}\n\n\treturn layers\n}\n\n// returns if it was the last\nfunc (dm DepMap[T]) remove(key, node T) bool {\n\tif nodes := dm[key]; len(nodes) == 1 {\n\t\t// The only element in the nodeset must be `node`, so we\n\t\t// can delete the entry entirely.\n\t\tdelete(dm, key)\n\t\treturn true\n\t} else {\n\t\t// Otherwise, remove the single node from the nodeset.\n\t\tdelete(nodes, node)\n\t\treturn false\n\t}\n}\n\n// Prune removes the node,\n// its dependencies if there are no other dependents\n// and its dependents\n//\n// It returns the list of nodes that were removed (including node). The returned order is based\n// on recursive traversal and is not guaranteed to be stable.\nfunc (g *Graph[T, V]) Prune(node T) []T {\n\tpruned := []T{node}\n\t// Remove edges from things that depend on `node`.\n\tfor dependent := range g.dependents[node] {\n\t\tlast := g.dependencies.remove(dependent, node)\n\t\tif last {\n\t\t\tpruned = append(pruned, g.Prune(dependent)...)\n\t\t}\n\t}\n\n\tdelete(g.dependents, node)\n\n\t// Remove all edges from node to the things it depends on.\n\tfor dependency := range g.dependencies[node] {\n\t\tlast := g.dependents.remove(dependency, node)\n\t\tif last {\n\t\t\tpruned = append(pruned, g.Prune(dependency)...)\n\t\t}\n\t}\n\n\tdelete(g.dependencies, node)\n\n\t// Finally, remove the node itself.\n\tdelete(g.nodes, node)\n\treturn pruned\n}\n\nfunc (g *Graph[T, V]) remove(node T) {\n\t// Remove edges from things that depend on `node`.\n\tfor dependent := range g.dependents[node] {\n\t\tg.dependencies.remove(dependent, node)\n\t}\n\n\tdelete(g.dependents, node)\n\n\t// Remove all edges from node to the things it depends on.\n\tfor dependency := range g.dependencies[node] {\n\t\tg.dependents.remove(dependency, node)\n\t}\n\n\tdelete(g.dependencies, node)\n\n\t// Finally, remove the node itself.\n\tdelete(g.nodes, node)\n}\n\n// Dependencies returns all transitive dependencies of child (excluding child itself).\n// The returned set is nil if child is not present in the graph.\nfunc (g *Graph[T, V]) Dependencies(child T) NodeSet[T] {\n\treturn g.buildTransitive(child, g.ImmediateDependencies)\n}\n\n// ImmediateDependencies returns the direct dependencies of node.\n// The returned set is nil if node has no direct dependencies (or is not present).\nfunc (g *Graph[T, V]) ImmediateDependencies(node T) NodeSet[T] {\n\treturn g.dependencies[node]\n}\n\n// Dependents returns all transitive dependents of parent (excluding parent itself).\n// The returned set is nil if parent is not present in the graph.\nfunc (g *Graph[T, V]) Dependents(parent T) NodeSet[T] {\n\treturn g.buildTransitive(parent, g.ImmediateDependents)\n}\n\n// ImmediateDependents returns the direct dependents of node.\n// The returned set is nil if node has no direct dependents (or is not present).\nfunc (g *Graph[T, V]) ImmediateDependents(node T) NodeSet[T] {\n\treturn g.dependents[node]\n}\n\nfunc (g *Graph[T, V]) clone() *Graph[T, V] {\n\treturn &Graph[T, V]{\n\t\tdependencies: g.dependencies.copy(),\n\t\tdependents:   g.dependents.copy(),\n\t\tnodes:        g.nodes.copy(),\n\t\tnodeInfo:     g.nodeInfo, // not copied, as it is not modified\n\t}\n}\n\n// buildTransitive starts at `root` and continues calling `nextFn` to keep discovering more nodes until\n// the graph cannot produce any more. It returns the set of all discovered nodes.\nfunc (g *Graph[T, V]) buildTransitive(root T, nextFn func(T) NodeSet[T]) NodeSet[T] {\n\tif _, ok := g.nodes[root]; !ok {\n\t\treturn nil\n\t}\n\n\tout := make(NodeSet[T])\n\tsearchNext := []T{root}\n\n\tfor len(searchNext) > 0 {\n\t\t// List of new nodes from this layer of the dependency graph. This is\n\t\t// assigned to `searchNext` at the end of the outer \"discovery\" loop.\n\t\tdiscovered := []T{}\n\n\t\tfor _, node := range searchNext {\n\t\t\t// For each node to discover, find the next nodes.\n\t\t\tfor nextNode := range nextFn(node) {\n\t\t\t\t// If we have not seen the node before, add it to the output as well\n\t\t\t\t// as the list of nodes to traverse in the next iteration.\n\t\t\t\tif _, ok := out[nextNode]; !ok {\n\t\t\t\t\tout[nextNode] = true\n\n\t\t\t\t\tdiscovered = append(discovered, nextNode)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsearchNext = discovered\n\t}\n\n\treturn out\n}\n\nfunc (s NodeSet[T]) copy() NodeSet[T] {\n\tout := make(NodeSet[T], len(s))\n\tmaps.Copy(out, s)\n\n\treturn out\n}\n\nfunc (dm DepMap[T]) copy() DepMap[T] {\n\tout := make(DepMap[T], len(dm))\n\tfor k := range dm {\n\t\tout[k] = dm[k].copy()\n\t}\n\n\treturn out\n}\n\nfunc (dm DepMap[T]) add(key, node T) {\n\tnodes, ok := dm[key]\n\tif !ok {\n\t\tnodes = make(NodeSet[T])\n\t\tdm[key] = nodes\n\t}\n\n\tnodes[node] = true\n}\n"
  },
  {
    "path": "pkg/dep/topo/dep_test.go",
    "content": "package topo\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestGraph_DependenciesAndDependents_Direct(t *testing.T) {\n\tg := New[string, struct{}]()\n\n\t// yay depends on go\n\trequire.NoError(t, g.DependOn(\"yay\", \"go\"))\n\n\t// Dependencies(\"yay\") => {\"go\"}\n\tdepsYay := g.Dependencies(\"yay\")\n\trequire.NotNil(t, depsYay)\n\trequire.Len(t, depsYay, 1)\n\trequire.True(t, depsYay[\"go\"])\n\n\t// Dependencies(\"go\") => {} (empty set, because \"go\" is in the graph but has no deps)\n\tdepsGo := g.Dependencies(\"go\")\n\trequire.NotNil(t, depsGo)\n\trequire.Len(t, depsGo, 0)\n\n\t// Dependents(\"go\") => {\"yay\"}\n\tdependentsGo := g.Dependents(\"go\")\n\trequire.NotNil(t, dependentsGo)\n\trequire.Len(t, dependentsGo, 1)\n\trequire.True(t, dependentsGo[\"yay\"])\n\n\t// Dependents(\"yay\") => {} (empty set, because nothing depends on yay)\n\tdependentsYay := g.Dependents(\"yay\")\n\trequire.NotNil(t, dependentsYay)\n\trequire.Len(t, dependentsYay, 0)\n}\n\nfunc TestGraph_DependenciesAndDependents_Transitive(t *testing.T) {\n\tg := New[string, struct{}]()\n\n\t// yay depends on go; foo depends on yay\n\trequire.NoError(t, g.DependOn(\"yay\", \"go\"))\n\trequire.NoError(t, g.DependOn(\"foo\", \"yay\"))\n\n\t// Dependencies(\"foo\") => {\"yay\", \"go\"}\n\tdepsFoo := g.Dependencies(\"foo\")\n\trequire.NotNil(t, depsFoo)\n\trequire.Len(t, depsFoo, 2)\n\trequire.True(t, depsFoo[\"yay\"])\n\trequire.True(t, depsFoo[\"go\"])\n\n\t// Dependents(\"go\") => {\"yay\", \"foo\"} (transitive)\n\tdependentsGo := g.Dependents(\"go\")\n\trequire.NotNil(t, dependentsGo)\n\trequire.Len(t, dependentsGo, 2)\n\trequire.True(t, dependentsGo[\"yay\"])\n\trequire.True(t, dependentsGo[\"foo\"])\n\n\t// Dependents(\"yay\") => {\"foo\"}\n\tdependentsYay := g.Dependents(\"yay\")\n\trequire.NotNil(t, dependentsYay)\n\trequire.Len(t, dependentsYay, 1)\n\trequire.True(t, dependentsYay[\"foo\"])\n}\n\nfunc TestGraph_DependenciesAndDependents_MissingNodeReturnsNil(t *testing.T) {\n\tg := New[string, struct{}]()\n\n\t// For nodes not present in the graph, transitive queries return nil.\n\trequire.Nil(t, g.Dependencies(\"missing\"))\n\trequire.Nil(t, g.Dependents(\"missing\"))\n\n\t// Adding edges adds nodes; existing nodes with no deps/dependents return an empty set (non-nil).\n\trequire.NoError(t, g.DependOn(\"yay\", \"go\"))\n\trequire.NotNil(t, g.Dependencies(\"go\"))\n\trequire.Len(t, g.Dependencies(\"go\"), 0)\n\trequire.NotNil(t, g.Dependents(\"yay\"))\n\trequire.Len(t, g.Dependents(\"yay\"), 0)\n}\n"
  },
  {
    "path": "pkg/dep/topo/errors.go",
    "content": "package topo\n\nimport \"errors\"\n\nvar (\n\t// ErrSelfReferential is returned when attempting to create an edge where a node depends on itself.\n\tErrSelfReferential = errors.New(\" self-referential dependencies not allowed\")\n\n\t// ErrConflictingAlias is reserved for when a \"provides\" alias is defined more than once.\n\t// Note: current Graph APIs overwrite provides entries; this error is not currently returned.\n\tErrConflictingAlias = errors.New(\" alias already defined\")\n\n\t// ErrCircular is returned when attempting to create an edge that would introduce a cycle.\n\tErrCircular = errors.New(\" circular dependencies not allowed\")\n)\n"
  },
  {
    "path": "pkg/download/abs.go",
    "content": "package download\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"regexp\"\n\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n)\n\nconst (\n\tMaxConcurrentFetch = 20\n\tabsPackageURL      = \"https://gitlab.archlinux.org/archlinux/packaging/packages\"\n)\n\nvar (\n\tErrInvalidRepository  = errors.New(gotext.Get(\"invalid repository\"))\n\tErrABSPackageNotFound = errors.New(gotext.Get(\"package not found in repos\"))\n)\n\ntype regexReplace struct {\n\trepl  string\n\tmatch *regexp.Regexp\n}\n\n// regex replacements for Gitlab URLs\n// info: https://gitlab.archlinux.org/archlinux/devtools/-/blob/6ce666a1669235749c17d5c44d8a24dea4a135da/src/lib/api/gitlab.sh#L84\nvar gitlabRepl = []regexReplace{\n\t{repl: `$1-$2`, match: regexp.MustCompile(`([a-zA-Z0-9]+)\\+([a-zA-Z]+)`)},\n\t{repl: `plus`, match: regexp.MustCompile(`\\+`)},\n\t{repl: `-`, match: regexp.MustCompile(`[^a-zA-Z0-9_\\-.]`)},\n\t{repl: `-`, match: regexp.MustCompile(`[_\\-]{2,}`)},\n\t{repl: `unix-tree`, match: regexp.MustCompile(`^tree$`)},\n}\n\n// Return format for pkgbuild\n// https://gitlab.archlinux.org/archlinux/packaging/packages/0ad/-/raw/main/PKGBUILD\nfunc getPackagePKGBUILDURL(pkgName string) string {\n\treturn fmt.Sprintf(\"%s/%s/-/raw/main/PKGBUILD\", absPackageURL, convertPkgNameForURL(pkgName))\n}\n\n// Return format for pkgbuild repo\n// https://gitlab.archlinux.org/archlinux/packaging/packages/0ad.git\nfunc getPackageRepoURL(pkgName string) string {\n\treturn fmt.Sprintf(\"%s/%s.git\", absPackageURL, convertPkgNameForURL(pkgName))\n}\n\n// convert pkgName for Gitlab URL path (repo name)\nfunc convertPkgNameForURL(pkgName string) string {\n\tfor _, regex := range gitlabRepl {\n\t\tpkgName = regex.match.ReplaceAllString(pkgName, regex.repl)\n\t}\n\treturn pkgName\n}\n\n// ABSPKGBUILD retrieves the PKGBUILD file to a dest directory.\nfunc ABSPKGBUILD(httpClient HTTPRequestDoer, dbName, pkgName string) ([]byte, error) {\n\tpackageURL := getPackagePKGBUILDURL(pkgName)\n\n\tresp, err := httpClient.Get(packageURL)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, ErrABSPackageNotFound\n\t}\n\n\tdefer resp.Body.Close()\n\n\tpkgBuild, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn pkgBuild, nil\n}\n\n// ABSPKGBUILDRepo retrieves the PKGBUILD repository to a dest directory.\nfunc ABSPKGBUILDRepo(ctx context.Context, cmdBuilder exe.GitCmdBuilder,\n\tdbName, pkgName, dest string, force bool,\n) (bool, error) {\n\tpkgURL := getPackageRepoURL(pkgName)\n\n\treturn downloadGitRepo(ctx, cmdBuilder, pkgURL,\n\t\tpkgName, dest, force, \"--single-branch\")\n}\n"
  },
  {
    "path": "pkg/download/abs_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage download\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n)\n\nconst gitExtrasPKGBUILD = `pkgname=git-extras\npkgver=6.1.0\npkgrel=1\npkgdesc=\"GIT utilities -- repo summary, commit counting, repl, changelog population and more\"\narch=('any')\nurl=\"https://github.com/tj/${pkgname}\"\nlicense=('MIT')\ndepends=('git')\nsource=(\"${pkgname}-${pkgver}.tar.gz::${url}/archive/${pkgver}.tar.gz\")\nsha256sums=('7be0b15ee803d76d2c2e8036f5d9db6677f2232bb8d2c4976691ff7ae026a22f')\nb2sums=('3450edecb3116e19ffcf918b118aee04f025c06d812e29e8701f35a3c466b13d2578d41c8e1ee93327743d0019bf98bb3f397189e19435f89e3a259ff1b82747')\n\npackage() {\n    cd \"${srcdir}/${pkgname}-${pkgver}\"\n\n    # avoid annoying interactive prompts if an alias is in your gitconfig\n    export GIT_CONFIG=/dev/null\n    make DESTDIR=\"${pkgdir}\" PREFIX=/usr SYSCONFDIR=/etc install\n    install -Dm644 LICENSE \"${pkgdir}/usr/share/licenses/${pkgname}/LICENSE\"\n}`\n\nfunc Test_getPackageURL(t *testing.T) {\n\tt.Parallel()\n\ttype args struct {\n\t\tdb      string\n\t\tpkgName string\n\t}\n\ttests := []struct {\n\t\tname    string\n\t\targs    args\n\t\twant    string\n\t\twantErr bool\n\t}{\n\t\t{\n\t\t\tname: \"extra package\",\n\t\t\targs: args{\n\t\t\t\tdb:      \"extra\",\n\t\t\t\tpkgName: \"kitty\",\n\t\t\t},\n\t\t\twant:    \"https://gitlab.archlinux.org/archlinux/packaging/packages/kitty/-/raw/main/PKGBUILD\",\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname: \"core package\",\n\t\t\targs: args{\n\t\t\t\tdb:      \"core\",\n\t\t\t\tpkgName: \"linux\",\n\t\t\t},\n\t\t\twant:    \"https://gitlab.archlinux.org/archlinux/packaging/packages/linux/-/raw/main/PKGBUILD\",\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname: \"personal repo package\",\n\t\t\targs: args{\n\t\t\t\tdb:      \"sweswe\",\n\t\t\t\tpkgName: \"zabix\",\n\t\t\t},\n\t\t\twant:    \"https://gitlab.archlinux.org/archlinux/packaging/packages/zabix/-/raw/main/PKGBUILD\",\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname: \"special name +\",\n\t\t\targs: args{\n\t\t\t\tdb:      \"core\",\n\t\t\t\tpkgName: \"my+package\",\n\t\t\t},\n\t\t\twant:    \"https://gitlab.archlinux.org/archlinux/packaging/packages/my-package/-/raw/main/PKGBUILD\",\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname: \"special name %\",\n\t\t\targs: args{\n\t\t\t\tdb:      \"core\",\n\t\t\t\tpkgName: \"my%package\",\n\t\t\t},\n\t\t\twant:    \"https://gitlab.archlinux.org/archlinux/packaging/packages/my-package/-/raw/main/PKGBUILD\",\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname: \"special name _-\",\n\t\t\targs: args{\n\t\t\t\tdb:      \"core\",\n\t\t\t\tpkgName: \"my_-package\",\n\t\t\t},\n\t\t\twant:    \"https://gitlab.archlinux.org/archlinux/packaging/packages/my-package/-/raw/main/PKGBUILD\",\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname: \"special name ++\",\n\t\t\targs: args{\n\t\t\t\tdb:      \"core\",\n\t\t\t\tpkgName: \"my++package\",\n\t\t\t},\n\t\t\twant:    \"https://gitlab.archlinux.org/archlinux/packaging/packages/mypluspluspackage/-/raw/main/PKGBUILD\",\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname: \"special name tree\",\n\t\t\targs: args{\n\t\t\t\tdb:      \"sweswe\",\n\t\t\t\tpkgName: \"tree\",\n\t\t\t},\n\t\t\twant:    \"https://gitlab.archlinux.org/archlinux/packaging/packages/unix-tree/-/raw/main/PKGBUILD\",\n\t\t\twantErr: false,\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tgot := getPackagePKGBUILDURL(tt.args.pkgName)\n\t\t\tassert.Equal(t, tt.want, got)\n\t\t})\n\t}\n}\n\nfunc TestGetABSPkgbuild(t *testing.T) {\n\tt.Parallel()\n\n\ttype args struct {\n\t\tdbName  string\n\t\tbody    string\n\t\tstatus  int\n\t\tpkgName string\n\t\twantURL string\n\t}\n\ttests := []struct {\n\t\tname    string\n\t\targs    args\n\t\twant    string\n\t\twantErr bool\n\t}{\n\t\t{\n\t\t\tname: \"found package\",\n\t\t\targs: args{\n\t\t\t\tdbName:  \"core\",\n\t\t\t\tbody:    gitExtrasPKGBUILD,\n\t\t\t\tstatus:  200,\n\t\t\t\tpkgName: \"git-extras\",\n\t\t\t\twantURL: \"https://gitlab.archlinux.org/archlinux/packaging/packages/git-extras/-/raw/main/PKGBUILD\",\n\t\t\t},\n\t\t\twant:    gitExtrasPKGBUILD,\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname: \"not found package\",\n\t\t\targs: args{\n\t\t\t\tdbName:  \"core\",\n\t\t\t\tbody:    \"\",\n\t\t\t\tstatus:  404,\n\t\t\t\tpkgName: \"git-git\",\n\t\t\t\twantURL: \"https://gitlab.archlinux.org/archlinux/packaging/packages/git-git/-/raw/main/PKGBUILD\",\n\t\t\t},\n\t\t\twant:    \"\",\n\t\t\twantErr: true,\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\thttpClient := &testClient{\n\t\t\t\tt:       t,\n\t\t\t\twantURL: tt.args.wantURL,\n\t\t\t\tbody:    tt.args.body,\n\t\t\t\tstatus:  tt.args.status,\n\t\t\t}\n\t\t\tgot, err := ABSPKGBUILD(httpClient, tt.args.dbName, tt.args.pkgName)\n\t\t\tif tt.wantErr {\n\t\t\t\tassert.Error(t, err)\n\t\t\t} else {\n\t\t\t\tassert.NoError(t, err)\n\t\t\t}\n\n\t\t\tassert.Equal(t, tt.want, string(got))\n\t\t})\n\t}\n}\n\nfunc Test_getPackageRepoURL(t *testing.T) {\n\tt.Parallel()\n\n\ttype args struct {\n\t\tpkgName string\n\t}\n\ttests := []struct {\n\t\tname    string\n\t\targs    args\n\t\twant    string\n\t\twantErr bool\n\t}{\n\t\t{\n\t\t\tname:    \"extra package\",\n\t\t\targs:    args{pkgName: \"zoxide\"},\n\t\t\twant:    \"https://gitlab.archlinux.org/archlinux/packaging/packages/zoxide.git\",\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:    \"core package\",\n\t\t\targs:    args{pkgName: \"linux\"},\n\t\t\twant:    \"https://gitlab.archlinux.org/archlinux/packaging/packages/linux.git\",\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:    \"personal repo package\",\n\t\t\targs:    args{pkgName: \"sweswe\"},\n\t\t\twant:    \"https://gitlab.archlinux.org/archlinux/packaging/packages/sweswe.git\",\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:    \"special name +\",\n\t\t\targs:    args{pkgName: \"my+package\"},\n\t\t\twant:    \"https://gitlab.archlinux.org/archlinux/packaging/packages/my-package.git\",\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:    \"special name %\",\n\t\t\targs:    args{pkgName: \"my%package\"},\n\t\t\twant:    \"https://gitlab.archlinux.org/archlinux/packaging/packages/my-package.git\",\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:    \"special name _-\",\n\t\t\targs:    args{pkgName: \"my_-package\"},\n\t\t\twant:    \"https://gitlab.archlinux.org/archlinux/packaging/packages/my-package.git\",\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:    \"special name ++\",\n\t\t\targs:    args{pkgName: \"my++package\"},\n\t\t\twant:    \"https://gitlab.archlinux.org/archlinux/packaging/packages/mypluspluspackage.git\",\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname:    \"special name tree\",\n\t\t\targs:    args{pkgName: \"tree\"},\n\t\t\twant:    \"https://gitlab.archlinux.org/archlinux/packaging/packages/unix-tree.git\",\n\t\t\twantErr: false,\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tgot := getPackageRepoURL(tt.args.pkgName)\n\t\t\tassert.Equal(t, tt.want, got)\n\t\t})\n\t}\n}\n\n// GIVEN no previous existing folder\n// WHEN ABSPKGBUILDRepo is called\n// THEN a clone command should be formed\nfunc TestABSPKGBUILDRepo(t *testing.T) {\n\tt.Parallel()\n\tcmdRunner := &testRunner{}\n\twant := \"/usr/local/bin/git --no-replace-objects -C /tmp/doesnt-exist clone --no-progress --single-branch https://gitlab.archlinux.org/archlinux/packaging/packages/linux.git linux\"\n\tif os.Getuid() == 0 {\n\t\tld := \"systemd-run\"\n\t\tif path, _ := exec.LookPath(ld); path != \"\" {\n\t\t\tld = path\n\t\t}\n\t\twant = fmt.Sprintf(\"%s --service-type=oneshot --pipe --wait --pty --quiet -p DynamicUser=yes -p CacheDirectory=yay -E HOME=/tmp  --no-replace-objects -C /tmp/doesnt-exist clone --no-progress --single-branch https://gitlab.archlinux.org/archlinux/packaging/packages/linux.git linux\", ld)\n\t}\n\n\tcmdBuilder := &testGitBuilder{\n\t\tindex: 0,\n\t\ttest:  t,\n\t\twant:  want,\n\t\tparentBuilder: &exe.CmdBuilder{\n\t\t\tRunner:   cmdRunner,\n\t\t\tGitBin:   \"/usr/local/bin/git\",\n\t\t\tGitFlags: []string{\"--no-replace-objects\"},\n\t\t},\n\t}\n\tnewClone, err := ABSPKGBUILDRepo(context.Background(), cmdBuilder, \"core\", \"linux\", \"/tmp/doesnt-exist\", false)\n\tassert.NoError(t, err)\n\tassert.Equal(t, true, newClone)\n}\n\n// GIVEN a previous existing folder with permissions\n// WHEN ABSPKGBUILDRepo is called\n// THEN a pull command should be formed\nfunc TestABSPKGBUILDRepoExistsPerms(t *testing.T) {\n\tt.Parallel()\n\tdir := t.TempDir()\n\n\tos.MkdirAll(filepath.Join(dir, \"linux\", \".git\"), 0o777)\n\n\twant := fmt.Sprintf(\"/usr/local/bin/git --no-replace-objects -C %s/linux pull --rebase --autostash\", dir)\n\tif os.Getuid() == 0 {\n\t\tld := \"systemd-run\"\n\t\tif path, _ := exec.LookPath(ld); path != \"\" {\n\t\t\tld = path\n\t\t}\n\t\twant = fmt.Sprintf(\"%s --service-type=oneshot --pipe --wait --pty --quiet -p DynamicUser=yes -p CacheDirectory=yay -E HOME=/tmp  --no-replace-objects -C %s/linux pull --rebase --autostash\", ld, dir)\n\t}\n\n\tcmdRunner := &testRunner{}\n\tcmdBuilder := &testGitBuilder{\n\t\tindex: 0,\n\t\ttest:  t,\n\t\twant:  want,\n\t\tparentBuilder: &exe.CmdBuilder{\n\t\t\tRunner:   cmdRunner,\n\t\t\tGitBin:   \"/usr/local/bin/git\",\n\t\t\tGitFlags: []string{\"--no-replace-objects\"},\n\t\t},\n\t}\n\tnewClone, err := ABSPKGBUILDRepo(context.Background(), cmdBuilder, \"core\", \"linux\", dir, false)\n\tassert.NoError(t, err)\n\tassert.Equal(t, false, newClone)\n}\n"
  },
  {
    "path": "pkg/download/aur.go",
    "content": "package download\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"compress/gzip\"\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"path\"\n\t\"sync\"\n\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/multierror\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\nfunc AURPKGBUILD(httpClient HTTPRequestDoer, pkgName, aurURL string) ([]byte, error) {\n\tvalues := url.Values{}\n\tvalues.Set(\"h\", pkgName)\n\tpkgURL := aurURL + \"/cgit/aur.git/plain/PKGBUILD?\" + values.Encode()\n\n\tresp, err := httpClient.Get(pkgURL)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, ErrAURPackageNotFound{pkgName: pkgName}\n\t}\n\n\tdefer resp.Body.Close()\n\n\tpkgBuild, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn pkgBuild, nil\n}\n\n// AURPkgbuildRepo retrieves the PKGBUILD repository to a dest directory.\nfunc AURPKGBUILDRepo(ctx context.Context, cmdBuilder exe.GitCmdBuilder, aurURL, pkgName, dest string, force bool) (bool, error) {\n\tpkgURL := fmt.Sprintf(\"%s/%s.git\", aurURL, pkgName)\n\n\treturn downloadGitRepo(ctx, cmdBuilder, pkgURL, pkgName, dest, force)\n}\n\nfunc AURPKGBUILDRepos(\n\tctx context.Context,\n\tcmdBuilder exe.GitCmdBuilder, logger *text.Logger,\n\ttargets []string, aurURL, dest string, force bool,\n) (map[string]bool, error) {\n\tcloned := make(map[string]bool, len(targets))\n\n\tvar (\n\t\tmux  sync.Mutex\n\t\terrs multierror.MultiError\n\t\twg   sync.WaitGroup\n\t)\n\n\tsem := make(chan uint8, MaxConcurrentFetch)\n\n\tfor _, target := range targets {\n\t\tsem <- 1\n\t\twg.Add(1)\n\n\t\tgo func(target string) {\n\t\t\tdefer func() {\n\t\t\t\t<-sem\n\t\t\t\twg.Done()\n\t\t\t}()\n\n\t\t\tnewClone, err := AURPKGBUILDRepo(ctx, cmdBuilder, aurURL, target, dest, force)\n\n\t\t\tmux.Lock()\n\t\t\tprogress := len(cloned)\n\t\t\tif err != nil {\n\t\t\t\terrs.Add(err)\n\t\t\t\tmux.Unlock()\n\t\t\t\tlogger.OperationInfoln(\n\t\t\t\t\tgotext.Get(\"(%d/%d) Failed to download PKGBUILD: %s\",\n\t\t\t\t\t\tprogress, len(targets), text.Cyan(target)))\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tcloned[target] = newClone\n\t\t\tprogress = len(cloned)\n\t\t\tmux.Unlock()\n\n\t\t\tlogger.OperationInfoln(\n\t\t\t\tgotext.Get(\"(%d/%d) Downloaded PKGBUILD: %s\",\n\t\t\t\t\tprogress, len(targets), text.Cyan(target)))\n\t\t}(target)\n\t}\n\n\twg.Wait()\n\n\treturn cloned, errs.Return()\n}\n\n// ScannerCloser combines a bufio.Scanner with a Close method.\ntype ScannerCloser struct {\n\t*bufio.Scanner\n\tcloser io.Closer\n}\n\n// Close closes the underlying gzip reader if present.\nfunc (s *ScannerCloser) Close() error {\n\tif s.closer != nil {\n\t\treturn s.closer.Close()\n\t}\n\treturn nil\n}\n\n// GetPackageScanner fetches the AUR packages.gz file and returns a scanner for reading its contents.\n// The caller must call Close() on the returned ScannerCloser when done to properly release resources.\nfunc GetPackageScanner(ctx context.Context, client HTTPRequestDoer, aurURL string, logger *text.Logger) (*ScannerCloser, error) {\n\tu, err := url.Parse(aurURL)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tu.Path = path.Join(u.Path, \"packages.gz\")\n\tpackagesURL := u.String()\n\n\tresp, err := client.Get(packagesURL)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif resp.StatusCode != http.StatusOK {\n\t\tresp.Body.Close()\n\t\treturn nil, fmt.Errorf(\"invalid status code: %d\", resp.StatusCode)\n\t}\n\n\t// Read the entire body to allow trying gzip decompression\n\tbody, err := io.ReadAll(resp.Body)\n\tresp.Body.Close()\n\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Try to decompress as gzip; if that fails, use raw body\n\tvar reader io.Reader\n\tvar closer io.Closer\n\n\tgzReader, gzErr := gzip.NewReader(bytes.NewReader(body))\n\tif gzErr == nil {\n\t\treader = gzReader\n\t\tcloser = gzReader\n\t} else {\n\t\tif logger != nil {\n\t\t\tlogger.Debugln(\"gzip decompression not needed, using raw response body\")\n\t\t}\n\t\treader = bytes.NewReader(body)\n\t}\n\n\tscanner := bufio.NewScanner(reader)\n\n\treturn &ScannerCloser{\n\t\tScanner: scanner,\n\t\tcloser:  closer,\n\t}, nil\n}\n"
  },
  {
    "path": "pkg/download/aur_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage download\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n)\n\nfunc TestGetAURPkgbuild(t *testing.T) {\n\tt.Parallel()\n\n\ttype args struct {\n\t\tbody    string\n\t\tstatus  int\n\t\tpkgName string\n\t\twantURL string\n\t}\n\ttests := []struct {\n\t\tname    string\n\t\targs    args\n\t\twant    string\n\t\twantErr bool\n\t}{\n\t\t{\n\t\t\tname: \"found package\",\n\t\t\targs: args{\n\t\t\t\tbody:    gitExtrasPKGBUILD,\n\t\t\t\tstatus:  200,\n\t\t\t\tpkgName: \"git-extras\",\n\t\t\t\twantURL: \"https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=git-extras\",\n\t\t\t},\n\t\t\twant:    gitExtrasPKGBUILD,\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname: \"not found package\",\n\t\t\targs: args{\n\t\t\t\tbody:    \"\",\n\t\t\t\tstatus:  404,\n\t\t\t\tpkgName: \"git-git\",\n\t\t\t\twantURL: \"https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=git-git\",\n\t\t\t},\n\t\t\twant:    \"\",\n\t\t\twantErr: true,\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\thttpClient := &testClient{\n\t\t\t\tt:       t,\n\t\t\t\twantURL: tt.args.wantURL,\n\t\t\t\tbody:    tt.args.body,\n\t\t\t\tstatus:  tt.args.status,\n\t\t\t}\n\t\t\tgot, err := AURPKGBUILD(httpClient, tt.args.pkgName, \"https://aur.archlinux.org\")\n\t\t\tif tt.wantErr {\n\t\t\t\tassert.Error(t, err)\n\t\t\t} else {\n\t\t\t\tassert.NoError(t, err)\n\t\t\t}\n\n\t\t\tassert.Equal(t, tt.want, string(got))\n\t\t})\n\t}\n}\n\n// GIVEN no previous existing folder\n// WHEN AURPKGBUILDRepo is called\n// THEN a clone command should be formed\nfunc TestAURPKGBUILDRepo(t *testing.T) {\n\tt.Parallel()\n\twant := \"/usr/local/bin/git --no-replace-objects -C /tmp/doesnt-exist clone --no-progress https://aur.archlinux.org/yay-bin.git yay-bin\"\n\tif os.Getuid() == 0 {\n\t\tld := \"systemd-run\"\n\t\tif path, _ := exec.LookPath(ld); path != \"\" {\n\t\t\tld = path\n\t\t}\n\t\twant = fmt.Sprintf(\"%s --service-type=oneshot --pipe --wait --pty --quiet -p DynamicUser=yes -p CacheDirectory=yay -E HOME=/tmp  --no-replace-objects -C /tmp/doesnt-exist clone --no-progress https://aur.archlinux.org/yay-bin.git yay-bin\", ld)\n\t}\n\n\tcmdRunner := &testRunner{}\n\tcmdBuilder := &testGitBuilder{\n\t\tindex: 0,\n\t\ttest:  t,\n\t\twant:  want,\n\t\tparentBuilder: &exe.CmdBuilder{\n\t\t\tRunner:   cmdRunner,\n\t\t\tGitBin:   \"/usr/local/bin/git\",\n\t\t\tGitFlags: []string{\"--no-replace-objects\"},\n\t\t},\n\t}\n\tnewCloned, err := AURPKGBUILDRepo(context.Background(), cmdBuilder, \"https://aur.archlinux.org\", \"yay-bin\", \"/tmp/doesnt-exist\", false)\n\tassert.NoError(t, err)\n\tassert.Equal(t, true, newCloned)\n}\n\n// GIVEN a previous existing folder with permissions\n// WHEN AURPKGBUILDRepo is called\n// THEN a pull command should be formed\nfunc TestAURPKGBUILDRepoExistsPerms(t *testing.T) {\n\tt.Parallel()\n\tdir := t.TempDir()\n\n\tos.MkdirAll(filepath.Join(dir, \"yay-bin\", \".git\"), 0o777)\n\n\twant := fmt.Sprintf(\"/usr/local/bin/git --no-replace-objects -C %s/yay-bin pull --rebase --autostash\", dir)\n\tif os.Getuid() == 0 {\n\t\tld := \"systemd-run\"\n\t\tif path, _ := exec.LookPath(ld); path != \"\" {\n\t\t\tld = path\n\t\t}\n\t\twant = fmt.Sprintf(\"%s --service-type=oneshot --pipe --wait --pty --quiet -p DynamicUser=yes -p CacheDirectory=yay -E HOME=/tmp  --no-replace-objects -C %s/yay-bin pull --rebase --autostash\", ld, dir)\n\t}\n\n\tcmdRunner := &testRunner{}\n\tcmdBuilder := &testGitBuilder{\n\t\tindex: 0,\n\t\ttest:  t,\n\t\twant:  want,\n\t\tparentBuilder: &exe.CmdBuilder{\n\t\t\tRunner:   cmdRunner,\n\t\t\tGitBin:   \"/usr/local/bin/git\",\n\t\t\tGitFlags: []string{\"--no-replace-objects\"},\n\t\t},\n\t}\n\tcloned, err := AURPKGBUILDRepo(context.Background(), cmdBuilder, \"https://aur.archlinux.org\", \"yay-bin\", dir, false)\n\tassert.NoError(t, err)\n\tassert.Equal(t, false, cloned)\n}\n\nfunc TestAURPKGBUILDRepos(t *testing.T) {\n\tt.Parallel()\n\tdir := t.TempDir()\n\n\tos.MkdirAll(filepath.Join(dir, \"yay-bin\", \".git\"), 0o777)\n\n\ttargets := []string{\"yay\", \"yay-bin\", \"yay-git\"}\n\tcmdRunner := &testRunner{}\n\tcmdBuilder := &testGitBuilder{\n\t\tindex: 0,\n\t\ttest:  t,\n\t\twant:  \"\",\n\t\tparentBuilder: &exe.CmdBuilder{\n\t\t\tRunner:   cmdRunner,\n\t\t\tGitBin:   \"/usr/local/bin/git\",\n\t\t\tGitFlags: []string{},\n\t\t},\n\t}\n\tcloned, err := AURPKGBUILDRepos(context.Background(), cmdBuilder, newTestLogger(), targets, \"https://aur.archlinux.org\", dir, false)\n\n\tassert.NoError(t, err)\n\tassert.EqualValues(t, map[string]bool{\"yay\": true, \"yay-bin\": false, \"yay-git\": true}, cloned)\n}\n"
  },
  {
    "path": "pkg/download/errors.go",
    "content": "package download\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/leonelquinteros/gotext\"\n)\n\n// ErrAURPackageNotFound means that package was not found in AUR.\ntype ErrAURPackageNotFound struct {\n\tpkgName string\n}\n\nfunc (e ErrAURPackageNotFound) Error() string {\n\treturn fmt.Sprintln(gotext.Get(\"package not found in AUR\"), \":\", e.pkgName)\n}\n\ntype ErrGetPKGBUILDRepo struct {\n\tinner   error\n\tpkgName string\n\terrOut  string\n}\n\nfunc (e ErrGetPKGBUILDRepo) Error() string {\n\treturn fmt.Sprintln(gotext.Get(\"error fetching %s: %s\", e.pkgName, e.errOut),\n\t\t\"\\n\\t context:\", e.inner.Error())\n}\n\nfunc (e *ErrGetPKGBUILDRepo) Unwrap() error {\n\treturn e.inner\n}\n"
  },
  {
    "path": "pkg/download/unified.go",
    "content": "package download\n\nimport (\n\t\"context\"\n\t\"net/http\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sync\"\n\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/aur\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/multierror\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\n// HTTPRequestDoer is an interface for HTTP clients that can perform GET requests.\ntype HTTPRequestDoer interface {\n\tGet(string) (*http.Response, error)\n}\n\ntype DBSearcher interface {\n\tSyncPackage(string) db.IPackage\n\tSyncPackageFromDB(string, string) db.IPackage\n}\n\nfunc downloadGitRepo(ctx context.Context, cmdBuilder exe.GitCmdBuilder,\n\tpkgURL, pkgName, dest string, force bool, gitArgs ...string,\n) (bool, error) {\n\tfinalDir := filepath.Join(dest, pkgName)\n\tnewClone := true\n\n\tswitch _, err := os.Stat(filepath.Join(finalDir, \".git\")); {\n\tcase os.IsNotExist(err) || (err == nil && force):\n\t\tif _, errD := os.Stat(finalDir); force && errD == nil {\n\t\t\tif errR := os.RemoveAll(finalDir); errR != nil {\n\t\t\t\treturn false, ErrGetPKGBUILDRepo{inner: errR, pkgName: pkgName, errOut: \"\"}\n\t\t\t}\n\t\t}\n\n\t\tgitArgs = append(gitArgs, pkgURL, pkgName)\n\n\t\tcloneArgs := make([]string, 0, len(gitArgs)+4)\n\t\tcloneArgs = append(cloneArgs, \"clone\", \"--no-progress\")\n\t\tcloneArgs = append(cloneArgs, gitArgs...)\n\t\tcmd := cmdBuilder.BuildGitCmd(ctx, dest, cloneArgs...)\n\n\t\t_, stderr, errCapture := cmdBuilder.Capture(cmd)\n\t\tif errCapture != nil {\n\t\t\treturn false, ErrGetPKGBUILDRepo{inner: errCapture, pkgName: pkgName, errOut: stderr}\n\t\t}\n\tcase err != nil:\n\t\treturn false, ErrGetPKGBUILDRepo{\n\t\t\tinner:   err,\n\t\t\tpkgName: pkgName,\n\t\t\terrOut:  gotext.Get(\"error reading %s\", filepath.Join(dest, pkgName, \".git\")),\n\t\t}\n\tdefault:\n\t\tcmd := cmdBuilder.BuildGitCmd(ctx, filepath.Join(dest, pkgName), \"pull\", \"--rebase\", \"--autostash\")\n\n\t\t_, stderr, errCmd := cmdBuilder.Capture(cmd)\n\t\tif errCmd != nil {\n\t\t\treturn false, ErrGetPKGBUILDRepo{inner: errCmd, pkgName: pkgName, errOut: stderr}\n\t\t}\n\n\t\tnewClone = false\n\t}\n\n\treturn newClone, nil\n}\n\nfunc getURLName(pkg db.IPackage) string {\n\tname := pkg.Base()\n\tif name == \"\" {\n\t\tname = pkg.Name()\n\t}\n\n\treturn name\n}\n\nfunc PKGBUILDs(dbExecutor DBSearcher, aurClient aur.QueryClient, httpClient *http.Client,\n\tlogger *text.Logger, targets []string, aurURL string, mode parser.TargetMode,\n) (map[string][]byte, error) {\n\tpkgbuilds := make(map[string][]byte, len(targets))\n\n\tvar (\n\t\tmux  sync.Mutex\n\t\terrs multierror.MultiError\n\t\twg   sync.WaitGroup\n\t)\n\n\tsem := make(chan uint8, MaxConcurrentFetch)\n\n\tfor _, target := range targets {\n\t\t// Probably replaceable by something in query.\n\t\tdbName, name, isAUR, toSkip := getPackageUsableName(dbExecutor, aurClient, logger, target, mode)\n\t\tif toSkip {\n\t\t\tcontinue\n\t\t}\n\n\t\tsem <- 1\n\n\t\twg.Add(1)\n\n\t\tgo func(target, dbName, pkgName string, aur bool) {\n\t\t\tvar (\n\t\t\t\terr      error\n\t\t\t\tpkgbuild []byte\n\t\t\t)\n\n\t\t\tif aur {\n\t\t\t\tpkgbuild, err = AURPKGBUILD(httpClient, pkgName, aurURL)\n\t\t\t} else {\n\t\t\t\tpkgbuild, err = ABSPKGBUILD(httpClient, dbName, pkgName)\n\t\t\t}\n\n\t\t\tif err == nil {\n\t\t\t\tmux.Lock()\n\t\t\t\tpkgbuilds[target] = pkgbuild\n\t\t\t\tmux.Unlock()\n\t\t\t} else {\n\t\t\t\terrs.Add(err)\n\t\t\t}\n\n\t\t\t<-sem\n\t\t\twg.Done()\n\t\t}(target, dbName, name, isAUR)\n\t}\n\n\twg.Wait()\n\n\treturn pkgbuilds, errs.Return()\n}\n\nfunc PKGBUILDRepos(ctx context.Context, dbExecutor DBSearcher, aurClient aur.QueryClient,\n\tcmdBuilder exe.GitCmdBuilder, logger *text.Logger,\n\ttargets []string, mode parser.TargetMode, aurURL, dest string, force bool,\n) (map[string]bool, error) {\n\tcloned := make(map[string]bool, len(targets))\n\n\tvar (\n\t\tmux  sync.Mutex\n\t\terrs multierror.MultiError\n\t\twg   sync.WaitGroup\n\t)\n\n\tsem := make(chan uint8, MaxConcurrentFetch)\n\n\tfor _, target := range targets {\n\t\t// Probably replaceable by something in query.\n\t\tdbName, name, isAUR, toSkip := getPackageUsableName(dbExecutor, aurClient, logger, target, mode)\n\t\tif toSkip {\n\t\t\tcontinue\n\t\t}\n\n\t\tsem <- 1\n\n\t\twg.Add(1)\n\n\t\tgo func(target, dbName, pkgName string, aur bool) {\n\t\t\tvar (\n\t\t\t\terr      error\n\t\t\t\tnewClone bool\n\t\t\t)\n\n\t\t\tif aur {\n\t\t\t\tnewClone, err = AURPKGBUILDRepo(ctx, cmdBuilder, aurURL, pkgName, dest, force)\n\t\t\t} else {\n\t\t\t\tnewClone, err = ABSPKGBUILDRepo(ctx, cmdBuilder, dbName, pkgName, dest, force)\n\t\t\t}\n\n\t\t\tprogress := 0\n\n\t\t\tif err != nil {\n\t\t\t\terrs.Add(err)\n\t\t\t} else {\n\t\t\t\tmux.Lock()\n\t\t\t\tcloned[target] = newClone\n\t\t\t\tprogress = len(cloned)\n\t\t\t\tmux.Unlock()\n\t\t\t}\n\n\t\t\tif aur {\n\t\t\t\tlogger.OperationInfoln(\n\t\t\t\t\tgotext.Get(\"(%d/%d) Downloaded PKGBUILD: %s\",\n\t\t\t\t\t\tprogress, len(targets), text.Cyan(pkgName)))\n\t\t\t} else {\n\t\t\t\tlogger.OperationInfoln(\n\t\t\t\t\tgotext.Get(\"(%d/%d) Downloaded PKGBUILD from ABS: %s\",\n\t\t\t\t\t\tprogress, len(targets), text.Cyan(pkgName)))\n\t\t\t}\n\n\t\t\t<-sem\n\n\t\t\twg.Done()\n\t\t}(target, dbName, name, isAUR)\n\t}\n\n\twg.Wait()\n\n\treturn cloned, errs.Return()\n}\n\nfunc getPackageUsableName(dbExecutor DBSearcher, aurClient aur.QueryClient,\n\tlogger *text.Logger, target string, mode parser.TargetMode,\n) (dbname, pkgname string, isAUR, toSkip bool) {\n\tdbName, name := text.SplitDBFromName(target)\n\tif dbName != \"aur\" && mode.AtLeastRepo() {\n\t\tvar pkg db.IPackage\n\t\tif dbName != \"\" {\n\t\t\tpkg = dbExecutor.SyncPackageFromDB(name, dbName)\n\t\t} else {\n\t\t\tpkg = dbExecutor.SyncPackage(name)\n\t\t}\n\n\t\tif pkg != nil {\n\t\t\treturn pkg.DB().Name(), getURLName(pkg), false, false\n\t\t}\n\n\t\t// Package not found in specified DB - skip it\n\t\tif dbName != \"\" {\n\t\t\treturn dbName, name, true, true\n\t\t}\n\t}\n\n\tif mode == parser.ModeRepo {\n\t\treturn dbName, name, true, true\n\t}\n\n\tpkgs, err := aurClient.Get(context.Background(), &aur.Query{\n\t\tBy:       aur.Name,\n\t\tContains: false,\n\t\tNeedles:  []string{name},\n\t})\n\tif err != nil {\n\t\tlogger.Warnln(err)\n\t\treturn dbName, name, true, true\n\t}\n\n\tif len(pkgs) == 0 {\n\t\treturn dbName, name, true, true\n\t}\n\n\treturn \"aur\", name, true, false\n}\n"
  },
  {
    "path": "pkg/download/unified_integration_test.go",
    "content": "//go:build integration\n// +build integration\n\npackage download\n\nimport (\n\t\"context\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\n\t\"github.com/Jguer/aur\"\n\n\tmockaur \"github.com/Jguer/yay/v12/pkg/dep/mock\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\nfunc TestIntegrationPKGBUILDReposDefinedDBClone(t *testing.T) {\n\tdir := t.TempDir()\n\n\tmockClient := &mockaur.MockAUR{\n\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\treturn []aur.Pkg{{}}, nil // fakes a package found for all\n\t\t},\n\t}\n\ttargets := []string{\"core/linux\", \"yay-bin\", \"yay-git\"}\n\n\ttestLogger := text.NewLogger(os.Stdout, os.Stderr, strings.NewReader(\"\"), true, \"test\")\n\tcmdRunner := &exe.OSRunner{Log: testLogger}\n\tcmdBuilder := &exe.CmdBuilder{\n\t\tRunner:   cmdRunner,\n\t\tGitBin:   \"git\",\n\t\tGitFlags: []string{},\n\t\tLog:      testLogger,\n\t}\n\tsearcher := &testDBSearcher{\n\t\tabsPackagesDB: map[string]string{\"linux\": \"core\"},\n\t}\n\tcloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,\n\t\tcmdBuilder, testLogger.Child(\"test\"),\n\t\ttargets, parser.ModeAny, \"https://aur.archlinux.org\", dir, false)\n\n\tassert.NoError(t, err)\n\tassert.EqualValues(t, map[string]bool{\"core/linux\": true, \"yay-bin\": true, \"yay-git\": true}, cloned)\n}\n\nfunc TestIntegrationPKGBUILDReposNotExist(t *testing.T) {\n\tdir := t.TempDir()\n\n\tmockClient := &mockaur.MockAUR{\n\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\treturn []aur.Pkg{{}}, nil // fakes a package found for all\n\t\t},\n\t}\n\ttargets := []string{\"core/yay\", \"yay-bin\", \"yay-git\"}\n\ttestLogger := text.NewLogger(os.Stdout, os.Stderr, strings.NewReader(\"\"), true, \"test\")\n\tcmdRunner := &exe.OSRunner{Log: testLogger}\n\tcmdBuilder := &exe.CmdBuilder{\n\t\tRunner:   cmdRunner,\n\t\tGitBin:   \"git\",\n\t\tGitFlags: []string{},\n\t\tLog:      testLogger,\n\t}\n\n\tsearcher := &testDBSearcher{\n\t\tabsPackagesDB: map[string]string{\"yay\": \"core\"},\n\t}\n\tcloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,\n\t\tcmdBuilder, testLogger.Child(\"test\"),\n\t\ttargets, parser.ModeAny, \"https://aur.archlinux.org\", dir, false)\n\n\tassert.Error(t, err)\n\tassert.EqualValues(t, map[string]bool{\"yay-bin\": true, \"yay-git\": true}, cloned)\n}\n\n// GIVEN 2 aur packages and 1 in repo\n// WHEN defining as specified targets\n// THEN all aur be found and cloned\nfunc TestIntegrationPKGBUILDFull(t *testing.T) {\n\tmockClient := &mockaur.MockAUR{\n\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\treturn []aur.Pkg{{}}, nil\n\t\t},\n\t}\n\n\ttestLogger := text.NewLogger(os.Stdout, os.Stderr, strings.NewReader(\"\"), true, \"test\")\n\ttargets := []string{\"core/linux\", \"aur/yay-bin\", \"yay-git\"}\n\tsearcher := &testDBSearcher{\n\t\tabsPackagesDB: map[string]string{\"linux\": \"core\"},\n\t}\n\n\tfetched, err := PKGBUILDs(searcher, mockClient, &http.Client{}, testLogger.Child(\"test\"),\n\t\ttargets, \"https://aur.archlinux.org\", parser.ModeAny)\n\n\tassert.NoError(t, err)\n\n\tfor _, target := range targets {\n\t\tassert.Contains(t, fetched, target)\n\t\tassert.NotEmpty(t, fetched[target])\n\t}\n}\n"
  },
  {
    "path": "pkg/download/unified_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage download\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"gopkg.in/h2non/gock.v1\"\n\n\t\"github.com/Jguer/aur\"\n\n\tmockaur \"github.com/Jguer/yay/v12/pkg/dep/mock\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\nfunc newTestLogger() *text.Logger {\n\treturn text.NewLogger(io.Discard, io.Discard, strings.NewReader(\"\"), true, \"test\")\n}\n\n// GIVEN 2 aur packages and 1 in repo\n// GIVEN package in repo is already present\n// WHEN defining package db as a target\n// THEN all should be found and cloned, except the repo one\nfunc TestPKGBUILDReposDefinedDBPull(t *testing.T) {\n\tt.Parallel()\n\tdir := t.TempDir()\n\n\tmockClient := &mockaur.MockAUR{\n\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\treturn []aur.Pkg{{}}, nil // fakes a package found for all\n\t\t},\n\t}\n\n\ttestLogger := text.NewLogger(os.Stdout, os.Stderr, strings.NewReader(\"\"), true, \"test\")\n\n\tos.MkdirAll(filepath.Join(dir, \"yay\", \".git\"), 0o777)\n\n\ttargets := []string{\"core/yay\", \"yay-bin\", \"yay-git\"}\n\tcmdRunner := &testRunner{}\n\tcmdBuilder := &testGitBuilder{\n\t\tindex: 0,\n\t\ttest:  t,\n\t\tparentBuilder: &exe.CmdBuilder{\n\t\t\tRunner:   cmdRunner,\n\t\t\tGitBin:   \"/usr/local/bin/git\",\n\t\t\tGitFlags: []string{},\n\t\t\tLog:      testLogger,\n\t\t},\n\t}\n\tsearcher := &testDBSearcher{\n\t\tabsPackagesDB: map[string]string{\"yay\": \"core\"},\n\t}\n\tcloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,\n\t\tcmdBuilder, newTestLogger(),\n\t\ttargets, parser.ModeAny, \"https://aur.archlinux.org\", dir, false)\n\n\tassert.NoError(t, err)\n\tassert.EqualValues(t, map[string]bool{\"core/yay\": false, \"yay-bin\": true, \"yay-git\": true}, cloned)\n}\n\n// GIVEN 2 aur packages and 1 in repo\n// WHEN defining package db as a target\n// THEN all should be found and cloned\nfunc TestPKGBUILDReposDefinedDBClone(t *testing.T) {\n\tt.Parallel()\n\tdir := t.TempDir()\n\n\tmockClient := &mockaur.MockAUR{\n\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\treturn []aur.Pkg{{}}, nil // fakes a package found for all\n\t\t},\n\t}\n\ttargets := []string{\"core/yay\", \"yay-bin\", \"yay-git\"}\n\tcmdRunner := &testRunner{}\n\tcmdBuilder := &testGitBuilder{\n\t\tindex: 0,\n\t\ttest:  t,\n\t\tparentBuilder: &exe.CmdBuilder{\n\t\t\tRunner:   cmdRunner,\n\t\t\tGitBin:   \"/usr/local/bin/git\",\n\t\t\tGitFlags: []string{},\n\t\t},\n\t}\n\tsearcher := &testDBSearcher{\n\t\tabsPackagesDB: map[string]string{\"yay\": \"core\"},\n\t}\n\tcloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,\n\t\tcmdBuilder, newTestLogger(),\n\t\ttargets, parser.ModeAny, \"https://aur.archlinux.org\", dir, false)\n\n\tassert.NoError(t, err)\n\tassert.EqualValues(t, map[string]bool{\"core/yay\": true, \"yay-bin\": true, \"yay-git\": true}, cloned)\n}\n\n// GIVEN 2 aur packages and 1 in repo\n// WHEN defining as non specified targets\n// THEN all should be found and cloned\nfunc TestPKGBUILDReposClone(t *testing.T) {\n\tt.Parallel()\n\tdir := t.TempDir()\n\n\tmockClient := &mockaur.MockAUR{\n\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\treturn []aur.Pkg{{}}, nil // fakes a package found for all\n\t\t},\n\t}\n\ttargets := []string{\"yay\", \"yay-bin\", \"yay-git\"}\n\tcmdRunner := &testRunner{}\n\tcmdBuilder := &testGitBuilder{\n\t\tindex: 0,\n\t\ttest:  t,\n\t\tparentBuilder: &exe.CmdBuilder{\n\t\t\tRunner:   cmdRunner,\n\t\t\tGitBin:   \"/usr/local/bin/git\",\n\t\t\tGitFlags: []string{},\n\t\t},\n\t}\n\tsearcher := &testDBSearcher{\n\t\tabsPackagesDB: map[string]string{\"yay\": \"core\"},\n\t}\n\tcloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,\n\t\tcmdBuilder, newTestLogger(),\n\t\ttargets, parser.ModeAny, \"https://aur.archlinux.org\", dir, false)\n\n\tassert.NoError(t, err)\n\tassert.EqualValues(t, map[string]bool{\"yay\": true, \"yay-bin\": true, \"yay-git\": true}, cloned)\n}\n\n// GIVEN 2 aur packages and 1 in repo but wrong db\n// WHEN defining as non specified targets\n// THEN all aur be found and cloned\nfunc TestPKGBUILDReposNotFound(t *testing.T) {\n\tt.Parallel()\n\tdir := t.TempDir()\n\n\tmockClient := &mockaur.MockAUR{\n\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\treturn []aur.Pkg{{}}, nil // fakes a package found for all\n\t\t},\n\t}\n\ttargets := []string{\"extra/yay\", \"yay-bin\", \"yay-git\"}\n\tcmdRunner := &testRunner{}\n\tcmdBuilder := &testGitBuilder{\n\t\tindex: 0,\n\t\ttest:  t,\n\t\tparentBuilder: &exe.CmdBuilder{\n\t\t\tRunner:   cmdRunner,\n\t\t\tGitBin:   \"/usr/local/bin/git\",\n\t\t\tGitFlags: []string{},\n\t\t},\n\t}\n\tsearcher := &testDBSearcher{\n\t\tabsPackagesDB: map[string]string{\"yay\": \"core\"},\n\t}\n\tcloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,\n\t\tcmdBuilder, newTestLogger(),\n\t\ttargets, parser.ModeAny, \"https://aur.archlinux.org\", dir, false)\n\n\tassert.NoError(t, err)\n\tassert.EqualValues(t, map[string]bool{\"yay-bin\": true, \"yay-git\": true}, cloned)\n}\n\n// GIVEN 2 aur packages and 1 in repo\n// WHEN defining as non specified targets in repo mode\n// THEN only repo should be cloned\nfunc TestPKGBUILDReposRepoMode(t *testing.T) {\n\tt.Parallel()\n\tdir := t.TempDir()\n\n\tmockClient := &mockaur.MockAUR{\n\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\treturn []aur.Pkg{}, nil // fakes a package found for all\n\t\t},\n\t}\n\ttargets := []string{\"yay\", \"yay-bin\", \"yay-git\"}\n\tcmdRunner := &testRunner{}\n\tcmdBuilder := &testGitBuilder{\n\t\tindex: 0,\n\t\ttest:  t,\n\t\tparentBuilder: &exe.CmdBuilder{\n\t\t\tRunner:   cmdRunner,\n\t\t\tGitBin:   \"/usr/local/bin/git\",\n\t\t\tGitFlags: []string{},\n\t\t},\n\t}\n\tsearcher := &testDBSearcher{\n\t\tabsPackagesDB: map[string]string{\"yay\": \"core\"},\n\t}\n\tcloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,\n\t\tcmdBuilder, newTestLogger(),\n\t\ttargets, parser.ModeRepo, \"https://aur.archlinux.org\", dir, false)\n\n\tassert.NoError(t, err)\n\tassert.EqualValues(t, map[string]bool{\"yay\": true}, cloned)\n}\n\n// GIVEN 2 aur packages and 1 in repo\n// WHEN defining as specified targets\n// THEN all aur be found and cloned\nfunc TestPKGBUILDFull(t *testing.T) {\n\tt.Parallel()\n\n\tmockClient := &mockaur.MockAUR{\n\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\treturn []aur.Pkg{{}}, nil\n\t\t},\n\t}\n\tgock.New(\"https://aur.archlinux.org\").\n\t\tGet(\"/cgit/aur.git/plain/PKGBUILD\").MatchParam(\"h\", \"yay-git\").\n\t\tReply(200).\n\t\tBodyString(\"example_yay-git\")\n\tgock.New(\"https://aur.archlinux.org\").\n\t\tGet(\"/cgit/aur.git/plain/PKGBUILD\").MatchParam(\"h\", \"yay-bin\").\n\t\tReply(200).\n\t\tBodyString(\"example_yay-bin\")\n\n\tgock.New(\"https://gitlab.archlinux.org/\").\n\t\tGet(\"archlinux/packaging/packages/yay/-/raw/main/PKGBUILD\").\n\t\tReply(200).\n\t\tBodyString(\"example_yay\")\n\n\tdefer gock.Off()\n\ttargets := []string{\"core/yay\", \"aur/yay-bin\", \"yay-git\"}\n\tsearcher := &testDBSearcher{\n\t\tabsPackagesDB: map[string]string{\"yay\": \"core\"},\n\t}\n\n\tfetched, err := PKGBUILDs(searcher, mockClient, &http.Client{}, newTestLogger(),\n\t\ttargets, \"https://aur.archlinux.org\", parser.ModeAny)\n\n\tassert.NoError(t, err)\n\tassert.EqualValues(t, map[string][]byte{\n\t\t\"core/yay\":    []byte(\"example_yay\"),\n\t\t\"aur/yay-bin\": []byte(\"example_yay-bin\"),\n\t\t\"yay-git\":     []byte(\"example_yay-git\"),\n\t}, fetched)\n}\n\n// GIVEN 2 aur packages and 1 in repo\n// WHEN aur packages are not found\n// only repo should be cloned\nfunc TestPKGBUILDReposMissingAUR(t *testing.T) {\n\tt.Parallel()\n\tdir := t.TempDir()\n\n\tmockClient := &mockaur.MockAUR{\n\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\treturn []aur.Pkg{}, nil // fakes a package found for all\n\t\t},\n\t}\n\ttargets := []string{\"core/yay\", \"aur/yay-bin\", \"aur/yay-git\"}\n\tcmdRunner := &testRunner{}\n\tcmdBuilder := &testGitBuilder{\n\t\tindex: 0,\n\t\ttest:  t,\n\t\tparentBuilder: &exe.CmdBuilder{\n\t\t\tRunner:   cmdRunner,\n\t\t\tGitBin:   \"/usr/local/bin/git\",\n\t\t\tGitFlags: []string{},\n\t\t},\n\t}\n\tsearcher := &testDBSearcher{\n\t\tabsPackagesDB: map[string]string{\"yay\": \"core\"},\n\t}\n\tcloned, err := PKGBUILDRepos(context.Background(), searcher, mockClient,\n\t\tcmdBuilder, newTestLogger(),\n\t\ttargets, parser.ModeAny, \"https://aur.archlinux.org\", dir, false)\n\n\tassert.NoError(t, err)\n\tassert.EqualValues(t, map[string]bool{\"core/yay\": true}, cloned)\n}\n"
  },
  {
    "path": "pkg/download/utils_test.go",
    "content": "package download\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"net/http\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\n\talpm \"github.com/Jguer/dyalpm\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/db/mock\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n)\n\ntype testRunner struct{}\n\nfunc (t *testRunner) Capture(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\treturn \"\", \"\", nil\n}\n\nfunc (t *testRunner) Show(cmd *exec.Cmd) error {\n\treturn nil\n}\n\ntype testGitBuilder struct {\n\tindex         int\n\ttest          *testing.T\n\twant          string\n\tparentBuilder *exe.CmdBuilder\n}\n\nfunc (t *testGitBuilder) BuildGitCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd {\n\tcmd := t.parentBuilder.BuildGitCmd(ctx, dir, extraArgs...)\n\n\tif t.want != \"\" {\n\t\tassert.Equal(t.test, t.want, cmd.String())\n\t}\n\n\treturn cmd\n}\n\nfunc (c *testGitBuilder) Show(cmd *exec.Cmd) error {\n\treturn c.parentBuilder.Show(cmd)\n}\n\nfunc (c *testGitBuilder) Capture(cmd *exec.Cmd) (stdout, stderr string, err error) {\n\treturn c.parentBuilder.Capture(cmd)\n}\n\ntype (\n\ttestDB struct {\n\t\talpm.Database\n\t\tname string\n\t}\n\ttestPackage struct {\n\t\t*mock.Package\n\t\tdb *testDB\n\t}\n\ttestDBSearcher struct {\n\t\tabsPackagesDB map[string]string\n\t}\n\n\ttestClient struct {\n\t\tt       *testing.T\n\t\twantURL string\n\t\tbody    string\n\t\tstatus  int\n\t}\n)\n\nfunc (d *testDB) Name() string {\n\treturn d.name\n}\n\nfunc (p *testPackage) DB() alpm.Database {\n\treturn p.db\n}\n\nfunc (d *testDBSearcher) SyncPackage(name string) db.IPackage {\n\tif v, ok := d.absPackagesDB[name]; ok {\n\t\treturn &testPackage{\n\t\t\tPackage: &mock.Package{\n\t\t\t\tPName: name,\n\t\t\t\tPBase: name,\n\t\t\t},\n\t\t\tdb: &testDB{name: v},\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (d *testDBSearcher) SyncPackageFromDB(name string, db string) db.IPackage {\n\tif v, ok := d.absPackagesDB[name]; ok && v == db {\n\t\treturn &testPackage{\n\t\t\tPackage: &mock.Package{\n\t\t\t\tPName: name,\n\t\t\t\tPBase: name,\n\t\t\t},\n\t\t\tdb: &testDB{name: v},\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (t *testClient) Get(url string) (*http.Response, error) {\n\tassert.Equal(t.t, t.wantURL, url)\n\treturn &http.Response{StatusCode: t.status, Body: io.NopCloser(strings.NewReader(t.body))}, nil\n}\n"
  },
  {
    "path": "pkg/intrange/intrange.go",
    "content": "package intrange\n\nimport (\n\t\"strconv\"\n\t\"strings\"\n\t\"unicode\"\n\n\tmapset \"github.com/deckarep/golang-set/v2\"\n)\n\n// IntRange stores a max and min amount for range.\ntype IntRange struct {\n\tmin int\n\tmax int\n}\n\n// IntRanges is a slice of IntRange.\ntype IntRanges []IntRange\n\nfunc makeIntRange(minVal, maxVal int) IntRange {\n\treturn IntRange{\n\t\tmin: minVal,\n\t\tmax: maxVal,\n\t}\n}\n\n// Get returns true if the argument n is included in the closed range\n// between min and max.\nfunc (r IntRange) Get(n int) bool {\n\treturn n >= r.min && n <= r.max\n}\n\n// Get returns true if the argument n is included in the closed range\n// between min and max of any of the provided IntRanges.\nfunc (rs IntRanges) Get(n int) bool {\n\tfor _, r := range rs {\n\t\tif r.Get(n) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ParseNumberMenu parses input for number menus split by spaces or commas\n// supports individual selection: 1 2 3 4\n// supports range selections: 1-4 10-20\n// supports negation: ^1 ^1-4\n//\n// include and excule holds numbers that should be added and should not be added\n// respectively. other holds anything that can't be parsed as an int. This is\n// intended to allow words inside of number menus. e.g. 'all' 'none' 'abort'\n// of course the implementation is up to the caller, this function mearley parses\n// the input and organizes it.\nfunc ParseNumberMenu(input string) (include, exclude IntRanges,\n\totherInclude, otherExclude mapset.Set[string],\n) {\n\tinclude = make(IntRanges, 0)\n\texclude = make(IntRanges, 0)\n\totherInclude = mapset.NewThreadUnsafeSet[string]()\n\totherExclude = mapset.NewThreadUnsafeSet[string]()\n\n\twords := strings.FieldsFunc(input, func(c rune) bool {\n\t\treturn unicode.IsSpace(c) || c == ','\n\t})\n\n\tfor _, word := range words {\n\t\tvar (\n\t\t\tnum1 int\n\t\t\tnum2 int\n\t\t\terr  error\n\t\t)\n\n\t\tinvert := false\n\t\tother := otherInclude\n\n\t\tif word[0] == '^' {\n\t\t\tinvert = true\n\t\t\tother = otherExclude\n\t\t\tword = word[1:]\n\t\t}\n\n\t\tranges := strings.SplitN(word, \"-\", 2)\n\n\t\tnum1, err = strconv.Atoi(ranges[0])\n\t\tif err != nil {\n\t\t\tother.Add(strings.ToLower(word))\n\t\t\tcontinue\n\t\t}\n\n\t\tif len(ranges) == 2 {\n\t\t\tnum2, err = strconv.Atoi(ranges[1])\n\t\t\tif err != nil {\n\t\t\t\tother.Add(strings.ToLower(word))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\tnum2 = num1\n\t\t}\n\n\t\tmi := min(num1, num2)\n\t\tma := max(num1, num2)\n\n\t\tif !invert {\n\t\t\tinclude = append(include, makeIntRange(mi, ma))\n\t\t} else {\n\t\t\texclude = append(exclude, makeIntRange(mi, ma))\n\t\t}\n\t}\n\n\treturn include, exclude, otherInclude, otherExclude\n}\n"
  },
  {
    "path": "pkg/intrange/intrange_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage intrange\n\nimport (\n\t\"testing\"\n\n\tmapset \"github.com/deckarep/golang-set/v2\"\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestParseNumberMenu(t *testing.T) {\n\tt.Parallel()\n\ttype result struct {\n\t\tInclude      IntRanges\n\t\tExclude      IntRanges\n\t\tOtherInclude mapset.Set[string]\n\t\tOtherExclude mapset.Set[string]\n\t}\n\n\tinputs := []string{\n\t\t\"1 2 3 4 5\",\n\t\t\"1-10 5-15\",\n\t\t\"10-5 90-85\",\n\t\t\"1 ^2 ^10-5 99 ^40-38 ^123 60-62\",\n\t\t\"abort all none\",\n\t\t\"a-b ^a-b ^abort\",\n\t\t\"-9223372036854775809-9223372036854775809\",\n\t\t\"1\\t2   3      4\\t\\t  \\t 5\",\n\t\t\"1 2,3, 4,  5,6 ,7  ,8\",\n\t\t\"\",\n\t\t\"   \\t   \",\n\t\t\"A B C D E\",\n\t}\n\n\texpected := []result{\n\t\t{IntRanges{\n\t\t\tmakeIntRange(1, 1),\n\t\t\tmakeIntRange(2, 2),\n\t\t\tmakeIntRange(3, 3),\n\t\t\tmakeIntRange(4, 4),\n\t\t\tmakeIntRange(5, 5),\n\t\t}, IntRanges{}, mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()},\n\t\t{IntRanges{\n\t\t\tmakeIntRange(1, 10),\n\t\t\tmakeIntRange(5, 15),\n\t\t}, IntRanges{}, mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()},\n\t\t{IntRanges{\n\t\t\tmakeIntRange(5, 10),\n\t\t\tmakeIntRange(85, 90),\n\t\t}, IntRanges{}, mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()},\n\t\t{\n\t\t\tIntRanges{\n\t\t\t\tmakeIntRange(1, 1),\n\t\t\t\tmakeIntRange(99, 99),\n\t\t\t\tmakeIntRange(60, 62),\n\t\t\t},\n\t\t\tIntRanges{\n\t\t\t\tmakeIntRange(2, 2),\n\t\t\t\tmakeIntRange(5, 10),\n\t\t\t\tmakeIntRange(38, 40),\n\t\t\t\tmakeIntRange(123, 123),\n\t\t\t},\n\t\t\tmapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string](),\n\t\t},\n\t\t{IntRanges{}, IntRanges{}, mapset.NewThreadUnsafeSet(\"abort\", \"all\", \"none\"), mapset.NewThreadUnsafeSet[string]()},\n\t\t{IntRanges{}, IntRanges{}, mapset.NewThreadUnsafeSet(\"a-b\"), mapset.NewThreadUnsafeSet(\"abort\", \"a-b\")},\n\t\t{IntRanges{}, IntRanges{}, mapset.NewThreadUnsafeSet(\"-9223372036854775809-9223372036854775809\"), mapset.NewThreadUnsafeSet[string]()},\n\t\t{IntRanges{\n\t\t\tmakeIntRange(1, 1),\n\t\t\tmakeIntRange(2, 2),\n\t\t\tmakeIntRange(3, 3),\n\t\t\tmakeIntRange(4, 4),\n\t\t\tmakeIntRange(5, 5),\n\t\t}, IntRanges{}, mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()},\n\t\t{IntRanges{\n\t\t\tmakeIntRange(1, 1),\n\t\t\tmakeIntRange(2, 2),\n\t\t\tmakeIntRange(3, 3),\n\t\t\tmakeIntRange(4, 4),\n\t\t\tmakeIntRange(5, 5),\n\t\t\tmakeIntRange(6, 6),\n\t\t\tmakeIntRange(7, 7),\n\t\t\tmakeIntRange(8, 8),\n\t\t}, IntRanges{}, mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()},\n\t\t{IntRanges{}, IntRanges{}, mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()},\n\t\t{IntRanges{}, IntRanges{}, mapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()},\n\t\t{IntRanges{}, IntRanges{}, mapset.NewThreadUnsafeSet(\"a\", \"b\", \"c\", \"d\", \"e\"), mapset.NewThreadUnsafeSet[string]()},\n\t}\n\n\tfor n, in := range inputs {\n\t\tres := expected[n]\n\t\tinclude, exclude, otherInclude, otherExclude := ParseNumberMenu(in)\n\n\t\tassert.True(t, intRangesEqual(include, res.Include), \"Test %d Failed: Expected: include=%+v got include=%+v\", n+1, res.Include, include)\n\t\tassert.True(t, intRangesEqual(exclude, res.Exclude), \"Test %d Failed: Expected: exclude=%+v got exclude=%+v\", n+1, res.Exclude, exclude)\n\t\tassert.True(t, otherInclude.Equal(res.OtherInclude), \"Test %d Failed: Expected: otherInclude=%+v got otherInclude=%+v\", n+1, res.OtherInclude, otherInclude)\n\t\tassert.True(t, otherExclude.Equal(res.OtherExclude), \"Test %d Failed: Expected: otherExclude=%+v got otherExclude=%+v\", n+1, res.OtherExclude, otherExclude)\n\t}\n}\n\nfunc TestIntRange_Get(t *testing.T) {\n\tt.Parallel()\n\ttype fields struct {\n\t\tmin int\n\t\tmax int\n\t}\n\ttype args struct {\n\t\tn int\n\t}\n\ttests := []struct {\n\t\tname   string\n\t\tfields fields\n\t\targs   args\n\t\twant   bool\n\t}{\n\t\t{name: \"normal range true\", fields: fields{0, 10}, args: args{5}, want: true},\n\t\t{name: \"normal start range true\", fields: fields{0, 10}, args: args{0}, want: true},\n\t\t{name: \"normal end range true\", fields: fields{0, 10}, args: args{10}, want: true},\n\t\t{name: \"small range true\", fields: fields{1, 1}, args: args{1}, want: true},\n\t\t{name: \"normal start range false\", fields: fields{1, 2}, args: args{0}, want: false},\n\t\t{name: \"normal end range false\", fields: fields{1, 2}, args: args{3}, want: false},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tr := IntRange{\n\t\t\t\tmin: tt.fields.min,\n\t\t\t\tmax: tt.fields.max,\n\t\t\t}\n\t\t\tif got := r.Get(tt.args.n); got != tt.want {\n\t\t\t\tt.Errorf(\"IntRange.Get() = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc intRangesEqual(a, b IntRanges) bool {\n\tif a == nil && b == nil {\n\t\treturn true\n\t}\n\n\tif a == nil || b == nil {\n\t\treturn false\n\t}\n\n\tif len(a) != len(b) {\n\t\treturn false\n\t}\n\n\tfor n := range a {\n\t\tr1 := a[n]\n\t\tr2 := b[n]\n\n\t\tif r1.min != r2.min || r1.max != r2.max {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\nfunc TestIntRanges_Get(t *testing.T) {\n\tt.Parallel()\n\ttype args struct {\n\t\tn int\n\t}\n\ttests := []struct {\n\t\tname string\n\t\trs   IntRanges\n\t\targs args\n\t\twant bool\n\t}{\n\t\t{name: \"normal range true\", rs: IntRanges{{0, 10}}, args: args{5}, want: true},\n\t\t{name: \"normal ranges in between true\", rs: IntRanges{{0, 4}, {5, 10}}, args: args{5}, want: true},\n\t\t{name: \"normal ranges in between false\", rs: IntRanges{{0, 4}, {6, 10}}, args: args{5}, want: false},\n\t\t{name: \"normal start range true\", rs: IntRanges{{0, 10}}, args: args{0}, want: true},\n\t\t{name: \"normal end range true\", rs: IntRanges{{0, 10}}, args: args{10}, want: true},\n\t\t{name: \"small range true\", rs: IntRanges{{1, 1}, {3, 3}}, args: args{1}, want: true},\n\t\t{name: \"normal start range false\", rs: IntRanges{{1, 2}}, args: args{0}, want: false},\n\t\t{name: \"normal end range false\", rs: IntRanges{{1, 2}}, args: args{3}, want: false},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tif got := tt.rs.Get(tt.args.n); got != tt.want {\n\t\t\t\tt.Errorf(\"IntRanges.Get() = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/menus/clean_menu.go",
    "content": "// Clean Build Menu functions\npackage menus\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"os\"\n\n\tmapset \"github.com/deckarep/golang-set/v2\"\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\nfunc anyExistInCache(pkgbuildDirs map[string]string) bool {\n\tfor _, dir := range pkgbuildDirs {\n\t\tif _, err := os.Stat(dir); !os.IsNotExist(err) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\nfunc CleanFn(ctx context.Context, run *runtime.Runtime, w io.Writer,\n\tpkgbuildDirsByBase map[string]string, installed mapset.Set[string],\n) error {\n\tif len(pkgbuildDirsByBase) == 0 {\n\t\treturn nil // no work to do\n\t}\n\n\tif !anyExistInCache(pkgbuildDirsByBase) {\n\t\treturn nil\n\t}\n\n\tskipFunc := func(pkg string) bool {\n\t\tdir := pkgbuildDirsByBase[pkg]\n\t\t// TOFIX: new install engine dir will always exist, check if unclean instead\n\t\tif _, err := os.Stat(dir); os.IsNotExist(err) {\n\t\t\treturn true\n\t\t}\n\n\t\treturn false\n\t}\n\n\tbases := make([]string, 0, len(pkgbuildDirsByBase))\n\tfor pkg := range pkgbuildDirsByBase {\n\t\tbases = append(bases, pkg)\n\t}\n\n\ttoClean, errClean := selectionMenu(run.Logger, pkgbuildDirsByBase, bases, installed,\n\t\tgotext.Get(\"Packages to cleanBuild?\"),\n\t\tsettings.NoConfirm, run.Cfg.AnswerClean, skipFunc)\n\tif errClean != nil {\n\t\treturn errClean\n\t}\n\n\tfor i, base := range toClean {\n\t\tdir := pkgbuildDirsByBase[base]\n\t\trun.Logger.OperationInfoln(gotext.Get(\"Deleting (%d/%d): %s\", i+1, len(toClean), text.Cyan(dir)))\n\n\t\tif err := run.CmdBuilder.Show(run.CmdBuilder.BuildGitCmd(ctx, dir, \"reset\", \"--hard\", \"origin/HEAD\")); err != nil {\n\t\t\trun.Logger.Warnln(gotext.Get(\"Unable to clean:\"), dir)\n\n\t\t\treturn err\n\t\t}\n\n\t\tif err := run.CmdBuilder.Show(run.CmdBuilder.BuildGitCmd(ctx, dir, \"clean\", \"-fdx\")); err != nil {\n\t\t\trun.Logger.Warnln(gotext.Get(\"Unable to clean:\"), dir)\n\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/menus/diff_menu.go",
    "content": "// file dedicated to diff menu\npackage menus\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"strings\"\n\n\tmapset \"github.com/deckarep/golang-set/v2\"\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/multierror\"\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\nconst (\n\tgitEmptyTree   = \"4b825dc642cb6eb9a060e54bf8d69288fbee4904\"\n\tgitDiffRefName = \"AUR_SEEN\"\n)\n\nfunc showPkgbuildDiffs(ctx context.Context, cmdBuilder exe.ICmdBuilder, logger *text.Logger,\n\tpkgbuildDirs map[string]string, bases []string,\n) error {\n\tvar errMulti multierror.MultiError\n\n\tfor _, pkg := range bases {\n\t\tdir := pkgbuildDirs[pkg]\n\n\t\tstart, err := getLastSeenHash(ctx, cmdBuilder, dir)\n\t\tif err != nil {\n\t\t\terrMulti.Add(err)\n\n\t\t\tcontinue\n\t\t}\n\n\t\tif start != gitEmptyTree {\n\t\t\thasDiff, err := gitHasDiff(ctx, cmdBuilder, dir)\n\t\t\tif err != nil {\n\t\t\t\terrMulti.Add(err)\n\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif !hasDiff {\n\t\t\t\tlogger.Warnln(gotext.Get(\"%s: No changes -- skipping\", text.Cyan(pkg)))\n\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\targs := []string{\n\t\t\t\"diff\",\n\t\t\tstart + \"..HEAD@{upstream}\", \"--src-prefix\",\n\t\t\tdir + \"/\", \"--dst-prefix\", dir + \"/\", \"--\", \".\", \":(exclude).SRCINFO\",\n\t\t}\n\t\tif text.UseColor {\n\t\t\targs = append(args, \"--color=always\")\n\t\t} else {\n\t\t\targs = append(args, \"--color=never\")\n\t\t}\n\n\t\t_ = cmdBuilder.Show(cmdBuilder.BuildGitCmd(ctx, dir, args...))\n\t}\n\n\treturn errMulti.Return()\n}\n\n// Check whether or not a diff exists between the last reviewed diff and\n// HEAD@{upstream}.\nfunc gitHasDiff(ctx context.Context, cmdBuilder exe.ICmdBuilder, dir string) (bool, error) {\n\tif gitHasLastSeenRef(ctx, cmdBuilder, dir) {\n\t\tstdout, stderr, err := cmdBuilder.Capture(\n\t\t\tcmdBuilder.BuildGitCmd(ctx, dir, \"rev-parse\", gitDiffRefName, \"HEAD@{upstream}\"))\n\t\tif err != nil {\n\t\t\treturn false, fmt.Errorf(\"%s%w\", stderr, err)\n\t\t}\n\n\t\tlines := strings.Split(stdout, \"\\n\")\n\t\tlastseen := lines[0]\n\t\tupstream := lines[1]\n\n\t\treturn lastseen != upstream, nil\n\t}\n\t// If AUR_SEEN does not exists, we have never reviewed a diff for this package\n\t// and should display it.\n\treturn true, nil\n}\n\n// Return whether or not we have reviewed a diff yet. It checks for the existence of\n// AUR_SEEN in the git ref-list.\nfunc gitHasLastSeenRef(ctx context.Context, cmdBuilder exe.ICmdBuilder, dir string) bool {\n\t_, _, err := cmdBuilder.Capture(\n\t\tcmdBuilder.BuildGitCmd(ctx,\n\t\t\tdir, \"rev-parse\", \"--quiet\", \"--verify\", gitDiffRefName))\n\n\treturn err == nil\n}\n\n// Returns the last reviewed hash. If AUR_SEEN exists it will return this hash.\n// If it does not it will return empty tree as no diff have been reviewed yet.\nfunc getLastSeenHash(ctx context.Context, cmdBuilder exe.ICmdBuilder, dir string) (string, error) {\n\tif gitHasLastSeenRef(ctx, cmdBuilder, dir) {\n\t\tstdout, stderr, err := cmdBuilder.Capture(\n\t\t\tcmdBuilder.BuildGitCmd(ctx,\n\t\t\t\tdir, \"rev-parse\", gitDiffRefName))\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"%s %w\", stderr, err)\n\t\t}\n\n\t\tlines := strings.Split(stdout, \"\\n\")\n\n\t\treturn lines[0], nil\n\t}\n\n\treturn gitEmptyTree, nil\n}\n\n// Update the AUR_SEEN ref to HEAD. We use this ref to determine which diff were\n// reviewed by the user.\nfunc gitUpdateSeenRef(ctx context.Context, cmdBuilder exe.ICmdBuilder, dir string) error {\n\t_, stderr, err := cmdBuilder.Capture(\n\t\tcmdBuilder.BuildGitCmd(ctx,\n\t\t\tdir, \"update-ref\", gitDiffRefName, \"HEAD\"))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%s %w\", stderr, err)\n\t}\n\n\treturn nil\n}\n\nfunc updatePkgbuildSeenRef(ctx context.Context, cmdBuilder exe.ICmdBuilder, pkgbuildDirs map[string]string, bases []string) error {\n\tvar errMulti multierror.MultiError\n\n\tfor _, pkg := range bases {\n\t\tdir := pkgbuildDirs[pkg]\n\t\tif err := gitUpdateSeenRef(ctx, cmdBuilder, dir); err != nil {\n\t\t\terrMulti.Add(err)\n\t\t}\n\t}\n\n\treturn errMulti.Return()\n}\n\nfunc DiffFn(ctx context.Context, run *runtime.Runtime, w io.Writer,\n\tpkgbuildDirsByBase map[string]string, installed mapset.Set[string],\n) error {\n\tif len(pkgbuildDirsByBase) == 0 {\n\t\treturn nil // no work to do\n\t}\n\n\tbases := make([]string, 0, len(pkgbuildDirsByBase))\n\tfor base := range pkgbuildDirsByBase {\n\t\tbases = append(bases, base)\n\t}\n\n\ttoDiff, errMenu := selectionMenu(run.Logger, pkgbuildDirsByBase, bases, installed, gotext.Get(\"Diffs to show?\"),\n\t\tsettings.NoConfirm, run.Cfg.AnswerDiff, nil)\n\tif errMenu != nil || len(toDiff) == 0 {\n\t\treturn errMenu\n\t}\n\n\tif errD := showPkgbuildDiffs(ctx, run.CmdBuilder, run.Logger, pkgbuildDirsByBase, toDiff); errD != nil {\n\t\treturn errD\n\t}\n\n\trun.Logger.Println()\n\n\tif !run.Logger.ContinueTask(gotext.Get(\"Proceed with install?\"), true, false) {\n\t\treturn settings.ErrUserAbort{}\n\t}\n\n\tif errUpd := updatePkgbuildSeenRef(ctx, run.CmdBuilder, pkgbuildDirsByBase, toDiff); errUpd != nil {\n\t\treturn errUpd\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/menus/edit_menu.go",
    "content": "// edit menu\npackage menus\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"io\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\tgosrc \"github.com/Morganamilo/go-srcinfo\"\n\tmapset \"github.com/deckarep/golang-set/v2\"\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\n// Editor returns the preferred system editor.\nfunc editor(log *text.Logger, editorConfig, editorFlags string, noConfirm bool) (editor string, args []string) {\n\tswitch {\n\tcase editorConfig != \"\":\n\t\teditor, err := exec.LookPath(editorConfig)\n\t\tif err != nil {\n\t\t\tlog.Errorln(err)\n\t\t} else {\n\t\t\treturn editor, strings.Fields(editorFlags)\n\t\t}\n\n\t\tfallthrough\n\tcase os.Getenv(\"VISUAL\") != \"\":\n\t\tif editorArgs := strings.Fields(os.Getenv(\"VISUAL\")); len(editorArgs) != 0 {\n\t\t\teditor, err := exec.LookPath(editorArgs[0])\n\t\t\tif err != nil {\n\t\t\t\tlog.Errorln(err)\n\t\t\t} else {\n\t\t\t\treturn editor, editorArgs[1:]\n\t\t\t}\n\t\t}\n\n\t\tfallthrough\n\tcase os.Getenv(\"EDITOR\") != \"\":\n\t\tif editorArgs := strings.Fields(os.Getenv(\"EDITOR\")); len(editorArgs) != 0 {\n\t\t\teditor, err := exec.LookPath(editorArgs[0])\n\t\t\tif err != nil {\n\t\t\t\tlog.Errorln(err)\n\t\t\t} else {\n\t\t\t\treturn editor, editorArgs[1:]\n\t\t\t}\n\t\t}\n\n\t\tfallthrough\n\tdefault:\n\t\tlog.Errorln(\"\\n\", gotext.Get(\"%s is not set\", text.Bold(text.Cyan(\"$EDITOR\"))))\n\t\tlog.Warnln(gotext.Get(\"Add %s or %s to your environment variables\", text.Bold(text.Cyan(\"$EDITOR\")), text.Bold(text.Cyan(\"$VISUAL\"))))\n\n\t\tfor {\n\t\t\tlog.Infoln(gotext.Get(\"Edit PKGBUILD with?\"))\n\n\t\t\teditorInput, err := log.GetInput(\"\", noConfirm)\n\t\t\tif err != nil {\n\t\t\t\tlog.Errorln(err)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\teditorArgs := strings.Fields(editorInput)\n\t\t\tif len(editorArgs) == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\teditor, err := exec.LookPath(editorArgs[0])\n\t\t\tif err != nil {\n\t\t\t\tlog.Errorln(err)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\treturn editor, editorArgs[1:]\n\t\t}\n\t}\n}\n\nfunc editPkgbuilds(log *text.Logger, pkgbuildDirs map[string]string, bases []string, editorConfig,\n\teditorFlags string, srcinfos map[string]*gosrc.Srcinfo, noConfirm bool,\n) error {\n\tpkgbuilds := make([]string, 0, len(bases))\n\n\tfor _, pkg := range bases {\n\t\tdir := pkgbuildDirs[pkg]\n\t\tpkgbuilds = append(pkgbuilds, filepath.Join(dir, \"PKGBUILD\"))\n\n\t\tif srcinfos != nil {\n\t\t\tfor _, splitPkg := range srcinfos[pkg].SplitPackages() {\n\t\t\t\tif splitPkg.Install != \"\" {\n\t\t\t\t\tpkgbuilds = append(pkgbuilds, filepath.Join(dir, splitPkg.Install))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif len(pkgbuilds) > 0 {\n\t\teditor, editorArgs := editor(log, editorConfig, editorFlags, noConfirm)\n\t\teditorArgs = append(editorArgs, pkgbuilds...)\n\t\teditcmd := exec.CommandContext(context.Background(), editor, editorArgs...)\n\t\teditcmd.Stdin, editcmd.Stdout, editcmd.Stderr = os.Stdin, os.Stdout, os.Stderr\n\n\t\tif err := editcmd.Run(); err != nil {\n\t\t\treturn errors.New(gotext.Get(\"editor did not exit successfully, aborting: %s\", err))\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc EditFn(ctx context.Context, run *runtime.Runtime, w io.Writer,\n\tpkgbuildDirsByBase map[string]string, installed mapset.Set[string],\n) error {\n\tif len(pkgbuildDirsByBase) == 0 {\n\t\treturn nil // no work to do\n\t}\n\n\tbases := make([]string, 0, len(pkgbuildDirsByBase))\n\tfor pkg := range pkgbuildDirsByBase {\n\t\tbases = append(bases, pkg)\n\t}\n\n\ttoEdit, errMenu := selectionMenu(run.Logger, pkgbuildDirsByBase, bases, installed,\n\t\tgotext.Get(\"PKGBUILDs to edit?\"), settings.NoConfirm, run.Cfg.AnswerEdit, nil)\n\tif errMenu != nil || len(toEdit) == 0 {\n\t\treturn errMenu\n\t}\n\n\t// TOFIX: remove or use srcinfo data\n\tif errEdit := editPkgbuilds(run.Logger, pkgbuildDirsByBase,\n\t\ttoEdit, run.Cfg.Editor, run.Cfg.EditorFlags, nil, settings.NoConfirm); errEdit != nil {\n\t\treturn errEdit\n\t}\n\n\trun.Logger.Println()\n\n\tif !run.Logger.ContinueTask(gotext.Get(\"Proceed with install?\"), true, false) {\n\t\treturn settings.ErrUserAbort{}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/menus/menu.go",
    "content": "package menus\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/intrange\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\n\tmapset \"github.com/deckarep/golang-set/v2\"\n)\n\nfunc pkgbuildNumberMenu(logger *text.Logger, pkgbuildDirs map[string]string,\n\tbases []string, installed mapset.Set[string],\n) {\n\ttoPrint := \"\"\n\n\tfor n, pkgBase := range bases {\n\t\tdir := pkgbuildDirs[pkgBase]\n\t\ttoPrint += fmt.Sprintf(text.Magenta(\"%3d\")+\" %-40s\", len(pkgbuildDirs)-n,\n\t\t\ttext.Bold(pkgBase))\n\n\t\tif installed.Contains(pkgBase) {\n\t\t\ttoPrint += text.Bold(text.Green(gotext.Get(\" (Installed)\")))\n\t\t}\n\n\t\t// TODO: remove or refactor to check if git dir is unclean\n\t\tif _, err := os.Stat(dir); !os.IsNotExist(err) {\n\t\t\ttoPrint += text.Bold(text.Green(gotext.Get(\" (Build Files Exist)\")))\n\t\t}\n\n\t\ttoPrint += \"\\n\"\n\t}\n\n\tlogger.Print(toPrint)\n}\n\nfunc selectionMenu(logger *text.Logger, pkgbuildDirs map[string]string, bases []string, installed mapset.Set[string],\n\tmessage string, noConfirm bool, defaultAnswer string, skipFunc func(string) bool,\n) ([]string, error) {\n\tselected := make([]string, 0)\n\n\tpkgbuildNumberMenu(logger, pkgbuildDirs, bases, installed)\n\n\tlogger.Infoln(message)\n\tlogger.Infoln(gotext.Get(\"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\", text.Cyan(gotext.Get(\"[N]one\"))))\n\n\tselectInput, err := logger.GetInput(defaultAnswer, noConfirm)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\teInclude, eExclude, eOtherInclude, eOtherExclude := intrange.ParseNumberMenu(selectInput)\n\teIsInclude := len(eExclude) == 0 && eOtherExclude.Cardinality() == 0\n\n\tif eOtherInclude.Contains(\"abort\") || eOtherInclude.Contains(\"ab\") {\n\t\treturn nil, settings.ErrUserAbort{}\n\t}\n\n\tif eOtherInclude.Contains(\"n\") || eOtherInclude.Contains(\"none\") {\n\t\treturn selected, nil\n\t}\n\n\tfor i, pkgBase := range bases {\n\t\tif skipFunc != nil && skipFunc(pkgBase) {\n\t\t\tcontinue\n\t\t}\n\n\t\tanyInstalled := installed.Contains(pkgBase)\n\n\t\tif !eIsInclude && eExclude.Get(len(bases)-i) {\n\t\t\tcontinue\n\t\t}\n\n\t\tif anyInstalled && (eOtherInclude.Contains(\"i\") || eOtherInclude.Contains(\"installed\")) {\n\t\t\tselected = append(selected, pkgBase)\n\t\t\tcontinue\n\t\t}\n\n\t\tif !anyInstalled && (eOtherInclude.Contains(\"no\") || eOtherInclude.Contains(\"notinstalled\")) {\n\t\t\tselected = append(selected, pkgBase)\n\t\t\tcontinue\n\t\t}\n\n\t\tif eOtherInclude.Contains(\"a\") || eOtherInclude.Contains(\"all\") {\n\t\t\tselected = append(selected, pkgBase)\n\t\t\tcontinue\n\t\t}\n\n\t\tif eIsInclude && (eInclude.Get(len(bases)-i) || eOtherInclude.Contains(pkgBase)) {\n\t\t\tselected = append(selected, pkgBase)\n\t\t}\n\n\t\tif !eIsInclude && (!eExclude.Get(len(bases)-i) && !eOtherExclude.Contains(pkgBase)) {\n\t\t\tselected = append(selected, pkgBase)\n\t\t}\n\t}\n\n\treturn selected, nil\n}\n"
  },
  {
    "path": "pkg/multierror/multierror.go",
    "content": "package multierror\n\nimport \"sync\"\n\n// MultiError type handles error accumulation from goroutines.\ntype MultiError struct {\n\tErrors []error\n\tmux    sync.Mutex\n}\n\n// Error turns the MultiError structure into a string.\nfunc (err *MultiError) Error() string {\n\tstr := \"\"\n\n\tfor _, e := range err.Errors {\n\t\tstr += e.Error() + \"\\n\"\n\t}\n\n\treturn str[:len(str)-1]\n}\n\n// Add adds an error to the Multierror structure.\nfunc (err *MultiError) Add(e error) {\n\tif e == nil {\n\t\treturn\n\t}\n\n\terr.mux.Lock()\n\terr.Errors = append(err.Errors, e)\n\terr.mux.Unlock()\n}\n\n// Return is used as a wrapper on return on whether to return the\n// MultiError Structure if errors exist or nil instead of delivering an empty structure.\nfunc (err *MultiError) Return() error {\n\tif len(err.Errors) > 0 {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/news/.snapshots/TestPrintNewsFeed-all-quiet",
    "content": "\u001b[1m\u001b[35m2019-12-20\u001b[0m\u001b[0m \u001b[1mXorg cleanup requires manual intervention\u001b[0m\n\u001b[1m\u001b[35m2020-01-04\u001b[0m\u001b[0m \u001b[1mNow using Zstandard instead of xz for package compression\u001b[0m\n\u001b[1m\u001b[35m2020-01-15\u001b[0m\u001b[0m \u001b[1mrsync compatibility\u001b[0m\n\u001b[1m\u001b[35m2020-02-17\u001b[0m\u001b[0m \u001b[1msshd needs restarting after upgrading to openssh-8.2p1\u001b[0m\n\u001b[1m\u001b[35m2020-02-22\u001b[0m\u001b[0m \u001b[1mPlanet Arch Linux migration\u001b[0m\n\u001b[1m\u001b[35m2020-02-24\u001b[0m\u001b[0m \u001b[1mThe Future of the Arch Linux Project Leader\u001b[0m\n\u001b[1m\u001b[35m2020-03-01\u001b[0m\u001b[0m \u001b[1mfirewalld>=0.8.1-2 update requires manual intervention\u001b[0m\n\u001b[1m\u001b[35m2020-03-19\u001b[0m\u001b[0m \u001b[1mhplip 3.20.3-2 update requires manual intervention\u001b[0m\n\u001b[1m\u001b[35m2020-04-13\u001b[0m\u001b[0m \u001b[1mnss>=3.51.1-1 and lib32-nss>=3.51.1-1 updates require manual intervention\u001b[0m\n\u001b[1m\u001b[35m2020-04-14\u001b[0m\u001b[0m \u001b[1mzn_poly 0.9.2-2 update requires manual intervention\u001b[0m\n\n"
  },
  {
    "path": "pkg/news/.snapshots/TestPrintNewsFeed-all-verbose",
    "content": "\u001b[1m\u001b[35m2019-12-20\u001b[0m\u001b[0m \u001b[1mXorg cleanup requires manual intervention\u001b[0m\nIn the process of Xorg cleanup the update requires manual\nintervention when you hit this message:\n\n\u001b[36m:: installing xorgproto (2019.2-2) breaks dependency 'inputproto' required by lib32-libxi\n:: installing xorgproto (2019.2-2) breaks dependency 'dmxproto' required by libdmx\n:: installing xorgproto (2019.2-2) breaks dependency 'xf86dgaproto' required by libxxf86dga\n:: installing xorgproto (2019.2-2) breaks dependency 'xf86miscproto' required by libxxf86misc\n\u001b[0m\nwhen updating, use: \u001b[36mpacman -Rdd libdmx libxxf86dga libxxf86misc && pacman -Syu\u001b[0m to perform the upgrade.\n\u001b[0m\n\u001b[1m\u001b[35m2020-01-04\u001b[0m\u001b[0m \u001b[1mNow using Zstandard instead of xz for package compression\u001b[0m\nAs announced on the mailing list, on Friday, Dec 27 2019, our package compression scheme has changed from xz (.pkg.tar.xz) to zstd (.pkg.tar.zst).\n\nzstd and xz trade blows in their compression ratio. Recompressing all packages to zstd with our options yields a total ~0.8% increase in package size on all of our packages combined, but the decompression time for all packages saw a ~1300% speedup.\n\nWe already have more than 545 zstd-compressed packages in our repositories, and as packages get updated more will keep rolling in. We have not found any user-facing issues as of yet, so things appear to be working.\n\nAs a packager, you will automatically start building .pkg.tar.zst packages if you are using the latest version of devtools (>= 20191227).\nAs an end-user no manual intervention is required, assuming that you have read and followed the news post from late last year.\n\nIf you nevertheless haven't updated libarchive since 2018, all hope is not lost! Binary builds of pacman-static are available from Eli Schwartz' personal repository (or direct link to binary), signed with their Trusted User keys, with which you can perform the update.\n\u001b[0m\n\u001b[1m\u001b[35m2020-01-15\u001b[0m\u001b[0m \u001b[1mrsync compatibility\u001b[0m\nOur \u001b[36mrsync\u001b[0m package was shipped with bundled \u001b[36mzlib\u001b[0m to provide compatibility\nwith the old-style \u001b[36m--compress\u001b[0m option up to version 3.1.0. Version 3.1.1 was\nreleased on 2014-06-22 and is shipped by all major distributions now.\n\nSo we decided to finally drop the bundled library and ship a package with\nsystem \u001b[36mzlib\u001b[0m. This also fixes security issues, actual ones and in future. Go\nand blame those running old versions if you encounter errors with \u001b[36mrsync\n3.1.3-3\u001b[0m.\n\u001b[0m\n\u001b[1m\u001b[35m2020-02-17\u001b[0m\u001b[0m \u001b[1msshd needs restarting after upgrading to openssh-8.2p1\u001b[0m\nAfter upgrading to openssh-8.2p1, the existing SSH daemon will be unable to accept new connections. (See FS#65517.) When upgrading remote hosts, please make sure to restart the SSH daemon using \u001b[36msystemctl restart sshd\u001b[0m right after running \u001b[36mpacman -Syu\u001b[0m. If you are upgrading to openssh-8.2p1-3 or higher, this restart will happen automatically.\n\u001b[0m\n\u001b[1m\u001b[35m2020-02-22\u001b[0m\u001b[0m \u001b[1mPlanet Arch Linux migration\u001b[0m\nThe software behind planet.archlinux.org was implemented in Python 2 and is no longer maintained upstream. This functionality has now been implemented in archlinux.org's archweb backend which is actively maintained but offers a slightly different experience.\n\nThe most notable changes are the offered feeds and the feed location. Archweb only offers an Atom feed which is located at here.\n\u001b[0m\n\u001b[1m\u001b[35m2020-02-24\u001b[0m\u001b[0m \u001b[1mThe Future of the Arch Linux Project Leader\u001b[0m\nHello everyone,\n\nSome of you may know me from the days when I was much more involved in Arch, but most of you probably just know me as a name on the website. I’ve been with Arch for some time, taking the leadership of this beast over from Judd back in 2007. But, as these things often go, my involvement has slid down to minimal levels over time. It’s high time that changes.\n\nArch Linux needs involved leadership to make hard decisions and direct the project where it needs to go. And I am not in a position to do this.\n\nIn a team effort, the Arch Linux staff devised a new process for determining future leaders. From now on, leaders will be elected by the staff for a term length of two years. Details of this new process can be found here\n\nIn the first official vote with Levente Polyak (anthraxx), Gaetan Bisson (vesath), Giancarlo Razzolini (grazzolini), and Sven-Hendrik Haase (svenstaro) as candidates, and through 58 verified votes, a winner was chosen:\n\nLevente Polyak (anthraxx) will be taking over the reins of this ship. Congratulations!\n\nThanks for everything over all these years,\nAaron Griffin (phrakture)\n\u001b[0m\n\u001b[1m\u001b[35m2020-03-01\u001b[0m\u001b[0m \u001b[1mfirewalld>=0.8.1-2 update requires manual intervention\u001b[0m\nThe firewalld package prior to version 0.8.1-2 was missing the compiled python modules. This has been fixed in 0.8.1-2, so the upgrade will need to overwrite the untracked pyc files created. If you get errors like these\n\n\u001b[36mfirewalld: /usr/lib/python3.8/site-packages/firewall/__pycache__/__init__.cpython-38.pyc exists in filesystem\nfirewalld: /usr/lib/python3.8/site-packages/firewall/__pycache__/client.cpython-38.pyc exists in filesystem\nfirewalld: /usr/lib/python3.8/site-packages/firewall/__pycache__/dbus_utils.cpython-38.pyc exists in filesystem\n...many more...\n\u001b[0m\nwhen updating, use\n\n\u001b[36mpacman -Suy --overwrite /usr/lib/python3.8/site-packages/firewall/\\*\n\u001b[0m\nto perform the upgrade.\n\u001b[0m\n\u001b[1m\u001b[35m2020-03-19\u001b[0m\u001b[0m \u001b[1mhplip 3.20.3-2 update requires manual intervention\u001b[0m\nThe hplip package prior to version 3.20.3-2 was missing the compiled\npython modules. This has been fixed in 3.20.3-2, so the upgrade will\nneed to overwrite the untracked pyc files that were created. If you get errors\nsuch as these\n\n\u001b[36mhplip: /usr/share/hplip/base/__pycache__/__init__.cpython-38.pyc exists in filesystem\nhplip: /usr/share/hplip/base/__pycache__/avahi.cpython-38.pyc exists in filesystem\nhplip: /usr/share/hplip/base/__pycache__/codes.cpython-38.pyc exists in filesystem\n...many more...\n\u001b[0m\nwhen updating, use\n\n\u001b[36mpacman -Suy --overwrite /usr/share/hplip/\\*\n\u001b[0m\nto perform the upgrade.\n\u001b[0m\n\u001b[1m\u001b[35m2020-04-13\u001b[0m\u001b[0m \u001b[1mnss>=3.51.1-1 and lib32-nss>=3.51.1-1 updates require manual intervention\u001b[0m\nThe nss and lib32-nss packages prior to version 3.51.1-1 were missing a soname link each. This has been fixed in 3.51.1-1, so the upgrade will need to overwrite the untracked files created by ldconfig. If you get any of these errors\n\n\u001b[36mnss: /usr/lib/p11-kit-trust.so exists in filesystem\nlib32-nss: /usr/lib32/p11-kit-trust.so exists in filesystem\n\u001b[0m\nwhen updating, use\n\n\u001b[36mpacman -Syu --overwrite /usr/lib\\*/p11-kit-trust.so\n\u001b[0m\nto perform the upgrade.\n\u001b[0m\n\u001b[1m\u001b[35m2020-04-14\u001b[0m\u001b[0m \u001b[1mzn_poly 0.9.2-2 update requires manual intervention\u001b[0m\nThe zn_poly package prior to version 0.9.2-2 was missing a soname link.\nThis has been fixed in 0.9.2-2, so the upgrade will need to overwrite the\nuntracked files created by ldconfig. If you get an error\n\n\u001b[36mzn_poly: /usr/lib/libzn_poly-0.9.so  exists in filesystem\n\u001b[0m\nwhen updating, use\n\n\u001b[36mpacman -Syu --overwrite usr/lib/libzn_poly-0.9.so\n\u001b[0m\nto perform the upgrade.\n\u001b[0m\n\n"
  },
  {
    "path": "pkg/news/.snapshots/TestPrintNewsFeed-latest-quiet",
    "content": "\u001b[1m\u001b[35m2020-04-13\u001b[0m\u001b[0m \u001b[1mnss>=3.51.1-1 and lib32-nss>=3.51.1-1 updates require manual intervention\u001b[0m\n\u001b[1m\u001b[35m2020-04-14\u001b[0m\u001b[0m \u001b[1mzn_poly 0.9.2-2 update requires manual intervention\u001b[0m\n\n"
  },
  {
    "path": "pkg/news/.snapshots/TestPrintNewsFeed-latest-quiet-topdown",
    "content": "\u001b[1m\u001b[35m2020-04-14\u001b[0m\u001b[0m \u001b[1mzn_poly 0.9.2-2 update requires manual intervention\u001b[0m\n\u001b[1m\u001b[35m2020-04-13\u001b[0m\u001b[0m \u001b[1mnss>=3.51.1-1 and lib32-nss>=3.51.1-1 updates require manual intervention\u001b[0m\n\n"
  },
  {
    "path": "pkg/news/.snapshots/TestPrintNewsFeedSameDay",
    "content": "\u001b[1m\u001b[35m2020-04-14\u001b[0m\u001b[0m \u001b[1mzn_poly 0.9.2-2 update requires manual intervention\u001b[0m\nThe zn_poly package prior to version 0.9.2-2 was missing a soname link.\u001b[0m\n\n"
  },
  {
    "path": "pkg/news/news.go",
    "content": "package news\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/xml\"\n\t\"html\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\ntype item struct {\n\tTitle       string `xml:\"title\"`\n\tLink        string `xml:\"link\"`\n\tDescription string `xml:\"description\"`\n\tPubDate     string `xml:\"pubDate\"`\n\tCreator     string `xml:\"dc:creator\"`\n}\n\nfunc (item *item) printNews(logger *text.Logger, buildTime time.Time, all, quiet bool) {\n\tvar fd string\n\n\tdate, err := time.Parse(time.RFC1123Z, item.PubDate)\n\n\tif err != nil {\n\t\tlogger.Errorln(err)\n\t} else {\n\t\tfd = text.FormatTime(int(date.Unix()))\n\t\tif !all && !buildTime.IsZero() {\n\t\t\tif buildTime.After(date) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\n\tlogger.Println(text.Bold(text.Magenta(fd)), text.Bold(strings.TrimSpace(item.Title)))\n\n\tif !quiet {\n\t\tdesc := strings.TrimSpace(parseNews(item.Description))\n\t\tlogger.Println(desc)\n\t}\n}\n\ntype channel struct {\n\tTitle         string `xml:\"title\"`\n\tLink          string `xml:\"link\"`\n\tDescription   string `xml:\"description\"`\n\tLanguage      string `xml:\"language\"`\n\tLastbuilddate string `xml:\"lastbuilddate\"`\n\tItems         []item `xml:\"item\"`\n}\n\ntype rss struct {\n\tChannel channel `xml:\"channel\"`\n}\n\nfunc PrintNewsFeed(ctx context.Context, client *http.Client, logger *text.Logger,\n\tcutOffDate time.Time, bottomUp, all, quiet bool,\n) error {\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, \"https://archlinux.org/feeds/news\", http.NoBody)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tresp, err := client.Do(req) // #nosec G704\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tdefer resp.Body.Close()\n\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\trssGot := rss{}\n\n\td := xml.NewDecoder(bytes.NewReader(body))\n\tif err := d.Decode(&rssGot); err != nil {\n\t\treturn err\n\t}\n\n\tif bottomUp {\n\t\tfor i := len(rssGot.Channel.Items) - 1; i >= 0; i-- {\n\t\t\trssGot.Channel.Items[i].printNews(logger, cutOffDate, all, quiet)\n\t\t}\n\t} else {\n\t\tfor i := 0; i < len(rssGot.Channel.Items); i++ {\n\t\t\trssGot.Channel.Items[i].printNews(logger, cutOffDate, all, quiet)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// Crude html parsing, good enough for the arch news\n// This is only displayed in the terminal so there should be no security\n// concerns.\nfunc parseNews(str string) string {\n\tvar (\n\t\tbuffer       bytes.Buffer\n\t\ttagBuffer    bytes.Buffer\n\t\tescapeBuffer bytes.Buffer\n\t\tinTag        = false\n\t\tinEscape     = false\n\t)\n\n\tfor _, char := range str {\n\t\tif inTag {\n\t\t\tif char == '>' {\n\t\t\t\tinTag = false\n\n\t\t\t\tswitch tagBuffer.String() {\n\t\t\t\tcase \"code\":\n\t\t\t\t\tbuffer.WriteString(text.CyanCode)\n\t\t\t\tcase \"/code\":\n\t\t\t\t\tbuffer.WriteString(text.ResetCode)\n\t\t\t\tcase \"/p\":\n\t\t\t\t\tbuffer.WriteRune('\\n')\n\t\t\t\t}\n\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\ttagBuffer.WriteRune(char)\n\n\t\t\tcontinue\n\t\t}\n\n\t\tif inEscape {\n\t\t\tif char == ';' {\n\t\t\t\tinEscape = false\n\n\t\t\t\tescapeBuffer.WriteRune(char)\n\t\t\t\ts := html.UnescapeString(escapeBuffer.String())\n\t\t\t\tbuffer.WriteString(s)\n\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tescapeBuffer.WriteRune(char)\n\n\t\t\tcontinue\n\t\t}\n\n\t\tif char == '<' {\n\t\t\tinTag = true\n\n\t\t\ttagBuffer.Reset()\n\n\t\t\tcontinue\n\t\t}\n\n\t\tif char == '&' {\n\t\t\tinEscape = true\n\n\t\t\tescapeBuffer.Reset()\n\t\t\tescapeBuffer.WriteRune(char)\n\n\t\t\tcontinue\n\t\t}\n\n\t\tbuffer.WriteRune(char)\n\t}\n\n\tbuffer.WriteString(text.ResetCode)\n\n\treturn buffer.String()\n}\n"
  },
  {
    "path": "pkg/news/news_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage news\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/bradleyjkemp/cupaloy\"\n\t\"github.com/stretchr/testify/assert\"\n\t\"gopkg.in/h2non/gock.v1\"\n\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\nconst lastNews = `\n<rss xmlns:atom=\"http://www.w3.org/2005/Atom\" version=\"2.0\">\n   <channel>\n      <title>Arch Linux: Recent news updates</title>\n      <link>https://www.archlinux.org/news/</link>\n      <description>The latest and greatest news from the Arch Linux distribution.</description>\n      <atom:link href=\"https://www.archlinux.org/feeds/news/\" rel=\"self\" />\n      <language>en-us</language>\n      <lastBuildDate>Tue, 14 Apr 2020 16:30:32 +0000</lastBuildDate>\n      <item>\n         <title>zn_poly 0.9.2-2 update requires manual intervention</title>\n         <link>https://www.archlinux.org/news/zn_poly-092-2-update-requires-manual-intervention/</link>\n         <description>&lt;p&gt;The zn_poly package prior to version 0.9.2-2 was missing a soname link.</description>\n         <dc:creator xmlns:dc=\"http://purl.org/dc/elements/1.1/\">Antonio Rojas</dc:creator>\n         <pubDate>Tue, 14 Apr 2020 16:30:30 +0000</pubDate>\n         <guid isPermaLink=\"false\">tag:www.archlinux.org,2020-04-14:/news/zn_poly-092-2-update-requires-manual-intervention/</guid>\n      </item>\n   </channel>\n</rss>\n`\n\nconst sampleNews = `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\"><channel><title>Arch Linux: Recent news updates</title><link>https://www.archlinux.org/news/</link><description>The latest and greatest news from the Arch Linux distribution.</description><atom:link href=\"https://www.archlinux.org/feeds/news/\" rel=\"self\"></atom:link><language>en-us</language><lastBuildDate>Tue, 14 Apr 2020 16:30:32 +0000</lastBuildDate><item><title>zn_poly 0.9.2-2 update requires manual intervention</title><link>https://www.archlinux.org/news/zn_poly-092-2-update-requires-manual-intervention/</link><description>&lt;p&gt;The zn_poly package prior to version 0.9.2-2 was missing a soname link.\nThis has been fixed in 0.9.2-2, so the upgrade will need to overwrite the\nuntracked files created by ldconfig. If you get an error&lt;/p&gt;\n&lt;pre&gt;&lt;code&gt;zn_poly: /usr/lib/libzn_poly-0.9.so  exists in filesystem\n&lt;/code&gt;&lt;/pre&gt;\n&lt;p&gt;when updating, use&lt;/p&gt;\n&lt;pre&gt;&lt;code&gt;pacman -Syu --overwrite usr/lib/libzn_poly-0.9.so\n&lt;/code&gt;&lt;/pre&gt;\n&lt;p&gt;to perform the upgrade.&lt;/p&gt;</description><dc:creator xmlns:dc=\"http://purl.org/dc/elements/1.1/\">Antonio Rojas</dc:creator><pubDate>Tue, 14 Apr 2020 16:30:30 +0000</pubDate><guid isPermaLink=\"false\">tag:www.archlinux.org,2020-04-14:/news/zn_poly-092-2-update-requires-manual-intervention/</guid></item><item><title>nss&gt;=3.51.1-1 and lib32-nss&gt;=3.51.1-1 updates require manual intervention</title><link>https://www.archlinux.org/news/nss3511-1-and-lib32-nss3511-1-updates-require-manual-intervention/</link><description>&lt;p&gt;The nss and lib32-nss packages prior to version 3.51.1-1 were missing a soname link each. This has been fixed in 3.51.1-1, so the upgrade will need to overwrite the untracked files created by ldconfig. If you get any of these errors&lt;/p&gt;\n&lt;pre&gt;&lt;code&gt;nss: /usr/lib/p11-kit-trust.so exists in filesystem\nlib32-nss: /usr/lib32/p11-kit-trust.so exists in filesystem\n&lt;/code&gt;&lt;/pre&gt;\n&lt;p&gt;when updating, use&lt;/p&gt;\n&lt;pre&gt;&lt;code&gt;pacman -Syu --overwrite /usr/lib\\*/p11-kit-trust.so\n&lt;/code&gt;&lt;/pre&gt;\n&lt;p&gt;to perform the upgrade.&lt;/p&gt;</description><dc:creator xmlns:dc=\"http://purl.org/dc/elements/1.1/\">Jan Alexander Steffens</dc:creator><pubDate>Mon, 13 Apr 2020 00:35:58 +0000</pubDate><guid isPermaLink=\"false\">tag:www.archlinux.org,2020-04-13:/news/nss3511-1-and-lib32-nss3511-1-updates-require-manual-intervention/</guid></item><item><title>hplip 3.20.3-2 update requires manual intervention</title><link>https://www.archlinux.org/news/hplip-3203-2-update-requires-manual-intervention/</link><description>&lt;p&gt;The hplip package prior to version 3.20.3-2 was missing the compiled\npython modules. This has been fixed in 3.20.3-2, so the upgrade will\nneed to overwrite the untracked pyc files that were created. If you get errors\nsuch as these&lt;/p&gt;\n&lt;pre&gt;&lt;code&gt;hplip: /usr/share/hplip/base/__pycache__/__init__.cpython-38.pyc exists in filesystem\nhplip: /usr/share/hplip/base/__pycache__/avahi.cpython-38.pyc exists in filesystem\nhplip: /usr/share/hplip/base/__pycache__/codes.cpython-38.pyc exists in filesystem\n...many more...\n&lt;/code&gt;&lt;/pre&gt;\n&lt;p&gt;when updating, use&lt;/p&gt;\n&lt;pre&gt;&lt;code&gt;pacman -Suy --overwrite /usr/share/hplip/\\*\n&lt;/code&gt;&lt;/pre&gt;\n&lt;p&gt;to perform the upgrade.&lt;/p&gt;</description><dc:creator xmlns:dc=\"http://purl.org/dc/elements/1.1/\">Andreas Radke</dc:creator><pubDate>Thu, 19 Mar 2020 06:53:30 +0000</pubDate><guid isPermaLink=\"false\">tag:www.archlinux.org,2020-03-19:/news/hplip-3203-2-update-requires-manual-intervention/</guid></item><item><title>firewalld&gt;=0.8.1-2 update requires manual intervention</title><link>https://www.archlinux.org/news/firewalld081-2-update-requires-manual-intervention/</link><description>&lt;p&gt;The firewalld package prior to version 0.8.1-2 was missing the compiled python modules. This has been fixed in 0.8.1-2, so the upgrade will need to overwrite the untracked pyc files created. If you get errors like these&lt;/p&gt;\n&lt;pre&gt;&lt;code&gt;firewalld: /usr/lib/python3.8/site-packages/firewall/__pycache__/__init__.cpython-38.pyc exists in filesystem\nfirewalld: /usr/lib/python3.8/site-packages/firewall/__pycache__/client.cpython-38.pyc exists in filesystem\nfirewalld: /usr/lib/python3.8/site-packages/firewall/__pycache__/dbus_utils.cpython-38.pyc exists in filesystem\n...many more...\n&lt;/code&gt;&lt;/pre&gt;\n&lt;p&gt;when updating, use&lt;/p&gt;\n&lt;pre&gt;&lt;code&gt;pacman -Suy --overwrite /usr/lib/python3.8/site-packages/firewall/\\*\n&lt;/code&gt;&lt;/pre&gt;\n&lt;p&gt;to perform the upgrade.&lt;/p&gt;</description><dc:creator xmlns:dc=\"http://purl.org/dc/elements/1.1/\">Jan Alexander Steffens</dc:creator><pubDate>Sun, 01 Mar 2020 16:36:48 +0000</pubDate><guid isPermaLink=\"false\">tag:www.archlinux.org,2020-03-01:/news/firewalld081-2-update-requires-manual-intervention/</guid></item><item><title>The Future of the Arch Linux Project Leader</title><link>https://www.archlinux.org/news/the-future-of-the-arch-linux-project-leader/</link><description>&lt;p&gt;Hello everyone,&lt;/p&gt;\n&lt;p&gt;Some of you may know me from the days when I was much more involved in Arch, but most of you probably just know me as a name on the website. I’ve been with Arch for some time, taking the leadership of this beast over from Judd back in 2007. But, as these things often go, my involvement has slid down to minimal levels over time. It’s high time that changes.&lt;/p&gt;\n&lt;p&gt;Arch Linux needs involved leadership to make hard decisions and direct the project where it needs to go. And I am not in a position to do this.&lt;/p&gt;\n&lt;p&gt;In a team effort, the Arch Linux staff devised a new process for determining future leaders. From now on, leaders will be elected by the staff for a term length of two years. Details of this new process can be found &lt;a href=\"https://wiki.archlinux.org/index.php/DeveloperWiki:Project_Leader\"&gt;here&lt;/a&gt;&lt;/p&gt;\n&lt;p&gt;In the first official vote with Levente Polyak (anthraxx), Gaetan Bisson (vesath), Giancarlo Razzolini (grazzolini), and Sven-Hendrik Haase (svenstaro) as candidates, and through 58 verified votes, a winner was chosen:&lt;/p&gt;\n&lt;p&gt;&lt;strong&gt;Levente Polyak (anthraxx) will be taking over the reins of this ship. Congratulations!&lt;/strong&gt;&lt;/p&gt;\n&lt;p&gt;&lt;em&gt;Thanks for everything over all these years,&lt;br /&gt;\nAaron Griffin (phrakture)&lt;/em&gt;&lt;/p&gt;</description><dc:creator xmlns:dc=\"http://purl.org/dc/elements/1.1/\">Aaron Griffin</dc:creator><pubDate>Mon, 24 Feb 2020 15:56:28 +0000</pubDate><guid isPermaLink=\"false\">tag:www.archlinux.org,2020-02-24:/news/the-future-of-the-arch-linux-project-leader/</guid></item><item><title>Planet Arch Linux migration</title><link>https://www.archlinux.org/news/planet-arch-linux-migration/</link><description>&lt;p&gt;The software behind planet.archlinux.org was implemented in Python 2 and is no longer maintained upstream. This functionality has now been implemented in archlinux.org's archweb backend which is actively maintained but offers a slightly different experience.&lt;/p&gt;\n&lt;p&gt;The most notable changes are the offered feeds and the feed location. Archweb only offers an Atom feed which is located at &lt;a href=\"https://archlinux.org/feeds/planet\"&gt;here&lt;/a&gt;.&lt;/p&gt;</description><dc:creator xmlns:dc=\"http://purl.org/dc/elements/1.1/\">Jelle van der Waa</dc:creator><pubDate>Sat, 22 Feb 2020 22:43:00 +0000</pubDate><guid isPermaLink=\"false\">tag:www.archlinux.org,2020-02-22:/news/planet-arch-linux-migration/</guid></item><item><title>sshd needs restarting after upgrading to openssh-8.2p1</title><link>https://www.archlinux.org/news/sshd-needs-restarting-after-upgrading-to-openssh-82p1/</link><description>&lt;p&gt;After upgrading to openssh-8.2p1, the existing SSH daemon will be unable to accept new connections. (See &lt;a href=\"https://bugs.archlinux.org/task/65517\"&gt;FS#65517&lt;/a&gt;.) When upgrading remote hosts, please make sure to restart the SSH daemon using &lt;code&gt;systemctl restart sshd&lt;/code&gt; right after running &lt;code&gt;pacman -Syu&lt;/code&gt;. If you are upgrading to openssh-8.2p1-3 or higher, this restart will happen automatically.&lt;/p&gt;</description><dc:creator xmlns:dc=\"http://purl.org/dc/elements/1.1/\">Gaetan Bisson</dc:creator><pubDate>Mon, 17 Feb 2020 01:35:04 +0000</pubDate><guid isPermaLink=\"false\">tag:www.archlinux.org,2020-02-17:/news/sshd-needs-restarting-after-upgrading-to-openssh-82p1/</guid></item><item><title>rsync compatibility</title><link>https://www.archlinux.org/news/rsync-compatibility/</link><description>&lt;p&gt;Our &lt;code&gt;rsync&lt;/code&gt; package was shipped with bundled &lt;code&gt;zlib&lt;/code&gt; to provide compatibility\nwith the old-style &lt;code&gt;--compress&lt;/code&gt; option up to version 3.1.0. Version 3.1.1 was\nreleased on 2014-06-22 and is shipped by all major distributions now.&lt;/p&gt;\n&lt;p&gt;So we decided to finally drop the bundled library and ship a package with\nsystem &lt;code&gt;zlib&lt;/code&gt;. This also fixes security issues, actual ones and in future. Go\nand blame those running old versions if you encounter errors with &lt;code&gt;rsync\n3.1.3-3&lt;/code&gt;.&lt;/p&gt;</description><dc:creator xmlns:dc=\"http://purl.org/dc/elements/1.1/\">Christian Hesse</dc:creator><pubDate>Wed, 15 Jan 2020 20:14:43 +0000</pubDate><guid isPermaLink=\"false\">tag:www.archlinux.org,2020-01-15:/news/rsync-compatibility/</guid></item><item><title>Now using Zstandard instead of xz for package compression</title><link>https://www.archlinux.org/news/now-using-zstandard-instead-of-xz-for-package-compression/</link><description>&lt;p&gt;As announced on the &lt;a href=\"https://lists.archlinux.org/pipermail/arch-dev-public/2019-December/029752.html\"&gt;mailing list&lt;/a&gt;, on Friday, Dec 27 2019, our package compression scheme has changed from xz (.pkg.tar.xz) to &lt;a href=\"https://lists.archlinux.org/pipermail/arch-dev-public/2019-December/029778.html\"&gt;zstd (.pkg.tar.zst)&lt;/a&gt;.&lt;/p&gt;\n&lt;p&gt;zstd and xz trade blows in their compression ratio. Recompressing all packages to zstd with our options yields a total ~0.8% increase in package size on all of our packages combined, but the decompression time for all packages saw a ~1300% speedup.&lt;/p&gt;\n&lt;p&gt;We already have more than 545 zstd-compressed packages in our repositories, and as packages get updated more will keep rolling in. We have not found any user-facing issues as of yet, so things appear to be working.&lt;/p&gt;\n&lt;p&gt;As a packager, you will automatically start building .pkg.tar.zst packages if you are using the latest version of devtools (&amp;gt;= 20191227).&lt;br /&gt;\nAs an end-user no manual intervention is required, assuming that you have read and followed the news post &lt;a href=\"https://www.archlinux.org/news/required-update-to-recent-libarchive/\"&gt;from late last year&lt;/a&gt;.&lt;/p&gt;\n&lt;p&gt;If you nevertheless haven't updated libarchive since 2018, all hope is not lost! Binary builds of pacman-static are available from Eli Schwartz' &lt;a href=\"https://wiki.archlinux.org/index.php/Unofficial_user_repositories#eschwartz\"&gt;personal repository&lt;/a&gt; (or direct link to &lt;a href=\"https://pkgbuild.com/~eschwartz/repo/x86_64-extracted/\"&gt;binary&lt;/a&gt;), signed with their Trusted User keys, with which you can perform the update.&lt;/p&gt;</description><dc:creator xmlns:dc=\"http://purl.org/dc/elements/1.1/\">Robin Broda</dc:creator><pubDate>Sat, 04 Jan 2020 20:35:55 +0000</pubDate><guid isPermaLink=\"false\">tag:www.archlinux.org,2020-01-04:/news/now-using-zstandard-instead-of-xz-for-package-compression/</guid></item><item><title>Xorg cleanup requires manual intervention</title><link>https://www.archlinux.org/news/xorg-cleanup-requires-manual-intervention/</link><description>&lt;p&gt;In the process of &lt;a href=\"https://bugs.archlinux.org/task/64892\"&gt;Xorg cleanup&lt;/a&gt; the update requires manual\nintervention when you hit this message:&lt;/p&gt;\n&lt;pre&gt;&lt;code&gt;:: installing xorgproto (2019.2-2) breaks dependency 'inputproto' required by lib32-libxi\n:: installing xorgproto (2019.2-2) breaks dependency 'dmxproto' required by libdmx\n:: installing xorgproto (2019.2-2) breaks dependency 'xf86dgaproto' required by libxxf86dga\n:: installing xorgproto (2019.2-2) breaks dependency 'xf86miscproto' required by libxxf86misc\n&lt;/code&gt;&lt;/pre&gt;\n&lt;p&gt;when updating, use: &lt;code&gt;pacman -Rdd libdmx libxxf86dga libxxf86misc &amp;amp;&amp;amp; pacman -Syu&lt;/code&gt; to perform the upgrade.&lt;/p&gt;</description><dc:creator xmlns:dc=\"http://purl.org/dc/elements/1.1/\">Andreas Radke</dc:creator><pubDate>Fri, 20 Dec 2019 13:37:40 +0000</pubDate><guid isPermaLink=\"false\">tag:www.archlinux.org,2019-12-20:/news/xorg-cleanup-requires-manual-intervention/</guid></item></channel></rss>\n`\n\nfunc TestPrintNewsFeed(t *testing.T) {\n\tlayout := \"2006-01-02\"\n\tstr := \"2020-04-13\"\n\tlastNewsTime, _ := time.Parse(layout, str)\n\n\ttype args struct {\n\t\tcutOffDate time.Time\n\t\tbottomUp   bool\n\t\tall        bool\n\t\tquiet      bool\n\t}\n\ttests := []struct {\n\t\tname    string\n\t\targs    args\n\t\twantErr bool\n\t}{\n\t\t{name: \"all-verbose\", args: args{bottomUp: true, cutOffDate: time.Now(), all: true, quiet: false}, wantErr: false},\n\t\t{name: \"all-quiet\", args: args{bottomUp: true, cutOffDate: lastNewsTime, all: true, quiet: true}, wantErr: false},\n\t\t{name: \"latest-quiet\", args: args{bottomUp: true, cutOffDate: lastNewsTime, all: false, quiet: true}, wantErr: false},\n\t\t{name: \"latest-quiet-topdown\", args: args{bottomUp: false, cutOffDate: lastNewsTime, all: false, quiet: true}, wantErr: false},\n\t}\n\tt.Setenv(\"TZ\", \"UTC\")\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tgock.New(\"https://archlinux.org\").\n\t\t\t\tGet(\"/feeds/news\").\n\t\t\t\tReply(200).\n\t\t\t\tBodyString(sampleNews)\n\n\t\t\tdefer gock.Off()\n\n\t\t\tr, w, _ := os.Pipe()\n\t\t\tlogger := text.NewLogger(w, w, strings.NewReader(\"\"), false, \"logger\")\n\n\t\t\terr := PrintNewsFeed(context.Background(), &http.Client{}, logger,\n\t\t\t\ttt.args.cutOffDate, tt.args.bottomUp, tt.args.all, tt.args.quiet)\n\t\t\tassert.NoError(t, err)\n\n\t\t\tw.Close()\n\t\t\tout, _ := io.ReadAll(r)\n\t\t\tcupaloy.SnapshotT(t, out)\n\t\t})\n\t}\n}\n\n// GIVEN last build time at 13h00\n// WHEN there's a news posted at 18h00\n// THEN it should still be printed\nfunc TestPrintNewsFeedSameDay(t *testing.T) {\n\tstr := \"2020-04-14T13:04:05Z\"\n\tlastNewsTime, _ := time.Parse(time.RFC3339, str)\n\n\tgock.New(\"https://archlinux.org\").\n\t\tGet(\"/feeds/news\").\n\t\tReply(200).\n\t\tBodyString(lastNews)\n\n\tdefer gock.Off()\n\n\tr, w, _ := os.Pipe()\n\tlogger := text.NewLogger(w, w, strings.NewReader(\"\"), false, \"logger\")\n\n\terr := PrintNewsFeed(context.Background(), &http.Client{}, logger,\n\t\tlastNewsTime, true, false, false)\n\tassert.NoError(t, err)\n\n\tw.Close()\n\tout, _ := io.ReadAll(r)\n\tcupaloy.SnapshotT(t, out)\n}\n"
  },
  {
    "path": "pkg/query/aur_warnings.go",
    "content": "package query\n\nimport (\n\t\"strings\"\n\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/aur\"\n\talpm \"github.com/Jguer/dyalpm\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\ntype AURWarnings struct {\n\tOrphans    []string\n\tOutOfDate  []string\n\tMissing    []string\n\tLocalNewer []string\n\n\tlog *text.Logger\n}\n\nfunc NewWarnings(logger *text.Logger) *AURWarnings {\n\treturn &AURWarnings{log: logger}\n}\n\nfunc (warnings *AURWarnings) AddToWarnings(remote map[string]alpm.Package, aurPkg *aur.Pkg) {\n\tname := aurPkg.Name\n\tpkg, ok := remote[name]\n\tif !ok {\n\t\treturn\n\t}\n\n\tif aurPkg.Maintainer == \"\" && !pkg.ShouldIgnore() {\n\t\twarnings.Orphans = append(warnings.Orphans, name)\n\t}\n\n\tif aurPkg.OutOfDate != 0 && !pkg.ShouldIgnore() {\n\t\twarnings.OutOfDate = append(warnings.OutOfDate, name)\n\t}\n\n\tif !pkg.ShouldIgnore() && !isDevelPackage(pkg) && db.VerCmp(pkg.Version(), aurPkg.Version) > 0 {\n\t\tleft, right := GetVersionDiff(pkg.Version(), aurPkg.Version)\n\n\t\tnewerMsg := gotext.Get(\"%s: local (%s) is newer than AUR (%s)\",\n\t\t\ttext.Cyan(name),\n\t\t\tleft, right,\n\t\t)\n\n\t\twarnings.LocalNewer = append(warnings.LocalNewer, newerMsg)\n\t}\n}\n\nfunc (warnings *AURWarnings) CalculateMissing(remoteNames []string,\n\tremote map[string]alpm.Package, aurData map[string]*aur.Pkg,\n) {\n\tfor _, name := range remoteNames {\n\t\tif _, ok := aurData[name]; !ok && !remote[name].ShouldIgnore() {\n\t\t\tif _, ok := aurData[strings.TrimSuffix(name, \"-debug\")]; !ok {\n\t\t\t\twarnings.Missing = append(warnings.Missing, name)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc (warnings *AURWarnings) Print() {\n\tnormalMissing, debugMissing := filterDebugPkgs(warnings.Missing)\n\n\tif len(normalMissing) > 0 {\n\t\twarnings.log.Warnln(gotext.Get(\"Packages not in AUR:\"), formatNames(normalMissing))\n\t}\n\n\tif len(debugMissing) > 0 {\n\t\twarnings.log.Warnln(gotext.Get(\"Missing AUR Debug Packages:\"), formatNames(debugMissing))\n\t}\n\n\tif len(warnings.Orphans) > 0 {\n\t\twarnings.log.Warnln(gotext.Get(\"Orphan (unmaintained) AUR Packages:\"), formatNames(warnings.Orphans))\n\t}\n\n\tif len(warnings.OutOfDate) > 0 {\n\t\twarnings.log.Warnln(gotext.Get(\"Flagged Out Of Date AUR Packages:\"), formatNames(warnings.OutOfDate))\n\t}\n\n\tif len(warnings.LocalNewer) > 0 {\n\t\tfor _, newer := range warnings.LocalNewer {\n\t\t\twarnings.log.Warnln(newer)\n\t\t}\n\t}\n}\n\nfunc filterDebugPkgs(names []string) (normal, debug []string) {\n\tnormal = make([]string, 0, len(names))\n\tdebug = make([]string, 0, len(names))\n\n\tfor _, name := range names {\n\t\tif strings.HasSuffix(name, \"-debug\") {\n\t\t\tdebug = append(debug, name)\n\t\t} else {\n\t\t\tnormal = append(normal, name)\n\t\t}\n\t}\n\n\treturn\n}\n\nfunc formatNames(names []string) string {\n\treturn \" \" + text.Cyan(strings.Join(names, \"  \"))\n}\n"
  },
  {
    "path": "pkg/query/errors.go",
    "content": "package query\n\nimport (\n\t\"github.com/leonelquinteros/gotext\"\n)\n\n// ErrAURSearch means that it was not possible to connect to the AUR.\ntype ErrAURSearch struct {\n\tinner error\n}\n\nfunc (e ErrAURSearch) Error() string {\n\treturn gotext.Get(\"Error during AUR search: %s\\n\", e.inner.Error())\n}\n\n// ErrNoQuery means that query was not executed.\ntype ErrNoQuery struct{}\n\nfunc (e ErrNoQuery) Error() string {\n\treturn gotext.Get(\"no query was executed\")\n}\n\ntype ErrTargetNotFound struct{}\n\nfunc (e ErrTargetNotFound) Error() string {\n\treturn gotext.Get(\"no package found for targets\")\n}\n"
  },
  {
    "path": "pkg/query/filter.go",
    "content": "package query\n\nimport (\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\nfunc RemoveInvalidTargets(logger *text.Logger, targets []string, mode parser.TargetMode) []string {\n\tfilteredTargets := make([]string, 0)\n\n\tfor _, target := range targets {\n\t\tdbName, _ := text.SplitDBFromName(target)\n\n\t\tif dbName == \"aur\" && !mode.AtLeastAUR() {\n\t\t\tlogger.Warnln(gotext.Get(\"%s: can't use target with option --repo -- skipping\", text.Cyan(target)))\n\t\t\tcontinue\n\t\t}\n\n\t\tif dbName != \"aur\" && dbName != \"\" && !mode.AtLeastRepo() {\n\t\t\tlogger.Warnln(gotext.Get(\"%s: can't use target with option --aur -- skipping\", text.Cyan(target)))\n\t\t\tcontinue\n\t\t}\n\n\t\tfilteredTargets = append(filteredTargets, target)\n\t}\n\n\treturn filteredTargets\n}\n"
  },
  {
    "path": "pkg/query/metric.go",
    "content": "package query\n\nimport (\n\t\"strings\"\n\n\t\"github.com/adrg/strutil\"\n)\n\nconst minVotes = 30\nconst minPopularity = 0.5\nconst (\n\tseparateSourceMax = 45.0\n\tseparateSourceMin = 5.0\n)\n\nfunc (a *abstractResults) aurSortByMetric(pkg *abstractResult) float64 {\n\tvotesScore := 1 - (minVotes / (minVotes + float64(pkg.votes)))\n\tif pkg.popularity <= 0 {\n\t\treturn votesScore\n\t}\n\n\tpopularityScore := 1 - (minPopularity / (minPopularity + pkg.popularity))\n\n\treturn (votesScore + popularityScore) / 2\n}\n\nfunc (a *abstractResults) GetMetric(pkg *abstractResult) float64 {\n\tif v, ok := a.distanceCache[pkg.name]; ok {\n\t\treturn v\n\t}\n\n\tif strings.EqualFold(pkg.name, a.search) {\n\t\treturn 1.0\n\t}\n\n\tsim := strutil.Similarity(pkg.name, a.search, a.metric)\n\n\tfor _, prov := range pkg.provides {\n\t\t// If the package provides search, it's a perfect match\n\t\t// AUR packages don't populate provides\n\t\tcandidate := strutil.Similarity(prov, a.search, a.metric) * 0.80\n\t\tif candidate > sim {\n\t\t\tsim = candidate\n\t\t}\n\t}\n\n\tsimDesc := strutil.Similarity(pkg.description, a.search, a.metric)\n\n\t// slightly overweight sync sources by always giving them max popularity\n\tpopularity := 1.0\n\tif pkg.source == \"aur\" {\n\t\tpopularity = a.aurSortByMetric(pkg)\n\t}\n\n\tsim = sim*0.5 + simDesc*0.2 + popularity*0.3\n\n\ta.distanceCache[pkg.name] = sim\n\n\treturn sim\n}\n\nfunc (a *abstractResults) separateSourceScore(source string, score float64) float64 {\n\tif !a.separateSources {\n\t\treturn 0\n\t}\n\n\tif score == 1.0 {\n\t\treturn 50\n\t}\n\n\tif v, ok := a.separateSourceCache[source]; ok {\n\t\treturn v\n\t}\n\n\t// AUR is always lowest priority\n\tif source == \"aur\" {\n\t\treturn 0\n\t}\n\n\t// Score sync repositories based on pacman.conf order (as reflected by dbExecutor.Repos()).\n\t// First repo gets max, last repo gets min, evenly distributed across the range.\n\tfor i, repo := range a.repoOrder {\n\t\tif repo != source {\n\t\t\tcontinue\n\t\t}\n\n\t\tn := len(a.repoOrder)\n\t\tif n == 1 {\n\t\t\ta.separateSourceCache[source] = separateSourceMax\n\t\t\treturn separateSourceMax\n\t\t}\n\n\t\tstep := (separateSourceMax - separateSourceMin) / float64(n-1)\n\t\tsourceScore := separateSourceMax - (float64(i) * step)\n\t\ta.separateSourceCache[source] = sourceScore\n\t\treturn sourceScore\n\t}\n\n\treturn 0\n}\n\nfunc (a *abstractResults) calculateMetric(pkg *abstractResult) float64 {\n\tscore := a.GetMetric(pkg)\n\treturn a.separateSourceScore(pkg.source, score) + score\n}\n"
  },
  {
    "path": "pkg/query/metric_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage query\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestSeparateSourceScore_UsesRepoOrderEvenlyDistributed(t *testing.T) {\n\tt.Parallel()\n\n\t// Any non-1.0 score avoids the special-case 50 return.\n\tconst sim = 0.5\n\tconst delta = 1e-1\n\n\tt.Run(\"arch repos (core/extra/community/multilib)\", func(t *testing.T) {\n\t\ta := &abstractResults{\n\t\t\tseparateSources:     true,\n\t\t\trepoOrder:           []string{\"core\", \"extra\", \"community\", \"multilib\"},\n\t\t\tseparateSourceCache: map[string]float64{},\n\t\t}\n\n\t\tassert.InDelta(t, 45.0, a.separateSourceScore(\"core\", sim), delta)\n\t\tassert.InDelta(t, 31.6, a.separateSourceScore(\"extra\", sim), delta)\n\t\tassert.InDelta(t, 18.3, a.separateSourceScore(\"community\", sim), delta)\n\t\tassert.InDelta(t, 5.0, a.separateSourceScore(\"multilib\", sim), delta)\n\t\tassert.Equal(t, 0.0, a.separateSourceScore(\"aur\", sim))\n\t})\n\n\tt.Run(\"arch arm repos (core/extra/alarm/aur)\", func(t *testing.T) {\n\t\ta := &abstractResults{\n\t\t\tseparateSources:     true,\n\t\t\trepoOrder:           []string{\"core\", \"extra\", \"alarm\", \"aur\"},\n\t\t\tseparateSourceCache: map[string]float64{},\n\t\t}\n\n\t\t// Note: AUR is not a sync repository; it is always lowest priority (0) regardless of repo order.\n\t\tassert.InDelta(t, 45.0, a.separateSourceScore(\"core\", sim), delta)\n\t\tassert.InDelta(t, 31.6, a.separateSourceScore(\"extra\", sim), delta)\n\t\tassert.InDelta(t, 18.3, a.separateSourceScore(\"alarm\", sim), delta)\n\t\tassert.Equal(t, 0.0, a.separateSourceScore(\"aur\", sim))\n\t})\n}\n"
  },
  {
    "path": "pkg/query/query_builder.go",
    "content": "package query\n\nimport (\n\t\"cmp\"\n\t\"context\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"unicode\"\n\n\t\"github.com/Jguer/aur\"\n\talpm \"github.com/Jguer/dyalpm\"\n\t\"github.com/adrg/strutil\"\n\t\"github.com/adrg/strutil/metrics\"\n\tmapset \"github.com/deckarep/golang-set/v2\"\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/intrange\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\ntype SearchVerbosity int\n\n// Verbosity settings for search.\nconst (\n\tNumberMenu SearchVerbosity = iota\n\tDetailed\n\tMinimal\n)\n\ntype Builder interface {\n\tLen() int\n\tExecute(ctx context.Context, dbExecutor db.Executor, pkgS []string)\n\tResults(dbExecutor db.Executor, verboseSearch SearchVerbosity) error\n\tGetTargets(include, exclude intrange.IntRanges, otherExclude mapset.Set[string]) ([]string, error)\n}\n\ntype SortFunc func(pkgA, pkgB abstractResult) int\n\ntype SourceQueryBuilder struct {\n\tresults           []abstractResult\n\tsortBy            string\n\tsearchBy          string\n\ttargetMode        parser.TargetMode\n\tqueryMap          map[string]map[string]any\n\tbottomUp          bool\n\tsingleLineResults bool\n\tseparateSources   bool\n\n\taurClient aur.QueryClient\n\tlogger    *text.Logger\n}\n\nfunc NewSourceQueryBuilder(\n\taurClient aur.QueryClient,\n\tlogger *text.Logger,\n\tsortBy string,\n\ttargetMode parser.TargetMode,\n\tsearchBy string,\n\tbottomUp,\n\tsingleLineResults bool,\n\tseparateSources bool,\n) *SourceQueryBuilder {\n\treturn &SourceQueryBuilder{\n\t\taurClient:         aurClient,\n\t\tlogger:            logger,\n\t\tbottomUp:          bottomUp,\n\t\tsortBy:            sortBy,\n\t\ttargetMode:        targetMode,\n\t\tsearchBy:          searchBy,\n\t\tsingleLineResults: singleLineResults,\n\t\tseparateSources:   separateSources,\n\t\tqueryMap:          map[string]map[string]any{},\n\t\tresults:           make([]abstractResult, 0, 100),\n\t}\n}\n\ntype abstractResult struct {\n\tsource         string\n\tname           string\n\tdescription    string\n\tpackageBase    string\n\tvotes          int\n\tpopularity     float64\n\tfirstSubmitted int\n\tlastModified   int\n\tprovides       []string\n}\n\ntype abstractResults struct {\n\tresults         []abstractResult\n\tsearch          string\n\tmetric          strutil.StringMetric\n\tseparateSources bool\n\tsortByFunc      SortFunc\n\trepoOrder       []string\n\n\tdistanceCache       map[string]float64\n\tseparateSourceCache map[string]float64\n}\n\nfunc (a *abstractResults) Len() int      { return len(a.results) }\nfunc (a *abstractResults) Swap(i, j int) { a.results[i], a.results[j] = a.results[j], a.results[i] }\n\nfunc (a *abstractResults) Less(i, j int) bool {\n\tpkgA := a.results[i]\n\tpkgB := a.results[j]\n\t// Sort in descending order by default\n\treturn a.sortByFunc(pkgA, pkgB) > 0\n}\n\nfunc (a *abstractResults) GetSortFunc(sortBy string, bottomUp bool) SortFunc {\n\tvar sortFunc SortFunc\n\n\t// Primary sort\n\tswitch sortBy {\n\tcase \"base\":\n\t\tsortFunc = func(pkgA, pkgB abstractResult) int {\n\t\t\treturn cmp.Compare(pkgA.packageBase, pkgB.packageBase)\n\t\t}\n\tcase \"modified\":\n\t\tsortFunc = func(pkgA, pkgB abstractResult) int {\n\t\t\treturn cmp.Compare(pkgA.lastModified, pkgB.lastModified)\n\t\t}\n\tcase \"name\":\n\t\tsortFunc = func(pkgA, pkgB abstractResult) int {\n\t\t\treturn cmp.Compare(pkgA.name, pkgB.name)\n\t\t}\n\tcase \"popularity\":\n\t\tsortFunc = func(pkgA, pkgB abstractResult) int {\n\t\t\treturn cmp.Compare(pkgA.popularity, pkgB.popularity)\n\t\t}\n\tcase \"submitted\":\n\t\tsortFunc = func(pkgA, pkgB abstractResult) int {\n\t\t\treturn cmp.Compare(pkgA.firstSubmitted, pkgB.firstSubmitted)\n\t\t}\n\tcase \"votes\":\n\t\tsortFunc = func(pkgA, pkgB abstractResult) int {\n\t\t\treturn cmp.Compare(pkgA.votes, pkgB.votes)\n\t\t}\n\tdefault:\n\t\tsortFunc = func(pkgA, pkgB abstractResult) int {\n\t\t\treturn 0\n\t\t}\n\t}\n\n\t// Sort by metric as a tie-breaker. Also handle separating sources when not a tie\n\t{\n\t\toriginalSortFunc := sortFunc\n\t\tsortFunc = func(pkgA, pkgB abstractResult) int {\n\t\t\tif cmpResult := originalSortFunc(pkgA, pkgB); cmpResult != 0 {\n\t\t\t\tif a.separateSources {\n\t\t\t\t\tif cmpSources := strings.Compare(pkgA.source, pkgB.source); cmpSources != 0 {\n\t\t\t\t\t\treturn cmpSources\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn cmpResult\n\t\t\t}\n\n\t\t\tmetricA := a.calculateMetric(&pkgA)\n\t\t\tmetricB := a.calculateMetric(&pkgB)\n\t\t\treturn cmp.Compare(metricA, metricB)\n\t\t}\n\t}\n\n\tif bottomUp {\n\t\t// Invert sort for bottom-up sorting\n\t\toriginalSortFunc := sortFunc\n\t\tsortFunc = func(pkgA, pkgB abstractResult) int {\n\t\t\treturn -originalSortFunc(pkgA, pkgB)\n\t\t}\n\t}\n\n\treturn sortFunc\n}\n\nfunc (s *SourceQueryBuilder) Execute(ctx context.Context, dbExecutor db.Executor, pkgS []string) {\n\tvar aurErr error\n\n\tpkgS = RemoveInvalidTargets(s.logger, pkgS, s.targetMode)\n\n\tmetric := &metrics.Hamming{\n\t\tCaseSensitive: false,\n\t}\n\n\tsortableResults := &abstractResults{\n\t\tresults:             []abstractResult{},\n\t\tsearch:              strings.Join(pkgS, \"\"),\n\t\tmetric:              metric,\n\t\tseparateSources:     s.separateSources,\n\t\trepoOrder:           dbExecutor.Repos(),\n\t\tdistanceCache:       map[string]float64{},\n\t\tseparateSourceCache: map[string]float64{},\n\t}\n\tsortableResults.sortByFunc = sortableResults.GetSortFunc(s.sortBy, s.bottomUp)\n\n\tvar repoResults []alpm.Package\n\tif s.targetMode.AtLeastRepo() {\n\t\trepoResults = dbExecutor.SyncPackages(pkgS...)\n\n\t\tfor i := range repoResults {\n\t\t\tdbName := repoResults[i].DB().Name()\n\t\t\tif s.queryMap[dbName] == nil {\n\t\t\t\ts.queryMap[dbName] = map[string]any{}\n\t\t\t}\n\n\t\t\ts.queryMap[dbName][repoResults[i].Name()] = repoResults[i]\n\n\t\t\trawProvides := repoResults[i].Provides()\n\n\t\t\tprovides := make([]string, len(rawProvides))\n\t\t\tfor j := range rawProvides {\n\t\t\t\tprovides[j] = rawProvides[j].Name\n\t\t\t}\n\n\t\t\tsortableResults.results = append(sortableResults.results, abstractResult{\n\t\t\t\tsource:         repoResults[i].DB().Name(),\n\t\t\t\tname:           repoResults[i].Name(),\n\t\t\t\tdescription:    repoResults[i].Description(),\n\t\t\t\tpackageBase:    repoResults[i].Base(),\n\t\t\t\tvotes:          -1,\n\t\t\t\tpopularity:     -1,\n\t\t\t\tfirstSubmitted: -1,\n\t\t\t\tlastModified:   -1,\n\t\t\t\tprovides:       provides,\n\t\t\t})\n\t\t}\n\t}\n\n\tif s.targetMode.AtLeastAUR() {\n\t\tvar aurResults []aur.Pkg\n\t\taurResults, aurErr = queryAUR(ctx, s.aurClient, pkgS, s.searchBy)\n\t\tdbName := \"aur\"\n\n\t\tfor i := range aurResults {\n\t\t\tif s.queryMap[dbName] == nil {\n\t\t\t\ts.queryMap[dbName] = map[string]any{}\n\t\t\t}\n\n\t\t\tby := getSearchBy(s.searchBy)\n\t\t\tif (by == aur.NameDesc || by == aur.None || by == aur.Name) &&\n\t\t\t\t!matchesSearch(&aurResults[i], pkgS) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\ts.queryMap[dbName][aurResults[i].Name] = aurResults[i]\n\n\t\t\tsortableResults.results = append(sortableResults.results, abstractResult{\n\t\t\t\tsource:         dbName,\n\t\t\t\tname:           aurResults[i].Name,\n\t\t\t\tdescription:    aurResults[i].Description,\n\t\t\t\tpackageBase:    aurResults[i].PackageBase,\n\t\t\t\tvotes:          aurResults[i].NumVotes,\n\t\t\t\tpopularity:     aurResults[i].Popularity,\n\t\t\t\tfirstSubmitted: aurResults[i].FirstSubmitted,\n\t\t\t\tlastModified:   aurResults[i].LastModified,\n\t\t\t\tprovides:       aurResults[i].Provides,\n\t\t\t})\n\t\t}\n\t}\n\n\tsort.Sort(sortableResults)\n\ts.results = sortableResults.results\n\n\tif aurErr != nil {\n\t\ts.logger.Errorln(ErrAURSearch{inner: aurErr})\n\n\t\tif len(repoResults) != 0 {\n\t\t\ts.logger.Warnln(gotext.Get(\"Showing repo packages only\"))\n\t\t}\n\t}\n}\n\nfunc (s *SourceQueryBuilder) Results(dbExecutor db.Executor, verboseSearch SearchVerbosity) error {\n\tfor i := range s.results {\n\t\tif verboseSearch == Minimal {\n\t\t\ts.logger.Println(s.results[i].name)\n\t\t\tcontinue\n\t\t}\n\n\t\tvar toPrint string\n\n\t\tif verboseSearch == NumberMenu {\n\t\t\tif s.bottomUp {\n\t\t\t\ttoPrint += text.Magenta(strconv.Itoa(len(s.results)-i)) + \" \"\n\t\t\t} else {\n\t\t\t\ttoPrint += text.Magenta(strconv.Itoa(i+1)) + \" \"\n\t\t\t}\n\t\t}\n\n\t\tpkg := s.queryMap[s.results[i].source][s.results[i].name]\n\n\t\tswitch pPkg := pkg.(type) {\n\t\tcase aur.Pkg:\n\t\t\ttoPrint += aurPkgSearchString(&pPkg, dbExecutor, s.singleLineResults)\n\t\tcase alpm.Package:\n\t\t\ttoPrint += syncPkgSearchString(pPkg, dbExecutor, s.singleLineResults)\n\t\t}\n\n\t\ts.logger.Println(toPrint)\n\t}\n\n\treturn nil\n}\n\nfunc (s *SourceQueryBuilder) Len() int {\n\treturn len(s.results)\n}\n\nfunc (s *SourceQueryBuilder) GetTargets(include, exclude intrange.IntRanges,\n\totherExclude mapset.Set[string],\n) ([]string, error) {\n\tvar (\n\t\tisInclude = len(exclude) == 0 && otherExclude.Cardinality() == 0\n\t\ttargets   []string\n\t\tlenRes    = len(s.results)\n\t)\n\n\tfor i := 1; i <= s.Len(); i++ {\n\t\ttarget := i - 1\n\t\tif s.bottomUp {\n\t\t\ttarget = lenRes - i\n\t\t}\n\n\t\tif (isInclude && include.Get(i)) || (!isInclude && !exclude.Get(i)) {\n\t\t\ttargets = append(targets, s.results[target].source+\"/\"+s.results[target].name)\n\t\t}\n\t}\n\n\treturn targets, nil\n}\n\nfunc matchesSearch(pkg *aur.Pkg, terms []string) bool {\n\tif len(terms) <= 1 {\n\t\treturn true\n\t}\n\n\tfor _, pkgN := range terms {\n\t\tif strings.IndexFunc(pkgN, unicode.IsSymbol) != -1 {\n\t\t\treturn true\n\t\t}\n\n\t\tname := strings.ToLower(pkg.Name)\n\t\tdesc := strings.ToLower(pkg.Description)\n\t\ttarg := strings.ToLower(pkgN)\n\n\t\tif !strings.Contains(name, targ) && !strings.Contains(desc, targ) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n"
  },
  {
    "path": "pkg/query/query_builder_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage query\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/Jguer/aur\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db/mock\"\n\tmockaur \"github.com/Jguer/yay/v12/pkg/dep/mock\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestSourceQueryBuilder(t *testing.T) {\n\tt.Parallel()\n\ttype testCase struct {\n\t\tdesc              string\n\t\tsearch            []string\n\t\tbottomUp          bool\n\t\tseparateSources   bool\n\t\tsortBy            string\n\t\tverbosity         SearchVerbosity\n\t\ttargetMode        parser.TargetMode\n\t\tsingleLineResults bool\n\t\tsearchBy          string\n\t\twantResults       []string\n\t\twantOutput        []string\n\t}\n\n\ttestCases := []testCase{\n\t\t{\n\t\t\tdesc:            \"sort-by-metric bottomup separatesources\",\n\t\t\tsearch:          []string{\"linux\"},\n\t\t\tbottomUp:        true,\n\t\t\tseparateSources: true,\n\t\t\tsortBy:          \"\",\n\t\t\tverbosity:       Detailed,\n\t\t\twantResults:     []string{\"linux-ck\", \"linux-zen\", \"linux\"},\n\t\t\twantOutput: []string{\n\t\t\t\t\"\\x1b]8;;https://aur.archlinux.org/packages/linux-ck\\x1b\\\\\\x1b[1m\\x1b[34maur\\x1b[0m\\x1b[0m/\\x1b[1mlinux-ck\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.12-1\\x1b[0m\\x1b[1m (+450\\x1b[0m \\x1b[1m1.51) \\x1b[0m\\n    The Linux-ck kernel and modules with ck's hrtimer patches\\n\",\n\t\t\t\t\"\\x1b]8;;https://archlinux.org/packages/core/x86_64/linux-zen\\x1b\\\\\\x1b[1m\\x1b[33mcore\\x1b[0m\\x1b[0m/\\x1b[1mlinux-zen\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.0\\x1b[0m\\x1b[1m (1.0 B 1.0 B) \\x1b[0m\\n    The Linux ZEN kernel and modules\\n\",\n\t\t\t\t\"\\x1b]8;;https://archlinux.org/packages/core/x86_64/linux\\x1b\\\\\\x1b[1m\\x1b[33mcore\\x1b[0m\\x1b[0m/\\x1b[1mlinux\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.0\\x1b[0m\\x1b[1m (1.0 B 1.0 B) \\x1b[0m\\n    The Linux kernel and modules\\n\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc:            \"sort-by-metric topdown separatesources\",\n\t\t\tsearch:          []string{\"linux\"},\n\t\t\tbottomUp:        false,\n\t\t\tseparateSources: true,\n\t\t\tsortBy:          \"\",\n\t\t\tverbosity:       Detailed,\n\t\t\twantResults:     []string{\"linux\", \"linux-zen\", \"linux-ck\"},\n\t\t\twantOutput: []string{\n\t\t\t\t\"\\x1b]8;;https://archlinux.org/packages/core/x86_64/linux\\x1b\\\\\\x1b[1m\\x1b[33mcore\\x1b[0m\\x1b[0m/\\x1b[1mlinux\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.0\\x1b[0m\\x1b[1m (1.0 B 1.0 B) \\x1b[0m\\n    The Linux kernel and modules\\n\",\n\t\t\t\t\"\\x1b]8;;https://archlinux.org/packages/core/x86_64/linux-zen\\x1b\\\\\\x1b[1m\\x1b[33mcore\\x1b[0m\\x1b[0m/\\x1b[1mlinux-zen\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.0\\x1b[0m\\x1b[1m (1.0 B 1.0 B) \\x1b[0m\\n    The Linux ZEN kernel and modules\\n\",\n\t\t\t\t\"\\x1b]8;;https://aur.archlinux.org/packages/linux-ck\\x1b\\\\\\x1b[1m\\x1b[34maur\\x1b[0m\\x1b[0m/\\x1b[1mlinux-ck\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.12-1\\x1b[0m\\x1b[1m (+450\\x1b[0m \\x1b[1m1.51) \\x1b[0m\\n    The Linux-ck kernel and modules with ck's hrtimer patches\\n\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc:            \"sort-by-metric bottomup noseparatesources\",\n\t\t\tsearch:          []string{\"linux\"},\n\t\t\tbottomUp:        true,\n\t\t\tseparateSources: false,\n\t\t\tsortBy:          \"\",\n\t\t\tverbosity:       Detailed,\n\t\t\twantResults:     []string{\"linux-ck\", \"linux-zen\", \"linux\"},\n\t\t\twantOutput: []string{\n\t\t\t\t\"\\x1b]8;;https://aur.archlinux.org/packages/linux-ck\\x1b\\\\\\x1b[1m\\x1b[34maur\\x1b[0m\\x1b[0m/\\x1b[1mlinux-ck\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.12-1\\x1b[0m\\x1b[1m (+450\\x1b[0m \\x1b[1m1.51) \\x1b[0m\\n    The Linux-ck kernel and modules with ck's hrtimer patches\\n\",\n\t\t\t\t\"\\x1b]8;;https://archlinux.org/packages/core/x86_64/linux-zen\\x1b\\\\\\x1b[1m\\x1b[33mcore\\x1b[0m\\x1b[0m/\\x1b[1mlinux-zen\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.0\\x1b[0m\\x1b[1m (1.0 B 1.0 B) \\x1b[0m\\n    The Linux ZEN kernel and modules\\n\",\n\t\t\t\t\"\\x1b]8;;https://archlinux.org/packages/core/x86_64/linux\\x1b\\\\\\x1b[1m\\x1b[33mcore\\x1b[0m\\x1b[0m/\\x1b[1mlinux\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.0\\x1b[0m\\x1b[1m (1.0 B 1.0 B) \\x1b[0m\\n    The Linux kernel and modules\\n\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc:            \"sort-by-metric topdown noseparatesources\",\n\t\t\tsearch:          []string{\"linux\"},\n\t\t\tbottomUp:        false,\n\t\t\tseparateSources: false,\n\t\t\tsortBy:          \"\",\n\t\t\tverbosity:       Detailed,\n\t\t\twantResults:     []string{\"linux\", \"linux-zen\", \"linux-ck\"},\n\t\t\twantOutput: []string{\n\t\t\t\t\"\\x1b]8;;https://archlinux.org/packages/core/x86_64/linux\\x1b\\\\\\x1b[1m\\x1b[33mcore\\x1b[0m\\x1b[0m/\\x1b[1mlinux\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.0\\x1b[0m\\x1b[1m (1.0 B 1.0 B) \\x1b[0m\\n    The Linux kernel and modules\\n\",\n\t\t\t\t\"\\x1b]8;;https://archlinux.org/packages/core/x86_64/linux-zen\\x1b\\\\\\x1b[1m\\x1b[33mcore\\x1b[0m\\x1b[0m/\\x1b[1mlinux-zen\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.0\\x1b[0m\\x1b[1m (1.0 B 1.0 B) \\x1b[0m\\n    The Linux ZEN kernel and modules\\n\",\n\t\t\t\t\"\\x1b]8;;https://aur.archlinux.org/packages/linux-ck\\x1b\\\\\\x1b[1m\\x1b[34maur\\x1b[0m\\x1b[0m/\\x1b[1mlinux-ck\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.12-1\\x1b[0m\\x1b[1m (+450\\x1b[0m \\x1b[1m1.51) \\x1b[0m\\n    The Linux-ck kernel and modules with ck's hrtimer patches\\n\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc:            \"sort-by-metric bottomup separatesources number-menu\",\n\t\t\tsearch:          []string{\"linux\"},\n\t\t\tbottomUp:        true,\n\t\t\tseparateSources: true,\n\t\t\tsortBy:          \"\",\n\t\t\tverbosity:       NumberMenu,\n\t\t\twantResults:     []string{\"linux-ck\", \"linux-zen\", \"linux\"},\n\t\t\twantOutput: []string{\n\t\t\t\t\"\\x1b[35m3\\x1b[0m \\x1b]8;;https://aur.archlinux.org/packages/linux-ck\\x1b\\\\\\x1b[1m\\x1b[34maur\\x1b[0m\\x1b[0m/\\x1b[1mlinux-ck\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.12-1\\x1b[0m\\x1b[1m (+450\\x1b[0m \\x1b[1m1.51) \\x1b[0m\\n    The Linux-ck kernel and modules with ck's hrtimer patches\\n\",\n\t\t\t\t\"\\x1b[35m2\\x1b[0m \\x1b]8;;https://archlinux.org/packages/core/x86_64/linux-zen\\x1b\\\\\\x1b[1m\\x1b[33mcore\\x1b[0m\\x1b[0m/\\x1b[1mlinux-zen\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.0\\x1b[0m\\x1b[1m (1.0 B 1.0 B) \\x1b[0m\\n    The Linux ZEN kernel and modules\\n\",\n\t\t\t\t\"\\x1b[35m1\\x1b[0m \\x1b]8;;https://archlinux.org/packages/core/x86_64/linux\\x1b\\\\\\x1b[1m\\x1b[33mcore\\x1b[0m\\x1b[0m/\\x1b[1mlinux\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.0\\x1b[0m\\x1b[1m (1.0 B 1.0 B) \\x1b[0m\\n    The Linux kernel and modules\\n\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc:            \"sort-by-metric topdown separatesources number-menu\",\n\t\t\tsearch:          []string{\"linux\"},\n\t\t\tbottomUp:        false,\n\t\t\tseparateSources: true,\n\t\t\tsortBy:          \"\",\n\t\t\tverbosity:       NumberMenu,\n\t\t\twantResults:     []string{\"linux\", \"linux-zen\", \"linux-ck\"},\n\t\t\twantOutput: []string{\n\t\t\t\t\"\\x1b[35m1\\x1b[0m \\x1b]8;;https://archlinux.org/packages/core/x86_64/linux\\x1b\\\\\\x1b[1m\\x1b[33mcore\\x1b[0m\\x1b[0m/\\x1b[1mlinux\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.0\\x1b[0m\\x1b[1m (1.0 B 1.0 B) \\x1b[0m\\n    The Linux kernel and modules\\n\",\n\t\t\t\t\"\\x1b[35m2\\x1b[0m \\x1b]8;;https://archlinux.org/packages/core/x86_64/linux-zen\\x1b\\\\\\x1b[1m\\x1b[33mcore\\x1b[0m\\x1b[0m/\\x1b[1mlinux-zen\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.0\\x1b[0m\\x1b[1m (1.0 B 1.0 B) \\x1b[0m\\n    The Linux ZEN kernel and modules\\n\",\n\t\t\t\t\"\\x1b[35m3\\x1b[0m \\x1b]8;;https://aur.archlinux.org/packages/linux-ck\\x1b\\\\\\x1b[1m\\x1b[34maur\\x1b[0m\\x1b[0m/\\x1b[1mlinux-ck\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.12-1\\x1b[0m\\x1b[1m (+450\\x1b[0m \\x1b[1m1.51) \\x1b[0m\\n    The Linux-ck kernel and modules with ck's hrtimer patches\\n\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc:            \"sort-by-name bottomup separatesources number-menu\",\n\t\t\tsearch:          []string{\"linux\"},\n\t\t\tbottomUp:        true,\n\t\t\tseparateSources: true,\n\t\t\tsortBy:          \"name\",\n\t\t\tverbosity:       NumberMenu,\n\t\t\twantResults:     []string{\"linux-ck\", \"linux\", \"linux-zen\"},\n\t\t\twantOutput: []string{\n\t\t\t\t\"\\x1b[35m3\\x1b[0m \\x1b]8;;https://aur.archlinux.org/packages/linux-ck\\x1b\\\\\\x1b[1m\\x1b[34maur\\x1b[0m\\x1b[0m/\\x1b[1mlinux-ck\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.12-1\\x1b[0m\\x1b[1m (+450\\x1b[0m \\x1b[1m1.51) \\x1b[0m\\n    The Linux-ck kernel and modules with ck's hrtimer patches\\n\",\n\t\t\t\t\"\\x1b[35m2\\x1b[0m \\x1b]8;;https://archlinux.org/packages/core/x86_64/linux\\x1b\\\\\\x1b[1m\\x1b[33mcore\\x1b[0m\\x1b[0m/\\x1b[1mlinux\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.0\\x1b[0m\\x1b[1m (1.0 B 1.0 B) \\x1b[0m\\n    The Linux kernel and modules\\n\",\n\t\t\t\t\"\\x1b[35m1\\x1b[0m \\x1b]8;;https://archlinux.org/packages/core/x86_64/linux-zen\\x1b\\\\\\x1b[1m\\x1b[33mcore\\x1b[0m\\x1b[0m/\\x1b[1mlinux-zen\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.0\\x1b[0m\\x1b[1m (1.0 B 1.0 B) \\x1b[0m\\n    The Linux ZEN kernel and modules\\n\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc:            \"sort-by-name topdown separatesources number-menu\",\n\t\t\tsearch:          []string{\"linux\"},\n\t\t\tbottomUp:        false,\n\t\t\tseparateSources: true,\n\t\t\tsortBy:          \"name\",\n\t\t\tverbosity:       NumberMenu,\n\t\t\twantResults:     []string{\"linux-zen\", \"linux\", \"linux-ck\"},\n\t\t\twantOutput: []string{\n\t\t\t\t\"\\x1b[35m1\\x1b[0m \\x1b]8;;https://archlinux.org/packages/core/x86_64/linux-zen\\x1b\\\\\\x1b[1m\\x1b[33mcore\\x1b[0m\\x1b[0m/\\x1b[1mlinux-zen\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.0\\x1b[0m\\x1b[1m (1.0 B 1.0 B) \\x1b[0m\\n    The Linux ZEN kernel and modules\\n\",\n\t\t\t\t\"\\x1b[35m2\\x1b[0m \\x1b]8;;https://archlinux.org/packages/core/x86_64/linux\\x1b\\\\\\x1b[1m\\x1b[33mcore\\x1b[0m\\x1b[0m/\\x1b[1mlinux\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.0\\x1b[0m\\x1b[1m (1.0 B 1.0 B) \\x1b[0m\\n    The Linux kernel and modules\\n\",\n\t\t\t\t\"\\x1b[35m3\\x1b[0m \\x1b]8;;https://aur.archlinux.org/packages/linux-ck\\x1b\\\\\\x1b[1m\\x1b[34maur\\x1b[0m\\x1b[0m/\\x1b[1mlinux-ck\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.12-1\\x1b[0m\\x1b[1m (+450\\x1b[0m \\x1b[1m1.51) \\x1b[0m\\n    The Linux-ck kernel and modules with ck's hrtimer patches\\n\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc:            \"sort-by-name bottomup noseparatesources minimal\",\n\t\t\tsearch:          []string{\"linux\"},\n\t\t\tbottomUp:        true,\n\t\t\tseparateSources: false,\n\t\t\tsortBy:          \"name\",\n\t\t\tverbosity:       Minimal,\n\t\t\twantResults:     []string{\"linux\", \"linux-ck\", \"linux-zen\"},\n\t\t\twantOutput: []string{\n\t\t\t\t\"linux\\n\",\n\t\t\t\t\"linux-ck\\n\",\n\t\t\t\t\"linux-zen\\n\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc:            \"only-aur minimal\",\n\t\t\tsearch:          []string{\"linux\"},\n\t\t\tbottomUp:        true,\n\t\t\tseparateSources: true,\n\t\t\tsortBy:          \"name\",\n\t\t\tverbosity:       Minimal,\n\t\t\ttargetMode:      parser.ModeAUR,\n\t\t\twantResults:     []string{\"linux-ck\"},\n\t\t\twantOutput: []string{\n\t\t\t\t\"linux-ck\\n\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc:            \"only-repo minimal\",\n\t\t\tsearch:          []string{\"linux\"},\n\t\t\tbottomUp:        true,\n\t\t\tseparateSources: true,\n\t\t\tsortBy:          \"name\",\n\t\t\tverbosity:       Minimal,\n\t\t\ttargetMode:      parser.ModeRepo,\n\t\t\twantResults:     []string{\"linux\", \"linux-zen\"},\n\t\t\twantOutput: []string{\n\t\t\t\t\"linux\\n\",\n\t\t\t\t\"linux-zen\\n\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc:              \"sort-by-name singleline\",\n\t\t\tsearch:            []string{\"linux\"},\n\t\t\tbottomUp:          true,\n\t\t\tseparateSources:   true,\n\t\t\tsortBy:            \"name\",\n\t\t\tverbosity:         Detailed,\n\t\t\tsingleLineResults: true,\n\t\t\twantResults:       []string{\"linux-ck\", \"linux\", \"linux-zen\"},\n\t\t\twantOutput: []string{\n\t\t\t\t\"\\x1b]8;;https://aur.archlinux.org/packages/linux-ck\\x1b\\\\\\x1b[1m\\x1b[34maur\\x1b[0m\\x1b[0m/\\x1b[1mlinux-ck\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.12-1\\x1b[0m\\x1b[1m (+450\\x1b[0m \\x1b[1m1.51) \\x1b[0m\\tThe Linux-ck kernel and modules with ck's hrtimer patches\\n\",\n\t\t\t\t\"\\x1b]8;;https://archlinux.org/packages/core/x86_64/linux\\x1b\\\\\\x1b[1m\\x1b[33mcore\\x1b[0m\\x1b[0m/\\x1b[1mlinux\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.0\\x1b[0m\\x1b[1m (1.0 B 1.0 B) \\x1b[0m\\tThe Linux kernel and modules\\n\",\n\t\t\t\t\"\\x1b]8;;https://archlinux.org/packages/core/x86_64/linux-zen\\x1b\\\\\\x1b[1m\\x1b[33mcore\\x1b[0m\\x1b[0m/\\x1b[1mlinux-zen\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.0\\x1b[0m\\x1b[1m (1.0 B 1.0 B) \\x1b[0m\\tThe Linux ZEN kernel and modules\\n\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc:            \"sort-by-name search-by-name\",\n\t\t\tsearch:          []string{\"linux-ck\"},\n\t\t\tbottomUp:        true,\n\t\t\tseparateSources: true,\n\t\t\tsortBy:          \"name\",\n\t\t\tverbosity:       Detailed,\n\t\t\tsearchBy:        \"name\",\n\t\t\ttargetMode:      parser.ModeAUR,\n\t\t\twantResults:     []string{\"linux-ck\"},\n\t\t\twantOutput: []string{\n\t\t\t\t\"\\x1b]8;;https://aur.archlinux.org/packages/linux-ck\\x1b\\\\\\x1b[1m\\x1b[34maur\\x1b[0m\\x1b[0m/\\x1b[1mlinux-ck\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.12-1\\x1b[0m\\x1b[1m (+450\\x1b[0m \\x1b[1m1.51) \\x1b[0m\\n    The Linux-ck kernel and modules with ck's hrtimer patches\\n\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc:            \"only-aur search-by-several-terms\",\n\t\t\tsearch:          []string{\"linux-ck\", \"hrtimer\"},\n\t\t\tbottomUp:        true,\n\t\t\tseparateSources: true,\n\t\t\tverbosity:       Detailed,\n\t\t\ttargetMode:      parser.ModeAUR,\n\t\t\twantResults:     []string{\"linux-ck\"},\n\t\t\twantOutput: []string{\n\t\t\t\t\"\\x1b]8;;https://aur.archlinux.org/packages/linux-ck\\x1b\\\\\\x1b[1m\\x1b[34maur\\x1b[0m\\x1b[0m/\\x1b[1mlinux-ck\\x1b[0m\\x1b]8;;\\x1b\\\\ \\x1b[36m5.16.12-1\\x1b[0m\\x1b[1m (+450\\x1b[0m \\x1b[1m1.51) \\x1b[0m\\n    The Linux-ck kernel and modules with ck's hrtimer patches\\n\",\n\t\t\t},\n\t\t},\n\t}\n\n\tmockDB := &mock.DBExecutor{\n\t\tReposFn: func() []string {\n\t\t\t// Match pacman.conf parsing order for source separation.\n\t\t\treturn []string{\"core\"}\n\t\t},\n\t\tSyncPackagesFn: func(pkgs ...string) []mock.IPackage {\n\t\t\tmockDB := mock.NewDB(\"core\")\n\t\t\treturn []mock.IPackage{\n\t\t\t\t&mock.Package{\n\t\t\t\t\tPBase:         \"linux\",\n\t\t\t\t\tPName:         \"linux\",\n\t\t\t\t\tPVersion:      \"5.16.0\",\n\t\t\t\t\tPDescription:  \"The Linux kernel and modules\",\n\t\t\t\t\tPSize:         1,\n\t\t\t\t\tPISize:        1,\n\t\t\t\t\tPDB:           mockDB,\n\t\t\t\t\tPArchitecture: \"x86_64\",\n\t\t\t\t},\n\t\t\t\t&mock.Package{\n\t\t\t\t\tPBase:         \"linux-zen\",\n\t\t\t\t\tPName:         \"linux-zen\",\n\t\t\t\t\tPVersion:      \"5.16.0\",\n\t\t\t\t\tPDescription:  \"The Linux ZEN kernel and modules\",\n\t\t\t\t\tPSize:         1,\n\t\t\t\t\tPISize:        1,\n\t\t\t\t\tPDB:           mockDB,\n\t\t\t\t\tPArchitecture: \"x86_64\",\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage {\n\t\t\treturn nil\n\t\t},\n\t}\n\n\tmockAUR := &mockaur.MockAUR{\n\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\treturn []aur.Pkg{\n\t\t\t\t{\n\t\t\t\t\tDescription:    \"The Linux-ck kernel and modules with ck's hrtimer patches\",\n\t\t\t\t\tFirstSubmitted: 1311346274,\n\t\t\t\t\tID:             1045311,\n\t\t\t\t\tLastModified:   1646250901,\n\t\t\t\t\tMaintainer:     \"graysky\",\n\t\t\t\t\tName:           \"linux-ck\",\n\t\t\t\t\tNumVotes:       450,\n\t\t\t\t\tOutOfDate:      0,\n\t\t\t\t\tPackageBase:    \"linux-ck\",\n\t\t\t\t\tPackageBaseID:  50911,\n\t\t\t\t\tPopularity:     1.511141,\n\t\t\t\t\tURL:            \"https://wiki.archlinux.org/index.php/Linux-ck\",\n\t\t\t\t\tURLPath:        \"/cgit/aur.git/snapshot/linux-ck.tar.gz\",\n\t\t\t\t\tVersion:        \"5.16.12-1\",\n\t\t\t\t},\n\t\t\t}, nil\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.desc, func(t *testing.T) {\n\t\t\tw := &strings.Builder{}\n\t\t\tqueryBuilder := NewSourceQueryBuilder(mockAUR,\n\t\t\t\ttext.NewLogger(w, io.Discard, strings.NewReader(\"\"), false, \"test\"),\n\t\t\t\ttc.sortBy, tc.targetMode, tc.searchBy, tc.bottomUp,\n\t\t\t\ttc.singleLineResults, tc.separateSources)\n\n\t\t\tqueryBuilder.Execute(context.Background(), mockDB, tc.search)\n\n\t\t\tassert.Len(t, queryBuilder.results, len(tc.wantResults))\n\t\t\tassert.Equal(t, len(tc.wantResults), queryBuilder.Len())\n\t\t\tfor i, name := range tc.wantResults {\n\t\t\t\tassert.Equal(t, name, queryBuilder.results[i].name)\n\t\t\t}\n\n\t\t\tqueryBuilder.Results(mockDB, tc.verbosity)\n\n\t\t\tassert.Equal(t, strings.Join(tc.wantOutput, \"\"), w.String())\n\t\t})\n\t}\n}\n\nfunc TestSourceQueryBuilderTieSortsByRepoOrder(t *testing.T) {\n\tt.Parallel()\n\n\ttype testCase struct {\n\t\tdesc      string\n\t\tbottomUp  bool\n\t\trepoOrder []string\n\t\twantNames []string\n\t}\n\n\ttestCases := []testCase{\n\t\t{\n\t\t\tdesc:      \"sort-by-metric topdown repo-order-core-extra\",\n\t\t\tbottomUp:  false,\n\t\t\trepoOrder: []string{\"core\", \"extra\"},\n\t\t\twantNames: []string{\"systemd\", \"systemd-libs\", \"python-systemd\", \"systemd-git\"},\n\t\t},\n\t\t{\n\t\t\tdesc:      \"sort-by-metric topdown repo-order-extra-core\",\n\t\t\tbottomUp:  false,\n\t\t\trepoOrder: []string{\"extra\", \"core\"},\n\t\t\twantNames: []string{\"systemd\", \"python-systemd\", \"systemd-libs\", \"systemd-git\"},\n\t\t},\n\t\t{\n\t\t\tdesc:      \"sort-by-metric bottomup repo-order-core-extra\",\n\t\t\tbottomUp:  true,\n\t\t\trepoOrder: []string{\"core\", \"extra\"},\n\t\t\twantNames: []string{\"systemd-git\", \"python-systemd\", \"systemd-libs\", \"systemd\"},\n\t\t},\n\t\t{\n\t\t\tdesc:      \"sort-by-metric bottomup repo-order-extra-core\",\n\t\t\tbottomUp:  true,\n\t\t\trepoOrder: []string{\"extra\", \"core\"},\n\t\t\twantNames: []string{\"systemd-git\", \"systemd-libs\", \"python-systemd\", \"systemd\"},\n\t\t},\n\t}\n\n\tmockDB := &mock.DBExecutor{\n\t\tSyncPackagesFn: func(pkgs ...string) []mock.IPackage {\n\t\t\treturn []mock.IPackage{\n\t\t\t\t&mock.Package{\n\t\t\t\t\tPBase:         \"systemd\",\n\t\t\t\t\tPName:         \"systemd\",\n\t\t\t\t\tPVersion:      \"259-1\",\n\t\t\t\t\tPDescription:  \"system and service manager\",\n\t\t\t\t\tPSize:         1,\n\t\t\t\t\tPISize:        1,\n\t\t\t\t\tPDB:           mock.NewDB(\"core\"),\n\t\t\t\t\tPArchitecture: \"x86_64\",\n\t\t\t\t},\n\t\t\t\t&mock.Package{\n\t\t\t\t\tPBase:         \"systemd\",\n\t\t\t\t\tPName:         \"systemd-libs\",\n\t\t\t\t\tPVersion:      \"259-1\",\n\t\t\t\t\tPDescription:  \"systemd client libraries\",\n\t\t\t\t\tPSize:         1,\n\t\t\t\t\tPISize:        1,\n\t\t\t\t\tPDB:           mock.NewDB(\"core\"),\n\t\t\t\t\tPArchitecture: \"x86_64\",\n\t\t\t\t},\n\t\t\t\t&mock.Package{\n\t\t\t\t\tPBase:         \"python-systemd\",\n\t\t\t\t\tPName:         \"python-systemd\",\n\t\t\t\t\tPVersion:      \"235-4\",\n\t\t\t\t\tPDescription:  \"Python bindings for systemd\",\n\t\t\t\t\tPSize:         1,\n\t\t\t\t\tPISize:        1,\n\t\t\t\t\tPDB:           mock.NewDB(\"extra\"),\n\t\t\t\t\tPArchitecture: \"x86_64\",\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage {\n\t\t\treturn nil\n\t\t},\n\t}\n\n\tmockAUR := &mockaur.MockAUR{\n\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\treturn []aur.Pkg{\n\t\t\t\t{\n\t\t\t\t\tDescription:    \"system and service manager (git version)\",\n\t\t\t\t\tFirstSubmitted: 1445633397,\n\t\t\t\t\tID:             1909597,\n\t\t\t\t\tLastModified:   1765571424,\n\t\t\t\t\tMaintainer:     \"Atsutane\",\n\t\t\t\t\tName:           \"systemd-git\",\n\t\t\t\t\tNumVotes:       11,\n\t\t\t\t\tOutOfDate:      0,\n\t\t\t\t\tPackageBase:    \"systemd-git\",\n\t\t\t\t\tPackageBaseID:  102323,\n\t\t\t\t\tPopularity:     0.005618,\n\t\t\t\t\tURL:            \"https://www.github.com/systemd/systemd\",\n\t\t\t\t\tURLPath:        \"/cgit/aur.git/snapshot/systemd-git.tar.gz\",\n\t\t\t\t\tVersion:        \"259.rc3.r85286.7524671f74c-1\",\n\t\t\t\t},\n\t\t\t}, nil\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.desc, func(t *testing.T) {\n\t\t\tw := &strings.Builder{}\n\t\t\tmockDB.ReposFn = func() []string {\n\t\t\t\treturn tc.repoOrder\n\t\t\t}\n\t\t\tqueryBuilder := NewSourceQueryBuilder(mockAUR,\n\t\t\t\ttext.NewLogger(w, io.Discard, strings.NewReader(\"\"), false, \"test\"),\n\t\t\t\t\"\", parser.ModeAny, \"\", tc.bottomUp,\n\t\t\t\tfalse, true)\n\n\t\t\tqueryBuilder.Execute(context.Background(), mockDB, []string{\"systemd\"})\n\n\t\t\tgotNames := make([]string, len(queryBuilder.results))\n\t\t\tfor i, result := range queryBuilder.results {\n\t\t\t\tgotNames[i] = result.name\n\t\t\t}\n\n\t\t\tassert.Equal(t, tc.wantNames, gotNames)\n\t\t})\n\t}\n}\n\nfunc TestSourceQueryBuilderTieDoesNotSeparateSources(t *testing.T) {\n\tt.Parallel()\n\n\ttype testCase struct {\n\t\tdesc      string\n\t\tbottomUp  bool\n\t\twantNames []string\n\t}\n\n\ttestCases := []testCase{\n\t\t{\n\t\t\tdesc:      \"sort-by-metric topdown\",\n\t\t\tbottomUp:  false,\n\t\t\twantNames: []string{\"yay\", \"ruby-yard\", \"yay-git\"},\n\t\t},\n\t\t{\n\t\t\tdesc:      \"sort-by-metric bottomup\",\n\t\t\tbottomUp:  true,\n\t\t\twantNames: []string{\"yay-git\", \"ruby-yard\", \"yay\"},\n\t\t},\n\t}\n\n\tmockDB, mockAUR := newYayQueryBuilderMocks()\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.desc, func(t *testing.T) {\n\t\t\tw := &strings.Builder{}\n\t\t\tqueryBuilder := NewSourceQueryBuilder(mockAUR,\n\t\t\t\ttext.NewLogger(w, io.Discard, strings.NewReader(\"\"), false, \"test\"),\n\t\t\t\t\"\", parser.ModeAny, \"\", tc.bottomUp,\n\t\t\t\tfalse, true)\n\n\t\t\tqueryBuilder.Execute(context.Background(), mockDB, []string{\"yay\"})\n\n\t\t\tgotNames := make([]string, len(queryBuilder.results))\n\t\t\tfor i, result := range queryBuilder.results {\n\t\t\t\tgotNames[i] = result.name\n\t\t\t}\n\n\t\t\tassert.Equal(t, tc.wantNames, gotNames)\n\t\t})\n\t}\n}\n\nfunc TestSourceQueryBuilderSortByFields(t *testing.T) {\n\tt.Parallel()\n\n\ttype testCase struct {\n\t\tdesc      string\n\t\tsortBy    string\n\t\tbottomUp  bool\n\t\twantNames []string\n\t}\n\n\ttestCases := []testCase{\n\t\t{\n\t\t\tdesc:      \"sort-by-base topdown\",\n\t\t\tsortBy:    \"base\",\n\t\t\tbottomUp:  false,\n\t\t\twantNames: []string{\"yay-git\", \"yay\", \"ruby-yard\"},\n\t\t},\n\t\t{\n\t\t\tdesc:      \"sort-by-base bottomup\",\n\t\t\tsortBy:    \"base\",\n\t\t\tbottomUp:  true,\n\t\t\twantNames: []string{\"ruby-yard\", \"yay\", \"yay-git\"},\n\t\t},\n\t\t{\n\t\t\tdesc:      \"sort-by-modified topdown\",\n\t\t\tsortBy:    \"modified\",\n\t\t\tbottomUp:  false,\n\t\t\twantNames: []string{\"yay-git\", \"yay\", \"ruby-yard\"},\n\t\t},\n\t\t{\n\t\t\tdesc:      \"sort-by-modified bottomup\",\n\t\t\tsortBy:    \"modified\",\n\t\t\tbottomUp:  true,\n\t\t\twantNames: []string{\"ruby-yard\", \"yay\", \"yay-git\"},\n\t\t},\n\t\t{\n\t\t\tdesc:      \"sort-by-name topdown\",\n\t\t\tsortBy:    \"name\",\n\t\t\tbottomUp:  false,\n\t\t\twantNames: []string{\"yay-git\", \"yay\", \"ruby-yard\"},\n\t\t},\n\t\t{\n\t\t\tdesc:      \"sort-by-name bottomup\",\n\t\t\tsortBy:    \"name\",\n\t\t\tbottomUp:  true,\n\t\t\twantNames: []string{\"ruby-yard\", \"yay\", \"yay-git\"},\n\t\t},\n\t\t{\n\t\t\tdesc:      \"sort-by-popularity topdown\",\n\t\t\tsortBy:    \"popularity\",\n\t\t\tbottomUp:  false,\n\t\t\twantNames: []string{\"yay\", \"yay-git\", \"ruby-yard\"},\n\t\t},\n\t\t{\n\t\t\tdesc:      \"sort-by-popularity bottomup\",\n\t\t\tsortBy:    \"popularity\",\n\t\t\tbottomUp:  true,\n\t\t\twantNames: []string{\"ruby-yard\", \"yay-git\", \"yay\"},\n\t\t},\n\t\t{\n\t\t\tdesc:      \"sort-by-votes topdown\",\n\t\t\tsortBy:    \"votes\",\n\t\t\tbottomUp:  false,\n\t\t\twantNames: []string{\"yay\", \"yay-git\", \"ruby-yard\"},\n\t\t},\n\t\t{\n\t\t\tdesc:      \"sort-by-votes bottomup\",\n\t\t\tsortBy:    \"votes\",\n\t\t\tbottomUp:  true,\n\t\t\twantNames: []string{\"ruby-yard\", \"yay-git\", \"yay\"},\n\t\t},\n\t\t{\n\t\t\tdesc:      \"sort-by-submitted topdown\",\n\t\t\tsortBy:    \"submitted\",\n\t\t\tbottomUp:  false,\n\t\t\twantNames: []string{\"yay-git\", \"yay\", \"ruby-yard\"},\n\t\t},\n\t\t{\n\t\t\tdesc:      \"sort-by-submitted bottomup\",\n\t\t\tsortBy:    \"submitted\",\n\t\t\tbottomUp:  true,\n\t\t\twantNames: []string{\"ruby-yard\", \"yay\", \"yay-git\"},\n\t\t},\n\t\t{\n\t\t\tdesc:      \"sort-by-metric topdown\",\n\t\t\tsortBy:    \"\",\n\t\t\tbottomUp:  false,\n\t\t\twantNames: []string{\"yay\", \"yay-git\", \"ruby-yard\"},\n\t\t},\n\t\t{\n\t\t\tdesc:      \"sort-by-metric bottomup\",\n\t\t\tsortBy:    \"\",\n\t\t\tbottomUp:  true,\n\t\t\twantNames: []string{\"ruby-yard\", \"yay-git\", \"yay\"},\n\t\t},\n\t}\n\n\tmockDB, mockAUR := newYayQueryBuilderMocks()\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.desc, func(t *testing.T) {\n\t\t\tw := &strings.Builder{}\n\t\t\tqueryBuilder := NewSourceQueryBuilder(mockAUR,\n\t\t\t\ttext.NewLogger(w, io.Discard, strings.NewReader(\"\"), false, \"test\"),\n\t\t\t\ttc.sortBy, parser.ModeAny, \"\", tc.bottomUp,\n\t\t\t\tfalse, false)\n\n\t\t\tqueryBuilder.Execute(context.Background(), mockDB, []string{\"yay\"})\n\n\t\t\tgotNames := make([]string, len(queryBuilder.results))\n\t\t\tfor i, result := range queryBuilder.results {\n\t\t\t\tgotNames[i] = result.name\n\t\t\t}\n\n\t\t\tassert.Equal(t, tc.wantNames, gotNames)\n\t\t})\n\t}\n}\n\nfunc newYayQueryBuilderMocks() (*mock.DBExecutor, *mockaur.MockAUR) {\n\tmockDB := &mock.DBExecutor{\n\t\tReposFn: func() []string {\n\t\t\t// Match pacman.conf parsing order for source separation.\n\t\t\treturn []string{\"core\", \"extra\"}\n\t\t},\n\t\tSyncPackagesFn: func(pkgs ...string) []mock.IPackage {\n\t\t\tmockDB := mock.NewDB(\"extra\")\n\t\t\treturn []mock.IPackage{\n\t\t\t\t&mock.Package{\n\t\t\t\t\tPBase:         \"ruby-yard\",\n\t\t\t\t\tPName:         \"ruby-yard\",\n\t\t\t\t\tPVersion:      \"0.9.34-5\",\n\t\t\t\t\tPDescription:  \"YARD is a Ruby Documentation tool. The Y stands for \\\"Yay!\\\"\",\n\t\t\t\t\tPSize:         1,\n\t\t\t\t\tPISize:        1,\n\t\t\t\t\tPDB:           mockDB,\n\t\t\t\t\tPArchitecture: \"x86_64\",\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t\tLocalPackageFn: func(string) mock.IPackage {\n\t\t\treturn nil\n\t\t},\n\t}\n\n\tmockAUR := &mockaur.MockAUR{\n\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\treturn []aur.Pkg{\n\t\t\t\t{\n\t\t\t\t\tDescription:    \"Yet another yogurt. Pacman wrapper and AUR helper written in go.\",\n\t\t\t\t\tFirstSubmitted: 1475688004,\n\t\t\t\t\tID:             1911141,\n\t\t\t\t\tLastModified:   1765742501,\n\t\t\t\t\tMaintainer:     \"jguer\",\n\t\t\t\t\tName:           \"yay\",\n\t\t\t\t\tNumVotes:       2461,\n\t\t\t\t\tOutOfDate:      0,\n\t\t\t\t\tPackageBase:    \"yay\",\n\t\t\t\t\tPackageBaseID:  115973,\n\t\t\t\t\tPopularity:     34.903162,\n\t\t\t\t\tURL:            \"https://github.com/Jguer/yay\",\n\t\t\t\t\tURLPath:        \"/cgit/aur.git/snapshot/yay.tar.gz\",\n\t\t\t\t\tVersion:        \"12.5.7-1\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tDescription:    \"Yet another yogurt. Pacman wrapper and AUR helper written in go. (development version)\",\n\t\t\t\t\tFirstSubmitted: 1517205142,\n\t\t\t\t\tID:             1911143,\n\t\t\t\t\tLastModified:   1765742519,\n\t\t\t\t\tMaintainer:     \"jguer\",\n\t\t\t\t\tName:           \"yay-git\",\n\t\t\t\t\tNumVotes:       55,\n\t\t\t\t\tOutOfDate:      0,\n\t\t\t\t\tPackageBase:    \"yay-git\",\n\t\t\t\t\tPackageBaseID:  129573,\n\t\t\t\t\tPopularity:     1.850171,\n\t\t\t\t\tURL:            \"https://github.com/Jguer/yay\",\n\t\t\t\t\tURLPath:        \"/cgit/aur.git/snapshot/yay-git.tar.gz\",\n\t\t\t\t\tVersion:        \"12.5.7.r0.g44dfda05-1\",\n\t\t\t\t},\n\t\t\t}, nil\n\t\t},\n\t}\n\n\treturn mockDB, mockAUR\n}\n"
  },
  {
    "path": "pkg/query/source.go",
    "content": "package query\n\nimport (\n\t\"context\"\n\n\t\"github.com/Jguer/aur\"\n\t\"github.com/hashicorp/go-multierror\"\n)\n\n// queryAUR searches AUR and narrows based on subarguments.\nfunc queryAUR(ctx context.Context,\n\taurClient aur.QueryClient,\n\tpkgS []string, searchBy string,\n) ([]aur.Pkg, error) {\n\tvar (\n\t\terr error\n\t\tby  = getSearchBy(searchBy)\n\t)\n\n\tfor _, word := range pkgS {\n\t\tr, errM := aurClient.Get(ctx, &aur.Query{\n\t\t\tNeedles:  []string{word},\n\t\t\tBy:       by,\n\t\t\tContains: true,\n\t\t})\n\t\tif errM == nil {\n\t\t\treturn r, nil\n\t\t}\n\n\t\terr = multierror.Append(err, errM)\n\t}\n\n\treturn nil, err\n}\n"
  },
  {
    "path": "pkg/query/types.go",
    "content": "package query\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n\n\t\"github.com/Jguer/aur\"\n\talpm \"github.com/Jguer/dyalpm\"\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\ntype Pkg = aur.Pkg\n\nfunc getSearchBy(value string) aur.By {\n\tswitch value {\n\tcase \"name\":\n\t\treturn aur.Name\n\tcase \"maintainer\":\n\t\treturn aur.Maintainer\n\tcase \"submitter\":\n\t\treturn aur.Submitter\n\tcase \"depends\":\n\t\treturn aur.Depends\n\tcase \"makedepends\":\n\t\treturn aur.MakeDepends\n\tcase \"optdepends\":\n\t\treturn aur.OptDepends\n\tcase \"checkdepends\":\n\t\treturn aur.CheckDepends\n\tcase \"provides\":\n\t\treturn aur.Provides\n\tcase \"conflicts\":\n\t\treturn aur.Conflicts\n\tcase \"replaces\":\n\t\treturn aur.Replaces\n\tcase \"groups\":\n\t\treturn aur.Groups\n\tcase \"keywords\":\n\t\treturn aur.Keywords\n\tcase \"comaintainers\":\n\t\treturn aur.CoMaintainers\n\tdefault:\n\t\treturn aur.NameDesc\n\t}\n}\n\nfunc aurPkgSearchString(\n\tpkg *aur.Pkg,\n\tdbExecutor db.Executor,\n\tsingleLineResults bool,\n) string {\n\tlinkText := text.Bold(text.ColorHash(\"aur\")) + \"/\" + text.Bold(pkg.Name)\n\ttoPrint := text.CreateRepoLink(\"aur\", \"\", pkg.Name, linkText) +\n\t\t\" \" + text.Cyan(pkg.Version) +\n\t\ttext.Bold(\" (+\"+strconv.Itoa(pkg.NumVotes)) +\n\t\t\" \" + text.Bold(strconv.FormatFloat(pkg.Popularity, 'f', 2, 64)+\") \")\n\n\tif pkg.Maintainer == \"\" {\n\t\ttoPrint += text.Bold(text.Red(gotext.Get(\"(Orphaned)\"))) + \" \"\n\t}\n\n\tif pkg.OutOfDate != 0 {\n\t\ttoPrint += text.Bold(text.Red(gotext.Get(\"(Out-of-date: %s)\", text.FormatTime(pkg.OutOfDate)))) + \" \"\n\t}\n\n\tif localPkg := dbExecutor.LocalPackage(pkg.Name); localPkg != nil {\n\t\tif localPkg.Version() != pkg.Version {\n\t\t\ttoPrint += text.Bold(text.Green(gotext.Get(\"(Installed: %s)\", localPkg.Version())))\n\t\t} else {\n\t\t\ttoPrint += text.Bold(text.Green(gotext.Get(\"(Installed)\")))\n\t\t}\n\t}\n\n\tif singleLineResults {\n\t\ttoPrint += \"\\t\"\n\t} else {\n\t\ttoPrint += \"\\n    \"\n\t}\n\n\ttoPrint += pkg.Description\n\n\treturn toPrint\n}\n\n// PrintSearch receives a RepoSearch type and outputs pretty text.\nfunc syncPkgSearchString(pkg alpm.Package, dbExecutor db.Executor, singleLineResults bool) string {\n\tlinkText := text.Bold(text.ColorHash(pkg.DB().Name())) + \"/\" + text.Bold(pkg.Name())\n\ttoPrint := text.CreateRepoLink(pkg.DB().Name(), pkg.Architecture(), pkg.Name(), linkText) +\n\t\t\" \" + text.Cyan(pkg.Version()) +\n\t\ttext.Bold(\" (\"+text.Human(pkg.Size())+\n\t\t\t\" \"+text.Human(pkg.ISize())+\") \")\n\n\tpackageGroups := dbExecutor.PackageGroups(pkg)\n\tif len(packageGroups) != 0 {\n\t\ttoPrint += fmt.Sprint(packageGroups, \" \")\n\t}\n\n\tif localPkg := dbExecutor.LocalPackage(pkg.Name()); localPkg != nil {\n\t\tif localPkg.Version() != pkg.Version() {\n\t\t\ttoPrint += text.Bold(text.Green(gotext.Get(\"(Installed: %s)\", localPkg.Version())))\n\t\t} else {\n\t\t\ttoPrint += text.Bold(text.Green(gotext.Get(\"(Installed)\")))\n\t\t}\n\t}\n\n\tif singleLineResults {\n\t\ttoPrint += \"\\t\"\n\t} else {\n\t\ttoPrint += \"\\n    \"\n\t}\n\n\ttoPrint += pkg.Description()\n\n\treturn toPrint\n}\n"
  },
  {
    "path": "pkg/query/version_diff.go",
    "content": "package query\n\nimport (\n\t\"strings\"\n\t\"unicode\"\n\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\n\talpm \"github.com/Jguer/dyalpm\"\n)\n\nfunc GetVersionDiff(oldVersion, newVersion string) (left, right string) {\n\tif oldVersion == newVersion {\n\t\treturn oldVersion + text.Red(\"\"), newVersion + text.Green(\"\")\n\t}\n\n\tdiffPosition := 0\n\n\tcheckWords := func(str string, index int, words ...string) bool {\n\t\t// Make sure the word is not part of a longer word\n\t\tongoingWord := unicode.IsLetter(rune(str[index]))\n\t\tif ongoingWord {\n\t\t\treturn false\n\t\t}\n\n\t\tfor _, word := range words {\n\t\t\twordLength := len(word)\n\n\t\t\tnextIndex := index + 1\n\t\t\tif (index < len(str)-wordLength) &&\n\t\t\t\t(str[nextIndex:(nextIndex+wordLength)] == word) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\n\t\treturn false\n\t}\n\n\tfor index, char := range oldVersion {\n\t\tcharIsSpecial := !unicode.IsLetter(char) && !unicode.IsNumber(char)\n\n\t\tif (index >= len(newVersion)) || (char != rune(newVersion[index])) {\n\t\t\tif charIsSpecial {\n\t\t\t\tdiffPosition = index\n\t\t\t}\n\n\t\t\tbreak\n\t\t}\n\n\t\tif charIsSpecial ||\n\t\t\t(((index == len(oldVersion)-1) || (index == len(newVersion)-1)) &&\n\t\t\t\t((len(oldVersion) != len(newVersion)) ||\n\t\t\t\t\t(oldVersion[index] == newVersion[index]))) ||\n\t\t\tcheckWords(oldVersion, index, \"rc\", \"pre\", \"alpha\", \"beta\") {\n\t\t\tdiffPosition = index + 1\n\t\t}\n\t}\n\n\tsamePart := oldVersion[0:diffPosition]\n\n\tleft = samePart + text.Red(oldVersion[diffPosition:])\n\tright = samePart + text.Green(newVersion[diffPosition:])\n\n\treturn left, right\n}\n\nfunc isDevelName(name string) bool {\n\tfor _, suffix := range []string{\"git\", \"svn\", \"hg\", \"bzr\", \"nightly\", \"insiders-bin\"} {\n\t\tif strings.HasSuffix(name, \"-\"+suffix) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn strings.Contains(name, \"-always-\")\n}\n\nfunc isDevelPackage(pkg alpm.Package) bool {\n\treturn isDevelName(pkg.Name()) || isDevelName(pkg.Base())\n}\n"
  },
  {
    "path": "pkg/query/version_diff_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage query\n\nimport (\n\t\"testing\"\n\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\nfunc TestVersionDiff(t *testing.T) {\n\ttestCases := []struct {\n\t\tname     string\n\t\ta        string\n\t\tb        string\n\t\twantDiff string\n\t}{\n\t\t{\n\t\t\tname:     \"1.0.0-1 -> 1.0.0-2\",\n\t\t\ta:        \"1.0.0-1\",\n\t\t\tb:        \"1.0.0-2\",\n\t\t\twantDiff: \"1.0.0-\" + text.Red(\"1\") + \" \" + \"1.0.0-\" + text.Green(\"2\"),\n\t\t},\n\t\t{\n\t\t\tname:     \"1.0.0-1 -> 1.0.1-1\",\n\t\t\ta:        \"1.0.0-1\",\n\t\t\tb:        \"1.0.1-1\",\n\t\t\twantDiff: \"1.0.\" + text.Red(\"0-1\") + \" \" + \"1.0.\" + text.Green(\"1-1\"),\n\t\t},\n\t\t{\n\t\t\tname:     \"3.0.0~alpha7-3 -> 3.0.0~alpha7-4\",\n\t\t\ta:        \"3.0.0~alpha7-3\",\n\t\t\tb:        \"3.0.0~alpha7-4\",\n\t\t\twantDiff: \"3.0.0~alpha7-\" + text.Red(\"3\") + \" \" + \"3.0.0~alpha7-\" + text.Green(\"4\"),\n\t\t},\n\t\t{\n\t\t\tname:     \"3.0.0~beta7-3 -> 3.0.0~beta8-3\",\n\t\t\ta:        \"3.0.0~beta7-3\",\n\t\t\tb:        \"3.0.0~beta8-3\",\n\t\t\twantDiff: \"3.0.0~\" + text.Red(\"beta7-3\") + \" \" + \"3.0.0~\" + text.Green(\"beta8-3\"),\n\t\t},\n\t\t{\n\t\t\tname:     \"23.04.r131.b1bfe05-1 -> 23.04.r131.b1bfe07-1\",\n\t\t\ta:        \"23.04.r131.b1bfe05-1\",\n\t\t\tb:        \"23.04.r131.b1bfe07-1\",\n\t\t\twantDiff: \"23.04.r131.\" + text.Red(\"b1bfe05-1\") + \" \" + \"23.04.r131.\" + text.Green(\"b1bfe07-1\"),\n\t\t},\n\t\t{\n\t\t\tname:     \"1.0.arch0-1 -> 1.0.arch1-2\",\n\t\t\ta:        \"1.0.arch0-1\",\n\t\t\tb:        \"1.0.arch1-2\",\n\t\t\twantDiff: \"1.0.\" + text.Red(\"arch0-1\") + \" \" + \"1.0.\" + text.Green(\"arch1-2\"),\n\t\t},\n\t}\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\toriginalUseColor := text.UseColor\n\t\t\ttext.UseColor = true\n\t\t\tleft, right := GetVersionDiff(tc.a, tc.b)\n\t\t\tgotDiff := left + \" \" + right\n\t\t\tif gotDiff != tc.wantDiff {\n\t\t\t\tt.Errorf(\"VersionDiff(%s, %s) = %s, want %s\", tc.a, tc.b, gotDiff, tc.wantDiff)\n\t\t\t}\n\t\t\ttext.UseColor = originalUseColor\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/runtime/pacman.go",
    "content": "package runtime\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\n\tpacmanconf \"github.com/Morganamilo/go-pacmanconf\"\n\t\"golang.org/x/term\"\n)\n\nfunc retrievePacmanConfig(cmdArgs *parser.Arguments, pacmanConfigPath string) (*pacmanconf.Config, bool, error) {\n\troot := \"/\"\n\tif value, _, exists := cmdArgs.GetArg(\"root\", \"r\"); exists {\n\t\troot = value\n\t}\n\n\tpacmanConf, stderr, err := pacmanconf.PacmanConf(\"--config\", pacmanConfigPath, \"--root\", root)\n\tif err != nil {\n\t\tcmdErr := err\n\t\tif stderr != \"\" {\n\t\t\tcmdErr = fmt.Errorf(\"%w\\n%s\", err, stderr)\n\t\t}\n\n\t\treturn nil, false, cmdErr\n\t}\n\n\tif dbPath, _, exists := cmdArgs.GetArg(\"dbpath\", \"b\"); exists {\n\t\tpacmanConf.DBPath = dbPath\n\t}\n\n\tif arch := cmdArgs.GetArgs(\"arch\"); arch != nil {\n\t\tpacmanConf.Architecture = append(pacmanConf.Architecture, arch...)\n\t}\n\n\tif ignoreArray := cmdArgs.GetArgs(\"ignore\"); ignoreArray != nil {\n\t\tpacmanConf.IgnorePkg = append(pacmanConf.IgnorePkg, ignoreArray...)\n\t}\n\n\tif ignoreGroupsArray := cmdArgs.GetArgs(\"ignoregroup\"); ignoreGroupsArray != nil {\n\t\tpacmanConf.IgnoreGroup = append(pacmanConf.IgnoreGroup, ignoreGroupsArray...)\n\t}\n\n\tif cacheArray := cmdArgs.GetArgs(\"cachedir\"); cacheArray != nil {\n\t\tpacmanConf.CacheDir = cacheArray\n\t}\n\n\tif gpgDir, _, exists := cmdArgs.GetArg(\"gpgdir\"); exists {\n\t\tpacmanConf.GPGDir = gpgDir\n\t}\n\n\tuseColor := pacmanConf.Color && term.IsTerminal(int(os.Stdout.Fd()))\n\n\tswitch value, _, _ := cmdArgs.GetArg(\"color\"); value {\n\tcase \"always\":\n\t\tuseColor = true\n\tcase \"auto\":\n\t\tuseColor = term.IsTerminal(int(os.Stdout.Fd()))\n\tcase \"never\":\n\t\tuseColor = false\n\t}\n\n\treturn pacmanConf, useColor, nil\n}\n"
  },
  {
    "path": "pkg/runtime/pacman_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage runtime\n\nimport (\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/Morganamilo/go-pacmanconf\"\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n)\n\n// normalizePath removes trailing slashes from paths (except for root \"/\").\nfunc normalizePath(p string) string {\n\tif p == \"/\" {\n\t\treturn p\n\t}\n\treturn strings.TrimSuffix(p, \"/\")\n}\n\n// normalizePaths normalizes a slice of paths.\nfunc normalizePaths(paths []string) []string {\n\tresult := make([]string, len(paths))\n\tfor i, p := range paths {\n\t\tresult[i] = normalizePath(p)\n\t}\n\treturn result\n}\n\n// normalizePacmanConf normalizes directory paths in a pacmanconf.Config\n// to handle differences between pacman versions (with/without trailing slashes).\nfunc normalizePacmanConf(conf *pacmanconf.Config) {\n\tconf.RootDir = normalizePath(conf.RootDir)\n\tconf.DBPath = normalizePath(conf.DBPath)\n\tconf.GPGDir = normalizePath(conf.GPGDir)\n\tconf.CacheDir = normalizePaths(conf.CacheDir)\n\tconf.HookDir = normalizePaths(conf.HookDir)\n}\n\nfunc TestPacmanConf(t *testing.T) {\n\tt.Parallel()\n\tpath := \"../../testdata/pacman.conf\"\n\n\tabsPath, err := filepath.Abs(path)\n\trequire.NoError(t, err)\n\n\t// detect the architecture of the system\n\texpectedArch := []string{\"x86_64\"}\n\tif runtime.GOARCH == \"arm64\" {\n\t\texpectedArch = []string{\"aarch64\"}\n\t}\n\n\texpectedPacmanConf := &pacmanconf.Config{\n\t\tRootDir: \"/\", DBPath: \"/var/lib/pacman\",\n\t\tCacheDir: []string{\"/var/cache/pacman/pkg\"},\n\t\tHookDir:  []string{\"/etc/pacman.d/hooks\"},\n\t\tGPGDir:   \"/etc/pacman.d/gnupg\", LogFile: \"/var/log/pacman.log\",\n\t\tHoldPkg: []string{\"pacman\", \"glibc\"}, IgnorePkg: []string{\"xorm\"},\n\t\tIgnoreGroup: []string{\"yorm\"}, Architecture: expectedArch,\n\t\tXferCommand: \"/usr/bin/wget --passive-ftp -c -O %o %u\",\n\t\tNoUpgrade:   []string(nil), NoExtract: []string(nil), CleanMethod: []string{\"KeepInstalled\"},\n\t\tSigLevel:           []string{\"PackageRequired\", \"PackageTrustedOnly\", \"DatabaseOptional\", \"DatabaseTrustedOnly\"},\n\t\tLocalFileSigLevel:  []string{\"PackageOptional\", \"PackageTrustedOnly\"},\n\t\tRemoteFileSigLevel: []string{\"PackageRequired\", \"PackageTrustedOnly\"}, UseSyslog: true,\n\t\tColor: true, UseDelta: 0, TotalDownload: false, CheckSpace: true,\n\t\tVerbosePkgLists: true, DisableDownloadTimeout: false,\n\t\tRepos: []pacmanconf.Repository{\n\t\t\t{\n\t\t\t\tName: \"core\", Servers: []string{\"Core\"},\n\t\t\t\tSigLevel: []string(nil), Usage: []string{\"All\"},\n\t\t\t},\n\t\t\t{\n\t\t\t\tName: \"extra\", Servers: []string{\"Extra\"}, SigLevel: []string(nil),\n\t\t\t\tUsage: []string{\"All\"},\n\t\t\t},\n\t\t\t{\n\t\t\t\tName: \"multilib\", Servers: []string{\"repo3\", \"multilib\"},\n\t\t\t\tSigLevel: []string(nil), Usage: []string{\"All\"},\n\t\t\t},\n\t\t},\n\t}\n\n\tpacmanConf, color, err := retrievePacmanConfig(parser.MakeArguments(), absPath)\n\tassert.Nil(t, err)\n\tassert.NotNil(t, pacmanConf)\n\tassert.Equal(t, color, false)\n\n\t// Normalize paths to handle differences between pacman versions\n\t// (some versions include trailing slashes, some don't)\n\tnormalizePacmanConf(pacmanConf)\n\tassert.EqualValues(t, expectedPacmanConf, pacmanConf)\n}\n"
  },
  {
    "path": "pkg/runtime/runtime.go",
    "content": "package runtime\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"time\"\n\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/query\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\t\"github.com/Jguer/yay/v12/pkg/vcs\"\n\n\t\"github.com/Jguer/aur\"\n\t\"github.com/Jguer/aur/metadata\"\n\t\"github.com/Jguer/aur/rpc\"\n\t\"github.com/Jguer/votar/pkg/vote\"\n\t\"github.com/Morganamilo/go-pacmanconf\"\n\n\t\"golang.org/x/net/proxy\"\n)\n\ntype Runtime struct {\n\tCfg          *settings.Configuration\n\tQueryBuilder query.Builder\n\tPacmanConf   *pacmanconf.Config\n\tVCSStore     vcs.Store\n\tCmdBuilder   exe.ICmdBuilder\n\tHTTPClient   *http.Client\n\tVoteClient   *vote.Client\n\tAURClient    aur.QueryClient\n\tLogger       *text.Logger\n}\n\nfunc NewRuntime(cfg *settings.Configuration, cmdArgs *parser.Arguments, version string) (*Runtime, error) {\n\tlogger := text.NewLogger(os.Stdout, os.Stderr, os.Stdin, cfg.Debug, \"runtime\")\n\trunner := exe.NewOSRunner(logger.Child(\"runner\"))\n\n\ttransport := http.DefaultTransport.(*http.Transport).Clone()\n\ttransport.IdleConnTimeout = 90 * time.Second\n\ttransport.TLSHandshakeTimeout = 30 * time.Second\n\ttransport.ResponseHeaderTimeout = 30 * time.Second\n\ttransport.MaxIdleConns = 100\n\ttransport.MaxIdleConnsPerHost = 10\n\n\tif socks5Proxy := os.Getenv(\"SOCKS5_PROXY\"); socks5Proxy != \"\" {\n\t\tdialer, err := proxy.SOCKS5(\"tcp\", socks5Proxy, nil, proxy.Direct)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tcontextDialer, ok := dialer.(proxy.ContextDialer)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"SOCKS5 dialer does not support DialContext\")\n\t\t}\n\t\ttransport.DialContext = contextDialer.DialContext\n\t}\n\n\thttpClient := &http.Client{\n\t\tTimeout:   30 * time.Second,\n\t\tTransport: transport,\n\t}\n\n\tuserAgent := fmt.Sprintf(\"Yay/%s\", version)\n\tvoteClient, errVote := vote.NewClient(vote.WithUserAgent(userAgent),\n\t\tvote.WithHTTPClient(httpClient))\n\tif errVote != nil {\n\t\treturn nil, errVote\n\t}\n\n\tvoteClient.SetCredentials(\n\t\tos.Getenv(\"AUR_USERNAME\"),\n\t\tos.Getenv(\"AUR_PASSWORD\"))\n\n\tuserAgentFn := func(ctx context.Context, req *http.Request) error {\n\t\treq.Header.Set(\"User-Agent\", userAgent)\n\t\treturn nil\n\t}\n\n\tvar aurCache aur.QueryClient\n\taurCache, errAURCache := metadata.New(\n\t\tmetadata.WithHTTPClient(httpClient),\n\t\tmetadata.WithCacheFilePath(filepath.Join(cfg.BuildDir, \"aur.json\")),\n\t\tmetadata.WithRequestEditorFn(userAgentFn),\n\t\tmetadata.WithBaseURL(cfg.AURURL),\n\t\tmetadata.WithDebugLogger(logger.Debugln),\n\t)\n\tif errAURCache != nil {\n\t\treturn nil, fmt.Errorf(gotext.Get(\"failed to retrieve aur Cache\")+\": %w\", errAURCache)\n\t}\n\n\taurClient, errAUR := rpc.NewClient(\n\t\trpc.WithHTTPClient(httpClient),\n\t\trpc.WithBaseURL(cfg.AURRPCURL),\n\t\trpc.WithRequestEditorFn(userAgentFn),\n\t\trpc.WithLogFn(logger.Debugln))\n\tif errAUR != nil {\n\t\treturn nil, errAUR\n\t}\n\n\tif cfg.UseRPC {\n\t\taurCache = aurClient\n\t}\n\n\tpacmanConf, useColor, err := retrievePacmanConfig(cmdArgs, cfg.PacmanConf)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// FIXME: get rid of global\n\ttext.UseColor = useColor\n\n\tcmdBuilder := exe.NewCmdBuilder(cfg, runner, logger.Child(\"cmdbuilder\"), pacmanConf.DBPath)\n\n\tvcsStore := vcs.NewInfoStore(\n\t\tcfg.VCSFilePath, cmdBuilder,\n\t\tlogger.Child(\"vcs\"))\n\n\tif err := vcsStore.Load(); err != nil {\n\t\treturn nil, err\n\t}\n\n\tqueryBuilder := query.NewSourceQueryBuilder(\n\t\taurClient,\n\t\tlogger.Child(\"mixed.querybuilder\"), cfg.SortBy,\n\t\tcfg.Mode, cfg.SearchBy,\n\t\tcfg.BottomUp, cfg.SingleLineResults, cfg.SeparateSources)\n\n\trun := &Runtime{\n\t\tCfg:          cfg,\n\t\tQueryBuilder: queryBuilder,\n\t\tPacmanConf:   pacmanConf,\n\t\tVCSStore:     vcsStore,\n\t\tCmdBuilder:   cmdBuilder,\n\t\tHTTPClient:   httpClient,\n\t\tVoteClient:   voteClient,\n\t\tAURClient:    aurCache,\n\t\tLogger:       logger,\n\t}\n\n\treturn run, nil\n}\n"
  },
  {
    "path": "pkg/runtime/runtime_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage runtime_test\n\nimport (\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n)\n\nfunc TestBuildRuntime(t *testing.T) {\n\tt.Parallel()\n\tpath := \"../../testdata/pacman.conf\"\n\n\tabsPath, err := filepath.Abs(path)\n\trequire.NoError(t, err)\n\n\t// Prepare test inputs\n\tcfg := &settings.Configuration{\n\t\tDebug:       true,\n\t\tUseRPC:      false,\n\t\tAURURL:      \"https://aur.archlinux.org\",\n\t\tAURRPCURL:   \"https://aur.archlinux.org/rpc\",\n\t\tBuildDir:    \"/tmp\",\n\t\tVCSFilePath: \"\",\n\t\tPacmanConf:  absPath,\n\t}\n\tcmdArgs := parser.MakeArguments()\n\tversion := \"1.0.0\"\n\n\t// Call the function being tested\n\trun, err := runtime.NewRuntime(cfg, cmdArgs, version)\n\trequire.NoError(t, err)\n\n\t// Assert the function's output\n\tassert.NotNil(t, run)\n\tassert.NotNil(t, run.QueryBuilder)\n\tassert.NotNil(t, run.PacmanConf)\n\tassert.NotNil(t, run.VCSStore)\n\tassert.NotNil(t, run.CmdBuilder)\n\tassert.NotNil(t, run.HTTPClient)\n\tassert.NotNil(t, run.VoteClient)\n\tassert.NotNil(t, run.AURClient)\n\tassert.NotNil(t, run.Logger)\n}\n"
  },
  {
    "path": "pkg/settings/args.go",
    "content": "package settings\n\nimport (\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n)\n\nfunc (c *Configuration) ParseCommandLine(a *parser.Arguments) error {\n\tif err := a.Parse(); err != nil {\n\t\treturn err\n\t}\n\n\tc.extractYayOptions(a)\n\n\treturn nil\n}\n\nfunc (c *Configuration) extractYayOptions(a *parser.Arguments) {\n\tfor option, value := range a.Options {\n\t\tif c.handleOption(option, value.First()) {\n\t\t\ta.DelArg(option)\n\t\t}\n\t}\n\n\tc.AURURL = strings.TrimRight(c.AURURL, \"/\")\n\n\t// if AurRPCURL is set, use that for /rpc calls\n\tif c.AURRPCURL == \"\" {\n\t\tc.AURRPCURL = c.AURURL + \"/rpc?\"\n\t\treturn\n\t}\n\n\tif !strings.HasSuffix(c.AURRPCURL, \"?\") {\n\t\tif strings.HasSuffix(c.AURRPCURL, \"/rpc\") {\n\t\t\tc.AURRPCURL += \"?\"\n\t\t} else {\n\t\t\tc.AURRPCURL = strings.TrimRight(c.AURRPCURL, \"/\") + \"/rpc?\"\n\t\t}\n\t}\n}\n\nfunc (c *Configuration) handleOption(option, value string) bool {\n\tboolValue, err := strconv.ParseBool(value)\n\tif err != nil {\n\t\tboolValue = true\n\t}\n\n\tswitch option {\n\tcase \"aururl\":\n\t\tc.AURURL = value\n\tcase \"aurrpcurl\":\n\t\tc.AURRPCURL = value\n\tcase \"save\":\n\t\tc.SaveConfig = boolValue\n\tcase \"afterclean\", \"cleanafter\":\n\t\tc.CleanAfter = boolValue\n\tcase \"keepsrc\":\n\t\tc.KeepSrc = boolValue\n\tcase \"debug\":\n\t\tc.Debug = boolValue\n\t\treturn !boolValue\n\tcase \"devel\":\n\t\tc.Devel = boolValue\n\tcase \"topdown\":\n\t\tc.BottomUp = false\n\tcase \"bottomup\":\n\t\tc.BottomUp = true\n\tcase \"singlelineresults\":\n\t\tc.SingleLineResults = true\n\tcase \"doublelineresults\":\n\t\tc.SingleLineResults = false\n\tcase \"completioninterval\":\n\t\tn, err := strconv.Atoi(value)\n\t\tif err == nil {\n\t\t\tc.CompletionInterval = n\n\t\t}\n\tcase \"sortby\":\n\t\tc.SortBy = value\n\tcase \"searchby\":\n\t\tc.SearchBy = value\n\tcase \"noconfirm\":\n\t\tNoConfirm = boolValue\n\tcase \"config\":\n\t\tc.PacmanConf = value\n\tcase \"redownload\":\n\t\tc.ReDownload = \"yes\"\n\tcase \"redownloadall\":\n\t\tc.ReDownload = \"all\"\n\tcase \"noredownload\":\n\t\tc.ReDownload = \"no\"\n\tcase \"rebuild\":\n\t\tc.ReBuild = parser.RebuildModeYes\n\tcase \"rebuildall\":\n\t\tc.ReBuild = parser.RebuildModeAll\n\tcase \"rebuildtree\":\n\t\tc.ReBuild = parser.RebuildModeTree\n\tcase \"norebuild\":\n\t\tc.ReBuild = parser.RebuildModeNo\n\tcase \"batchinstall\":\n\t\tc.BatchInstall = boolValue\n\tcase \"answerclean\":\n\t\tc.AnswerClean = value\n\tcase \"noanswerclean\":\n\t\tc.AnswerClean = \"\"\n\tcase \"answerdiff\":\n\t\tc.AnswerDiff = value\n\tcase \"noanswerdiff\":\n\t\tc.AnswerDiff = \"\"\n\tcase \"answeredit\":\n\t\tc.AnswerEdit = value\n\tcase \"noansweredit\":\n\t\tc.AnswerEdit = \"\"\n\tcase \"answerupgrade\":\n\t\tc.AnswerUpgrade = value\n\tcase \"noanswerupgrade\":\n\t\tc.AnswerUpgrade = \"\"\n\tcase \"gpgflags\":\n\t\tc.GpgFlags = value\n\tcase \"mflags\":\n\t\tc.MFlags = value\n\tcase \"gitflags\":\n\t\tc.GitFlags = value\n\tcase \"builddir\":\n\t\tc.BuildDir = value\n\tcase \"editor\":\n\t\tc.Editor = value\n\tcase \"editorflags\":\n\t\tc.EditorFlags = value\n\tcase \"makepkg\":\n\t\tc.MakepkgBin = value\n\tcase \"makepkgconf\":\n\t\tc.MakepkgConf = value\n\tcase \"nomakepkgconf\":\n\t\tc.MakepkgConf = \"\"\n\tcase \"pacman\":\n\t\tc.PacmanBin = value\n\tcase \"git\":\n\t\tc.GitBin = value\n\tcase \"gpg\":\n\t\tc.GpgBin = value\n\tcase \"sudo\":\n\t\tc.SudoBin = value\n\tcase \"sudoflags\":\n\t\tc.SudoFlags = value\n\tcase \"requestsplitn\":\n\t\tn, err := strconv.Atoi(value)\n\t\tif err == nil && n > 0 {\n\t\t\tc.RequestSplitN = n\n\t\t}\n\tcase \"sudoloop\":\n\t\tc.SudoLoop = boolValue\n\tcase \"provides\":\n\t\tc.Provides = boolValue\n\tcase \"pgpfetch\":\n\t\tc.PGPFetch = boolValue\n\tcase \"cleanmenu\":\n\t\tc.CleanMenu = boolValue\n\tcase \"diffmenu\":\n\t\tc.DiffMenu = boolValue\n\tcase \"editmenu\":\n\t\tc.EditMenu = boolValue\n\tcase \"useask\":\n\t\tc.UseAsk = boolValue\n\tcase \"combinedupgrade\":\n\t\tc.CombinedUpgrade = boolValue\n\tcase \"a\", \"aur\":\n\t\tc.Mode = parser.ModeAUR\n\tcase \"N\", \"repo\":\n\t\tc.Mode = parser.ModeRepo\n\tcase \"removemake\":\n\t\tc.RemoveMake = \"yes\"\n\tcase \"noremovemake\":\n\t\tc.RemoveMake = \"no\"\n\tcase \"askremovemake\":\n\t\tc.RemoveMake = \"ask\"\n\tcase \"askyesremovemake\":\n\t\tc.RemoveMake = \"askyes\"\n\tcase \"separatesources\":\n\t\tc.SeparateSources = boolValue\n\tdefault:\n\t\treturn false\n\t}\n\n\treturn true\n}\n"
  },
  {
    "path": "pkg/settings/config.go",
    "content": "package settings\n\nimport (\n\t\"bytes\"\n\t_ \"embed\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\n\t\"github.com/leonelquinteros/gotext\"\n\t\"gopkg.in/ini.v1\"\n)\n\n//go:embed yay.conf\nvar defaultsINI []byte\n\n// HideMenus indicates if pacman's provider menus must be hidden.\nvar HideMenus = false\n\n// NoConfirm indicates if user input should be skipped.\nvar NoConfirm = false\n\n// Configuration stores yay's config.\ntype Configuration struct {\n\tAURURL                 string `json:\"aururl\" ini:\"AurUrl\"`\n\tAURRPCURL              string `json:\"aurrpcurl\" ini:\"AurRpcUrl\"`\n\tBuildDir               string `json:\"buildDir\" ini:\"BuildDir\"`\n\tEditor                 string `json:\"editor\" ini:\"Editor\"`\n\tEditorFlags            string `json:\"editorflags\" ini:\"EditorFlags\"`\n\tMakepkgBin             string `json:\"makepkgbin\" ini:\"MakepkgBin\"`\n\tMakepkgConf            string `json:\"makepkgconf\" ini:\"MakepkgConf\"`\n\tPacmanBin              string `json:\"pacmanbin\" ini:\"PacmanBin\"`\n\tPacmanConf             string `json:\"pacmanconf\" ini:\"PacmanConf\"`\n\tReDownload             string `json:\"redownload\" ini:\"ReDownload\"`\n\tAnswerClean            string `json:\"answerclean\" ini:\"AnswerClean\"`\n\tAnswerDiff             string `json:\"answerdiff\" ini:\"AnswerDiff\"`\n\tAnswerEdit             string `json:\"answeredit\" ini:\"AnswerEdit\"`\n\tAnswerUpgrade          string `json:\"answerupgrade\" ini:\"AnswerUpgrade\"`\n\tGitBin                 string `json:\"gitbin\" ini:\"GitBin\"`\n\tGpgBin                 string `json:\"gpgbin\" ini:\"GpgBin\"`\n\tGpgFlags               string `json:\"gpgflags\" ini:\"GpgFlags\"`\n\tMFlags                 string `json:\"mflags\" ini:\"MFlags\"`\n\tSortBy                 string `json:\"sortby\" ini:\"SortBy\"`\n\tSearchBy               string `json:\"searchby\" ini:\"SearchBy\"`\n\tGitFlags               string `json:\"gitflags\" ini:\"GitFlags\"`\n\tRemoveMake             string `json:\"removemake\" ini:\"RemoveMake\"`\n\tSudoBin                string `json:\"sudobin\" ini:\"SudoBin\"`\n\tSudoFlags              string `json:\"sudoflags\" ini:\"SudoFlags\"`\n\tVersion                string `json:\"version\" ini:\"-\"`\n\tRequestSplitN          int    `json:\"requestsplitn\" ini:\"RequestSplitN\"`\n\tCompletionInterval     int    `json:\"completionrefreshtime\" ini:\"CompletionInterval\"`\n\tMaxConcurrentDownloads int    `json:\"maxconcurrentdownloads\" ini:\"MaxConcurrentDownloads\"`\n\tBottomUp               bool   `json:\"bottomup\" ini:\"BottomUp\"`\n\tSudoLoop               bool   `json:\"sudoloop\" ini:\"SudoLoop\"`\n\tDevel                  bool   `json:\"devel\" ini:\"Devel\"`\n\tCleanAfter             bool   `json:\"cleanAfter\" ini:\"CleanAfter\"`\n\tKeepSrc                bool   `json:\"keepSrc\" ini:\"KeepSrc\"`\n\tProvides               bool   `json:\"provides\" ini:\"Provides\"`\n\tPGPFetch               bool   `json:\"pgpfetch\" ini:\"PgpFetch\"`\n\tCleanMenu              bool   `json:\"cleanmenu\" ini:\"CleanMenu\"`\n\tDiffMenu               bool   `json:\"diffmenu\" ini:\"DiffMenu\"`\n\tEditMenu               bool   `json:\"editmenu\" ini:\"EditMenu\"`\n\tCombinedUpgrade        bool   `json:\"combinedupgrade\" ini:\"CombinedUpgrade\"`\n\tUseAsk                 bool   `json:\"useask\" ini:\"UseAsk\"`\n\tBatchInstall           bool   `json:\"batchinstall\" ini:\"BatchInstall\"`\n\tSingleLineResults      bool   `json:\"singlelineresults\" ini:\"SingleLineResults\"`\n\tSeparateSources        bool   `json:\"separatesources\" ini:\"SeparateSources\"`\n\tDebug                  bool   `json:\"debug\" ini:\"Debug\"`\n\tUseRPC                 bool   `json:\"rpc\" ini:\"Rpc\"`\n\tDoubleConfirm          bool   `json:\"doubleconfirm\" ini:\"DoubleConfirm\"` // confirm install before and after build\n\n\tCompletionPath string             `json:\"-\" ini:\"-\"`\n\tVCSFilePath    string             `json:\"-\" ini:\"-\"`\n\tSaveConfig     bool               `json:\"-\" ini:\"-\"`\n\tMode           parser.TargetMode  `json:\"-\" ini:\"-\"`\n\tReBuild        parser.RebuildMode `json:\"rebuild\" ini:\"ReBuild\"`\n}\n\n// Save writes yay config to INI file.\nfunc (c *Configuration) Save(configPath, version string) error {\n\t// Use INI config path instead of JSON\n\tiniPath := GetINIConfigPath()\n\tif iniPath == \"\" {\n\t\treturn fmt.Errorf(\"unable to determine config path\")\n\t}\n\n\treturn c.SaveINI(iniPath)\n}\n\nfunc (c *Configuration) expandEnv() {\n\tc.AURURL = os.ExpandEnv(c.AURURL)\n\tc.AURRPCURL = os.ExpandEnv(c.AURRPCURL)\n\tc.BuildDir = expandEnvOrHome(c.BuildDir)\n\tc.Editor = expandEnvOrHome(c.Editor)\n\tc.EditorFlags = os.ExpandEnv(c.EditorFlags)\n\tc.MakepkgBin = expandEnvOrHome(c.MakepkgBin)\n\tc.MakepkgConf = expandEnvOrHome(c.MakepkgConf)\n\tc.PacmanBin = expandEnvOrHome(c.PacmanBin)\n\tc.PacmanConf = expandEnvOrHome(c.PacmanConf)\n\tc.GpgFlags = os.ExpandEnv(c.GpgFlags)\n\tc.MFlags = os.ExpandEnv(c.MFlags)\n\tc.GitFlags = os.ExpandEnv(c.GitFlags)\n\tc.SortBy = os.ExpandEnv(c.SortBy)\n\tc.SearchBy = os.ExpandEnv(c.SearchBy)\n\tc.GitBin = expandEnvOrHome(c.GitBin)\n\tc.GpgBin = expandEnvOrHome(c.GpgBin)\n\tc.SudoBin = expandEnvOrHome(c.SudoBin)\n\tc.SudoFlags = os.ExpandEnv(c.SudoFlags)\n\tc.ReDownload = os.ExpandEnv(c.ReDownload)\n\tc.ReBuild = parser.RebuildMode(os.ExpandEnv(string(c.ReBuild)))\n\tc.AnswerClean = os.ExpandEnv(c.AnswerClean)\n\tc.AnswerDiff = os.ExpandEnv(c.AnswerDiff)\n\tc.AnswerEdit = os.ExpandEnv(c.AnswerEdit)\n\tc.AnswerUpgrade = os.ExpandEnv(c.AnswerUpgrade)\n\tc.RemoveMake = os.ExpandEnv(c.RemoveMake)\n}\n\nfunc expandEnvOrHome(path string) string {\n\tpath = os.ExpandEnv(path)\n\tif strings.HasPrefix(path, \"~/\") {\n\t\tpath = filepath.Join(os.Getenv(\"HOME\"), path[2:])\n\t}\n\n\treturn path\n}\n\nfunc (c *Configuration) String() string {\n\tvar buf bytes.Buffer\n\tenc := json.NewEncoder(&buf)\n\tenc.SetIndent(\"\", \"\\t\")\n\n\tif err := enc.Encode(c); err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t}\n\n\treturn buf.String()\n}\n\n// check privilege elevator exists otherwise try to find another one.\nfunc (c *Configuration) setPrivilegeElevator() error {\n\tif auth := os.Getenv(\"PACMAN_AUTH\"); auth != \"\" {\n\t\tc.SudoBin = auth\n\t\tif auth != \"sudo\" {\n\t\t\tc.SudoFlags = \"\"\n\t\t\tc.SudoLoop = false\n\t\t}\n\t}\n\n\tfor _, bin := range [...]string{c.SudoBin, \"sudo\"} {\n\t\tif _, err := exec.LookPath(bin); err == nil {\n\t\t\tc.SudoBin = bin\n\t\t\treturn nil // wrapper or sudo command existing. Retrocompatiblity\n\t\t}\n\t}\n\n\tc.SudoFlags = \"\"\n\tc.SudoLoop = false\n\n\tfor _, bin := range [...]string{\"run0\", \"doas\", \"pkexec\", \"su\"} {\n\t\tif _, err := exec.LookPath(bin); err == nil {\n\t\t\tc.SudoBin = bin\n\t\t\treturn nil // command existing\n\t\t}\n\t}\n\n\treturn &ErrPrivilegeElevatorNotFound{confValue: c.SudoBin}\n}\n\nfunc DefaultConfig(version string) *Configuration {\n\tcfg := &Configuration{\n\t\tVersion: version,\n\t\tMode:    parser.ModeAny,\n\t}\n\n\t// Load defaults from embedded INI\n\tiniCfg, err := ini.LoadSources(ini.LoadOptions{\n\t\tAllowBooleanKeys:    true,\n\t\tInsensitive:         true,\n\t\tInsensitiveSections: true,\n\t\tIgnoreInlineComment: true,\n\t}, defaultsINI)\n\tif err != nil {\n\t\t// Fallback to minimal defaults if embedded config fails\n\t\tcfg.AURURL = \"https://aur.archlinux.org\"\n\t\tcfg.BuildDir = os.ExpandEnv(\"$HOME/.cache/yay\")\n\t\treturn cfg\n\t}\n\n\t// Map the default section\n\t_ = iniCfg.Section(\"\").MapTo(cfg)\n\n\t// Also map [options] section if present\n\tif iniCfg.HasSection(\"options\") {\n\t\t_ = iniCfg.Section(\"options\").MapTo(cfg)\n\t}\n\n\treturn cfg\n}\n\nfunc NewConfig(logger *text.Logger, configPath, version string) (*Configuration, error) {\n\tnewConfig := DefaultConfig(version)\n\n\tcacheHome, errCache := getCacheHome()\n\tif errCache != nil && logger != nil {\n\t\tlogger.Errorln(errCache)\n\t}\n\n\tnewConfig.BuildDir = cacheHome\n\tnewConfig.CompletionPath = filepath.Join(cacheHome, completionFileName)\n\tnewConfig.VCSFilePath = filepath.Join(cacheHome, vcsFileName)\n\n\t// Load system-wide INI config first (silently ignored if not present)\n\tif err := newConfig.loadINI(SystemConfigPath); err != nil && logger != nil {\n\t\tlogger.Errorln(err)\n\t}\n\n\t// Load user JSON config (legacy, overrides system config)\n\tnewConfig.load(configPath)\n\n\t// Load user INI config (takes priority over JSON when both exist)\n\tuserINIPath := GetINIConfigPath()\n\tif userINIPath != \"\" {\n\t\tif err := newConfig.loadINI(userINIPath); err != nil && logger != nil {\n\t\t\tlogger.Errorln(err)\n\t\t}\n\t}\n\n\tif aurdest := os.Getenv(\"AURDEST\"); aurdest != \"\" {\n\t\tnewConfig.BuildDir = aurdest\n\t}\n\n\tnewConfig.expandEnv()\n\n\tif newConfig.BuildDir != systemdCache {\n\t\terrBuildDir := initDir(newConfig.BuildDir)\n\t\tif errBuildDir != nil {\n\t\t\treturn nil, errBuildDir\n\t\t}\n\t}\n\n\tif errPE := newConfig.setPrivilegeElevator(); errPE != nil {\n\t\treturn nil, errPE\n\t}\n\n\treturn newConfig, nil\n}\n\nfunc (c *Configuration) load(configPath string) {\n\tcfile, err := os.Open(configPath)\n\tif !os.IsNotExist(err) && err != nil {\n\t\tfmt.Fprintln(os.Stderr,\n\t\t\tgotext.Get(\"failed to open config file '%s': %s\", configPath, err))\n\t\treturn\n\t}\n\n\tdefer cfile.Close()\n\n\tif !os.IsNotExist(err) {\n\t\tdecoder := json.NewDecoder(cfile)\n\t\tif err = decoder.Decode(c); err != nil {\n\t\t\tfmt.Fprintln(os.Stderr,\n\t\t\t\tgotext.Get(\"failed to read config file '%s': %s\", configPath, err))\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "pkg/settings/config_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage settings\n\nimport (\n\t\"encoding/json\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n)\n\n// GIVEN a non existing build dir in the config\n// WHEN the config is loaded\n// THEN the directory should be created\nfunc TestNewConfig(t *testing.T) {\n\tconfigDir := t.TempDir()\n\terr := os.MkdirAll(filepath.Join(configDir, \"yay\"), 0o755)\n\tassert.NoError(t, err)\n\n\tt.Setenv(\"XDG_CONFIG_HOME\", configDir)\n\n\tcacheDir := t.TempDir()\n\n\tconfig := map[string]string{\"BuildDir\": filepath.Join(cacheDir, \"test-build-dir\")}\n\n\tf, err := os.Create(filepath.Join(configDir, \"yay\", \"config.json\"))\n\tassert.NoError(t, err)\n\n\tdefer f.Close()\n\n\tconfigJSON, _ := json.Marshal(config)\n\t_, err = f.WriteString(string(configJSON))\n\tassert.NoError(t, err)\n\n\tnewConfig, err := NewConfig(nil, GetConfigPath(), \"v1.0.0\")\n\tassert.NoError(t, err)\n\n\tassert.Equal(t, filepath.Join(cacheDir, \"test-build-dir\"), newConfig.BuildDir)\n\n\t_, err = os.Stat(filepath.Join(cacheDir, \"test-build-dir\"))\n\tassert.NoError(t, err)\n}\n\n// GIVEN a non existing build dir in the config and AURDEST set to a non-existing folder\n// WHEN the config is loaded\n// THEN the directory of AURDEST should be created and selected\nfunc TestNewConfigAURDEST(t *testing.T) {\n\tconfigDir := t.TempDir()\n\terr := os.MkdirAll(filepath.Join(configDir, \"yay\"), 0o755)\n\tassert.NoError(t, err)\n\n\tt.Setenv(\"XDG_CONFIG_HOME\", configDir)\n\n\tcacheDir := t.TempDir()\n\n\tconfig := map[string]string{\"BuildDir\": filepath.Join(cacheDir, \"test-other-dir\")}\n\tt.Setenv(\"AURDEST\", filepath.Join(cacheDir, \"test-build-dir\"))\n\n\tf, err := os.Create(filepath.Join(configDir, \"yay\", \"config.json\"))\n\tassert.NoError(t, err)\n\n\tdefer f.Close()\n\n\tconfigJSON, _ := json.Marshal(config)\n\t_, err = f.WriteString(string(configJSON))\n\tassert.NoError(t, err)\n\n\tnewConfig, err := NewConfig(nil, GetConfigPath(), \"v1.0.0\")\n\tassert.NoError(t, err)\n\n\tassert.Equal(t, filepath.Join(cacheDir, \"test-build-dir\"), newConfig.BuildDir)\n\n\t_, err = os.Stat(filepath.Join(cacheDir, \"test-build-dir\"))\n\tassert.NoError(t, err)\n}\n\n// Test tilde expansion in AURDEST\nfunc TestNewConfigAURDESTTildeExpansion(t *testing.T) {\n\tconfigDir := t.TempDir()\n\terr := os.MkdirAll(filepath.Join(configDir, \"yay\"), 0o755)\n\tassert.NoError(t, err)\n\n\tt.Setenv(\"XDG_CONFIG_HOME\", configDir)\n\n\thomeDir := t.TempDir()\n\tcacheDir := t.TempDir()\n\n\tconfig := map[string]string{\"BuildDir\": filepath.Join(cacheDir, \"test-other-dir\")}\n\tt.Setenv(\"AURDEST\", \"~/test-build-dir\")\n\tt.Setenv(\"HOME\", homeDir)\n\n\tf, err := os.Create(filepath.Join(configDir, \"yay\", \"config.json\"))\n\tassert.NoError(t, err)\n\n\tdefer f.Close()\n\n\tconfigJSON, _ := json.Marshal(config)\n\t_, err = f.WriteString(string(configJSON))\n\tassert.NoError(t, err)\n\n\tnewConfig, err := NewConfig(nil, GetConfigPath(), \"v1.0.0\")\n\tassert.NoError(t, err)\n\n\tassert.Equal(t, filepath.Join(homeDir, \"test-build-dir\"), newConfig.BuildDir)\n\n\t_, err = os.Stat(filepath.Join(homeDir, \"test-build-dir\"))\n\tassert.NoError(t, err)\n}\n\n// GIVEN default config\n// WHEN setPrivilegeElevator gets called\n// THEN sudobin should stay as \"sudo\" (given sudo exists)\nfunc TestConfiguration_setPrivilegeElevator(t *testing.T) {\n\tpath := t.TempDir()\n\n\tdoas := filepath.Join(path, \"sudo\")\n\t_, err := os.Create(doas)\n\tos.Chmod(doas, 0o755)\n\tassert.NoError(t, err)\n\n\tconfig := DefaultConfig(\"test\")\n\tconfig.SudoLoop = true\n\tconfig.SudoFlags = \"-v\"\n\n\tt.Setenv(\"PATH\", path)\n\terr = config.setPrivilegeElevator()\n\tassert.NoError(t, err)\n\n\tassert.Equal(t, \"sudo\", config.SudoBin)\n\tassert.Equal(t, \"-v\", config.SudoFlags)\n\tassert.True(t, config.SudoLoop)\n}\n\n// GIVEN default config and sudo loop enabled\n// GIVEN only su in path\n// WHEN setPrivilegeElevator gets called\n// THEN sudobin should be changed to \"su\"\nfunc TestConfiguration_setPrivilegeElevator_su(t *testing.T) {\n\tpath := t.TempDir()\n\n\tdoas := filepath.Join(path, \"su\")\n\t_, err := os.Create(doas)\n\tos.Chmod(doas, 0o755)\n\tassert.NoError(t, err)\n\n\tconfig := DefaultConfig(\"test\")\n\tconfig.SudoLoop = true\n\tconfig.SudoFlags = \"-v\"\n\n\tt.Setenv(\"PATH\", path)\n\terr = config.setPrivilegeElevator()\n\n\tassert.NoError(t, err)\n\tassert.Equal(t, \"su\", config.SudoBin)\n\tassert.Equal(t, \"\", config.SudoFlags)\n\tassert.False(t, config.SudoLoop)\n}\n\n// GIVEN default config and sudo loop enabled\n// GIVEN no sudo in path\n// WHEN setPrivilegeElevator gets called\n// THEN sudobin should be changed to \"su\"\nfunc TestConfiguration_setPrivilegeElevator_no_path(t *testing.T) {\n\tt.Setenv(\"PATH\", \"\")\n\tconfig := DefaultConfig(\"test\")\n\tconfig.SudoLoop = true\n\tconfig.SudoFlags = \"-v\"\n\n\terr := config.setPrivilegeElevator()\n\n\tassert.Error(t, err)\n\tassert.Equal(t, \"sudo\", config.SudoBin)\n\tassert.Equal(t, \"\", config.SudoFlags)\n\tassert.False(t, config.SudoLoop)\n}\n\n// GIVEN default config and sudo loop enabled\n// GIVEN doas in path\n// WHEN setPrivilegeElevator gets called\n// THEN sudobin should be changed to \"doas\"\nfunc TestConfiguration_setPrivilegeElevator_doas(t *testing.T) {\n\tpath := t.TempDir()\n\n\tdoas := filepath.Join(path, \"doas\")\n\t_, err := os.Create(doas)\n\tos.Chmod(doas, 0o755)\n\tassert.NoError(t, err)\n\n\tconfig := DefaultConfig(\"test\")\n\tconfig.SudoLoop = true\n\tconfig.SudoFlags = \"-v\"\n\n\tt.Setenv(\"PATH\", path)\n\terr = config.setPrivilegeElevator()\n\tassert.NoError(t, err)\n\tassert.Equal(t, \"doas\", config.SudoBin)\n\tassert.Equal(t, \"\", config.SudoFlags)\n\tassert.False(t, config.SudoLoop)\n}\n\n// GIVEN default config and sudo loop enabled\n// GIVEN run0 in path\n// WHEN setPrivilegeElevator gets called\n// THEN sudobin should be changed to \"run0\"\nfunc TestConfiguration_setPrivilegeElevator_run0(t *testing.T) {\n\tpath := t.TempDir()\n\n\tdoas := filepath.Join(path, \"run0\")\n\t_, err := os.Create(doas)\n\tos.Chmod(doas, 0o755)\n\tassert.NoError(t, err)\n\n\tconfig := DefaultConfig(\"test\")\n\tconfig.SudoLoop = true\n\tconfig.SudoFlags = \"-v\"\n\n\tt.Setenv(\"PATH\", path)\n\terr = config.setPrivilegeElevator()\n\tassert.NoError(t, err)\n\tassert.Equal(t, \"run0\", config.SudoBin)\n\tassert.Equal(t, \"\", config.SudoFlags)\n\tassert.False(t, config.SudoLoop)\n}\n\n// GIVEN config with wrapper and sudo loop enabled\n// GIVEN wrapper is in path\n// WHEN setPrivilegeElevator gets called\n// THEN sudobin should be kept as the wrapper\nfunc TestConfiguration_setPrivilegeElevator_custom_script(t *testing.T) {\n\tpath := t.TempDir()\n\n\twrapper := filepath.Join(path, \"custom-wrapper\")\n\t_, err := os.Create(wrapper)\n\tos.Chmod(wrapper, 0o755)\n\tassert.NoError(t, err)\n\n\tconfig := DefaultConfig(\"test\")\n\tconfig.SudoLoop = true\n\tconfig.SudoBin = wrapper\n\tconfig.SudoFlags = \"-v\"\n\n\tt.Setenv(\"PATH\", path)\n\terr = config.setPrivilegeElevator()\n\n\tassert.NoError(t, err)\n\tassert.Equal(t, wrapper, config.SudoBin)\n\tassert.Equal(t, \"-v\", config.SudoFlags)\n\tassert.True(t, config.SudoLoop)\n}\n\n// GIVEN default config and sudo loop enabled\n// GIVEN doas as PACMAN_AUTH env variable\n// WHEN setPrivilegeElevator gets called\n// THEN sudobin should be changed to \"doas\"\nfunc TestConfiguration_setPrivilegeElevator_pacman_auth_doas(t *testing.T) {\n\tpath := t.TempDir()\n\n\tdoas := filepath.Join(path, \"doas\")\n\t_, err := os.Create(doas)\n\tos.Chmod(doas, 0o755)\n\trequire.NoError(t, err)\n\n\tsudo := filepath.Join(path, \"sudo\")\n\t_, err = os.Create(sudo)\n\tos.Chmod(sudo, 0o755)\n\trequire.NoError(t, err)\n\n\tconfig := DefaultConfig(\"test\")\n\tconfig.SudoBin = \"sudo\"\n\tconfig.SudoLoop = true\n\tconfig.SudoFlags = \"-v\"\n\n\tt.Setenv(\"PACMAN_AUTH\", \"doas\")\n\tt.Setenv(\"PATH\", path)\n\terr = config.setPrivilegeElevator()\n\tassert.NoError(t, err)\n\tassert.Equal(t, \"doas\", config.SudoBin)\n\tassert.Equal(t, \"\", config.SudoFlags)\n\tassert.False(t, config.SudoLoop)\n}\n\n// GIVEN config with doas configed and sudo loop enabled\n// GIVEN sudo as PACMAN_AUTH env variable\n// WHEN setPrivilegeElevator gets called\n// THEN sudobin should be changed to \"sudo\"\nfunc TestConfiguration_setPrivilegeElevator_pacman_auth_sudo(t *testing.T) {\n\tpath := t.TempDir()\n\n\tdoas := filepath.Join(path, \"doas\")\n\t_, err := os.Create(doas)\n\tos.Chmod(doas, 0o755)\n\trequire.NoError(t, err)\n\n\tsudo := filepath.Join(path, \"sudo\")\n\t_, err = os.Create(sudo)\n\tos.Chmod(sudo, 0o755)\n\trequire.NoError(t, err)\n\n\tconfig := DefaultConfig(\"test\")\n\tconfig.SudoBin = \"doas\"\n\tconfig.SudoLoop = true\n\tconfig.SudoFlags = \"-v\"\n\n\tt.Setenv(\"PACMAN_AUTH\", \"sudo\")\n\tt.Setenv(\"PATH\", path)\n\terr = config.setPrivilegeElevator()\n\tassert.NoError(t, err)\n\tassert.Equal(t, \"sudo\", config.SudoBin)\n\tassert.Equal(t, \"-v\", config.SudoFlags)\n\tassert.True(t, config.SudoLoop)\n}\n"
  },
  {
    "path": "pkg/settings/dirs.go",
    "content": "package settings\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n)\n\nconst (\n\tconfigFileName     string = \"config.json\" // configFileName holds the name of the config file.\n\tiniConfigFileName  string = \"yay.conf\"    // iniConfigFileName holds the name of the INI config file.\n\tvcsFileName        string = \"vcs.json\"    // vcsFileName holds the name of the vcs file.\n\tcompletionFileName string = \"completion.cache\"\n\tsystemdCache       string = \"/var/cache/yay\" // systemd should handle cache creation\n)\n\nfunc GetConfigPath() string {\n\tif configHome := os.Getenv(\"XDG_CONFIG_HOME\"); configHome != \"\" {\n\t\tconfigDir := filepath.Join(configHome, \"yay\")\n\t\tif err := initDir(configDir); err == nil {\n\t\t\treturn filepath.Join(configDir, configFileName)\n\t\t}\n\t}\n\n\tif configHome := os.Getenv(\"HOME\"); configHome != \"\" {\n\t\tconfigDir := filepath.Join(configHome, \".config\", \"yay\")\n\t\tif err := initDir(configDir); err == nil {\n\t\t\treturn filepath.Join(configDir, configFileName)\n\t\t}\n\t}\n\n\treturn \"\"\n}\n\n// GetINIConfigPath returns the path to the user's INI config file (yay.conf).\n// This is used for both loading (with priority over JSON) and saving.\nfunc GetINIConfigPath() string {\n\tif configHome := os.Getenv(\"XDG_CONFIG_HOME\"); configHome != \"\" {\n\t\tconfigDir := filepath.Join(configHome, \"yay\")\n\t\tif err := initDir(configDir); err == nil {\n\t\t\treturn filepath.Join(configDir, iniConfigFileName)\n\t\t}\n\t}\n\n\tif configHome := os.Getenv(\"HOME\"); configHome != \"\" {\n\t\tconfigDir := filepath.Join(configHome, \".config\", \"yay\")\n\t\tif err := initDir(configDir); err == nil {\n\t\t\treturn filepath.Join(configDir, iniConfigFileName)\n\t\t}\n\t}\n\n\treturn \"\"\n}\n\nfunc getCacheHome() (string, error) {\n\tuid := os.Geteuid()\n\n\tif cacheHome := os.Getenv(\"XDG_CACHE_HOME\"); cacheHome != \"\" && uid != 0 {\n\t\tcacheDir := filepath.Join(cacheHome, \"yay\")\n\t\tif err := initDir(cacheDir); err == nil {\n\t\t\treturn cacheDir, nil\n\t\t}\n\t}\n\n\tif cacheHome := os.Getenv(\"HOME\"); cacheHome != \"\" && uid != 0 {\n\t\tcacheDir := filepath.Join(cacheHome, \".cache\", \"yay\")\n\t\tif err := initDir(cacheDir); err == nil {\n\t\t\treturn cacheDir, nil\n\t\t}\n\t}\n\n\tif uid == 0 && os.Getenv(\"SUDO_USER\") == \"\" && os.Getenv(\"DOAS_USER\") == \"\" {\n\t\treturn systemdCache, nil // Don't create directory if systemd-run takes care of it\n\t}\n\n\ttmpDir := filepath.Join(os.TempDir(), \"yay\")\n\n\treturn tmpDir, initDir(tmpDir)\n}\n\nfunc initDir(dir string) error {\n\tif _, err := os.Stat(dir); os.IsNotExist(err) {\n\t\tif err = os.MkdirAll(dir, 0o755); err != nil {\n\t\t\treturn &ErrRuntimeDir{inner: err, dir: dir}\n\t\t}\n\t} else if err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/settings/dirs_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage settings\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n)\n\n// GIVEN no user directories and sudo user\n// WHEN cache home is selected\n// THEN the selected cache home should be in the tmp dir\nfunc Test_getCacheHome(t *testing.T) {\n\tdir := t.TempDir()\n\trequire.NoError(t, os.Unsetenv(\"XDG_CACHE_HOME\"))\n\trequire.NoError(t, os.Unsetenv(\"HOME\"))\n\tt.Setenv(\"SUDO_USER\", \"test\")\n\tt.Setenv(\"TMPDIR\", dir)\n\n\tgot, err := getCacheHome()\n\trequire.NoError(t, err)\n\tassert.Equal(t, filepath.Join(dir, \"yay\"), got)\n\n\trequire.NoError(t, os.Unsetenv(\"TMPDIR\"))\n\trequire.NoError(t, os.Unsetenv(\"SUDO_USER\"))\n}\n"
  },
  {
    "path": "pkg/settings/errors.go",
    "content": "package settings\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/leonelquinteros/gotext\"\n)\n\ntype ErrPrivilegeElevatorNotFound struct {\n\tconfValue string\n}\n\nfunc (e *ErrPrivilegeElevatorNotFound) Error() string {\n\treturn fmt.Sprintf(\"unable to find a privilege elevator, config value: %s\", e.confValue)\n}\n\ntype ErrRuntimeDir struct {\n\tinner error\n\tdir   string\n}\n\nfunc (e *ErrRuntimeDir) Error() string {\n\treturn gotext.Get(\"failed to create directory '%s': %s\", e.dir, e.inner)\n}\n\ntype ErrUserAbort struct{}\n\nfunc (e ErrUserAbort) Error() string {\n\treturn gotext.Get(\"aborting due to user\")\n}\n"
  },
  {
    "path": "pkg/settings/exe/cmd_builder.go",
    "content": "package exe\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"os/user\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n\t\"syscall\"\n\t\"time\"\n\n\tmapset \"github.com/deckarep/golang-set/v2\"\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\nconst SudoLoopDuration = 241\n\nvar gitDenyList = mapset.NewThreadUnsafeSet(\n\t\"GIT_WORK_TREE\",\n\t\"GIT_DIR\",\n)\n\ntype GitCmdBuilder interface {\n\tRunner\n\tBuildGitCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd\n}\n\ntype ICmdBuilder interface {\n\tRunner\n\tBuildGitCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd\n\tBuildGPGCmd(ctx context.Context, extraArgs ...string) *exec.Cmd\n\tBuildMakepkgCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd\n\tBuildPacmanCmd(ctx context.Context, args *parser.Arguments, mode parser.TargetMode, noConfirm bool) *exec.Cmd\n\tAddMakepkgFlag(string)\n\tGetKeepSrc() bool\n\tSudoLoop()\n}\n\ntype CmdBuilder struct {\n\tGitBin           string\n\tGitFlags         []string\n\tGPGBin           string\n\tGPGFlags         []string\n\tMakepkgFlags     []string\n\tMakepkgConfPath  string\n\tMakepkgBin       string\n\tSudoBin          string\n\tSudoFlags        []string\n\tSudoLoopEnabled  bool\n\tPacmanBin        string\n\tPacmanConfigPath string\n\tPacmanDBPath     string\n\tKeepSrc          bool\n\tRunner           Runner\n\tLog              *text.Logger\n}\n\nfunc NewCmdBuilder(cfg *settings.Configuration, runner Runner, logger *text.Logger, dbPath string) *CmdBuilder {\n\treturn &CmdBuilder{\n\t\tGitBin:           cfg.GitBin,\n\t\tGitFlags:         strings.Fields(cfg.GitFlags),\n\t\tGPGBin:           cfg.GpgBin,\n\t\tGPGFlags:         strings.Fields(cfg.GpgFlags),\n\t\tMakepkgFlags:     strings.Fields(cfg.MFlags),\n\t\tMakepkgConfPath:  cfg.MakepkgConf,\n\t\tMakepkgBin:       cfg.MakepkgBin,\n\t\tSudoBin:          cfg.SudoBin,\n\t\tSudoFlags:        strings.Fields(cfg.SudoFlags),\n\t\tSudoLoopEnabled:  cfg.SudoLoop,\n\t\tPacmanBin:        cfg.PacmanBin,\n\t\tPacmanConfigPath: cfg.PacmanConf,\n\t\tPacmanDBPath:     dbPath,\n\t\tKeepSrc:          cfg.KeepSrc,\n\t\tRunner:           runner,\n\t\tLog:              logger,\n\t}\n}\n\nfunc (c *CmdBuilder) BuildGPGCmd(ctx context.Context, extraArgs ...string) *exec.Cmd {\n\targs := make([]string, len(c.GPGFlags), len(c.GPGFlags)+len(extraArgs))\n\tcopy(args, c.GPGFlags)\n\n\tif len(extraArgs) > 0 {\n\t\targs = append(args, extraArgs...)\n\t}\n\n\tcmd := exec.CommandContext(ctx, c.GPGBin, args...)\n\n\tcmd = c.deElevateCommand(ctx, cmd)\n\n\treturn cmd\n}\n\nfunc gitFilteredEnv() []string {\n\tvar env []string\n\n\tfor _, envVar := range os.Environ() {\n\t\tenvKey := strings.SplitN(envVar, \"=\", 2)[0]\n\t\tif !gitDenyList.Contains(envKey) {\n\t\t\tenv = append(env, envVar)\n\t\t}\n\t}\n\n\tenv = append(env, \"GIT_TERMINAL_PROMPT=0\")\n\n\treturn env\n}\n\nfunc (c *CmdBuilder) BuildGitCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd {\n\targs := make([]string, len(c.GitFlags), len(c.GitFlags)+len(extraArgs))\n\tcopy(args, c.GitFlags)\n\n\tif dir != \"\" {\n\t\targs = append(args, \"-C\", dir)\n\t}\n\n\tif len(extraArgs) > 0 {\n\t\targs = append(args, extraArgs...)\n\t}\n\n\tcmd := exec.CommandContext(ctx, c.GitBin, args...)\n\n\tcmd.Env = gitFilteredEnv()\n\n\tcmd = c.deElevateCommand(ctx, cmd)\n\n\treturn cmd\n}\n\nfunc (c *CmdBuilder) AddMakepkgFlag(flag string) {\n\tc.MakepkgFlags = append(c.MakepkgFlags, flag)\n}\n\nfunc (c *CmdBuilder) BuildMakepkgCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd {\n\targs := make([]string, len(c.MakepkgFlags), len(c.MakepkgFlags)+len(extraArgs))\n\tcopy(args, c.MakepkgFlags)\n\n\tif c.MakepkgConfPath != \"\" {\n\t\targs = append(args, \"--config\", c.MakepkgConfPath)\n\t}\n\n\tif len(extraArgs) > 0 {\n\t\targs = append(args, extraArgs...)\n\t}\n\n\tcmd := exec.CommandContext(ctx, c.MakepkgBin, args...)\n\tcmd.Dir = dir\n\n\tcmd = c.deElevateCommand(ctx, cmd)\n\n\treturn cmd\n}\n\n// deElevateCommand, `systemd-run` code based on pikaur.\nfunc (c *CmdBuilder) deElevateCommand(ctx context.Context, cmd *exec.Cmd) *exec.Cmd {\n\tif os.Geteuid() != 0 {\n\t\treturn cmd\n\t}\n\n\togCaller := \"\"\n\tif caller := os.Getenv(\"SUDO_USER\"); caller != \"\" {\n\t\togCaller = caller\n\t} else if caller := os.Getenv(\"DOAS_USER\"); caller != \"\" {\n\t\togCaller = caller\n\t}\n\n\tif userFound, err := user.Lookup(ogCaller); err == nil {\n\t\tcmd.SysProcAttr = &syscall.SysProcAttr{}\n\t\tuid64, errUid := strconv.ParseUint(userFound.Uid, 10, 32)\n\t\tgid64, errGid := strconv.ParseUint(userFound.Gid, 10, 32)\n\t\tif errUid == nil && errGid == nil {\n\t\t\tcmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid64), Gid: uint32(gid64)}\n\t\t\treturn cmd\n\t\t}\n\t}\n\n\tcmdArgs := []string{\n\t\t\"--service-type=oneshot\",\n\t\t\"--pipe\", \"--wait\", \"--pty\", \"--quiet\",\n\t\t\"-p\", \"DynamicUser=yes\",\n\t\t\"-p\", \"CacheDirectory=yay\",\n\t\t\"-E\", \"HOME=/tmp\",\n\t}\n\n\tif cmd.Dir != \"\" {\n\t\tcmdArgs = append(cmdArgs, \"-p\", fmt.Sprintf(\"WorkingDirectory=%s\", cmd.Dir))\n\t}\n\n\tfor _, envVarName := range [...]string{\"http_proxy\", \"https_proxy\", \"ftp_proxy\"} {\n\t\tif env := os.Getenv(envVarName); env != \"\" {\n\t\t\tcmdArgs = append(cmdArgs, \"-E\", fmt.Sprintf(\"%s=%s\", envVarName, env))\n\t\t}\n\t}\n\n\tpath, _ := exec.LookPath(cmd.Args[0])\n\n\tcmdArgs = append(cmdArgs, path)\n\tcmdArgs = append(cmdArgs, cmd.Args[1:]...)\n\n\tsystemdCmd := exec.CommandContext(ctx, \"systemd-run\", cmdArgs...) // #nosec G702\n\tsystemdCmd.Dir = cmd.Dir\n\n\treturn systemdCmd\n}\n\nfunc (c *CmdBuilder) buildPrivilegeElevatorCommand(ctx context.Context, ogArgs []string) *exec.Cmd {\n\tif c.SudoBin == \"su\" {\n\t\treturn exec.CommandContext(ctx, c.SudoBin, \"-c\", strings.Join(ogArgs, \" \"))\n\t}\n\n\targArr := make([]string, 0, len(c.SudoFlags)+len(ogArgs))\n\targArr = append(argArr, c.SudoFlags...)\n\targArr = append(argArr, ogArgs...)\n\n\treturn exec.CommandContext(ctx, c.SudoBin, argArr...)\n}\n\nfunc (c *CmdBuilder) BuildPacmanCmd(ctx context.Context, args *parser.Arguments, mode parser.TargetMode, noConfirm bool) *exec.Cmd {\n\targArr := make([]string, 0, 32)\n\tneedsRoot := args.NeedRoot(mode)\n\n\targArr = append(argArr, c.PacmanBin)\n\targArr = append(argArr, args.FormatGlobals()...)\n\targArr = append(argArr, args.FormatArgs()...)\n\n\tif noConfirm {\n\t\targArr = append(argArr, \"--noconfirm\")\n\t}\n\n\targArr = append(argArr, \"--config\", c.PacmanConfigPath, \"--\")\n\targArr = append(argArr, args.Targets...)\n\n\tif needsRoot {\n\t\tc.waitLock(c.PacmanDBPath)\n\n\t\tif os.Geteuid() != 0 {\n\t\t\treturn c.buildPrivilegeElevatorCommand(ctx, argArr)\n\t\t}\n\t}\n\n\treturn exec.CommandContext(ctx, argArr[0], argArr[1:]...)\n}\n\n// waitLock will lock yay checking the status of db.lck until it does not exist.\nfunc (c *CmdBuilder) waitLock(dbPath string) {\n\tlockDBPath := filepath.Join(dbPath, \"db.lck\")\n\tif _, err := os.Stat(lockDBPath); err != nil {\n\t\treturn\n\t}\n\n\tc.Log.Warnln(gotext.Get(\"%s is present.\", lockDBPath))\n\tc.Log.Warn(gotext.Get(\"There may be another Pacman instance running. Waiting...\"))\n\n\tfor {\n\t\ttime.Sleep(3 * time.Second)\n\n\t\tif _, err := os.Stat(lockDBPath); err != nil {\n\t\t\tc.Log.Println()\n\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc (c *CmdBuilder) SudoLoop() {\n\tc.updateSudo()\n\n\tgo c.sudoLoopBackground()\n}\n\nfunc (c *CmdBuilder) sudoLoopBackground() {\n\tfor {\n\t\tc.updateSudo()\n\t\ttime.Sleep(SudoLoopDuration * time.Second)\n\t}\n}\n\nfunc (c *CmdBuilder) updateSudo() {\n\tfor {\n\t\terr := c.Show(exec.CommandContext(context.Background(), c.SudoBin, \"-v\"))\n\t\tif err != nil {\n\t\t\tc.Log.Errorln(err)\n\t\t} else {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nfunc (c *CmdBuilder) Show(cmd *exec.Cmd) error {\n\treturn c.Runner.Show(cmd)\n}\n\nfunc (c *CmdBuilder) Capture(cmd *exec.Cmd) (stdout, stderr string, err error) {\n\treturn c.Runner.Capture(cmd)\n}\n\nfunc (c *CmdBuilder) GetKeepSrc() bool {\n\treturn c.KeepSrc\n}\n"
  },
  {
    "path": "pkg/settings/exe/exec.go",
    "content": "package exe\n\nimport (\n\t\"errors\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"syscall\"\n\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\ntype Runner interface {\n\tCapture(cmd *exec.Cmd) (stdout string, stderr string, err error)\n\tShow(cmd *exec.Cmd) error\n}\n\ntype OSRunner struct {\n\tLog *text.Logger\n}\n\nfunc NewOSRunner(log *text.Logger) *OSRunner {\n\treturn &OSRunner{log}\n}\n\nfunc (r *OSRunner) Show(cmd *exec.Cmd) error {\n\tcmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr\n\tcmd.SysProcAttr = &syscall.SysProcAttr{\n\t\tPdeathsig: syscall.SIGTERM,\n\t}\n\tr.Log.Debugln(\"running\", cmd.String())\n\treturn cmd.Run()\n}\n\nfunc (r *OSRunner) Capture(cmd *exec.Cmd) (stdout, stderr string, err error) {\n\tr.Log.Debugln(\"capturing\", cmd.String())\n\tcmd.SysProcAttr = &syscall.SysProcAttr{\n\t\tPdeathsig: syscall.SIGTERM,\n\t}\n\n\toutbuf, err := cmd.Output()\n\tstdout = strings.TrimSpace(string(outbuf))\n\n\tif err != nil {\n\t\texitErr := &exec.ExitError{}\n\t\tif errors.As(err, &exitErr) {\n\t\t\tstderr = strings.TrimSpace(string(exitErr.Stderr))\n\t\t}\n\t}\n\n\treturn stdout, stderr, err\n}\n"
  },
  {
    "path": "pkg/settings/exe/mock.go",
    "content": "package exe\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os/exec\"\n\t\"sync\"\n\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n)\n\ntype Call struct {\n\tRes  []any\n\tArgs []any\n\tDir  string\n}\n\nfunc (c *Call) String() string {\n\treturn fmt.Sprintf(\"%+v\", c.Args)\n}\n\ntype MockBuilder struct {\n\tRunner                 Runner\n\tBuildMakepkgCmdCallsMu sync.Mutex\n\tBuildMakepkgCmdCalls   []Call\n\tBuildMakepkgCmdFn      func(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd\n\tBuildPacmanCmdFn       func(ctx context.Context, args *parser.Arguments, mode parser.TargetMode, noConfirm bool) *exec.Cmd\n\tGetKeepSrcFn           func() bool\n}\n\ntype MockRunner struct {\n\tShowCallsMu    sync.Mutex\n\tShowCalls      []Call\n\tCaptureCallsMu sync.Mutex\n\tCaptureCalls   []Call\n\tShowFn         func(cmd *exec.Cmd) error\n\tCaptureFn      func(cmd *exec.Cmd) (stdout string, stderr string, err error)\n}\n\nfunc (m *MockBuilder) BuildGPGCmd(ctx context.Context, extraArgs ...string) *exec.Cmd {\n\treturn exec.CommandContext(ctx, \"gpg\", extraArgs...)\n}\n\nfunc (m *MockBuilder) BuildMakepkgCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd {\n\tvar res *exec.Cmd\n\tif m.BuildMakepkgCmdFn != nil {\n\t\tres = m.BuildMakepkgCmdFn(ctx, dir, extraArgs...)\n\t} else {\n\t\tres = exec.CommandContext(ctx, \"makepkg\", extraArgs...)\n\t}\n\n\tm.BuildMakepkgCmdCallsMu.Lock()\n\tm.BuildMakepkgCmdCalls = append(m.BuildMakepkgCmdCalls, Call{\n\t\tRes: []any{res},\n\t\tArgs: []any{\n\t\t\tctx,\n\t\t\tdir,\n\t\t\textraArgs,\n\t\t},\n\t})\n\tm.BuildMakepkgCmdCallsMu.Unlock()\n\n\treturn res\n}\n\nfunc (m *MockBuilder) AddMakepkgFlag(flag string) {\n}\n\nfunc (m *MockBuilder) BuildGitCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd {\n\treturn exec.CommandContext(ctx, \"git\", extraArgs...)\n}\n\nfunc (m *MockBuilder) BuildPacmanCmd(ctx context.Context, args *parser.Arguments, mode parser.TargetMode, noConfirm bool) *exec.Cmd {\n\tvar res *exec.Cmd\n\n\tif m.BuildPacmanCmdFn != nil {\n\t\tres = m.BuildPacmanCmdFn(ctx, args, mode, noConfirm)\n\t} else {\n\t\tres = exec.CommandContext(ctx, \"pacman\")\n\t}\n\n\treturn res\n}\n\nfunc (m *MockBuilder) SetPacmanDBPath(path string) {\n}\n\nfunc (m *MockBuilder) SudoLoop() {\n}\n\nfunc (m *MockBuilder) Capture(cmd *exec.Cmd) (stdout, stderr string, err error) {\n\treturn m.Runner.Capture(cmd)\n}\n\nfunc (m *MockBuilder) Show(cmd *exec.Cmd) error {\n\treturn m.Runner.Show(cmd)\n}\n\nfunc (m *MockBuilder) GetKeepSrc() bool {\n\treturn false\n}\n\nfunc (m *MockRunner) Capture(cmd *exec.Cmd) (stdout, stderr string, err error) {\n\tm.CaptureCallsMu.Lock()\n\tm.CaptureCalls = append(m.CaptureCalls, Call{\n\t\tArgs: []any{\n\t\t\tcmd,\n\t\t},\n\t\tDir: cmd.Dir,\n\t})\n\tm.CaptureCallsMu.Unlock()\n\n\tif m.CaptureFn != nil {\n\t\treturn m.CaptureFn(cmd)\n\t}\n\n\treturn \"\", \"\", nil\n}\n\nfunc (m *MockRunner) Show(cmd *exec.Cmd) error {\n\tvar err error\n\tif m.ShowFn != nil {\n\t\terr = m.ShowFn(cmd)\n\t}\n\n\tm.ShowCallsMu.Lock()\n\tm.ShowCalls = append(m.ShowCalls, Call{\n\t\tArgs: []any{\n\t\t\tcmd,\n\t\t},\n\t\tDir: cmd.Dir,\n\t})\n\tm.ShowCallsMu.Unlock()\n\n\treturn err\n}\n"
  },
  {
    "path": "pkg/settings/ini.go",
    "content": "package settings\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"gopkg.in/ini.v1\"\n)\n\n// SystemConfigPath is the path to the system-wide INI configuration file.\nconst SystemConfigPath = \"/etc/yay.conf\"\n\n// loadINI parses an INI configuration file and applies values to the Configuration.\n// It silently returns nil if the file doesn't exist.\n// Uses struct tags for mapping (e.g., `ini:\"AurUrl\"`).\nfunc (c *Configuration) loadINI(path string) error {\n\tif _, err := os.Stat(path); os.IsNotExist(err) {\n\t\treturn nil\n\t}\n\n\tcfg, err := ini.LoadSources(ini.LoadOptions{\n\t\tAllowBooleanKeys:    true,\n\t\tInsensitive:         true,\n\t\tInsensitiveSections: true,\n\t\tIgnoreInlineComment: true,\n\t}, path)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to load INI config file '%s': %w\", path, err)\n\t}\n\n\t// Map the default section to the config struct\n\tif err := cfg.Section(\"\").MapTo(c); err != nil {\n\t\treturn fmt.Errorf(\"failed to map INI config '%s': %w\", path, err)\n\t}\n\n\t// Also map [options] section if present (for compatibility)\n\tif cfg.HasSection(\"options\") {\n\t\tif err := cfg.Section(\"options\").MapTo(c); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to map INI [options] section '%s': %w\", path, err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// SaveINI writes the configuration to an INI file at the specified path.\nfunc (c *Configuration) SaveINI(path string) error {\n\tcfg := ini.Empty(ini.LoadOptions{\n\t\tAllowBooleanKeys: true,\n\t})\n\n\t// Use [options] section for compatibility with system config\n\tsection, err := cfg.NewSection(\"options\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create INI section: %w\", err)\n\t}\n\n\tif err := section.ReflectFrom(c); err != nil {\n\t\treturn fmt.Errorf(\"failed to reflect config to INI: %w\", err)\n\t}\n\n\t// Ensure parent directory exists\n\tif dir := filepath.Dir(path); dir != \"\" {\n\t\tif _, err := os.Stat(dir); os.IsNotExist(err) {\n\t\t\tif mkErr := os.MkdirAll(dir, 0o755); mkErr != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to create config directory: %w\", mkErr)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn cfg.SaveTo(path)\n}\n"
  },
  {
    "path": "pkg/settings/ini_test.go",
    "content": "package settings\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestConfigurationLoadINI(t *testing.T) {\n\tt.Parallel()\n\n\tt.Run(\"load nonexistent file returns nil\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tcfg := DefaultConfig(\"test\")\n\n\t\terr := cfg.loadINI(\"/nonexistent/path/yay.conf\")\n\t\tassert.NoError(t, err)\n\t})\n\n\tt.Run(\"load valid INI file\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\tcontent := `# System-wide yay configuration\n[options]\nAurUrl = https://custom.aur.org\nBuildDir = /var/cache/yay\nEditor = vim\nDevel = true\nSudoLoop = yes\nRequestSplitN = 200\nBottomUp = false\n\n; This is also a comment\nCleanAfter = 1\n`\n\t\ttmpDir := t.TempDir()\n\t\tiniPath := filepath.Join(tmpDir, \"yay.conf\")\n\t\trequire.NoError(t, os.WriteFile(iniPath, []byte(content), 0o644))\n\n\t\tcfg := DefaultConfig(\"test\")\n\t\terr := cfg.loadINI(iniPath)\n\t\trequire.NoError(t, err)\n\n\t\tassert.Equal(t, \"https://custom.aur.org\", cfg.AURURL)\n\t\tassert.Equal(t, \"/var/cache/yay\", cfg.BuildDir)\n\t\tassert.Equal(t, \"vim\", cfg.Editor)\n\t\tassert.True(t, cfg.Devel)\n\t\tassert.True(t, cfg.SudoLoop)\n\t\tassert.Equal(t, 200, cfg.RequestSplitN)\n\t\tassert.False(t, cfg.BottomUp)\n\t\tassert.True(t, cfg.CleanAfter)\n\t})\n\n\tt.Run(\"load INI file with all option types\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\tcontent := `\n# String options\nAurUrl = https://aur.example.com\nAurRpcUrl = https://aur.example.com/rpc\nBuildDir = /tmp/build\nEditor = nvim\nEditorFlags = -p\nMakepkgBin = /usr/bin/makepkg\nMakepkgConf = /etc/makepkg.conf\nPacmanBin = /usr/bin/pacman\nPacmanConf = /etc/pacman.conf\nGitBin = /usr/bin/git\nGpgBin = /usr/bin/gpg\nGpgFlags = --keyserver-options\nMFlags = -s\nSortBy = votes\nSearchBy = name\nGitFlags = --depth=1\nRemoveMake = yes\nSudoBin = doas\nSudoFlags = -n\nReDownload = all\nAnswerClean = All\nAnswerDiff = None\nAnswerEdit = None\nAnswerUpgrade = None\nReBuild = all\n\n# Integer options\nRequestSplitN = 100\nCompletionInterval = 3\nMaxConcurrentDownloads = 4\n\n# Boolean options\nBottomUp = true\nSudoLoop = false\nDevel = no\nCleanAfter = true\nKeepSrc = false\nProvides = true\nPgpFetch = false\nCleanMenu = yes\nDiffMenu = no\nEditMenu = true\nCombinedUpgrade = false\nUseAsk = true\nBatchInstall = false\nSingleLineResults = true\nSeparateSources = false\nDebug = no\nRpc = yes\nDoubleConfirm = false\n`\n\t\ttmpDir := t.TempDir()\n\t\tiniPath := filepath.Join(tmpDir, \"yay.conf\")\n\t\trequire.NoError(t, os.WriteFile(iniPath, []byte(content), 0o644))\n\n\t\tcfg := DefaultConfig(\"test\")\n\t\terr := cfg.loadINI(iniPath)\n\t\trequire.NoError(t, err)\n\n\t\t// String options\n\t\tassert.Equal(t, \"https://aur.example.com\", cfg.AURURL)\n\t\tassert.Equal(t, \"https://aur.example.com/rpc\", cfg.AURRPCURL)\n\t\tassert.Equal(t, \"/tmp/build\", cfg.BuildDir)\n\t\tassert.Equal(t, \"nvim\", cfg.Editor)\n\t\tassert.Equal(t, \"-p\", cfg.EditorFlags)\n\t\tassert.Equal(t, \"/usr/bin/makepkg\", cfg.MakepkgBin)\n\t\tassert.Equal(t, \"/etc/makepkg.conf\", cfg.MakepkgConf)\n\t\tassert.Equal(t, \"/usr/bin/pacman\", cfg.PacmanBin)\n\t\tassert.Equal(t, \"/etc/pacman.conf\", cfg.PacmanConf)\n\t\tassert.Equal(t, \"/usr/bin/git\", cfg.GitBin)\n\t\tassert.Equal(t, \"/usr/bin/gpg\", cfg.GpgBin)\n\t\tassert.Equal(t, \"--keyserver-options\", cfg.GpgFlags)\n\t\tassert.Equal(t, \"-s\", cfg.MFlags)\n\t\tassert.Equal(t, \"votes\", cfg.SortBy)\n\t\tassert.Equal(t, \"name\", cfg.SearchBy)\n\t\tassert.Equal(t, \"--depth=1\", cfg.GitFlags)\n\t\tassert.Equal(t, \"yes\", cfg.RemoveMake)\n\t\tassert.Equal(t, \"doas\", cfg.SudoBin)\n\t\tassert.Equal(t, \"-n\", cfg.SudoFlags)\n\t\tassert.Equal(t, \"all\", cfg.ReDownload)\n\t\tassert.Equal(t, \"All\", cfg.AnswerClean)\n\t\tassert.Equal(t, \"None\", cfg.AnswerDiff)\n\t\tassert.Equal(t, \"None\", cfg.AnswerEdit)\n\t\tassert.Equal(t, \"None\", cfg.AnswerUpgrade)\n\t\tassert.Equal(t, \"all\", string(cfg.ReBuild))\n\n\t\t// Integer options\n\t\tassert.Equal(t, 100, cfg.RequestSplitN)\n\t\tassert.Equal(t, 3, cfg.CompletionInterval)\n\t\tassert.Equal(t, 4, cfg.MaxConcurrentDownloads)\n\n\t\t// Boolean options\n\t\tassert.True(t, cfg.BottomUp)\n\t\tassert.False(t, cfg.SudoLoop)\n\t\tassert.False(t, cfg.Devel)\n\t\tassert.True(t, cfg.CleanAfter)\n\t\tassert.False(t, cfg.KeepSrc)\n\t\tassert.True(t, cfg.Provides)\n\t\tassert.False(t, cfg.PGPFetch)\n\t\tassert.True(t, cfg.CleanMenu)\n\t\tassert.False(t, cfg.DiffMenu)\n\t\tassert.True(t, cfg.EditMenu)\n\t\tassert.False(t, cfg.CombinedUpgrade)\n\t\tassert.True(t, cfg.UseAsk)\n\t\tassert.False(t, cfg.BatchInstall)\n\t\tassert.True(t, cfg.SingleLineResults)\n\t\tassert.False(t, cfg.SeparateSources)\n\t\tassert.False(t, cfg.Debug)\n\t\tassert.True(t, cfg.UseRPC)\n\t\tassert.False(t, cfg.DoubleConfirm)\n\t})\n\n\tt.Run(\"load INI without section header\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\tcontent := `# Config without section header\nAurUrl = https://custom.aur.org\nDevel = true\nRequestSplitN = 250\n`\n\t\ttmpDir := t.TempDir()\n\t\tiniPath := filepath.Join(tmpDir, \"yay.conf\")\n\t\trequire.NoError(t, os.WriteFile(iniPath, []byte(content), 0o644))\n\n\t\tcfg := DefaultConfig(\"test\")\n\t\terr := cfg.loadINI(iniPath)\n\t\trequire.NoError(t, err)\n\n\t\tassert.Equal(t, \"https://custom.aur.org\", cfg.AURURL)\n\t\tassert.True(t, cfg.Devel)\n\t\tassert.Equal(t, 250, cfg.RequestSplitN)\n\t})\n\n\tt.Run(\"load INI with boolean keys (no value)\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\tcontent := `# Boolean keys without values are treated as true\nDevel\nSudoLoop\nCleanAfter\n`\n\t\ttmpDir := t.TempDir()\n\t\tiniPath := filepath.Join(tmpDir, \"yay.conf\")\n\t\trequire.NoError(t, os.WriteFile(iniPath, []byte(content), 0o644))\n\n\t\tcfg := DefaultConfig(\"test\")\n\t\tcfg.Devel = false\n\t\tcfg.SudoLoop = false\n\t\tcfg.CleanAfter = false\n\n\t\terr := cfg.loadINI(iniPath)\n\t\trequire.NoError(t, err)\n\n\t\tassert.True(t, cfg.Devel)\n\t\tassert.True(t, cfg.SudoLoop)\n\t\tassert.True(t, cfg.CleanAfter)\n\t})\n\n\tt.Run(\"unknown options are ignored\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\tcontent := `AurUrl = https://custom.aur.org\nunknownoption = somevalue\nanotherunknown = 123\n`\n\t\ttmpDir := t.TempDir()\n\t\tiniPath := filepath.Join(tmpDir, \"yay.conf\")\n\t\trequire.NoError(t, os.WriteFile(iniPath, []byte(content), 0o644))\n\n\t\tcfg := DefaultConfig(\"test\")\n\t\terr := cfg.loadINI(iniPath)\n\t\trequire.NoError(t, err)\n\n\t\tassert.Equal(t, \"https://custom.aur.org\", cfg.AURURL)\n\t})\n}\n\nfunc TestSystemConfigPath(t *testing.T) {\n\tt.Parallel()\n\tassert.Equal(t, \"/etc/yay.conf\", SystemConfigPath)\n}\n\nfunc TestConfigurationSaveINI(t *testing.T) {\n\tt.Parallel()\n\n\tt.Run(\"save and reload config\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\tcfg := DefaultConfig(\"test\")\n\t\tcfg.AURURL = \"https://custom.aur.org\"\n\t\tcfg.BuildDir = \"/custom/build\"\n\t\tcfg.Editor = \"nvim\"\n\t\tcfg.Devel = true\n\t\tcfg.SudoLoop = true\n\t\tcfg.RequestSplitN = 150\n\t\tcfg.BottomUp = true\n\t\tcfg.CleanAfter = false\n\n\t\ttmpDir := t.TempDir()\n\t\tiniPath := filepath.Join(tmpDir, \"yay.conf\")\n\n\t\terr := cfg.SaveINI(iniPath)\n\t\trequire.NoError(t, err)\n\n\t\t// Verify file was created\n\t\t_, err = os.Stat(iniPath)\n\t\trequire.NoError(t, err)\n\n\t\t// Load into new config and verify values\n\t\tcfg2 := DefaultConfig(\"test\")\n\t\terr = cfg2.loadINI(iniPath)\n\t\trequire.NoError(t, err)\n\n\t\tassert.Equal(t, \"https://custom.aur.org\", cfg2.AURURL)\n\t\tassert.Equal(t, \"/custom/build\", cfg2.BuildDir)\n\t\tassert.Equal(t, \"nvim\", cfg2.Editor)\n\t\tassert.True(t, cfg2.Devel)\n\t\tassert.True(t, cfg2.SudoLoop)\n\t\tassert.Equal(t, 150, cfg2.RequestSplitN)\n\t\tassert.True(t, cfg2.BottomUp)\n\t\tassert.False(t, cfg2.CleanAfter)\n\t})\n\n\tt.Run(\"save creates directory if not exists\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\tcfg := DefaultConfig(\"test\")\n\t\tcfg.AURURL = \"https://test.aur.org\"\n\n\t\ttmpDir := t.TempDir()\n\t\tnestedPath := filepath.Join(tmpDir, \"nested\", \"dir\", \"yay.conf\")\n\n\t\terr := cfg.SaveINI(nestedPath)\n\t\trequire.NoError(t, err)\n\n\t\t// Verify file was created\n\t\t_, err = os.Stat(nestedPath)\n\t\trequire.NoError(t, err)\n\t})\n\n\tt.Run(\"roundtrip preserves all field types\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\tcfg := DefaultConfig(\"test\")\n\t\t// String fields\n\t\tcfg.AURURL = \"https://roundtrip.aur.org\"\n\t\tcfg.AURRPCURL = \"https://roundtrip.aur.org/rpc\"\n\t\tcfg.BuildDir = \"/roundtrip/build\"\n\t\tcfg.Editor = \"emacs\"\n\t\tcfg.EditorFlags = \"-nw\"\n\t\tcfg.SudoBin = \"doas\"\n\t\tcfg.SudoFlags = \"-n\"\n\t\tcfg.ReDownload = \"all\"\n\t\tcfg.ReBuild = \"tree\"\n\n\t\t// Integer fields\n\t\tcfg.RequestSplitN = 75\n\t\tcfg.CompletionInterval = 5\n\t\tcfg.MaxConcurrentDownloads = 8\n\n\t\t// Boolean fields\n\t\tcfg.BottomUp = true\n\t\tcfg.SudoLoop = false\n\t\tcfg.Devel = true\n\t\tcfg.CleanAfter = false\n\t\tcfg.UseRPC = true\n\t\tcfg.BatchInstall = true\n\n\t\ttmpDir := t.TempDir()\n\t\tiniPath := filepath.Join(tmpDir, \"yay.conf\")\n\n\t\terr := cfg.SaveINI(iniPath)\n\t\trequire.NoError(t, err)\n\n\t\tcfg2 := DefaultConfig(\"test\")\n\t\terr = cfg2.loadINI(iniPath)\n\t\trequire.NoError(t, err)\n\n\t\t// Verify all fields\n\t\tassert.Equal(t, cfg.AURURL, cfg2.AURURL)\n\t\tassert.Equal(t, cfg.AURRPCURL, cfg2.AURRPCURL)\n\t\tassert.Equal(t, cfg.BuildDir, cfg2.BuildDir)\n\t\tassert.Equal(t, cfg.Editor, cfg2.Editor)\n\t\tassert.Equal(t, cfg.EditorFlags, cfg2.EditorFlags)\n\t\tassert.Equal(t, cfg.SudoBin, cfg2.SudoBin)\n\t\tassert.Equal(t, cfg.SudoFlags, cfg2.SudoFlags)\n\t\tassert.Equal(t, cfg.ReDownload, cfg2.ReDownload)\n\t\tassert.Equal(t, cfg.ReBuild, cfg2.ReBuild)\n\t\tassert.Equal(t, cfg.RequestSplitN, cfg2.RequestSplitN)\n\t\tassert.Equal(t, cfg.CompletionInterval, cfg2.CompletionInterval)\n\t\tassert.Equal(t, cfg.MaxConcurrentDownloads, cfg2.MaxConcurrentDownloads)\n\t\tassert.Equal(t, cfg.BottomUp, cfg2.BottomUp)\n\t\tassert.Equal(t, cfg.SudoLoop, cfg2.SudoLoop)\n\t\tassert.Equal(t, cfg.Devel, cfg2.Devel)\n\t\tassert.Equal(t, cfg.CleanAfter, cfg2.CleanAfter)\n\t\tassert.Equal(t, cfg.UseRPC, cfg2.UseRPC)\n\t\tassert.Equal(t, cfg.BatchInstall, cfg2.BatchInstall)\n\t})\n}\n"
  },
  {
    "path": "pkg/settings/parser/parser.go",
    "content": "package parser\n\nimport (\n\t\"bufio\"\n\t\"errors\"\n\t\"fmt\"\n\t\"maps\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/leonelquinteros/gotext\"\n)\n\ntype Option struct {\n\tGlobal bool\n\tArgs   []string\n}\n\nfunc (o *Option) Add(args ...string) {\n\tif o.Args == nil {\n\t\to.Args = args\n\t\treturn\n\t}\n\n\to.Args = append(o.Args, args...)\n}\n\nfunc (o *Option) First() string {\n\tif len(o.Args) == 0 {\n\t\treturn \"\"\n\t}\n\n\treturn o.Args[0]\n}\n\nfunc (o *Option) Set(arg string) {\n\to.Args = []string{arg}\n}\n\nfunc (o *Option) String() string {\n\treturn fmt.Sprintf(\"Global:%v Args:%v\", o.Global, o.Args)\n}\n\n// Arguments Parses command line arguments in a way we can interact with programmatically but\n// also in a way that can easily be passed to pacman later on.\ntype Arguments struct {\n\tOp      string\n\tOptions map[string]*Option\n\tTargets []string\n}\n\nfunc (a *Arguments) String() string {\n\treturn fmt.Sprintf(\"Op:%v Options:%+v Targets: %v\", a.Op, a.Options, a.Targets)\n}\n\nfunc (a *Arguments) CreateOrAppendOption(option string, values ...string) {\n\tif a.Options[option] == nil {\n\t\ta.Options[option] = &Option{\n\t\t\tArgs: values,\n\t\t}\n\t} else {\n\t\ta.Options[option].Add(values...)\n\t}\n}\n\nfunc MakeArguments() *Arguments {\n\treturn &Arguments{\n\t\t\"\",\n\t\tmake(map[string]*Option),\n\t\tmake([]string, 0),\n\t}\n}\n\nfunc (a *Arguments) CopyGlobal() *Arguments {\n\tcp := MakeArguments()\n\n\tfor k, v := range a.Options {\n\t\tif v.Global {\n\t\t\tcp.Options[k] = v\n\t\t}\n\t}\n\n\treturn cp\n}\n\nfunc (a *Arguments) Copy() (cp *Arguments) {\n\tcp = MakeArguments()\n\n\tcp.Op = a.Op\n\n\tmaps.Copy(cp.Options, a.Options)\n\n\tcp.Targets = make([]string, len(a.Targets))\n\tcopy(cp.Targets, a.Targets)\n\n\treturn\n}\n\nfunc (a *Arguments) DelArg(options ...string) {\n\tfor _, option := range options {\n\t\tdelete(a.Options, option)\n\t}\n}\n\nfunc (a *Arguments) NeedRoot(mode TargetMode) bool {\n\tif a.ExistsArg(\"h\", \"help\") {\n\t\treturn false\n\t}\n\n\tswitch a.Op {\n\tcase \"D\", \"database\":\n\t\tif a.ExistsArg(\"k\", \"check\") {\n\t\t\treturn false\n\t\t}\n\n\t\treturn true\n\tcase \"F\", \"files\":\n\t\tif a.ExistsArg(\"y\", \"refresh\") {\n\t\t\treturn true\n\t\t}\n\n\t\treturn false\n\tcase \"Q\", \"query\":\n\t\tif a.ExistsArg(\"k\", \"check\") {\n\t\t\treturn true\n\t\t}\n\n\t\treturn false\n\tcase \"R\", \"remove\":\n\t\tif a.ExistsArg(\"p\", \"print\", \"print-format\") {\n\t\t\treturn false\n\t\t}\n\n\t\treturn true\n\tcase \"S\", \"sync\":\n\t\tswitch {\n\t\tcase a.ExistsArg(\"y\", \"refresh\"):\n\t\t\treturn true\n\t\tcase a.ExistsArg(\"p\", \"print\", \"print-format\"):\n\t\t\treturn false\n\t\tcase a.ExistsArg(\"s\", \"search\"):\n\t\t\treturn false\n\t\tcase a.ExistsArg(\"l\", \"list\"):\n\t\t\treturn false\n\t\tcase a.ExistsArg(\"g\", \"groups\"):\n\t\t\treturn false\n\t\tcase a.ExistsArg(\"i\", \"info\"):\n\t\t\treturn false\n\t\tcase a.ExistsArg(\"c\", \"clean\") && mode == ModeAUR:\n\t\t\treturn false\n\t\t}\n\n\t\treturn true\n\tcase \"U\", \"upgrade\":\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\nfunc (a *Arguments) addOP(op string) error {\n\tif a.Op != \"\" {\n\t\treturn errors.New(gotext.Get(\"only one operation may be used at a time\"))\n\t}\n\n\ta.Op = op\n\n\treturn nil\n}\n\nfunc (a *Arguments) addParam(option, arg string) error {\n\tif !isArg(option) {\n\t\treturn errors.New(gotext.Get(\"invalid option '%s'\", option))\n\t}\n\n\tif isOp(option) {\n\t\treturn a.addOP(option)\n\t}\n\n\ta.CreateOrAppendOption(option, strings.Split(arg, \",\")...)\n\n\tif isGlobal(option) {\n\t\ta.Options[option].Global = true\n\t}\n\n\treturn nil\n}\n\nfunc (a *Arguments) AddArg(options ...string) error {\n\tfor _, option := range options {\n\t\terr := a.addParam(option, \"\")\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// Multiple args acts as an OR operator.\nfunc (a *Arguments) ExistsArg(options ...string) bool {\n\tfor _, option := range options {\n\t\tif _, exists := a.Options[option]; exists {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\nfunc (a *Arguments) GetArg(options ...string) (arg string, double, exists bool) {\n\tfor _, option := range options {\n\t\tvalue, exists := a.Options[option]\n\t\tif exists {\n\t\t\treturn value.First(), len(value.Args) >= 2, len(value.Args) >= 1\n\t\t}\n\t}\n\n\treturn arg, false, false\n}\n\nfunc (a *Arguments) GetArgs(option string) (args []string) {\n\tvalue, exists := a.Options[option]\n\tif exists {\n\t\treturn value.Args\n\t}\n\n\treturn nil\n}\n\nfunc (a *Arguments) AddTarget(targets ...string) {\n\ta.Targets = append(a.Targets, targets...)\n}\n\nfunc (a *Arguments) ClearTargets() {\n\ta.Targets = make([]string, 0)\n}\n\n// Multiple args acts as an OR operator.\nfunc (a *Arguments) ExistsDouble(options ...string) bool {\n\tfor _, option := range options {\n\t\tif value, exists := a.Options[option]; exists {\n\t\t\treturn len(value.Args) >= 2\n\t\t}\n\t}\n\n\treturn false\n}\n\nfunc (a *Arguments) FormatArgs() (args []string) {\n\tif a.Op != \"\" {\n\t\targs = append(args, formatArg(a.Op))\n\t}\n\n\tfor option, arg := range a.Options {\n\t\tif arg.Global || option == \"--\" {\n\t\t\tcontinue\n\t\t}\n\n\t\tformattedOption := formatArg(option)\n\t\tfor _, value := range arg.Args {\n\t\t\targs = append(args, formattedOption)\n\t\t\tif hasParam(option) {\n\t\t\t\targs = append(args, value)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn args\n}\n\nfunc (a *Arguments) FormatGlobals() (args []string) {\n\tfor option, arg := range a.Options {\n\t\tif !arg.Global {\n\t\t\tcontinue\n\t\t}\n\n\t\tformattedOption := formatArg(option)\n\n\t\tfor _, value := range arg.Args {\n\t\t\targs = append(args, formattedOption)\n\t\t\tif hasParam(option) {\n\t\t\t\targs = append(args, value)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn args\n}\n\nfunc formatArg(arg string) string {\n\tif len(arg) > 1 {\n\t\targ = \"--\" + arg\n\t} else {\n\t\targ = \"-\" + arg\n\t}\n\n\treturn arg\n}\n\nfunc isArg(arg string) bool {\n\tswitch arg {\n\tcase \"-\", \"--\":\n\tcase \"ask\":\n\tcase \"D\", \"database\":\n\tcase \"Q\", \"query\":\n\tcase \"R\", \"remove\":\n\tcase \"S\", \"sync\":\n\tcase \"T\", \"deptest\":\n\tcase \"U\", \"upgrade\":\n\tcase \"F\", \"files\":\n\tcase \"V\", \"version\":\n\tcase \"h\", \"help\":\n\tcase \"Y\", \"yay\":\n\tcase \"W\", \"web\":\n\tcase \"P\", \"show\":\n\tcase \"B\", \"build\":\n\tcase \"G\", \"getpkgbuild\":\n\tcase \"b\", \"dbpath\":\n\tcase \"r\", \"root\":\n\tcase \"v\", \"verbose\":\n\tcase \"arch\":\n\tcase \"cachedir\":\n\tcase \"color\":\n\tcase \"config\":\n\tcase \"debug\":\n\tcase \"gpgdir\":\n\tcase \"hookdir\":\n\tcase \"logfile\":\n\tcase \"noconfirm\":\n\tcase \"confirm\":\n\tcase \"disable-download-timeout\":\n\tcase \"sysroot\":\n\tcase \"d\", \"nodeps\":\n\tcase \"assume-installed\":\n\tcase \"dbonly\":\n\tcase \"noprogressbar\":\n\tcase \"numberupgrades\":\n\tcase \"noscriptlet\":\n\tcase \"p\", \"print\":\n\tcase \"print-format\":\n\tcase \"asdeps\":\n\tcase \"asexplicit\":\n\tcase \"ignore\":\n\tcase \"ignoregroup\":\n\tcase \"needed\":\n\tcase \"overwrite\":\n\tcase \"f\", \"force\":\n\tcase \"c\", \"changelog\":\n\tcase \"deps\":\n\tcase \"e\", \"explicit\":\n\tcase \"g\", \"groups\":\n\tcase \"i\", \"info\":\n\tcase \"k\", \"check\":\n\tcase \"l\", \"list\":\n\tcase \"m\", \"foreign\":\n\tcase \"n\", \"native\":\n\tcase \"o\", \"owns\":\n\tcase \"file\":\n\tcase \"q\", \"quiet\":\n\tcase \"s\", \"search\":\n\tcase \"t\", \"unrequired\":\n\tcase \"u\", \"upgrades\":\n\tcase \"cascade\":\n\tcase \"nosave\":\n\tcase \"recursive\":\n\tcase \"unneeded\":\n\tcase \"clean\":\n\tcase \"sysupgrade\":\n\tcase \"w\", \"downloadonly\":\n\tcase \"y\", \"refresh\":\n\tcase \"x\", \"regex\":\n\tcase \"machinereadable\":\n\tcase \"disable-sandbox\":\n\t// yay options\n\tcase \"aururl\":\n\tcase \"aurrpcurl\":\n\tcase \"save\":\n\tcase \"afterclean\", \"cleanafter\":\n\tcase \"keepsrc\":\n\tcase \"devel\":\n\tcase \"topdown\":\n\tcase \"bottomup\":\n\tcase \"completioninterval\":\n\tcase \"sortby\":\n\tcase \"searchby\":\n\tcase \"redownload\":\n\tcase \"redownloadall\":\n\tcase \"noredownload\":\n\tcase \"rebuild\":\n\tcase \"rebuildall\":\n\tcase \"rebuildtree\":\n\tcase \"norebuild\":\n\tcase \"batchinstall\":\n\tcase \"answerclean\":\n\tcase \"noanswerclean\":\n\tcase \"answerdiff\":\n\tcase \"noanswerdiff\":\n\tcase \"answeredit\":\n\tcase \"noansweredit\":\n\tcase \"answerupgrade\":\n\tcase \"noanswerupgrade\":\n\tcase \"gpgflags\":\n\tcase \"mflags\":\n\tcase \"gitflags\":\n\tcase \"builddir\":\n\tcase \"editor\":\n\tcase \"editorflags\":\n\tcase \"makepkg\":\n\tcase \"makepkgconf\":\n\tcase \"nomakepkgconf\":\n\tcase \"pacman\":\n\tcase \"git\":\n\tcase \"gpg\":\n\tcase \"sudo\":\n\tcase \"sudoflags\":\n\tcase \"requestsplitn\":\n\tcase \"sudoloop\":\n\tcase \"provides\":\n\tcase \"pgpfetch\":\n\tcase \"cleanmenu\":\n\tcase \"diffmenu\":\n\tcase \"editmenu\":\n\tcase \"useask\":\n\tcase \"combinedupgrade\":\n\tcase \"a\", \"aur\":\n\tcase \"N\", \"repo\":\n\tcase \"removemake\":\n\tcase \"noremovemake\":\n\tcase \"askremovemake\":\n\tcase \"askyesremovemake\":\n\tcase \"complete\":\n\tcase \"stats\":\n\tcase \"news\":\n\tcase \"gendb\":\n\tcase \"currentconfig\":\n\tcase \"defaultconfig\":\n\tcase \"singlelineresults\":\n\tcase \"doublelineresults\":\n\tcase \"separatesources\":\n\tdefault:\n\t\treturn false\n\t}\n\n\treturn true\n}\n\nfunc isOp(op string) bool {\n\tswitch op {\n\tcase \"V\", \"version\":\n\tcase \"D\", \"database\":\n\tcase \"F\", \"files\":\n\tcase \"Q\", \"query\":\n\tcase \"R\", \"remove\":\n\tcase \"S\", \"sync\":\n\tcase \"T\", \"deptest\":\n\tcase \"U\", \"upgrade\":\n\t// yay specific\n\tcase \"Y\", \"yay\":\n\tcase \"W\", \"web\":\n\tcase \"B\", \"build\":\n\tcase \"P\", \"show\":\n\tcase \"G\", \"getpkgbuild\":\n\tdefault:\n\t\treturn false\n\t}\n\n\treturn true\n}\n\nfunc isGlobal(op string) bool {\n\tswitch op {\n\tcase \"b\", \"dbpath\":\n\tcase \"r\", \"root\":\n\tcase \"v\", \"verbose\":\n\tcase \"arch\":\n\tcase \"cachedir\":\n\tcase \"color\":\n\tcase \"config\":\n\tcase \"debug\":\n\tcase \"gpgdir\":\n\tcase \"hookdir\":\n\tcase \"logfile\":\n\tcase \"noconfirm\":\n\tcase \"confirm\":\n\tdefault:\n\t\treturn false\n\t}\n\n\treturn true\n}\n\nfunc hasParam(arg string) bool {\n\tswitch arg {\n\tcase \"dbpath\", \"b\":\n\tcase \"root\", \"r\":\n\tcase \"sysroot\":\n\tcase \"config\":\n\tcase \"ignore\":\n\tcase \"assume-installed\":\n\tcase \"overwrite\":\n\tcase \"ask\":\n\tcase \"cachedir\":\n\tcase \"hookdir\":\n\tcase \"logfile\":\n\tcase \"ignoregroup\":\n\tcase \"arch\":\n\tcase \"print-format\":\n\tcase \"gpgdir\":\n\tcase \"color\":\n\t// yay params\n\tcase \"aururl\":\n\tcase \"aurrpcurl\":\n\tcase \"mflags\":\n\tcase \"gpgflags\":\n\tcase \"gitflags\":\n\tcase \"builddir\":\n\tcase \"editor\":\n\tcase \"editorflags\":\n\tcase \"makepkg\":\n\tcase \"makepkgconf\":\n\tcase \"pacman\":\n\tcase \"git\":\n\tcase \"gpg\":\n\tcase \"sudo\":\n\tcase \"sudoflags\":\n\tcase \"requestsplitn\":\n\tcase \"answerclean\":\n\tcase \"answerdiff\":\n\tcase \"answeredit\":\n\tcase \"answerupgrade\":\n\tcase \"completioninterval\":\n\tcase \"sortby\":\n\tcase \"searchby\":\n\tdefault:\n\t\treturn false\n\t}\n\n\treturn true\n}\n\n// Parses short hand options such as:\n// -Syu -b /some/path -.\nfunc (a *Arguments) parseShortOption(arg, param string) (usedNext bool, err error) {\n\tif arg == \"-\" {\n\t\terr = a.AddArg(\"-\")\n\t\treturn\n\t}\n\n\targ = arg[1:]\n\n\tfor k, _char := range arg {\n\t\tchar := string(_char)\n\n\t\tif hasParam(char) {\n\t\t\tif k < len(arg)-1 {\n\t\t\t\terr = a.addParam(char, arg[k+1:])\n\t\t\t} else {\n\t\t\t\tusedNext = true\n\t\t\t\terr = a.addParam(char, param)\n\t\t\t}\n\n\t\t\tbreak\n\t\t} else {\n\t\t\terr = a.AddArg(char)\n\t\t\tif err != nil {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\n\treturn\n}\n\n// Parses full length options such as:\n// --sync --refresh --sysupgrade --dbpath /some/path --.\nfunc (a *Arguments) parseLongOption(arg, param string) (usedNext bool, err error) {\n\tif arg == \"--\" {\n\t\terr = a.AddArg(arg)\n\t\treturn\n\t}\n\n\targ = arg[2:]\n\n\tswitch split := strings.SplitN(arg, \"=\", 2); {\n\tcase len(split) == 2:\n\t\terr = a.addParam(split[0], split[1])\n\tcase hasParam(arg):\n\t\terr = a.addParam(arg, param)\n\t\tusedNext = true\n\tdefault:\n\t\terr = a.AddArg(arg)\n\t}\n\n\treturn\n}\n\nfunc (a *Arguments) parseStdin() error {\n\tfi, err := os.Stdin.Stat()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Ensure data is piped\n\tif (fi.Mode() & os.ModeCharDevice) != 0 {\n\t\treturn errors.New(gotext.Get(\"argument '-' specified without input on stdin\"))\n\t}\n\n\tscanner := bufio.NewScanner(os.Stdin)\n\tscanner.Split(bufio.ScanLines)\n\n\tfor scanner.Scan() {\n\t\ta.AddTarget(scanner.Text())\n\t}\n\n\treturn os.Stdin.Close()\n}\n\nfunc (a *Arguments) Parse() error {\n\targs := os.Args[1:]\n\tusedNext := false\n\n\tfor k, arg := range args {\n\t\tvar nextArg string\n\n\t\tif usedNext {\n\t\t\tusedNext = false\n\t\t\tcontinue\n\t\t}\n\n\t\tif k+1 < len(args) {\n\t\t\tnextArg = args[k+1]\n\t\t}\n\n\t\tvar err error\n\t\tswitch {\n\t\tcase a.ExistsArg(\"--\"):\n\t\t\ta.AddTarget(arg)\n\t\tcase strings.HasPrefix(arg, \"--\"):\n\t\t\tusedNext, err = a.parseLongOption(arg, nextArg)\n\t\tcase strings.HasPrefix(arg, \"-\"):\n\t\t\tusedNext, err = a.parseShortOption(arg, nextArg)\n\t\tdefault:\n\t\t\ta.AddTarget(arg)\n\t\t}\n\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif a.Op == \"\" {\n\t\tif len(a.Targets) > 0 {\n\t\t\ta.Op = \"Y\"\n\t\t} else {\n\t\t\t// Handle args incompatible with -Syu\n\t\t\tif a.ExistsArg(\"c\", \"clean\") {\n\t\t\t\tfmt.Println(gotext.Get(\"the clean command requires an operation to be specified\"))\n\t\t\t\tfmt.Println(gotext.Get(\"did you mean yay -Scc (clean caches) or yay -Ycc (clean orphaned packages)?\"))\n\n\t\t\t\treturn errors.New(gotext.Get(\"invalid option\"))\n\t\t\t}\n\n\t\t\tif _, err := a.parseShortOption(\"-Syu\", \"\"); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\n\tif a.ExistsArg(\"-\") {\n\t\tif err := a.parseStdin(); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\ta.DelArg(\"-\")\n\n\t\tfile, err := os.Open(\"/dev/tty\")\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tos.Stdin = file\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/settings/parser/parser_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage parser\n\nimport (\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestOption_Add(t *testing.T) {\n\tt.Parallel()\n\ttype fields struct {\n\t\tArgs []string\n\t}\n\ttype args struct {\n\t\targ string\n\t}\n\ttests := []struct {\n\t\tname   string\n\t\tfields fields\n\t\targs   args\n\t\twant   []string\n\t}{\n\t\t{name: \"simple add\", fields: fields{\n\t\t\tArgs: []string{\"a\", \"b\"},\n\t\t}, args: args{\n\t\t\targ: \"c\",\n\t\t}, want: []string{\"a\", \"b\", \"c\"}},\n\t\t{name: \"null add\", fields: fields{\n\t\t\tArgs: nil,\n\t\t}, args: args{\n\t\t\targ: \"c\",\n\t\t}, want: []string{\"c\"}},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\to := &Option{\n\t\t\t\tArgs: tt.fields.Args,\n\t\t\t}\n\t\t\to.Add(tt.args.arg)\n\t\t\tassert.ElementsMatch(t, tt.want, o.Args)\n\t\t})\n\t}\n}\n\nfunc TestOption_Set(t *testing.T) {\n\tt.Parallel()\n\ttype fields struct {\n\t\tArgs []string\n\t}\n\ttype args struct {\n\t\targ string\n\t}\n\ttests := []struct {\n\t\tname   string\n\t\tfields fields\n\t\targs   args\n\t\twant   []string\n\t}{\n\t\t{name: \"simple set\", fields: fields{\n\t\t\tArgs: []string{\"a\", \"b\"},\n\t\t}, args: args{\n\t\t\targ: \"c\",\n\t\t}, want: []string{\"c\"}},\n\t\t{name: \"null set\", fields: fields{\n\t\t\tArgs: nil,\n\t\t}, args: args{\n\t\t\targ: \"c\",\n\t\t}, want: []string{\"c\"}},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\to := &Option{\n\t\t\t\tArgs: tt.fields.Args,\n\t\t\t}\n\t\t\to.Set(tt.args.arg)\n\t\t\tassert.ElementsMatch(t, tt.want, o.Args)\n\t\t})\n\t}\n}\n\nfunc TestOption_First(t *testing.T) {\n\tt.Parallel()\n\ttype fields struct {\n\t\tArgs []string\n\t}\n\ttests := []struct {\n\t\tname   string\n\t\tfields fields\n\t\twant   string\n\t}{\n\t\t{name: \"simple first\", fields: fields{\n\t\t\tArgs: []string{\"a\", \"b\"},\n\t\t}, want: \"a\"},\n\t\t{name: \"null first\", fields: fields{\n\t\t\tArgs: nil,\n\t\t}, want: \"\"},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\to := &Option{\n\t\t\t\tArgs: tt.fields.Args,\n\t\t\t}\n\t\t\tassert.Equal(t, tt.want, o.First())\n\t\t})\n\t}\n}\n\nfunc TestMakeArguments(t *testing.T) {\n\tt.Parallel()\n\targs := MakeArguments()\n\tassert.NotNil(t, args)\n\tassert.Equal(t, \"\", args.Op)\n\tassert.Empty(t, args.Options)\n\tassert.Empty(t, args.Targets)\n}\n\nfunc TestArguments_CopyGlobal(t *testing.T) {\n\tt.Parallel()\n\ttype fields struct {\n\t\tOp      string\n\t\tOptions map[string]*Option\n\t\tTargets []string\n\t}\n\ttests := []struct {\n\t\tname   string\n\t\tfields fields\n\t\twant   *Arguments\n\t}{\n\t\t{name: \"simple\", fields: fields{\n\t\t\tOp: \"Q\",\n\t\t\tOptions: map[string]*Option{\n\t\t\t\t\"a\": {}, \"arch\": {\n\t\t\t\t\tGlobal: true,\n\t\t\t\t\tArgs:   []string{\"x86_x64\"},\n\t\t\t\t}, \"boo\": {Global: true, Args: []string{\"a\", \"b\"}},\n\t\t\t},\n\t\t\tTargets: []string{\"a\", \"b\"},\n\t\t}, want: &Arguments{\n\t\t\tOp: \"\",\n\t\t\tOptions: map[string]*Option{\n\t\t\t\t\"arch\": {\n\t\t\t\t\tGlobal: true,\n\t\t\t\t\tArgs:   []string{\"x86_x64\"},\n\t\t\t\t}, \"boo\": {Global: true, Args: []string{\"a\", \"b\"}},\n\t\t\t},\n\t\t\tTargets: []string{},\n\t\t}},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tcmdArgs := &Arguments{\n\t\t\t\tOp:      tt.fields.Op,\n\t\t\t\tOptions: tt.fields.Options,\n\t\t\t\tTargets: tt.fields.Targets,\n\t\t\t}\n\t\t\tgot := cmdArgs.CopyGlobal()\n\t\t\tassert.NotEqualValues(t, tt.fields.Options, got.Options)\n\t\t\tassert.NotEqualValues(t, tt.fields.Targets, got.Targets)\n\t\t\tassert.NotEqual(t, tt.fields.Op, got.Op)\n\t\t\tassert.Equal(t, tt.want, got)\n\t\t})\n\t}\n}\n\nfunc TestArguments_Copy(t *testing.T) {\n\tt.Parallel()\n\ttype fields struct {\n\t\tOp      string\n\t\tOptions map[string]*Option\n\t\tTargets []string\n\t}\n\ttests := []struct {\n\t\tname   string\n\t\tfields fields\n\t\twant   *Arguments\n\t}{\n\t\t{name: \"simple\", fields: fields{\n\t\t\tOp: \"Q\",\n\t\t\tOptions: map[string]*Option{\n\t\t\t\t\"a\": {}, \"arch\": {\n\t\t\t\t\tArgs: []string{\"x86_x64\"}, Global: true,\n\t\t\t\t}, \"boo\": {Args: []string{\"a\", \"b\"}, Global: true},\n\t\t\t},\n\t\t\tTargets: []string{\"a\", \"b\"},\n\t\t}, want: &Arguments{\n\t\t\tOp: \"Q\",\n\t\t\tOptions: map[string]*Option{\n\t\t\t\t\"a\": {}, \"arch\": {\n\t\t\t\t\tGlobal: true,\n\t\t\t\t\tArgs:   []string{\"x86_x64\"},\n\t\t\t\t}, \"boo\": {Args: []string{\"a\", \"b\"}, Global: true},\n\t\t\t},\n\t\t\tTargets: []string{\"a\", \"b\"},\n\t\t}},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tcmdArgs := &Arguments{\n\t\t\t\tOp:      tt.fields.Op,\n\t\t\t\tOptions: tt.fields.Options,\n\t\t\t\tTargets: tt.fields.Targets,\n\t\t\t}\n\t\t\tgot := cmdArgs.Copy()\n\t\t\tassert.Equal(t, cmdArgs, got)\n\t\t\tassert.Equal(t, tt.want, got)\n\t\t})\n\t}\n}\n\nfunc TestArguments_DelArg(t *testing.T) {\n\tt.Parallel()\n\targs := MakeArguments()\n\targs.addParam(\"arch\", \"arg\")\n\targs.addParam(\"ask\", \"arg\")\n\targs.DelArg(\"arch\", \"ask\")\n\tassert.Empty(t, args.Options)\n}\n\nfunc TestArguments_FormatArgs(t *testing.T) {\n\tt.Parallel()\n\ttype fields struct {\n\t\tOp      string\n\t\tOptions map[string]*Option\n\t\tTargets []string\n\t}\n\ttests := []struct {\n\t\tname     string\n\t\tfields   fields\n\t\twantArgs []string\n\t}{\n\t\t{name: \"simple\", fields: fields{\n\t\t\tOp:      \"S\",\n\t\t\tOptions: map[string]*Option{},\n\t\t\tTargets: []string{\"yay\", \"yay-bin\", \"yay-git\"},\n\t\t}, wantArgs: []string{\"-S\"}},\n\t\t{name: \"only global\", fields: fields{\n\t\t\tOp:      \"Y\",\n\t\t\tOptions: map[string]*Option{\"noconfirm\": {Global: true, Args: []string{\"\"}}},\n\t\t\tTargets: []string{\"yay\", \"yay-bin\", \"yay-git\"},\n\t\t}, wantArgs: []string{\"-Y\"}},\n\t\t{name: \"options single\", fields: fields{\n\t\t\tOp:      \"Y\",\n\t\t\tOptions: map[string]*Option{\"overwrite\": {Args: []string{\"/tmp/a\"}}, \"useask\": {Args: []string{\"\"}}},\n\t\t\tTargets: []string{},\n\t\t}, wantArgs: []string{\"-Y\", \"--overwrite\", \"/tmp/a\", \"--useask\"}},\n\t\t{name: \"options doubles\", fields: fields{\n\t\t\tOp:      \"Y\",\n\t\t\tOptions: map[string]*Option{\"overwrite\": {Args: []string{\"/tmp/a\", \"/tmp/b\", \"/tmp/c\"}}, \"needed\": {Args: []string{\"\"}}},\n\t\t\tTargets: []string{},\n\t\t}, wantArgs: []string{\"-Y\", \"--overwrite\", \"/tmp/a\", \"--overwrite\", \"/tmp/b\", \"--overwrite\", \"/tmp/c\", \"--needed\"}},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tcmdArgs := &Arguments{\n\t\t\t\tOp:      tt.fields.Op,\n\t\t\t\tOptions: tt.fields.Options,\n\t\t\t\tTargets: tt.fields.Targets,\n\t\t\t}\n\t\t\tgotArgs := cmdArgs.FormatArgs()\n\t\t\tassert.ElementsMatch(t, gotArgs, tt.wantArgs)\n\t\t})\n\t}\n}\n\nfunc TestArguments_FormatGlobalArgs(t *testing.T) {\n\tt.Parallel()\n\ttype fields struct {\n\t\tOp      string\n\t\tOptions map[string]*Option\n\t\tTargets []string\n\t}\n\ttests := []struct {\n\t\tname     string\n\t\tfields   fields\n\t\twantArgs []string\n\t}{\n\t\t{name: \"simple\", fields: fields{\n\t\t\tOp:      \"S\",\n\t\t\tOptions: map[string]*Option{\"dbpath\": {Global: true, Args: []string{\"/tmp/a\", \"/tmp/b\"}}},\n\t\t\tTargets: []string{\"yay\", \"yay-bin\", \"yay-git\"},\n\t\t}, wantArgs: []string{\"--dbpath\", \"/tmp/a\", \"--dbpath\", \"/tmp/b\"}},\n\t\t{name: \"only global\", fields: fields{\n\t\t\tOp:      \"Y\",\n\t\t\tOptions: map[string]*Option{\"noconfirm\": {Global: true, Args: []string{\"\"}}},\n\t\t\tTargets: []string{\"yay\", \"yay-bin\", \"yay-git\"},\n\t\t}, wantArgs: []string{\"--noconfirm\"}},\n\t\t{name: \"options single\", fields: fields{\n\t\t\tOp:      \"Y\",\n\t\t\tOptions: map[string]*Option{\"overwrite\": {Args: []string{\"/tmp/a\"}}, \"useask\": {Args: []string{\"\"}}},\n\t\t\tTargets: []string{},\n\t\t}, wantArgs: []string(nil)},\n\t\t{name: \"options doubles\", fields: fields{\n\t\t\tOp:      \"Y\",\n\t\t\tOptions: map[string]*Option{\"overwrite\": {Args: []string{\"/tmp/a\", \"/tmp/b\", \"/tmp/c\"}}, \"needed\": {Args: []string{\"\"}}},\n\t\t\tTargets: []string{},\n\t\t}, wantArgs: []string(nil)},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tcmdArgs := &Arguments{\n\t\t\t\tOp:      tt.fields.Op,\n\t\t\t\tOptions: tt.fields.Options,\n\t\t\t\tTargets: tt.fields.Targets,\n\t\t\t}\n\t\t\tgotArgs := cmdArgs.FormatGlobals()\n\t\t\tassert.ElementsMatch(t, tt.wantArgs, gotArgs)\n\t\t})\n\t}\n}\n\nfunc Test_isArg(t *testing.T) {\n\tt.Parallel()\n\tgot := isArg(\"zorg\")\n\tassert.False(t, got)\n\n\tgot = isArg(\"dbpath\")\n\tassert.True(t, got)\n}\n\nfunc TestArguments_ParseStdin(t *testing.T) {\n\tinput := []byte(\"yay\")\n\n\tr, w, err := os.Pipe()\n\trequire.NoError(t, err)\n\n\t_, err = w.Write(input)\n\trequire.NoError(t, err)\n\tw.Close()\n\n\t// Restore stdin after the test.\n\tdefer func(o *os.File) { os.Stdin = o }(os.Stdin)\n\tos.Stdin = r\n\n\targs := MakeArguments()\n\terr = args.parseStdin()\n\tassert.NoError(t, err)\n\n\texpectedTargets := []string{string(input)}\n\tassert.ElementsMatch(t, args.Targets, expectedTargets)\n}\n\nfunc TestArguments_ParseStdin_broken_pipe(t *testing.T) {\n\tr, _, err := os.Pipe()\n\trequire.NoError(t, err)\n\tr.Close() // Close early to break pipe\n\n\t// Restore stdin after the test.\n\tdefer func(o *os.File) { os.Stdin = o }(os.Stdin)\n\tos.Stdin = r\n\n\targs := MakeArguments()\n\terr = args.parseStdin()\n\tassert.Error(t, err)\n}\n"
  },
  {
    "path": "pkg/settings/parser/rebuild_mode.go",
    "content": "package parser\n\ntype RebuildMode string\n\nconst (\n\tRebuildModeNo   RebuildMode = \"no\"\n\tRebuildModeYes  RebuildMode = \"yes\"\n\tRebuildModeTree RebuildMode = \"tree\"\n\tRebuildModeAll  RebuildMode = \"all\"\n)\n"
  },
  {
    "path": "pkg/settings/parser/target_mode.go",
    "content": "package parser\n\ntype TargetMode int\n\nconst (\n\tModeAny TargetMode = iota\n\tModeAUR\n\tModeRepo\n)\n\nfunc (mode TargetMode) AtLeastAUR() bool {\n\treturn mode == ModeAny || mode == ModeAUR\n}\n\nfunc (mode TargetMode) AtLeastRepo() bool {\n\treturn mode == ModeAny || mode == ModeRepo\n}\n"
  },
  {
    "path": "pkg/settings/yay.conf",
    "content": "# /etc/yay.conf - System-wide yay configuration\n[options]\n\n# AUR Settings\nAurUrl = https://aur.archlinux.org\n#AurRpcUrl = https://aur.archlinux.org/rpc\n\n# Directories\nBuildDir = ~/.cache/yay\n\n# Binaries\n#Editor = vim\n#EditorFlags = \nMakepkgBin = makepkg\n#MakepkgConf = \nPacmanBin = pacman\nPacmanConf = /etc/pacman.conf\nGitBin = git\nGpgBin = gpg\nSudoBin = sudo\n\n# Flags\n# GpgFlags = \n# MFlags = \n# GitFlags = \n# SudoFlags = \n\n# Search/Display\nBottomUp\n# SingleLineResults\nSeparateSources\n\n# Sorting\n#SortBy = \nSearchBy = name-desc\n\n# Build options\n#Devel\n#CleanAfter\n#KeepSrc\n#BatchInstall\n\nRemoveMake = ask\n\n# Download options\nReDownload = no\nReBuild = no\nPgpFetch\n\n# Menus\nCleanMenu\nDiffMenu\n# EditMenu\n\n# Prompts\n#AnswerClean = \n#AnswerDiff = \n#AnswerEdit = \n#AnswerUpgrade = \n\n# Behavior\nCombinedUpgrade\n#SudoLoop\n#Provides\n#UseAsk\nDoubleConfirm\nRpc\n#Debug\n\n# Limits\nRequestSplitN = 150\nCompletionInterval = 7\nMaxConcurrentDownloads = 1\n"
  },
  {
    "path": "pkg/sync/build/errors.go",
    "content": "package build\n\nimport (\n\t\"errors\"\n\t\"strings\"\n\n\t\"github.com/leonelquinteros/gotext\"\n)\n\nvar ErrInstallRepoPkgs = errors.New(gotext.Get(\"error installing repo packages\"))\n\ntype FailedIgnoredPkgError struct {\n\tpkgErrors map[string]error\n}\n\nfunc (e *FailedIgnoredPkgError) Error() string {\n\tvar sb strings.Builder\n\tsb.WriteString(gotext.Get(\"Failed to install the following packages. Manual intervention is required:\"))\n\n\tfor pkg, err := range e.pkgErrors {\n\t\tsb.WriteString(\"\\n\")\n\t\tsb.WriteString(pkg)\n\t\tsb.WriteString(\" - \")\n\t\tsb.WriteString(err.Error())\n\t}\n\n\treturn sb.String()\n}\n\ntype PkgDestNotInListError struct {\n\tname string\n}\n\nfunc (e *PkgDestNotInListError) Error() string {\n\treturn gotext.Get(\"could not find PKGDEST for: %s\", e.name)\n}\n\ntype FindPkgDestError struct {\n\tname, pkgDest string\n}\n\nfunc (e *FindPkgDestError) Error() string {\n\treturn gotext.Get(\n\t\t\"the PKGDEST for %s is listed by makepkg but does not exist: %s\",\n\t\te.name, e.pkgDest)\n}\n\ntype SetPkgReasonError struct {\n\texp bool // explicit\n}\n\nfunc (e *SetPkgReasonError) Error() string {\n\treason := gotext.Get(\"explicit\")\n\tif !e.exp {\n\t\treason = gotext.Get(\"dependency\")\n\t}\n\n\treturn gotext.Get(\"error updating package install reason to %s\", reason)\n}\n\ntype NoPkgDestsFoundError struct {\n\tdir string\n}\n\nfunc (e *NoPkgDestsFoundError) Error() string {\n\treturn gotext.Get(\"could not find any package archives listed in %s\", e.dir)\n}\n"
  },
  {
    "path": "pkg/sync/build/installer.go",
    "content": "package build\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"maps\"\n\t\"os\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/dep\"\n\t\"github.com/Jguer/yay/v12/pkg/multierror\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\t\"github.com/Jguer/yay/v12/pkg/vcs\"\n\n\tmapset \"github.com/deckarep/golang-set/v2\"\n\t\"github.com/leonelquinteros/gotext\"\n)\n\ntype (\n\tPostInstallHookFunc func(ctx context.Context) error\n\tInstaller           struct {\n\t\tdbExecutor           db.Executor\n\t\tpostInstallHooks     []PostInstallHookFunc\n\t\tfailedAndIgnored     map[string]error\n\t\texeCmd               exe.ICmdBuilder\n\t\tvcsStore             vcs.Store\n\t\ttargetMode           parser.TargetMode\n\t\trebuildMode          parser.RebuildMode\n\t\torigTargets          mapset.Set[string]\n\t\tdownloadOnly         bool\n\t\tinstallBuiltPackages bool\n\t\tlog                  *text.Logger\n\n\t\tmanualConfirmRequired bool\n\t}\n)\n\nfunc NewInstaller(dbExecutor db.Executor,\n\texeCmd exe.ICmdBuilder, vcsStore vcs.Store, targetMode parser.TargetMode,\n\trebuildMode parser.RebuildMode, downloadOnly bool, logger *text.Logger,\n) *Installer {\n\treturn &Installer{\n\t\tdbExecutor:            dbExecutor,\n\t\tpostInstallHooks:      []PostInstallHookFunc{},\n\t\tfailedAndIgnored:      map[string]error{},\n\t\texeCmd:                exeCmd,\n\t\tvcsStore:              vcsStore,\n\t\ttargetMode:            targetMode,\n\t\trebuildMode:           rebuildMode,\n\t\tdownloadOnly:          downloadOnly,\n\t\tinstallBuiltPackages:  true,\n\t\tlog:                   logger,\n\t\tmanualConfirmRequired: true,\n\t}\n}\n\nfunc (installer *Installer) SetInstallBuiltPackages(install bool) {\n\tinstaller.installBuiltPackages = install\n}\n\nfunc (installer *Installer) CompileFailedAndIgnored() (map[string]error, error) {\n\tif len(installer.failedAndIgnored) == 0 {\n\t\treturn installer.failedAndIgnored, nil\n\t}\n\n\treturn installer.failedAndIgnored, &FailedIgnoredPkgError{\n\t\tpkgErrors: installer.failedAndIgnored,\n\t}\n}\n\nfunc (installer *Installer) AddPostInstallHook(hook PostInstallHookFunc) {\n\tif hook == nil {\n\t\treturn\n\t}\n\n\tinstaller.postInstallHooks = append(installer.postInstallHooks, hook)\n}\n\nfunc (installer *Installer) RunPostInstallHooks(ctx context.Context) error {\n\tvar errMulti multierror.MultiError\n\n\tfor _, hook := range installer.postInstallHooks {\n\t\tif err := hook(ctx); err != nil {\n\t\t\terrMulti.Add(err)\n\t\t}\n\t}\n\n\treturn errMulti.Return()\n}\n\nfunc (installer *Installer) Install(ctx context.Context,\n\tcmdArgs *parser.Arguments,\n\ttargets []map[string]*dep.InstallInfo,\n\tpkgBuildDirs map[string]string,\n\texcluded []string,\n\tmanualConfirmRequired bool,\n) error {\n\tinstaller.log.Debugln(\"manualConfirmRequired:\", manualConfirmRequired)\n\tinstaller.manualConfirmRequired = manualConfirmRequired\n\n\tinstaller.origTargets = mapset.NewThreadUnsafeSet[string]()\n\tfor _, targetString := range cmdArgs.Targets {\n\t\tinstaller.origTargets.Add(dep.ToTarget(targetString).Name)\n\t}\n\tinstaller.log.Debugln(\"origTargets:\", installer.origTargets)\n\n\t// Reorganize targets into layers of dependencies\n\tvar errMulti multierror.MultiError\n\tfor i := len(targets) - 1; i >= 0; i-- {\n\t\tlastLayer := i == 0\n\t\terrI := installer.handleLayer(ctx, cmdArgs, targets[i], pkgBuildDirs, lastLayer, excluded)\n\t\tif errI == nil && lastLayer {\n\t\t\t// success after rollups\n\t\t\treturn nil\n\t\t}\n\n\t\tif errI != nil {\n\t\t\terrMulti.Add(errI)\n\t\t\tif lastLayer {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\t// rollup\n\t\t\tinstaller.log.Warnln(gotext.Get(\"Failed to install layer, rolling up to next layer.\"), \"error:\", errI)\n\t\t\ttargets[i-1] = mergeLayers(targets[i-1], targets[i])\n\t\t}\n\t}\n\n\treturn errMulti.Return()\n}\n\nfunc mergeLayers(layer1, layer2 map[string]*dep.InstallInfo) map[string]*dep.InstallInfo {\n\tmaps.Copy(layer1, layer2)\n\n\treturn layer1\n}\n\nfunc (installer *Installer) appendNoConfirm() bool {\n\treturn !installer.manualConfirmRequired || settings.NoConfirm\n}\n\nfunc (installer *Installer) handleLayer(ctx context.Context,\n\tcmdArgs *parser.Arguments,\n\tlayer map[string]*dep.InstallInfo,\n\tpkgBuildDirs map[string]string,\n\tlastLayer bool,\n\texcluded []string,\n) error {\n\t// Install layer\n\tnameToBaseMap := make(map[string]string, len(layer))\n\tsyncDeps, syncExp, syncGroups := mapset.NewThreadUnsafeSet[string](),\n\t\tmapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()\n\taurDeps, aurExp, aurOrigTargetBases := mapset.NewThreadUnsafeSet[string](),\n\t\tmapset.NewThreadUnsafeSet[string](), mapset.NewThreadUnsafeSet[string]()\n\n\tupgradeSync := false\n\tfor name, info := range layer {\n\t\tswitch info.Source {\n\t\tcase dep.AUR, dep.SrcInfo:\n\t\t\tnameToBaseMap[name] = *info.AURBase\n\t\t\tif installer.origTargets.Contains(name) {\n\t\t\t\taurOrigTargetBases.Add(*info.AURBase)\n\t\t\t}\n\n\t\t\tswitch info.Reason {\n\t\t\tcase dep.Explicit:\n\t\t\t\tif cmdArgs.ExistsArg(\"asdeps\", \"asdep\") {\n\t\t\t\t\taurDeps.Add(name)\n\t\t\t\t} else {\n\t\t\t\t\taurExp.Add(name)\n\t\t\t\t}\n\t\t\tcase dep.Dep, dep.MakeDep, dep.CheckDep:\n\t\t\t\t// Only apply --asexplicit to packages that are explicitly targeted\n\t\t\t\tif cmdArgs.ExistsArg(\"asexplicit\", \"asexp\") && installer.origTargets.Contains(name) {\n\t\t\t\t\taurExp.Add(name)\n\t\t\t\t} else {\n\t\t\t\t\taurDeps.Add(name)\n\t\t\t\t}\n\t\t\t}\n\t\tcase dep.Sync:\n\t\t\tif info.Upgrade {\n\t\t\t\tupgradeSync = true\n\t\t\t\tcontinue // do not add to targets, let pacman handle it\n\t\t\t}\n\t\t\tcompositePkgName := fmt.Sprintf(\"%s/%s\", *info.SyncDBName, name)\n\n\t\t\tif info.IsGroup {\n\t\t\t\tsyncGroups.Add(compositePkgName)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tswitch info.Reason {\n\t\t\tcase dep.Explicit:\n\t\t\t\tif cmdArgs.ExistsArg(\"asdeps\", \"asdep\") {\n\t\t\t\t\tsyncDeps.Add(compositePkgName)\n\t\t\t\t} else {\n\t\t\t\t\tsyncExp.Add(compositePkgName)\n\t\t\t\t}\n\t\t\tcase dep.Dep, dep.MakeDep, dep.CheckDep:\n\t\t\t\t// Only apply --asexplicit to packages that are explicitly targeted\n\t\t\t\tif cmdArgs.ExistsArg(\"asexplicit\", \"asexp\") && installer.origTargets.Contains(name) {\n\t\t\t\t\tsyncExp.Add(compositePkgName)\n\t\t\t\t} else {\n\t\t\t\t\tsyncDeps.Add(compositePkgName)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tinstaller.log.Debugln(\"syncDeps\", syncDeps, \"SyncExp\", syncExp,\n\t\t\"aurDeps\", aurDeps, \"aurExp\", aurExp, \"upgrade\", upgradeSync)\n\n\terrShow := installer.installSyncPackages(ctx, cmdArgs, syncDeps, syncExp, syncGroups,\n\t\texcluded, upgradeSync, installer.appendNoConfirm())\n\tif errShow != nil {\n\t\treturn ErrInstallRepoPkgs\n\t}\n\n\terrAur := installer.installAURPackages(ctx, cmdArgs, aurDeps, aurExp,\n\t\taurOrigTargetBases, nameToBaseMap, pkgBuildDirs, true, lastLayer,\n\t\tinstaller.appendNoConfirm())\n\n\treturn errAur\n}\n\nfunc (installer *Installer) installAURPackages(ctx context.Context,\n\tcmdArgs *parser.Arguments,\n\taurDepNames, aurExpNames, aurOrigTargetBases mapset.Set[string],\n\tnameToBase, pkgBuildDirsByBase map[string]string,\n\tinstallIncompatible bool,\n\tlastLayer bool,\n\tnoConfirm bool,\n) error {\n\tall := aurDepNames.Union(aurExpNames).ToSlice()\n\tif len(all) == 0 {\n\t\treturn nil\n\t}\n\n\tbuiltPkgDests := make(map[string]map[string]string)\n\tdeps := make([]string, 0, aurDepNames.Cardinality())\n\texps := make([]string, 0, aurExpNames.Cardinality())\n\tpkgArchives := make([]string, 0, len(all))\n\n\tfor _, name := range all {\n\t\tbase := nameToBase[name]\n\t\tdir := pkgBuildDirsByBase[base]\n\n\t\tpkgdests, ok := builtPkgDests[base]\n\t\tif ok {\n\t\t\tinstaller.log.Debugln(\"skipping built pkgbase\", base, \"package\", name)\n\t\t} else {\n\t\t\tvar errMake error\n\t\t\tinstaller.log.Debugln(\"building pkgbase\", base, \"package\", name)\n\t\t\tpkgdests, errMake = installer.buildPkg(ctx, dir, base,\n\t\t\t\tinstallIncompatible, cmdArgs.ExistsArg(\"needed\"), aurOrigTargetBases.Contains(base))\n\t\t\tbuiltPkgDests[base] = pkgdests\n\t\t\tif errMake != nil {\n\t\t\t\tif !lastLayer {\n\t\t\t\t\treturn fmt.Errorf(\"%s - %w\", gotext.Get(\"error making: %s\", base), errMake)\n\t\t\t\t}\n\n\t\t\t\tinstaller.failedAndIgnored[name] = errMake\n\t\t\t\tinstaller.log.Errorln(gotext.Get(\"error making: %s\", base), \"-\", errMake)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\tif len(pkgdests) == 0 {\n\t\t\tinstaller.log.Warnln(gotext.Get(\"nothing to install for %s\", text.Cyan(base)))\n\t\t\tcontinue\n\t\t}\n\n\t\tnewPKGArchives, hasDebug, err := installer.getNewTargets(pkgdests, name)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tpkgArchives = append(pkgArchives, newPKGArchives...)\n\n\t\tif isDep := installer.isDep(cmdArgs, aurExpNames, name); isDep {\n\t\t\tdeps = append(deps, name)\n\t\t} else {\n\t\t\texps = append(exps, name)\n\t\t}\n\n\t\tif hasDebug {\n\t\t\tdeps = append(deps, name+\"-debug\")\n\t\t}\n\t}\n\n\tif len(pkgArchives) == 0 || !installer.installBuiltPackages {\n\t\treturn nil\n\t}\n\n\tif err := installPkgArchive(ctx, installer.exeCmd, installer.targetMode,\n\t\tinstaller.vcsStore, cmdArgs, pkgArchives, noConfirm); err != nil {\n\t\treturn fmt.Errorf(\"%s - %w\", fmt.Sprintf(gotext.Get(\"error installing:\")+\" %v\", pkgArchives), err)\n\t}\n\n\tif err := setInstallReason(ctx, installer.exeCmd, installer.targetMode, cmdArgs, deps, exps); err != nil {\n\t\treturn fmt.Errorf(\"%s - %w\", fmt.Sprintf(gotext.Get(\"error installing:\")+\" %v\", pkgArchives), err)\n\t}\n\n\treturn nil\n}\n\nfunc (installer *Installer) buildPkg(ctx context.Context,\n\tdir, base string,\n\tinstallIncompatible, needed, isTarget bool,\n) (map[string]string, error) {\n\targs := []string{\"--nobuild\", \"-f\"}\n\n\tif !installer.exeCmd.GetKeepSrc() {\n\t\targs = append(args, \"-C\")\n\t}\n\n\tif installIncompatible {\n\t\targs = append(args, \"--ignorearch\")\n\t}\n\n\t// pkgver bump\n\tif err := installer.exeCmd.Show(\n\t\tinstaller.exeCmd.BuildMakepkgCmd(ctx, dir, args...)); err != nil {\n\t\treturn nil, err\n\t}\n\n\tpkgdests, pkgVersion, errList := parsePackageList(ctx, installer.exeCmd, dir)\n\tif errList != nil {\n\t\treturn nil, errList\n\t}\n\n\tswitch {\n\tcase needed && installer.pkgsAreAlreadyInstalled(pkgdests, pkgVersion) || installer.downloadOnly:\n\t\targs = []string{\"--nobuild\", \"--noextract\", \"--ignorearch\"}\n\t\tpkgdests = map[string]string{}\n\t\tinstaller.log.Warnln(gotext.Get(\"%s is up to date -- skipping\", text.Cyan(base+\"-\"+pkgVersion)))\n\tcase installer.skipAlreadyBuiltPkg(isTarget, pkgdests):\n\t\targs = []string{\"--nobuild\", \"--noextract\", \"--ignorearch\"}\n\t\tinstaller.log.Warnln(gotext.Get(\"%s already made -- skipping build\", text.Cyan(base+\"-\"+pkgVersion)))\n\tdefault:\n\t\targs = []string{\"-f\", \"--noconfirm\", \"--noextract\", \"--noprepare\", \"--holdver\"}\n\t\tif installIncompatible {\n\t\t\targs = append(args, \"--ignorearch\")\n\t\t}\n\t}\n\n\tif !installer.exeCmd.GetKeepSrc() {\n\t\targs = append(args, \"-c\")\n\t}\n\n\terrMake := installer.exeCmd.Show(\n\t\tinstaller.exeCmd.BuildMakepkgCmd(ctx,\n\t\t\tdir, args...))\n\tif errMake != nil {\n\t\treturn nil, errMake\n\t}\n\n\tif installer.downloadOnly {\n\t\treturn map[string]string{}, nil\n\t}\n\n\treturn pkgdests, nil\n}\n\nfunc (installer *Installer) pkgsAreAlreadyInstalled(pkgdests map[string]string, pkgVersion string) bool {\n\tfor pkgName := range pkgdests {\n\t\tif !installer.dbExecutor.IsCorrectVersionInstalled(pkgName, pkgVersion) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\nfunc pkgsAreBuilt(logger *text.Logger, pkgdests map[string]string) bool {\n\tfor _, pkgdest := range pkgdests {\n\t\tif _, err := os.Stat(pkgdest); err != nil {\n\t\t\tlogger.Debugln(\"pkgIsBuilt:\", pkgdest, \"does not exist\")\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\nfunc (installer *Installer) skipAlreadyBuiltPkg(isTarget bool, pkgdests map[string]string) bool {\n\tswitch installer.rebuildMode {\n\tcase parser.RebuildModeNo:\n\t\treturn pkgsAreBuilt(installer.log, pkgdests)\n\tcase parser.RebuildModeYes:\n\t\treturn !isTarget && pkgsAreBuilt(installer.log, pkgdests)\n\t// case parser.RebuildModeTree: // TODO\n\t// case parser.RebuildModeAll: // TODO\n\tdefault:\n\t\t// same as RebuildModeNo\n\t\treturn pkgsAreBuilt(installer.log, pkgdests)\n\t}\n}\n\nfunc (*Installer) isDep(cmdArgs *parser.Arguments, aurExpNames mapset.Set[string], name string) bool {\n\tswitch {\n\tcase cmdArgs.ExistsArg(\"asdeps\", \"asdep\"):\n\t\treturn true\n\tcase cmdArgs.ExistsArg(\"asexplicit\", \"asexp\"):\n\t\treturn false\n\tcase aurExpNames.Contains(name):\n\t\treturn false\n\t}\n\n\treturn true\n}\n\nfunc (installer *Installer) getNewTargets(pkgdests map[string]string, name string,\n) (archives []string, good bool, err error) {\n\tpkgdest, ok := pkgdests[name]\n\tif !ok {\n\t\treturn nil, false, &PkgDestNotInListError{name: name}\n\t}\n\n\tpkgArchives := make([]string, 0, 2)\n\n\tif _, errStat := os.Stat(pkgdest); os.IsNotExist(errStat) {\n\t\treturn nil, false, &FindPkgDestError{name: name, pkgDest: pkgdest}\n\t}\n\n\tpkgArchives = append(pkgArchives, pkgdest)\n\n\tdebugName := name + \"-debug\"\n\n\tpkgdestDebug, ok := pkgdests[debugName]\n\tif ok {\n\t\tif _, errStat := os.Stat(pkgdestDebug); errStat == nil {\n\t\t\tpkgArchives = append(pkgArchives, pkgdestDebug)\n\t\t} else {\n\t\t\tok = false\n\t\t}\n\t}\n\n\treturn pkgArchives, ok, nil\n}\n\nfunc (installer *Installer) installSyncPackages(ctx context.Context, cmdArgs *parser.Arguments,\n\tsyncDeps, // repo targets that are deps\n\tsyncExp mapset.Set[string], // repo targets that are exp\n\tsyncGroups mapset.Set[string], // repo targets that are groups\n\texcluded []string,\n\tupgrade bool, // run even without targets\n\tnoConfirm bool,\n) error {\n\trepoTargets := syncDeps.Union(syncExp).Union(syncGroups).ToSlice()\n\tif len(repoTargets) == 0 && !upgrade {\n\t\treturn nil\n\t}\n\n\targuments := cmdArgs.Copy()\n\targuments.DelArg(\"asdeps\", \"asdep\")\n\targuments.DelArg(\"asexplicit\", \"asexp\")\n\targuments.DelArg(\"i\", \"install\")\n\targuments.Op = \"S\"\n\targuments.ClearTargets()\n\targuments.AddTarget(repoTargets...)\n\n\t// Don't upgrade all repo packages if only AUR upgrades are specified\n\tif installer.targetMode == parser.ModeAUR {\n\t\targuments.DelArg(\"u\", \"upgrades\")\n\t}\n\n\tif len(excluded) > 0 {\n\t\targuments.CreateOrAppendOption(\"ignore\", excluded...)\n\t}\n\n\terrShow := installer.exeCmd.Show(installer.exeCmd.BuildPacmanCmd(ctx,\n\t\targuments, installer.targetMode, noConfirm))\n\tif errShow != nil {\n\t\treturn errShow\n\t}\n\n\tif errD := asdeps(ctx, installer.exeCmd, installer.targetMode, cmdArgs, syncDeps.ToSlice()); errD != nil {\n\t\treturn errD\n\t}\n\n\tif errE := asexp(ctx, installer.exeCmd, installer.targetMode, cmdArgs, syncExp.ToSlice()); errE != nil {\n\t\treturn errE\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/sync/build/installer_test.go",
    "content": "package build\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db/mock\"\n\t\"github.com/Jguer/yay/v12/pkg/dep\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\t\"github.com/Jguer/yay/v12/pkg/vcs\"\n)\n\nfunc newTestLogger() *text.Logger {\n\treturn text.NewLogger(io.Discard, io.Discard, strings.NewReader(\"\"), true, \"test\")\n}\n\nfunc ptrString(s string) *string {\n\treturn &s\n}\n\nfunc TestInstaller_InstallNeeded(t *testing.T) {\n\tt.Parallel()\n\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\ttype testCase struct {\n\t\tdesc        string\n\t\tisInstalled bool\n\t\tisBuilt     bool\n\t\twantShow    []string\n\t\twantCapture []string\n\t}\n\n\ttestCases := []testCase{\n\t\t{\n\t\t\tdesc:        \"not installed and not built\",\n\t\t\tisInstalled: false,\n\t\t\tisBuilt:     false,\n\t\t\twantShow: []string{\n\t\t\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\t\t\"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch\",\n\t\t\t\t\"pacman -U --needed --config  -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst\",\n\t\t\t\t\"pacman -D -q --asexplicit --config  -- yay\",\n\t\t\t},\n\t\t\twantCapture: []string{\"makepkg --packagelist\"},\n\t\t},\n\t\t{\n\t\t\tdesc:        \"not installed and built\",\n\t\t\tisInstalled: false,\n\t\t\tisBuilt:     true,\n\t\t\twantShow: []string{\n\t\t\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\t\t\"makepkg -c --nobuild --noextract --ignorearch\",\n\t\t\t\t\"pacman -U --needed --config  -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst\",\n\t\t\t\t\"pacman -D -q --asexplicit --config  -- yay\",\n\t\t\t},\n\t\t\twantCapture: []string{\"makepkg --packagelist\"},\n\t\t},\n\t\t{\n\t\t\tdesc:        \"installed\",\n\t\t\tisInstalled: true,\n\t\t\tisBuilt:     false,\n\t\t\twantShow: []string{\n\t\t\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\t\t\"makepkg -c --nobuild --noextract --ignorearch\",\n\t\t\t},\n\t\t\twantCapture: []string{\"makepkg --packagelist\"},\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.desc, func(td *testing.T) {\n\t\t\ttmpDir := td.TempDir()\n\t\t\tpkgTar := tmpDir + \"/yay-91.0.0-1-x86_64.pkg.tar.zst\"\n\n\t\t\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\t\t\treturn pkgTar, \"\", nil\n\t\t\t}\n\n\t\t\ti := 0\n\t\t\tshowOverride := func(cmd *exec.Cmd) error {\n\t\t\t\ti++\n\t\t\t\tif i == 2 {\n\t\t\t\t\tif !tc.isBuilt {\n\t\t\t\t\t\tf, err := os.OpenFile(pkgTar, os.O_RDONLY|os.O_CREATE, 0o666)\n\t\t\t\t\t\trequire.NoError(td, err)\n\t\t\t\t\t\trequire.NoError(td, f.Close())\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\t// create a mock file\n\t\t\tif tc.isBuilt {\n\t\t\t\tf, err := os.OpenFile(pkgTar, os.O_RDONLY|os.O_CREATE, 0o666)\n\t\t\t\trequire.NoError(td, err)\n\t\t\t\trequire.NoError(td, f.Close())\n\t\t\t}\n\n\t\t\tisCorrectInstalledOverride := func(string, string) bool {\n\t\t\t\treturn tc.isInstalled\n\t\t\t}\n\n\t\t\tmockDB := &mock.DBExecutor{IsCorrectVersionInstalledFn: isCorrectInstalledOverride}\n\t\t\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\t\t\tcmdBuilder := &exe.CmdBuilder{\n\t\t\t\tMakepkgBin:      makepkgBin,\n\t\t\t\tSudoBin:         \"su\",\n\t\t\t\tPacmanBin:       pacmanBin,\n\t\t\t\tRunner:          mockRunner,\n\t\t\t\tSudoLoopEnabled: false,\n\t\t\t}\n\n\t\t\tcmdBuilder.Runner = mockRunner\n\n\t\t\tinstaller := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,\n\t\t\t\tparser.RebuildModeNo, false, newTestLogger())\n\n\t\t\tcmdArgs := parser.MakeArguments()\n\t\t\tcmdArgs.AddArg(\"needed\")\n\t\t\tcmdArgs.AddTarget(\"yay\")\n\n\t\t\tpkgBuildDirs := map[string]string{\n\t\t\t\t\"yay\": tmpDir,\n\t\t\t}\n\n\t\t\ttargets := []map[string]*dep.InstallInfo{\n\t\t\t\t{\n\t\t\t\t\t\"yay\": {\n\t\t\t\t\t\tSource:      dep.AUR,\n\t\t\t\t\t\tReason:      dep.Explicit,\n\t\t\t\t\t\tVersion:     \"91.0.0-1\",\n\t\t\t\t\t\tSrcinfoPath: ptrString(tmpDir + \"/.SRCINFO\"),\n\t\t\t\t\t\tAURBase:     ptrString(\"yay\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\n\t\t\terrI := installer.Install(context.Background(), cmdArgs, targets, pkgBuildDirs, []string{}, false)\n\t\t\trequire.NoError(td, errI)\n\n\t\t\trequire.Len(td, mockRunner.ShowCalls, len(tc.wantShow))\n\t\t\trequire.Len(td, mockRunner.CaptureCalls, len(tc.wantCapture))\n\n\t\t\tfor i, call := range mockRunner.ShowCalls {\n\t\t\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\t\t\tshow = strings.ReplaceAll(show, tmpDir, \"/testdir\") // replace the temp dir with a static path\n\t\t\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\t\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\n\t\t\t\t// options are in a different order on different systems and on CI root user is used\n\t\t\t\tassert.Subset(td, strings.Split(show, \" \"), strings.Split(tc.wantShow[i], \" \"), show)\n\t\t\t}\n\n\t\t\tfor i, call := range mockRunner.CaptureCalls {\n\t\t\t\tcapture := call.Args[0].(*exec.Cmd).String()\n\t\t\t\tcapture = strings.ReplaceAll(capture, tmpDir, \"/testdir\") // replace the temp dir with a static path\n\t\t\t\tcapture = strings.ReplaceAll(capture, makepkgBin, \"makepkg\")\n\t\t\t\tcapture = strings.ReplaceAll(capture, pacmanBin, \"pacman\")\n\t\t\t\tassert.Subset(td, strings.Split(capture, \" \"), strings.Split(tc.wantCapture[i], \" \"), capture)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestInstaller_BuildOnlySkipsInstall(t *testing.T) {\n\tt.Parallel()\n\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\ttmpDir := t.TempDir()\n\tpkgTar := tmpDir + \"/yay-91.0.0-1-x86_64.pkg.tar.zst\"\n\n\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\treturn pkgTar, \"\", nil\n\t}\n\n\ti := 0\n\tshowOverride := func(cmd *exec.Cmd) error {\n\t\ti++\n\t\tif i == 2 {\n\t\t\tf, err := os.OpenFile(pkgTar, os.O_RDONLY|os.O_CREATE, 0o666)\n\t\t\trequire.NoError(t, err)\n\t\t\trequire.NoError(t, f.Close())\n\t\t}\n\t\treturn nil\n\t}\n\n\tmockDB := &mock.DBExecutor{}\n\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\tcmdBuilder := &exe.CmdBuilder{\n\t\tMakepkgBin:      makepkgBin,\n\t\tSudoBin:         \"su\",\n\t\tPacmanBin:       pacmanBin,\n\t\tRunner:          mockRunner,\n\t\tSudoLoopEnabled: false,\n\t}\n\n\tcmdBuilder.Runner = mockRunner\n\n\tinstaller := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,\n\t\tparser.RebuildModeNo, false, newTestLogger())\n\tinstaller.SetInstallBuiltPackages(false)\n\n\tcmdArgs := parser.MakeArguments()\n\tcmdArgs.AddTarget(\"yay\")\n\n\tpkgBuildDirs := map[string]string{\n\t\t\"yay\": tmpDir,\n\t}\n\n\ttargets := []map[string]*dep.InstallInfo{\n\t\t{\n\t\t\t\"yay\": {\n\t\t\t\tSource:      dep.AUR,\n\t\t\t\tReason:      dep.Explicit,\n\t\t\t\tVersion:     \"91.0.0-1\",\n\t\t\t\tSrcinfoPath: ptrString(tmpDir + \"/.SRCINFO\"),\n\t\t\t\tAURBase:     ptrString(\"yay\"),\n\t\t\t},\n\t\t},\n\t}\n\n\terr = installer.Install(context.Background(), cmdArgs, targets, pkgBuildDirs, []string{}, false)\n\trequire.NoError(t, err)\n\n\twantShow := []string{\n\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch\",\n\t}\n\n\trequire.Len(t, mockRunner.ShowCalls, len(wantShow))\n\trequire.Len(t, mockRunner.CaptureCalls, 1)\n\n\tfor i, call := range mockRunner.ShowCalls {\n\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\tshow = strings.ReplaceAll(show, tmpDir, \"/testdir\")\n\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\n\t\tassert.Subset(t, strings.Split(show, \" \"), strings.Split(wantShow[i], \" \"), show)\n\t\tassert.NotContains(t, show, \"pacman -U\")\n\t}\n\n\tfor _, call := range mockRunner.CaptureCalls {\n\t\tcapture := call.Args[0].(*exec.Cmd).String()\n\t\tcapture = strings.ReplaceAll(capture, tmpDir, \"/testdir\")\n\t\tcapture = strings.ReplaceAll(capture, makepkgBin, \"makepkg\")\n\t\tcapture = strings.ReplaceAll(capture, pacmanBin, \"pacman\")\n\t\tassert.Subset(t, strings.Split(capture, \" \"), strings.Split(\"makepkg --packagelist\", \" \"), capture)\n\t}\n}\n\nfunc TestInstaller_InstallMixedSourcesAndLayers(t *testing.T) {\n\tt.Parallel()\n\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\ttype testCase struct {\n\t\tdesc        string\n\t\ttargets     []map[string]*dep.InstallInfo\n\t\twantShow    []string\n\t\twantCapture []string\n\t}\n\n\ttmpDir := t.TempDir()\n\ttmpDirJfin := t.TempDir()\n\n\ttestCases := []testCase{\n\t\t{\n\t\t\tdesc: \"same layer -- different sources\",\n\t\t\twantShow: []string{\n\t\t\t\t\"pacman -S --config /etc/pacman.conf -- core/linux\",\n\t\t\t\t\"pacman -D -q --asdeps --config /etc/pacman.conf -- linux\",\n\t\t\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\t\t\"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch\",\n\t\t\t\t\"pacman -U --config /etc/pacman.conf -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst\",\n\t\t\t\t\"pacman -D -q --asexplicit --config /etc/pacman.conf -- yay\",\n\t\t\t},\n\t\t\twantCapture: []string{\"makepkg --packagelist\"},\n\t\t\ttargets: []map[string]*dep.InstallInfo{\n\t\t\t\t{\n\t\t\t\t\t\"yay\": {\n\t\t\t\t\t\tSource:      dep.AUR,\n\t\t\t\t\t\tReason:      dep.Explicit,\n\t\t\t\t\t\tVersion:     \"91.0.0-1\",\n\t\t\t\t\t\tSrcinfoPath: ptrString(tmpDir + \"/.SRCINFO\"),\n\t\t\t\t\t\tAURBase:     ptrString(\"yay\"),\n\t\t\t\t\t},\n\t\t\t\t\t\"linux\": {\n\t\t\t\t\t\tSource:     dep.Sync,\n\t\t\t\t\t\tReason:     dep.Dep,\n\t\t\t\t\t\tVersion:    \"17.0.0-1\",\n\t\t\t\t\t\tSyncDBName: ptrString(\"core\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc: \"different layer -- different sources\",\n\t\t\twantShow: []string{\n\t\t\t\t\"pacman -S --config /etc/pacman.conf -- core/linux\",\n\t\t\t\t\"pacman -D -q --asdeps --config /etc/pacman.conf -- linux\",\n\t\t\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\t\t\"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch\",\n\t\t\t\t\"pacman -U --config /etc/pacman.conf -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst\",\n\t\t\t\t\"pacman -D -q --asexplicit --config /etc/pacman.conf -- yay\",\n\t\t\t},\n\t\t\twantCapture: []string{\"makepkg --packagelist\"},\n\t\t\ttargets: []map[string]*dep.InstallInfo{\n\t\t\t\t{\n\t\t\t\t\t\"yay\": {\n\t\t\t\t\t\tSource:      dep.AUR,\n\t\t\t\t\t\tReason:      dep.Explicit,\n\t\t\t\t\t\tVersion:     \"91.0.0-1\",\n\t\t\t\t\t\tSrcinfoPath: ptrString(tmpDir + \"/.SRCINFO\"),\n\t\t\t\t\t\tAURBase:     ptrString(\"yay\"),\n\t\t\t\t\t},\n\t\t\t\t}, {\n\t\t\t\t\t\"linux\": {\n\t\t\t\t\t\tSource:     dep.Sync,\n\t\t\t\t\t\tReason:     dep.Dep,\n\t\t\t\t\t\tVersion:    \"17.0.0-1\",\n\t\t\t\t\t\tSyncDBName: ptrString(\"core\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc: \"same layer -- sync\",\n\t\t\twantShow: []string{\n\t\t\t\t\"pacman -S --config /etc/pacman.conf -- extra/linux-zen core/linux\",\n\t\t\t\t\"pacman -D -q --asexplicit --config /etc/pacman.conf -- linux-zen linux\",\n\t\t\t},\n\t\t\twantCapture: []string{},\n\t\t\ttargets: []map[string]*dep.InstallInfo{\n\t\t\t\t{\n\t\t\t\t\t\"linux-zen\": {\n\t\t\t\t\t\tSource:     dep.Sync,\n\t\t\t\t\t\tReason:     dep.Explicit,\n\t\t\t\t\t\tVersion:    \"18.0.0-1\",\n\t\t\t\t\t\tSyncDBName: ptrString(\"extra\"),\n\t\t\t\t\t},\n\t\t\t\t\t\"linux\": {\n\t\t\t\t\t\tSource:     dep.Sync,\n\t\t\t\t\t\tReason:     dep.Explicit,\n\t\t\t\t\t\tVersion:    \"17.0.0-1\",\n\t\t\t\t\t\tSyncDBName: ptrString(\"core\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc: \"same layer -- aur\",\n\t\t\twantShow: []string{\n\t\t\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\t\t\"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch\",\n\t\t\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\t\t\"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch\",\n\t\t\t\t\"pacman -U --config /etc/pacman.conf -- pacman -U --config /etc/pacman.conf -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst\",\n\t\t\t\t\"pacman -D -q --asexplicit --config /etc/pacman.conf -- yay\",\n\t\t\t},\n\t\t\twantCapture: []string{\"makepkg --packagelist\", \"makepkg --packagelist\"},\n\t\t\ttargets: []map[string]*dep.InstallInfo{\n\t\t\t\t{\n\t\t\t\t\t\"yay\": {\n\t\t\t\t\t\tSource:      dep.AUR,\n\t\t\t\t\t\tReason:      dep.Explicit,\n\t\t\t\t\t\tVersion:     \"91.0.0-1\",\n\t\t\t\t\t\tSrcinfoPath: ptrString(tmpDir + \"/.SRCINFO\"),\n\t\t\t\t\t\tAURBase:     ptrString(\"yay\"),\n\t\t\t\t\t},\n\t\t\t\t\t\"jellyfin-server\": {\n\t\t\t\t\t\tSource:      dep.AUR,\n\t\t\t\t\t\tReason:      dep.Explicit,\n\t\t\t\t\t\tVersion:     \"10.8.8-1\",\n\t\t\t\t\t\tSrcinfoPath: ptrString(tmpDirJfin + \"/.SRCINFO\"),\n\t\t\t\t\t\tAURBase:     ptrString(\"jellyfin\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc: \"different layer -- aur\",\n\t\t\twantShow: []string{\n\t\t\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\t\t\"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch\",\n\t\t\t\t\"pacman -U --config /etc/pacman.conf -- pacman -U --config /etc/pacman.conf -- /testdir/jellyfin-server-10.8.8-1-x86_64.pkg.tar.zst\",\n\t\t\t\t\"pacman -D -q --asdeps --config /etc/pacman.conf -- jellyfin-server\",\n\t\t\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\t\t\"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch\",\n\t\t\t\t\"pacman -U --config /etc/pacman.conf -- pacman -U --config /etc/pacman.conf -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst\",\n\t\t\t\t\"pacman -D -q --asexplicit --config /etc/pacman.conf -- yay\",\n\t\t\t},\n\t\t\twantCapture: []string{\"makepkg --packagelist\", \"makepkg --packagelist\"},\n\t\t\ttargets: []map[string]*dep.InstallInfo{\n\t\t\t\t{\n\t\t\t\t\t\"yay\": {\n\t\t\t\t\t\tSource:      dep.AUR,\n\t\t\t\t\t\tReason:      dep.Explicit,\n\t\t\t\t\t\tVersion:     \"91.0.0-1\",\n\t\t\t\t\t\tSrcinfoPath: ptrString(tmpDir + \"/.SRCINFO\"),\n\t\t\t\t\t\tAURBase:     ptrString(\"yay\"),\n\t\t\t\t\t},\n\t\t\t\t}, {\n\t\t\t\t\t\"jellyfin-server\": {\n\t\t\t\t\t\tSource:      dep.AUR,\n\t\t\t\t\t\tReason:      dep.MakeDep,\n\t\t\t\t\t\tVersion:     \"10.8.8-1\",\n\t\t\t\t\t\tSrcinfoPath: ptrString(tmpDirJfin + \"/.SRCINFO\"),\n\t\t\t\t\t\tAURBase:     ptrString(\"jellyfin\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.desc, func(td *testing.T) {\n\t\t\tpkgTar := tmpDir + \"/yay-91.0.0-1-x86_64.pkg.tar.zst\"\n\t\t\tjfinPkgTar := tmpDirJfin + \"/jellyfin-server-10.8.8-1-x86_64.pkg.tar.zst\"\n\n\t\t\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\t\t\tif cmd.Dir == tmpDirJfin {\n\t\t\t\t\treturn jfinPkgTar, \"\", nil\n\t\t\t\t}\n\n\t\t\t\tif cmd.Dir == tmpDir {\n\t\t\t\t\treturn pkgTar, \"\", nil\n\t\t\t\t}\n\n\t\t\t\treturn \"\", \"\", fmt.Errorf(\"unexpected command: %s - %s\", cmd.String(), cmd.Dir)\n\t\t\t}\n\n\t\t\tshowOverride := func(cmd *exec.Cmd) error {\n\t\t\t\tif strings.Contains(cmd.String(), \"makepkg -f --noconfirm\") && cmd.Dir == tmpDir {\n\t\t\t\t\tf, err := os.OpenFile(pkgTar, os.O_RDONLY|os.O_CREATE, 0o666)\n\t\t\t\t\trequire.NoError(td, err)\n\t\t\t\t\trequire.NoError(td, f.Close())\n\t\t\t\t}\n\n\t\t\t\tif strings.Contains(cmd.String(), \"makepkg -f --noconfirm\") && cmd.Dir == tmpDirJfin {\n\t\t\t\t\tf, err := os.OpenFile(jfinPkgTar, os.O_RDONLY|os.O_CREATE, 0o666)\n\t\t\t\t\trequire.NoError(td, err)\n\t\t\t\t\trequire.NoError(td, f.Close())\n\t\t\t\t}\n\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tdefer os.Remove(pkgTar)\n\t\t\tdefer os.Remove(jfinPkgTar)\n\n\t\t\tisCorrectInstalledOverride := func(string, string) bool {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tmockDB := &mock.DBExecutor{IsCorrectVersionInstalledFn: isCorrectInstalledOverride}\n\t\t\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\t\t\tcmdBuilder := &exe.CmdBuilder{\n\t\t\t\tMakepkgBin:       makepkgBin,\n\t\t\t\tSudoBin:          \"su\",\n\t\t\t\tPacmanBin:        pacmanBin,\n\t\t\t\tPacmanConfigPath: \"/etc/pacman.conf\",\n\t\t\t\tRunner:           mockRunner,\n\t\t\t\tSudoLoopEnabled:  false,\n\t\t\t}\n\n\t\t\tcmdBuilder.Runner = mockRunner\n\n\t\t\tinstaller := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny, parser.RebuildModeNo, false, newTestLogger())\n\n\t\t\tcmdArgs := parser.MakeArguments()\n\t\t\tcmdArgs.AddTarget(\"yay\")\n\n\t\t\tpkgBuildDirs := map[string]string{\n\t\t\t\t\"yay\":      tmpDir,\n\t\t\t\t\"jellyfin\": tmpDirJfin,\n\t\t\t}\n\n\t\t\terrI := installer.Install(context.Background(), cmdArgs, tc.targets, pkgBuildDirs, []string{}, false)\n\t\t\trequire.NoError(td, errI)\n\n\t\t\trequire.Len(td, mockRunner.ShowCalls, len(tc.wantShow))\n\t\t\trequire.Len(td, mockRunner.CaptureCalls, len(tc.wantCapture))\n\n\t\t\tfor i, call := range mockRunner.ShowCalls {\n\t\t\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\t\t\tshow = strings.ReplaceAll(show, tmpDir, \"/testdir\")     // replace the temp dir with a static path\n\t\t\t\tshow = strings.ReplaceAll(show, tmpDirJfin, \"/testdir\") // replace the temp dir with a static path\n\t\t\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\t\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\n\t\t\t\t// options are in a different order on different systems and on CI root user is used\n\t\t\t\tassert.Subset(td, strings.Split(show, \" \"), strings.Split(tc.wantShow[i], \" \"), show)\n\t\t\t}\n\n\t\t\tfor i, call := range mockRunner.CaptureCalls {\n\t\t\t\tcapture := call.Args[0].(*exec.Cmd).String()\n\t\t\t\tcapture = strings.ReplaceAll(capture, tmpDir, \"/testdir\") // replace the temp dir with a static path\n\t\t\t\tcapture = strings.ReplaceAll(capture, tmpDirJfin, \"/testdir\")\n\t\t\t\tcapture = strings.ReplaceAll(capture, makepkgBin, \"makepkg\")\n\t\t\t\tcapture = strings.ReplaceAll(capture, pacmanBin, \"pacman\")\n\t\t\t\tassert.Subset(td, strings.Split(capture, \" \"), strings.Split(tc.wantCapture[i], \" \"), capture)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestInstaller_RunPostHooks(t *testing.T) {\n\tmockDB := &mock.DBExecutor{}\n\tmockRunner := &exe.MockRunner{}\n\tcmdBuilder := &exe.CmdBuilder{\n\t\tMakepkgBin:       \"makepkg\",\n\t\tSudoBin:          \"su\",\n\t\tPacmanBin:        \"pacman\",\n\t\tPacmanConfigPath: \"/etc/pacman.conf\",\n\t\tRunner:           mockRunner,\n\t\tSudoLoopEnabled:  false,\n\t}\n\n\tcmdBuilder.Runner = mockRunner\n\n\tinstaller := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,\n\t\tparser.RebuildModeNo, false, newTestLogger())\n\n\tcalled := false\n\thook := func(ctx context.Context) error {\n\t\tcalled = true\n\t\treturn nil\n\t}\n\n\tinstaller.AddPostInstallHook(hook)\n\tinstaller.RunPostInstallHooks(context.Background())\n\n\tassert.True(t, called)\n}\n\nfunc TestInstaller_CompileFailed(t *testing.T) {\n\tt.Parallel()\n\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\ttype testCase struct {\n\t\tdesc           string\n\t\ttargets        []map[string]*dep.InstallInfo\n\t\twantErrInstall bool\n\t\twantErrCompile bool\n\t\tfailBuild      bool\n\t\tfailPkgInstall bool\n\t}\n\n\ttmpDir := t.TempDir()\n\n\ttestCases := []testCase{\n\t\t{\n\t\t\tdesc:           \"one layer\",\n\t\t\twantErrInstall: false,\n\t\t\twantErrCompile: true,\n\t\t\tfailBuild:      true,\n\t\t\tfailPkgInstall: false,\n\t\t\ttargets: []map[string]*dep.InstallInfo{\n\t\t\t\t{\n\t\t\t\t\t\"yay\": {\n\t\t\t\t\t\tSource:      dep.AUR,\n\t\t\t\t\t\tReason:      dep.Explicit,\n\t\t\t\t\t\tVersion:     \"91.0.0-1\",\n\t\t\t\t\t\tSrcinfoPath: ptrString(tmpDir + \"/.SRCINFO\"),\n\t\t\t\t\t\tAURBase:     ptrString(\"yay\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc:           \"one layer -- fail install\",\n\t\t\twantErrInstall: true,\n\t\t\twantErrCompile: false,\n\t\t\tfailBuild:      false,\n\t\t\tfailPkgInstall: true,\n\t\t\ttargets: []map[string]*dep.InstallInfo{\n\t\t\t\t{\n\t\t\t\t\t\"yay\": {\n\t\t\t\t\t\tSource:      dep.AUR,\n\t\t\t\t\t\tReason:      dep.Explicit,\n\t\t\t\t\t\tVersion:     \"91.0.0-1\",\n\t\t\t\t\t\tSrcinfoPath: ptrString(tmpDir + \"/.SRCINFO\"),\n\t\t\t\t\t\tAURBase:     ptrString(\"yay\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc:           \"two layers\",\n\t\t\twantErrInstall: false,\n\t\t\twantErrCompile: true,\n\t\t\tfailBuild:      true,\n\t\t\tfailPkgInstall: false,\n\t\t\ttargets: []map[string]*dep.InstallInfo{\n\t\t\t\t{\"bob\": {\n\t\t\t\t\tAURBase: ptrString(\"yay\"),\n\t\t\t\t}},\n\t\t\t\t{\n\t\t\t\t\t\"yay\": {\n\t\t\t\t\t\tSource:      dep.AUR,\n\t\t\t\t\t\tReason:      dep.Explicit,\n\t\t\t\t\t\tVersion:     \"91.0.0-1\",\n\t\t\t\t\t\tSrcinfoPath: ptrString(tmpDir + \"/.SRCINFO\"),\n\t\t\t\t\t\tAURBase:     ptrString(\"yay\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.desc, func(td *testing.T) {\n\t\t\tpkgTar := tmpDir + \"/yay-91.0.0-1-x86_64.pkg.tar.zst\"\n\n\t\t\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\t\t\treturn pkgTar, \"\", nil\n\t\t\t}\n\n\t\t\tshowOverride := func(cmd *exec.Cmd) error {\n\t\t\t\tif tc.failBuild && strings.Contains(cmd.String(), \"makepkg -f --noconfirm\") && cmd.Dir == tmpDir {\n\t\t\t\t\treturn errors.New(\"makepkg failed\")\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tisCorrectInstalledOverride := func(string, string) bool {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tmockDB := &mock.DBExecutor{IsCorrectVersionInstalledFn: isCorrectInstalledOverride}\n\t\t\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\t\t\tcmdBuilder := &exe.CmdBuilder{\n\t\t\t\tMakepkgBin:      makepkgBin,\n\t\t\t\tSudoBin:         \"su\",\n\t\t\t\tPacmanBin:       pacmanBin,\n\t\t\t\tRunner:          mockRunner,\n\t\t\t\tSudoLoopEnabled: false,\n\t\t\t}\n\n\t\t\tcmdBuilder.Runner = mockRunner\n\n\t\t\tinstaller := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,\n\t\t\t\tparser.RebuildModeNo, false, newTestLogger())\n\n\t\t\tcmdArgs := parser.MakeArguments()\n\t\t\tcmdArgs.AddArg(\"needed\")\n\t\t\tcmdArgs.AddTarget(\"yay\")\n\n\t\t\tpkgBuildDirs := map[string]string{\n\t\t\t\t\"yay\": tmpDir,\n\t\t\t}\n\n\t\t\terrI := installer.Install(context.Background(), cmdArgs, tc.targets, pkgBuildDirs, []string{}, false)\n\t\t\tif tc.wantErrInstall {\n\t\t\t\trequire.Error(td, errI)\n\t\t\t} else {\n\t\t\t\trequire.NoError(td, errI)\n\t\t\t}\n\t\t\tfailed, err := installer.CompileFailedAndIgnored()\n\t\t\tif tc.wantErrCompile {\n\t\t\t\trequire.Error(td, err)\n\t\t\t\tfor key := range failed {\n\t\t\t\t\tassert.ErrorContains(td, err, key)\n\t\t\t\t}\n\t\t\t\tuniqueBases := make(map[string]struct{})\n\t\t\t\tfor _, layer := range tc.targets {\n\t\t\t\t\tfor _, info := range layer {\n\t\t\t\t\t\tif info.AURBase != nil {\n\t\t\t\t\t\t\tuniqueBases[*info.AURBase] = struct{}{}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\trequire.Len(td, failed, len(uniqueBases))\n\t\t\t} else {\n\t\t\t\trequire.NoError(td, err)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestInstaller_InstallSplitPackage(t *testing.T) {\n\tt.Parallel()\n\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\ttype testCase struct {\n\t\tdesc        string\n\t\twantShow    []string\n\t\twantCapture []string\n\t\ttargets     []map[string]*dep.InstallInfo\n\t}\n\n\ttmpDir := t.TempDir()\n\n\ttestCases := []testCase{\n\t\t{\n\t\t\tdesc: \"jellyfin\",\n\t\t\ttargets: []map[string]*dep.InstallInfo{\n\t\t\t\t{\"jellyfin\": {\n\t\t\t\t\tSource:      dep.AUR,\n\t\t\t\t\tReason:      dep.Explicit,\n\t\t\t\t\tVersion:     \"10.8.4-1\",\n\t\t\t\t\tSrcinfoPath: ptrString(tmpDir + \"/.SRCINFO\"),\n\t\t\t\t\tAURBase:     ptrString(\"jellyfin\"),\n\t\t\t\t}},\n\t\t\t\t{\n\t\t\t\t\t\"jellyfin-server\": {\n\t\t\t\t\t\tSource:      dep.AUR,\n\t\t\t\t\t\tReason:      dep.Dep,\n\t\t\t\t\t\tVersion:     \"10.8.4-1\",\n\t\t\t\t\t\tSrcinfoPath: ptrString(tmpDir + \"/.SRCINFO\"),\n\t\t\t\t\t\tAURBase:     ptrString(\"jellyfin\"),\n\t\t\t\t\t},\n\t\t\t\t\t\"jellyfin-web\": {\n\t\t\t\t\t\tSource:      dep.AUR,\n\t\t\t\t\t\tReason:      dep.Dep,\n\t\t\t\t\t\tVersion:     \"10.8.4-1\",\n\t\t\t\t\t\tSrcinfoPath: ptrString(tmpDir + \"/.SRCINFO\"),\n\t\t\t\t\t\tAURBase:     ptrString(\"jellyfin\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"dotnet-runtime-6.0\": {\n\t\t\t\t\t\tSource:     dep.Sync,\n\t\t\t\t\t\tReason:     dep.Dep,\n\t\t\t\t\t\tVersion:    \"6.0.12.sdk112-1\",\n\t\t\t\t\t\tSyncDBName: ptrString(\"community\"),\n\t\t\t\t\t},\n\t\t\t\t\t\"aspnet-runtime\": {\n\t\t\t\t\t\tSource:     dep.Sync,\n\t\t\t\t\t\tReason:     dep.Dep,\n\t\t\t\t\t\tVersion:    \"6.0.12.sdk112-1\",\n\t\t\t\t\t\tSyncDBName: ptrString(\"community\"),\n\t\t\t\t\t},\n\t\t\t\t\t\"dotnet-sdk-6.0\": {\n\t\t\t\t\t\tSource:     dep.Sync,\n\t\t\t\t\t\tReason:     dep.MakeDep,\n\t\t\t\t\t\tVersion:    \"6.0.12.sdk112-1\",\n\t\t\t\t\t\tSyncDBName: ptrString(\"community\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twantShow: []string{\n\t\t\t\t\"pacman -S --config /etc/pacman.conf -- community/dotnet-runtime-6.0 community/aspnet-runtime community/dotnet-sdk-6.0\",\n\t\t\t\t\"pacman -D -q --asdeps --config /etc/pacman.conf -- dotnet-runtime-6.0 aspnet-runtime dotnet-sdk-6.0\",\n\t\t\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\t\t\"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch\",\n\t\t\t\t\"pacman -U --config /etc/pacman.conf -- /testdir/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst /testdir/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst\",\n\t\t\t\t\"pacman -D -q --asdeps --config /etc/pacman.conf -- jellyfin-server jellyfin-web\",\n\t\t\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\t\t\"makepkg -c --nobuild --noextract --ignorearch\",\n\t\t\t\t\"pacman -U --config /etc/pacman.conf -- /testdir/jellyfin-10.8.4-1-x86_64.pkg.tar.zst\",\n\t\t\t\t\"pacman -D -q --asexplicit --config /etc/pacman.conf -- jellyfin\",\n\t\t\t},\n\t\t\twantCapture: []string{\"makepkg --packagelist\", \"makepkg --packagelist\"},\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.desc, func(td *testing.T) {\n\t\t\tpkgTars := []string{\n\t\t\t\ttmpDir + \"/jellyfin-10.8.4-1-x86_64.pkg.tar.zst\",\n\t\t\t\ttmpDir + \"/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst\",\n\t\t\t\ttmpDir + \"/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst\",\n\t\t\t}\n\n\t\t\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\t\t\treturn strings.Join(pkgTars, \"\\n\"), \"\", nil\n\t\t\t}\n\n\t\t\ti := 0\n\t\t\tshowOverride := func(cmd *exec.Cmd) error {\n\t\t\t\ti++\n\t\t\t\tif i == 4 {\n\t\t\t\t\tfor _, pkgTar := range pkgTars {\n\t\t\t\t\t\tf, err := os.OpenFile(pkgTar, os.O_RDONLY|os.O_CREATE, 0o666)\n\t\t\t\t\t\trequire.NoError(td, err)\n\t\t\t\t\t\trequire.NoError(td, f.Close())\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tisCorrectInstalledOverride := func(string, string) bool {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tmockDB := &mock.DBExecutor{IsCorrectVersionInstalledFn: isCorrectInstalledOverride}\n\t\t\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\t\t\tcmdBuilder := &exe.CmdBuilder{\n\t\t\t\tMakepkgBin:       makepkgBin,\n\t\t\t\tSudoBin:          \"su\",\n\t\t\t\tPacmanBin:        pacmanBin,\n\t\t\t\tPacmanConfigPath: \"/etc/pacman.conf\",\n\t\t\t\tRunner:           mockRunner,\n\t\t\t\tSudoLoopEnabled:  false,\n\t\t\t}\n\n\t\t\tcmdBuilder.Runner = mockRunner\n\n\t\t\tinstaller := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,\n\t\t\t\tparser.RebuildModeNo, false, newTestLogger())\n\n\t\t\tcmdArgs := parser.MakeArguments()\n\t\t\tcmdArgs.AddTarget(\"jellyfin\")\n\n\t\t\tpkgBuildDirs := map[string]string{\n\t\t\t\t\"jellyfin\": tmpDir,\n\t\t\t}\n\n\t\t\terrI := installer.Install(context.Background(), cmdArgs, tc.targets, pkgBuildDirs, []string{}, false)\n\t\t\trequire.NoError(td, errI)\n\n\t\t\trequire.Len(td, mockRunner.ShowCalls, len(tc.wantShow))\n\t\t\trequire.Len(td, mockRunner.CaptureCalls, len(tc.wantCapture))\n\n\t\t\tfor i, call := range mockRunner.ShowCalls {\n\t\t\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\t\t\tshow = strings.ReplaceAll(show, tmpDir, \"/testdir\") // replace the temp dir with a static path\n\t\t\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\t\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\n\t\t\t\t// options are in a different order on different systems and on CI root user is used\n\t\t\t\tassert.Subset(td, strings.Split(show, \" \"),\n\t\t\t\t\tstrings.Split(tc.wantShow[i], \" \"),\n\t\t\t\t\tfmt.Sprintf(\"got at %d: %s \\n\", i, show))\n\t\t\t}\n\n\t\t\tfor i, call := range mockRunner.CaptureCalls {\n\t\t\t\tcapture := call.Args[0].(*exec.Cmd).String()\n\t\t\t\tcapture = strings.ReplaceAll(capture, tmpDir, \"/testdir\") // replace the temp dir with a static path\n\t\t\t\tcapture = strings.ReplaceAll(capture, makepkgBin, \"makepkg\")\n\t\t\t\tcapture = strings.ReplaceAll(capture, pacmanBin, \"pacman\")\n\t\t\t\tassert.Subset(td, strings.Split(capture, \" \"), strings.Split(tc.wantCapture[i], \" \"), capture)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestInstaller_InstallDownloadOnly(t *testing.T) {\n\tt.Parallel()\n\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\ttype testCase struct {\n\t\tdesc        string\n\t\tisInstalled bool\n\t\tisBuilt     bool\n\t\twantShow    []string\n\t\twantCapture []string\n\t}\n\n\ttestCases := []testCase{\n\t\t{\n\t\t\tdesc:        \"not installed and not built\",\n\t\t\tisInstalled: false,\n\t\t\tisBuilt:     false,\n\t\t\twantShow: []string{\n\t\t\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\t\t\"makepkg -c --nobuild --noextract --ignorearch\",\n\t\t\t},\n\t\t\twantCapture: []string{\"makepkg --packagelist\"},\n\t\t},\n\t\t{\n\t\t\tdesc:        \"not installed and built\",\n\t\t\tisInstalled: false,\n\t\t\tisBuilt:     true,\n\t\t\twantShow: []string{\n\t\t\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\t\t\"makepkg -c --nobuild --noextract --ignorearch\",\n\t\t\t},\n\t\t\twantCapture: []string{\"makepkg --packagelist\"},\n\t\t},\n\t\t{\n\t\t\tdesc:        \"installed\",\n\t\t\tisInstalled: true,\n\t\t\tisBuilt:     false,\n\t\t\twantShow: []string{\n\t\t\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\t\t\"makepkg -c --nobuild --noextract --ignorearch\",\n\t\t\t},\n\t\t\twantCapture: []string{\"makepkg --packagelist\"},\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.desc, func(td *testing.T) {\n\t\t\ttmpDir := td.TempDir()\n\t\t\tpkgTar := tmpDir + \"/yay-91.0.0-1-x86_64.pkg.tar.zst\"\n\n\t\t\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\t\t\treturn pkgTar, \"\", nil\n\t\t\t}\n\n\t\t\ti := 0\n\t\t\tshowOverride := func(cmd *exec.Cmd) error {\n\t\t\t\ti++\n\t\t\t\tif i == 2 {\n\t\t\t\t\tif !tc.isBuilt {\n\t\t\t\t\t\tf, err := os.OpenFile(pkgTar, os.O_RDONLY|os.O_CREATE, 0o666)\n\t\t\t\t\t\trequire.NoError(td, err)\n\t\t\t\t\t\trequire.NoError(td, f.Close())\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\t// create a mock file\n\t\t\tif tc.isBuilt {\n\t\t\t\tf, err := os.OpenFile(pkgTar, os.O_RDONLY|os.O_CREATE, 0o666)\n\t\t\t\trequire.NoError(td, err)\n\t\t\t\trequire.NoError(td, f.Close())\n\t\t\t}\n\n\t\t\tisCorrectInstalledOverride := func(string, string) bool {\n\t\t\t\treturn tc.isInstalled\n\t\t\t}\n\n\t\t\tmockDB := &mock.DBExecutor{IsCorrectVersionInstalledFn: isCorrectInstalledOverride}\n\t\t\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\t\t\tcmdBuilder := &exe.CmdBuilder{\n\t\t\t\tMakepkgBin:      makepkgBin,\n\t\t\t\tSudoBin:         \"su\",\n\t\t\t\tPacmanBin:       pacmanBin,\n\t\t\t\tRunner:          mockRunner,\n\t\t\t\tSudoLoopEnabled: false,\n\t\t\t}\n\n\t\t\tcmdBuilder.Runner = mockRunner\n\n\t\t\tinstaller := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,\n\t\t\t\tparser.RebuildModeNo, true, newTestLogger())\n\n\t\t\tcmdArgs := parser.MakeArguments()\n\t\t\tcmdArgs.AddTarget(\"yay\")\n\n\t\t\tpkgBuildDirs := map[string]string{\n\t\t\t\t\"yay\": tmpDir,\n\t\t\t}\n\n\t\t\ttargets := []map[string]*dep.InstallInfo{\n\t\t\t\t{\n\t\t\t\t\t\"yay\": {\n\t\t\t\t\t\tSource:      dep.AUR,\n\t\t\t\t\t\tReason:      dep.Explicit,\n\t\t\t\t\t\tVersion:     \"91.0.0-1\",\n\t\t\t\t\t\tSrcinfoPath: ptrString(tmpDir + \"/.SRCINFO\"),\n\t\t\t\t\t\tAURBase:     ptrString(\"yay\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\n\t\t\terrI := installer.Install(context.Background(), cmdArgs, targets, pkgBuildDirs, []string{}, false)\n\t\t\trequire.NoError(td, errI)\n\n\t\t\trequire.Len(td, mockRunner.ShowCalls, len(tc.wantShow))\n\t\t\trequire.Len(td, mockRunner.CaptureCalls, len(tc.wantCapture))\n\t\t\trequire.Empty(td, installer.failedAndIgnored)\n\n\t\t\tfor i, call := range mockRunner.ShowCalls {\n\t\t\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\t\t\tshow = strings.ReplaceAll(show, tmpDir, \"/testdir\") // replace the temp dir with a static path\n\t\t\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\t\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\n\t\t\t\t// options are in a different order on different systems and on CI root user is used\n\t\t\t\tassert.Subset(td, strings.Split(show, \" \"), strings.Split(tc.wantShow[i], \" \"), show)\n\t\t\t}\n\n\t\t\tfor i, call := range mockRunner.CaptureCalls {\n\t\t\t\tcapture := call.Args[0].(*exec.Cmd).String()\n\t\t\t\tcapture = strings.ReplaceAll(capture, tmpDir, \"/testdir\") // replace the temp dir with a static path\n\t\t\t\tcapture = strings.ReplaceAll(capture, makepkgBin, \"makepkg\")\n\t\t\t\tcapture = strings.ReplaceAll(capture, pacmanBin, \"pacman\")\n\t\t\t\tassert.Subset(td, strings.Split(capture, \" \"), strings.Split(tc.wantCapture[i], \" \"), capture)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestInstaller_InstallGroup(t *testing.T) {\n\tt.Parallel()\n\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\ttype testCase struct {\n\t\tdesc        string\n\t\twantShow    []string\n\t\twantCapture []string\n\t}\n\n\ttestCases := []testCase{\n\t\t{\n\t\t\tdesc: \"group\",\n\t\t\twantShow: []string{\n\t\t\t\t\"pacman -S --noconfirm --config  -- community/kubernetes-tools\",\n\t\t\t},\n\t\t\twantCapture: []string{},\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.desc, func(td *testing.T) {\n\t\t\ttmpDir := td.TempDir()\n\n\t\t\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\t\t\treturn \"\", \"\", nil\n\t\t\t}\n\n\t\t\tshowOverride := func(cmd *exec.Cmd) error {\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tmockDB := &mock.DBExecutor{}\n\t\t\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\t\t\tcmdBuilder := &exe.CmdBuilder{\n\t\t\t\tMakepkgBin:      makepkgBin,\n\t\t\t\tSudoBin:         \"su\",\n\t\t\t\tPacmanBin:       pacmanBin,\n\t\t\t\tRunner:          mockRunner,\n\t\t\t\tSudoLoopEnabled: false,\n\t\t\t}\n\n\t\t\tcmdBuilder.Runner = mockRunner\n\n\t\t\tinstaller := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,\n\t\t\t\tparser.RebuildModeNo, true, newTestLogger())\n\n\t\t\tcmdArgs := parser.MakeArguments()\n\t\t\tcmdArgs.AddTarget(\"kubernetes-tools\")\n\n\t\t\tpkgBuildDirs := map[string]string{}\n\n\t\t\ttargets := []map[string]*dep.InstallInfo{\n\t\t\t\t{\n\t\t\t\t\t\"kubernetes-tools\": {\n\t\t\t\t\t\tSource:     dep.Sync,\n\t\t\t\t\t\tReason:     dep.Explicit,\n\t\t\t\t\t\tVersion:    \"\",\n\t\t\t\t\t\tIsGroup:    true,\n\t\t\t\t\t\tSyncDBName: ptrString(\"community\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\n\t\t\terrI := installer.Install(context.Background(), cmdArgs, targets, pkgBuildDirs, []string{}, false)\n\t\t\trequire.NoError(td, errI)\n\n\t\t\trequire.Len(td, mockRunner.ShowCalls, len(tc.wantShow))\n\t\t\trequire.Len(td, mockRunner.CaptureCalls, len(tc.wantCapture))\n\t\t\trequire.Empty(td, installer.failedAndIgnored)\n\n\t\t\tfor i, call := range mockRunner.ShowCalls {\n\t\t\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\t\t\tshow = strings.ReplaceAll(show, tmpDir, \"/testdir\") // replace the temp dir with a static path\n\t\t\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\t\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\n\t\t\t\t// options are in a different order on different systems and on CI root user is used\n\t\t\t\tassert.Subset(td, strings.Split(show, \" \"), strings.Split(tc.wantShow[i], \" \"), show)\n\t\t\t}\n\n\t\t\tfor i, call := range mockRunner.CaptureCalls {\n\t\t\t\tcapture := call.Args[0].(*exec.Cmd).String()\n\t\t\t\tcapture = strings.ReplaceAll(capture, tmpDir, \"/testdir\") // replace the temp dir with a static path\n\t\t\t\tcapture = strings.ReplaceAll(capture, makepkgBin, \"makepkg\")\n\t\t\t\tcapture = strings.ReplaceAll(capture, pacmanBin, \"pacman\")\n\t\t\t\tassert.Subset(td, strings.Split(capture, \" \"), strings.Split(tc.wantCapture[i], \" \"), capture)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestInstaller_InstallRebuild(t *testing.T) {\n\tt.Parallel()\n\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\ttype testCase struct {\n\t\tdesc          string\n\t\trebuildOption parser.RebuildMode\n\t\tisInstalled   bool\n\t\tisBuilt       bool\n\t\twantShow      []string\n\t\twantCapture   []string\n\t\ttargets       []map[string]*dep.InstallInfo\n\t}\n\n\ttmpDir := t.TempDir()\n\n\ttestCases := []testCase{\n\t\t{\n\t\t\tdesc:          \"--norebuild(default) when built and not installed\",\n\t\t\trebuildOption: parser.RebuildModeNo,\n\t\t\tisBuilt:       true,\n\t\t\tisInstalled:   false,\n\t\t\twantShow: []string{\n\t\t\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\t\t\"makepkg -c --nobuild --noextract --ignorearch\",\n\t\t\t\t\"pacman -U --config  -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst\",\n\t\t\t\t\"pacman -D -q --asexplicit --config  -- yay\",\n\t\t\t},\n\t\t\twantCapture: []string{\"makepkg --packagelist\"},\n\t\t\ttargets: []map[string]*dep.InstallInfo{\n\t\t\t\t{\n\t\t\t\t\t\"yay\": {\n\t\t\t\t\t\tSource:      dep.AUR,\n\t\t\t\t\t\tReason:      dep.Explicit,\n\t\t\t\t\t\tVersion:     \"91.0.0-1\",\n\t\t\t\t\t\tSrcinfoPath: ptrString(tmpDir + \"/.SRCINFO\"),\n\t\t\t\t\t\tAURBase:     ptrString(\"yay\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc:          \"--rebuild when built and not installed\",\n\t\t\trebuildOption: parser.RebuildModeYes,\n\t\t\tisBuilt:       true,\n\t\t\tisInstalled:   false,\n\t\t\twantShow: []string{\n\t\t\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\t\t\"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch\",\n\t\t\t\t\"pacman -U --config  -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst\",\n\t\t\t\t\"pacman -D -q --asexplicit --config  -- yay\",\n\t\t\t},\n\t\t\twantCapture: []string{\"makepkg --packagelist\"},\n\t\t\ttargets: []map[string]*dep.InstallInfo{\n\t\t\t\t{\n\t\t\t\t\t\"yay\": {\n\t\t\t\t\t\tSource:      dep.AUR,\n\t\t\t\t\t\tReason:      dep.Explicit,\n\t\t\t\t\t\tVersion:     \"91.0.0-1\",\n\t\t\t\t\t\tSrcinfoPath: ptrString(tmpDir + \"/.SRCINFO\"),\n\t\t\t\t\t\tAURBase:     ptrString(\"yay\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc:          \"--rebuild when built and installed\",\n\t\t\trebuildOption: parser.RebuildModeYes,\n\t\t\tisInstalled:   true,\n\t\t\tisBuilt:       true,\n\t\t\twantShow: []string{\n\t\t\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\t\t\"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch\",\n\t\t\t\t\"pacman -U --config  -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst\",\n\t\t\t\t\"pacman -D -q --asexplicit --config  -- yay\",\n\t\t\t},\n\t\t\twantCapture: []string{\"makepkg --packagelist\"},\n\t\t\ttargets: []map[string]*dep.InstallInfo{\n\t\t\t\t{\n\t\t\t\t\t\"yay\": {\n\t\t\t\t\t\tSource:      dep.AUR,\n\t\t\t\t\t\tReason:      dep.Explicit,\n\t\t\t\t\t\tVersion:     \"91.0.0-1\",\n\t\t\t\t\t\tSrcinfoPath: ptrString(tmpDir + \"/.SRCINFO\"),\n\t\t\t\t\t\tAURBase:     ptrString(\"yay\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdesc:          \"--rebuild when built and installed previously as dep\",\n\t\t\trebuildOption: parser.RebuildModeYes,\n\t\t\tisInstalled:   true,\n\t\t\tisBuilt:       true,\n\t\t\twantShow: []string{\n\t\t\t\t\"makepkg --nobuild -f -C --ignorearch\",\n\t\t\t\t\"makepkg -f -c --noconfirm --noextract --noprepare --holdver --ignorearch\",\n\t\t\t\t\"pacman -U --config  -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst\",\n\t\t\t\t\"pacman -D -q --asdeps --config  -- yay\",\n\t\t\t},\n\t\t\twantCapture: []string{\"makepkg --packagelist\"},\n\t\t\ttargets: []map[string]*dep.InstallInfo{\n\t\t\t\t{\n\t\t\t\t\t\"yay\": {\n\t\t\t\t\t\tSource:      dep.AUR,\n\t\t\t\t\t\tReason:      dep.Dep,\n\t\t\t\t\t\tVersion:     \"91.0.0-1\",\n\t\t\t\t\t\tSrcinfoPath: ptrString(tmpDir + \"/.SRCINFO\"),\n\t\t\t\t\t\tAURBase:     ptrString(\"yay\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.desc, func(td *testing.T) {\n\t\t\ttmpDir := td.TempDir()\n\t\t\tpkgTar := tmpDir + \"/yay-91.0.0-1-x86_64.pkg.tar.zst\"\n\n\t\t\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\t\t\treturn pkgTar, \"\", nil\n\t\t\t}\n\n\t\t\ti := 0\n\t\t\tshowOverride := func(cmd *exec.Cmd) error {\n\t\t\t\ti++\n\t\t\t\tif i == 2 {\n\t\t\t\t\tif !tc.isBuilt {\n\t\t\t\t\t\tf, err := os.OpenFile(pkgTar, os.O_RDONLY|os.O_CREATE, 0o666)\n\t\t\t\t\t\trequire.NoError(td, err)\n\t\t\t\t\t\trequire.NoError(td, f.Close())\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\t// create a mock file\n\t\t\tif tc.isBuilt {\n\t\t\t\tf, err := os.OpenFile(pkgTar, os.O_RDONLY|os.O_CREATE, 0o666)\n\t\t\t\trequire.NoError(td, err)\n\t\t\t\trequire.NoError(td, f.Close())\n\t\t\t}\n\n\t\t\tisCorrectInstalledOverride := func(string, string) bool {\n\t\t\t\treturn tc.isInstalled\n\t\t\t}\n\n\t\t\tmockDB := &mock.DBExecutor{IsCorrectVersionInstalledFn: isCorrectInstalledOverride}\n\t\t\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\t\t\tcmdBuilder := &exe.CmdBuilder{\n\t\t\t\tMakepkgBin:      makepkgBin,\n\t\t\t\tSudoBin:         \"su\",\n\t\t\t\tPacmanBin:       pacmanBin,\n\t\t\t\tRunner:          mockRunner,\n\t\t\t\tSudoLoopEnabled: false,\n\t\t\t}\n\n\t\t\tcmdBuilder.Runner = mockRunner\n\n\t\t\tinstaller := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,\n\t\t\t\ttc.rebuildOption, false, newTestLogger())\n\n\t\t\tcmdArgs := parser.MakeArguments()\n\t\t\tcmdArgs.AddTarget(\"yay\")\n\n\t\t\tpkgBuildDirs := map[string]string{\n\t\t\t\t\"yay\": tmpDir,\n\t\t\t}\n\n\t\t\terrI := installer.Install(context.Background(), cmdArgs, tc.targets, pkgBuildDirs, []string{}, false)\n\t\t\trequire.NoError(td, errI)\n\n\t\t\trequire.Len(td, mockRunner.ShowCalls, len(tc.wantShow))\n\t\t\trequire.Len(td, mockRunner.CaptureCalls, len(tc.wantCapture))\n\n\t\t\tfor i, call := range mockRunner.ShowCalls {\n\t\t\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\t\t\tshow = strings.ReplaceAll(show, tmpDir, \"/testdir\") // replace the temp dir with a static path\n\t\t\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\t\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\n\t\t\t\t// options are in a different order on different systems and on CI root user is used\n\t\t\t\tassert.Subset(td, strings.Split(show, \" \"), strings.Split(tc.wantShow[i], \" \"), show)\n\t\t\t}\n\n\t\t\tfor i, call := range mockRunner.CaptureCalls {\n\t\t\t\tcapture := call.Args[0].(*exec.Cmd).String()\n\t\t\t\tcapture = strings.ReplaceAll(capture, tmpDir, \"/testdir\") // replace the temp dir with a static path\n\t\t\t\tcapture = strings.ReplaceAll(capture, makepkgBin, \"makepkg\")\n\t\t\t\tcapture = strings.ReplaceAll(capture, pacmanBin, \"pacman\")\n\t\t\t\tassert.Subset(td, strings.Split(capture, \" \"), strings.Split(tc.wantCapture[i], \" \"), capture)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestInstaller_InstallUpgrade(t *testing.T) {\n\tt.Parallel()\n\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\ttype testCase struct {\n\t\tdesc       string\n\t\ttargetMode parser.TargetMode\n\t}\n\n\ttmpDir := t.TempDir()\n\n\ttestCases := []testCase{\n\t\t{\n\t\t\tdesc:       \"target any\",\n\t\t\ttargetMode: parser.ModeAny,\n\t\t},\n\t\t{\n\t\t\tdesc:       \"target repo\",\n\t\t\ttargetMode: parser.ModeRepo,\n\t\t},\n\t\t{\n\t\t\tdesc:       \"target aur\",\n\t\t\ttargetMode: parser.ModeAUR,\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.desc, func(td *testing.T) {\n\t\t\tmockDB := &mock.DBExecutor{}\n\t\t\tmockRunner := &exe.MockRunner{}\n\t\t\tcmdBuilder := &exe.CmdBuilder{\n\t\t\t\tMakepkgBin:      makepkgBin,\n\t\t\t\tSudoBin:         \"su\",\n\t\t\t\tPacmanBin:       pacmanBin,\n\t\t\t\tRunner:          mockRunner,\n\t\t\t\tSudoLoopEnabled: false,\n\t\t\t}\n\n\t\t\tinstaller := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, tc.targetMode,\n\t\t\t\tparser.RebuildModeNo, false, newTestLogger())\n\n\t\t\tcmdArgs := parser.MakeArguments()\n\t\t\tcmdArgs.AddArg(\"u\", \"upgrades\") // Make sure both args are removed\n\n\t\t\ttargets := []map[string]*dep.InstallInfo{\n\t\t\t\t{\n\t\t\t\t\t\"linux\": {\n\t\t\t\t\t\tSource:     dep.Sync,\n\t\t\t\t\t\tReason:     dep.Dep,\n\t\t\t\t\t\tVersion:    \"17.0.0-1\",\n\t\t\t\t\t\tSyncDBName: ptrString(\"core\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\n\t\t\terrI := installer.Install(context.Background(), cmdArgs, targets, map[string]string{}, []string{}, false)\n\t\t\trequire.NoError(td, errI)\n\n\t\t\trequire.NotEmpty(td, mockRunner.ShowCalls)\n\n\t\t\t// The first call is the only call being test\n\t\t\tcall := mockRunner.ShowCalls[0]\n\t\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\t\tshow = strings.ReplaceAll(show, tmpDir, \"/testdir\") // replace the temp dir with a static path\n\t\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\n\t\t\tif tc.targetMode == parser.ModeAUR {\n\t\t\t\tassert.NotContains(td, show, \"--upgrades\")\n\t\t\t\tassert.NotContains(td, show, \"-u\")\n\t\t\t} else {\n\t\t\t\tassert.Contains(td, show, \"--upgrades\")\n\t\t\t\tassert.Contains(td, show, \"-u\")\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestInstaller_KeepSrc(t *testing.T) {\n\tt.Parallel()\n\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\ttype testCase struct {\n\t\tdesc     string\n\t\twantShow []string\n\t\ttargets  []map[string]*dep.InstallInfo\n\t}\n\n\ttmpDir := t.TempDir()\n\n\ttestCases := []testCase{\n\t\t{\n\t\t\tdesc: \"--keepsrc\",\n\t\t\twantShow: []string{\n\t\t\t\t\"makepkg --nobuild -f --ignorearch\",\n\t\t\t\t\"makepkg --nobuild --noextract --ignorearch\",\n\t\t\t\t\"pacman -U --config  -- /testdir/yay-92.0.0-1-x86_64.pkg.tar.zst\",\n\t\t\t\t\"pacman -D -q --asexplicit --config  -- yay\",\n\t\t\t},\n\t\t\ttargets: []map[string]*dep.InstallInfo{\n\t\t\t\t{\n\t\t\t\t\t\"yay\": {\n\t\t\t\t\t\tSource:      dep.AUR,\n\t\t\t\t\t\tReason:      dep.Explicit,\n\t\t\t\t\t\tVersion:     \"92.0.0-1\",\n\t\t\t\t\t\tSrcinfoPath: ptrString(tmpDir + \"/.SRCINFO\"),\n\t\t\t\t\t\tAURBase:     ptrString(\"yay\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.desc, func(td *testing.T) {\n\t\t\ttmpDir := td.TempDir()\n\t\t\tpkgTar := tmpDir + \"/yay-92.0.0-1-x86_64.pkg.tar.zst\"\n\n\t\t\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\t\t\treturn pkgTar, \"\", nil\n\t\t\t}\n\n\t\t\t// create a mock file\n\t\t\tf, err := os.OpenFile(pkgTar, os.O_RDONLY|os.O_CREATE, 0o666)\n\t\t\trequire.NoError(td, err)\n\t\t\trequire.NoError(td, f.Close())\n\n\t\t\tmockDB := &mock.DBExecutor{}\n\t\t\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride}\n\t\t\tcmdBuilder := &exe.CmdBuilder{\n\t\t\t\tMakepkgBin:      makepkgBin,\n\t\t\t\tSudoBin:         \"su\",\n\t\t\t\tPacmanBin:       pacmanBin,\n\t\t\t\tKeepSrc:         true,\n\t\t\t\tRunner:          mockRunner,\n\t\t\t\tSudoLoopEnabled: false,\n\t\t\t}\n\n\t\t\tinstaller := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,\n\t\t\t\tparser.RebuildModeNo, false, newTestLogger())\n\n\t\t\tcmdArgs := parser.MakeArguments()\n\t\t\tcmdArgs.AddTarget(\"yay\")\n\n\t\t\tpkgBuildDirs := map[string]string{\n\t\t\t\t\"yay\": tmpDir,\n\t\t\t}\n\n\t\t\terrI := installer.Install(context.Background(), cmdArgs, tc.targets, pkgBuildDirs, []string{}, false)\n\t\t\trequire.NoError(td, errI)\n\n\t\t\trequire.Len(td, mockRunner.ShowCalls, len(tc.wantShow))\n\n\t\t\tfor i, call := range mockRunner.ShowCalls {\n\t\t\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\t\t\tshow = strings.ReplaceAll(show, tmpDir, \"/testdir\") // replace the temp dir with a static path\n\t\t\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\t\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\n\t\t\t\t// options are in a different order on different systems and on CI root user is used\n\t\t\t\tassert.Subset(td, strings.Split(show, \" \"), strings.Split(tc.wantShow[i], \" \"), show)\n\n\t\t\t\t// Only assert makepkg commands don't have clean arguments\n\t\t\t\tif strings.HasPrefix(show, \"makepkg\") {\n\t\t\t\t\tassert.NotContains(td, show, \"-c\")\n\t\t\t\t\tassert.NotContains(td, show, \"-C\")\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\n// TestInstaller_InstallAsExplicit tests that --asexplicit flag only affects\n// targeted packages, not their dependencies. This is a regression test for\n// the bug where --asexplicit was ignored when reinstalling packages previously\n// installed as dependencies.\nfunc TestInstaller_InstallAsExplicit(t *testing.T) {\n\tt.Parallel()\n\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\ttmpDir := t.TempDir()\n\n\ttype testCase struct {\n\t\tdesc        string\n\t\tcmdArgs     func() *parser.Arguments\n\t\ttargets     []map[string]*dep.InstallInfo\n\t\twantShow    []string\n\t\twantCapture []string\n\t}\n\n\ttestCases := []testCase{\n\t\t{\n\t\t\tdesc: \"reinstall dep as explicit with --asexplicit (AUR)\",\n\t\t\tcmdArgs: func() *parser.Arguments {\n\t\t\t\targs := parser.MakeArguments()\n\t\t\t\targs.AddArg(\"asexplicit\")\n\t\t\t\targs.AddTarget(\"yay\")\n\t\t\t\treturn args\n\t\t\t},\n\t\t\ttargets: []map[string]*dep.InstallInfo{\n\t\t\t\t{\n\t\t\t\t\t\"yay\": {\n\t\t\t\t\t\tSource:      dep.AUR,\n\t\t\t\t\t\tReason:      dep.Dep,\n\t\t\t\t\t\tVersion:     \"91.0.0-1\",\n\t\t\t\t\t\tSrcinfoPath: ptrString(tmpDir + \"/.SRCINFO\"),\n\t\t\t\t\t\tAURBase:     ptrString(\"yay\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twantShow: []string{\n\t\t\t\t\"makepkg --nobuild --ignorearch\",\n\t\t\t\t\"makepkg --noconfirm --noextract --noprepare --holdver --ignorearch\",\n\t\t\t\t\"pacman -U --config -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst\",\n\t\t\t\t\"pacman -D --asexplicit -q --config -- yay\",\n\t\t\t},\n\t\t\twantCapture: []string{\"makepkg --packagelist\"},\n\t\t},\n\t\t{\n\t\t\tdesc: \"reinstall dep as explicit with --asexplicit (Sync)\",\n\t\t\tcmdArgs: func() *parser.Arguments {\n\t\t\t\targs := parser.MakeArguments()\n\t\t\t\targs.AddArg(\"asexplicit\")\n\t\t\t\targs.AddTarget(\"linux\")\n\t\t\t\treturn args\n\t\t\t},\n\t\t\ttargets: []map[string]*dep.InstallInfo{\n\t\t\t\t{\n\t\t\t\t\t\"linux\": {\n\t\t\t\t\t\tSource:     dep.Sync,\n\t\t\t\t\t\tReason:     dep.Dep,\n\t\t\t\t\t\tVersion:    \"17.0.0-1\",\n\t\t\t\t\t\tSyncDBName: ptrString(\"core\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twantShow: []string{\n\t\t\t\t\"pacman -S --config /etc/pacman.conf -- core/linux\",\n\t\t\t\t\"pacman -D -q --asexplicit --config /etc/pacman.conf -- linux\",\n\t\t\t},\n\t\t\twantCapture: []string{},\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.desc, func(td *testing.T) {\n\t\t\tpkgTar := tmpDir + \"/yay-91.0.0-1-x86_64.pkg.tar.zst\"\n\n\t\t\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\t\t\treturn pkgTar, \"\", nil\n\t\t\t}\n\n\t\t\tshowOverride := func(cmd *exec.Cmd) error {\n\t\t\t\tif strings.Contains(cmd.String(), \"makepkg -f --noconfirm\") && cmd.Dir == tmpDir {\n\t\t\t\t\tf, err := os.OpenFile(pkgTar, os.O_RDONLY|os.O_CREATE, 0o666)\n\t\t\t\t\trequire.NoError(td, err)\n\t\t\t\t\trequire.NoError(td, f.Close())\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tisCorrectInstalledOverride := func(string, string) bool {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tmockDB := &mock.DBExecutor{IsCorrectVersionInstalledFn: isCorrectInstalledOverride}\n\t\t\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\t\t\tcmdBuilder := &exe.CmdBuilder{\n\t\t\t\tMakepkgBin:       makepkgBin,\n\t\t\t\tSudoBin:          \"su\",\n\t\t\t\tPacmanBin:        pacmanBin,\n\t\t\t\tPacmanConfigPath: \"/etc/pacman.conf\",\n\t\t\t\tRunner:           mockRunner,\n\t\t\t\tSudoLoopEnabled:  false,\n\t\t\t}\n\n\t\t\tinstaller := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny,\n\t\t\t\tparser.RebuildModeNo, false, newTestLogger())\n\n\t\t\tcmdArgs := tc.cmdArgs()\n\n\t\t\tpkgBuildDirs := map[string]string{\n\t\t\t\t\"yay\": tmpDir,\n\t\t\t}\n\n\t\t\terrI := installer.Install(context.Background(), cmdArgs, tc.targets, pkgBuildDirs, []string{}, false)\n\t\t\trequire.NoError(td, errI)\n\n\t\t\trequire.Len(td, mockRunner.ShowCalls, len(tc.wantShow))\n\t\t\trequire.Len(td, mockRunner.CaptureCalls, len(tc.wantCapture))\n\n\t\t\tfor i, call := range mockRunner.ShowCalls {\n\t\t\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\t\t\tshow = strings.ReplaceAll(show, tmpDir, \"/testdir\")\n\t\t\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\t\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\n\t\t\t\tassert.Subset(td, strings.Split(show, \" \"), strings.Split(tc.wantShow[i], \" \"), show)\n\t\t\t}\n\n\t\t\tfor i, call := range mockRunner.CaptureCalls {\n\t\t\t\tcapture := call.Args[0].(*exec.Cmd).String()\n\t\t\t\tcapture = strings.ReplaceAll(capture, tmpDir, \"/testdir\")\n\t\t\t\tcapture = strings.ReplaceAll(capture, makepkgBin, \"makepkg\")\n\t\t\t\tcapture = strings.ReplaceAll(capture, pacmanBin, \"pacman\")\n\t\t\t\tassert.Subset(td, strings.Split(capture, \" \"), strings.Split(tc.wantCapture[i], \" \"), capture)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/sync/build/pkg_archive.go",
    "content": "package build\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/vcs\"\n)\n\nfunc installPkgArchive(ctx context.Context,\n\tcmdBuilder exe.ICmdBuilder,\n\tmode parser.TargetMode,\n\tvcsStore vcs.Store,\n\tcmdArgs *parser.Arguments,\n\tpkgArchives []string,\n\tnoConfirm bool,\n) error {\n\tif len(pkgArchives) == 0 {\n\t\treturn nil\n\t}\n\n\targuments := cmdArgs.Copy()\n\targuments.ClearTargets()\n\targuments.Op = \"U\"\n\targuments.DelArg(\"confirm\")\n\targuments.DelArg(\"noconfirm\")\n\targuments.DelArg(\"c\", \"clean\")\n\targuments.DelArg(\"i\", \"install\")\n\targuments.DelArg(\"q\", \"quiet\")\n\targuments.DelArg(\"y\", \"refresh\")\n\targuments.DelArg(\"u\", \"sysupgrade\")\n\targuments.DelArg(\"w\", \"downloadonly\")\n\targuments.DelArg(\"asdeps\", \"asdep\")\n\targuments.DelArg(\"asexplicit\", \"asexp\")\n\n\targuments.AddTarget(pkgArchives...)\n\n\tif errShow := cmdBuilder.Show(cmdBuilder.BuildPacmanCmd(ctx,\n\t\targuments, mode, noConfirm)); errShow != nil {\n\t\treturn errShow\n\t}\n\n\tif errStore := vcsStore.Save(); errStore != nil {\n\t\tfmt.Fprintln(os.Stderr, errStore)\n\t}\n\n\treturn nil\n}\n\nfunc setInstallReason(ctx context.Context,\n\tcmdBuilder exe.ICmdBuilder, mode parser.TargetMode,\n\tcmdArgs *parser.Arguments, deps, exps []string,\n) error {\n\tif len(deps)+len(exps) == 0 {\n\t\treturn nil\n\t}\n\n\tif errDeps := asdeps(ctx, cmdBuilder, mode, cmdArgs, deps); errDeps != nil {\n\t\treturn errDeps\n\t}\n\n\treturn asexp(ctx, cmdBuilder, mode, cmdArgs, exps)\n}\n\nfunc setPkgReason(ctx context.Context,\n\tcmdBuilder exe.ICmdBuilder,\n\tmode parser.TargetMode,\n\tcmdArgs *parser.Arguments, pkgs []string, exp bool,\n) error {\n\tif len(pkgs) == 0 {\n\t\treturn nil\n\t}\n\n\tcmdArgs = cmdArgs.CopyGlobal()\n\tif exp {\n\t\tif err := cmdArgs.AddArg(\"q\", \"D\", \"asexplicit\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\tif err := cmdArgs.AddArg(\"q\", \"D\", \"asdeps\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tfor _, compositePkgName := range pkgs {\n\t\tpkgSplit := strings.Split(compositePkgName, \"/\")\n\n\t\tpkgName := pkgSplit[0]\n\t\tif len(pkgSplit) > 1 {\n\t\t\tpkgName = pkgSplit[1]\n\t\t}\n\n\t\tcmdArgs.AddTarget(pkgName)\n\t}\n\n\tif err := cmdBuilder.Show(cmdBuilder.BuildPacmanCmd(ctx,\n\t\tcmdArgs, mode, settings.NoConfirm)); err != nil {\n\t\treturn &SetPkgReasonError{exp: exp}\n\t}\n\n\treturn nil\n}\n\nfunc asdeps(ctx context.Context,\n\tcmdBuilder exe.ICmdBuilder,\n\tmode parser.TargetMode, cmdArgs *parser.Arguments, pkgs []string,\n) error {\n\treturn setPkgReason(ctx, cmdBuilder, mode, cmdArgs, pkgs, false)\n}\n\nfunc asexp(ctx context.Context,\n\tcmdBuilder exe.ICmdBuilder,\n\tmode parser.TargetMode, cmdArgs *parser.Arguments, pkgs []string,\n) error {\n\treturn setPkgReason(ctx, cmdBuilder, mode, cmdArgs, pkgs, true)\n}\n\nfunc parsePackageList(ctx context.Context, cmdBuilder exe.ICmdBuilder,\n\tdir string,\n) (pkgdests map[string]string, pkgVersion string, err error) {\n\targs := []string{\"--packagelist\", \"--ignorearch\"}\n\tstdout, stderr, err := cmdBuilder.Capture(\n\t\tcmdBuilder.BuildMakepkgCmd(ctx, dir, args...))\n\tif err != nil {\n\t\treturn nil, \"\", fmt.Errorf(\"%s %w\", stderr, err)\n\t}\n\n\tlines := strings.Split(stdout, \"\\n\")\n\tpkgdests = make(map[string]string, len(lines))\n\n\tfor _, line := range lines {\n\t\tif line == \"\" {\n\t\t\tcontinue\n\t\t}\n\n\t\tfileName := filepath.Base(line)\n\t\tsplit := strings.Split(fileName, \"-\")\n\n\t\tif len(split) < 4 {\n\t\t\treturn nil, \"\", errors.New(gotext.Get(\"cannot find package name: %v\", split))\n\t\t}\n\n\t\t// pkgname-pkgver-pkgrel-arch.pkgext\n\t\t// This assumes 3 dashes after the pkgname, Will cause an error\n\t\t// if the PKGEXT contains a dash. Please no one do that.\n\t\tpkgName := strings.Join(split[:len(split)-3], \"-\")\n\t\tpkgVersion = strings.Join(split[len(split)-3:len(split)-1], \"-\")\n\t\tpkgdests[pkgName] = line\n\t}\n\n\tif len(pkgdests) == 0 {\n\t\treturn nil, \"\", &NoPkgDestsFoundError{dir}\n\t}\n\n\treturn pkgdests, pkgVersion, nil\n}\n"
  },
  {
    "path": "pkg/sync/build/pkg_archive_test.go",
    "content": "package build\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os/exec\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n)\n\nfunc TestParsePackageList(t *testing.T) {\n\tt.Parallel()\n\n\ttype testCase struct {\n\t\tdesc           string\n\t\tmockStdout     string\n\t\tmockStderr     string\n\t\tmockErr        error\n\t\twantPkgDests   map[string]string\n\t\twantPkgVersion string\n\t\twantErr        bool\n\t\twantErrText    string // Optional: specific error text to check\n\t}\n\n\ttestCases := []testCase{\n\t\t{\n\t\t\tdesc:       \"Standard package\",\n\t\t\tmockStdout: \"/path/to/package-1.2.3-4-x86_64.pkg.tar.zst\\n\",\n\t\t\twantPkgDests: map[string]string{\n\t\t\t\t\"package\": \"/path/to/package-1.2.3-4-x86_64.pkg.tar.zst\",\n\t\t\t},\n\t\t\twantPkgVersion: \"1.2.3-4\",\n\t\t\twantErr:        false,\n\t\t},\n\t\t{\n\t\t\tdesc:       \"Package with dash in name\",\n\t\t\tmockStdout: \"/path/to/package-name-with-dash-1.0.0-1-any.pkg.tar.gz\\n\",\n\t\t\twantPkgDests: map[string]string{\n\t\t\t\t\"package-name-with-dash\": \"/path/to/package-name-with-dash-1.0.0-1-any.pkg.tar.gz\",\n\t\t\t},\n\t\t\twantPkgVersion: \"1.0.0-1\",\n\t\t\twantErr:        false, // This should fail with current logic but pass with regex\n\t\t},\n\t\t{\n\t\t\tdesc:       \"Multiple packages\",\n\t\t\tmockStdout: \"/path/to/pkg1-1.0-1-x86_64.pkg.tar.zst\\n/other/path/pkg2-2.5-3-any.pkg.tar.xz\\n\",\n\t\t\twantPkgDests: map[string]string{\n\t\t\t\t\"pkg1\": \"/path/to/pkg1-1.0-1-x86_64.pkg.tar.zst\",\n\t\t\t\t\"pkg2\": \"/other/path/pkg2-2.5-3-any.pkg.tar.xz\",\n\t\t\t},\n\t\t\twantPkgVersion: \"2.5-3\", // Version of the last package processed\n\t\t\twantErr:        false,\n\t\t},\n\t\t{\n\t\t\tdesc:       \"Empty input\",\n\t\t\tmockStdout: \"\",\n\t\t\twantErr:    true, // Expect NoPkgDestsFoundError\n\t\t},\n\t\t{\n\t\t\tdesc:       \"Input with only newline\",\n\t\t\tmockStdout: \"\\n\",\n\t\t\twantErr:    true, // Expect NoPkgDestsFoundError\n\t\t},\n\t\t{\n\t\t\tdesc:       \"Makepkg error\",\n\t\t\tmockStderr: \"makepkg failed\",\n\t\t\tmockErr:    fmt.Errorf(\"exit status 1\"),\n\t\t\twantErr:    true,\n\t\t},\n\t\t{\n\t\t\tdesc:       \"Malformed filename (too few dashes)\",\n\t\t\tmockStdout: \"/path/to/malformed-package.pkg.tar.zst\\n\",\n\t\t\twantErr:    true, // Expect \"cannot find package name\" error\n\t\t},\n\t\t{\n\t\t\tdesc:       \"Package with epoch\",\n\t\t\tmockStdout: \"/path/to/epochpkg-1:2.0.0-1-x86_64.pkg.tar.zst\\n\",\n\t\t\twantPkgDests: map[string]string{\n\t\t\t\t\"epochpkg\": \"/path/to/epochpkg-1:2.0.0-1-x86_64.pkg.tar.zst\",\n\t\t\t},\n\t\t\twantPkgVersion: \"1:2.0.0-1\",\n\t\t\twantErr:        false, // This might fail with current logic\n\t\t},\n\t\t{\n\t\t\tdesc:       \"Package with .zst extension\",\n\t\t\tmockStdout: \"/path/to/zstdpkg-3.3-1-any.pkg.tar.zst\\n\",\n\t\t\twantPkgDests: map[string]string{\n\t\t\t\t\"zstdpkg\": \"/path/to/zstdpkg-3.3-1-any.pkg.tar.zst\",\n\t\t\t},\n\t\t\twantPkgVersion: \"3.3-1\",\n\t\t\twantErr:        false,\n\t\t},\n\t\t{\n\t\t\tdesc:       \"Package with .gz extension\",\n\t\t\tmockStdout: \"/path/to/gzpkg-3.3-1-any.pkg.tar.gz\\n\",\n\t\t\twantPkgDests: map[string]string{\n\t\t\t\t\"gzpkg\": \"/path/to/gzpkg-3.3-1-any.pkg.tar.gz\",\n\t\t\t},\n\t\t\twantPkgVersion: \"3.3-1\",\n\t\t\twantErr:        false,\n\t\t},\n\t\t{\n\t\t\tdesc:       \"Package with .xz extension\",\n\t\t\tmockStdout: \"/path/to/xzpkg-3.3-1-any.pkg.tar.xz\\n\",\n\t\t\twantPkgDests: map[string]string{\n\t\t\t\t\"xzpkg\": \"/path/to/xzpkg-3.3-1-any.pkg.tar.xz\",\n\t\t\t},\n\t\t\twantPkgVersion: \"3.3-1\",\n\t\t\twantErr:        false,\n\t\t},\n\t\t{\n\t\t\tdesc:       \"Package with .bz2 extension\",\n\t\t\tmockStdout: \"/path/to/bz2pkg-3.3-1-any.pkg.tar.bz2\\n\",\n\t\t\twantPkgDests: map[string]string{\n\t\t\t\t\"bz2pkg\": \"/path/to/bz2pkg-3.3-1-any.pkg.tar.bz2\",\n\t\t\t},\n\t\t\twantPkgVersion: \"3.3-1\",\n\t\t\twantErr:        false,\n\t\t},\n\t\t{\n\t\t\tdesc:       \"Package with .tar extension (uncompressed)\",\n\t\t\tmockStdout: \"/path/to/tarpkg-3.3-1-any.pkg.tar\\n\",\n\t\t\twantPkgDests: map[string]string{\n\t\t\t\t\"tarpkg\": \"/path/to/tarpkg-3.3-1-any.pkg.tar\",\n\t\t\t},\n\t\t\twantPkgVersion: \"3.3-1\",\n\t\t\twantErr:        false,\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\t// capture range variable\n\t\tt.Run(tc.desc, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tmockRunner := &exe.MockRunner{\n\t\t\t\tCaptureFn: func(cmd *exec.Cmd) (string, string, error) {\n\t\t\t\t\t// Basic check to ensure the command looks right\n\t\t\t\t\trequire.Contains(t, cmd.String(), \"--packagelist\")\n\t\t\t\t\treturn tc.mockStdout, tc.mockStderr, tc.mockErr\n\t\t\t\t},\n\t\t\t}\n\t\t\tcmdBuilder := &exe.CmdBuilder{Runner: mockRunner} // Simplified for this test\n\n\t\t\tpkgdests, pkgVersion, err := parsePackageList(context.Background(), cmdBuilder, \"/fake/dir\")\n\n\t\t\tif tc.wantErr {\n\t\t\t\tassert.Error(t, err)\n\t\t\t\tif tc.wantErrText != \"\" {\n\t\t\t\t\tassert.Contains(t, err.Error(), tc.wantErrText)\n\t\t\t\t}\n\t\t\t\t// Check for specific error types if needed\n\t\t\t\tif tc.desc == \"Empty input\" || tc.desc == \"Input with only newline\" {\n\t\t\t\t\tassert.IsType(t, &NoPkgDestsFoundError{}, err)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tassert.NoError(t, err)\n\t\t\t\tassert.Equal(t, tc.wantPkgDests, pkgdests)\n\t\t\t\tassert.Equal(t, tc.wantPkgVersion, pkgVersion)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/sync/srcinfo/pgp/keys.go",
    "content": "package pgp\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"os/exec\"\n\t\"strings\"\n\n\tgosrc \"github.com/Morganamilo/go-srcinfo\"\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\n// pgpKeySet maps a PGP key with a list of PKGBUILDs that require it.\n// This is similar to stringSet, used throughout the code.\ntype pgpKeySet map[string][]string\n\nfunc (set pgpKeySet) toSlice() []string {\n\tslice := make([]string, 0, len(set))\n\tfor v := range set {\n\t\tslice = append(slice, v)\n\t}\n\n\treturn slice\n}\n\nfunc (set pgpKeySet) set(key, p string) {\n\t// Using ToUpper to make sure keys with a different case will be\n\t// considered the same.\n\tupperKey := strings.ToUpper(key)\n\tset[upperKey] = append(set[upperKey], p)\n}\n\nfunc (set pgpKeySet) get(key string) bool {\n\tupperKey := strings.ToUpper(key)\n\t_, exists := set[upperKey]\n\n\treturn exists\n}\n\ntype GPGCmdBuilder interface {\n\texe.Runner\n\tBuildGPGCmd(ctx context.Context, extraArgs ...string) *exec.Cmd\n}\n\n// CheckPgpKeys iterates through the keys listed in the PKGBUILDs and if needed,\n// asks the user whether yay should try to import them.\nfunc CheckPgpKeys(ctx context.Context, logger *text.Logger, pkgbuildDirsByBase map[string]string, srcinfos map[string]*gosrc.Srcinfo,\n\tcmdBuilder GPGCmdBuilder, noConfirm bool,\n) ([]string, error) {\n\t// Let's check the keys individually, and then we can offer to import\n\t// the problematic ones.\n\tproblematic := make(pgpKeySet)\n\n\t// Mapping all the keys.\n\tfor pkg := range pkgbuildDirsByBase {\n\t\tsrcinfo := srcinfos[pkg]\n\n\t\tfor _, key := range srcinfo.ValidPGPKeys {\n\t\t\t// If key already marked as problematic, indicate the current\n\t\t\t// PKGBUILD requires it.\n\t\t\tif problematic.get(key) {\n\t\t\t\tproblematic.set(key, pkg)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif err := cmdBuilder.Show(cmdBuilder.BuildGPGCmd(ctx, \"--list-keys\", key)); err != nil {\n\t\t\t\tproblematic.set(key, pkg)\n\t\t\t}\n\t\t}\n\t}\n\n\t// No key issues!\n\tif len(problematic) == 0 {\n\t\treturn []string{}, nil\n\t}\n\n\tstr, err := formatKeysToImport(logger, problematic)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tlogger.Println(\"\\n\", str)\n\n\tif logger.ContinueTask(gotext.Get(\"Import?\"), true, noConfirm) {\n\t\treturn problematic.toSlice(), importKeys(ctx, logger, cmdBuilder, problematic.toSlice())\n\t}\n\n\treturn problematic.toSlice(), nil\n}\n\n// importKeys tries to import the list of keys specified in its argument.\nfunc importKeys(ctx context.Context, logger *text.Logger, cmdBuilder GPGCmdBuilder, keys []string) error {\n\tlogger.OperationInfoln(gotext.Get(\"Importing keys with gpg...\"))\n\n\tif err := cmdBuilder.Show(cmdBuilder.BuildGPGCmd(ctx, append([]string{\"--recv-keys\"}, keys...)...)); err != nil {\n\t\treturn errors.New(gotext.Get(\"problem importing keys\"))\n\t}\n\n\treturn nil\n}\n\n// formatKeysToImport receives a set of keys and returns a string containing the\n// question asking the user wants to import the problematic keys.\nfunc formatKeysToImport(logger *text.Logger, keys pgpKeySet) (string, error) {\n\tif len(keys) == 0 {\n\t\treturn \"\", errors.New(gotext.Get(\"no keys to import\"))\n\t}\n\n\tvar buffer bytes.Buffer\n\n\tbuffer.WriteString(logger.SprintOperationInfo(gotext.Get(\"PGP keys need importing:\")))\n\n\tfor key, bases := range keys {\n\t\tpkglist := \"\"\n\t\tfor _, base := range bases {\n\t\t\tpkglist += base + \"  \"\n\t\t}\n\n\t\tpkglist = strings.TrimRight(pkglist, \" \")\n\t\tbuffer.WriteString(\"\\n\" + logger.SprintWarn(gotext.Get(\"%s, required by: %s\", text.Cyan(key), text.Cyan(pkglist))))\n\t}\n\n\treturn buffer.String(), nil\n}\n"
  },
  {
    "path": "pkg/sync/srcinfo/pgp/keys_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage pgp\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"os/exec\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n\n\tgosrc \"github.com/Morganamilo/go-srcinfo\"\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\nfunc newTestLogger() *text.Logger {\n\treturn text.NewLogger(io.Discard, io.Discard, strings.NewReader(\"\"), true, \"test\")\n}\n\nfunc makeSrcinfo(pkgbase string, pgpkeys ...string) *gosrc.Srcinfo {\n\tsrcinfo := gosrc.Srcinfo{}\n\tsrcinfo.Pkgbase = pkgbase\n\tsrcinfo.ValidPGPKeys = pgpkeys\n\n\treturn &srcinfo\n}\n\nfunc TestCheckPgpKeys(t *testing.T) {\n\tgpgBin := t.TempDir() + \"/gpg\"\n\n\tf, err := os.OpenFile(gpgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\ttestcases := []struct {\n\t\tname        string\n\t\tpkgs        map[string]string\n\t\tsrcinfos    map[string]*gosrc.Srcinfo\n\t\twantError   bool\n\t\twantShow    []string\n\t\twantCapture []string\n\t\tshowFn      func(cmd *exec.Cmd) error\n\t\texpected    []string\n\t}{\n\t\t// cower: single package, one valid key not yet in the keyring.\n\t\t// 487EACC08557AD082088DABA1EB2638FF56C0C53: Dave Reisner.\n\t\t{\n\t\t\tname:      \" one valid key not yet in the keyring\",\n\t\t\tpkgs:      map[string]string{\"cower\": \"\"},\n\t\t\tsrcinfos:  map[string]*gosrc.Srcinfo{\"cower\": makeSrcinfo(\"cower\", \"487EACC08557AD082088DABA1EB2638FF56C0C53\")},\n\t\t\twantError: false,\n\t\t\twantShow: []string{\n\t\t\t\t\"gpg --homedir /tmp --list-keys 487EACC08557AD082088DABA1EB2638FF56C0C53\",\n\t\t\t\t\"gpg --homedir /tmp --recv-keys 487EACC08557AD082088DABA1EB2638FF56C0C53\",\n\t\t\t},\n\t\t\twantCapture: []string{},\n\t\t\tshowFn: func(cmd *exec.Cmd) error {\n\t\t\t\ts := cmd.String()\n\t\t\t\tif strings.Contains(s, \"--list-keys\") {\n\t\t\t\t\treturn fmt.Errorf(\"key not found\")\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t},\n\t\t\texpected: []string{\"487EACC08557AD082088DABA1EB2638FF56C0C53\"},\n\t\t},\n\t\t// libc++: single package, two valid keys not yet in the keyring.\n\t\t// 11E521D646982372EB577A1F8F0871F202119294: Tom Stellard.\n\t\t// B6C8F98282B944E3B0D5C2530FC3042E345AD05D: Hans Wennborg.\n\t\t{\n\t\t\tname:      \"two valid keys not yet in the keyring\",\n\t\t\tpkgs:      map[string]string{\"libc++\": \"\"},\n\t\t\tsrcinfos:  map[string]*gosrc.Srcinfo{\"libc++\": makeSrcinfo(\"libc++\", \"11E521D646982372EB577A1F8F0871F202119294\", \"B6C8F98282B944E3B0D5C2530FC3042E345AD05D\")},\n\t\t\twantError: false,\n\t\t\twantShow: []string{\n\t\t\t\t\"gpg --homedir /tmp --list-keys 11E521D646982372EB577A1F8F0871F202119294\",\n\t\t\t\t\"gpg --homedir /tmp --list-keys B6C8F98282B944E3B0D5C2530FC3042E345AD05D\",\n\t\t\t\t\"gpg --homedir /tmp --recv-keys 11E521D646982372EB577A1F8F0871F202119294 B6C8F98282B944E3B0D5C2530FC3042E345AD05D\",\n\t\t\t},\n\t\t\twantCapture: []string{},\n\t\t\tshowFn: func(cmd *exec.Cmd) error {\n\t\t\t\ts := cmd.String()\n\t\t\t\tif strings.Contains(s, \"--list-keys\") {\n\t\t\t\t\treturn fmt.Errorf(\"key not found\")\n\t\t\t\t}\n\n\t\t\t\treturn nil\n\t\t\t},\n\t\t\texpected: []string{\"11E521D646982372EB577A1F8F0871F202119294\", \"B6C8F98282B944E3B0D5C2530FC3042E345AD05D\"},\n\t\t},\n\t\t{\n\t\t\tname: \"Two dummy packages requiring the same key\",\n\t\t\tpkgs: map[string]string{\"dummy-1\": \"\", \"dummy-2\": \"\"},\n\t\t\tsrcinfos: map[string]*gosrc.Srcinfo{\n\t\t\t\t\"dummy-1\": makeSrcinfo(\"dummy-1\",\n\t\t\t\t\t\"ABAF11C65A2970B130ABE3C479BE3E4300411886\"),\n\t\t\t\t\"dummy-2\": makeSrcinfo(\"dummy-2\", \"ABAF11C65A2970B130ABE3C479BE3E4300411886\"),\n\t\t\t},\n\t\t\twantError:   false,\n\t\t\texpected:    []string{\"ABAF11C65A2970B130ABE3C479BE3E4300411886\"},\n\t\t\twantCapture: []string{},\n\t\t\twantShow: []string{\n\t\t\t\t\"gpg --homedir /tmp --list-keys ABAF11C65A2970B130ABE3C479BE3E4300411886\",\n\t\t\t\t\"gpg --homedir /tmp --recv-keys ABAF11C65A2970B130ABE3C479BE3E4300411886\",\n\t\t\t},\n\t\t\tshowFn: func(cmd *exec.Cmd) error {\n\t\t\t\ts := cmd.String()\n\t\t\t\tif strings.Contains(s, \"--list-keys\") {\n\t\t\t\t\treturn fmt.Errorf(\"key not found\")\n\t\t\t\t}\n\n\t\t\t\treturn nil\n\t\t\t},\n\t\t},\n\t\t// dummy package: single package, two valid keys, one of them already\n\t\t// in the keyring.\n\t\t// 11E521D646982372EB577A1F8F0871F202119294: Tom Stellard.\n\t\t// C52048C0C0748FEE227D47A2702353E0F7E48EDB: Thomas Dickey.\n\t\t{\n\t\t\tname: \"one already in keyring\",\n\t\t\tpkgs: map[string]string{\"dummy-3\": \"\"},\n\t\t\tsrcinfos: map[string]*gosrc.Srcinfo{\n\t\t\t\t\"dummy-3\": makeSrcinfo(\"dummy-3\", \"11E521D646982372EB577A1F8F0871F202119294\", \"C52048C0C0748FEE227D47A2702353E0F7E48EDB\"),\n\t\t\t},\n\t\t\twantError:   false,\n\t\t\texpected:    []string{\"C52048C0C0748FEE227D47A2702353E0F7E48EDB\"},\n\t\t\twantCapture: []string{},\n\t\t\tshowFn: func(cmd *exec.Cmd) error {\n\t\t\t\ts := cmd.String()\n\t\t\t\tif strings.Contains(s, \"--list-keys\") &&\n\t\t\t\t\t!strings.Contains(s, \"11E521D646982372EB577A1F8F0871F202119294\") {\n\t\t\t\t\treturn fmt.Errorf(\"key not found\")\n\t\t\t\t}\n\n\t\t\t\treturn nil\n\t\t\t},\n\t\t\twantShow: []string{\n\t\t\t\t\"gpg --homedir /tmp --list-keys 11E521D646982372EB577A1F8F0871F202119294\",\n\t\t\t\t\"gpg --homedir /tmp --list-keys C52048C0C0748FEE227D47A2702353E0F7E48EDB\",\n\t\t\t\t\"gpg --homedir /tmp --recv-keys C52048C0C0748FEE227D47A2702353E0F7E48EDB\",\n\t\t\t},\n\t\t},\n\t\t// Two dummy packages with existing keys.\n\t\t{\n\t\t\tname: \"two existing\",\n\t\t\tpkgs: map[string]string{\"dummy-4\": \"\", \"dummy-5\": \"\"},\n\t\t\tsrcinfos: map[string]*gosrc.Srcinfo{\n\t\t\t\t\"dummy-4\": makeSrcinfo(\"dummy-4\", \"11E521D646982372EB577A1F8F0871F202119294\"),\n\t\t\t\t\"dummy-5\": makeSrcinfo(\"dummy-5\", \"C52048C0C0748FEE227D47A2702353E0F7E48EDB\"),\n\t\t\t},\n\t\t\twantError:   false,\n\t\t\texpected:    []string{},\n\t\t\twantCapture: []string{},\n\t\t\tshowFn: func(cmd *exec.Cmd) error {\n\t\t\t\treturn nil\n\t\t\t},\n\t\t\twantShow: []string{\n\t\t\t\t\"gpg --homedir /tmp --list-keys 11E521D646982372EB577A1F8F0871F202119294\",\n\t\t\t\t\"gpg --homedir /tmp --list-keys C52048C0C0748FEE227D47A2702353E0F7E48EDB\",\n\t\t\t},\n\t\t},\n\t\t// Dummy package with invalid key, should fail.\n\t\t{\n\t\t\tname:        \"one invalid\",\n\t\t\tpkgs:        map[string]string{\"dummy-7\": \"\"},\n\t\t\tsrcinfos:    map[string]*gosrc.Srcinfo{\"dummy-7\": makeSrcinfo(\"dummy-7\", \"THIS-SHOULD-FAIL\")},\n\t\t\twantError:   true,\n\t\t\twantCapture: []string{},\n\t\t\twantShow: []string{\n\t\t\t\t\"gpg --homedir /tmp --list-keys THIS-SHOULD-FAIL\",\n\t\t\t\t\"gpg --homedir /tmp --recv-keys THIS-SHOULD-FAIL\",\n\t\t\t},\n\t\t\tshowFn: func(cmd *exec.Cmd) error {\n\t\t\t\ts := cmd.String()\n\t\t\t\tif strings.Contains(s, \"--list-keys\") {\n\t\t\t\t\treturn fmt.Errorf(\"key not found\")\n\t\t\t\t}\n\n\t\t\t\tif strings.Contains(s, \"--recv-keys\") {\n\t\t\t\t\treturn fmt.Errorf(\"invalid key\")\n\t\t\t\t}\n\n\t\t\t\treturn nil\n\t\t\t},\n\t\t},\n\t\t// Dummy package with both an invalid an another valid key, should fail.\n\t\t// A314827C4E4250A204CE6E13284FC34C8E4B1A25: Thomas Bächler.\n\t\t{\n\t\t\tname:        \"one invalid, one valid\",\n\t\t\tpkgs:        map[string]string{\"dummy-8\": \"\"},\n\t\t\tsrcinfos:    map[string]*gosrc.Srcinfo{\"dummy-8\": makeSrcinfo(\"dummy-8\", \"A314827C4E4250A204CE6E13284FC34C8E4B1A25\", \"THIS-SHOULD-FAIL\")},\n\t\t\twantError:   true,\n\t\t\texpected:    []string{},\n\t\t\twantCapture: []string{},\n\t\t\tshowFn: func(cmd *exec.Cmd) error {\n\t\t\t\ts := cmd.String()\n\t\t\t\tif strings.Contains(s, \"--list-keys\") {\n\t\t\t\t\treturn fmt.Errorf(\"key not found\")\n\t\t\t\t}\n\n\t\t\t\tif strings.Contains(s, \"--recv-keys\") {\n\t\t\t\t\treturn fmt.Errorf(\"invalid key\")\n\t\t\t\t}\n\n\t\t\t\treturn nil\n\t\t\t},\n\t\t\twantShow: []string{\n\t\t\t\t\"gpg --homedir /tmp --list-keys A314827C4E4250A204CE6E13284FC34C8E4B1A25\",\n\t\t\t\t\"gpg --homedir /tmp --list-keys THIS-SHOULD-FAIL\",\n\t\t\t\t\"gpg --homedir /tmp --recv-keys A314827C4E4250A204CE6E13284FC34C8E4B1A25 THIS-SHOULD-FAIL\",\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, tt := range testcases {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tmockRunner := &exe.MockRunner{\n\t\t\t\tShowFn: tt.showFn,\n\t\t\t\tCaptureFn: func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\t\t\t\treturn \"\", \"\", nil\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tcmdBuilder := exe.CmdBuilder{\n\t\t\t\tGPGBin:   gpgBin,\n\t\t\t\tGPGFlags: []string{\"--homedir /tmp\"},\n\t\t\t\tRunner:   mockRunner,\n\t\t\t}\n\t\t\tproblematic, err := CheckPgpKeys(context.Background(), newTestLogger(), tt.pkgs, tt.srcinfos, &cmdBuilder, true)\n\n\t\t\trequire.Len(t, mockRunner.ShowCalls, len(tt.wantShow))\n\t\t\trequire.Len(t, mockRunner.CaptureCalls, len(tt.wantCapture))\n\n\t\t\tsort.SliceStable(mockRunner.ShowCalls, func(i, j int) bool {\n\t\t\t\treturn mockRunner.ShowCalls[i].Args[0].(*exec.Cmd).String() < mockRunner.ShowCalls[j].Args[0].(*exec.Cmd).String()\n\t\t\t})\n\t\t\tfor i, call := range mockRunner.ShowCalls {\n\t\t\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\t\t\tshow = strings.ReplaceAll(show, gpgBin, \"gpg\")\n\n\t\t\t\t// options are in a different order on different systems and on CI root user is used\n\t\t\t\tassert.Subset(t, strings.Split(show, \" \"), strings.Split(tt.wantShow[i], \" \"), show)\n\t\t\t}\n\n\t\t\tfor i, call := range mockRunner.CaptureCalls {\n\t\t\t\tcapture := call.Args[0].(*exec.Cmd).String()\n\t\t\t\tcapture = strings.ReplaceAll(capture, gpgBin, \"gpg\")\n\t\t\t\tassert.Subset(t, strings.Split(capture, \" \"), strings.Split(tt.wantCapture[i], \" \"), capture)\n\t\t\t}\n\n\t\t\tif tt.wantError {\n\t\t\t\trequire.Error(t, err)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\trequire.NoError(t, err)\n\n\t\t\tassert.ElementsMatch(t, tt.expected, problematic, fmt.Sprintf(\"%#v\", problematic))\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/sync/srcinfo/pgp/testdata/11E521D646982372EB577A1F8F0871F202119294",
    "content": "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\n=/J5n\n"
  },
  {
    "path": "pkg/sync/srcinfo/pgp/testdata/487EACC08557AD082088DABA1EB2638FF56C0C53",
    "content": "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\nv5Wb1miAZnGDGEfyuYnSAw==\n=bVs6\n"
  },
  {
    "path": "pkg/sync/srcinfo/pgp/testdata/647F28654894E3BD457199BE38DBBDC86092693E",
    "content": "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\nHKc5w55soziCllQ=\n=PQVe\n"
  },
  {
    "path": "pkg/sync/srcinfo/pgp/testdata/A314827C4E4250A204CE6E13284FC34C8E4B1A25",
    "content": "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\noSf3hW01pA==\n=cv82\n"
  },
  {
    "path": "pkg/sync/srcinfo/pgp/testdata/ABAF11C65A2970B130ABE3C479BE3E4300411886",
    "content": "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\n8jMWgR7U4vQMGuOReoECpO8gNUWr2yAhHelm+A/8L1Un8q7S6eJafBeCsg8WD1eRApvD76cC\nViDfbyoeSU/hWxitB1OdV1FzdbGa7/dQuYUBmi8MtFAZ4okCHAQQAQgABgUCTnplUgAKCRDT\nb3abwRgE8JZYD/0WH4k/timxBCGW3ERN6cCyOOzqj52cdZBXwyzaobeA6m7/d5+GzpmvVqHG\ne3Arb4PoQH6L462iH1iCCbKvK7lhHKCmtVXM6orcbkfZTi1IYy2lOATsRX1OKWL3O9U/wKhU\ntw62pQEBt0FIFZLd00Jamh5iT3MxUhcrT4ZWlXjC4cfJ89vzOjvpLs1hnhqx9t/HfPDwMsbG\ne40PxGrLzq2pLpwS/L3M703JGTCblrHTLbVmGWfLpMBsp2g3L5V5+JSHnI0wgYrF9S+lTkOS\nbFmIbmYuwaJHCaGtVTd3Mx3MUJspZuT9Oj4MeB0a/X++8YbSXA7uKkzqLFv0Yv//////////\n////////////////////////////////////////////////////////////////////////\n////////////////////////////////////////////////////////////////////////\n////////////////////////////////////////////////////////////////////////\n////////////////////////////////////////////////////////////////////////\n/////////////////////////////////////////////////4kCHAQQAQgABgUCTqblgAAK\nCRDnv8jslYYRCd8mEACQnqydgXN+myvn0uZZeic7wSqbHOXLcG9z2fS40pujAvmTEeO0994O\nBrvfM95BRcLBch9ZpHK5asvwoYy9nnXQ0Rn16ldKahYd9TpZ+eJUohIRI5gKkIiwD5nmot+F\nNYMQLD0SOn5WHPuINIg72TK7oUKobCP7Tbb5Kv7rf2VmqpcCcYwNXsQ1lMPnR3msZlNuidlr\nZhAS7RMvb08eUYAso3KHR0srQoqGkYWZdjQnnj4Ver8Y4q9REEpDw67r4lxp5LBCgBGY78c4\ntbTVZa7Efa5zA282+v7bkzoaMgJxqDns61de3Af8snUEpCFTBWkqCMGkWiNx70ZNfX3Z1z3c\n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\nLddgYrylZH+MwNDlB5u3I138\n=6ybs\n"
  },
  {
    "path": "pkg/sync/srcinfo/pgp/testdata/B6C8F98282B944E3B0D5C2530FC3042E345AD05D",
    "content": "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\nix4eSNK5nln0jUq167H2IH//2sf8dw==\n=pTiW\n"
  },
  {
    "path": "pkg/sync/srcinfo/pgp/testdata/C52048C0C0748FEE227D47A2702353E0F7E48EDB",
    "content": "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\n=Nbc4\n"
  },
  {
    "path": "pkg/sync/srcinfo/service.go",
    "content": "package srcinfo\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"path/filepath\"\n\n\tgosrc \"github.com/Morganamilo/go-srcinfo\"\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/dep\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/sync/srcinfo/pgp\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\t\"github.com/Jguer/yay/v12/pkg/vcs\"\n)\n\ntype Service struct {\n\tdbExecutor db.Executor\n\tcfg        *settings.Configuration\n\tcmdBuilder pgp.GPGCmdBuilder\n\tvcsStore   vcs.Store\n\tlog        *text.Logger\n\n\tpkgBuildDirs map[string]string\n\tsrcInfos     map[string]*gosrc.Srcinfo\n}\n\nfunc NewService(dbExecutor db.Executor, cfg *settings.Configuration, logger *text.Logger,\n\tcmdBuilder exe.ICmdBuilder, vcsStore vcs.Store, pkgBuildDirs map[string]string,\n) (*Service, error) {\n\tsrcinfos, err := ParseSrcinfoFilesByBase(logger, pkgBuildDirs, true)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &Service{\n\t\tdbExecutor:   dbExecutor,\n\t\tcfg:          cfg,\n\t\tcmdBuilder:   cmdBuilder,\n\t\tvcsStore:     vcsStore,\n\t\tpkgBuildDirs: pkgBuildDirs,\n\t\tsrcInfos:     srcinfos,\n\t\tlog:          logger,\n\t}, nil\n}\n\nfunc (s *Service) IncompatiblePkgs(ctx context.Context) ([]string, error) {\n\tincompatible := []string{}\n\n\talpmArch, err := s.dbExecutor.AlpmArchitectures()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\nnextpkg:\n\tfor base, srcinfo := range s.srcInfos {\n\t\tfor _, arch := range srcinfo.Arch {\n\t\t\tif db.ArchIsSupported(alpmArch, arch) {\n\t\t\t\tcontinue nextpkg\n\t\t\t}\n\t\t}\n\t\tincompatible = append(incompatible, base)\n\t}\n\n\treturn incompatible, nil\n}\n\nfunc (s *Service) CheckPGPKeys(ctx context.Context) error {\n\t_, errCPK := pgp.CheckPgpKeys(ctx, s.log.Child(\"pgp\"), s.pkgBuildDirs, s.srcInfos, s.cmdBuilder, settings.NoConfirm)\n\treturn errCPK\n}\n\nfunc (s *Service) UpdateVCSStore(ctx context.Context, targets []map[string]*dep.InstallInfo, ignore map[string]error,\n) error {\n\tfor _, srcinfo := range s.srcInfos {\n\t\tif srcinfo.Source == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\t// TODO: high complexity - refactor\n\t\tfor i := range srcinfo.Packages {\n\t\t\tfor j := range targets {\n\t\t\t\tif _, ok := targets[j][srcinfo.Packages[i].Pkgname]; !ok {\n\t\t\t\t\ts.log.Debugln(\"skipping VCS update for\", srcinfo.Packages[i].Pkgname, \"not in targets\")\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif _, ok := ignore[srcinfo.Packages[i].Pkgname]; ok {\n\t\t\t\t\ts.log.Debugln(\"skipping VCS update for\", srcinfo.Packages[i].Pkgname, \"due to install error\")\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\ts.log.Debugln(\"checking VCS entry for\", srcinfo.Packages[i].Pkgname, fmt.Sprintf(\"source: %v\", srcinfo.Source))\n\t\t\t\ts.vcsStore.Update(ctx, srcinfo.Packages[i].Pkgname, srcinfo.Source)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc ParseSrcinfoFilesByBase(logger *text.Logger, pkgBuildDirs map[string]string, errIsFatal bool) (map[string]*gosrc.Srcinfo, error) {\n\tsrcinfos := make(map[string]*gosrc.Srcinfo)\n\n\tk := 0\n\tfor base, dir := range pkgBuildDirs {\n\t\tlogger.OperationInfoln(gotext.Get(\"(%d/%d) Parsing SRCINFO: %s\", k+1, len(pkgBuildDirs), text.Cyan(base)))\n\n\t\tpkgbuild, err := gosrc.ParseFile(filepath.Join(dir, \".SRCINFO\"))\n\t\tif err != nil {\n\t\t\tif !errIsFatal {\n\t\t\t\tlogger.Warnln(gotext.Get(\"failed to parse %s -- skipping: %s\", base, err))\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\treturn nil, errors.New(gotext.Get(\"failed to parse %s: %s\", base, err))\n\t\t}\n\n\t\tsrcinfos[base] = pkgbuild\n\t\tk++\n\t}\n\n\treturn srcinfos, nil\n}\n"
  },
  {
    "path": "pkg/sync/srcinfo/service_test.go",
    "content": "package srcinfo\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"strings\"\n\t\"testing\"\n\n\tgosrc \"github.com/Morganamilo/go-srcinfo\"\n\n\t\"github.com/stretchr/testify/assert\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db/mock\"\n\t\"github.com/Jguer/yay/v12/pkg/dep\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\t\"github.com/Jguer/yay/v12/pkg/vcs\"\n)\n\nfunc newTestLogger() *text.Logger {\n\treturn text.NewLogger(io.Discard, io.Discard, strings.NewReader(\"\"), true, \"test\")\n}\n\nfunc TestNewService(t *testing.T) {\n\tdbExecutor := &mock.DBExecutor{}\n\tcfg := &settings.Configuration{}\n\tcmdBuilder := &exe.MockBuilder{}\n\tvcsStore := &vcs.Mock{}\n\tpkgBuildDirs := map[string]string{\n\t\t\"jellyfin\": \"../../../testdata/jfin\",\n\t\t\"cephbin\":  \"../../../testdata/cephbin\",\n\t}\n\n\tsrv, err := NewService(dbExecutor, cfg, newTestLogger(), cmdBuilder, vcsStore, pkgBuildDirs)\n\tassert.NoError(t, err)\n\tassert.NotNil(t, srv)\n\tassert.Equal(t, dbExecutor, srv.dbExecutor)\n\tassert.Equal(t, cfg, srv.cfg)\n\tassert.Equal(t, cmdBuilder, srv.cmdBuilder)\n\tassert.Equal(t, vcsStore, srv.vcsStore)\n\tassert.Equal(t, pkgBuildDirs, srv.pkgBuildDirs)\n\tassert.NotNil(t, srv.srcInfos)\n}\n\nfunc TestService_IncompatiblePkgs(t *testing.T) {\n\tsrv := &Service{\n\t\tdbExecutor: &mock.DBExecutor{AlpmArchitecturesFn: func() ([]string, error) {\n\t\t\treturn []string{\"x86_64\"}, nil\n\t\t}},\n\t\tsrcInfos: map[string]*gosrc.Srcinfo{\n\t\t\t\"pkg1\": {\n\t\t\t\tPackage: gosrc.Package{\n\t\t\t\t\tArch: []string{\"x86_64\", \"any\"},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"pkg2\": {\n\t\t\t\tPackage: gosrc.Package{\n\t\t\t\t\tArch: []string{\"any\"},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"pkg3\": {\n\t\t\t\tPackage: gosrc.Package{\n\t\t\t\t\tArch: []string{\"armv7h\"},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"pkg4\": {\n\t\t\t\tPackage: gosrc.Package{\n\t\t\t\t\tArch: []string{\"i683\", \"x86_64\"},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tincompatible, err := srv.IncompatiblePkgs(context.Background())\n\tassert.NoError(t, err)\n\tassert.ElementsMatch(t, []string{\"pkg3\"}, incompatible)\n}\n\nfunc TestService_CheckPGPKeys(t *testing.T) {\n\tsrv := &Service{\n\t\tlog: newTestLogger(),\n\t\tpkgBuildDirs: map[string]string{\n\t\t\t\"pkg1\": \"/path/to/pkg1\",\n\t\t\t\"pkg2\": \"/path/to/pkg2\",\n\t\t},\n\t\tsrcInfos: map[string]*gosrc.Srcinfo{\n\t\t\t\"pkg1\": {\n\t\t\t\tPackages: []gosrc.Package{\n\t\t\t\t\t{Pkgname: \"pkg1\"},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"pkg2\": {\n\t\t\t\tPackages: []gosrc.Package{\n\t\t\t\t\t{Pkgname: \"pkg2\"},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\terr := srv.CheckPGPKeys(context.Background())\n\tassert.NoError(t, err)\n}\n\nfunc TestService_UpdateVCSStore(t *testing.T) {\n\tsrv := &Service{\n\t\tsrcInfos: map[string]*gosrc.Srcinfo{\n\t\t\t\"pkg1\": {\n\t\t\t\tPackages: []gosrc.Package{\n\t\t\t\t\t{Pkgname: \"pkg1\"},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"pkg2\": {\n\t\t\t\tPackages: []gosrc.Package{\n\t\t\t\t\t{Pkgname: \"pkg2\"},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tvcsStore: &vcs.Mock{},\n\t}\n\n\ttargets := []map[string]*dep.InstallInfo{\n\t\t{\n\t\t\t\"pkg1\": {},\n\t\t\t\"pkg2\": {},\n\t\t},\n\t}\n\tignore := map[string]error{}\n\n\terr := srv.UpdateVCSStore(context.Background(), targets, ignore)\n\tassert.NoError(t, err)\n}\n"
  },
  {
    "path": "pkg/sync/sync.go",
    "content": "package sync\n\nimport (\n\t\"context\"\n\n\t\"github.com/Jguer/yay/v12/pkg/completion\"\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/dep\"\n\t\"github.com/Jguer/yay/v12/pkg/multierror\"\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/sync/build\"\n\t\"github.com/Jguer/yay/v12/pkg/sync/srcinfo\"\n\t\"github.com/Jguer/yay/v12/pkg/sync/workdir\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\n\t\"github.com/leonelquinteros/gotext\"\n)\n\ntype OperationService struct {\n\tctx        context.Context\n\tcfg        *settings.Configuration\n\tdbExecutor db.Executor\n\tlogger     *text.Logger\n}\n\nfunc NewOperationService(ctx context.Context,\n\tdbExecutor db.Executor,\n\trun *runtime.Runtime,\n) *OperationService {\n\treturn &OperationService{\n\t\tctx:        ctx,\n\t\tcfg:        run.Cfg,\n\t\tdbExecutor: dbExecutor,\n\t\tlogger:     run.Logger.Child(\"operation\"),\n\t}\n}\n\nfunc (o *OperationService) Run(ctx context.Context, run *runtime.Runtime,\n\tcmdArgs *parser.Arguments,\n\ttargets []map[string]*dep.InstallInfo, excluded []string,\n) error {\n\tif len(targets) == 0 {\n\t\to.logger.Println(\"\", gotext.Get(\"there is nothing to do\"))\n\t\treturn nil\n\t}\n\tpreparer := workdir.NewPreparer(o.dbExecutor, run.CmdBuilder, o.cfg, o.logger.Child(\"workdir\"))\n\tinstaller := build.NewInstaller(o.dbExecutor, run.CmdBuilder,\n\t\trun.VCSStore, o.cfg.Mode, o.cfg.ReBuild,\n\t\tcmdArgs.ExistsArg(\"w\", \"downloadonly\"), run.Logger.Child(\"installer\"))\n\n\tshouldInstall := !cmdArgs.ExistsArg(\"w\", \"downloadonly\")\n\tif cmdArgs.Op == \"B\" && !cmdArgs.ExistsArg(\"i\", \"install\") {\n\t\tshouldInstall = false\n\t}\n\tinstaller.SetInstallBuiltPackages(shouldInstall)\n\n\tpkgBuildDirs, errInstall := preparer.Run(ctx, run, targets)\n\tif errInstall != nil {\n\t\treturn errInstall\n\t}\n\n\tif cleanFunc := preparer.ShouldCleanMakeDeps(run, cmdArgs); cleanFunc != nil {\n\t\tinstaller.AddPostInstallHook(cleanFunc)\n\t}\n\n\tif cleanAURDirsFunc := preparer.ShouldCleanAURDirs(run, pkgBuildDirs); cleanAURDirsFunc != nil {\n\t\tinstaller.AddPostInstallHook(cleanAURDirsFunc)\n\t}\n\n\tif completion.NeedsUpdate(o.cfg.CompletionPath, o.cfg.CompletionInterval, false) {\n\t\tgo func() {\n\t\t\terrComp := completion.UpdateCache(ctx, run.HTTPClient, o.dbExecutor,\n\t\t\t\to.cfg.AURURL, o.cfg.CompletionPath, o.logger)\n\t\t\tif errComp != nil {\n\t\t\t\to.logger.Warnln(errComp)\n\t\t\t}\n\t\t}()\n\t}\n\n\tsrcInfo, errInstall := srcinfo.NewService(o.dbExecutor, o.cfg,\n\t\to.logger.Child(\"srcinfo\"), run.CmdBuilder, run.VCSStore, pkgBuildDirs)\n\tif errInstall != nil {\n\t\treturn errInstall\n\t}\n\n\tincompatible, errInstall := srcInfo.IncompatiblePkgs(ctx)\n\tif errInstall != nil {\n\t\treturn errInstall\n\t}\n\n\tif errIncompatible := confirmIncompatible(o.logger, incompatible); errIncompatible != nil {\n\t\treturn errIncompatible\n\t}\n\n\tif errPGP := srcInfo.CheckPGPKeys(ctx); errPGP != nil {\n\t\treturn errPGP\n\t}\n\n\tif errInstall := installer.Install(ctx, cmdArgs, targets, pkgBuildDirs,\n\t\texcluded, o.manualConfirmRequired(cmdArgs)); errInstall != nil {\n\t\treturn errInstall\n\t}\n\n\tvar multiErr multierror.MultiError\n\n\tfailedAndIgnored, err := installer.CompileFailedAndIgnored()\n\tif err != nil {\n\t\tmultiErr.Add(err)\n\t}\n\n\tif !cmdArgs.ExistsArg(\"w\", \"downloadonly\") {\n\t\tif err := srcInfo.UpdateVCSStore(ctx, targets, failedAndIgnored); err != nil {\n\t\t\to.logger.Warnln(err)\n\t\t}\n\t}\n\n\tif err := installer.RunPostInstallHooks(ctx); err != nil {\n\t\tmultiErr.Add(err)\n\t}\n\n\treturn multiErr.Return()\n}\n\nfunc (o *OperationService) manualConfirmRequired(cmdArgs *parser.Arguments) bool {\n\treturn (!cmdArgs.ExistsArg(\"u\", \"sysupgrade\") && cmdArgs.Op != \"Y\") || o.cfg.DoubleConfirm\n}\n\nfunc confirmIncompatible(logger *text.Logger, incompatible []string) error {\n\tif len(incompatible) > 0 {\n\t\tlogger.Warnln(gotext.Get(\"The following packages are not compatible with your architecture:\"))\n\n\t\tfor _, pkg := range incompatible {\n\t\t\tlogger.Print(\"  \" + text.Cyan(pkg))\n\t\t}\n\n\t\tlogger.Println()\n\n\t\tif !logger.ContinueTask(gotext.Get(\"Try to build them anyway?\"), true, settings.NoConfirm) {\n\t\t\treturn &settings.ErrUserAbort{}\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/sync/workdir/aur_source.go",
    "content": "package workdir\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"runtime\"\n\t\"sync\"\n\n\tmapset \"github.com/deckarep/golang-set/v2\"\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/multierror\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\ntype ErrDownloadSource struct {\n\tinner   error\n\tpkgName string\n\terrOut  string\n}\n\nfunc (e ErrDownloadSource) Error() string {\n\treturn fmt.Sprintln(gotext.Get(\"error downloading sources: %s\", text.Cyan(e.pkgName)),\n\t\t\"\\n\\t context:\", e.inner.Error(), \"\\n\\t\", e.errOut)\n}\n\nfunc (e *ErrDownloadSource) Unwrap() error {\n\treturn e.inner\n}\n\nfunc downloadPKGBUILDSource(ctx context.Context,\n\tcmdBuilder exe.ICmdBuilder, pkgBuildDir string, installIncompatible bool,\n) error {\n\targs := []string{\"--verifysource\", \"--skippgpcheck\", \"-f\"}\n\n\tif !cmdBuilder.GetKeepSrc() {\n\t\targs = append(args, \"-Cc\")\n\t}\n\n\tif installIncompatible {\n\t\targs = append(args, \"--ignorearch\")\n\t}\n\n\terr := cmdBuilder.Show(\n\t\tcmdBuilder.BuildMakepkgCmd(ctx, pkgBuildDir, args...))\n\tif err != nil {\n\t\treturn ErrDownloadSource{inner: err, pkgName: pkgBuildDir}\n\t}\n\n\treturn nil\n}\n\nfunc downloadPKGBUILDSourceWorker(ctx context.Context, wg *sync.WaitGroup,\n\tdirChannel <-chan string, valOut chan<- string, errOut chan<- error,\n\tcmdBuilder exe.ICmdBuilder, incompatible bool,\n) {\n\tfor pkgBuildDir := range dirChannel {\n\t\terr := downloadPKGBUILDSource(ctx, cmdBuilder, pkgBuildDir, incompatible)\n\t\tif err != nil {\n\t\t\terrOut <- ErrDownloadSource{inner: err, pkgName: pkgBuildDir, errOut: \"\"}\n\t\t} else {\n\t\t\tvalOut <- pkgBuildDir\n\t\t}\n\t}\n\n\twg.Done()\n}\n\nfunc downloadPKGBUILDSourceFanout(ctx context.Context, cmdBuilder exe.ICmdBuilder, pkgBuildDirs map[string]string,\n\tincompatible bool, maxConcurrentDownloads int,\n) error {\n\tif len(pkgBuildDirs) == 0 {\n\t\treturn nil // no work to do\n\t}\n\n\tif len(pkgBuildDirs) == 1 {\n\t\tfor _, pkgBuildDir := range pkgBuildDirs {\n\t\t\treturn downloadPKGBUILDSource(ctx, cmdBuilder, pkgBuildDir, incompatible)\n\t\t}\n\t}\n\n\tvar (\n\t\tnumOfWorkers    = runtime.NumCPU()\n\t\twg              = &sync.WaitGroup{}\n\t\tc               = make(chan string)\n\t\tfanInChanValues = make(chan string)\n\t\tfanInChanErrors = make(chan error)\n\t)\n\n\tif maxConcurrentDownloads != 0 {\n\t\tnumOfWorkers = maxConcurrentDownloads\n\t}\n\n\tdedupSet := mapset.NewThreadUnsafeSet[string]()\n\n\tgo func() {\n\t\tfor _, pkgbuildDir := range pkgBuildDirs {\n\t\t\tif !dedupSet.Contains(pkgbuildDir) {\n\t\t\t\tc <- pkgbuildDir\n\t\t\t\tdedupSet.Add(pkgbuildDir)\n\t\t\t}\n\t\t}\n\n\t\tclose(c)\n\t}()\n\n\t// Launch Workers\n\twg.Add(numOfWorkers)\n\n\tfor s := 0; s < numOfWorkers; s++ {\n\t\tgo downloadPKGBUILDSourceWorker(ctx, wg, c,\n\t\t\tfanInChanValues, fanInChanErrors, cmdBuilder, incompatible)\n\t}\n\n\tgo func() {\n\t\twg.Wait()\n\t\tclose(fanInChanValues)\n\t\tclose(fanInChanErrors)\n\t}()\n\n\treturnErr := multierror.MultiError{}\n\nreceiver:\n\tfor {\n\t\tselect {\n\t\tcase _, ok := <-fanInChanValues:\n\t\t\tif !ok {\n\t\t\t\tbreak receiver\n\t\t\t}\n\t\tcase err, ok := <-fanInChanErrors:\n\t\t\tif !ok {\n\t\t\t\tbreak receiver\n\t\t\t}\n\t\t\treturnErr.Add(err)\n\t\t}\n\t}\n\n\treturn returnErr.Return()\n}\n"
  },
  {
    "path": "pkg/sync/workdir/aur_source_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage workdir\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"sync/atomic\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\n\t\"github.com/Jguer/yay/v12/pkg/multierror\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n)\n\ntype TestMakepkgBuilder struct {\n\texe.ICmdBuilder\n\tparentBuilder *exe.CmdBuilder\n\ttest          *testing.T\n\tpasses        uint32\n\twant          string\n\twantDir       string\n\tshowError     error\n}\n\nfunc (z *TestMakepkgBuilder) BuildMakepkgCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd {\n\tcmd := z.parentBuilder.BuildMakepkgCmd(ctx, dir, extraArgs...)\n\tif z.want != \"\" {\n\t\tassert.Contains(z.test, cmd.String(), z.want)\n\t}\n\n\tif z.GetKeepSrc() {\n\t\tassert.NotContains(z.test, cmd.String(), \"-Cc\")\n\t}\n\n\tif z.wantDir != \"\" {\n\t\tassert.Equal(z.test, z.wantDir, cmd.Dir)\n\t}\n\n\tatomic.AddUint32(&z.passes, 1)\n\n\treturn cmd\n}\n\nfunc (z *TestMakepkgBuilder) Show(cmd *exec.Cmd) error {\n\treturn z.showError\n}\n\nfunc (z *TestMakepkgBuilder) GetKeepSrc() bool {\n\treturn z.parentBuilder.KeepSrc\n}\n\n// GIVEN 1 package\n// WHEN downloadPKGBUILDSource is called\n// THEN 1 call should be made to makepkg with the specified parameters and dir\nfunc Test_downloadPKGBUILDSource(t *testing.T) {\n\tt.Parallel()\n\n\ttype testCase struct {\n\t\tdesc    string\n\t\tkeepSrc bool\n\t\twant    string\n\t}\n\n\ttestCases := []testCase{\n\t\t{\n\t\t\tdesc:    \"keepsrc\",\n\t\t\tkeepSrc: true,\n\t\t\twant:    \"makepkg --nocheck --config /etc/not.conf --verifysource --skippgpcheck -f\",\n\t\t},\n\t\t{\n\t\t\tdesc:    \"nokeepsrc\",\n\t\t\tkeepSrc: false,\n\t\t\twant:    \"makepkg --nocheck --config /etc/not.conf --verifysource --skippgpcheck -f -Cc\",\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.desc, func(td *testing.T) {\n\t\t\tcmdBuilder := &TestMakepkgBuilder{\n\t\t\t\tparentBuilder: &exe.CmdBuilder{\n\t\t\t\t\tMakepkgConfPath: \"/etc/not.conf\",\n\t\t\t\t\tMakepkgFlags:    []string{\"--nocheck\"},\n\t\t\t\t\tMakepkgBin:      \"makepkg\",\n\t\t\t\t\tKeepSrc:         tc.keepSrc,\n\t\t\t\t},\n\t\t\t\ttest:    t,\n\t\t\t\twant:    tc.want,\n\t\t\t\twantDir: \"/tmp/yay-bin\",\n\t\t\t}\n\t\t\terr := downloadPKGBUILDSource(context.Background(), cmdBuilder, filepath.Join(\"/tmp\", \"yay-bin\"), false)\n\t\t\tassert.NoError(t, err)\n\t\t\tassert.Equal(t, 1, int(cmdBuilder.passes))\n\t\t})\n\t}\n}\n\n// GIVEN 1 package\n// WHEN downloadPKGBUILDSource is called\n// THEN 1 call should be made to makepkg which should return error\nfunc Test_downloadPKGBUILDSourceError(t *testing.T) {\n\tt.Parallel()\n\tcmdBuilder := &TestMakepkgBuilder{\n\t\tparentBuilder: &exe.CmdBuilder{MakepkgConfPath: \"/etc/not.conf\", MakepkgFlags: []string{\"--nocheck\"}, MakepkgBin: \"makepkg\"},\n\t\ttest:          t,\n\t\twant:          \"makepkg --nocheck --config /etc/not.conf --verifysource --skippgpcheck -f -Cc\",\n\t\twantDir:       \"/tmp/yay-bin\",\n\t\tshowError:     &exec.ExitError{},\n\t}\n\terr := downloadPKGBUILDSource(context.Background(), cmdBuilder, filepath.Join(\"/tmp\", \"yay-bin\"), false)\n\tassert.Error(t, err)\n\tassert.EqualError(t, err, \"error downloading sources: \\x1b[36m/tmp/yay-bin\\x1b[0m \\n\\t context: <nil> \\n\\t \\n\")\n}\n\n// GIVEN 5 packages\n// WHEN downloadPKGBUILDSourceFanout is called\n// THEN 5 calls should be made to makepkg\nfunc Test_downloadPKGBUILDSourceFanout(t *testing.T) {\n\tt.Parallel()\n\n\tpkgBuildDirs := map[string]string{\n\t\t\"yay\":     \"/tmp/yay\",\n\t\t\"yay-bin\": \"/tmp/yay-bin\",\n\t\t\"yay-git\": \"/tmp/yay-git\",\n\t\t\"yay-v11\": \"/tmp/yay-v11\",\n\t\t\"yay-v12\": \"/tmp/yay-v12\",\n\t}\n\tfor _, maxConcurrentDownloads := range []int{0, 3} {\n\t\tt.Run(fmt.Sprintf(\"maxconcurrentdownloads set to %d\", maxConcurrentDownloads), func(t *testing.T) {\n\t\t\tcmdBuilder := &TestMakepkgBuilder{\n\t\t\t\tparentBuilder: &exe.CmdBuilder{\n\t\t\t\t\tMakepkgConfPath: \"/etc/not.conf\",\n\t\t\t\t\tMakepkgFlags:    []string{\"--nocheck\"}, MakepkgBin: \"makepkg\",\n\t\t\t\t},\n\t\t\t\ttest: t,\n\t\t\t}\n\n\t\t\terr := downloadPKGBUILDSourceFanout(context.Background(), cmdBuilder, pkgBuildDirs, true, maxConcurrentDownloads)\n\t\t\tassert.NoError(t, err)\n\t\t\tassert.Equal(t, 5, int(cmdBuilder.passes))\n\t\t})\n\t}\n}\n\n// GIVEN 1 package\n// WHEN downloadPKGBUILDSourceFanout is called\n// THEN 1 calls should be made to makepkg without concurrency\nfunc Test_downloadPKGBUILDSourceFanoutNoCC(t *testing.T) {\n\tt.Parallel()\n\tcmdBuilder := &TestMakepkgBuilder{\n\t\tparentBuilder: &exe.CmdBuilder{\n\t\t\tMakepkgConfPath: \"/etc/not.conf\",\n\t\t\tMakepkgFlags:    []string{\"--nocheck\"}, MakepkgBin: \"makepkg\",\n\t\t},\n\t\ttest: t,\n\t}\n\n\tpkgBuildDirs := map[string]string{\"yay\": \"/tmp/yay\"}\n\n\terr := downloadPKGBUILDSourceFanout(context.Background(), cmdBuilder, pkgBuildDirs, false, 0)\n\tassert.NoError(t, err)\n\tassert.Equal(t, 1, int(cmdBuilder.passes))\n}\n\n// GIVEN 5 packages\n// WHEN downloadPKGBUILDSourceFanout is called\n// THEN 5 calls should be made to makepkg\nfunc Test_downloadPKGBUILDSourceFanoutError(t *testing.T) {\n\tt.Parallel()\n\tcmdBuilder := &TestMakepkgBuilder{\n\t\tparentBuilder: &exe.CmdBuilder{\n\t\t\tMakepkgConfPath: \"/etc/not.conf\",\n\t\t\tMakepkgFlags:    []string{\"--nocheck\"}, MakepkgBin: \"makepkg\",\n\t\t},\n\t\ttest:      t,\n\t\tshowError: &exec.ExitError{},\n\t}\n\n\tpkgBuildDirs := map[string]string{\n\t\t\"yay\":     \"/tmp/yay\",\n\t\t\"yay-bin\": \"/tmp/yay-bin\",\n\t\t\"yay-git\": \"/tmp/yay-git\",\n\t\t\"yay-v11\": \"/tmp/yay-v11\",\n\t\t\"yay-v12\": \"/tmp/yay-v12\",\n\t}\n\n\terr := downloadPKGBUILDSourceFanout(context.Background(), cmdBuilder, pkgBuildDirs, false, 0)\n\tassert.Error(t, err)\n\tassert.Equal(t, 5, int(cmdBuilder.passes))\n\tassert.Len(t, err.(*multierror.MultiError).Errors, 5)\n}\n"
  },
  {
    "path": "pkg/sync/workdir/clean.go",
    "content": "package workdir\n\nimport (\n\t\"context\"\n\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\nfunc removeMake(ctx context.Context, config *settings.Configuration,\n\tcmdBuilder exe.ICmdBuilder, makeDeps []string, cmdArgs *parser.Arguments,\n) error {\n\tremoveArguments := cmdArgs.CopyGlobal()\n\n\terr := removeArguments.AddArg(\"R\", \"s\", \"u\")\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, pkg := range makeDeps {\n\t\tremoveArguments.AddTarget(pkg)\n\t}\n\n\toldValue := settings.NoConfirm\n\tsettings.NoConfirm = true\n\terr = cmdBuilder.Show(cmdBuilder.BuildPacmanCmd(ctx,\n\t\tremoveArguments, config.Mode, settings.NoConfirm))\n\tsettings.NoConfirm = oldValue\n\n\treturn err\n}\n\nfunc cleanAfter(ctx context.Context, run *runtime.Runtime,\n\tcmdBuilder exe.ICmdBuilder, pkgbuildDirs map[string]string,\n) {\n\trun.Logger.Println(gotext.Get(\"removing untracked AUR files from cache...\"))\n\n\ti := 0\n\tfor _, dir := range pkgbuildDirs {\n\t\trun.Logger.OperationInfoln(gotext.Get(\"Cleaning (%d/%d): %s\", i+1, len(pkgbuildDirs), text.Cyan(dir)))\n\n\t\t_, stderr, err := cmdBuilder.Capture(\n\t\t\tcmdBuilder.BuildGitCmd(\n\t\t\t\tctx, dir, \"reset\", \"--hard\", \"HEAD\"))\n\t\tif err != nil {\n\t\t\trun.Logger.Errorln(gotext.Get(\"error resetting %s: %s\", dir, stderr))\n\t\t}\n\n\t\tif err := run.CmdBuilder.Show(\n\t\t\trun.CmdBuilder.BuildGitCmd(\n\t\t\t\tctx, dir, \"clean\", \"-fx\", \"--exclude\", \"*.pkg.*\")); err != nil {\n\t\t\trun.Logger.Errorln(err)\n\t\t}\n\n\t\ti++\n\t}\n}\n"
  },
  {
    "path": "pkg/sync/workdir/merge.go",
    "content": "package workdir\n\nimport (\n\t\"context\"\n\t\"errors\"\n\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n)\n\nfunc gitMerge(ctx context.Context, cmdBuilder exe.ICmdBuilder, dir string) error {\n\t_, stderr, err := cmdBuilder.Capture(\n\t\tcmdBuilder.BuildGitCmd(ctx,\n\t\t\tdir, \"reset\", \"--hard\", \"HEAD\"))\n\tif err != nil {\n\t\treturn errors.New(gotext.Get(\"error resetting %s: %s\", dir, stderr))\n\t}\n\n\t_, stderr, err = cmdBuilder.Capture(\n\t\tcmdBuilder.BuildGitCmd(ctx,\n\t\t\tdir, \"merge\", \"--no-edit\", \"--ff\"))\n\tif err != nil {\n\t\treturn errors.New(gotext.Get(\"error merging %s: %s\", dir, stderr))\n\t}\n\n\treturn nil\n}\n\nfunc mergePkgbuilds(ctx context.Context, cmdBuilder exe.ICmdBuilder, pkgbuildDirs map[string]string) error {\n\tfor _, dir := range pkgbuildDirs {\n\t\terr := gitMerge(ctx, cmdBuilder, dir)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/sync/workdir/preparer.go",
    "content": "package workdir\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/dep\"\n\t\"github.com/Jguer/yay/v12/pkg/download\"\n\t\"github.com/Jguer/yay/v12/pkg/menus\"\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/sync/build\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\n\tgosrc \"github.com/Morganamilo/go-srcinfo\"\n\tmapset \"github.com/deckarep/golang-set/v2\"\n\t\"github.com/leonelquinteros/gotext\"\n)\n\ntype HookType string\n\nconst (\n\t// PreDownloadSourcesHook is called before sourcing a package\n\tPreDownloadSourcesHook HookType = \"pre-download-sources\"\n)\n\ntype HookFn func(ctx context.Context, run *runtime.Runtime, w io.Writer,\n\tpkgbuildDirsByBase map[string]string, installed mapset.Set[string],\n) error\n\ntype Hook struct {\n\tName   string\n\tHookfn HookFn\n\tType   HookType\n}\n\ntype Preparer struct {\n\tdbExecutor      db.Executor\n\tcmdBuilder      exe.ICmdBuilder\n\tcfg             *settings.Configuration\n\thooks           []Hook\n\tdownloadSources bool\n\tlog             *text.Logger\n\n\tmakeDeps []string\n}\n\nfunc NewPreparerWithoutHooks(dbExecutor db.Executor, cmdBuilder exe.ICmdBuilder,\n\tcfg *settings.Configuration, logger *text.Logger, downloadSources bool,\n) *Preparer {\n\treturn &Preparer{\n\t\tdbExecutor:      dbExecutor,\n\t\tcmdBuilder:      cmdBuilder,\n\t\tcfg:             cfg,\n\t\thooks:           []Hook{},\n\t\tdownloadSources: downloadSources,\n\t\tlog:             logger,\n\t}\n}\n\nfunc NewPreparer(dbExecutor db.Executor, cmdBuilder exe.ICmdBuilder,\n\tcfg *settings.Configuration, logger *text.Logger,\n) *Preparer {\n\tpreper := NewPreparerWithoutHooks(dbExecutor, cmdBuilder, cfg, logger, true)\n\n\tif cfg.CleanMenu {\n\t\tpreper.hooks = append(preper.hooks, Hook{\n\t\t\tName:   \"clean\",\n\t\t\tHookfn: menus.CleanFn,\n\t\t\tType:   PreDownloadSourcesHook,\n\t\t})\n\t}\n\n\tif cfg.DiffMenu {\n\t\tpreper.hooks = append(preper.hooks, Hook{\n\t\t\tName:   \"diff\",\n\t\t\tHookfn: menus.DiffFn,\n\t\t\tType:   PreDownloadSourcesHook,\n\t\t})\n\t}\n\n\tif cfg.EditMenu {\n\t\tpreper.hooks = append(preper.hooks, Hook{\n\t\t\tName:   \"edit\",\n\t\t\tHookfn: menus.EditFn,\n\t\t\tType:   PreDownloadSourcesHook,\n\t\t})\n\t}\n\n\treturn preper\n}\n\nfunc (preper *Preparer) ShouldCleanAURDirs(run *runtime.Runtime, pkgBuildDirs map[string]string) build.PostInstallHookFunc {\n\tif !preper.cfg.CleanAfter || len(pkgBuildDirs) == 0 {\n\t\treturn nil\n\t}\n\n\tpreper.log.Debugln(\"added post install hook to clean up AUR dirs\", pkgBuildDirs)\n\n\treturn func(ctx context.Context) error {\n\t\tcleanAfter(ctx, run, run.CmdBuilder, pkgBuildDirs)\n\t\treturn nil\n\t}\n}\n\nfunc (preper *Preparer) ShouldCleanMakeDeps(run *runtime.Runtime, cmdArgs *parser.Arguments) build.PostInstallHookFunc {\n\tif len(preper.makeDeps) == 0 {\n\t\treturn nil\n\t}\n\n\tswitch preper.cfg.RemoveMake {\n\tcase \"yes\":\n\t\tbreak\n\tcase \"no\":\n\t\treturn nil\n\tdefault:\n\t\tisYesDefault := preper.cfg.RemoveMake == \"askyes\"\n\t\tif !preper.log.ContinueTask(gotext.Get(\"Remove make dependencies after install?\"),\n\t\t\tisYesDefault, settings.NoConfirm) {\n\t\t\treturn nil\n\t\t}\n\t}\n\n\tpreper.log.Debugln(\"added post install hook to clean up AUR makedeps\", preper.makeDeps)\n\n\treturn func(ctx context.Context) error {\n\t\treturn removeMake(ctx, preper.cfg, run.CmdBuilder, preper.makeDeps, cmdArgs)\n\t}\n}\n\nfunc (preper *Preparer) Run(ctx context.Context, run *runtime.Runtime,\n\ttargets []map[string]*dep.InstallInfo,\n) (pkgbuildDirsByBase map[string]string, err error) {\n\tpreper.Present(targets)\n\n\tpkgBuildDirs, err := preper.PrepareWorkspace(ctx, run, targets)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn pkgBuildDirs, nil\n}\n\nfunc (preper *Preparer) Present(targets []map[string]*dep.InstallInfo) {\n\tpkgsBySourceAndReason := map[string]map[string][]string{}\n\n\tfor _, layer := range targets {\n\t\tfor pkgName, info := range layer {\n\t\t\tsource := dep.SourceNames[info.Source]\n\t\t\treason := dep.ReasonNames[info.Reason]\n\n\t\t\tvar pkgStr string\n\t\t\tif info.Version != \"\" {\n\t\t\t\tpkgStr = text.Cyan(fmt.Sprintf(\"%s-%s\", pkgName, info.Version))\n\t\t\t} else {\n\t\t\t\tpkgStr = text.Cyan(pkgName)\n\t\t\t}\n\n\t\t\tif _, ok := pkgsBySourceAndReason[source]; !ok {\n\t\t\t\tpkgsBySourceAndReason[source] = map[string][]string{}\n\t\t\t}\n\n\t\t\tpkgsBySourceAndReason[source][reason] = append(pkgsBySourceAndReason[source][reason], pkgStr)\n\n\t\t\tif info.Reason == dep.MakeDep {\n\t\t\t\tpreper.makeDeps = append(preper.makeDeps, pkgName)\n\t\t\t}\n\t\t}\n\t}\n\n\tfor source, pkgsByReason := range pkgsBySourceAndReason {\n\t\tfor reason, pkgs := range pkgsByReason {\n\t\t\tpreper.log.Printf(text.Bold(\"%s %s (%d):\")+\" %s\\n\",\n\t\t\t\tsource,\n\t\t\t\treason,\n\t\t\t\tlen(pkgs),\n\t\t\t\tstrings.Join(pkgs, \", \"))\n\t\t}\n\t}\n}\n\nfunc (preper *Preparer) PrepareWorkspace(ctx context.Context,\n\trun *runtime.Runtime, targets []map[string]*dep.InstallInfo,\n) (map[string]string, error) {\n\taurBasesToClone := mapset.NewThreadUnsafeSet[string]()\n\tpkgBuildDirsByBase := make(map[string]string, len(targets))\n\n\tfor _, layer := range targets {\n\t\tfor _, info := range layer {\n\t\t\tswitch info.Source {\n\t\t\tcase dep.AUR:\n\t\t\t\tpkgBase := *info.AURBase\n\t\t\t\tpkgBuildDir := filepath.Join(preper.cfg.BuildDir, pkgBase)\n\t\t\t\tif preper.needToCloneAURBase(info, pkgBuildDir) {\n\t\t\t\t\taurBasesToClone.Add(pkgBase)\n\t\t\t\t}\n\t\t\t\tpkgBuildDirsByBase[pkgBase] = pkgBuildDir\n\t\t\tcase dep.SrcInfo:\n\t\t\t\tpkgBase := *info.AURBase\n\t\t\t\tpkgBuildDirsByBase[pkgBase] = *info.SrcinfoPath\n\t\t\t}\n\t\t}\n\t}\n\n\tif _, errA := download.AURPKGBUILDRepos(ctx,\n\t\tpreper.cmdBuilder, preper.log.Child(\"download\"), aurBasesToClone.ToSlice(),\n\t\tpreper.cfg.AURURL, preper.cfg.BuildDir, false); errA != nil {\n\t\treturn nil, errA\n\t}\n\n\tif !preper.downloadSources {\n\t\treturn pkgBuildDirsByBase, nil\n\t}\n\n\tif err := mergePkgbuilds(ctx, preper.cmdBuilder, pkgBuildDirsByBase); err != nil {\n\t\treturn nil, err\n\t}\n\n\tremoteNames := preper.dbExecutor.InstalledRemotePackageNames()\n\tremoteNamesCache := mapset.NewThreadUnsafeSet(remoteNames...)\n\tfor _, hookFn := range preper.hooks {\n\t\tif hookFn.Type == PreDownloadSourcesHook {\n\t\t\tif err := hookFn.Hookfn(ctx, run, os.Stdout, pkgBuildDirsByBase, remoteNamesCache); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t}\n\n\tif errP := downloadPKGBUILDSourceFanout(ctx, preper.cmdBuilder,\n\t\tpkgBuildDirsByBase, false, preper.cfg.MaxConcurrentDownloads); errP != nil {\n\t\tpreper.log.Errorln(errP)\n\t}\n\n\treturn pkgBuildDirsByBase, nil\n}\n\nfunc (preper *Preparer) needToCloneAURBase(installInfo *dep.InstallInfo, pkgbuildDir string) bool {\n\tif preper.cfg.ReDownload == \"all\" {\n\t\treturn true\n\t}\n\n\tsrcinfoFile := filepath.Join(pkgbuildDir, \".SRCINFO\")\n\tif pkgbuild, err := gosrc.ParseFile(srcinfoFile); err == nil {\n\t\tif db.VerCmp(pkgbuild.Version(), installInfo.Version) >= 0 {\n\t\t\tpreper.log.OperationInfoln(\n\t\t\t\tgotext.Get(\"PKGBUILD up to date, skipping download: %s\",\n\t\t\t\t\ttext.Cyan(*installInfo.AURBase)))\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n"
  },
  {
    "path": "pkg/sync/workdir/preparer_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage workdir\n\nimport (\n\t\"io\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\nfunc newTestLogger() *text.Logger {\n\treturn text.NewLogger(io.Discard, io.Discard, strings.NewReader(\"\"), true, \"test\")\n}\n\n// Test order of pre-download-sources hooks\nfunc TestPreDownloadSourcesHooks(t *testing.T) {\n\ttestCases := []struct {\n\t\tname     string\n\t\tcfg      *settings.Configuration\n\t\twantHook []string\n\t}{\n\t\t{\n\t\t\tname: \"clean, diff, edit\",\n\t\t\tcfg: &settings.Configuration{\n\t\t\t\tCleanMenu: true,\n\t\t\t\tDiffMenu:  true,\n\t\t\t\tEditMenu:  true,\n\t\t\t},\n\t\t\twantHook: []string{\"clean\", \"diff\", \"edit\"},\n\t\t},\n\t\t{\n\t\t\tname: \"clean, edit\",\n\t\t\tcfg: &settings.Configuration{\n\t\t\t\tCleanMenu: true,\n\t\t\t\tDiffMenu:  false,\n\t\t\t\tEditMenu:  true,\n\t\t\t},\n\t\t\twantHook: []string{\"clean\", \"edit\"},\n\t\t},\n\t\t{\n\t\t\tname: \"clean, diff\",\n\t\t\tcfg: &settings.Configuration{\n\t\t\t\tCleanMenu: true,\n\t\t\t\tDiffMenu:  true,\n\t\t\t\tEditMenu:  false,\n\t\t\t},\n\t\t\twantHook: []string{\"clean\", \"diff\"},\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tpreper := NewPreparer(nil, nil, tc.cfg, newTestLogger())\n\n\t\t\tassert.Len(t, preper.hooks, len(tc.wantHook))\n\n\t\t\tgot := make([]string, 0, len(preper.hooks))\n\n\t\t\tfor _, hook := range preper.hooks {\n\t\t\t\tgot = append(got, hook.Name)\n\t\t\t}\n\n\t\t\tassert.Equal(t, tc.wantHook, got)\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/text/color.go",
    "content": "package text\n\nimport \"fmt\"\n\nconst (\n\tredCode     = \"\\x1b[31m\"\n\tgreenCode   = \"\\x1b[32m\"\n\tyellowCode  = \"\\x1b[33m\"\n\tblueCode    = \"\\x1b[34m\"\n\tmagentaCode = \"\\x1b[35m\"\n\tCyanCode    = \"\\x1b[36m\"\n\tboldCode    = \"\\x1b[1m\"\n\n\tResetCode = \"\\x1b[0m\"\n)\n\n// UseColor determines if package will emit colors.\nvar UseColor = true\n\nfunc stylize(startCode, in string) string {\n\tif UseColor {\n\t\treturn startCode + in + ResetCode\n\t}\n\n\treturn in\n}\n\nfunc Red(in string) string {\n\treturn stylize(redCode, in)\n}\n\nfunc Green(in string) string {\n\treturn stylize(greenCode, in)\n}\n\nfunc yellow(in string) string {\n\treturn stylize(yellowCode, in)\n}\n\nfunc Cyan(in string) string {\n\treturn stylize(CyanCode, in)\n}\n\nfunc Magenta(in string) string {\n\treturn stylize(magentaCode, in)\n}\n\nfunc Blue(in string) string {\n\treturn stylize(blueCode, in)\n}\n\nfunc Bold(in string) string {\n\treturn stylize(boldCode, in)\n}\n\n// ColorHash Colors text using a hashing algorithm. The same text will always produce the\n// same color while different text will produce a different color.\nfunc ColorHash(name string) (output string) {\n\tif !UseColor {\n\t\treturn name\n\t}\n\n\tvar hash uint = 5381\n\n\tfor i := 0; i < len(name); i++ {\n\t\thash = uint(name[i]) + ((hash << 5) + (hash))\n\t}\n\n\treturn fmt.Sprintf(\"\\x1b[%dm%s\\x1b[0m\", hash%6+31, name)\n}\n"
  },
  {
    "path": "pkg/text/convert.go",
    "content": "package text\n\nimport (\n\t\"fmt\"\n)\n\n// Human method returns results in human readable format.\nfunc Human(size int64) string {\n\tfloatsize := float32(size)\n\n\tunits := [...]string{\"\", \"Ki\", \"Mi\", \"Gi\", \"Ti\", \"Pi\", \"Ei\", \"Zi\", \"Yi\"}\n\tfor _, unit := range units {\n\t\tif floatsize < 1024 {\n\t\t\treturn fmt.Sprintf(\"%.1f %sB\", floatsize, unit)\n\t\t}\n\n\t\tfloatsize /= 1024\n\t}\n\n\treturn fmt.Sprintf(\"%d%s\", size, \"B\")\n}\n"
  },
  {
    "path": "pkg/text/errors.go",
    "content": "package text\n\nimport \"github.com/leonelquinteros/gotext\"\n\ntype ErrInputOverflow struct{}\n\nfunc (e ErrInputOverflow) Error() string {\n\treturn gotext.Get(\"input too long\")\n}\n"
  },
  {
    "path": "pkg/text/input.go",
    "content": "package text\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"strings\"\n\t\"unicode\"\n\t\"unicode/utf8\"\n\n\t\"github.com/leonelquinteros/gotext\"\n)\n\nfunc (l *Logger) GetInput(defaultValue string, noConfirm bool) (string, error) {\n\tl.Info()\n\n\tif defaultValue != \"\" || noConfirm {\n\t\tl.Println(defaultValue)\n\t\treturn defaultValue, nil\n\t}\n\n\treader := bufio.NewReader(l.r)\n\n\tbuf, overflow, err := reader.ReadLine()\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tif overflow {\n\t\treturn \"\", ErrInputOverflow{}\n\t}\n\n\treturn string(buf), nil\n}\n\n// ContinueTask prompts if user wants to continue task.\n// If NoConfirm is set the action will continue without user input.\nfunc (l *Logger) ContinueTask(s string, preset, noConfirm bool) bool {\n\tif noConfirm {\n\t\treturn preset\n\t}\n\n\tvar (\n\t\tresponse string\n\t\tpostFix  string\n\t\tn        string\n\t\ty        string\n\t\tyes      = gotext.Get(\"yes\")\n\t\tno       = gotext.Get(\"no\")\n\t)\n\n\t// Only use localized \"y\" and \"n\" if they are latin characters.\n\tif nRune, _ := utf8.DecodeRuneInString(no); unicode.Is(unicode.Latin, nRune) {\n\t\tn = string(nRune)\n\t} else {\n\t\tn = nDefault\n\t}\n\n\tif yRune, _ := utf8.DecodeRuneInString(yes); unicode.Is(unicode.Latin, yRune) {\n\t\ty = string(yRune)\n\t} else {\n\t\ty = yDefault\n\t}\n\n\tif preset { // If default behavior is true, use y as default.\n\t\tpostFix = fmt.Sprintf(\" [%s/%s] \", strings.ToUpper(y), n)\n\t} else { // If default behavior is anything else, use n as default.\n\t\tpostFix = fmt.Sprintf(\" [%s/%s] \", y, strings.ToUpper(n))\n\t}\n\n\tl.OperationInfo(Bold(s), Bold(postFix))\n\n\tif _, err := fmt.Fscanln(l.r, &response); err != nil {\n\t\treturn preset\n\t}\n\n\treturn strings.EqualFold(response, yes) ||\n\t\tstrings.EqualFold(response, y) ||\n\t\t(!strings.EqualFold(yDefault, n) && strings.EqualFold(response, yDefault))\n}\n"
  },
  {
    "path": "pkg/text/service.go",
    "content": "package text\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\nconst (\n\tarrow      = \"==>\"\n\tsmallArrow = \" ->\"\n\topSymbol   = \"::\"\n)\n\ntype Logger struct {\n\tname   string\n\tDebug  bool\n\tstdout io.Writer\n\tstderr io.Writer\n\tr      io.Reader\n}\n\nfunc NewLogger(stdout, stderr io.Writer, r io.Reader, debug bool, name string) *Logger {\n\treturn &Logger{\n\t\tDebug:  debug,\n\t\tname:   name,\n\t\tr:      r,\n\t\tstderr: stderr,\n\t\tstdout: stdout,\n\t}\n}\n\nfunc (l *Logger) Child(name string) *Logger {\n\treturn NewLogger(l.stdout, l.stderr, l.r, l.Debug, name)\n}\n\nfunc (l *Logger) Debugln(a ...any) {\n\tif !l.Debug {\n\t\treturn\n\t}\n\n\tl.Println(append([]any{\n\t\tBold(yellow(fmt.Sprintf(\"[DEBUG:%s]\", l.name))),\n\t}, a...)...)\n}\n\nfunc (l *Logger) OperationInfoln(a ...any) {\n\tl.Println(l.SprintOperationInfo(a...))\n}\n\nfunc (l *Logger) OperationInfo(a ...any) {\n\tl.Print(l.SprintOperationInfo(a...))\n}\n\nfunc (l *Logger) SprintOperationInfo(a ...any) string {\n\treturn fmt.Sprint(append([]any{Bold(Cyan(opSymbol + \" \")), boldCode}, a...)...) + ResetCode\n}\n\nfunc (l *Logger) Info(a ...any) {\n\tl.Print(append([]any{Bold(Green(arrow + \" \"))}, a...)...)\n}\n\nfunc (l *Logger) Infoln(a ...any) {\n\tl.Println(append([]any{Bold(Green(arrow))}, a...)...)\n}\n\nfunc (l *Logger) Warn(a ...any) {\n\tl.Print(l.SprintWarn(a...))\n}\n\nfunc (l *Logger) Warnln(a ...any) {\n\tl.Println(l.SprintWarn(a...))\n}\n\nfunc (l *Logger) SprintWarn(a ...any) string {\n\treturn fmt.Sprint(append([]any{Bold(yellow(smallArrow + \" \"))}, a...)...)\n}\n\nfunc (l *Logger) Error(a ...any) {\n\tfmt.Fprint(l.stderr, l.SprintError(a...))\n}\n\nfunc (l *Logger) Errorln(a ...any) {\n\tfmt.Fprintln(l.stderr, l.SprintError(a...))\n}\n\nfunc (l *Logger) SprintError(a ...any) string {\n\treturn fmt.Sprint(append([]any{Bold(Red(smallArrow + \" \"))}, a...)...)\n}\n\nfunc (l *Logger) Printf(format string, a ...any) {\n\tfmt.Fprintf(l.stdout, format, a...)\n}\n\nfunc (l *Logger) Println(a ...any) {\n\tfmt.Fprintln(l.stdout, a...)\n}\n\nfunc (l *Logger) Print(a ...any) {\n\tfmt.Fprint(l.stdout, a...)\n}\n"
  },
  {
    "path": "pkg/text/text.go",
    "content": "package text\n\nimport (\n\t\"strings\"\n\t\"unicode\"\n)\n\nconst (\n\tyDefault = \"y\"\n\tnDefault = \"n\"\n)\n\n// SplitDBFromName split apart db/package to db and package.\nfunc SplitDBFromName(pkg string) (db, name string) {\n\tsplit := strings.SplitN(pkg, \"/\", 2)\n\n\tif len(split) == 2 {\n\t\treturn split[0], split[1]\n\t}\n\n\treturn \"\", split[0]\n}\n\n// LessRunes compares two rune values, and returns true if the first argument is lexicographicaly smaller.\nfunc LessRunes(iRunes, jRunes []rune) bool {\n\tmaxLen := min(len(iRunes), len(jRunes))\n\n\tfor idx := 0; idx < maxLen; idx++ {\n\t\tir := iRunes[idx]\n\t\tjr := jRunes[idx]\n\n\t\tlir := unicode.ToLower(ir)\n\t\tljr := unicode.ToLower(jr)\n\n\t\tif lir != ljr {\n\t\t\treturn lir < ljr\n\t\t}\n\n\t\t// the lowercase runes are the same, so compare the original\n\t\tif ir != jr {\n\t\t\treturn ir < jr\n\t\t}\n\t}\n\n\treturn len(iRunes) < len(jRunes)\n}\n\nvar RepoUrls = map[string]string{\n\t\"core\":             \"https://archlinux.org/packages/core\",\n\t\"core-testing\":     \"https://archlinux.org/packages/core-testing\",\n\t\"extra\":            \"https://archlinux.org/packages/extra\",\n\t\"extra-testing\":    \"https://archlinux.org/packages/extra-testing\",\n\t\"gnome-unstable\":   \"https://archlinux.org/packages/gnome-unstable\",\n\t\"kde-unstable\":     \"https://archlinux.org/packages/kde-unstable\",\n\t\"multilib\":         \"https://archlinux.org/packages/multilib\",\n\t\"multilib-testing\": \"https://archlinux.org/packages/multilib-testing\",\n\t\"testing\":          \"https://archlinux.org/packages/testing\",\n\t\"aur\":              \"https://aur.archlinux.org/packages\",\n\t\"devel\":            \"https://aur.archlinux.org/packages\",\n}\n\nfunc CreateOSC8Link(url, text string) string {\n\tosc8Start := \"\\033]8;;\" + url + \"\\033\\\\\"\n\tosc8End := \"\\033]8;;\\033\\\\\"\n\treturn osc8Start + text + osc8End\n}\n\nfunc CreateRepoLink(repo, arch, pkgName, text string) string {\n\tif !UseColor {\n\t\treturn text\n\t}\n\n\turlBase, ok := RepoUrls[repo]\n\tif !ok {\n\t\treturn text\n\t}\n\n\tvar url string\n\tif repo == \"aur\" || repo == \"devel\" {\n\t\turl = urlBase + \"/\" + pkgName\n\t} else {\n\t\turl = urlBase + \"/\" + arch + \"/\" + pkgName\n\t}\n\n\treturn CreateOSC8Link(url, text)\n}\n"
  },
  {
    "path": "pkg/text/text_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage text\n\nimport (\n\t\"io\"\n\t\"os\"\n\t\"path\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/leonelquinteros/gotext\"\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestLessRunes(t *testing.T) {\n\tt.Parallel()\n\n\ttype args struct {\n\t\tiRunes []rune\n\t\tjRunes []rune\n\t}\n\n\ttests := []struct {\n\t\tname string\n\t\targs args\n\t\twant bool\n\t}{\n\t\t{name: \"nilslices\", args: args{iRunes: nil, jRunes: nil}, want: false},\n\t\t{name: \"emptyslices\", args: args{iRunes: []rune{}, jRunes: []rune{}}, want: false},\n\t\t{name: \"simpleslice a,b\", args: args{iRunes: []rune{'a'}, jRunes: []rune{'b'}}, want: true},\n\t\t{name: \"simpleslice b,a\", args: args{iRunes: []rune{'b'}, jRunes: []rune{'a'}}, want: false},\n\t\t{name: \"equalslice\", args: args{iRunes: []rune{'a', 'a', 'a'}, jRunes: []rune{'a', 'a', 'a'}}, want: false},\n\t\t{name: \"uppercase\", args: args{iRunes: []rune{'a'}, jRunes: []rune{'A'}}, want: false},\n\t\t{name: \"longerFirstArg\", args: args{iRunes: []rune{'a', 'b'}, jRunes: []rune{'a'}}, want: false},\n\t\t{name: \"longerSecondArg\", args: args{iRunes: []rune{'a'}, jRunes: []rune{'a', 'b'}}, want: true},\n\t\t{name: \"utf8 less\", args: args{iRunes: []rune{'世', '2', '0'}, jRunes: []rune{'世', '界', '3'}}, want: true},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tgot := LessRunes(tt.args.iRunes, tt.args.jRunes)\n\t\t\tassert.Equal(t, tt.want, got)\n\t\t})\n\t}\n}\n\nfunc TestContinueTask(t *testing.T) {\n\tt.Parallel()\n\ttype args struct {\n\t\ts         string\n\t\tpreset    bool\n\t\tnoConfirm bool\n\t\tinput     string\n\t}\n\ttests := []struct {\n\t\tname string\n\t\targs args\n\t\twant bool\n\t}{\n\t\t{name: \"noconfirm-true\", args: args{s: \"\", preset: true, noConfirm: true}, want: true},\n\t\t{name: \"noconfirm-false\", args: args{s: \"\", preset: false, noConfirm: true}, want: false},\n\t\t{name: \"noinput-false\", args: args{s: \"\", preset: false, noConfirm: false}, want: false},\n\t\t{name: \"noinput-true\", args: args{s: \"\", preset: true, noConfirm: false}, want: true},\n\t\t{name: \"input-false\", args: args{s: \"\", input: \"n\", preset: true, noConfirm: false}, want: false},\n\t\t{name: \"input-true\", args: args{s: \"\", input: \"y\", preset: false, noConfirm: false}, want: true},\n\t\t{name: \"input-false-complete\", args: args{s: \"\", input: \"no\", preset: true, noConfirm: false}, want: false},\n\t\t{name: \"input-true-complete\", args: args{s: \"\", input: \"yes\", preset: false, noConfirm: false}, want: true},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\t// create io.Reader with value of input\n\t\t\tin := strings.NewReader(tt.args.input)\n\t\t\tlogger := NewLogger(io.Discard, io.Discard, in, false, \"test\")\n\t\t\tgot := logger.ContinueTask(tt.args.s, tt.args.preset, tt.args.noConfirm)\n\t\t\trequire.Equal(t, tt.want, got)\n\t\t})\n\t}\n}\n\nfunc TestContinueTaskRU(t *testing.T) {\n\tstrCustom := `\nmsgid \"yes\"\nmsgstr \"да\"\n\t`\n\n\t// Create Locales directory and files on temp location\n\ttmpDir := t.TempDir()\n\tdirname := path.Join(tmpDir, \"en_US\")\n\terr := os.MkdirAll(dirname, os.ModePerm)\n\trequire.NoError(t, err)\n\n\tfDefault, err := os.Create(path.Join(dirname, \"yay.po\"))\n\trequire.NoError(t, err)\n\n\tdefer fDefault.Close()\n\n\t_, err = fDefault.WriteString(strCustom)\n\trequire.NoError(t, err)\n\n\tgotext.Configure(tmpDir, \"en_US\", \"yay\")\n\trequire.Equal(t, \"да\", gotext.Get(\"yes\"))\n\n\ttype args struct {\n\t\ts         string\n\t\tpreset    bool\n\t\tnoConfirm bool\n\t\tinput     string\n\t}\n\ttests := []struct {\n\t\tname string\n\t\targs args\n\t\twant bool\n\t}{\n\t\t{name: \"default input false\", args: args{s: \"\", input: \"n\", preset: true, noConfirm: false}, want: false},\n\t\t{name: \"default input true\", args: args{s: \"\", input: \"y\", preset: false, noConfirm: false}, want: true},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tin := strings.NewReader(tt.args.input)\n\t\t\tlogger := NewLogger(io.Discard, io.Discard, in, false, \"test\")\n\t\t\tgot := logger.ContinueTask(tt.args.s, tt.args.preset, tt.args.noConfirm)\n\t\t\trequire.Equal(t, tt.want, got)\n\t\t})\n\t}\n\tgotext.SetLanguage(\"\")\n}\n\nfunc TestContinueTaskDE(t *testing.T) {\n\tstrCustom := `\nmsgid \"yes\"\nmsgstr \"ja\"\n\t`\n\n\t// Create Locales directory and files on temp location\n\ttmpDir := t.TempDir()\n\tdirname := path.Join(tmpDir, \"en_US\")\n\terr := os.MkdirAll(dirname, os.ModePerm)\n\trequire.NoError(t, err)\n\n\tfDefault, err := os.Create(path.Join(dirname, \"yay.po\"))\n\trequire.NoError(t, err)\n\n\tdefer fDefault.Close()\n\n\t_, err = fDefault.WriteString(strCustom)\n\trequire.NoError(t, err)\n\n\tgotext.Configure(tmpDir, \"en_US\", \"yay\")\n\trequire.Equal(t, \"ja\", gotext.Get(\"yes\"))\n\n\ttype args struct {\n\t\ts         string\n\t\tpreset    bool\n\t\tnoConfirm bool\n\t\tinput     string\n\t}\n\ttests := []struct {\n\t\tname string\n\t\targs args\n\t\twant bool\n\t}{\n\t\t{name: \"default input false\", args: args{s: \"\", input: \"n\", preset: true, noConfirm: false}, want: false},\n\t\t{name: \"default input true\", args: args{s: \"\", input: \"y\", preset: false, noConfirm: false}, want: true},\n\t\t{name: \"custom input true\", args: args{s: \"\", input: \"j\", preset: false, noConfirm: false}, want: true},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tin := strings.NewReader(tt.args.input)\n\t\t\tlogger := NewLogger(io.Discard, io.Discard, in, false, \"test\")\n\t\t\tgot := logger.ContinueTask(tt.args.s, tt.args.preset, tt.args.noConfirm)\n\t\t\trequire.Equal(t, tt.want, got)\n\t\t})\n\t}\n\tgotext.SetLanguage(\"\")\n}\n\nfunc TestCreateRepoLink(t *testing.T) {\n\ttests := []struct {\n\t\tname     string\n\t\tuseColor bool\n\t\trepo     string\n\t\tarch     string\n\t\tpkgName  string\n\t\ttext     string\n\t\twant     string\n\t}{\n\t\t{\n\t\t\tname:     \"color disabled returns text\",\n\t\t\tuseColor: false,\n\t\t\trepo:     \"core\",\n\t\t\tarch:     \"x86_64\",\n\t\t\tpkgName:  \"linux\",\n\t\t\ttext:     \"core/linux\",\n\t\t\twant:     \"core/linux\",\n\t\t},\n\t\t{\n\t\t\tname:     \"unknown repo returns text\",\n\t\t\tuseColor: true,\n\t\t\trepo:     \"unknown\",\n\t\t\tarch:     \"x86_64\",\n\t\t\tpkgName:  \"linux\",\n\t\t\ttext:     \"core/linux\",\n\t\t\twant:     \"core/linux\",\n\t\t},\n\t\t{\n\t\t\tname:     \"aur repo uses package url\",\n\t\t\tuseColor: true,\n\t\t\trepo:     \"aur\",\n\t\t\tarch:     \"any\",\n\t\t\tpkgName:  \"yay\",\n\t\t\ttext:     \"aur/yay\",\n\t\t\twant:     \"\\033]8;;https://aur.archlinux.org/packages/yay\\033\\\\aur/yay\\033]8;;\\033\\\\\",\n\t\t},\n\t\t{\n\t\t\tname:     \"core repo uses arch in url\",\n\t\t\tuseColor: true,\n\t\t\trepo:     \"core\",\n\t\t\tarch:     \"x86_64\",\n\t\t\tpkgName:  \"linux\",\n\t\t\ttext:     \"core/linux\",\n\t\t\twant:     \"\\033]8;;https://archlinux.org/packages/core/x86_64/linux\\033\\\\core/linux\\033]8;;\\033\\\\\",\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\toriginal := UseColor\n\t\t\tUseColor = tt.useColor\n\t\t\tt.Cleanup(func() { UseColor = original })\n\n\t\t\tgot := CreateRepoLink(tt.repo, tt.arch, tt.pkgName, tt.text)\n\t\t\tassert.Equal(t, tt.want, got)\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/text/time.go",
    "content": "package text\n\nimport \"time\"\n\n// Formats a unix timestamp to ISO 8601 date (yyyy-mm-dd).\nfunc FormatTime(i int) string {\n\tt := time.Unix(int64(i), 0)\n\treturn t.Format(\"2006-01-02\")\n}\n\n// Formats a unix timestamp to ISO 8601 date (Mon 02 Jan 2006 03:04:05 PM MST).\nfunc FormatTimeQuery(i int) string {\n\tt := time.Unix(int64(i), 0)\n\treturn t.Format(\"Mon 02 Jan 2006 03:04:05 PM MST\")\n}\n"
  },
  {
    "path": "pkg/upgrade/.snapshots/Test_upAUR-No_Updates",
    "content": "\u001b[1m\u001b[33m ->\u001b[0m\u001b[0m \u001b[36mignored\u001b[0m: ignoring package upgrade (\u001b[31m1.0.0\u001b[0m => \u001b[32m2.0.0\u001b[0m)\n\n"
  },
  {
    "path": "pkg/upgrade/.snapshots/Test_upAUR-Simple_Update",
    "content": "\n"
  },
  {
    "path": "pkg/upgrade/.snapshots/Test_upAUR-Time_Update",
    "content": "\n"
  },
  {
    "path": "pkg/upgrade/service.go",
    "content": "package upgrade\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"github.com/Jguer/aur\"\n\talpm \"github.com/Jguer/dyalpm\"\n\tmapset \"github.com/deckarep/golang-set/v2\"\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/dep\"\n\t\"github.com/Jguer/yay/v12/pkg/dep/topo\"\n\t\"github.com/Jguer/yay/v12/pkg/intrange\"\n\t\"github.com/Jguer/yay/v12/pkg/multierror\"\n\t\"github.com/Jguer/yay/v12/pkg/query\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\t\"github.com/Jguer/yay/v12/pkg/vcs\"\n)\n\nconst cutOffExtra = 2\n\ntype UpgradeService struct {\n\tgrapher    *dep.Grapher\n\taurCache   aur.QueryClient\n\tdbExecutor db.Executor\n\tvcsStore   vcs.Store\n\tcfg        *settings.Configuration\n\tlog        *text.Logger\n\tnoConfirm  bool\n\n\tAURWarnings *query.AURWarnings\n}\n\nfunc NewUpgradeService(grapher *dep.Grapher, aurCache aur.QueryClient,\n\tdbExecutor db.Executor, vcsStore vcs.Store,\n\tcfg *settings.Configuration, noConfirm bool, logger *text.Logger,\n) *UpgradeService {\n\treturn &UpgradeService{\n\t\tgrapher:     grapher,\n\t\taurCache:    aurCache,\n\t\tdbExecutor:  dbExecutor,\n\t\tvcsStore:    vcsStore,\n\t\tcfg:         cfg,\n\t\tnoConfirm:   noConfirm,\n\t\tlog:         logger,\n\t\tAURWarnings: query.NewWarnings(logger.Child(\"warnings\")),\n\t}\n}\n\n// upGraph adds packages to upgrade to the graph.\nfunc (u *UpgradeService) upGraph(ctx context.Context, graph *topo.Graph[string, *dep.InstallInfo],\n\tenableDowngrade bool,\n\tfilter Filter,\n) (err error) {\n\tvar (\n\t\tdevelUp UpSlice\n\t\terrs    multierror.MultiError\n\t\taurdata = make(map[string]*aur.Pkg)\n\t\taurUp   UpSlice\n\t)\n\n\tremote := u.dbExecutor.InstalledRemotePackages()\n\tremoteNames := u.dbExecutor.InstalledRemotePackageNames()\n\n\tif u.cfg.Mode.AtLeastAUR() {\n\t\tu.log.OperationInfoln(gotext.Get(\"Searching AUR for updates...\"))\n\n\t\t_aurdata, err := u.aurCache.Get(ctx, &aur.Query{Needles: remoteNames, By: aur.Name})\n\n\t\terrs.Add(err)\n\n\t\tif err == nil {\n\t\t\tfor i := range _aurdata {\n\t\t\t\tpkg := &_aurdata[i]\n\t\t\t\taurdata[pkg.Name] = pkg\n\t\t\t\tu.AURWarnings.AddToWarnings(remote, pkg)\n\t\t\t}\n\n\t\t\tu.AURWarnings.CalculateMissing(remoteNames, remote, aurdata)\n\n\t\t\taurUp = UpAUR(u.log, remote, aurdata, enableDowngrade)\n\n\t\t\tif u.cfg.Devel {\n\t\t\t\tu.log.OperationInfoln(gotext.Get(\"Checking development packages...\"))\n\n\t\t\t\tdevelUp = UpDevel(ctx, u.log, remote, aurdata, u.vcsStore)\n\n\t\t\t\tu.vcsStore.CleanOrphans(remote)\n\t\t\t}\n\t\t}\n\t}\n\n\taurPkgsAdded := []*aur.Pkg{}\n\n\tnames := mapset.NewThreadUnsafeSet[string]()\n\tfor i := range develUp.Up {\n\t\tup := &develUp.Up[i]\n\t\t// check if deps are satisfied for aur packages\n\t\treason := dep.Explicit\n\t\tif up.Reason == alpm.PkgReasonDepend {\n\t\t\treason = dep.Dep\n\t\t}\n\n\t\tif filter != nil && !filter(up) {\n\t\t\tcontinue\n\t\t}\n\n\t\taurPkg := aurdata[up.Name]\n\t\tgraph = u.grapher.GraphAURTarget(ctx, graph, aurPkg, &dep.InstallInfo{\n\t\t\tReason:       reason,\n\t\t\tSource:       dep.AUR,\n\t\t\tAURBase:      &aurPkg.PackageBase,\n\t\t\tUpgrade:      true,\n\t\t\tDevel:        true,\n\t\t\tLocalVersion: up.LocalVersion,\n\t\t\tVersion:      up.RemoteVersion,\n\t\t})\n\t\tnames.Add(up.Name)\n\t\taurPkgsAdded = append(aurPkgsAdded, aurPkg)\n\t}\n\n\tfor i := range aurUp.Up {\n\t\tup := &aurUp.Up[i]\n\t\t// add devel packages if they are not already in the list\n\t\tif names.Contains(up.Name) {\n\t\t\tcontinue\n\t\t}\n\n\t\t// check if deps are satisfied for aur packages\n\t\treason := dep.Explicit\n\t\tif up.Reason == alpm.PkgReasonDepend {\n\t\t\treason = dep.Dep\n\t\t}\n\n\t\tif filter != nil && !filter(up) {\n\t\t\tcontinue\n\t\t}\n\n\t\taurPkg := aurdata[up.Name]\n\t\tgraph = u.grapher.GraphAURTarget(ctx, graph, aurPkg, &dep.InstallInfo{\n\t\t\tReason:       reason,\n\t\t\tSource:       dep.AUR,\n\t\t\tAURBase:      &aurPkg.PackageBase,\n\t\t\tUpgrade:      true,\n\t\t\tVersion:      up.RemoteVersion,\n\t\t\tLocalVersion: up.LocalVersion,\n\t\t})\n\t\taurPkgsAdded = append(aurPkgsAdded, aurPkg)\n\t}\n\n\tu.grapher.AddDepsForPkgs(ctx, aurPkgsAdded, graph)\n\n\tif u.cfg.Mode.AtLeastRepo() {\n\t\tu.log.OperationInfoln(gotext.Get(\"Searching databases for updates...\"))\n\n\t\tsyncUpgrades, err := u.dbExecutor.SyncUpgrades(enableDowngrade)\n\t\tfor _, up := range syncUpgrades {\n\t\t\tif filter != nil && !filter(&db.Upgrade{\n\t\t\t\tName:          up.Package.Name(),\n\t\t\t\tRemoteVersion: up.Package.Version(),\n\t\t\t\tRepository:    up.Package.DB().Name(),\n\t\t\t\tBase:          up.Package.Base(),\n\t\t\t\tLocalVersion:  up.LocalVersion,\n\t\t\t\tReason:        up.Reason,\n\t\t\t}) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tupgradeInfo := up\n\t\t\tgraph = u.grapher.GraphSyncPkg(ctx, graph, up.Package, &upgradeInfo)\n\t\t}\n\n\t\terrs.Add(err)\n\t}\n\n\treturn errs.Return()\n}\n\nfunc (u *UpgradeService) graphToUpSlice(graph *topo.Graph[string, *dep.InstallInfo]) (aurUp, repoUp UpSlice) {\n\taurUp = UpSlice{Up: make([]Upgrade, 0, graph.Len())}\n\trepoUp = UpSlice{Up: make([]Upgrade, 0, graph.Len()), Repos: u.dbExecutor.Repos()}\n\n\t_ = graph.ForEach(func(name string, info *dep.InstallInfo) error {\n\t\talpmReason := alpm.PkgReasonDepend\n\t\tif info.Reason == dep.Explicit {\n\t\t\talpmReason = alpm.PkgReasonExplicit\n\t\t}\n\n\t\tparents := graph.ImmediateDependencies(name)\n\t\textra := \"\"\n\t\tif len(parents) > 0 && !info.Upgrade && info.Reason == dep.MakeDep {\n\t\t\treducedParents := parents.Slice()[:min(cutOffExtra, len(parents))]\n\t\t\tif len(parents) > cutOffExtra {\n\t\t\t\treducedParents = append(reducedParents, \"...\")\n\t\t\t}\n\t\t\textra = fmt.Sprintf(\" (%s of %s)\", dep.ReasonNames[info.Reason], strings.Join(reducedParents, \", \"))\n\t\t}\n\n\t\tswitch info.Source {\n\t\tcase dep.AUR:\n\t\t\taurRepo := \"aur\"\n\t\t\tif info.Devel {\n\t\t\t\taurRepo = \"devel\"\n\t\t\t}\n\t\t\taurUp.Up = append(aurUp.Up, Upgrade{\n\t\t\t\tName:          name,\n\t\t\t\tRemoteVersion: info.Version,\n\t\t\t\tRepository:    aurRepo,\n\t\t\t\tBase:          *info.AURBase,\n\t\t\t\tLocalVersion:  info.LocalVersion,\n\t\t\t\tReason:        alpmReason,\n\t\t\t\tExtra:         extra,\n\t\t\t})\n\t\tcase dep.Sync:\n\t\t\trepoUp.Up = append(repoUp.Up, Upgrade{\n\t\t\t\tName:          name,\n\t\t\t\tRemoteVersion: info.Version,\n\t\t\t\tRepository:    *info.SyncDBName,\n\t\t\t\tBase:          \"\",\n\t\t\t\tLocalVersion:  info.LocalVersion,\n\t\t\t\tReason:        alpmReason,\n\t\t\t\tExtra:         extra,\n\t\t\t})\n\t\t}\n\t\treturn nil\n\t})\n\n\treturn aurUp, repoUp\n}\n\nfunc (u *UpgradeService) GraphUpgrades(ctx context.Context,\n\tgraph *topo.Graph[string, *dep.InstallInfo],\n\tenableDowngrade bool, filter Filter,\n) (*topo.Graph[string, *dep.InstallInfo], error) {\n\tif graph == nil {\n\t\tgraph = dep.NewGraph()\n\t}\n\n\terr := u.upGraph(ctx, graph, enableDowngrade, filter)\n\tif err != nil {\n\t\treturn graph, err\n\t}\n\n\treturn graph, nil\n}\n\n// userExcludeUpgrades asks the user which packages to exclude from the upgrade and\n// removes them from the graph\nfunc (u *UpgradeService) UserExcludeUpgrades(graph *topo.Graph[string, *dep.InstallInfo]) ([]string, error) {\n\tif graph.Len() == 0 {\n\t\treturn []string{}, nil\n\t}\n\taurUp, repoUp := u.graphToUpSlice(graph)\n\n\tsort.Sort(repoUp)\n\tsort.Sort(aurUp)\n\n\tallUp := UpSlice{Repos: append(repoUp.Repos, aurUp.Repos...)}\n\tfor _, up := range repoUp.Up {\n\t\tif up.LocalVersion == \"\" && up.Reason != alpm.PkgReasonExplicit {\n\t\t\tallUp.PulledDeps = append(allUp.PulledDeps, up)\n\t\t} else {\n\t\t\tallUp.Up = append(allUp.Up, up)\n\t\t}\n\t}\n\n\tfor _, up := range aurUp.Up {\n\t\tif up.LocalVersion == \"\" && up.Reason != alpm.PkgReasonExplicit {\n\t\t\tallUp.PulledDeps = append(allUp.PulledDeps, up)\n\t\t} else {\n\t\t\tallUp.Up = append(allUp.Up, up)\n\t\t}\n\t}\n\n\tif len(allUp.PulledDeps) > 0 {\n\t\tu.log.Printf(\"%s\"+text.Bold(\" %d \")+\"%s\\n\", text.Bold(text.Cyan(\"::\")),\n\t\t\tlen(allUp.PulledDeps), text.Bold(gotext.Get(\"%s will also be installed for this operation.\",\n\t\t\t\tgotext.GetN(\"dependency\", \"dependencies\", len(allUp.PulledDeps)))))\n\t\tallUp.PrintDeps(u.log)\n\t}\n\n\tu.log.Printf(\"%s\"+text.Bold(\" %d \")+\"%s\\n\", text.Bold(text.Cyan(\"::\")),\n\t\tlen(allUp.Up), text.Bold(gotext.Get(\"%s to upgrade/install.\", gotext.GetN(\"package\", \"packages\", len(allUp.Up)))))\n\tallUp.Print(u.log)\n\n\tu.log.Infoln(gotext.Get(\"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"))\n\tu.log.Warnln(gotext.Get(\"Excluding packages may cause partial upgrades and break systems\"))\n\n\tnumbers, err := u.log.GetInput(u.cfg.AnswerUpgrade, settings.NoConfirm)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// upgrade menu asks you which packages to NOT upgrade so in this case\n\t// exclude and include are kind of swapped\n\texclude, include, otherExclude, otherInclude := intrange.ParseNumberMenu(numbers)\n\n\t// true if user doesn't want to include specific repositories/packages\n\tnoIncludes := len(include) == 0 && otherInclude.Cardinality() == 0\n\n\t// No exclusions or inclusions specified, return early\n\tif noIncludes && len(exclude) == 0 && otherExclude.Cardinality() == 0 {\n\t\treturn []string{}, nil\n\t}\n\n\texcluded := make([]string, 0)\n\tfor i := range allUp.Up {\n\t\tup := &allUp.Up[i]\n\t\tupgradeID := len(allUp.Up) - i\n\n\t\t// check if user wants to exclude specific things (true) or include specific things\n\t\tif noIncludes {\n\t\t\t// exclude repositories mentioned by the user\n\t\t\tif otherExclude.Contains(up.Repository) {\n\t\t\t\tu.log.Debugln(\"pruning\", up.Name)\n\t\t\t\texcluded = append(excluded, graph.Prune(up.Name)...)\n\t\t\t}\n\t\t\t// exclude packages mentioned by the user\n\t\t\tif exclude.Get(upgradeID) {\n\t\t\t\tu.log.Debugln(\"pruning\", up.Name)\n\t\t\t\texcluded = append(excluded, graph.Prune(up.Name)...)\n\t\t\t}\n\n\t\t\t// If the user explicitly wants to include a package/repository, exclude everything else\n\t\t} else if !include.Get(upgradeID) && !otherInclude.Contains(up.Repository) {\n\t\t\tu.log.Debugln(\"pruning\", up.Name)\n\t\t\texcluded = append(excluded, graph.Prune(up.Name)...)\n\t\t}\n\t}\n\n\treturn excluded, nil\n}\n"
  },
  {
    "path": "pkg/upgrade/service_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage upgrade\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"os\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/Jguer/aur\"\n\talpm \"github.com/Jguer/dyalpm\"\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/db/mock\"\n\t\"github.com/Jguer/yay/v12/pkg/dep\"\n\t\"github.com/Jguer/yay/v12/pkg/dep/topo\"\n\t\"github.com/Jguer/yay/v12/pkg/query\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\t\"github.com/Jguer/yay/v12/pkg/vcs\"\n\n\tmockaur \"github.com/Jguer/yay/v12/pkg/dep/mock\"\n)\n\nfunc ptrString(s string) *string {\n\treturn &s\n}\n\nfunc TestUpgradeService_GraphUpgrades(t *testing.T) {\n\tt.Parallel()\n\tlinuxDepInfo := &dep.InstallInfo{\n\t\tReason:       dep.Explicit,\n\t\tSource:       dep.Sync,\n\t\tAURBase:      nil,\n\t\tLocalVersion: \"4.5.0-1\",\n\t\tVersion:      \"5.0.0-1\",\n\t\tSyncDBName:   ptrString(\"core\"),\n\t\tUpgrade:      true,\n\t\tDevel:        false,\n\t}\n\n\texampleDepInfoDevel := &dep.InstallInfo{\n\t\tSource:       dep.AUR,\n\t\tReason:       dep.Dep,\n\t\tAURBase:      ptrString(\"example\"),\n\t\tLocalVersion: \"2.2.1.r32.41baa362-1\",\n\t\tVersion:      \"latest-commit\",\n\t\tUpgrade:      true,\n\t\tDevel:        true,\n\t}\n\n\tnewDepInfo := &dep.InstallInfo{\n\t\tSource:       dep.Sync,\n\t\tReason:       dep.Dep,\n\t\tSyncDBName:   ptrString(\"core\"),\n\t\tVersion:      \"3.0.1-2\",\n\t\tLocalVersion: \"\",\n\t\tUpgrade:      true,\n\t\tDevel:        false,\n\t}\n\n\texampleDepInfoAUR := &dep.InstallInfo{\n\t\tSource:       dep.AUR,\n\t\tReason:       dep.Dep,\n\t\tAURBase:      ptrString(\"example\"),\n\t\tLocalVersion: \"2.2.1.r32.41baa362-1\",\n\t\tVersion:      \"2.2.1.r69.g8a10460-1\",\n\t\tUpgrade:      true,\n\t\tDevel:        false,\n\t}\n\n\tyayDepInfo := &dep.InstallInfo{\n\t\tReason:       dep.Explicit,\n\t\tSource:       dep.AUR,\n\t\tAURBase:      ptrString(\"yay\"),\n\t\tLocalVersion: \"10.2.3\",\n\t\tVersion:      \"10.2.4\",\n\t\tUpgrade:      true,\n\t\tDevel:        false,\n\t}\n\n\tcoreDB := mock.NewDB(\"core\")\n\tdbExe := &mock.DBExecutor{\n\t\tInstalledRemotePackageNamesFn: func() []string {\n\t\t\treturn []string{\"yay\", \"example-git\"}\n\t\t},\n\t\tInstalledRemotePackagesFn: func() map[string]mock.IPackage {\n\t\t\tmapRemote := make(map[string]mock.IPackage)\n\t\t\tmapRemote[\"yay\"] = &mock.Package{\n\t\t\t\tPName:    \"yay\",\n\t\t\t\tPBase:    \"yay\",\n\t\t\t\tPVersion: \"10.2.3\",\n\t\t\t\tPReason:  alpm.PkgReasonExplicit,\n\t\t\t}\n\n\t\t\tmapRemote[\"example-git\"] = &mock.Package{\n\t\t\t\tPName:    \"example-git\",\n\t\t\t\tPBase:    \"example\",\n\t\t\t\tPVersion: \"2.2.1.r32.41baa362-1\",\n\t\t\t\tPReason:  alpm.PkgReasonDepend,\n\t\t\t}\n\n\t\t\treturn mapRemote\n\t\t},\n\t\tLocalSatisfierExistsFn: func(string) bool { return false },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\treturn &mock.Package{\n\t\t\t\tPName:    \"new-dep\",\n\t\t\t\tPVersion: \"3.0.1-2\",\n\t\t\t\tPDB:      coreDB,\n\t\t\t}\n\t\t},\n\t\tSyncUpgradesFn: func(bool) (map[string]db.SyncUpgrade, error) {\n\t\t\tmapUpgrades := make(map[string]db.SyncUpgrade)\n\n\t\t\tmapUpgrades[\"linux\"] = db.SyncUpgrade{\n\t\t\t\tPackage: &mock.Package{\n\t\t\t\t\tPName:    \"linux\",\n\t\t\t\t\tPVersion: \"5.0.0-1\",\n\t\t\t\t\tPReason:  alpm.PkgReasonDepend,\n\t\t\t\t\tPDB:      coreDB,\n\t\t\t\t\tPDepends: mock.DependList{Depends: []alpm.Depend{\n\t\t\t\t\t\t{Name: \"new-dep\", Version: \"3.0.1\"},\n\t\t\t\t\t}},\n\t\t\t\t},\n\t\t\t\tLocalVersion: \"4.5.0-1\",\n\t\t\t\tReason:       alpm.PkgReasonExplicit,\n\t\t\t}\n\n\t\t\tmapUpgrades[\"new-dep\"] = db.SyncUpgrade{\n\t\t\t\tPackage: &mock.Package{\n\t\t\t\t\tPName:    \"new-dep\",\n\t\t\t\t\tPVersion: \"3.0.1-2\",\n\t\t\t\t\tPReason:  alpm.PkgReasonDepend,\n\t\t\t\t\tPDB:      coreDB,\n\t\t\t\t},\n\t\t\t\tLocalVersion: \"\",\n\t\t\t\tReason:       alpm.PkgReasonDepend,\n\t\t\t}\n\n\t\t\treturn mapUpgrades, nil\n\t\t},\n\t\tReposFn: func() []string { return []string{\"core\"} },\n\t}\n\tvcsStore := &vcs.Mock{\n\t\tToUpgradeReturn: []string{\"example-git\"},\n\t}\n\n\tmockAUR := &mockaur.MockAUR{\n\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\treturn []aur.Pkg{\n\t\t\t\t{Name: \"yay\", Version: \"10.2.4\", PackageBase: \"yay\"},\n\t\t\t\t{\n\t\t\t\t\tName: \"example-git\", Version: \"2.2.1.r69.g8a10460-1\",\n\t\t\t\t\tPackageBase: \"example\", Depends: []string{\"new-dep\"},\n\t\t\t\t},\n\t\t\t}, nil\n\t\t},\n\t}\n\ttype fields struct {\n\t\tinput     io.Reader\n\t\toutput    io.Writer\n\t\tnoConfirm bool\n\t\tdevel     bool\n\t}\n\ttype args struct {\n\t\tgraph           *topo.Graph[string, *dep.InstallInfo]\n\t\tenableDowngrade bool\n\t}\n\ttests := []struct {\n\t\tname         string\n\t\tfields       fields\n\t\targs         args\n\t\tmustExist    map[string]*dep.InstallInfo\n\t\tmustNotExist map[string]bool\n\t\twantExclude  []string\n\t\twantErr      bool\n\t}{\n\t\t{\n\t\t\tname: \"no input\",\n\t\t\tfields: fields{\n\t\t\t\tinput:     strings.NewReader(\"\\n\"),\n\t\t\t\toutput:    io.Discard,\n\t\t\t\tnoConfirm: false,\n\t\t\t},\n\t\t\targs: args{\n\t\t\t\tgraph:           nil,\n\t\t\t\tenableDowngrade: false,\n\t\t\t},\n\t\t\tmustExist: map[string]*dep.InstallInfo{\n\t\t\t\t\"yay\":         yayDepInfo,\n\t\t\t\t\"linux\":       linuxDepInfo,\n\t\t\t\t\"example-git\": exampleDepInfoAUR,\n\t\t\t\t\"new-dep\":     newDepInfo,\n\t\t\t},\n\t\t\tmustNotExist: map[string]bool{},\n\t\t\twantErr:      false,\n\t\t\twantExclude:  []string{},\n\t\t},\n\t\t{\n\t\t\tname: \"no input devel\",\n\t\t\tfields: fields{\n\t\t\t\tinput:     strings.NewReader(\"\\n\"),\n\t\t\t\toutput:    io.Discard,\n\t\t\t\tnoConfirm: false,\n\t\t\t\tdevel:     true,\n\t\t\t},\n\t\t\targs: args{\n\t\t\t\tgraph:           nil,\n\t\t\t\tenableDowngrade: false,\n\t\t\t},\n\t\t\tmustExist: map[string]*dep.InstallInfo{\n\t\t\t\t\"yay\":         yayDepInfo,\n\t\t\t\t\"linux\":       linuxDepInfo,\n\t\t\t\t\"example-git\": exampleDepInfoDevel,\n\t\t\t},\n\t\t\tmustNotExist: map[string]bool{},\n\t\t\twantErr:      false,\n\t\t\twantExclude:  []string{},\n\t\t},\n\t\t{\n\t\t\tname: \"exclude example-git\",\n\t\t\tfields: fields{\n\t\t\t\tinput:     strings.NewReader(\"2\\n\"),\n\t\t\t\toutput:    io.Discard,\n\t\t\t\tnoConfirm: false,\n\t\t\t},\n\t\t\targs: args{\n\t\t\t\tgraph:           nil,\n\t\t\t\tenableDowngrade: false,\n\t\t\t},\n\t\t\tmustExist: map[string]*dep.InstallInfo{\n\t\t\t\t\"yay\":   yayDepInfo,\n\t\t\t\t\"linux\": linuxDepInfo,\n\t\t\t},\n\t\t\tmustNotExist: map[string]bool{\"example-git\": true, \"new-dep\": true},\n\t\t\twantErr:      false,\n\t\t\twantExclude:  []string{\"example-git\", \"new-dep\"},\n\t\t},\n\t\t{\n\t\t\tname: \"exclude new-dep should have no effect\",\n\t\t\tfields: fields{\n\t\t\t\tinput:     strings.NewReader(\"1 3 4\\n\"),\n\t\t\t\toutput:    io.Discard,\n\t\t\t\tnoConfirm: false,\n\t\t\t},\n\t\t\targs: args{\n\t\t\t\tgraph:           nil,\n\t\t\t\tenableDowngrade: false,\n\t\t\t},\n\t\t\tmustExist: map[string]*dep.InstallInfo{\n\t\t\t\t\"example-git\": exampleDepInfoAUR,\n\t\t\t\t\"new-dep\":     newDepInfo,\n\t\t\t},\n\t\t\tmustNotExist: map[string]bool{\"linux\": true, \"yay\": true},\n\t\t\twantErr:      false,\n\t\t\twantExclude:  []string{\"linux\", \"yay\"},\n\t\t},\n\t\t{\n\t\t\tname: \"exclude yay\",\n\t\t\tfields: fields{\n\t\t\t\tinput:     strings.NewReader(\"1\\n\"),\n\t\t\t\toutput:    io.Discard,\n\t\t\t\tnoConfirm: false,\n\t\t\t},\n\t\t\targs: args{\n\t\t\t\tgraph:           nil,\n\t\t\t\tenableDowngrade: false,\n\t\t\t},\n\t\t\tmustExist: map[string]*dep.InstallInfo{\n\t\t\t\t\"linux\":       linuxDepInfo,\n\t\t\t\t\"example-git\": exampleDepInfoAUR,\n\t\t\t},\n\t\t\tmustNotExist: map[string]bool{\"yay\": true},\n\t\t\twantErr:      false,\n\t\t\twantExclude:  []string{\"yay\"},\n\t\t},\n\t\t{\n\t\t\tname: \"exclude linux\",\n\t\t\tfields: fields{\n\t\t\t\tinput:     strings.NewReader(\"3\\n\"),\n\t\t\t\toutput:    io.Discard,\n\t\t\t\tnoConfirm: false,\n\t\t\t},\n\t\t\targs: args{\n\t\t\t\tgraph:           nil,\n\t\t\t\tenableDowngrade: false,\n\t\t\t},\n\t\t\tmustExist: map[string]*dep.InstallInfo{\n\t\t\t\t\"yay\":         yayDepInfo,\n\t\t\t\t\"example-git\": exampleDepInfoAUR,\n\t\t\t\t\"new-dep\":     newDepInfo,\n\t\t\t},\n\t\t\tmustNotExist: map[string]bool{\"linux\": true},\n\t\t\twantErr:      false,\n\t\t\twantExclude:  []string{\"linux\"},\n\t\t},\n\t\t{\n\t\t\tname: \"only linux\",\n\t\t\tfields: fields{\n\t\t\t\tinput:     strings.NewReader(\"^3\\n\"),\n\t\t\t\toutput:    io.Discard,\n\t\t\t\tnoConfirm: false,\n\t\t\t},\n\t\t\targs: args{\n\t\t\t\tgraph:           nil,\n\t\t\t\tenableDowngrade: false,\n\t\t\t},\n\t\t\tmustExist: map[string]*dep.InstallInfo{\n\t\t\t\t\"linux\": linuxDepInfo,\n\t\t\t},\n\t\t\tmustNotExist: map[string]bool{\"yay\": true, \"example-git\": true},\n\t\t\twantErr:      false,\n\t\t\twantExclude:  []string{\"yay\", \"example-git\", \"new-dep\"},\n\t\t},\n\t\t{\n\t\t\tname: \"exclude all\",\n\t\t\tfields: fields{\n\t\t\t\tinput:     strings.NewReader(\"1-4\\n\"),\n\t\t\t\toutput:    io.Discard,\n\t\t\t\tnoConfirm: false,\n\t\t\t},\n\t\t\targs: args{\n\t\t\t\tgraph:           nil,\n\t\t\t\tenableDowngrade: false,\n\t\t\t},\n\t\t\tmustExist:    map[string]*dep.InstallInfo{},\n\t\t\tmustNotExist: map[string]bool{\"yay\": true, \"example-git\": true, \"linux\": true},\n\t\t\twantErr:      false,\n\t\t\twantExclude:  []string{\"yay\", \"example-git\", \"linux\", \"new-dep\"},\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tgrapher := dep.NewGrapher(dbExe, mockAUR,\n\t\t\t\tfalse, true, false, false, false, text.NewLogger(tt.fields.output, os.Stderr,\n\t\t\t\t\ttt.fields.input, true, \"test\"))\n\n\t\t\tcfg := &settings.Configuration{\n\t\t\t\tDevel: tt.fields.devel, Mode: parser.ModeAny,\n\t\t\t}\n\n\t\t\tlogger := text.NewLogger(tt.fields.output, os.Stderr,\n\t\t\t\ttt.fields.input, true, \"test\")\n\t\t\tu := &UpgradeService{\n\t\t\t\tlog:         logger,\n\t\t\t\tgrapher:     grapher,\n\t\t\t\taurCache:    mockAUR,\n\t\t\t\tdbExecutor:  dbExe,\n\t\t\t\tvcsStore:    vcsStore,\n\t\t\t\tcfg:         cfg,\n\t\t\t\tnoConfirm:   tt.fields.noConfirm,\n\t\t\t\tAURWarnings: query.NewWarnings(logger),\n\t\t\t}\n\n\t\t\tgot, err := u.GraphUpgrades(context.Background(), tt.args.graph, tt.args.enableDowngrade, func(*Upgrade) bool { return true })\n\t\t\tif (err != nil) != tt.wantErr {\n\t\t\t\tt.Errorf(\"UpgradeService.GraphUpgrades() error = %v, wantErr %v\", err, tt.wantErr)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\texcluded, err := u.UserExcludeUpgrades(got)\n\t\t\trequire.NoError(t, err)\n\n\t\t\tfor node, info := range tt.mustExist {\n\t\t\t\tassert.True(t, got.Exists(node), node)\n\t\t\t\tassert.Equal(t, info, got.GetNodeInfo(node).Value)\n\t\t\t}\n\n\t\t\tfor node := range tt.mustNotExist {\n\t\t\t\tassert.False(t, got.Exists(node), node)\n\t\t\t}\n\n\t\t\tassert.ElementsMatch(t, tt.wantExclude, excluded)\n\t\t})\n\t}\n}\n\nfunc TestUpgradeService_GraphUpgradesMissingDep(t *testing.T) {\n\tt.Parallel()\n\tnewDepMissingInfo := &dep.InstallInfo{\n\t\tSource:  dep.Missing,\n\t\tReason:  dep.Dep,\n\t\tVersion: \"\",\n\t}\n\n\texampleDepInfoAUR := &dep.InstallInfo{\n\t\tSource:       dep.AUR,\n\t\tReason:       dep.Dep,\n\t\tAURBase:      ptrString(\"example\"),\n\t\tLocalVersion: \"2.2.1.r32.41baa362-1\",\n\t\tVersion:      \"2.2.1.r69.g8a10460-1\",\n\t\tUpgrade:      true,\n\t\tDevel:        false,\n\t}\n\n\tyayDepInfo := &dep.InstallInfo{\n\t\tReason:       dep.Explicit,\n\t\tSource:       dep.AUR,\n\t\tAURBase:      ptrString(\"yay\"),\n\t\tLocalVersion: \"10.2.3\",\n\t\tVersion:      \"10.2.4\",\n\t\tUpgrade:      true,\n\t\tDevel:        false,\n\t}\n\n\tdbExe := &mock.DBExecutor{\n\t\tInstalledRemotePackageNamesFn: func() []string {\n\t\t\treturn []string{\"yay\", \"example-git\"}\n\t\t},\n\t\tInstalledRemotePackagesFn: func() map[string]mock.IPackage {\n\t\t\tmapRemote := make(map[string]mock.IPackage)\n\t\t\tmapRemote[\"yay\"] = &mock.Package{\n\t\t\t\tPName:    \"yay\",\n\t\t\t\tPBase:    \"yay\",\n\t\t\t\tPVersion: \"10.2.3\",\n\t\t\t\tPReason:  alpm.PkgReasonExplicit,\n\t\t\t}\n\n\t\t\tmapRemote[\"example-git\"] = &mock.Package{\n\t\t\t\tPName:    \"example-git\",\n\t\t\t\tPBase:    \"example\",\n\t\t\t\tPVersion: \"2.2.1.r32.41baa362-1\",\n\t\t\t\tPReason:  alpm.PkgReasonDepend,\n\t\t\t}\n\n\t\t\treturn mapRemote\n\t\t},\n\t\tLocalSatisfierExistsFn: func(string) bool { return false },\n\t\tSyncSatisfierFn:        func(s string) mock.IPackage { return nil },\n\t\tSyncUpgradesFn: func(bool) (map[string]db.SyncUpgrade, error) {\n\t\t\treturn map[string]db.SyncUpgrade{}, nil\n\t\t},\n\t\tReposFn: func() []string { return nil },\n\t}\n\tvcsStore := &vcs.Mock{\n\t\tToUpgradeReturn: []string{\"example-git\"},\n\t}\n\n\tmockAUR := &mockaur.MockAUR{\n\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\treturn []aur.Pkg{\n\t\t\t\t{\n\t\t\t\t\tName:        \"yay\",\n\t\t\t\t\tVersion:     \"10.2.4\",\n\t\t\t\t\tPackageBase: \"yay\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tName:        \"example-git\",\n\t\t\t\t\tVersion:     \"2.2.1.r69.g8a10460-1\",\n\t\t\t\t\tPackageBase: \"example\",\n\t\t\t\t\tDepends:     []string{\"new-dep-missing\"},\n\t\t\t\t},\n\t\t\t}, nil\n\t\t},\n\t}\n\ttype fields struct {\n\t\tinput     io.Reader\n\t\toutput    io.Writer\n\t\tnoConfirm bool\n\t\tdevel     bool\n\t}\n\ttype args struct {\n\t\tgraph           *topo.Graph[string, *dep.InstallInfo]\n\t\tenableDowngrade bool\n\t}\n\ttests := []struct {\n\t\tname         string\n\t\tfields       fields\n\t\targs         args\n\t\tmustExist    map[string]*dep.InstallInfo\n\t\tmustNotExist map[string]bool\n\t\twantExclude  []string\n\t\twantErr      bool\n\t}{\n\t\t{\n\t\t\tname: \"no input\",\n\t\t\tfields: fields{\n\t\t\t\tinput:     strings.NewReader(\"\\n\"),\n\t\t\t\toutput:    io.Discard,\n\t\t\t\tnoConfirm: false,\n\t\t\t},\n\t\t\targs: args{\n\t\t\t\tgraph:           nil,\n\t\t\t\tenableDowngrade: false,\n\t\t\t},\n\t\t\tmustExist: map[string]*dep.InstallInfo{\n\t\t\t\t\"yay\":             yayDepInfo,\n\t\t\t\t\"example-git\":     exampleDepInfoAUR,\n\t\t\t\t\"new-dep-missing\": newDepMissingInfo,\n\t\t\t},\n\t\t\tmustNotExist: map[string]bool{},\n\t\t\twantErr:      false,\n\t\t\twantExclude:  []string{},\n\t\t},\n\t\t{\n\t\t\tname: \"exclude example-git(with missing dep)\",\n\t\t\tfields: fields{\n\t\t\t\tinput:     strings.NewReader(\"2\\n\"),\n\t\t\t\toutput:    io.Discard,\n\t\t\t\tnoConfirm: false,\n\t\t\t},\n\t\t\targs: args{\n\t\t\t\tgraph:           nil,\n\t\t\t\tenableDowngrade: false,\n\t\t\t},\n\t\t\tmustExist: map[string]*dep.InstallInfo{\n\t\t\t\t\"yay\": yayDepInfo,\n\t\t\t},\n\t\t\tmustNotExist: map[string]bool{\"example-git\": true, \"new-dep-missing\": true},\n\t\t\twantErr:      false,\n\t\t\twantExclude:  []string{\"example-git\", \"new-dep-missing\"},\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tgrapher := dep.NewGrapher(dbExe, mockAUR,\n\t\t\t\tfalse, true, false, false, false, text.NewLogger(tt.fields.output, os.Stderr,\n\t\t\t\t\ttt.fields.input, true, \"test\"))\n\n\t\t\tcfg := &settings.Configuration{\n\t\t\t\tDevel: tt.fields.devel, Mode: parser.ModeAny,\n\t\t\t}\n\n\t\t\tlogger := text.NewLogger(tt.fields.output, os.Stderr,\n\t\t\t\ttt.fields.input, true, \"test\")\n\t\t\tu := &UpgradeService{\n\t\t\t\tlog:         logger,\n\t\t\t\tgrapher:     grapher,\n\t\t\t\taurCache:    mockAUR,\n\t\t\t\tdbExecutor:  dbExe,\n\t\t\t\tvcsStore:    vcsStore,\n\t\t\t\tcfg:         cfg,\n\t\t\t\tnoConfirm:   tt.fields.noConfirm,\n\t\t\t\tAURWarnings: query.NewWarnings(logger),\n\t\t\t}\n\n\t\t\tgot, err := u.GraphUpgrades(context.Background(), tt.args.graph, tt.args.enableDowngrade, func(*Upgrade) bool { return true })\n\t\t\tif (err != nil) != tt.wantErr {\n\t\t\t\tt.Errorf(\"UpgradeService.GraphUpgrades() error = %v, wantErr %v\", err, tt.wantErr)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\texcluded, err := u.UserExcludeUpgrades(got)\n\t\t\trequire.NoError(t, err)\n\n\t\t\tfor node, info := range tt.mustExist {\n\t\t\t\tassert.True(t, got.Exists(node), node)\n\t\t\t\tassert.Equal(t, info, got.GetNodeInfo(node).Value)\n\t\t\t}\n\n\t\t\tfor node := range tt.mustNotExist {\n\t\t\t\tassert.False(t, got.Exists(node), node)\n\t\t\t}\n\n\t\t\tassert.ElementsMatch(t, tt.wantExclude, excluded)\n\t\t})\n\t}\n}\n\nfunc TestUpgradeService_GraphUpgradesNoUpdates(t *testing.T) {\n\tt.Parallel()\n\tdbExe := &mock.DBExecutor{\n\t\tInstalledRemotePackageNamesFn: func() []string {\n\t\t\treturn []string{\"yay\", \"example-git\"}\n\t\t},\n\t\tInstalledRemotePackagesFn: func() map[string]mock.IPackage {\n\t\t\tmapRemote := make(map[string]mock.IPackage)\n\t\t\tmapRemote[\"yay\"] = &mock.Package{\n\t\t\t\tPName:    \"yay\",\n\t\t\t\tPBase:    \"yay\",\n\t\t\t\tPVersion: \"10.2.3\",\n\t\t\t\tPReason:  alpm.PkgReasonExplicit,\n\t\t\t}\n\n\t\t\tmapRemote[\"example-git\"] = &mock.Package{\n\t\t\t\tPName:    \"example-git\",\n\t\t\t\tPBase:    \"example\",\n\t\t\t\tPVersion: \"2.2.1.r32.41baa362-1\",\n\t\t\t\tPReason:  alpm.PkgReasonDepend,\n\t\t\t}\n\n\t\t\treturn mapRemote\n\t\t},\n\t\tSyncUpgradesFn: func(bool) (map[string]db.SyncUpgrade, error) {\n\t\t\tmapUpgrades := make(map[string]db.SyncUpgrade)\n\t\t\treturn mapUpgrades, nil\n\t\t},\n\t\tReposFn: func() []string { return []string{\"core\"} },\n\t}\n\tvcsStore := &vcs.Mock{\n\t\tToUpgradeReturn: []string{},\n\t}\n\n\tmockAUR := &mockaur.MockAUR{\n\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\treturn []aur.Pkg{}, nil\n\t\t},\n\t}\n\ttype fields struct {\n\t\tinput     io.Reader\n\t\toutput    io.Writer\n\t\tnoConfirm bool\n\t\tdevel     bool\n\t}\n\ttype args struct {\n\t\tgraph           *topo.Graph[string, *dep.InstallInfo]\n\t\tenableDowngrade bool\n\t}\n\ttests := []struct {\n\t\tname         string\n\t\tfields       fields\n\t\targs         args\n\t\tmustExist    map[string]*dep.InstallInfo\n\t\tmustNotExist map[string]bool\n\t\twantExclude  []string\n\t\twantErr      bool\n\t}{\n\t\t{\n\t\t\tname: \"no input\",\n\t\t\tfields: fields{\n\t\t\t\tinput:     strings.NewReader(\"\"),\n\t\t\t\toutput:    io.Discard,\n\t\t\t\tnoConfirm: false,\n\t\t\t},\n\t\t\targs: args{\n\t\t\t\tgraph:           nil,\n\t\t\t\tenableDowngrade: false,\n\t\t\t},\n\t\t\tmustExist:    map[string]*dep.InstallInfo{},\n\t\t\tmustNotExist: map[string]bool{},\n\t\t\twantErr:      false,\n\t\t\twantExclude:  []string{},\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tgrapher := dep.NewGrapher(dbExe, mockAUR,\n\t\t\t\tfalse, true, false, false, false, text.NewLogger(tt.fields.output, os.Stderr,\n\t\t\t\t\ttt.fields.input, true, \"test\"))\n\n\t\t\tcfg := &settings.Configuration{\n\t\t\t\tDevel: tt.fields.devel,\n\t\t\t\tMode:  parser.ModeAny,\n\t\t\t}\n\n\t\t\tlogger := text.NewLogger(tt.fields.output, os.Stderr,\n\t\t\t\ttt.fields.input, true, \"test\")\n\t\t\tu := &UpgradeService{\n\t\t\t\tlog:         logger,\n\t\t\t\tgrapher:     grapher,\n\t\t\t\taurCache:    mockAUR,\n\t\t\t\tdbExecutor:  dbExe,\n\t\t\t\tvcsStore:    vcsStore,\n\t\t\t\tcfg:         cfg,\n\t\t\t\tnoConfirm:   tt.fields.noConfirm,\n\t\t\t\tAURWarnings: query.NewWarnings(logger),\n\t\t\t}\n\n\t\t\tgot, err := u.GraphUpgrades(context.Background(), tt.args.graph, tt.args.enableDowngrade, func(*Upgrade) bool { return true })\n\t\t\tif (err != nil) != tt.wantErr {\n\t\t\t\tt.Errorf(\"UpgradeService.GraphUpgrades() error = %v, wantErr %v\", err, tt.wantErr)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\texcluded, err := u.UserExcludeUpgrades(got)\n\t\t\trequire.NoError(t, err)\n\n\t\t\tfor node, info := range tt.mustExist {\n\t\t\t\tassert.True(t, got.Exists(node), node)\n\t\t\t\tassert.Equal(t, info, got.GetNodeInfo(node).Value)\n\t\t\t}\n\n\t\t\tfor node := range tt.mustNotExist {\n\t\t\t\tassert.False(t, got.Exists(node), node)\n\t\t\t}\n\n\t\t\tassert.ElementsMatch(t, tt.wantExclude, excluded)\n\t\t})\n\t}\n}\n\nfunc TestUpgradeService_Warnings(t *testing.T) {\n\tt.Parallel()\n\tdbExe := &mock.DBExecutor{\n\t\tInstalledRemotePackageNamesFn: func() []string {\n\t\t\treturn []string{\"orphan\", \"outdated\", \"missing\", \"orphan-ignored\"}\n\t\t},\n\t\tInstalledRemotePackagesFn: func() map[string]mock.IPackage {\n\t\t\tmapRemote := make(map[string]mock.IPackage)\n\t\t\tmapRemote[\"orphan\"] = &mock.Package{\n\t\t\t\tPName:    \"orphan\",\n\t\t\t\tPBase:    \"orphan\",\n\t\t\t\tPVersion: \"10.2.3\",\n\t\t\t\tPReason:  alpm.PkgReasonExplicit,\n\t\t\t}\n\n\t\t\tmapRemote[\"outdated\"] = &mock.Package{\n\t\t\t\tPName:    \"outdated\",\n\t\t\t\tPBase:    \"outdated\",\n\t\t\t\tPVersion: \"10.2.3\",\n\t\t\t\tPReason:  alpm.PkgReasonExplicit,\n\t\t\t}\n\n\t\t\tmapRemote[\"missing\"] = &mock.Package{\n\t\t\t\tPName:    \"missing\",\n\t\t\t\tPBase:    \"missing\",\n\t\t\t\tPVersion: \"10.2.3\",\n\t\t\t\tPReason:  alpm.PkgReasonExplicit,\n\t\t\t}\n\n\t\t\tmapRemote[\"orphan-ignored\"] = &mock.Package{\n\t\t\t\tPName:         \"orphan-ignored\",\n\t\t\t\tPBase:         \"orphan-ignored\",\n\t\t\t\tPVersion:      \"10.2.3\",\n\t\t\t\tPReason:       alpm.PkgReasonExplicit,\n\t\t\t\tPShouldIgnore: true,\n\t\t\t}\n\n\t\t\treturn mapRemote\n\t\t},\n\t\tLocalSatisfierExistsFn: func(string) bool { return false },\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\treturn nil\n\t\t},\n\t\tSyncUpgradesFn: func(bool) (map[string]db.SyncUpgrade, error) {\n\t\t\tmapUpgrades := make(map[string]db.SyncUpgrade)\n\t\t\treturn mapUpgrades, nil\n\t\t},\n\t\tReposFn: func() []string { return []string{\"core\"} },\n\t}\n\tvcsStore := &vcs.Mock{\n\t\tToUpgradeReturn: []string{},\n\t}\n\n\tmockAUR := &mockaur.MockAUR{\n\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\treturn []aur.Pkg{\n\t\t\t\t{\n\t\t\t\t\tName: \"outdated\", Version: \"10.2.4\", PackageBase: \"orphan\",\n\t\t\t\t\tOutOfDate: 100, Maintainer: \"bob\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tName: \"orphan\", Version: \"10.2.4\", PackageBase: \"orphan\",\n\t\t\t\t\tMaintainer: \"\",\n\t\t\t\t},\n\t\t\t}, nil\n\t\t},\n\t}\n\n\tlogger := text.NewLogger(io.Discard, os.Stderr,\n\t\tstrings.NewReader(\"\\n\"), true, \"test\")\n\tgrapher := dep.NewGrapher(dbExe, mockAUR,\n\t\tfalse, true, false, false, false, logger)\n\n\tcfg := &settings.Configuration{\n\t\tDevel: false, Mode: parser.ModeAUR,\n\t}\n\n\tu := &UpgradeService{\n\t\tlog:         logger,\n\t\tgrapher:     grapher,\n\t\taurCache:    mockAUR,\n\t\tdbExecutor:  dbExe,\n\t\tvcsStore:    vcsStore,\n\t\tcfg:         cfg,\n\t\tnoConfirm:   true,\n\t\tAURWarnings: query.NewWarnings(logger),\n\t}\n\n\t_, err := u.GraphUpgrades(context.Background(), nil, false, func(*Upgrade) bool { return true })\n\trequire.NoError(t, err)\n\n\tassert.Equal(t, []string{\"missing\"}, u.AURWarnings.Missing)\n\tassert.Equal(t, []string{\"outdated\"}, u.AURWarnings.OutOfDate)\n\tassert.Equal(t, []string{\"orphan\"}, u.AURWarnings.Orphans)\n}\n\nfunc TestUpgradeService_GraphUpgrades_zfs_dkms(t *testing.T) {\n\tt.Parallel()\n\tzfsDKMSInfo := &dep.InstallInfo{\n\t\tReason:       dep.Explicit,\n\t\tSource:       dep.AUR,\n\t\tAURBase:      ptrString(\"zfs-dkms\"),\n\t\tLocalVersion: \"2.1.10-1\",\n\t\tVersion:      \"2.1.11-1\",\n\t\tUpgrade:      true,\n\t\tDevel:        false,\n\t}\n\n\tzfsUtilsInfo := &dep.InstallInfo{\n\t\tReason:       dep.Dep,\n\t\tSource:       dep.AUR,\n\t\tAURBase:      ptrString(\"zfs-utils\"),\n\t\tLocalVersion: \"2.1.10-1\",\n\t\tVersion:      \"2.1.11-1\",\n\t\tUpgrade:      true,\n\t\tDevel:        false,\n\t}\n\n\tvcsStore := &vcs.Mock{ToUpgradeReturn: []string{}}\n\n\tmockAUR := &mockaur.MockAUR{\n\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\tif len(query.Needles) == 2 {\n\t\t\t\treturn []aur.Pkg{\n\t\t\t\t\t{\n\t\t\t\t\t\tName: \"zfs-dkms\", Version: \"2.1.11-1\",\n\t\t\t\t\t\tPackageBase: \"zfs-dkms\", Depends: []string{\"zfs-utils=2.1.11\"},\n\t\t\t\t\t},\n\t\t\t\t\t{Name: \"zfs-utils\", Version: \"2.1.11-1\", PackageBase: \"zfs-utils\"},\n\t\t\t\t}, nil\n\t\t\t}\n\t\t\tif len(query.Needles) == 1 {\n\t\t\t\treturn []aur.Pkg{\n\t\t\t\t\t{Name: \"zfs-utils\", Version: \"2.1.11-1\", PackageBase: \"zfs-utils\"},\n\t\t\t\t}, nil\n\t\t\t}\n\t\t\tpanic(\"not implemented\")\n\t\t},\n\t}\n\ttype fields struct {\n\t\tinput     io.Reader\n\t\tnoConfirm bool\n\t\tdevel     bool\n\t}\n\ttype args struct {\n\t\tgraph           *topo.Graph[string, *dep.InstallInfo]\n\t\tenableDowngrade bool\n\t}\n\ttests := []struct {\n\t\tname           string\n\t\tfields         fields\n\t\targs           args\n\t\tmustExist      map[string]*dep.InstallInfo\n\t\tmustNotExist   map[string]bool\n\t\twantExclude    []string\n\t\twantErr        bool\n\t\tremotePackages []string\n\t}{\n\t\t{\n\t\t\tname: \"no input\",\n\t\t\tfields: fields{\n\t\t\t\tinput:     strings.NewReader(\"\\n\"),\n\t\t\t\tnoConfirm: false,\n\t\t\t},\n\t\t\targs: args{\n\t\t\t\tgraph:           nil,\n\t\t\t\tenableDowngrade: false,\n\t\t\t},\n\t\t\tmustExist: map[string]*dep.InstallInfo{\n\t\t\t\t\"zfs-dkms\":  zfsDKMSInfo,\n\t\t\t\t\"zfs-utils\": zfsUtilsInfo,\n\t\t\t},\n\t\t\tremotePackages: []string{\"zfs-utils\", \"zfs-dkms\"},\n\t\t\tmustNotExist:   map[string]bool{},\n\t\t\twantErr:        false,\n\t\t\twantExclude:    []string{},\n\t\t},\n\t\t{\n\t\t\tname: \"no input - inverted order\",\n\t\t\tfields: fields{\n\t\t\t\tinput:     strings.NewReader(\"\\n\"),\n\t\t\t\tnoConfirm: false,\n\t\t\t},\n\t\t\targs: args{\n\t\t\t\tgraph:           nil,\n\t\t\t\tenableDowngrade: false,\n\t\t\t},\n\t\t\tmustExist: map[string]*dep.InstallInfo{\n\t\t\t\t\"zfs-dkms\":  zfsDKMSInfo,\n\t\t\t\t\"zfs-utils\": zfsUtilsInfo,\n\t\t\t},\n\t\t\tremotePackages: []string{\"zfs-dkms\", \"zfs-utils\"},\n\t\t\tmustNotExist:   map[string]bool{},\n\t\t\twantErr:        false,\n\t\t\twantExclude:    []string{},\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tdbExe := &mock.DBExecutor{\n\t\t\t\tInstalledRemotePackageNamesFn: func() []string {\n\t\t\t\t\treturn tt.remotePackages\n\t\t\t\t},\n\t\t\t\tInstalledRemotePackagesFn: func() map[string]mock.IPackage {\n\t\t\t\t\tmapRemote := make(map[string]mock.IPackage)\n\t\t\t\t\tmapRemote[\"zfs-dkms\"] = &mock.Package{\n\t\t\t\t\t\tPName:    \"zfs-dkms\",\n\t\t\t\t\t\tPBase:    \"zfs-dkms\",\n\t\t\t\t\t\tPVersion: \"2.1.10-1\",\n\t\t\t\t\t\tPReason:  alpm.PkgReasonExplicit,\n\t\t\t\t\t\tPDepends: mock.DependList{Depends: []alpm.Depend{\n\t\t\t\t\t\t\t{Name: \"zfs-utils\", Version: \"2.1.10-1\"},\n\t\t\t\t\t\t}},\n\t\t\t\t\t}\n\n\t\t\t\t\tmapRemote[\"zfs-utils\"] = &mock.Package{\n\t\t\t\t\t\tPName:    \"zfs-utils\",\n\t\t\t\t\t\tPBase:    \"zfs-utils\",\n\t\t\t\t\t\tPVersion: \"2.1.10-1\",\n\t\t\t\t\t\tPReason:  alpm.PkgReasonDepend,\n\t\t\t\t\t}\n\n\t\t\t\t\treturn mapRemote\n\t\t\t\t},\n\t\t\t\tLocalSatisfierExistsFn: func(string) bool { return false },\n\t\t\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\t\t\treturn nil\n\t\t\t\t},\n\t\t\t\tSyncUpgradesFn: func(bool) (map[string]db.SyncUpgrade, error) {\n\t\t\t\t\tmapUpgrades := make(map[string]db.SyncUpgrade)\n\t\t\t\t\treturn mapUpgrades, nil\n\t\t\t\t},\n\t\t\t\tReposFn: func() []string { return []string{\"core\"} },\n\t\t\t}\n\n\t\t\tlogger := text.NewLogger(io.Discard, os.Stderr,\n\t\t\t\ttt.fields.input, true, \"test\")\n\t\t\tgrapher := dep.NewGrapher(dbExe, mockAUR,\n\t\t\t\tfalse, true, false, false, false, logger)\n\n\t\t\tcfg := &settings.Configuration{\n\t\t\t\tDevel: tt.fields.devel, Mode: parser.ModeAny,\n\t\t\t}\n\n\t\t\tu := &UpgradeService{\n\t\t\t\tlog:         logger,\n\t\t\t\tgrapher:     grapher,\n\t\t\t\taurCache:    mockAUR,\n\t\t\t\tdbExecutor:  dbExe,\n\t\t\t\tvcsStore:    vcsStore,\n\t\t\t\tcfg:         cfg,\n\t\t\t\tnoConfirm:   tt.fields.noConfirm,\n\t\t\t\tAURWarnings: query.NewWarnings(logger),\n\t\t\t}\n\n\t\t\tgot, err := u.GraphUpgrades(context.Background(), tt.args.graph, tt.args.enableDowngrade, func(*Upgrade) bool { return true })\n\t\t\tif (err != nil) != tt.wantErr {\n\t\t\t\tt.Errorf(\"UpgradeService.GraphUpgrades() error = %v, wantErr %v\", err, tt.wantErr)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\texcluded, err := u.UserExcludeUpgrades(got)\n\t\t\trequire.NoError(t, err)\n\n\t\t\tfor node, info := range tt.mustExist {\n\t\t\t\tassert.True(t, got.Exists(node), node)\n\t\t\t\tassert.Equal(t, info, got.GetNodeInfo(node).Value)\n\t\t\t}\n\n\t\t\tfor node := range tt.mustNotExist {\n\t\t\t\tassert.False(t, got.Exists(node), node)\n\t\t\t}\n\n\t\t\tassert.ElementsMatch(t, tt.wantExclude, excluded)\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/upgrade/sources.go",
    "content": "package upgrade\n\nimport (\n\t\"context\"\n\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/query\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\t\"github.com/Jguer/yay/v12/pkg/vcs\"\n)\n\nfunc UpDevel(\n\tctx context.Context,\n\tlog *text.Logger,\n\tremote map[string]db.IPackage,\n\taurdata map[string]*query.Pkg,\n\tlocalCache vcs.Store,\n) UpSlice {\n\ttoRemove := make([]string, 0)\n\ttoUpgrade := UpSlice{Up: make([]Upgrade, 0), Repos: []string{\"devel\"}}\n\n\tfor pkgName, pkg := range remote {\n\t\tif localCache.ToUpgrade(ctx, pkgName) {\n\t\t\tif _, ok := aurdata[pkgName]; !ok {\n\t\t\t\tlog.Warnln(gotext.Get(\"ignoring package devel upgrade (no AUR info found):\"), pkgName)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif pkg.ShouldIgnore() {\n\t\t\t\tprintIgnoringPackage(log, pkg, \"latest-commit\")\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\ttoUpgrade.Up = append(toUpgrade.Up,\n\t\t\t\tUpgrade{\n\t\t\t\t\tName:          pkg.Name(),\n\t\t\t\t\tBase:          pkg.Base(),\n\t\t\t\t\tRepository:    \"devel\",\n\t\t\t\t\tLocalVersion:  pkg.Version(),\n\t\t\t\t\tRemoteVersion: \"latest-commit\",\n\t\t\t\t\tReason:        pkg.Reason(),\n\t\t\t\t})\n\t\t}\n\t}\n\n\tlocalCache.RemovePackages(toRemove)\n\n\treturn toUpgrade\n}\n\nfunc printIgnoringPackage(log *text.Logger, pkg db.IPackage, newPkgVersion string) {\n\tleft, right := query.GetVersionDiff(pkg.Version(), newPkgVersion)\n\n\tpkgName := pkg.Name()\n\tlog.Warnln(gotext.Get(\"%s: ignoring package upgrade (%s => %s)\",\n\t\ttext.Cyan(pkgName),\n\t\tleft, right,\n\t))\n}\n\n// UpAUR gathers foreign packages and checks if they have new versions.\n// Output: Upgrade type package list.\nfunc UpAUR(log *text.Logger, remote map[string]db.IPackage, aurdata map[string]*query.Pkg,\n\tenableDowngrade bool,\n) UpSlice {\n\ttoUpgrade := UpSlice{Up: make([]Upgrade, 0), Repos: []string{\"aur\"}}\n\n\tfor name, pkg := range remote {\n\t\taurPkg, ok := aurdata[name]\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\n\t\tif (db.VerCmp(pkg.Version(), aurPkg.Version) < 0) ||\n\t\t\t(enableDowngrade && (db.VerCmp(pkg.Version(), aurPkg.Version) > 0)) {\n\t\t\tif pkg.ShouldIgnore() {\n\t\t\t\tprintIgnoringPackage(log, pkg, aurPkg.Version)\n\t\t\t} else {\n\t\t\t\ttoUpgrade.Up = append(toUpgrade.Up,\n\t\t\t\t\tUpgrade{\n\t\t\t\t\t\tName:          aurPkg.Name,\n\t\t\t\t\t\tBase:          aurPkg.PackageBase,\n\t\t\t\t\t\tRepository:    \"aur\",\n\t\t\t\t\t\tLocalVersion:  pkg.Version(),\n\t\t\t\t\t\tRemoteVersion: aurPkg.Version,\n\t\t\t\t\t\tReason:        pkg.Reason(),\n\t\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\treturn toUpgrade\n}\n"
  },
  {
    "path": "pkg/upgrade/sources_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage upgrade\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"os\"\n\t\"strings\"\n\t\"testing\"\n\n\taur \"github.com/Jguer/aur\"\n\t\"github.com/stretchr/testify/assert\"\n\n\talpm \"github.com/Jguer/dyalpm\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db/mock\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\t\"github.com/Jguer/yay/v12/pkg/vcs\"\n)\n\nfunc Test_upAUR(t *testing.T) {\n\tt.Parallel()\n\n\ttype args struct {\n\t\tremote          map[string]alpm.Package\n\t\taurdata         map[string]*aur.Pkg\n\t\tenableDowngrade bool\n\t}\n\ttests := []struct {\n\t\tname string\n\t\targs args\n\t\twant UpSlice\n\t}{\n\t\t{\n\t\t\tname: \"No Updates\",\n\t\t\targs: args{\n\t\t\t\tremote: map[string]alpm.Package{\n\t\t\t\t\t\"hello\":     &mock.Package{PName: \"hello\", PVersion: \"2.0.0\"},\n\t\t\t\t\t\"local_pkg\": &mock.Package{PName: \"local_pkg\", PVersion: \"1.1.0\"},\n\t\t\t\t\t\"ignored\":   &mock.Package{PName: \"ignored\", PVersion: \"1.0.0\", PShouldIgnore: true},\n\t\t\t\t},\n\t\t\t\taurdata: map[string]*aur.Pkg{\n\t\t\t\t\t\"hello\":   {Version: \"2.0.0\", Name: \"hello\"},\n\t\t\t\t\t\"ignored\": {Version: \"2.0.0\", Name: \"ignored\"},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: UpSlice{Repos: []string{\"aur\"}, Up: []Upgrade{}},\n\t\t},\n\t\t{\n\t\t\tname: \"Simple Update\",\n\t\t\targs: args{\n\t\t\t\tremote: map[string]alpm.Package{\n\t\t\t\t\t\"hello\": &mock.Package{PName: \"hello\", PVersion: \"2.0.0\"},\n\t\t\t\t},\n\t\t\t\taurdata: map[string]*aur.Pkg{\"hello\": {Version: \"2.1.0\", Name: \"hello\"}},\n\t\t\t},\n\t\t\twant: UpSlice{Repos: []string{\"aur\"}, Up: []Upgrade{{Name: \"hello\", Repository: \"aur\", LocalVersion: \"2.0.0\", RemoteVersion: \"2.1.0\"}}},\n\t\t},\n\t\t{\n\t\t\tname: \"Downgrade\",\n\t\t\targs: args{\n\t\t\t\tremote: map[string]alpm.Package{\n\t\t\t\t\t\"hello\": &mock.Package{PName: \"hello\", PVersion: \"2.0.0\"},\n\t\t\t\t},\n\t\t\t\taurdata:         map[string]*aur.Pkg{\"hello\": {Version: \"1.0.0\", Name: \"hello\"}},\n\t\t\t\tenableDowngrade: true,\n\t\t\t},\n\t\t\twant: UpSlice{Repos: []string{\"aur\"}, Up: []Upgrade{{Name: \"hello\", Repository: \"aur\", LocalVersion: \"2.0.0\", RemoteVersion: \"1.0.0\"}}},\n\t\t},\n\t\t{\n\t\t\tname: \"Downgrade Disabled\",\n\t\t\targs: args{\n\t\t\t\tremote: map[string]alpm.Package{\n\t\t\t\t\t\"hello\": &mock.Package{PName: \"hello\", PVersion: \"2.0.0\"},\n\t\t\t\t},\n\t\t\t\taurdata:         map[string]*aur.Pkg{\"hello\": {Version: \"1.0.0\", Name: \"hello\"}},\n\t\t\t\tenableDowngrade: false,\n\t\t\t},\n\t\t\twant: UpSlice{Repos: []string{\"aur\"}, Up: []Upgrade{}},\n\t\t},\n\t\t{\n\t\t\tname: \"Mixed Updates Downgrades\",\n\t\t\targs: args{\n\t\t\t\tenableDowngrade: true,\n\t\t\t\tremote: map[string]alpm.Package{\n\t\t\t\t\t\"up\":      &mock.Package{PName: \"up\", PVersion: \"2.0.0\"},\n\t\t\t\t\t\"same\":    &mock.Package{PName: \"same\", PVersion: \"3.0.0\"},\n\t\t\t\t\t\"down\":    &mock.Package{PName: \"down\", PVersion: \"1.1.0\"},\n\t\t\t\t\t\"ignored\": &mock.Package{PName: \"ignored\", PVersion: \"1.0.0\", PShouldIgnore: true},\n\t\t\t\t},\n\t\t\t\taurdata: map[string]*aur.Pkg{\n\t\t\t\t\t\"up\":      {Version: \"2.1.0\", Name: \"up\"},\n\t\t\t\t\t\"same\":    {Version: \"3.0.0\", Name: \"same\"},\n\t\t\t\t\t\"down\":    {Version: \"1.0.0\", Name: \"down\"},\n\t\t\t\t\t\"ignored\": {Version: \"2.0.0\", Name: \"ignored\"},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: UpSlice{Repos: []string{\"aur\"}, Up: []Upgrade{\n\t\t\t\t{Name: \"up\", Repository: \"aur\", LocalVersion: \"2.0.0\", RemoteVersion: \"2.1.0\"},\n\t\t\t\t{Name: \"down\", Repository: \"aur\", LocalVersion: \"1.1.0\", RemoteVersion: \"1.0.0\"},\n\t\t\t}},\n\t\t},\n\t\t{\n\t\t\tname: \"Ignore LastModified When Version Is Unchanged\",\n\t\t\targs: args{\n\t\t\t\tremote: map[string]alpm.Package{\n\t\t\t\t\t\"hello\": &mock.Package{PName: \"hello\", PVersion: \"2.0.0\"},\n\t\t\t\t},\n\t\t\t\taurdata: map[string]*aur.Pkg{\"hello\": {Version: \"2.0.0\", Name: \"hello\", LastModified: 9999999999}},\n\t\t\t},\n\t\t\twant: UpSlice{Repos: []string{\"aur\"}, Up: []Upgrade{}},\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tgot := UpAUR(text.NewLogger(io.Discard, os.Stderr, strings.NewReader(\"\"), false, \"test\"),\n\t\t\t\ttt.args.remote, tt.args.aurdata, tt.args.enableDowngrade)\n\t\t\tassert.ElementsMatch(t, tt.want.Repos, got.Repos)\n\t\t\tassert.ElementsMatch(t, tt.want.Up, got.Up)\n\t\t\tassert.Equal(t, tt.want.Len(), got.Len())\n\t\t})\n\t}\n}\n\nfunc Test_upDevel(t *testing.T) {\n\tt.Parallel()\n\n\ttype args struct {\n\t\tremote  map[string]alpm.Package\n\t\taurdata map[string]*aur.Pkg\n\t\tcached  vcs.Store\n\t}\n\ttests := []struct {\n\t\tname     string\n\t\targs     args\n\t\twant     UpSlice\n\t\tfinalLen int\n\t}{\n\t\t{\n\t\t\tname: \"No Updates\",\n\t\t\targs: args{\n\t\t\t\tcached: &vcs.Mock{},\n\t\t\t\tremote: map[string]alpm.Package{\n\t\t\t\t\t\"hello\":     &mock.Package{PName: \"hello\", PVersion: \"2.0.0\"},\n\t\t\t\t\t\"local_pkg\": &mock.Package{PName: \"local_pkg\", PVersion: \"1.1.0\"},\n\t\t\t\t\t\"ignored\":   &mock.Package{PName: \"ignored\", PVersion: \"1.0.0\", PShouldIgnore: true},\n\t\t\t\t},\n\t\t\t\taurdata: map[string]*aur.Pkg{\n\t\t\t\t\t\"hello\":   {Version: \"2.0.0\", Name: \"hello\"},\n\t\t\t\t\t\"ignored\": {Version: \"2.0.0\", Name: \"ignored\"},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: UpSlice{Repos: []string{\"devel\"}},\n\t\t},\n\t\t{\n\t\t\tname:     \"Simple Update\",\n\t\t\tfinalLen: 3,\n\t\t\targs: args{\n\t\t\t\tcached: &vcs.Mock{\n\t\t\t\t\tToUpgradeReturn: []string{\"hello\", \"hello4\"},\n\t\t\t\t},\n\t\t\t\tremote: map[string]alpm.Package{\n\t\t\t\t\t\"hello\":  &mock.Package{PName: \"hello\", PVersion: \"2.0.0\"},\n\t\t\t\t\t\"hello2\": &mock.Package{PName: \"hello2\", PVersion: \"3.0.0\"},\n\t\t\t\t\t\"hello4\": &mock.Package{PName: \"hello4\", PVersion: \"4.0.0\"},\n\t\t\t\t},\n\t\t\t\taurdata: map[string]*aur.Pkg{\n\t\t\t\t\t\"hello\":  {Version: \"2.0.0\", Name: \"hello\"},\n\t\t\t\t\t\"hello2\": {Version: \"2.0.0\", Name: \"hello2\"},\n\t\t\t\t\t\"hello4\": {Version: \"2.0.0\", Name: \"hello4\"},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: UpSlice{\n\t\t\t\tRepos: []string{\"devel\"}, Up: []Upgrade{\n\t\t\t\t\t{\n\t\t\t\t\t\tName:          \"hello\",\n\t\t\t\t\t\tRepository:    \"devel\",\n\t\t\t\t\t\tLocalVersion:  \"2.0.0\",\n\t\t\t\t\t\tRemoteVersion: \"latest-commit\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tName:          \"hello4\",\n\t\t\t\t\t\tRepository:    \"devel\",\n\t\t\t\t\t\tLocalVersion:  \"4.0.0\",\n\t\t\t\t\t\tRemoteVersion: \"latest-commit\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:     \"No update returned\",\n\t\t\tfinalLen: 1,\n\t\t\targs: args{\n\t\t\t\tcached: &vcs.Mock{ToUpgradeReturn: []string{}},\n\t\t\t\tremote: map[string]alpm.Package{\n\t\t\t\t\t\"hello\": &mock.Package{PName: \"hello\", PVersion: \"2.0.0\"},\n\t\t\t\t},\n\t\t\t\taurdata: map[string]*aur.Pkg{\"hello\": {Version: \"2.0.0\", Name: \"hello\"}},\n\t\t\t},\n\t\t\twant: UpSlice{Repos: []string{\"devel\"}},\n\t\t},\n\t\t{\n\t\t\tname:     \"No update returned - ignored\",\n\t\t\tfinalLen: 1,\n\t\t\targs: args{\n\t\t\t\tcached: &vcs.Mock{\n\t\t\t\t\tToUpgradeReturn: []string{\"hello\"},\n\t\t\t\t},\n\t\t\t\tremote: map[string]alpm.Package{\n\t\t\t\t\t\"hello\": &mock.Package{PName: \"hello\", PVersion: \"2.0.0\", PShouldIgnore: true},\n\t\t\t\t},\n\t\t\t\taurdata: map[string]*aur.Pkg{\"hello\": {Version: \"2.0.0\", Name: \"hello\"}},\n\t\t\t},\n\t\t\twant: UpSlice{Repos: []string{\"devel\"}},\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tgot := UpDevel(context.Background(),\n\t\t\t\ttext.NewLogger(io.Discard, os.Stderr, strings.NewReader(\"\"), false, \"test\"),\n\t\t\t\ttt.args.remote, tt.args.aurdata, tt.args.cached)\n\t\t\tassert.ElementsMatch(t, tt.want.Up, got.Up)\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/upgrade/upgrade.go",
    "content": "package upgrade\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/query\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\n// Filter decides if specific package should be included in the results.\ntype Filter func(*Upgrade) bool\n\n// Upgrade type describes a system upgrade.\ntype Upgrade = db.Upgrade\n\nfunc StylizedNameWithRepository(u *Upgrade) string {\n\treturn text.Bold(text.ColorHash(u.Repository)) + \"/\" + text.Bold(u.Name)\n}\n\n// upSlice is a slice of Upgrades.\ntype UpSlice struct {\n\tUp         []Upgrade\n\tRepos      []string\n\tPulledDeps []Upgrade\n}\n\nfunc (u UpSlice) Len() int      { return len(u.Up) }\nfunc (u UpSlice) Swap(i, j int) { u.Up[i], u.Up[j] = u.Up[j], u.Up[i] }\n\nfunc (u UpSlice) Less(i, j int) bool {\n\tif u.Up[i].Repository == u.Up[j].Repository {\n\t\tiRunes := []rune(u.Up[i].Name)\n\t\tjRunes := []rune(u.Up[j].Name)\n\n\t\treturn text.LessRunes(iRunes, jRunes)\n\t}\n\n\tfor _, db := range u.Repos {\n\t\tswitch db {\n\t\tcase u.Up[i].Repository:\n\t\t\treturn true\n\t\tcase u.Up[j].Repository:\n\t\t\treturn false\n\t\t}\n\t}\n\n\tiRunes := []rune(u.Up[i].Repository)\n\tjRunes := []rune(u.Up[j].Repository)\n\n\treturn text.LessRunes(iRunes, jRunes)\n}\n\n// calculateFormatting calculates formatting parameters for printing upgrades\nfunc calculateFormatting(upgrades []Upgrade) (longestName, longestVersion, longestNumber int) {\n\tfor i := range upgrades {\n\t\tupgrade := &upgrades[i]\n\t\tpackNameLen := len(StylizedNameWithRepository(upgrade))\n\t\tpackVersion, _ := query.GetVersionDiff(upgrade.LocalVersion, upgrade.RemoteVersion)\n\t\tpackVersionLen := len(packVersion)\n\t\tlongestName = max(packNameLen, longestName)\n\t\tlongestVersion = max(packVersionLen, longestVersion)\n\t}\n\n\tlenUp := len(upgrades)\n\tlongestNumber = len(fmt.Sprintf(\"%v\", lenUp))\n\n\treturn\n}\n\n// Print prints the details of the packages to upgrade.\nfunc (u UpSlice) Print(logger *text.Logger) {\n\tlongestName, longestVersion, longestNumber := calculateFormatting(u.Up)\n\n\tnamePadding := fmt.Sprintf(\"%%-%ds  \", longestName)\n\tversionPadding := fmt.Sprintf(\"%%-%ds\", longestVersion)\n\tnumberPadding := fmt.Sprintf(\"%%%dd  \", longestNumber)\n\n\tfor k := range u.Up {\n\t\tupgrade := &u.Up[k]\n\t\tleft, right := query.GetVersionDiff(upgrade.LocalVersion, upgrade.RemoteVersion)\n\n\t\tlogger.Print(text.Magenta(fmt.Sprintf(numberPadding, len(u.Up)-k)))\n\t\tlogger.Print(fmt.Sprintf(namePadding, StylizedNameWithRepository(upgrade)))\n\t\tlogger.Printf(\"%s -> %s\\n\", fmt.Sprintf(versionPadding, left), right)\n\t\tif upgrade.Extra != \"\" {\n\t\t\tlogger.Println(strings.Repeat(\" \", longestNumber), upgrade.Extra)\n\t\t}\n\t}\n}\n\nfunc (u UpSlice) PrintDeps(logger *text.Logger) {\n\tlongestName, longestVersion, longestNumber := calculateFormatting(u.PulledDeps)\n\n\tnamePadding := fmt.Sprintf(\"  %s%%-%ds  \", strings.Repeat(\" \", longestNumber), longestName)\n\tversionPadding := fmt.Sprintf(\"%%-%ds\", longestVersion)\n\n\tfor k := range u.PulledDeps {\n\t\tupgrade := &u.PulledDeps[k]\n\t\tleft, right := query.GetVersionDiff(upgrade.LocalVersion, upgrade.RemoteVersion)\n\n\t\tlogger.Printf(\"%s\", fmt.Sprintf(namePadding, StylizedNameWithRepository(upgrade)))\n\t\tlogger.Printf(\"%s -> %s\\n\", fmt.Sprintf(versionPadding, left), right)\n\t\tif upgrade.Extra != \"\" {\n\t\t\tlogger.Println(strings.Repeat(\" \", longestNumber), strings.ToLower(upgrade.Extra))\n\t\t}\n\t}\n\n\tlogger.Println()\n}\n"
  },
  {
    "path": "pkg/upgrade/upgrade_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage upgrade\n\nimport (\n\t\"testing\"\n\n\t\"github.com/Jguer/yay/v12/pkg/query\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\nfunc TestGetVersionDiff(t *testing.T) {\n\ttext.UseColor = true\n\n\ttype versionPair struct {\n\t\tOld string\n\t\tNew string\n\t}\n\n\tin := []versionPair{\n\t\t{\"1-1\", \"1-1\"},\n\t\t{\"1-1\", \"2-1\"},\n\t\t{\"2-1\", \"1-1\"},\n\t\t{\"1-1\", \"1-2\"},\n\t\t{\"1-2\", \"1-1\"},\n\t\t{\"1.2.3-1\", \"1.2.4-1\"},\n\t\t{\"1.8rc1+6+g0f377f94-1\", \"1.8rc1+1+g7e949283-1\"},\n\t\t{\"1.8rc1+6+g0f377f94-1\", \"1.8rc2+1+g7e949283-1\"},\n\t\t{\"1.8rc2\", \"1.9rc1\"},\n\t\t{\"2.99.917+812+g75795523-1\", \"2.99.917+823+gd9bf46e4-1\"},\n\t\t{\"1.2.9-1\", \"1.2.10-1\"},\n\t\t{\"1.2.10-1\", \"1.2.9-1\"},\n\t\t{\"1.2-1\", \"1.2.1-1\"},\n\t\t{\"1.2.1-1\", \"1.2-1\"},\n\t\t{\"0.7-4\", \"0.7+4+gd8d8c67-1\"},\n\t\t{\"1.0.2_r0-1\", \"1.0.2_r0-2\"},\n\t\t{\"1.0.2_r0-1\", \"1.0.2_r1-1\"},\n\t\t{\"1.0.2_r0-1\", \"1.0.3_r0-1\"},\n\t}\n\n\tout := []versionPair{\n\t\t{\"1-1\" + text.Red(\"\"), \"1-1\" + text.Green(\"\")},\n\t\t{text.Red(\"1-1\"), text.Green(\"2-1\")},\n\t\t{text.Red(\"2-1\"), text.Green(\"1-1\")},\n\t\t{\"1-\" + text.Red(\"1\"), \"1-\" + text.Green(\"2\")},\n\t\t{\"1-\" + text.Red(\"2\"), \"1-\" + text.Green(\"1\")},\n\t\t{\"1.2.\" + text.Red(\"3-1\"), \"1.2.\" + text.Green(\"4-1\")},\n\t\t{\"1.8rc1+\" + text.Red(\"6+g0f377f94-1\"), \"1.8rc1+\" + text.Green(\"1+g7e949283-1\")},\n\t\t{\"1.8\" + text.Red(\"rc1+6+g0f377f94-1\"), \"1.8\" + text.Green(\"rc2+1+g7e949283-1\")},\n\t\t{\"1.\" + text.Red(\"8rc2\"), \"1.\" + text.Green(\"9rc1\")},\n\t\t{\"2.99.917+\" + text.Red(\"812+g75795523-1\"), \"2.99.917+\" + text.Green(\"823+gd9bf46e4-1\")},\n\t\t{\"1.2.\" + text.Red(\"9-1\"), \"1.2.\" + text.Green(\"10-1\")},\n\t\t{\"1.2.\" + text.Red(\"10-1\"), \"1.2.\" + text.Green(\"9-1\")},\n\t\t{\"1.2\" + text.Red(\"-1\"), \"1.2\" + text.Green(\".1-1\")},\n\t\t{\"1.2\" + text.Red(\".1-1\"), \"1.2\" + text.Green(\"-1\")},\n\t\t{\"0.7\" + text.Red(\"-4\"), \"0.7\" + text.Green(\"+4+gd8d8c67-1\")},\n\t\t{\"1.0.2_r0-\" + text.Red(\"1\"), \"1.0.2_r0-\" + text.Green(\"2\")},\n\t\t{\"1.0.2_\" + text.Red(\"r0-1\"), \"1.0.2_\" + text.Green(\"r1-1\")},\n\t\t{\"1.0.\" + text.Red(\"2_r0-1\"), \"1.0.\" + text.Green(\"3_r0-1\")},\n\t}\n\n\tfor i, pair := range in {\n\t\to, n := query.GetVersionDiff(pair.Old, pair.New)\n\n\t\tif o != out[i].Old || n != out[i].New {\n\t\t\tt.Errorf(\"Test %-2d failed for update: expected (%s => %s) got (%s => %s) %d %d %d %d\",\n\t\t\t\ti+1, out[i].Old, out[i].New, o, n, len(out[i].Old), len(out[i].New), len(o), len(n))\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "pkg/vcs/.snapshots/TestInfoStore_Update-simple",
    "content": "{\n\t\"hello\": {\n\t\t\"github.com/jguer/yay.git\": {\n\t\t\t\"protocols\": [\n\t\t\t\t\"git\"\n\t\t\t],\n\t\t\t\"branch\": \"master\",\n\t\t\t\"sha\": \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "pkg/vcs/mock.go",
    "content": "package vcs\n\nimport (\n\t\"context\"\n\t\"slices\"\n\n\talpm \"github.com/Jguer/dyalpm\"\n\tgosrc \"github.com/Morganamilo/go-srcinfo\"\n)\n\ntype Mock struct {\n\tOriginsByPackage map[string]OriginInfoByURL\n\tToUpgradeReturn  []string\n}\n\nfunc (m *Mock) ToUpgrade(ctx context.Context, pkgName string) bool {\n\treturn slices.Contains(m.ToUpgradeReturn, pkgName)\n}\n\nfunc (m *Mock) Update(ctx context.Context, pkgName string, sources []gosrc.ArchString) {\n}\n\nfunc (m *Mock) Save() error {\n\treturn nil\n}\n\nfunc (m *Mock) RemovePackages(pkgs []string) {\n}\n\nfunc (m *Mock) Load() error {\n\treturn nil\n}\n\nfunc (m *Mock) CleanOrphans(pkgs map[string]alpm.Package) {\n}\n"
  },
  {
    "path": "pkg/vcs/vcs.go",
    "content": "package vcs\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"slices\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\talpm \"github.com/Jguer/dyalpm\"\n\tgosrc \"github.com/Morganamilo/go-srcinfo\"\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\nconst defaultTimeout = 15 * time.Second\n\ntype Store interface {\n\t// ToUpgrade returns true if the package needs to be updated.\n\tToUpgrade(ctx context.Context, pkgName string) bool\n\t// Update updates the VCS info of a package.\n\tUpdate(ctx context.Context, pkgName string, sources []gosrc.ArchString)\n\t// RemovePackages removes the VCS info of the packages given as arg if they exist.\n\tRemovePackages(pkgs []string)\n\t// Clean orphaned VCS info.\n\tCleanOrphans(pkgs map[string]alpm.Package)\n\t// Load loads the VCS info from disk.\n\tLoad() error\n\t// Save saves the VCS info to disk.\n\tSave() error\n}\n\n// InfoStore is a collection of OriginInfoByURL by Package.\n// Containing a map of last commit SHAs of a repo.\ntype InfoStore struct {\n\tOriginsByPackage map[string]OriginInfoByURL\n\tFilePath         string\n\tCmdBuilder       exe.GitCmdBuilder\n\tmux              sync.Mutex\n\tlogger           *text.Logger\n}\n\n// OriginInfoByURL stores the OriginInfo of each origin URL provided.\ntype OriginInfoByURL map[string]OriginInfo\n\n// OriginInfo contains the last commit sha of a repo\n// Example:\n//\n//\t\"github.com/Jguer/yay.git\": {\n//\t\t\"protocols\": [\n//\t\t\t\"https\"\n//\t\t],\n//\t\t\"branch\": \"next\",\n//\t\t\"sha\": \"c1171d41467c68ffd3c46748182a16366aaaf87b\"\n//\t}.\ntype OriginInfo struct {\n\tProtocols []string `json:\"protocols\"`\n\tBranch    string   `json:\"branch\"`\n\tSHA       string   `json:\"sha\"`\n}\n\nfunc NewInfoStore(filePath string, cmdBuilder exe.GitCmdBuilder,\n\tlogger *text.Logger,\n) *InfoStore {\n\tinfoStore := &InfoStore{\n\t\tCmdBuilder:       cmdBuilder,\n\t\tFilePath:         filePath,\n\t\tOriginsByPackage: map[string]OriginInfoByURL{},\n\t\tmux:              sync.Mutex{},\n\t\tlogger:           logger,\n\t}\n\n\treturn infoStore\n}\n\n// GetCommit parses HEAD commit from url and branch.\nfunc (v *InfoStore) getCommit(ctx context.Context, url, branch string, protocols []string) string {\n\tif len(protocols) > 0 {\n\t\tprotocol := protocols[len(protocols)-1]\n\n\t\tctxTimeout, cancel := context.WithTimeout(ctx, defaultTimeout)\n\t\tdefer cancel()\n\n\t\tcmd := v.CmdBuilder.BuildGitCmd(ctxTimeout, \"\", \"ls-remote\", protocol+\"://\"+url, branch)\n\n\t\tstdout, stderr, err := v.CmdBuilder.Capture(cmd)\n\t\tif err != nil {\n\t\t\texitError := &exec.ExitError{}\n\t\t\tif ok := errors.As(err, &exitError); ok && exitError.ExitCode() == 128 {\n\t\t\t\tv.logger.Warnln(gotext.Get(\"devel check for package failed: '%s' encountered an error\", cmd.String()), \": \", stderr)\n\t\t\t\treturn \"\"\n\t\t\t}\n\n\t\t\tv.logger.Warnln(gotext.Get(\"devel check for package failed: '%s' encountered an error\", cmd.String()), \": \", err)\n\n\t\t\treturn \"\"\n\t\t}\n\n\t\tsplit := strings.Fields(stdout)\n\n\t\tif len(split) < 2 {\n\t\t\treturn \"\"\n\t\t}\n\n\t\tcommit := split[0]\n\n\t\treturn commit\n\t}\n\n\treturn \"\"\n}\n\nfunc (v *InfoStore) Update(ctx context.Context, pkgName string, sources []gosrc.ArchString) {\n\tvar wg sync.WaitGroup\n\tinfo := make(OriginInfoByURL)\n\tcheckSource := func(source gosrc.ArchString) {\n\t\tdefer wg.Done()\n\n\t\turl, branch, protocols := parseSource(source.Value)\n\t\tif url == \"\" || branch == \"\" {\n\t\t\treturn\n\t\t}\n\n\t\tcommit := v.getCommit(ctx, url, branch, protocols)\n\t\tif commit == \"\" {\n\t\t\treturn\n\t\t}\n\n\t\tv.mux.Lock()\n\t\tinfo[url] = OriginInfo{\n\t\t\tprotocols,\n\t\t\tbranch,\n\t\t\tcommit,\n\t\t}\n\n\t\tv.OriginsByPackage[pkgName] = info\n\n\t\tv.logger.Debugln(gotext.Get(\"Found git repo: %s\", text.Cyan(url)))\n\n\t\tif err := v.Save(); err != nil {\n\t\t\tfmt.Fprintln(os.Stderr, err)\n\t\t}\n\t\tv.mux.Unlock()\n\t}\n\n\tfor _, source := range sources {\n\t\twg.Add(1)\n\n\t\tgo checkSource(source)\n\t}\n\n\twg.Wait()\n}\n\n// parseSource returns the git url, default branch and protocols it supports.\nfunc parseSource(source string) (url, branch string, protocols []string) {\n\tsplit := strings.Split(source, \"::\")\n\tsource = split[len(split)-1]\n\tsplit = strings.SplitN(source, \"://\", 2)\n\n\tif len(split) != 2 {\n\t\treturn \"\", \"\", nil\n\t}\n\n\tprotocols = strings.SplitN(split[0], \"+\", 2)\n\n\tgit := slices.Contains(protocols, \"git\")\n\n\tprotocols = protocols[len(protocols)-1:]\n\n\tif !git {\n\t\treturn \"\", \"\", nil\n\t}\n\n\tsplit = strings.SplitN(split[1], \"#\", 2)\n\tif len(split) == 2 {\n\t\tsecondSplit := strings.SplitN(split[1], \"=\", 2)\n\t\tif secondSplit[0] != \"branch\" {\n\t\t\t// source has #commit= or #tag= which makes them not vcs\n\t\t\t// packages because they reference a specific point\n\t\t\treturn \"\", \"\", nil\n\t\t}\n\n\t\tif len(secondSplit) == 2 {\n\t\t\turl = split[0]\n\t\t\tbranch = secondSplit[1]\n\t\t}\n\t} else {\n\t\turl = split[0]\n\t\tbranch = \"HEAD\"\n\t}\n\n\turl = strings.Split(url, \"?\")[0]\n\tbranch = strings.Split(branch, \"?\")[0]\n\n\treturn url, branch, protocols\n}\n\nfunc (v *InfoStore) ToUpgrade(ctx context.Context, pkgName string) bool {\n\tif infos, ok := v.OriginsByPackage[pkgName]; ok {\n\t\treturn v.needsUpdate(ctx, infos)\n\t}\n\n\treturn false\n}\n\nfunc (v *InfoStore) needsUpdate(ctx context.Context, infos OriginInfoByURL) bool {\n\t// used to signal we have gone through all sources and found nothing\n\tfinished := make(chan struct{})\n\talive := 0\n\n\t// if we find an update we use this to exit early and return true\n\thasUpdate := make(chan struct{})\n\n\tclosed := make(chan struct{})\n\tdefer close(closed)\n\n\tcheckHash := func(url string, info OriginInfo) {\n\t\thash := v.getCommit(ctx, url, info.Branch, info.Protocols)\n\n\t\tvar sendTo chan<- struct{}\n\t\tif hash != \"\" && hash != info.SHA {\n\t\t\tsendTo = hasUpdate\n\t\t} else {\n\t\t\tsendTo = finished\n\t\t}\n\n\t\tselect {\n\t\tcase sendTo <- struct{}{}:\n\t\tcase <-closed:\n\t\t}\n\t}\n\n\tfor url, info := range infos {\n\t\talive++\n\n\t\tgo checkHash(url, info)\n\t}\n\n\tfor {\n\t\tselect {\n\t\tcase <-hasUpdate:\n\t\t\treturn true\n\t\tcase <-finished:\n\t\t\talive--\n\t\t\tif alive == 0 {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc (v *InfoStore) Save() error {\n\tmarshalledinfo, err := json.MarshalIndent(v.OriginsByPackage, \"\", \"\\t\")\n\tif err != nil || string(marshalledinfo) == \"null\" {\n\t\treturn err\n\t}\n\n\tin, err := os.OpenFile(v.FilePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o644)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tdefer in.Close()\n\n\tif _, errM := in.Write(marshalledinfo); errM != nil {\n\t\treturn errM\n\t}\n\n\treturn in.Sync()\n}\n\n// RemovePackage removes package from VCS information.\nfunc (v *InfoStore) RemovePackages(pkgs []string) {\n\tupdated := false\n\n\tfor _, pkgName := range pkgs {\n\t\tif _, ok := v.OriginsByPackage[pkgName]; ok {\n\t\t\tdelete(v.OriginsByPackage, pkgName)\n\n\t\t\tupdated = true\n\t\t}\n\t}\n\n\tif updated {\n\t\tif err := v.Save(); err != nil {\n\t\t\tfmt.Fprintln(os.Stderr, err)\n\t\t}\n\t}\n}\n\n// LoadStore reads a json file and populates a InfoStore structure.\nfunc (v *InfoStore) Load() error {\n\tvfile, err := os.Open(v.FilePath)\n\tif !os.IsNotExist(err) && err != nil {\n\t\treturn fmt.Errorf(\"failed to open vcs file '%s': %w\", v.FilePath, err)\n\t}\n\n\tdefer vfile.Close()\n\n\tif !os.IsNotExist(err) {\n\t\tdecoder := json.NewDecoder(vfile)\n\t\tif err = decoder.Decode(&v.OriginsByPackage); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to read vcs '%s': %w\", v.FilePath, err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (v *InfoStore) CleanOrphans(pkgs map[string]alpm.Package) {\n\tmissing := make([]string, 0)\n\n\tfor pkgName := range v.OriginsByPackage {\n\t\tif _, ok := pkgs[pkgName]; !ok {\n\t\t\tv.logger.Debugln(\"removing orphaned vcs package:\", pkgName)\n\t\t\tmissing = append(missing, pkgName)\n\t\t}\n\t}\n\n\tv.RemovePackages(missing)\n}\n"
  },
  {
    "path": "pkg/vcs/vcs_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage vcs\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"io\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"testing\"\n\n\tgosrc \"github.com/Morganamilo/go-srcinfo\"\n\t\"github.com/bradleyjkemp/cupaloy\"\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\nfunc newTestLogger() *text.Logger {\n\treturn text.NewLogger(io.Discard, io.Discard, strings.NewReader(\"\"), true, \"test\")\n}\n\nfunc TestParsing(t *testing.T) {\n\tt.Parallel()\n\ttype source struct {\n\t\tURL       string\n\t\tBranch    string\n\t\tProtocols []string\n\t}\n\n\turls := []string{\n\t\t\"git+https://github.com/neovim/neovim.git\",\n\t\t\"git://github.com/jguer/yay.git#branch=master\",\n\t\t\"git://github.com/davidgiven/ack\",\n\t\t\"git://github.com/jguer/yay.git#tag=v3.440\",\n\t\t\"git://github.com/jguer/yay.git#commit=e5470c88c6e2f9e0f97deb4728659ffa70ef5d0c\",\n\t\t\"a+b+c+d+e+f://github.com/jguer/yay.git#branch=foo\",\n\t}\n\n\tsources := []source{\n\t\t{\"github.com/neovim/neovim.git\", \"HEAD\", []string{\"https\"}},\n\t\t{\"github.com/jguer/yay.git\", \"master\", []string{\"git\"}},\n\t\t{\"github.com/davidgiven/ack\", \"HEAD\", []string{\"git\"}},\n\t\t{\"\", \"\", nil},\n\t\t{\"\", \"\", nil},\n\t\t{\"\", \"\", nil},\n\t}\n\n\tfor n, url := range urls {\n\t\turl, branch, protocols := parseSource(url)\n\t\tcompare := sources[n]\n\n\t\tassert.Equal(t, compare.URL, url)\n\t\tassert.Equal(t, compare.Branch, branch)\n\t\tassert.Equal(t, compare.Protocols, protocols)\n\t}\n}\n\nfunc TestNewInfoStore(t *testing.T) {\n\tt.Parallel()\n\ttype args struct {\n\t\tfilePath   string\n\t\tcmdBuilder *exe.CmdBuilder\n\t}\n\ttests := []struct {\n\t\tname string\n\t\targs args\n\t}{\n\t\t{\n\t\t\tname: \"normal\",\n\t\t\targs: args{\n\t\t\t\t\"/tmp/a.json\",\n\t\t\t\t&exe.CmdBuilder{GitBin: \"git\", GitFlags: []string{\"--a\", \"--b\"}, Runner: &exe.OSRunner{\n\t\t\t\t\tLog: text.NewLogger(io.Discard, os.Stderr, strings.NewReader(\"\"), true, \"test\"),\n\t\t\t\t}},\n\t\t\t},\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tgot := NewInfoStore(tt.args.filePath, tt.args.cmdBuilder,\n\t\t\t\ttext.NewLogger(io.Discard, os.Stderr, strings.NewReader(\"\"), true, \"test\"))\n\t\t\tassert.NotNil(t, got)\n\t\t\tassert.Equal(t, []string{\"--a\", \"--b\"}, got.CmdBuilder.(*exe.CmdBuilder).GitFlags)\n\t\t\tassert.Equal(t, tt.args.cmdBuilder, got.CmdBuilder)\n\t\t\tassert.Equal(t, \"/tmp/a.json\", got.FilePath)\n\t\t})\n\t}\n}\n\ntype MockRunner struct {\n\tReturned []string\n\tIndex    int\n}\n\nfunc (r *MockRunner) Show(cmd *exec.Cmd) error {\n\treturn nil\n}\n\nfunc (r *MockRunner) Capture(cmd *exec.Cmd) (stdout, stderr string, err error) {\n\tstdout = r.Returned[r.Index]\n\tif r.Returned[0] == \"error\" {\n\t\terr = errors.New(\"possible error\")\n\t}\n\treturn stdout, stderr, err\n}\n\nfunc TestInfoStoreToUpgrade(t *testing.T) {\n\tt.Parallel()\n\ttype fields struct {\n\t\tCmdBuilder *exe.CmdBuilder\n\t}\n\ttype args struct {\n\t\tinfos OriginInfoByURL\n\t}\n\ttests := []struct {\n\t\tname   string\n\t\tfields fields\n\t\targs   args\n\t\twant   bool\n\t}{\n\t\t{\n\t\t\tname: \"simple-has_update\",\n\t\t\targs: args{infos: OriginInfoByURL{\n\t\t\t\t\"github.com/Jguer/z.git\": OriginInfo{\n\t\t\t\t\tProtocols: []string{\"https\"},\n\t\t\t\t\tBranch:    \"0\",\n\t\t\t\t\tSHA:       \"991c5b4146fd27f4aacf4e3111258a848934aaa1\",\n\t\t\t\t},\n\t\t\t}}, fields: fields{\n\t\t\t\tCmdBuilder: &exe.CmdBuilder{GitBin: \"git\", GitFlags: []string{\"\"}, Runner: &MockRunner{\n\t\t\t\t\tReturned: []string{\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\tHEAD\"},\n\t\t\t\t}},\n\t\t\t},\n\t\t\twant: true,\n\t\t},\n\t\t{\n\t\t\tname: \"double-has_update\",\n\t\t\targs: args{infos: OriginInfoByURL{\n\t\t\t\t\"github.com/Jguer/z.git\": OriginInfo{\n\t\t\t\t\tProtocols: []string{\"https\"},\n\t\t\t\t\tBranch:    \"0\",\n\t\t\t\t\tSHA:       \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\n\t\t\t\t},\n\t\t\t\t\"github.com/Jguer/a.git\": OriginInfo{\n\t\t\t\t\tProtocols: []string{\"https\"},\n\t\t\t\t\tBranch:    \"0\",\n\t\t\t\t\tSHA:       \"991c5b4146fd27f4aacf4e3111258a848934aaa1\",\n\t\t\t\t},\n\t\t\t}}, fields: fields{\n\t\t\t\tCmdBuilder: &exe.CmdBuilder{GitBin: \"git\", GitFlags: []string{\"\"}, Runner: &MockRunner{\n\t\t\t\t\tReturned: []string{\n\t\t\t\t\t\t\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\tHEAD\",\n\t\t\t\t\t\t\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\tHEAD\",\n\t\t\t\t\t},\n\t\t\t\t}},\n\t\t\t},\n\t\t\twant: true,\n\t\t},\n\t\t{\n\t\t\tname: \"simple-no_update\",\n\t\t\targs: args{infos: OriginInfoByURL{\n\t\t\t\t\"github.com/Jguer/z.git\": OriginInfo{\n\t\t\t\t\tProtocols: []string{\"https\"},\n\t\t\t\t\tBranch:    \"0\",\n\t\t\t\t\tSHA:       \"991c5b4146fd27f4aacf4e3111258a848934aaa1\",\n\t\t\t\t},\n\t\t\t}}, fields: fields{\n\t\t\t\tCmdBuilder: &exe.CmdBuilder{GitBin: \"git\", GitFlags: []string{\"\"}, Runner: &MockRunner{\n\t\t\t\t\tReturned: []string{\"991c5b4146fd27f4aacf4e3111258a848934aaa1\tHEAD\"},\n\t\t\t\t}},\n\t\t\t},\n\t\t\twant: false,\n\t\t},\n\t\t{\n\t\t\tname: \"simple-no_split\",\n\t\t\targs: args{infos: OriginInfoByURL{\n\t\t\t\t\"github.com/Jguer/z.git\": OriginInfo{\n\t\t\t\t\tProtocols: []string{\"https\"},\n\t\t\t\t\tBranch:    \"0\",\n\t\t\t\t\tSHA:       \"991c5b4146fd27f4aacf4e3111258a848934aaa1\",\n\t\t\t\t},\n\t\t\t}}, fields: fields{\n\t\t\t\tCmdBuilder: &exe.CmdBuilder{GitBin: \"git\", GitFlags: []string{\"\"}, Runner: &MockRunner{\n\t\t\t\t\tReturned: []string{\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"},\n\t\t\t\t}},\n\t\t\t},\n\t\t\twant: false,\n\t\t},\n\t\t{\n\t\t\tname: \"simple-error\",\n\t\t\targs: args{infos: OriginInfoByURL{\n\t\t\t\t\"github.com/Jguer/z.git\": OriginInfo{\n\t\t\t\t\tProtocols: []string{\"https\"},\n\t\t\t\t\tBranch:    \"0\",\n\t\t\t\t\tSHA:       \"991c5b4146fd27f4aacf4e3111258a848934aaa1\",\n\t\t\t\t},\n\t\t\t}}, fields: fields{\n\t\t\t\tCmdBuilder: &exe.CmdBuilder{\n\t\t\t\t\tGitBin: \"git\", GitFlags: []string{\"\"},\n\t\t\t\t\tRunner: &MockRunner{\n\t\t\t\t\t\tReturned: []string{\"error\"},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: false,\n\t\t},\n\t\t{\n\t\t\tname: \"simple-no protocol\",\n\t\t\targs: args{infos: OriginInfoByURL{\n\t\t\t\t\"github.com/Jguer/z.git\": OriginInfo{\n\t\t\t\t\tProtocols: []string{},\n\t\t\t\t\tBranch:    \"0\",\n\t\t\t\t\tSHA:       \"991c5b4146fd27f4aacf4e3111258a848934aaa1\",\n\t\t\t\t},\n\t\t\t}}, fields: fields{\n\t\t\t\tCmdBuilder: &exe.CmdBuilder{GitBin: \"git\", GitFlags: []string{\"\"}, Runner: &MockRunner{\n\t\t\t\t\tReturned: []string{\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"},\n\t\t\t\t}},\n\t\t\t},\n\t\t\twant: false,\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tv := &InfoStore{\n\t\t\t\tlogger:     newTestLogger(),\n\t\t\t\tCmdBuilder: tt.fields.CmdBuilder,\n\t\t\t\tOriginsByPackage: map[string]OriginInfoByURL{\n\t\t\t\t\t\"yay\": tt.args.infos,\n\t\t\t\t},\n\t\t\t}\n\t\t\tgot := v.ToUpgrade(context.Background(), \"yay\")\n\t\t\tassert.Equal(t, tt.want, got)\n\t\t})\n\t}\n}\n\nfunc TestInfoStore_NeedsUpdate(t *testing.T) {\n\tt.Parallel()\n\ttype fields struct {\n\t\tCmdBuilder *exe.CmdBuilder\n\t}\n\ttype args struct {\n\t\tinfos OriginInfoByURL\n\t}\n\ttests := []struct {\n\t\tname   string\n\t\tfields fields\n\t\targs   args\n\t\twant   bool\n\t}{\n\t\t{\n\t\t\tname: \"simple-has_update\",\n\t\t\targs: args{infos: OriginInfoByURL{\n\t\t\t\t\"github.com/Jguer/z.git\": OriginInfo{\n\t\t\t\t\tProtocols: []string{\"https\"},\n\t\t\t\t\tBranch:    \"0\",\n\t\t\t\t\tSHA:       \"991c5b4146fd27f4aacf4e3111258a848934aaa1\",\n\t\t\t\t},\n\t\t\t}}, fields: fields{\n\t\t\t\tCmdBuilder: &exe.CmdBuilder{GitBin: \"git\", GitFlags: []string{\"\"}, Runner: &MockRunner{\n\t\t\t\t\tReturned: []string{\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\tHEAD\"},\n\t\t\t\t}},\n\t\t\t},\n\t\t\twant: true,\n\t\t},\n\t\t{\n\t\t\tname: \"double-has_update\",\n\t\t\targs: args{infos: OriginInfoByURL{\n\t\t\t\t\"github.com/Jguer/z.git\": OriginInfo{\n\t\t\t\t\tProtocols: []string{\"https\"},\n\t\t\t\t\tBranch:    \"0\",\n\t\t\t\t\tSHA:       \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\n\t\t\t\t},\n\t\t\t\t\"github.com/Jguer/a.git\": OriginInfo{\n\t\t\t\t\tProtocols: []string{\"https\"},\n\t\t\t\t\tBranch:    \"0\",\n\t\t\t\t\tSHA:       \"991c5b4146fd27f4aacf4e3111258a848934aaa1\",\n\t\t\t\t},\n\t\t\t}}, fields: fields{\n\t\t\t\tCmdBuilder: &exe.CmdBuilder{GitBin: \"git\", GitFlags: []string{\"\"}, Runner: &MockRunner{\n\t\t\t\t\tReturned: []string{\n\t\t\t\t\t\t\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\tHEAD\",\n\t\t\t\t\t\t\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\tHEAD\",\n\t\t\t\t\t},\n\t\t\t\t}},\n\t\t\t},\n\t\t\twant: true,\n\t\t},\n\t\t{\n\t\t\tname: \"simple-no_update\",\n\t\t\targs: args{infos: OriginInfoByURL{\n\t\t\t\t\"github.com/Jguer/z.git\": OriginInfo{\n\t\t\t\t\tProtocols: []string{\"https\"},\n\t\t\t\t\tBranch:    \"0\",\n\t\t\t\t\tSHA:       \"991c5b4146fd27f4aacf4e3111258a848934aaa1\",\n\t\t\t\t},\n\t\t\t}}, fields: fields{\n\t\t\t\tCmdBuilder: &exe.CmdBuilder{GitBin: \"git\", GitFlags: []string{\"\"}, Runner: &MockRunner{\n\t\t\t\t\tReturned: []string{\"991c5b4146fd27f4aacf4e3111258a848934aaa1\tHEAD\"},\n\t\t\t\t}},\n\t\t\t},\n\t\t\twant: false,\n\t\t},\n\t\t{\n\t\t\tname: \"simple-no_split\",\n\t\t\targs: args{infos: OriginInfoByURL{\n\t\t\t\t\"github.com/Jguer/z.git\": OriginInfo{\n\t\t\t\t\tProtocols: []string{\"https\"},\n\t\t\t\t\tBranch:    \"0\",\n\t\t\t\t\tSHA:       \"991c5b4146fd27f4aacf4e3111258a848934aaa1\",\n\t\t\t\t},\n\t\t\t}}, fields: fields{\n\t\t\t\tCmdBuilder: &exe.CmdBuilder{GitBin: \"git\", GitFlags: []string{\"\"}, Runner: &MockRunner{\n\t\t\t\t\tReturned: []string{\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"},\n\t\t\t\t}},\n\t\t\t},\n\t\t\twant: false,\n\t\t},\n\t\t{\n\t\t\tname: \"simple-error\",\n\t\t\targs: args{infos: OriginInfoByURL{\n\t\t\t\t\"github.com/Jguer/z.git\": OriginInfo{\n\t\t\t\t\tProtocols: []string{\"https\"},\n\t\t\t\t\tBranch:    \"0\",\n\t\t\t\t\tSHA:       \"991c5b4146fd27f4aacf4e3111258a848934aaa1\",\n\t\t\t\t},\n\t\t\t}}, fields: fields{\n\t\t\t\tCmdBuilder: &exe.CmdBuilder{\n\t\t\t\t\tGitBin: \"git\", GitFlags: []string{\"\"},\n\t\t\t\t\tRunner: &MockRunner{\n\t\t\t\t\t\tReturned: []string{\"error\"},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twant: false,\n\t\t},\n\t\t{\n\t\t\tname: \"simple-no protocol\",\n\t\t\targs: args{infos: OriginInfoByURL{\n\t\t\t\t\"github.com/Jguer/z.git\": OriginInfo{\n\t\t\t\t\tProtocols: []string{},\n\t\t\t\t\tBranch:    \"0\",\n\t\t\t\t\tSHA:       \"991c5b4146fd27f4aacf4e3111258a848934aaa1\",\n\t\t\t\t},\n\t\t\t}}, fields: fields{\n\t\t\t\tCmdBuilder: &exe.CmdBuilder{GitBin: \"git\", GitFlags: []string{\"\"}, Runner: &MockRunner{\n\t\t\t\t\tReturned: []string{\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"},\n\t\t\t\t}},\n\t\t\t},\n\t\t\twant: false,\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tv := &InfoStore{\n\t\t\t\tlogger:     newTestLogger(),\n\t\t\t\tCmdBuilder: tt.fields.CmdBuilder,\n\t\t\t}\n\t\t\tgot := v.needsUpdate(context.Background(), tt.args.infos)\n\t\t\tassert.Equal(t, tt.want, got)\n\t\t})\n\t}\n}\n\nfunc TestInfoStore_Update(t *testing.T) {\n\tt.Parallel()\n\ttype fields struct {\n\t\tOriginsByPackage map[string]OriginInfoByURL\n\t\tCmdBuilder       *exe.CmdBuilder\n\t}\n\ttype args struct {\n\t\tpkgName string\n\t\tsources []gosrc.ArchString\n\t}\n\ttests := []struct {\n\t\tname   string\n\t\tfields fields\n\t\targs   args\n\t}{\n\t\t{\n\t\t\tname: \"simple\",\n\t\t\targs: args{\n\t\t\t\tpkgName: \"hello\",\n\t\t\t\tsources: []gosrc.ArchString{{Value: \"git://github.com/jguer/yay.git#branch=master\"}},\n\t\t\t},\n\t\t\tfields: fields{\n\t\t\t\tOriginsByPackage: make(map[string]OriginInfoByURL),\n\t\t\t\tCmdBuilder: &exe.CmdBuilder{\n\t\t\t\t\tGitBin: \"git\", GitFlags: []string{\"\"},\n\t\t\t\t\tRunner: &MockRunner{Returned: []string{\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa HEAD\"}},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tfile, err := os.CreateTemp(\"/tmp\", \"yay-infostore-*-test\")\n\tfilePath := file.Name()\n\trequire.NoError(t, err)\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tv := &InfoStore{\n\t\t\t\tOriginsByPackage: tt.fields.OriginsByPackage,\n\t\t\t\tlogger:           newTestLogger(),\n\t\t\t\tFilePath:         filePath,\n\t\t\t\tCmdBuilder:       tt.fields.CmdBuilder,\n\t\t\t}\n\n\t\t\tv.Update(context.Background(), tt.args.pkgName, tt.args.sources)\n\t\t\tassert.Len(t, tt.fields.OriginsByPackage, 1)\n\n\t\t\tmarshalledinfo, err := json.MarshalIndent(tt.fields.OriginsByPackage, \"\", \"\\t\")\n\t\t\tassert.NoError(t, err)\n\n\t\t\tcupaloy.SnapshotT(t, marshalledinfo)\n\n\t\t\tv.Load()\n\t\t\tassert.Len(t, tt.fields.OriginsByPackage, 1)\n\n\t\t\tmarshalledinfo, err = json.MarshalIndent(tt.fields.OriginsByPackage, \"\", \"\\t\")\n\t\t\tassert.NoError(t, err)\n\n\t\t\tcupaloy.SnapshotT(t, marshalledinfo)\n\t\t})\n\t}\n\n\trequire.NoError(t, os.Remove(filePath))\n}\n\nfunc TestInfoStore_Remove(t *testing.T) {\n\tt.Parallel()\n\ttype fields struct {\n\t\tOriginsByPackage map[string]OriginInfoByURL\n\t}\n\ttype args struct {\n\t\tpkgs []string\n\t}\n\ttests := []struct {\n\t\tname   string\n\t\tfields fields\n\t\targs   args\n\t}{\n\t\t{\n\t\t\tname: \"simple\",\n\t\t\targs: args{pkgs: []string{\"a\", \"c\"}},\n\t\t\tfields: fields{\n\t\t\t\tOriginsByPackage: map[string]OriginInfoByURL{\n\t\t\t\t\t\"a\": {},\n\t\t\t\t\t\"b\": {},\n\t\t\t\t\t\"c\": {},\n\t\t\t\t\t\"d\": {},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tfile, err := os.CreateTemp(\"/tmp\", \"yay-vcs-*-test\")\n\tfilePath := file.Name()\n\trequire.NoError(t, err)\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tv := &InfoStore{\n\t\t\t\tOriginsByPackage: tt.fields.OriginsByPackage,\n\t\t\t\tlogger:           newTestLogger(),\n\t\t\t\tFilePath:         filePath,\n\t\t\t}\n\t\t\tv.RemovePackages(tt.args.pkgs)\n\t\t\tassert.Len(t, tt.fields.OriginsByPackage, 2)\n\t\t})\n\t}\n\n\trequire.NoError(t, os.Remove(filePath))\n}\n\nfunc TestInfoStore_CleanOrphans(t *testing.T) {\n\tt.Parallel()\n\ttype fields struct {\n\t\tOriginsByPackage map[string]OriginInfoByURL\n\t}\n\ttype args struct {\n\t\tpkgs map[string]db.IPackage\n\t}\n\ttests := []struct {\n\t\tname   string\n\t\tfields fields\n\t\targs   args\n\t}{\n\t\t{\n\t\t\tname: \"simple\",\n\t\t\targs: args{pkgs: map[string]db.IPackage{\"a\": nil, \"b\": nil, \"d\": nil}},\n\t\t\tfields: fields{\n\t\t\t\tOriginsByPackage: map[string]OriginInfoByURL{\n\t\t\t\t\t\"a\": {},\n\t\t\t\t\t\"b\": {},\n\t\t\t\t\t\"c\": {},\n\t\t\t\t\t\"d\": {},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tfile, err := os.CreateTemp(\"/tmp\", \"yay-vcs-*-test\")\n\tfilePath := file.Name()\n\trequire.NoError(t, err)\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tv := &InfoStore{\n\t\t\t\tOriginsByPackage: tt.fields.OriginsByPackage,\n\t\t\t\tFilePath:         filePath,\n\t\t\t\tlogger:           text.NewLogger(io.Discard, os.Stderr, strings.NewReader(\"\"), false, \"test\"),\n\t\t\t}\n\t\t\tv.CleanOrphans(tt.args.pkgs)\n\t\t\tassert.Len(t, tt.fields.OriginsByPackage, 3)\n\t\t})\n\t}\n\n\trequire.NoError(t, os.Remove(filePath))\n}\n"
  },
  {
    "path": "po/ca.po",
    "content": "# \n# Translators:\n# Davidmp <medipas@gmail.com>, 2025\n# \nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: Davidmp <medipas@gmail.com>, 2025\\n\"\n\"Language-Team: Catalan (https://app.transifex.com/yay-1/teams/123732/ca/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: ca\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Directori de construcció:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Introduïu un número (per defecte = 1):\"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \"(Els fitxers de compilació ja existeixen)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \"(Instal·lat)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \"[Instal·lat]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \"No hi ha res per fer.\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"%s [T]ot [Av]orta [I]nstal·lat [No] instal·lat o (1 2 3, 1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s ja fet: se n'omet la construcció.\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s no està establert.\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s és present.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s està al dia: s'omet.\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s per actualitzar / instal·lar.\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%s també s'instal·larà per a aquesta operació.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, requerit per %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: sense canvis, s'omet.\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: no es pot usar l'objectiu amb l'opció --aur, s'omet.\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: no es pot usar l'objectiu amb l'opció --repo, s'omet.\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: s'ignora l'actualització del paquet (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: el paquet local (%s) és més nou que el de l'AUR (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"\"\n\"%s: establiu les variables d'entorn AUR_NOMDUSUARI i AUR_CONTRASENYA per \"\n\"votar.\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) PKGBUILD baixat de l'ABS: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) PKGBUILD baixat: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) Ha fallat baixar el PKGBUILD: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) S'analitza SRCINFO: %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(Instal·lat)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(Instal·lat: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Orfes)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Obsolet: %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"URL de l'AUR\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Afegiu %s o %s a les variables d'entorn.\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Eviteu executar el yay com a root / sudo.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Comprova'n la dependència\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Comprova les dependències\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"Es comproven els paquets de desenvolupament...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Es neteja (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Té conflicte amb\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Se suprimeix (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Dependència\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Depèn de\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Descripció\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Diferències per mostrar?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"Desactiva la configuració de \\\"proporciona\\\" per defecte.\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"Voleu suprimir TOTS els paquets de l'AUR de la memòria cau?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"Voleu suprimir TOTS els fitxers de l'AUR sense seguiment?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"Voleu suprimir tots els altres paquets de l'AUR de la memòria cau?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"Amb què voleu editar el PKGBUILD?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Error durant la cerca a l'AUR: %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"L'exclusió de paquets pot provocar actualitzacions parcials i trencar els \"\n\"sistemes.\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Explícit\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Paquets instal·lats explícitament: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"No s'ha pogut trobar el paquet de l'AUR per a\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"Ha fallat instal·lar la capa. Es passa a la següent.\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"Ha fallat instal·lar els paquets següents. Cal intervenció manual:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Enviat primer\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Paquets de l'AUR obsolets marcats:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Paquets forans instal·lats: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"S'ha trobat el repositori git: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB ha acabat. No s'ha instal·lat cap paquet.\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Grups\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Ho importo?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"S'importen claus amb gpg...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Paraules clau\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Darrera modificació\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Llicències\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Local\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Mantenidor\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Dependència de construcció\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Dependències de construcció\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Manca\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Manquen paquets de depuració de l'AUR:\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Nom\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:564\nmsgid \"No AUR package found for\"\nmsgstr \"No s'ha trobat cap paquet d'AUR per a\"\n\n#: pkg/dep/dep_graph.go:564\nmsgid \"required by\"\nmsgstr \"requerit per \"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"No s'ha trobat cap paquet per\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Cap\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Dependències opcionals\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Paquets d'AUR orfes (no mantinguts):\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Obsolet\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"Cal importar claus PGP:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD actualitzat, s'omet la baixada: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"PKGBUILDs per editar?\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Base de paquets\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"ID de la base de paquets\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"Paquets no a l'AUR:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Paquets per a la neteja de la construcció?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Paquets per excloure\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"Paquets per excloure: (p. ex.: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" o nom del repositori)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Paquets per instal·lar (p. ex.: 1 2 3, 1-3 o ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Popularitat\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Voleu continuar la instal·lació?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Proporciona\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"\"\n\"Suprimeixo les dependències de construcció després de la instal·lació?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Reemplaça\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"Repositori\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"Repositori de l'AUR\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Se cerquen actualitzacions a l'AUR...\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"Se cerquen actualitzacions a les bases de dades...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Es mostren només paquets dels repositoris.\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"Mida de la memòria cau del pacman %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"Mida de la memòria cau del yay %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"URL de la instantània\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Sincronització\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"Els deu paquets més grossos:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"Els paquets següents no són compatibles amb la vostra arquitectura:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"Hi ha %[1]d proveïdors disponibles per a %[2]s:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"\"\n\"Pot ser que hi hagi una altra instància del Pacman en execució. S'espera...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Mida total ocupada pels paquets: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Total de paquets instal·lats: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Intento construir-los tanmateix?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"No es pot netejar:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"No s'han pogut trobar els paquets següents:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"No es pot gestionar el vot del paquet per a %s. Error: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"No es pot suprimir %s: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Versió\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Vots\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Versió del yay: v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"Ca[p]\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"s'avorta a causa de l'usuari\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"argument '-' especificat sense entrada a stdin\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"no es pot trobar PKGBUILD i SRCINFO al directori\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"no es pot trobar el nom del paquet: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"no s'ha pogut trobar PKGDEST per a %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"no s'han pogut trobar tots els paquets necessaris\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"no s'ha pogut trobar cap arxiu de paquets llistat a %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"dependència\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"la comprovació del paquet ha fallat: %s ha trobat un error\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"l'editor no ha sortit correctament, s'avorta: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"error en baixar les fonts: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"error en obtenir %s: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"error en instal·lar paquets dels repositoris\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"error d'instal·lació:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"error de construcció: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"error en combinar %s: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"error en llegir %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"error en actualitzar les bases de dades\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"error en restablir %s: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"error en actualitzar el motiu d'instal·lació del paquet a %s\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"explícit\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"ha fallat crear el directori %s: %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"ha fallat obrir el fitxer de configuració %s: %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"ha fallat analitzar %s, s'omet: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"no s'ha pogut analitzar %s: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"ha fallat analitzar .SRCINFO\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"ha fallat llegir el fitxer de configuració %s: %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"ha fallat obtenir la cau de l'AUR\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"\"\n\"s'ignora l'actualització del paquet de desenvolupament (no se n'ha trobat \"\n\"cap informació a l'AUR):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"entrada massa llarga\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"número no vàlid: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"opció no vàlida: %s\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"opció no vàlida: \\\"--deps\\\" i \\\"--explicit\\\" no es poden usar juntes\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"repositori no vàlid\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"valor no vàlid: %d no és entre %d i %d\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"no\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"sense claus per importar\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"no s'ha executat cap consulta\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"no s'han especificat directoris de destinació\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"no hi ha res per instal·lar per %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"només es pot usar una operació alhora\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"només es permet una destinació\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"paquet\"\nmsgstr[1] \"paquets\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"no s'ha trobat el paquet %s\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"paquet no trobat a l'AUR\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"paquet no trobat als repositoris\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"problema d'importació de claus\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"se suprimeixen paquets de l'AUR de la memòria cau...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"\"\n\"se suprimeixen els fitxers de l'AUR sense seguiment de la memòria cau...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"el PKGDEST per a %s està llistat per makepkg però no existeix:%s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"No hi ha res per fer.\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"no se'n pot crear el maneig: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"operació no manejada\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"versió desconeguda\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"sí\"\n"
  },
  {
    "path": "po/ca_ES.po",
    "content": "# \n# Translators:\n# Davidmp <medipas@gmail.com>, 2025\n# \nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: Davidmp <medipas@gmail.com>, 2025\\n\"\n\"Language-Team: Catalan (Spain) (https://app.transifex.com/yay-1/teams/123732/ca_ES/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: ca_ES\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Directori de construcció:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Introduïu un número (per defecte = 1):\"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \"(Els fitxers de compilació ja existeixen)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \"(Instal·lat)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \"[Instal·lat]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \"No hi ha res per fer.\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"%s [T]ot [Av]orta [I]nstal·lat [No] instal·lat o (1 2 3, 1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s ja fet: se n'omet la construcció.\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s no està establert.\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s és present.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s està al dia: s'omet.\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s per actualitzar / instal·lar.\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%s també s'instal·larà per a aquesta operació.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, requerit per %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: sense canvis, s'omet.\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: no es pot usar l'objectiu amb l'opció --aur, s'omet.\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: no es pot usar l'objectiu amb l'opció --repo, s'omet.\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: s'ignora l'actualització del paquet (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: el paquet local (%s) és més nou que el de l'AUR (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"\"\n\"%s: establiu les variables d'entorn AUR_NOMDUSUARI i AUR_CONTRASENYA per \"\n\"votar.\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) PKGBUILD baixat de l'ABS: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) PKGBUILD baixat: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) Ha fallat baixar el PKGBUILD: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) S'analitza SRCINFO: %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(Instal·lat)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(Instal·lat: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Orfes)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Obsolet: %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"URL de l'AUR\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Afegiu %s o %s a les variables d'entorn.\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Eviteu executar el yay com a root / sudo.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Comprova'n la dependència\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Comprova les dependències\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"Es comproven els paquets de desenvolupament...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Es neteja (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Té conflicte amb\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Se suprimeix (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Dependència\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Depèn de\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Descripció\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Diferències per mostrar?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"Desactiva la configuració de \\\"proporciona\\\" per defecte.\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"Voleu suprimir TOTS els paquets de l'AUR de la memòria cau?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"Voleu suprimir TOTS els fitxers de l'AUR sense seguiment?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"Voleu suprimir tots els altres paquets de l'AUR de la memòria cau?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"Amb què voleu editar el PKGBUILD?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Error durant la cerca a l'AUR: %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"L'exclusió de paquets pot provocar actualitzacions parcials i trencar els \"\n\"sistemes.\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Explícit\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Paquets instal·lats explícitament: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"No s'ha pogut trobar el paquet de l'AUR per a\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"Ha fallat instal·lar la capa. Es passa a la següent.\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"Ha fallat instal·lar els paquets següents. Cal intervenció manual:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Enviat primer\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Paquets de l'AUR obsolets marcats:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Paquets forans instal·lats: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"S'ha trobat el repositori git: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB ha acabat. No s'ha instal·lat cap paquet.\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Grups\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Ho importo?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"S'importen claus amb gpg...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Paraules clau\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Darrera modificació\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Llicències\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Local\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Mantenidor\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Dependència de construcció\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Dependències de construcció\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Manca\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Manquen paquets de depuració de l'AUR:\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Nom\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:564\nmsgid \"No AUR package found for\"\nmsgstr \"No s'ha trobat cap paquet d'AUR per a\"\n\n#: pkg/dep/dep_graph.go:564\nmsgid \"required by\"\nmsgstr \"requerit per \"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"No s'ha trobat cap paquet per\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Cap\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Dependències opcionals\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Paquets d'AUR orfes (no mantinguts):\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Obsolet\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"Cal importar claus PGP:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD actualitzat, s'omet la baixada: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"PKGBUILDs per editar?\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Base de paquets\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"ID de la base de paquets\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"Paquets no a l'AUR:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Paquets per a la neteja de la construcció?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Paquets per excloure\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"Paquets per excloure: (p. ex.: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" o nom del repositori)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Paquets per instal·lar (p. ex.: 1 2 3, 1-3 o ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Popularitat\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Voleu continuar la instal·lació?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Proporciona\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"\"\n\"Suprimeixo les dependències de construcció després de la instal·lació?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Reemplaça\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"Repositori\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"Repositori de l'AUR\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Se cerquen actualitzacions a l'AUR...\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"Se cerquen actualitzacions a les bases de dades...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Es mostren només paquets dels repositoris.\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"Mida de la memòria cau del pacman %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"Mida de la memòria cau del yay %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"URL de la instantània\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Sincronització\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"Els deu paquets més grossos:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"Els paquets següents no són compatibles amb la vostra arquitectura:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"Hi ha %[1]d proveïdors disponibles per a %[2]s:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"\"\n\"Pot ser que hi hagi una altra instància del Pacman en execució. S'espera...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Mida total ocupada pels paquets: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Total de paquets instal·lats: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Intento construir-los tanmateix?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"No es pot netejar:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"No s'han pogut trobar els paquets següents:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"No es pot gestionar el vot del paquet per a %s. Error: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"No es pot suprimir %s: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Versió\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Vots\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Versió del yay: v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"Ca[p]\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"s'avorta a causa de l'usuari\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"argument '-' especificat sense entrada a stdin\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"no es pot trobar PKGBUILD i SRCINFO al directori\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"no es pot trobar el nom del paquet: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"no s'ha pogut trobar PKGDEST per a %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"no s'han pogut trobar tots els paquets necessaris\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"no s'ha pogut trobar cap arxiu de paquets llistat a %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"dependència\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"la comprovació del paquet ha fallat: %s ha trobat un error\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"l'editor no ha sortit correctament, s'avorta: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"error en baixar les fonts: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"error en obtenir %s: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"error en instal·lar paquets dels repositoris\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"error d'instal·lació:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"error de construcció: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"error en combinar %s: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"error en llegir %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"error en actualitzar les bases de dades\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"error en restablir %s: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"error en actualitzar el motiu d'instal·lació del paquet a %s\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"explícit\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"ha fallat crear el directori %s: %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"ha fallat obrir el fitxer de configuració %s: %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"ha fallat analitzar %s, s'omet: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"no s'ha pogut analitzar %s: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"ha fallat analitzar .SRCINFO\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"ha fallat llegir el fitxer de configuració %s: %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"ha fallat obtenir la cau de l'AUR\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"\"\n\"s'ignora l'actualització del paquet de desenvolupament (no se n'ha trobat \"\n\"cap informació a l'AUR):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"entrada massa llarga\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"número no vàlid: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"opció no vàlida: %s\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"opció no vàlida: \\\"--deps\\\" i \\\"--explicit\\\" no es poden usar juntes\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"repositori no vàlid\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"valor no vàlid: %d no és entre %d i %d\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"no\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"sense claus per importar\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"no s'ha executat cap consulta\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"no s'han especificat directoris de destinació\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"no hi ha res per instal·lar per %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"només es pot usar una operació alhora\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"només es permet una destinació\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"paquet\"\nmsgstr[1] \"paquets\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"no s'ha trobat el paquet %s\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"paquet no trobat a l'AUR\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"paquet no trobat als repositoris\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"problema d'importació de claus\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"se suprimeixen paquets de l'AUR de la memòria cau...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"\"\n\"se suprimeixen els fitxers de l'AUR sense seguiment de la memòria cau...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"el PKGDEST per a %s està llistat per makepkg però no existeix:%s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"No hi ha res per fer.\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"no se'n pot crear el maneig: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"operació no manejada\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"versió desconeguda\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"sí\"\n"
  },
  {
    "path": "po/cs.po",
    "content": "#\n# Translators:\n# Fjuro Fjuro, 2022\n# a30a45d5047eb877c4dc397ded846f36_1de9be1, 2023\n# Matyáš Černý, 2023\n# walken, 2024\n#\nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: walken, 2024\\n\"\n\"Language-Team: Czech (https://app.transifex.com/yay-1/teams/123732/cs/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: cs\\n\"\n\"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \"(Soubory sestavení existují)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \"(Nainstalováno)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \"[Nainstalováno]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \"není co dělat\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"\"\n\"%s [A]Vše [Ab]Zrušit [I]Nainstalováno [No]Nenainstalováno nebo (1 2 3, 1-3, \"\n\"^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%sjiž existuje -- přeskakuji sestavení\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s není nastaven\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s je přítomný\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s je aktualizován -- přeskakuji\"\n\n#: pkg/upgrade/service.go:292\nmsgid \"%s to upgrade/install.\"\nmsgstr \" %s k povýšení/instalaci.\"\n\n#: pkg/upgrade/service.go:286\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%s bude také nainstalován pro tuto operaci. \"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, vyžadován balíčkem %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: Žádné změny -- přeskakuji\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: nelze použít cíl s možností --aur -- přeskakuji\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: nelze použít cíl s možností --repo -- přeskakuji\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: ignoruji aktualizaci balíčku (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: místní (%s) je novější než AUR (%s) \"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"\"\n\"prosím nastavte proměnné prostředí AUR_USERNAME a AUR_PASSWORD pro hodnocení\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) Stažen PKGBUILD z ABS: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) Stažen PKGBUILD: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) Nepodařilo se stáhnout PKGBUILD\\\\: %s \"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) Parsování SRCINFO: %s\"\n\n#: pkg/query/types.go:72 pkg/query/types.go:103\nmsgid \"(Installed)\"\nmsgstr \"(Nainstalováno)\"\n\n#: pkg/query/types.go:70 pkg/query/types.go:101\nmsgid \"(Installed: %s)\"\nmsgstr \"(Nainstalováno: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Osamocené)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Zastaralé: %s)\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"URL AUR\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Přidejte %s nebo %s do svých proměnných prostředí \"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Vyhněte se spuštění yay jako root/sudo.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Zkontrolovat závislost\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Zkontrolovat závislosti\"\n\n#: pkg/upgrade/service.go:90\nmsgid \"Checking development packages...\"\nmsgstr \"Kontrola vývojových balíčků...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Čištění (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Konflikt s\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Mazání (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Závislost\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Závisí na\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Popis\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Zobrazit rozdíly?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"Zákaz nastavení 'provides' jako výchozí\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"Chcete odstranit VŠECHNY balíčky AUR z mezipaměti?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"Chcete odstranit VŠECHNY nesledované soubory AUR?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"Chcete odstranit všechny ostatní balíčky AUR z mezipaměti?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"Upravit PKGBUILD pomocí?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Chyby při hledání v AUR: %s\\n\"\n\n#: pkg/upgrade/service.go:296\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"Vyjímání balíčků může způsobovat částečné aktualizace a rozbíjet systémy.\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Explicitní\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Explicitně nainstalované balíčky: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"Chyba hledání balíčku AUR:\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"Chyba instalace vrstvy, zabaluji k další vrstvě.\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"Selhala instalace těchto balíčků. Ruční zásah je vyžadován.\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"První odeslané\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Označené zastaralé balíčky AUR:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Neznámé nainstalované balíčky: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Nalezen repozitář git: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB dokončena. Nebyly nainstalovány žádné balíčky\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Skupiny\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Importovat?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"Importování klíčů pomocí gpg...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Klíčová slova\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Naposledy upraveno\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Licence\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Místní\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Správce\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Závislosti pro sestavení\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Vytvořit závislosti\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Chybějící ladicí balíčky AUR:\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Chybějící\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Název\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:548\nmsgid \"No AUR package found for\"\nmsgstr \"AUR balíček nenalezen pro\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"Nebyly nalezeny žádné balíčky pro\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Žádné\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Volitelné závislosti\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Osamocené (neudržované) balíčky AUR:\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Zastaralé\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"Je třeba importovat klíče PGP:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD je aktuální, přeskakuji: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"PKGBUILDy k upravení?\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"Základní ID aplikace\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Základ aplikace\"\n\n#: pkg/query/aur_warnings.go:67\nmsgid \"Packages not in AUR:\"\nmsgstr \"Balíčky mimo AUR:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Balíčky ke cleanBuild?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Balíčky k vyjmutí.\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"Balíčky k vyloučení: (např.: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" nebo název repozitáře)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Balíčky k instalaci (např.: 1 2 3, 1-3 nebo ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Popularita\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Pokračovat v instalaci?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Poskytuje\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"Odstranit vytvořené závislosti po instalaci?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Nahrazuje\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"Repozitář AUR\"\n\n#: print.go:30 pkg/db/ialpm/alpm.go:191\nmsgid \"Repository\"\nmsgstr \"Repozitář\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:72\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Prohledávání AUR pro aktualizace...\"\n\n#: pkg/upgrade/service.go:160\nmsgid \"Searching databases for updates...\"\nmsgstr \"Prohledávání databází k aktualizaci...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Zobrazování pouze balíčků repozitáře\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"Velikost mezipaměti pacman %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"Velikost mezipaměti yay %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"URL snapshotu\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Synchronizace\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"Deset největších balíčků\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"Následující balíčky nejsou kompatibilní s vaší architekturou:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"Pro %[2]s je dostupných %[1]d poskytovatelů:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"Možná běží další instance Pacman. Čekání...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Celková velikost zabraná balíčky: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Celkem nainstalovaných balíčků: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Pokusit se je přesto sestavit?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"Nepodařilo se vyčistit:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"Nepodařilo se nalézt následující balíčky:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"Nelze hlasovat pro balíček: %s. chyba: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"Nelze odebrat %s:%s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Verze\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Hlasy\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Verze yay v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N]Žádné\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Adresář sestavení:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Zadejte číslo (výchozí=1):\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"rušení kvůli uživateli\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"argument '-' použit bez vstupu na stdin\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"PKGBUILD a .SRCINFO nebyly nalezeny ve složce\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"nepodařilo se nalézt název balíčku: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"nepodařilo se nalézt PKGDEST pro: %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"Nepodařilo se nalézt všechny požadované balíčky\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"nenalezeny žádné archivy balíčků v %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:287\nmsgid \"dependency\"\nmsgstr \"závislost\"\n\n#: pkg/vcs/vcs.go:96 pkg/vcs/vcs.go:100\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"kontrola devel balíčku selhala: '%s' narazil na chybu\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"editor nebyl úspěšně ukončen, rušení: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"chyba při stahování zdrojů: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"chyba při načítání %s: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"chyba při instalaci balíčků repozitáře\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"chyba při instalaci:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"chyba při vytváření: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"chyba při slučování %s: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"chyba při čtení %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"chyba při obnovování databází\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"chyba při resetování %s: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"chyba při aktualizaci důvodu instalace balíčku na\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"explicitní\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"nepodařilo se vytvořit adresář '%s': %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"nepodařilo se otevřít konfigurační soubor '%s': %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"nepodařilo se parsovat %s -- přeskakuji: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"nepodařilo se parsovat %s: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"nepodařilo se parsovat .SRCINFO\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"nepodařilo se přečíst konfigurační soubor '%s': %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"nepodařilo se získat aur Cache\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"ignoruji vývojovou aktualizaci balíčku (AUR informace nenalezeny)\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"vstup příliš dlouhý\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"neplatné číslo: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"neplatná možnost '%s'\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"\"\n\"neplatná možnost: '--deps' a '--explicit' nemohou být použity současně\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"neplatný repozitář\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"neplatná hodnota: %d není mezi %d a %d\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"žádné klíče k importování\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"nebyl vykonán žádný dotaz\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"nebyly specifikovány cílové adresáře\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"ne\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"nic k nainstalování pro %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"naráz může být použita pouze jedna operace\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"je dovolený pouze jeden cíl\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"balíček '%s' nebyl nalezen\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"balíček nenalezen v AUR\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"balíček nenalezen v repozitářích\"\n\n#: pkg/upgrade/service.go:292\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"balíček\"\nmsgstr[1] \"balíčky\"\nmsgstr[2] \"balíčky\"\nmsgstr[3] \"balíčky\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"problém při importování klíčů\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"odstraňování balíčků AUR z mezipaměti...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"odstraňování nesledovaných souborů AUR z mezipaměti...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"PKGDEST pro %s je v seznamu makepkg ale neexistuje: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"není co dělat\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"nepodařilo se CreateHandle: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"neznámá operace\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"neznámá-verze\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"ano\"\n"
  },
  {
    "path": "po/de.po",
    "content": "# \n# Translators:\n# Julian Neupert <julian.neupert@gmail.com>, 2021\n# Chris Boesch, 2021\n# Oliver Conzen, 2021\n# J G, 2022\n# Andre Bouillet, 2022\n# cf9fef41dd781c154ed35b0d2df25c28_1d7ee01, 2022\n# Lukas Müller (Lukas), 2022\n# Arne Brücher, 2023\n# Ananas 77, 2023\n# 452f4d2d2d15be3f170375e4fa84f9da_7bd63b3, 2023\n# Lukas Esc, 2023\n# Manuel Schneider, 2023\n# Marethyu _, 2023\n# Severin Hamader <severin.hamader@yahoo.de>, 2025\n# 0x3C50 No, 2026\n# \nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: 0x3C50 No, 2026\\n\"\n\"Language-Team: German (https://app.transifex.com/yay-1/teams/123732/de/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: de\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Build-Verzeichnis:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Geben Sie eine Zahl ein (Vorgabe=1):\"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \" (Build-Dateien sind vorhanden)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \" (Installiert)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \"[Installiert]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \" es gibt nichts zu tun\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"\"\n\"%s [A]lle [Ab]brechen [I]nstalliert [No]nicht installiert oder (1 2 3, 1-3, \"\n\"^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s Bereits erledigt -- Build wird übersprungen\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s ist nicht definiert\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s ist vorhanden.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s ist bereits aktuell -- wird übersprungen\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s zu upgraden/installieren.\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%s wird für diesen Vorgang ebenfalls installiert.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, benötigt von: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: Keine Änderungen -- wird übersprungen\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: Argument --aur nicht möglich -- wird übersprungen\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: Argument --repo nicht möglich -- wird übersprungen\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: Ignoriere Paketaktualisierung (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: lokales (%s) ist neuer als das AUR (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"\"\n\"Bitte AUR_USERNAME und AUR_PASSWORD Umgebungsvariablen setzen um abzustimmen\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) PKGBUILD von ABS heruntergeladen: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) PKGBUILD heruntergeladen: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) Es wurde nicht geschaft PKGBUILD zu aktualisieren: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) SRCINFO geparst: %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(Installiert)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(Installiert: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Verwaist)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Veraltet: %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"AUR-URL\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"%s oder %s zu den Umgebungsvariablen hinzufügen\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Vermeide es yay als root/sudo zu nutzen!\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Überprüfe Abhängigkeiten\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Prüfe Abhängigkeiten\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"Prüfe Entwicklungspakete...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Säubere (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Ist in Konflikt mit\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Lösche (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Abhängigkeit\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Ist abhängig von\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Beschreibung\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Unterschiede zeigen?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"'provides' Einstellung automatisch abschalten\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"Wollen Sie ALLE AUR-Pakete aus dem Cache entfernen?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"Wollen Sie ALLE nicht überwachten AUR-Dateien entfernen?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"Wollen Sie alle anderen AUR-Pakete aus dem Cache entfernen?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"PKGBUILD editieren mit?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Fehler während AUR-Suche: %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"Das Ausschließen von Paketen kann zu teilweisen Aktualisierungen führen und \"\n\"Systeme beschädigen.\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Explizit\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Explizit installierte Pakete: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"AUR-Paket nicht gefunden für\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"\"\n\"Die Installationsschicht ist fehlgeschlagen, es wird zur nächsten Schicht \"\n\"übergegangen.\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"\"\n\"Die folgenden Pakete konnten nicht installiert werden. Ein manueller \"\n\"Eingriff ist erforderlich:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Erstmals eingereicht\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Als nicht aktuell markierte AUR-Pakete:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Installierte Fremdpakete: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Git-Repo gefunden: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB beendet. Es wurden keine Pakete installiert\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Gruppen\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Importieren?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"Importiere Schlüssel mit gpg...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Stichworte\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Zuletzt geändert\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Lizenzen\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Lokal\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Betreuer\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Erstelle Abhängigkeit.\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Abhängigkeiten herstellen\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Fehlend\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Fehlende AUR Debug-Pakete: \"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Name\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:564\nmsgid \"No AUR package found for\"\nmsgstr \"Kein AUR-Paket gefunden für\"\n\n#: pkg/dep/dep_graph.go:564\nmsgid \"required by\"\nmsgstr \"benötigt von\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"Kein gefunden für\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Keine\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Optionale Abhängigkeiten\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Verwaiste (nicht gepflegte) AUR-Pakete:\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Veraltet\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"PGP-Schlüssel müssen importiert werden: \"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD ist auf dem neuesten Stand, überspringe Herunterladen: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"Welche PKGBUILDs editieren?\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Paketbasis\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"Paket-Basis-ID\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"Pakete nicht im AUR:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Pakete neu erstellen?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Auszuschließende Pakete\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"Pakete zum Ausschließen: (z.B. \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" oder Repo-Name)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Zu installierende Pakete: (z.B. 1 2 3, 1-3 oder ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Beliebtheit\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Mit der Installation fortfahren?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Bietet\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"Abhängigkeiten nach der Installation entfernen?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Ersetzt\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"Repository\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"Repository AUR\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Durchsuche AUR nach Updates...\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"Durchsuche Datenbanken nach Updates...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Zeige nur Repo-Pakete\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"Größe des pacman-Cache %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"Größe des yay-Cache %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"Snapshot-URL\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Synchronisieren\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"Die zehn größten Pakete:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"Die folgenden Pakete sind mit Ihrer Architektur inkompatibel:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"Es sind %[1]d Anbieter verfügbar für %[2]s:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"Eine andere Instanz von Pacman ist aktiv. Warte...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Gesamtgröße der installierten Pakete: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Insgesamt installierte Pakete: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Build trotzdem versuchen?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"Kann nicht entfernen:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"Konnte die folgenden Pakete nicht finden: \"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"Paketabstimmung nicht möglich für:%s. Fehler: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"Kann nicht entfernt werden %s: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Version\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Stimmen\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Yay-Version v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N] Keine\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"Abbruch durch den Benutzer\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"Argument '-' ohne Eingabe in stdin angegeben\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"kann PKGBUILD und .SRCINFO im Verzeichnis nicht finden\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"Kann Paketname nicht finden: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"Kann PKGDEST nicht finden für: %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"konnte nicht alle erforderlichen Pakete finden\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"konnte keine Paketarchive finden ist nicht aufgeführt in %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"Abhängigkeit\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"Entwicklungstest fehlgeschlagen für Paket: '%s' Fehler gefunden.\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"Editor wurde nicht erfogreich beendet, breche ab: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"Fehler beim Herunterladen der Quellen: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"Fehler beim Abrufen von %s: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"Fehler bei der Installation der Repo-Pakete\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"Fehler bei der Installation: \"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"Fehler beim Erstellen: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"Fehler beim Zusammenführen von %s: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"Fehler beim Lesen von %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"Fehler beim Aktualisieren der Datenbanken\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"Fehler beim Zurücksetzen von %s: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"Fehler bei der Aktualisierung der Paket-Installation aufgrund von %s\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"explizit\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"Fehler beim Erstellen von Verzeichnis '%s': %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"Fehler beim Öffnen der Konfigurationsdatei '%s': %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"Fehler beim Parsen von %s -- überspringe: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"Fehler beim Parsen von: %s: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"Fehler von Parsen von .SRCINFO\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"Fehler beim Lesen der Konfigurationsdatei '%s': %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"Erhalten des AUR Caches ist fehlgeschlagen\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"ignoriere devel Paket Aktualisierung (keine AUR Info gefunden):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"Eingabe zu lang\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"Ungültige Nummer: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"Ungültige Option '%s'\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"\"\n\"Ungültige Option: '--deps' und '--explicit' können nicht zusammen genutzt \"\n\"werden\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"Ungültiges Repository\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"Ungültiger Wert: %d ist nicht zwischen %d und %d\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"nein\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"Keine Schlüssel zu importieren\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"Es wurde keine Abfrage ausgeführt\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"Kein Ziel Verzeichnis angegeben\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"nichts zu installieren für %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"Nur eine Operation kann gleichzeitig benutzt werden\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"Nur ein Ziel ist erlaubt\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"Paket\"\nmsgstr[1] \"Pakete\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"Paket '%s' konnte nicht gefunden werden\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"Paket nicht im AUR gefunden\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"Paket nicht in den Repos gefunden\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"Problem beim Importieren der Schlüssel\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"Entferne AUR-Pakete aus dem Cache...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"Entferne nicht überwachte AUR-Dateien aus dem Cache...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"PKGDEST für %s ist in MAKEPKG aufgeführt, existiert aber nicht: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"es gibt nichts zu tun\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"Kann CreateHandle nicht erstellen: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"Unbehandelte Operation\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"Unbekannte Version\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"ja\"\n"
  },
  {
    "path": "po/en.po",
    "content": "msgid \"\"\nmsgstr \"\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: \\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\n#: pkg/db/ialpm/alpm.go:201\n#: pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \"\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \"\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \"\"\n\n#: cmd.go:410\n#: vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \"\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:460\n#: pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"\"\n\n#: vote.go:51\nmsgid \"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for voting\"\nmsgstr \"\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"\"\n\n#: pkg/download/aur.go:92\n#: pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"\"\n\n#: pkg/query/types.go:103\n#: pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"\"\n\n#: pkg/query/types.go:101\n#: pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:437\n#: pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:442\n#: pkg/dep/dep_graph.go:564\nmsgid \"No AUR package found for\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:564\nmsgid \"required by\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"\"\n\n#: print.go:53\n#: print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"\"\n\n#: pkg/menus/diff_menu.go:172\n#: pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"\"\n\n#: pkg/db/ialpm/alpm.go:191\n#: print.go:30\nmsgid \"Repository\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"\"\n\n#: pkg/db/ialpm/alpm.go:179\n#: pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"\"\n\n#: clean.go:194\n#: pkg/menus/clean_menu.go:65\n#: pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"\"\n\n#: get.go:42\n#: get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"\"\n\n#: pkg/sync/build/errors.go:50\n#: pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"\"\n\n#: pkg/vcs/vcs.go:100\n#: pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"\"\n\n#: pkg/sync/build/installer.go:266\n#: pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"\"\n\n#: pkg/sync/build/installer.go:233\n#: pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"\"\n\n#: pkg/sync/workdir/clean.go:51\n#: pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"\"\n\n#: pkg/cmd/graph/main.go:46\n#: pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"\"\n\n#: pkg/db/ialpm/alpm.go:222\n#: pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"\"\n\n#: pkg/db/ialpm/alpm.go:227\n#: pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"\"\n\n#: clean.go:178\n#: pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"\"\n"
  },
  {
    "path": "po/es.po",
    "content": "# \n# Translators:\n# J G, 2021\n# Ivan Garcia, 2021\n# Percy De La Rosa, 2022\n# Brighton Saldaña, 2022\n# Antonio Alvarado-Hernández, 2023\n# brandon galvis, 2023\n# Angel López, 2023\n# C C, 2023\n# Claudio Yanez, 2025\n# Pablo Lezaeta Reyes <prflr88@gmail.com>, 2025\n# \nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: Pablo Lezaeta Reyes <prflr88@gmail.com>, 2025\\n\"\n\"Language-Team: Spanish (https://app.transifex.com/yay-1/teams/123732/es/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: es\\n\"\n\"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Carpeta de compilación:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Introduzca un número (por omisión=1): \"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \" (Archivos de compilación existen)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \" (Instalado)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \" [Instalado]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \" no hay nada que hacer\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"%s [A]Todos [Ab]ortar [I]nstalados [No]Instalados o (1 2 3, 1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s ya creado -- omitiendo compilación\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s no está definido\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s está presente.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s está actualizado -- ignorando\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s por actualizar/instalar.\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%s también será instalado para esta operación.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, necesario para: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: Sin cambios -- ignorando\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"\"\n\"%s: no es posible utilizar el objetivo con la opción --aur -- ignorando\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"\"\n\"%s: no es posible utilizar el objetivo con la opción --repo -- ignorando\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: actualización del paquete ignorada (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"\"\n\"%s: paquete local (%s) es más nuevo que el paquete disponible en el AUR (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"\"\n\"%s: por favor, configure las variables de entorno AUR_USERNAME y \"\n\"AUR_PASSWORD para votar\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) PKGBUILD descargado de ABS: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) PKGBUILD Descargado : %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) No se pudo descargar el PKGBUILD: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) Analizando SRCINFO: %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(Instalado)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(Instalado: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Huérfano)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Desactualizado: %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"URL del AUR\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Añade %s o %s a tus variables de entorno\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Evite ejecutar yay como superusuario. root/sudo.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Verificar dependencia\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Dependencias de verificación\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"Verificando paquetes de desarrollo...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Limpiando (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Conflictos con\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Borrando (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Dependencia\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Depende de\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Descripción\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"¿Diffs a mostrar?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"Deshabilitar ajuste «provee» por omisión \"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"¿Quieres borrar TODOS los paquetes del AUR de la caché?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"¿Quieres borrar TODOS los archivos del AUR sin rastrear?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"¿Quieres borrar los otros paquetes del AUR de la caché?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"¿Editar PKGBUILD con?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Error al buscar en el AUR: %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"Excluir paquetes puede causar actualizaciones parciales y rupturas de \"\n\"sistemas\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Explícito\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Paquetes explícitamente instalados: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"No se pudo encontrar el paquete en el AUR para\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"No se pudo instalar la capa, rodando hacia la siguiente capa.\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"\"\n\"No se pudieron instalar los siguientes paquetes. Se requiere intervención \"\n\"manual:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Primera vez subido\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Paquetes del AUR marcados como desactualizados:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Paquetes exteriores instalados: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Repositorio git encontrado: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB finalizó. Ningún paquete fue instalado\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Grupos\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"¿Importar?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"Importando llaves con gpg...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Palabras clave\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Última vez modificado\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Licencias\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Local\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Responsable\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Crear dependencia\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Dependencias de compilación\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Ausente\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Paquetes de depuración del AUR faltantes:\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Nombre\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:548\nmsgid \"No AUR package found for\"\nmsgstr \"Ningún paquete del AUR para\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"No se encontró un paquete para\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Ninguno\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Dependencias opcionales\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Paquetes del AUR huérfanos (no mantenidos): \"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Desactualizado\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"Llaves PGP a importar:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD actualizado, omitiendo descarga: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"¿PKGBUILDs a editar?\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Paquete base\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"ID de paquete base\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"Paquetes que no están en el AUR:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"¿Paquetes a limpiar antes de compilar?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Paquetes a excluir\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"\"\n\"Paquetes a excluir: (ej.: «1 2 3», «1-3», «^4» o nombre del repositorio)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Paquetes a instalar (ej..: 1 2 3, 1-3 or ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Popularidad\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"¿Proceder con la instalación?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Provee\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"¿Borrar dependencias de instalación después de instalar?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Remplaza\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"Repositorio\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"Repositorio AUR\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Buscando actualizaciones en el AUR...\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"Buscando actualizaciones en los repositorios...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Mostrando solamente paquetes de los repositorios\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"Tamaño de la cache de pacman %s:%s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"Tamaño de la cache de yay %s:%s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"URL de snapshot\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Sincronizar\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"Diez paquetes más grandes:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"Los siguientes paquetes no son compatibles con su arquitectura:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"Existen %[1]d paquetes que proveen %[2]s:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"\"\n\"Es posible que exista otra instancia de Pacman en ejecución. Esperando...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Tamaño total ocupado por los paquetes: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Número de paquetes instalados: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"¿Intentar compilarlos de todas formas?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"No es posible limpiar:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"No es posible encontrar los siguientes paquetes:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"No se ha podido gestionar el voto del paquete para: %s. error: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"No se puede eliminar %s: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Versión\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Votos\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Versión de yay v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N]inguno\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"abortando por el usuario\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"argumento «-» especificado sin entrada en stdin\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"no se pudo encontrar PKGBUILD y .SRCINFO en el directorio\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"no es posible encontrar el paquete: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"no fue posible encontrar PKGDEST para: %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"no se han encontrado todos los paquetes necesarios\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"no pudo encontrar ningún archivo de paquetes listado en %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"dependencia\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"\"\n\"la verificación de desarrollo para el paquete ha fallado: «%s» se encontró \"\n\"un error\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"el editor no terminó correctamente, abortando: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"error descargando fuentes: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"error descargando %s: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"error instalando paquetes del repositorio\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"error al instalar:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"error al compilar: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"error al fusionar %s: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"error leyendo %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"error refrescando las bases de datos\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"error al reiniciar en %s: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"error al actualizar el paquete motivo de instalación para %s\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"explícito\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"no se pudo crear directorio «%s»: %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"no se pudo al abrir archivo de configuración «%s»: %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"no se pudo analizar %s -- ignorando: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"no se pudo al analizar %s: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"no se pudo analizar .SRCINFO\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"no se pudo al leer archivo de configuración «%s»: %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"no se pudo recuperar el aur Cache\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"\"\n\"ignorando la actualización del paquete de desarollo (no se ha encontrado \"\n\"información en el AUR):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"entrada demasiado larga\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"número no válido: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"opción no válida «%s»\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"opción inválida: «--deps» y «--explicit» no deben usarse a la vez\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"repositorio inválido \"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"valor no válido: %d no está entre %d y %d\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"no\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"ninguna llave por importar\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"no se ha realizado ninguna consulta\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"no se han especificado directorios de destino\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"nada que instalar para %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"sólo una operación se puede usar a la vez\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"sólo se permite un objetivo\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"paquete\"\nmsgstr[1] \"paquetes\"\nmsgstr[2] \"paquetes\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"paquete «%s» no fue encontrado\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"paquete no encontrado en el AUR\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"paquete no encontrado en los repositorios \"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"problema al importar llaves\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"borrando paquetes del AUR de la caché...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"borrando archivos del AUR no rastreados de la caché...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"el PKGDEST para %s está listado por makepkg pero no existe: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"no hay nada que hacer\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"no fue posible ejecutar CreateHandle: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"operación no implementada\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"versión-desconocida\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"sí\"\n"
  },
  {
    "path": "po/eu.po",
    "content": "#\n# Translators:\n# J G <transifex@jguer.space>, 2021\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: PACKAGE VERSION\\n\"\n\"PO-Revision-Date: 2021-08-13 22:55+0000\\n\"\n\"Last-Translator: J G <transifex@jguer.space>, 2021\\n\"\n\"Language-Team: Basque (https://www.transifex.com/yay-1/teams/123732/eu/)\\n\"\n\"Language: eu\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \" (Konpilazio fitxategiak existitzen dira)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \" (Instalatuta)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \" [Instalatuta]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \" ez dago ezer egiteko\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"\"\n\"%s Guzti[A]k [Ab]ortatu [I]nstalatuak [No]Ez instalatuak edo (1 2 3, 1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s eginda dago jada -- konpilazioa alde batera uzten\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s ezarri gabe dago\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s presente dago.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s eguneratuta dago - alde batera uzten\"\n\n#: pkg/upgrade/service.go:292\n#, fuzzy\nmsgid \"%s to upgrade/install.\"\nmsgstr \"eguneratzeko pakete.\"\n\n#: pkg/upgrade/service.go:286\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, honek beharrezkoa du: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: Aldaketarik ez -- alde batera uzten\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: ezin da helburua --aur aukerarekin erabili -- alde batera uzten\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: ezin da helburua --repo aukerarekin erabili -- alde batera uzten\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: paketearen eguneraketa alde batera uzten (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: pakete lokala (%s) AURekoa (%s) baino berriagoa da\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for voting\"\nmsgstr \"\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) PKGBUILD ABStik deskargatuta: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\n#, fuzzy\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) PKGBUILD ABStik deskargatuta: %s\"\n\n#: pkg/download/aur.go:82\n#, fuzzy\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) PKGBUILD ABStik deskargatuta: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) SRCINFO aztertzen: %s\"\n\n#: pkg/query/types.go:72 pkg/query/types.go:103\nmsgid \"(Installed)\"\nmsgstr \"(Instalatuta)\"\n\n#: pkg/query/types.go:70 pkg/query/types.go:101\nmsgid \"(Installed: %s)\"\nmsgstr \"(Instalatuta: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Umezurtz)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Zaharkituta: %s)\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"AUReko URLa\"\n\n#: pkg/dep/dep_graph.go:75\n#, fuzzy\nmsgid \"AUR\"\nmsgstr \"URLa\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Gehitu %s edo %s zure ingurune-aldagaietara\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Saihestu yay root/sudo bezala exekutatzea.\"\n\n#: pkg/dep/dep_graph.go:63\n#, fuzzy\nmsgid \"Check Dependency\"\nmsgstr \"Egiaztapen menpekotasunak\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Egiaztapen menpekotasunak\"\n\n#: pkg/upgrade/service.go:90\nmsgid \"Checking development packages...\"\nmsgstr \"Garapen paketeak egiaztatzen...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"(%d/%d) garbitzen: %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Gatazkak hauekin\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"(%d/%d) ezabatzen: %s\"\n\n#: pkg/dep/dep_graph.go:61\n#, fuzzy\nmsgid \"Dependency\"\nmsgstr \"Behar du\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Behar du\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Deskribapena\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Aldaketak erakutsi?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"Cachean dauden AUR pakete GUZTIAK kendu nahi dituzu?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"Jarraipen gabeko AUR fitxategi GUZTIAK kendu nahi dituzu?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"Cachean dauden beste AUR paketeak kendu nahi dituzu?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"PKGBUILD zerekin editatu?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Errorea AURen bilatzerakoan: %s\\n\"\n\n#: pkg/upgrade/service.go:296\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Eskuz instalatutako paketeak: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\n#, fuzzy\nmsgid \"Failed to find AUR package for\"\nmsgstr \"Zaharkitu gisa markatutako AUR paketeak:\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Lehenengo bidalita\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Zaharkitu gisa markatutako AUR paketeak:\"\n\n#: print.go:90\n#, fuzzy\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Kanpotik instalatu diren paketeak: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Git biltegia aurkitu da: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB amaitu da. Ez da paketerik instalatu\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Taldeak\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Inportatu?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"Gakoak GPGrekin inportatzen...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Gako-hitzak\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Azken aldaketa\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Lizentziak\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Arduraduna\"\n\n#: pkg/dep/dep_graph.go:62\n#, fuzzy\nmsgid \"Make Dependency\"\nmsgstr \"Menpekotasunak burutzea\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Menpekotasunak burutzea\"\n\n#: pkg/query/aur_warnings.go:71\n#, fuzzy\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Faltan dauden AUR paketeak:\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Izena\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:548\nmsgid \"No AUR package found for\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Deus ez\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Hautazko menpekotasunak\"\n\n#: pkg/query/aur_warnings.go:75\n#, fuzzy\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Umezurtz geratu diren AUR paketeak:\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Zaharkituta\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"PGP gakoek inportatu behar dute:\"\n\n#: pkg/sync/workdir/preparer.go:252\n#, fuzzy\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD eguneratuta, alde batera uzten (%d/%d): %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"Editatzeko PKGBUILDak?\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"Pakete-oinarriaren IDa\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Pakete-oinarria\"\n\n#: pkg/query/aur_warnings.go:67\nmsgid \"Packages not in AUR:\"\nmsgstr \"\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Konpilatu aurretik garbitzeko paketeak?\"\n\n#: pkg/dep/dep_graph.go:202\n#, fuzzy\nmsgid \"Packages to exclude\"\nmsgstr \"eguneratzeko pakete.\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"\"\n\"Kanpoan uzteko paketeak: (adb: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" edo biltegiaren \"\n\"izena)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Instalatzeko paketeak (eg.: 1 2 3, 1-3 edo ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Ospea\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Instalatu?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Hornitzen du\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"Konpilatzeko menpekotasunak ezabatu instalatu ostean?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"AUR biltegia\"\n\n#: print.go:30 pkg/db/ialpm/alpm.go:191\nmsgid \"Repository\"\nmsgstr \"Biltegia\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"\"\n\n#: pkg/upgrade/service.go:72\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Eguneraketak AURen bilatzen...\"\n\n#: pkg/upgrade/service.go:160\nmsgid \"Searching databases for updates...\"\nmsgstr \"Datu-baseetan eguneraketak bilatzen...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Biltegietako paketeak soilik erakusten\"\n\n#: print.go:95\n#, fuzzy\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"%s analizatzeak huts egin du: %s\"\n\n#: print.go:98\n#, fuzzy\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"%s analizatzeak huts egin du: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"PKGBUILDaren argazkiaren URLa\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"Hamar pakete handienak:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"Ondorengo paketeak ez dira zure arkitekturarekin bateragarriak:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\n#, fuzzy\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"%[1]d hornitzaile eskuragarri %[2]s paketearentzat:\\n\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"Baliteke beste Pacman instantzia bat exekutzan aritzea. Zain...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Pakete guztiek erabilitako biltegiratzea: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Instalatu diren paketeak: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Saiatu konpilatzen hala ere?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URLa\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\n#, fuzzy\nmsgid \"Unable to clean:\"\nmsgstr \"ezin da CreateHandle burutu: %s\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"\"\n\n#: clean.go:170\n#, fuzzy\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"%s analizatzeak huts egin du: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Bertsioa\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Botoak\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Yay bertsioa v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"I[N]or ez\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Konpilazio direktorioa:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Idatzi zenbaki bat (lehenetsia=1): \"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"erabiltzailearengatik bertan behera uzten\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"ezin da paketearen izena aurkitu: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"ezin izan da aurkitu PKGDEST %s paketearentzat\"\n\n#: errors.go:9\n#, fuzzy\nmsgid \"could not find all required packages\"\nmsgstr \"Ez izan dira aurkitu beharrezko pakete guztiak:\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:287\n#, fuzzy\nmsgid \"dependency\"\nmsgstr \"Behar du\"\n\n#: pkg/vcs/vcs.go:96 pkg/vcs/vcs.go:100\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"editorea ez da behar bezala irten, bertan behera uzten: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"errorea iturriak deskargatzerakoan: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"errorea %s lortzerakoan: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"errorea biltegitako paketeak instalatzerakoan\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\n#, fuzzy\nmsgid \"error installing:\"\nmsgstr \"errorea biltegitako paketeak instalatzerakoan\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"konpilazio akatsa: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"errorea %s bateratzerakoan: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"errorea %s irakurtzerakoan\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"errorea datu-baseak freskatzerakoan\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"errorea %s berrezartzerakoan: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"'%s' konfigurazio direktorioa sortzeak huts egin du: %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"'%s' konfigurazio fitxategia irekitzeak huts egin du: %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"%s analizatzeak huts egin du -- alde batera uzten: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"%s analizatzeak huts egin du: %s\"\n\n#: local_install.go:77\n#, fuzzy\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"%s analizatzeak huts egin du: %s\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"'%s' konfigurazio fitxategia irakurtzeak huts egin du: %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"\"\n\n#: pkg/upgrade/sources.go:27\n#, fuzzy\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"%s: paketearen eguneraketa alde batera uzten (%s => %s)\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"sarrera luzeegia\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"zenbaki baliogabea: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"'%s' aukera baliogabea\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"\"\n\n#: pkg/download/abs.go:22\n#, fuzzy\nmsgid \"invalid repository\"\nmsgstr \"Biltegia\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"balio baliogabea: %d ez dago %d eta %d artean\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"inportatzeko gakorik ez\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"ez\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"aldi berean operazio bakarra erabil daiteke\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"ez da aurkitu '%s' paketea\"\n\n#: pkg/download/errors.go:15\n#, fuzzy\nmsgid \"package not found in AUR\"\nmsgstr \"ez da aurkitu '%s' paketea\"\n\n#: pkg/download/abs.go:23\n#, fuzzy\nmsgid \"package not found in repos\"\nmsgstr \"ez da aurkitu '%s' paketea\"\n\n#: pkg/upgrade/service.go:292\n#, fuzzy\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"Pakete-oinarria\"\nmsgstr[1] \"Pakete-oinarria\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"arazoa gakoak inportatzerakoan\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"AUR paketeak cachetik kentzen...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"jarraipen gabeko AUR fitxategiak cachetik kentzen...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"\"\n\"%s(e)rako PKGDESTa makepkg-ek zerrendatzen du, baina ez da existitzen: %s\"\n\n#: pkg/sync/sync.go:45\n#, fuzzy\nmsgid \"there is nothing to do\"\nmsgstr \" ez dago ezer egiteko\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"ezin da CreateHandle burutu: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"sostengurik gabeko eragiketa\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"bertsio ezezaguna\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"bai\"\n\n#~ msgid \" (Target\"\n#~ msgstr \" (Helburua\"\n\n#~ msgid \" (Wanted by: \"\n#~ msgstr \" (Honek behar du: \"\n\n#~ msgid \" Input too long\"\n#~ msgstr \" Sarrera luzeegia\"\n\n#~ msgid \"Installing %s will remove:\"\n#~ msgstr \"%s instalatzeak ezabatuko du:\"\n\n#~ msgid \"%s already downloaded -- use -f to overwrite\"\n#~ msgstr \"%s deskargatuta dago -- erabili -f gainidazteko\"\n\n#~ msgid \"%s and %s unset\"\n#~ msgstr \"%s eta %s ezarri gabe\"\n\n#~ msgid \"%s not satisfied, flushing install queue\"\n#~ msgstr \"%s ez da betetzen, instalazio ilara ezabatzen\"\n\n#~ msgid \"Checking for conflicts...\"\n#~ msgstr \"Gatazkak bilatzen...\"\n\n#~ msgid \"Checking for inner conflicts...\"\n#~ msgstr \"Barneko gatazkak bilatzen...\"\n\n#~ msgid \"Conflicting packages will have to be confirmed manually\"\n#~ msgstr \"Pakete gatazkatsuak eskuz egiaztatu beharko dira\"\n\n#~ msgid \"Downloaded PKGBUILD (%d/%d): %s\"\n#~ msgstr \"(%d/%d) PKGBUILDak deskargatuta: %s\"\n\n#~ msgid \"Missing ABS packages:\"\n#~ msgstr \"Faltan dauden ABS paketeak:\"\n\n#~ msgid \"Querying AUR...\"\n#~ msgstr \"AURen bilatzen...\"\n\n#~ msgid \"\"\n#~ \"\\n\"\n#~ \"Inner conflicts found:\"\n#~ msgstr \"\"\n#~ \"\\n\"\n#~ \"Barne gatazkak aurkitu dira:\"\n\n#~ msgid \"\"\n#~ \"\\n\"\n#~ \"Package conflicts found:\"\n#~ msgstr \"\"\n#~ \"\\n\"\n#~ \"Pakete arteko gaztakak aurkitu dira:\"\n\n#~ msgid \"error cloning %s: %s\"\n#~ msgstr \"errorea %s klonatzerakoan: %s\"\n\n#~ msgid \"error during AUR search: %s\"\n#~ msgstr \"errorea AURen bilatzerakoan: %s\"\n\n#~ msgid \"failed to create BuildDir directory '%s': %s\"\n#~ msgstr \"'%s' BuildDir direktorioa sortzeak huts egin du: %s\"\n\n#~ msgid \"failed to get pkgbuild: %s: %s\"\n#~ msgstr \"PKGBUILD lortzeak huts egin du: %s: %s\"\n\n#~ msgid \"failed to link %s: %s\"\n#~ msgstr \"%s estekatzeak huts egin du: %s\"\n\n#~ msgid \"failed to open vcs file '%s': %s\"\n#~ msgstr \"'%s' VCS fitxategia irekitzeak huts egin du: %s\"\n\n#~ msgid \"failed to read vcs file '%s': %s\"\n#~ msgstr \"'%s' VCS fitxategia irakurtzeak huts egin du: %s\"\n\n#~ msgid \"invalid sort mode. Fix with yay -Y --bottomup --save\"\n#~ msgstr \"\"\n#~ \"ordenatzeko modu baliogabea. Konpondu 'yay -Y --bottomup --save' \"\n#~ \"exekutatzen\"\n\n#~ msgid \"no packages match search\"\n#~ msgstr \"paketerik ez dator bat bilaketarekin\"\n\n#~ msgid \"package conflicts can not be resolved with noconfirm, aborting\"\n#~ msgstr \"\"\n#~ \"pakete arteko gatazkak ezin dira noconfirm-ekin konpondu, bertan behera \"\n#~ \"uzten\"\n\n#~ msgid \"refusing to install AUR packages as root, aborting\"\n#~ msgstr \"\"\n#~ \"AUR paketeak root gisa instalatzeari uko egiten, bertan behera uzten\"\n\n#~ msgid \"failed to create cache directory '%s': %s\"\n#~ msgstr \"'%s' cache direktorioa sortzeak huts egin du: %s\"\n"
  },
  {
    "path": "po/fi.po",
    "content": "# Translators:\n# Joonas Miettinen, 2026\n# \nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: Joonas Miettinen, 2026\\n\"\n\"Language-Team: Finnish (https://app.transifex.com/yay-1/teams/123732/fi/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: fi\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Kääntöhakemisto:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Anna numero (oletusarvo=1):\"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \"(Kääntötiedostot ovat olemassa)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \"(Asennettu)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \"[Asennettu]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \"ei tehtävää\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"\"\n\"%s [A]Kaikki [Ab]Keskeytä [I]Asennettu [No]Ei asennettu tai (1 2 3, 1-3, ^4)\"\n\" \"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s on jo käännetty --- ei käännetä\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"asetusta %s ei ole asetettu\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s on olemassa.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"Asennuskohdetta %s ei tarvitse päivittää --- jatketaan\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s päivittääksesi tai asentaaksesi.\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"Myös %s asennetaan tätä toimenpidettä varten.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, tarpeellinen riippuvuus seuraavalle: %s \"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: Ei muutoksia -- jatketaan\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: kohdetta ei voi käyttää valinnalla --aur -- jätetään huomiotta\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: kohdetta ei voi käyttää valinnalla --repo -- jätetään huomiotta\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: pakettia ei päivitetä (%s => %s) \"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: paikallinen (%s) on uudempi kuin AUR:ssa (%s) \"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"\"\n\"%s: aseta ympäristömuuttujat AUR_USERNAME ja AUR_PASSWORD äänestääksesi \"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) PKGBUILD ladattu ABS:stä: %s \"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) PKGBUILD ladattu: %s \"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) PKGBUILDin lataaminen epäonnistui: %s \"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) Jäsennetään SRCINFO: %s \"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(Asennettu)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(Asennettu: %s) \"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Orvoksi jäänyt) \"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Vanhentunut: %s) \"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR \"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"AUR URL \"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Lisää %s tai %s ympäristömuuttujiisi\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"\"\n\"yay:ia ei suositella ajettavan pääkäyttäjänä tai sudo-komennon kanssa.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Tarkista riippuvuus\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Tarkista riippuvuudet\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"Tarkistetaan kehityspaketit...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Puhdistetaan (%d/%d): %s \"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Ei sovi seuraavan kanssa yhteen\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Poistetaan (%d/%d): %s \"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Riippuvuus\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Riippuu seuraavasta\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Kuvaus\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Näytä erot?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"Poista asetus 'provides' käytöstä oletusarvoisesti\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"Haluatko poistaa KAIKKI AUR-paketit välimuistista?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"Haluatko poistaa KAIKKI seuraamattomat AUR-tiedostot?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"Haluatko poistaa kaikki muut AUR-paketit välimuistista?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"Millä haluat muokata PKGBUILD-tiedostoa?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Virhe AUR-haun aikana: %s \\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"Pakettien jättäminen pois voi kohtaa osittaiseen päivitykseen ja voi rikkoa \"\n\"järjestelmiä\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Nimellä pyydetty\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Asennetut nimellä pyydetyt paketit: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"AUR-paketteja ei löytynyt seuraavalle(ille)\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"Kerroksen asennus epäonnistui, siirrytään seuraavaan kerrokseen.\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"\"\n\"Seuraavien pakettien asennus epäonnistui. Käyttäjältä edellytetään \"\n\"toimenpiteitä:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Ladattiin palveluun ensimmäistä kertaa\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Vanhentuneeksi merkityt AUR-paketit: \"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Vieraat asennetut paketit: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Seuraava git-tietovarasto löytyi: %s \"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB valmistui. Yhtään pakettia ei asennettu\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Ryhmät\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Tuo?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"Tuodaan avaimet gpg:in avulla...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Avainsanat\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Viimeksi muokattu\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Lisenssit\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Paikallinen\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Ylläpitäjä\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Kääntöriippuvuus\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Kääntöriippuvuudet\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Puuttuva(vat)\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Puuttuvat AUR-virheenkorjauspaketit:\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Nimi\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:564\nmsgid \"No AUR package found for\"\nmsgstr \"Seuraavalle(ville) ei löytynyt yhtään AUR-pakettia\"\n\n#: pkg/dep/dep_graph.go:564\nmsgid \"required by\"\nmsgstr \"on seuraavan edellyttämä: \"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"Yhtään pakettia ei löytynyt seuraavalle(ville)\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Ei mitään/yhtään\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Valinnaiset riippuvuudet\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Orvot (ei ylläpitäjää) AUR-paketit:\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Vanhentunut\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"PGP-avaimet täytyy tuoda:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD on uusin, jätetään lataamatta: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"Muokattavat PKGBUILD-tiedostot?\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Paketin perusta\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"Paketin perustan tunniste\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"Paketit joita ei löydy AUR:ista:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Paketit jotka haluat asentaa puhtaasti (cleanBuild)?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Pois jätettävät paketit\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"Pois jätettävät paketit (esim. \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" tai tietovarasto nimi)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Asennettavat paketit (esim. 1 2 3, 1-3 tai ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Suosio\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Jatka asennukseen?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Mahdollistaa\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"Poista kääntöriippuvuudet asennuksen jälkeen?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Korvaa\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"Tietovarasto\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"Tietovarasto AUR\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Etsitään päivityksitä AUR:ista...\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"Etsitään päivityksiä tietokannoista...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Vain tietovarastopaketit näytetään\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"pacman-välimuistin koko %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"yay-välimuistin koko %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"Tilannekuvan URL\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Synkronoi\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"Kymmenen suurinta pakettia:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"\"\n\"Seuraavat paketit eivät ole yhteensopivia tietokonearkkitehtuurisi kanssa:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"%s[1]d tarjoajaa saatavilla %[2]:lle:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"Toinen pacman-prosessi saattaa olla käynnissä. Odotetaan...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Paketit vievät muistia yhteensä: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Yhteensä asennettuja paketteja: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Yritä silti kääntää ne?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"Ei voida puhdistaa:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"Seuraavia paketteja ei löytynyt:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"Ääntä paketille %s ei voitu käsitellä. Virheviesti: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"Pakettia %s ei voitu poistaa: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Versio\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Äänet\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"yay-versio v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N]Ei yhtään\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"keskeytetään käyttäjän pyynnöstä\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"argumentti '-' annettu ilman stdin-syötettä\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"hakemistosta ei löydy PKGBUILD- ja .SRCINFO-tiedostoa\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"paketin nimeä ei löydy: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"PKGDEST ei löytynyt paketille %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"kaikkia vaadittuja paketteja ei löytynyt\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"yhtään pakettiarkistoa ei löytynyt listasta %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"riippuvuus\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"kehitystarkistus paketille '%s' kohtasi virheen\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"\"\n\"muokkausohjelma kaatui tai se suljettiin virheellisesti, keskeytetään: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"lähteiden lataaminen epäonnistui: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"kohteen %s noutaminen epäonnistui: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"tietovarastopakettien asentaminen epäonnistui\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"seuraavan(ien) asentaminen epäonnistui:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"seuraavan(ien) kääntäminen epäonnistui: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"kohteiden %s yhdistäminen epäonnistui: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"kohdetta %s ei voinut lukea\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"tietokantojen päivittäminen epäonnistui\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"kohteen %s nollaaminen epäonnistui: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"paketin päivittäminen epäonnistui; riippuvuus/nimellä pyydetty:  %s\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"nimellä pyydetty\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"hakemistoa '%s' ei voitu luoda: %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"asetustiedostoa '%s' ei voitu lukea: %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"kohteen '%s' jäsentäminen epäonnistui ja se jätetään välistä: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"kohteen '%s' jäsentäminen epäonnistui: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \".SRCINFOn jäsentäminen epäonnistui\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"asetustiedostoa '%s' ei voitu lukea: %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"AUR-välimuistia ei voitu noutaa\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"paketin kehityspäivitys jätetään huomiotta (AUR-tietoja ei löytynyt):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"syöte on liian pitkä\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"numero ei kelpaa: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"valinta ei kelpaa: '%s'\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"\"\n\"valinta ei kelpaa: valintoja '--deps' ja '--explicit' ei voi tehdä samaan \"\n\"aikaan\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"tietovarasto ei kelpaa\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"arvo ei kelpaa: %d ei ole %d:n ja %d:n välillä\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"ei\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"ei tuotavia avaimia\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"yhtään kyselyä ei toteutettu\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"yhtään kohdehakemistoa ei määritetty\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"ei asennettavaa valinnalla(oilla) %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"toimenpiteitä voi käyttää vain yhtä kerrallaan\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"vain yksi kohde sallitaan\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"paketit\"\nmsgstr[1] \"paketit\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"pakettia '%s' ei löytynyt\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"pakettia ei löytynyt AUR:ista\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"pakettia ei löytynyt tietovarastoista\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"avainten tuomisessa esiintyi ongelma\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"poistetaan AUR-paketit välimuistista...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"poistetaan seuraamattomat AUR-tiedostot välimuistista...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"\"\n\"paketin %s PKGDEST on makepkg:n listalla mutta sitä ei ole olemassa: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"ei tehtävää\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"käsittelyn luonti (CreateHandle) epäonnistui: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"käsittelemätön toimenpide\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"tuntematon versio\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"kyllä\"\n"
  },
  {
    "path": "po/fr.po",
    "content": "# Translators:\n# Benjamin Chenebault, 2023\n# anthony tonitch <d.tonitch@gmail.com>, 2024\n# Edgar Fournival, 2024\n# J G, 2024\n# Sylvain Bx, 2024\n# Mathias Brugger, 2024\n# Léane GRASSER, 2024\n# ariasuni <aria@ariasuni.eu>, 2026\n# \nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: ariasuni <aria@ariasuni.eu>, 2026\\n\"\n\"Language-Team: French (https://app.transifex.com/yay-1/teams/123732/fr/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: fr\\n\"\n\"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Répertoire de compilation :\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Saisissez un nombre (valeur par défaut : 1) :\"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \" (Les fichiers de compilation existent)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \" (Installé)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \" [Installé]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \" il n'y a rien à faire\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"%s [A]Tous [Ab]Annuler [I]nstallés [No]nInstallés ou (1 2 3, 1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s déjà créé -- compilation ignorée\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s n'est pas définie\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s existe.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s est à jour -- ignoré\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s à mettre à jour ou à installer.\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%s à installer pour effectuer cette opération.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, nécessaire pour : %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s : Aucun changement -- ignoré\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s : la cible est incompatible avec l'option --aur -- ignoré\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s : la cible est incompatible avec l'option --repo -- ignoré\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s : mise à jour du paquet ignorée (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"\"\n\"%s : le paquet local (%s) est plus récent que le paquet disponible sur l'AUR\"\n\" (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"\"\n\"%s : définissez les variables d'environnement AUR_USERNAME et AUR_PASSWORD \"\n\"avant de pouvoir voter\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) PKGBUILD téléchargé depuis l'ABS : %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) PKGBUILD téléchargé : %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) Échec du téléchargement du PKGBUILD : %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) Analyse du SRCINFO : %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(Installé)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(Installé : %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Orphelin)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Obsolète : %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"URL sur l'AUR\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Ajoutez %s ou %s à vos variables d'environnement\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Évitez d'exécuter yay en tant que root ou via sudo.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Dépendance de vérification\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Dépendances vérif.\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"Vérification des paquets de développement…\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Nettoyage (%d/%d) : %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Est en conflit avec\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Suppression (%d/%d) : %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Dépendance\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Dépend de\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Description\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Diffs à afficher ?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"Désactiver par défaut le paramètre \\\"provides\\\"\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"Voulez-vous supprimer TOUS les paquets de l'AUR dans le cache ?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"\"\n\"Voulez-vous supprimer TOUS les fichiers non suivis des paquets de l'AUR ?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"\"\n\"Voulez-vous supprimer tous les autres paquets de l'AUR dans le cache ?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"Modifier le PKGBUILD avec ?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Erreur lors de la recherche dans l'AUR : %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"L'exclusion de paquets peut mener à une mise à jour partielle de votre \"\n\"système et pourrait le casser\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Explicite\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Paquets installés explicitement : %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"Impossible de trouver un paquet sur l'AUR correspondant à\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"Échec de l'installation de la couche, passage à la couche suivante.\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"\"\n\"Échec de l'installation des paquets suivants. Une intervention manuelle est \"\n\"requise :\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Envoyé le\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Paquets de l'AUR marqués comme obsolètes :\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Paquets étrangers installés : %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Dépôt Git trouvé : %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB terminé. Aucun paquet n'a été installé\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Groupes\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Importer ?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"Importation des clés avec gpg…\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Mots-clés\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Modifié le\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Licences\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Local\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Mainteneur\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Dépendance de création\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Dépendances créat.\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Manquant\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Paquets de débogage de l'AUR manquants :\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Nom\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:564\nmsgid \"No AUR package found for\"\nmsgstr \"Aucun paquet trouvé sur l'AUR correspondant à\"\n\n#: pkg/dep/dep_graph.go:564\nmsgid \"required by\"\nmsgstr \"requis par\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"Aucun paquet trouvé correspondant à\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"--\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Dépendances opt.\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Paquets de l'AUR orphelins (non maintenus) :\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Obsolète\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"Des clés PGP doivent être importées :\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD à jour, téléchargement ignoré : %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"PKGBUILDs à modifier ?\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Paquet base\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"ID du paquet base\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"Paquets absents de l'AUR :\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Paquets à cleanBuild ?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Paquets à exclure\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"Paquets à exclure : (ex. « 1 2 3 », « 1-3 », « ^4 » ou noms de dépôt)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Paquets à installer (ex. 1 2 3, 1-3 ou ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Popularité\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Procéder à l'installation ?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Fournit\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"Supprimer les dépendances de création après l'installation ?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Remplace\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"Dépôt\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"Dépôt AUR\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Recherche des mises à jour sur l'AUR…\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"Recherche des mises à jour dans les bases de données…\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Affichage uniquement des paquets provenant des dépôts\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"Taille du cache de pacman %s : %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"Taille du cache de yay %s : %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"URL de l'instantané\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Sync\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"Les dix paquets les plus lourds :\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"Les paquets suivants sont incompatibles avec votre architecture :\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"%[1]d paquets fournissant %[2]s sont disponibles :\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"\"\n\"Il semblerait qu'une autre instance de Pacman soit en cours d'exécution. En \"\n\"attente…\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Taille totale occupée par les paquets : %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Nombre de paquets installés : %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Essayer quand même de les compiler ?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"Impossible de nettoyer :\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"Impossible de trouver les paquets suivants :\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"Impossible de gérer le vote pour : %s. Erreur : %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"Impossible de supprimer %s : %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Version\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Votes\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Yay version v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N]Aucun\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"abandon dû à l'utilisateur\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"argument '-' spécifié et aucune entrée dans stdin\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"\"\n\"impossible de trouver les fichiers PKGBUILD et .SRCINFO dans le répertoire\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"impossible de trouver le nom de paquet : %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"impossible de trouver le PKGDEST pour : %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"impossible de trouver tous les paquets requis\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"aucune archive de paquet trouvée parmi celles listées dans %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"dépendance\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"\"\n\"échec de la vérification du paquet de développement : '%s' a rencontré une \"\n\"erreur\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"l'éditeur ne s'est pas terminé avec succès, abandon : %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"erreur lors du téléchargement des sources : %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"erreur lors de la récupération de %s : %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"erreur lors de l'installation des paquets provenant des dépôts\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"erreur lors de l'installation de :\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"erreur lors de la compilation de : %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"erreur lors de la fusion (%s) : %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"erreur lors de la lecture de %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"erreur lors de l'actualisation des bases de données\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"erreur lors de la réinitialisation de %s : %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"\"\n\"erreur lors de la modification du motif d'installation du paquet en « %s »\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"explicite\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"échec de la création du répertoire '%s' : %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"échec de l'ouverture du fichier de configuration '%s' : %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"échec de l'analyse de %s -- ignoré : %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"échec de l'analyse de %s : %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"échec de l'analyse du .SRCINFO\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"échec de la lecture du fichier de configuration '%s' : %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"échec de la récupération du cache AUR\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"\"\n\"mise à jour du paquet de développement ignorée (infos AUR introuvables) :\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"entrée trop longue\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"nombre invalide : %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"option '%s' invalide\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"\"\n\"option invalide : '--deps' et '--explicit' ne peuvent pas être utilisés \"\n\"ensemble\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"dépôt invalide\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"valeur invalide : %d n'est pas entre %d et %d\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"non\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"aucune clé à importer\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"aucune requête n'a été exécutée\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"aucun répertoire cible spécifié\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"rien à installer pour %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"une seule opération peut être réalisée à la fois\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"une seule cible est autorisée\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"paquet\"\nmsgstr[1] \"paquets\"\nmsgstr[2] \"paquets\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"le paquet '%s' est introuvable\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"paquet introuvable dans l'AUR\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"paquet introuvable dans les dépôts\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"erreur lors de l'importation des clés\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"suppression des paquets de l'AUR du cache…\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"\"\n\"suppression des fichiers non suivis dans les paquets de l'AUR en cache…\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"le PKGDEST pour %s est listé par makepkg mais n'existe pas : %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"il n'y a rien à faire\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"impossible de CreateHandle : %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"opération non gérée\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"version-inconnue\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"oui\"\n"
  },
  {
    "path": "po/fr_FR.po",
    "content": "# Translators:\n# J G, 2021\n# Mr Strik3, 2022\n# Maxime Demolin, 2023\n# Mathias Brugger, 2023\n# Sylvain Bx, 2023\n# Bertrand Junqua, 2024\n# Barsanuphe, 2024\n# Léane GRASSER, 2024\n# ariasuni <aria@ariasuni.eu>, 2026\n# \nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: ariasuni <aria@ariasuni.eu>, 2026\\n\"\n\"Language-Team: French (France) (https://app.transifex.com/yay-1/teams/123732/fr_FR/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: fr_FR\\n\"\n\"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Répertoire de compilation :\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Saisissez un nombre (valeur par défaut : 1) :\"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \" (Les fichiers de compilation existent)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \" (Installé)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \" [Installé]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \" il n'y a rien à faire\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"%s [A]Tous [Ab]Annuler [I]nstallés [No]nInstallés ou (1 2 3, 1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s déjà créé -- compilation ignorée\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s n'est pas définie\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s existe.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s est à jour -- ignoré\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s à mettre à jour ou à installer.\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%s à installer pour effectuer cette opération.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, nécessaire pour : %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s : Aucun changement -- ignoré\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s : la cible est incompatible avec l'option --aur -- ignoré\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s : la cible est incompatible avec l'option --repo -- ignoré\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s : mise à jour du paquet ignorée (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"\"\n\"%s : le paquet local (%s) est plus récent que le paquet disponible sur l'AUR\"\n\" (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"\"\n\"%s : définissez les variables d'environnement AUR_USERNAME et AUR_PASSWORD \"\n\"avant de pouvoir voter\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) PKGBUILD téléchargé depuis l'ABS : %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) PKGBUILD téléchargé : %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) Échec du téléchargement du PKGBUILD : %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) Analyse du SRCINFO : %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(Installé)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(Installé : %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Orphelin)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Obsolète : %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"URL sur l'AUR\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Ajoutez %s ou %s à vos variables d'environnement\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Évitez d'exécuter yay en tant que root ou via sudo.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Dépendance de vérification\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Dépendances vérif.\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"Vérification des paquets de développement…\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Nettoyage (%d/%d) : %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Est en conflit avec\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Suppression (%d/%d) : %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Dépendance\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Dépend de\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Description\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Diffs à afficher ?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"Désactiver par défaut le paramètre \\\"provides\\\"\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"Voulez-vous supprimer TOUS les paquets de l'AUR dans le cache ?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"\"\n\"Voulez-vous supprimer TOUS les fichiers non suivis des paquets de l'AUR ?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"\"\n\"Voulez-vous supprimer tous les autres paquets de l'AUR dans le cache ?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"Modifier le PKGBUILD avec ?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Erreur lors de la recherche dans l'AUR : %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"L'exclusion de paquets peut mener à une mise à jour partielle de votre \"\n\"système et pourrait le casser\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Explicite\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Paquets installés explicitement : %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"Impossible de trouver un paquet sur l'AUR correspondant à\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"Échec de l'installation de la couche, passage à la couche suivante.\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"\"\n\"Échec de l'installation des paquets suivants. Une intervention manuelle est \"\n\"requise :\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Envoyé le\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Paquets de l'AUR marqués comme obsolètes :\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Paquets étrangers installés : %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Dépôt Git trouvé : %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB terminé. Aucun paquet n'a été installé\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Groupes\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Importer ?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"Importation des clés avec gpg…\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Mots-clés\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Modifié le\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Licences\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Local\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Mainteneur\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Dépendance de création\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Dépendances créat.\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Manquant\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Paquets de débogage de l'AUR manquants :\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Nom\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:564\nmsgid \"No AUR package found for\"\nmsgstr \"Aucun paquet trouvé sur l'AUR correspondant à\"\n\n#: pkg/dep/dep_graph.go:564\nmsgid \"required by\"\nmsgstr \"requis par\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"Aucun paquet trouvé correspondant à\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"--\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Dépendances opt.\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Paquets de l'AUR orphelins (non maintenus) :\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Obsolète\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"Des clés PGP doivent être importées :\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD à jour, téléchargement ignoré : %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"PKGBUILDs à modifier ?\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Paquet base\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"ID du paquet base\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"Paquets absents de l'AUR :\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Paquets à cleanBuild ?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Paquets à exclure\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"Paquets à exclure : (ex. « 1 2 3 », « 1-3 », « ^4 » ou noms de dépôt)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Paquets à installer (ex. 1 2 3, 1-3 ou ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Popularité\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Procéder à l'installation ?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Fournit\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"Supprimer les dépendances de création après l'installation ?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Remplace\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"Dépôt\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"Dépôt AUR\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Recherche des mises à jour sur l'AUR…\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"Recherche des mises à jour dans les bases de données…\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Affichage uniquement des paquets provenant des dépôts\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"Taille du cache de pacman %s : %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"Taille du cache de yay %s : %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"URL de l'instantané\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Sync\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"Les dix paquets les plus lourds :\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"Les paquets suivants sont incompatibles avec votre architecture :\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"%[1]d paquets fournissant %[2]s sont disponibles :\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"\"\n\"Il semblerait qu'une autre instance de Pacman soit en cours d'exécution. En \"\n\"attente…\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Taille totale occupée par les paquets : %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Nombre de paquets installés : %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Essayer quand même de les compiler ?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"Impossible de nettoyer :\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"Impossible de trouver les paquets suivants :\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"Impossible de gérer le vote pour : %s. Erreur : %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"Impossible de supprimer %s : %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Version\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Votes\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Yay version v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N]Aucun\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"abandon dû à l'utilisateur\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"argument '-' spécifié et aucune entrée dans stdin\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"\"\n\"impossible de trouver les fichiers PKGBUILD et .SRCINFO dans le répertoire\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"impossible de trouver le nom de paquet : %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"impossible de trouver le PKGDEST pour : %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"impossible de trouver tous les paquets requis\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"aucune archive de paquet trouvée parmi celles listées dans %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"dépendance\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"\"\n\"échec de la vérification du paquet de développement : '%s' a rencontré une \"\n\"erreur\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"l'éditeur ne s'est pas terminé avec succès, abandon : %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"erreur lors du téléchargement des sources : %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"erreur lors de la récupération de %s : %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"erreur lors de l'installation des paquets provenant des dépôts\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"erreur lors de l'installation de :\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"erreur lors de la compilation de : %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"erreur lors de la fusion (%s) : %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"erreur lors de la lecture de %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"erreur lors de l'actualisation des bases de données\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"erreur lors de la réinitialisation de %s : %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"\"\n\"erreur lors de la modification du motif d'installation du paquet en « %s »\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"explicite\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"échec de la création du répertoire '%s' : %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"échec de l'ouverture du fichier de configuration '%s' : %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"échec de l'analyse de %s -- ignoré : %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"échec de l'analyse de %s : %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"échec de l'analyse du .SRCINFO\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"échec de la lecture du fichier de configuration '%s' : %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"échec de la récupération du cache AUR\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"\"\n\"mise à jour du paquet de développement ignorée (infos AUR introuvables) :\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"entrée trop longue\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"nombre invalide : %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"option '%s' invalide\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"\"\n\"option invalide : '--deps' et '--explicit' ne peuvent pas être utilisés \"\n\"ensemble\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"dépôt invalide\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"valeur invalide : %d n'est pas entre %d et %d\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"non\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"aucune clé à importer\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"aucune requête n'a été exécutée\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"aucun répertoire cible spécifié\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"rien à installer pour %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"une seule opération peut être réalisée à la fois\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"une seule cible est autorisée\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"paquet\"\nmsgstr[1] \"paquets\"\nmsgstr[2] \"paquets\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"le paquet '%s' est introuvable\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"paquet introuvable dans l'AUR\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"paquet introuvable dans les dépôts\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"erreur lors de l'importation des clés\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"suppression des paquets de l'AUR du cache…\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"\"\n\"suppression des fichiers non suivis dans les paquets de l'AUR en cache…\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"le PKGDEST pour %s est listé par makepkg mais n'existe pas : %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"il n'y a rien à faire\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"impossible de CreateHandle : %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"opération non gérée\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"version-inconnue\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"oui\"\n"
  },
  {
    "path": "po/he.po",
    "content": "#\n# Translators:\n# lavi landa, 2024\n# Yaron Shahrabani <sh.yaron@gmail.com>, 2024\n#\nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: Yaron Shahrabani <sh.yaron@gmail.com>, 2024\\n\"\n\"Language-Team: Hebrew (https://app.transifex.com/yay-1/teams/123732/he/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: he\\n\"\n\"Plural-Forms: nplurals=3; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: 2;\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \" (קיימים קובצי בנייה)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \" (מותקנת)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \" [מותקנת]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \"אין מטרות לביצוע\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"\"\n\"%s [A]-הכול [Ab]-ביטול [I]-מותקנות [No]-לא מותקנות או (1 2 3, 1-3, ‎^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s כבר נבנתה -- לא תיבנה שוב\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s לא מוגדר\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s קיימת.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s עדכנית -- מדלגים\"\n\n#: pkg/upgrade/service.go:292\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s לשדרוג/התקנה.\"\n\n#: pkg/upgrade/service.go:286\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"גם %s תותקן לשם הפעולה הזאת.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, נדרשה ע״י: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: אין שינויים -- מדלגים\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: אי אפשר להשתמש ביעד עם האפשרות ‎--aur -- מדלגים\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: אי אפשר להשתמש ביעד עם האפשרות ‎--repo -- מדלגים\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: מתעלמים משדרוג חבילה (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: מקומית (%s) חדשה יותר מ־AUR (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"%s: נא להגדיר את משתני הסביבה AUR_USERNAME ו־AUR_PASSWORD כדי להצביע\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) PKGBUILD ירד מ־ABS: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) PKGBUILD שירד: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) הורדת PKGBUILD נכשלה: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) מתבצע פענוח של SRCINFO: %s\"\n\n#: pkg/query/types.go:72 pkg/query/types.go:103\nmsgid \"(Installed)\"\nmsgstr \"(מותקנת)\"\n\n#: pkg/query/types.go:70 pkg/query/types.go:101\nmsgid \"(Installed: %s)\"\nmsgstr \"(מותקנת: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(יתומה)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(לא עדכנית: %s)\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"כתובת AUR\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"יש להוסיף %s או %s למשתני הסביבה שלך\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"כדאי להימנע מהפעלה תחת root/sudo.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"בדיקת תלות\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"בדיקת תלויות\"\n\n#: pkg/upgrade/service.go:90\nmsgid \"Checking development packages...\"\nmsgstr \"חבילות הפיתוח נבדקות…\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"מתבצע ניקיון (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"סותר את\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"מתבצעת מחיקה (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"תלות\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"תלויה ב־\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"תיאור\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"הבדלים להצגה?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"להשבית את הגדרת ‚provides’ (מספקת) כברירת מחדל\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"להסיר את כל חבילות ה־AUR מהמטמון?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"להסיר את כל קובצי ה־AUR שאינם במעקב?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"להסיר את כל חבילות ה־AUR האחרות מהמטמון?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"לערוך את PKGBUILD עם?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"שגיאה בחיפוש AUR: %s\\n\"\n\n#: pkg/upgrade/service.go:296\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"החרגת חבילות עשויה להוביל לשדרוג חלקי ולפגוע במערכות\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"מפורש\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"חבילות שהותקנו מפורשות: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"נכשל האיתור בחבילת AUR עבור\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"התקנת השכבה נכשלה, מתבצעת התקדמות לשכבה הבאה.\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"התקנת החבילות הבאות נכשלה. נדרשת התערבות ידנית:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"הוגשה לראשונה\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"חבילות AUR שסומנו כלא עדכניות:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"חבילות זרות מותקנות: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"נמצא מאגר git: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB הסתיים. לא הותקנו חבילות\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"קבוצות\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"לייבא?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"מתבצע ייבוא מפתחות עם gpg…\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"מילות מפתח\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"שינוי אחרון\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"רישיונות\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"מקומי\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"תחזוקה\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"תלות בנייה\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"תלויות בנייה\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"חבילות ניפוי שגיאות חסרות ב־AUR:\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"חסרות\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"שם\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:548\nmsgid \"No AUR package found for\"\nmsgstr \"לא נמצאה חבילת AUR עבור\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"לא נמצאה חבילה עבור\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"ללא\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"תלויות רשות\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"חבילות AUR יתומות (לא מתוחזקות):\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"לא עדכניות\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"מפתחות PGP שיש לייבא:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD עדכני, לא תתבצע הורדה: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"קובצי PKGBUILD לעריכה?\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"מזהה בסיס החבילה\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"בסיס חבילה\"\n\n#: pkg/query/aur_warnings.go:67\nmsgid \"Packages not in AUR:\"\nmsgstr \"חבילות שאינן ב־AUR:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"חבילות לבנייה מההתחלה (cleanBuild)?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"חבילות להחרגה\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"חבילות שיוחרגו: (למשל: „1 2 3”, „1-3”, „‎^4” או שם המאגר)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"חבילות להתקנה (למשל: 1 2 3, 1-3 או ‎^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"פופולריות\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"להמשיך בהתקנה?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"מספקת\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"להסיר תלויות בנייה לאחר ההתקנה?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"מחליפה\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"מאגר AUR\"\n\n#: print.go:30 pkg/db/ialpm/alpm.go:191\nmsgid \"Repository\"\nmsgstr \"מאגר\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:72\nmsgid \"Searching AUR for updates...\"\nmsgstr \"מתבצע חיפוש אחר עדכונים ב־AUR…\"\n\n#: pkg/upgrade/service.go:160\nmsgid \"Searching databases for updates...\"\nmsgstr \"מתבצע חיפוש אחר עדכונים במסדי הנתונים…\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"מוצגות חבילות מאגר בלבד\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"גודל המטמון של pacman %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"גודל המטמון של yay %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"כתובת לכידה\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"סנכרון\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"עשרת החבילות הגדולות:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"החבילות הבאות אינן תואמות לארכיטקטורת המעבד שלך:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"יש %[1]d ספקים זמינים עבור %[2]s:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"יכול להיות שעוד מופע של Pacman פעיל. ממתינים…\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"הגודל הכולל שתופסות החבילות: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"סך כל החבילות המותקנות: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"לנסות לבנות אותן בכל מקרה?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"כתובת\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"לא ניתן לפנות:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"לא ניתן למצוא את החבילות הבאות:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"לא ניתן לטפל בהצבעות חבילה עבור: %s. שגיאה: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"לא ניתן להסיר את %s: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"גרסה\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"הצבעות\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Yay גרסה ‎v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N]-כלום\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"תיקיית בנייה:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"נא להקליד מספר (ברירת מחדל=1): \"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"בוטל לבקשת המשתמש\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"סופק המשתנה ‚-’ ללא שום קלט ל־stdin\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"לא ניתן לאתר PKGBUILD ו־‎.SRCINFO בתיקייה\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"לא ניתן למצוא את שם החבילה: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"לא ניתן למצוא PKGDEST עבור: %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"לא ניתן למצוא את כל החבילות הנחוצות\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"לא ניתן למצוא ארכיוני חבילות כלשהם שמופיעים תחת %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:287\nmsgid \"dependency\"\nmsgstr \"תלות\"\n\n#: pkg/vcs/vcs.go:96 pkg/vcs/vcs.go:100\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"בדיקת פיתוח לחבילה נכשלה: ‚%s’ נתקל בשגיאה\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"העורך לא יצא כמו שצריך, הפעולה מבוטלת: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"שגיאה בהורדת קוד מקור: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"שגיאה במשיכת %s: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"שגיאה בהתקנת חבילות מאגר\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"שגיאה בהתקנה:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"שגיאה בבנייה: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"שגיאה במיזוג %s: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"שגיאה בקריאת %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"שגיאה ברענון מסדי נתונים\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"שגיאה באיפוס %s: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"שגיאה בעדכון סיבת התקנת החבילה לכדי %s\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"מפורש\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"יצירת התיקייה ‚%s’ נכשלה: %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"פתיחת קובץ ההגדרות ‚%s’ נכשלה: %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"הפענוח של %s נכשל -- מדלגים: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"הפענוח של %s נכשל: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"פענוח ה־‎.SRCINFO נכשל\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"קריאת קובץ ההגדרות ‚%s’ נכשלה: %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"משיכת המטמון של ה־aur נכשלה\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"התעלמות משדרוג חבילת פיתוח (devel - לא נמצאו פרטים ב־AUR):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"הקלט ארוך מדי\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"מס׳ שגוי: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"האפשרות ‚%s’ שגויה\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"אפשרות שגויה: אסור להשתמש ב־‚‎--deps' וב־‚‎--explicit’ יחד\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"מאגר שגוי\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"ערך שגוי: %d לא בין %d לבין %d\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"אין מפתחות לייבוא\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"לא הופעלה שאילתה\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"לא צוינו תיקיות יעד\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"לא\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"אין מה להתקין עבור %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"אפשר להשתמש בפעולה אחת בכל רגע נתון\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"מותר רק יעד אחד\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"החבילה ‚%s’ נכשלה\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"החבילה לא נמצאה ב־AUR\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"החבילה לא נמצאה במאגרים\"\n\n#: pkg/upgrade/service.go:292\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"חבילה\"\nmsgstr[1] \"חבילות\"\nmsgstr[2] \"חבילות\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"תקלה בייבוא מפתחות\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"חבילות AUR נמחקות מהמטמון…\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"קובצי AUR שאינם במעקב נמחקים מהמטמון…\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"ה־PKGDEST עבור %s מוצג על ידי makepkg אך אינו קיים: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"אין מטרות לביצוע\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"לא ניתן ליצור כינוי (CreateHandle): %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"פעולה שלא טופלה\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"גרסה-לא-ידועה\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"כן\"\n"
  },
  {
    "path": "po/he_IL.po",
    "content": "#\n# Translators:\n# Yaron Shahrabani <sh.yaron@gmail.com>, 2024\n# lavi landa, 2024\n#\nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: lavi landa, 2024\\n\"\n\"Language-Team: Hebrew (Israel) (https://app.transifex.com/yay-1/teams/123732/he_IL/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: he_IL\\n\"\n\"Plural-Forms: nplurals=3; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: 2;\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \" (קיימים קובצי בנייה)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \" (מותקנת)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \" [מותקנת]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \"אין מטרות לביצוע\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"\"\n\"%s [A]-הכול [Ab]-ביטול [I]-מותקנות [No]-לא מותקנות או (1 2 3, 1-3, ‎^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s כבר נבנתה -- לא תיבנה שוב\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s לא מוגדר\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s קיימת.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s עדכנית -- מדלגים\"\n\n#: pkg/upgrade/service.go:292\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s לשדרוג/התקנה.\"\n\n#: pkg/upgrade/service.go:286\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"גם %s תותקן לשם הפעולה הזאת.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, נדרשה ע״י: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: אין שינויים -- מדלגים\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: אי אפשר להשתמש ביעד עם האפשרות ‎--aur -- מדלגים\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: אי אפשר להשתמש ביעד עם האפשרות ‎--repo -- מדלגים\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: מתעלמים משדרוג חבילה (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: מקומית (%s) חדשה יותר מ־AUR (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"%s: נא להגדיר את משתני הסביבה AUR_USERNAME ו־AUR_PASSWORD כדי להצביע\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) PKGBUILD ירד מ־ABS: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) PKGBUILD שירד: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) לא הצליח להוריד PKGBUILD: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) מתבצע פענוח של SRCINFO: %s\"\n\n#: pkg/query/types.go:72 pkg/query/types.go:103\nmsgid \"(Installed)\"\nmsgstr \"(מותקנת)\"\n\n#: pkg/query/types.go:70 pkg/query/types.go:101\nmsgid \"(Installed: %s)\"\nmsgstr \"(מותקנת: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(יתומה)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(לא עדכנית: %s)\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"כתובת AUR\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"יש להוסיף %s או %s למשתני הסביבה שלך\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"כדאי להימנע מהפעלה תחת root/sudo.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"בדיקת תלות\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"בדיקת תלויות\"\n\n#: pkg/upgrade/service.go:90\nmsgid \"Checking development packages...\"\nmsgstr \"חבילות הפיתוח נבדקות…\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"מתבצע ניקיון (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"סותר את\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"מתבצעת מחיקה (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"תלות\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"תלויה ב־\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"תיאור\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"הבדלים להצגה?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"להשבית את הגדרת ‚provides’ (מספקת) כברירת מחדל\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"להסיר את כל חבילות ה־AUR מהמטמון?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"להסיר את כל קובצי ה־AUR שאינם במעקב?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"להסיר את כל חבילות ה־AUR האחרות מהמטמון?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"לערוך את PKGBUILD עם?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"שגיאה בחיפוש AUR: %s\\n\"\n\n#: pkg/upgrade/service.go:296\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"החרגת חבילות עשויה להוביל לשדרוג חלקי ולפגוע במערכות\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"מפורש\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"חבילות שהותקנו מפורשות: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"נכשל האיתור בחבילת AUR עבור\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"התקנת השכבה נכשלה, מתבצעת התקדמות לשכבה הבאה.\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"התקנת החבילות הבאות נכשלה. נדרשת התערבות ידנית:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"הוגשה לראשונה\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"חבילות AUR שסומנו כלא עדכניות:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"חבילות זרות מותקנות: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"נמצא מאגר git: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"יצירת מסד הנתונים (GenDB) הסתיימה. לא הותקנו חבילות\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"קבוצות\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"לייבא?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"מתבצע ייבוא מפתחות עם gpg…\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"מילות מפתח\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"שינוי אחרון\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"רישיונות\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"מקומי\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"תחזוקה\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"תלות בנייה\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"תלויות בנייה\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"חבילות ניפוי שגיאות חסרות ב־AUR:\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"חסרות\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"שם\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:548\nmsgid \"No AUR package found for\"\nmsgstr \"לא נמצאה חבילת AUR עבור\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"לא נמצאה חבילה עבור\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"ללא\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"תלויות רשות\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"חבילות AUR יתומות (לא מתוחזקות):\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"לא עדכניות\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"מפתחות PGP שיש לייבא:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD עדכני, לא תתבצע הורדה: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"קובצי PKGBUILD לעריכה?\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"מזהה בסיס החבילה\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"בסיס חבילה\"\n\n#: pkg/query/aur_warnings.go:67\nmsgid \"Packages not in AUR:\"\nmsgstr \"חבילות שאינן ב־AUR:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"חבילות לבנייה מההתחלה (cleanBuild)?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"חבילות להחרגה\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"חבילות שיוחרגו: (למשל: „1 2 3”, „1-3”, „‎^4” או שם המאגר)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"חבילות להתקנה (למשל: 1 2 3, 1-3 או ‎^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"פופולריות\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"להמשיך בהתקנה?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"מספקת\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"להסיר תלויות בנייה לאחר ההתקנה?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"מחליף\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"מאגר AUR\"\n\n#: print.go:30 pkg/db/ialpm/alpm.go:191\nmsgid \"Repository\"\nmsgstr \"מאגר\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:72\nmsgid \"Searching AUR for updates...\"\nmsgstr \"מתבצע חיפוש אחר עדכונים ב־AUR…\"\n\n#: pkg/upgrade/service.go:160\nmsgid \"Searching databases for updates...\"\nmsgstr \"מתבצע חיפוש אחר עדכונים במסדי הנתונים…\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"מוצגות חבילות מאגר בלבד\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"גודל המטמון של pacman %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"גודל המטמון של yay %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"כתובת לכידה\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"סנכרון\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"עשרת החבילות הגדולות:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"החבילות הבאות אינן תואמות לארכיטקטורת המעבד שלך:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"יש %[1]d ספקים זמינים עבור %[2]s:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"יכול להיות שעוד מופע של Pacman פעיל. ממתינים…\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"הגודל הכולל שתופסות החבילות: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"סך כל החבילות המותקנות: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"לנסות לבנות אותן בכל מקרה?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"כתובת\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"לא ניתן לפנות:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"לא ניתן למצוא את החבילות הבאות:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"לא ניתן לטפל בהצבעות חבילה עבור: %s. שגיאה: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"לא ניתן להסיר את %s: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"גרסה\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"הצבעות\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Yay גרסה ‎v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N]-כלום\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"תיקיית בנייה:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"נא להקליד מספר (ברירת מחדל=1): \"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"בוטל לבקשת המשתמש\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"סופק המשתנה ‚-’ ללא שום קלט ל־stdin\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"לא ניתן לאתר PKGBUILD ו־‎.SRCINFO בתיקייה\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"לא ניתן למצוא את שם החבילה: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"לא ניתן למצוא PKGDEST עבור: %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"לא ניתן למצוא את כל החבילות הנחוצות\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"לא ניתן למצוא ארכיוני חבילות כלשהם שמופיעים תחת %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:287\nmsgid \"dependency\"\nmsgstr \"תלות\"\n\n#: pkg/vcs/vcs.go:96 pkg/vcs/vcs.go:100\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"בדיקת פיתוח לחבילה נכשלה: ‚%s’ נתקל בשגיאה\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"העורך לא יצא כמו שצריך, הפעולה מבוטלת: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"שגיאה בהורדת קוד מקור: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"שגיאה במשיכת %s: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"שגיאה בהתקנת חבילות מאגר\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"שגיאה בהתקנה:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"שגיאה בבנייה: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"שגיאה במיזוג %s: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"שגיאה בקריאת %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"שגיאה ברענון מסדי נתונים\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"שגיאה באיפוס %s: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"שגיאה בעדכון סיבת התקנת החבילה לכדי %s\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"מפורש\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"יצירת התיקייה ‚%s’ נכשלה: %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"פתיחת קובץ ההגדרות ‚%s’ נכשלה: %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"הפענוח של %s נכשל -- מדלגים: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"הפענוח של %s נכשל: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"פענוח ה־‎.SRCINFO נכשל\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"קריאת קובץ ההגדרות ‚%s’ נכשלה: %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"משיכת המטמון של ה־aur נכשלה\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"התעלמות משדרוג חבילת פיתוח (devel - לא נמצאו פרטים ב־AUR):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"הקלט ארוך מדי\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"מס׳ שגוי: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"האפשרות ‚%s’ שגויה\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"אפשרות שגויה: אסור להשתמש ב־‚‎--deps' וב־‚‎--explicit’ יחד\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"מאגר שגוי\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"ערך שגוי: %d לא בין %d לבין %d\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"אין מפתחות לייבוא\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"לא הופעלה שאילתה\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"לא צוינו תיקיות יעד\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"לא\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"אין מה להתקין עבור %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"אפשר להשתמש בפעולה אחת בכל רגע נתון\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"מותר רק יעד אחד\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"החבילה ‚%s’ נכשלה\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"החבילה לא נמצאה ב־AUR\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"החבילה לא נמצאה במאגרים\"\n\n#: pkg/upgrade/service.go:292\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"חבילה\"\nmsgstr[1] \"חבילות\"\nmsgstr[2] \"חבילות\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"תקלה בייבוא מפתחות\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"חבילות AUR נמחקות מהמטמון…\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"קובצי AUR שאינם במעקב נמחקים מהמטמון…\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"ה־PKGDEST עבור %s מוצג על ידי makepkg אך אינו קיים: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"אין מטרות לביצוע\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"לא ניתן ליצור כינוי (CreateHandle): %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"פעולה שלא טופלה\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"גרסה-לא-ידועה\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"כן\"\n"
  },
  {
    "path": "po/hu.po",
    "content": "# \n# Translators:\n# Szigeti Péter, 2021\n# summoner <summoner@disroot.org>, 2025\n# \nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: summoner <summoner@disroot.org>, 2025\\n\"\n\"Language-Team: Hungarian (https://app.transifex.com/yay-1/teams/123732/hu/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: hu\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Összeállítási könyvtár:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Írjon be egy számot (alapértelmezett=1): \"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \" (Összeállítási fájlok léteznek)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \" (Telepítve)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \" [Telepítve]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \" nincs tennivaló\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"\"\n\"%s [A]Összes [Ab]Megszakítás [I]Telepített [No]Nem telepített, vagy (1 2 3, \"\n\"1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s már kész -- összeállítás kihagyása\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s nincs beállítva\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s létezik.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s naprakész -- kihagyás\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s a frissítéshez/telepítéshez.\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%s is telepítve lesz ehhez a művelethez.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, szükséges a következő(k)höz: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: Nincs változtatás -- kihagyás\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: nem használható a cél az --aur kapcsolóval -- kihagyás\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: nem használható a cél a --repo kapcsolóval -- kihagyás\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: csomagfrissítés mellőzése (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: helyi (%s) frissebb mint az AUR-beli (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"\"\n\"%s: állítsa be az AUR_USERNAME és AUR_PASSWORD környezeti változókat a \"\n\"szavazáshoz\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) PKGBUILD letöltve az ABS-ből: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) PKGBUILD letöltve: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) Nem sikerült letölteni a PKGBUILD-et: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) SRCINFO vizsgálata: %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(Telepítve)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(Telepítve: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Elárvult)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Elavult: %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"AUR webcím\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Állítsa be a(z) %s vagy a(z) %s környezeti változót\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Ne futtassa a yay-t root-ként/sudo-val.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Függőség ellenőrzése\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Függőségek ellenőrzése\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"Fejlesztői csomagok ellenőrzése…\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Tisztítás (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Ütközik a következővel\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Törlés (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Függőség:\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Függőség(ek)\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Leírás\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Összehasonlítások megjelenítése?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"A „provides” opció alapértelmezett kikapcsolása\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"\"\n\"Biztosan el akarja távolítani az ÖSSZES AUR csomagot a gyorsítótárból?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"Biztosan el akarja távolítani az ÖSSZES nem követett AUR fájlt?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"\"\n\"Biztosan el akarja távolítani az összes többi AUR csomagot a gyorsítótárból?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"Mivel szerkeszti a PKGBUILD-et?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Hiba történt az AUR-ban való kereséskor: %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"A csomagok kizárása részleges frissítéseket és rendszertöréseket okozhat\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Kifejezetten\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Kifejezetten telepített csomagok: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"Nem sikerült megtalálni a következőhöz tartozó AUR-csomagot:\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"Nem sikerült telepíteni a réteget, áttérés a következő rétegre.\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"\"\n\"Nem sikerült telepíteni a következő csomagokat. Kézi beavatkozás szükséges:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Először beküldve\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Elavultnak jelölt AUR-csomagok:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Idegen telepített csomagok: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Git-tároló találat: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB végzett. Nem lett új csomag telepítve\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Csoportok\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Importálás?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"Kulcsok importálása gpg-vel…\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Kulcsszavak\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Legutóbb módosítva\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Licencek\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Helyi\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Karbantartó\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Fordítási függőség\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Fordítási függőségek\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Hiányzik\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Hiányzó AUR-hibakereső-csomagok:\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Név\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:564\nmsgid \"No AUR package found for\"\nmsgstr \"Nem található AUR-csomag a következőhöz:\"\n\n#: pkg/dep/dep_graph.go:564\nmsgid \"required by\"\nmsgstr \"szükséges a következő(k)höz\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"Nem található csomag a következőhöz:\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Semmi\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Nem kötelező függőségek\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Árva (nem karbantartott) AUR-csomagok:\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Elavult\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"Importálandó PGP-kulcsok:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"A PKGBUILD naprakész, a letöltés kihagyása: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"PKGBUILD-ek szerkesztése?\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Csomag alapja\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"Csomagazonosító-alap\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"A következő csomag nincs az AUR-ban:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Csomagok a tiszta összeállításhoz?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Kizárandó csomagok\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"\"\n\"Kizárandó csomagok: (például: „1 2 3”, „1-3”, „^4”, vagy a tároló neve)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Telepítendő csomagok (például: „1 2 3”, „1-3” vagy „^4”)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Népszerűség\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Folytatja a telepítést?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Szolgáltatók\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"Fordítási függőségek eltávolítása a telepítés után?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Cserék\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"Tároló\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"AUR-tároló\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Frissítések keresése az AUR-ban…\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"Frissítések keresése az adatbázisokban…\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Csak a tároló csomagjainak megjelenítése\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"A pacman gyorsítótárának mérete %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"A yay gyorsítótárának mérete %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"Pillanatkép webcíme\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Szinkronizálás\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"A tíz legnagyobb csomag:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"\"\n\"A következő csomagok nem kompatibilisek a processzor architektúrájával:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"%[1]d szolgáltató érhető el a következőhöz: %[2]d:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"Lehet, hogy már fut a pacman. Kis türelmet…\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Csomagok által elfoglalt összes hely: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Összes telepített csomag: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Mégis megpróbálja összeállítani őket?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"Webcím\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"Nem tisztítható:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"Nem sikerült megtalálni a következő csomagokat:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"\"\n\"Nem lehet feldolgozni a következő csomagra való szavazást: %s. hiba: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"Nem lehet eltávolítani a következőt: %s: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Verzió\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Szavazatok\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Yay verziója: v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N]semmi\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"a felhasználó kérésére megszakítva\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"„-” argumentum lett megadva az stdin bemenete nélkül\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"nem található a PKGBUILD és az .SRCINFO a könyvtárban\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"nem található a csomagnév: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"nem található a csomaghoz PKGDEST: %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"nem sikerült megtalálni minden szükséges csomagot\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"\"\n\"nem sikerült megtalálni egyetlen csomagarchívumot sem a(z) %s listában\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"függőség\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"a csomag fejlesztői ellenőrzése nem sikerült: a(z) „%s” hibát észlelt\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"nem lépett ki sikeresen a szerkesztő, megszakítva: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"hiba a következő forrásfájl(ok) letöltésekor: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"hiba a következő letöltésekor: %s: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"hiba a tárolóból származó csomagok telepítésekor\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"hiba a következő telepítésekor:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"hiba a következő fordításakor: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"hiba a következő beolvasztásakor: %s: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"hiba a következő olvasásakor: %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"hiba az adatbázisok frissítésekor\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"hiba a következő visszaállításakor: %s: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"hiba a csomag telepítési okának frissítésekor a következőre: %s\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"kifejezetten\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"nem sikerült létrehozni a következő könyvtárat: „%s”: %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"nem sikerült megnyitni a következő könyvtárat: „%s”: %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"nem sikerült elemezni a következőt: %s -- kihagyás: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"nem sikerült elemezni a következőt: %s: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"nem sikerült elemezni az .SRCINFO-t\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"nem sikerült olvasni a következő konfigurációs fájlt: „%s”: %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"nem sikerült lekérni az AUR-gyorsítótárát\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"\"\n\"fejlesztői csomag frissítésének mellőzése (nem található AUR-információ):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"a bemenet túl hosszú\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"érvénytelen szám: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"érvénytelen opció: „%s”\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"érvénytelen opció: „--deps” és „--explicit” nem használható egyszerre\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"érvénytelen tároló\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"érvénytelen érték: %d, az érték nem %d és %d között van\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"nem\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"nincs importálandó kulcs\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"nem történt lekérdezés\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"nincs megadva célkönyvtár\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"nincs mit telepíteni a következőhöz: %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"egyszerre csak egy művelet használható\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"csak egy cél engedélyezett\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"csomag\"\nmsgstr[1] \"csomagok\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"nem található a(z) „%s” csomag\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"a csomag nem található az AUR-ban\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"a csomag nem található a tárolókban\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"hiba a kulcsok importálásakor\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"AUR-csomagok eltávolítása a gyorsítótárból…\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"nem követett AUR-fájlok eltávolítása a gyorsítótárból…\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"a(z) %s PKGDEST-jét a makepkg listázza, de nem létezik: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"nincs semmi tennivaló\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"sikertelen CreateHandle: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"nem kezelt művelet\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"ismeretlen verzió\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"igen\"\n"
  },
  {
    "path": "po/id.po",
    "content": "# \n# Translators:\n# Ludovico, 2022\n# Alif Fathur, 2024\n# Linerly <linerly@proton.me>, 2024\n# \nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: Linerly <linerly@proton.me>, 2024\\n\"\n\"Language-Team: Indonesian (https://app.transifex.com/yay-1/teams/123732/id/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: id\\n\"\n\"Plural-Forms: nplurals=1; plural=0;\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Direktori build:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Masukkan sebuah nomor (bawaan=1):\"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \"(File build Sudah Ada)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \"(Terpasang)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \"[Terpasang]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \"tidak ada yang dapat dilakukan\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"\"\n\"%s [A]Semua [Ab]Batalkan [I]Terpasang [No]Belum terpasang atau (1 2 3, 1-3, \"\n\"^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s sudah dibuat -- melewatkan proses build\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s belum diatur\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s sudah ada.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s sudah yang terbaru -- melewatkan\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s untuk diupgrade/dipasang.\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%s juga akan dipasang untuk tindakan ini.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, dibutuhkan oleh: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: Tidak ada perubahan -- melewatkan\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: tidak dapat menggunakan target dengan --aur -- melewatkan\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: tidak dapat menggunakan target dengan opsi --repo -- melewatkan\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: mengabaikan pengupgradean paket (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: lokal (%s) lebih baru dari yang AUR (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"\"\n\"%s: seilahkan atur variabel environment AUR_USERNAME dan AUR_PASSWORD untuk \"\n\"pemungutan suara\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) PKGBUILD diunduh dari ABS: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) PKGBUILD terunduh: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) Gagal mengunduh PKGBUILD: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) Menguraikan SRCINFO: %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(Terpasang)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(Terpasang: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Ditinggalkan)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Kedaluwarsa: %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"URL AUR\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Tambahkan %s atau %s ke variabel environment Anda\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Hindari menjalankan yay sebagai root/sudo.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Periksa dependensi\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Periksa Ketergantungan\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"Memeriksa paket-paket pengembangan...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Membersihkan (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Berkonflik Dengan\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Menghapus (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Ketergantungan\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Tergantung Pada\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Deskripsi\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Tampilkan perbedaan?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"Nonaktifkan pengaturan 'menyediakan' secara bawaan\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"Apakah Anda ingin menghapus SEMUA paket AUR dari cache?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"Apakah Anda ingin menghapus SEMUA file AUR yang tidak dilacak?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"Apakah Anda ingin menghapus semua paket AUR lainnya dari cache?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"Edit PKGBUILD dengan?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Terjadi kesalahan melakukan pencarian AUR: %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"Tidak menyertakan paket dapat menyebabkan peningkatan parsial dan merusak \"\n\"sistem\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Eksplisit\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Paket yang terpasang secara eksplisit: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"Gagal mencari paket AUR untuk\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"Gagal memasang lapisan, menggulirkan ke lapisan berikutnya.\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"Gagal memasang paket berikut. Intervensi manual dibutuhkan:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Pengiriman Pertama\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Paket AUR Yang Ditandai Sebagai Kedaluwarsa:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Total paket-paket asing yang terpasang: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Ditemukan repositori git: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB selesai. Tidak ada paket yang terpasang\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Grup\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Impor?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"Mengimpor kunci-kunci dengan gpg...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Kata Kunci\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Terakhir Diubah\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Lisensi\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Lokal\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Pemelihara\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Ketergantungan Make\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Dependensi Make\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Tidak Ditemukan\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Paket Debug AUR Yang Tidak Ditemukan:\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Nama\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:548\nmsgid \"No AUR package found for\"\nmsgstr \"Tidak ada paket AUR yang ditemukan untuk\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"Tidak ada paket yang ditemukan untuk\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Tidak Ada\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Dependensi Opsional\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Paket AUR Tersendiri (tidak dipelihara):\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Kedaluwarsa\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"Kunci-kunci PGP membutuhkan pengimporan:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD sudah terbaru, melewati pengunduhan: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"PKGBUILD apa saja untuk diedit?\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Basis Paket\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"ID Basis Paket\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"Paket yang tidak ada di AUR:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Paket-paket di bangunBersih?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Paket untuk tidak disertakan\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"\"\n\"Paket-paket yang tidak disertakan: (mis: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\", atau \"\n\"nama repositori)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Paket-paket untuk dipasang (mis: 1 2 3, 1-3, atau ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Popularitas\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Lanjutkan dengan instalasi?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Menyediakan\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"Hapus dependensi make setelah pemasangan?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Menggantikan\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"Repositori\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"Repositori AUR\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Mencari AUR untuk pembaruan...\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"Mencari database untuk pembaruan...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Menampilkan paket-paket repositori saja\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"Ukuran cache pacman %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"Ukuran cache yay%s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"URL Snapshot\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Sinkron\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"Sepuluh paket terbesar:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"Paket-paket berikut ini tidak kompatibel dengan arsitektur Anda:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"Tersedia %[1]d penyedia untuk %[2]s:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"Mungkin ada instansi Pacman yang lain. Menunggu...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Total Ukuran ditempati oleh paket-paket: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Total paket-paket terpasang: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Coba membangun saja?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"Tidak dapat membersihkan:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"Tidak dapat mencari paket-paket berikut ini:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"Tidak dapat menangani pemungutan suara paket untuk: %s. kesalahan: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"Tidak dapat menghapus %s: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Versi\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Suara\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Yay versi v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[T]idak Ada\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"membatalkan karena pengguna\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"argumen '-' ditentukan tanpa masukan pada stdin\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"tidak dapat menemukan PKGBUILD dan .SRCINFO di direktori\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"tidak dapat menemukan nama paket: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"tidak dapat menemukan PKGDEST untuk: %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"tidak dapat menemukan semua paket yang dibutuhkan\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"tidak dapat mencari paket arsip apa pun yang terdaftar di %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"ketergantungan\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"pemeriksaan devel untuk paket gagal: '%s' mengalami sebuah kesalahan\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"editor tidak berhasil keluar, membatalkan: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"terjadi kesalahan mengunduh sumber-sumber: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"terjadi kesalahan mendapatkan %s: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"terjadi kesalahan memasang paket-paket repositori\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"terjadi kesalahan memasang:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"terjadi kesalahan membuat: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"terjadi kesalahan menggabungkan %s: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"terjadi kesalahan membaca %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"terjadi kesalahan memuat ulang basis data\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"terjadi kesalahan mengatur ulang %s: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"terjadi kesalahan memperbarui alasan pemasangan paket ke %s\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"eksplisit\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"gagal untuk membuat direktori '%s': %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"gagal untuk membuka file konfigurasi '%s': %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"gagal untuk menguraikan %s -- melewatkan: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"gagal untuk menguraikan %s: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"gagal mengurai .SRCINFO\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"gagal untuk membaca file konfigurasi '%s': %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"gagal mendapatkan Cache aur\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"\"\n\"mengabaikan pembaruan paket devel (tidak ada info AUR yang ditemukan):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"input terlalu panjang\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"Nomor tidak valid: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"opsi '%s' tidak valid\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"\"\n\"opsi tidak valid: '--deps' dan '--explicit' tidak boleh digunakan bersama\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"repositori tidak valid\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"nilai tidak valid: %d tidak di antara %d dan %d\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"tidak\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"tidak ada kunci-kunci untuk diimpor\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"tidak ada pencarian yang dilakukan\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"tidak ada sasaran direktori yang ditetapkan\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"tidka ada yang untuk dipasang untuk %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"hanya satu operasi yang dapat digunakan\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"hanya satu target yang diperbolehkan\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"paket\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"paket '%s' tidak ditemukan\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"paket tidak ditemukan di AUR\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"paket tidak ditemukan di repositori\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"terjadi masalah mengimpor kunci-kunci\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"menghapus paket-paket AUR dari cache...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"menghapus file AUR yang tidak dilacak dari cache...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"PKGDEST untuk %s didaftarkan oleh makepkg tetapi tidak ada: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"tidak ada yang dapat dilakukan\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"tidak dapat CreateHandle: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"operasi tidak diproses\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"versi-tidak-diketahui\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"ya\"\n"
  },
  {
    "path": "po/it_IT.po",
    "content": "# \n# Translators:\n# Cardellino, 2021\n# Giulio Terigi, 2022\n# Simone Dotto <simonedotto@protonmail.com>, 2022\n# jheitz223, 2023\n# Vincenzo Reale <vinx.reale@gmail.com>, 2025\n# \nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: Vincenzo Reale <vinx.reale@gmail.com>, 2025\\n\"\n\"Language-Team: Italian (Italy) (https://app.transifex.com/yay-1/teams/123732/it_IT/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: it_IT\\n\"\n\"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Cartella di compilazione:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Inserisci un numero (predefinito=1) \"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \" (I file di compilazione sono già presenti)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \" (Installato)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \" [Installato]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \" non c'è nulla da fare\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"\"\n\"%s [A]Tutti [Ab]Annulla [I]nstallati [No]nInstallati oppure (1 2 3, 1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s già fatto -- compilazione saltata\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s non è impostato\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s è presente.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s è aggiornato -- ignorato\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s da aggiornare/installare.\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%s sarà inoltre installato per questa operazione.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, richiesto da: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: Nessuna modifica -- ignorato \"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: non si può usare il target con l'opzione --aur -- ignorato\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: non si può usare il target con l'opzione --repo -- ignorato\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: aggiornamento dei pacchetti ignorato (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: il pacchetto locale (%s) è più nuovo del pacchetto AUR (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"\"\n\"%s: imposta le variabili d'ambiente AUR_USERNAME e AUR_PASSWORD prima di \"\n\"votare\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) PKGBUILD scaricato da ABS: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) PKGBUILD scaricato: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) Scaricamento PKGBUILD non riuscito: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) Analisi SRCINFO: %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(Installato)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(Installato: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Orfano)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Obsoleto: %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"URL di AUR\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Aggiungi %s o %s alle tue variabili d'ambiente\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Evita di eseguire yay come root/sudo.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Controllo dipendenza\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Controllo dipendenze\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"Verifica dei pacchetti di sviluppo in corso...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Pulizia (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Conflitti con\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Eliminazione (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Dipendenza\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Dipende da\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Descrizione\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Differenze da mostrare?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"Disabilita l'impostazione 'provides' in modo predefinito\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"Vuoi rimuovere TUTTI i pacchetti AUR dalla cache?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"Vuoi rimuovere TUTTI i file AUR non monitorati?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"Vuoi rimuovere tutti gli altri pacchetti AUR dalla cache?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"Con cosa modificare il PKGBUILD?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Errore durante la ricerca in AUR: %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"L'esclusione di pacchetti potrebbe causare aggiornamenti parziali e \"\n\"danneggiare i sistemi\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Esplicito\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Pacchetti installati esplicitamente: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"Impossibile trovare il pacchetto AUR per\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"\"\n\"Installazione del livello non riuscita, passaggio al livello successivo.\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"\"\n\"Installazione dei seguenti pacchetti non riuscita. È richiesto l'intervento \"\n\"manuale:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Primo invio\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Pacchetti AUR con flag obsoleto:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Totale dei pacchetti estranei installati: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Trovato repository git: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB terminato. Nessun pacchetto è stato installato\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Gruppi\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Importare?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"Importazione delle chiavi con gpg in corso...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Parole chiave\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Ultima modifica\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Licenze\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Locale\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Responsabile\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Dipendenza Make\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Make dipendenze\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Mancante\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Pacchetti AUR di debug mancanti:\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Nome\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:564\nmsgid \"No AUR package found for\"\nmsgstr \"Nessun pacchetto AUR trovato per\"\n\n#: pkg/dep/dep_graph.go:564\nmsgid \"required by\"\nmsgstr \"richiesto da\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"Nessun pacchetto trovato per\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Nessuno\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Dipendenze opzionali\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Pacchetti AUR orfani (non mantenuti):\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Obsoleto\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"Le chiavi PGP devono essere importate:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD aggiornato, scaricamento ignorato: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"Quali PKGBUILD modificare?\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Pacchetto base\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"ID pacchetto base\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"Pacchetti non in AUR:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Pacchetti da compilare in modo pulito?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Pacchetti da escludere\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"Pacchetti da escludere: (es: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" o il nome del repo)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Pacchetti da installare (es: 1 2 3, 1-3 o ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Popolarità\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Procedere con l'installazione?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Fornisce\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"Rimuovere le dipendenze di make dopo l'installazione?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Sostituisce\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"Repository\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"Repository AUR\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Ricerca di aggiornamenti su AUR in corso...\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"Ricerca di aggiornamenti nei database in corso...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Visualizzazione dei soli pacchetti del repo\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"Dimensione della cache di pacman %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"Dimensione della cache di yay %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"URL snapshot\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Sincronizza\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"I dieci pacchetti più grandi:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"I seguenti pacchetti non sono compatibili con la tua architettura:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"Ci sono %[1]d fornitori disponibili per %[2]s:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"\"\n\"Potrebbe esserci un'altra istanza di Pacman in esecuzione. In attesa... \"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Dimensione totale occupata dai pacchetti: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Totale dei pacchetti installati: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Provare a compilarli comunque?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"Impossibile pulire:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"Impossibile trovare i seguenti pacchetti:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"Impossibile gestire il voto per: %s. errore: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"Impossibile rimuovere %s: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Versione\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Voti\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Versione di yay v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N]essuno\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"interruzione su richiesta dell'utente in corso\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"argomento '-' specificato senza input su stdin\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"impossibile trovare PKGBUILD e .SRCINFO nella cartella\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"impossibile trovare un pacchetto di nome: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"impossibile trovare il PKGDEST per: %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"impossibile trovare tutti i pacchetti richiesti\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"impossibile trovare alcun archivio di pacchetti elencato in %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"dipendenza\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"\"\n\"devel check non riuscito per il pacchetto: '%s' ha riscontrato un errore\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"l'editor non è uscito correttamente, interruzione in corso: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"errore durante lo scaricamento dei sorgenti: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"errore durante il recupero di %s: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"errore durante l'installazione dei pacchetti del repo\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"installazione non riuscita:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"errore durante la creazione: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"errore durante l'unione di %s: %s \"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"errore durante la lettura di %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"errore durante l'aggiornamento dei database\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"errore durante il ripristino di %s: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"\"\n\"aggiornamento della ragione d'installazione del pacchetto a %s non è \"\n\"riuscito\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"esplicito\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"creazione della cartella '%s' non riuscita: %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"apertura del file di configurazione '%s' non riuscita: %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"analisi di %s non riuscita -- ignorato: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"analisi di %s non riuscita: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"analisi .SRCINFO non riuscita\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"lettura del file di configurazione '%s' non riuscita: %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"recupero della cache di AUR non riuscito\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"\"\n\"aggiornamento devel del pacchetto ignorato (nessuna informazione AUR \"\n\"trovata):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"input troppo lungo\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"numero non valido: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"opzione non valida '%s'\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"\"\n\"opzione non valida: '--deps' e '--explicit' non possono essere usate insieme\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"repository non valido\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"valore non valido: %d non è compreso tra %d e %d\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"no\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"nessuna chiave da importare\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"nessuna richiesta è stata eseguita\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"nessuna cartella di destinazione specificata\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"nulla da installare per %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"è possibile eseguire una sola operazione alla volta\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"è permessa solo una destinazione\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"pacchetto\"\nmsgstr[1] \"pacchetti\"\nmsgstr[2] \"pacchetti\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"il pacchetto '%s' non è stato trovato\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"pacchetto non trovato su AUR\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"pacchetto non trovato nei repository\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"problema durante l'importazione delle chiavi\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"eliminazione dei pacchetti AUR dalla cache...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"eliminazione dei file AUR non tracciati dalla cache...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"il PKGDEST per %s è elencato da makepkg, ma non esiste: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \" non c'è nulla da fare\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"impossibile creare un handle: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"operazione non gestita\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"versione-sconosciuta\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"sì\"\n"
  },
  {
    "path": "po/ja.po",
    "content": "#\n# Translators:\n# J G <transifex@jguer.space>, 2021\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: PACKAGE VERSION\\n\"\n\"PO-Revision-Date: 2021-08-13 22:55+0000\\n\"\n\"Last-Translator: J G <transifex@jguer.space>, 2021\\n\"\n\"Language-Team: Japanese (https://www.transifex.com/yay-1/teams/123732/ja/)\\n\"\n\"Language: ja\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=1; plural=0;\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \" (ビルドファイルが存在)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \" (インストール済み)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \" [インストール済み]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \" 何もすることがありません\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"\"\n\"%s [A]全て [Ab]中止 [I]インストール済み [No]未インストール または (1 2 3, \"\n\"1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s は既に作成済みです -- ビルドをスキップします\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s が設定されていません\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s が存在します。\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s は最新です -- スキップ\"\n\n#: pkg/upgrade/service.go:292\n#, fuzzy\nmsgid \"%s to upgrade/install.\"\nmsgstr \"アップグレードするパッケージ。\"\n\n#: pkg/upgrade/service.go:286\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s、必要とするパッケージ: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: 変更なし -- スキップ\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: 対象に --aur オプションを使うことができません -- スキップ\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: 対象に --repo オプションを使うことができません -- スキップ\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: パッケージのアップグレードを無視 (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: ローカルのパッケージ (%s) は AUR (%s) よりも新しいバージョンです\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for voting\"\nmsgstr \"\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) ABS から PKGBUILD をダウンロード: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\n#, fuzzy\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) ABS から PKGBUILD をダウンロード: %s\"\n\n#: pkg/download/aur.go:82\n#, fuzzy\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) ABS から PKGBUILD をダウンロード: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) SRCINFO を解析中: %s\"\n\n#: pkg/query/types.go:72 pkg/query/types.go:103\nmsgid \"(Installed)\"\nmsgstr \"(インストール済み)\"\n\n#: pkg/query/types.go:70 pkg/query/types.go:101\nmsgid \"(Installed: %s)\"\nmsgstr \"(インストール済み: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(メンテナ不在)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(古いバージョン: %s)\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"AUR URL\"\n\n#: pkg/dep/dep_graph.go:75\n#, fuzzy\nmsgid \"AUR\"\nmsgstr \"URL\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"%s または %s を環境変数に追加してください\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"yay を root や sudo で実行しないでください。\"\n\n#: pkg/dep/dep_graph.go:63\n#, fuzzy\nmsgid \"Check Dependency\"\nmsgstr \"チェック時の依存パッケージ\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"チェック時の依存パッケージ\"\n\n#: pkg/upgrade/service.go:90\nmsgid \"Checking development packages...\"\nmsgstr \"開発パッケージを確認...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"消去 (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"衝突するパッケージ\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"削除 (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\n#, fuzzy\nmsgid \"Dependency\"\nmsgstr \"依存するパッケージ\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"依存するパッケージ\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"説明\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"差異を表示しますか？\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"キャッシュから全ての AUR パッケージを削除しますか？\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"未追跡の AUR ファイルを全て削除しますか？\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"キャッシュから他の全ての AUR パッケージを削除しますか？\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"PKGBUILD をどのエディタで編集しますか？\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"AUR 検索時のエラー: %s\\n\"\n\n#: pkg/upgrade/service.go:296\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"明示的にインストールしたパッケージ: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\n#, fuzzy\nmsgid \"Failed to find AUR package for\"\nmsgstr \"古いバージョンのフラグが立てられた AUR パッケージ:\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"最初の投稿\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"古いバージョンのフラグが立てられた AUR パッケージ:\"\n\n#: print.go:90\n#, fuzzy\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"全ての外部からインストールされたパッケージ: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"git リポジトリを発見しました: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB が完了しました。パッケージのインストールは行われません\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"グループ\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"インポートしますか？\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"鍵を gpg でインポートします...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"キーワード\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"最終更新\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"ライセンス\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"メンテナ\"\n\n#: pkg/dep/dep_graph.go:62\n#, fuzzy\nmsgid \"Make Dependency\"\nmsgstr \"ビルド時の依存パッケージ\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"ビルド時の依存パッケージ\"\n\n#: pkg/query/aur_warnings.go:71\n#, fuzzy\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"存在しない AUR パッケージ:\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"名前\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:548\nmsgid \"No AUR package found for\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"なし\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"任意の依存パッケージ\"\n\n#: pkg/query/aur_warnings.go:75\n#, fuzzy\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"メンテナが存在しない AUR パッケージ:\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"古いバージョン\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"PGP 鍵をインポートする必要があります:\"\n\n#: pkg/sync/workdir/preparer.go:252\n#, fuzzy\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD は最新です、スキップ (%d/%d): %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"PKGBUILD を編集しますか？\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"パッケージベース ID\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"パッケージベース\"\n\n#: pkg/query/aur_warnings.go:67\nmsgid \"Packages not in AUR:\"\nmsgstr \"\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"パッケージをクリーンビルドしますか？\"\n\n#: pkg/dep/dep_graph.go:202\n#, fuzzy\nmsgid \"Packages to exclude\"\nmsgstr \"アップグレードするパッケージ。\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"\"\n\"除外するパッケージ: (例: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" またはリポジトリ名)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"インストールするパッケージ (例: 1 2 3, 1-3 または ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"人気度\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"インストールを実行しますか？\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"提供\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"ビルド時の依存パッケージをインストール後に削除しますか？\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"リポジトリ AUR\"\n\n#: print.go:30 pkg/db/ialpm/alpm.go:191\nmsgid \"Repository\"\nmsgstr \"リポジトリ\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"\"\n\n#: pkg/upgrade/service.go:72\nmsgid \"Searching AUR for updates...\"\nmsgstr \"AUR からアップデートを検索...\"\n\n#: pkg/upgrade/service.go:160\nmsgid \"Searching databases for updates...\"\nmsgstr \"データベースからアップデートを検索...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"リポジトリのパッケージだけを表示\"\n\n#: print.go:95\n#, fuzzy\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"%s のパースに失敗: %s\"\n\n#: print.go:98\n#, fuzzy\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"%s のパースに失敗: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"スナップショット URL\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"最も巨大な10のパッケージ:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"\"\n\"以下のパッケージはあなたの使っているアーキテクチャと互換性がありません:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\n#, fuzzy\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"%[1]d 個のパッケージが %[2]s を提供しています:\\n\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"他の Pacman インスタンスが実行中です。待機します...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"パッケージによって使用される合計容量: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"全てのインストールされたパッケージ: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"それでもパッケージをビルドしますか？\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\n#, fuzzy\nmsgid \"Unable to clean:\"\nmsgstr \"ハンドルを作成できません: %s\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"\"\n\n#: clean.go:170\n#, fuzzy\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"%s のパースに失敗: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"バージョン\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"投票\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Yay バージョン v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N]なし\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"ビルドディレクトリ:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"数字を入力してください (デフォルト=1): \"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"ユーザーによって中止\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"パッケージの名前を見つけることができません: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"PKGDEST を見つけることができません: %s\"\n\n#: errors.go:9\n#, fuzzy\nmsgid \"could not find all required packages\"\nmsgstr \"必要なパッケージを全て確認することができません:\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:287\n#, fuzzy\nmsgid \"dependency\"\nmsgstr \"依存するパッケージ\"\n\n#: pkg/vcs/vcs.go:96 pkg/vcs/vcs.go:100\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"エディタが正しく終了しませんでした、中止: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"ソースのダウンロード時にエラー: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"%s の取得時にエラー: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"リポジトリのパッケージのインストール時にエラー\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\n#, fuzzy\nmsgid \"error installing:\"\nmsgstr \"リポジトリのパッケージのインストール時にエラー\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"ビルド時にエラー: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"%s のマージ時にエラー: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"%s の読み取り時にエラー\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"データベースの更新時にエラー\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"%s の再設定時にエラー: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"設定ディレクトリ '%s' の作成に失敗: %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"設定ファイル '%s' のオープンに失敗: %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"%s のパースに失敗 -- スキップ: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"%s のパースに失敗: %s\"\n\n#: local_install.go:77\n#, fuzzy\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"%s のパースに失敗: %s\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"設定ファイル '%s' の読み込みに失敗: %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"\"\n\n#: pkg/upgrade/sources.go:27\n#, fuzzy\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"%s: パッケージのアップグレードを無視 (%s => %s)\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"入力が長すぎます\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"不正な数字: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"不正なオプション '%s'\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"\"\n\n#: pkg/download/abs.go:22\n#, fuzzy\nmsgid \"invalid repository\"\nmsgstr \"リポジトリ\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"不正な値: %d は %d と %d の間にありません\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"インポートする鍵がありません\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"no\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"一度に使用できる操作はひとつだけです\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"パッケージ '%s' が見つかりませんでした\"\n\n#: pkg/download/errors.go:15\n#, fuzzy\nmsgid \"package not found in AUR\"\nmsgstr \"パッケージ '%s' が見つかりませんでした\"\n\n#: pkg/download/abs.go:23\n#, fuzzy\nmsgid \"package not found in repos\"\nmsgstr \"パッケージ '%s' が見つかりませんでした\"\n\n#: pkg/upgrade/service.go:292\n#, fuzzy\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"パッケージベース\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"鍵のインポート時にエラー\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"キャッシュから AUR パッケージを削除...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"キャッシュから未追跡の AUR ファイルを削除...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"%s の PKGDEST が makepkg によって指定されていますが存在しません: %s\"\n\n#: pkg/sync/sync.go:45\n#, fuzzy\nmsgid \"there is nothing to do\"\nmsgstr \" 何もすることがありません\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"ハンドルを作成できません: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"ハンドルが存在しない操作\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"不明なバージョン\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"yes\"\n\n#~ msgid \" (Target\"\n#~ msgstr \" (対象\"\n\n#~ msgid \" (Wanted by: \"\n#~ msgstr \" (必要としているパッケージ: \"\n\n#~ msgid \" Input too long\"\n#~ msgstr \" 入力が長すぎます\"\n\n#~ msgid \"Installing %s will remove:\"\n#~ msgstr \"%s をインストールすることで削除されるパッケージ:\"\n\n#~ msgid \"%s already downloaded -- use -f to overwrite\"\n#~ msgstr \"%s は既にダウンロードされています -- -f で上書きできます\"\n\n#~ msgid \"%s and %s unset\"\n#~ msgstr \"%s と %s が設定されていません\"\n\n#~ msgid \"%s not satisfied, flushing install queue\"\n#~ msgstr \"%s が満たされていません、インストールキューを消去\"\n\n#~ msgid \"Checking for conflicts...\"\n#~ msgstr \"衝突を確認...\"\n\n#~ msgid \"Checking for inner conflicts...\"\n#~ msgstr \"内部衝突を確認...\"\n\n#~ msgid \"Conflicting packages will have to be confirmed manually\"\n#~ msgstr \"衝突するパッケージを手動で確認する必要があります\"\n\n#~ msgid \"Downloaded PKGBUILD (%d/%d): %s\"\n#~ msgstr \"PKGBUILD のダウンロード (%d/%d): %s\"\n\n#~ msgid \"Missing ABS packages:\"\n#~ msgstr \"存在しない ABS パッケージ:\"\n\n#~ msgid \"Querying AUR...\"\n#~ msgstr \"AUR を検索...\"\n\n#~ msgid \"\"\n#~ \"\\n\"\n#~ \"Inner conflicts found:\"\n#~ msgstr \"\"\n#~ \"\\n\"\n#~ \"内部衝突が存在します:\"\n\n#~ msgid \"\"\n#~ \"\\n\"\n#~ \"Package conflicts found:\"\n#~ msgstr \"\"\n#~ \"\\n\"\n#~ \"パッケージの衝突が存在します:\"\n\n#~ msgid \"error cloning %s: %s\"\n#~ msgstr \"%s の複製時にエラー: %s\"\n\n#~ msgid \"error during AUR search: %s\"\n#~ msgstr \"AUR の検索時にエラー: %s\"\n\n#~ msgid \"failed to create BuildDir directory '%s': %s\"\n#~ msgstr \"BuildDir ディレクトリ '%s' の作成に失敗: %s\"\n\n#~ msgid \"failed to get pkgbuild: %s: %s\"\n#~ msgstr \"pkgbuild の取得に失敗: %s: %s\"\n\n#~ msgid \"failed to link %s: %s\"\n#~ msgstr \"%s のリンクに失敗: %s\"\n\n#~ msgid \"failed to open vcs file '%s': %s\"\n#~ msgstr \"vcs ファイル '%s' のオープンに失敗: %s\"\n\n#~ msgid \"failed to read vcs file '%s': %s\"\n#~ msgstr \"vcs ファイル '%s' の読み込みに失敗: %s\"\n\n#~ msgid \"invalid sort mode. Fix with yay -Y --bottomup --save\"\n#~ msgstr \"不正なソートモードです。yay -Y --bottomup --save で修正してください\"\n\n#~ msgid \"no packages match search\"\n#~ msgstr \"検索にマッチするパッケージがありません\"\n\n#~ msgid \"package conflicts can not be resolved with noconfirm, aborting\"\n#~ msgstr \"パッケージの衝突は noconfirm で解決できません、中止\"\n\n#~ msgid \"refusing to install AUR packages as root, aborting\"\n#~ msgstr \"AUR パッケージの root によるインストールを拒否します、中止\"\n\n#~ msgid \"failed to create cache directory '%s': %s\"\n#~ msgstr \"キャッシュディレクトリ '%s' の作成に失敗: %s\"\n"
  },
  {
    "path": "po/ko.po",
    "content": "# \n# Translators:\n# J G, 2021\n# JungHee Lee <daemul72@gmail.com>, 2025\n# \nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: JungHee Lee <daemul72@gmail.com>, 2025\\n\"\n\"Language-Team: Korean (https://app.transifex.com/yay-1/teams/123732/ko/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: ko\\n\"\n\"Plural-Forms: nplurals=1; plural=0;\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"빌드 디렉터리:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"숫자를 입력하세요 (기본값=1): \"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \" (빌드 파일 존재)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \" (설치됨)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \" [설치됨]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \" 할 작업 없음\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"%s [A]모두 [Ab]중단 [I]설치됨 [No]설치안함 / (1 2 3, 1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s 이미 빌드됨 -- 빌드 건너뛰는 중\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s 지정되지 않음\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s가 존재합니다.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s 최신 버전임 -- 건너뛰는 중\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"업그레이드/설치하려면 %s 선택합니다.\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"이 작업을 위해 %s 또한 설치됩니다.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, 필요한 패키지: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: 변경사항 없음 -- 건너뛰는 중\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: 대상에 --aur 옵션 사용할 수 없음 -- 건너뛰는 중\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: 대상에 --repo 옵션 사용할 수 없음 -- 건너뛰는 중\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: 패키지 업그레이드 무시하는 중 (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: 로컬 (%s) 버전이 AUR (%s)보다 높음\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"%s: 투표를 위해 AUR_USERNAME 및 AUR_PASSWORD 환경 변수를 설정하십시오\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) ABS에서 PKGBUILD 다운로드됨: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) PKGBUILD 다운로드됨: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) PKGBUILD 다운로드에 실패함: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) SRCINFO 분석하는 중: %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(설치됨)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(설치됨: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(고립됨)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(오래됨: %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"AUR URL\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"%s 또는 %s를 환경 변수에 추가합니다\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"root/sudo로 yay를 실행하지 마세요.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"종속성 확인\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"종속성 확인\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"개발 패키지 확인하는 중...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"비우는 중 (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"충돌하는 패키지\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"삭제하는 중 (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"종속성\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"종속하는 패키지\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"설명\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"표시할 차이점(Diff)이 있나요?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"기본적으로 '제공 패키지' 설정 비활성화\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"캐시에 있는 AUR 패키지를 모두 제거하시겠습니까?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"추척되지 않은 AUR 파일을 모두 제거하시겠습니까?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"캐시의 다른 AUR 패키지를 모두 제거하시겠습니까?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"다음으로 PKGBUILD를 편집하시겠습니까?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"AUR 검색 중 오류: %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"패키지를 제외하면 부분 업그레이드 및 시스템 중단이 발생할 수 있습니다.\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"명시적\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"명시적으로 설치된 패키지: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"다음에 대한 AUR 패키지를 찾지 못함\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"레이어를 설치하지 못하여, 다음 레이어로 롤업합니다.\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"다음 패키지를 설치하지 못했습니다. 수동 개입이 필요합니다:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"처음 제출됨\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"오래된 AUR 패키지로 플래그 지정됨:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"외부 설치된 패키지: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"git 저장소 찾음: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB 완료됨. 패키지가 설치되지 않았습니다\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"그룹\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"가져올까요?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"gpg로 키 가져오는 중...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"키워드\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"마지막 수정됨\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"라이선스\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"로컬\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"유지관리자\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"종속성 만들기\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"종속성 만들기\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"누락됨\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"누락된 AUR 디버그 패키지:\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"이름\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:564\nmsgid \"No AUR package found for\"\nmsgstr \"다음 AUR 패키지를 찾을 수 없음\"\n\n#: pkg/dep/dep_graph.go:564\nmsgid \"required by\"\nmsgstr \"연관된 패키지\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"다음 패키지를 찾을 수 없음\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"없음\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"선택적 종속성\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"고립 (유지 관리되지 않는) AUR 패키지:\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"오래됨\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"가져와야 할 PGP 키:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD 최신 버전임, 다운로드 건너뛰는 중: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"PKGBUILD를 편집하시겠습니까?\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"패키지 베이스\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"패키지 베이스 ID\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"AUR에 없는 패키지:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"cleanBuild할 패키지는 무엇인가요?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"제외할 패키지\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"제외할 패키지: (예: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" 혹은 저장소 이름)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"설치할 패키지: (예: 1 2 3, 1-3 혹은 ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"인기순\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"설치를 계속 진행하시겠습니까?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"제공 패키지\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"설치 후 make 종속성을 제거하시겠습니까?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"교체하기\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"저장소\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"저장소 AUR\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"AUR에서 업데이트 검색하는 중...\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"데이터베이스에서 업데이트 검색하는 중...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"저장소 패키지만 표시하는 중\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"pacman 캐시 %s의 크기: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"yay 캐시 %s의 크기: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"스냅숏 URL\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"동기화\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"가장 큰 10개 패키지:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"다음 패키지는 이 컴퓨터의 아키텍처와 호환되지 않음:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"%[2]s에 대해 %[1]d개의 의존성 충족 패키지가 있습니다:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"다른 pacman 인스턴스가 실행 중입니다. 대기 중...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"패키지가 차지하는 전체 크기: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"설치된 전체 패키지: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"그래도 빌드할까요?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"비울 수 없음:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"다음 패키지를 찾을 수 없음:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"다음의 패키지 투표를 처리할 수 없습니다: %s. 오류: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"%s 제거할 수 없음: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"버전\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"투표\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Yay 버전 v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N]안함\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"사용자에 의해 중단됨\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"stdin에 대한 입력없이 독립변수 '-' 지정됨\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"디렉터리에서 PKGBUILD 및 .SRCINFO를 찾을 수 없음\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"패키지 이름을 찾을 수 없음: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"PKGDEST를 찾을 수 없음: %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"필요한 패키지를 모두 찾을 수 없음\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"%s에 나열된 패키지 아카이브를 찾을 수 없음\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"종속성\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"패키지에 대한 devel 확인 실패함: '%s'에 하나의 오류가 발생했습니다\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"편집기가 제대로 종료되지 않음, 중단하는 중: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"소스 다운로드 중 오류: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"%s 가져오는 중 오류: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"저장소 패키지 설치 중 오류\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"설치 중 오류:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"빌드 중 오류: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"%s 병합하는 중 오류: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"%s 읽는 중 오류\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"데이터베이스 갱신하는 중 오류\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"%s 재설정하는 중 오류: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"패키지 설치 근거를 %s로 업데이트하는 중 오류\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"명시적\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"'%s' 디렉터리 만들기 실패함: %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \" '%s' 구성 파일 열기 실패함: %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"%s 분석 실패함 -- 건너뜁니다: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"%s 분석 실패함: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \".SRCINFO를 분석하지 못했습니다\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"'%s' 구성 파일 읽기 실패함: %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"AUR 캐시를 검색하지 못했습니다\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"패키지 개발 업그레이드 무시하는 중 (AUR 정보를 찾을 수 없음):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"너무 긴 입력\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"잘못된 숫자: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"잘못된 옵션 '%s'\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"잘못된 옵션: '--deps'와 '--explicit'는 함께 사용할 수 없습니다\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"잘못된 저장소\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"잘못된 값: %d가 %d와 %d 사이에 있지 않음\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"아니요\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"가져올 키 없음\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"실행된 쿼리가 없습니다\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"지정된 대상 디렉터리가 없습니다\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"%s 용으로 설치할 항목 없음\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"한번에 한 작업만 쓸 수 있음\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"하나의 대상만 허용됩니다\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"패키지\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"'%s' 패키지를 찾지 못했습니다\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"AUR에서 패키지를 찾을 수 없습니다\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"저장소에서 패키지를 찾을 수 없습니다\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"키 가져오는 중 오류\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"캐시에서 AUR 패키지 제거하는 중...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"캐시에서 추적되지 않은 AUR 패키지 제거하는 중...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"makepkg에 등록된 %s의 PKGDEST가 존재하지 않음: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"할 작업 없음\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"CreateHandle 할 수 없음: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"핸들되지 않은 작업\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"알 수 없는 버전\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"예\"\n"
  },
  {
    "path": "po/nl.po",
    "content": "# \n# Translators:\n# Jonathan van der Steege <jonakeys@hotmail.com>, 2023\n# Loek Le Blansch <loek@pipeframe.xyz>, 2023\n# Luke Rieff, 2023\n# Ariejan de Vroom <ariejan@ariejan.net>, 2024\n# Heimen Stoffels <vistausss@fastmail.com>, 2025\n# \nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: Heimen Stoffels <vistausss@fastmail.com>, 2025\\n\"\n\"Language-Team: Dutch (https://app.transifex.com/yay-1/teams/123732/nl/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: nl\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Bouwmap:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Voer een getal in (standaard=1):\"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \"(Bouwbestanden zijn aanwezig)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \"(Geïnstalleerd)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \"[Geïnstalleerd]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \"er valt niets te doen\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"\"\n\"[A]lle [An]nuleren [G]eïnstalleerd [N]iet geïnstalleerd of (1 2 3, 1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s is al gemaakt -- de bouw wordt overgeslagen\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s is niet ingesteld\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s is aanwezig.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s is actueel -- wordt overgeslagen\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s op te waarderen/installeren.\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%s wordt ook geïnstalleerd bij het uitvoeren van deze actie.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, benodigd door: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: Geen wijzigingen -- wordt overgeslagen\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: kan doel niet gebruiken i.c.m. optie --aur -- wordt overgeslagen\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: kan doel niet gebruiken i.c.m. optie --repo -- wordt overgeslagen\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: pakketupgrade wordt genegeerd (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: de lokale versie (%s) is nieuwer dan de AUR-versie (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"\"\n\"%s: gebruik de omgevingsvariabelen AUR_USERNAME en AUR_PASSWORD om te \"\n\"stemmen\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) PKGBUILD gedownload van ABS: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) PKGBUILD gedownload: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) De PKGBUILD kan niet worden gedownload: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) Bezig met verwerken van SRCINFO: %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(Geïnstalleerd)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(Geïnstalleerd: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Onteigend)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Verouderd: %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"AUR-url\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Voeg %s of %s toe aan uw omgevingsvariabelen\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Voer yay niet uit als root/sudo.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Afhankelijkheid controleren\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Afhankelijkheden controleren\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"Bezig met controleren van ontwikkelpakketten…\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Bezig met opruimen… (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Botst met\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Bezig met verwijderen… (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Afhankelijkheid\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Afhankelijk van\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Beschrijving\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Verschillen tonen?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"Schakel de ‘biedt’-instelling standaard uit\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"Wilt u ALLE AUR-pakketten verwijderen uit de cache?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"Wilt u ALLE niet-gevolgde AUR-bestanden verwijderen?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"Wilt u alle andere AUR-pakketten verwijderen uit de cache?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"PKGBUILD bewerken met?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Fout tijdens AUR-zoekactie: %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"Pakketten uitsluiten kan mogelijk leiden tot onafgeronde upgrades en/of \"\n\"beschadigde systemen\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Uitdrukkelijk\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Uitdrukkelijk geïnstalleerde pakketten: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"Er is geen AUR-pakket gevonden voor \"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"\"\n\"Het installeren van de laag is mislukt - de volgende laag wordt gebruikt\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"\"\n\"De volgende pakketten konden niet worden geïnstalleerd. Handmatige \"\n\"interventie is vereist:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Eerst ingezonden op\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Verouderde AUR-pakketten:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Van buitenaf geïnstalleerde pakketten: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Git-repo aangetroffen: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB is afgerond. Er zijn geen pakketten zijn geïnstalleerd.\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Groepen\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Importeren?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"Bezig met importeren van sleutels…\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Trefwoorden\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Laatst bewerkt op\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Licenties\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Lokaal\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Onderhouder\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Make-afhankelijkheid\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Make-afhankelijkheden\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Ontbrekend\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Ontbrekende AUR-foutopsporingspakketten:\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Naam\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:564\nmsgid \"No AUR package found for\"\nmsgstr \"Geen AUR-pakket gevonden voor \"\n\n#: pkg/dep/dep_graph.go:564\nmsgid \"required by\"\nmsgstr \"benodigd door\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"Geen AUR-pakket gevonden voor \"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Geen\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Optionele afhankelijkheden\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Onteigende (niet-onderhouden) AUR-pakketten:\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Verouderd\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"Te importeren pgp-sleutels:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"\"\n\"De PKGBUILD is actueel, dus het downloaden van ‘%s’ wordt overgeslagen.\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"Te bewerken PKGBUILDs?\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Pakketbasis\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"Basis-id van pakket\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"Pakketten niet in AUR:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Te herbouwen pakketten?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Uitgesloten pakketten\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"\"\n\"Uit te sluiten pakketten: (bijv. ‘1 2 3’, ‘1-3’, ‘^4’ of pakketbronnaam)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Te installeren pakketten (bijv. 1 2 3, 1-3 of ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Populariteit\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Doorgaan met installeren?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Biedt\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"Make-afhankelijkheden verwijderen na installatie?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Vervangt\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"Pakketbron\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"AUR-repo\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Bezig met zoeken naar AUR-updates…\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"Bezig met zoeken naar updates in databanken…\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Toont alleen repo-pakketten\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"Omvang van pacman-cache %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"Omvang van yay-cache %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"Momentopname-url\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Synchroniseren\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"Tien grootste pakketten:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"De volgende pakketten zijn niet compatibel met uw architectuur:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"Er zijn %[1]d bronnen die %[2]s aanbieden:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"Wellicht is er een ander proces van Pacman bezig. Aan het wachten…\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Totale omvang van pakketten: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Totaalaantal geïnstalleerde pakketten: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Toch doorgaan met bouwen?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"Url\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"Het opruimen is mislukt:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"De volgende pakketten zijn niet aangetroffen:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"De stem op ‘%s’ kan niet worden verwerkt. Foutmelding: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"‘%s’ kan niet worden verwijderd: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Versie\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Stemmen\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Yay-versie v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[G]een\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"afbreken vanwege gebruiker\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"‘-’ als optie ingevoerd zonder invoer op stdin\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"Er zijn geen PKGBUILD en .SRCINFO aangetroffen in de map\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"Er is geen pakket met de naam “%v” aangetroffen\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"Er is geen PKGDEST aangetroffen voor ‘%s’\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"Niet alle vereiste pakketten zijn aangetroffen\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"Er zijn geen pakketarchieven aangetroffen in %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"afhankelijkheid\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"Ontwikkelcontrole van pakket mislukt: fout opgetreden in ‘%s’\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"De bewerker is niet goed afgesloten - het proces wordt afgebroken: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"De bronnen kunnen niet worden opgehaald: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"‘%s’ kan niet worden opgehaald: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"De pakketten kunnen niet worden geïnstalleerd\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"Het installeren van de volgende pakketten is mislukt:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"Het maken van de volgende pakketten is mislukt: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"‘%s’ kan niet worden samengevoegd: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"‘%s’ kan niet worden uitgelezen\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"De databanken kunnen niet worden vernieuwd\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"‘%s’ kan niet worden hersteld: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"Het bijwerken van de installatiereden naar %s is mislukt\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"Uitdrukkelijk\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"‘%s’ kan niet worden aangemaakt: %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"‘%s’ kan niet worden geopend: %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"‘%s’ kan niet worden verwerkt -- wordt overgeslagen: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"‘%s’ kan niet worden verwerkt: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \".SRCINFO kan niet worden verwerkt\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"‘%s’ kan niet worden uitgelezen: %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"De AUR-cache kan niet worden opgehaald\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"De ontwikkelupgrade is genegeerd (geen AUR-informatie aangetroffen):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"De invoer is te lang\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"Ongeldig getal: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"Ongeldige optie: ‘%s’\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"\"\n\"Ongeldige optie: ‘--deps’ en ‘--explicit’ mogen niet gelijktijdig worden \"\n\"gebruikt\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"Ongeldige pakketbron\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"Ongeldige waarde: %d ligt niet tussen %d en %d\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"nee\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"Er zijn geen te importeren sleutels\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"Er is geen zoekactie uitgevoerd\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"Er zijn geen doelmappen opgegeven\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"Er is niets te installeren voor %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"Er mag slechts één actie per keer worden uitgevoerd\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"Er is slechts één doel toegestaan\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"Pakket\"\nmsgstr[1] \"Pakketten\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"‘%s’ is niet aangetroffen\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"Het pakket is niet aangetroffen in de AUR\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"Het pakket is niet aangetroffen in de pakketbronnen\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"De sleutels kunnen niet worden geïmporteerd\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"Bezig met verwijderen van AUR-pakketten uit cache…\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"Bezig met verwijderen van niet-gevolgde AUR-bestanden uit cache…\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"De PKGDEST van ‘%s’ wordt vermeld door makepkg, maar bestaat niet: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"Er is niets meer te doen\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"CreateHandle kan niet worden uitgevoerd: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"Onafgehandelde actie\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"Onbekende versie\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"ja\"\n"
  },
  {
    "path": "po/pl.po",
    "content": "# \n# Translators:\n# J G, 2021\n# Oskar <me@medzik.dev>, 2022\n# A_Salata, 2024\n# SMT Broadcast, 2024\n# Chair n, 2024\n# Paweł Bernaciak, 2024\n# Mariusz Bubak, 2024\n# Bartłomiej Konecki, 2024\n# Tadeusz Magura-Witkowski, 2024\n# Tymon Marek, 2025\n# iwo wolani, 2025\n# Artur Wdowik, 2026\n#\nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: Artur Wdowik, 2026\\n\"\n\"Language-Team: Polish (https://app.transifex.com/yay-1/teams/123732/pl/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: pl\\n\"\n\"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Folder kompilacji:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Wybierz wartość (domyślnie=1): \"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \"(Pliki Budowy Istnieją)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \" (zainstalowano)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \" [zainstalowano]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \" nie ma nic do zrobienia\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"\"\n\"%s [A]Wszystkie [Ab]Anuluj [I]Zainstalowane [No]Nie zainstalowane lub (1 2 \"\n\"3, 1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s już jest zbudowany - pomijam budowanie\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s jest nieokreślony\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s jest już obecny.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s jest aktualny - pomijam\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s do aktualizacji/instalacji.\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%s również zostanie zainstalowanie w ramach operacji.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, wymagane przez: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: Bez zmian - pomijam\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: nie jest dostępny z --aur - pomijam\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: nie jest dostępny z --repo - pomijam\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: ignoruję aktualizację pakietu (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: wersja lokalna (%s) jest nowsza niż ta z AUR (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"\"\n\"%s: wprowadź proszę zmienne środowiskowe AUR_USERNAME oraz AUR_PASSWORD by \"\n\"móc głosować\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) Pobrano PKGBUILD z ABS-u: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) Pobrany PKGBUILD: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) Nie udało się pobrać PKGBUILD: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) Przetwarzam SRCINFO: %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(Zainstalowana)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(Zainstalowano: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Osierocona)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Nieaktualny od: %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"AUR URL\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Dodaj %s lub %s do zmiennych środowiskowych\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Unikaj uruchamiania yay jako root lub z sudo.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Sprawdzanie Zależności\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Sprawdź Zależności\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"Sprawdzanie pakietów w wersjach rozwojowych...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Czyszczenie (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Koliduje z\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Usuwanie (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Zależność\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Zależy od\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Opis\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Pokazać różnice?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"Domyślnie wyłącza ustawienie 'provides'  \"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"Czy chcesz usunąć WSZYSTKIE pakiety AUR z pamięci podręcznej?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"Czy chcesz usunąć WSZYSTKIE nieśledzone pliki AUR?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"Czy chcesz usunąć wszystkie inne pakiety AUR z pamięci podręczniej?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"Edytor PKGBUILD-ów?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Błąd podczas wyszukiwania w AUR: %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"Wykluczanie pakietów może spowodować częściową aktualizacje i uszkodzenie \"\n\"systemu\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Jawne\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Jawnie zainstalowane pakiety: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"Nie znaleziono pakietu AUR dla\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"Niepowodzenie zainstalowania warstwy, przewijanie do następnej warstwy\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"Nie udało sie zainstalować następujących pakietów. Wymagana interwencja \"\n\"użytkownika:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Zamieszczono po raz pierwszy\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Pakiety AUR oznaczone jako nieaktualne:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Obce zainstalowane pakiety: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Znaleziono repozytorium git: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"Zakończono GenDB. Nie zainstalowano żadnych pakietów\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Grupy\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Zaimportować?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"Importowanie kluczy przy użyciu gpg...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Słowa kluczowe\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Ostatnio zmodyfikowano\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Licencje\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Lokalne\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Opiekun\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Zależność Budowania\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Zbuduj zależności\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Zaginiony\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Brakujące Pakiety Debugowania AUR:\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Nazwa\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:548\nmsgid \"No AUR package found for\"\nmsgstr \"Nie znaleziono pakietu AUR dla\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"Nie znaleziono pakietu dla\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Brak\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Opcjonalne zależności\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Osierocone (nieutrzymywane) pakiety AUR:\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Nieaktualne\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"Klucze PGP wymagające zaimportowania:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD jest aktualny, pomijam pobieranie: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"Edytować PKGBUILD-y?\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Podstawa Pakietu\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"ID Podstawy Pakietu\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"Pakiety nie występujace w AUR:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Pakiety do zbudowania od zera?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Pakiety do wykluczenia\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"Wykluczone pakiety: (np.: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" lub nazwa repozytorium)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Pakiety do zainstalowania (np.: 1 2 3, 1-3 or ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Popularność\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Kontynuować instalację?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Dostarcza\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"Usunąć zależności potrzebne do zbudowania po instalacji?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Zastępuje\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"Repozytorium\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"Repozytorium AUR\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Poszukuję aktualizacji w AUR...\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"Poszukuję aktualizacji w bazie danych...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Pokazuję tylko pakiety z repozytoriów\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"Rozmiar pamięci podręcznej Pacmana %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"Rozmiar pamięci podręcznej yay %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"URL Snapshota\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Synchronizacja\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"Dziesięć największych pakietów:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"Te pakiety nie są kompatybilne z architekturą Twojego systemu:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"Jest %d możliwych źródeł dla %s:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"Prawdopodobnie działa teraz inna instancja Pacmana. Czekam...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Łączny rozmiar zajmowany przez pakiety: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Łączna liczba zainstalowanych pakietów: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Spróbować je zbudować mimo wszystko?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"Nie można sprzątnąć:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"Nie udało się znaleźć następujących pakietów:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"Nie udało się obsłużyć oceny pakietu dla: %s. err: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"Nie udało się usunąć %s: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Wersja\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Głosów\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Wersja yay v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N]ic\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"przerwane przez użytkownika\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"argument '-' określony bez danych wejściowych\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"nie znaleziono PKGBUILD i .SRCINFO w katalogu\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"nie odnalazłem pakietu: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"nie odnalazłem PKGDEST dla: %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"nie znaleziono wszystkich wymaganych pakietów\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"nie udało się znaleźć żadnych archiwów pakietów z listy %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"zależność\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"błąd sprawdzania wersji rozwojowej: '%s' napotkało na błąd\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"edytor nie zamknął się poprawnie, anuluję: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"błąd ściągania źródeł: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"błąd podczas ściągania %s: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"błąd podczas instalowania pakietów z repozytorium\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"Błąd podczas instalacji:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"błąd podczas budowania: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"błąd podczas scalania %s: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"błąd podczas odczytywania %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"błąd odświeżania baz danych\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"błąd podczas resetowania %s: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"błąd aktualizacji pakietu z przyczyn %s\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"jawne\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"nie udało się stworzyć katalogu '%s': %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"nie udało się otworzyć pliku konfiguracyjnego '%s': %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"nie udało się przetworzyć %s - pomijam: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"nie udało się przetworzyć %s: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"nie udało się przetworzyć .SRCINFO\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"nie udało się odczytać pliku konfiguracyjnego '%s': %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"Nie udało się pozyskać pamięci podręcznej AUR\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"ignorowanie aktualizacji wersji rozwojowej (brak informacji w AUR):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"zbyt długie dane wejściowe\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"niepoprawna liczba: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"niepoprawna opcja '%s'\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"niepoprawna opcja: '--deps' i '--explicit' nie mogą być razem używane\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"Nieprawidłowe repozytorium\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"niepoprawna wartość: %d nie jest pomiędzy %d a %d\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"nie\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"brak kluczy do zaimportowania\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"nie uruchomiono żadnego polecenia\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"Nie określono folderu docelowego\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"Nic do instalowania dla %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"tylko jedna operacja może być użyta na raz\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"dozwolony jest tylko jeden cel\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"pakiet\"\nmsgstr[1] \"pakietów\"\nmsgstr[2] \"pakietów\"\nmsgstr[3] \"pakiety\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"pakiet '%s' nie został odnaleziony\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"Nie znaleziono pakietu w AUR\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"Nie znaleziono pakietu w repozytoriach\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"błąd importowania kluczy\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"usuwanie z pamięci podręcznej pakietów z AUR...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"usuwanie z pamięci podręcznej nieśledzonych plików z AUR...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"PKGDEST dla %s jest wyszczególniony w makepkg, ale nie istnieje: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"Nie ma nic do zrobienia\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"błąd w CreateHandle: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"nieobsłużona operacja\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"nieznana wersja\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"tak\"\n"
  },
  {
    "path": "po/pl_PL.po",
    "content": "# \n# Translators:\n# J G, 2021\n# Oskar <me@medzik.dev>, 2022\n# A_Salata, 2024\n# SMT Broadcast, 2024\n# Chair n, 2024\n# Paweł Bernaciak, 2024\n# Mariusz Bubak, 2024\n# Bartłomiej Konecki, 2024\n# Tadeusz Magura-Witkowski, 2024\n# Tymon Marek, 2025\n# iwo wolani, 2025\n# Artur Wdowik, 2026\n#\nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: Artur Wdowik, 2026\\n\"\n\"Language-Team: Polish (https://app.transifex.com/yay-1/teams/123732/pl/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: pl\\n\"\n\"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Folder kompilacji:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Wybierz wartość (domyślnie=1): \"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \"(Pliki Budowy Istnieją)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \" (zainstalowano)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \" [zainstalowano]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \" nie ma nic do zrobienia\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"\"\n\"%s [A]Wszystkie [Ab]Anuluj [I]Zainstalowane [No]Nie zainstalowane lub (1 2 \"\n\"3, 1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s już jest zbudowany - pomijam budowanie\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s jest nieokreślony\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s jest już obecny.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s jest aktualny - pomijam\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s do aktualizacji/instalacji.\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%s również zostanie zainstalowanie w ramach operacji.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, wymagane przez: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: Bez zmian - pomijam\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: nie jest dostępny z --aur - pomijam\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: nie jest dostępny z --repo - pomijam\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: ignoruję aktualizację pakietu (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: wersja lokalna (%s) jest nowsza niż ta z AUR (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"\"\n\"%s: wprowadź proszę zmienne środowiskowe AUR_USERNAME oraz AUR_PASSWORD by \"\n\"móc głosować\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) Pobrano PKGBUILD z ABS-u: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) Pobrany PKGBUILD: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) Nie udało się pobrać PKGBUILD: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) Przetwarzam SRCINFO: %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(Zainstalowana)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(Zainstalowano: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Osierocona)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Nieaktualny od: %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"AUR URL\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Dodaj %s lub %s do zmiennych środowiskowych\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Unikaj uruchamiania yay jako root lub z sudo.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Sprawdzanie Zależności\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Sprawdź Zależności\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"Sprawdzanie pakietów w wersjach rozwojowych...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Czyszczenie (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Koliduje z\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Usuwanie (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Zależność\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Zależy od\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Opis\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Pokazać różnice?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"Domyślnie wyłącza ustawienie 'provides'  \"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"Czy chcesz usunąć WSZYSTKIE pakiety AUR z pamięci podręcznej?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"Czy chcesz usunąć WSZYSTKIE nieśledzone pliki AUR?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"Czy chcesz usunąć wszystkie inne pakiety AUR z pamięci podręczniej?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"Edytor PKGBUILD-ów?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Błąd podczas wyszukiwania w AUR: %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"Wykluczanie pakietów może spowodować częściową aktualizacje i uszkodzenie \"\n\"systemu\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Jawne\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Jawnie zainstalowane pakiety: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"Nie znaleziono pakietu AUR dla\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"Niepowodzenie zainstalowania warstwy, przewijanie do następnej warstwy\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"Nie udało sie zainstalować następujących pakietów. Wymagana interwencja \"\n\"użytkownika:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Zamieszczono po raz pierwszy\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Pakiety AUR oznaczone jako nieaktualne:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Obce zainstalowane pakiety: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Znaleziono repozytorium git: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"Zakończono GenDB. Nie zainstalowano żadnych pakietów\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Grupy\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Zaimportować?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"Importowanie kluczy przy użyciu gpg...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Słowa kluczowe\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Ostatnio zmodyfikowano\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Licencje\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Lokalne\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Opiekun\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Zależność Budowania\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Zbuduj zależności\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Zaginiony\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Brakujące Pakiety Debugowania AUR:\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Nazwa\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:548\nmsgid \"No AUR package found for\"\nmsgstr \"Nie znaleziono pakietu AUR dla\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"Nie znaleziono pakietu dla\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Brak\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Opcjonalne zależności\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Osierocone (nieutrzymywane) pakiety AUR:\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Nieaktualne\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"Klucze PGP wymagające zaimportowania:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD jest aktualny, pomijam pobieranie: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"Edytować PKGBUILD-y?\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Podstawa Pakietu\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"ID Podstawy Pakietu\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"Pakiety nie występujace w AUR:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Pakiety do zbudowania od zera?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Pakiety do wykluczenia\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"Wykluczone pakiety: (np.: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" lub nazwa repozytorium)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Pakiety do zainstalowania (np.: 1 2 3, 1-3 or ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Popularność\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Kontynuować instalację?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Dostarcza\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"Usunąć zależności potrzebne do zbudowania po instalacji?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Zastępuje\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"Repozytorium\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"Repozytorium AUR\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Poszukuję aktualizacji w AUR...\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"Poszukuję aktualizacji w bazie danych...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Pokazuję tylko pakiety z repozytoriów\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"Rozmiar pamięci podręcznej Pacmana %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"Rozmiar pamięci podręcznej yay %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"URL Snapshota\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Synchronizacja\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"Dziesięć największych pakietów:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"Te pakiety nie są kompatybilne z architekturą Twojego systemu:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"Jest %d możliwych źródeł dla %s:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"Prawdopodobnie działa teraz inna instancja Pacmana. Czekam...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Łączny rozmiar zajmowany przez pakiety: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Łączna liczba zainstalowanych pakietów: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Spróbować je zbudować mimo wszystko?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"Nie można sprzątnąć:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"Nie udało się znaleźć następujących pakietów:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"Nie udało się obsłużyć oceny pakietu dla: %s. err: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"Nie udało się usunąć %s: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Wersja\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Głosów\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Wersja yay v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N]ic\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"przerwane przez użytkownika\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"argument '-' określony bez danych wejściowych\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"nie znaleziono PKGBUILD i .SRCINFO w katalogu\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"nie odnalazłem pakietu: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"nie odnalazłem PKGDEST dla: %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"nie znaleziono wszystkich wymaganych pakietów\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"nie udało się znaleźć żadnych archiwów pakietów z listy %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"zależność\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"błąd sprawdzania wersji rozwojowej: '%s' napotkało na błąd\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"edytor nie zamknął się poprawnie, anuluję: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"błąd ściągania źródeł: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"błąd podczas ściągania %s: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"błąd podczas instalowania pakietów z repozytorium\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"Błąd podczas instalacji:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"błąd podczas budowania: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"błąd podczas scalania %s: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"błąd podczas odczytywania %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"błąd odświeżania baz danych\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"błąd podczas resetowania %s: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"błąd aktualizacji pakietu z przyczyn %s\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"jawne\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"nie udało się stworzyć katalogu '%s': %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"nie udało się otworzyć pliku konfiguracyjnego '%s': %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"nie udało się przetworzyć %s - pomijam: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"nie udało się przetworzyć %s: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"nie udało się przetworzyć .SRCINFO\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"nie udało się odczytać pliku konfiguracyjnego '%s': %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"Nie udało się pozyskać pamięci podręcznej AUR\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"ignorowanie aktualizacji wersji rozwojowej (brak informacji w AUR):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"zbyt długie dane wejściowe\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"niepoprawna liczba: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"niepoprawna opcja '%s'\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"niepoprawna opcja: '--deps' i '--explicit' nie mogą być razem używane\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"Nieprawidłowe repozytorium\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"niepoprawna wartość: %d nie jest pomiędzy %d a %d\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"nie\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"brak kluczy do zaimportowania\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"nie uruchomiono żadnego polecenia\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"Nie określono folderu docelowego\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"Nic do instalowania dla %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"tylko jedna operacja może być użyta na raz\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"dozwolony jest tylko jeden cel\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"pakiet\"\nmsgstr[1] \"pakietów\"\nmsgstr[2] \"pakietów\"\nmsgstr[3] \"pakiety\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"pakiet '%s' nie został odnaleziony\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"Nie znaleziono pakietu w AUR\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"Nie znaleziono pakietu w repozytoriach\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"błąd importowania kluczy\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"usuwanie z pamięci podręcznej pakietów z AUR...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"usuwanie z pamięci podręcznej nieśledzonych plików z AUR...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"PKGDEST dla %s jest wyszczególniony w makepkg, ale nie istnieje: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"Nie ma nic do zrobienia\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"błąd w CreateHandle: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"nieobsłużona operacja\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"nieznana wersja\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"tak\"\n"
  },
  {
    "path": "po/pt.po",
    "content": "# \n# Translators:\n# J G, 2021\n# Eduardo Ervideira, 2023\n# Hugo Carvalho <hugokarvalho@hotmail.com>, 2023\n# Matheus Calegaro <iflops@live.com>, 2024\n# \nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: Matheus Calegaro <iflops@live.com>, 2024\\n\"\n\"Language-Team: Portuguese (https://app.transifex.com/yay-1/teams/123732/pt/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: pt\\n\"\n\"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Diretório de compilação:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Introduza um número (por padrão=1): \"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \" (Existem ficheiros de compilação)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \" (Instalado)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \" [Instalado]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \" não há nada a fazer\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"\"\n\"%s [A]Todos [Ab]ortar [I]nstalado [No]Não instalado or (1 2 3, 1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s já efetuado -- a ignorar compilação\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s não está definido\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s está presente.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s está atualizado -- a ignorar\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s a atualizar/instalar.\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%s também será instalado para esta operação.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, necessário para: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: Sem modificações -- a ignorar\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"\"\n\"%s: não é possível utilizar a opção --aur com este pacote -- a ignorar\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"\"\n\"%s: não é possível utilizar a opção --repo com este pacote -- a ignorar\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: a ignorar atualização de pacote (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: local (%s) é mais recente que AUR (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"\"\n\"%s: definir variáveis de ambiente AUR_USERNAME e AUR_PASSWORD para votação\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) PKGBUILD ABS transferido: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) PKGBUILD transferido: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) Falha ao transferir PKGBUILD: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) Analisando SRCINFO: %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(Instalado)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(Instalado: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Orfão)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Desatualizado: %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"URL AUR\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Adicione %s ou %s às suas variáveis de ambiente\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Evite executar o yay como root/sudo.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Verificar dependências\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Dependências de verificação\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"A verificar pacotes de desenvolvimento...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"A limpar (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Em conflito com\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"A eliminar (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Dependências\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Depende de\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Descrição\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Diffs a mostrar?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"Desativar a definição 'fornece' por defeito\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"Quer remover todos os pacotes AUR da cache?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"Quer remover todos os ficheiros AUR não rastreados?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"Quer remover todos os outros pacotes AUR da cache?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"Editar PKGBUILD com?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Erro durante a pesquisa AUR: %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"A exclusão de pacotes pode causar atualizações parciais e quebra de sistemas\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Explícito\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Pacotes explicitamente instalados: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"Falha ao localizar pacote AUR para\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"Falha ao instalar camada, indo até à camada seguinte.\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"\"\n\"Falha ao instalar os seguintes pacotes. É necessária a intervenção manual:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Primeira submissão\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Pacotes AUR marcados como desatualizados:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Pacotes externos instalados: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Repositório git encontrado: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB terminado. Nenhum pacote foi instalado\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Grupos\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Importar?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"A importar chaves com gpg...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Palavras-chave\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Última Modificação\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Licenças\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Local\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Responsável pela manutenção\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Criar dependências\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Dependências Make\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Em falta\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Pacotes de depuração AUR em falta:\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Nome\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:548\nmsgid \"No AUR package found for\"\nmsgstr \"Nenhum pacote AUR encontrado para\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"Nenhum pacote encontrado para\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Nenhum\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Dependências opcionais\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Pacotes AUR órfãos (não mantidos):\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Desatualizado\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"Chaves PGP a importar:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD atualizado, a ignorar a transferência: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"PKGBUILDs a editar?\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Pacote Base\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"ID do Pacote Base\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"Pacotes que não estão no AUR:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Pacotes a compilar a limpo?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Pacotes a excluir\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"Pacotes a excluir:  (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Pacotes a instalar (eg: 1 2 3, 1-3 or ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Popularidade\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Proceder com a instalação?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Fornece\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"Remover as dependências de make pós-instalação?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Substitui\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"Repositório\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"Repositório AUR\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"A procurar atualizações na AUR...\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"A procurar atualizações nos repositórios...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Mostrando apenas pacotes do repositório\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"Tamanho da cache do pacman %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"Tamanho da cache do yay %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"URL Snapshot\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Sincronizar\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"Dez maiores pacotes:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"Os seguintes pacotes não são compatíveis com a sua arquitetura:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"Existem %[1]d provedores disponíveis para %[2]s:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"Poderá haver outro Pacman em execução. Aguardar...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Tamanho total ocupado por pacotes: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Total instalado de pacotes: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Tentar compilar mesmo assim?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"Não foi possível limpar:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"Não foi possível encontrar os seguintes pacotes:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"Não foi possível gerir votação de pacote para: %s err: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"Não foi possível remover %s: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Versão\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Votos\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Versão Yay v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N]enhum\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"a abortar por opção do utilizador\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"argumento '-' especificado sem entrada em stdin\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"não foi possível localizar PKGBUILD e .SRCINFO no diretório\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"nome de pacote não encontrado: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"não encontrado PKGDEST para: %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"não foi possível localizar todos os pacotes necessários\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"não foi possível localizar nenhum arquivo de pacotes listados em %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"dependência\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"\"\n\"falha na pesquisa por pacotes de desenvolvimento: '%s' encontrou um erro\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"editor não terminou com sucesso, abortando: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"erro ao descarregar fontes: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"erro ao buscar %s: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"erro ao instalar pacotes de repositório\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"erro ao instalar:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"erro ao compilar: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"erro ao fundir %s: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"erro ao ler %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"erro ao recarregar base de dados\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"erro ao repor %s: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"erro ao atualizar instalação do pacote motivo para %s\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"explícito\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"falha ao criar pasta '%s': %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"falha ao abrir arquivo de configuração '%s': %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"falha ao analisar %s -- ignorando: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"falha ao analisar %s: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"falha ao analisar .SRCINFO\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"falha ao ler ficheiro de configuração '%s': %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"falha ao recuperar cache aur\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"\"\n\"a ignorar a atualização de desenvolvimento do pacote (não foi encontrada \"\n\"informação AUR):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"input demasiado longo\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"número inválido: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"opção inválida '%s'\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"\"\n\"opção inválida: '--deps' e '--explicit' não podem ser usados em conjunto\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"repositório inválido\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"valor inválido: %d não está entre %d e %d\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"não\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"nenhuma chave a importar\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"nenhuma análise foi executada\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"nenhum diretório de destino especificado\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"nada a instalar para %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"apenas uma operação pode ser utilizada ao mesmo tempo\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"apenas um destino é permitido\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"pacote\"\nmsgstr[1] \"pacotes\"\nmsgstr[2] \"pacotes\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"pacote '%s' não foi encontrado\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"pacote não encontrado no AUR\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"pacote não encontrado nos repositórios\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"problema ao importar chaves\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"a remover pacotes AUR da cache...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"a remover ficheiros AUR não rastreados da cache...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"o PKGDEST para %s é listado pelo makepkg mas não existe: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"não há nada a fazer\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"não é possível executar CreateHandle: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"operação não implementada\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"versão-desconhecida\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"sim\"\n"
  },
  {
    "path": "po/pt_BR.po",
    "content": "# \n# Translators:\n# J G, 2021\n# Otto Micheletti <michelettiotto@gmail.com>, 2021\n# Harrison Ferreira, 2022\n# Zisa, 2022\n# Fernando Macedo, 2023\n# Felipe Avelar, 2023\n# Lucas Miranda <Liddack@outlook.com>, 2023\n# Matheus Calegaro, 2024\n# Mateus Eduardo, 2025\n# \nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: Mateus Eduardo, 2025\\n\"\n\"Language-Team: Portuguese (Brazil) (https://app.transifex.com/yay-1/teams/123732/pt_BR/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: pt_BR\\n\"\n\"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Diretório de compilação:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Digite um número (padrão=1): \"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \" (Arquivos de Build Existem)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \" (Instalado)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \" [Instalado]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \" não há nada a ser feito\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"\"\n\"%s [A]Todos [Ab]Abortar [I]Instalados [No]Não Instalados ou (1 2 3, 1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s já construído -- pulando build\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s não está definido\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s está presente.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s está atualizado -- pulando\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s para atualizar/instalar.\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%s também será instalado para essa operação.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, requeridos por: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: Sem mudanças -- pulando\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"\"\n\"%s: não é possível utilizar o argumento '--aur' com este pacote -- pulando\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"\"\n\"%s: não é possível utilizar o argumento  '--repo' com este pacote -- pulando\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: ignorando atualização do pacote (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: o pacote local (%s) é mais recente que o do AUR (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"\"\n\"%s: por favor, configure as variáveis de ambiente AUR_USERNAME e \"\n\"AUR_PASSWORD para votar\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) PKGBUILD baixado do ABS: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) PKGBUILD transferido: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) Falha ao baixar PKGBUILD: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) Analisando SRCINFO: %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(Instalado)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(Instalado: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Órfão)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Desatualizado: %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"URL do AUR\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Adicione %s ou %s às suas variáveis de ambiente\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Evite executar o yay como root/sudo.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Verificar dependências\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Dependências de verificação\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"Verificando pacotes em desenvolvimento...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Limpando (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Em conflito com\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Removendo (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Dependências\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Depende de\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Descrição\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Exibir diffs?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"Desativar a definição 'fornece' por padrão\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"Você deseja remover TODOS os pacotes AUR do cache?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"Você deseja remover TODOS os pacotes AUR não monitorados?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"Você deseja remover todos os outros pacotes AUR do cache?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"Editar PKGBUILD com?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Erro durante a busca no AUR: %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"A exclusão de pacotes pode causar atualizações parciais e quebrar sistemas\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Explícito\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Pacotes explicitamente instalados: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"Falha ao localizar pacote AUR para\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"Falha ao instalar camada, indo até à camada seguinte.\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"\"\n\"Falha ao instalar os seguintes pacotes. É necessária a intervenção manual:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Primeira submissão\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Pacotes AUR marcados como desatualizados:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Pacotes externos instalados: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Repositório git encontrado: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB finalizado. Nenhum pacote foi instalado\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Grupos\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Importar?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"Importando chaves com gpg...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Palavras-chave\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Última modificação\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Licenças\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Local\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Mantenedor\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Criar dependências\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Dependências Make\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Em falta\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Pacotes de debug do AUR em falta:\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Nome\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:564\nmsgid \"No AUR package found for\"\nmsgstr \"Nenhum pacote AUR localizado para\"\n\n#: pkg/dep/dep_graph.go:564\nmsgid \"required by\"\nmsgstr \"exigido por\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"Nenhum pacote encontrado para\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Nenhum\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Depêndencias Opcionais\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Pacotes AUR órfãos (não mantidos):\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Desatualizado\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"Chaves PGP que precisam ser importadas:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD atualizado, ignorando a transferência: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"PKGBUILDs a serem editados?\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Pacotes Base\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"ID do Pacote Base\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"Pacotes que não estão no AUR:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Limpar e construir quais pacotes?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Pacotes a excluir\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"Pacotes a excluir: (ex: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" ou nome do repositório)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Pacotes a instalar (ex: 1 2 3, 1-3 ou ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Popularidade\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Prosseguir com a instalação?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Fornece\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"Remover dependências make após a instalação?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Substitui\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"Repositório\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"Repositório AUR\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Procurando atualizações no AUR...\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"Procurando atualizações nos bancos de dados...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Mostrando somente pacotes do repositório\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"Tamanho da cache do pacman %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"Tamanho da cache do yay %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"URL para Snapshot\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Sincronizar\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"Dez maiores pacotes:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"Os seguintes pacotes não são compatíveis com a sua arquitetura:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"Existem %[1]d provedores disponíveis para %[2]s:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"Pode haver outra instância do Pacman em execução. Aguardando...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Espaço total ocupado por pacotes: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Total de pacotes instalados: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Tentar construí-los mesmo assim?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"Não foi possível limpar:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"Não foi possível encontrar os seguintes pacotes:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"Não foi possível gerir votação de pacote para: %s err: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"Não foi possível remover %s: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Versão\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Votos\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Versão do Yay v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N]Nenhum\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"abortando devido ao usuário\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"argumento '-' especificado sem entrada em stdin\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"não foi possível localizar PKGBUILD e .SRCINFO no diretório\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"não foi possível encontrar o nome do pacote: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"não foi possível encontrar PKGDEST para: %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"não foi possível localizar todos os pacotes necessários\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"não foi possível localizar nenhum arquivo de pacotes listados em %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"dependência\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"a busca por pacotes devel falhou: '%s' encontrou um erro\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"editor não finalizou com sucesso, abortando: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"erro ao descarregar as fontes: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"erro ao buscar %s: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"erro ao instalar pacotes do repositório\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"erro ao instalar:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"erro ao construir: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"erro ao mesclar %s: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"erro ao ler %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"erro ao recarregar base de dados\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"erro ao resetar %s: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"erro ao atualizar instalação do pacote motivo para %s\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"explícito\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"falha ao criar diretório '%s':%s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"falha ao abrir o arquivo de configuração '%s': %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"falha ao analisar %s -- pulando: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"falha ao analisar %s: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"falha ao analisar .SRCINFO\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"falha ao ler o arquivo de configuração '%s': %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"falha ao recuperar cache aur\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"\"\n\"ignorando a atualização do desenvolvimento do pacote (não foi localizada \"\n\"informação AUR):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"input muito longo\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"número inválido: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"argumento inválido '%s'\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"\"\n\"opção inválida: os argumentos '--deps' e '--explicit' não podem ser usados \"\n\"juntos \"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"repositório inválido\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"valor inválido: %d não está entre %d e %d\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"não\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"nenhuma chave para ser importada\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"nenhuma busca foi executada\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"nenhum diretório de destino especificado\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"nada a instalar para %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"somente uma operação pode ser utilizada de cada vez\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"apenas um destino é permitido\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"pacote\"\nmsgstr[1] \"pacotes\"\nmsgstr[2] \"pacotes\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"pacote '%s' não foi encontrado\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"pacote não encontrado no AUR\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"pacote não encontrado nos repositórios\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"problema ao importar as chaves\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"removendo pacotes AUR do cache...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"removendo arquivos do AUR não rastreados do cache...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"o PKGDEST para %s está listado pelo makepkg porém não existe: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \" não há nada a ser feito\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"não foi possível executar CreateHandle: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"operação sem manuseio\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"versão-desconhecida\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"sim\"\n"
  },
  {
    "path": "po/ru.po",
    "content": "# \n# Translators:\n# Vladislav Zenkov, 2022\n# Kira Malinova, 2023\n# Victor Golovanenko <drygdryg2014@yandex.ru>, 2023\n# Dancheg97 F, 2023\n# falixfresh, 2023\n# Ravenso BlacK, 2023\n# Vladislav Grechannik, 2024\n# Vladimir Yerilov, 2025\n# Alexandra Harbar, 2025\n# Maxim Tyuterev, 2026\n# \nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: Maxim Tyuterev, 2026\\n\"\n\"Language-Team: Russian (https://app.transifex.com/yay-1/teams/123732/ru/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: ru\\n\"\n\"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Каталог сборки:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Введите номер (по умолчанию=1):\"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \" (Файлы сборки существуют)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \"(Установлено)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \"[Установлено]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \"делать больше нечего\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"\"\n\"%s [В]се [От]менить [У]становленные [Не]установленные или (1 2 3, 1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s уже собран -- сборка пропускается\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s не задан\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s уже существует.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s обновлён -- пропуск\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"обновить/установить.\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"также будет установлен для этой операции.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, требуется пакету: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: Нет изменений -- пропуск\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: невозможно использовать цель с параметром --aur -- skipping\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: невозможно использовать цель с параметром --repo -- skipping\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: игнорирование обновления пакета (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: локальный пакет (%s) новее, чем в AUR (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"\"\n\"%s: пожалуйста, укажите переменные среды AUR_USERNAME и AUR_PASSWORD для \"\n\"голосования\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) Загружен PKGBUILD из ABS: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) Загружен PKGBUILD: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) Не удалось загрузить PKGBUILD:\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) Анализ SRCINFO: %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(Установлено)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(Установлено: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Осиротевший)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Устарел: %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"Ссылка на AUR\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Добавьте %s или %s в переменные среды\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Избегайте запуска yay от имени root/sudo.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Проверка зависимости\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Зависимости, требуемые для проверки\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"Проверка пакетов разработки...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Очистка (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Конфликтует с\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Удаление (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Зависимость\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Зависит от\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Описание\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Показать изменения?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"Отключите настройку 'обеспечивает' по умолчанию\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"Вы хотите удалить ВСЕ пакеты AUR из кэша?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"Вы хотите удалить ВСЕ неотслеживаемые файлы AUR?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"Вы хотите удалить все остальные пакеты AUR из кэша?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"Отредактировать PKGBUILD?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Ошибка поиска в AUR: %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"Исключение пакетов может привести к частичному обновлению и сломать систему\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Явно\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Явно установленные пакеты: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"Не удалось найти пакет AUR для\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"Ошибка установки слоя, переход на следующий слой.\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"\"\n\"Не удалось установить следующие пакеты — требуется ручное вмешательство:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Впервые представленный\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Пакеты AUR, помеченные как устаревшие:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Cторонних пакетов установлено: \"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Найден git репозиторий: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"Генерирование БД завершено. Никакие пакеты не были установлены\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Группы\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Импортировать?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"Импортирование ключей с помощью GPG...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Ключевые слова\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Последнее изменение\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Лицензии\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Локальный\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Сопровождающий\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Создание зависимости\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Зависимости, требуемые для сборки\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Отсутствующие\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Отсутствующие в AUR пакеты для отладки:\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Название\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:564\nmsgid \"No AUR package found for\"\nmsgstr \"Не найден пакет AUR для\"\n\n#: pkg/dep/dep_graph.go:564\nmsgid \"required by\"\nmsgstr \"нужен для\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"Не найден пакет для\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Нет\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Дополнительные зависимости\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Осиротевшие (неподдерживаемые) пакеты AUR:\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Устарел\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"Ключи PGP, требующие импорта:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD находится в актуальном состоянии, пропускается загрузка: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"Отредактировать PKGBUILD?\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Базовый пакет\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"Идентификатор пакета\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"Пакет не найден в AUR:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Пакеты для чистой сборки?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Пакеты для исключения\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"Исключить пакеты: (напр.: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" или название репозитория)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Пакеты для установки: (напр.: 1 2 3, 1-3 or ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Популярность\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Продолжить установку?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Предоставляет\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"Удалить зависимости сборки после установки?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Заменяет\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"Репозиторий\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"Репозиторий AUR\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Поиск обновлений пакетов AUR...\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"Поиск обновлений в базах данных...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Показываются только пакеты из репозиториев\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"Размер кэша pacman %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"Размер кэша yay %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"Ссылка снимка\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Синхронизация\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"Десять самых больших пакетов:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"Следующие пакеты несовместимы с вашей архитектурой:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"%[2]s доступен в %[1]d источниках:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"Возможно, запущен другой процесс Pacman. Ожидание...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Суммарный размер, занятый пакетами: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Всего установлено пакетов: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Попытаться собрать, несмотря на несовместимость?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"Невозможно очистить:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"Не удалось найти следующие пакеты:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"Не удалось обработать голосование за: %s. ошибка: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"Не удается удалить %s: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Версия\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Голосов\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Версия Yay: v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[Н]ет\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"прервано пользователем\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"аргумент '-' задан без ввода из stdin\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"не удалось найти PKGBUILD и .SRCINFO в каталоге\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"Неудалось найти пакет с названием: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"не удалось найти PKGDEST для: %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"не удалось найти все необходимые пакеты\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"Не удалось найти архивы пакетов в %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"зависимости\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"проверка пакета '%s' не завершена из-за ошибки\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"неудачный выход из редактора, отмена: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"ошибка загрузки исходников: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"ошибка скачивания %s: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"ошибка установки пакетов из репозиториев\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"ошибка установки:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"ошибка сборки: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"ошибка объединения %s: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"ошибка чтения %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"ошибка обновления базы данных\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"ошибка сброса %s: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"ошибка изменения причины установки пакета на %s\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"явно\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"ошибка создания каталога '%s': %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"ошибка открытия файла конфигурации '%s': %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"ошибка при анализе %s --- пропуск: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"ошибка при анализе %s: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"ошибка при анализе .SRCINFO\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"не удалось прочитать файл конфигурации '%s': %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"не удалось получить кэш AUR\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"Игнорирование обновления пакета devel (информация об AUR не найдена):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"ввод слишком длинный\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"неверное число: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"неверная опция '%s'\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"\"\n\"неверная опция: невозможно использовать опции '--deps' и '--explicit' \"\n\"одновременно\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"недействительный репозиторий\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"неверное значение: %d не в промежутке между %d и %d \"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"нет\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"нет ключей для импорта\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"запрос не был выполнен\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"не выбраны целевые директории\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"нечего установить из %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"только одна операция может быть вызвана за один раз\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"разрешена только одна цель\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"пакет\"\nmsgstr[1] \"пакеты\"\nmsgstr[2] \"пакеты\"\nmsgstr[3] \"пакеты\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"пакет '%s' не найден\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"пакет не найден в AUR\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"пакет не найден в репозиториях\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"проблема импортирования ключей\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"удаление пакетов AUR из кэша...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"удаление неотслеживаемых файлов AUR из кэша...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"файл PKGDEST для %s указан в выводе makepkg, но не существует: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"делать больше нечего\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"невозможно выполнить CreateHandle: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"необработанная операция\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"неизвестная версия\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"да\"\n"
  },
  {
    "path": "po/ru_RU.po",
    "content": "# \n# Translators:\n# J G, 2021\n# makvasm, 2021\n# antsif.a, 2022\n# Demir Yerli, 2022\n# Антон Карасев <uselessfire@gmail.com>, 2023\n# Ravenso BlacK, 2024\n# Victor Golovanenko <drygdryg2014@yandex.ru>, 2024\n# Vladislav Zenkov, 2024\n# falixfresh, 2024\n# Kira Malinova, 2024\n# Dancheg97 F, 2024\n# Vladislav Grechannik, 2024\n# ratijas, 2024\n# Vladimir Yerilov, 2025\n# Maxim Tyuterev, 2026\n# \nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: Maxim Tyuterev, 2026\\n\"\n\"Language-Team: Russian (Russia) (https://app.transifex.com/yay-1/teams/123732/ru_RU/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: ru_RU\\n\"\n\"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Каталог сборки:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Введите номер (по умолчанию = 1): \"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \" (файлы сборки существуют)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \" (Установлено)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \" [Установлено]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \"делать нечего\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"\"\n\"%s [A]Все [Ab]Прервать [I]Установленные [No]Неустановленные или (1 2 3, 1-3,\"\n\" ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s уже собран --- сборка пропускается\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s не задан\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s уже существует.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%sобновлён до последней версии --- пропуск\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s обновить/установить.\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%s также будет установлен для этой операции.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, требуется пакету: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: Нет изменений --- пропуск\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: невозможно использовать цель с опцией --aur --- пропуск\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: невозможно использовать цель с опцией --repo --- пропуск\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: пропуск обновления пакета (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: локальная версия (%s) новее, чем в AUR (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"\"\n\"пожалуйста, укажите AUR_USERNAME и AUR_PASSWORD в переменных среды для \"\n\"возможности голосовать\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) Скачан PKGBUILD из ABS: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) Скачан PKGBUILD: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) Не удалось загрузить PKGBUILD:\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) Анализ SRCINFO: %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(установлено)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(установлено: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(сирота в AUR)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(устарел: %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"AUR URL\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Добавьте %s или %s в переменные окружения\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Не запускайте yay от имени root/sudo.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Проверка зависимости\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Зависимости проверки\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"Проверка пакетов в разработке (-git, -svn и т.п.)...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Очистка (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Конфликтует с\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Удаление (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Зависимость\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Зависит от\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Описание\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Показать изменения?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"Отключите настройку 'обеспечивает' по умолчанию\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"Вы хотите удалить все пакеты AUR из кэша?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"Вы хотите удалить все неотслеживаемые файлы AUR?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"Вы хотите удалить все остальные пакеты AUR из кэша?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"Отредактировать PKGBUILD?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Ошибка поиска в AUR: %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"Исключение пакетов может привести к частичным обновлениям и поломкам системы\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Явно\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Пакеты, установленные по запросу пользователя: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"Не удалось найти пакет AUR для\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"Ошибка установки слоя, переход на следующий слой.\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"\"\n\"Не удалось установить следующие пакеты. Необходимо ручное вмешательство:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Впервые загружен на AUR\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Пакеты AUR, помеченные как устаревшие:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Установлено сторонних пакетов: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Найден git-репозиторий: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB завершён без установки пакетов\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Группы\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Импортировать?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"Импортирование ключей с помощью gpg...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Ключевые слова\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Последнее изменение\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Лицензии\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Локальный\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Сопровождающий\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Зависимость сборки\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Зависимости сборки\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Отсутствующие\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Отсутствующие в AUR пакеты для отладки:\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Название\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:564\nmsgid \"No AUR package found for\"\nmsgstr \"Не найден пакет AUR для\"\n\n#: pkg/dep/dep_graph.go:564\nmsgid \"required by\"\nmsgstr \"нужен для\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"Не найден пакет для\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Нет\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Факультативные зависимости\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Брошенные (без сопровождающего) пакеты AUR:\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Устарел\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"Ключи PGP, требующие импорта:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"Актуальный PKGBUILD, пропуск загрузки\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"Отредактировать PKGBUILD?\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Группа пакетов\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"ID группы пакетов\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"Пакет не найден в AUR:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Пакеты, для которых требуется очистить кэш сборки?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Пакеты для исключения\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"Пакеты для исключения: (пример: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" или имя в репозитории)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Пакеты для установки (пример: 1 2 3, 1-3 или ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Популярность\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Продолжить установку?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Обеспечивает\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"Удалить зависимости для сборки после установки?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Заменяет\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"Репозиторий\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"Репозиторий AUR\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Поиск обновлений в AUR...\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"Поиск обновлений в базе данных...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Показываются только пакеты из репозиториев\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"Размер кэша \\\"pacman\\\"\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"Размер кэша \\\"yay\\\"\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"URL архива\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Синхронизация\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"10 самых объёмных пакетов:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"Следующие пакеты несовместимы с архитектурой вашего процессора:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"%[2]s доступен в %[1]d источниках:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"Возможно, запущен другой экземпляр Pacman. Ожидание...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Суммарный размер, занятый пакетами: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Всего установлено пакетов: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Попытаться собрать их, несмотря на несовместимость?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"Невозможно очистить:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"Не удалось найти следующие пакеты:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"Не удалось обработать голосование за: %s. ошибка: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"Не удается удалить %s: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Версия\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Голосов\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Yay версии v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N]Нет\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"прерывание по запросу пользователя\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"аргумент '-' задан без ввода из stdin\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"не удалось найти PKGBUILD и .SRCINFO в каталоге\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"невозможно найти пакет: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"невозможно найти файл PKGDEST для: %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"не удалось найти все необходимые пакеты\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"Не удалось найти архивы пакетов в %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"зависимость\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"Проверка для пакета '%s' не закончилась успехом\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"выход из редактора был неуспешным, прерывание: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"ошибка загрузки исходников: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"ошибка получения %s: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"ошибка установки пакетов из репозиториев\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"ошибка установки:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"ошибка сборки: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"ошибка объединения %s: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"ошибка чтения %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"ошибка обновления базы данных\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"ошибка сброса %s: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"ошибка изменения причины установки пакета на %s\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"явно\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"ошибка создания каталога '%s': %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"ошибка открытия файла конфигурации '%s': %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"ошибка при анализе %s --- пропуск: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"ошибка при анализе %s: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"ошибка при анализе .SRCINFO\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"ошибка чтения файла конфигурации '%s': %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"не удалось получить кэш AUR\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"Игнорирование обновления пакета devel (информация об AUR не найдена):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"ввод слишком длинный\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"некорректный номер: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"некорректный параметр '%s'\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"\"\n\"некорректный параметр:  '--deps' и '--explicit' не могут быть использованы \"\n\"вместе\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"недействительный репозиторий\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"некорректное значение: %d не лежит между %d и %d\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"нет\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"нет ключей для импорта\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"запрос не был выполнен\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"не выбраны целевые директории\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"нечего установить из %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"только одна операция может быть вызвана за один раз\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"разрешена только одна цель\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"пакет\"\nmsgstr[1] \"пакеты\"\nmsgstr[2] \"пакеты\"\nmsgstr[3] \"пакеты\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"пакет '%s' не найден\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"пакет не найден в AUR\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"пакет не найден в репозиториях\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"проблема импортирования ключей\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"удаление пакетов AUR из кэша...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"удаление неотслеживаемых файлов AUR из кэша...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"файл PKGDEST для %s означен в выводе makepkg, но не существует: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"делать больше нечего\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"невозможно выполнить CreateHandle: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"неизвестная операция\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"неизвестная версия\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"да\"\n"
  },
  {
    "path": "po/sk.po",
    "content": "#\n# Translators:\n# Matej Mrenica, 2022\n# Peter Cyprich, 2024\n# Michal Fusatý, 2024\n#\nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: Michal Fusatý, 2024\\n\"\n\"Language-Team: Slovak (https://app.transifex.com/yay-1/teams/123732/sk/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: sk\\n\"\n\"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n >= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Adresár zostavenia:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Zadajte číslo (predvolené=1):\"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \"(Súbory na zostavenie existujú)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \"(Nainštalované)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \"[Nainštalované]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \"nie je čo robiť\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"\"\n\"%s [A]Všetko [Ab]Zrušiť [I]Nainštalované [No]Nenainštalované alebo (1 2 3, \"\n\"1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s už vytvorené -- preskočenie zostavenia\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s nie je nastavené\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s je prítomný.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s je aktuálny -- preskakujem\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s na aktualizáciu/inštaláciu.\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%sbude tiež nainštalovaný pre túto operáciu.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, vyžaduje: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s Žiadne zmeny -- preskakujem\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%snemožno použiť cieľ s voľbou --aur -- preskakujem\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s nemožno použiť cieľ s voľbou --repo -- preskakujem\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s ignorujem aktualizáciu balíčka (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s lokálne (%s) je novšie ako AUR (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"\"\n\"%s prosím nastavte premenné prostredia AUR_USERNAME (používateľské meno AUR)\"\n\" a AUR_PASSWORD (heslo AUR) pre hlasovanie\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) Stiahnuté PKGBUILD z ABS: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) Stiahnuté PKGBUILD: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) Nepodarilo sa stiahnuť PKGBUILD: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) Analýza SRCINFO: %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(Nainštalované)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(Nainštalované: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Osirotené)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Zastarané: %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"AUR URL\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Pridajte %s or %s do vašich premenných prostredia\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Vyhnite sa spúšťaniu yay ako root/sudo.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Skontrolovať závislosti\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Skontrolovať závislosti\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"Kontrolujem balíčky vývoja...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Čiestenie (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Konflikty s\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Mazanie (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Závislosť\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Závisí na\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Popis\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Rozdiely na zobrazenie?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"Predvolene zrušiť nastavenie 'provides'\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"Chcete odstrániť VŠETKY balíky AUR z vyrovnávacej pamäte?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"Chcete odstrániť VŠETKY nesledované súbory AUR?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"Chcete odstrániť všetky ostatné balíky AUR z vyrovnávacej pamäte?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"Upraviť PKGBUILD s?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Chyba počas vyhľadávania AUR: %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"Vynechanie balíčkov môže spôsobiť čiastočné vylepšienia a zničiť systém\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Explicitne\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Explicitne nainštalované balíky: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"Nepodarilo sa nájsť AUR balíček \"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"Nepodarilo sa nainštalovať vrstvu, presúvam sa na ďalšiu vrstvu\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"\"\n\"Nepodarilo sa nainštalovať nasledovné balíčky. Je potrebná manuálna \"\n\"interakcia: \"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Prvý krát predložené\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Balíčky AUR označené ako neaktuálne:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Cudzie nainšťalované balíčky: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Nájdený git repozitár: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB dokončené. Žiadne balíčky neboli nainštalované\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Skupiny\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Importovať?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"Importovanie kľúčov pomocou gpg...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Kľúčové slová\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Naposledy upravené\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Licencie\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Lokálne\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Správca\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Spraviť závislosť\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Spraviť závislosť\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Chýbajúce\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Chýbajúce AUR balíčky na ladenie: \"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Názov\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:548\nmsgid \"No AUR package found for\"\nmsgstr \"Nenašiel sa AUR balíček pre \"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"Nenašiel sa balíček pre \"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Žiadne\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Voliteľné závislosti\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Osirotené (neudržiavané) balíčky AUR: \"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Zastarané\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"PGP kľúče potrebujú importovať:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD aktuálne, preskakujem sťahovanie: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"PKGBUILDy na editáciu?\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Základ balíčka\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"ID Základu balíčka\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"Balíčky, ktoré nie sú v AUR:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Balíčky, ktoré vybudovať nanovo?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Balíčky, ktoré vynechať\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"\"\n\"Balíčky, ktoré vynechať: (napr.: \\\"1 2 3\\\", \\\"1-3\\\" \\\"^4\\\" alebo názov \"\n\"repozitára)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Balíčky na inštaláciu (napr: 1 2 3, 1-3 or ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Popularita\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Pokračovať s inštaláciou?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Poskytuje\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"Odstrániť make závislosti po inštalácií?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Nahrádza\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"Repozitár\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"Repozitár AUR\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Vyhľadávanie aktualizácií v AUR...\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"Vyhľadávanie aktualizácií v databázach...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Zobrazenie iba repo balíčkov\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"Veľkosť pacman cache %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"Veľkosť yay cache %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"URL Snapshotu\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Synchronizácia\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"Desať najväčších balíčkov:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"Nasledovné balíčky nie sú kompatibilné s vašou architektúrou: \"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"\"\n\"Existuje/existujú %d poskytovateľ/poskytovatelia/poskytovateľov pre %s: \"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"Môže byť spustená ďalšia inštancia Pacmana. Čakanie...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Celková veľkosť obsadená balíčkami: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Celkový počet nainštalovaných balíčkov: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Pokúsiť sa ich zostaviť aj tak?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"Nepodarilo sa vyčistiť:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"Nie je možné nájsť nasledujúce balíčky:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"Nie je možné spracovať hlasovanie o balíku pre: %s. err: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"Nepodarilo sa odstrániť %s: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Verzia\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Hlasy\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Verzia Yay v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N]Žiadne\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"prerušenie kvôli používateľovi\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"argument \\\"-\\\" špecifikovaný bez vstupu alebo štandardného vstupu\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"nepodarilo sa nájsť PKGBUILD a .SRCINFO v adresári\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"nepodarilo sa nájsť názov balíčku: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"nemožno nájsť PKGDEST pre: %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"nemožno nájsť všetky potrebné balíčky\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"nemožno nájst žiadne archívy balíčkov uvedené v %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"závislosť\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"nepodarilo sa skontrolovať vývoj pre balíček: '%s' postihla chyba\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"editor nebol úspešne ukončený, ruším: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"chyba pri sťahovaní zdrojov: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"načítanie chýb %s: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"chyba pri inštalácií balíčkov z repozitára\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"chyba pri inštalovaní:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"chyba vytvárania: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"chyba pri zlúčení %s: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"chyba čítania %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"chyba obnovenia databáz\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"chyba resetovania %s: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"chyba pri aktualizácii dôvodu inštalácie balíka na %s\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"explicitné\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"nepodarilo sa vytvoriť adresár '%s': %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"nepodarilo sa otvoriť konfiguračný súbor '%s': %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"nepodarilo sa analyzovať %s -- preskakujem: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"nepodarilo sa analyzovať %s: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"nepodarilo sa analyzovať .SRCINFO\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"nepodarilo sa prečítať konfiguračný súbor '%s': %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"nepodarilo sa získať aur cache\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"ignorujem aktualizáciu balíčka vývoja (nenašli sa AUR informácie):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"vstup príliš dlhý\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"neplatné číslo: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"neplatná možnosť '%s'\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"neplatná možnosť: '--deps' a '--explicit' nemôže byť použité spolu\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"neplatný repozitár\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"neplatná hodnota: %d nie je mezdi %d a %d\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"nie\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"žiadne kľúče na importovanie\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"nebola vykonaná žiadna požiadavka\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"nie sú špecifikované žiadne adresáre\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"nie je čo inštalovať pre %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"naraz môže byť použitá iba jedna operácia\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"je povolený iba jeden cieľ\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"balíček\"\nmsgstr[1] \"balíčkov\"\nmsgstr[2] \"balíčkov\"\nmsgstr[3] \"balíčky\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"balíček '%s' sa nenašiel\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"balíček sa nenašiel v AUR\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"balíček sa nenašiel v repozitároch\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"problém s importom kľúčov\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"odstraňujem balíčky AUR z cache...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"odstraňujem nesledované AUR balíčky z cache...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"PKGDEST pre %s je uvedený v makepkg, ale neexistuje %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"nie je čo urobiť\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"nepodarilo sa CreateHandle: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"neošetrená operácia\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"neznáma-verzia\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"áno\"\n"
  },
  {
    "path": "po/sv.po",
    "content": "# \n# Translators:\n# J G, 2021\n# August Wikerfors, 2023\n# Luna Jernberg <droidbittin@gmail.com>, 2026\n# \nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: Luna Jernberg <droidbittin@gmail.com>, 2026\\n\"\n\"Language-Team: Swedish (https://app.transifex.com/yay-1/teams/123732/sv/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: sv\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Byggkatalog:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Ange ett nummer: (standard = 1): \"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \" (Byggfiler finns)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \" (Installerad)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \" [Installerad]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \" inget behöver göras\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"\"\n\"%s [A]lla [Ab]Avbryt [I]nstallerade [No]EjInstallerade eller (1 2 3, 1-3, \"\n\"^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s redan byggt -- hoppar över bygge\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s är inte inställd\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s finns.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s är ajour -- hoppar över\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s att uppgradera/installera.\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%s kommer också att installeras för denna operation.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, krävs av: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: Inga ändringar -- hoppar över\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: kan inte använda mål med växeln --aur -- hoppar över\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: kan inte använda mål med växeln --repo -- hoppar över\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: ignorerar paketuppgradering (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: lokalt paket (%s) är nyare än AUR (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"\"\n\"%s: vänligen ställ in miljövariablerna AUR_USERNAME och AUR_PASSWORD för att\"\n\" rösta\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) Hämtat PKGBUILD från ABS: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) Hämtat PKGBUILD: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) Misslyckades att ladda ner PKGBUILD: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) Tolkar SRCINFO: %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(Installerad)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(Installerade: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Övergiven)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Föråldrade: %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"AUR-webbadress\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Lägg till %s eller %s bland dina miljövariabler\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Undvik att köra yay som root/sudo.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Kontrollberoende\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Kontrollberoenden\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"Kontrollerar utvecklingspaket...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Rensar (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Krockar med\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Tar bort (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Beroende\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Beror av\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Beskrivning\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Visa diff?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"Inaktivera  \\\"tillhandahåller\\\" inställning som standard\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"Vill du verkligen ta bort ALLA AUR-paket från cachen?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"Vill du verkligen ta bort ALLA ospårade AUR-filer?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"Vill du verkligen ta bort alla andra AUR-paket från cachen?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"Redigera PKGBUILD med?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Fel vid AUR-sökning: %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"Att exkludera paket kan orsaka partiella uppgraderingar och ha sönder system\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Uttryckligen\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Uttryckligen installerade paket: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"Misslyckades att hitta AUR paket för\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"Misslyckades att installera lager, rullar upp till nästa lager.\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"Misslyckades att bygga följande paket. Manuell intervention krävs:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Först skapad\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"AUR-paket markerade som föråldrade:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Okända installerade paket: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Hittade git-arkiv: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB klar. Inga paket installerades\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Grupper\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Importera?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"Importerar nycklar med gpg...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Nyckelord\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Senast ändrad\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Licenser\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Lokal\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Underhållare\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Byggberoende\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Byggberoenden\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Saknas\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Saknar AUR-felsökningspaket:\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Namn\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:564\nmsgid \"No AUR package found for\"\nmsgstr \"Inga AUR paket hittades för\"\n\n#: pkg/dep/dep_graph.go:564\nmsgid \"required by\"\nmsgstr \"krävs av:\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"Inget paket hittades för\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Inga\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Valfria beroenden\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Föräldralösa (icke underhållna) AUR paket:\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Föråldrat\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"PGP-nycklar kräver import:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD uppdaterad, hoppar över nedladdning: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"Redigera PKGBUILD-filer?\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Grundpaket\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"Grundpakets-ID\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"Paket som inte finns i AUR:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Bygg paket rent (cleanBuild)?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Paket att exkludera\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"\"\n\"Paket att hoppa över: (t.ex: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" eller \"\n\"centralkatalogsnamn)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Paket att installera (t.ex: 1 2 3, 1-3 eller ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Popularitet\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Fortsätt med installation?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Tillhandahåller\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"Ta bort byggberoenden efter installation?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Ersätter\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"Centralkatalog\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"Centralkatalog AUR\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Söker efter uppdateringar på AUR...\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"Söker efter uppdateringar i databaserna...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Visar endast centralkatalogspaket\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"Storlek på pacman cache %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"Storlek på yay cache %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"Snapshot-URL\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Synk\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"Tio största paketen:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"Följande paket stöds inte av din arkitektur:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"Det finns %[1]d tillhandahållare tillgängliga för %[2]s:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"Det kan finns en till instans av pacman som kör. Väntar...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Total paketstorlek: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Antal installerade paket: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Försök att bygga dem ändå?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"Webbadress\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"Kunde inte rensa:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"Det gick inte att hitta följande paket:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"Kan inte hantera paketröstning för: %s . fel: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"Kunde inte ta bort %s: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Version\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Röster\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Yay-version v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N]Inga\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"avbryter på grund av användare\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"argument '-' specificerat utan indata på stdin\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"kan inte hitta PKGBUILD eller .SRCINFO i katalog\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"kunde inte hitta paketet: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"kunde inte hitta PKGDEST för: %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"kunde inte hitta alla paket som krävs\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"kunde inte hitta några paketarkiv listade i %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"beroende\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"Utvecklings koll för paket misslyckades '%s' stötte på ett fel\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"redigeraren avslutades inte korrekt, avbryter: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"fel vid nedladdning av källfiler: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"fel vid hämtning av %s: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"fel vid installation av centralkatalogspaket\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"fel vid installation:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"fel vid bygge: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"fel vid sammanslagning av %s: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"fel vid läsning av %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"fel vid uppdatering av databaserna\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"fel vid återställning av %s: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"fel vid uppdatering av paketinstallations anledning till %s\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"uttryckligen\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"misslyckades med att skapa katalog '%s': %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"misslyckades med att öppna konfigurationsfilen '%s': %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"misslyckades med att tolka %s -- hoppar över: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"misslyckades med att tolka %s: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"misslyckades med att tolka .SRCINFO\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"misslyckades med att läsa konfigurationsfilen '%s': %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"misslyckades med att hämta aur Cache\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"ignorerar paket devel uppgradering (ingen AUR info hittades):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"för lång indata\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"ogiltigt nummer: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"ogiltig växel '%s'\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"\"\n\"ogiltigt alternativ: '--deps' och '--explicit' kan inte användas tillsammans\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"ogiltig centralkatalog\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"ogiltigt värde: %d är inte mellan %d och %d\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"nej\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"inga nycklar att importera\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"ingen fråga utfördes\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"inga målkataloger specificerade\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"inget att installera för %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"bara en operation går att utföra åt gången\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"endast ett mål är tillåtet\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"paket\"\nmsgstr[1] \"paket\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"paketet '%s' kunde inte hittas\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"paketet hittades inte i AUR\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"paketet hittades inte i centralkatalogerna\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"ett problem uppstod vid nyckelimporten\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"tar bort AUR-paket från cachen...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"tar bort ospårade AUR-filer från cachen...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"den PKGDEST för %s som står med i makepkg finns ej: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"det finns ingenting att göra\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"misslyckades med att skapa handtag (CreateHandle): %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"okänd operation\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"okänd-version\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"ja\"\n"
  },
  {
    "path": "po/tr.po",
    "content": "#\n# Translators:\n# Ahmet Arda Kavakcı, 2022\n# Mehmet Özgür Bayhan <mozgurbayhan@gmail.com>, 2023\n# can avar, 2023\n# yiğit yeten, 2023\n#\nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: yiğit yeten, 2023\\n\"\n\"Language-Team: Turkish (https://app.transifex.com/yay-1/teams/123732/tr/)\\n\"\n\"Language: tr\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n > 1);\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \"(Kurulum Dosyaları Var)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \"(Kuruldu)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \"[Kuruldu]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \"yapılacak bir şey yok\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"%s [A]Hepsi [Ab]İptal [I]Kurulmuş [No]Kurulmamış veya (1 2 3, 1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s çoktan yapıldı -- yapılandırma atlanıyor\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s belirlenmiş değil\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s hâlihazırda bulunuyor.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s güncel -- atlanıyor\"\n\n#: pkg/upgrade/service.go:292\n#, fuzzy\nmsgid \"%s to upgrade/install.\"\nmsgstr \"Yükseltilecek/yüklenecek paketler.\"\n\n#: pkg/upgrade/service.go:286\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, ihtiyaç duyan: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: Değişiklik yok -- atlanıyor\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: hedef --aur seçeneği ile kullanılamaz -- atlanıyor\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: hedef --repo seçeneği ile kullanılamaz -- atlanıyor\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: paket güncellemesi göz ardı ediliyor (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: yerel (%s) AUR'dan (%s) daha güncel\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for voting\"\nmsgstr \"\"\n\"Oy verebilmek için AUR_USERNAME ve AUR_PASSWORD ortam değişkenlerini \"\n\"ayarlayın\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) PKGBUILD, ABS'den indirildi: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) PKGBUILD indirildi: %s\"\n\n#: pkg/download/aur.go:82\n#, fuzzy\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) PKGBUILD indirildi: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) SRCINFO çözümleniyor: %s\"\n\n#: pkg/query/types.go:72 pkg/query/types.go:103\nmsgid \"(Installed)\"\nmsgstr \"(Kuruldu)\"\n\n#: pkg/query/types.go:70 pkg/query/types.go:101\nmsgid \"(Installed: %s)\"\nmsgstr \"(Kuruldu: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Öksüz bırakıldı)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Güncel değil: %s)\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"AUR URL\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Ortam değişkenlerinize %s veya %s seçeneklerini ekleyin\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Yay'ı root/sudo olarak çalıştırmaktan kaçının\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Bağımlılık Kontrolü\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Bağımlıkları Kontrol Et\"\n\n#: pkg/upgrade/service.go:90\nmsgid \"Checking development packages...\"\nmsgstr \"Geliştirme paketleri kontrol ediliyor...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Temizleniyor (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Çakışıyor:\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Siliniyor (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Bağımlılık\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Bağımlı:\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Açıklama\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Gösterilecek olan değişiklikler (diff)?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"Varsayılan olarak 'provides' ayarını geçersiz kıl\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"AUR paketlerinin TÜMÜNÜ önbellekten silmek istiyor musun?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"İzlenmemiş AUR paketlerinin TÜM dosyalarını silmek istiyor musun?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"Tüm diğer AUR paketlerini önbellekten silmek istiyor musun?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"PKGBUILD'i neyle düzenleyeceksin?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"AUR araması yaparken hata: %s\\n\"\n\n#: pkg/upgrade/service.go:296\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"Paketlerin dışlanması, kısmi yükseltmelere ve sistemlerin bozulmasına neden \"\n\"olabilir\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Açık\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Doğrudan kurulan paketler: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"Şunun için AUR paketi bulunamadı:\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"Katman yüklenemedi, sonraki katmana geçiliyor.\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"İstenen paketler yüklenemedi. Manüel müdahale gerekli:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"İlk İletilen\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Eski Olarak İşaretlenmiş AUR Paketleri:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Yabancı kurulan paketler: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Git deposu bulundu: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB tamamlandı. Hiçbir paket kurulmadı\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Gruplar\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"İçe Aktar?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"GPG anahtarları içe aktarılıyor...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Anahtar Kelimeler\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Son Değiştirme\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Lisanslar\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Yerel\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Bakımcı:\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Make Bağımlılığı\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Make Bağımlılıkları\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Eksik AUR Hata Ayıklama Paketleri:\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Kayıp\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"İsim\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:548\nmsgid \"No AUR package found for\"\nmsgstr \"Şunun için AUR paketi bulunamadı: \"\n\n#: pkg/dep/dep_graph.go:182\n#, fuzzy\nmsgid \"No package found for\"\nmsgstr \"Şunun için AUR paketi bulunamadı: \"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Yok\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"İsteğe Bağlı Bağımlılıklar\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Orphan (bakımsız) AUR Paketleri:\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Eski\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"İçe aktarılması gereken PGP anahtarları:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD güncel, indirme geçiliyor: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"Düzenlenecek PKGBUILD'ler?\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"Paket Temel Kimliği (ID):\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Paket Temeli\"\n\n#: pkg/query/aur_warnings.go:67\nmsgid \"Packages not in AUR:\"\nmsgstr \"AUR'da bulunmayan paketler:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"cleanBuild yapılacak paketler?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Dışlanacak paketler\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"Dışlanacak paketler: (ör. \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" veya depo ismi)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Kurulacak paketler (ör. 1 2 3, 1-3 veya ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Popülerlik\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Kurmaya devam et?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Sağlar:\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"Make bağımlılıkları kurulum sonrası silinsin mi?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"AUR Deposu\"\n\n#: print.go:30 pkg/db/ialpm/alpm.go:191\nmsgid \"Repository\"\nmsgstr \"Depo\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:72\nmsgid \"Searching AUR for updates...\"\nmsgstr \"AUR güncellemeleri aranıyor...\"\n\n#: pkg/upgrade/service.go:160\nmsgid \"Searching databases for updates...\"\nmsgstr \"Veritabanlarında güncellemeler aranıyor...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Sadece depo paketleri gösteriliyor\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"pacman önbelleğinin boyutu: %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"yay önbelleğinin boyutu: %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"Anlık görüntü URL'si\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Senkronize\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"En büyük 10 paket:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"Aşağıdaki paketler sistem mimarin ile uyumlu değil:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"%[2]s için %[1]d sağlayıcı bulunuyor:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"Başka bir Pacman talebi çalışıyor olabilir. Bekleniyor...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Paketlerin tuttuğu Toplam Boyut: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"İndirilen toplam paketler: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Yine de yapılandırmaya çalış?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"Temizlenemiyor:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"Aşağıdaki paketler bulunamadı:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"Şunlar için paket oylaması işlenemiyor:%s. hata: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"Kaldırılamıyor %s: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Sürüm\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Oylar\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Yay sürümü v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N]Hiçbiri\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Yapım dizini:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Bir sayı girin (varsayılan=1):\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"kullanıcı nedeniyle iptal ediliyor\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"stdin üzerinde girdi olmadan '-' argümanı kullanıldı\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"dizin içerisinde PKGBUILD ve .SRCINFO bulunamadı\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"paket ismi bulunamadı: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"PKGDEST dizini bulunamadı: %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"tüm gereken paketler bulunamadı\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"arşivde listelenmiş paketler bulunamadı %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:287\nmsgid \"dependency\"\nmsgstr \"bağımlılık\"\n\n#: pkg/vcs/vcs.go:96 pkg/vcs/vcs.go:100\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"Paket gelişim kontrolü başarısız: '%s' hatayla karşılaştı\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"düzenleyici başarılı bir şekilde çıkış yapmadı, iptal ediliyor: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"kaynaklar indirilirken hata: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"%s getirilirken hata: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"depo paketleri indirilirken hata\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"kurarken hata:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"yapılırken hata: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"%s birleştirilirken hata: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"%s okunurken hata\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"veritabanlarını yenilenirken hata\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"%s yenilenirken hata: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"paket yükleme nedeni güncellenirken hata oluştu %s\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"açık\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"'%s' dizini oluşturulamadı: %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"'%s' yapılandırma dosyası açılamadı: %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"%s çözümlenirken hata -- atlanıyor: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"%s çözümlenirken hata: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \" .SRCINFO ayrıştırılamadı\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"'%s' yapılandırma dosyası okunurken hata: %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"aur Cache alınamadı\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"devel paketi yükseltmesi yok sayılıyor (AUR bilgisi bulunamadı):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"girdi çok uzun\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"geçersiz sayı: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"geçersiz seçenek '%s'\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"geçersiz seçenek: '--deps' ve '--explicit' beraber kullanılamaz\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"geçersiz depo\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"geçersiz değer: %d, %d ile %d arasında değil.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"aktarılacak anahtar yok\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"hiçbir sorgu çalıştırılmadı\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"hiç bir hedef dizin belirtilmedi\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"hayır\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"indirelecek bir şey yok %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"bir seferde sadece bir işlem kullanılabilir\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"'%s' paketi bulunamadı\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"paket AUR'da bulunamadı\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"paket depolarda bulunamadı\"\n\n#: pkg/upgrade/service.go:292\n#, fuzzy\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"Paket Temeli\"\nmsgstr[1] \"Paket Temeli\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"anahtarları aktarırken sorun\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"AUR paketleri önbellekten siliniyor...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"izlenmemiş AUR paketleri önbellekten siliniyor...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"%s için olan PKGDEST, makepkg'da listelenmiş ancak bulunmuyor: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"yapılacak bir şey yok\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"CreateHandle yapılamıyor: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"beklenmeyen işlem\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"bilinmeyen sürüm\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"evet\"\n\n#~ msgid \" (Target\"\n#~ msgstr \"(Hedef\"\n\n#~ msgid \" (Wanted by: \"\n#~ msgstr \"(Tarafından isteniyor:\"\n\n#~ msgid \"%s not satisfied, flushing install queue\"\n#~ msgstr \"%s sağlanmamış, indirme kuyruğu boşaltılıyor\"\n\n#~ msgid \"Checking for conflicts...\"\n#~ msgstr \"Çakışmalar kontrol ediliyor...\"\n\n#~ msgid \"Checking for inner conflicts...\"\n#~ msgstr \"İç çakışmalar kontrol ediliyor...\"\n\n#~ msgid \"Conflicting packages will have to be confirmed manually\"\n#~ msgstr \"Çakışan paketlerin elle onaylanması gerekecek\"\n\n#~ msgid \"Inner conflicts found:\"\n#~ msgstr \"İç çakışmalar bulundu:\"\n\n#~ msgid \"Installing %s will remove:\"\n#~ msgstr \"%s paketini kurmak şunları kaldıracak:\"\n\n#~ msgid \"PKGBUILD up to date, Skipping (%d/%d): %s\"\n#~ msgstr \"PKGBUILD güncel, Atlanıyor (%d/%d): %s\"\n\n#~ msgid \"Package conflicts found:\"\n#~ msgstr \"Paket çakışmaları bulundu:\"\n\n#~ msgid \"Packages to upgrade.\"\n#~ msgstr \"Yükseltilecek paketler.\"\n\n#~ msgid \"Querying AUR...\"\n#~ msgstr \"AUR sorgulanıyor...\"\n\n#~ msgid \"could not find all required packages:\"\n#~ msgstr \"tüm gereken paketler bulunamadı:\"\n\n#~ msgid \"could not find srcinfo for: %s\"\n#~ msgstr \"%s : İçin scrinfo bulunamadı\"\n\n#~ msgid \"package conflicts can not be resolved with noconfirm, aborting\"\n#~ msgstr \"paket çakışmaları noconfirm ile çözümlenemedi, iptal ediliyor\"\n"
  },
  {
    "path": "po/uk.po",
    "content": "#\n# Translators:\n# Volodymyr Markiv <vov4uk21@gmail.com>, 2021\n# Igor Lukyanov, 2023\n# Andrii Lytvyn, 2023\n# null null, 2023\n# Andrii Yermak, 2024\n#\nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: Andrii Yermak, 2024\\n\"\n\"Language-Team: Ukrainian (https://app.transifex.com/yay-1/teams/123732/uk/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: uk\\n\"\n\"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Каталог збірки:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Введіть число (типово=1):\"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \"(Файли Збірки Існують)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \"(Встановлено)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \"[Встановлено]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \"тут нічого робити\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"\"\n\"%s [A]Всі [Ab]Скасувати [I]Встановлені [No]Невстановлені чи (1 2 3, 1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s вже зроблено -- пропуск збірки\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s не задано\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s вже існує.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s є актуальним -- пропуск\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s  для оновлення/встановлення.\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%s також буде встановлено для цієї операції.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s потребується для: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s:  Нема змін -- пропуск\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: не вдалося застосувати ціль з параметром --aur -- пропуск\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: не вдалося застосувати ціль з параметром --repo -- пропуск\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: ігнорування оновлення пакунка ( %s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: встановлений пакунок (%s) новіший ніж у AUR (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"\"\n\"%s: будь ласка встановіть змінні середовища AUR_USERNAME та AUR_PASSWORD для\"\n\" цього голосування\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) PKGBUILD завантажено з ABS: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) Завантажено PKGBUILD: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) Не вдалося завантажити PKGBUILD: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) Аналіз SRCINFO: %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(Встановлено)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(Встановлено: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Осиротілий)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Застарілий: %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"AUR URL\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Додайте %s або %s до змінних середовища\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Не запускайте yay від імені root/sudo.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Перевірити залежності\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Залежності Перевірки\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"Перевірка пакунків розробки...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Очистка (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Конфліктує з\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Видалення (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Залежність\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Залежить Від\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Опис\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Показати зміни?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"Вимкнути параметр 'provides' за замовчуванням\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"Ви бажаєте видалити ВСІ пакунки AUR з кешу?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"Ви бажаєте видалити ВСІ невідстежувані файли AUR?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"Ви бажаєте видалити всі інші пакунки AUR з кешу?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"Редагувати PKGBUILD за допомогою?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Помилка під час пошуку у AUR: %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"Виключення пакетів може привести до часткового оновлення та зламати систему \"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Явно\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Явно встановлені пакунки: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"Не вдалося знайти AUR пакет для\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"Не вдалося встановити шар, перекочуємось до наступного шару.\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"Не вдалося встановити наступні пакети. Необхідне ручне втручання:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Вперше Завантажений\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Пакунки з AUR, що позначені як застарілі:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Сторонні встановлені пакунки: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Знайдено git-репозиторій: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB завершено. Пакунки не встановлено\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Групи\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Імпортувати?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"Імпортування ключів за допомогою gpg...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Ключові слова\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Остання зміна\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Ліцензії\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Локальний\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Супроводжувач\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Зібрати залежність\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Залежності Збірки\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Нестачає\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Відсутні налагоджувальні пакунки з AUR:\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Ім'я\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:548\nmsgid \"No AUR package found for\"\nmsgstr \"Не знайдено AUR пакету для\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"Пакунок не знайдено для\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Ні\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Необов'язкові Залежності\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Сирі (що не супроводжуються) AUR Пакети:\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Застарілий\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"Необхідно імпортувати ключі PGP:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD оновлений, пропускаємо завантаження: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"Редагувати PKGBUILDs?\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Група Пакунків\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"ID Групи Пакунків\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"Пакети не в AUR:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Пакунки для чистої збірки?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Пакети для виключення\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"\"\n\"Пакунки, які потрібно виключити: (наприклад, \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" або \"\n\"назва репозиторію)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Пакунки для встановлення (наприклад: 1 2 3, 1-3 або ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Популярність\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Продовжити встановлення?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Забезпечує\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"Видалити залежності збірки після встановлення?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Замінює\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"Репозиторій\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"Репозиторій AUR\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Пошук оновлень у AUR...\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"Пошук оновлень у базах даних...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Показано лише пакунки з репозиторіїв\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"Розмір кешу pacman %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"Розмір кешу yay %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"URL знімка\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Синхронізувати\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"Десять найбільших пакунків:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"Наступні пакунки не сумісні з вашою архітектурою:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"Існує %[1]d постачальників для %[2]s:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"Можливо, запущено інший екземпляр Pacman. Очікування...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Загальний розмір, зайнятий пакунками: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Загальна кількість встановлених пакунків: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Все одно спробувати їх побудувати?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"Неможливо очистити:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"Не вдалося знайти наступні пакунки:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"Неможливо обробити голос за пакет: %s. помилка: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"Неможливо видалити %s: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Версія\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Голоси\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Версія Yay v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N]Ні\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"зупинка через користувача\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"аргумент '-' вказаний без вводу у stdin\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"не вдалося знайти PKGBUILD та .SRCINFO в директорії\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"не вдається знайти пакунок: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"не вдалося знайти PKGDEST для: %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"не знайдені всі необхідні пакунки\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"не знайдено жодного пакунку з перелічених у %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"залежність\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"розробницька перевірка пакунку не вдалася: '%s' сталася помилка\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"вихід з редактора був успішним, переривання: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"помилка завантаження вихідного коду:\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"помилка отримання %s: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"помилка встановлення пакунку з репозиторіїв\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"помилка встановлення:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"помилка збірки: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"помилка об'єднання %s: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"помилка читання %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"помилка оновлення баз даних\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"помилка скидання %s: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"помилка оновлення причини встановлення пакунка для %s\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"явно\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"не вдалося створити каталог '%s': %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"не вдалося відкрити файл конфігурації '%s': %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"не вдалося проаналізувати %s -- пропуск: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"не вдалося проаналізувати %s: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"не вдалося проаналізувати .SRCINFO\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"не вдалося прочитати конфігураційний файл '%s': %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"не вдалося отримати кеш AUR\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"ігноруємо оновлення розробки пакунка (нема інформації в AUR):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"введення занадто довге\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"некоректний номер: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"некоректний параметр '%s'\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"\"\n\"некоректний параметр: '--deps' і '--explicit' не можна використовувати разом\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"недійсний репозиторій\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"некоректне значення: %d не знаходиться між %d та %d\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"ні\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"нема ключів для імпорту\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"запит не виконано\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"цільова директорія не вказана\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"нема чого встановити для %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"одночасно можна використовувати лише одну операцію\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"дозволена лише одна ціль\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"пакунок\"\nmsgstr[1] \"пакунки\"\nmsgstr[2] \"пакунків\"\nmsgstr[3] \"пакунків\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"пакунок '%s' не знайдено\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"пакунок не знайдено в AUR\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"пакунок не знайдено в репозиторіях\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"проблема імпортування ключів\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"видалення пакунків AUR з кешу...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"видалення невідстежених файлів AUR з кешу...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"PKGDEST для %s перераховано makepkg, але не існує: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"нема чого робити\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"неможливо створити Handle:\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"необроблена операція\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"невідома версія\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"так\"\n"
  },
  {
    "path": "po/vi.po",
    "content": "# \n# Translators:\n# Tín Nguyễn, 2022\n# Katoji Rikito, 2023\n# Nguyễn Tri Phương, 2024\n# Phong Phạm Thanh, 2025\n# Nguyễn Hoàng Minh <mr.hatdau@gmail.com>, 2025\n# \nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: Nguyễn Hoàng Minh <mr.hatdau@gmail.com>, 2025\\n\"\n\"Language-Team: Vietnamese (https://app.transifex.com/yay-1/teams/123732/vi/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: vi\\n\"\n\"Plural-Forms: nplurals=1; plural=0;\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Vị trí lưu tệp xây dựng:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Hãy nhập số (mặc định = 1)\"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \"(Tệp Xây Dựng Đã Tồn Tại)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \"(Đã cài đặt)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \"[Đã cài đặt]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \"không có tác vụ cần làm\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"\"\n\"%s [A] Tất cả  [Ab] Hủy  [I] Đã được cài đặt  [No] Chưa được cài đặt hoặc (1\"\n\" 2 3, 1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s đã được xây dựng -- đang bỏ qua\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s chưa được đặt\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s có tồn tại\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s đã là phiên bản mới nhất -- đang bỏ qua\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s để nâng cấp/cài đặt\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%s cũng sẽ được cài đặt cho hoạt động này.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, cần thiết cho: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: Không có thay đổi nào -- đang bỏ qua\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: không thể sử dụng mục tiêu với lựa chọn --aur -- đang bỏ qua\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: không thể sử dụng mục tiêu với lựa chọn --repo -- đang bỏ qua\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: đang bỏ qua cập nhật gói (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: phiên bản cục bộ (%s) mới hơn phiên bản từ AUR (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"%s: hãy đặt biến AUR_USERNAME và AUR_PASSWORD cho việc bỏ phiếu\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) Đã tải PKGBUILD từ ABS: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) Đã tải PKGBUILD: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) Tải PKGBUILD thất bại: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) Đang đọc SRCINFO: %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(Đã cài đặt)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(Đã cài đặt: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Đơn lẻ)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Lỗi thời: %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"URL của AUR\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Thêm %s hoặc %s làm vào các biến môi trường của bạn\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Tránh chạy yay khi là root hoặc dùng sudo.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Kiểm tra gói phụ thuộc\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"K.tra ph.thuộc\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"Đang kiểm tra các gói tự xây dựng...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Đang dọn (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Mâu thuẫn với\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Đang xóa (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Gói phụ thuộc\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Phụ thuộc vào\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Mô tả\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Hiện ra các thay đổi?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"Tắt cài đặt 'provides' theo mặc định\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"Bạn có muốn loại bỏ TOÀN BỘ các gói từ AUR ra khỏi bộ nhớ không?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"Bạn có muốn loại bỏ TOÀN BỘ các tệp từ AUR không được theo dõi không?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"\"\n\"Bạn có muốn loại bỏ toàn bộ các tệp AUR còn lại trong kho nhớ tạm không?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"Chỉnh sửa PKGBUILD bằng?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Lỗi khi thực hiện tìm kiếm trong AUR: %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"Việc bỏ qua các gói có thể khiến cho bản cập nhật không đầy đủ và làm hỏng \"\n\"hệ thống\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Cụ thể\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Các gói được cài đặt cụ thể: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"Không thể tìm gói AUR cho\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"Cài đặt lớp thất bại, đang đến lớp tiếp theo.\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"Đã thất bại khi cài đặt những gói sau. Yêu cầu can thiệp thủ công:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Lần nộp đầu tiên\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Các gói AUR bị đánh dấu lỗi thời:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Gói ngoại lai đã được cài đặt: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Tìm thấy kho chứa git: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"Hoàn thành GenDB. Không có gói được cài đặt\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Nhóm\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Nhập?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"Đang nhập khóa với gpg...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Từ khóa\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Lần sửa cuối\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Giấy phép\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Cục bộ\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Người bảo trì\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Gói phụ thuộc cho make\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Gói ph.thuộc make\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Đang thiếu\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Đang thiếu gói AUR gỡ lỗi:\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Tên\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:548\nmsgid \"No AUR package found for\"\nmsgstr \"Không tìm thấy gói AUR cho\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"Không tìm thấy gói cho\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Không có\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Gói phụ thuộc không bắt buộc\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Gói AUR đơn lẻ (không được bảo trì):\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Lỗi thời\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"Khóa PGP cần nhập:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"Tệp PKGBUILD đã ở bản mới nhất, đang bỏ qua: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"Những tệp PKGBUILD cần chỉnh sửa? \"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Gói gốc\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"ID của gói gốc\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"Gói không ở trong AUR:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Những gói để chạy cleanBuild (xây dựng từ nguồn)?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Những gói bỏ lại\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"Những gói bỏ lại (v.d.: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" hay tên kho chứa)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Những gói cài đặt (vd: 1 2 3, 1-3 hoặc ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Độ phổ biến\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Tiếp tục cài đặt?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Cung cấp\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"Gỡ phụ thuộc xây dựng gói sau khi cài đặt?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Thay thế\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"Kho chứa\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"Kho chứa AUR\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Đang tìm kiếm phiên bản cập nhật từ AUR...\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"Đang tìm kiếm phiên bản cập nhật từ cơ sở dữ liệu...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Chỉ hiện gói từ kho chứa\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"Kích cỡ bộ nhớ tạm pacman %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"Kích cỡ bộ nhớ tạm yay %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"URL Snapshot\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Đồng bộ hóa\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"Mười gói lớn nhất:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"Những gói sau đây không phù hợp với kiến trúc máy tính của bạn:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"Có %[1]d nhà phát hành cho %[2]s:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"Có thể đang có một tiến trình Pacman khác đang chạy. Đang đợi...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Tổng kích cỡ chiếm dụng bởi các gói: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Tổng các gói đã cài đặt: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Vẫn xây dựng gói?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"Không thể dọn:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"Không thể tìm thấy những gói sau:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"Không thể xử lý phiếu bầu cho gói: %s. Lỗi: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"Không thể xóa %s:%s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Phiên bản\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Số lượng bầu chọn\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Phiên bản yay số v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N] Không có\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"hủy bởi người dùng\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"đối số '-' được dùng mà không có đầu vào từ stdin\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"không tìm được PKGBUILD và .SRCINFO trong thư mục\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"không thể tìm thấy gói: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"không thể tìm thấy PKGDEST cho: %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"không thể tìm thấy các gói được yêu cầu\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"không thể tìm thấy các gói lưu trữ được liệt kê ở %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"phần phụ thuộc\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"thất bại khi kiểm tra gói tự xây dựng: %s đã bị lỗi\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"phần mềm chỉnh sửa không thoát thành công, đang ngắt: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"có lỗi trong khi đang tải nguồn: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"có lỗi trong khi thu thập %s: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"có lỗi trong khi đang tải gói từ kho mã nguồn (repo)\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"có lỗi trong khi cài đặt:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"có lỗi trong khi tạo: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"có lỗi trong khi hợp nhất %s: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"có lỗi trong khi đọc tệp %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"có lỗi trong khi cập nhật cơ sở dữ liệu\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"có lỗi trong khi đưa về trạng thái mặc định %s: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"có lỗi trong khi đang cập nhật lý do tải gói sang %s\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"cụ thể\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"tạo thư mục '%s' thất bại: %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"mở tệp cài đặt '%s' thất bại: %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"thất bị khi đọc %s -- bỏ qua: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"thất bại khi đọc %s: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"thất bại khi đọc .SRCINFO\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"thất bại khi đọc tệp cài đặt '%s': %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"tải kho nhớ AUR thất bại\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"\"\n\"bỏ qua cập nhật phần mềm tự xây dựng (không tìm thấy thông tin trên AUR):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"nhập liệu quá dài\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"số không hợp lệ: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"lựa chọn '%s' không hợp lệ\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"\"\n\"lựa chọn không hợp lệ: '--deps' và '--explicit' không thể sử dụng cùng nhau\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"kho không hợp lệ\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"giá trị không hợp lệ: %d không nằm giữa %d và %d\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"không\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"không có keys để thêm vào\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"không có truy vấn được thực hành\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"không có thư mục được xác định\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"không có gì để tải cho %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"chỉ được sử dụng một lệnh trong một lần gọi\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"chỉ cho phép 1 đối tượng duy nhất\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"các gói\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"không tìm thấy gói '%s'\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"không tìm được gói trong AUR\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"không tìm được gói trong các kho\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"có vấn đề trong khi thêm keys\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"đang xóa các gói AUR khỏi bộ nhớ đệm...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"đang loại bỏ các tệp AUR không được theo dõi khỏi bộ nhớ\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"\"\n\"tệp PKGDEST của %s được gọi trong lệnh makepkg nhưng không tồn tại: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"không thể làm được gì cả\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"không sử dùng được hàm CreateHandle: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"lệnh không được xử lý\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"phiên-bản-không-xác-định\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"có\"\n"
  },
  {
    "path": "po/vi_VN.po",
    "content": "# \n# Translators:\n# su va, 2023\n# Tín Nguyễn, 2024\n# Nguyễn Tri Phương, 2024\n# Phong Phạm Thanh, 2025\n# Minh Nguyen <mr.hatdau@gmail.com>, 2025\n# \nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: Minh Nguyen <mr.hatdau@gmail.com>, 2025\\n\"\n\"Language-Team: Vietnamese (Viet Nam) (https://app.transifex.com/yay-1/teams/123732/vi_VN/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: vi_VN\\n\"\n\"Plural-Forms: nplurals=1; plural=0;\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"Vị trí lưu tệp dựng:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"Hãy nhập số (Mặc định = 1)\"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \"(File để Build có sẵn)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \"(Đã cài đặt)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \"[Đã cài đặt]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \"không còn gì \"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"%s [A] Tất cả [Ab] Hủy [I] Đã cài [No] Chưa cài hoặc (1 2 3, 1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s đã make -- bỏ qua bước \"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"%s chưa được đặt\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s đã có sẵn.\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s đã cập nhật -- bỏ qua\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s để nâng cấp/cài đặt.\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%s cũng sẽ được cài đặt để thực hiện việc này.\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, bắt buộc cho:%s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: Không thay đổi -- bỏ qua\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: không thể dùng target với lựa chọn --aur -- bỏ qua\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: không thể dùng đối tượng với lựa chọn --repo -- bỏ qua\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: bỏ qua việc nâng cấp gói (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: bản trên máy (%s) mới hơn bản trên AUR (%s)\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"%s: set các biến môi trường AUR_USERNAME và AUR_PASSWORD để bầu chọn\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) Đã tải xuống PKGBUILD từ ABS: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) Đã tải xuống PKGBUILD: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) Tải xuống PKGBUILD thất bại: %s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) Đang đọc SRCINFO: %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(Đã cài)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(Đã cài: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(Đã bị bỏ)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(Chưa được cập nhật: %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"AUR \"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"Thêm %s hoặc %s vào các biến môi trường của bạn\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"Tránh chạy yay bằng root/sudo.\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"Kiểm tra gói phụ thuộc\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"Kiểm tra các gói phụ thuộc\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"Đang kiểm tra các gói dev\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"Đang dọn (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"Xung đột với\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"Đang xóa (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"Gói phụ thuộc\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"Phụ thuộc vào\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"Mô tả\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"Hiện ra sự khác nhau?\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"Tắt cài đặt 'provides' theo mặc định\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"Bạn có muốn loại bỏ TOÀN BỘ gói AUR ra khỏi kho nhớ tạm không?\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"Bạn có muốn loại bỏ TOÀN BỘ các tệp AUR chưa được theo dõi không?\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"\"\n\"Bạn có muốn loại bỏ toàn bộ các tệp AUR còn lại trong kho nhớ tạm không?\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"Chỉnh sửa PKGBUILD bằng?\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"Lỗi khi thực hiện tìm kiếm AUR: %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"\"\n\"Bỏ lại các gói này có thể khiến cho bản cập nhật không đầy đủ và làm hỏng hệ\"\n\" thống\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"Cụ thể\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"Các gói được cài đặt cụ thể:\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"Không thể tìm gói AUR cho\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"Cài đặt layer thất bại, quay trở lại layer tiếp theo\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"Cài đặt những gói dưới đây thất bại. Yêu cầu can thiệp thủ công:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"Bản Nộp Đầu Tiên\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"Gói AUR Đã Bị Đánh Dấu Lỗi Thời\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"Gói ngoại lai đã được cài đặt: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"Tìm thấy kho chứa git: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"Hoàn thành GenDB. Không cài đặt gói nào.\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"Nhóm\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"Nhập?\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"Đang nhập khóa với gpg...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"Từ khóa\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"Sửa Lần Cuối\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"Giấy Phép\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"Cục Bộ\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"Người Bảo Trì\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"Yêu Cầu Make\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"Y/c Make\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"Thiếu\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"Thiếu gói AUR gỡ lỗi:\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"Tên\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:548\nmsgid \"No AUR package found for\"\nmsgstr \"Không tìm thấy gói AUR cho\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"Không tìm thấy gói cho\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"Không Có\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"Phụ Thuộc Không Bắt Buộc\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"Gói AUR Orphan (không được bảo trì)\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"Lỗi thời\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"Khóa PGP cần nhập:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD đã ở bản mới nhất, bỏ qua tải xuống: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"Những PKGBUILD cần chỉnh sửa? \"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"Base Của Gói\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"Base ID Của Gói\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"Gói không ở trong AUR:\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"Những gói để chạy cleanBuild?\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"Những gói bỏ lại\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"Những gói bỏ lại (ví dụ: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" hay tên kho chứa)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"Những gói cài đặt (vd: 1 2 3, 1-3 hoặc ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"Độ Phổ Biến\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"Tiếp tục cài đặt?\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"Cung Cấp\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"Gỡ phụ thuộc xây dựng gói sau khi cài đặt?\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"Thay Thế\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"Kho Chứa\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"Kho Chứa AUR\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"Đang tìm kiếm cập nhật từ AUR...\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"Đang tìm kiếm cập nhật từ cơ sở dữ liệu...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"Chỉ hiện gói từ kho chứa\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"Kích cỡ kho nhớ tạm pacman %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"Kích cỡ kho nhớ tạm yay %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"URL Snapshot\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"Đồng Bộ Hóa\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"Mười gói lớn nhất:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"Những gói sau đây không phù hợp với kiến trúc máy tính của bạn:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"Có %[1]d nhà phát hành cho %[2]d:\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"Có thể đang có một tiến trình Pacman khác đang chạy. Đang đợi...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"Tổng Kích Cỡ chiếm dụng bởi các gói:\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"Tổng các gói đã cài đặt: %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"Vẫn xây dựng gói?\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"Không thể dọn:\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"Không thể tìm thấy những gói sau:\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"Không thể xử lý phiếu bầu cho gói: %s. Lỗi: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"Không thể xóa %s:%s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"Phiên bản\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"Bầu chọn\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Phiên bản yay số %s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N] Không có\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"hủy bởi người dùng\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"đối số '-' được dùng mà không có đầu vào từ stdin\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"không tìm được PKGBUILD và .SRCINFO trong thư mục\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"không thể tìm thấy gói: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"không thể tìm thấy PKGDEST cho: %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"không thể tìm thấy các gói yêu cầu\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"không thể tìm thấy các gói lưu trữ được liệt kê ở %s\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"phần phụ thuộc\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"không kiểm tra được gói tự xây dựng: %s đã bị lỗi\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"phần mềm chỉnh sửa không thoát thành công, đang ngắt: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"lỗi khi đang tải nguồn: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"lỗi khi thu thập %s: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"lỗi khi đang tải gói từ kho mã nguồn (repo)\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"có lỗi trong khi cài đặt:\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"có lỗi trong khi tạo tệp:\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"có lỗi trong khi hợp nhất %s: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"có lỗi trong khi đọc tệp %s\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"có lỗi trong khi làm mới dữ liệu\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"lỗi khi đưa về trạng thái mặc định %s: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"lỗi khi đang cập nhật lý do tải gói sang %s\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"cụ thể\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"tạo thư mục '%s' thất bại: %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"mở tệp cài đặt `%s` thất bại: %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"thất bị khi đọc %s -- sẽ bỏ qua: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"thất bại khi đọc %s: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"thất bại khi đọc .SRCINFO\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"thất bại khi đọc tệp cài đặt '%s': %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"tải kho nhớ AUR thất bại\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"\"\n\"bỏ qua cập nhật phần mềm tự xây dựng (không tìm thấy thông tin trên AUR):\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"nhập liệu quá dài\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"số không hợp lệ: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"lựa chọn '%s' không hợp lệ\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"\"\n\"lựa chọn không hợp lệ: '--deps' và '--explicit' không thể sử dụng cùng nhau\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"kho không khả dụng\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"giá trị không hợp lệ: %d không nằm giữa %d và %d\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"không\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"không có keys để thêm vào\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"không có truy vấn được thực hành\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"không có thư mục được xác định\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"không có gì để tải cho %s\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"chỉ được sử dụng một lệnh trong một lần gọi\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"chỉ cho phép 1 đối tượng duy nhất\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"các gói\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"không tìm thấy gói'%s'\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"không tìm được gói trong AUR\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"không tìm được gói trong các kho\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"có vấn đề trong khi thêm keys\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"đang xóa các gói AUR khỏi bộ nhớ đệm...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"đang loại bỏ các tệp AUR không được theo dõi khỏi bộ nhớ\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"\"\n\"tệp PKGDEST của %s được gọi trong lệnh makepkg nhưng không tồn tại: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"không thể làm được gì cả\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"không sử dùng được hàm CreateHandle: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"không thể xử lý hoạt động\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"phiên-bản-không-xác-định\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"có\"\n"
  },
  {
    "path": "po/zh_CN.po",
    "content": "# \n# Translators:\n# J G, 2022\n# Moon Xanadu <xmoonox@gmail.com>, 2023\n# kanna 5, 2023\n# Songer Hy, 2023\n# Celestially H., 2023\n# lakejason0 <sunliyuan200402@outlook.com>, 2023\n# Alex Wang, 2023\n# Xuekai Deng, 2024\n# CloverGit, 2024\n# qsdwindows <2687267056@qq.com>, 2025\n# Haowen Shi, 2025\n# \nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: Haowen Shi, 2025\\n\"\n\"Language-Team: Chinese (China) (https://app.transifex.com/yay-1/teams/123732/zh_CN/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: zh_CN\\n\"\n\"Plural-Forms: nplurals=1; plural=0;\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"构建目录:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"输入数字 (默认=1): \"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \" (构建文件已存在)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \" (已安装)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \" [已安装]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \" 今日无事可做\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"%s [A]全部 [Ab]中止 [I]已安装 [No]未安装 或 (1 2 3, 1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s 已生成 -- 跳过构建\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"未设置 %s\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s 存在。\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s 是最新的 -- 跳过\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s 将被升级/安装。\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%s 也会为此操作而被安装。\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, 被以下需要: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: 没有更改 -- 跳过\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: 不能将目标与选项 --aur 一起使用 -- 跳过\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: 不能将目标与选项 --repo 一起使用 -- 跳过\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: 忽略包升级 (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: 本地 (%s) 比 AUR (%s) 更新\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"%s: 请设置 AUR_USERNAME 与 AUR_PASSWORD 环境变量以投票\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) 从 ABS 下载了 PKGBUILD: %s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) 下载了 PKGBUILD: %s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d) 下载PKGBUILD失败\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) 正在解析 SRCINFO: %s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(已安装)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(已安装: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(孤包)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(过时的: %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"AUR URL\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"将 %s 或 %s 添加到你的环境变量\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"避免以 root/sudo 运行 yay。\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"作为检查依赖安装\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"检查依赖\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"正在检查开发包...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"正在清理 (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"与它冲突\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"正在删除 (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"作为依赖安装\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"依赖以下包\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"描述\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"显示哪些包的差异？\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"默认禁用 'provides' 设置\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"你是否要从缓存中删除所有 AUR 软件包？\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"你是否要删除所有未跟踪的 AUR 文件？\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"你是否要从缓存中删除所有其他 AUR 软件包？\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"使用什么来编辑 PKGBUILD？\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"搜索 AUR 时出错: %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"排除软件包可能会导致不完整的升级并破坏系统\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"单独指定安装\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"单独指定安装的软件包: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"查找 AUR 软件包失败：\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"层级安装失败，正在合并到下一个层级。\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"无法安装以下软件包, 需要手动介入处理:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"首次提交\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"标记为过时的 AUR 软件包:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"已安装的外部软件包: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"已找到 git 仓库: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB 完成。 没有安装任何软件包\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"组\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"导入？\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"正在导入 GPG 密钥...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"关键字\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"最后修改\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"许可证\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"本地\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"维护者\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"作为构建依赖安装\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"构建依赖\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"缺少\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"缺少 AUR 调试包:\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"名称\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:548\nmsgid \"No AUR package found for\"\nmsgstr \"找不到 AUR 包\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"找不到包\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"没有\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"可选依赖\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"孤包 (无人维护) 的 AUR 软件包：\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"过时\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"需要导入的 PGP 密钥:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD 是最新的，跳过下载: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"要编辑哪些 PKGBUILD？\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"基本包\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"基本包 ID\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"不在 AUR 中的软件包：\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"清理哪些包的构建文件？\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"要排除的软件包\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"要排除的包: (示例: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" 或软件库名称)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"要安装的包 (示例: 1 2 3, 1-3 或 ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"受欢迎度\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"继续安装？\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"提供\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"安装后删除构建依赖？\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"替换\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"软件库\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"AUR 软件库\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"正在搜索 AUR 更新...\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"正在搜索数据库更新...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"仅显示软件库软件包\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"pacman 缓存大小 %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"yay 缓存大小 %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"快照 URL\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"同步\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"十个最大的软件包:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"下列软件包与你的系统架构不兼容:\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"对于 %[2] 有 %[1]d 个结果：\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"可能还有另一个 Pacman 实例正在运行。等待中...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"包占用的总大小: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"已安装的软件包总数:  %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"依然尝试构建吗？\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"URL\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"无法清理：\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"找不到下列软件包：\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"无法处理软件包的投票: %s。错误: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"无法删除 %s: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"版本\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"得票\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Yay 版本 v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N]没有\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"用户自行终止\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"指定了参数“-”，但未在 stdin 输入任何内容\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"在目录中找不到 PKGBUILD 和 .SRCINFO 文件\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"找不到包名: %v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"找不到 PKGDEST: %s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"无法找到所有必需的软件包\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"在 %s 中无法找到任何软件包存档\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"作为依赖安装\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"软件包的开发检查失败: '%s' 遇到了错误\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"编辑器未成功退出，正在中止: %s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"下载源文件时出错: %s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"获取 %s 时出错: %s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"安装软件库软件包时出错\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"安装时出错: \"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"生成时出错: %s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"合并 %s 时出错: %s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"读取 %s 时出错\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"刷新数据库时出错\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"重置 %s 时出错: %s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"更新软件包时因 %s 出错\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"单独指定安装\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"无法创建目录 '%s': %s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"无法打开配置文件 '%s': %s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"无法解析 %s -- 跳过: %s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"无法解析 %s: %s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"无法解析 .SRCINFO\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"无法读取配置文件 '%s': %s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"无法获取 AUR 缓存\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"忽略软件包开发更新（未找到 AUR 信息）：\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"输入过长\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"无效数字: %s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"无效选项 '%s'\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"无效选项: '--deps' 和 '--explicit' 不能同时指定\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"无效软件库\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"无效值: %d 不在 %d 和 %d 之间\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"no\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"没有要导入的密钥\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"没有查询被执行\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"未指定目标目录\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"%s 没有需要安装的依赖软件包\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"一次只能使用一项操作\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"仅允许一个目标\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"软件包\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"找不到软件包 '%s'\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"AUR 中找不到软件包\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"软件库中找不到软件包\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"导入密钥时出现问题\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"正在从缓存中删除 AUR 软件包...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"正在从缓存中删除未跟踪的 AUR 文件...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"%s 的 PKGDEST 由 makepkg 列出，但不存在: %s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"今日无事可做\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"无法创建句柄: %s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"未处理的操作\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"未知版本\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"yes\"\n"
  },
  {
    "path": "po/zh_TW.po",
    "content": "# \n# Translators:\n# J G, 2022\n# lakejason0 <sunliyuan200402@outlook.com>, 2023\n# Oliver Tzeng, 2025\n# zangmen hsu(neko_0xff) <chzang55@gmail.com>, 2025\n# Kisaragi Hiu <flyingfeather1501@gmail.com>, 2025\n# \nmsgid \"\"\nmsgstr \"\"\n\"Last-Translator: Kisaragi Hiu <flyingfeather1501@gmail.com>, 2025\\n\"\n\"Language-Team: Chinese (Taiwan) (https://app.transifex.com/yay-1/teams/123732/zh_TW/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: zh_TW\\n\"\n\"Plural-Forms: nplurals=1; plural=0;\\n\"\n\"X-Generator: xgotext\\n\"\n\n#: clean.go:83\nmsgid \"\"\n\"\\n\"\n\"Build directory:\"\nmsgstr \"\"\n\"\\n\"\n\"編譯資料夾:\"\n\n#: pkg/db/ialpm/alpm.go:201 pkg/dep/dep_graph.go:740\nmsgid \"\"\n\"\\n\"\n\"Enter a number (default=1): \"\nmsgstr \"\"\n\"\\n\"\n\"輸入數字 (預設=1): \"\n\n#: pkg/menus/menu.go:32\nmsgid \" (Build Files Exist)\"\nmsgstr \" (編譯檔案已存在)\"\n\n#: pkg/menus/menu.go:27\nmsgid \" (Installed)\"\nmsgstr \" (已安裝)\"\n\n#: cmd.go:453\nmsgid \" [Installed]\"\nmsgstr \" [已安裝]\"\n\n#: cmd.go:410 vote.go:36\nmsgid \" there is nothing to do\"\nmsgstr \" 無事可做\"\n\n#: pkg/menus/menu.go:49\nmsgid \"%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)\"\nmsgstr \"%s [A]全部 [Ab]中止 [I]已安裝 [No]未安裝 或 (1 2 3, 1-3, ^4)\"\n\n#: pkg/sync/build/installer.go:308\nmsgid \"%s already made -- skipping build\"\nmsgstr \"%s 已編譯 -- 跳過編譯\"\n\n#: pkg/menus/edit_menu.go:57\nmsgid \"%s is not set\"\nmsgstr \"未設定 %s\"\n\n#: pkg/settings/exe/cmd_builder.go:257\nmsgid \"%s is present.\"\nmsgstr \"%s 存在。\"\n\n#: pkg/dep/dep_graph.go:460 pkg/sync/build/installer.go:305\nmsgid \"%s is up to date -- skipping\"\nmsgstr \"%s 是最新的 -- 跳過\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"%s to upgrade/install.\"\nmsgstr \"%s 個要升級/安裝的套件。\"\n\n#: pkg/upgrade/service.go:285\nmsgid \"%s will also be installed for this operation.\"\nmsgstr \"%s 也會為此操作被安裝。 \"\n\n#: pkg/sync/srcinfo/pgp/keys.go:124\nmsgid \"%s, required by: %s\"\nmsgstr \"%s, 需要: %s\"\n\n#: pkg/menus/diff_menu.go:49\nmsgid \"%s: No changes -- skipping\"\nmsgstr \"%s: 沒有更改 -- 跳過\"\n\n#: pkg/query/filter.go:22\nmsgid \"%s: can't use target with option --aur -- skipping\"\nmsgstr \"%s: 不能將目標與選項 --aur 一起使用 -- 跳過\"\n\n#: pkg/query/filter.go:17\nmsgid \"%s: can't use target with option --repo -- skipping\"\nmsgstr \"%s: 不能將目標與選項 --repo 一起使用 -- 跳過\"\n\n#: pkg/upgrade/sources.go:57\nmsgid \"%s: ignoring package upgrade (%s => %s)\"\nmsgstr \"%s: 忽略套件包升級 (%s => %s)\"\n\n#: pkg/query/aur_warnings.go:46\nmsgid \"%s: local (%s) is newer than AUR (%s)\"\nmsgstr \"%s: 本機 (%s) 比 AUR (%s) 更新\"\n\n#: vote.go:51\nmsgid \"\"\n\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for \"\n\"voting\"\nmsgstr \"%s: 請設定 AUR_USERNAME 與 AUR_PASSWORD 環境變數以進行投票\"\n\n#: pkg/download/unified.go:192\nmsgid \"(%d/%d) Downloaded PKGBUILD from ABS: %s\"\nmsgstr \"(%d/%d) 從 ABS 下載了 PKGBUILD：%s\"\n\n#: pkg/download/aur.go:92 pkg/download/unified.go:188\nmsgid \"(%d/%d) Downloaded PKGBUILD: %s\"\nmsgstr \"(%d/%d) 下載了 PKGBUILD：%s\"\n\n#: pkg/download/aur.go:82\nmsgid \"(%d/%d) Failed to download PKGBUILD: %s\"\nmsgstr \"(%d/%d)下載  PKGBUILD 時失敗：%s\"\n\n#: pkg/sync/srcinfo/service.go:109\nmsgid \"(%d/%d) Parsing SRCINFO: %s\"\nmsgstr \"(%d/%d) 正在解析 SRCINFO：%s\"\n\n#: pkg/query/types.go:103 pkg/query/types.go:72\nmsgid \"(Installed)\"\nmsgstr \"(已安裝)\"\n\n#: pkg/query/types.go:101 pkg/query/types.go:70\nmsgid \"(Installed: %s)\"\nmsgstr \"(已安裝: %s)\"\n\n#: pkg/query/types.go:61\nmsgid \"(Orphaned)\"\nmsgstr \"(棄置)\"\n\n#: pkg/query/types.go:65\nmsgid \"(Out-of-date: %s)\"\nmsgstr \"(過期的: %s)\"\n\n#: pkg/dep/dep_graph.go:75\nmsgid \"AUR\"\nmsgstr \"AUR\"\n\n#: print.go:44\nmsgid \"AUR URL\"\nmsgstr \"AUR 網址\"\n\n#: pkg/menus/edit_menu.go:58\nmsgid \"Add %s or %s to your environment variables\"\nmsgstr \"將 %s 或 %s 添加到環境變數中\"\n\n#: main.go:60\nmsgid \"Avoid running yay as root/sudo.\"\nmsgstr \"避免以 root/sudo 執行 yay。\"\n\n#: pkg/dep/dep_graph.go:63\nmsgid \"Check Dependency\"\nmsgstr \"作為檢查依賴安裝\"\n\n#: print.go:41\nmsgid \"Check Deps\"\nmsgstr \"檢查依賴\"\n\n#: pkg/upgrade/service.go:89\nmsgid \"Checking development packages...\"\nmsgstr \"正在檢查開發套件包...\"\n\n#: pkg/sync/workdir/clean.go:45\nmsgid \"Cleaning (%d/%d): %s\"\nmsgstr \"正在清理 (%d/%d): %s\"\n\n#: print.go:42\nmsgid \"Conflicts With\"\nmsgstr \"與它衝突\"\n\n#: pkg/menus/clean_menu.go:62\nmsgid \"Deleting (%d/%d): %s\"\nmsgstr \"正在刪除 (%d/%d): %s\"\n\n#: pkg/dep/dep_graph.go:61\nmsgid \"Dependency\"\nmsgstr \"作為依賴安裝\"\n\n#: print.go:38\nmsgid \"Depends On\"\nmsgstr \"依賴於\"\n\n#: print.go:33\nmsgid \"Description\"\nmsgstr \"描述\"\n\n#: pkg/menus/diff_menu.go:160\nmsgid \"Diffs to show?\"\nmsgstr \"顯示差異？\"\n\n#: pkg/settings/migrations.go:25\nmsgid \"Disable 'provides' setting by default\"\nmsgstr \"預設停用「provides」設定\"\n\n#: clean.go:78\nmsgid \"Do you want to remove ALL AUR packages from cache?\"\nmsgstr \"您是否要從快取中刪除所有 AUR 套件包？\"\n\n#: clean.go:95\nmsgid \"Do you want to remove ALL untracked AUR files?\"\nmsgstr \"您是否要刪除所有未使用的 AUR 檔案？\"\n\n#: clean.go:80\nmsgid \"Do you want to remove all other AUR packages from cache?\"\nmsgstr \"您是否要從快取中刪除所有其他 AUR 套件包？\"\n\n#: pkg/menus/edit_menu.go:61\nmsgid \"Edit PKGBUILD with?\"\nmsgstr \"使用什麼來編輯 PKGBUILD？\"\n\n#: pkg/query/errors.go:13\nmsgid \"Error during AUR search: %s\\n\"\nmsgstr \"搜尋 AUR 時出錯: %s\\n\"\n\n#: pkg/upgrade/service.go:295\nmsgid \"Excluding packages may cause partial upgrades and break systems\"\nmsgstr \"排除套件包則會造成部分功能更新而使系統無法正常運作\"\n\n#: pkg/dep/dep_graph.go:60\nmsgid \"Explicit\"\nmsgstr \"單獨指定安裝\"\n\n#: print.go:91\nmsgid \"Explicitly installed packages: %s\"\nmsgstr \"單獨指定安装的套件包: %s\"\n\n#: pkg/dep/dep_graph.go:437 pkg/dep/dep_graph.go:535\nmsgid \"Failed to find AUR package for\"\nmsgstr \"尋找 AUR 套件包時失敗\"\n\n#: pkg/sync/build/installer.go:120\nmsgid \"Failed to install layer, rolling up to next layer.\"\nmsgstr \"層級安裝失敗，將合併到下一個層級。\"\n\n#: pkg/sync/build/errors.go:16\nmsgid \"\"\n\"Failed to install the following packages. Manual intervention is required:\"\nmsgstr \"無法安裝以下的套件包。需要自行手動處理:\"\n\n#: print.go:45\nmsgid \"First Submitted\"\nmsgstr \"首次提交\"\n\n#: pkg/query/aur_warnings.go:83\nmsgid \"Flagged Out Of Date AUR Packages:\"\nmsgstr \"標記為過期的 AUR 套件包:\"\n\n#: print.go:90\nmsgid \"Foreign installed packages: %s\"\nmsgstr \"已安裝的外部套件包: %s\"\n\n#: pkg/vcs/vcs.go:144\nmsgid \"Found git repo: %s\"\nmsgstr \"已找到 git 倉庫源: %s\"\n\n#: vcs.go:72\nmsgid \"GenDB finished. No packages were installed\"\nmsgstr \"GenDB 完成。沒有安裝任何套件包\"\n\n#: print.go:36\nmsgid \"Groups\"\nmsgstr \"群組別\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:88\nmsgid \"Import?\"\nmsgstr \"匯入？\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:97\nmsgid \"Importing keys with gpg...\"\nmsgstr \"正在匯入 gpg 金鑰...\"\n\n#: print.go:46\nmsgid \"Keywords\"\nmsgstr \"關鍵字\"\n\n#: print.go:47\nmsgid \"Last Modified\"\nmsgstr \"最後修改\"\n\n#: print.go:35\nmsgid \"Licenses\"\nmsgstr \"授權條款\"\n\n#: pkg/dep/dep_graph.go:77\nmsgid \"Local\"\nmsgstr \"本機\"\n\n#: print.go:48\nmsgid \"Maintainer\"\nmsgstr \"維護者\"\n\n#: pkg/dep/dep_graph.go:62\nmsgid \"Make Dependency\"\nmsgstr \"作為編譯依賴安裝\"\n\n#: print.go:40\nmsgid \"Make Deps\"\nmsgstr \"編譯依賴\"\n\n#: pkg/dep/dep_graph.go:79\nmsgid \"Missing\"\nmsgstr \"缺少\"\n\n#: pkg/query/aur_warnings.go:75\nmsgid \"Missing AUR Debug Packages:\"\nmsgstr \"缺少 AUR 除錯套件包：\"\n\n#: print.go:31\nmsgid \"Name\"\nmsgstr \"名稱\"\n\n#: pkg/dep/dep_graph.go:442 pkg/dep/dep_graph.go:548\nmsgid \"No AUR package found for\"\nmsgstr \"沒有找到 AUR 套件包\"\n\n#: pkg/dep/dep_graph.go:182\nmsgid \"No package found for\"\nmsgstr \"未找到套件包\"\n\n#: print.go:225\nmsgid \"None\"\nmsgstr \"不做任何動作\"\n\n#: print.go:39\nmsgid \"Optional Deps\"\nmsgstr \"可選擇的依賴選項\"\n\n#: pkg/query/aur_warnings.go:79\nmsgid \"Orphan (unmaintained) AUR Packages:\"\nmsgstr \"孤立 (不受維護) 的 AUR 套件：\"\n\n#: print.go:53 print.go:55\nmsgid \"Out-of-date\"\nmsgstr \"過期\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:115\nmsgid \"PGP keys need importing:\"\nmsgstr \"需要匯入的 PGP 金鑰:\"\n\n#: pkg/sync/workdir/preparer.go:252\nmsgid \"PKGBUILD up to date, skipping download: %s\"\nmsgstr \"PKGBUILD 是最新的，跳過下載: %s\"\n\n#: pkg/menus/edit_menu.go:130\nmsgid \"PKGBUILDs to edit?\"\nmsgstr \"要編輯哪些 PKGBUILD 檔案？\"\n\n#: print.go:61\nmsgid \"Package Base\"\nmsgstr \"套件包基礎\"\n\n#: print.go:60\nmsgid \"Package Base ID\"\nmsgstr \"套件包基礎編號\"\n\n#: pkg/query/aur_warnings.go:71\nmsgid \"Packages not in AUR:\"\nmsgstr \"不在 AUR 裡的套件包：\"\n\n#: pkg/menus/clean_menu.go:54\nmsgid \"Packages to cleanBuild?\"\nmsgstr \"清理哪些套件包的編譯檔案？\"\n\n#: pkg/dep/dep_graph.go:202\nmsgid \"Packages to exclude\"\nmsgstr \"要排除的套件包\"\n\n#: pkg/upgrade/service.go:294\nmsgid \"Packages to exclude: (eg: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" or repo name)\"\nmsgstr \"要排除的套件包：(例如: \\\"1 2 3\\\", \\\"1-3\\\", \\\"^4\\\" 或倉庫源名稱)\"\n\n#: cmd.go:392\nmsgid \"Packages to install (eg: 1 2 3, 1-3 or ^4)\"\nmsgstr \"要安裝的套件包 (例如: 1 2 3, 1-3 或 ^4)\"\n\n#: print.go:49\nmsgid \"Popularity\"\nmsgstr \"熱門度\"\n\n#: pkg/menus/diff_menu.go:172 pkg/menus/edit_menu.go:143\nmsgid \"Proceed with install?\"\nmsgstr \"繼續安裝？\"\n\n#: print.go:37\nmsgid \"Provides\"\nmsgstr \"提供\"\n\n#: pkg/sync/workdir/preparer.go:125\nmsgid \"Remove make dependencies after install?\"\nmsgstr \"安裝後刪除編譯依賴？\"\n\n#: print.go:43\nmsgid \"Replaces\"\nmsgstr \"替換\"\n\n#: pkg/db/ialpm/alpm.go:191 print.go:30\nmsgid \"Repository\"\nmsgstr \"軟體源\"\n\n#: pkg/dep/dep_graph.go:730\nmsgid \"Repository AUR\"\nmsgstr \"AUR 軟體源\"\n\n#: pkg/dep/dep_graph.go:78\nmsgid \"SRCINFO\"\nmsgstr \"SRCINFO\"\n\n#: pkg/upgrade/service.go:71\nmsgid \"Searching AUR for updates...\"\nmsgstr \"搜尋 AUR 來獲取更新...\"\n\n#: pkg/upgrade/service.go:159\nmsgid \"Searching databases for updates...\"\nmsgstr \"搜尋資料庫來獲取更新...\"\n\n#: pkg/query/query_builder.go:214\nmsgid \"Showing repo packages only\"\nmsgstr \"僅顯示軟體源中的套件包\"\n\n#: print.go:95\nmsgid \"Size of pacman cache %s: %s\"\nmsgstr \"pacman 快取大小 %s: %s\"\n\n#: print.go:98\nmsgid \"Size of yay cache %s: %s\"\nmsgstr \"yay 快取大小 %s: %s\"\n\n#: print.go:62\nmsgid \"Snapshot URL\"\nmsgstr \"快照網址\"\n\n#: pkg/dep/dep_graph.go:76\nmsgid \"Sync\"\nmsgstr \"同步\"\n\n#: print.go:100\nmsgid \"Ten biggest packages:\"\nmsgstr \"前十大的套件包:\"\n\n#: pkg/sync/sync.go:124\nmsgid \"The following packages are not compatible with your architecture:\"\nmsgstr \"以下套件不支援您的系統架構：\"\n\n#: pkg/db/ialpm/alpm.go:179 pkg/dep/dep_graph.go:726\nmsgid \"There are %[1]d providers available for %[2]s:\"\nmsgstr \"對於 %[2]s 有 %[1]d 個結果：\"\n\n#: pkg/settings/exe/cmd_builder.go:258\nmsgid \"There may be another Pacman instance running. Waiting...\"\nmsgstr \"可能還有另一個 pacman 程序正在執行。等待中...\"\n\n#: print.go:92\nmsgid \"Total Size occupied by packages: %s\"\nmsgstr \"套件包佔用的空間: %s\"\n\n#: print.go:89\nmsgid \"Total installed packages: %s\"\nmsgstr \"已安裝的套件包總數:  %s\"\n\n#: pkg/sync/sync.go:132\nmsgid \"Try to build them anyway?\"\nmsgstr \"依然嘗試編譯它們？\"\n\n#: print.go:34\nmsgid \"URL\"\nmsgstr \"網址\"\n\n#: clean.go:194 pkg/menus/clean_menu.go:65 pkg/menus/clean_menu.go:71\nmsgid \"Unable to clean:\"\nmsgstr \"無法清理：\"\n\n#: get.go:42 get.go:74\nmsgid \"Unable to find the following packages:\"\nmsgstr \"找不到下列套件包：\"\n\n#: vote.go:20\nmsgid \"Unable to handle package vote for: %s. err: %s\"\nmsgstr \"無法處理套件包的投票: %s。錯誤: %s\"\n\n#: clean.go:170\nmsgid \"Unable to remove %s: %s\"\nmsgstr \"無法移除 %s: %s\"\n\n#: print.go:32\nmsgid \"Version\"\nmsgstr \"版本\"\n\n#: print.go:50\nmsgid \"Votes\"\nmsgstr \"得到票數\"\n\n#: print.go:87\nmsgid \"Yay version v%s\"\nmsgstr \"Yay 版本 v%s\"\n\n#: pkg/menus/menu.go:49\nmsgid \"[N]one\"\nmsgstr \"[N]不做任何動作\"\n\n#: pkg/settings/errors.go:29\nmsgid \"aborting due to user\"\nmsgstr \"使用者已自行中止 yay\"\n\n#: pkg/settings/parser/parser.go:608\nmsgid \"argument '-' specified without input on stdin\"\nmsgstr \"指定了參數 '-' 但沒有 stdin 或其他輸入值\"\n\n#: local_install.go:26\nmsgid \"cannot find PKGBUILD and .SRCINFO in directory\"\nmsgstr \"目錄內找不到 PKGBUILD 與 .SRCINFO 檔案\"\n\n#: pkg/sync/build/pkg_archive.go:148\nmsgid \"cannot find package name: %v\"\nmsgstr \"找不到套件名稱：%v\"\n\n#: pkg/sync/build/errors.go:30\nmsgid \"could not find PKGDEST for: %s\"\nmsgstr \"找不到 PKGDEST：%s\"\n\n#: errors.go:9\nmsgid \"could not find all required packages\"\nmsgstr \"找不到所有需要的套件包\"\n\n#: pkg/sync/build/errors.go:61\nmsgid \"could not find any package archives listed in %s\"\nmsgstr \"找不到任何 %s 中列舉的套件封存檔\"\n\n#: pkg/sync/build/errors.go:50 pkg/upgrade/service.go:286\nmsgid \"dependency\"\nmsgstr \"作為依賴安裝\"\n\n#: pkg/vcs/vcs.go:100 pkg/vcs/vcs.go:96\nmsgid \"devel check for package failed: '%s' encountered an error\"\nmsgstr \"開發套件包檢查失敗：「%s」 遇到了錯誤\"\n\n#: pkg/menus/edit_menu.go:110\nmsgid \"editor did not exit successfully, aborting: %s\"\nmsgstr \"編輯器未成功退出，正在中止：%s\"\n\n#: pkg/sync/workdir/aur_source.go:24\nmsgid \"error downloading sources: %s\"\nmsgstr \"下載套件包檔案時出錯：%s\"\n\n#: pkg/download/errors.go:25\nmsgid \"error fetching %s: %s\"\nmsgstr \"取得 %s 時出錯：%s\"\n\n#: pkg/sync/build/errors.go:9\nmsgid \"error installing repo packages\"\nmsgstr \"安裝套件包時出錯\"\n\n#: pkg/sync/build/installer.go:266 pkg/sync/build/installer.go:270\nmsgid \"error installing:\"\nmsgstr \"安裝時出錯：\"\n\n#: pkg/sync/build/installer.go:233 pkg/sync/build/installer.go:237\nmsgid \"error making: %s\"\nmsgstr \"編譯時出錯：%s\"\n\n#: pkg/sync/workdir/merge.go:24\nmsgid \"error merging %s: %s\"\nmsgstr \"合併 %s 時出錯：%s\"\n\n#: pkg/download/unified.go:59\nmsgid \"error reading %s\"\nmsgstr \"讀取 %s 時出錯\"\n\n#: sync.go:36\nmsgid \"error refreshing databases\"\nmsgstr \"重新整理資料庫時出錯\"\n\n#: pkg/sync/workdir/clean.go:51 pkg/sync/workdir/merge.go:17\nmsgid \"error resetting %s: %s\"\nmsgstr \"重置 %s 時出錯：%s\"\n\n#: pkg/sync/build/errors.go:53\nmsgid \"error updating package install reason to %s\"\nmsgstr \"更新套件安裝原因至 %s 時出錯\"\n\n#: pkg/sync/build/errors.go:48\nmsgid \"explicit\"\nmsgstr \"單獨指定安裝\"\n\n#: pkg/settings/errors.go:23\nmsgid \"failed to create directory '%s': %s\"\nmsgstr \"無法建立資料夾 '%s'：%s\"\n\n#: pkg/settings/config.go:281\nmsgid \"failed to open config file '%s': %s\"\nmsgstr \"無法開啟設定檔案 '%s'：%s\"\n\n#: pkg/sync/srcinfo/service.go:114\nmsgid \"failed to parse %s -- skipping: %s\"\nmsgstr \"無法解析 %s -- 跳過：%s\"\n\n#: pkg/sync/srcinfo/service.go:118\nmsgid \"failed to parse %s: %s\"\nmsgstr \"無法解析 %s：%s\"\n\n#: local_install.go:77\nmsgid \"failed to parse .SRCINFO\"\nmsgstr \"無法解析 .SRCINFO\"\n\n#: pkg/settings/config.go:291\nmsgid \"failed to read config file '%s': %s\"\nmsgstr \"無法讀取設定檔案 '%s'：%s\"\n\n#: pkg/cmd/graph/main.go:46 pkg/runtime/runtime.go:73\nmsgid \"failed to retrieve aur Cache\"\nmsgstr \"無法取得 AUR 快取\"\n\n#: pkg/upgrade/sources.go:27\nmsgid \"ignoring package devel upgrade (no AUR info found):\"\nmsgstr \"忽略軟體包開發更新 (未找到 AUR 資訊)：\"\n\n#: pkg/text/errors.go:8\nmsgid \"input too long\"\nmsgstr \"輸入太長\"\n\n#: pkg/db/ialpm/alpm.go:222 pkg/dep/dep_graph.go:761\nmsgid \"invalid number: %s\"\nmsgstr \"無效數字：%s\"\n\n#: pkg/settings/parser/parser.go:174\nmsgid \"invalid option '%s'\"\nmsgstr \"無效選項「%s」\"\n\n#: cmd.go:197\nmsgid \"invalid option: '--deps' and '--explicit' may not be used together\"\nmsgstr \"無效選項：不能同時指定「--deps」與「--explicit」\"\n\n#: pkg/download/abs.go:22\nmsgid \"invalid repository\"\nmsgstr \"無效軟體源\"\n\n#: pkg/db/ialpm/alpm.go:227 pkg/dep/dep_graph.go:767\nmsgid \"invalid value: %d is not between %d and %d\"\nmsgstr \"無效值: %d 不在 %d 和 %d 之間\"\n\n#: pkg/text/input.go:48\nmsgid \"no\"\nmsgstr \"否\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:110\nmsgid \"no keys to import\"\nmsgstr \"沒有要匯入的金鑰\"\n\n#: pkg/query/errors.go:20\nmsgid \"no query was executed\"\nmsgstr \"未進行任何查詢\"\n\n#: local_install.go:66\nmsgid \"no target directories specified\"\nmsgstr \"沒有指定目標目錄\"\n\n#: pkg/sync/build/installer.go:242\nmsgid \"nothing to install for %s\"\nmsgstr \"沒有要為 %s 安裝的東西\"\n\n#: pkg/settings/parser/parser.go:164\nmsgid \"only one operation may be used at a time\"\nmsgstr \"一次只能使用一項操作\"\n\n#: pkg/cmd/graph/main.go:70\nmsgid \"only one target is allowed\"\nmsgstr \"只能有一個目標\"\n\n#: pkg/upgrade/service.go:291\nmsgid \"package\"\nmsgid_plural \"packages\"\nmsgstr[0] \"套件包\"\n\n#: print.go:187\nmsgid \"package '%s' was not found\"\nmsgstr \"找不到套件包「%s」\"\n\n#: pkg/download/errors.go:15\nmsgid \"package not found in AUR\"\nmsgstr \"AUR 中找不到套件包\"\n\n#: pkg/download/abs.go:23\nmsgid \"package not found in repos\"\nmsgstr \"倉庫源中找不到套件包\"\n\n#: pkg/sync/srcinfo/pgp/keys.go:100\nmsgid \"problem importing keys\"\nmsgstr \"匯入金鑰時出錯\"\n\n#: clean.go:105\nmsgid \"removing AUR packages from cache...\"\nmsgstr \"正在從快取中刪除 AUR 套件包...\"\n\n#: clean.go:178 pkg/sync/workdir/clean.go:41\nmsgid \"removing untracked AUR files from cache...\"\nmsgstr \"正在從暫存中刪除未追蹤的 AUR 檔案...\"\n\n#: pkg/sync/build/errors.go:38\nmsgid \"the PKGDEST for %s is listed by makepkg but does not exist: %s\"\nmsgstr \"%s 的 PKGDEST 由 makepkg 列出，但不存在：%s\"\n\n#: pkg/sync/sync.go:45\nmsgid \"there is nothing to do\"\nmsgstr \"無事可做\"\n\n#: pkg/db/ialpm/alpm.go:247\nmsgid \"unable to CreateHandle: %s\"\nmsgstr \"無法  CreateHandle：%s\"\n\n#: cmd.go:186\nmsgid \"unhandled operation\"\nmsgstr \"未處理的操作\"\n\n#: cmd.go:450\nmsgid \"unknown-version\"\nmsgstr \"未知版本\"\n\n#: pkg/text/input.go:47\nmsgid \"yes\"\nmsgstr \"是\"\n"
  },
  {
    "path": "print.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\t\"syscall\"\n\t\"unicode\"\n\n\taur \"github.com/Jguer/aur\"\n\tmapset \"github.com/deckarep/golang-set/v2\"\n\t\"github.com/leonelquinteros/gotext\"\n\t\"golang.org/x/sys/unix\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/dep\"\n\t\"github.com/Jguer/yay/v12/pkg/query\"\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\t\"github.com/Jguer/yay/v12/pkg/upgrade\"\n)\n\n// printInfo prints package info like pacman -Si.\nfunc printInfo(logger *text.Logger, config *settings.Configuration, a *aur.Pkg, extendedInfo bool) {\n\tprintInfoValue(logger, gotext.Get(\"Repository\"), \"aur\")\n\tprintInfoValue(logger, gotext.Get(\"Name\"), a.Name)\n\tprintInfoValue(logger, gotext.Get(\"Version\"), a.Version)\n\tprintInfoValue(logger, gotext.Get(\"Description\"), a.Description)\n\tprintInfoValue(logger, gotext.Get(\"URL\"), a.URL)\n\tprintInfoValue(logger, gotext.Get(\"Licenses\"), a.License...)\n\tprintInfoValue(logger, gotext.Get(\"Groups\"), a.Groups...)\n\tprintInfoValue(logger, gotext.Get(\"Provides\"), a.Provides...)\n\tprintInfoValue(logger, gotext.Get(\"Depends On\"), a.Depends...)\n\tprintInfoValue(logger, gotext.Get(\"Optional Deps\"), a.OptDepends...)\n\tprintInfoValue(logger, gotext.Get(\"Make Deps\"), a.MakeDepends...)\n\tprintInfoValue(logger, gotext.Get(\"Check Deps\"), a.CheckDepends...)\n\tprintInfoValue(logger, gotext.Get(\"Conflicts With\"), a.Conflicts...)\n\tprintInfoValue(logger, gotext.Get(\"Replaces\"), a.Replaces...)\n\tprintInfoValue(logger, gotext.Get(\"AUR URL\"), config.AURURL+\"/packages/\"+a.Name)\n\tprintInfoValue(logger, gotext.Get(\"First Submitted\"), text.FormatTimeQuery(a.FirstSubmitted))\n\tprintInfoValue(logger, gotext.Get(\"Keywords\"), a.Keywords...)\n\tprintInfoValue(logger, gotext.Get(\"Last Modified\"), text.FormatTimeQuery(a.LastModified))\n\tprintInfoValue(logger, gotext.Get(\"Maintainer\"), a.Maintainer)\n\tprintInfoValue(logger, gotext.Get(\"Popularity\"), fmt.Sprintf(\"%f\", a.Popularity))\n\tprintInfoValue(logger, gotext.Get(\"Votes\"), fmt.Sprintf(\"%d\", a.NumVotes))\n\n\tif a.OutOfDate != 0 {\n\t\tprintInfoValue(logger, gotext.Get(\"Out-of-date\"), text.FormatTimeQuery(a.OutOfDate))\n\t} else {\n\t\tprintInfoValue(logger, gotext.Get(\"Out-of-date\"), \"No\")\n\t}\n\n\tif extendedInfo {\n\t\tprintInfoValue(logger, \"ID\", fmt.Sprintf(\"%d\", a.ID))\n\t\tprintInfoValue(logger, gotext.Get(\"Package Base ID\"), fmt.Sprintf(\"%d\", a.PackageBaseID))\n\t\tprintInfoValue(logger, gotext.Get(\"Package Base\"), a.PackageBase)\n\t\tprintInfoValue(logger, gotext.Get(\"Snapshot URL\"), config.AURURL+a.URLPath)\n\t}\n\n\tlogger.Println()\n}\n\n// BiggestPackages prints the name of the ten biggest packages in the system.\nfunc biggestPackages(logger *text.Logger, dbExecutor db.Executor) {\n\tpkgS := dbExecutor.BiggestPackages()\n\n\tif len(pkgS) < 10 {\n\t\treturn\n\t}\n\n\tfor i := range 10 {\n\t\tlogger.Printf(\"%s: %s\\n\", text.Bold(pkgS[i].Name()), text.Cyan(text.Human(pkgS[i].ISize())))\n\t}\n}\n\n// localStatistics prints installed packages statistics.\nfunc localStatistics(ctx context.Context, run *runtime.Runtime, dbExecutor db.Executor) error {\n\tinfo := statistics(run, dbExecutor)\n\n\tremoteNames := dbExecutor.InstalledRemotePackageNames()\n\tremote := dbExecutor.InstalledRemotePackages()\n\trun.Logger.Infoln(gotext.Get(\"Yay version v%s\", yayVersion))\n\trun.Logger.Println(text.Bold(text.Cyan(\"===========================================\")))\n\trun.Logger.Infoln(gotext.Get(\"Total installed packages: %s\", text.Cyan(strconv.Itoa(info.Totaln))))\n\trun.Logger.Infoln(gotext.Get(\"Foreign installed packages: %s\", text.Cyan(strconv.Itoa(len(remoteNames)))))\n\trun.Logger.Infoln(gotext.Get(\"Explicitly installed packages: %s\", text.Cyan(strconv.Itoa(info.Expln))))\n\trun.Logger.Infoln(gotext.Get(\"Total Size occupied by packages: %s\", text.Cyan(text.Human(info.TotalSize))))\n\n\tfor path, size := range info.pacmanCaches {\n\t\trun.Logger.Infoln(gotext.Get(\"Size of pacman cache %s: %s\", path, text.Cyan(text.Human(size))))\n\t}\n\n\trun.Logger.Infoln(gotext.Get(\"Size of yay cache %s: %s\", run.Cfg.BuildDir, text.Cyan(text.Human(info.yayCache))))\n\trun.Logger.Println(text.Bold(text.Cyan(\"===========================================\")))\n\trun.Logger.Infoln(gotext.Get(\"Ten biggest packages:\"))\n\tbiggestPackages(run.Logger, dbExecutor)\n\trun.Logger.Println(text.Bold(text.Cyan(\"===========================================\")))\n\n\taurData, err := run.AURClient.Get(ctx, &aur.Query{\n\t\tNeedles: remoteNames,\n\t\tBy:      aur.Name,\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\n\twarnings := query.NewWarnings(run.Logger.Child(\"warnings\"))\n\tfor i := range aurData {\n\t\twarnings.AddToWarnings(remote, &aurData[i])\n\t}\n\n\twarnings.Print()\n\n\treturn nil\n}\n\nfunc printUpdateList(ctx context.Context, run *runtime.Runtime, cmdArgs *parser.Arguments,\n\tdbExecutor db.Executor, enableDowngrade bool, filter upgrade.Filter,\n) error {\n\tquietMode := cmdArgs.ExistsArg(\"q\", \"quiet\")\n\n\t// TODO: handle quiet mode in a better way\n\tlogger := text.NewLogger(io.Discard, os.Stderr, os.Stdin, run.Cfg.Debug, \"update-list\")\n\tdbExecutor.SetLogger(logger.Child(\"db\"))\n\toldNoConfirm := settings.NoConfirm\n\tsettings.NoConfirm = true\n\t// restoring global NoConfirm to make tests work properly\n\tdefer func() { settings.NoConfirm = oldNoConfirm }()\n\n\ttargets := mapset.NewThreadUnsafeSet(cmdArgs.Targets...)\n\tgrapher := dep.NewGrapher(dbExecutor, run.AURClient, false, true,\n\t\tfalse, false, cmdArgs.ExistsArg(\"needed\"), logger.Child(\"grapher\"))\n\n\tupService := upgrade.NewUpgradeService(\n\t\tgrapher, run.AURClient, dbExecutor, run.VCSStore,\n\t\trun.Cfg, true, logger.Child(\"upgrade\"))\n\n\tgraph, errSysUp := upService.GraphUpgrades(ctx, nil,\n\t\tenableDowngrade, filter)\n\tif errSysUp != nil {\n\t\treturn errSysUp\n\t}\n\n\tif graph.Len() == 0 {\n\t\treturn fmt.Errorf(\"\")\n\t}\n\n\tnoTargets := targets.Cardinality() == 0\n\tforeignFilter := cmdArgs.ExistsArg(\"m\", \"foreign\")\n\tnativeFilter := cmdArgs.ExistsArg(\"n\", \"native\")\n\n\tnoUpdates := true\n\t_ = graph.ForEach(func(pkgName string, ii *dep.InstallInfo) error {\n\t\tif !ii.Upgrade {\n\t\t\treturn nil\n\t\t}\n\n\t\tif noTargets || targets.Contains(pkgName) {\n\t\t\tif ii.Source == dep.Sync && foreignFilter {\n\t\t\t\treturn nil\n\t\t\t} else if ii.Source == dep.AUR && nativeFilter {\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tif quietMode {\n\t\t\t\trun.Logger.Printf(\"%s\\n\", pkgName)\n\t\t\t} else {\n\t\t\t\trun.Logger.Printf(\"%s %s -> %s\\n\", text.Bold(pkgName), text.Bold(text.Green(ii.LocalVersion)),\n\t\t\t\t\ttext.Bold(text.Green(ii.Version)))\n\t\t\t}\n\n\t\t\ttargets.Remove(pkgName)\n\t\t\tnoUpdates = false\n\t\t}\n\n\t\treturn nil\n\t})\n\n\tmissing := false\n\ttargets.Each(func(pkgName string) bool {\n\t\tif dbExecutor.LocalPackage(pkgName) == nil {\n\t\t\trun.Logger.Errorln(gotext.Get(\"package '%s' was not found\", pkgName))\n\t\t\tmissing = true\n\t\t}\n\t\treturn false\n\t})\n\n\tif missing || noUpdates {\n\t\treturn fmt.Errorf(\"\")\n\t}\n\n\treturn nil\n}\n\nfunc printInfoValue(logger *text.Logger, key string, values ...string) {\n\tconst (\n\t\tkeyLength  = 32\n\t\tdelimCount = 2\n\t)\n\n\tspecialWordsCount := 0\n\n\tfor _, runeValue := range key {\n\t\t// CJK handling: the character 'ー' is Katakana\n\t\t// but if use unicode.Katakana, it will return false\n\t\tif unicode.IsOneOf([]*unicode.RangeTable{\n\t\t\tunicode.Han,\n\t\t\tunicode.Hiragana,\n\t\t\tunicode.Katakana,\n\t\t\tunicode.Hangul,\n\t\t}, runeValue) || runeValue == 'ー' {\n\t\t\tspecialWordsCount++\n\t\t}\n\t}\n\n\tkeyTextCount := specialWordsCount - keyLength + delimCount\n\tstr := fmt.Sprintf(text.Bold(\"%-*s: \"), keyTextCount, key)\n\n\tif len(values) == 0 || (len(values) == 1 && values[0] == \"\") {\n\t\tlogger.Printf(\"%s%s\\n\", str, gotext.Get(\"None\"))\n\t\treturn\n\t}\n\n\tmaxCols := getColumnCount()\n\tcols := keyLength + len(values[0])\n\tstr += values[0]\n\n\tfor _, value := range values[1:] {\n\t\tif maxCols > keyLength && cols+len(value)+delimCount >= maxCols {\n\t\t\tcols = keyLength\n\t\t\tstr += \"\\n\" + strings.Repeat(\" \", keyLength)\n\t\t} else if cols != keyLength {\n\t\t\tstr += strings.Repeat(\" \", delimCount)\n\t\t\tcols += delimCount\n\t\t}\n\n\t\tstr += value\n\t\tcols += len(value)\n\t}\n\n\tlogger.Println(str)\n}\n\nvar cachedColumnCount = -1\n\nfunc getColumnCount() int {\n\tif cachedColumnCount > 0 {\n\t\treturn cachedColumnCount\n\t}\n\n\tif count, err := strconv.Atoi(os.Getenv(\"COLUMNS\")); err == nil {\n\t\tcachedColumnCount = count\n\t\treturn cachedColumnCount\n\t}\n\n\tif ws, err := unix.IoctlGetWinsize(syscall.Stdout, unix.TIOCGWINSZ); err == nil {\n\t\tcachedColumnCount = int(ws.Col)\n\t\treturn cachedColumnCount\n\t}\n\n\treturn 80\n}\n"
  },
  {
    "path": "print_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/Jguer/aur\"\n\talpm \"github.com/Jguer/dyalpm\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/db/mock\"\n\tmockaur \"github.com/Jguer/yay/v12/pkg/dep/mock\"\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\t\"github.com/Jguer/yay/v12/pkg/vcs\"\n)\n\nfunc TestPrintUpdateList(t *testing.T) {\n\t// The current method of capturing os.Stdout hinders parallelization.\n\t// Setting of global settings.NoConfirm in printUpdateList also hinders parallelization.\n\t// t.Parallel()\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tf, err := os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tmockDBName := mock.NewDB(\"core\")\n\tmockDB := &mock.DBExecutor{\n\t\tAlpmArchitecturesFn: func() ([]string, error) {\n\t\t\treturn []string{\"x86_64\"}, nil\n\t\t},\n\t\tRefreshHandleFn: func() error {\n\t\t\treturn nil\n\t\t},\n\t\tReposFn: func() []string {\n\t\t\treturn []string{\"core\"}\n\t\t},\n\t\tInstalledRemotePackagesFn: func() map[string]alpm.Package {\n\t\t\treturn map[string]alpm.Package{\n\t\t\t\t\"vosk-api\": &mock.Package{\n\t\t\t\t\tPName:    \"vosk-api\",\n\t\t\t\t\tPVersion: \"0.3.43-1\",\n\t\t\t\t\tPBase:    \"vosk-api\",\n\t\t\t\t\tPReason:  alpm.PkgReasonExplicit,\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t\tInstalledRemotePackageNamesFn: func() []string {\n\t\t\treturn []string{\"vosk-api\"}\n\t\t},\n\t\tSyncUpgradesFn: func(\n\t\t\tbool,\n\t\t) (map[string]db.SyncUpgrade, error) {\n\t\t\treturn map[string]db.SyncUpgrade{\n\t\t\t\t\"linux\": {\n\t\t\t\t\tPackage: &mock.Package{\n\t\t\t\t\t\tPName:    \"linux\",\n\t\t\t\t\t\tPVersion: \"5.10.0\",\n\t\t\t\t\t\tPDB:      mockDBName,\n\t\t\t\t\t},\n\t\t\t\t\tLocalVersion: \"4.3.0\",\n\t\t\t\t\tReason:       alpm.PkgReasonExplicit,\n\t\t\t\t},\n\t\t\t\t\"go\": {\n\t\t\t\t\tPackage: &mock.Package{\n\t\t\t\t\t\tPName:    \"go\",\n\t\t\t\t\t\tPVersion: \"2:1.20.4-1\",\n\t\t\t\t\t\tPDB:      mockDBName,\n\t\t\t\t\t},\n\t\t\t\t\tLocalVersion: \"2:1.20.3-1\",\n\t\t\t\t\tReason:       alpm.PkgReasonExplicit,\n\t\t\t\t},\n\t\t\t}, nil\n\t\t},\n\t\tLocalPackageFn: func(s string) mock.IPackage {\n\t\t\tif s == \"no-update-pkg\" {\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName:    \"no-update-pkg\",\n\t\t\t\t\tPVersion: \"3.3.3\",\n\t\t\t\t\tPDB:      mockDBName,\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t\tSetLoggerFn: func(logger *text.Logger) {},\n\t}\n\n\tmockDBNoUpdates := &mock.DBExecutor{\n\t\tAlpmArchitecturesFn: func() ([]string, error) {\n\t\t\treturn []string{\"x86_64\"}, nil\n\t\t},\n\t\tRefreshHandleFn: func() error {\n\t\t\treturn nil\n\t\t},\n\t\tReposFn: func() []string {\n\t\t\treturn []string{\"core\"}\n\t\t},\n\t\tInstalledRemotePackagesFn: func() map[string]alpm.Package {\n\t\t\treturn map[string]alpm.Package{\n\t\t\t\t\"vosk-api\": &mock.Package{\n\t\t\t\t\tPName:    \"vosk-api\",\n\t\t\t\t\tPVersion: \"0.3.43-1\",\n\t\t\t\t\tPBase:    \"vosk-api\",\n\t\t\t\t\tPReason:  alpm.PkgReasonExplicit,\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t\tInstalledRemotePackageNamesFn: func() []string {\n\t\t\treturn []string{\"vosk-api\"}\n\t\t},\n\t\tSyncUpgradesFn: func(\n\t\t\tbool,\n\t\t) (map[string]db.SyncUpgrade, error) {\n\t\t\treturn map[string]db.SyncUpgrade{}, nil\n\t\t},\n\t\tLocalPackageFn: func(s string) mock.IPackage {\n\t\t\treturn nil\n\t\t},\n\t\tSetLoggerFn: func(logger *text.Logger) {},\n\t}\n\n\tmockAUR := &mockaur.MockAUR{\n\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\treturn []aur.Pkg{\n\t\t\t\t{\n\t\t\t\t\tName:        \"vosk-api\",\n\t\t\t\t\tPackageBase: \"vosk-api\",\n\t\t\t\t\tVersion:     \"0.3.45-1\",\n\t\t\t\t},\n\t\t\t}, nil\n\t\t},\n\t}\n\n\tmockAURNoUpdates := &mockaur.MockAUR{\n\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\treturn []aur.Pkg{\n\t\t\t\t{\n\t\t\t\t\tName:        \"vosk-api\",\n\t\t\t\t\tPackageBase: \"vosk-api\",\n\t\t\t\t\tVersion:     \"0.3.43-1\",\n\t\t\t\t},\n\t\t\t}, nil\n\t\t},\n\t}\n\n\ttype mockData struct {\n\t\tdb       *mock.DBExecutor\n\t\taurCache *mockaur.MockAUR\n\t}\n\n\ttestCases := []struct {\n\t\tname     string\n\t\tmockData mockData\n\t\targs     []string\n\t\ttargets  []string\n\t\twantPkgs []string\n\t\twantErr  bool\n\t}{\n\t\t{\n\t\t\tname:     \"Qu\",\n\t\t\tmockData: mockData{mockDB, mockAUR},\n\t\t\targs:     []string{\"Q\", \"u\"},\n\t\t\ttargets:  []string{},\n\t\t\twantPkgs: []string{\n\t\t\t\tfmt.Sprintf(\"%s %s -> %s\",\n\t\t\t\t\ttext.Bold(\"linux\"),\n\t\t\t\t\ttext.Bold(text.Green(\"4.3.0\")),\n\t\t\t\t\ttext.Bold(text.Green(\"5.10.0\")),\n\t\t\t\t),\n\t\t\t\tfmt.Sprintf(\"%s %s -> %s\",\n\t\t\t\t\ttext.Bold(\"go\"),\n\t\t\t\t\ttext.Bold(text.Green(\"2:1.20.3-1\")),\n\t\t\t\t\ttext.Bold(text.Green(\"2:1.20.4-1\")),\n\t\t\t\t),\n\t\t\t\tfmt.Sprintf(\"%s %s -> %s\",\n\t\t\t\t\ttext.Bold(\"vosk-api\"),\n\t\t\t\t\ttext.Bold(text.Green(\"0.3.43-1\")),\n\t\t\t\t\ttext.Bold(text.Green(\"0.3.45-1\")),\n\t\t\t\t),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:     \"Quq\",\n\t\t\tmockData: mockData{mockDB, mockAUR},\n\t\t\targs:     []string{\"Q\", \"u\", \"q\"},\n\t\t\ttargets:  []string{},\n\t\t\twantPkgs: []string{\"linux\", \"go\", \"vosk-api\"},\n\t\t},\n\t\t{\n\t\t\tname:     \"Quq linux\",\n\t\t\tmockData: mockData{mockDB, mockAUR},\n\t\t\targs:     []string{\"Q\", \"u\", \"q\"},\n\t\t\ttargets:  []string{\"linux\"},\n\t\t\twantPkgs: []string{\"linux\"},\n\t\t},\n\t\t{\n\t\t\tname:     \"Qunq\",\n\t\t\tmockData: mockData{mockDB, mockAUR},\n\t\t\targs:     []string{\"Q\", \"u\", \"n\", \"q\"},\n\t\t\ttargets:  []string{},\n\t\t\twantPkgs: []string{\"linux\", \"go\"},\n\t\t},\n\t\t{\n\t\t\tname:     \"Qumq\",\n\t\t\tmockData: mockData{mockDB, mockAUR},\n\t\t\targs:     []string{\"Q\", \"u\", \"m\", \"q\"},\n\t\t\ttargets:  []string{},\n\t\t\twantPkgs: []string{\"vosk-api\"},\n\t\t},\n\t\t{\n\t\t\tname:     \"Quq no-update-pkg\",\n\t\t\tmockData: mockData{mockDB, mockAUR},\n\t\t\targs:     []string{\"Q\", \"u\", \"q\"},\n\t\t\ttargets:  []string{\"no-update-pkg\"},\n\t\t\twantPkgs: []string{},\n\t\t\twantErr:  true,\n\t\t},\n\t\t{\n\t\t\tname:     \"Quq non-existent-pkg\",\n\t\t\tmockData: mockData{mockDB, mockAUR},\n\t\t\targs:     []string{\"Q\", \"u\", \"q\"},\n\t\t\ttargets:  []string{\"non-existent-pkg\"},\n\t\t\twantPkgs: []string{},\n\t\t\twantErr:  true,\n\t\t},\n\t\t{\n\t\t\tname:     \"Qu no-updates-any\",\n\t\t\tmockData: mockData{mockDBNoUpdates, mockAURNoUpdates},\n\t\t\targs:     []string{\"Q\", \"u\"},\n\t\t\ttargets:  []string{},\n\t\t\twantPkgs: []string{},\n\t\t\twantErr:  true,\n\t\t},\n\t\t{\n\t\t\tname:     \"Qun no-updates-native\",\n\t\t\tmockData: mockData{mockDBNoUpdates, mockAUR},\n\t\t\targs:     []string{\"Q\", \"u\", \"n\"},\n\t\t\ttargets:  []string{},\n\t\t\twantPkgs: []string{},\n\t\t\twantErr:  true,\n\t\t},\n\t\t{\n\t\t\tname:     \"Qum no-updates-foreign\",\n\t\t\tmockData: mockData{mockDB, mockAURNoUpdates},\n\t\t\targs:     []string{\"Q\", \"u\", \"m\"},\n\t\t\ttargets:  []string{},\n\t\t\twantPkgs: []string{},\n\t\t\twantErr:  true,\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tcmdBuilder := &exe.CmdBuilder{\n\t\t\t\tSudoBin:          \"su\",\n\t\t\t\tPacmanBin:        pacmanBin,\n\t\t\t\tPacmanConfigPath: \"/etc/pacman.conf\",\n\t\t\t\tRunner:           &exe.MockRunner{},\n\t\t\t\tSudoLoopEnabled:  false,\n\t\t\t}\n\n\t\t\tr, w, _ := os.Pipe()\n\n\t\t\tlogger := text.NewLogger(w, io.Discard, strings.NewReader(\"\"), true, \"test\")\n\n\t\t\trun := &runtime.Runtime{\n\t\t\t\tCfg: &settings.Configuration{\n\t\t\t\t\tRemoveMake: \"no\",\n\t\t\t\t},\n\t\t\t\tLogger:     logger,\n\t\t\t\tCmdBuilder: cmdBuilder,\n\t\t\t\tVCSStore:   &vcs.Mock{},\n\t\t\t\tAURClient:  tc.mockData.aurCache,\n\t\t\t}\n\n\t\t\tcmdArgs := parser.MakeArguments()\n\t\t\tcmdArgs.AddArg(tc.args...)\n\t\t\tcmdArgs.AddTarget(tc.targets...)\n\n\t\t\terr = handleCmd(context.Background(), run, cmdArgs, tc.mockData.db)\n\n\t\t\tw.Close()\n\t\t\tout, _ := io.ReadAll(r)\n\n\t\t\tif tc.wantErr {\n\t\t\t\trequire.Error(t, err)\n\t\t\t\tassert.EqualError(t, err, \"\")\n\t\t\t} else {\n\t\t\t\trequire.NoError(t, err)\n\t\t\t}\n\n\t\t\toutStr := string(out)\n\t\t\toutPkgs := make([]string, 0)\n\t\t\tif outStr != \"\" {\n\t\t\t\toutPkgs = strings.Split(strings.TrimSuffix(outStr, \"\\n\"), \"\\n\")\n\t\t\t}\n\n\t\t\tassert.ElementsMatch(t, outPkgs, tc.wantPkgs, \"Lists of packages should match\")\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "query.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io/fs\"\n\t\"path/filepath\"\n\n\taur \"github.com/Jguer/aur\"\n\talpm \"github.com/Jguer/dyalpm\"\n\tmapset \"github.com/deckarep/golang-set/v2\"\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/query\"\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\n// SyncSearch presents a query to the local repos and to the AUR.\nfunc syncSearch(ctx context.Context, pkgS []string,\n\tdbExecutor db.Executor, queryBuilder query.Builder, verbose bool,\n) error {\n\tqueryBuilder.Execute(ctx, dbExecutor, pkgS)\n\n\tsearchMode := query.Minimal\n\tif verbose {\n\t\tsearchMode = query.Detailed\n\t}\n\n\treturn queryBuilder.Results(dbExecutor, searchMode)\n}\n\n// SyncInfo serves as a pacman -Si for repo packages and AUR packages.\nfunc syncInfo(ctx context.Context, run *runtime.Runtime,\n\tcmdArgs *parser.Arguments, pkgS []string, dbExecutor db.Executor,\n) error {\n\tvar (\n\t\tremoteAurPkgs []aur.Pkg\n\t\terr           error\n\t\tmissing       = false\n\t)\n\n\tpkgS = query.RemoveInvalidTargets(run.Logger, pkgS, run.Cfg.Mode)\n\n\texpandedPackages := []string{}\n\tfor _, pkg := range pkgS {\n\t\tgroupPackages := dbExecutor.PackagesFromGroup(pkg)\n\t\tif len(groupPackages) > 0 {\n\t\t\tfor _, p := range groupPackages {\n\t\t\t\texpandedPackages = append(expandedPackages, p.Name())\n\t\t\t}\n\t\t} else {\n\t\t\texpandedPackages = append(expandedPackages, pkg)\n\t\t}\n\t}\n\tpkgS = expandedPackages\n\n\taurS, repoS := packageSlices(pkgS, run.Cfg, dbExecutor)\n\n\tif len(repoS) == 0 && len(aurS) == 0 {\n\t\tif run.Cfg.Mode != parser.ModeRepo {\n\t\t\taurS = dbExecutor.InstalledRemotePackageNames()\n\t\t}\n\n\t\tif run.Cfg.Mode != parser.ModeAUR {\n\t\t\trepoS = dbExecutor.InstalledSyncPackageNames()\n\t\t}\n\t}\n\n\tif len(aurS) != 0 {\n\t\tnoDB := make([]string, 0, len(aurS))\n\n\t\tfor _, pkg := range aurS {\n\t\t\t_, name := text.SplitDBFromName(pkg)\n\t\t\tnoDB = append(noDB, name)\n\t\t}\n\n\t\tremoteAurPkgs, err = run.AURClient.Get(ctx, &aur.Query{\n\t\t\tNeedles: noDB,\n\t\t\tBy:      aur.Name,\n\t\t})\n\t\tif err != nil {\n\t\t\trun.Logger.Errorln(err)\n\t\t}\n\n\t\t// Check for any missing packages and print errors for any not found\n\t\tfound := mapset.NewThreadUnsafeSet[string]()\n\t\tfor i := range remoteAurPkgs {\n\t\t\tfound.Add(remoteAurPkgs[i].Name)\n\t\t}\n\n\t\tfor _, name := range noDB {\n\t\t\tif !found.Contains(name) {\n\t\t\t\tmissing = true\n\t\t\t\trun.Logger.Errorln(gotext.Get(\"No AUR package found for\"), \" \", name)\n\t\t\t}\n\t\t}\n\t}\n\n\tif len(repoS) != 0 || (len(aurS) == 0 && len(repoS) == 0) {\n\t\targuments := cmdArgs.Copy()\n\t\targuments.ClearTargets()\n\t\targuments.AddTarget(repoS...)\n\n\t\terr = run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,\n\t\t\targuments, run.Cfg.Mode, settings.NoConfirm))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tfor i := range remoteAurPkgs {\n\t\tprintInfo(run.Logger, run.Cfg, &remoteAurPkgs[i], cmdArgs.ExistsDouble(\"i\"))\n\t}\n\n\tif missing {\n\t\terr = fmt.Errorf(\"\")\n\t}\n\n\treturn err\n}\n\n// PackageSlices separates an input slice into aur and repo slices.\nfunc packageSlices(toCheck []string, config *settings.Configuration, dbExecutor db.Executor) (aurNames, repoNames []string) {\n\tfor _, _pkg := range toCheck {\n\t\tdbName, name := text.SplitDBFromName(_pkg)\n\n\t\tif dbName == \"aur\" || config.Mode == parser.ModeAUR {\n\t\t\taurNames = append(aurNames, _pkg)\n\t\t\tcontinue\n\t\t} else if dbName != \"\" || config.Mode == parser.ModeRepo {\n\t\t\trepoNames = append(repoNames, _pkg)\n\t\t\tcontinue\n\t\t}\n\n\t\tif dbExecutor.SyncSatisfierExists(name) ||\n\t\t\tlen(dbExecutor.PackagesFromGroup(name)) != 0 {\n\t\t\trepoNames = append(repoNames, _pkg)\n\t\t} else {\n\t\t\taurNames = append(aurNames, _pkg)\n\t\t}\n\t}\n\n\treturn aurNames, repoNames\n}\n\n// MapSetMap is a Map of Sets.\ntype mapSetMap[T comparable] map[T]mapset.Set[T]\n\n// Add adds a new value to the Map.\n// If n is already in the map, then v is appended to the StringSet under that key.\n// Otherwise a new Set is created containing v.\nfunc (mss mapSetMap[T]) Add(n, v T) {\n\tif _, ok := mss[n]; !ok {\n\t\tmss[n] = mapset.NewSet[T]()\n\t}\n\n\tmss[n].Add(v)\n}\n\n// HangingPackages returns a list of packages installed as deps\n// and unneeded by the system\n// removeOptional decides whether optional dependencies are counted or not.\nfunc hangingPackages(removeOptional bool, dbExecutor db.Executor) (hanging []string) {\n\t// safePackages represents every package in the system in one of 3 states\n\t// State = 0 - Remove package from the system\n\t// State = 1 - Keep package in the system; need to iterate over dependencies\n\t// State = 2 - Keep package and have iterated over dependencies\n\tsafePackages := make(map[string]uint8)\n\t// provides stores a mapping from the provides name back to the original package name\n\tprovides := make(mapSetMap[string])\n\n\tpackages := dbExecutor.LocalPackages()\n\t// Mark explicit dependencies and enumerate the provides list\n\tfor _, pkg := range packages {\n\t\tif pkg.Reason() == alpm.PkgReasonExplicit {\n\t\t\tsafePackages[pkg.Name()] = 1\n\t\t} else {\n\t\t\tsafePackages[pkg.Name()] = 0\n\t\t}\n\n\t\tfor _, dep := range dbExecutor.PackageProvides(pkg) {\n\t\t\tprovides.Add(dep.Name, pkg.Name())\n\t\t}\n\t}\n\n\titerateAgain := true\n\n\tfor iterateAgain {\n\t\titerateAgain = false\n\n\t\tfor _, pkg := range packages {\n\t\t\tif state := safePackages[pkg.Name()]; state == 0 || state == 2 {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tsafePackages[pkg.Name()] = 2\n\t\t\tdeps := dbExecutor.PackageDepends(pkg)\n\n\t\t\tif !removeOptional {\n\t\t\t\tdeps = append(deps, dbExecutor.PackageOptionalDepends(pkg)...)\n\t\t\t}\n\n\t\t\t// Update state for dependencies\n\t\t\tfor _, dep := range deps {\n\t\t\t\t// Don't assume a dependency is installed\n\t\t\t\tstate, ok := safePackages[dep.Name]\n\t\t\t\tif !ok {\n\t\t\t\t\t// Check if dep is a provides rather than actual package name\n\t\t\t\t\tif pset, ok2 := provides[dep.Name]; ok2 {\n\t\t\t\t\t\tfor p := range pset.Iter() {\n\t\t\t\t\t\t\tif safePackages[p] == 0 {\n\t\t\t\t\t\t\t\titerateAgain = true\n\t\t\t\t\t\t\t\tsafePackages[p] = 1\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tif state == 0 {\n\t\t\t\t\titerateAgain = true\n\t\t\t\t\tsafePackages[dep.Name] = 1\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Build list of packages to be removed\n\tfor _, pkg := range packages {\n\t\tif safePackages[pkg.Name()] == 0 {\n\t\t\thanging = append(hanging, pkg.Name())\n\t\t}\n\t}\n\n\treturn hanging\n}\n\nfunc getFolderSize(path string) (size int64) {\n\t_ = filepath.WalkDir(path, func(p string, entry fs.DirEntry, err error) error {\n\t\tif err != nil || entry == nil {\n\t\t\treturn nil\n\t\t}\n\t\tinfo, infoErr := entry.Info()\n\t\tif infoErr != nil || info == nil {\n\t\t\treturn nil\n\t\t}\n\t\tsize += info.Size()\n\t\treturn nil\n\t})\n\n\treturn size\n}\n\n// Statistics returns statistics about packages installed in system.\nfunc statistics(run *runtime.Runtime, dbExecutor db.Executor) (res struct {\n\tTotaln       int\n\tExpln        int\n\tTotalSize    int64\n\tpacmanCaches map[string]int64\n\tyayCache     int64\n},\n) {\n\tfor _, pkg := range dbExecutor.LocalPackages() {\n\t\tres.TotalSize += pkg.ISize()\n\t\tres.Totaln++\n\n\t\tif pkg.Reason() == alpm.PkgReasonExplicit {\n\t\t\tres.Expln++\n\t\t}\n\t}\n\n\tres.pacmanCaches = make(map[string]int64)\n\tfor _, path := range run.PacmanConf.CacheDir {\n\t\tres.pacmanCaches[path] = getFolderSize(path)\n\t}\n\n\tres.yayCache = getFolderSize(run.Cfg.BuildDir)\n\n\treturn\n}\n"
  },
  {
    "path": "query_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage main\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db/mock\"\n\tmockaur \"github.com/Jguer/yay/v12/pkg/dep/mock\"\n\t\"github.com/Jguer/yay/v12/pkg/query\"\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\n\t\"github.com/Jguer/aur\"\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc getFromFile(t *testing.T, filePath string) mockaur.GetFunc {\n\tf, err := os.Open(filePath)\n\trequire.NoError(t, err)\n\n\tfBytes, err := io.ReadAll(f)\n\trequire.NoError(t, err)\n\n\tpkgs := []aur.Pkg{}\n\terr = json.Unmarshal(fBytes, &pkgs)\n\trequire.NoError(t, err)\n\n\treturn func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\treturn pkgs, nil\n\t}\n}\n\nfunc TestSyncInfo(t *testing.T) {\n\tt.Parallel()\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\n\ttestCases := []struct {\n\t\tname     string\n\t\targs     []string\n\t\ttargets  []string\n\t\twantShow []string\n\t\twantErr  bool\n\t}{\n\t\t{\n\t\t\tname:     \"Si linux\",\n\t\t\targs:     []string{\"S\", \"i\"},\n\t\t\ttargets:  []string{\"linux\"},\n\t\t\twantShow: []string{\"pacman\", \"-S\", \"-i\", \"--config\", \"/etc/pacman.conf\", \"--\", \"linux\"},\n\t\t},\n\t\t{\n\t\t\tname:     \"Si jellyfin\",\n\t\t\targs:     []string{\"S\", \"i\"},\n\t\t\ttargets:  []string{\"jellyfin\"},\n\t\t\twantShow: []string{},\n\t\t},\n\t\t{\n\t\t\tname:     \"Si linux jellyfin\",\n\t\t\targs:     []string{\"S\", \"i\"},\n\t\t\ttargets:  []string{\"linux\", \"jellyfin\"},\n\t\t\twantShow: []string{\"pacman\", \"-S\", \"-i\", \"--config\", \"/etc/pacman.conf\", \"--\", \"linux\"},\n\t\t},\n\t\t{\n\t\t\tname:     \"Si jellyfin\",\n\t\t\targs:     []string{\"S\", \"i\"},\n\t\t\ttargets:  []string{\"jellyfin\"},\n\t\t\twantShow: []string{},\n\t\t},\n\t\t{\n\t\t\tname:     \"Si missing\",\n\t\t\targs:     []string{\"S\", \"i\"},\n\t\t\ttargets:  []string{\"missing\"},\n\t\t\twantShow: []string{},\n\t\t\twantErr:  true,\n\t\t},\n\t\t{\n\t\t\tname:     \"Si arduino\",\n\t\t\targs:     []string{\"S\", \"i\"},\n\t\t\ttargets:  []string{\"arduino\"},\n\t\t\twantShow: []string{\"pacman\", \"-S\", \"-i\", \"--config\", \"/etc/pacman.conf\", \"--\", \"arduino-cli\"},\n\t\t},\n\t}\n\n\tdbExc := &mock.DBExecutor{\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\tif s == \"linux\" {\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName: \"linux\",\n\t\t\t\t\tPBase: \"linux\",\n\t\t\t\t}\n\t\t\t}\n\t\t\tif s == \"arduino-cli\" {\n\t\t\t\treturn &mock.Package{\n\t\t\t\t\tPName: \"arduino-cli\",\n\t\t\t\t\tPBase: \"arduino-cli\",\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t\tPackagesFromGroupFn: func(s string) []mock.IPackage {\n\t\t\tif s == \"arduino\" {\n\t\t\t\treturn []mock.IPackage{\n\t\t\t\t\t&mock.Package{PName: \"arduino-cli\"},\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t}\n\n\tmockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\tif query.Needles[0] == \"jellyfin\" {\n\t\t\tjfinFn := getFromFile(t, \"pkg/dep/testdata/jellyfin.json\")\n\t\t\treturn jfinFn(ctx, query)\n\t\t}\n\n\t\treturn nil, fmt.Errorf(\"not found\")\n\t}}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tmockRunner := &exe.MockRunner{\n\t\t\t\tCaptureFn: func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\t\t\t\treturn \"\", \"\", nil\n\t\t\t\t},\n\t\t\t\tShowFn: func(cmd *exec.Cmd) error { return nil },\n\t\t\t}\n\t\t\tcmdBuilder := &exe.CmdBuilder{\n\t\t\t\tSudoBin:          \"su\",\n\t\t\t\tPacmanBin:        pacmanBin,\n\t\t\t\tPacmanConfigPath: \"/etc/pacman.conf\",\n\t\t\t\tGitBin:           \"git\",\n\t\t\t\tRunner:           mockRunner,\n\t\t\t\tSudoLoopEnabled:  false,\n\t\t\t}\n\n\t\t\trun := &runtime.Runtime{\n\t\t\t\tCmdBuilder: cmdBuilder,\n\t\t\t\tAURClient:  mockAUR,\n\t\t\t\tLogger:     newTestLogger(),\n\t\t\t\tCfg:        &settings.Configuration{},\n\t\t\t}\n\n\t\t\tcmdArgs := parser.MakeArguments()\n\t\t\tcmdArgs.AddArg(tc.args...)\n\t\t\tcmdArgs.AddTarget(tc.targets...)\n\n\t\t\terr := handleCmd(context.Background(),\n\t\t\t\trun, cmdArgs, dbExc,\n\t\t\t)\n\n\t\t\tif tc.wantErr {\n\t\t\t\trequire.Error(t, err)\n\t\t\t\tassert.EqualError(t, err, \"\")\n\t\t\t} else {\n\t\t\t\trequire.NoError(t, err)\n\t\t\t}\n\t\t\tif len(tc.wantShow) == 0 {\n\t\t\t\tassert.Empty(t, mockRunner.ShowCalls)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tfor i, call := range mockRunner.ShowCalls {\n\t\t\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\t\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\n\t\t\t\t// options are in a different order on different systems and on CI root user is used\n\t\t\t\tassert.Subset(t, strings.Split(show, \" \"),\n\t\t\t\t\tstrings.Split(tc.wantShow[i], \" \"),\n\t\t\t\t\tfmt.Sprintf(\"%d - %s\", i, show))\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Should not error when there is a DB called aur\nfunc TestSyncSearchAURDB(t *testing.T) {\n\tt.Parallel()\n\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\ttestCases := []struct {\n\t\tname       string\n\t\targs       []string\n\t\ttargets    []string\n\t\twantShow   []string\n\t\twantErr    bool\n\t\tbottomUp   bool\n\t\tsingleLine bool\n\t\tmixed      bool\n\t}{\n\t\t{\n\t\t\tname:     \"Ss jellyfin false false\",\n\t\t\targs:     []string{\"S\", \"s\"},\n\t\t\ttargets:  []string{\"jellyfin\"},\n\t\t\twantShow: []string{},\n\t\t},\n\t\t{\n\t\t\tname:       \"Ss jellyfin true false\",\n\t\t\targs:       []string{\"S\", \"s\"},\n\t\t\ttargets:    []string{\"jellyfin\"},\n\t\t\twantShow:   []string{},\n\t\t\tsingleLine: true,\n\t\t},\n\t\t{\n\t\t\tname:       \"Ss jellyfin true true\",\n\t\t\targs:       []string{\"S\", \"s\"},\n\t\t\ttargets:    []string{\"jellyfin\"},\n\t\t\twantShow:   []string{},\n\t\t\tsingleLine: true,\n\t\t\tmixed:      true,\n\t\t},\n\t\t{\n\t\t\tname:       \"Ss jellyfin false true\",\n\t\t\targs:       []string{\"S\", \"s\"},\n\t\t\ttargets:    []string{\"jellyfin\"},\n\t\t\twantShow:   []string{},\n\t\t\tsingleLine: false,\n\t\t\tmixed:      true,\n\t\t},\n\t\t{\n\t\t\tname:       \"Ss jellyfin true true - bottomup\",\n\t\t\targs:       []string{\"S\", \"s\"},\n\t\t\ttargets:    []string{\"jellyfin\"},\n\t\t\twantShow:   []string{},\n\t\t\tsingleLine: true,\n\t\t\tmixed:      true,\n\t\t\tbottomUp:   true,\n\t\t},\n\t}\n\n\tdbExc := &mock.DBExecutor{\n\t\tSyncPackagesFn: func(s ...string) []mock.IPackage {\n\t\t\treturn []mock.IPackage{\n\t\t\t\t&mock.Package{\n\t\t\t\t\tPName: \"jellyfin\",\n\t\t\t\t\tPBase: \"jellyfin\",\n\t\t\t\t\tPDB:   mock.NewDB(\"aur\"),\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t\tLocalPackageFn: func(s string) mock.IPackage {\n\t\t\treturn &mock.Package{\n\t\t\t\tPName: \"jellyfin\",\n\t\t\t\tPBase: \"jellyfin\",\n\t\t\t\tPDB:   mock.NewDB(\"aur\"),\n\t\t\t}\n\t\t},\n\t\tPackagesFromGroupFn: func(s string) []mock.IPackage {\n\t\t\treturn nil\n\t\t},\n\t}\n\n\tmockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\tif query.Needles[0] == \"jellyfin\" {\n\t\t\tjfinFn := getFromFile(t, \"pkg/dep/testdata/jellyfin.json\")\n\t\t\treturn jfinFn(ctx, query)\n\t\t}\n\n\t\treturn nil, fmt.Errorf(\"not found\")\n\t}}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tmockRunner := &exe.MockRunner{\n\t\t\t\tCaptureFn: func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\t\t\t\treturn \"\", \"\", nil\n\t\t\t\t},\n\t\t\t\tShowFn: func(cmd *exec.Cmd) error { return nil },\n\t\t\t}\n\t\t\tcmdBuilder := &exe.CmdBuilder{\n\t\t\t\tSudoBin:          \"su\",\n\t\t\t\tPacmanBin:        pacmanBin,\n\t\t\t\tPacmanConfigPath: \"/etc/pacman.conf\",\n\t\t\t\tGitBin:           \"git\",\n\t\t\t\tRunner:           mockRunner,\n\t\t\t\tSudoLoopEnabled:  false,\n\t\t\t}\n\n\t\t\trun := &runtime.Runtime{\n\t\t\t\tCmdBuilder: cmdBuilder,\n\t\t\t\tAURClient:  mockAUR,\n\t\t\t\tQueryBuilder: query.NewSourceQueryBuilder(mockAUR, newTestLogger(), \"votes\", parser.ModeAny, \"name\",\n\t\t\t\t\ttc.bottomUp, tc.singleLine, tc.mixed),\n\t\t\t\tLogger: newTestLogger(),\n\t\t\t\tCfg:    &settings.Configuration{},\n\t\t\t}\n\n\t\t\tcmdArgs := parser.MakeArguments()\n\t\t\tcmdArgs.AddArg(tc.args...)\n\t\t\tcmdArgs.AddTarget(tc.targets...)\n\n\t\t\terr := handleCmd(context.Background(),\n\t\t\t\trun, cmdArgs, dbExc,\n\t\t\t)\n\n\t\t\tif tc.wantErr {\n\t\t\t\trequire.Error(t, err)\n\t\t\t\tassert.EqualError(t, err, \"\")\n\t\t\t} else {\n\t\t\t\trequire.NoError(t, err)\n\t\t\t}\n\t\t\tif len(tc.wantShow) == 0 {\n\t\t\t\tassert.Empty(t, mockRunner.ShowCalls)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tfor i, call := range mockRunner.ShowCalls {\n\t\t\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\t\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\n\t\t\t\t// options are in a different order on different systems and on CI root user is used\n\t\t\t\tassert.Subset(t, strings.Split(show, \" \"),\n\t\t\t\t\tstrings.Split(tc.wantShow[i], \" \"),\n\t\t\t\t\tfmt.Sprintf(\"%d - %s\", i, show))\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "sync.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/dep\"\n\t\"github.com/Jguer/yay/v12/pkg/multierror\"\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/sync\"\n\t\"github.com/Jguer/yay/v12/pkg/upgrade\"\n)\n\nfunc syncInstall(ctx context.Context,\n\trun *runtime.Runtime,\n\tcmdArgs *parser.Arguments,\n\tdbExecutor db.Executor,\n) error {\n\taurCache := run.AURClient\n\trefreshArg := cmdArgs.ExistsArg(\"y\", \"refresh\")\n\tnoDeps := cmdArgs.ExistsArg(\"d\", \"nodeps\")\n\tnoCheck := strings.Contains(run.Cfg.MFlags, \"--nocheck\")\n\tif noDeps {\n\t\trun.CmdBuilder.AddMakepkgFlag(\"-d\")\n\t}\n\n\tif refreshArg && run.Cfg.Mode.AtLeastRepo() {\n\t\tif errR := earlyRefresh(ctx, run.Cfg, run.CmdBuilder, cmdArgs); errR != nil {\n\t\t\treturn fmt.Errorf(\"%s - %w\", gotext.Get(\"error refreshing databases\"), errR)\n\t\t}\n\n\t\t// we may have done -Sy, our handle now has an old\n\t\t// database.\n\t\tif errRefresh := dbExecutor.RefreshHandle(); errRefresh != nil {\n\t\t\treturn errRefresh\n\t\t}\n\t}\n\n\tgrapher := dep.NewGrapher(dbExecutor, aurCache, false, settings.NoConfirm,\n\t\tnoDeps, noCheck, cmdArgs.ExistsArg(\"needed\"), run.Logger.Child(\"grapher\"))\n\n\tgraph, err := grapher.GraphFromTargets(ctx, nil, cmdArgs.Targets)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\texcluded := []string{}\n\tif cmdArgs.ExistsArg(\"u\", \"sysupgrade\") {\n\t\tvar errSysUp error\n\n\t\tupService := upgrade.NewUpgradeService(\n\t\t\tgrapher, aurCache, dbExecutor, run.VCSStore,\n\t\t\trun.Cfg, settings.NoConfirm, run.Logger.Child(\"upgrade\"))\n\n\t\tgraph, errSysUp = upService.GraphUpgrades(ctx,\n\t\t\tgraph, cmdArgs.ExistsDouble(\"u\", \"sysupgrade\"),\n\t\t\tfunc(*upgrade.Upgrade) bool { return true })\n\t\tif errSysUp != nil {\n\t\t\treturn errSysUp\n\t\t}\n\n\t\tupService.AURWarnings.Print()\n\n\t\texcluded, errSysUp = upService.UserExcludeUpgrades(graph)\n\t\tif errSysUp != nil {\n\t\t\treturn errSysUp\n\t\t}\n\t}\n\n\topService := sync.NewOperationService(ctx, dbExecutor, run)\n\tmultiErr := &multierror.MultiError{}\n\ttargets := graph.TopoSortedLayers(func(s string, ii *dep.InstallInfo) error {\n\t\tif ii.Source == dep.Missing {\n\t\t\tmultiErr.Add(fmt.Errorf(\"%w: %s %s\", ErrPackagesNotFound, s, ii.Version))\n\t\t}\n\t\treturn nil\n\t})\n\n\tif err := multiErr.Return(); err != nil {\n\t\treturn err\n\t}\n\n\treturn opService.Run(ctx, run, cmdArgs, targets, excluded)\n}\n\nfunc earlyRefresh(ctx context.Context, cfg *settings.Configuration, cmdBuilder exe.ICmdBuilder, cmdArgs *parser.Arguments) error {\n\targuments := cmdArgs.Copy()\n\tif cfg.CombinedUpgrade {\n\t\targuments.DelArg(\"u\", \"sysupgrade\")\n\t}\n\targuments.DelArg(\"s\", \"search\")\n\targuments.DelArg(\"i\", \"info\")\n\targuments.DelArg(\"l\", \"list\")\n\targuments.ClearTargets()\n\n\treturn cmdBuilder.Show(cmdBuilder.BuildPacmanCmd(ctx,\n\t\targuments, cfg.Mode, settings.NoConfirm))\n}\n"
  },
  {
    "path": "sync_test.go",
    "content": "//go:build !integration\n// +build !integration\n\npackage main\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"github.com/Jguer/aur\"\n\talpm \"github.com/Jguer/dyalpm\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/db/mock\"\n\tmockaur \"github.com/Jguer/yay/v12/pkg/dep/mock\"\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/settings\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/exe\"\n\t\"github.com/Jguer/yay/v12/pkg/settings/parser\"\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n\t\"github.com/Jguer/yay/v12/pkg/vcs\"\n)\n\nfunc TestSyncUpgrade(t *testing.T) {\n\tt.Parallel()\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tgitBin := t.TempDir() + \"/git\"\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(gitBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\treturn \"\", \"\", nil\n\t}\n\n\tshowOverride := func(cmd *exec.Cmd) error {\n\t\treturn nil\n\t}\n\n\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\tcmdBuilder := &exe.CmdBuilder{\n\t\tMakepkgBin:       makepkgBin,\n\t\tSudoBin:          \"su\",\n\t\tPacmanBin:        pacmanBin,\n\t\tPacmanConfigPath: \"/etc/pacman.conf\",\n\t\tGitBin:           \"git\",\n\t\tRunner:           mockRunner,\n\t\tSudoLoopEnabled:  false,\n\t}\n\n\tcmdArgs := parser.MakeArguments()\n\tcmdArgs.AddArg(\"S\")\n\tcmdArgs.AddArg(\"y\")\n\tcmdArgs.AddArg(\"u\")\n\n\tdbName := mock.NewDB(\"core\")\n\n\tdb := &mock.DBExecutor{\n\t\tAlpmArchitecturesFn: func() ([]string, error) {\n\t\t\treturn []string{\"x86_64\"}, nil\n\t\t},\n\t\tRefreshHandleFn: func() error {\n\t\t\treturn nil\n\t\t},\n\t\tReposFn: func() []string {\n\t\t\treturn []string{\"core\"}\n\t\t},\n\t\tInstalledRemotePackagesFn: func() map[string]alpm.Package {\n\t\t\treturn map[string]alpm.Package{}\n\t\t},\n\t\tInstalledRemotePackageNamesFn: func() []string {\n\t\t\treturn []string{}\n\t\t},\n\t\tSyncUpgradesFn: func(\n\t\t\tbool,\n\t\t) (map[string]db.SyncUpgrade, error) {\n\t\t\treturn map[string]db.SyncUpgrade{\n\t\t\t\t\"linux\": {\n\t\t\t\t\tPackage: &mock.Package{\n\t\t\t\t\t\tPName:    \"linux\",\n\t\t\t\t\t\tPVersion: \"5.10.0\",\n\t\t\t\t\t\tPDB:      dbName,\n\t\t\t\t\t},\n\t\t\t\t\tLocalVersion: \"4.3.0\",\n\t\t\t\t\tReason:       alpm.PkgReasonExplicit,\n\t\t\t\t},\n\t\t\t}, nil\n\t\t},\n\t}\n\n\trun := &runtime.Runtime{\n\t\tCfg: &settings.Configuration{\n\t\t\tRemoveMake: \"no\",\n\t\t},\n\t\tLogger:     text.NewLogger(io.Discard, os.Stderr, strings.NewReader(\"\\n\"), true, \"test\"),\n\t\tCmdBuilder: cmdBuilder,\n\t\tVCSStore:   &vcs.Mock{},\n\t\tAURClient: &mockaur.MockAUR{\n\t\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\t\treturn []aur.Pkg{}, nil\n\t\t\t},\n\t\t},\n\t}\n\terr = handleCmd(context.Background(), run, cmdArgs, db)\n\trequire.NoError(t, err)\n\n\twantCapture := []string{}\n\twantShow := []string{\n\t\t\"pacman -S -y --config /etc/pacman.conf --\",\n\t\t\"pacman -S -y -u --config /etc/pacman.conf --\",\n\t}\n\n\trequire.Len(t, mockRunner.ShowCalls, len(wantShow))\n\trequire.Len(t, mockRunner.CaptureCalls, len(wantCapture))\n\n\tfor i, call := range mockRunner.ShowCalls {\n\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\t\tshow = strings.ReplaceAll(show, gitBin, \"git\")\n\n\t\t// options are in a different order on different systems and on CI root user is used\n\t\tassert.Subset(t, strings.Split(show, \" \"), strings.Split(wantShow[i], \" \"), fmt.Sprintf(\"%d - %s\", i, show))\n\t}\n}\n\nfunc TestSyncUpgrade_IgnoreAll(t *testing.T) {\n\tt.Parallel()\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tgitBin := t.TempDir() + \"/git\"\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(gitBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\treturn \"\", \"\", nil\n\t}\n\n\tshowOverride := func(cmd *exec.Cmd) error {\n\t\treturn nil\n\t}\n\n\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\tcmdBuilder := &exe.CmdBuilder{\n\t\tMakepkgBin:       makepkgBin,\n\t\tSudoBin:          \"su\",\n\t\tPacmanBin:        pacmanBin,\n\t\tPacmanConfigPath: \"/etc/pacman.conf\",\n\t\tGitBin:           \"git\",\n\t\tRunner:           mockRunner,\n\t\tSudoLoopEnabled:  false,\n\t}\n\n\tcmdArgs := parser.MakeArguments()\n\tcmdArgs.AddArg(\"S\")\n\tcmdArgs.AddArg(\"y\")\n\tcmdArgs.AddArg(\"u\")\n\n\tdbName := mock.NewDB(\"core\")\n\n\tdb := &mock.DBExecutor{\n\t\tAlpmArchitecturesFn: func() ([]string, error) {\n\t\t\treturn []string{\"x86_64\"}, nil\n\t\t},\n\t\tRefreshHandleFn: func() error {\n\t\t\treturn nil\n\t\t},\n\t\tReposFn: func() []string {\n\t\t\treturn []string{\"core\"}\n\t\t},\n\t\tInstalledRemotePackagesFn: func() map[string]alpm.Package {\n\t\t\treturn map[string]alpm.Package{}\n\t\t},\n\t\tInstalledRemotePackageNamesFn: func() []string {\n\t\t\treturn []string{}\n\t\t},\n\t\tSyncUpgradesFn: func(\n\t\t\tbool,\n\t\t) (map[string]db.SyncUpgrade, error) {\n\t\t\treturn map[string]db.SyncUpgrade{\n\t\t\t\t\"linux\": {\n\t\t\t\t\tPackage: &mock.Package{\n\t\t\t\t\t\tPName:    \"linux\",\n\t\t\t\t\t\tPVersion: \"5.10.0\",\n\t\t\t\t\t\tPDB:      dbName,\n\t\t\t\t\t},\n\t\t\t\t\tLocalVersion: \"4.3.0\",\n\t\t\t\t\tReason:       alpm.PkgReasonExplicit,\n\t\t\t\t},\n\t\t\t}, nil\n\t\t},\n\t}\n\n\trun := &runtime.Runtime{\n\t\tCfg: &settings.Configuration{\n\t\t\tRemoveMake: \"no\",\n\t\t},\n\t\tLogger:     text.NewLogger(io.Discard, os.Stderr, strings.NewReader(\"1\\n\"), true, \"test\"),\n\t\tCmdBuilder: cmdBuilder,\n\t\tVCSStore:   &vcs.Mock{},\n\t\tAURClient: &mockaur.MockAUR{\n\t\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\t\treturn []aur.Pkg{}, nil\n\t\t\t},\n\t\t},\n\t}\n\terr = handleCmd(context.Background(), run, cmdArgs, db)\n\trequire.NoError(t, err)\n\n\twantCapture := []string{}\n\twantShow := []string{\n\t\t\"pacman -S -y --config /etc/pacman.conf --\",\n\t}\n\n\trequire.Len(t, mockRunner.ShowCalls, len(wantShow))\n\trequire.Len(t, mockRunner.CaptureCalls, len(wantCapture))\n\n\tfor i, call := range mockRunner.ShowCalls {\n\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\t\tshow = strings.ReplaceAll(show, gitBin, \"git\")\n\n\t\t// options are in a different order on different systems and on CI root user is used\n\t\tassert.Subset(t, strings.Split(show, \" \"), strings.Split(wantShow[i], \" \"), fmt.Sprintf(\"%d - %s\", i, show))\n\t}\n}\n\nfunc TestSyncUpgrade_IgnoreOne(t *testing.T) {\n\tt.Parallel()\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\tgitBin := t.TempDir() + \"/git\"\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(gitBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\treturn \"\", \"\", nil\n\t}\n\n\tshowOverride := func(cmd *exec.Cmd) error {\n\t\treturn nil\n\t}\n\n\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\tcmdBuilder := &exe.CmdBuilder{\n\t\tMakepkgBin:       makepkgBin,\n\t\tSudoBin:          \"su\",\n\t\tPacmanBin:        pacmanBin,\n\t\tPacmanConfigPath: \"/etc/pacman.conf\",\n\t\tGitBin:           \"git\",\n\t\tRunner:           mockRunner,\n\t\tSudoLoopEnabled:  false,\n\t}\n\n\tcmdArgs := parser.MakeArguments()\n\tcmdArgs.AddArg(\"S\")\n\tcmdArgs.AddArg(\"y\")\n\tcmdArgs.AddArg(\"u\")\n\n\tdbName := mock.NewDB(\"core\")\n\n\tdb := &mock.DBExecutor{\n\t\tAlpmArchitecturesFn: func() ([]string, error) {\n\t\t\treturn []string{\"x86_64\"}, nil\n\t\t},\n\t\tRefreshHandleFn: func() error {\n\t\t\treturn nil\n\t\t},\n\t\tReposFn: func() []string {\n\t\t\treturn []string{\"core\"}\n\t\t},\n\t\tInstalledRemotePackagesFn: func() map[string]alpm.Package {\n\t\t\treturn map[string]alpm.Package{}\n\t\t},\n\t\tInstalledRemotePackageNamesFn: func() []string {\n\t\t\treturn []string{}\n\t\t},\n\t\tSyncUpgradesFn: func(\n\t\t\tbool,\n\t\t) (map[string]db.SyncUpgrade, error) {\n\t\t\treturn map[string]db.SyncUpgrade{\n\t\t\t\t\"gcc\": {\n\t\t\t\t\tPackage: &mock.Package{\n\t\t\t\t\t\tPName:    \"gcc\",\n\t\t\t\t\t\tPVersion: \"6.0.0\",\n\t\t\t\t\t\tPDB:      dbName,\n\t\t\t\t\t},\n\t\t\t\t\tLocalVersion: \"5.0.0\",\n\t\t\t\t\tReason:       alpm.PkgReasonExplicit,\n\t\t\t\t},\n\t\t\t\t\"linux\": {\n\t\t\t\t\tPackage: &mock.Package{\n\t\t\t\t\t\tPName:    \"linux\",\n\t\t\t\t\t\tPVersion: \"5.10.0\",\n\t\t\t\t\t\tPDB:      dbName,\n\t\t\t\t\t},\n\t\t\t\t\tLocalVersion: \"4.3.0\",\n\t\t\t\t\tReason:       alpm.PkgReasonExplicit,\n\t\t\t\t},\n\t\t\t\t\"linux-headers\": {\n\t\t\t\t\tPackage: &mock.Package{\n\t\t\t\t\t\tPName:    \"linux-headers\",\n\t\t\t\t\t\tPVersion: \"5.10.0\",\n\t\t\t\t\t\tPDB:      dbName,\n\t\t\t\t\t},\n\t\t\t\t\tLocalVersion: \"4.3.0\",\n\t\t\t\t\tReason:       alpm.PkgReasonDepend,\n\t\t\t\t},\n\t\t\t}, nil\n\t\t},\n\t}\n\n\trun := &runtime.Runtime{\n\t\tCfg: &settings.Configuration{\n\t\t\tRemoveMake: \"no\",\n\t\t},\n\t\tLogger:     text.NewLogger(io.Discard, os.Stderr, strings.NewReader(\"1\\n\"), true, \"test\"),\n\t\tCmdBuilder: cmdBuilder,\n\t\tVCSStore:   &vcs.Mock{},\n\t\tAURClient: &mockaur.MockAUR{\n\t\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\t\treturn []aur.Pkg{}, nil\n\t\t\t},\n\t\t},\n\t}\n\n\terr = handleCmd(context.Background(), run, cmdArgs, db)\n\trequire.NoError(t, err)\n\n\twantCapture := []string{}\n\twantShow := []string{\n\t\t\"pacman -S -y --config /etc/pacman.conf --\",\n\t\t\"pacman -S -y -u --config /etc/pacman.conf --ignore linux-headers --\",\n\t}\n\n\trequire.Len(t, mockRunner.ShowCalls, len(wantShow))\n\trequire.Len(t, mockRunner.CaptureCalls, len(wantCapture))\n\n\tfor i, call := range mockRunner.ShowCalls {\n\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\t\tshow = strings.ReplaceAll(show, gitBin, \"git\")\n\n\t\t// options are in a different order on different systems and on CI root user is used\n\t\tassert.Subset(t, strings.Split(show, \" \"), strings.Split(wantShow[i], \" \"), fmt.Sprintf(\"%d - %s\", i, show))\n\t}\n}\n\n// Pinned deps with rollup\nfunc TestSyncUpgradeAURPinnedSplitPackage(t *testing.T) {\n\tt.Parallel()\n\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\tpacmanBin := t.TempDir() + \"/pacman\"\n\ttmpDir := t.TempDir()\n\tgitBin := t.TempDir() + \"/git\"\n\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tf, err = os.OpenFile(gitBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\trequire.NoError(t, err)\n\trequire.NoError(t, f.Close())\n\n\tpkgBuildDir := tmpDir + \"/vosk-api\"\n\tos.Mkdir(pkgBuildDir, 0o755)\n\tfSource, err := os.OpenFile(pkgBuildDir+\"/.SRCINFO\", os.O_RDWR|os.O_CREATE, 0o666)\n\trequire.NoError(t, err)\n\tn, errF := fSource.WriteString(`pkgbase = vosk-api\n\tpkgdesc = Offline speech recognition toolkit\n\tpkgver = 0.3.45\n\tpkgrel = 1\n\turl = https://alphacephei.com/vosk/\n\tarch = x86_64\n\tlicense = Apache\n\npkgname = vosk-api\n\tpkgdesc = vosk-api\n\npkgname = python-vosk\n\tpkgdesc = Python module for vosk-api\n\tdepends = vosk-api=0.3.45`)\n\trequire.NoError(t, errF)\n\trequire.Greater(t, n, 0)\n\trequire.NoError(t, fSource.Close())\n\n\ttars := []string{\n\t\ttmpDir + \"/vosk-api-0.3.45-1-x86_64.pkg.tar.zst\",\n\t\ttmpDir + \"/python-vosk-0.3.45-1-x86_64.pkg.tar.zst\",\n\t}\n\n\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\treturn strings.Join(tars, \"\\n\"), \"\", nil\n\t}\n\n\tonce := sync.Once{}\n\n\tshowOverride := func(cmd *exec.Cmd) error {\n\t\tonce.Do(func() {\n\t\t\tfor _, tar := range tars {\n\t\t\t\tf, err := os.OpenFile(tar, os.O_RDONLY|os.O_CREATE, 0o666)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\trequire.NoError(t, f.Close())\n\t\t\t}\n\t\t})\n\t\tif sanitizeCall(cmd.String(), tmpDir, makepkgBin,\n\t\t\tpacmanBin, gitBin) == \"pacman -U --config /etc/pacman.conf -- /testdir/vosk-api-0.3.45-1-x86_64.pkg.tar.zst\" {\n\t\t\treturn errors.New(\"Unsatisfied dependency\")\n\t\t}\n\t\treturn nil\n\t}\n\n\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\tcmdBuilder := &exe.CmdBuilder{\n\t\tMakepkgBin:       makepkgBin,\n\t\tSudoBin:          \"su\",\n\t\tPacmanBin:        pacmanBin,\n\t\tPacmanConfigPath: \"/etc/pacman.conf\",\n\t\tGitBin:           \"git\",\n\t\tRunner:           mockRunner,\n\t\tSudoLoopEnabled:  false,\n\t}\n\n\tcmdArgs := parser.MakeArguments()\n\tcmdArgs.AddArg(\"S\")\n\tcmdArgs.AddArg(\"y\")\n\tcmdArgs.AddArg(\"u\")\n\n\tdb := &mock.DBExecutor{\n\t\tAlpmArchitecturesFn: func() ([]string, error) {\n\t\t\treturn []string{\"x86_64\"}, nil\n\t\t},\n\t\tRefreshHandleFn: func() error {\n\t\t\treturn nil\n\t\t},\n\t\tReposFn: func() []string {\n\t\t\treturn []string{\"core\"}\n\t\t},\n\t\tSyncSatisfierFn: func(s string) mock.IPackage {\n\t\t\treturn nil\n\t\t},\n\t\tInstalledRemotePackagesFn: func() map[string]alpm.Package {\n\t\t\treturn map[string]alpm.Package{\n\t\t\t\t\"vosk-api\": &mock.Package{\n\t\t\t\t\tPName:    \"vosk-api\",\n\t\t\t\t\tPVersion: \"0.3.43-1\",\n\t\t\t\t\tPBase:    \"vosk-api\",\n\t\t\t\t\tPReason:  alpm.PkgReasonDepend,\n\t\t\t\t},\n\t\t\t\t\"python-vosk\": &mock.Package{\n\t\t\t\t\tPName:    \"python-vosk\",\n\t\t\t\t\tPVersion: \"0.3.43-1\",\n\t\t\t\t\tPBase:    \"python-vosk\",\n\t\t\t\t\tPReason:  alpm.PkgReasonExplicit,\n\t\t\t\t\t// TODO: fix mock Depends\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t\tInstalledRemotePackageNamesFn: func() []string {\n\t\t\treturn []string{\"vosk-api\", \"python-vosk\"}\n\t\t},\n\t\tLocalSatisfierExistsFn: func(s string) bool {\n\t\t\treturn false\n\t\t},\n\t\tSyncUpgradesFn: func(\n\t\t\tbool,\n\t\t) (map[string]db.SyncUpgrade, error) {\n\t\t\treturn map[string]db.SyncUpgrade{}, nil\n\t\t},\n\t}\n\n\trun := &runtime.Runtime{\n\t\tCfg: &settings.Configuration{\n\t\t\tDoubleConfirm: true,\n\t\t\tRemoveMake:    \"no\",\n\t\t\tBuildDir:      tmpDir,\n\t\t},\n\t\tLogger:     text.NewLogger(io.Discard, os.Stderr, strings.NewReader(\"\\n\\n\\n\\n\"), true, \"test\"),\n\t\tCmdBuilder: cmdBuilder,\n\t\tVCSStore:   &vcs.Mock{},\n\t\tAURClient: &mockaur.MockAUR{\n\t\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\t\treturn []aur.Pkg{\n\t\t\t\t\t{\n\t\t\t\t\t\tName:        \"vosk-api\",\n\t\t\t\t\t\tPackageBase: \"vosk-api\",\n\t\t\t\t\t\tVersion:     \"0.3.45-1\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tName:        \"python-vosk\",\n\t\t\t\t\t\tPackageBase: \"vosk-api\",\n\t\t\t\t\t\tVersion:     \"0.3.45-1\",\n\t\t\t\t\t\tDepends: []string{\n\t\t\t\t\t\t\t\"vosk-api=0.3.45\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}, nil\n\t\t\t},\n\t\t},\n\t}\n\n\terr = handleCmd(context.Background(), run, cmdArgs, db)\n\trequire.NoError(t, err)\n\n\twantCapture := []string{\n\t\t\"/usr/bin/git -C /testdir/vosk-api reset --hard HEAD\",\n\t\t\"/usr/bin/git -C /testdir/vosk-api merge --no-edit --ff\",\n\t\t\"makepkg --packagelist\",\n\t\t\"makepkg --packagelist\",\n\t}\n\twantShow := []string{\n\t\t\"pacman -S -y --config /etc/pacman.conf --\",\n\t\t\"makepkg --verifysource --skippgpcheck -f -Cc\", \"makepkg --nobuild -f -C --ignorearch\",\n\t\t\"makepkg -c --nobuild --noextract --ignorearch\",\n\t\t\"pacman -U --config /etc/pacman.conf -- /testdir/vosk-api-0.3.45-1-x86_64.pkg.tar.zst\",\n\t\t\"makepkg --nobuild -f -C --ignorearch\", \"makepkg -c --nobuild --noextract --ignorearch\",\n\t\t\"pacman -U --config /etc/pacman.conf -- /testdir/vosk-api-0.3.45-1-x86_64.pkg.tar.zst /testdir/python-vosk-0.3.45-1-x86_64.pkg.tar.zst\",\n\t\t\"pacman -D -q --asdeps --config /etc/pacman.conf -- vosk-api\",\n\t\t\"pacman -D -q --asexplicit --config /etc/pacman.conf -- python-vosk\",\n\t}\n\n\trequire.Len(t, mockRunner.ShowCalls, len(wantShow),\n\t\tfmt.Sprintf(\"%#v\", sanitizeCalls(mockRunner.ShowCalls, tmpDir, makepkgBin, pacmanBin, gitBin)))\n\trequire.Len(t, mockRunner.CaptureCalls, len(wantCapture),\n\t\tfmt.Sprintf(\"%#v\", sanitizeCalls(mockRunner.CaptureCalls, tmpDir, makepkgBin, pacmanBin, gitBin)))\n\n\tfor i, call := range mockRunner.ShowCalls {\n\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\tshow = strings.ReplaceAll(show, tmpDir, \"/testdir\") // replace the temp dir with a static path\n\t\tshow = strings.ReplaceAll(show, makepkgBin, \"makepkg\")\n\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\t\tshow = strings.ReplaceAll(show, gitBin, \"git\")\n\n\t\t// options are in a different order on different systems and on CI root user is used\n\t\tassert.Subset(t, strings.Split(show, \" \"), strings.Split(wantShow[i], \" \"), fmt.Sprintf(\"%d - %s\", i, show))\n\t}\n}\n\nfunc sanitizeCalls(calls []exe.Call, tmpDir, makepkg, pacman, git string) []string {\n\tsan := make([]string, 0, len(calls))\n\tfor _, c := range calls {\n\t\ts := c.Args[0].(*exec.Cmd).String()\n\t\tsan = append(san, sanitizeCall(s, tmpDir, makepkg, pacman, git))\n\t}\n\n\treturn san\n}\n\nfunc sanitizeCall(s, tmpDir, makepkg, pacman, git string) string {\n\t_, after, found := strings.Cut(s, makepkg)\n\tif found {\n\t\ts = \"makepkg\" + after\n\t}\n\n\t_, after, found = strings.Cut(s, pacman)\n\tif found {\n\t\ts = \"pacman\" + after\n\t}\n\n\t_, after, found = strings.Cut(s, git)\n\tif found {\n\t\ts = \"git\" + after\n\t}\n\n\ts = strings.ReplaceAll(s, tmpDir, \"/testdir\")\n\n\treturn s\n}\n\nfunc TestSyncUpgrade_NoCombinedUpgrade(t *testing.T) {\n\tt.Parallel()\n\n\ttestCases := []struct {\n\t\tname            string\n\t\tcombinedUpgrade bool\n\t\twant            []string\n\t}{\n\t\t{\n\t\t\tname:            \"combined upgrade\",\n\t\t\tcombinedUpgrade: true,\n\t\t\twant:            []string{\"pacman -S -y -u --config /etc/pacman.conf --\"},\n\t\t},\n\t\t{\n\t\t\tname:            \"no combined upgrade\",\n\t\t\tcombinedUpgrade: false,\n\t\t\twant:            []string{\"pacman -S -y --config /etc/pacman.conf --\"},\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tmakepkgBin := t.TempDir() + \"/makepkg\"\n\t\t\tpacmanBin := t.TempDir() + \"/pacman\"\n\t\t\tgitBin := t.TempDir() + \"/git\"\n\t\t\tf, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\t\t\trequire.NoError(t, err)\n\t\t\trequire.NoError(t, f.Close())\n\n\t\t\tf, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\t\t\trequire.NoError(t, err)\n\t\t\trequire.NoError(t, f.Close())\n\n\t\t\tf, err = os.OpenFile(gitBin, os.O_RDONLY|os.O_CREATE, 0o755)\n\t\t\trequire.NoError(t, err)\n\t\t\trequire.NoError(t, f.Close())\n\n\t\t\tcaptureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {\n\t\t\t\treturn \"\", \"\", nil\n\t\t\t}\n\n\t\t\tshowOverride := func(cmd *exec.Cmd) error {\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tmockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}\n\t\t\tcmdBuilder := &exe.CmdBuilder{\n\t\t\t\tMakepkgBin:       makepkgBin,\n\t\t\t\tSudoBin:          \"su\",\n\t\t\t\tPacmanBin:        pacmanBin,\n\t\t\t\tPacmanConfigPath: \"/etc/pacman.conf\",\n\t\t\t\tGitBin:           \"git\",\n\t\t\t\tRunner:           mockRunner,\n\t\t\t\tSudoLoopEnabled:  false,\n\t\t\t}\n\n\t\t\tcmdArgs := parser.MakeArguments()\n\t\t\tcmdArgs.AddArg(\"S\")\n\t\t\tcmdArgs.AddArg(\"y\")\n\t\t\tcmdArgs.AddArg(\"u\")\n\n\t\t\tdb := &mock.DBExecutor{\n\t\t\t\tAlpmArchitecturesFn: func() ([]string, error) {\n\t\t\t\t\treturn []string{\"x86_64\"}, nil\n\t\t\t\t},\n\t\t\t\tRefreshHandleFn: func() error {\n\t\t\t\t\treturn nil\n\t\t\t\t},\n\t\t\t\tReposFn: func() []string {\n\t\t\t\t\treturn []string{\"core\"}\n\t\t\t\t},\n\t\t\t\tInstalledRemotePackagesFn: func() map[string]alpm.Package {\n\t\t\t\t\treturn map[string]alpm.Package{}\n\t\t\t\t},\n\t\t\t\tInstalledRemotePackageNamesFn: func() []string {\n\t\t\t\t\treturn []string{}\n\t\t\t\t},\n\t\t\t\tSyncUpgradesFn: func(\n\t\t\t\t\tbool,\n\t\t\t\t) (map[string]db.SyncUpgrade, error) {\n\t\t\t\t\treturn map[string]db.SyncUpgrade{}, nil\n\t\t\t\t},\n\t\t\t}\n\n\t\t\trun := &runtime.Runtime{\n\t\t\t\tCfg: &settings.Configuration{\n\t\t\t\t\tRemoveMake:      \"no\",\n\t\t\t\t\tCombinedUpgrade: false,\n\t\t\t\t},\n\t\t\t\tLogger:     text.NewLogger(io.Discard, os.Stderr, strings.NewReader(\"1\\n\"), true, \"test\"),\n\t\t\t\tCmdBuilder: cmdBuilder,\n\t\t\t\tVCSStore:   &vcs.Mock{},\n\t\t\t\tAURClient: &mockaur.MockAUR{\n\t\t\t\t\tGetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {\n\t\t\t\t\t\treturn []aur.Pkg{}, nil\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\n\t\t\terr = handleCmd(context.Background(), run, cmdArgs, db)\n\t\t\trequire.NoError(t, err)\n\n\t\t\trequire.Len(t, mockRunner.ShowCalls, len(tc.want))\n\t\t\trequire.Len(t, mockRunner.CaptureCalls, 0)\n\n\t\t\tfor i, call := range mockRunner.ShowCalls {\n\t\t\t\tshow := call.Args[0].(*exec.Cmd).String()\n\t\t\t\tshow = strings.ReplaceAll(show, pacmanBin, \"pacman\")\n\n\t\t\t\t// options are in a different order on different systems and on CI root user is used\n\t\t\t\tassert.Subset(t, strings.Split(show, \" \"), strings.Split(tc.want[i], \" \"), fmt.Sprintf(\"%d - %s\", i, show))\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "testdata/cephbin/.SRCINFO",
    "content": "pkgbase = ceph-bin\n\tpkgdesc = Distributed, fault-tolerant storage platform delivering object, block, and file system\n\tpkgver = 17.2.6\n\tpkgrel = 2\n\turl = https://ceph.com/\n\tarch = x86_64\n\tlicense = GPL\n\tnoextract = ceph-17.2.6-2.tar.zst\n\tnoextract = ceph-libs-17.2.6-2.tar.zst\n\toptions = emptydirs\n\tsource = ceph-17.2.6-2.tar.zst::https://github.com/bazaah/aur-ceph/releases/download/v17.2.6-2/ceph_linux_x86_64.tar.zstd\n\tsource = ceph-libs-17.2.6-2.tar.zst::https://github.com/bazaah/aur-ceph/releases/download/v17.2.6-2/ceph_libs_linux_x86_64.tar.zstd\n\tsha512sums = db38d454ef9fda99fbe9a0954ccb4a8a7b66537f5cb1998dd552161049a6750a82a218d6e95f2bbc2a501637bf13f2f2d0fd6a12b367733cd294364722ba236c\n\tsha512sums = 2218b8d81ce8b94daa63ebd7674bd6d8e3da047ad46bbde1e1666eaa10d429a329ad1e6fa43d9f9d07ba5ce06b57dcc442ca3269eb482bffbb1c25d247d2ba1b\n\tsha512sums = 029f5fd11f30800a78fdc1e4c6541c413be498b284271ef93886268fd47002f6505df698c64a8118f1c2dcef22081c4fcc79e6047db7202d66f2e3e132830742\n\npkgname = ceph-bin\n\tdepends = ceph-libs=17.2.6-2\n\tdepends = dep1\n\tdepends = dep2\n\tprovides = ceph=17.2.6-2\n\tconflicts = ceph\n\npkgname = ceph-libs-bin\n\tdepends = dep1\n\tdepends = curl\n\tprovides = ceph-libs=17.2.6-2\n\tconflicts = ceph-libs\n\n"
  },
  {
    "path": "testdata/cephbin/PKGBUILD",
    "content": ""
  },
  {
    "path": "testdata/gourou/.SRCINFO",
    "content": "pkgbase = gourou\n\tpkgdesc = Download and decrypt adobe encrypted (acsm) pdf and epub files\n\tpkgver = 0.8.1\n\tpkgrel = 4\n\turl = https://indefero.soutade.fr/p/libgourou\n\tarch = x86_64\n\tlicense = LGPL3\n\tdepends = glibc\n\tdepends = gcc-libs\n\tdepends = zlib\n\tdepends = libzip\n\tdepends = openssl\n\tdepends = pugixml\n\tdepends = curl\n\tprovides = gourou=0.8.1\n\tprovides = libgourou=0.8.1\n\tconflicts = gourou-git\n\tconflicts = gourou-bin\n\toptions = strip\n\tsource = git://soutade.fr/libgourou.git#tag=v0.8.1\n\tsource = git://soutade.fr/updfparser.git#commit=a421098092ba600fb1686a7df8fc58cd67429f59\n\tsource = build.patch\n\tsha512sums = SKIP\n\tsha512sums = SKIP\n\tsha512sums = 768e49fddcabe8b4c6f771ebbddf2618ab59e7b1a399d99aa9a9881f932e092210878ef576144593684b4c3a763218c5b546dbe19fdbadeff13995245bffda19\n\npkgname = gourou\n"
  },
  {
    "path": "testdata/gourou/PKGBUILD",
    "content": ""
  },
  {
    "path": "testdata/jfin/.SRCINFO",
    "content": "pkgbase = jellyfin\n\tpkgdesc = The Free Software Media System\n\tpkgver = 10.8.4\n\tpkgrel = 1\n\turl = https://github.com/jellyfin/jellyfin\n\tarch = i686\n\tarch = x86_64\n\tarch = armv6h\n\tlicense = GPL2\n\tmakedepends = dotnet-sdk>=6\n\tmakedepends = dotnet-sdk<7\n\tmakedepends = nodejs\n\tmakedepends = npm\n\tmakedepends = git\n\tsource = jellyfin-10.8.4.tar.gz::https://github.com/jellyfin/jellyfin/archive/v10.8.4.tar.gz\n\tsource = jellyfin-web-10.8.4.tar.gz::https://github.com/jellyfin/jellyfin-web/archive/v10.8.4.tar.gz\n\tsource = jellyfin.conf\n\tsource = jellyfin.service\n\tsource = jellyfin.sysusers\n\tsource = jellyfin.tmpfiles\n\tsha512sums = cf472f36a759a7eb3724dac79d3bd2d6c9c58fc375293ad6eb8b5ce1ea1a8f6dd296cc36113b80b1c705a99eafb2bd9ffd9381fd52fa19aa12018d50656c9bde\n\tsha512sums = 21983940689475de7f9d37a1016fb2dd740986ac27ffa2e0eac0bc9c84d68ac557fdc8afb64ca70b867af2d1e438293b98d5c155da402d3e985ab831042ba176\n\tsha512sums = 2aa97a1a7a8a447171b59be3e93183e09cbbc32c816843cc47c6777b9aec48bd9c1d9d354f166e0b000ad8d2e94e6e4b0559aa52e5c159abbc103ed2c5afa3f0\n\tsha512sums = 99d02080b1b92e731250f39ddd13ceca7129d69d0c05e0939620cbc3f499a9574668c63fa889704a4905560888131e980d7ab1fbcc5837b04d33ce26daa9d42b\n\tsha512sums = 6fc2638e6ec4b1ee0240e17815c91107b694e5fde72c1bc7956c83067bbeacb632de899b86837e47a0ec04288131b15c20746373b45e0669c8976069a55d627a\n\tsha512sums = 45a62b62d97b9a83289d4dfde684163b1bcf340c1921fb958e5a701812c61b392901841940c67e5fa5148783277d5b4dc65ba01d3a22e8f855ea62154ad9be33\n\npkgname = jellyfin\n\tdepends = jellyfin-web=10.8.4\n\tdepends = jellyfin-server=10.8.4\n\npkgname = jellyfin-web\n\tpkgdesc = Jellyfin web client\n\npkgname = jellyfin-server\n\tpkgdesc = Jellyfin server component\n\tdepends = dotnet-runtime>=6\n\tdepends = dotnet-runtime<7\n\tdepends = aspnet-runtime>=6\n\tdepends = aspnet-runtime<7\n\tdepends = ffmpeg\n\tdepends = sqlite\n\tbackup = etc/conf.d/jellyfin\n"
  },
  {
    "path": "testdata/jfin/PKGBUILD",
    "content": ""
  },
  {
    "path": "testdata/libzip-git/.SRCINFO",
    "content": "pkgbase = libzip-git\n\tpkgdesc = C library for reading, creating, and modifying zip archives\n\tpkgver = 1.9.2.r144.gdadb14d5\n\tpkgrel = 1\n\turl = https://libzip.org/\n\tarch = i686\n\tarch = x86_64\n\tlicense = BSD\n\tmakedepends = git\n\tmakedepends = cmake\n\tdepends = glibc\n\tdepends = bzip2\n\tdepends = gnutls\n\tdepends = openssl\n\tdepends = xz\n\tdepends = zlib\n\tdepends = zstd\n\tprovides = libzip=1.9.2.r144.gdadb14d5\n\tconflicts = libzip\n\tsource = git+https://github.com/nih-at/libzip.git\n\tsha256sums = SKIP\n\npkgname = libzip-git\n"
  },
  {
    "path": "testdata/libzip-git/PKGBUILD",
    "content": ""
  },
  {
    "path": "testdata/pacman.conf",
    "content": "#\n# /etc/pacman.conf\n#\n# See the pacman.conf(5) manpage for option and repository directives\n\n#\n# GENERAL OPTIONS\n#\n[options]\n# The following paths are commented out with their default values listed.\n# If you wish to use different paths, uncomment and update the paths.\nRootDir     = /\nDBPath      = /var/lib/pacman/\nCacheDir    = /var/cache/pacman/pkg/\nLogFile     = /var/log/pacman.log\nGPGDir      = /etc/pacman.d/gnupg/\nHookDir     = /etc/pacman.d/hooks/\nHoldPkg     = pacman glibc\n#XferCommand = /usr/bin/curl -L -C - -f -o %o %u\nXferCommand = /usr/bin/wget --passive-ftp -c -O %o %u\nCleanMethod = KeepInstalled\nArchitecture = auto\n\n# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup\nIgnorePkg   = xorm\nIgnoreGroup = yorm\n\n#NoUpgrade   =\n#NoExtract   =\n\n# Misc options\nUseSyslog\nColor\nNoProgressBar\nCheckSpace\nVerbosePkgLists\nParallelDownloads = 5\n\n# By default, pacman accepts packages signed by keys that its local keyring\n# trusts (see pacman-key and its man page), as well as unsigned packages.\nSigLevel    = Required DatabaseOptional\nLocalFileSigLevel = Optional\nRemoteFileSigLevel = Required\n\n# NOTE: You must run `pacman-key --init` before first using pacman; the local\n# keyring can then be populated with the keys of all official Arch Linux\n# packagers with `pacman-key --populate archlinux`.\n\n#\n# REPOSITORIES\n#   - can be defined here or included from another file\n#   - pacman will search repositories in the order defined here\n#   - local/custom mirrors can be added here or in separate files\n#   - repositories listed first will take precedence when packages\n#     have identical names, regardless of version number\n#   - URLs will have $repo replaced by the name of the current repo\n#   - URLs will have $arch replaced by the name of the architecture\n#\n# Repository entries are of the format:\n#       [repo-name]\n#       Server = ServerName\n#       Include = IncludePath\n#\n# The header [repo-name] is crucial - it must be present and\n# uncommented to enable the repo.\n#\n\n# The testing repositories are disabled by default. To enable, uncomment the\n# repo name header and Include lines. You can add preferred servers immediately\n# after the header, and they will be used before the default mirrors.\n\n#[core-testing]\n#Include = /etc/pacman.d/mirrorlist\n\n[core]\nServer = Core\n\n#[extra-testing]\n#Include = /etc/pacman.d/mirrorlist\n\n[extra]\nServer = Extra\n\n# If you want to run 32 bit applications on your x86_64 system,\n# enable the multilib repositories as required here.\n\n#[multilib-testing]\n#Include = /etc/pacman.d/mirrorlist\n\n[multilib]\nServer = repo3\nServer = multilib\n# An example of a custom package repository.  See the pacman manpage for\n# tips on creating your own repositories.\n#[custom]\n#SigLevel = Optional TrustAll\n#Server = file:///home/custompkgs\n"
  },
  {
    "path": "vcs.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"sync\"\n\n\t\"github.com/Jguer/aur\"\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/db\"\n\t\"github.com/Jguer/yay/v12/pkg/dep\"\n\t\"github.com/Jguer/yay/v12/pkg/runtime\"\n\t\"github.com/Jguer/yay/v12/pkg/sync/srcinfo\"\n\t\"github.com/Jguer/yay/v12/pkg/sync/workdir\"\n)\n\nfunc infoToInstallInfo(info []aur.Pkg) []map[string]*dep.InstallInfo {\n\tinstallInfo := make([]map[string]*dep.InstallInfo, 1)\n\tinstallInfo[0] = map[string]*dep.InstallInfo{}\n\n\tfor i := range info {\n\t\tpkg := &info[i]\n\t\tinstallInfo[0][pkg.Name] = &dep.InstallInfo{\n\t\t\tAURBase: &pkg.PackageBase,\n\t\t\tSource:  dep.AUR,\n\t\t}\n\t}\n\n\treturn installInfo\n}\n\n// createDevelDB forces yay to create a DB of the existing development packages.\nfunc createDevelDB(ctx context.Context, run *runtime.Runtime, dbExecutor db.Executor) error {\n\tremoteNames := dbExecutor.InstalledRemotePackageNames()\n\n\trun.QueryBuilder.Execute(ctx, dbExecutor, remoteNames)\n\tinfo, err := run.AURClient.Get(ctx, &aur.Query{\n\t\tNeedles:  remoteNames,\n\t\tBy:       aur.Name,\n\t\tContains: false,\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tpreper := workdir.NewPreparerWithoutHooks(dbExecutor, run.CmdBuilder, run.Cfg, run.Logger.Child(\"workdir\"), false)\n\n\tmapInfo := infoToInstallInfo(info)\n\tpkgBuildDirsByBase, err := preper.Run(ctx, run, mapInfo)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tsrcinfos, err := srcinfo.ParseSrcinfoFilesByBase(run.Logger.Child(\"srcinfo\"), pkgBuildDirsByBase, false)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar wg sync.WaitGroup\n\tfor i := range srcinfos {\n\t\tfor iP := range srcinfos[i].Packages {\n\t\t\twg.Add(1)\n\n\t\t\tgo func(baseIndex string, packageIndex int) {\n\t\t\t\trun.VCSStore.Update(ctx, srcinfos[baseIndex].Packages[packageIndex].Pkgname, srcinfos[baseIndex].Source)\n\t\t\t\twg.Done()\n\t\t\t}(i, iP)\n\t\t}\n\t}\n\n\twg.Wait()\n\trun.Logger.OperationInfoln(gotext.Get(\"GenDB finished. No packages were installed\"))\n\n\treturn nil\n}\n"
  },
  {
    "path": "vote.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"errors\"\n\n\t\"github.com/Jguer/aur\"\n\t\"github.com/Jguer/votar/pkg/vote\"\n\t\"github.com/leonelquinteros/gotext\"\n\n\t\"github.com/Jguer/yay/v12/pkg/text\"\n)\n\ntype ErrAURVote struct {\n\tinner   error\n\tpkgName string\n}\n\nfunc (e *ErrAURVote) Error() string {\n\treturn gotext.Get(\"Unable to handle package vote for: %s. err: %s\", e.pkgName, e.inner.Error())\n}\n\nfunc handlePackageVote(ctx context.Context,\n\ttargets []string, aurClient aur.QueryClient, logger *text.Logger,\n\tvoteClient *vote.Client, upvote bool,\n) error {\n\tinfos, err := aurClient.Get(ctx, &aur.Query{\n\t\tNeedles: targets,\n\t\tBy:      aur.Name,\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif len(infos) == 0 {\n\t\tlogger.Println(gotext.Get(\" there is nothing to do\"))\n\t\treturn nil\n\t}\n\n\tfor i := range infos {\n\t\tvar err error\n\t\tif upvote {\n\t\t\terr = voteClient.Vote(ctx, infos[i].PackageBase)\n\t\t} else {\n\t\t\terr = voteClient.Unvote(ctx, infos[i].PackageBase)\n\t\t}\n\n\t\tif err != nil {\n\t\t\tif errors.Is(err, vote.ErrNoCredentials) {\n\t\t\t\treturn errors.New(\n\t\t\t\t\tgotext.Get(\"%s: please set AUR_USERNAME and AUR_PASSWORD environment variables for voting\",\n\t\t\t\t\t\terr.Error()))\n\t\t\t}\n\n\t\t\treturn &ErrAURVote{inner: err, pkgName: infos[i].Name}\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  }
]