[
  {
    "path": ".ci/docker-ci/alma/Dockerfile",
    "content": "FROM almalinux:8\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nRUN dnf -y update \\\n  && dnf install -y \\\n    # Direct dependencies:\n    bash \\\n    gawk \\\n    git \\\n    gnupg \\\n    # Assumed to be present:\n    diffutils \\\n    file \\\n    findutils \\\n    procps \\\n    make \\\n  && dnf clean all \\\n  && rm -rf /var/cache/yum\n"
  },
  {
    "path": ".ci/docker-ci/alpine/Dockerfile",
    "content": "FROM alpine:3.23.3\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\n# Don't install coreutils on Alpine,\n# so we get busybox versions of ps, stat, and ls. See #475\nRUN apk add --no-cache --update \\\n  # Direct dependencies:\n  bash \\\n  gawk \\\n  git \\\n  gnupg \\\n  # Assumed to be present:\n  file \\\n  make \\\n  procps\n"
  },
  {
    "path": ".ci/docker-ci/arch/Dockerfile",
    "content": "FROM archlinux:base-20220529.0.58327\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nRUN pacman -Syu --needed --noconfirm \\\n  # Direct dependencies:\n  bash \\\n  gawk \\\n  git \\\n  gnupg \\\n  # Assumed to be present:\n  diffutils \\\n  file \\\n  make \\\n  procps\n\n"
  },
  {
    "path": ".ci/docker-ci/debian-gnupg1/Dockerfile",
    "content": "FROM debian:13.3-slim\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nENV DEBIAN_FRONTEND='noninteractive'\nENV SECRETS_GPG_COMMAND='gpg1'\n\nRUN apt-get update \\\n  && apt-get install --no-install-recommends -y \\\n    # Direct dependencies:\n    gawk \\\n    git \\\n    gnupg1 \\\n    # Assumed to be present:\n    file \\\n    procps \\\n    make \\\n  # Cleaning cache:\n  && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \\\n  && apt-get clean -y && rm -rf /var/lib/apt/lists/*\n"
  },
  {
    "path": ".ci/docker-ci/debian-gnupg2/Dockerfile",
    "content": "FROM debian:13.3-slim\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nENV DEBIAN_FRONTEND='noninteractive'\n\nRUN apt-get update \\\n  && apt-get install --no-install-recommends -y \\\n    # Direct dependencies:\n    gawk \\\n    git \\\n    gnupg \\\n    # Assumed to be present:\n    file \\\n    procps \\\n    make \\\n  # Cleaning cache:\n  && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \\\n  && apt-get clean -y && rm -rf /var/lib/apt/lists/*\n"
  },
  {
    "path": ".ci/docker-ci/fedora/Dockerfile",
    "content": "FROM fedora:43\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nRUN dnf -y update \\\n  && dnf install -y \\\n    # Direct dependencies:\n    bash \\\n    gawk \\\n    git \\\n    gnupg \\\n    # Assumed to be present:\n    diffutils \\\n    file \\\n    findutils \\\n    procps \\\n    make \\\n  && dnf clean all \\\n  && rm -rf /var/cache/yum\n"
  },
  {
    "path": ".ci/docker-ci/rocky/Dockerfile",
    "content": "FROM rockylinux:8\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nRUN dnf -y update \\\n  && dnf install -y \\\n    # Direct dependencies:\n    bash \\\n    gawk \\\n    git \\\n    gnupg \\\n    # Assumed to be present:\n    diffutils \\\n    file \\\n    findutils \\\n    procps \\\n    make \\\n  && dnf clean all \\\n  && rm -rf /var/cache/yum\n"
  },
  {
    "path": ".ci/docker-ci/ubuntu/Dockerfile",
    "content": "FROM ubuntu:24.04\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nENV DEBIAN_FRONTEND=\"noninteractive\"\n\nRUN apt-get update \\\n  && apt-get install --no-install-recommends -y \\\n    # Direct dependencies:\n    gawk \\\n    git \\\n    gnupg \\\n    # Assumed to be present:\n    file \\\n    procps \\\n    make \\\n  # Cleaning cache:\n  && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \\\n  && apt-get clean -y && rm -rf /var/lib/apt/lists/*\n"
  },
  {
    "path": ".ci/github_release_script.sh",
    "content": "#!/usr/bin/env sh\n\nset -e\n\n# Installing additional deps:\napk add --no-cache curl jq\n\n# https://gist.github.com/Jaskaranbir/d5b065173b3a6f164e47a542472168c1\nUSER=\"$(echo \"$GITHUB_REPOSITORY\" | cut -d \"/\" -f1)\"\nPROJECT=\"$(echo \"$GITHUB_REPOSITORY\" | cut -d \"/\" -f2)\"\n\nLAST_RELEASE_TAG=$(curl \\\n    --header \"authorization: Bearer $GITHUB_TOKEN\" \\\n    --url \"https://api.github.com/repos/$GITHUB_REPOSITORY/releases/latest\" \\\n  | jq .tag_name | sed 's/\"//g'\n)\necho \"LAST_RELEASE_TAG=$LAST_RELEASE_TAG\"\nif [ \"$LAST_RELEASE_TAG\" = 'null' ]; then\n  # Most likely, we are facing rate-limiting problems,\n  # just try again later.\n  exit 1\nfi\n\nNEW_CHANGELOG='CHANGELOG-RELEASE.md'\n\n# Generate new CHANGELOG.md with just the last changes\ngithub_changelog_generator \\\n  --user \"$USER\" \\\n  --project \"$PROJECT\" \\\n  --token \"$GITHUB_OAUTH_TOKEN\" \\\n  --since-tag \"$LAST_RELEASE_TAG\" \\\n  --max-issues 100 \\\n  --no-issues \\\n  --release-branch 'master' \\\n  --token \"$GITHUB_TOKEN\" \\\n  --output \"$NEW_CHANGELOG\"\n\necho 'Done! Changelog:'\ncat \"$NEW_CHANGELOG\"\n"
  },
  {
    "path": ".ci/release-ci/alma/Dockerfile",
    "content": "FROM almalinux:8\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nRUN dnf -y update \\\n  && dnf install -y \\\n    # Required for our install script:\n    wget \\\n    sudo \\\n  && dnf clean all \\\n  && rm -rf /var/cache/yum\n"
  },
  {
    "path": ".ci/release-ci/alpine/Dockerfile",
    "content": "FROM alpine:3.23.3\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nRUN apk add --no-cache --update \\\n  # Required for our install script:\n  bash \\\n  wget\n"
  },
  {
    "path": ".ci/release-ci/debian/Dockerfile",
    "content": "FROM debian:13.3-slim\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nENV DEBIAN_FRONTEND='noninteractive'\n\nRUN apt-get update \\\n  && apt-get install --no-install-recommends -y \\\n    # Required to work with https-based repos and custom signed packages:\n    apt-transport-https \\\n    ca-certificates \\\n    # Required for our install script:\n    gnupg \\\n    sudo \\\n    wget \\\n  # Cleaning cache:\n  && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \\\n  && apt-get clean -y && rm -rf /var/lib/apt/lists/* \\\n  && adduser --disabled-password nonroot \\\n  && adduser nonroot sudo \\\n  && echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers\nUSER nonroot\n"
  },
  {
    "path": ".ci/release-ci/fedora/Dockerfile",
    "content": "FROM fedora:43\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nRUN dnf -y update \\\n  && dnf install -y \\\n    # Required for our install script:\n    wget \\\n    sudo \\\n  && dnf clean all \\\n  && rm -rf /var/cache/yum \\\n  && adduser --password='' -m nonroot \\\n  && echo 'nonroot ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers\nUSER nonroot\nWORKDIR /home/nonroot\n"
  },
  {
    "path": ".ci/release-ci/rocky/Dockerfile",
    "content": "FROM rockylinux:8\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nRUN dnf -y update \\\n  && dnf install -y \\\n    # Required for our install script:\n    wget \\\n    sudo \\\n  && dnf clean all \\\n  && rm -rf /var/cache/yum\n"
  },
  {
    "path": ".ci/release-ci/ubuntu/Dockerfile",
    "content": "FROM ubuntu:24.04\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nENV DEBIAN_FRONTEND='noninteractive'\n\nRUN apt-get update \\\n  && apt-get install --no-install-recommends -y \\\n    # Required to work with https-based repos and custom signed packages:\n    apt-transport-https \\\n    ca-certificates \\\n    # Required for our install script:\n    gnupg \\\n    sudo \\\n    wget \\\n  # Cleaning cache:\n  && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \\\n  && apt-get clean -y && rm -rf /var/lib/apt/lists/* \\\n  && adduser --disabled-password nonroot \\\n  && adduser nonroot sudo \\\n  && echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers\nUSER nonroot\n"
  },
  {
    "path": ".ci/releaser/alpine/Dockerfile",
    "content": "# Initially copied from\n# https://github.com/jordansissel/fpm/blob/master/Dockerfile\nFROM alpine:3.23.3\n\nSHELL [\"/bin/ash\", \"-eo\", \"pipefail\", \"-c\"]\n\nENV CODE_DIR='/code'\nENV SECRETS_PROJECT_ROOT=\"$CODE_DIR\"\nENV NFPM_VERSION='2.15.1'\n\nRUN apk add --no-cache --update \\\n    # fpm deps:\n    ruby \\\n    ruby-dev \\\n    gcc \\\n    libffi-dev \\\n    make \\\n    libc-dev \\\n    rpm \\\n    tar \\\n    # Direct dependencies:\n    bash \\\n    gawk \\\n    git \\\n    gnupg \\\n    # Assumed to be present:\n    curl \\\n    # envsubst for `nfpm`:\n    gettext \\\n  # Installing `nfpm`, it builds alpine packages:\n  && curl -sfL \"https://github.com/goreleaser/nfpm/releases/download/v${NFPM_VERSION}/nfpm_${NFPM_VERSION}_Linux_x86_64.tar.gz\" --output 'nfpm.tar.gz' \\\n  && tar -xf 'nfpm.tar.gz' nfpm \\\n  && mv nfpm '/usr/local/bin' \\\n  && chmod 755 '/usr/local/bin/nfpm' \\\n  && rm -rf 'nfpm.tar.gz' \\\n  # Installing `fpm`, it builds all other packages:\n  && gem install --no-document fpm\n\nWORKDIR $CODE_DIR\n"
  },
  {
    "path": ".editorconfig",
    "content": "# Check http://editorconfig.org for more information\n# This is the main config file for this project:\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\ntrim_trailing_whitespace = true\nend_of_line = lf\ninsert_final_newline = true\nindent_size = 2\n\n[Makefile]\nindent_style = tab\nindent_size = 4\n"
  },
  {
    "path": ".gitattributes",
    "content": "# Excluding from GitHub languages:\nvendor/ linguist-vendored\n\n# Excluding from GitHub diff:\n*.1 linguist-generated\n*.7 linguist-generated\n\n# Excluding from `git diff`:\n*.1 -diff\n*.7 -diff\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: wemake-services\nopen_collective: git-secret\ncustom: https://boosty.to/sobolevn\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "content": "<!-- Thanks for reporting an issue! Please make sure you click the link above to view the issue guidelines, then fill out the blanks below. -->\n\nWhat are the steps to reproduce this issue?\n-------------------------------------------\n1. …\n2. …\n3. …\n\nWhat happens?\n-------------\n…\n\nWhat were you expecting to happen?\n----------------------------------\n…\n\nAny logs, error output, etc?\n----------------------------\n(If it’s long, please paste to https://ghostbin.com/ and insert the link here.)\n\nAny other comments?\n-------------------\n…\n\nWhat versions of software are you using?\n----------------------------------------\n**Operating system:** (`uname -a`) …\n\n**`git-secret` path:** (`which git-secret`) …\n\n**`git-secret` version:** (`git secret --version`) …\n\n**`git` version:** (`git --version`) …\n\n**Shell type and version:** (`$SHELL --version`) …\n\n**`gpg` version:** (`gpg --version`) …\n\n<!-- Love git-secret? Please consider supporting our collective:\n👉  https://opencollective.com/git-secret/donate -->\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!-- Thanks for sending a pull request!\n\nHere's how it's done:\n0. If you are planning a large feature, please, discuss it first in a separate issue.\n   See also [CONTRIBUTING.md](https://github.com/sobolevn/git-secret/blob/master/CONTRIBUTING.md) if you haven't already.\n1. Make sure that you open your pull request against the `master` branch\n2. Make sure that your code has the same style as the surrounding code and git-secret in general\n3. Make sure your code passes using `shellcheck` with `make lint`\n4. You can also spell check your code using 'aspell -c {filename}'\n5. If you are adding or changing features, please add tests that cover the new behavior (in addition to the unchanged behavior if appropriate)\n6. Make sure that all tests pass\n7. Change the .md file(s) in man/man*/ to document your changes if appropriate\n   (regenerating man pages with 'make build-man' is optional)\n8. Add an entry to CHANGELOG.md explaining the change briefly and, if appropriate, referring to the related issue #\n\nPlease make sure you click the link above to view the contribution guidelines, then fill out the blanks below. -->\n\nWhat does this implement/fix? Explain your changes.\n---------------------------------------------------\n…\n\nDoes this close any currently open issues?\n------------------------------------------\n…\n\nAny relevant logs, error output, etc?\n-------------------------------------\n(If it’s long, please paste to https://ghostbin.com/ and insert the link here.)\n\nAny other comments?\n-------------------\n…\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "# GitHub-native dependabot setup, configuration:\n# https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/configuration-options-for-dependency-updates\nversion: 2\n\nupdates:\n\n# Docs and GitHub Actions:\n\n- package-ecosystem: bundler\n  directory: \"/docs\"\n  schedule:\n    interval: daily\n\n- package-ecosystem: github-actions\n  directory: \"/\"\n  schedule:\n    interval: daily\n\n# Our CI and release docker images:\n\n- package-ecosystem: docker\n  directory: \".ci/releaser/alpine\"\n  schedule:\n    interval: weekly\n\n# Release CI:\n\n- package-ecosystem: docker\n  directory: \".ci/release-ci/alpine\"\n  schedule:\n    interval: weekly\n\n- package-ecosystem: docker\n  directory: \".ci/release-ci/debian\"\n  schedule:\n    interval: weekly\n\n- package-ecosystem: docker\n  directory: \".ci/release-ci/ubuntu\"\n  schedule:\n    interval: weekly\n\n- package-ecosystem: docker\n  directory: \".ci/release-ci/centos\"\n  schedule:\n    interval: weekly\n\n- package-ecosystem: docker\n  directory: \".ci/release-ci/fedora\"\n  schedule:\n    interval: weekly\n\n# Docker CI:\n\n- package-ecosystem: docker\n  directory: \".ci/docker-ci/alpine\"\n  schedule:\n    interval: weekly\n\n- package-ecosystem: docker\n  directory: \".ci/docker-ci/debian-gnupg1\"\n  schedule:\n    interval: weekly\n\n- package-ecosystem: docker\n  directory: \".ci/docker-ci/debian-gnupg2\"\n  schedule:\n    interval: weekly\n\n- package-ecosystem: docker\n  directory: \".ci/docker-ci/ubuntu\"\n  schedule:\n    interval: weekly\n\n- package-ecosystem: docker\n  directory: \".ci/docker-ci/centos\"\n  schedule:\n    interval: weekly\n\n- package-ecosystem: docker\n  directory: \".ci/docker-ci/fedora\"\n  schedule:\n    interval: weekly\n"
  },
  {
    "path": ".github/workflows/build-man.yml",
    "content": "\nname: build-man\n\non:\n  push:\n    branches:\n      - master\n    paths:\n      - 'docs/**/*'\n      - '.github/workflows/build-man.yml'\n  pull_request:\n    paths:\n      - 'docs/**/*'\n      - '.github/workflows/build-man.yml'\n  workflow_dispatch:\n\nconcurrency: \n  group: ${{ github.head_ref || github.run_id }}-build-man\n  cancel-in-progress: true\n\njobs:\n  build-man:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v6\n    - name: Checks that manual generation works\n      run: make build-man\n"
  },
  {
    "path": ".github/workflows/github-pages.yml",
    "content": "name: github-pages\n\non:\n  push:\n    branches:\n      - master\n    paths:\n      - 'man/**/*'\n      - 'docs/**/*'\n      - 'utils/*/install.sh'\n\nconcurrency: \n  group: ${{ github.head_ref || github.run_id }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    steps:\n    - uses: actions/checkout@v6\n\n    - name: Build docs\n      run: make build-docs\n\n    - name: Deploy to Pages\n      uses: JamesIves/github-pages-deploy-action@v4.8.0\n      with:\n        token: ${{ secrets.GITHUB_TOKEN }}\n        branch: gh-pages # The branch the action should deploy to.\n        folder: docs # The folder the action should deploy.\n        clean: true # Automatically remove deleted files from the deploy branch\n"
  },
  {
    "path": ".github/workflows/release-ci.yml",
    "content": "name: release-ci\n\non:\n  workflow_dispatch:\n  schedule:\n    - cron: '0 0 * * *'\n\n  # In case we change the some build scripts:\n  push:\n    branches:\n      - master\n    paths:\n      - 'utils/**'\n      - '.ci/release-ci/**'\n      - 'Makefile'\n      - '.github/workflows/release-ci.yml'\n  pull_request:\n    paths:\n      - 'utils/**'\n      - '.ci/release-ci/**'\n      - 'Makefile'\n      - '.github/workflows/release-ci.yml'\n\nconcurrency:\n  group: ${{ github.head_ref || github.run_id }}\n  cancel-in-progress: true\n\njobs:\n  existing:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        include:\n          - release-type: deb\n            release-env: debian\n          - release-type: deb\n            release-env: ubuntu\n          - release-type: rpm\n            release-env: fedora\n          - release-type: rpm\n            release-env: rocky\n          - release-type: rpm\n            release-env: alma\n          - release-type: apk\n            release-env: alpine\n\n    steps:\n    - uses: actions/checkout@v6\n    - name: Run checks\n      run: |\n        SECRETS_RELEASE_ENV=\"${{ matrix.release-env }}\" \\\n        SECRETS_RELEASE_TYPE=\"${{ matrix.release-type }}\" \\\n        make release-ci\n\n  # Keep in sync with `release.yml`:\n  dryrun:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        release-type:\n          - apk\n          - deb\n          - rpm\n    steps:\n    - uses: actions/checkout@v6\n    - name: Run dry run of the release process\n      run: |\n        SECRETS_RELEASE_TYPE=\"${{ matrix.release-type }}\" \\\n        SECRETS_DEPLOY_DRY_RUN=1 \\\n        SECRETS_ARTIFACTORY_CREDENTIALS='fake' \\\n          make release\n\n  # https://github.community/t/run-github-actions-job-only-if-previous-job-has-failed/174786/2\n  create-issue-on-failure:\n    name: Create an issue if release-ci cron failed\n    runs-on: ubuntu-latest\n    needs: [existing, dryrun]\n    if: ${{ github.event_name == 'schedule' && github.repository == 'sobolevn/git-secret' && always() && (needs.existing.result == 'failure' || needs.dryrun.result == 'failure') }}\n    permissions:\n      issues: write\n    steps:\n      - uses: actions/github-script@v8\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          script: |\n            await github.rest.issues.create({\n              owner: \"sobolevn\",\n              repo: \"git-secret\",\n              title: `release-ci failure on ${new Date().toDateString()}`,\n              body: \"Details: https://github.com/sobolevn/git-secret/actions/workflows/release-ci.yml\",\n            })\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: release\n\non:\n  push:\n    tags:\n      - 'v*'\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.head_ref || github.run_id }}\n\njobs:\n  release-packages:\n    environment:\n      name: artifactory\n      url: https://gitsecret.jfrog.io/artifactory\n\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        release-type:\n          - apk\n          # - deb\n          # - rpm\n    steps:\n    - uses: actions/checkout@v6\n    - name: Run checks\n      run: SECRETS_RELEASE_TYPE=\"${{ matrix.release-type }}\" make release\n      env:\n        SECRETS_ARTIFACTORY_CREDENTIALS: ${{ secrets.SECRETS_ARTIFACTORY_CREDENTIALS }}\n\n  # github-release:\n  #   runs-on: ubuntu-latest\n  #   needs: ['release-packages']\n  #   steps:\n  #   - uses: actions/checkout@v6\n  #   - run: make changelog\n  #     env:\n  #       GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n  #   - uses: softprops/action-gh-release@v1\n  #     with:\n  #       # Generated above by `make changelog`:\n  #       body_path: CHANGELOG-RELEASE.md\n  #     env:\n  #       GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: test\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - 'docs/**'\n  pull_request:\n    paths-ignore:\n      - 'docs/**'\n  workflow_dispatch:\n\nconcurrency: \n  group: ${{ github.head_ref || github.run_id }}-test\n  cancel-in-progress: true\n\npermissions:\n  contents: read\n\njobs:\n  lint:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v6\n    - name: Shellcheck and Hadolint\n      run: make lint\n\n  docker-ci:\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        docker-env:\n          - alma\n          - alpine\n          #- arch           # disable arch testing for now, see #916\n          - debian-gnupg1  # We need to test legacy version of gnupg\n          - debian-gnupg2\n          - fedora\n          - rocky\n          - ubuntu\n    steps:\n    - uses: actions/checkout@v6\n    - name: Run checks\n      run: SECRETS_DOCKER_ENV=\"${{ matrix.docker-env }}\" make docker-ci\n\n  osx-ci:\n    runs-on: macos-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        test-verbose: [0, 1]\n    steps:\n    - uses: actions/checkout@v6\n    - name: Install deps\n      run: brew install gawk gnupg\n    - name: Run checks\n      run: SECRETS_TEST_VERBOSE=${{ matrix.test-verbose }} make test\n\n  freebsd-ci:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v6\n    - name: Run checks\n      id: test\n      uses: vmactions/freebsd-vm@v1\n      with:\n        usesh: true\n        prepare: pkg install -y gnupg bash gmake git gawk\n        run: gmake test\n\n  windows-wsl-ci:\n    runs-on: windows-latest\n    steps:\n    - uses: Vampire/setup-wsl@v6\n      with:\n        distribution: Ubuntu-22.04\n        update: 'true'\n        additional-packages: gnupg make man git gawk file\n    - run: git config --global core.autocrlf input\n    - uses: actions/checkout@v6\n    - shell: wsl-bash {0}\n      run: make test\n"
  },
  {
    "path": ".gitignore",
    "content": "#### joe made this: http://goel.io/joe\n\n#####=== Windows ===#####\n# Windows image file caches\nThumbs.db\nehthumbs.db\n\n# Folder config file\nDesktop.ini\n\n# Recycle Bin used on file shares\n$RECYCLE.BIN/\n\n# Windows Installer files\n*.cab\n*.msi\n*.msm\n*.msp\n\n# Windows shortcuts\n*.lnk\n\n#####=== Linux ===#####\n*~\n\n# KDE directory preferences\n.directory\n\n# Linux trash folder which might appear on any partition or disk\n.Trash-*\n\n#####=== MacOS ===#####\n.DS_Store\n.AppleDouble\n.LSOverride\n\n# Icon must end with two \\r\nIcon\n\n\n# Thumbnails\n._*\n\n# Files that might appear on external disk\n.Spotlight-V100\n.Trashes\n\n# Directories potentially created on remote AFP share\n.AppleDB\n.AppleDesktop\nNetwork Trash Folder\nTemporary Items\n.apdisk\n\n#####=== JetBrains ===#####\n# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm\n\n*.iml\n\n## Directory-based project format:\n.idea/\n# if you remove the above rule, at least ignore the following:\n\n# User-specific stuff:\n# .idea/workspace.xml\n# .idea/tasks.xml\n# .idea/dictionaries\n\n# Sensitive or high-churn files:\n# .idea/dataSources.ids\n# .idea/dataSources.xml\n# .idea/sqlDataSources.xml\n# .idea/dynamic.xml\n# .idea/uiDesigner.xml\n\n# Gradle:\n# .idea/gradle.xml\n# .idea/libraries\n\n# Mongo Explorer plugin:\n# .idea/mongoSettings.xml\n\n## File-based project format:\n*.ipr\n*.iws\n\n## Plugin-specific files:\n\n# IntelliJ\nout/\n\n# mpeltonen/sbt-idea plugin\n.idea_modules/\n\n# JIRA plugin\natlassian-ide-plugin.xml\n\n# Crashlytics plugin (for Android Studio and IntelliJ)\ncom_crashlytics_export_strings.xml\ncrashlytics.properties\ncrashlytics-build.properties\n\n#####=== SublimeText ===#####\n# cache files for sublime text\n*.tmlanguage.cache\n*.tmPreferences.cache\n*.stTheme.cache\n\n# workspace files are user-specific\n*.sublime-workspace\n\n# project files should be checked into the repository, unless a significant\n# proportion of contributors will probably not be using SublimeText\n# *.sublime-project\n\n# sftp configuration file\nsftp-config.json\n\n#####=== Jekyll ===#####\n_site/\n.sass-cache/\n\n#####=== Custom ===#####\n# Logic files:\n.gitsecret/\ngit-secret\n\n# Temporary packages:\ntemp/\n\n# Packaging:\nbuild/\n*.deb\n*.fpm\n\n# Docs:\ndocs/man\ndocs/_posts\ndocs/_includes/install-*.sh\ndocs/_includes/version.txt\nCHANGELOG-RELEASE.md\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\n## {{Next Version}}\n\n### Misc\n\n- NOTE: Arch instructions now say to install from source. Arch tests removed temporarily (#916)\n- NOTE: there is an issue when repo directory (or a parent dir) contains a space (#135)\n- Improve error messaging when we cannot find git repo (#874)\n- Temporarily disable apk builds on alpine (#881)\n- Have `hide -v` show output from gnupg\n- Documentation updates and fixes\n\n\n## 0.5.0\n\n### Features\n\n- Adds `SECRETS_GPG_ARMOR` env variable to use `gpg --armor`\n  when encrypting files, so secret files are stored\n  in text format rather than binary (#631)\n- Allow gnupg permission warnings in `tell`, `hide`, `reveal`, and `removeperson` (#811)\n- `git secret init` now sets `.gitsecret/keys` permission to 0700 (#811)\n- Improve verbose and non-verbose output\n\n### Bugfixes\n\n- Fix adding newlines to `.gitignore` entries (#643)\n- Fix `cat` and `reveal` on named files while in repo subdir (#710)\n- Fix `clean`, `hide`, `reveal` so they only remove marked secret files (#833)\n- Fix for `removeperson` if same email is present multiple times (#638)\n- Correct error message about files missing from .gitignore\n\n### Misc\n\n- Rename `killperson` command to `removeperson` (#684)\n- Improve error messaging decrypting nonexistent files (#706)\n- Improve, expand, correct, and update docs (#699)\n- Update docs for use with CI/CD server (#675)\n- Upgrade bats-core to v1.6.0 (#755)\n- Test, and build RPMS, with Rocky and Alma Linux instead of CentOS (#765)\n- Automate testing code on windows using WSL (#846)\n- Automate testing code on FreeBSD (#455)\n- Improve testing of .gitignore contents (#792)\n- Automate running verbose tests with SECRETS_TEST_VERBOSE=1 (#794)\n- Improve documentation about installing on Windows (#843)\n\n\n## 0.4.0\n\n### Bugfixes\n\n- Escape filenames with special characters before adding to `.gitignore`\n- Better error handling around telling an email twice (#634)\n- Fix for `-P` (#647)\n\n### Misc\n\n- Removed `test-kitchen`\n- Moved from `travis` to GitHub Actions\n- Changed almost all infrastructure code\n- Moved away from Bintray to Artifactory\n- Changes how GitHub Pages work\n- Add security disclaimer for git-secret-killperson\n- Improve documentation about releases\n- Man page improvements\n\n\n## Version 0.3.3\n\n### Bugfixes\n\n- In 'tell', warn about disabled, revoked, expired, or invalid keys (#552, #508, #317, #290, #283, #238)\n- Error if 'tell' is used on an email address with multiple keys (#552)\n- Don't let 'reveal' clobber secret files (#579)\n- Updated test key fixture that had expired (#607)\n\n### Misc\n\n- Improve docs about using gpg with git-secret (#577)\n- Text improvements and More about security in git-secret.7 man page (#603)\n- Reflect changes in ruby bundler during build process\n- Upgrade build process to ansible 2.9\n- Use shellcheck 0.7.1 with CI, not 'latest' (#609)\n- Improve output of `git-secret add`\n\n## Version 0.3.2\n\n### Bugfixes\n\n- Fix mention of version in git-secret add man page (#544)\n\n### Misc\n\n- Update developer docs, especially regarding mac, docker, and test-kitchen (#195)\n- Update man pages to mention version documented (#420)\n\n## Version 0.3.1\n\n### Misc\n\n- Update man pages\n\n## Version 0.3.0\n\n### Features\n\n- Support SECRETS_PINENTRY env var for gnupg --pinentry-mode parameter (#221)\n- Show output from gnupg if 'hide' fails (#516, #202, #317)\n- Add support for Busybox (#478)\n\n### Bugfixes\n\n- Use OSX's mktemp on OSX, even if there's another version in PATH. (#485)\n- Make rsync a build requirement on debian (#500)\n- Use gnupg1, not gnupg2, when tests specify gnupg1 (#241)\n- Note dependencies gawk, bash, and coreutils in linux packages (#493)\n- Handle case of key having no email and a comment (#527)\n- Avoid blank lines from output of 'clean -v'\n\n### Misc\n\n- Improve messaging and logic around deleting tmp files.\n- Add note about secrets and old keys (#499)\n- Transition build process from python 2 to python 3 (#487)\n- Upgrade build process from ansible 2.5 to ansible 2.8\n- Fix build process when installing gnupg2 source deps on Ubuntu\n- Close file descriptor 3 when running gnupg subprocesses (#521)\n- Small optimization in 'hide'\n- Improve code comments\n- Update docs to note that git-secret repos modified by git-secret 0.2.3 and\n  later are not backward compatible with pre-0.2.3 versions of git-secret. (#536)\n\n## Version 0.2.6\n\n### Features\n\n- git-secret is now available in Fedora, link added to README.md. (#315)\n- Support automated testing on windows with Travis CI (#372)\n- Support SECRETS_VERBOSE env var to enable verbosity (#323)\n- Use gpg without --quiet when decrypting in verbose mode (#394)\n- Add -v options to 'tell' and 'reveal', showing gpg output (#320, #395)\n- Change 'init' to never ignore .secret files (#362)\n- 'add' appends filepaths to .gitignore by default (#225)\n- Automate the GitHub release (#411)\n\n### Bugfixes\n\n- Fix 'hide -m' when used as first hide operation (#466)\n- Fix code to respect $TMPDIR when generating tmp files (#451)\n- Be more careful when deleting test files (#360)\n- Use separate directory when testing, instead of using $BATS_TMPDIR directly (#407)\n- Fix 'whoknows -l' and related tests on FreeBSD (#454)\n- Fix git-secret init when used on busybox (#475)\n- Update git-secret.io, fix utils/gh-branch.sh to use 'git all --add' (#344)\n- Fix link to homebrew's git-secret in README.md (#310)\n- Remove diagnostic output from test results (#324)\n- Remove un-needed redirection in 'reveal' (#325)\n- Fix link to current contributors in CONTRIBUTING.md (#331)\n- Fix tests when running from git hooks (#334)\n- Fix typo, remove temp directory in utils/tests.sh (#347)\n- Spelling fixes\n- Fix re: SECRETS_DIR in 'init' and SECRETS_EXTENSION in test_reveal.bats (#364)\n- git-secret will fail if you pass params or filenames that are not understood (#390)\n- Use SECRETS_GPG_COMMAND env var in gpg version check (#389)\n- Add header to git-secret.7 man page, for debian and doc improvement (#386)\n- Respect DESTDIR when installing as per GNU/debian/etc recommendations (#424)\n- Use git check-ignore to test for files ignored by git\n\n### Misc\n\n- Improve docs about hide -m option (#467)\n- Document SECRETS_VERBOSE and improve env var docs (#396)\n- Setting SECRETS_TEST_VERBOSE env var shows debug info during tests (EXPERIMENTAL)\n- Add documentation about how to write tests.\n- Suppress 'cleaning up temp files' messages unless in a verbose mode.\n- Improve git-secret user messaging.\n- Update CHANGELOG.md to mention fix for #281 in v0.2.5 (#311)\n- Add text explaining git-secret Style Guide and Development Philosophy\n- Use Shellcheck on tests/ files, changes for Shellcheck in tests/ (#368)\n- Use Shellcheck on MacOS/osx travis tests (#403)\n- Show commands run by Makefile as per debian upstream recommendations (#386)\n- Upgrade bats-core to v1.1.0, import bats-core into vendor/bats-core (#377)\n- Use gawk to parse emails from gpg output\n- Optimize code that parses keyrings\n- Remove unused code\n\n## Version 0.2.5\n\n### Features\n\n- Add support for FreeBSD (#244)\n- Add -l option to whoknows, which shows key expiration dates (#283)\n- Add -P option (preserve permissions) to reveal and hide (#172)\n- Add -F option (force, changing some errors to warnings) to hide and reveal (#253)\n- Allow user to specify name of secret dir at runtime using SECRETS_DIR env var, and test (#247, #250)\n\n### Bugfixes\n\n- Fix issues with spaces in paths and filenames (#226, #135)\n- Fix issue when 'hide' used in subdir of repo (#230)\n- Fix issues in 'changes' with trailing newlines (#291)\n- Fix 'hide' to only count actually hidden files as hidden (#280)\n- Fixed bugs and improved error messages (#174)\n- Issue error message when unable to hide a secret (#202, #238)\n- Accept gpg key with no name, only an email (#227)\n- Require keys to be specified by email, as documented (#267)\n- Disallow 'git secret tell' or 'killperson' with emails that are not in keyring (also #267)\n\n### Misc\n\n- Added notes about packages and for package maintainers (#281)\n- Improve documentation regarding operation with different versions of GPG (#274, #182)\n- Documentation improvements, error message and text improvements, and typo fixes (#254)\n- git-secret RFC#001 added, documenting a path towards independence from gpg binary formats (#208)\n- Add tests for expired gpg keys, and gpg keys with only emails (#276)\n\n## Version 0.2.4\n\n### Features\n\n- Added `git secret cat` feature (#141)\n\n### Bugfixes\n\n- `git secret hide` and `git secret changes` check for files more carefully (#153, #154)\n\n### Misc\n\n- Documentation and error message improvements (#126, #136, #144, #150)\n- Build and CI fixes (#152, #179, #186, #188, #189)\n- Migrate to `bats-core` bash testing framework\n\n## Version 0.2.3\n\n### Features\n\n- Added `-m` option to `hide` command, files will only be hidden when modifications are detected (#92)\n- Changed how path mappings file works: colon delimited FSDB in `.gitsecret/paths/mapping.cfg', so git-secret\n  can store checksums of hidden files. Note this means git-secret repos modified by git-secret 0.2.3\n  or later are not backward compatible with pre-0.2.3 versions of git-secret. (#92)\n- `git secret init` now adds `random_seed` to `.gitignore` (#93)\n\n### Bugfixes\n\n- Dropped `git check-ignore`, using `git add --dry-run` instead to check for ignored files (#105,#38)\n- Fixed `gnupg` >= 2.1 CI tests (#6)\n\n### Misc\n\n- Now users can run local CI tests using test-kitchen (#6)\n- Migrated travis ci tests to test-kitchen for Linux platforms.\n- Added more `gpg` version to test matrix (#99)\n- Added CentOS to test matrix (#38,#91)\n- All tested Linux platforms now use latest release of `shellcheck`\n- Added Alpine to test matrix, and apk is now built. (#75)\n\n## Version 0.2.2\n\n### Features\n\n- Change how the `usage` command works (#48)\n- Now `git-secret` works from any place inside `git-tree` (#56)\n- Added `-d` option to the `hide` command: it deletes unencrypted files (#62)\n- Added new command `changes` to see the diff between the secret files (#64)\n- Now it is possible to provide multiple emails to the `killperson` command (#73)\n- Now it is possible to provide multiple emails to the `tell` command (#72)\n\n### Bugfixes\n\n- Fixed bug when `_user_required` was not working after re-importing keys (#74)\n- Refactored `hide` and `clean` commands to be shorter\n\n### Misc\n\n- Now every doc in this project refer to `git-secret.io` instead of old `gh-pages` website (#71)\n- Now installation section is removed from main `man` file (#70)\n- Now \"See also\" sections in the `man` pages are clickable (#69)\n- Added \"Manual\" section to the manuals (#61)\n- Added `CentOS` container for `ci` testing (#38)\n- Tests are refactored. Added `clean` command tests, removed a lot of hard-coded things, moved tests execution from `./temp` folder to `/tmp`, added a lot of new check in old tests, and some new test cases (#52)\n- `shellcheck` is now supported with `make lint`\n\n## Version 0.2.1\n\n### Misc\n\n- Added `CONTRIBUTING.md` and `LICENSE.md`.\n- New brand logo in the `README.md`.\n- Added autodeploy to `bintray` in `.travis.yml`.\n- Now everything is tested inside the `docker`-containers and `OSX` (MacOS) images on `travis`.\n- Added `.ci/` folder for continuous integration, refactored `utils/` folder.\n- Everything is `shellcheck`ed (except `tests/`).\n\n## Version 0.2.0\n\n### Features\n\n- Added `changes` command to see the difference between current version of the hidden files and the committed one\n- Added `-f` option to the `reveal` command to remove prompts\n\n### Bugfixes\n\n- Some bugs are fixed\n\n### Misc\n\n- New installation instructions\n- Changed the way files were decrypted, now it is a separate function\n\n## Version 0.1.2\n\n### Features\n\n- Added `-i` option to the `git-secret-add` command, which auto adds unignored files to the `.gitignore`\n\n### Misc\n\n- `.github` templates added\n- Documentation improved with `Configuration` section\n- `Makefile` improvements with `.PHONY` and `install` target\n- Added extra tests: for custom filenames and new features\n\n## Version 0.1.1\n\n### Features\n\n- Added `--dry-run` option to the `git secret` command, which prevents any actions.\n\n### Misc\n\n- Removed animation from docs, now using `asciinema.org`\n- `install_full_fixture()` returns a fingerprint\n- `uninstall_full_fixture()` receives two args\n- Fixed bug when tests were failing with `gpg2`\n- New travis strategy: testing both `gpg` and `gpg2`\n\n## Version 0.1.0\n\n### Features\n\n- Implementation of git secret add\n- Implementation of git secret clean, with -v option\n- Implementation of git secret hide, with -c 'clean' and -v option\n- Implementation of git secret init\n- Implementation of git secret killperson\n- Implementation of git secret list\n- Implementation of git secret remove, with -c option\n- Implementation of git secret reveal, with -d homedir and -p passphrase options\n- Implementation of git secret tell, with -m email and -d homedir options\n- Implementation of git secret usage\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\nYour contributions are always welcome!\n\n\n## Getting started\n\n1. Create your own or pick an opened issue from the [tracker](https://github.com/sobolevn/git-secret/issues). Take a look at the [`help-wanted` tag](https://github.com/sobolevn/git-secret/labels/help%20wanted)\n\n2. Fork the git-secret repo and then clone the repository using a command like `git clone https://github.com/${YOUR_NAME}/git-secret.git`\n\n3. Make sure that everything works on the current platform by running `make test`.\n   You can also try the experimental `SECRETS_TEST_VERBOSE=1 make test`, which will\n   show you a lot of debug output while the tests are running.\n   Note that 'experimental' features may change or be removed in a future version of `git-secret`.\n\n4. If you want to test on multiple operating systems just push your PR, GitHub Actions will cover everything else\n\nBasically, our `make` file is the only thing you will need to work with this repo.\n\n\n## Process\n\n### Environment\n\nFor development of `git-secret` you should have these tools locally:\n\n- git\n- bash\n- gawk\n- gnupg (or gnupg2), see below if not packaged by your distribution/OS (i.e. MacOS)\n- sha256sum (on freebsd and MacOS `shasum` is used instead)\n- make\n\nTo test `git-secret` you will need:\n\n- [docker](https://www.docker.com/)\n\n### Code style\n\nNew features and changes should aim to be as clear, concise, simple, and consistent\n\n1. clear: make it as obvious as possible what the code is doing\n\n2. concise: your PR should be as few characters (not just lines) of changes as _reasonable_.\n   However, generally choose clarity over being concise.\n   Clarity and conciseness can be in conflict with each other. But\n   it's more important for the code to be understandable than for it to be small.\n   Therefore favor writing clear code over making shorter diffs in your PRs.\n\n3. simple: this dovetails with the previous two items.\n   git-secret is a security product, so it's best to have the code be easy to understand.\n   This also aids future development and helps minimize bugs.\n\n4. consistent: Write code that is consistent with the surrounding code and the rest of the git-secret code base.\n   Every code base has its own conventions and style that develop and accrete over time.\n\n   Consistency also means that the inputs and outputs of git-secret should be as consistent as reasonable\n   with related Unix and git tools, and follow the 'rule of least surprise',\n   also known as the 'principle of least astonishment': <https://en.wikipedia.org/wiki/Principle_of_least_astonishment>\n\nWe wrote this to clarify our thinking about how git-secret should be written.  Of course, these are philosophical goals,\nnot necessities for releasing code, so balancing these four ideals _perfectly_ is both unwarranted and impossible.\n\n### Writing PRs\n\nIf you're planning a large change to `git-secret` (for example, a lot of lines/characters of diffs, affecting multiple commands,\nchanging/adding a lot of behavior, or adding multiple command-line options), it's best to discuss the changes in an Issue first.\nAlso it's often best to implement larger or complex changes as a series of planned-out, smaller PRs,\neach making a small set of specific changes. This facilitates discussions of implementation, which often come to light\nonly after seeing the actual code used to perform a task.\n\nAs mentioned above, we seek to be consistent with surrounding git and Unix tools, so when writing changes to git-secret,\nthink about the input, output, and command-line options that similar Unix commands use.\n\nOur favor toward traditional Unix and git command-style inputs and outputs can also mean it's appropriate to\nlean heavily on git and widely-used Unix command features instead of re-implementing them in code.\n\n### Development Process\n\n1. Make changes to the git secret files that need to be changed\n\n2. When making changes to any files inside `src/`, for changes to take effect you will need to rebuild the `git-secret` script with `make clean && make build`\n\n3. Run `shellcheck` against all your changes with `make lint`.\n   You should also check your changes for spelling errors using 'aspell -c filename'.\n\n4. Add an entry to CHANGELOG.md, referring to the related issue # if appropriate\n\n5. Change the `man` source file(s) (we write them in markdown) in `man/man1` and `man/man7` to document your changes if appropriate\n\n6. Now, add all your files to the commit with `git add --all` and commit changes with `git commit`.\n   Write a good commit message which explains your work\n\n7. When running `git commit` the tests will run automatically, your commit will be canceled if they fail.\n   You can run the tests manually with `make clean build test`.\n\n8. Push to your repository, and make a pull-request against `master` branch. It's ideal to have one commit per pull-request,\nbut don't worry, it's easy to `squash` PRs into a small number of commits when they're merged.\n\n### Branches\n\nWe have two long-live branches: `master` for the git-secret code and man pages, and `gh-pages` for the static web site.\nThe `gh-pages` branch tracks the `master` branch's `docs` folder, and is kept up-to-date using a GitHub Action.\n\nDevelopment looks like this:\n\n> `your-branch` -> `master`\n\n- `master` branch is protected, so only fully tested code goes there. It is also used to create a new `git` tag and a `github` release\n\nBy convention, you can name your branches like `issue-###-short-description`, but that's not required.\nThe `gh-pages` branch is used for the pages at `git-secret.io`. See 'Release Process' below.\n\n### Writing tests\n\n`git-secret` uses [bats-core](https://github.com/bats-core/bats-core) for testing.\nSee the files in tests/ and the `bats-core` documentation for details.\n\nBecause the output of many commands can be affected by the SECRETS_VERBOSE environment\nvariable (which enables verbosity), it's best not to expect a particular number of lines of\noutput from commands.\n\n### Release process\n\nTo create a new release, (you'll first need permission to commit to the repo, of course):\n\nUpdate the content of `CHANGELOG.md` for the release (this should be a matter of changing headers),\nand update the version string in `src/version.sh`.\n\nWhen creating a commit inside the `master` branch (it is usually a documentation and changelog update with the version bump inside `src/version.sh`).\n\nThen, push your code to GitHub. It will start the CI.\n\nAfter all the checks have executed, GitHub Actions will test and build releases for specific platforms.\n\nWhile CI is doing it's building and testing, finish the release on github by pushing the new tag with:\n\n```bash\ngit push --tags\n```\n\nand then go to https://github.com/sobolevn/git-secret/releases to see that the new release is created. It might take some time.\n\n#### GitHub automated releases\n\nWe use GitHub actions to run the release process.\nWe use `artifactory` as an environment for the release.\nYou would need to get a review before release would be possible.\n\nIt can be reproduced locally with `make release`, but you will need `SECRETS_ARTIFACTORY_CREDENTIALS`.\n\nAfter packages are released to https://gitsecret.jfrog.io we trigger `release-ci` workflow to test that installation works correctly.\n\n#### Manual releases\n\nReleases to `brew` are made manually, and involve opening a PR on the [Homebrew Core](https://github.com/Homebrew/homebrew-core) repo .\nTo get started, see the\n[Homebrew docs about Formulae-related PRs](https://docs.brew.sh/How-To-Open-a-Homebrew-Pull-Request#formulae-related-pull-request)\nand `brew bump-formula-pr --help`\n\n### Downstream Packages\n\nThere are several distributions and packaging systems that may already have git-secret packaged for your distribution (although sometimes their versions are not the most current, and we recommend all users upgrade to 0.2.5 or above).\n\n### Notes to Downstream Packagers (Those who make packages for specific OSes/distributions)\n\nFirst of all, thank you for packaging git-secret for your platform! We appreciate it.\n\nWe also would like to welcome you to collaborate or discuss any issues, ideas or thoughts you have about\ngit-secret by submitting [issue report](https://github.com/sobolevn/git-secret/issues)\n(which can also be feature requests) or\n[pull requests](https://help.github.com/en/articles/creating-a-pull-request)\nvia the git repo at\n[git-secret on github](https://github.com/sobolevn/git-secret)\n\nPlease let us know if there are any changes you'd like to see to the source,\npackaging, testing, documentation, or other aspect of git-secret.\nWe look forward to hearing from you.\n\n\n## About GnuPG\n\nHere are some links to gnupg documentation that might be useful for those working with git-secret:\n\n- [GnuPG PDF Documentation](https://www.gnupg.org/documentation/manuals/gnupg.pdf)\n- [GnuPG doc/DETAILS File](https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/DETAILS)\n\n\n## Financial contributions\n\nWe also welcome financial contributions in full transparency on our [open collective](https://opencollective.com/git-secret).\nAnyone can file an expense. If the expense makes sense for the development of the community, it will be \"merged\" in the ledger of our open collective by the core contributors and the person who filed the expense will be reimbursed.\n\n\n## Credits\n\n### Contributors\n\nThank you to all the people who have already contributed\nto `git-secret` via commits to our git repository!\n\n[![List of contributors](https://opencollective.com/git-secret/contributors.svg?width=890&button=0)](https://github.com/sobolevn/git-secret/contributors)\n\n\n### Backers\n\nThank you to all our backers! [[Become a backer](https://opencollective.com/git-secret#backer)]\n\n<object type=\"image/svg+xml\" data=\"https://opencollective.com/git-secret/tiers/backer.svg?avatarHeight=36&width=600\" style=\"max-width: 100%;\"></object>\n\n\n### Sponsors\n\nThank you to all our sponsors! (please ask your company to also support this open source project by [becoming a sponsor](https://opencollective.com/git-secret#sponsor))\n\n<object type=\"image/svg+xml\" data=\"https://opencollective.com/git-secret/tiers/sponsor.svg?avatarHeight=36&width=600\" style=\"max-width: 100%;\"></object>\n"
  },
  {
    "path": "LICENSE.md",
    "content": "MIT License\n\nCopyright (c) 2016 Nikita Sobolev\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": "SHELL:=bash\nPREFIX?=\"/usr\"\nDESTDIR?=\n\n#\n# Building:\n#\n\n.PHONY: all\nall: build\n\n.PHONY: clean\nclean:\n\t@rm -f git-secret\n\n.PHONY: build\nbuild:\n\t@cat src/version.sh > git-secret\n\t@cat src/_utils/*.sh src/commands/*.sh >> git-secret\n\t@cat src/main.sh >> git-secret\n\t@chmod +x git-secret; sync\n\n.PHONY: install\ninstall:\n\t\"${SHELL}\" ./utils/install.sh \"${DESTDIR}${PREFIX}\"\n\n.PHONY: uninstall\nuninstall:\n\t\"${SHELL}\" ./utils/uninstall.sh \"${DESTDIR}${PREFIX}\"\n\n#\n# Testing and linting:\n#\n\n# The $(shell echo $${PWD}) construct is to access *nix paths under windows\n# Under git for windows '$PATH' is set to windows paths, e.g. C:\\Something\n# Using a sub-shell we get the raw *nix paths, e.g. /c/Something\n.PHONY: test\ntest: clean build\n\texport SECRETS_PROJECT_ROOT=\"$(shell echo $${PWD})\"; \\\n\texport PATH=\"$(shell echo $${PWD})/vendor/bats-core/bin:$(shell echo $${PWD}):$(shell echo $${PATH})\"; \\\n\t\"${SHELL}\" ./utils/tests.sh\n\n# We use this script in CI and you can do this too!\n# What happens here?\n# 1. We pass `SECRETS_DOCKER_ENV` variable into this job\n# 2. Based on it, we select a proper `docker` image to run test on\n# 3. We execute `make test` inside the `docker` container\n.PHONY: docker-ci\ndocker-ci: clean\n\t@[ -z \"${SECRETS_DOCKER_ENV}\" ] \\\n\t\t&& echo 'SECRETS_DOCKER_ENV is unset' && exit 1 || true\n\tdocker build \\\n\t\t-f \".ci/docker-ci/$${SECRETS_DOCKER_ENV}/Dockerfile\" \\\n\t\t-t \"gitsecret-$${SECRETS_DOCKER_ENV}:latest\" .\n\tdocker run --rm \\\n\t\t--volume=\"$${PWD}:/code\" \\\n\t\t-w /code \\\n\t\t\"gitsecret-$${SECRETS_DOCKER_ENV}\" \\\n\t\tmake test\n\n.PHONY: lint-shell\nlint-shell:\n\tdocker pull koalaman/shellcheck:latest\n\tdocker run \\\n\t\t--volume=\"$${PWD}:/code\" \\\n\t\t-w /code \\\n\t\t-e SHELLCHECK_OPTS='-s bash -S style -a' \\\n\t\t--rm koalaman/shellcheck \\\n\t\t$$(find src .ci utils tests docs -type f \\\n\t\t\t-name '*.sh' -o -name '*.bash' -o -name '*.bats')\n\n.PHONY: lint-docker\nlint-docker:\n\tdocker pull hadolint/hadolint:latest-alpine\n\tdocker run \\\n\t\t--volume=\"$${PWD}:/code\" \\\n\t\t-w /code \\\n\t\t--rm hadolint/hadolint \\\n\t\thadolint \\\n\t\t\t--ignore=DL3008 --ignore=DL3018 --ignore=DL3041 --ignore=DL3028 \\\n\t\t\t.ci/*/**/Dockerfile\n\n.PHONY: lint\nlint: lint-shell lint-docker\n\n#\n# Manuals and docs:\n#\n\n.PHONY: clean-man\nclean-man:\n\t@find \"man/\" -type f ! -name \"*.md\" -delete\n\n.PHONY: build-man\nbuild-man: build\n\tdocker pull msoap/ruby-ronn\n\texport GITSECRET_VERSION=\"$$(./git-secret --version)\" && docker run \\\n\t\t--volume=\"$${PWD}:/code\" \\\n\t\t-w /code \\\n\t\t--rm msoap/ruby-ronn \\\n\t\tronn --roff \\\n\t\t\t--organization=sobolevn \\\n\t\t\t--manual=\"git-secret $${GITSECRET_VERSION}\" \\\n\t\t\tman/*/*.md\n\n.PHONY: build-docs\nbuild-docs: build-man\n\t \"${SHELL}\" docs/build.sh\n\n.PHONY: docs\ndocs: build-docs\n\tdocker pull jekyll/jekyll\n\tdocker run \\\n\t\t--volume=\"$${PWD}/docs:/code\" \\\n\t\t-w /code \\\n\t\t-p 4000:4000 \\\n\t\t--rm jekyll/jekyll \\\n\t\tjekyll serve --safe --strict_front_matter\n\n.PHONY: changelog\nchangelog:\n\t@[ -z \"${GITHUB_REPOSITORY}\" ] \\\n\t\t&& echo 'GITHUB_REPOSITORY is unset' && exit 1 || true\n\t@[ -z \"${GITHUB_TOKEN}\" ] \\\n\t\t&& echo 'GITHUB_TOKEN is unset' && exit 1 || true\n\tdocker pull githubchangeloggenerator/github-changelog-generator\n\tdocker run \\\n\t\t--volume=\"$${PWD}:/code\" \\\n\t\t-w /code \\\n\t\t--entrypoint='' \\\n\t\t-e GITHUB_REPOSITORY \\\n\t\t-e GITHUB_TOKEN \\\n\t\t--rm githubchangeloggenerator/github-changelog-generator \\\n\t\tsh \".ci/github_release_script.sh\"\n\n#\n# Packaging:\n#\n\n.PHONY: build-release\nbuild-release: clean build-man\n\t@[ -z \"${SECRETS_RELEASE_TYPE}\" ] \\\n\t\t&& echo 'SECRETS_RELEASE_TYPE is unset' && exit 1 || true\n\tdocker build \\\n\t\t-f \".ci/releaser/alpine/Dockerfile\" \\\n\t\t-t \"gitsecret-releaser:latest\" .\n\tdocker run \\\n\t\t--volume=\"$${PWD}:/code\" \\\n\t\t--rm gitsecret-releaser \\\n\t\tbash \"./utils/$${SECRETS_RELEASE_TYPE}/build.sh\"\n\n.PHONY: release\nrelease: build-release\n\t@[ -z \"${SECRETS_ARTIFACTORY_CREDENTIALS}\" ] \\\n\t\t&& echo 'SECRETS_ARTIFACTORY_CREDENTIALS is unset' && exit 1 || true\n\tdocker run \\\n\t\t--volume=\"$${PWD}:/code\" \\\n\t\t-e SECRETS_ARTIFACTORY_CREDENTIALS \\\n\t\t-e SECRETS_DEPLOY_DRY_RUN \\\n\t\t--rm gitsecret-releaser \\\n\t\tbash \"./utils/$${SECRETS_RELEASE_TYPE}/deploy.sh\"\n\n.PHONY: release-ci\nrelease-ci:\n\t@[ -z \"${SECRETS_RELEASE_ENV}\" ] \\\n\t\t&& echo 'SECRETS_RELEASE_ENV is unset' && exit 1 || true\n\t@[ -z \"${SECRETS_RELEASE_TYPE}\" ] \\\n\t\t&& echo 'SECRETS_RELEASE_TYPE is unset' && exit 1 || true\n\tdocker build \\\n\t\t-f \".ci/release-ci/$${SECRETS_RELEASE_ENV}/Dockerfile\" \\\n\t\t-t \"gitsecret-release-$${SECRETS_RELEASE_ENV}:latest\" .\n\tdocker run --rm \\\n\t\t--volume=\"$${PWD}:/code\" \\\n\t\t-w /code \\\n\t\t\"gitsecret-release-$${SECRETS_RELEASE_ENV}\" \\\n\t\tbash -c \"set -e; bash \"./utils/$${SECRETS_RELEASE_TYPE}/install.sh\"\"\n"
  },
  {
    "path": "README.md",
    "content": "# git-secret\n\n\n[![test](https://github.com/sobolevn/git-secret/actions/workflows/test.yml/badge.svg?branch=master&event=push)](https://github.com/sobolevn/git-secret/actions/workflows/test.yml)\n[![release-ci](https://github.com/sobolevn/git-secret/actions/workflows/release-ci.yml/badge.svg)](https://github.com/sobolevn/git-secret/actions/workflows/release-ci.yml)\n[![Homebrew](https://img.shields.io/homebrew/v/git-secret.svg)](https://formulae.brew.sh/formula/git-secret)\n[![Supporters](https://img.shields.io/opencollective/all/git-secret.svg?color=gold&label=supporters)](https://opencollective.com/git-secret)\n\n[![git-secret](https://raw.githubusercontent.com/sobolevn/git-secret/gh-pages/images/git-secret-big.png)](https://git-secret.io/)\n\n\n## What is `git-secret`?\n\n`git-secret` is a bash tool which stores private data inside a git repo.\n`git-secret` encrypts files with permitted users' public keys,\nallowing users you trust to access encrypted data using pgp and their secret keys.\n\nWith `git-secret`, changes to access rights are simplified, and private-public key issues are handled for you.\n\nWhen someone's permission is revoked, secrets do not need to be changed with `git-secret` -\njust remove their key from the repo's keyring using `git secret removeperson their@email.com`,\nre-encrypt the files, and they won't be able to decrypt secrets anymore.\nIf you think the user might have copied the secrets or keys when they had access, then\nyou should also change the secrets.\n\n\n## Preview\n\n[![git-secret terminal preview](git-secret.gif)](https://asciinema.org/a/41811?autoplay=1)\n\n\n## Installation\n\n`git-secret` [supports `brew`](https://formulae.brew.sh/formula/git-secret), just type: `brew install git-secret`\n\nIt also supports `apt` and `yum`. You can also use `make` if you want to.\nSee the [installation section](https://sobolevn.me/git-secret/installation) for the details.\n\n### Requirements\n\n`git-secret` relies on several external packages:\n\n- `bash` since `3.2.57` (it is hard to tell the correct `patch` release)\n- `gawk` since `4.0.2`\n- `git` since `1.8.3.1`\n- `gpg` since `gnupg 1.4` to `gnupg 2.X`\n- `sha256sum` since `8.21` (on freebsd and MacOS `shasum` is used instead)\n\n\n## Contributing\n\nDo you want to help the project? Find an [issue](https://github.com/sobolevn/git-secret/issues)\nand send a PR. It is more than welcomed! See [CONTRIBUTING.md](CONTRIBUTING.md) on how to do that.\n\n### Security\n\nIn order to encrypt (git-secret hide -m) files only when modified, the path\nmappings file tracks sha256sum checksums of the files added (git-secret add) to\ngit-secret's path mappings filesystem database. Although, the chances of\nencountering a sha collision are low, it is recommend that you pad files with\nrandom data for greater security. Or avoid using  the `-m` option altogether.\nIf your secret file holds more data than just a single password these\nprecautions should not be necessary, but could be followed for greater\nsecurity.\n\nIf you found any security related issues, please do not disclose it in public. Send an email to `mail@sobolevn.me`\n\n\n## Changelog\n\n`git-secret` uses [semver](https://semver.org/). See [CHANGELOG.md](CHANGELOG.md).\n\n\n## Packagers\n\nThanks to all the people and groups who package `git-secret` for easier install on particular OSes and distributions!\n\n[![Packaging status](https://repology.org/badge/vertical-allrepos/git-secret.svg)](https://repology.org/project/git-secret/versions)\n\nHere are some packagings of `git-secret` that we're aware of:\n\n- https://formulae.brew.sh/formula/git-secret\n- https://packages.ubuntu.com/bionic/git-secret\n- https://src.fedoraproject.org/rpms/git-secret\n- https://aur.archlinux.org/packages/git-secret/\n- https://pkgs.alpinelinux.org/package/edge/testing/x86/git-secret\n- https://packages.debian.org/sid/git-secret\n- https://github.com/void-linux/void-packages/blob/master/srcpkgs/git-secret/template\n\nSuch packages are considered 'downstream' because the git-secret code 'flows' from the `git-secret` [repository](https://git-secret.io/installation)\nto the various rpm/deb/dpkg/etc packages that are created for specific OSes and distributions.\n\nWe have also added notes specifically for packagers in [CONTRIBUTING.md](CONTRIBUTING.md).\n\n\n## Sponsors\n\nSupport this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/git-secret#sponsor)]\n\n[![Sponsors](https://opencollective.com/git-secret/tiers/sponsor.svg?width=890)](https://opencollective.com/git-secret)\n\n\n## Backers\n\nThanks to all our backers!\n\n[![Backers](https://opencollective.com/git-secret/tiers/backer.svg?width=890&avatarHeight=36)](https://opencollective.com/git-secret)\n\n\n## Contributors\n\nThis project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].\n<a href=\"https://github.com/sobolevn/git-secret/graphs/contributors\"><img src=\"https://opencollective.com/git-secret/contributors.svg?width=890\" /></a>\n\n\n## License\n\nMIT. See [LICENSE.md](LICENSE.md) for details.\n\n\n## Thanks\n\nSpecial thanks to [Elio Qoshi](https://elioqoshi.me/sq/) from [ura](http://ura.design/) for the awesome logo.\n"
  },
  {
    "path": "RFC/RFC001.md",
    "content": "# RFC 0001 - A stable and forwards compatible public key storage format\n\n**Feature Name:** Stable public key storage\n\n**Status:** Final\n\n**Type:** Enhancement\n\n**Related components:** Core\n\n**Start Date:** 2018-06-14\n\n**Author:** Simon Massey\n\n**GitHub issues:** \n\n* #136 GnuPG2 2.2 vs 2.1 conflicts in keybox format\n\n## Summary\n\nA new internal public key storage format that avoids forwards compatibility issues between GPG releases. This proposal will keep forwards compatibility with older versions of git-secret. \n\n## Motivation\n\nGPG maintains backwards compatibility but not forwards compatibility. Running a new GPG version can and will upgrade the keyring storage files in a way that is not recognized by older versions of GPG. This is not normally a problem for typical GPG usage. Users will upgrade and rarely downgrade. It is a problem for git-secret as the keyring storage is committed to git and shared between users. Someone using an older version of GPG can no longer open the upgraded keyring file. \n\n## Approach\n\ngit-secret will move away from using the keyring format as shared storage of public keys. Instead, it will store public keys as exported keys in ASCII armor format. The public key export format is stable and forwards compatible. GPG users will typically be running different GPG or PGP versions and are able to exchange keys successfully. Bugs that affect git-secret's ability to use exported public keys will likely affect typical GPG key exchange usage. Such bugs are likely to be caught and fixed by the wider open source community. \n\ngit-secret may need to store and process meta-data about keys to make it efficient to work with keys that are stored within individual files. It will use the machine-readable [\"colon listings format\"](https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob_plain;f=doc/DETAILS) for this purpose. \n\nIt is anticipated that `bash` and `gawk` will be sufficient to work efficiently with the new file formats. \n\n## Design\n\nThe new storage format will be implemented as follows: \n\n1. Keys will be stored in `~/.gitsecret/keys` in `gpg  --armor --export` format. The use of ASCII armor rather than binary format is to make debugging of key related issues easier. The filename of the key will be `<keyid>.pub.gpg` (using Field 5 the \"64-bit keyid\" of the colon listings format)\n1. Key meta data will be stored alongside the key file in the `gpg --keyid-format long --with-colons` format. The file name will be `<keyid>.pub.cln`\n1. A folder `~/.gitsecret/cache` will be added to `.gitignore`. At this location, a public keyring will be maintained on a per user bases and won't be shared between users. This is simply a \"keyring cache\" of the keys used to encrypt files. \n\ngit-secret-tell will: \n\n1. Scan the set of `*.pub.cln` files to find all currently told identities. If the given identity is in the list do nothing. \n1. If the given identity isn't listed run `gpg  --armor --export` against the users `$HOME` keyring to create the  `<key-id>.pub.gpg`. \n1. Run `--keyid-format long --with-colons` of the exported key to create the `<key-id>.pub.cln`. \n\nNote that the additional steps to ensure that older versions of git-secret know about the newly told identity will be outlined below. \n\ngit-secret-hide will: \n\n1. Extract the list of \"64-bit keyid\"s who are told from the `*.pub.cln` files. Note that multiple identities can be listed against each key. \n1. Checked this against the list of \"64-bit keyid\"s in the \"keyring cache\" at `~/.gitsecret/cache`. \n1. Import any missing keys into the \"keyring cache\". It is anticipated that `gawk` will be sufficient to perform this calculation. \n1. Run the current logic using the \"keyring cache\". \n\nNote that the additional steps to ensure that older versions of git-secret know about the newly told user will be outlined below. \n\ngit-secret-whoknows will:\n\n1. The list of identities will be loaded by parsing the `.pub.cln` files. Note that multiple identities can be listed against each key. \n\ngit-secret-usage will:\n\n1. Document the git-secret-migrate command discussed in the next section. \n\ngit-secret-reveal will:\n\n* Be unchanged.  \n\ngit-secret-remove will:\n\n* Be unchanged. \n\ngit-secret-list will:\n\n* Be unchanged. \n\ngit-secret-killperson will:\n\n1. Remove the key from the keyring cache.\n1. Delete both `<key-id>.pub.gpg` and `<key-id>.pub.cln` files.\n\ngit-secret-init will:\n\n1. Add `~/.gitsecret/cache` into `.gitignore`.\n1. Run any current logic using the ignored \"keyring cache\".\n\ngit-secret-clean will:\n\n* Be unchanged. \n\ngit-secret-changes will:\n\n1. Show differences the `<key-id>.pub.gpg` and `<key-id>.pub.cln` files in `~/.gitsecret/keys`.\n\ngit-secret-add will:\n\n* Be unchanged. \n\nA new command git-secret-migrate will:\n\n1. Create the folder `~/.gitsecret/cache` and add it to the `.gitignore` file. \n1. Extract all keys from the old keyring generating `<key-id>.pub.gpg` and `<key-id>.pub.cln` files in `~/.gitsecret/keys`\n\n## Version Compatibility\n\nBackwards compatibility will the old keyring storage approach will be maintained as follows:\n\n1. For each changed command a guard will be added that checks for the existence of `.gitsecret/cache`.\n1. If the folder exists it proceeds as normal.\n1. If it does not exist it will report that the repo was initialized by an older version of git-secret and tell the user to run git-secret-migrate\n\nForwards compatibility with older versions of git-secret will be maintained as follows. \n\ngit-secret-hide will:\n\n1. Have a guard that will check for the existence of the old keyring. If it exists it will check it for any new public keys and extract them into the new format prior to running. \n\ngit-secret-tell will:\n\n1. Will check for the existence of the old keyring. If it exists it will load the new public key into it. \n\ngit-secret-killperson\n\n1. Will check for the existence of the old keyring. If it exists it will delete the user from it. \n\n\n## Drawbacks\n\nTo maintain forward compatibility the approach requires the existing logic to kept working for a period of time. We can give a deprecated warning if the forwards compatibility logic is running. The warning can be suppressed using a command-line flag. \n\n## Alternatives\n\nWhat other designs have been considered? Unknown. \n\nWhat is the impact of not doing this? Team members are locked out of secrets when only one other team member upgrades GPG. This can go undetected until the victims needs the secrets in a hurry for production support. Bad things then happen. \n\n## Unresolved questions\n\nWhat parts of the design are still to be done? None. \n"
  },
  {
    "path": "docs/Gemfile",
    "content": "source \"https://rubygems.org\"\n\ngroup :jekyll_plugins do\n  gem \"jekyll\", \">= 3.6.3\"\n  gem \"jekyll-seo-tag\", \"~> 2.8.0\"\nend\n"
  },
  {
    "path": "docs/_config.yml",
    "content": "# Site settings\ntitle: git-secret\nemail: mail@sobolevn.me\ndescription: Shell scripts to encrypt your private data inside a git repository.\nbaseurl: \"/git-secret\" # the subpath of your site, e.g. /blog\nurl: \"https://sobolevn.me\" # the base hostname & protocol for your site\n\n# GitHub links:\ngithub_username: sobolevn\ngithub_changelog: \"https://github.com/sobolevn/git-secret/blob/master/CHANGELOG.md\"\n\n# Seo settings:\nplugins:\n  - jekyll-seo-tag\n\n# Build settings\nmarkdown: kramdown\n"
  },
  {
    "path": "docs/_includes/favicons.html",
    "content": "<link rel=\"apple-touch-icon\" sizes=\"57x57\"\n    href=\"/images/favicons/apple-icon-57x57.png\">\n<link rel=\"apple-touch-icon\" sizes=\"60x60\"\n    href=\"/images/favicons/apple-icon-60x60.png\">\n<link rel=\"apple-touch-icon\" sizes=\"72x72\"\n    href=\"/images/favicons/apple-icon-72x72.png\">\n<link rel=\"apple-touch-icon\" sizes=\"76x76\"\n    href=\"/images/favicons/apple-icon-76x76.png\">\n<link rel=\"apple-touch-icon\" sizes=\"114x114\"\n    href=\"/images/favicons/apple-icon-114x114.png\">\n<link rel=\"apple-touch-icon\" sizes=\"120x120\"\n    href=\"/images/favicons/apple-icon-120x120.png\">\n<link rel=\"apple-touch-icon\" sizes=\"144x144\"\n    href=\"/images/favicons/apple-icon-144x144.png\">\n<link rel=\"apple-touch-icon\" sizes=\"152x152\"\n    href=\"/images/favicons/apple-icon-152x152.png\">\n<link rel=\"apple-touch-icon\" sizes=\"180x180\"\n    href=\"/images/favicons/apple-icon-180x180.png\">\n<link rel=\"icon\" type=\"image/png\" sizes=\"192x192\"\n    href=\"/images/favicons/android-icon-192x192.png\">\n<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\"\n    href=\"/images/favicons/favicon-32x32.png\">\n<link rel=\"icon\" type=\"image/png\" sizes=\"96x96\"\n    href=\"/images/favicons/favicon-96x96.png\">\n<link rel=\"icon\" type=\"image/png\" sizes=\"16x16\"\n    href=\"/images/favicons/favicon-16x16.png\">\n\n<link rel=\"manifest\" href=\"/images/favicons/manifest.json\">\n\n<meta name=\"msapplication-TileColor\" content=\"#ffffff\">\n<meta name=\"msapplication-TileImage\"\n    content=\"/images/favicons/ms-icon-144x144.png\">\n<meta name=\"theme-color\" content=\"#ffffff\">\n"
  },
  {
    "path": "docs/_includes/footer.html",
    "content": "<footer class=\"site-footer\">\n\n  <div class=\"wrapper\">\n\n    <h2 class=\"footer-heading\">{{ site.title }}</h2>\n\n    <div class=\"footer-col-wrapper\">\n      <div class=\"footer-col footer-col-1\">\n        <ul class=\"contact-list\">\n          <li><a href=\"http://wemake.services\">wemake.services</a></li>\n          <li><a href=\"mailto:{{ site.email }}\">{{ site.email }}</a></li>\n        </ul>\n      </div>\n\n      <div class=\"footer-col footer-col-2\">\n        <ul class=\"social-media-list\">\n          {% if site.github_username %}\n          <li>\n            {% include icon-github.html username=site.github_username %}\n          </li>\n          {% endif %}\n\n          {% if site.twitter_username %}\n          <li>\n            {% include icon-twitter.html username=site.twitter_username %}\n          </li>\n          {% endif %}\n        </ul>\n      </div>\n\n      <div class=\"footer-col footer-col-3\">\n        <p>{{ site.description }}</p>\n      </div>\n    </div>\n\n  </div>\n\n</footer>\n"
  },
  {
    "path": "docs/_includes/head.html",
    "content": "<head>\n  <meta charset=\"utf-8\">\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n\n  <title>{% if page.title %}{{ page.title }}{% else %}{{ site.title }}{% endif %}</title>\n  <meta name=\"description\" content=\"{% if page.excerpt %}{{ page.excerpt | strip_html | strip_newlines | truncate: 160 }}{% else %}{{ site.description }}{% endif %}\">\n\n  <link rel=\"stylesheet\" href=\"{{ \"/css/main.css\" | prepend: site.baseurl }}\">\n  <link rel=\"canonical\"\n    href=\"{{ page.url | replace:'index.html','' | prepend: site.baseurl | prepend: site.url }}\">\n  <link rel=\"alternate\" type=\"application/rss+xml\" title=\"{{ site.title }}\"\n    href=\"{{ \"/feed.xml\" | prepend: site.baseurl | prepend: site.url }}\">\n\n  {% include favicons.html %}\n\n  {% seo %}\n</head>\n"
  },
  {
    "path": "docs/_includes/header.html",
    "content": "<header class=\"site-header\">\n\n  <div class=\"wrapper\">\n\n    <a class=\"site-title\" href=\"{{ site.baseurl }}/\">\n      {{ site.title }} v{% include version.txt %}\n    </a>\n\n    <div class=\"site-nav\">\n      <a href=\"#\" class=\"menu-icon\">\n        <svg viewBox=\"0 0 18 15\">\n          <path fill=\"#424242\" d=\"M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.031C17.335,0,18,0.665,18,1.484L18,1.484z\"/>\n          <path fill=\"#424242\" d=\"M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0c0-0.82,0.665-1.484,1.484-1.484 h15.031C17.335,6.031,18,6.696,18,7.516L18,7.516z\"/>\n          <path fill=\"#424242\" d=\"M18,13.516C18,14.335,17.335,15,16.516,15H1.484C0.665,15,0,14.335,0,13.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.031C17.335,12.031,18,12.696,18,13.516L18,13.516z\"/>\n        </svg>\n      </a>\n\n      <div class=\"trigger\">\n        <!-- Place this tag where you want the button to render. -->\n        <a class=\"github-button\" href=\"https://github.com/sobolevn/git-secret\" data-icon=\"octicon-star\" data-size=\"large\" data-show-count=\"true\" aria-label=\"Star git-secret on GitHub\">\n          Star\n        </a>\n      </div>\n    </div>\n\n  </div>\n\n  <nav class=\"site-navigation\">\n    <a href=\"{{ \"/installation\" | prepend: site.baseurl }}\">Installation</a>\n    <a href=\"{{ \"/#commands\" | prepend: site.baseurl }}\">Commands</a>\n    <a href=\"{{ \"/plugins\" | prepend: site.baseurl }}\">External plugins</a>\n    <a href=\"{{ site.github_changelog }}\">Changelog</a>\n  </nav>\n\n</header>\n\n<!-- Required for GitHub buttons. -->\n<script async defer src=\"https://buttons.github.io/buttons.js\"></script>\n"
  },
  {
    "path": "docs/_includes/icon-github.html",
    "content": "<a href=\"https://github.com/{{ include.username }}\">\n    <span class=\"icon icon--github\">{% include icon-github.svg %}</span>\n    <span class=\"username\">{{ include.username }}</span>\n</a>\n"
  },
  {
    "path": "docs/_includes/icon-twitter.html",
    "content": "<a href=\"https://twitter.com/{{ include.username }}\">\n    <span class=\"icon icon--twitter\">{% include icon-twitter.svg %}</span>\n    <span class=\"username\">{{ include.username }}</span>\n</a>\n"
  },
  {
    "path": "docs/_includes/why.md",
    "content": "\n## Intro\n\nThere's a well known issue with deploying and configuring software on servers: \ngenerally you have to store your private data \n(such as database passwords, application secret-keys, OAuth secret keys, etc) \noutside of the git repository. \n\nIf you do choose to store these secrets unencrypted in your git repo, \neven if the repository is private, it is a security risk to copy \nthe secrets everywhere you check out your repo.\n\nWhat are some drawbacks of storing secrets separately from your git repo?\n\n1. These files are not version controlled. \nFilenames, locations, and passwords change from time to time,\nor new information appears, and other information is removed. \nWhen secrets are stored separately from your repo,\nyou can not tell for sure which version of the configuration file was used with each commit\nor deploy.\n\n2. When building the automated deployment system there will be one extra step: \ndownload and place these secret-configuration files where they need to be. \nThis also means you have to maintain extra secure servers where all your secrets are stored.\n\n\n### How does `git-secret` solve these problems?\n\n1. `git-secret` encrypts files and stores them inside your `git` repository, providing a history of changes for every commit.\n2. `git-secret` doesn't require any extra deploy operations other than providing the appropriate\nprivate key (to allow decryption), and using `git secret reveal`\nto decrypt all the secret files.\n\n### What is `git-secret`?\n\n`git-secret` is a bash tool to store your private data inside a `git` repo. \n\nHow's that? Basically, it uses `gpg` to encrypt files with the \npublic keys of the users that you trust, and which you have specified with\n`git secret tell email@address.id`.\nThen these users can decrypt these files using their personal secret key. \n\nWhy deal with all this private/public key stuff? \nTo make it easier to manage access rights. \nWhen you want to remove someone's access, use `git secret removeperson email@address.id`\nto delete their public key from your repo's git-secret keyring, and reencrypt the files. \nThen they won't be able to decrypt secrets anymore.\n\n[![git-secret terminal preview](https://raw.githubusercontent.com/sobolevn/git-secret/master/git-secret.gif)](https://asciinema.org/a/41811?autoplay=1)\n"
  },
  {
    "path": "docs/_layouts/default.html",
    "content": "<!DOCTYPE html>\n<html>\n\n  {% include head.html %}\n\n  <body>\n\n    {% include header.html %}\n\n    <div class=\"page-content\">\n      <div class=\"wrapper\">\n        {{ content }}\n      </div>\n    </div>\n\n    {% include footer.html %}\n\n    <!-- Place this tag in your head or just before your close body tag. -->\n    <script async defer src=\"https://buttons.github.io/buttons.js\"></script>\n  </body>\n\n</html>\n"
  },
  {
    "path": "docs/_layouts/page.html",
    "content": "---\nlayout: default\n---\n<article class=\"post\">\n\n  <header class=\"post-header\">\n    <h1 class=\"post-title\">{{ page.title }}</h1>\n  </header>\n\n  <div class=\"post-content\">\n    {{ content }}\n  </div>\n\n</article>\n"
  },
  {
    "path": "docs/_layouts/post.html",
    "content": "---\nlayout: default\n---\n<article class=\"post\" itemscope itemtype=\"http://schema.org/BlogPosting\">\n\n  <header class=\"post-header\">\n    <h1 class=\"post-title\" itemprop=\"name headline\">\n        {{ page.title }}\n    </h1>\n\n    <p class=\"post-meta\">\n        <time datetime=\"{{ page.date | date_to_xmlschema }}\" itemprop=\"datePublished\">\n            {{ page.date | date: \"%b %-d, %Y\" }}\n        </time>\n\n        {% if page.author %}\n            • <span itemprop=\"author\" itemscope itemtype=\"http://schema.org/Person\">\n                <span itemprop=\"name\">\n                    {{ page.author }}\n                </span>\n            </span>\n        {% endif %}\n    </p>\n  </header>\n\n  <div class=\"post-content\" itemprop=\"articleBody\">\n    {{ content }}\n  </div>\n\n</article>\n"
  },
  {
    "path": "docs/_sass/_base.scss",
    "content": "/**\n * Reset some basic elements\n */\nbody, h1, h2, h3, h4, h5, h6,\np, blockquote, pre, hr,\ndl, dd, ol, ul, figure {\n    margin: 0;\n    padding: 0;\n}\n\n\n\n/**\n * Basic styling\n */\nbody {\n    font: $base-font-weight #{$base-font-size}/#{$base-line-height} $base-font-family;\n    color: $text-color;\n    background-color: $background-color;\n    -webkit-text-size-adjust: 100%;\n    -webkit-font-feature-settings: \"kern\" 1;\n    -moz-font-feature-settings: \"kern\" 1;\n    -o-font-feature-settings: \"kern\" 1;\n    font-feature-settings: \"kern\" 1;\n    font-kerning: normal;\n}\n\n\n\n/**\n * Set `margin-bottom` to maintain vertical rhythm\n */\nh1, h2, h3, h4, h5, h6,\np, blockquote, pre,\nul, ol, dl, figure,\n%vertical-rhythm {\n    margin-bottom: $spacing-unit / 2;\n}\n\n\n\n/**\n * Images\n */\nimg {\n    max-width: 100%;\n    vertical-align: middle;\n}\n\n\n\n/**\n * Figures\n */\nfigure > img {\n    display: block;\n}\n\nfigcaption {\n    font-size: $small-font-size;\n}\n\n\n\n/**\n * Lists\n */\nul, ol {\n    margin-left: $spacing-unit;\n}\n\nli {\n    > ul,\n    > ol {\n         margin-bottom: 0;\n    }\n}\n\n\n\n/**\n * Headings\n */\nh1, h2, h3, h4, h5, h6 {\n    font-weight: $base-font-weight;\n}\n\n\n\n/**\n * Links\n */\na {\n    color: $brand-color;\n    text-decoration: none;\n\n    &:visited {\n        color: darken($brand-color, 15%);\n    }\n\n    &:hover {\n        color: $text-color;\n        text-decoration: underline;\n    }\n}\n\n\n\n/**\n * Blockquotes\n */\nblockquote {\n    color: $purple-color;\n    border-left: 4px solid $purple-color-light;\n    padding-left: $spacing-unit / 2;\n    font-size: 18px;\n    letter-spacing: -1px;\n    font-style: italic;\n\n    > :last-child {\n        margin-bottom: 0;\n    }\n}\n\n\n\n/**\n * Code formatting\n */\npre,\ncode {\n    font-size: 15px;\n    border: 1px solid $purple-color-light;\n    border-radius: 3px;\n    background-color: #eef;\n}\n\ncode {\n    padding: 1px 5px;\n}\n\npre {\n    padding: 8px 12px;\n    overflow-x: auto;\n\n    > code {\n        border: 0;\n        padding-right: 0;\n        padding-left: 0;\n    }\n}\n\n\n\n/**\n * Wrapper\n */\n.wrapper {\n    max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit} * 2));\n    max-width:         calc(#{$content-width} - (#{$spacing-unit} * 2));\n    margin-right: auto;\n    margin-left: auto;\n    padding-right: $spacing-unit;\n    padding-left: $spacing-unit;\n    @extend %clearfix;\n\n    @include media-query($on-laptop) {\n        max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit}));\n        max-width:         calc(#{$content-width} - (#{$spacing-unit}));\n        padding-right: $spacing-unit / 2;\n        padding-left: $spacing-unit / 2;\n    }\n}\n\n\n\n/**\n * Clearfix\n */\n%clearfix {\n\n    &:after {\n        content: \"\";\n        display: table;\n        clear: both;\n    }\n}\n\n\n\n/**\n * Icons\n */\n.icon {\n\n    > svg {\n        display: inline-block;\n        width: 16px;\n        height: 16px;\n        vertical-align: middle;\n\n        path {\n            fill: $purple-color;\n        }\n    }\n}\n"
  },
  {
    "path": "docs/_sass/_layout.scss",
    "content": "/**\n * Site header\n */\n.site-header {\n    border-top: 5px solid $purple-color-dark;\n    border-bottom: 1px solid $purple-color-light;\n    min-height: 56px;\n\n    // Positioning context for the mobile navigation icon\n    position: relative;\n}\n\n.site-title {\n    font-size: 26px;\n    font-weight: 300;\n    line-height: 56px;\n    letter-spacing: -1px;\n    margin-bottom: 0;\n    float: left;\n\n    &,\n    &:visited {\n        color: $purple-color-dark;\n    }\n}\n\n.site-nav {\n    @extend %clearfix;\n    float: right;\n    line-height: 56px;\n\n    .menu-icon {\n        display: none;\n    }\n\n    .page-link {\n        color: $text-color;\n        line-height: $base-line-height;\n\n        // Gaps between nav items, but not on the last one\n        &:not(:last-child) {\n            margin-right: 20px;\n        }\n    }\n\n    @include media-query($on-palm) {\n        position: absolute;\n        top: 9px;\n        right: $spacing-unit / 2;\n        background-color: $background-color;\n        border: 1px solid $purple-color-light;\n        border-radius: 5px;\n        text-align: right;\n\n        .menu-icon {\n            display: block;\n            float: right;\n            width: 36px;\n            height: 26px;\n            line-height: 0;\n            padding-top: 10px;\n            text-align: center;\n\n            > svg {\n                width: 18px;\n                height: 15px;\n\n                path {\n                    fill: $purple-color-dark;\n                }\n            }\n        }\n\n        .trigger {\n            clear: both;\n            display: none;\n        }\n\n        &:hover .trigger, &:active .trigger {\n            display: block;\n            padding-bottom: 5px;\n        }\n\n        .page-link {\n            display: block;\n            padding: 5px 10px;\n\n            &:not(:last-child) {\n                margin-right: 0;\n            }\n            margin-left: 20px;\n        }\n    }\n\n    .trigger {\n        padding-top: 13px;\n    }\n}\n\n\n\n/**\n * Site footer\n */\n.site-footer {\n    border-top: 1px solid $purple-color-light;\n    padding: $spacing-unit 0;\n}\n\n.footer-heading {\n    font-size: 18px;\n    margin-bottom: $spacing-unit / 2;\n}\n\n.contact-list,\n.social-media-list {\n    list-style: none;\n    margin-left: 0;\n}\n\n.footer-col-wrapper {\n    font-size: 15px;\n    color: $grey-color;\n    margin-left: -$spacing-unit / 2;\n    @extend %clearfix;\n}\n\n.footer-col {\n    float: left;\n    margin-bottom: $spacing-unit / 2;\n    padding-left: $spacing-unit / 2;\n}\n\n.footer-col-1 {\n    width: -webkit-calc(35% - (#{$spacing-unit} / 2));\n    width:         calc(35% - (#{$spacing-unit} / 2));\n}\n\n.footer-col-2 {\n    width: -webkit-calc(20% - (#{$spacing-unit} / 2));\n    width:         calc(20% - (#{$spacing-unit} / 2));\n}\n\n.footer-col-3 {\n    width: -webkit-calc(45% - (#{$spacing-unit} / 2));\n    width:         calc(45% - (#{$spacing-unit} / 2));\n}\n\n@include media-query($on-laptop) {\n    .footer-col-1,\n    .footer-col-2 {\n        width: -webkit-calc(50% - (#{$spacing-unit} / 2));\n        width:         calc(50% - (#{$spacing-unit} / 2));\n    }\n\n    .footer-col-3 {\n        width: -webkit-calc(100% - (#{$spacing-unit} / 2));\n        width:         calc(100% - (#{$spacing-unit} / 2));\n    }\n}\n\n@include media-query($on-palm) {\n    .footer-col {\n        float: none;\n        width: -webkit-calc(100% - (#{$spacing-unit} / 2));\n        width:         calc(100% - (#{$spacing-unit} / 2));\n    }\n}\n\n\n\n/**\n * Page content\n */\n.page-content {\n    padding: $spacing-unit 0;\n}\n\n.page-heading {\n    font-size: 20px;\n}\n\n.post-list {\n    li {\n        margin-bottom: 10px;\n    }\n}\n\n.post-meta {\n    font-size: $small-font-size;\n    color: $grey-color;\n}\n\n.post-link {\n    display: block;\n    font-size: 24px;\n}\n\n\n\n/**\n * Posts\n */\n.post-header {\n    margin-bottom: $spacing-unit;\n}\n\n.post-title {\n    font-size: 42px;\n    letter-spacing: -1px;\n    line-height: 1;\n\n    @include media-query($on-laptop) {\n        font-size: 36px;\n    }\n}\n\n.post-content {\n    margin-bottom: $spacing-unit;\n\n    h2 {\n        font-size: 32px;\n\n        @include media-query($on-laptop) {\n            font-size: 28px;\n        }\n    }\n\n    h3 {\n        font-size: 26px;\n\n        @include media-query($on-laptop) {\n            font-size: 22px;\n        }\n    }\n\n    h4 {\n        font-size: 20px;\n\n        @include media-query($on-laptop) {\n            font-size: 18px;\n        }\n    }\n}\n\n\n/**\n * Navigation\n */\n.site-navigation {\n    @extend .wrapper;\n\n    display: flex;\n    justify-content: space-between;\n    flex-wrap: wrap;\n\n    a {\n        color: $purple-color-dark;\n\n        @include media-query($on-laptop) {\n            flex-basis: 100%;\n            text-align: center;\n        }\n    }\n}\n\n\n/**\n * Homepage\n */\n .home {\n    .home-logo-image {\n        margin-top: 50px;\n        margin-bottom: 70px;\n    }\n }\n"
  },
  {
    "path": "docs/_sass/_syntax-highlighting.scss",
    "content": "/**\n * Syntax highlighting styles\n */\n.highlight {\n    background: #fff;\n    @extend %vertical-rhythm;\n\n    .highlighter-rouge & {\n      background: #eef;\n    }\n\n    .c     { color: #998; font-style: italic } // Comment\n    .err   { color: #a61717; background-color: #e3d2d2 } // Error\n    .k     { font-weight: bold } // Keyword\n    .o     { font-weight: bold } // Operator\n    .cm    { color: #998; font-style: italic } // Comment.Multiline\n    .cp    { color: #999; font-weight: bold } // Comment.Preproc\n    .c1    { color: #998; font-style: italic } // Comment.Single\n    .cs    { color: #999; font-weight: bold; font-style: italic } // Comment.Special\n    .gd    { color: #000; background-color: #fdd } // Generic.Deleted\n    .gd .x { color: #000; background-color: #faa } // Generic.Deleted.Specific\n    .ge    { font-style: italic } // Generic.Emph\n    .gr    { color: #a00 } // Generic.Error\n    .gh    { color: #999 } // Generic.Heading\n    .gi    { color: #000; background-color: #dfd } // Generic.Inserted\n    .gi .x { color: #000; background-color: #afa } // Generic.Inserted.Specific\n    .go    { color: #888 } // Generic.Output\n    .gp    { color: #555 } // Generic.Prompt\n    .gs    { font-weight: bold } // Generic.Strong\n    .gu    { color: #aaa } // Generic.Subheading\n    .gt    { color: #a00 } // Generic.Traceback\n    .kc    { font-weight: bold } // Keyword.Constant\n    .kd    { font-weight: bold } // Keyword.Declaration\n    .kp    { font-weight: bold } // Keyword.Pseudo\n    .kr    { font-weight: bold } // Keyword.Reserved\n    .kt    { color: #458; font-weight: bold } // Keyword.Type\n    .m     { color: #099 } // Literal.Number\n    .s     { color: #d14 } // Literal.String\n    .na    { color: #008080 } // Name.Attribute\n    .nb    { color: #0086B3 } // Name.Builtin\n    .nc    { color: #458; font-weight: bold } // Name.Class\n    .no    { color: #008080 } // Name.Constant\n    .ni    { color: #800080 } // Name.Entity\n    .ne    { color: #900; font-weight: bold } // Name.Exception\n    .nf    { color: #900; font-weight: bold } // Name.Function\n    .nn    { color: #555 } // Name.Namespace\n    .nt    { color: #000080 } // Name.Tag\n    .nv    { color: #008080 } // Name.Variable\n    .ow    { font-weight: bold } // Operator.Word\n    .w     { color: #bbb } // Text.Whitespace\n    .mf    { color: #099 } // Literal.Number.Float\n    .mh    { color: #099 } // Literal.Number.Hex\n    .mi    { color: #099 } // Literal.Number.Integer\n    .mo    { color: #099 } // Literal.Number.Oct\n    .sb    { color: #d14 } // Literal.String.Backtick\n    .sc    { color: #d14 } // Literal.String.Char\n    .sd    { color: #d14 } // Literal.String.Doc\n    .s2    { color: #d14 } // Literal.String.Double\n    .se    { color: #d14 } // Literal.String.Escape\n    .sh    { color: #d14 } // Literal.String.Heredoc\n    .si    { color: #d14 } // Literal.String.Interpol\n    .sx    { color: #d14 } // Literal.String.Other\n    .sr    { color: #009926 } // Literal.String.Regex\n    .s1    { color: #d14 } // Literal.String.Single\n    .ss    { color: #990073 } // Literal.String.Symbol\n    .bp    { color: #999 } // Name.Builtin.Pseudo\n    .vc    { color: #008080 } // Name.Variable.Class\n    .vg    { color: #008080 } // Name.Variable.Global\n    .vi    { color: #008080 } // Name.Variable.Instance\n    .il    { color: #099 } // Literal.Number.Integer.Long\n}\n"
  },
  {
    "path": "docs/build.sh",
    "content": "#!/usr/bin/env bash\n\n# Should be called from the root folder, not inside `docs/` folder\n# See `make build-docs`\n\nset -e\n\nMAN_LOCATION='man/man1'\nMAN7_LOCATION='man/man7'\nPOSTS_LOCATION='docs/_posts'\n\n\nfunction checkout_manuals {\n  cp -R man/ docs/man\n}\n\n\nfunction copy_to_posts {\n  # Cleaning old files:\n  rm -f \"$POSTS_LOCATION/*.md\"\n  rm -rf \"$POSTS_LOCATION\"\n  mkdir -p \"$POSTS_LOCATION\"\n\n  # Moving new command files:\n  local timestamp\n  local current_date\n\n  timestamp=$(date \"+%Y-%m-%d %H:%M:%S %z\")\n  current_date=$(date \"+%Y-%m-%d\")\n\n  # Creating command reference:\n  for com in \"$MAN_LOCATION\"/git-secret-*.1.md; do\n    local short_name\n    short_name=$(echo \"$com\" | sed -n \"s|$MAN_LOCATION/\\(.*\\)\\.1\\.md|\\1|p\")\n    local command_header=\"---\nlayout: post\ntitle: '${short_name}'\ndate: ${timestamp}\npermalink: ${short_name}\ncategories: command\n---\"\n\n    local post_filename=\"$POSTS_LOCATION/${current_date}-${short_name}.md\"\n    echo \"$command_header\" > \"$post_filename\"\n    cat \"$com\" >> \"$post_filename\"\n  done\n\n  # Creating main usage file:\n  local usage_header=\"---\nlayout: post\ntitle: 'git-secret'\ndate: ${timestamp}\npermalink: git-secret\ncategories: usage\n---\"\n  local usage_filename=\"$POSTS_LOCATION/${current_date}-git-secret.md\"\n  echo \"$usage_header\" > \"$usage_filename\"\n  cat \"$MAN7_LOCATION/git-secret.7.md\" >> \"$usage_filename\"\n}\n\n\nfunction copy_install_scripts {\n  # We test these scripts using `release-ci`,\n  # so, installation instructions will always be up-to-date:\n  cp utils/deb/install.sh docs/_includes/install-deb.sh\n  cp utils/rpm/install.sh docs/_includes/install-rpm.sh\n  cp utils/apk/install.sh docs/_includes/install-apk.sh\n}\n\n\nfunction copy_version {\n   ./git-secret --version > docs/_includes/version.txt\n}\n\n\ncheckout_manuals\ncopy_to_posts\ncopy_install_scripts\ncopy_version\n"
  },
  {
    "path": "docs/css/main.scss",
    "content": "---\n# Only the main Sass file needs front matter (the dashes are enough)\n---\n@charset \"utf-8\";\n\n\n\n// Our variables\n$base-font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n$base-font-size:   16px;\n$base-font-weight: 400;\n$small-font-size:  $base-font-size * 0.875;\n$base-line-height: 1.5;\n\n$spacing-unit:     30px;\n\n$text-color:       #111;\n$background-color: #fdfdfd;\n\n$grey-color:       #828282;\n$grey-color-light: lighten($grey-color, 40%);\n$grey-color-dark:  darken($grey-color, 25%);\n\n$purple-color:       rgb(238, 81, 59);\n$purple-color-light: lighten($purple-color, 40%);\n$purple-color-dark:  darken($purple-color, 25%);\n\n$brand-color:      $purple-color;\n\n// Width of the content area\n$content-width:    800px;\n\n$on-palm:          600px;\n$on-laptop:        800px;\n\n\n\n// Use media queries like this:\n// @include media-query($on-palm) {\n//     .wrapper {\n//         padding-right: $spacing-unit / 2;\n//         padding-left: $spacing-unit / 2;\n//     }\n// }\n@mixin media-query($device) {\n    @media screen and (max-width: $device) {\n        @content;\n    }\n}\n\n\n\n// Import partials from `sass_dir` (defaults to `_sass`)\n@import\n        \"base\",\n        \"layout\",\n        \"syntax-highlighting\"\n;\n"
  },
  {
    "path": "docs/feed.xml",
    "content": "---\nlayout: null\n---\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\">\n  <channel>\n    <title>{{ site.title | xml_escape }}</title>\n    <description>{{ site.description | xml_escape }}</description>\n    <link>{{ site.url }}{{ site.baseurl }}/</link>\n    <atom:link href=\"{{ \"/feed.xml\" | prepend: site.baseurl | prepend: site.url }}\" rel=\"self\" type=\"application/rss+xml\"/>\n    <pubDate>{{ site.time | date_to_rfc822 }}</pubDate>\n    <lastBuildDate>{{ site.time | date_to_rfc822 }}</lastBuildDate>\n    <generator>Jekyll v{{ jekyll.version }}</generator>\n    {% for post in site.posts limit:10 %}\n      <item>\n        <title>{{ post.title | xml_escape }}</title>\n        <description>{{ post.content | xml_escape }}</description>\n        <pubDate>{{ post.date | date_to_rfc822 }}</pubDate>\n        <link>{{ post.url | prepend: site.baseurl | prepend: site.url }}</link>\n        <guid isPermaLink=\"true\">{{ post.url | prepend: site.baseurl | prepend: site.url }}</guid>\n        {% for tag in post.tags %}\n        <category>{{ tag | xml_escape }}</category>\n        {% endfor %}\n        {% for cat in post.categories %}\n        <category>{{ cat | xml_escape }}</category>\n        {% endfor %}\n      </item>\n    {% endfor %}\n  </channel>\n</rss>\n"
  },
  {
    "path": "docs/images/favicons/browserconfig.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<browserconfig><msapplication><tile><square70x70logo src=\"/ms-icon-70x70.png\"/><square150x150logo src=\"/ms-icon-150x150.png\"/><square310x310logo src=\"/ms-icon-310x310.png\"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>"
  },
  {
    "path": "docs/images/favicons/manifest.json",
    "content": "{\n \"name\": \"App\",\n \"icons\": [\n  {\n   \"src\": \"\\/android-icon-36x36.png\",\n   \"sizes\": \"36x36\",\n   \"type\": \"image\\/png\",\n   \"density\": \"0.75\"\n  },\n  {\n   \"src\": \"\\/android-icon-48x48.png\",\n   \"sizes\": \"48x48\",\n   \"type\": \"image\\/png\",\n   \"density\": \"1.0\"\n  },\n  {\n   \"src\": \"\\/android-icon-72x72.png\",\n   \"sizes\": \"72x72\",\n   \"type\": \"image\\/png\",\n   \"density\": \"1.5\"\n  },\n  {\n   \"src\": \"\\/android-icon-96x96.png\",\n   \"sizes\": \"96x96\",\n   \"type\": \"image\\/png\",\n   \"density\": \"2.0\"\n  },\n  {\n   \"src\": \"\\/android-icon-144x144.png\",\n   \"sizes\": \"144x144\",\n   \"type\": \"image\\/png\",\n   \"density\": \"3.0\"\n  },\n  {\n   \"src\": \"\\/android-icon-192x192.png\",\n   \"sizes\": \"192x192\",\n   \"type\": \"image\\/png\",\n   \"density\": \"4.0\"\n  }\n ]\n}"
  },
  {
    "path": "docs/index.html",
    "content": "---\nlayout: default\n---\n\n<div class=\"home\">\n\n  <img src=\"{{ \"/images/git-secret-big.png\" | prepend: site.baseurl }}\"\n       alt=\"git-secret\"\n       title=\"git-secret\"\n       class=\"home-logo-image\" />\n\n  <h1>Synopsis</h1>\n\n  {% capture markdown_file %}\n    {% include why.md %}\n  {% endcapture %}\n\n  {{ markdown_file | markdownify }}\n\n  {% for post in site.categories.usage %}\n    {{ post.content }}\n  {% endfor %}\n\n  <h2 class=\"page-heading\" id=\"commands\">Command Reference</h2>\n\n  <ul class=\"post-list\">\n    {% for post in site.categories.command %}\n      <li>\n        <h2>\n          <a class=\"post-link\" href=\"{{ post.url | prepend: site.baseurl }}\">\n            {{ post.title }}\n          </a>\n        </h2>\n      </li>\n    {% endfor %}\n  </ul>\n\n  <p class=\"rss-subscribe\">\n    subscribe\n    <a href=\"{{ \"/feed.xml\" | prepend: site.baseurl }}\">via RSS</a>\n  </p>\n\n</div>\n"
  },
  {
    "path": "docs/installation.md",
    "content": "---\nlayout: default\n---\n\n# Installation\n\n## Dependencies\n\n`git-secret` relies on two dependencies: `git` and `gpg`. Download and install them before using this project. `git-secret` is tested to work with:\n\n```\ngit version 2.7.0\ngpg (GnuPG) 1.4.20\n```\n\n## Supported platforms\n\n`git-secret` is tested with `Mac OS X` >= 10.9, `Ubuntu` >= 14.04, `Debian` >= 8.3, \n`Fedora` / `Rocky Linux` / `AlmaLinux`, `FreeBSD`, and `Windows` >= 10 using `WSL`.\nYou can check the full list of automated test platforms\n[here](https://github.com/sobolevn/git-secret/blob/master/.github/workflows/test.yml).\n\nWe are always interested in getting `git-secret` working and tested on additional systems.\nIf you get `git-secret` working on a new system and the tests pass for you, \nyou can add a GitHub Action to test your platform to that file. \nAlso we welcome improvements to tests or `git-secret` code for any platform.\n\n## Installation process\n\nThere are several ways to install `git-secret`, depending on your OS and distribution.\nThey generally all have different installation processes, so we only go into \na short explanation of each. \n(We welcome documentation improvements.)\n\n---\n\n### Mac OS X / Homebrew\n\nThis is a packaging system for OSX. To install `git-secret` on OSX, you can install\n`homebrew` and then use:\n\n```bash\nbrew install git-secret\n````\n\n---\n\n### Debian-Type Systems / `deb` package\n\n`deb` is a packaging system for [Debian](https://www.debian.org/) and related linux\ndistributions.\n\nYou can find the `deb` repository [here](https://gitsecret.jfrog.io/artifactory/git-secret-deb/).\nPre-requirements: make sure you have installed `apt-transport-https` and `ca-certificates`\n\n```bash\n{% include install-deb.sh %}\n```\n\n---\n\n### Red Hat Systems / `rpm` package\n\n`rpm` is a packaging system for Fedora, CentOS, and other Red Hat based linux distributions.\nYou can find the `rpm` repository [here](https://gitsecret.jfrog.io/artifactory/git-secret-rpm/).\n\n```bash\n{% include install-rpm.sh %}\n```\n\n---\n\n### Alpine Systems / `apk` package\n\n`apk` is a packaging system for Alpine.\nYou can find the `apk` `git-secret` packaging \n[here](https://gitsecret.jfrog.io/artifactory/git-secret-apk/),\nand you can see a list of supported architectures \n[here](https://github.com/sobolevn/git-secret/blob/master/utils/apk/meta.sh)\n\n```bash\n{% include install-apk.sh %}\n```\n\n---\n\n### Arch Linux\n\nUse `Manual Installation` method described below.\n\n---\n\n### Windows / `WSL`, `Cygwin`, `MSYS`, or `Mingw-w64`\n\n`git-secret` depends on many unix tools and features that Windows systems do not usually\ninclude by default.  Therefore to get `git-secret` running on Windows you have to \ninstall these tools, probably using one of the toolkits described below. \nEach has a different install and setup process. There may also be other \nways to install the unix prerequisites on Windows.\n\nOnce the prerequisite unix tools are installed,\nyou can use the Manual Installation instructions below to \nmanually install `git-secret` (see below).  \n\nSome ways to install the required unix tools on windows include\nWSL, CYGWIN, MSYS, and Mingw-w64 \n(internally, these tools may share some components).\n\nDocumenting how each is installed and used is beyond the scope of this document, \nso we will cover the topic in broad strokes. Improvements to this documentation\n(or any other git-secret documentation) are welcome. \n\nAgain, after you install the unix tools needed, you can install \n`git-secret` on windows using the `Manual Installation` steps below.\n\n#### WSL\n\nPerhaps the easiest way to get `git-secret` operating on windows is using `WSL`\n(if your system supports it). \nHere are instructions to install [WSL](https://docs.microsoft.com/en-us/windows/wsl/install)\nYou'll need to install these additional packages: `gnupg`, `make`, `man`, `git`, `gawk`, `file`.\n\nWe have successfully set up automated testing of `git-secret` on `WSL`, \nso we are confident this method works.\n\n#### Mingw-w64\n\nAnother way to install the prerequisites for `git-secret` on Windows is to use \n[Mingw-w64](https://www.mingw-w64.org/) and install the needed packages.\nBy default, the `Mingw-w64` installation will be saved to `C:\\msys64`. You'll need to \ninstall `make` and probably other tools such as `gnupg`, `make`, `man`, `git`, and `gawk`. \n(This list might not be complete). \n\n#### MSYS and Cygwin\n\n`git-secret` also works with [MSYS](https://www.msys2.org/)\nand [Cygwin](https://www.cygwin.com/), and we have gotten _most_ of the way to getting\n`git-secret`'s self-tests running on these setups with Windows (see \n[windows-related issues](https://github.com/sobolevn/git-secret/issues?q=is%3Aissue+is%3Aopen+windows)).\n\nWe welcome contributions to `git-secret` and its documentation .\n\n---\n\n### Manual Installation\n\n```bash\ngit clone https://github.com/sobolevn/git-secret.git git-secret\ncd git-secret && make build\nPREFIX=\"/usr/local\" make install\n```\n\nNote that you can change `PREFIX` to be any directory you subsequently include in in your `PATH`\nenvironment variable. We generally recommend you stick to the default \ninstall locations for simplicity, but if you know what you're doing you are welcome to change it.\n\n"
  },
  {
    "path": "docs/plugins.md",
    "content": "---\nlayout: default\n---\n\n# External plugins\n\nHere's a list of external plugins for `git-secret` developed by other awesome developers:\n\n- [git-secret-diff](https://github.com/msilvestre/git-secret-diff) adds `git secret diff` command similar to `git diff` to see changes in your secrets in different commits\n"
  },
  {
    "path": "man/man1/git-secret-add.1",
    "content": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-ADD\" \"1\" \"May 2022\" \"sobolevn\" \"git-secret 0.5.1-alpha1\"\n.\n.SH \"NAME\"\n\\fBgit\\-secret\\-add\\fR \\- starts to track added files\\.\n.\n.SH \"SYNOPSIS\"\n.\n.nf\n\ngit secret add [\\-v] [\\-i] <pathspec>\\.\\.\\.\n.\n.fi\n.\n.SH \"DESCRIPTION\"\n\\fBgit secret add\\fR \\- tells \\fBgit secret\\fR which files hold secrets\\.\n.\n.P\nAdds filepath(s) into \\fB\\.gitsecret/paths/mapping\\.cfg\\fR\\. (It is not recommended to alter \\fB\\.gitsecret/paths/mapping\\.cfg\\fR manually\\.)\n.\n.P\nAs of 0\\.2\\.6, this command also ensures the filepath is in \\fB\\.gitignore\\fR as the contents are now considered secret and should not be committed into the repository unencrypted\\.\n.\n.P\nThe \\fBadd\\fR action will fail unless there are already users in \\fBgit\\-secret\\fR\\'s keyring\\.\n.\n.P\n(See git\\-secret(7) \\fIhttps://git\\-secret\\.io/git\\-secret\\fR for information about renaming the \\.gitsecret folder using the SECRETS_DIR environment variable\\.\n.\n.SH \"OPTIONS\"\n.\n.nf\n\n\\-v  \\- verbose, shows extra information\\.\n\\-i  \\- does nothing, adding paths to \\.gitignore is now the default behavior\\.\n\\-h  \\- shows this help\\.\n.\n.fi\n.\n.SH \"MANUAL\"\nRun \\fBman git\\-secret\\-add\\fR to see this document\\.\n.\n.SH \"SEE ALSO\"\ngit\\-secret\\-init(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-init\\fR, git\\-secret\\-tell(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-tell\\fR, git\\-secret\\-hide(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-hide\\fR, git\\-secret\\-reveal(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-reveal\\fR\n"
  },
  {
    "path": "man/man1/git-secret-add.1.md",
    "content": "git-secret-add - starts to track added files.\n=============================================\n\n## SYNOPSIS\n\n    git secret add [-v] [-i] <pathspec>...\n\n\n## DESCRIPTION\n`git secret add` - tells `git secret` which files hold secrets.\n\nAdds filepath(s) into `.gitsecret/paths/mapping.cfg`.\n(It is not recommended to alter `.gitsecret/paths/mapping.cfg` manually.)\n\nAs of 0.2.6, this command also ensures the filepath is in `.gitignore`\nas the contents are now considered secret and should not be committed into the repository unencrypted.\n\nThe `add` action will fail unless there are already users in `git-secret`'s keyring.\n\n\n(See [git-secret(7)](https://git-secret.io/git-secret) for information about renaming the .gitsecret\nfolder using the SECRETS_DIR environment variable.\n\n## OPTIONS\n\n    -v  - verbose, shows extra information.\n    -i  - does nothing, adding paths to .gitignore is now the default behavior.\n    -h  - shows this help.\n\n\n## MANUAL\n\nRun `man git-secret-add` to see this document.\n\n\n## SEE ALSO\n\n[git-secret-init(1)](https://git-secret.io/git-secret-init), [git-secret-tell(1)](https://git-secret.io/git-secret-tell),\n[git-secret-hide(1)](https://git-secret.io/git-secret-hide), [git-secret-reveal(1)](https://git-secret.io/git-secret-reveal)\n"
  },
  {
    "path": "man/man1/git-secret-cat.1",
    "content": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-CAT\" \"1\" \"May 2022\" \"sobolevn\" \"git-secret 0.5.1-alpha1\"\n.\n.SH \"NAME\"\n\\fBgit\\-secret\\-cat\\fR \\- decrypts files passed on command line to stdout\\.\n.\n.SH \"SYNOPSIS\"\n.\n.nf\n\ngit secret cat [\\-d dir] [\\-p password] filename [filenames]\n.\n.fi\n.\n.SH \"DESCRIPTION\"\n\\fBgit\\-secret\\-cat\\fR \\- prints the decrypted contents of the passed files\\.\n.\n.P\nAs with \\fBgit\\-secret\\-reveal\\fR, you\\'ll need to have the private key for one of the emails allowed to decrypt this repo in your personal keyring\\.\n.\n.P\nNote this command can be affected by the \\fBSECRETS_PINENTRY\\fR environment variable\\. See (See git\\-secret(7) \\fIhttps://git\\-secret\\.io/git\\-secret\\fR for information using \\fBSECRETS_PINENTRY\\fR\\.\n.\n.SH \"OPTIONS\"\n.\n.nf\n\n\\-d  \\- specifies `\\-\\-homedir` option for the `gpg`, use this option if you store your keys in a custom location\\.\n\\-p  \\- specifies password for noinput mode, adds `\\-\\-passphrase` option for `gpg`\\.\n\\-h  \\- shows help\\.\n.\n.fi\n.\n.SH \"MANUAL\"\nRun \\fBman git\\-secret\\-cat\\fR to see this document\\.\n.\n.SH \"SEE ALSO\"\ngit\\-secret\\-init(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-init\\fR, git\\-secret\\-tell(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-tell\\fR, git\\-secret\\-add(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-add\\fR, git\\-secret\\-hide(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-hide\\fR, git\\-secret\\-reveal(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-cat\\fR\n"
  },
  {
    "path": "man/man1/git-secret-cat.1.md",
    "content": "git-secret-cat - decrypts files passed on command line to stdout.\n=============================================\n\n## SYNOPSIS\n\n    git secret cat [-d dir] [-p password] filename [filenames]\n\n\n## DESCRIPTION\n`git-secret-cat` - prints the decrypted contents of the passed files.\n\nAs with `git-secret-reveal`, you'll need to have the private key for one of the emails allowed to\ndecrypt this repo in your personal keyring.\n\nNote this command can be affected by the `SECRETS_PINENTRY` environment variable. See\n(See [git-secret(7)](https://git-secret.io/git-secret) for information using `SECRETS_PINENTRY`.\n\n\n## OPTIONS\n\n    -d  - specifies `--homedir` option for the `gpg`, use this option if you store your keys in a custom location.\n    -p  - specifies password for noinput mode, adds `--passphrase` option for `gpg`.\n    -h  - shows help.\n\n\n## MANUAL\n\nRun `man git-secret-cat` to see this document.\n\n\n## SEE ALSO\n\n[git-secret-init(1)](https://git-secret.io/git-secret-init), [git-secret-tell(1)](https://git-secret.io/git-secret-tell), [git-secret-add(1)](https://git-secret.io/git-secret-add), [git-secret-hide(1)](https://git-secret.io/git-secret-hide), [git-secret-reveal(1)](https://git-secret.io/git-secret-cat)\n"
  },
  {
    "path": "man/man1/git-secret-changes.1",
    "content": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-CHANGES\" \"1\" \"May 2022\" \"sobolevn\" \"git-secret 0.5.1-alpha1\"\n.\n.SH \"NAME\"\n\\fBgit\\-secret\\-changes\\fR \\- view diff of the hidden files\\.\n.\n.SH \"SYNOPSIS\"\n.\n.nf\n\ngit secret changes [\\-h] [\\-d dir] [\\-p password] [pathspec]\\.\\.\\.\n.\n.fi\n.\n.SH \"DESCRIPTION\"\n\\fBgit\\-secret\\-changes\\fR \\- shows changes between the current versions of secret files and encrypted versions\\.\n.\n.P\nIf no filenames are provided, changes to all hidden files will be shown\\. Alternately, provide any number of hidden files to this command as arguments, and it will show changes for those files\\.\n.\n.P\nNote files must be specified by their unencrypted names, without the \\fB\\.secret\\fR suffix, (or whatever is specified by the \\fBSECRETS_EXTENSION\\fR environment variable)\\.\n.\n.P\nNote also this command can be affected by the \\fBSECRETS_PINENTRY\\fR environment variable\\. See (See git\\-secret(7) \\fIhttps://git\\-secret\\.io/git\\-secret\\fR for information using \\fBSECRETS_PINENTRY\\fR\\.\n.\n.SH \"OPTIONS\"\n.\n.nf\n\n\\-d  \\- specifies `\\-\\-homedir` option for the `gpg`\\. Use this option if you store your keys in a custom location\\.\n\\-p  \\- specifies password for noinput mode, adds `\\-\\-passphrase` option for `gpg`\\.\n\\-h  \\- shows help\\.\n.\n.fi\n.\n.SH \"MANUAL\"\nRun \\fBman git\\-secret\\-changes\\fR to see this document\\.\n.\n.SH \"SEE ALSO\"\ngit\\-secret\\-add(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-add\\fR, git\\-secret\\-tell(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-tell\\fR, git\\-secret\\-hide(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-hide\\fR, git\\-secret\\-reveal(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-reveal\\fR, git\\-secret\\-cat(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-cat\\fR\n"
  },
  {
    "path": "man/man1/git-secret-changes.1.md",
    "content": "git-secret-changes - view diff of the hidden files.\n===================================================\n\n## SYNOPSIS\n\n    git secret changes [-h] [-d dir] [-p password] [pathspec]...\n\n\n## DESCRIPTION\n`git-secret-changes` - shows changes between the current versions of secret files and encrypted versions.\n\nIf no filenames are provided, changes to all hidden files will be shown. Alternately,\nprovide any number of hidden files to this command as arguments, and it will show changes for those files.\n\nNote files must be specified by their unencrypted names, without the `.secret` suffix,\n(or whatever is specified by the `SECRETS_EXTENSION` environment variable).\n\nNote also this command can be affected by the `SECRETS_PINENTRY` environment variable. See\n(See [git-secret(7)](https://git-secret.io/git-secret) for information using `SECRETS_PINENTRY`.\n\n\n## OPTIONS\n\n    -d  - specifies `--homedir` option for the `gpg`. Use this option if you store your keys in a custom location.\n    -p  - specifies password for noinput mode, adds `--passphrase` option for `gpg`.\n    -h  - shows help.\n\n\n## MANUAL\n\nRun `man git-secret-changes` to see this document.\n\n\n## SEE ALSO\n\n[git-secret-add(1)](https://git-secret.io/git-secret-add), [git-secret-tell(1)](https://git-secret.io/git-secret-tell),\n[git-secret-hide(1)](https://git-secret.io/git-secret-hide), [git-secret-reveal(1)](https://git-secret.io/git-secret-reveal),\n[git-secret-cat(1)](https://git-secret.io/git-secret-cat)\n"
  },
  {
    "path": "man/man1/git-secret-clean.1",
    "content": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-CLEAN\" \"1\" \"May 2022\" \"sobolevn\" \"git-secret 0.5.1-alpha1\"\n.\n.SH \"NAME\"\n\\fBgit\\-secret\\-clean\\fR \\- removes all the hidden files\\.\n.\n.SH \"SYNOPSIS\"\n.\n.nf\n\ngit secret clean [\\-v]\n.\n.fi\n.\n.SH \"DESCRIPTION\"\n\\fBgit\\-secret\\-clean\\fR \\- deletes all files in the current \\fBgit\\-secret\\fR repo that end with \\fB\\.secret\\fR\\.\n.\n.P\nYou can change the extension \\fBgit\\-secret\\fR uses for encrypted files with the \\fBSECRETS_EXTENSION\\fR environment variable\\.\n.\n.P\nNote that it will delete any files ending in \\fB\\.secret\\fR, even if they are not tracked by \\fBgit\\-secret\\fR\\.\n.\n.P\nAlso note that this command does not delete unencrypted versions of files\\.\n.\n.P\nVerbose mode, enabled with the \\fB\\-v\\fR option, displays the filenames deleted\\.\n.\n.SH \"OPTIONS\"\n.\n.nf\n\n\\-v  \\- verbose mode, shows which files are deleted\\.\n\\-h  \\- shows this help\\.\n.\n.fi\n.\n.P\nYou can also enable verbosity using the SECRETS_VERBOSE environment variable, as documented at git\\-secret(7) \\fIhttps://git\\-secret\\.io/\\fR\n.\n.SH \"MANUAL\"\nRun \\fBman git\\-secret\\-clean\\fR to see this document\\.\n.\n.SH \"SEE ALSO\"\ngit\\-secret\\-whoknows(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-whoknows\\fR, git\\-secret\\-add(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-add\\fR, git\\-secret\\-remove(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-remove\\fR, git\\-secret\\-removeperson(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-removeperson\\fR\n"
  },
  {
    "path": "man/man1/git-secret-clean.1.md",
    "content": "git-secret-clean - removes all the hidden files.\n================================================\n\n## SYNOPSIS\n\n    git secret clean [-v]\n\n\n## DESCRIPTION\n`git-secret-clean` - deletes all files in the current `git-secret` repo that end with `.secret`.\n\nYou can change the extension `git-secret` uses for encrypted files\nwith the `SECRETS_EXTENSION` environment variable.\n\nNote that it will delete any files ending in `.secret`, even if they are not tracked by `git-secret`. \n\nAlso note that this command does not delete unencrypted versions of files.\n\nVerbose mode, enabled with the `-v` option, displays the filenames deleted.\n\n\n## OPTIONS\n\n    -v  - verbose mode, shows which files are deleted.\n    -h  - shows this help.\n\nYou can also enable verbosity using the SECRETS_VERBOSE environment variable,\nas documented at [git-secret(7)](https://git-secret.io/)\n\n## MANUAL\n\nRun `man git-secret-clean` to see this document.\n\n\n## SEE ALSO\n\n[git-secret-whoknows(1)](https://git-secret.io/git-secret-whoknows), [git-secret-add(1)](https://git-secret.io/git-secret-add),\n[git-secret-remove(1)](https://git-secret.io/git-secret-remove), [git-secret-removeperson(1)](https://git-secret.io/git-secret-removeperson)\n"
  },
  {
    "path": "man/man1/git-secret-hide.1",
    "content": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-HIDE\" \"1\" \"May 2022\" \"sobolevn\" \"git-secret 0.5.1-alpha1\"\n.\n.SH \"NAME\"\n\\fBgit\\-secret\\-hide\\fR \\- encrypts all added files with repo keyring\\.\n.\n.SH \"SYNOPSIS\"\n.\n.nf\n\ngit secret hide [\\-c] [\\-F] [\\-P] [\\-v] [\\-d] [\\-m]\n.\n.fi\n.\n.SH \"DESCRIPTION\"\n\\fBgit\\-secret\\-hide\\fR \\- writes an encrypted version of each file added by \\fBgit\\-secret\\-add\\fR command\\.\n.\n.P\nThen anyone enabled via \\fBgit secret tell\\fR can decrypt these files\\.\n.\n.P\nUnder the hood, \\fBgit\\-secret\\fR uses the keyring of public keys in \\fB\\.gitsecret/keys\\fR to \\fIencrypt\\fR files, encrypted versions are typically called \\fBfilename\\.txt\\.secret\\fR\\.\n.\n.P\nLater permitted users can use their secret key (typically from their home directory) to \\fIdecrypt\\fR files\\.\n.\n.P\nIt is recommended to encrypt (or re\\-encrypt) all the files in a \\fBgit\\-secret\\fR repo each time \\fBgit secret hide\\fR is run\\.\n.\n.br\nOtherwise the keyring (the one stored in \\fB\\.gitsecret/keys/*\\.gpg\\fR), may have changed since the last time the files were encrypted, and it\\'s possible to create a state where the users in the output of \\fBgit secret whoknows\\fR may not be able to decrypt the some files in the repo, or may be able decrypt files they\\'re not supposed to be able to\\.\n.\n.P\nIn other words, unless you re\\-encrypt all the files in a repo each time you \\fBhide\\fR any, it\\'s possible to make it so some files can no longer be decrypted by users who should be (and would appear) able to decrypt them, and vice\\-versa\\.\n.\n.P\nIf you know what you are doing and wish to encrypt or re\\-encrypt only a subset of the files even after reading the above paragraphs, you can use the \\fB\\-F\\fR or \\fB\\-m\\fR options\\. The \\fB\\-F\\fR option forces \\fBgit secret hide\\fR to skip any hidden files where the unencrypted versions aren\\'t present\\. The \\fB\\-m\\fR option skips any hidden files that have not be been modified since the last time they were encrypted\\.\n.\n.SH \"OPTIONS\"\n.\n.nf\n\n\\-v  \\- verbose, shows extra information\\.\n\\-c  \\- deletes encrypted files before creating new ones\\.\n\\-F  \\- forces hide to continue if a file to encrypt is missing\\.\n\\-P  \\- preserve permissions of unencrypted file in encrypted file\\.\n\\-d  \\- deletes unencrypted files after encryption\\.\n\\-m  \\- encrypt files only when modified\\.\n\\-h  \\- shows help\\.\n.\n.fi\n.\n.SH \"ENV VARIABLES\"\n.\n.IP \"\\(bu\" 4\n\\fBSECRETS_GPG_COMMAND\\fR changes the default \\fBgpg\\fR command to anything else\n.\n.IP \"\\(bu\" 4\n\\fBSECRETS_GPG_ARMOR\\fR is a boolean to enable \\fB\\-\\-armor\\fR mode \\fIhttps://www\\.gnupg\\.org/gph/en/manual/r1290\\.html\\fR to store secrets in text format over binary\n.\n.IP \"\\(bu\" 4\n\\fBSECRETS_DIR\\fR changes the default \\fB\\.gitsecret/\\fR folder to another name as documented at git\\-secret(7) \\fIhttps://git\\-secret\\.io/\\fR\n.\n.IP \"\\(bu\" 4\n\\fBSECRETS_EXTENSION\\fR changes the default \\fB\\.secret\\fR file extension\n.\n.IP \"\\(bu\" 4\n\\fBSECRETS_VERBOSE\\fR changes the output verbosity as documented at git\\-secret(7) \\fIhttps://git\\-secret\\.io/\\fR\n.\n.IP \"\\(bu\" 4\n\\fBSECRETS_PINENTRY\\fR changes the \\fBgpg \\-\\-pinentry\\fR mode \\fIhttps://github\\.com/gpg/pinentry\\fR as documented at git\\-secret(7) \\fIhttps://git\\-secret\\.io/\\fR\n.\n.IP \"\" 0\n.\n.SH \"MANUAL\"\nRun \\fBman git\\-secret\\-hide\\fR to see this document\\.\n.\n.SH \"SEE ALSO\"\ngit\\-secret\\-init(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-init\\fR, git\\-secret\\-tell(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-tell\\fR, git\\-secret\\-add(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-add\\fR, git\\-secret\\-reveal(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-reveal\\fR, git\\-secret\\-cat(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-cat\\fR\n"
  },
  {
    "path": "man/man1/git-secret-hide.1.md",
    "content": "git-secret-hide - encrypts all added files with repo keyring.\n==================================================================\n\n## SYNOPSIS\n\n    git secret hide [-c] [-F] [-P] [-v] [-d] [-m]\n\n\n## DESCRIPTION\n`git-secret-hide`  - writes an encrypted version of each file added by `git-secret-add` command.\n\nThen anyone enabled via `git secret tell` can decrypt these files. \n\nUnder the hood, `git-secret` uses the keyring of public keys in `.gitsecret/keys` to _encrypt_ files,\nencrypted versions are typically called `filename.txt.secret`.\n\nLater permitted users can use their secret key (typically from their home directory) to _decrypt_ files.\n\nIt is recommended to encrypt (or re-encrypt) all the files in a `git-secret` repo each\ntime `git secret hide` is run.  \nOtherwise the keyring (the one stored in `.gitsecret/keys/*.gpg`),\nmay have changed since the last time the files were encrypted, and it's possible\nto create a state where the users in the output of `git secret whoknows`\nmay not be able to decrypt the some files in the repo, or may be able decrypt files\nthey're not supposed to be able to.\n\nIn other words, unless you re-encrypt all the files in a repo each time you `hide` any,\nit's possible to make it so some files can no longer be decrypted by users who should be\n(and would appear) able to decrypt them, and vice-versa.\n\nIf you know what you are doing and wish\nto encrypt or re-encrypt only a subset of the files\neven after reading the above paragraphs, you can use the `-F` or `-m` options.\nThe `-F` option forces `git secret hide` to skip any hidden files\nwhere the unencrypted versions aren't present.\nThe `-m` option skips any hidden files that have\nnot be been modified since the last time they were encrypted.\n\n\n## OPTIONS\n\n    -v  - verbose, shows extra information.\n    -c  - deletes encrypted files before creating new ones.\n    -F  - forces hide to continue if a file to encrypt is missing.\n    -P  - preserve permissions of unencrypted file in encrypted file.\n    -d  - deletes unencrypted files after encryption.\n    -m  - encrypt files only when modified.\n    -h  - shows help.\n\n\n## ENV VARIABLES\n\n- `SECRETS_GPG_COMMAND` changes the default `gpg` command to anything else\n- `SECRETS_GPG_ARMOR` is a boolean to enable [`--armor` mode](https://www.gnupg.org/gph/en/manual/r1290.html) to store secrets in text format over binary\n- `SECRETS_DIR` changes the default `.gitsecret/` folder to another name as documented at [git-secret(7)](https://git-secret.io/)\n- `SECRETS_EXTENSION` changes the default `.secret` file extension\n- `SECRETS_VERBOSE` changes the output verbosity as documented at [git-secret(7)](https://git-secret.io/)\n- `SECRETS_PINENTRY` changes the [`gpg --pinentry` mode](https://github.com/gpg/pinentry) as documented at [git-secret(7)](https://git-secret.io/)\n\n\n## MANUAL\n\nRun `man git-secret-hide` to see this document.\n\n\n## SEE ALSO\n\n[git-secret-init(1)](https://git-secret.io/git-secret-init), [git-secret-tell(1)](https://git-secret.io/git-secret-tell),\n[git-secret-add(1)](https://git-secret.io/git-secret-add), [git-secret-reveal(1)](https://git-secret.io/git-secret-reveal),\n[git-secret-cat(1)](https://git-secret.io/git-secret-cat)\n"
  },
  {
    "path": "man/man1/git-secret-init.1",
    "content": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-INIT\" \"1\" \"May 2022\" \"sobolevn\" \"git-secret 0.5.1-alpha1\"\n.\n.SH \"NAME\"\n\\fBgit\\-secret\\-init\\fR \\- initializes git\\-secret repository\\.\n.\n.SH \"SYNOPSIS\"\n.\n.nf\n\ngit secret init\n.\n.fi\n.\n.SH \"DESCRIPTION\"\n\\fBgit\\-secret\\-init\\fR \\- initializes a \\fBgit\\-secret\\fR repo by setting up a \\fB\\.gitsecret\\fR directory\\.\n.\n.P\n\\fBgit\\-secret\\-init\\fR should be run inside a \\fBgit\\fR repo, to create the \\fB\\.gitsecret\\fR directory and initialize the repo for git\\-secret\\. Until a repository is initialized with \\fBgit secret init\\fR, all other \\fBgit\\-secret\\fR commands are unavailable\\.\n.\n.P\nIf a \\fB\\.gitsecret\\fR directory already exists, \\fBgit\\-secret\\-init\\fR exits without making any changes\\. Otherwise,\n.\n.IP \"\\(bu\" 4\n\\fB\\.gitignore\\fR is modified to ignore \\fBgit\\-secret\\fR\\'s \\fBrandom_seed_file\\fR, and to not ignore \\fB\\.secret\\fR files,\n.\n.IP \"\\(bu\" 4\na \\.gitsecret directory is created with the sub\\-directories /keys and /paths,\n.\n.IP \"\\(bu\" 4\nThe \\fB\\.gitsecret/keys\\fR subdirectory permission is set to 700 to make gnupg happy\\.\n.\n.IP \"\" 0\n.\n.P\nSee git\\-secret(7) \\fIhttps://git\\-secret\\.io/git\\-secret\\fR for information about renaming the \\.gitsecret folder with the \\fBSECRETS_DIR\\fR environment variable, and changing the extension \\fBgit\\-secret\\fR uses for secret files with the \\fBSECRETS_EXTENSION\\fR environment variable\\.\n.\n.SH \"OPTIONS\"\n.\n.nf\n\n\\-h  \\- shows this help\\.\n.\n.fi\n.\n.SH \"MANUAL\"\nRun \\fBman git\\-secret\\-init\\fR to see this document\\.\n.\n.SH \"SEE ALSO\"\ngit\\-secret\\-usage(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-usage\\fR, git\\-secret\\-tell(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-tell\\fR\n"
  },
  {
    "path": "man/man1/git-secret-init.1.md",
    "content": "git-secret-init - initializes git-secret repository.\n====================================================\n\n## SYNOPSIS\n\n    git secret init\n\n\n## DESCRIPTION\n`git-secret-init` - initializes a `git-secret` repo by setting up a `.gitsecret` directory.\n\n`git-secret-init` should be run inside a `git` repo, to create the \n`.gitsecret` directory and initialize the repo for git-secret.\nUntil a repository is initialized with `git secret init`, all other `git-secret` commands are unavailable.\n\nIf a `.gitsecret` directory already exists, `git-secret-init` exits without making any changes.\nOtherwise, \n\n* `.gitignore` is modified to ignore `git-secret`'s `random_seed_file`,\nand to not ignore `.secret` files,\n\n* a .gitsecret directory is created with the sub-directories /keys and /paths,\n\n* The `.gitsecret/keys` subdirectory permission is set to 700 to make gnupg happy.\n\nSee [git-secret(7)](https://git-secret.io/git-secret) for information about renaming the .gitsecret\nfolder with the `SECRETS_DIR` environment variable, and changing the extension `git-secret` uses for secret files\nwith the `SECRETS_EXTENSION` environment variable.\n\n\n## OPTIONS\n\n    -h  - shows this help.\n\n\n## MANUAL\n\nRun `man git-secret-init` to see this document.\n\n\n## SEE ALSO\n\n[git-secret-usage(1)](https://git-secret.io/git-secret-usage), [git-secret-tell(1)](https://git-secret.io/git-secret-tell)\n"
  },
  {
    "path": "man/man1/git-secret-list.1",
    "content": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-LIST\" \"1\" \"May 2022\" \"sobolevn\" \"git-secret 0.5.1-alpha1\"\n.\n.SH \"NAME\"\n\\fBgit\\-secret\\-list\\fR \\- prints all the added files\\.\n.\n.SH \"SYNOPSIS\"\n.\n.nf\n\ngit secret list\n.\n.fi\n.\n.SH \"DESCRIPTION\"\n\\fBgit\\-secret\\-list\\fR \\- print the files currently considered secret in this repo\\.\n.\n.P\nShows tracked files from \\fB\\.gitsecret/paths/mapping\\.cfg\\fR\\.\n.\n.P\n(See git\\-secret(7) \\fIhttps://git\\-secret\\.io/git\\-secret\\fR for information about renaming the \\.gitsecret folder using the \\fBSECRETS_DIR\\fR environment variable\\.\n.\n.SH \"OPTIONS\"\n.\n.nf\n\n\\-h  \\- shows this help\\.\n.\n.fi\n.\n.SH \"MANUAL\"\nRun \\fBman git\\-secret\\-list\\fR to see this document\\.\n.\n.SH \"SEE ALSO\"\ngit\\-secret\\-whoknows(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-whoknows\\fR, git\\-secret\\-add(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-add\\fR, git\\-secret\\-remove(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-remove\\fR, git\\-secret\\-hide(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-hide\\fR, git\\-secret\\-reveal(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-reveal\\fR, git\\-secret\\-cat(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-cat\\fR\n"
  },
  {
    "path": "man/man1/git-secret-list.1.md",
    "content": "git-secret-list - prints all the added files.\n=============================================\n\n## SYNOPSIS\n\n    git secret list\n\n\n## DESCRIPTION\n`git-secret-list` - print the files currently considered secret in this repo.\n\nShows tracked files from `.gitsecret/paths/mapping.cfg`.\n\n(See [git-secret(7)](https://git-secret.io/git-secret) for information about renaming the .gitsecret\nfolder using the `SECRETS_DIR` environment variable.\n\n\n## OPTIONS\n\n    -h  - shows this help.\n\n\n## MANUAL\n\nRun `man git-secret-list` to see this document.\n\n\n## SEE ALSO\n\n[git-secret-whoknows(1)](https://git-secret.io/git-secret-whoknows), [git-secret-add(1)](https://git-secret.io/git-secret-add),\n[git-secret-remove(1)](https://git-secret.io/git-secret-remove), [git-secret-hide(1)](https://git-secret.io/git-secret-hide),\n[git-secret-reveal(1)](https://git-secret.io/git-secret-reveal), [git-secret-cat(1)](https://git-secret.io/git-secret-cat)\n"
  },
  {
    "path": "man/man1/git-secret-remove.1",
    "content": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-REMOVE\" \"1\" \"May 2022\" \"sobolevn\" \"git-secret 0.5.1-alpha1\"\n.\n.SH \"NAME\"\n\\fBgit\\-secret\\-remove\\fR \\- removes files from index\\.\n.\n.SH \"SYNOPSIS\"\n.\n.nf\n\ngit secret remove [\\-c] <pathspec>\\.\\.\\.\n.\n.fi\n.\n.SH \"DESCRIPTION\"\n\\fBgit\\-secret\\-remove\\fR \\- stops files from being tracked by \\fBgit\\-secret\\fR\\.\n.\n.P\nThis deletes filenames from \\fB\\.gitsecret/paths/mapping\\.cfg\\fR, which stops these files from being tracked by \\fBgit\\-secret\\fR, and from being encrypted to, or decrypted from, \\fB\\.secret\\fR encrypted versions\\.\n.\n.P\nThere\\'s also a \\-c option to delete existing encrypted versions of the files provided\\.\n.\n.P\nNote unlike \\fBadd\\fR, which automatically add pathnames to \\fB\\.gitignore\\fR, \\fBremove\\fR does not delete pathnames from \\fB\\.gitignore\\fR\\.\n.\n.P\n(See git\\-secret(7) \\fIhttps://git\\-secret\\.io/git\\-secret\\fR for information about renaming the \\.gitsecret folder using the \\fBSECRETS_DIR\\fR environment variable\\.\n.\n.SH \"OPTIONS\"\n.\n.nf\n\n\\-c  \\- deletes existing real encrypted files\\.\n\\-h  \\- shows help\\.\n.\n.fi\n.\n.SH \"MANUAL\"\nRun \\fBman git\\-secret\\-remove\\fR to see this document\\.\n.\n.SH \"SEE ALSO\"\ngit\\-secret\\-add(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-add\\fR, git\\-secret\\-clean(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-clean\\fR, git\\-secret\\-removeperson(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-removeperson\\fR\n"
  },
  {
    "path": "man/man1/git-secret-remove.1.md",
    "content": "git-secret-remove - removes files from index.\n=============================================\n\n## SYNOPSIS\n\n    git secret remove [-c] <pathspec>...\n\n\n## DESCRIPTION\n`git-secret-remove` - stops files from being tracked by `git-secret`.\n\nThis deletes filenames from `.gitsecret/paths/mapping.cfg`, \nwhich stops these files from being tracked by `git-secret`, and from\nbeing encrypted to, or decrypted from, `.secret` encrypted versions.\n\nThere's also a -c option to delete existing encrypted versions of the files provided.\n\nNote unlike `add`, which automatically add pathnames to `.gitignore`, \n`remove` does not delete pathnames from `.gitignore`.\n\n(See [git-secret(7)](https://git-secret.io/git-secret) for information about renaming the .gitsecret\nfolder using the `SECRETS_DIR` environment variable.\n\n\n## OPTIONS\n\n    -c  - deletes existing real encrypted files.\n    -h  - shows help.\n\n\n## MANUAL\n\nRun `man git-secret-remove` to see this document.\n\n\n## SEE ALSO\n\n[git-secret-add(1)](https://git-secret.io/git-secret-add), [git-secret-clean(1)](https://git-secret.io/git-secret-clean),\n[git-secret-removeperson(1)](https://git-secret.io/git-secret-removeperson)\n"
  },
  {
    "path": "man/man1/git-secret-removeperson.1",
    "content": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-REMOVEPERSON\" \"1\" \"May 2022\" \"sobolevn\" \"git-secret 0.5.1-alpha1\"\n.\n.SH \"NAME\"\n\\fBgit\\-secret\\-removeperson\\fR \\- removes user\\'s public key from repo keyring\\.\n.\n.SH \"SYNOPSIS\"\n.\n.nf\n\ngit secret removeperson <emails>\\.\\.\\.\n.\n.fi\n.\n.SH \"DESCRIPTION\"\n\\fBgit\\-secret\\-removeperson\\fR \\- removes public keys for passed email addresses from repo\\'s \\fBgit\\-secret\\fR keyring\\.\n.\n.P\nThis command is used to begin the process of disallowing a user from encrypting and decrypting secrets with \\fBgit\\-secret\\fR\\.\n.\n.P\nIf you remove a user\\'s access with \\fBgit\\-secret\\-removeperson\\fR, and then run \\fBgit\\-secret\\-reveal\\fR and \\fBgit\\-secret\\-hide \\-r\\fR, that user will no longer be able user to decrypt the hidden files\\.\n.\n.SH \"OPTIONS\"\n.\n.nf\n\n\\-h  \\- shows this help\\.\n.\n.fi\n.\n.SH \"MANUAL\"\nRun \\fBman git\\-secret\\-removeperson\\fR to see this document\\.\n.\n.SH \"SEE ALSO\"\ngit\\-secret\\-tell(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-tell\\fR, git\\-secret\\-remove(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-remove\\fR, git\\-secret\\-clean(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-clean\\fR\n"
  },
  {
    "path": "man/man1/git-secret-removeperson.1.md",
    "content": "git-secret-removeperson - removes user's public key from repo keyring.\n==================================================================================\n\n## SYNOPSIS\n\n    git secret removeperson <emails or fingerprints>...\n\n\n## DESCRIPTION\n`git-secret-removeperson` - removes public keys for passed email addresses or GPG fingerprints from repo's `git-secret` keyring.\n\nThis command is used to begin the process of disallowing a user from encrypting and decrypting secrets with `git-secret`.\n\nIf you remove a user's access with `git-secret-removeperson`, and then run `git-secret-reveal` and `git-secret-hide -r`,\nthat user will no longer be able user to decrypt the hidden files.\n\n\n## OPTIONS\n\n    -h  - shows this help.\n\n\n## MANUAL\n\nRun `man git-secret-removeperson` to see this document.\n\n\n## SEE ALSO\n\n[git-secret-tell(1)](https://git-secret.io/git-secret-tell), [git-secret-remove(1)](https://git-secret.io/git-secret-remove),\n[git-secret-clean(1)](https://git-secret.io/git-secret-clean)\n"
  },
  {
    "path": "man/man1/git-secret-reveal.1",
    "content": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-REVEAL\" \"1\" \"May 2022\" \"sobolevn\" \"git-secret 0.5.1-alpha1\"\n.\n.SH \"NAME\"\n\\fBgit\\-secret\\-reveal\\fR \\- decrypts all added files\\.\n.\n.SH \"SYNOPSIS\"\n.\n.nf\n\ngit secret reveal [\\-f] [\\-F] [\\-P] [\\-v] [\\-d dir] [\\-p password] [pathspec]\\.\\.\\.\n.\n.fi\n.\n.SH \"DESCRIPTION\"\n\\fBgit\\-secret\\-reveal\\fR \\- decrypts passed files, or all files considered secret by \\fBgit\\-secret\\fR\\.\n.\n.P\nUnder the hood, \\fBreveal\\fR uses the \\fBgpg \\-\\-decrypt\\fR command and your private key (typically from your personal keyring in your home directory) to \\fIdecrypt\\fR files\\.\n.\n.P\nTherefore, for this operation to succeed, your personal keyring must contain a private key matching one of the public keys which were used to encrypt the secrets \\-\\- i\\.e\\., one of the public keys in your repo\\'s \\fBgit\\-secret\\fR keyring when the file was encrypted\\.\n.\n.SH \"OPTIONS\"\n.\n.nf\n\n\\-f  \\- forces gpg to overwrite existing files without prompt\\.\n\\-F  \\- forces reveal to continue even if a file fails to decrypt\\.\n\\-d  \\- specifies `\\-\\-homedir` option for the `gpg`, basically use this option if you store your keys in a custom location\\.\n\\-v  \\- verbose, shows extra information\\.\n\\-p  \\- specifies password for noinput mode, adds `\\-\\-passphrase` option for `gpg`\\.\n\\-P  \\- preserve permissions of encrypted file in unencrypted file\\.\n\\-h  \\- shows help\\.\n.\n.fi\n.\n.SH \"ENV VARIABLES\"\n.\n.IP \"\\(bu\" 4\n\\fBSECRETS_GPG_COMMAND\\fR changes the default \\fBgpg\\fR command to anything else\n.\n.IP \"\\(bu\" 4\n\\fBSECRETS_GPG_ARMOR\\fR is a boolean to enable \\fB\\-\\-armor\\fR mode \\fIhttps://www\\.gnupg\\.org/gph/en/manual/r1290\\.html\\fR to store secrets in text format over binary\n.\n.IP \"\\(bu\" 4\n\\fBSECRETS_DIR\\fR changes the default \\fB\\.gitsecret/\\fR folder to another name as documented at git\\-secret(7) \\fIhttps://git\\-secret\\.io/\\fR\n.\n.IP \"\\(bu\" 4\n\\fBSECRETS_EXTENSION\\fR changes the default \\fB\\.secret\\fR file extension\n.\n.IP \"\\(bu\" 4\n\\fBSECRETS_VERBOSE\\fR changes the output verbosity as documented at git\\-secret(7) \\fIhttps://git\\-secret\\.io/\\fR\n.\n.IP \"\\(bu\" 4\n\\fBSECRETS_PINENTRY\\fR changes the \\fBgpg \\-\\-pinentry\\fR mode \\fIhttps://github\\.com/gpg/pinentry\\fR as documented at git\\-secret(7) \\fIhttps://git\\-secret\\.io/\\fR\n.\n.IP \"\" 0\n.\n.SH \"MANUAL\"\nRun \\fBman git\\-secret\\-reveal\\fR to see this document\\.\n.\n.SH \"SEE ALSO\"\ngit\\-secret\\-init(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-init\\fR, git\\-secret\\-cat(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-cat\\fR, git\\-secret\\-tell(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-tell\\fR, git\\-secret\\-add(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-add\\fR, git\\-secret\\-hide(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-hide\\fR\n"
  },
  {
    "path": "man/man1/git-secret-reveal.1.md",
    "content": "git-secret-reveal - decrypts all added files.\n=============================================\n\n## SYNOPSIS\n\n    git secret reveal [-f] [-F] [-P] [-v] [-d dir] [-p password] [pathspec]...\n\n\n## DESCRIPTION\n`git-secret-reveal` - decrypts passed files, or all files considered secret by `git-secret`.\n\nUnder the hood, `reveal` uses the `gpg --decrypt` command\nand your private key (typically from your personal keyring in your\nhome directory) to _decrypt_ files.\n\nTherefore, for this operation to succeed, your personal keyring must contain a private key \nmatching one of the public keys which were used to encrypt the secrets --\ni.e., one of the public keys in your repo's `git-secret` keyring when the file was encrypted. \n\n\n\n## OPTIONS\n\n    -f  - forces gpg to overwrite existing files without prompt.\n    -F  - forces reveal to continue even if a file fails to decrypt.\n    -d  - specifies `--homedir` option for the `gpg`, basically use this option if you store your keys in a custom location.\n    -v  - verbose, shows extra information.\n    -p  - specifies password for noinput mode, adds `--passphrase` option for `gpg`.\n    -P  - preserve permissions of encrypted file in unencrypted file.\n    -h  - shows help.\n\n\n## ENV VARIABLES\n\n- `SECRETS_GPG_COMMAND` changes the default `gpg` command to anything else\n- `SECRETS_GPG_ARMOR` is a boolean to enable [`--armor` mode](https://www.gnupg.org/gph/en/manual/r1290.html) to store secrets in text format over binary\n- `SECRETS_DIR` changes the default `.gitsecret/` folder to another name as documented at [git-secret(7)](https://git-secret.io/)\n- `SECRETS_EXTENSION` changes the default `.secret` file extension\n- `SECRETS_VERBOSE` changes the output verbosity as documented at [git-secret(7)](https://git-secret.io/)\n- `SECRETS_PINENTRY` changes the [`gpg --pinentry` mode](https://github.com/gpg/pinentry) as documented at [git-secret(7)](https://git-secret.io/)\n\n\n## MANUAL\n\nRun `man git-secret-reveal` to see this document.\n\n\n## SEE ALSO\n\n[git-secret-init(1)](https://git-secret.io/git-secret-init), [git-secret-cat(1)](https://git-secret.io/git-secret-cat),\n[git-secret-tell(1)](https://git-secret.io/git-secret-tell), [git-secret-add(1)](https://git-secret.io/git-secret-add),\n[git-secret-hide(1)](https://git-secret.io/git-secret-hide)\n"
  },
  {
    "path": "man/man1/git-secret-tell.1",
    "content": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-TELL\" \"1\" \"May 2022\" \"sobolevn\" \"git-secret 0.5.1-alpha1\"\n.\n.SH \"NAME\"\n\\fBgit\\-secret\\-tell\\fR \\- adds person who can access private data\\.\n.\n.SH \"SYNOPSIS\"\n.\n.nf\n\ngit secret tell [\\-m] [\\-d dir] [emails]\\.\\.\\.\n.\n.fi\n.\n.SH \"DESCRIPTION\"\n\\fBgit\\-secret tell\\fR \\- adds user(s) to the list of those able to encrypt/decrypt secrets\\.\n.\n.P\nThis lets the specified user encrypt new files, but will not immediately be able to decrypt existing files, which were encrypted without their key\\. Files should be re\\-encrypted with the new keyring by someone who already has access in order for the new user to be able to decrypt the files\\.\n.\n.P\n\\fBgit\\-secret tell\\fR works only with email addresses, and will exit with an error if you have multiple keys in your keyring with specified email addresses, or if one of the specified emails is already associated with a key in the \\fBgit\\-secret\\fR repo\\'s keyring\\.\n.\n.P\nUnder the hood, \\fBgit\\-secret\\-tell\\fR searches in the current user\\'s \\fBgnupg\\fR keyring for public key(s) of passed email(s), then imports the corresponding public key(s) into your \\fBgit\\-secret\\fR repo\\'s keyring\\.\n.\n.P\nVersions of \\fBgit\\-secret tell\\fR after \\fB0\\.3\\.2\\fR will warn about keys that are expired, revoked, or otherwise invalid\\. It will also warn if multiple keys are found for a single email address\\.\n.\n.P\n\\fBDo not manually import secret keys into \\fBgit\\-secret\\fR\\fR\\. It won\\'t work with imported secret keys anyway\\.\n.\n.P\nFor more details about how \\fBgit\\-secret\\fR uses public and private keys, see the documentation for \\fBgit\\-secret\\-hide\\fR and \\fBgit\\-secret\\-reveal\\fR\\.\n.\n.SH \"OPTIONS\"\n.\n.nf\n\n\\-m  \\- uses your current `git config user\\.email` setting as an identifier for the key\\.\n\\-d  \\- specifies `\\-\\-homedir` option for `gpg`, basically use this option if your store your keys in a custom location\\.\n\\-h  \\- shows help\\.\n.\n.fi\n.\n.SH \"MANUAL\"\nRun \\fBman git\\-secret\\-tell\\fR to see this document\\.\n.\n.SH \"SEE ALSO\"\ngit\\-secret\\-init(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-init\\fR, git\\-secret\\-add(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-add\\fR, git\\-secret\\-hide(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-hide\\fR, git\\-secret\\-reveal(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-reveal\\fR, git\\-secret\\-cat(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-cat\\fR, git\\-secret\\-removeperson(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-removeperson\\fR\n"
  },
  {
    "path": "man/man1/git-secret-tell.1.md",
    "content": "git-secret-tell - adds person who can access private data.\n===============================================================\n\n## SYNOPSIS\n\n    git secret tell [-m] [-d dir] [emails or fingerprints]...\n\n\n## DESCRIPTION\n`git-secret tell` - adds user(s) to the list of those able to encrypt/decrypt secrets.\n\nThis lets the specified user encrypt new files,\nbut will not immediately be able to decrypt existing files, which were encrypted without their key.\nFiles should be re-encrypted with the new keyring by someone who already has access\nin order for the new user to be able to decrypt the files.\n\n`git-secret tell` works with email addresses or GPG key fingerprints, and will exit with an error if you have\nmultiple keys in your keyring with specified email addresses, or if one of the specified emails\nis already associated with a key in the `git-secret` repo's keyring.\n\nUnder the hood, `git-secret-tell` searches in the current user's `gnupg` keyring for public key(s) of passed\nemail(s) or fingerprint(s), then imports the corresponding public key(s) into your `git-secret` repo's keyring.\n\nFingerprints should be specified as a hex string of 8 or more characters (e.g., full 40-character fingerprints).\n\nVersions of `git-secret tell` after `0.3.2` will warn about keys that are expired, revoked, or otherwise invalid.\nIt will also warn if multiple keys are found for a single email address.\n\n**Do not manually import secret keys into `git-secret`**. It won't work with imported secret keys anyway.\n\nFor more details about how `git-secret` uses public and private keys,\nsee the documentation for `git-secret-hide` and `git-secret-reveal`.\n\n## OPTIONS\n\n    -m  - uses your current `git config user.email` setting as an identifier for the key.\n    -d  - specifies `--homedir` option for `gpg`, basically use this option if your store your keys in a custom location.\n    -h  - shows help.\n\n\n## MANUAL\n\nRun `man git-secret-tell` to see this document.\n\n\n## SEE ALSO\n\n[git-secret-init(1)](https://git-secret.io/git-secret-init), [git-secret-add(1)](https://git-secret.io/git-secret-add),\n[git-secret-hide(1)](https://git-secret.io/git-secret-hide), [git-secret-reveal(1)](https://git-secret.io/git-secret-reveal),\n[git-secret-cat(1)](https://git-secret.io/git-secret-cat), [git-secret-removeperson(1)](https://git-secret.io/git-secret-removeperson)\n"
  },
  {
    "path": "man/man1/git-secret-usage.1",
    "content": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-USAGE\" \"1\" \"May 2022\" \"sobolevn\" \"git-secret 0.5.1-alpha1\"\n.\n.SH \"NAME\"\n\\fBgit\\-secret\\-usage\\fR \\- prints all the available commands\\.\n.\n.SH \"SYNOPSIS\"\n.\n.nf\n\ngit secret usage\n.\n.fi\n.\n.SH \"DESCRIPTION\"\n\\fBgit\\-secret\\-usage\\fR \\- prints all the available \\fBgit\\-secret\\fR commands\\.\n.\n.SH \"OPTIONS\"\n.\n.nf\n\n\\-h  \\- shows this help\\.\n.\n.fi\n.\n.SH \"MANUAL\"\nRun \\fBman git\\-secret\\-usage\\fR to see this document\\.\n.\n.SH \"SEE ALSO\"\ngit\\-secret\\-init(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-init\\fR, git\\-secret\\-add(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-add\\fR, git\\-secret\\-hide(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-hide\\fR, git\\-secret\\-reveal(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-reveal\\fR, git\\-secret\\-cat(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-cat\\fR\n"
  },
  {
    "path": "man/man1/git-secret-usage.1.md",
    "content": "git-secret-usage - prints all the available commands.\n=====================================================\n\n## SYNOPSIS\n\n    git secret usage\n\n\n## DESCRIPTION\n`git-secret-usage` - prints all the available `git-secret` commands.\n\n\n## OPTIONS\n\n    -h  - shows this help.\n\n\n## MANUAL\n\nRun `man git-secret-usage` to see this document.\n\n\n## SEE ALSO\n\n[git-secret-init(1)](https://git-secret.io/git-secret-init), [git-secret-add(1)](https://git-secret.io/git-secret-add),\n[git-secret-hide(1)](https://git-secret.io/git-secret-hide), [git-secret-reveal(1)](https://git-secret.io/git-secret-reveal),\n[git-secret-cat(1)](https://git-secret.io/git-secret-cat)\n"
  },
  {
    "path": "man/man1/git-secret-whoknows.1",
    "content": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-WHOKNOWS\" \"1\" \"May 2022\" \"sobolevn\" \"git-secret 0.5.1-alpha1\"\n.\n.SH \"NAME\"\n\\fBgit\\-secret\\-whoknows\\fR \\- print email for each key in the keyring\\.\n.\n.SH \"SYNOPSIS\"\n.\n.nf\n\ngit secret whoknows\n.\n.fi\n.\n.SH \"DESCRIPTION\"\n\\fBgit\\-secret\\-whoknows\\fR \\- print email addresses allowed to access the secrets in this repo\\.\n.\n.SH \"OPTIONS\"\n.\n.nf\n\n\\-l  \\- \\'long\\' output, shows key expiration dates\\.\n\\-h  \\- shows this help\\.\n.\n.fi\n.\n.SH \"MANUAL\"\nRun \\fBman git\\-secret\\-whoknows\\fR to see this document\\.\n.\n.SH \"SEE ALSO\"\ngit\\-secret\\-list(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-list\\fR, git\\-secret\\-tell(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-tell\\fR, git\\-secret\\-hide(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-hide\\fR, git\\-secret\\-reveal(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-reveal\\fR, git\\-secret\\-cat(1) \\fIhttps://git\\-secret\\.io/git\\-secret\\-cat\\fR\n"
  },
  {
    "path": "man/man1/git-secret-whoknows.1.md",
    "content": "git-secret-whoknows - print email for each key in the keyring.\n======================================================================\n\n## SYNOPSIS\n\n    git secret whoknows\n\n\n## DESCRIPTION\n`git-secret-whoknows` - print email addresses allowed to access the secrets in this repo.\n\n\n## OPTIONS\n\n    -l  - 'long' output, shows key expiration dates.\n    -h  - shows this help.\n\n\n## MANUAL\n\nRun `man git-secret-whoknows` to see this document.\n\n\n## SEE ALSO\n\n[git-secret-list(1)](https://git-secret.io/git-secret-list), [git-secret-tell(1)](https://git-secret.io/git-secret-tell),\n[git-secret-hide(1)](https://git-secret.io/git-secret-hide), [git-secret-reveal(1)](https://git-secret.io/git-secret-reveal),\n[git-secret-cat(1)](https://git-secret.io/git-secret-cat)\n"
  },
  {
    "path": "man/man7/git-secret.7",
    "content": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\" \"7\" \"June 2022\" \"sobolevn\" \"git-secret 0.5.1-alpha1\"\n.\n.SH \"NAME\"\n\\fBgit\\-secret\\fR \\- bash tool to store private data inside a git repo\\.\n.\n.SH \"Usage: Setting up git\\-secret in a repository\"\nThese steps cover the basic process of using \\fBgit\\-secret\\fR to specify users and files that will interact with \\fBgit\\-secret\\fR, and to encrypt and decrypt secrets\\.\n.\n.IP \"1.\" 4\nBefore starting, \\fImake sure you have created a \\fBgpg\\fR RSA key\\-pair\\fR: which are a public key and a secret key pair, identified by your email address and stored with your gpg configuration\\. Generally this gpg configuration and keys will be stored somewhere in your home directory\\.\n.\n.IP \"2.\" 4\nBegin with an existing or new git repository\\.\n.\n.IP \"3.\" 4\nInitialize the \\fBgit\\-secret\\fR repository by running \\fBgit secret init\\fR\\. The \\fB\\.gitsecret/\\fR folder will be created, with subdirectories \\fBkeys/\\fR and \\fBpaths/\\fR, \\fB\\.gitsecret/keys/random_seed\\fR will be added to \\fB\\.gitignore\\fR, and \\fB\\.gitignore\\fR will be configured to \\fInot\\fR ignore \\fB\\.secret\\fR files\\.\n.\n.IP \"\" 0\n.\n.P\n\\fBNote\\fR all the contents of the \\fB\\.gitsecret/\\fR folder should be checked in, \\fB/except/\\fR the \\fBrandom_seed\\fR file\\. This also means that of all the files in \\fB\\.gitsecret/\\fR, only the \\fBrandom_seed\\fR file should be mentioned in your \\fB\\.gitignore\\fR file\\.\n.\n.IP \"1.\" 4\nAdd the first user to the \\fBgit\\-secret\\fR repo keyring by running \\fBgit secret tell your@email\\.id\\fR\\.\n.\n.IP \"2.\" 4\nNow it\\'s time to add files you wish to encrypt inside the \\fBgit\\-secret\\fR repository\\. This can be done by running \\fBgit secret add <filenames\\.\\.\\.>\\fR command, which will also (as of 0\\.2\\.6) add entries to \\fB\\.gitignore\\fR, stopping those files from being added or committed to the repo unencrypted\\.\n.\n.IP \"3.\" 4\nThen run \\fBgit secret hide\\fR to encrypt the files you added with \\fBgit secret add\\fR\\. The files will be encrypted with the public keys in your git\\-secret repo\\'s keyring, each corresponding to a user\\'s email that you used with \\fBtell\\fR\\.\n.\n.IP \"\" 0\n.\n.P\nAfter using \\fBgit secret hide\\fR to encrypt your data, it is safe to commit your changes\\. \\fBNOTE:\\fR It\\'s recommended to add the \\fBgit secret hide\\fR command to your \\fBpre\\-commit\\fR hook, so you won\\'t miss any changes\\.\n.\n.IP \"1.\" 4\nLater you can decrypt files with the \\fBgit secret reveal\\fR command, or print their contents to stdout with the \\fBgit secret cat\\fR command\\. If you used a password on your GPG key (always recommended), it will ask you for your password\\. And you\\'re done!\n.\n.IP \"\" 0\n.\n.SS \"Usage: Adding someone to a repository using git\\-secret\"\n.\n.IP \"1.\" 4\n\\fIGet their \\fBgpg\\fR public\\-key\\fR\\. \\fBYou won\\'t need their secret key\\.\\fR They can export their public key for you using a command like: \\fBgpg \\-\\-armor \\-\\-export their@email\\.id > public_key\\.txt # \\-\\-armor here makes it ascii\\fR\n.\n.IP \"2.\" 4\nImport this key into your \\fBgpg\\fR keyring (in \\fB~/\\.gnupg\\fR or similar) by running \\fBgpg \\-\\-import public_key\\.txt\\fR\n.\n.IP \"3.\" 4\nNow add this person to your secrets repo by running \\fBgit secret tell their@email\\.id\\fR (this will be the email address associated with their public key)\n.\n.IP \"4.\" 4\nNow remove the other user\\'s public key from your personal keyring with \\fBgpg \\-\\-delete\\-keys their@email\\.id\\fR\n.\n.IP \"5.\" 4\nThe newly added user cannot yet read the encrypted files\\. Now, re\\-encrypt the files using \\fBgit secret reveal; git secret hide \\-d\\fR, and then commit and push the newly encrypted files\\. (The \\-d options deletes the unencrypted file after re\\-encrypting it)\\. Now the newly added user will be able to decrypt the files in the repo using \\fBgit\\-secret reveal\\fR\\.\n.\n.IP \"\" 0\n.\n.P\nNote that when you first add a user to a git\\-secret repo, they will not be able to decrypt existing files until another user re\\-encrypts the files with the new keyring\\.\n.\n.P\nIf you do not want unexpected keys added, you can configure some server\\-side security policy with the \\fBpre\\-receive\\fR hook\\.\n.\n.SS \"Using gpg\"\nYou can follow a quick \\fBgpg\\fR tutorial at devdungeon \\fIhttps://www\\.devdungeon\\.com/content/gpg\\-tutorial\\fR\\. Here are the most useful commands to get started:\n.\n.P\nTo generate a RSA key\\-pair, run:\n.\n.IP \"\" 4\n.\n.nf\n\ngpg \\-\\-gen\\-key\n.\n.fi\n.\n.IP \"\" 0\n.\n.P\nTo export your public key, run:\n.\n.IP \"\" 4\n.\n.nf\n\ngpg \\-\\-armor \\-\\-export your\\.email@address\\.com > public\\-key\\.gpg\n.\n.fi\n.\n.IP \"\" 0\n.\n.P\nTo import the public key of someone else (to share the secret with them for instance), run:\n.\n.IP \"\" 4\n.\n.nf\n\ngpg \\-\\-import public\\-key\\.gpg\n.\n.fi\n.\n.IP \"\" 0\n.\n.P\nTo make sure you get the original public keys of the indicated persons, be sure to use a secure channel to transfer it, or use a service you trust, preferably one that uses encryption such as Keybase, to retrieve their public key\\. Otherwise you could grant the wrong person access to your secrets by mistake!\n.\n.SS \"Using git\\-secret for Continuous Integration / Continuous Deployment (CI/CD)\"\nWhen using \\fBgit\\-secret\\fR for CI/CD, you get the benefit that any deployment is necessarily done with the correct configuration, since it is collocated with the changes in your code\\.\n.\n.P\nOne way of doing it is the following:\n.\n.IP \"1.\" 4\n\\fIcreate a gpg key\\fR for your CI/CD environment\\. You can chose any name and email address you want: for instance \\fBMyApp Example <myapp@example\\.com>\\fR if your app is called MyApp and your CI/CD provider is Example\\. It is easier not to define a passphrase for that key\\. However, if defining a passphrase is unavoidable, use a unique passphrase for the private key\\.\n.\n.IP \"2.\" 4\nrun \\fBgpg \\-\\-armor \\-\\-export\\-secret\\-key myapp@example\\.com\\fR to get your private key value\n.\n.IP \"3.\" 4\nCreate an env var on your CI/CD server \\fBGPG_PRIVATE_KEY\\fR and assign it the private key value\\. If a passphrase has been setup for the private key, create another env var on the CI/CD server \\fBGPG_PASSPHRASE\\fR and assign it the passphrase of the private key\\.\n.\n.IP \"4.\" 4\nThen write your Continuous Deployment build script\\. For instance:\n.\n.IP \"\" 0\n.\n.IP \"\" 4\n.\n.nf\n\n# As the first step: install git\\-secret,\n# see: https://git\\-secret\\.io/installation\n\n# Create private key file\necho \"$GPG_PRIVATE_KEY\" > \\./private_key\\.gpg\n# Import private key and avoid the \"Inappropriate ioctl for device\" error\ngpg \\-\\-batch \\-\\-yes \\-\\-pinentry\\-mode loopback \\-\\-import private_key\\.gpg\n# Reveal secrets without user interaction and with passphrase\\. If no passphrase\n# is created for the key, remove `\\-p $GPG_PASSPHRASE`\ngit secret reveal \\-p \"$GPG_PASSPHRASE\"\n# carry on with your build script, secret files are available \\.\\.\\.\n.\n.fi\n.\n.IP \"\" 0\n.\n.P\nNote: your CI/CD might not allow you to create a multiline value\\. In that case, you can export it on one line with\n.\n.IP \"\" 4\n.\n.nf\n\ngpg \\-\\-armor \\-\\-export\\-secret\\-key myapp@example\\.com | tr \\'\\en\\' \\',\\'\n.\n.fi\n.\n.IP \"\" 0\n.\n.P\nYou can then create your private key file with:\n.\n.IP \"\" 4\n.\n.nf\n\necho \"$GPG_PRIVATE_KEY\" | tr \\',\\' \\'\\en\\' > \\./private_key\\.gpg\n.\n.fi\n.\n.IP \"\" 0\n.\n.P\nAlso note: the \\fBgpg\\fR version on the CI/CD server \\fBMUST INTEROPERATE\\fR with the one used locally\\. Otherwise, \\fBgpg\\fR decryption can fail, which leads to \\fBgit secret reveal\\fR reporting \\fBcannot find decrypted version of file\\fR error\\. The best way to ensure this is to use the same version of gnupg on different systems\\.\n.\n.SH \"Environment Variables and Configuration\"\nYou can configure the version of \\fBgpg\\fR used, or the extension your encrypted files use, to suit your workflow better\\. To do so, just set the required variable to the value you need\\. This can be done in your shell environment file or with each \\fBgit\\-secret\\fR command\\. See below, or the man page of \\fBgit\\-secret\\fR for an explanation of the environment variables \\fBgit\\-secret\\fR uses\\.\n.\n.P\nThe settings available to be changed are:\n.\n.IP \"\\(bu\" 4\n\\fB$SECRETS_VERBOSE\\fR \\- sets the verbose flag to on for all \\fBgit\\-secret\\fR commands; is identical to using \\fB\\-v\\fR on each command that supports it\\.\n.\n.IP \"\\(bu\" 4\n\\fB$SECRETS_GPG_COMMAND\\fR \\- sets the \\fBgpg\\fR alternatives, defaults to \\fBgpg\\fR\\. It can be changed to \\fBgpg\\fR, \\fBgpg2\\fR, \\fBpgp\\fR, \\fB/usr/local/gpg\\fR or any other value\\. After doing so rerun the tests to be sure that it won\\'t break anything\\. Tested with \\fBgpg\\fR and \\fBgpg2\\fR\\.\n.\n.IP \"\\(bu\" 4\n\\fB$SECRETS_GPG_ARMOR\\fR \\- sets the \\fBgpg\\fR \\fB\\-\\-armor\\fR mode \\fIhttps://www\\.gnupg\\.org/gph/en/manual/r1290\\.html\\fR\\. Can be set to \\fB1\\fR to store secrets file as text\\. By default is \\fB0\\fR and store files as binaries\\.\n.\n.IP \"\\(bu\" 4\n\\fB$SECRETS_EXTENSION\\fR \\- sets the secret files extension, defaults to \\fB\\.secret\\fR\\. It can be changed to any valid file extension\\.\n.\n.IP \"\\(bu\" 4\n\\fB$SECRETS_DIR\\fR \\- sets the directory where \\fBgit\\-secret\\fR stores its files, defaults to \\fB\\.gitsecret\\fR\\. It can be changed to any valid directory name\\.\n.\n.IP \"\\(bu\" 4\n\\fB$SECRETS_PINENTRY\\fR \\- allows user to specify a setting for \\fBgpg\\fR\\'s \\fB\\-\\-pinentry\\fR option\\. See \\fBgpg\\fR docs \\fIhttps://github\\.com/gpg/pinentry\\fR for details about gpg\\'s \\fB\\-\\-pinentry\\fR option\\.\n.\n.IP \"\" 0\n.\n.SH \"The <code>\\.gitsecret</code> folder (can be overridden with <code>SECRETS_DIR</code>)\"\nThis folder contains information about the files encrypted by git\\-secret, and about which public/private key sets can access the encrypted data\\.\n.\n.P\nYou can change the name of this directory using the SECRETS_DIR environment variable\\.\n.\n.P\nUse the various \\fBgit\\-secret\\fR commands to manipulate the files in \\fB\\.gitsecret\\fR, you should not change the data in these files directly\\.\n.\n.P\nExactly which files exist in the \\fB\\.gitsecret\\fR folder and what their contents are vary slightly across different versions of gpg\\. Also, some versions of gpg might not work well with keyrings created or modified with newer versions of gpg\\. Thus it is best to use git\\-secret with the same version of gpg being used by all users\\. This can be forced by installing matching versions of gpg and using \\fBSECRETS_GPG_COMMAND\\fR environment variable\\.\n.\n.P\nFor example, there is an issue between \\fBgpg\\fR version 2\\.1\\.20 and later versions which can cause problems reading and writing keyring files between systems (this shows up in errors like \\'gpg: skipped packet of type 12 in keybox\\')\\.\n.\n.P\nThis is not the only issue it is possible to encounter sharing files between different versions of \\fBgpg\\fR\\. Generally you are most likely to encounter issues between \\fBgpg\\fR versions if you use \\fBgit\\-secret tell\\fR or \\fBgit\\-secret removeperson\\fR to modify your repo\\'s \\fBgit\\-secret\\fR keyring using a newer version of \\fBgpg\\fR, and then try to operate on that keyring using an older version of \\fBgpg\\fR\\.\n.\n.P\nThe \\fBgit\\-secret\\fR internal data is separated into two directories:\n.\n.SS \"<code>\\.gitsecret/paths</code>\"\nThis directory currently contains only the file \\fBmapping\\.cfg\\fR, which lists all the files git\\-secret will consider secret\\. In other words, the path mappings: what files are tracked to be hidden and revealed\\.\n.\n.P\nAll other internal data used by git\\-secret is stored in the directory:\n.\n.SS \"<code>\\.gitsecret/keys</code>\"\nThis directory contains data used by \\fBgit\\-secret\\fR and \\fBgpg\\fR to encrypt files to be accessed by the permitted users\\.\n.\n.P\nIn particular, this directory contains a \\fBgnupg keyring\\fR with public keys for the emails used with \\fBtell\\fR\\.\n.\n.P\nThis is the keyring used to encrypt files with \\fBgit\\-secret\\-hide\\fR\\.\n.\n.P\n\\fBgit\\-secret\\-reveal\\fR and \\fBgit\\-secret\\-cat\\fR, which decrypt secrets, instead use the user\\'s \\fIprivate keys\\fR (which probably reside somewhere like ~/\\.gnupg/)\\. Note that user\\'s private keys, needed for decryption, are \\fInot\\fR in the \\fB\\.gitsecret/keys\\fR directory\\.\n.\n.P\nGenerally speaking, all the files in this directory \\fIexcept\\fR \\fBrandom_seed\\fR should be checked into your repo\\. By default, \\fBgit secret init\\fR will add the file \\fB\\.gitsecret/keys/random_seed\\fR to your \\fB\\.gitignore\\fR file\\.\n.\n.P\nAgain, you can change the name of this directory using the SECRETS_DIR environment variable\\.\n"
  },
  {
    "path": "man/man7/git-secret.7.md",
    "content": "git-secret - bash tool to store private data inside a git repo.\n=============================================\n\n## Usage: Setting up git-secret in a repository\n\nThese steps cover the basic process of using `git-secret`\nto specify users and files that will interact with `git-secret`, \nand to encrypt and decrypt secrets.\n\n0. Before starting, [make sure you have created a `gpg` RSA key-pair](#using-gpg): \nwhich are a public key and a secret key pair, identified by your email address and\nstored with your gpg configuration.\nGenerally this gpg configuration and keys will be stored somewhere in your home directory.\n\n1. Begin with an existing or new git repository. \n\n2. Initialize the `git-secret` repository by running `git secret init`. The `.gitsecret/` folder will be created,\nwith subdirectories `keys/` and `paths/`, \n`.gitsecret/keys/random_seed` will be added to `.gitignore`,\nand `.gitignore` will be configured to _not_ ignore `.secret` files.\n\n**Note** all the contents of the `.gitsecret/` folder should be checked in, **/except/** the `random_seed` file.\nThis also means that of all the files in `.gitsecret/`, only the `random_seed` file should be mentioned in your `.gitignore` file.\n\n3. Add the first user to the `git-secret` repo keyring by running `git secret tell your@email.id`.\n\n4. Now it's time to add files you wish to encrypt inside the `git-secret` repository.\nThis can be done by running `git secret add <filenames...>` command, which will also (as of 0.2.6) \nadd entries to `.gitignore`, stopping those files from being added or committed to the repo unencrypted. \n\n5. Then run `git secret hide` to encrypt the files you added with `git secret add`.\nThe files will be encrypted with the public keys in your git-secret repo's keyring,\neach corresponding to a user's email that you used with `tell`.\n\nAfter using `git secret hide` to encrypt your data, it is safe to commit your changes.\n**NOTE:** It's recommended to add the `git secret hide` command to your `pre-commit` hook, so you won't miss any changes.\n\n6. Later you can decrypt files with the `git secret reveal` command, or print their contents to stdout with the\n`git secret cat` command. If you used a password on your GPG key (always recommended), it will ask you for your password.\nAnd you're done!\n\n### Usage: Adding someone to a repository using git-secret\n\n1. [Get their `gpg` public-key](#using-gpg). **You won't need their secret key.**\nThey can export their public key for you using a command like: \n`gpg --armor --export their@email.id > public_key.txt # --armor here makes it ascii`\n \n2. Import this key into your `gpg` keyring (in `~/.gnupg` or similar) by running `gpg --import public_key.txt`\n\n3. Now add this person to your secrets repo by running `git secret tell their@email.id`\n(this will be the email address associated with their public key)\n\n4. Now remove the other user's public key from your personal keyring with `gpg --delete-keys their@email.id`\n\n5. The newly added user cannot yet read the encrypted files. Now, re-encrypt the files using\n`git secret reveal; git secret hide -d`, and then commit and push the newly encrypted files.\n(The -d options deletes the unencrypted file after re-encrypting it).\nNow the newly added user will be able to decrypt the files in the repo using `git-secret reveal`.\n\nNote that when you first add a user to a git-secret repo, they will not be able to decrypt existing files\nuntil another user re-encrypts the files with the new keyring.  \n\nIf you do not\nwant unexpected keys added, you can configure some server-side security policy with the `pre-receive` hook.\n\n### Using gpg\n\nYou can follow a quick `gpg` tutorial at [devdungeon](https://www.devdungeon.com/content/gpg-tutorial). Here are the most useful commands to get started:\n\nTo generate a RSA key-pair, run:\n\n```shell\ngpg --gen-key\n```\n\nTo export your public key, run:\n\n```shell\ngpg --armor --export your.email@address.com > public-key.gpg\n```\n\nTo import the public key of someone else (to share the secret with them for instance), run:\n\n```shell\ngpg --import public-key.gpg\n```\n\nTo make sure you get the original public keys of the indicated persons, be sure to use a secure channel to transfer it, or use a service you trust, preferably one that uses encryption such as Keybase, to retrieve their public key. Otherwise you could grant the wrong person access to your secrets by mistake!\n\n### Using git-secret for Continuous Integration / Continuous Deployment (CI/CD)\n\nWhen using `git-secret` for CI/CD, you get the benefit that any deployment is necessarily done with the correct configuration, since it is collocated\nwith the changes in your code.\n\nOne way of doing it is the following:\n\n1. [create a gpg key](#using-gpg) for your CI/CD environment. You can chose any name and email address you want: for instance `MyApp Example <myapp@example.com>`\nif your app is called MyApp and your CI/CD provider is Example. It is easier not to define a passphrase for that key. However, if defining a passphrase is unavoidable, use a unique passphrase for the private key.\n2. run `gpg --armor --export-secret-key myapp@example.com` to get your private key value\n3. Create an env var on your CI/CD server `GPG_PRIVATE_KEY` and assign it the private key value. If a passphrase has been setup for the private key, create another env var on the CI/CD server `GPG_PASSPHRASE` and assign it the passphrase of the private key.\n4. Then write your Continuous Deployment build script. For instance:\n\n```shell\n# As the first step: install git-secret,\n# see: https://git-secret.io/installation\n\n# Create private key file\necho \"$GPG_PRIVATE_KEY\" > ./private_key.gpg\n# Import private key and avoid the \"Inappropriate ioctl for device\" error\ngpg --batch --yes --pinentry-mode loopback --import private_key.gpg\n# Reveal secrets without user interaction and with passphrase. If no passphrase\n# is created for the key, remove `-p $GPG_PASSPHRASE`\ngit secret reveal -p \"$GPG_PASSPHRASE\"\n# carry on with your build script, secret files are available ...\n```\n\nNote: your CI/CD might not allow you to create a multiline value. In that case, you can export it on one line with\n\n```shell\ngpg --armor --export-secret-key myapp@example.com | tr '\\n' ','\n```\n\nYou can then create your private key file with:\n\n```shell\necho \"$GPG_PRIVATE_KEY\" | tr ',' '\\n' > ./private_key.gpg\n```\n\nAlso note: the `gpg` version on the CI/CD server **MUST INTEROPERATE** with the one used locally. Otherwise, `gpg` decryption can fail, which leads to `git secret reveal` reporting `cannot find decrypted version of file` error. The best way to ensure this is to use the same version of gnupg on different systems.\n\n## Environment Variables and Configuration\n\nYou can configure the version of `gpg` used, or the extension your encrypted files use, to suit your workflow better.\nTo do so, just set the required variable to the value you need.\nThis can be done in your shell environment file or with each `git-secret` command.\nSee below, or the man page of `git-secret` for an explanation of the environment variables `git-secret` uses.\n\nThe settings available to be changed are:\n\n* `$SECRETS_VERBOSE` - sets the verbose flag to on for all `git-secret` commands; is identical to using `-v` on each command that supports it.\n\n* `$SECRETS_GPG_COMMAND` - sets the `gpg` alternatives, defaults to `gpg`.\nIt can be changed to `gpg`, `gpg2`, `pgp`, `/usr/local/gpg` or any other value.\nAfter doing so rerun the tests to be sure that it won't break anything. Tested with `gpg` and `gpg2`.\n\n* `$SECRETS_GPG_ARMOR` - sets the `gpg` [`--armor` mode](https://www.gnupg.org/gph/en/manual/r1290.html). Can be set to `1` to store secrets file as text. By default is `0` and store files as binaries.\n\n* `$SECRETS_EXTENSION` - sets the secret files extension, defaults to `.secret`. It can be changed to any valid file extension.\n\n* `$SECRETS_DIR` - sets the directory where `git-secret` stores its files, defaults to `.gitsecret`. It can be changed to any valid directory name.\n\n* `$SECRETS_PINENTRY` - allows user to specify a setting for `gpg`'s `--pinentry` option. See [`gpg` docs](https://github.com/gpg/pinentry) for details about gpg's `--pinentry` option.\n\n## The `.gitsecret` folder (can be overridden with `SECRETS_DIR`)\n\nThis folder contains information about the files encrypted by git-secret,\nand about which public/private key sets can access the encrypted data.\n\nYou can change the name of this directory using the SECRETS_DIR environment variable.\n\nUse the various `git-secret` commands to manipulate the files in `.gitsecret`,\nyou should not change the data in these files directly.\n\nExactly which files exist in the `.gitsecret` folder and what their contents are\nvary slightly across different versions of gpg. Also, some versions of gpg\nmight not work well with keyrings created or modified with newer versions of gpg. \nThus it is best to use git-secret with the same version of gpg being used by all users.\nThis can be forced by installing matching versions of gpg \nand using `SECRETS_GPG_COMMAND` environment variable.\n\nFor example, there is an issue between `gpg` version 2.1.20 and later versions\nwhich can cause problems reading and writing keyring files between systems\n(this shows up in errors like 'gpg: skipped packet of type 12 in keybox').\n\nThis is not the only issue it is possible to encounter sharing files between different versions\nof `gpg`.\nGenerally you are most likely to encounter issues between `gpg`\nversions if you use `git-secret tell` or `git-secret removeperson` to modify\nyour repo's `git-secret` keyring using a newer version of `gpg`, and then try to operate\non that keyring using an older version of `gpg`.\n\nThe `git-secret` internal data is separated into two directories:\n\n### `.gitsecret/paths`\n\nThis directory currently contains only the file `mapping.cfg`, which lists all the files git-secret will consider secret.\nIn other words, the path mappings: what files are tracked to be hidden and revealed.\n\nAll other internal data used by git-secret is stored in the directory:\n\n### `.gitsecret/keys`\n\nThis directory contains data used by `git-secret` and `gpg` to encrypt files to \nbe accessed by the permitted users.\n\nIn particular, this directory contains a `gnupg keyring` with public keys for the emails used with `tell`.\n\nThis is the keyring used to encrypt files with `git-secret-hide`. \n\n`git-secret-reveal` and `git-secret-cat`, which decrypt secrets,\ninstead use the user's _private keys_ (which probably reside somewhere like ~/.gnupg/).\nNote that user's private keys, needed for decryption, are _not_ in the `.gitsecret/keys` directory.\n\nGenerally speaking, all the files in this directory *except* `random_seed` should be checked into your repo.\nBy default, `git secret init` will add the file `.gitsecret/keys/random_seed` to your `.gitignore` file.\n\nAgain, you can change the name of this directory using the SECRETS_DIR environment variable.\n"
  },
  {
    "path": "src/_utils/_git_secret_tools.sh",
    "content": "#!/usr/bin/env bash\n\n# Folders:\n_SECRETS_DIR=${SECRETS_DIR:-\".gitsecret\"}\n# if SECRETS_DIR env var is set, use that instead of .gitsecret\n# for full path to secrets dir, use _get_secrets_dir()\n# from _git_secret_tools.sh\n_SECRETS_DIR_KEYS=\"${_SECRETS_DIR}/keys\"\n_SECRETS_DIR_PATHS=\"${_SECRETS_DIR}/paths\"\n\n# Files:\n_SECRETS_DIR_KEYS_TRUSTDB=\"${_SECRETS_DIR_KEYS}/trustdb.gpg\"\n\n_SECRETS_DIR_PATHS_MAPPING=\"${_SECRETS_DIR_PATHS}/mapping.cfg\"\n\n\n# shellcheck disable=SC2153\nif [[ -n \"$SECRETS_VERBOSE\" ]] && [[ \"$SECRETS_VERBOSE\" -ne 0 ]]; then\n  # shellcheck disable=SC2034\n  _SECRETS_VERBOSE='1'\n  # _SECRETS_VERBOSE is empty or '1'. \n  # Empty means 'off', any other value means 'on'.\nfi\n\n: \"${SECRETS_EXTENSION:=\".secret\"}\"\n\n# Commands:\n: \"${SECRETS_GPG_COMMAND:=\"gpg\"}\"\n: \"${SECRETS_CHECKSUM_COMMAND:=\"_os_based __sha256\"}\"\n: \"${SECRETS_OCTAL_PERMS_COMMAND:=\"_os_based __get_octal_perms\"}\"\n: \"${SECRETS_EPOCH_TO_DATE:=\"_os_based __epoch_to_date\"}\"\n\n# Temp Dir:\n: \"${TMPDIR:=/tmp}\"\n\n# AWK scripts:\n# shellcheck disable=SC2016\nAWK_FSDB_HAS_RECORD='\nBEGIN { FS=\":\"; OFS=\":\"; cnt=0; }\n{\n  if ( key == $1 )\n  {\n    cnt++\n  }\n}\nEND { if ( cnt > 0 ) print \"0\"; else print \"1\"; }\n'\n\n# shellcheck disable=SC2016\nAWK_FSDB_RM_RECORD='\nBEGIN { FS=\":\"; OFS=\":\"; }\n{\n  if ( key != $1 )\n  {\n    print $1,$2;\n  }\n}\n'\n\n# shellcheck disable=SC2016\nAWK_FSDB_CLEAR_HASHES='\nBEGIN { FS=\":\"; OFS=\":\"; }\n{\n  print $1,\"\";\n}\n'\n\n# shellcheck disable=SC2016\nAWK_GPG_VER_CHECK='\n/^gpg/{\n  version=$3\n  n=split(version,array,\".\")\n  if( n >= 2) {\n    if(array[1] >= 2)\n    {\n      if(array[2] >= 1)\n      {\n        print 1\n      }\n      else\n      {\n        print 0\n      }\n    }\n    else\n    {\n      print 0\n    }\n  }\n  else if(array[1] >= 2)\n  {\n    print 1\n  }\n  else\n  {\n    print 0\n  }\n}\n'\n\n# This is 1 for gpg version 2.1 or greater, otherwise 0\nGPG_VER_MIN_21=\"$($SECRETS_GPG_COMMAND --version | gawk \"$AWK_GPG_VER_CHECK\")\"\n\n\n# Bash:\n\n# echos 0 if function exists, otherwise non-zero\nfunction _function_exists {\n  local function_name=\"$1\" # required\n\n  declare -f -F \"$function_name\" > /dev/null 2>&1\n  echo $?\n}\n\n\n# OS based:\n\nfunction _os_based {\n  # Pass function name as first parameter.\n  # It will be invoked as os-based function with the postfix.\n\n  case \"$(uname -s)\" in\n\n    Darwin)\n      \"$1_osx\" \"${@:2}\"\n    ;;\n\n    Linux)\n      \"$1_linux\" \"${@:2}\"\n    ;;\n\n    MINGW*)\n      \"$1_linux\" \"${@:2}\"\n    ;;\n\n    MSYS*)\n      \"$1_linux\" \"${@:2}\"\n    ;;\n\n    CYGWIN*)\n      \"$1_linux\" \"${@:2}\"\n    ;;\n\n    FreeBSD)\n      \"$1_freebsd\" \"${@:2}\"\n    ;;\n\n    # TODO: add MS Windows support.\n    # MINGW32*|MSYS*)\n    #   $1_ms ${@:2}\n    # ;;\n\n    *)\n      _abort 'unsupported OS.'\n    ;;\n  esac\n}\n\n\n# File System:\n\nfunction _clean_windows_path {\n  # This function transforms windows paths to *nix paths\n  # such as  c:\\this\\that.file -> /c/this/that/file\n  # shellcheck disable=SC2001\n  echo \"$1\" | sed 's#^\\([a-zA-Z]\\):/#/\\1/#'\n}\n\n\nfunction _set_config {\n  # This function creates a line in the config, or alters it.\n\n  local key=\"$1\" # required\n  local value=\"$2\" # required\n  local filename=\"$3\" # required\n\n  # The exit status is 0 (true) if the name was found, 1 (false) if not:\n  local contains\n  contains=$(grep -Fq \"$key\" \"$filename\"; echo \"$?\")\n\n  # Append or alter?\n  if [[ \"$contains\" -eq 0 ]]; then\n    _os_based __replace_in_file \"$@\"\n  elif [[ \"$contains\" -eq 1 ]]; then\n    echo \"${key} = ${value}\" >> \"$filename\"\n  fi\n}\n\n\n# this sets the global variable 'temporary_filename'\n# currently this function is only used by 'hide'\nfunction _temporary_file {\n  # This function creates temporary file\n  # which will be removed on system exit.\n  temporary_filename=$(_os_based __temp_file)  # is not `local` on purpose.\n\n  trap 'if [[ -f \"$temporary_filename\" ]]; then if [[ -n \"$_SECRETS_VERBOSE\" ]] || [[ \"$SECRETS_TEST_VERBOSE\" == 1 ]]; then echo \"git-secret: cleaning up: $temporary_filename\"; fi; rm -f \"$temporary_filename\"; fi;' EXIT\n}\n\n\n# Helper function\n\n\nfunction _gawk_inplace {\n  local dest_file=\"${!#}\"  # last argument\n\n  _temporary_file\n\n  gawk \"$@\" > \"$temporary_filename\"\n  mv \"$temporary_filename\" \"$dest_file\"\n}\n\n\n# File System Database (fsdb):\n\n\nfunction _get_record_filename {\n  # Returns 1st field from passed record\n  local record=\"$1\"\n  local filename\n  filename=$(echo \"$record\" | awk -F: '{print $1}')\n\n  echo \"$filename\"\n}\n\n\nfunction _get_record_hash {\n  # Returns 2nd field from passed record\n  local record=\"$1\"\n  local hash\n  hash=$(echo \"$record\" | awk -F: '{print $2}')\n\n  echo \"$hash\"\n}\n\n\nfunction _fsdb_has_record {\n  # First parameter is the key\n  # Second is the fsdb\n  local key=\"$1\"  # required\n  local fsdb=\"$2\" # required\n\n  # 0 on contains, 1 for error.\n  gawk -v key=\"$key\" \"$AWK_FSDB_HAS_RECORD\" \"$fsdb\"\n}\n\n\nfunction _fsdb_rm_record {\n  # First parameter is the key (filename)\n  # Second is the path to fsdb\n  local key=\"$1\"  # required\n  local fsdb=\"$2\" # required\n\n  _gawk_inplace -v \"key=$key\" \"$AWK_FSDB_RM_RECORD\" \"$fsdb\"\n}\n\n\nfunction _fsdb_clear_hashes {\n  # First parameter is the path to fsdb\n  local fsdb=\"$1\" # required\n\n  _gawk_inplace \"$AWK_FSDB_CLEAR_HASHES\" \"$fsdb\"\n}\n\n\n# Manuals:\n\n\nfunction _show_manual_for {\n  local function_name=\"$1\" # required\n\n  man \"git-secret-${function_name}\"\n  exit 0\n}\n\n\n# Invalid options\n\nfunction _invalid_option_for {\n  local function_name=\"$1\" # required\n\n  man \"git-secret-${function_name}\"\n  exit 1\n}\n\n\n# VCS:\n\n\nfunction _check_ignore {\n  local filename=\"$1\" # required\n\n  local result\n  result=\"$(git check-ignore -q \"$filename\"; echo $?)\"\n  # returns 1 when not ignored, and 0 when ignored\n  echo \"$result\"\n}\n\n\nfunction _git_normalize_filename {\n  local filename=\"$1\" # required\n\n  local result\n  result=$(git ls-files --full-name -o \"$filename\")\n  echo \"$result\"\n}\n\n\nfunction _maybe_create_gitignore {\n  # This function creates '.gitignore' if it was missing.\n\n  local full_path\n  full_path=$(_prepend_root_path '.gitignore')\n\n  if [[ ! -f \"$full_path\" ]]; then\n    touch \"$full_path\"\n  fi\n}\n\n\nfunction _add_ignored_file {\n  # This function adds a line with the filename into the '.gitignore' file.\n  # It also creates '.gitignore' if it's not there\n\n  local filename=\"$1\" # required\n\n  _maybe_create_gitignore\n\n  local full_path\n  full_path=$(_prepend_root_path '.gitignore')\n\n  printf '%q\\n' \"$filename\" >> \"$full_path\"\n}\n\n\nfunction _is_inside_git_tree {\n  # Checks if we are working inside the `git` tree.\n  local result\n  result=$(git rev-parse --is-inside-work-tree > /dev/null 2>&1; echo $?)\n\n  echo \"$result\"\n}\n\n\nfunction _is_tracked_in_git {\n  local filename=\"$1\" # required\n  local result\n  result=\"$(git ls-files --error-unmatch \"$filename\" >/dev/null 2>&1; echo $?)\"\n\n  if [[ \"$result\" -eq 0 ]]; then\n    echo \"1\"\n  else\n    echo \"0\"\n  fi\n}\n\n\n# This can give unexpected .git dir when used in a _subdirectory_\n# of another git repo; See #431 and #433.\nfunction _get_git_root_path {\n  # We need this function to get the location of the `.git` folder,\n  # since `.gitsecret` (or value set by SECRETS_DIR env var)\n  # must be in the same dir.\n\n  local result\n  result=$(_clean_windows_path \"$(git rev-parse --show-toplevel)\")\n  echo \"$result\"\n}\n\n\n# Relative paths:\n\nfunction _prepend_root_path {\n  # This function adds root path to any other path.\n\n  local path=\"$1\" # required\n\n  local root_path\n  root_path=$(_get_git_root_path)\n\n  echo \"$root_path/$path\"\n}\n\n\n# if passed a name like 'filename.txt', returns a full path in the repo\n# For #710: if we are in a subdir, fixup the path with the subdir\nfunction _prepend_relative_root_path {\n  local path=\"$1\" # required\n\n  local full_path\n  full_path=$(_prepend_root_path \"$path\")\n\n  local subdir\n  subdir=$(git rev-parse --show-prefix)   # get the subdir of repo, like \"subdir/\"\n  if [ -n \"$subdir\" ]; then\n    full_path=\"$(dirname \"$full_path\")/${subdir}/$(basename \"$full_path\")\"\n  fi\n\n  echo \"$full_path\"\n}\n\nfunction _get_secrets_dir {\n  _prepend_root_path \"${_SECRETS_DIR}\"\n}\n\n\nfunction _get_secrets_dir_keys {\n  _prepend_root_path \"${_SECRETS_DIR_KEYS}\"\n}\n\n\nfunction _get_secrets_dir_path {\n  _prepend_root_path \"${_SECRETS_DIR_PATHS}\"\n}\n\n\nfunction _get_secrets_dir_keys_trustdb {\n  _prepend_root_path \"${_SECRETS_DIR_KEYS_TRUSTDB}\"\n}\n\n\nfunction _get_secrets_dir_paths_mapping {\n  _prepend_root_path \"${_SECRETS_DIR_PATHS_MAPPING}\"\n}\n\n\n# Logic:\n\nfunction _message {\n  local message=\"$1\" # required\n  echo \"git-secret: $message\"\n}\n\n\nfunction _abort {\n  local message=\"$1\" # required\n  local exit_code=${2:-\"1\"}     # defaults to 1\n\n  >&2 echo \"git-secret: abort: $message\"\n  exit \"$exit_code\"\n}\n\n\n# _warn() sends warnings to stdout so user sees them\nfunction _warn {\n  local message=\"$1\" # required\n\n  >&2 echo \"git-secret: warning: $message\"\n}\n\n\n# _warn_or_abort \"$error_message\" \"$exit_code\" \"$error_ok\"\nfunction _warn_or_abort {\n  local message=\"$1\"            # required\n  local exit_code=${2:-\"1\"}     # defaults to 1\n  local error_ok=${3:-0}        # can be 0 or 1\n\n  if [[ \"$error_ok\" -eq \"0\" ]]; then\n    if [[ \"$exit_code\" -eq \"0\" ]]; then\n      # if caller sends an exit_code of 0, we change it to 1 before aborting.\n      exit_code=1\n    fi\n    _abort \"$message\" \"$exit_code\"\n  else\n    _warn \"$message\" \"$exit_code\"\n  fi\n}\n\n\nfunction _find_and_remove_secrets_formatted {\n  local filenames\n  _list_all_added_files # sets array variable 'filenames'\n\n  for filename in \"${filenames[@]}\"; do\n    local path # absolute path\n    encrypted_filename=$(_get_encrypted_filename \"$filename\")\n    if [[ -f \"$encrypted_filename\" ]]; then\n      rm \"$encrypted_filename\"\n      if [[ -n \"$_SECRETS_VERBOSE\" ]]; then\n        echo \"git-secret: deleted: $encrypted_filename\"\n      fi\n    fi\n  done\n}\n\n\n\n# this sets the global array variable 'filenames'\nfunction _list_all_added_files {\n  local path_mappings\n  path_mappings=$(_get_secrets_dir_paths_mapping)\n\n  if [[ ! -s \"$path_mappings\" ]]; then\n    _abort \"path_mappings file is missing or empty: $path_mappings\"\n  fi\n\n  local filename\n  filenames=()      # not local\n  while read -r line; do\n    filename=$(_get_record_filename \"$line\")\n    filenames+=(\"$filename\")\n  done < \"$path_mappings\"\n\n  declare -a filenames     # so caller can get list from filenames array\n}\n\n\nfunction _secrets_dir_exists {\n  # This function checks if \"$_SECRETS_DIR\" exists and.\n\n  local full_path\n  full_path=$(_get_secrets_dir)\n\n  if [[ ! -d \"$full_path\" ]]; then\n    local name\n    name=$(basename \"$full_path\")\n    _abort \"directory '$name' does not exist. Use 'git secret init' to initialize git-secret\"\n  fi\n}\n\n\nfunction _secrets_dir_is_not_ignored {\n  # This function checks that \"$_SECRETS_DIR\" is not ignored.\n\n  local git_secret_dir\n  git_secret_dir=$(_get_secrets_dir)\n\n  local ignores\n  ignores=$(_check_ignore \"$git_secret_dir\")\n\n  if [[ ! $ignores -eq 1 ]]; then\n    _abort \"entry already in .gitignore: $git_secret_dir\"\n  fi\n}\n\n\nfunction _exe_is_busybox {\n  local exe\n  exe=\"$1\"\n\n  # we assume stat is from busybox if it's a symlink\n  local is_busybox=0\n  local stat_path\n  stat_path=$(command -v \"$exe\")\n  if [ -L \"$stat_path\" ]; then\n    is_busybox=1\n  fi\n  echo \"$is_busybox\"\n}\n\n\n# this is used by just about every command\nfunction _user_required {\n  # This function does a bunch of validations:\n  # 1. It calls `_secrets_dir_exists` to verify that \"$_SECRETS_DIR\" exists.\n  # 2. It ensures that \"$_SECRETS_DIR_KEYS_TRUSTDB\" exists.\n  # 3. It ensures that there are added public keys.\n\n  _secrets_dir_exists\n\n  local trustdb\n  trustdb=$(_get_secrets_dir_keys_trustdb)\n\n  local error_message=\"no public keys for users found. run 'git secret tell email@address'.\"\n  if [[ ! -f \"$trustdb\" ]]; then\n    _abort \"$error_message\"\n  fi\n\n  local secrets_dir_keys\n  secrets_dir_keys=$(_get_secrets_dir_keys)\n\n  # for info about 3>&-\n  # see https://github.com/bats-core/bats-core/blob/master/docs/source/writing-tests.md#file-descriptor-3-read-this-if-bats-hangs \n  local keys_exist\n  keys_exist=$($SECRETS_GPG_COMMAND --homedir \"$secrets_dir_keys\" --no-permission-warning -n --list-keys 3>&-)\n  local exit_code=$?\n  if [[ -z \"$keys_exist\" ]]; then\n    _abort \"$error_message\"\n  fi\n  if [[ \"$exit_code\" -ne 0 ]]; then\n    # this might catch corner case where gpg --list-keys shows\n    # 'gpg: skipped packet of type 12 in keybox' warnings but succeeds?\n    # See #136\n    echo \"$keys_exist\"\t# show whatever _did_ come out of gpg\n    _abort \"problem listing public keys with gpg: exit code $exit_code\"\n  fi\n}\n\n\n# note: this has the same 'username matching' issue described in\n# https://github.com/sobolevn/git-secret/issues/268\n# where it will match emails that have other emails as substrings.\n# we need to use fingerprints for a unique key id with gpg.\nfunction _get_user_key_expiry {\n  # This function returns the user's key's expiry, as an epoch.\n  # It will return the empty string\n  # if there is no expiry date for the user's key\n  local username=\"$1\"\n  local line\n\n  local secrets_dir_keys\n  secrets_dir_keys=$(_get_secrets_dir_keys)\n\n  # 3>&- closes fd 3 for bats, see https://github.com/bats-core/bats-core/blob/master/docs/source/writing-tests.md#file-descriptor-3-read-this-if-bats-hangs\n  line=$($SECRETS_GPG_COMMAND --homedir \"$secrets_dir_keys\" --no-permission-warning --list-public-keys --with-colon --fixed-list-mode \"$username\" | grep ^pub: 3>&-)\n\n  local expiry_epoch\n  expiry_epoch=$(echo \"$line\" | cut -d: -f7)\n  echo \"$expiry_epoch\"\n}\n\n\nfunction _assert_keyring_contains_emails {\n  local homedir=\"$1\"\n  local keyring_name=\"$2\"\n  local emails=\"$3\"\n\n  # 1 here means 'expect $emails in keyring':\n  _assert_keyring_emails \"$homedir\" \"$keyring_name\" \"$emails\" 1\n}\n\n\nfunction _assert_keyring_doesnt_contain_emails {\n  local homedir=\"$1\"\n  local keyring_name=\"$2\"\n  local emails=\"$3\"\n\n  # 0 here means 'don't expect $emails in keyring':\n  _assert_keyring_emails \"$homedir\" \"$keyring_name\" \"$emails\" 0\n}\n\nfunction _assert_keyring_contains_emails_at_least_once {\n  local homedir=$1\n  local keyring_name=$2\n  local emails=$3\n  _assert_keyring_emails \"$homedir\" \"$keyring_name\" \"$emails\" 1 1 # expect the email at least once in the keyring\n}\n\n\n\nfunction _is_gpg_fingerprint {\n  # Returns 0 if the input looks like a GPG fingerprint or key ID\n  # (8+ hex characters), 1 otherwise.\n  local input=\"$1\"\n  local clean_input\n  clean_input=$(echo \"$input\" | tr -d ' ')\n  if [[ \"$clean_input\" =~ ^[A-Fa-f0-9]{8,}$ ]]; then\n    return 0\n  else\n    return 1\n  fi\n}\n\n\nfunction _check_fingerprint_in_keyring {\n  # Checks if a key matching the given fingerprint exists in the keyring.\n  # Returns 0 if found, 1 if not found.\n  local homedir=\"$1\"\n  local fingerprint=\"$2\"\n\n  local args=()\n  if [[ -n \"$homedir\" ]]; then\n    args+=( \"--homedir\" \"$homedir\" )\n  fi\n\n  # 3>&- closes fd 3 for bats\n  $SECRETS_GPG_COMMAND \"${args[@]}\" --no-permission-warning --list-keys \"$fingerprint\" > /dev/null 2>&1 3>&-\n  return $?\n}\n\n\nfunction _assert_keyring_emails {\n  local homedir=\"$1\"\n  local keyring_name=\"$2\"\n  local emails=\"$3\"\n  # set this to:\n  # 0 to not expect the email in the keyring;\n  # 1 to expect the email in the keyring\n  local expected=\"$4\"\n  local allow_duplicates=$5 # set this to 0 to not allow duplicate emails in the keyring when processing assertion (optional)\n\n  local gpg_uids\n  gpg_uids=$(_get_users_in_gpg_keyring \"$homedir\")\n  for email in \"${emails[@]}\"; do\n    if _is_gpg_fingerprint \"$email\"; then\n      # For fingerprints, check directly with gpg\n      if [[ $expected -eq 1 ]]; then\n        if ! _check_fingerprint_in_keyring \"$homedir\" \"$email\"; then\n          _abort \"no key found in gpg $keyring_name for fingerprint: $email\"\n        fi\n      else\n        if _check_fingerprint_in_keyring \"$homedir\" \"$email\"; then\n          _abort \"key already exists in gpg $keyring_name for fingerprint: $email\"\n        fi\n      fi\n    else\n      if [[ $email != *\"@\"* ]]; then\n        _abort \"does not appear to be an email or fingerprint: $email\"\n      fi\n      local emails_found=0\n      for uid in $gpg_uids; do\n        if [[ \"$uid\" == \"$email\" ]]; then\n          emails_found=$((emails_found+1))\n        fi\n      done\n      if [[ $expected -eq 1 ]]; then\n          if [[ $emails_found -eq 0 ]]; then\n            _abort \"no key found in gpg $keyring_name for: $email\"\n          elif [[ $emails_found -gt 1 ]]; then\n            if [[ $allow_duplicates -ne 1 ]]; then\n              _abort \"$emails_found keys found in gpg $keyring_name for: $email\"\n            fi\n          fi\n      else\n          if [[ $emails_found -gt 0 ]]; then\n            _abort \"$emails_found keys found in gpg $keyring_name for: $email\"\n          fi\n      fi\n    fi\n\n  done\n}\n\n\nfunction _get_encrypted_filename {\n  local filename\n  filename=\"$(dirname \"$1\")/$(basename \"$1\" \"$SECRETS_EXTENSION\")\"\n  echo \"${filename}${SECRETS_EXTENSION}\" | sed -e 's#^\\./##'\n}\n\n\n# this is used throughout this file, and in 'whoknows'\nfunction _get_users_in_gpg_keyring {\n  # show the users in the gpg keyring.\n  # `whoknows` command uses it internally.\n  # parses the `gpg` public keys\n  local homedir=$1\n  local result\n  local args=()\n  if [[ -n \"$homedir\" ]]; then\n    args+=( \"--homedir\" \"$homedir\" )\n  fi\n\n  ## We use --fixed-list-mode so older versions of gpg emit 'uid:' lines.\n  ## Gawk splits on colon as --with-colon, matches field 1 as 'uid',\n  result=$($SECRETS_GPG_COMMAND \"${args[@]}\" --no-permission-warning --list-public-keys --with-colon --fixed-list-mode | \\\n      gawk -F: '$1==\"uid\"' )\n\n  local emails\n  emails=$(_extract_emails_from_gpg_output \"$result\")\n\n  # For #508 / #552: warn user if gpg indicates keys are one of:\n  # i=invalid, d=disabled, r=revoked, e=expired, n=not valid\n  # See https://github.com/gpg/gnupg/blob/master/doc/DETAILS#field-2---validity # for more on gpg 'validity codes'.\n  local invalid_lines\n  invalid_lines=$(echo \"$result\" | gawk -F: '$2==\"i\" || $2==\"d\" || $2==\"r\" || $2==\"e\" || $2==\"n\"')\n\n  local emails_with_invalid_keys\n  emails_with_invalid_keys=$(_extract_emails_from_gpg_output \"$invalid_lines\")\n\n  if [[ -n \"$emails_with_invalid_keys\" ]]; then\n     _warn \"at least one key for email(s) is revoked, expired, or otherwise invalid: $emails_with_invalid_keys\"\n  fi\n\n  echo \"$emails\"\n}\n\n\nfunction _extract_emails_from_gpg_output {\n  local result=$1\n\n  # gensub() outputs email from <> within field 10, \"User-ID\".  If there's no <>, then field is just an email address\n  #  (and maybe a comment) and we pass it through.\n  # Sed at the end removes any 'comment' that appears in parentheses, for #530\n  # 3>&- closes fd 3 for bats, see https://github.com/bats-core/bats-core/blob/master/docs/source/writing-tests.md#file-descriptor-3-read-this-if-bats-hangs\n  local emails\n  emails=$(echo \"$result\" | gawk -F: '{print gensub(/.*<(.*)>.*/, \"\\\\1\", \"g\", $10); }' | sed 's/([^)]*)//g' 3>&-)\n  echo \"$emails\"\n}\n\n\nfunction _get_users_in_gitsecret_keyring {\n  # show the users in the gitsecret keyring.\n  local secrets_dir_keys\n  secrets_dir_keys=$(_get_secrets_dir_keys)\n\n  local result\n  result=$(_get_users_in_gpg_keyring \"$secrets_dir_keys\")\n\n  echo \"$result\"\n}\n\n\nfunction _get_recipients {\n  # This function is required to create an encrypted file for different users.\n  # These users are called 'recipients' in the `gpg` terms.\n  # It basically just parses the `gpg` public keys\n\n  local result\n  # put -r before each user:\n  result=$(_get_users_in_gitsecret_keyring | sed 's/^/-r/')\n  echo \"$result\"\n}\n\n\nfunction _decrypt {\n  # required:\n  local filename=\"$1\"\n\n  # optional:\n  local write_to_file=${2:-1} # can be 0 or 1\n  local force=${3:-0} # can be 0 or 1\n  local homedir=${4:-\"\"}\n  local passphrase=${5:-\"\"}\n  local error_ok=${6:-0} # can be 0 or 1\n\n  local encrypted_filename\n  encrypted_filename=$(_get_encrypted_filename \"$filename\")\n\n  if [ ! -f \"$encrypted_filename\" ]; then\n    _warn_or_abort \"cannot find file to decrypt: $encrypted_filename\" \"1\" \"$error_ok\"\n  else\n    # we no longer use --no-permission-warning on decryption, for #811 \n    local args=( \"--use-agent\" \"--decrypt\" )\n  \n    if [[ \"$write_to_file\" -eq 1 ]]; then\n      args+=( \"-o\" \"$filename\" )\n    fi\n  \n    if [[ \"$force\" -eq 1 ]]; then\n      args+=( \"--yes\" )\n    fi\n  \n    if [[ -n \"$homedir\" ]]; then\n      args+=( \"--homedir\" \"$homedir\" )\n    fi\n  \n    if [[ \"$GPG_VER_MIN_21\" -eq 1 ]]; then\n      if [[ -n \"$SECRETS_PINENTRY\" ]]; then\n        args+=( \"--pinentry-mode\" \"$SECRETS_PINENTRY\" )\n      else\n        args+=( \"--pinentry-mode\" \"loopback\" )\n      fi\n    fi\n\n    if [[ -z \"$_SECRETS_VERBOSE\" ]]; then\n      args+=( \"--quiet\" )\n    fi\n\n    set +e   # disable 'set -e' so we can capture exit_code\n  \n    #echo \"# gpg passphrase: $passphrase\" >&3\n    local exit_code\n    if [[ -n \"$passphrase\" ]]; then\n      exec 5<<<\"$passphrase\"  # use 5, because descriptors 3 and 4 are used by bats\n      $SECRETS_GPG_COMMAND \"${args[@]}\" --batch --yes --no-tty --passphrase-fd 5 \"$encrypted_filename\"\n      exit_code=$?\n      exec 5>&-   # close file descriptor 5\n    else\n      $SECRETS_GPG_COMMAND \"${args[@]}\" \"$encrypted_filename\"\n      exit_code=$?\n    fi\n  \n    set -e  # re-enable set -e\n  \n    # note that according to https://github.com/sobolevn/git-secret/issues/238 ,\n    # it's possible for gpg to return a 0 exit code but not have decrypted the file\n    #echo \"# gpg exit code: $exit_code, error_ok: $error_ok\" >&3\n    if [[ \"$exit_code\" -ne \"0\" ]]; then\n      local msg=\"problem decrypting file with gpg: exit code $exit_code: $filename\"\n      _warn_or_abort \"$msg\" \"$exit_code\" \"$error_ok\"\n    fi\n  fi\n\n  # at this point the file should be written to disk or output to stdout\n}\n"
  },
  {
    "path": "src/_utils/_git_secret_tools_freebsd.sh",
    "content": "#!/usr/bin/env bash\n\n# support for freebsd. Mostly the same as MacOS.\n\n\n# shellcheck disable=SC1117\nfunction __replace_in_file_freebsd {\n  sed -i.bak \"s/^\\($1[[:space:]]*=[[:space:]]*\\).*\\$/\\1$2/\" \"$3\"\n}\n\n\nfunction __temp_file_freebsd {\n  local filename\n  # man mktemp on FreeBSD:\n  # ...\n  # If\tthe -t prefix option is\tgiven, mktemp will generate a template string\n  #   based on the prefix and the TMPDIR\tenvironment variable if\tset.  The\n  #   default location if TMPDIR\tis not set is /tmp. \"\n\n  filename=$(mktemp -t _git_secret )\n  echo \"$filename\";\n}\n\n\nfunction __sha256_freebsd {\n  # this is in a different location than MacOS\n  /usr/local/bin/shasum -a256 \"$1\"\n}\n\nfunction __get_octal_perms_freebsd {\n  local filename\n  filename=$1\n  local perms\n  perms=$(stat -f \"%04OLp\" \"$filename\")\n  # perms is a string like '0644'.\n  # In the \"%04OLp':\n  #   the '04' means 4 digits, 0 padded.  So we get 0644, not 644.\n  #   the 'O' means Octal.\n  #   the 'Lp' means 'low subfield of file type and permissions (st_mode).'\n  #     (without 'L' you get 6 digits like '100644'.)\n  echo \"$perms\"\n}\n\nfunction __epoch_to_date_freebsd {\n  local epoch=$1;\n  if [ -z \"$epoch\" ]; then\n    echo ''\n  else\n    local cmd=\"date -I -r $epoch\"\n    #echo \"# running: $cmd\" >&3\n    local datetime\n    datetime=$($cmd)\n    echo \"$datetime\"\n  fi\n}\n"
  },
  {
    "path": "src/_utils/_git_secret_tools_linux.sh",
    "content": "#!/usr/bin/env bash\n\n\n# shellcheck disable=SC1117\nfunction __replace_in_file_linux {\n  sed -i.bak \"s/^\\($1\\s*=\\s*\\).*\\$/\\1$2/\" \"$3\"\n}\n\n\nfunction __temp_file_linux {\n  local filename\n  # man mktemp on CentOS 7:\n  # mktemp [OPTION]... [TEMPLATE]\n  # ...\n  #  -p DIR, --tmpdir[=DIR]\n  #        interpret TEMPLATE relative to DIR; if DIR is not specified,\n  #        use $TMPDIR if set, else /tmp.  With this option, TEMPLATE\n  #        must not be an absolute name; unlike  with -t, TEMPLATE may\n  #        contain slashes, but mktemp creates only the final component\n  # ...\n  #  -t     interpret TEMPLATE as a single file name component,\n  #         relative to a directory: $TMPDIR, if set; else the directory\n  #         specified via -p; else /tmp [deprecated]\n\n  filename=$(mktemp -p \"${TMPDIR}\" _git_secret.XXXXXX )\n  # makes a filename like /$TMPDIR/_git_secret.ONIHo\n  echo \"$filename\"\n}\n\nfunction __sha256_linux {\n  sha256sum \"$1\"\n}\n\nfunction __get_octal_perms_linux {\n  local filename\n  filename=$1\n\n  local stat_is_busybox\n  stat_is_busybox=$(_exe_is_busybox \"stat\")\n  local perms   # a string like '644'\n  if [ \"$stat_is_busybox\" -eq 1 ]; then\n    # special case for busybox, which doesn't understand --format\n    perms=$(stat -c '%a' \"$filename\")\n  else\n    perms=$(stat --format '%a' \"$filename\")\n  fi\n  echo \"$perms\"\n}\n\nfunction __epoch_to_date_linux {\n  local epoch=$1;\n  if [ -z \"$epoch\" ]; then\n    echo ''\n  else\n    local cmd=\"date +%F -d @$epoch\"\n    local datetime\n    datetime=$($cmd)\n    echo \"$datetime\"\n  fi\n}\n"
  },
  {
    "path": "src/_utils/_git_secret_tools_osx.sh",
    "content": "#!/usr/bin/env bash\n\n\n# shellcheck disable=SC1117\nfunction __replace_in_file_osx {\n  sed -i.bak \"s/^\\($1[[:space:]]*=[[:space:]]*\\).*\\$/\\1$2/\" \"$3\"\n}\n\n\nfunction __temp_file_osx {\n  local filename\n  # man mktemp on OSX:\n  # ...\n  # \"If the -t prefix option is given, mktemp will generate a template string\n  #   based on the prefix and the _CS_DARWIN_USER_TEMP_DIR configuration vari-\n  #   able if available.  Fallback locations if _CS_DARWIN_USER_TEMP_DIR is not\n  #   available are TMPDIR and /tmp.\"\n\n  # we use /usr/bin/mktemp in case there's another mktemp available. See #485\n  filename=$(/usr/bin/mktemp -t _git_secret )\n  # On OSX this can make a filename like\n  # '/var/folders/nz/vv4_91234569k3tkvyszvwg90009gn/T/_git_secret.HhvUPlUI'\n  echo \"$filename\";\n}\n\n\nfunction __sha256_osx {\n  /usr/bin/shasum -a256 \"$1\"\n}\n\nfunction __get_octal_perms_osx {\n  local filename\n  filename=$1\n  local perms\n  # we use /usr/bin/stat in case there's another stat available from brew. See #918\n  perms=$(/usr/bin/stat -f \"%04OLp\" \"$filename\")\n  # see _git_secret_tools_freebsd.sh for more about stat's format string\n  echo \"$perms\"\n}\n\nfunction __epoch_to_date_osx {\n  local epoch=$1;\n  if [ -z \"$epoch\" ]; then\n    echo ''\n  else\n    #date -r 234234234 +\"%Y-%m-%d\"\n    local datetime\n    datetime=$(date -r \"$epoch\" +'%Y-%m-%d')\n    echo \"$datetime\"\n  fi\n}\n\n"
  },
  {
    "path": "src/commands/git_secret_add.sh",
    "content": "#!/usr/bin/env bash\n\n\nfunction add {\n  OPTIND=1\n\n  while getopts \"ihv\" opt; do\n    case \"$opt\" in\n      i) ;;    # this doesn't change anything\n\n      h) _show_manual_for \"add\";;\n\n      v) _SECRETS_VERBOSE=1;;\n\n      *) _invalid_option_for \"add\";;\n    esac\n  done\n\n  shift $((OPTIND-1))\n  [ \"$1\" = \"--\" ] && shift\n\n  _user_required\n\n  # Checking if all files are correct (ignored and inside the repo):\n\n  local not_ignored=()\n  local items=( \"$@\" )\n\n  # Checking if all files in options are ignored:\n  for item in \"${items[@]}\"; do\n    local path # absolute path\n    local normalized_path # relative to the .git dir\n    normalized_path=$(_git_normalize_filename \"$item\")\n    path=$(_prepend_root_path \"$normalized_path\")\n\n    # check that the file is not tracked\n    local in_git\n    in_git=$(_is_tracked_in_git \"$item\")\n    if [[ \"$in_git\" -ne 0  ]]; then\n       _abort \"file tracked in git, consider using 'git rm --cached $item'\"\n    fi\n\n    # Checking that file is valid:\n    if [[ ! -f \"$path\" ]]; then\n      _abort \"file not found: $item\"\n    fi\n\n    # Checking that it is ignored:\n    local ignored\n    ignored=$(_check_ignore \"$path\")\n\n    if [[ \"$ignored\" -ne 0 ]]; then\n      # Collect unignored files:\n      not_ignored+=(\"$normalized_path\")\n    fi\n  done\n\n  # Are there any unignored files?\n\n  if [[ ! \"${#not_ignored[@]}\" -eq 0 ]]; then\n    # Add these files to `.gitignore` automatically:\n    # see https://github.com/sobolevn/git-secret/issues/18 for more.\n\n    for item in \"${not_ignored[@]}\"; do\n      _message \"file not in .gitignore, adding: $item\"\n      _add_ignored_file \"$item\"\n    done\n  fi\n\n  # Adding files to path mappings:\n\n  local fsdb\n  fsdb=$(_get_secrets_dir_paths_mapping)\n  local count\n  count=0\n\n  for item in \"${items[@]}\"; do\n    local path\n    local key\n    path=$(_git_normalize_filename \"$item\")\n    key=\"$path\"\n\n    # Adding files into system, skipping duplicates.\n    local already_in\n    already_in=$(_fsdb_has_record \"$key\" \"$fsdb\")\n    if [[ \"$already_in\" -eq 1 ]]; then\n      echo \"$key\" >> \"$fsdb\"\n       if [[ -n \"$_SECRETS_VERBOSE\" ]]; then\n        _message \"adding file: $key\"\n      fi\n\n      ((count=count+1))\n    fi\n  done\n\n  _message \"$count item(s) added.\"\n}\n"
  },
  {
    "path": "src/commands/git_secret_cat.sh",
    "content": "#!/usr/bin/env bash\n\n\nfunction cat {\n  local homedir=''\n  local passphrase=''\n\n  OPTIND=1\n\n  while getopts 'hd:p:' opt; do\n    case \"$opt\" in\n      h) _show_manual_for 'cat';;\n\n      p) passphrase=$OPTARG;;\n\n      d) homedir=$(_clean_windows_path \"$OPTARG\");;\n\n      *) _invalid_option_for 'cat';;\n    esac\n  done\n\n  shift $((OPTIND-1))\n  [ \"$1\" = '--' ] && shift\n\n  _user_required\n\n  # Command logic:\n\n  for line in \"$@\"\n  do\n    local filename\n    local path\n\n    filename=$(_get_record_filename \"$line\")\n    path=$(_prepend_relative_root_path \"$filename\")  # this uses the _relative version because of #710\n\n    # The parameters are: filename, write-to-file, force, homedir, passphrase\n    _decrypt \"$path\" \"0\" \"0\" \"$homedir\" \"$passphrase\"\n  done\n}\n"
  },
  {
    "path": "src/commands/git_secret_changes.sh",
    "content": "#!/usr/bin/env bash\n\nfunction changes {\n  local passphrase=\"\"\n\n  OPTIND=1\n\n  while getopts 'hd:p:' opt; do\n    case \"$opt\" in\n      h) _show_manual_for 'changes';;\n\n      p) passphrase=$OPTARG;;\n\n      d) homedir=$(_clean_windows_path \"$OPTARG\");;\n\n      *) _invalid_option_for 'changes';;\n    esac\n  done\n\n  shift $((OPTIND-1))\n  [ \"$1\" = '--' ] && shift\n\n  _user_required\n\n  filenames=(\"$@\")  # list of positional parameters. global.\n  if [[ ${#filenames[@]} -eq 0 ]]; then\n    # Checking if no filenames are passed, show diff for all files.\n    _list_all_added_files    # this sets the array variable 'filenames'\n  fi\n\n  IFS='\n  '\n\n  for filename in \"${filenames[@]}\"; do\n    local path # absolute path\n    local normalized_path # relative to the .git dir\n    local encrypted_filename\n    normalized_path=$(_git_normalize_filename \"$filename\")\n    encrypted_filename=$(_get_encrypted_filename \"$filename\")\n\n    if [[ ! -f \"$encrypted_filename\" ]]; then\n        _abort \"cannot find encrypted version of file: $filename\"\n    fi\n    if [[ -n \"$normalized_path\" ]]; then\n      path=$(_prepend_root_path \"$normalized_path\")\n    else\n      # Path was already normalized\n      path=$(_prepend_root_path \"$filename\")\n    fi\n\n    if [[ ! -f \"$path\" ]]; then\n        _abort \"file not found. Consider using 'git secret reveal': $filename\"\n    fi\n\n    # Now we have all the data required to do the last encryption and compare results:\n    # now do a two-step to protect trailing newlines from the $() construct.\n    local decrypted_x\n    local decrypted\n    decrypted_x=$(_decrypt \"$path\" \"0\" \"0\" \"$homedir\" \"$passphrase\"; echo x$?)\n    decrypted=\"${decrypted_x%x*}\"\n    # we ignore the exit code because _decrypt will abort_ if appropriate.\n\n\n    _message \"changes in ${path}:\"\n    # diff the result:\n    # we have the '|| true' because `diff` returns error code if files differ.\n    diff -u <(echo -n \"$decrypted\") \"$path\" || true\n  done\n}\n"
  },
  {
    "path": "src/commands/git_secret_clean.sh",
    "content": "#!/usr/bin/env bash\n\n\nfunction clean {\n  OPTIND=1\n\n  # shellcheck disable=SC2034\n  while getopts 'vh' opt; do\n    case \"$opt\" in\n      v) _SECRETS_VERBOSE=1;;\n\n      h) _show_manual_for 'clean';;\n\n      *) _invalid_option_for 'clean';;\n    esac\n  done\n\n  shift $((OPTIND-1))\n  [ \"$1\" = '--' ] && shift\n\n  if [ $# -ne 0 ]; then\n    _abort \"clean does not understand params: $*\"\n  fi\n\n  _user_required\n\n  _find_and_remove_secrets_formatted\n}\n"
  },
  {
    "path": "src/commands/git_secret_hide.sh",
    "content": "#!/usr/bin/env bash\n\n# shellcheck disable=SC2016\nAWK_FSDB_UPDATE_HASH='\nBEGIN { FS=\":\"; OFS=\":\"; }\n{\n  if ( key == $1 )\n  {\n    print key,hash;\n  }\n  else\n  {\n    print $1,$2;\n  }\n}\n'\n\n\nfunction _optional_delete {\n  local delete=\"$1\"\n\n  if [[ $delete -eq 1 ]]; then\n    local path_mappings\n    path_mappings=$(_get_secrets_dir_paths_mapping)\n\n    # We use custom formatting here:\n    if [[ -n \"$_SECRETS_VERBOSE\" ]]; then\n      _message 'removing unencrypted files'\n    fi\n\n    while read -r line; do  # each line is a record like: filename: or filename:hash\n      local filename\n      filename=$(_get_record_filename \"$line\")\n      if [[ -e \"$filename\" ]]; then \n        rm \"$filename\"\n        if [[ -n \"$_SECRETS_VERBOSE\" ]]; then\n          _message \"deleted: $filename\"\n        fi\n      fi\n    done < \"$path_mappings\"\n  fi\n}\n\nfunction _get_checksum_local {\n  local checksum=\"$SECRETS_CHECKSUM_COMMAND\"\n  echo \"$checksum\"\n}\n\nfunction _get_file_hash {\n  local input_path=\"$1\" # Required\n  local checksum_local\n  local file_hash\n\n  checksum_local=\"$(_get_checksum_local)\"\n  file_hash=$($checksum_local \"$input_path\" | gawk '{print $1}')\n\n  echo \"$file_hash\"\n}\n\nfunction _fsdb_update_hash {\n  local key=\"$1\"\n  local hash=\"$2\"\n  local fsdb          # path_mappings\n\n  fsdb=$(_get_secrets_dir_paths_mapping)\n\n  _gawk_inplace -v \"key=$key\" -v \"hash=$hash\" \"$AWK_FSDB_UPDATE_HASH\" \"$fsdb\"\n}\n\n\nfunction hide {\n  local clean=0\n  local preserve=0\n  local delete=0\n  local update_only_modified=0\n  local force_continue=0\n\n  OPTIND=1\n\n  while getopts 'cFPdmvh' opt; do\n    case \"$opt\" in\n      c) clean=1;;\n\n      F) force_continue=1;;\n\n      P) preserve=1;;\n\n      d) delete=1;;\n\n      m) update_only_modified=1;;\n\n      v) _SECRETS_VERBOSE=1;;\n\n      h) _show_manual_for 'hide';;\n\n      *) _invalid_option_for 'hide';;\n    esac\n  done\n\n  shift $((OPTIND-1))\n  [ \"$1\" = '--' ] && shift\n\n  if [ $# -ne 0 ]; then\n    _abort \"hide does not understand params: $*\"\n  fi\n\n  # We need user to continue:\n  _user_required\n\n  # If -c option was provided, clean the hidden files\n  # before creating new ones.\n  # BUG: if passed files, we should only delete them, but we always delete all secret files; see issue #834\n  if [[ $clean -eq 1 ]]; then\n    _find_and_remove_secrets_formatted\n  fi\n\n  # Encrypting files:\n\n  local path_mappings\n  path_mappings=$(_get_secrets_dir_paths_mapping)\n  local num_mappings\n  num_mappings=$(gawk 'END{print NR}' \"$path_mappings\")\n\n  # make sure all the unencrypted files needed are present\n  local to_hide=()\n  while read -r record; do\n    to_hide+=(\"$record\")  # add record to array\n  done < \"$path_mappings\"\n\n  local recipients\n  recipients=$(_get_recipients)\n\n  local secrets_dir_keys\n  secrets_dir_keys=$(_get_secrets_dir_keys)\n\n  local counter=0\n  for record in \"${to_hide[@]}\"; do\n    local filename\n    local fsdb_file_hash\n    local encrypted_filename\n    filename=$(_get_record_filename \"$record\")\n    fsdb_file_hash=$(_get_record_hash \"$record\")\n    encrypted_filename=$(_get_encrypted_filename \"$filename\")\n\n    local input_path\n    local output_path\n    input_path=$(_prepend_root_path \"$filename\")\n    output_path=$(_prepend_root_path \"$encrypted_filename\")\n\n    # Checking that file is valid:\n    if [[ ! -f \"$input_path\" ]]; then\n      # this catches the case where some decrypted files don't exist\n      _warn_or_abort \"file not found: $input_path\" \"1\" \"$force_continue\"\n    else\n      file_hash=$(_get_file_hash \"$input_path\")\n\n      # encrypt file only if required\n      if [[ \"$update_only_modified\" -eq 0 ]] ||\n         [[ \"$fsdb_file_hash\" != \"$file_hash\" ]]; then\n\n        # we no longer use --no-permission-warning here, for #811\n        local args=( --homedir \"$secrets_dir_keys\" --use-agent --yes '--trust-model=always' --encrypt )\n\n        # SECRETS_GPG_ARMOR is expected to be empty or '1'.\n        # Empty means 'off', any other value means 'on'.\n        # See: https://github.com/sobolevn/git-secret/pull/661\n        # shellcheck disable=SC2153\n        if [[ -n \"$SECRETS_GPG_ARMOR\" ]] &&\n           [[ \"$SECRETS_GPG_ARMOR\" -ne 0 ]]; then\n          args+=( '--armor' )\n        fi\n\n        if [[ -n \"$_SECRETS_VERBOSE\" ]]; then\n          args+=( '--verbose' )\n        fi\n\n        # we depend on $recipients being split on whitespace\n        # shellcheck disable=SC2206\n        args+=( $recipients -o \"$output_path\" \"$input_path\" )\n\n        set +e  # disable 'set -e' so we can capture exit_code\n\n     \t  # For info about `3>&-` see:\n        # https://github.com/bats-core/bats-core/blob/master/docs/source/writing-tests.md#file-descriptor-3-read-this-if-bats-hangs\n        local gpg_output\n        gpg_output=$($SECRETS_GPG_COMMAND \"${args[@]}\" 3>&-)  # we leave stderr alone\n        local exit_code=$?\n\n        set -e  # re-enable set -e\n\n        local error=0\n        if [[ \"$exit_code\" -ne 0 ]] || [[ ! -f \"$output_path\" ]]; then\n          error=1\n        fi\n\n        if [[ \"$error\" -ne 0 ]] || [[ -n \"$_SECRETS_VERBOSE\" ]]; then\n          if [[ -n \"$gpg_output\" ]]; then\n            echo \"$gpg_output\"\n          fi\n        fi\n\n        if [[ ! -f \"$output_path\" ]]; then\n          # if gpg can't encrypt a file we asked it to, that's an error unless in force_continue mode.\n          _warn_or_abort \"problem encrypting file with gpg: exit code $exit_code: $filename\" \"$exit_code\" \"$force_continue\"\n        else\n          counter=$((counter+1))\n          if [[ \"$preserve\" == 1 ]]; then\n            local perms\n            perms=$($SECRETS_OCTAL_PERMS_COMMAND \"$input_path\")\n            chmod \"$perms\" \"$output_path\"\n          fi\n        fi\n\n        # Update file hash for future use of -m\n        local key=\"$filename\"\n        local hash=\"$file_hash\"\n        _fsdb_update_hash \"$key\" \"$hash\"\n      fi\n    fi\n  done\n\n  # If -d option was provided, it would delete the source files\n  # after we have already hidden them.\n  _optional_delete \"$delete\"\n\n  _message \"done. $counter of $num_mappings files are hidden.\"\n}\n"
  },
  {
    "path": "src/commands/git_secret_init.sh",
    "content": "#!/usr/bin/env bash\n\n# shellcheck disable=SC2016\nAWK_ADD_TO_GITIGNORE='\nBEGIN {\n  cnt=0\n}\n\nfunction check_print_line(line){\n  if (line == pattern) {\n    cnt++\n  }\n  print line\n}\n\n# main function\n{\n  check_print_line($0)      # check and print first line\n  while (getline == 1) {    # check and print all other\n    check_print_line($0)\n  }\n}\n\nEND {\n  if ( cnt == 0) {         # if file did not contain pattern add\n    print pattern\n  }\n}\n'\n\nfunction gitignore_add_pattern {\n  local pattern\n  local gitignore_file_path\n\n  pattern=\"$1\"\n  gitignore_file_path=$(_prepend_root_path '.gitignore')\n\n  _maybe_create_gitignore\n  _gawk_inplace -v \"pattern=$pattern\" \"$AWK_ADD_TO_GITIGNORE\" \"$gitignore_file_path\"\n}\n\nfunction init {\n  OPTIND=1\n\n  while getopts 'h' opt; do\n    case \"$opt\" in\n      h) _show_manual_for 'init';;\n\n      *) _invalid_option_for 'init';;\n    esac\n  done\n\n  shift $((OPTIND-1))\n  [ \"$1\" = '--' ] && shift\n\n  if [ $# -ne 0 ]; then\n    _abort \"init does not understand params: $*\"\n  fi\n\n  # Check if '.gitsecret/' already exists:\n  local git_secret_dir\n  git_secret_dir=$(_get_secrets_dir)\n\n  if [[ -d \"$git_secret_dir\" ]]; then\n    _abort 'already initialized.'\n  fi\n\n  # Check if it is ignored:\n  _secrets_dir_is_not_ignored\n\n  # Create internal files:\n\n  mkdir \"$git_secret_dir\" \"$(_get_secrets_dir_keys)\" \"$(_get_secrets_dir_path)\"\n  chmod 700 \"$(_get_secrets_dir_keys)\"  # for #811, set to rwx------\n  touch \"$(_get_secrets_dir_paths_mapping)\"\n\n  _message \"init created: '$git_secret_dir/'\"\n\n  local random_seed_file\n  random_seed_file=\"${_SECRETS_DIR}/keys/random_seed\"\n  gitignore_add_pattern \"$random_seed_file\"\n  gitignore_add_pattern \"!*$SECRETS_EXTENSION\"\n\n  # TODO: git attributes to view diffs\n}\n"
  },
  {
    "path": "src/commands/git_secret_list.sh",
    "content": "#!/usr/bin/env bash\n\n\nfunction list {\n  OPTIND=1\n\n  while getopts 'h' opt; do\n    case \"$opt\" in\n      h) _show_manual_for 'list';;\n\n      *) _invalid_option_for 'list';;\n    esac\n  done\n\n  shift $((OPTIND-1))\n  [ \"$1\" = '--' ] && shift\n\n  if [ $# -ne 0 ]; then\n    _abort \"list does not understand params: $*\"\n  fi\n\n  _user_required\n\n  # Command logic:\n  filenames=()\n  _list_all_added_files  # exports 'filenames' array\n  local filename\n  for filename in \"${filenames[@]}\"; do\n    echo \"$filename\"    # do not prepend 'git-secret: '\n  done\n}\n"
  },
  {
    "path": "src/commands/git_secret_remove.sh",
    "content": "#!/usr/bin/env bash\n\n\nfunction remove {\n  local clean=0\n\n  OPTIND=1\n\n  while getopts 'ch' opt; do\n    case \"$opt\" in\n      c) clean=1;;\n\n      h) _show_manual_for 'remove';;\n\n      *) _invalid_option_for 'remove';;\n    esac\n  done\n\n  shift $((OPTIND-1))\n  [ \"$1\" = '--' ] && shift\n\n  # Validate if user exists:\n  _user_required\n\n  # Command logic:\n\n  local path_mappings\n  path_mappings=$(_get_secrets_dir_paths_mapping)\n\n  for item in \"$@\"; do\n    local path # absolute path\n    local normalized_path # relative to .git folder\n    normalized_path=$(_git_normalize_filename \"$item\")\n    path=$(_prepend_root_path \"$normalized_path\")\n\n    # Checking if file exists:\n    if [[ ! -f \"$path\" ]]; then\n      _abort \"file not found: $item\"\n    fi\n\n    # Deleting it from path mappings:\n    # Remove record from fsdb with matching key\n    local key\n    key=\"$normalized_path\"\n    fsdb=\"$path_mappings\"\n    _fsdb_rm_record \"$key\" \"$fsdb\"\n\n    rm -f \"${path_mappings}.bak\"  # not all systems create '.bak'\n\n    # Optional clean:\n    if [[ \"$clean\" -eq 1 ]]; then\n      local encrypted_filename\n      encrypted_filename=$(_get_encrypted_filename \"$path\")\n\n      rm \"$encrypted_filename\" # fail on error\n      if [[ -n \"$_SECRETS_VERBOSE\" ]]; then\n          _message \"deleted: $encrypted_filename\"\n      fi\n    fi\n  done\n\n  echo 'git-secret: removed from index.'\n  echo \"git-secret: ensure that files: [$*] are now not ignored.\"\n}\n"
  },
  {
    "path": "src/commands/git_secret_removeperson.sh",
    "content": "#!/usr/bin/env bash\n\n\nfunction removeperson {\n  OPTIND=1\n\n  while getopts 'h' opt; do\n    case \"$opt\" in\n      h) _show_manual_for 'removeperson';;\n\n      *) _invalid_option_for 'removeperson';;\n    esac\n  done\n\n  shift $((OPTIND-1))\n  [ \"$1\" = \"--\" ] && shift\n\n  _user_required\n\n  # Command logic:\n\n  local emails=( \"$@\" )\n\n  if [[ ${#emails[@]} -eq 0 ]]; then\n    _abort \"at least one email or fingerprint is required for removeperson.\"\n  fi\n  # Getting the local git-secret `gpg` key directory:\n  local secrets_dir_keys\n  secrets_dir_keys=$(_get_secrets_dir_keys)\n\n  _assert_keyring_contains_emails_at_least_once \"$secrets_dir_keys\" \"git-secret keyring\" \"${emails[@]}\"\n\n  local args=( --homedir \"$secrets_dir_keys\" --batch --yes )\n  # we no longer use --no-permission-warning here in non-verbose mode, for #811\n\n  for email in \"${emails[@]}\"; do\n    # see https://github.com/bats-core/bats-core/blob/master/docs/source/writing-tests.md#file-descriptor-3-read-this-if-bats-hangs for info about 3>&-\n    $SECRETS_GPG_COMMAND \"${args[@]}\" --delete-key \"$email\" 3>&-\n    local exit_code=$?\n    if [[ \"$exit_code\" -ne 0 ]]; then\n      _abort \"problem deleting key for '$email' with gpg: exit code $exit_code\"\n    fi\n  done\n\n  _message 'removed keys.'\n  _message \"now [$*] do not have an access to the repository.\"\n  _message 'make sure to hide the existing secrets again.'\n}\n\nfunction killperson {\n  echo \"Warning: 'killperson' has been renamed to 'removeperson'. This alias will be removed in the future versions, please switch to call 'removeperson' going forward.\"\n\n  removeperson \"$@\"\n}\n"
  },
  {
    "path": "src/commands/git_secret_reveal.sh",
    "content": "#!/usr/bin/env bash\n\n\nfunction reveal {\n  local homedir=''\n  local passphrase=''\n  local force=0             # this means 'clobber without warning'\n  local force_continue=0    # this means 'continue if we have decryption errors'\n  local preserve=0\n\n  OPTIND=1\n\n  while getopts 'hfFPd:p:v' opt; do\n    # line below is for _SECRETS_VERBOSE\n    # shellcheck disable=SC2034\n    case \"$opt\" in\n      h) _show_manual_for 'reveal';;\n\n      f) force=1;;\n\n      F) force_continue=1;;\n\n      P) preserve=1;;\n\n      p) passphrase=$OPTARG;;\n\n      d) homedir=$(_clean_windows_path \"$OPTARG\");;\n\n      v) _SECRETS_VERBOSE=1;;\n\n      *) _invalid_option_for 'reveal';;\n    esac\n  done\n\n  shift $((OPTIND-1))\n  [ \"$1\" = '--' ] && shift\n\n  _user_required\n\n  # Command logic:\n\n  local path_mappings\n  path_mappings=$(_get_secrets_dir_paths_mapping)\n\n  local counter=0\n  local to_show=( \"$@\" )\n  local path_prepend_func='_prepend_relative_root_path'\n\n  if [ ${#to_show[@]} -eq 0 ]; then\n    path_prepend_func='_prepend_root_path'\n    while read -r record; do\n      to_show+=(\"$record\")  # add record to array\n    done < \"$path_mappings\"\n  fi\n\n  for line in \"${to_show[@]}\"; do\n    local filename\n    local path\n    filename=$(_get_record_filename \"$line\")\n    path=$(\"$path_prepend_func\" \"$filename\")\n\n    if [[ \"$filename\" == *\"$SECRETS_EXTENSION\" ]]; then\n      _abort \"cannot decrypt to secret version of file: $filename\"\n    fi\n\n    # The parameters are: filename, write-to-file, force, homedir, passphrase, error_ok\n    _decrypt \"$path\" \"1\" \"$force\" \"$homedir\" \"$passphrase\" \"$force_continue\"\n\n    if [[ ! -f \"$path\" ]]; then\n      _warn_or_abort \"cannot find decrypted version of file: $filename\" \"2\" \"$force_continue\"\n    else\n      counter=$((counter+1))\n      local secret_file\n      secret_file=$(_get_encrypted_filename \"$path\")\n      if [[ \"$preserve\" == 1 ]] && [[ -f \"$secret_file\" ]]; then\n        local perms\n        perms=$($SECRETS_OCTAL_PERMS_COMMAND \"$secret_file\")\n        chmod \"$perms\" \"$path\"\n      fi\n    fi\n\n  done\n\n  _message \"done. $counter of ${#to_show[@]} files are revealed.\"\n}\n"
  },
  {
    "path": "src/commands/git_secret_tell.sh",
    "content": "#!/usr/bin/env bash\n\n# shellcheck disable=SC2016\nAWK_GPG_KEY_CNT='\nBEGIN { cnt=0; OFS=\":\"; FS=\":\"; }\nflag=0; $1 == \"pub\" { cnt++ }\nEND { print cnt }\n'\n\nfunction get_gpg_key_count {\n  local secrets_dir_keys\n  secrets_dir_keys=$(_get_secrets_dir_keys)\n  # 3>&- closes fd 3 for bats, see https://github.com/bats-core/bats-core/blob/master/docs/source/writing-tests.md#file-descriptor-3-read-this-if-bats-hangs\n  $SECRETS_GPG_COMMAND --homedir \"$secrets_dir_keys\" --no-permission-warning --list-public-keys --with-colon | gawk \"$AWK_GPG_KEY_CNT\" 3>&-\n  local exit_code=$?\n  if [[ \"$exit_code\" -ne 0 ]]; then\n    _abort \"problem counting keys with gpg: exit code $exit_code\"\n  fi\n}\n\nfunction tell {\n  local emails\n  local self_email=0\n  local homedir\n\n  # A POSIX variable\n  # Reset in case getopts has been used previously in the shell.\n  OPTIND=1\n\n  while getopts \"vhmd:\" opt; do\n    case \"$opt\" in\n      v) _SECRETS_VERBOSE=1;;\n\n      h) _show_manual_for \"tell\";;\n\n      m) self_email=1;;\n\n      d) homedir=$(_clean_windows_path \"$OPTARG\");;\n\n      *) _invalid_option_for 'tell';;\n    esac\n  done\n\n  shift $((OPTIND-1))\n  [ \"$1\" = \"--\" ] && shift\n\n  # Validates that application is initialized:\n  _secrets_dir_exists\n\n  # Command logic:\n  emails=( \"$@\" )\n  local git_email\n\n  if [[ \"$self_email\" -eq 1 ]]; then\n    git_email=$(git config user.email)\n\n    if [[ -z \"$git_email\" ]]; then\n      _abort \"'git config user.email' is not set.\"\n    fi\n\n    emails+=(\"$git_email\")\n  fi\n\n  if [[ \"${#emails[@]}\" -eq 0 ]]; then\n    # If after possible addition of git_email, emails are still empty,\n    # we should raise an exception.\n    _abort \"you must use -m or provide at least one email address or fingerprint.\"\n  fi\n\n  local secrets_dir_keys\n  secrets_dir_keys=$(_get_secrets_dir_keys)\n\n  _assert_keyring_contains_emails \"$homedir\" \"user keyring\" \"${emails[@]}\"\n  _assert_keyring_doesnt_contain_emails \"$secrets_dir_keys\" \"git-secret keyring\" \"${emails[@]}\"\n\n  local start_key_cnt\n  start_key_cnt=$(get_gpg_key_count)\n  for email in \"${emails[@]}\"; do\n    _temporary_file  # note that `_temporary_file` will export `temporary_filename` var.\n    # shellcheck disable=SC2154\n    local keyfile=\"$temporary_filename\"\n\n    # 3>&- closes fd 3 for bats, see https://github.com/bats-core/bats-core/blob/master/docs/source/writing-tests.md#file-descriptor-3-read-this-if-bats-hangs\n    local exit_code\n    if [[ -z \"$homedir\" ]]; then\n      $SECRETS_GPG_COMMAND --export -a \"$email\" > \"$keyfile\" 3>&-\n      exit_code=$?\n    else\n      # This means that homedir is set as an extra argument via `-d`:\n      # we no longer use --no-permission-warning here, for #811\n      $SECRETS_GPG_COMMAND --homedir=\"$homedir\" \\\n        --export -a \"$email\" > \"$keyfile\" 3>&-\n      exit_code=$?\n    fi\n    if [[ \"$exit_code\" -ne 0 ]]; then\n      _abort \"problem exporting public key for '$email' with gpg: exit code $exit_code\"\n    fi\n\n    if [[ ! -s \"$keyfile\" ]]; then\n      _abort \"no keyfile found for '$email'. Check your key name: 'gpg --list-keys'.\"\n    fi\n\n    # Importing public key to the local keyring:\n    local args=( --homedir \"$secrets_dir_keys\" --import \"$keyfile\" )\n    if [[ -z \"$_SECRETS_VERBOSE\" ]]; then\n      $SECRETS_GPG_COMMAND \"${args[@]}\" > /dev/null 2>&1 3>&-\n    else\n      $SECRETS_GPG_COMMAND \"${args[@]}\" 3>&-\n    fi\n    exit_code=$?\n\n    rm -f \"$keyfile\" || _abort \"error removing temporary keyfile: $keyfile\"\n\n    if [[ \"$exit_code\" -ne 0 ]]; then\n      _abort \"problem importing public key for '$email' with gpg: exit code $exit_code\"\n    fi\n  done\n\n  _message \"done. ${emails[*]} added as user(s) who know the secret.\"\n\n  # force re-encrypting of files if required\n  local fsdb\n  local end_key_cnt\n  fsdb=$(_get_secrets_dir_paths_mapping)\n  end_key_cnt=$(get_gpg_key_count)\n  [[ $start_key_cnt -ne $end_key_cnt ]] && _fsdb_clear_hashes \"$fsdb\"\n}\n"
  },
  {
    "path": "src/commands/git_secret_usage.sh",
    "content": "#!/usr/bin/env bash\n\n\nfunction usage {\n  OPTIND=1\n\n  while getopts \"h?\" opt; do\n    case \"$opt\" in\n      h) _show_manual_for \"usage\";;\n\n      *) _invalid_option_for \"usage\";;\n    esac\n  done\n\n  shift $((OPTIND-1))\n  [ \"$1\" = \"--\" ] && shift\n\n  echo \"usage: git secret [--version] [command] [command-options]\"\n  echo \"\"\n  echo \"options:\"\n  echo \" --version                 - prints the version number\"\n  echo \"\"\n  echo \"commands:\"\n  echo \"see 'git secret [command] -h' for more info about commands and their options\"\n  echo \" add [file.txt]            - adds file to be hidden to the list\"\n  echo \" cat [file.txt]            - decrypts and prints contents of the file\"\n  echo \" changes [file.txt.secret] - indicates if the file changed since last commit\"\n  echo \" clean                     - deletes all encrypted files\"\n  echo \" hide                      - encrypts (or re-encrypts) the files to be hidden\"\n  echo \" init                      - initializes the  git-secret repository\"\n  echo \" removeperson [emails]     - deletes a person's public key from the keyring\"\n  echo \" list                      - prints all the added files\"\n  echo \" remove [files]            - removes files from the list of hidden files\"\n  echo \" reveal                    - decrypts all hidden files\"\n  echo \" tell [email]              - imports a person's public key into the keyring\"\n  echo \" usage                     - prints this message\"\n  echo \" whoknows                  - prints list of authorized email addresses\"\n}\n"
  },
  {
    "path": "src/commands/git_secret_whoknows.sh",
    "content": "#!/usr/bin/env bash\n\n\nfunction whoknows {\n  OPTIND=1\n\n  local long_display=0\n  while getopts \"hl?\" opt; do\n    case \"$opt\" in\n      h) _show_manual_for \"whoknows\";;\n\n      l) long_display=1;;   # like ls -l\n\n      *) _invalid_option_for \"whoknows\";;\n    esac\n  done\n\n  shift $((OPTIND-1))\n  [ \"$1\" = \"--\" ] && shift\n\n  if [ $# -ne 0 ]; then\n    _abort \"whoknows does not understand params: $*\"\n  fi\n\n  # Validating, that we have a user:\n  _user_required\n\n  local users\n\n  # Getting the users from gpg:\n  users=$(_get_users_in_gitsecret_keyring)\n  for user in $users; do\n      echo -n \"$user\"\n\n      if [[ \"$long_display\" -eq 1 ]]; then\n        local expiration\n        expiration=$(_get_user_key_expiry \"$user\")\n        if [[ -n \"$expiration\"  ]]; then\n          local expiration_date\n          expiration_date=$($SECRETS_EPOCH_TO_DATE \"$expiration\")\n          echo -n \" (expires: $expiration_date)\"\n        else\n          echo -n \" (expires: never)\"\n        fi\n      fi\n\n      echo\n  done\n}\n"
  },
  {
    "path": "src/main.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\nfunction _check_setup {\n  # Checking git and secret-plugin setup:\n  local is_tree\n  is_tree=$(_is_inside_git_tree)\n  if [[ \"$is_tree\" -ne 0 ]]; then\n    _abort \"git cannot locate repo. Perhaps use 'git init'/'git clone', then 'git secret init'\"\n  fi\n\n  # Checking if the '.gitsecret' dir (or as set by SECRETS_DIR) is not ignored:\n  _secrets_dir_is_not_ignored\n\n  # Checking gpg setup:\n  local keys_dir\n  keys_dir=$(_get_secrets_dir_keys)\n\n  local secring=\"$keys_dir/secring.gpg\"\n  if [[ -f $secring ]] && [[ -s $secring ]]; then\n    # secring.gpg exists and is not empty,\n    # someone has imported a private key.\n    _abort 'it seems that someone has imported a secret key.'\n  fi\n}\n\nfunction _incorrect_usage {\n  local message=\"$1\"\n  local exitcode=\"$2\"\n  shift 2\n  echo \"git-secret: abort: ${message}\"\n  usage \"$@\"\n  exit \"${exitcode}\"\n}\n\nfunction _show_version {\n  echo \"$GITSECRET_VERSION\"\n  exit 0\n}\n\n\nfunction _init_script {\n  if [[ $# == 0 ]]; then\n    _incorrect_usage 'no input parameters provided.' 126 \"$@\"\n  fi\n\n  # Parse plugin-level options:\n  local dry_run=0\n\n  while [[ $# -gt 0 ]]; do\n    local opt=\"$1\"\n\n    case \"$opt\" in\n      # Options for quick-exit strategy:\n      --dry-run)\n        dry_run=1\n        shift;;\n\n      --version) _show_version;;\n\n      *) break;;  # do nothing\n    esac\n  done\n\n  if [[ \"$dry_run\" == 0 ]]; then\n    # Checking for proper set-up:\n    _check_setup\n\n    # Routing the input command:\n    local function_exists\n    function_exists=$(_function_exists \"$1\")\n\n    if [[ \"$function_exists\" == 0 ]] && [[ ! $1 == _* ]]; then\n      $1 \"${@:2}\"\n    else  # TODO: elif [[ $(_plugin_exists $1) == 0 ]]; then\n      _incorrect_usage \"command $1 not found.\" 126 \"$@\"\n    fi\n  fi\n}\n\n\n_init_script \"$@\"\n"
  },
  {
    "path": "src/version.sh",
    "content": "#!/usr/bin/env bash\n\n# shellcheck disable=SC2034\nGITSECRET_VERSION='0.5.1-alpha1'\n"
  },
  {
    "path": "tests/_test_base.bash",
    "content": "#!/usr/bin/env bash\n\n# This file is following a name convention defined in:\n# https://github.com/bats-core/bats-core\n\n# shellcheck disable=SC1090\nsource \"$SECRETS_PROJECT_ROOT/src/version.sh\"\n# shellcheck disable=SC1090\nsource \"$SECRETS_PROJECT_ROOT/src/_utils/_git_secret_tools.sh\"\nsource \"$SECRETS_PROJECT_ROOT/src/_utils/_git_secret_tools_freebsd.sh\"\nsource \"$SECRETS_PROJECT_ROOT/src/_utils/_git_secret_tools_linux.sh\"\nsource \"$SECRETS_PROJECT_ROOT/src/_utils/_git_secret_tools_osx.sh\"\n\n# Constants:\nFIXTURES_DIR=\"$BATS_TEST_DIRNAME/fixtures\"\n\nTEST_GPG_HOMEDIR=\"$BATS_TMPDIR\"\n\n# TODO: factor out tempdir creation.\n# On osx TEST_OUTPUT_FILE, still has 'XXXXXX's, like\n#   /var/folders/mm/_f0j67x10l92b4zznyx4ylzh00017w/T/gitsecret_output.XXXXXX.RaqyGYqL\nTEST_OUTPUT_FILE=$(\n  TMPDIR=\"$BATS_TMPDIR\" mktemp -t 'gitsecret_output.XXXXXX'\n)\n\n\n# shellcheck disable=SC2016\nAWK_GPG_GET_FP='\nBEGIN { OFS=\":\"; FS=\":\"; }\n{\n  if ( $1 == \"fpr\" )\n  {\n    print $10\n    exit\n  }\n}\n'\n\n# git >= 2.28.0 supports --initial-branch=main\nfunction is_git_version_ge_2_28_0 { # based on code from github autopilot\n    # shellcheck disable=SC2155\n    local git_version=$(git --version | awk '{print $3}')\n    # shellcheck disable=SC2155\n    local git_version_major=$(echo \"$git_version\" | awk -F. '{print $1}')\n    # shellcheck disable=SC2155\n    local git_version_minor=$(echo \"$git_version\" | awk -F. '{print $2}')\n    # shellcheck disable=SC2155\n    local git_version_patch=$(echo \"$git_version\" | awk -F. '{print $3}')\n    if [[ \"$git_version_major\" -ge 2 ]] && [[ \"$git_version_minor\" -ge 28 ]] && [[ \"$git_version_patch\" -ge 0 ]]; then\n        echo 0\n    else\n        echo 1\n    fi\n}\n\n# GPG-based stuff:\n: \"${SECRETS_GPG_COMMAND:='gpg'}\"\n\n# This function is used with absolute homedir set and disabled warnings:\nfunction _gpgtest {\n  \"$SECRETS_GPG_COMMAND\" --homedir \"$TEST_GPG_HOMEDIR\" --no-permission-warning --batch \"$@\"\n}\n\n# Test key fixture data. Fixtures are at tests/fixtures/gpg/$email\n\n# See tests/fixtures/gpg/README.md for more\n# on key fixtures 'user[1-5]@gitsecret.io'\n# these two are 'normal' keys.\nexport TEST_DEFAULT_USER='user1@gitsecret.io'\nexport TEST_SECOND_USER='user2@gitsecret.io'\n\n# TEST_NONAME_USER (user3) created with '--quick-key-generate'\n# and has only an email, no username.\nexport TEST_NONAME_USER='user3@gitsecret.io'\n\n# TEST_EXPIRED_USER (user4) has expired\nexport TEST_EXPIRED_USER='user4@gitsecret.io'    # this key expires 2018-09-24\n\n# fixture filename is named this,\n# but key has no email and a comment, as per #527\nexport TEST_NOEMAIL_COMMENT_USER='user5@gitsecret.io'\n\nexport TEST_ATTACKER_USER='attacker1@gitsecret.io'\n\n\nexport TEST_DEFAULT_FILENAME='space file' # has spaces\nexport TEST_SECOND_FILENAME='space file two' # has spaces\nexport TEST_THIRD_FILENAME='space file three'  # has spaces\nexport TEST_FOURTH_FILENAME='space file three [] * $'  # has spaces and special chars\n\n\nfunction test_user_password {\n  # Password for 'user3@gitsecret.io' is 'user3pass'\n  # As it was set on key creation.\n  # shellcheck disable=SC2001\n  echo \"$1\" | sed -e 's/@.*/pass/'\n}\n\n\n# Files:\n\nfunction file_has_line {\n  # First parameter is the key, second is the filename.\n\n  local line=\"$1\" # required\n  local filename=\"$2\" # required\n\n  local exit_code\n  # -F means 'Interpret PATTERN as a list of fixed strings' (not regexen)\n  # -x means 'Select only those matches that exactly match the whole line'\n  exit_code=$(grep -Fx \"$line\" \"$filename\" 2>&1 > /dev/null; echo $?)\n\n  # 0 means contains, 1 means not contains, and probably >1 for errors.\n  echo \"$exit_code\"\n}\n\n\n# GPG:\n\nfunction stop_gpg_agent {\n  local username\n  username=$(id -u -n)\n  if [[ \"$SECRETS_DOCKER_ENV\" == 'windows' ]]; then\n    ps -l -u \"$username\" | gawk \\\n      '/gpg-agent/ { if ( $0 !~ \"awk\" ) { system(\"kill \"$1) } }' >> \"$TEST_OUTPUT_FILE\" 2>&1\n  else\n    local ps_is_busybox\n    ps_is_busybox=$(_exe_is_busybox 'ps')\n    if [[ $ps_is_busybox -eq '1' ]]; then\n      # On Alpine/busybox, ps doesn't show command arguments, so use gpgconf instead\n      gpgconf --homedir \"$TEST_GPG_HOMEDIR\" --kill gpg-agent >> \"$TEST_OUTPUT_FILE\" 2>&1 || true\n    else\n      ps -wx -U \"$username\" | gawk \\\n        '/gpg-agent --homedir/ { if ( $0 !~ \"awk\" ) { system(\"kill \"$1) } }' >> \"$TEST_OUTPUT_FILE\" 2>&1\n    fi\n  fi\n}\n\n\nfunction get_gpg_fingerprint_by_email {\n  local email=\"$1\"\n  local fingerprint\n\n  fingerprint=$(_gpgtest --with-fingerprint \\\n                         --with-colon \\\n                         --list-secret-key \"$email\" | gawk \"$AWK_GPG_GET_FP\")\n  echo \"$fingerprint\"\n}\n\n\nfunction get_gpg_public_fingerprint_by_email {\n  local email=\"$1\"\n  local fingerprint\n\n  fingerprint=$(_gpgtest --with-fingerprint \\\n                         --with-colon \\\n                         --list-keys \"$email\" | gawk \"$AWK_GPG_GET_FP\")\n  echo \"$fingerprint\"\n}\n\n\nfunction install_fixture_key {\n  local public_key=\"$BATS_TMPDIR/public-${1}.key\"\n\n  cp \"$FIXTURES_DIR/gpg/${1}/public.key\" \"$public_key\"\n  _gpgtest --import \"$public_key\" >> \"$TEST_OUTPUT_FILE\" 2>&1\n  rm -f \"$public_key\" || _abort \"Couldn't delete public key: $public_key\"\n}\n\n\nfunction install_fixture_full_key {\n  local private_key=\"$BATS_TMPDIR/private-${1}.key\"\n  local email\n  local fingerprint\n\n  email=\"$1\"\n\n  cp \"$FIXTURES_DIR/gpg/${1}/private.key\" \"$private_key\"\n\n  if [[ \"${GPG_VER_21:-0}\" -eq 1 ]]; then\n    test_user_password \"$1\" | _gpgtest --allow-secret-key-import \\\n      --import \"$private_key\" >> \"${TEST_OUTPUT_FILE}\" 2>&1\n  else\n    _gpgtest --allow-secret-key-import \\\n      --import \"$private_key\" >> \"${TEST_OUTPUT_FILE}\" 2>&1\n  fi\n\n  # since 0.1.2 fingerprint is returned:\n  fingerprint=$(get_gpg_fingerprint_by_email \"$email\")\n\n  install_fixture_key \"$1\"\n\n  rm -f \"$private_key\" || _abort \"Couldn't delete private key: $private_key\"\n  # return fingerprint to delete it later:\n  echo \"$fingerprint\"\n}\n\n\nfunction uninstall_fixture_key {\n  local email\n\n  email=\"$1\"\n  _gpgtest --yes --delete-key \"$email\" >> \"$TEST_OUTPUT_FILE\" 2>&1\n}\n\n\nfunction uninstall_fixture_full_key {\n  local email\n  email=\"$1\"\n\n  local fingerprint=\"$2\"\n  if [[ -z \"$fingerprint\" ]]; then\n    # see issue_12, fingerprint on `gpg2` has different format:\n    fingerprint=$(get_gpg_fingerprint_by_email \"$email\")\n  fi\n\n  _gpgtest --yes --delete-secret-keys \"$fingerprint\" >> \"$TEST_OUTPUT_FILE\" 2>&1\n\n  uninstall_fixture_key \"$1\"\n}\n\n\n# Git:\n\nfunction git_set_config_email {\n  git config --local user.email \"$1\"\n}\n\n\nfunction git_commit {\n  git_set_config_email \"$1\"\n\n  local user_name\n  local commit_gpgsign\n\n  user_name=$(git config user.name)\n\n  commit_gpgsign=$(git config commit.gpgsign)\n\n  git config --local user.name \"$TEST_DEFAULT_USER\"\n  git config --local commit.gpgsign false\n\n  git add --all\n  git commit -m \"$2\"\n\n  git config --local user.name \"$user_name\"\n  git config --local commit.gpgsign \"$commit_gpgsign\"\n}\n\n\nfunction remove_git_repository {\n  rm -rf \".git\"\n}\n\n\n# Git Secret:\n\nfunction set_state_initial {\n  cd \"$BATS_TMPDIR\" || exit 1\n  rm -rf \"${BATS_TMPDIR:?}/*\"\n  # Safety net: remove hidden dirs that may persist from a prior failed teardown.\n  # The rm above is a no-op (glob inside double quotes is literal), so we must\n  # explicitly clean up dot-dirs to prevent 'already initialized' errors.\n  rm -rf \"${BATS_TMPDIR:?}/${_SECRETS_DIR}\"\n  rm -rf \"${BATS_TMPDIR:?}/.git\"\n  rm -rf \"${BATS_TMPDIR:?}/.gitignore\"\n}\n\n\nfunction set_state_git {\n  local has_initial_branch_option\n  has_initial_branch_option=$(is_git_version_ge_2_28_0) # 0 for true\n  if [[ \"$has_initial_branch_option\" == 0 ]]; then\n    git init --initial-branch=main | sed 's/^/git: /' >> \"$TEST_OUTPUT_FILE\" 2>&1\n  else\n    git init | sed 's/^/git: /' >> \"$TEST_OUTPUT_FILE\" 2>&1\n  fi\n}\n\n\nfunction set_state_secret_init {\n  git secret init >> \"$TEST_OUTPUT_FILE\" 2>&1\n}\n\n\nfunction set_state_secret_tell {\n  local email\n\n  email=\"$1\"\n  git secret tell -d \"$TEST_GPG_HOMEDIR\" \"$email\" >> \"$TEST_OUTPUT_FILE\" 2>&1\n}\n\n\nfunction set_state_secret_add {\n  local filename=\"$1\"\n  local content=\"$2\"\n  echo \"$content\" > \"$filename\"      # we add a newline\n\n  git secret add \"$filename\" >> \"$TEST_OUTPUT_FILE\" 2>&1\n}\n\nfunction set_state_secret_add_without_newline {\n  local filename=\"$1\"\n  local content=\"$2\"\n  echo -n \"$content\" > \"$filename\"      # we do not add a newline\n\n  git secret add \"$filename\" >> \"$TEST_OUTPUT_FILE\" 2>&1\n}\n\n\nfunction set_state_secret_hide {\n  local armor=\"$1\"\n  SECRETS_GPG_ARMOR=\"$armor\" git secret hide >> \"$TEST_OUTPUT_FILE\" 2>&1\n}\n\n\nfunction unset_current_state {\n  # states order:\n  # initial, git, secret_init, secret_tell, secret_add, secret_hide\n\n  # unsets `secret_hide`\n  # removes .secret files:\n  git secret clean >> \"$TEST_OUTPUT_FILE\" 2>&1\n\n  # unsets `secret_add`, `secret_tell` and `secret_init` by removing $_SECRETS_DIR\n  local secrets_dir\n  secrets_dir=$(_get_secrets_dir)\n\n  rm -rf \"$secrets_dir\"\n  rm -rf '.gitignore'\n\n  # unsets `git` state\n  remove_git_repository\n\n  # stop gpg-agent\n  stop_gpg_agent\n\n  # SECRETS_TEST_VERBOSE is experimental\n  if [[ \"$SECRETS_TEST_VERBOSE\" == 1 ]]; then\n    # display the captured output as bats diagnostic (fd3, preceded by '# ')\n    sed \"s/^/# $BATS_TEST_DESCRIPTION: VERBOSE OUTPUT: /\" < \"$TEST_OUTPUT_FILE\" >&3\n\n    # display the last $output\n    # shellcheck disable=SC2001,SC2154\n    echo \"$output\" | sed \"s/^/# $BATS_TEST_DESCRIPTION: FINAL OUTPUT: /\" >&3\n  fi\n\n  rm -f \"$TEST_OUTPUT_FILE\"\n\n  # new code to remove temporary gpg homedir artifacts.\n  # For #360, 'find and rm only relevant files when test fails'.\n  # ${VAR:?} will cause command to fail if VAR is 0 length, as per shellcheck SC2115\n  rm -vrf \"${TEST_GPG_HOMEDIR:?}/private-keys*\" 2>&1 | sed 's/^/# unset_current_state: rm /'\n  rm -vrf \"${TEST_GPG_HOMEDIR:?}/*.kbx\"         2>&1 | sed 's/^/# unset_current_state: rm /'\n  rm -vrf \"${TEST_GPG_HOMEDIR:?}/*.kbx~\"        2>&1 | sed 's/^/# unset_current_state: rm /'\n  rm -vrf \"${TEST_GPG_HOMEDIR:?}/*.gpg\"         2>&1 | sed 's/^/# unset_current_state: rm /'\n  rm -vrf \"${TEST_GPG_HOMEDIR:?}/${TEST_DEFAULT_FILENAME}\" 2>&1 | sed 's/^/# unset_current_state: rm /'\n  rm -vrf \"${TEST_GPG_HOMEDIR:?}/${TEST_SECOND_FILENAME}\"  2>&1 | sed 's/^/# unset_current_state: rm /'\n  rm -vrf \"${TEST_GPG_HOMEDIR:?}/${TEST_THIRD_FILENAME}\"   2>&1 | sed 's/^/# unset_current_state: rm /'\n  rm -vrf \"${TEST_GPG_HOMEDIR:?}/${TEST_FOURTH_FILENAME}\"  2>&1 | sed 's/^/# unset_current_state: rm /'\n\n  # return to the base dir:\n  cd \"$SECRETS_PROJECT_ROOT\" || exit 1\n}\n\n# show output if we wind up manually removing the test output file in a trap\ntrap 'if [[ -f \"$TEST_OUTPUT_FILE\" ]]; then if [[ \"$SECRETS_TEST_VERBOSE\" == 1 ]]; then echo \"git-secret: test: cleaning up: $TEST_OUTPUT_FILE\"; fi; rm -f \"$TEST_OUTPUT_FILE\"; fi;' EXIT\n\nfunction bats_diag_file {\n  local filename=$1\n\n  echo \"# DEBUG: begin contents: $filename\" >&3\n  sed -e 's/^/# DEBUG: /' < \"$filename\" >&3\n  echo \"# DEBUG: end contents: $filename\" >&3\n}\n"
  },
  {
    "path": "tests/fixtures/gpg/README.md",
    "content": "== public/private key pairs for test keys\n\n* git-secret test keys are named user1@gitsecret.io through \n  user5@gitsecret.io\n\n* All test keysets have the passphrases 'userNpass' I.E., 'user3pass' \n  for user3@gitsecret.io.\n\n* The public/private key sets were exported with (for example)\n    `gpg --export --armor user4 > tests/fixtures/gpg/user4/public.key`\n  and\n    `gpg --export-secret-keys --armor user4 > tests/fixtures/gpg/user4/private.key`\n\n* user1 and user2 are normal gpg key sets for user1@gitsecret.io and \n  user2@gitsecret.io, and have the passphrases 'user1pass' and 'user2pass'.\n\n* user3 was created by `gpg --quick-generate user3@gitsecret.io` \n  and therefore has only an email associated with it (no username).  \n  This user was created to fix \n  https://github.com/sobolevn/git-secret/issues/227,\n  \"keys with email address but no name not recognized by whoknows\".\n  The passphrase is 'user3pass'.\n\n* user4 was created with `gpg --gen-key`, using the name 'user4'\n  and the email address user4@gitsecret.io, and is also set to \n  expire on 2018-09-23. \n  To set the key's expiry, I used the \n `gpg --edit-key user@email` command's `expiry` function. \n  The passphrase is 'user4pass'.\n\n* user5 was created for issue #527, where keys were being rejected if they \n  didn't have an email address, and had whitespace in their 'comment'.\n  using `gpg --full-generate-key` with name 'user5', no email address, \n  the comment 'comment comment', and the passphrase 'user5pass'.  \n  \n"
  },
  {
    "path": "tests/fixtures/gpg/attacker1@gitsecret.io/private.key",
    "content": "-----BEGIN PGP PRIVATE KEY BLOCK-----\nVersion: GnuPG v1\n\nlQO+BFaigVQBCADC5dJ0xweZ+6L0owo2wpKSbQFGQoRJxYVcc1dWe3zNZ5yBrJDV\nN79rYV5AmHnIGDAJrHHV9rYM4+C8obKka7P3ROm0RMsYKDhpQXWFjsOrl1rjWL86\n6D4X7Q5uuJWluPp1+hbzpBmNCX3Y5sr1fmCazvR5iIAvY3EkYbqDt2+BtGTqlevY\nivWiOoPKRY9Dc44rKQh8GmaVJzcO3D21IF70i3GnOtjUSK8DWXdD4BrtYTE/9Ua4\nbmT2pOPmGMcI38pQHZQXqMPTzloakZk9qIbBoB3FS/UFxQr3R3V+tXPm1Eca/75G\n+U4VCRLUFWsDU5d+oTCFCa0qNjGnLFOE85C7ABEBAAH+AwMCW7i8uGNVEnRgGKI3\n2g1TXbUxgqg8ayjCkE2m99KmtbzxAAGJfuETnpxMo9U5JDOk68UC4jgArfWFOad5\nQ3waxbCmKOTuSKqiA1FjXVoL5CtSzziygJ2XSLFh+fOsyeXWSdsmHjIQsXmwSnEm\n9TJxNHNA5AL53lX+ike78cP8fNNlZSFWzfqGSe2nHgLICqMAk8hDUO6s/zFrHmbb\n6Bu7azLTe4r9oEHcD8XsGlxhUUntK8WFPnrZlAdo++E8Ax4VQA/KXaU7STNutMQu\ntvuIOB+E6RRH/lKesIwt2Hrbin/AQKzyyedUJOVqW/UCsXBN9dnpbdR5pSn3eXxy\nLLb3S7whUVUE3HSrVqTRoyupyX10lAecpHPJMB6qq054x1xStPAkcsuVGrewznjD\nZywicif6QzbBc6ZN1tS7fOxxJ9vn5qT9et0xnIJqFc++eofJHJ/Wl9eBtg5XTis7\n69ERbU6GjqVJhAmPPQNoEVUhS1hJimQxAF/oqhEO8yTEJhmGZIzYTrQ1GcLh/AiH\nqkZ5LVwraTrXOJJaRzBL+bzfJa91MJVIpfS9wDTpW/CFvFp9Og/dYmTDfE1zLgSv\ntPSD6RcFxiOTkAeLRN7X5RdFqHjWdhgu2hyd87jpfGt3u0BK1iWW6CptSeNrSFXy\nlEsU3VuBFMRIjdUAXDefN8/99LdSgO7FkLyJsTeTxGOgrdp9fJF3ZEnk5wYRj6Im\n/3NyEq5gdeow02LPIgBGqsXi5iHSAaSJEZnpguCsJqeDnzsGmiLBfy2/MS03+XzU\nFW4OxbNxprDJdheHYqJ6k2z7xchkPedk0s9JpDVe/5ShMyrJI0THP2psPm+EVlKK\n7lDpNf4hRj2by8HYLa/X21AgS8WLTWd+osyO5HQxqhMlDqtpKkOJ4q6ylb3QgDNU\nGrQiYXR0YWNrZXIxIDxhdHRhY2tlcjFAZ2l0c2VjcmV0LmlvPokBOAQTAQIAIgUC\nVqKBVAIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQiAEDMVPMIKV1RwgA\nsQAQmjtDpyKS/+zzFgVuOqu5QffqylFMXw8zrchiBLTeTCEKoixNj5cccpAG9xDU\nZcMwMw/lSAz1MXSfQ6GGvl4ErlZrlx9SSacqPwDNoKWMci9PDb3JpaXZtQQCrDmw\nnZpSE6bKvhAoTIaA6Tn8g4uOo3vTyDuX1DznrcUFrMCW7vw5ztttA1hvg5iHrs4d\nia/FaRX0SOf9y/0u9kQW2pkWlVL2pRgQaYwHl7FQRGnrwibxyEpTQ8x+d8uU87DN\naaiUZ5GcsZT2U6cmhuz/k0IFGL408huF5h50KVFTYQNQc3Le3v9wrh88Obn4ciX/\n2YizefDo5WGt5/mvlUfp750DvQRWooFUAQgAv54OkX9n0+L/59UUWWtqz+siBF3o\n3wMU0AKoATIZbilxoOPHzvv8iWpSlShTNsY4HqsZf7tIqfJLq91EigV0uQs0v6zw\nzFC31t8lQaQy0g0uv04xnMIvYw4xRhUa7dBphokeuuSCU7uJzq6za3Ia1hoNZEfd\nlEG/1LdGMzMLURxUlWWwpzRJdPEpEd6/InavNiffiGaiJXfTUQfpicz0k7eyXgK5\nPat07UaIW80gol+fghu4BhEHAWAfAV6ocd/YfUn7Hax55l0/npC3Y72JMhhSW11H\ngOE1iz33INGF9pfNL+VQwQj9gUQCOcczquD4NQ7RgQAdZQ2K9k4caOzbxQARAQAB\n/gMDAlu4vLhjVRJ0YNV0uVpXwCia2Vq2WMzxN0UyvAeF9QwkV8LAJt3O/VwzdJDg\njWALHfUHysylbmE3nwAL6gOznL+XQ/Sf1v0dzDZZi8S64t4DNGnk7wRuui2/ZRVd\n3jM2tiW/Y7ijWIpEaRwH8jtrV6+zoUt76YgBcgun+nhUzcGbdvh11Ygu5VHYxNU3\nJ7p4E80gClGsciNO9B+hgR8kg+wGc+C0LBey1mh5A0AWqO0NwFlF8YlpleC09Pld\nI3+NJ4miZUMS6ue5Me1QvBcAvaY3Vuh2U0RPICI2Athx0xpILktnuANqjxg4BiZI\nLelaxxl12ycdO5Im1IUXiLBgMOBRFvRQ/6iEb/oTGRN8aY5W93LQ7nSyKdn6B6V5\nHzDfuwrDJP6Q+sMi3SCEFgaNpNTRPu11gvMAj1V+4zwgsflZHVgkKSwvg2pRXAPp\nrNfJo6d0bfImF9w2J/2d/gYSOoWsC92VG0KY8hVWkHOBUVZFyRl4zv8UNoCtBPkM\nWq00X0J3ZNAjnPE8hl2OK4q+4r0Q3CecVgK0tlTMqVfgNVgG0X6LV7xmbViY4HuA\nkvfmLkTFwL3NzpGVtm4S2DjMUQQygjS2GOfOM4TrNd9Jn5WMCP/7HX5K/3VjL4ai\nmpAoz0A2UeA116KaniW8PnZCm9A+ZFVALjsikgi1gBEuJC2+mgUfhbPtni41qcio\nmhN9si+BE7HhiFk8I/+xg7bAmNcw6hk/zESfKKxqqV4iiauQBy9zEtA7Gg8chcK+\n08eaunF2abkF8xbYPOF8p71sHo2UeJ1gK1lGMzTt1p7NSZm0F9VmPcy8WWjzna1z\noRy44TyWcW90abV5gCerAhSDAlrdwZfcRG6NXT/wG0TjoCMgiIhR1X1gjpozV6NB\n3fB9sc/NDhhibsqA0i0JiYkBHwQYAQIACQUCVqKBVAIbDAAKCRCIAQMxU8wgpQqe\nCACBDi7KrqQzdzeipLadUsaTptvFBlwavpCLRtNbJI8v5i4kr8cLmyqGAwCS8Yem\n3SCI/K4ujln8an6XrhsOE/uwfyQz5iUcP7BN9sIEp/ITOIXu0q0kzxThmpJqHzvf\nbvkPemFEiwYwGZn87cFXmd7FMEoFIt/s/bCnPCuBkxvUMj/D65Sb5x1X+FzWjK2m\nOVJGpTHAixns+DDHOfXEkghQTfj1pX/LBV9nXKlSZtpDO/p/kx+xITxXA/a4EDtD\n2JpZBYmSTcbyVamQEMTzMIfEUhMbSrhKRYcm6g5Jbu5oy0ci/5qIhsR45pA7JSc0\n0Vjcr8GgU7JyYnSqF2Ua8YA6\n=Ygfi\n-----END PGP PRIVATE KEY BLOCK-----\n"
  },
  {
    "path": "tests/fixtures/gpg/attacker1@gitsecret.io/public.key",
    "content": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: GnuPG v1\n\nmQENBFaigVQBCADC5dJ0xweZ+6L0owo2wpKSbQFGQoRJxYVcc1dWe3zNZ5yBrJDV\nN79rYV5AmHnIGDAJrHHV9rYM4+C8obKka7P3ROm0RMsYKDhpQXWFjsOrl1rjWL86\n6D4X7Q5uuJWluPp1+hbzpBmNCX3Y5sr1fmCazvR5iIAvY3EkYbqDt2+BtGTqlevY\nivWiOoPKRY9Dc44rKQh8GmaVJzcO3D21IF70i3GnOtjUSK8DWXdD4BrtYTE/9Ua4\nbmT2pOPmGMcI38pQHZQXqMPTzloakZk9qIbBoB3FS/UFxQr3R3V+tXPm1Eca/75G\n+U4VCRLUFWsDU5d+oTCFCa0qNjGnLFOE85C7ABEBAAG0ImF0dGFja2VyMSA8YXR0\nYWNrZXIxQGdpdHNlY3JldC5pbz6JATgEEwECACIFAlaigVQCGwMGCwkIBwMCBhUI\nAgkKCwQWAgMBAh4BAheAAAoJEIgBAzFTzCCldUcIALEAEJo7Q6cikv/s8xYFbjqr\nuUH36spRTF8PM63IYgS03kwhCqIsTY+XHHKQBvcQ1GXDMDMP5UgM9TF0n0Ohhr5e\nBK5Wa5cfUkmnKj8AzaCljHIvTw29yaWl2bUEAqw5sJ2aUhOmyr4QKEyGgOk5/IOL\njqN708g7l9Q8563FBazAlu78Oc7bbQNYb4OYh67OHYmvxWkV9Ejn/cv9LvZEFtqZ\nFpVS9qUYEGmMB5exUERp68Im8chKU0PMfnfLlPOwzWmolGeRnLGU9lOnJobs/5NC\nBRi+NPIbheYedClRU2EDUHNy3t7/cK4fPDm5+HIl/9mIs3nw6OVhref5r5VH6e+5\nAQ0EVqKBVAEIAL+eDpF/Z9Pi/+fVFFlras/rIgRd6N8DFNACqAEyGW4pcaDjx877\n/IlqUpUoUzbGOB6rGX+7SKnyS6vdRIoFdLkLNL+s8MxQt9bfJUGkMtINLr9OMZzC\nL2MOMUYVGu3QaYaJHrrkglO7ic6us2tyGtYaDWRH3ZRBv9S3RjMzC1EcVJVlsKc0\nSXTxKRHevyJ2rzYn34hmoiV301EH6YnM9JO3sl4CuT2rdO1GiFvNIKJfn4IbuAYR\nBwFgHwFeqHHf2H1J+x2seeZdP56Qt2O9iTIYUltdR4DhNYs99yDRhfaXzS/lUMEI\n/YFEAjnHM6rg+DUO0YEAHWUNivZOHGjs28UAEQEAAYkBHwQYAQIACQUCVqKBVAIb\nDAAKCRCIAQMxU8wgpQqeCACBDi7KrqQzdzeipLadUsaTptvFBlwavpCLRtNbJI8v\n5i4kr8cLmyqGAwCS8Yem3SCI/K4ujln8an6XrhsOE/uwfyQz5iUcP7BN9sIEp/IT\nOIXu0q0kzxThmpJqHzvfbvkPemFEiwYwGZn87cFXmd7FMEoFIt/s/bCnPCuBkxvU\nMj/D65Sb5x1X+FzWjK2mOVJGpTHAixns+DDHOfXEkghQTfj1pX/LBV9nXKlSZtpD\nO/p/kx+xITxXA/a4EDtD2JpZBYmSTcbyVamQEMTzMIfEUhMbSrhKRYcm6g5Jbu5o\ny0ci/5qIhsR45pA7JSc00Vjcr8GgU7JyYnSqF2Ua8YA6\n=CU3L\n-----END PGP PUBLIC KEY BLOCK-----\n"
  },
  {
    "path": "tests/fixtures/gpg/user1@gitsecret.io/private.key",
    "content": "-----BEGIN PGP PRIVATE KEY BLOCK-----\nVersion: GnuPG v1\n\nlQO+BFaigO0BCACwtBp5eg1d68f9WhmYew/4eU5zjaJsNj1DHsHokxsUt9QpIdVq\nDuPxlW8pTOUrhqQZd0ozaaDMswwFpzkblelQJzt/juqy/lkK2StlQfK2YRk7zehV\nHA6YOtTFyYbyheCeSFNJ4bfy3nn1lSDTtSmDpQBz19hVBP9JapI8K96nTSuK0NAb\nFEZ7ZdFLdXbtEkXHtTL+eqrys8UI7Ou+iZZ+dBlwTl9Jszg/b6IjYCYFT/LKuLX3\nss9fI/ypuwjB+1zys9WNDiNrrb8e26GDeOjfTH0vPuV9nU2gqLVzlssTLiWkrjSW\ng3OhO3jBBa59oEf60eBreL0FZ74LqRsPT8NVABEBAAH+AwMCDb97GbFDRhZgU4Gp\n0YHMOv/Fy3ENidzrv+jbviH170EKpIgizpIpzen4SwTT+dbks+MM9vPvvaDbJPBo\nqTkPYOm9ON6jBRTzAF0ITiioSjhXhpYHJ4eLCUPt+qSTtFLPQChSAOmmUKQD2zUP\ncLG0gjKUiapu0klbcyF8mpKIuUuQUFG0fdlEWNoKzxKF0nlQ9Fn2CTCLaJK/a8tp\nFdoO0naGBYsCUMFHIs+ntaCoQZcUl52JfcLVq0HteISCqybX13lrJIlVGRLB4YYj\nCcIsymAc2/sbKpPHRcQQHcaiPL6z20P9yo8DyLwSB1j/RnqMJU4XBY7wS7sOeJMy\nd5QhTbq3i4kgpqh59q0uJamVKJNLEb/qVZDycdgj3EIU1C7HEukaiefPnvqDFWwx\no88VOZoeqKCvf2QQgM1a4AgwpkZ20jvDK3ydeGWA9d+BsqgfKUOfjbhxc2J5W3Fk\nJ/tpjQQErEPRbRZNi9aEYNNBNZeZ1NVsu32kO3FJfj2bgAsTduHK6PAoHT3M2gXW\nEzshsMqeFabWgMLfgXA65oOmcBkCQpcRXJHEwghLS6qGkNgB9R+tWBdnfpLgCELa\nk+aYUf28szbzMyxfBfCUoMFT052oNQmeerHg4BgTQNaWMuFG9qsI5DzxFmmXLhBs\nuMZ15oOgJHaT19zW9xMV6REnnHLFrwQ6pm0bO+kDrHBiOLGG7YcjoVb1aqMRaFSu\nPo8pFNLKuLSJ35wWrGms4N9MQH1jOSWMsmOnYvJofakpA2JAXIkitNjQuo2UbA8N\nbx+klajhlBJDdyO6Z6o2dndr+XHg5tKfK+6XSuK50Xr9CdV7R6hpZG2Ek+OUNewD\nM+1DuXC/9EVOs8H1bdBd2WuGOwAgUhNND/YGqcYBqCxplvVIYeMzhgR4O3ZUNodG\nwLQadXNlcjEgPHVzZXIxQGdpdHNlY3JldC5pbz6JATgEEwECACIFAlaigO0CGwMG\nCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJENKAWkGC6Z/0fskH/RIZyEdxw80P\nqyNRVg79wrhut63y7ovseavqN6wpECgkK4urqVNBErzA1LqEQONGLUjcgStCdSGA\nYJlw5ZJ67K7oRidzODnZovLndT4D1WYkf4v4jnl95CblJUkPSMHKny+uw0Mrgl3Q\nKri5BxBggMHu330cgthpyUC0P+yqi1YRHde+2P107IdkpLYgJ1qJz3loAgm6AmG0\nkwiK6wIZzbIwvnEtZDVxvofrM1o5lAXgH+puxyC7lZaU8gnJqXGM5rYJAEPC3E6M\nm45f3JkEjnbd5ruJ07SQJ0DGklKGKL5zTG0lX30Mb28EXX0OAK1MODIHvd3LcSqb\nVJ6lMXUJehKdA74EVqKA7QEIANqD9vGoR651Kdn0z0FOVkSgZQG43KtXsoj0ifC/\neC58JqPhRCTFcSLb55AIGLsAHcu+yRwkSwBrCisTIHqO15dSbYbbj+1LfYX0lOBN\ntGEXZA4NZ02hGOmsC2ND4+1qQ5afBIjDlMd5ceQY3MipdWHn0mi5CF04iaLDmMPE\niy6C7NKofuSs+4+kyzg49RdnjP/Oe4cIsiEe4B6CvMPrnOoOXyMck6DmZz/Hj8+p\nkeGh+vaT3/sbTyCrOEPmaC+HmLf2jCycr6wxVkOjwEY1V1ZhVVi+27uN2FskmEJm\nqeQhsDhwKhqLWmez9kWAz9TbqAVB5E5yatJMmxc6pcIkbpEAEQEAAf4DAwINv3sZ\nsUNGFmAjXQZ3NwRZ0DnvYj9t1cHfdaWtD/hKj2rlsRdgbcuANeZ5gcrZL6iXEvns\nSMuSNGx3moQBDZytbRPGVP3s5LWaZqsCj/BiCePWepVYaJTYNxXZ40bGTEy7VDL5\nrnRw9KwJzG3NNg5siKHBDbQNZZhdN1Q1PLHyxK5JnDspXtvTuYmHy0mVveY2WviE\ncnaGq07PtchE0tYIyRQgrJ3szJoh17Z/aLGR77zWLGzqF4UVQIBRLuCxrUeUTEUU\n3CHbveY0AKa5SQIu0fKyYBkeyWuWgX1JdPGFiFlPaiwId3ba+0DlXNwlHKJgWCGP\nGtGcNVo/AyUdTwQncNsXiwxJ3RG2AsqASRINQLsbUqKUE20WHBFbyRnHQcJby2si\nhjruM6mXLI4jqyMxtER9JXv1B/MTfLH8uxEOVYma3Wmp41vkICqH0LygHQ1tTKUf\nbMh0A517s53YFvkrbd110p7bfQcqpeAfZ2vUNKW/G7pUt+4sFeTPJ8A6XrBEt3rk\nH7kMjU7wI3PSm3UzEnMzxNFga40qwzclPOa1ka9KvJpH60E7pSLwf9AaYOJfuKST\nn/6uk/q+UONZZgcbtrPCaRptd86lInxHu9R8s7T7/ZK3/oPmU7M5leg7NmuAWshG\neb+XGBO/QugLVdMz9Dc/3YELzPe+CqjRUiVpBoNfAGurZ0ou7o1KgeOQovcuh1wt\ncpHM55XeuxRvM5Xz5FgKinU0pw9t7uuASOF1Y3d7PncBkfkpvxjbPqyspVHEbloA\nJvDB7Eim8KcSIS+/DVPMdohfRdcLQLeUU7FSQ10HxERSgD4HQ70jQLYyHEsOqZv2\n04U/cwpD1EfdzITb8LQNPIPyPsgehbaMNonYiTXFW2uUBgPriAtqPSG7wF/FJbN0\nTT9N9PWFVoNciQEfBBgBAgAJBQJWooDtAhsMAAoJENKAWkGC6Z/0DY0H/A14kv3S\nl0CBUkAn6XtfsEvdBKyeOZjPNlK1HzgNwPCkbpOR4g9mTqA4tr/XzpJk/A2VE5y0\n/DIaRnxivy9trnjQG7eNdymm08My+GRCPWOkceIlSV7IBZh2iMvYpFVXELOcjH6x\nldc+RQiJ0irRXs28XbXYc7T4JYZr7xgDQIb6yyaAAdd6//k1oHGQf2uTsNWZzs43\nOBAN2ze3DdYWXMtsskHVvnnFJSAR+03rg92VMSAfh6GKq0aFF12qTUAAWVEkoAFH\ngRBQRqVFT9RgKOgk7VRlytO1sv5bP5ZlvE5IvN9HCTHLOYCr/sTgOb3oYYQ/zZAm\nBh9SiS8oRa1I+f4=\n=PunG\n-----END PGP PRIVATE KEY BLOCK-----\n"
  },
  {
    "path": "tests/fixtures/gpg/user1@gitsecret.io/public.key",
    "content": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: GnuPG v1\n\nmQENBFaigO0BCACwtBp5eg1d68f9WhmYew/4eU5zjaJsNj1DHsHokxsUt9QpIdVq\nDuPxlW8pTOUrhqQZd0ozaaDMswwFpzkblelQJzt/juqy/lkK2StlQfK2YRk7zehV\nHA6YOtTFyYbyheCeSFNJ4bfy3nn1lSDTtSmDpQBz19hVBP9JapI8K96nTSuK0NAb\nFEZ7ZdFLdXbtEkXHtTL+eqrys8UI7Ou+iZZ+dBlwTl9Jszg/b6IjYCYFT/LKuLX3\nss9fI/ypuwjB+1zys9WNDiNrrb8e26GDeOjfTH0vPuV9nU2gqLVzlssTLiWkrjSW\ng3OhO3jBBa59oEf60eBreL0FZ74LqRsPT8NVABEBAAG0GnVzZXIxIDx1c2VyMUBn\naXRzZWNyZXQuaW8+iQE4BBMBAgAiBQJWooDtAhsDBgsJCAcDAgYVCAIJCgsEFgID\nAQIeAQIXgAAKCRDSgFpBgumf9H7JB/0SGchHccPND6sjUVYO/cK4bret8u6L7Hmr\n6jesKRAoJCuLq6lTQRK8wNS6hEDjRi1I3IErQnUhgGCZcOWSeuyu6EYnczg52aLy\n53U+A9VmJH+L+I55feQm5SVJD0jByp8vrsNDK4Jd0Cq4uQcQYIDB7t99HILYaclA\ntD/sqotWER3Xvtj9dOyHZKS2ICdaic95aAIJugJhtJMIiusCGc2yML5xLWQ1cb6H\n6zNaOZQF4B/qbscgu5WWlPIJyalxjOa2CQBDwtxOjJuOX9yZBI523ea7idO0kCdA\nxpJShii+c0xtJV99DG9vBF19DgCtTDgyB73dy3Eqm1SepTF1CXoSuQENBFaigO0B\nCADag/bxqEeudSnZ9M9BTlZEoGUBuNyrV7KI9Inwv3gufCaj4UQkxXEi2+eQCBi7\nAB3LvskcJEsAaworEyB6jteXUm2G24/tS32F9JTgTbRhF2QODWdNoRjprAtjQ+Pt\nakOWnwSIw5THeXHkGNzIqXVh59JouQhdOImiw5jDxIsuguzSqH7krPuPpMs4OPUX\nZ4z/znuHCLIhHuAegrzD65zqDl8jHJOg5mc/x4/PqZHhofr2k9/7G08gqzhD5mgv\nh5i39owsnK+sMVZDo8BGNVdWYVVYvtu7jdhbJJhCZqnkIbA4cCoai1pns/ZFgM/U\n26gFQeROcmrSTJsXOqXCJG6RABEBAAGJAR8EGAECAAkFAlaigO0CGwwACgkQ0oBa\nQYLpn/QNjQf8DXiS/dKXQIFSQCfpe1+wS90ErJ45mM82UrUfOA3A8KRuk5HiD2ZO\noDi2v9fOkmT8DZUTnLT8MhpGfGK/L22ueNAbt413KabTwzL4ZEI9Y6Rx4iVJXsgF\nmHaIy9ikVVcQs5yMfrGV1z5FCInSKtFezbxdtdhztPglhmvvGANAhvrLJoAB13r/\n+TWgcZB/a5Ow1ZnOzjc4EA3bN7cN1hZcy2yyQdW+ecUlIBH7TeuD3ZUxIB+HoYqr\nRoUXXapNQABZUSSgAUeBEFBGpUVP1GAo6CTtVGXK07Wy/ls/lmW8Tki830cJMcs5\ngKv+xOA5vehhhD/NkCYGH1KJLyhFrUj5/g==\n=0Q64\n-----END PGP PUBLIC KEY BLOCK-----\n"
  },
  {
    "path": "tests/fixtures/gpg/user2@gitsecret.io/private.key",
    "content": "-----BEGIN PGP PRIVATE KEY BLOCK-----\nVersion: GnuPG v1\n\nlQO9BFaigRUBCACgb+7xhV1nJZim3noxozslfrWXPYEVQt7Is8QjATaKg6ULqImi\ntpgnlUNCaEAd3PMufVSqd416KyytwUOBVaFIEej/SJcJ2UU4nFvJsvo4bNmInOc3\ncNSqJ5VcI7D++wdHSecr2YayWtsh85jt6xI2oGBN334Yl6sHnNGC/vmE0pWovpib\nrwAW7bWSOYOQxpzANm9O+9oJ6WsTGVVWkZ/SAaRo+VYDA5rwCI6STt+rEcKalr5C\nsbtqELDDDrYYviU4kZx6WYdiDcF5ATSiuGZrQTjEdBFc+GmFxbW+aumeC+Y1jYOp\naYUhbDKffnrxvFjm5+3PBbrPmJ5rFWr1f00bABEBAAH+AwMC33BVxMhK6IpgUYTN\n9Se4Ys+bykytIN9jRVRzshJ/qYWU1L2wWwEc99P+4Yfi85x++KF8iD2jlym+/KKp\n27La2ke3Bx7IvWK3YMwyUalxw/ri8C08g8XHlOZeUJW894dYaTRq2vYMBUW0F10J\nuGF1HGWqUYO4NlOMbs9W+RmUXWlItjlpdCTJdRKRPYzokrKh232NH188mYUscx62\ntrLq28nNZZ9WOFhsAiMji0qpUilPg8Pt/XupwiDscPYbVEXfTDRjkDbVbz+/Gpfx\nHbt7aWT/2rFTp0lV2EVVp+e9je0qQaGSAED8cy3mw4lVJcTUcTWfSHauEJBN3FOI\nBV7bltO4UwIToSDvUV7zZR7u9CcnpuVWXcMWppHPc6383dJ+siTG5+zHLOG99eWA\nnwsnw1w/4j64uywJKPteMkSNGO+aFCawzMMi3LPwokVtmr8gklvb2v9wmWRVf1j6\nTKeWPhzBC2kkrymuttMZyeOkyZhAPR3097v9S8CyTKbjBi4hEREt2CI2Q1GpSYLJ\nc/6RMCKh7Y+4ODw/encswL71eY4c3HqELz+GS0nzaumdIH57t/pBj1dbl63Z6gjz\nEJaOtS5I/otayLjcXQtIlV8xQwXcsgzFUYejVeb5n5IXWxxYn0Qh6uBB0GxffBQD\nlI6R58Rygmd1JOwe6WL1eFc319qfxoaDlhxxkOctUeyRB3fU/K4/KAjlVUGCfdCe\nVTJqwNMyKUNhbPoSWamMHFoJRk5O7bSlvfct6LcUcjRmK+z5SowUYC5ZeyfoeEES\nr8wX/UCFCP+syWFAICU96U9jmQeE310YF32TgI9BZiwkB9WXoiDdwcCdlBHqEOW8\n7OISrpawan9hu1dV88P1LM13TcwJEt1yhzHHqDf6ZOopOt+LciBUlZ4wLLlsc+H/\ntBp1c2VyMiA8dXNlcjJAZ2l0c2VjcmV0LmlvPokBOAQTAQIAIgUCVqKBFQIbAwYL\nCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQ6qDk62szbIs/ewgAi4L2kIJEtqC0\nZUFGV9GJmvj/guEyY5buUKVXUMpNd8NhZ9uRLBFmG68mtjIlN8twNucXUTO2lLWY\nhMJpUhjobdRPzw887rNqswSIpWavPZreMKgXJ72/2md9m7cr9FmEZ9fZx80tBwdL\n2+cYa1Iixuo2vk2Un0LD42qCbh0nRxSDf3g6yDtSHYZ4i6I89XwA5TSG1/C0uIcr\nRKGDBkhd05sqCJ9t/m6oAxk3A8nZM+i2uS0+dmOVwAmDv6/A64+Aff5hYsx87UeA\ndU76ni3rw0pZXTn90wv/aY0deicDlmSUattSNg/G6KoE6RERL47ityU07D4yUvTB\nGL5gVveBX50DvgRWooEVAQgAtDzDXdJSOwmDj/JhAk0wD+RBjxIzO/V/FXCotHaq\niSSRvZ0Jn6CMrGa0EKksGXjqY6+jhC/HLb9hXjR+ciU/E64IVNJdtGp77rjVUygr\nsY0f0ZUSQufTC9lcVAP8wNx59Bk0nluO0zeH0lMRU/cLdyGCs7C3odO5xVvFl5IJ\n6jH/95y6BdRGSDNTnzeQXT+fUHxLZbPG6AbLIXDOAK2OAHnUY62uGLF8l69x1Hym\nLVqD9TYTU9VpYq9Il8e18O6fqE1MEp4zHkyTf6IvCgZrOFL+XApwHYy1NskKi9WN\nDdQCvpDqvNSPZSqrajTdeJ4NzuVip+ccDT/tZVTA8A+0aQARAQAB/gMDAt9wVcTI\nSuiKYDgqOvDcasfFXeOTZdQn9tXs5VFeauKvovg1B6yVSE9SM/dg0vnIpIQ+b2nV\nWm7IZXYsI6CpYWzQeAbp25Jg2lqCgmcbh9vpF5d+y/Unu1Mn8gbCRAjrwx9QLwzE\nKWUL7mt2vjesZM883iwC6PKYZnEtTuxXF5STnhjZLr5yjrAX7dEQy4m03FfXoGj0\ntNo+sR+EE2zTSgrVD3VhUFmPTiND8wWUssjQHEMgjYJOc8C05HE2ftqI6GSF8pUP\ndZag3da0OwZVI8ww2Qcu8Dkkgblv3AulLv/oaiSrS7oJvDZC+aQw+3X91FFlwn+A\nAiwa9bL6iAJb7KjgLIV4HDXLAC8FqiM5pPFu+fvPKsqP2x/iDvkJlAD8ZqXKHFQF\n9F/jKUXgQ7+7vmQy6SJ3RCB7pMS5tCo6kE184C5htppYuKztRVlkePmK8ioT0sJE\n1wpW6AGwaJsnXk1tza0C9yrl9TArO3R+JpImHj4AbOZ//WweOODHJFJQP6TcRZC9\nFOkEIBbPGq4cHKXwYSUlD5hGFCPhTI+EYPxGxKJcw73hYDAWRVtVTb2vdC20FiRM\nuSXBaMa6zisawidYo7+HLSICn1n9swP8YhBLWdQkxIW9dwA37AXbDfbJDxkWSJl8\nsGW+P5cTlhh+hA2sD28daBtFrbYOBVsIHQg6ozYk5RLR1Vddif8XN/tWEl2mvhKs\n5QYW31M496B/tD63JQt1N6ilMLodBho1R6++2hIthF+10gjKjUmC10cGbrRx8cgl\nwlRrHiVzLNL+co0WMAnEnCC9fA4gruN/mVCSkbMDkvv1VywXl5ogzRq3OjPXDXft\n4UgYKfNC5tTmWx+uFc9KcPFN7CS/hFovjRIV+grmWbJkG4HvGrK9AG/a84ufQ/si\nZjprbtOy6amJAR8EGAECAAkFAlaigRUCGwwACgkQ6qDk62szbIvUZQf/adIYw+fH\nM1zlGJH+C/lEFoGi0AXOTqBH13T+haoykwrxnBOdaTGY196bj+uiSbtFqQWcuMNr\nOWNNH6NAl30Ujya/ltLv7FJ3DOuUyIU/3Bhp1t1+jEppMJRYk2pkRmmTg2lrOgSv\nPiqNgmK/FBx3t+JCtmQxtrTBBnJcmx5/8YGdOCEsiGJ2jl+5Im4XgT0OhQX320o8\n2XrK7/Pp+ttmc7ExT6pc53sSYRUfEyObpCYVIz1nWK1FujfW+ojFFUvhHPwSL3ny\ndkJORg8lcQm/zXjbgCeMZ/l3ynkvSA+X9/Q7aQWGrpU0LRLGAeA9PZZDYx9JTQUY\nFfGupHnbRtqsqQ==\n=7tcw\n-----END PGP PRIVATE KEY BLOCK-----\n"
  },
  {
    "path": "tests/fixtures/gpg/user2@gitsecret.io/public.key",
    "content": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: GnuPG v1\n\nmQENBFaigRUBCACgb+7xhV1nJZim3noxozslfrWXPYEVQt7Is8QjATaKg6ULqImi\ntpgnlUNCaEAd3PMufVSqd416KyytwUOBVaFIEej/SJcJ2UU4nFvJsvo4bNmInOc3\ncNSqJ5VcI7D++wdHSecr2YayWtsh85jt6xI2oGBN334Yl6sHnNGC/vmE0pWovpib\nrwAW7bWSOYOQxpzANm9O+9oJ6WsTGVVWkZ/SAaRo+VYDA5rwCI6STt+rEcKalr5C\nsbtqELDDDrYYviU4kZx6WYdiDcF5ATSiuGZrQTjEdBFc+GmFxbW+aumeC+Y1jYOp\naYUhbDKffnrxvFjm5+3PBbrPmJ5rFWr1f00bABEBAAG0GnVzZXIyIDx1c2VyMkBn\naXRzZWNyZXQuaW8+iQE4BBMBAgAiBQJWooEVAhsDBgsJCAcDAgYVCAIJCgsEFgID\nAQIeAQIXgAAKCRDqoOTrazNsiz97CACLgvaQgkS2oLRlQUZX0Yma+P+C4TJjlu5Q\npVdQyk13w2Fn25EsEWYbrya2MiU3y3A25xdRM7aUtZiEwmlSGOht1E/PDzzus2qz\nBIilZq89mt4wqBcnvb/aZ32btyv0WYRn19nHzS0HB0vb5xhrUiLG6ja+TZSfQsPj\naoJuHSdHFIN/eDrIO1IdhniLojz1fADlNIbX8LS4hytEoYMGSF3TmyoIn23+bqgD\nGTcDydkz6La5LT52Y5XACYO/r8Drj4B9/mFizHztR4B1TvqeLevDSlldOf3TC/9p\njR16JwOWZJRq21I2D8boqgTpEREvjuK3JTTsPjJS9MEYvmBW94FfuQENBFaigRUB\nCAC0PMNd0lI7CYOP8mECTTAP5EGPEjM79X8VcKi0dqqJJJG9nQmfoIysZrQQqSwZ\neOpjr6OEL8ctv2FeNH5yJT8TrghU0l20anvuuNVTKCuxjR/RlRJC59ML2VxUA/zA\n3Hn0GTSeW47TN4fSUxFT9wt3IYKzsLeh07nFW8WXkgnqMf/3nLoF1EZIM1OfN5Bd\nP59QfEtls8boBsshcM4ArY4AedRjra4YsXyXr3HUfKYtWoP1NhNT1Wlir0iXx7Xw\n7p+oTUwSnjMeTJN/oi8KBms4Uv5cCnAdjLU2yQqL1Y0N1AK+kOq81I9lKqtqNN14\nng3O5WKn5xwNP+1lVMDwD7RpABEBAAGJAR8EGAECAAkFAlaigRUCGwwACgkQ6qDk\n62szbIvUZQf/adIYw+fHM1zlGJH+C/lEFoGi0AXOTqBH13T+haoykwrxnBOdaTGY\n196bj+uiSbtFqQWcuMNrOWNNH6NAl30Ujya/ltLv7FJ3DOuUyIU/3Bhp1t1+jEpp\nMJRYk2pkRmmTg2lrOgSvPiqNgmK/FBx3t+JCtmQxtrTBBnJcmx5/8YGdOCEsiGJ2\njl+5Im4XgT0OhQX320o82XrK7/Pp+ttmc7ExT6pc53sSYRUfEyObpCYVIz1nWK1F\nujfW+ojFFUvhHPwSL3nydkJORg8lcQm/zXjbgCeMZ/l3ynkvSA+X9/Q7aQWGrpU0\nLRLGAeA9PZZDYx9JTQUYFfGupHnbRtqsqQ==\n=HLsH\n-----END PGP PUBLIC KEY BLOCK-----\n"
  },
  {
    "path": "tests/fixtures/gpg/user3@gitsecret.io/private.key",
    "content": "-----BEGIN PGP PRIVATE KEY BLOCK-----\nVersion: GnuPG v2.0.22 (GNU/Linux)\n\nlQPGBFtLVc0BCACwGHyefi/z8xeH6KpLN2k9+PlHAPpwJaW+8siaWjbQenkbWX6/\ncVBFBwLNVCY+UacKNKVPxYDgS9UkAGlqD1GRGISh9uvIKW/w4T2LBxDQBGlYsTdL\nKhOY1eTb5c7fa3ai17CqNam384+fqD9WCiK3PnO/1QLW48E8Q3R7JgyxmFB96FCb\nPZuRAMcBmKR7aa2yp493gGoI6Ts04gd33zDex0Qywz7u1rKNp/Sirb35nJUZ7Q63\nfof2LXSaJXEnHMdE6BFMkIhSluMAICxnb8uD57QilPSh3dkd5VmZAwd0dFV9orLA\nzlBnRu/VOmQA3bXaT8/g+F0XiA/r+4ARLnyRABEBAAH+BwMClcCGX/kaiEXsI8qd\nO+lPmY0IPpbYpG943Uo11Y2H2kCNEMu0m+jDanUH3uc3Cxuytfnq9kxzqetJgkw+\nsbYADZR7eWD9w2Su0hlJjMDWK0GXIsTLdf9KYwUi5g2CCqfglb7OJxpfQWd8gQiJ\n3QmxTLH54WVzEuFb3GbjeAnAVk8AgyP4zsMtBJbo4NuSZ3W/jVaNiJgdeWe9YWFx\nmngTLST+LgostcgAew/372zH8UM82uVC0pxk+FDfInFrnd9s6QZla2iGJgi8nwby\nkA0Kys9wRbO4ItWU/IdtLecv+FL8CKeZJf1ZirAU3MFQOg/snEfd56o0wFLt1mhC\nUIH+QwWGUolvihuXoI138bD67lE0dBiPuUjb+E4lgT8P0h2NYKtIwtWAO5xYdYtA\ncDOkFbTEOOtw4ylHTv3yx5866t5ddbl8G5P2+JGHKlNlfKxRQR71vy82ndbUz2V4\n59ImSNZUgFP43Q8YH78sZhrhNec15+Ek8jqZSfVajRotTc1reYeNU+qu8gKln3Uz\nyKAyci0DvIjG0IW+mbiXEf49yiYMZHoyGrFYpTBAp709yFufr8wQv0h/BN3UdGqI\ngwbJ6kjQrm0S48Vw+A8YkxeaiahpCpbAiwoDa5PN5NZvFwXmXwQkx5fCeyhRkxdf\nUtPV5uDa1WznIt2gHP2NKTP54nEfLq4eLcwjvLcyjXn9aAZRmNMwbOBJ9Uf4x06S\nxzBI5FUL+2aqHrEedCeyW4AsndVaKOWNfzqjY7Y8cDuqpQj3o6yWbGy8u1kGDPK+\nv6gCe3Ub+y801kqN2IyegSyjK6t2H+j0y7Y+I2J33SBKgztiEcWgM4N70zaCV+vj\n5ekYXwp4N2w1yWkejk0heIiDdaxRWejs6WImDMOvinXot/arbqwEKkr3nNhbFNoq\nCRWZ45DsnlkxtBJ1c2VyM0BnaXRzZWNyZXQuaW+JAU4EEwEIADgWIQRz/JOETMGC\nSt9zD7Gz/JMICuU7UQIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAUCX2X3vwAK\nCRCz/JMICuU7URxqB/0ZqQ6tZh5mnZ/kC2TLb4GQJqZbZOyb4I6uI2LH3di43EX9\nUMtJvXBsl5rR68jCpJfrzC/nCWkVLC9meNydUgDXGNJyEyp22dXJoSvfzcI1WFOT\nOK7JdHi9TtsmqEKZk9YC0rliaisb886vXrB4LsbyLqRYYc0+9oRLZnWbY9mc+44B\nrnFOWpMayELnJMhNq5awSJhwc983VEwExyHdCStj94Q2SBM/v9xpo+xjjbJVe8qt\nIJXvA5aJPi1HObpWBJq+3ZWVqKfWY8wUojPn+N7PUuUvBGzUanfpbdKs025XjO4Y\n0zbh+2/W8JcFs1nL5fEALZ6LVy0clldLB+Rco3c4nQPGBFtLVc0BCAD2b/acD8ik\nPMeu+TSRz1xkwrxjMh14kx5bWLWmhAdFK3FkpRzRy/u7URMYyc1e4k1Vd+srScc6\nPHfAyW5dP7kyuV/I3qGVJTGDtp3YDcXg9TSToYp65Vo+RTTlGE3GVeVs/KVs3Ipf\n2oBgxbXZi+twrQ6ZUr+Ak7M9oWimNyGkYr/kOC/8zO5haxsYNamOtBmcedlkctHx\nh3auZ57XGDHCt1h5fMRMzNoVqhyWmg+XW7O30HY8f5AX37rHgtpuCku7ejzX35NX\n+jLelR5a2f2Q+SVs02pGmOF6n4PKJA3pPXYfouR8wuiiFjifxVq1AQQm0J1MJeMi\ntHu+VcXx8KBrABEBAAH+BwMCaZaMo90qa/DsAWmMT3aso9qu+MdYX8RB3ZSLiTG7\nxAA8B1bzNJ4NUpjyaPiVbxP6VCau6rUzgbzw7HC7w3w7FIfuPT4KTQACsHcyXMzQ\nbAeK5C4u6vbeFJGa0j7oNJm9prwGg6QDOMdyuS9LCz2i997ZMt/uvs22xw+nDzdU\n1UzV6zXQ0iB87zejnmyWYJfELr13N7TvyOsQdIaeeIsoNkPnoNFCFaUOj8WUABfk\nMjijXZin9neyoXBIoFQg093QeArWzIrtXGcMFjk4EacboUpPOE4/Ybxy7Jsd/AxM\nJGwT6Ptqx6TDg/epAuaQhUNbivS4N4TcDKIoKsXBdKXgGGuhp7zajxShaNC1GQmZ\n9+Gz7jiFiQl0hJVeK83lK5w4BguNcpIAomN5rvA8R9pOAcC5r84C4QBHGXvD3Upn\nyXda+EgJ5M2v8sk79vliPbZbKHLpq97PrHj8TUJ1jRD7QmpW0ko6KOuFZSItW7Tp\nu1zXNmFpLIEJovkZiHrsypCwSQefjcQ44G1AdYncTOVj64+nduJnqB6IiisziI1U\nX9VUl9Q1v+EArdIjxUjAQSz1Ykcw6Jg6X+6AzfNSX0Yoy/PrCId10JjAqIkuHFiG\n4Q3IvM+1/irI0izc2LAwqiuSIXWgiOIT2hslVixEo9Kbm9ZIoVPaEIOC1KnC4cGg\nFjemal2kuZmZ7EzOh8i9slFGyVFYYCLg/03TVmM13Do3e0DJ18da3H2zhgjyQul+\nVQbAWnZxNExPyKwfTsFkXxZk7dTlO7VbL6iCDCZwDAQfZt27zIvOKpvMw7TSKLw1\nafDX9wj0XzQ70d3CfPzVayjfbgw727C6O8tjUDJJC/vI5e7II5uFd8oiq+iwj/Hc\nlAsZO9VabmX/BZ9rh+JppQExGr/+0qnxJI+6TYCvxe712rBsCpO+iQE2BBgBCAAg\nFiEEc/yThEzBgkrfcw+xs/yTCArlO1EFAltLVc0CGwwACgkQs/yTCArlO1E9Zwf/\ncrn9d7qCZGpgQbaQj1lIr1LtLHzscl60Ug/9mL3u7Tc9ys5qg+EB+Y0zl6Y7MpNH\nt/XTFbLU0oqK1JVM7pJVZxqFHnKq5StpWtiCQ7v3wtpdziub1S1kmtiIW3VRMMqQ\nGW/CjkRj1532KqaeefM8rDXKP4l/AB8gvfXs+Xh4tgET49jh/COIh8aKVAMcEe2R\n8yz8eCtmk7AcwcyYGDZdpiHk99MPM9ACi6Aqp55fmPKuslMjL1LvWjlGEDzmOZQY\ntfwMTb5idXqfbmC9Qo7kSRZAW34rAoTDwHh5E6591UEV7wkBhU34w3WUt8BLVRdO\niK5wCW5ErIHh7mpgpvRK4Q==\n=wl8Z\n-----END PGP PRIVATE KEY BLOCK-----\n"
  },
  {
    "path": "tests/fixtures/gpg/user3@gitsecret.io/public.key",
    "content": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: GnuPG v2.0.22 (GNU/Linux)\n\nmQENBFtLVc0BCACwGHyefi/z8xeH6KpLN2k9+PlHAPpwJaW+8siaWjbQenkbWX6/\ncVBFBwLNVCY+UacKNKVPxYDgS9UkAGlqD1GRGISh9uvIKW/w4T2LBxDQBGlYsTdL\nKhOY1eTb5c7fa3ai17CqNam384+fqD9WCiK3PnO/1QLW48E8Q3R7JgyxmFB96FCb\nPZuRAMcBmKR7aa2yp493gGoI6Ts04gd33zDex0Qywz7u1rKNp/Sirb35nJUZ7Q63\nfof2LXSaJXEnHMdE6BFMkIhSluMAICxnb8uD57QilPSh3dkd5VmZAwd0dFV9orLA\nzlBnRu/VOmQA3bXaT8/g+F0XiA/r+4ARLnyRABEBAAG0EnVzZXIzQGdpdHNlY3Jl\ndC5pb4kBTgQTAQgAOBYhBHP8k4RMwYJK33MPsbP8kwgK5TtRAhsDBQsJCAcCBhUK\nCQgLAgQWAgMBAh4BAheABQJfZfe/AAoJELP8kwgK5TtRHGoH/RmpDq1mHmadn+QL\nZMtvgZAmpltk7Jvgjq4jYsfd2LjcRf1Qy0m9cGyXmtHryMKkl+vML+cJaRUsL2Z4\n3J1SANcY0nITKnbZ1cmhK9/NwjVYU5M4rsl0eL1O2yaoQpmT1gLSuWJqKxvzzq9e\nsHguxvIupFhhzT72hEtmdZtj2Zz7jgGucU5akxrIQuckyE2rlrBImHBz3zdUTATH\nId0JK2P3hDZIEz+/3Gmj7GONslV7yq0gle8Dlok+LUc5ulYEmr7dlZWop9ZjzBSi\nM+f43s9S5S8EbNRqd+lt0qzTbleM7hjTNuH7b9bwlwWzWcvl8QAtnotXLRyWV0sH\n5Fyjdzi5AQ0EW0tVzQEIAPZv9pwPyKQ8x675NJHPXGTCvGMyHXiTHltYtaaEB0Ur\ncWSlHNHL+7tRExjJzV7iTVV36ytJxzo8d8DJbl0/uTK5X8jeoZUlMYO2ndgNxeD1\nNJOhinrlWj5FNOUYTcZV5Wz8pWzcil/agGDFtdmL63CtDplSv4CTsz2haKY3IaRi\nv+Q4L/zM7mFrGxg1qY60GZx52WRy0fGHdq5nntcYMcK3WHl8xEzM2hWqHJaaD5db\ns7fQdjx/kBffuseC2m4KS7t6PNffk1f6Mt6VHlrZ/ZD5JWzTakaY4Xqfg8okDek9\ndh+i5HzC6KIWOJ/FWrUBBCbQnUwl4yK0e75VxfHwoGsAEQEAAYkBNgQYAQgAIBYh\nBHP8k4RMwYJK33MPsbP8kwgK5TtRBQJbS1XNAhsMAAoJELP8kwgK5TtRPWcH/3K5\n/Xe6gmRqYEG2kI9ZSK9S7Sx87HJetFIP/Zi97u03PcrOaoPhAfmNM5emOzKTR7f1\n0xWy1NKKitSVTO6SVWcahR5yquUraVrYgkO798LaXc4rm9UtZJrYiFt1UTDKkBlv\nwo5EY9ed9iqmnnnzPKw1yj+JfwAfIL317Pl4eLYBE+PY4fwjiIfGilQDHBHtkfMs\n/HgrZpOwHMHMmBg2XaYh5PfTDzPQAougKqeeX5jyrrJTIy9S71o5RhA85jmUGLX8\nDE2+YnV6n25gvUKO5EkWQFt+KwKEw8B4eROufdVBFe8JAYVN+MN1lLfAS1UXToiu\ncAluRKyB4e5qYKb0SuE=\n=ccTC\n-----END PGP PUBLIC KEY BLOCK-----\n"
  },
  {
    "path": "tests/fixtures/gpg/user4@gitsecret.io/private.key",
    "content": "-----BEGIN PGP PRIVATE KEY BLOCK-----\nVersion: GnuPG v2.0.22 (GNU/Linux)\n\nlQO+BFumzaQBCADp6MO1IRBIbdJoABK3EUWxBjZKE/jAcAYGizfXh3rLm3QjBumR\nEHET67sfOJUIbqGbhfw+/PbpxKG1um3BcV85gXWcqW77ch/YupyJH0NNP3sBZ76W\nJqJXASGKR2JkBM5KSgNkS13LdMXTaXM9zwZuCOU1T4geapV/Zj4W614qzO8mRlOt\ngIl8/moxP0IwZneJvBhYLCCQg8i+zedIUvF5eneW9kwEtS84/PLXQ/HfbEuDaq0O\ndHmkXBNwp41PsnriMc78lahEXU9Xh9VUPwBYGs/kyXhhLEdhSBq/5zKdDldg2lc8\nyKqZyenvoS5iKzJJU9QDjHP6gsYlhJ3c5WM5ABEBAAH+AwMCaxzgsFgqaQDj7Pbz\nL6zsxufuY59yw7vrae83yVai2erjJY4nZekvvB5ckZc83egDzkQjQIIMScwV4cJx\nTKiU1+dW+u3hcO1Qo4LDPCb3LFNiIfOoqKytDePZlfbL94VyANiGp6YLG4Z8rGrj\npD7uINdCAIYK8EcXhJDwBnu7CaWkel+zeF3QCvppvKCcRN3RTabziXwcRaFcDnA3\n5FfUssPU6X3bGMGiZnu3P6HDVksHfbsTjNIfsbvuejkbZxIvj52mTnDhSTkL0/uh\nZAB6b4QWdY7+Df0ePPuRu/d1RCovx4HGI1Fi0YemcZ1AOet8y/LcEN9gs0jkL2Ux\nEevYDFVVd0J5MFISrmu7PTPBWn9TV7no2Tr3i21HIocNSWwkpK0uMI6ezMEPSCIb\nYTR6lSfeuVnQyUkLDGVvO4QGENra2unJRrXXrIwQk8qZK3p0PJ1Vss7kvR2RepIJ\nWsaSALHEyvHNeMtdlgyp10mBGmN9a+f2Wa5fqGsdLIDCOhztOnpEhJWNo4Rbjbov\n8jx404sQvs84CN+VLvoXt6uSalzcxgWhyYMHhkmHc5X54pLACM1HL0EDfFtzb/rm\nrxXRzCxBxVMjFlCkZHt0SEYjP8bRDmqzyiHe1er3AuJCyY2VoiIfoc9iy2OkcONs\nbTrppNPe07v9UFcYjPiOWRuzPaEryBArteiT9u9x4eTi5QfYAqGChOHBIRKwnRgS\nTTJQnKoIWvwxaQ/o7fzfveS1NKnWdahZr7dE/+pA3DFvBWBLkrPQSXYHpbzPjx3t\nHB5AOJXQHWMFb2FUggu+uFANvUljc33AqHiJLD6eV3y7AQLIxJyol/S5kCkZ6f+I\njnOg2V0VvuxFgx7WNnAomhq8d2JDi9WagqdjwmmT5qJbeixHZBvhg1hgZyaJLMep\nrLQadXNlcjQgPHVzZXI0QGdpdHNlY3JldC5pbz6JAT8EEwECACkCGwMHCwkIBwMC\nAQYVCAIJCgsEFgIDAQIeAQIXgAUCW6bPFQUJAAFS8QAKCRDm1MhM34HEJVd3CACA\nsegF3UqDH3LuupOageZDKlmxRv9VSze7TC1p300eulvi4MsE/LlYoPGcS3BYxh7f\nW0ADOrLQA2mxL3cMuLB2L7gMByt7/wjmMmc0uTW1iCXQxMcRbn28ppBGEm4gRvP2\nn7rI0cu/xNKc/zFIPZOdaykf+yfWZZZ22qWvbKlWi5MDQZYH9CsGvs6DKoTXKMxv\nfJCywZIfIPTPfQLHBKfXClyCUtj8FpFTGGmzthcAc95MhXASqWyAqlVHhXcTiOs1\njbedNQDG9og0qPkwJLu6yMPKZGEpg0qTtTCZlizblS8vvPHWYht/e/W6MX0sfZmO\nkweoudVozcBptiMq5vKHnQO+BFumzaQBCAC0qy+0Htba6RbLJymI69kIN6jQhUUD\nmRPwj+87QilUTNUYFalyPMT6e3oiZpr/o1a75oeZm/8Ys8+npipUrt4XByfO4zQ+\nfF8U6+2YqCNnyYInFECDI9Csotlj3HXULb02A6dRKC9hvvGHoIoL2B0sIZUarXaS\n6shUUJqxH1Z86I5V//cMVYndqvvTWkc3I1HIT4RHJUGbLHM5ePnbNisMDxnCAb+S\ndp95M7LflZtH0GqO7RRKvCXi17lC352U8MdId/OtN4auu7IhDW2eOBUO486cerDL\nYYVlqhXC9o5tJfxPwtDQiIQCw1PmrtPnMtLhXRRg6H/3eVY9tZ/W4C9PABEBAAH+\nAwMCaxzgsFgqaQDjxHj0GMNo74Zls1gLk+o6HyjlvgnCtp7m5n8rkgaDKhRtaTkm\nAQBtKXhxfzFzQ1/RJfz3hBpYetAoW/HOE2ZQvLAigsbsHGRr+LF6W4i/8SG06jDW\n2eyAKCbe45PWgcNzRqoyxWjOQXJc3UMXK3pX1oiyrt8WcsckGZxpsF24YUAxoNjz\nYlVFisqgpnBV6tCeD5L/68ibQvfiK2Eh7VtBPCf4yesZ6HjjVCAXkb4dbEhuuGCH\nezlPfAQhtlqwuoLFlI8HCR/qOEhCgd6u9aoVd5xYxHYa6DQ7sM/04iH79XTr7KGz\n07ltAgknRxEgq8EGYXUzEJ4fzqwbYxmo7iJjUbZApO+tKWYcpC4jSfITNOGOCrHC\naQ/KzrtV0imm/RIhG/ZRZidWHf9gntjgc4kLKQuJZZUlUd1LHYqd7+5keiiDRxMr\n1ddsMW1VBsKunZ6ryREkwzgbFzxT+ZWJlggHR15+h0+koWVvSiIj91s3Uw7PtrDe\nbOllsIQw0GnutJ08MVhduuk8M8vNapG3ZGrvXBD25qyV3EHSHoCagdBqtG8NxDpE\n/lQFk13kdeyXAPBneuGgvNAwbjWHn3qL23qsHTae1hslXcVTSIFxqrMuuENjuQc4\n7k4Ma/JhXLjj0/avA+mrLJC4c6/HzN16bBcVlKqLF3r/g8xUyE17WQETzL2AMOOn\nUrKycP6d/VKGTr5VrlJl14dEACNya7anucSMv+4cat0DNOeYg3fB6hNRpR8bjOF+\nfHuXkurLo/zH1wNCKBA6wV1/B9+E+EdBSwr1a1/79u+IqsLZh4piHxl6nIUAtkdV\nUwZXpuA9XuXP5RmxTwPuutnsYJz/LQKzI7B71PJjGzQqkfsl7jx9KsPkkqtd+RRY\nlFieM3t7hY9fcBmIO4eaYIkBHwQYAQIACQUCW6bNpAIbDAAKCRDm1MhM34HEJdaU\nB/9RH9XEO/f2ntmmYEJ1sYheUeKw0ZvOxaMz2poWrEJABY4C/slNpQL5rSeZ5jQf\n4Gpe/IUWYd/Q24b4cDvYvngGQ+c63DlM2pVtcVKkyvWyLYmimr4WaLLyk1JYgqrW\nuLfXwsd2x7O42Cm4sevfPQS1hfgaWIfg9Gb1CVtlbJhq7iO5BBY5xPAXG70MksSq\nX/PO1ah3/ZBWuzd66nXBC/oX0tTj5W0hBuXrOkjHhXh42v26BX1xrHgq2ivuiqw/\nPDHGFJ4K5x3A6Pz8UuAOlESJRPemOT++pV1LvFlkGSGTxrOIS/wvPT3skNeXsyDN\nVJ97gZKyfwWA4E3gTZGuYr3s\n=1Mtg\n-----END PGP PRIVATE KEY BLOCK-----\n"
  },
  {
    "path": "tests/fixtures/gpg/user4@gitsecret.io/public.key",
    "content": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: GnuPG v2.0.22 (GNU/Linux)\n\nmQENBFumzaQBCADp6MO1IRBIbdJoABK3EUWxBjZKE/jAcAYGizfXh3rLm3QjBumR\nEHET67sfOJUIbqGbhfw+/PbpxKG1um3BcV85gXWcqW77ch/YupyJH0NNP3sBZ76W\nJqJXASGKR2JkBM5KSgNkS13LdMXTaXM9zwZuCOU1T4geapV/Zj4W614qzO8mRlOt\ngIl8/moxP0IwZneJvBhYLCCQg8i+zedIUvF5eneW9kwEtS84/PLXQ/HfbEuDaq0O\ndHmkXBNwp41PsnriMc78lahEXU9Xh9VUPwBYGs/kyXhhLEdhSBq/5zKdDldg2lc8\nyKqZyenvoS5iKzJJU9QDjHP6gsYlhJ3c5WM5ABEBAAG0GnVzZXI0IDx1c2VyNEBn\naXRzZWNyZXQuaW8+iQE/BBMBAgApAhsDBwsJCAcDAgEGFQgCCQoLBBYCAwECHgEC\nF4AFAlumzxUFCQABUvEACgkQ5tTITN+BxCVXdwgAgLHoBd1Kgx9y7rqTmoHmQypZ\nsUb/VUs3u0wtad9NHrpb4uDLBPy5WKDxnEtwWMYe31tAAzqy0ANpsS93DLiwdi+4\nDAcre/8I5jJnNLk1tYgl0MTHEW59vKaQRhJuIEbz9p+6yNHLv8TSnP8xSD2TnWsp\nH/sn1mWWdtqlr2ypVouTA0GWB/QrBr7OgyqE1yjMb3yQssGSHyD0z30CxwSn1wpc\nglLY/BaRUxhps7YXAHPeTIVwEqlsgKpVR4V3E4jrNY23nTUAxvaINKj5MCS7usjD\nymRhKYNKk7UwmZYs25UvL7zx1mIbf3v1ujF9LH2ZjpMHqLnVaM3AabYjKubyh7kB\nDQRbps2kAQgAtKsvtB7W2ukWyycpiOvZCDeo0IVFA5kT8I/vO0IpVEzVGBWpcjzE\n+nt6Imaa/6NWu+aHmZv/GLPPp6YqVK7eFwcnzuM0PnxfFOvtmKgjZ8mCJxRAgyPQ\nrKLZY9x11C29NgOnUSgvYb7xh6CKC9gdLCGVGq12kurIVFCasR9WfOiOVf/3DFWJ\n3ar701pHNyNRyE+ERyVBmyxzOXj52zYrDA8ZwgG/knafeTOy35WbR9Bqju0USrwl\n4te5Qt+dlPDHSHfzrTeGrruyIQ1tnjgVDuPOnHqwy2GFZaoVwvaObSX8T8LQ0IiE\nAsNT5q7T5zLS4V0UYOh/93lWPbWf1uAvTwARAQABiQEfBBgBAgAJBQJbps2kAhsM\nAAoJEObUyEzfgcQl1pQH/1Ef1cQ79/ae2aZgQnWxiF5R4rDRm87FozPamhasQkAF\njgL+yU2lAvmtJ5nmNB/gal78hRZh39DbhvhwO9i+eAZD5zrcOUzalW1xUqTK9bIt\niaKavhZosvKTUliCqta4t9fCx3bHs7jYKbix6989BLWF+BpYh+D0ZvUJW2VsmGru\nI7kEFjnE8BcbvQySxKpf887VqHf9kFa7N3rqdcEL+hfS1OPlbSEG5es6SMeFeHja\n/boFfXGseCraK+6KrD88McYUngrnHcDo/PxS4A6URIlE96Y5P76lXUu8WWQZIZPG\ns4hL/C89PeyQ15ezIM1Un3uBkrJ/BYDgTeBNka5ivew=\n=L85k\n-----END PGP PUBLIC KEY BLOCK-----\n"
  },
  {
    "path": "tests/fixtures/gpg/user5@gitsecret.io/private.key",
    "content": "-----BEGIN PGP PRIVATE KEY BLOCK-----\n\nlQPGBF1yX48BCAC7TVKvW81RjJKcGI21cI1iUEPkpWCqXwUjt9UsJ8g+2BW45gmX\n9tLKPp5ax6hJoLQpcSkOsKcNdigSwHeB+TjIgGshAQOgOXLgnU6oETkobxrv3TcQ\nL0gF09jgnUvdzaCSgqtLndgejG1g5SsYIzzHYSTAj/7t5WY2AQKVsiE9pELxUqLB\nQQQ97YHklp26sNXT9FYBNZvLN661PvTB2fgMxMrLkE0i8brAC51zyp0/PCy7huDz\n9zjryMCReKkwfVIpevBJspHx1P2HLNe+b+O28C4U0r8CuWSk116itbfKGCtWL8LL\nkhMUBD4j+6zO1E33HVeRR6hypU8ZhbDIX9BzABEBAAH+BwMCrMDlojZX/jjr0l3U\n8acJEKVGWAq8dxt+UKNm5PSNZksQdcsz4E1JL/4JitfRhvrH24OGJnGrmMYeQJjH\nDw+dHUf8UDD8KpRigihCug44VM36ZtiCxfQ8+x01DQ8G6dntZmphg6B0dJbvhUJa\nYEuRk1n5rVH1lMEitq3ZcnvnU4hJxWfKdo8qI+MReaiVtODk42y0kA6/7y+w+a1j\n7wWtVsdHvvC5f698Z0FKzSGxHWGgE2bFWaRxhuX0WIBMgDsr2H+jcvb51c3SIWkd\neCTupBomcv99FYcBUHf4VnjJGgBn4ibU49BZtMbmTHeB4bNb/hTCwhWuW50mr2yt\nGZ/Ued2y6khcaDXlsQGdqUn7/4KEe3vpwVU6RzKrxBMhaY2zZdwVEAb9c/2szSt6\n+YOhopOmH23lWF5iu2pdRcU9pJtj614tpIGOLC4H8e+im+buy+jOIvj6eECH50zK\nzHchOvrCWAG4qcVTSAv2J2Ywa1wzKxUfoPbpCZJ7pJvt2pjxa2Mh1vjlydle4/Tq\n6qcu4OONdJPiDu2n0DvThfZXxWPqYrQKNPok/uIuOyux3U3JKgBdCKW9wj6wXvik\nTakIRvsPjMsTkyP5J7GoFokw/7tTd8fww6+HK7o171+bT1/oEmp+ulE/U5mcaVTw\nuabWtLt9gignidle6R4GlVI/xo/J/szcQyiv9/MA1z0tC5FIM2HYF4ADg2de8MbE\ndQKyNZxkAoFtofE8WDsMVf/C2BzTpLp9yqTGhZptCWlkU+OpBxLaVIa1tlw0mbt0\nPWujKEatkdFOHhuutjLCWGiB84FKkPPti0YkfJxPxbXDMa2p7KvCSSrrkZM2mKBq\n13hcLm4ANUWQCFJHpCriMg79xLSL6zEL4Lt6V+Soi1dDtH5jwox+SsC273BZXyq8\nrjOisteYwarjtBd1c2VyNSAoY29tbWVudCBjb21tZW50KYkBTgQTAQgAOBYhBPbR\njRmpf0xIpd59km5RnYONIUgfBQJdcl+PAhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4B\nAheAAAoJEG5RnYONIUgfhQQH/38uO9hvFdc72UnYjCADZXvdSa1T+vSKJfF9Sa+D\nSe2F3JlwYPvpDnEovMmi7RuUJ1n7mGzTFJ6HLHs4Z26P6VtmC2e3ue2/OltK24zd\nzeH80WfGmFfJ1cFShO5mGEk+ga3HhhCHPE9zkEM+HO+Dn+IDBuJL4PAvu6c6buVo\nK9GDbo7tkCFB1+vw39CmEmnPuIoGygliJxKqiqHsS/Jn4KkNyecT8z5xaA41lGdA\nZbda6og4u0vsj7Uctder22tdVKDWg1Jwr23ORBYCD2ssQKUq31G/kvQeZxCTdZD8\nt/V3pQz0uru/c/NvVLX1eZDXwM+viR/Ck5oyTETkHF9LZNedA8YEXXJfjwEIAMxn\nJVMiOyZfPclOt1oQv51vrmbWyiKHSNn9OwtW2HQIWXT5cpA76ojceLxF2Gz3Lr8k\n5ZqJQZb2jTB/HGDeJMVOQobsfJLD2llM99PFFdE/lAlu+/jQp90hu/gLo9egu+aI\nZP6YRmvJMLseB8t22dWGb8OpnZgTzAL9uk8vhYzMLGCiOezC0pzxKCDsIfBtpHDy\nb9Z06cD4hywvtaRCJOXanUhv2rbPEcNRoYqY3kFlaV37NxMRyCplODq6HmrsxsUp\nhJmHA227HtBHJzJtRcewyOcvHE3TovynDPDNtk+KtvZfiqvvKDwEXjrygYiB/xZP\niFvT5f4xB6hicJq8+78AEQEAAf4HAwJRNs0fBsU0LOueT8yhsPFyxg+XYBeAR5Hx\nNyCFrIXaDSTY+TrTpbY0o2wrBgZtI+YAuVCgqkmQDzp8Dhb21Dcx2Zg4xJ92KHcE\ndwq/VMz9l5l6JgfEg7Dt8XUCeetYKEkX/li9Q9urwBpZ3oPIjjhZoK74zfGA0Qtk\nqRYCXHhBVme7pxAfirmX0jiLbDv5nV+fzJXqTzY/Zsaodw0w9CiuzZ5ftM7kk7QH\nTGEeGB0yaEgm7LPupGxfkHnY7IU7f1g4e7QhQcFSHady2HrtEVYFgsdlxxCxSFzK\nG3zctVTTTQKb67zVNKtblizSHRq21gx/uutReh+RZUhTJewfpOpup7e9oNDxpkSW\nnkiHU91vNaOfdfuID7V6eIYKM3yCvrc5z9NKBYklGX2wYm9qEObBF1LrQD2c/M/+\nRn6gnJLdUo0Q95URwngCrchz1i7MVWje3VfsuiHRsB62NFLOGeDqkdoJ7PPCRHeS\nWXaZUK7/a7B6wZuf4fafEVWSpgonWvL3bxCLlPau5zYvo40WLzFtIVT6gBCR/TBY\nAhUVrrvn1Ssqrz1RRD7ebbFR59yDsEyJaL4cdJzVidB4+tp9XAJ0yjiGJyCJW5NR\neW0dR1jHDacBPMnxgqKtXpn7d0PMx0oghD0wFiQsGqi6aWJs8+qGWugCoHZUiJB2\nR/N0MO7l4CuJYECSIiVqgu08h7ZQ3CgROGEFVYaBmkX50DFwLe9FkurOE83jNiJE\nd7QKhc2IE6RQ0j9bS7GcBkNjED7jUCryLbwI8ITekHnSt0BiFnVb9rZ3cMYNArcS\n5rDZ4JQYsqGiGb03VZqW9VXD/40tTtkLU5EaN9tgroQiHovCfLiug4WbRYz26wZF\ncnMHaQCPHYAKme72bAypjzooN4KT5KE8uyNQo3/1eEwd2AKRFEl4f2uBTNqJATYE\nGAEIACAWIQT20Y0ZqX9MSKXefZJuUZ2DjSFIHwUCXXJfjwIbDAAKCRBuUZ2DjSFI\nH+agCACVQyt3pbCPgJ8CXXhMaaH0Y16DJDxy/AXzQL7hxHzgqIrHuOygADCXvMcH\npb6kznMG4pVfeNZtm+FDoQ7rDPcY9T9eSQD6Fw2hzemysdWAoD9ZUNwynw125Og7\nnmOmXIJLQ58J0bDVfb34zwYfdE45LTaQXO2ODx4foMpzCv86XUE4GboQSnUrU1VN\nafrbVTSZ7Zna6yNzgtCVomSjxDhCZ+nnYQsTwXqERqby8v2KpgWM3yVV84q2ED2N\n51JUIdXFjejFyHWjDHYfYPo4s/I75gYKsTCFo9lGqkcVKX13HMCI7J4KGrmxLVJq\nswK2XO60K8/knDo78U2RvVf+Goat\n=9tu1\n-----END PGP PRIVATE KEY BLOCK-----\n"
  },
  {
    "path": "tests/fixtures/gpg/user5@gitsecret.io/public.key",
    "content": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQENBF1yX48BCAC7TVKvW81RjJKcGI21cI1iUEPkpWCqXwUjt9UsJ8g+2BW45gmX\n9tLKPp5ax6hJoLQpcSkOsKcNdigSwHeB+TjIgGshAQOgOXLgnU6oETkobxrv3TcQ\nL0gF09jgnUvdzaCSgqtLndgejG1g5SsYIzzHYSTAj/7t5WY2AQKVsiE9pELxUqLB\nQQQ97YHklp26sNXT9FYBNZvLN661PvTB2fgMxMrLkE0i8brAC51zyp0/PCy7huDz\n9zjryMCReKkwfVIpevBJspHx1P2HLNe+b+O28C4U0r8CuWSk116itbfKGCtWL8LL\nkhMUBD4j+6zO1E33HVeRR6hypU8ZhbDIX9BzABEBAAG0F3VzZXI1IChjb21tZW50\nIGNvbW1lbnQpiQFOBBMBCAA4FiEE9tGNGal/TEil3n2SblGdg40hSB8FAl1yX48C\nGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQblGdg40hSB+FBAf/fy472G8V\n1zvZSdiMIANle91JrVP69Iol8X1Jr4NJ7YXcmXBg++kOcSi8yaLtG5QnWfuYbNMU\nnocsezhnbo/pW2YLZ7e57b86W0rbjN3N4fzRZ8aYV8nVwVKE7mYYST6BrceGEIc8\nT3OQQz4c74Of4gMG4kvg8C+7pzpu5Wgr0YNuju2QIUHX6/Df0KYSac+4igbKCWIn\nEqqKoexL8mfgqQ3J5xPzPnFoDjWUZ0Blt1rqiDi7S+yPtRy116vba11UoNaDUnCv\nbc5EFgIPayxApSrfUb+S9B5nEJN1kPy39XelDPS6u79z829UtfV5kNfAz6+JH8KT\nmjJMROQcX0tk17kBDQRdcl+PAQgAzGclUyI7Jl89yU63WhC/nW+uZtbKIodI2f07\nC1bYdAhZdPlykDvqiNx4vEXYbPcuvyTlmolBlvaNMH8cYN4kxU5Chux8ksPaWUz3\n08UV0T+UCW77+NCn3SG7+Auj16C75ohk/phGa8kwux4Hy3bZ1YZvw6mdmBPMAv26\nTy+FjMwsYKI57MLSnPEoIOwh8G2kcPJv1nTpwPiHLC+1pEIk5dqdSG/ats8Rw1Gh\nipjeQWVpXfs3ExHIKmU4OroeauzGxSmEmYcDbbse0EcnMm1Fx7DI5y8cTdOi/KcM\n8M22T4q29l+Kq+8oPAReOvKBiIH/Fk+IW9Pl/jEHqGJwmrz7vwARAQABiQE2BBgB\nCAAgFiEE9tGNGal/TEil3n2SblGdg40hSB8FAl1yX48CGwwACgkQblGdg40hSB/m\noAgAlUMrd6Wwj4CfAl14TGmh9GNegyQ8cvwF80C+4cR84KiKx7jsoAAwl7zHB6W+\npM5zBuKVX3jWbZvhQ6EO6wz3GPU/XkkA+hcNoc3psrHVgKA/WVDcMp8NduToO55j\nplyCS0OfCdGw1X29+M8GH3ROOS02kFztjg8eH6DKcwr/Ol1BOBm6EEp1K1NVTWn6\n21U0me2Z2usjc4LQlaJko8Q4Qmfp52ELE8F6hEam8vL9iqYFjN8lVfOKthA9jedS\nVCHVxY3oxch1owx2H2D6OLPyO+YGCrEwhaPZRqpHFSl9dxzAiOyeChq5sS1SarMC\ntlzutCvP5Jw6O/FNkb1X/hqGrQ==\n=ghZU\n-----END PGP PUBLIC KEY BLOCK-----\n"
  },
  {
    "path": "tests/test_add.bats",
    "content": "#!/usr/bin/env bats\n\nload _test_base\n\n\nfunction setup {\n  install_fixture_key \"$TEST_DEFAULT_USER\"\n\n  set_state_initial\n  set_state_git\n  set_state_secret_init\n  set_state_secret_tell \"$TEST_DEFAULT_USER\"\n}\n\n\nfunction teardown {\n  uninstall_fixture_key \"$TEST_DEFAULT_USER\"\n  unset_current_state\n}\n\n\n@test \"run 'add' normally\" {\n  # Preparations:\n  local filename=\"$TEST_DEFAULT_FILENAME\"\n  echo \"content\" > \"$filename\"\n\n  run git secret add \"$filename\"\n  [ \"$status\" -eq 0 ]\n\n  # Ensuring that path mappings was set correctly:\n  local path_mappings\n  path_mappings=$(_get_secrets_dir_paths_mapping)\n\n  local files_list\n  files_list=$(cat \"$path_mappings\")\n  [ \"$files_list\" = \"$filename\" ]\n\n  # Cleaning up:\n  rm \"$filename\" \".gitignore\"\n}\n\n\n@test \"run 'add' with bad arg\" {\n  local test_file=\"$TEST_DEFAULT_FILENAME\"\n  touch \"$test_file\"\n  echo \"content\" > \"$test_file\"\n\n  run git secret add -Z \"$test_file\"\n  [ \"$status\" -ne 0 ]\n\n  rm \"$test_file\"\n}\n\n\n@test \"run 'add' for file ignored by default\" {\n  local test_file=\"$TEST_DEFAULT_FILENAME\"\n  touch \"$test_file\"\n  echo \"content\" > \"$test_file\"\n\n  run git secret add \"$test_file\"\n  [ \"$status\" -eq 0 ]\n\n  rm \"$test_file\"\n}\n\n\n@test \"run 'add' for file ignored with '-i' and '.gitignore' contents\" {\n  local test_file=\"$TEST_DEFAULT_FILENAME\"\n  touch \"$test_file\"\n  echo \"content\" > \"$test_file\"\n\n  local quoted_name\n  quoted_name=$(printf '%q' \"$test_file\")\n\n  # add -i is now a no-op (See #225) so this tests that -i does nothing.\n  run git secret add -i \"$test_file\"\n  [ \"$status\" -eq 0 ]\n\n  run file_has_line \"$quoted_name\" \".gitignore\"\n  [ \"$output\" = '0' ]\n\n  local expected=.gitsec/keys/random_seed$'\\n'\\!\\*.sec$'\\n'$quoted_name\n  echo \"$expected\" > '.expected'\n\n  [ \"$(cmp '.expected' '.gitignore'; echo $?)\" -eq 0 ]\n\n  rm \"$test_file\" '.expected'\n}\n\n\n@test \"run 'add' for file ignored by default and with '-i' in subfolder\" {\n  # This test covers this issue:\n  # https://github.com/sobolevn/git-secret/issues/85 task 1\n\n  if [[ \"$BATS_RUNNING_FROM_GIT\" -eq 1 ]]; then\n    # See #334 for more about this\n    skip \"this test is skipped while 'git commit'\"\n  fi\n\n  # Preparations:\n  local test_dir='test_dir'\n  local nested_dir=\"$test_dir/adding\"\n  local current_dir=\"$PWD\"\n\n  mkdir -p \"$nested_dir\"\n  cd \"$nested_dir\"\n\n  local test_file='test_file.auto_ignore'\n  touch \"$test_file\"\n  echo \"content\" > \"$test_file\"\n\n  # Test commands:\n  run git secret add -i \"$test_file\"\n  [ \"$status\" -eq 0 ]\n\n  [[ -f \"$current_dir/.gitignore\" ]]\n  run file_has_line \"$nested_dir/$test_file\" \"$current_dir/.gitignore\"\n  [ \"$output\" = '0' ]\n\n  # .gitignore was not created:\n  [[ ! -f \".gitignore\" ]]\n\n  # Cleaning up:\n  cd \"$current_dir\"\n  rm -r \"$test_dir\"\n}\n\n\n@test \"run 'add' for relative path\" {\n  if [[ \"$BATS_RUNNING_FROM_GIT\" -eq 1 ]]; then\n    skip \"this test is skipped while 'git commit'. See #334\"\n  fi\n\n  # Preparations:\n  local root='test_dir'\n  local node=\"$root/node\"\n  local sibling=\"$root/sibling\"\n  local test_file=\"$node/$TEST_DEFAULT_FILENAME\"\n  local current_dir=\"$PWD\"\n\n  mkdir -p \"$node\"\n  mkdir -p \"$sibling\"\n\n  echo \"content\" > \"$test_file\"\n\n  cd \"$sibling\"\n\n  # Testing:\n  run git secret add \"../node/$TEST_DEFAULT_FILENAME\"\n  [ \"$status\" -eq 0 ]\n  [[ \"$output\" == *\"git-secret: 1 item(s) added.\"* ]]\n\n  # Testing mappings content:\n  local path_mappings\n  path_mappings=$(_get_secrets_dir_paths_mapping)\n\n  local files_list\n  files_list=$(cat \"$path_mappings\")\n  [ \"$files_list\" = \"$test_file\" ]\n\n  # Cleaning up:\n  cd \"$current_dir\"\n  rm -r \"$root\"\n}\n\n\n@test \"run 'add' for file in subfolder\" {\n  if [[ \"$BATS_RUNNING_FROM_GIT\" -eq 1 ]]; then\n    # See #334 for more about this\n    skip \"this test is skipped while 'git commit'\"\n  fi\n\n  # Preparations:\n  local test_file=\"$TEST_DEFAULT_FILENAME\"\n  local test_dir='test_dir'\n\n  mkdir -p \"$test_dir\"\n  touch \"$test_dir/$test_file\"\n  echo \"content\" > \"$test_dir/$test_file\"\n\n  # Testing:\n  run git secret add \"$test_dir/$test_file\"\n  [ \"$status\" -eq 0 ]\n  [[ \"$output\" == *\"git-secret: 1 item(s) added.\"* ]]\n\n  # Cleaning up:\n  rm -r \"$test_dir\"\n}\n\n\n@test \"run 'add' twice for one file\" {\n  # Preparations:\n  local filename=\"$TEST_DEFAULT_FILENAME\"\n  echo \"content\" > \"$filename\"\n\n  # Testing:\n  run git secret add \"$filename\"\n  run git secret add \"$filename\"\n  [ \"$status\" -eq 0 ]\n  [[ \"$output\" = *\"git-secret: 0 item(s) added.\"* ]]\n\n  # Ensuring that path mappings was set correctly:\n  local path_mappings\n  path_mappings=$(_get_secrets_dir_paths_mapping)\n\n  local files_list\n  files_list=$(cat \"$path_mappings\")\n  [ \"$files_list\" = \"$filename\" ]\n\n  # Cleaning up:\n  rm \"$filename\" \".gitignore\"\n}\n\n\n@test \"run 'add' for multiple files, and test .gitignore contents\" {\n  # Preparations:\n  local filename1=\"$TEST_DEFAULT_FILENAME\"\n  echo \"content1\" > \"$filename1\"\n\n  local filename2=\"$TEST_SECOND_FILENAME\"\n  echo \"content2\" > \"$filename2\"\n\n  # Testing:\n  run git secret add \"$filename1\" \"$filename2\"\n  [ \"$status\" -eq 0 ]\n  [[ \"$output\" = *\"git-secret: 2 item(s) added.\"* ]]   # there may be additional lines too\n\n  # test .gitignore has 4 lines as expected\n  local gitignore_linecount\n  gitignore_linecount=$(wc -l < .gitignore)\n  [ \"$gitignore_linecount\" -eq 4 ]          # two added by `git secret init`, and one for each `added` file\n\n  # Cleaning up:\n  rm \"$filename1\" \"$filename2\" \".gitignore\"\n}\n\n@test \"run 'add -v' for multiple files\" {\n  # Preparations:\n  local filename1=\"$TEST_DEFAULT_FILENAME\"\n  echo \"content1\" > \"$filename1\"\n\n  local filename2=\"$TEST_SECOND_FILENAME\"\n  echo \"content2\" > \"$filename2\"\n\n  # Testing:\n  run git secret add -v \"$filename1\" \"$filename2\"\n\n  [ \"$status\" -eq 0 ]\n  [[ \"$output\" == *\"git-secret: adding file: ${TEST_DEFAULT_FILENAME}\"* ]]\n  [[ \"$output\" == *\"git-secret: adding file: ${TEST_SECOND_FILENAME}\"* ]]\n  [[ \"$output\" == *\"git-secret: 2 item(s) added.\"* ]]\n\n  # Cleaning up:\n  rm \"$filename1\" \"$filename2\" \".gitignore\"\n}\n\n@test \"run 'add' for file with special chars\" {\n  # Preparations:\n  local filename=\"$TEST_FOURTH_FILENAME\"\n  echo \"content\" > \"$filename\"\n\n  run git secret add \"$filename\"\n  [ \"$status\" -eq 0 ]\n\n  # Ensuring that path mappings was set correctly:\n  local path_mappings\n  path_mappings=$(_get_secrets_dir_paths_mapping)\n\n  local files_list\n  files_list=$(cat \"$path_mappings\")\n  [ \"$files_list\" = \"$filename\" ]\n\n  # Ensuring the file is correctly git-ignored\n  run git check-ignore \"$filename\"\n  [ \"$status\" -eq 0 ]\n\n  # Cleaning up:\n  rm \"$filename\" \".gitignore\"\n}\n"
  },
  {
    "path": "tests/test_cat.bats",
    "content": "#!/usr/bin/env bats\n# shellcheck disable=SC2030,SC2031\n# above is to avoid shellcheck info warnings that we don't understand\n\nload _test_base\n\nFILE_TO_HIDE=\"$TEST_DEFAULT_FILENAME\"\nFILE_CONTENTS=\"hidden content юникод\"\n\nFINGERPRINT=\"\"\n\n\nfunction setup {\n  FINGERPRINT=$(install_fixture_full_key \"$TEST_DEFAULT_USER\")\n\n  set_state_initial\n  set_state_git\n  set_state_secret_init\n  set_state_secret_tell \"$TEST_DEFAULT_USER\"\n  set_state_secret_add \"$FILE_TO_HIDE\" \"$FILE_CONTENTS\"\n  set_state_secret_hide\n}\n\n\nfunction teardown {\n  uninstall_fixture_full_key \"$TEST_DEFAULT_USER\" \"$FINGERPRINT\"\n  unset_current_state\n}\n\n\n@test \"run 'cat' with password argument\" {\n  local password\n  password=$(test_user_password \"$TEST_DEFAULT_USER\")\n  run git secret cat -d \"$TEST_GPG_HOMEDIR\" -p \"$password\" \"$FILE_TO_HIDE\"\n\n  [ \"$status\" -eq 0 ]\n\n  # $output is the output from 'git secret cat' above\n  [ \"$FILE_CONTENTS\" == \"$output\" ]\n}\n\n\n@test \"run 'cat' with password argument and SECRETS_VERBOSE=1\" {\n  local password\n  password=$(test_user_password \"$TEST_DEFAULT_USER\")\n  SECRETS_VERBOSE=1 run git secret cat -d \"$TEST_GPG_HOMEDIR\" -p \"$password\" \"$FILE_TO_HIDE\"\n\n  [ \"$status\" -eq 0 ]\n\n  # $output _contains_ the output from 'git secret cat',\n  # may have extra output from gpg\n  [[ \"$output\" == *\"$FILE_CONTENTS\"* ]]\n}\n\n\n@test \"run 'cat' with bad filename\" {\n  run git secret cat -d \"$TEST_GPG_HOMEDIR\" -p \"$password\" NO_SUCH_FILE\n  [ \"$status\" -eq 1 ]\n}\n\n\n@test \"run 'cat' with bad arg\" {\n  local password\n  password=$(test_user_password \"$TEST_DEFAULT_USER\")\n  run git secret cat -Z -d \"$TEST_GPG_HOMEDIR\" -p \"$password\" \"$FILE_TO_HIDE\"\n  [ \"$status\" -ne 0 ]\n}\n\n@test \"run 'cat' from subdir\" {\n  local password\n  password=$(test_user_password \"$TEST_DEFAULT_USER\")\n\n  mkdir subdir\n  echo \"content2\" > subdir/new_filename.txt\n\n  ( # start subshell for subdir tests\n    cd subdir\n    run git secret add new_filename.txt\n    [ \"$status\" -eq 0 ]\n    run git secret hide\n    [ \"$status\" -eq 0 ]\n\n    run git secret cat -d \"$TEST_GPG_HOMEDIR\" -p \"$password\" new_filename.txt\n    [ \"$status\" -eq 0 ]\n  ) # end subshell, cd back up\n\n  # clean up\n  rm -rf subdir\n}\n"
  },
  {
    "path": "tests/test_changes.bats",
    "content": "#!/usr/bin/env bats\n\nload _test_base\n\nFILE_TO_HIDE=\"$TEST_DEFAULT_FILENAME\"\nSECOND_FILE_TO_HIDE=\"$TEST_SECOND_FILENAME\"\nTHIRD_FILE_TO_HIDE=\"$TEST_THIRD_FILENAME\"\nFILE_NON_EXISTENT=\"NO-SUCH-FILE\"\nFILE_CONTENTS=\"hidden content юникод\"\n\nFINGERPRINT=\"\"\n\n\nfunction setup {\n  FINGERPRINT=$(install_fixture_full_key \"$TEST_DEFAULT_USER\")\n\n  set_state_initial\n  set_state_git\n  set_state_secret_init\n  set_state_secret_tell \"$TEST_DEFAULT_USER\"\n  set_state_secret_add \"$FILE_TO_HIDE\" \"$FILE_CONTENTS\"\n  set_state_secret_add \"$SECOND_FILE_TO_HIDE\" \"$FILE_CONTENTS\"\n  set_state_secret_hide\n}\n\n\nfunction teardown {\n  rm \"$FILE_TO_HIDE\" \"$SECOND_FILE_TO_HIDE\"\n\n  uninstall_fixture_full_key \"$TEST_DEFAULT_USER\" \"$FINGERPRINT\"\n  unset_current_state\n}\n\n\n@test \"run 'changes' on one file with no file changed\" {\n  local password\n  password=$(test_user_password \"$TEST_DEFAULT_USER\")\n\n  run git secret changes -d \"$TEST_GPG_HOMEDIR\" -p \"$password\" \"$FILE_TO_HIDE\"\n  [ \"$status\" -eq 0 ]\n\n  local num_lines\n  num_lines=$(echo \"$output\" | wc -l)\n  [[ \"$num_lines\" -eq 1 ]]\n}\n\n\n@test \"run 'changes' with one file changed\" {\n  local new_content='new content'\n  echo \"$new_content\" >> \"$FILE_TO_HIDE\"\n\n  local password\n  password=$(test_user_password \"$TEST_DEFAULT_USER\")\n\n  run git secret changes -d \"$TEST_GPG_HOMEDIR\" -p \"$password\" \"$FILE_TO_HIDE\"\n  [ \"$status\" -eq 0 ]\n\n  # Testing that output has both filename and changes:\n  local fullpath\n  fullpath=$(_prepend_root_path \"$FILE_TO_HIDE\")\n  [[ \"$output\" == *\"changes in $fullpath\"* ]]\n  [[ \"$output\" == *\"hidden content юникод\"* ]]\n  [[ \"$output\" == *\"+$new_content\"* ]]\n\n  local num_lines\n  num_lines=$(echo \"$output\" | wc -l)\n  [[ \"$num_lines\" -eq 6 ]]\n\n}\n\n\n@test \"run 'changes' with source file missing\" {\n  local password\n  password=$(test_user_password \"$TEST_DEFAULT_USER\")\n  rm \"$FILE_TO_HIDE\" || _abort \"error removing: $FILE_TO_HIDE\"\n\n  run git secret changes -d \"$TEST_GPG_HOMEDIR\" -p \"$password\" \"$FILE_TO_HIDE\"\n  [ \"$status\" -ne 0 ]\n}\n\n\n@test \"run 'changes' with hidden file missing\" {\n  local password\n  local encrypted_file\n  password=$(test_user_password \"$TEST_DEFAULT_USER\")\n  encrypted_file=$(_get_encrypted_filename \"$FILE_TO_HIDE\")\n  rm \"$encrypted_file\" || _abort \"error removing: $encrypted_file\"\n\n  run git secret changes -d \"$TEST_GPG_HOMEDIR\" -p \"$password\" \"$FILE_TO_HIDE\"\n  [ \"$status\" -ne 0 ]\n}\n\n\n@test \"run 'changes' with one file changed (with deletions)\" {\n  local new_content='replace'\n  local password\n  password=$(test_user_password \"$TEST_DEFAULT_USER\")\n  echo \"$new_content\" > \"$FILE_TO_HIDE\"\n\n  run git secret changes -d \"$TEST_GPG_HOMEDIR\" -p \"$password\" \"$FILE_TO_HIDE\"\n  [ \"$status\" -eq 0 ]\n\n  # Testing that output has both filename and changes:\n  local fullpath\n  fullpath=$(_prepend_root_path \"$FILE_TO_HIDE\")\n  [[ \"$output\" == *\"changes in $fullpath\"* ]]\n  [[ \"$output\" == *\"-$FILE_CONTENTS\"* ]]\n  [[ \"$output\" == *\"+$new_content\"* ]]\n}\n\n\n@test \"run 'changes' on two files with no file changed\" {\n  local password\n  password=$(test_user_password \"$TEST_DEFAULT_USER\")\n\n  run git secret changes -d \"$TEST_GPG_HOMEDIR\" -p \"$password\"\n\n\n  [ \"$status\" -eq 0 ]\n\n  local num_lines\n  num_lines=$(echo \"$output\" | wc -l)\n  [[ \"$num_lines\" -eq 2 ]]\n}\n\n\n@test \"run 'changes' with multiple files changed\" {\n  local new_content='new content'\n  local second_new_content='something different'\n  local password\n  password=$(test_user_password \"$TEST_DEFAULT_USER\")\n  echo \"$new_content\" >> \"$FILE_TO_HIDE\"\n  echo \"$second_new_content\" >> \"$SECOND_FILE_TO_HIDE\"\n\n  run git secret changes -d \"$TEST_GPG_HOMEDIR\" -p \"$password\"\n  [ \"$status\" -eq 0 ]\n\n  # Testing that output has both filename and changes:\n  local fullpath\n  fullpath=$(_prepend_root_path \"$FILE_TO_HIDE\")\n\n  [[ \"$output\" == *\"changes in $fullpath\"* ]]\n  [[ \"$output\" == *\"+$new_content\"* ]]\n\n  local second_path\n  second_path=$(_prepend_root_path \"$SECOND_FILE_TO_HIDE\")\n  [[ \"$output\" == *\"changes in $second_path\"* ]]\n  [[ \"$output\" == *\"+$second_new_content\"* ]]\n}\n\n\n@test \"run 'changes' with multiple selected files changed\" {\n  local new_content='new content'\n  local second_new_content='something different'\n  echo \"$new_content\" >> \"$FILE_TO_HIDE\"\n  echo \"$second_new_content\" >> \"$SECOND_FILE_TO_HIDE\"\n\n  local password\n  password=$(test_user_password \"$TEST_DEFAULT_USER\")\n\n  run git secret changes -d \"$TEST_GPG_HOMEDIR\" -p \"$password\" \\\n    \"$FILE_TO_HIDE\" \"$SECOND_FILE_TO_HIDE\"\n\n  [ \"$status\" -eq 0 ]\n\n  # Testing that output has both filename and changes:\n  local fullpath\n  fullpath=$(_prepend_root_path \"$FILE_TO_HIDE\")\n  [[ \"$output\" == *\"changes in $fullpath\"* ]]\n  [[ \"$output\" == *\"+$new_content\"* ]]\n\n  local second_path\n  second_path=$(_prepend_root_path \"$SECOND_FILE_TO_HIDE\")\n  [[ \"$output\" == *\"changes in $second_path\"* ]]\n  [[ \"$output\" == *\"+$second_new_content\"* ]]\n}\n\n\n@test \"run 'changes' on file that does not exist\" {\n  local password\n  password=$(test_user_password \"$TEST_DEFAULT_USER\")\n\n  run git secret changes \\\n    -d \"$TEST_GPG_HOMEDIR\" \\\n    -p \"$password\" \\\n    \"$FILE_NON_EXISTENT\"\n\n  [ \"$status\" -ne 0 ]\n}\n\n\n@test \"run 'changes' on one file without newlines\" {\n  set_state_secret_add_without_newline \"$THIRD_FILE_TO_HIDE\" \"$FILE_CONTENTS\"\n  set_state_secret_hide\n\n  local password\n  password=$(test_user_password \"$TEST_DEFAULT_USER\")\n\n  run git secret changes \\\n    -d \"$TEST_GPG_HOMEDIR\" \\\n    -p \"$password\" \\\n    \"$THIRD_FILE_TO_HIDE\"\n  [ \"$status\" -eq 0 ]\n\n  local num_lines\n  num_lines=$(echo \"$output\" | wc -l)\n  [[ \"$num_lines\" -eq 1 ]]\n\n  rm -f \"$THIRD_FILE_TO_HIDE\"\n}\n\n@test \"run 'changes' with bad arg\" {\n  run git secret changes -Z\n  [ \"$status\" -ne 0 ]\n}\n\n"
  },
  {
    "path": "tests/test_clean.bats",
    "content": "#!/usr/bin/env bats\n\nload _test_base\n\nFIRST_FILE=\"$TEST_DEFAULT_FILENAME\"\nSECOND_FILE=\"$TEST_SECOND_FILENAME\"\n\n\nfunction setup {\n  install_fixture_key \"$TEST_DEFAULT_USER\"\n\n  set_state_initial\n  set_state_git\n  set_state_secret_init\n  set_state_secret_tell \"$TEST_DEFAULT_USER\"\n  set_state_secret_add \"$FIRST_FILE\" \"somecontent\"\n  set_state_secret_add \"$SECOND_FILE\" \"somecontent2\"\n  set_state_secret_hide\n}\n\n\nfunction teardown {\n  # This also needs to be cleaned:\n  rm \"$FIRST_FILE\" \"$SECOND_FILE\"\n\n  uninstall_fixture_key \"$TEST_DEFAULT_USER\"\n  unset_current_state\n}\n\n\nfunction _secret_files_exists {\n  echo \"$(find . -type f -name \"*.$SECRETS_EXTENSION\" \\\n    -print0 2>/dev/null | grep -q .; echo \"$?\")\"\n}\n\n\n@test \"run 'clean' normally\" {\n  run git secret clean\n  [ \"$status\" -eq 0 ]\n\n  # There must be no .secret files:\n  [ \"$(_secret_files_exists)\" -ne 0 ]\n}\n\n\n@test \"run 'clean' with extra filename\" {\n  run git secret clean extra_filename\n  [ \"$status\" -ne 0 ]\n}\n\n\n@test \"run 'clean' with bad arg\" {\n  run git secret clean -Z\n  [ \"$status\" -ne 0 ]\n}\n\n\n@test \"run 'clean' with '-v'\" {\n  run git secret clean -v\n  [ \"$status\" -eq 0 ]\n\n  # There must be no .secret files:\n  [ \"$(_secret_files_exists)\" -ne 0 ]\n\n  local first_filename\n  local second_filename\n  first_filename=$(_get_encrypted_filename \"$FIRST_FILE\")\n  second_filename=$(_get_encrypted_filename \"$SECOND_FILE\")\n\n  # Output must be verbose:\n  [[ \"$output\" == *\"deleted\"* ]]\n  [[ \"$output\" == *\"$first_filename\"* ]]\n  [[ \"$output\" == *\"$second_filename\"* ]]\n}\n\n# this test is like above, but uses SECRETS_VERBOSE env var\n@test \"run 'clean' with 'SECRETS_VERBOSE=1'\" {\n  SECRETS_VERBOSE=1 run git secret clean\n  [ \"$status\" -eq 0 ]\n\n  # Output must be verbose:\n  [[ \"$output\" == *\"deleted:\"* ]]\n}\n\n# this test is like above, but sets SECRETS_VERBOSE env var to 0\n# and expected non-verbose output\n@test \"run 'clean' with 'SECRETS_VERBOSE=0'\" {\n  SECRETS_VERBOSE=0 run git secret clean\n  [ \"$status\" -eq 0 ]\n\n  # Output must not be verbose:\n  [[ \"$output\" != *\"cleaning\"* ]]\n}\n"
  },
  {
    "path": "tests/test_expiration.bats",
    "content": "#!/usr/bin/env bats\n\nexport TZ=\"GMT\"\n\nload _test_base\n\n\nfunction setup {\n  install_fixture_key \"$TEST_EXPIRED_USER\"\n\n  set_state_initial\n  set_state_git\n  set_state_secret_init\n  set_state_secret_tell \"$TEST_EXPIRED_USER\"\n}\n\n\nfunction teardown {\n  uninstall_fixture_key \"$TEST_EXPIRED_USER\"\n  unset_current_state\n}\n\n\n@test \"run 'hide' using expired key\" {\n  FILE_TO_HIDE=\"$TEST_DEFAULT_FILENAME\"\n  FILE_CONTENTS=\"hidden content юникод\"\n  set_state_secret_add \"$FILE_TO_HIDE\" \"$FILE_CONTENTS\"\n\n  run git secret hide\n  # this will fail, because we're using an expired key\n\n  # echo \"$output\" | sed \"s/^/# '$BATS_TEST_DESCRIPTION' output: /\" >&3\n    # output will look like:\n    # 'abort: problem encrypting file with gpg: exit code 2: space file'\n  # echo \"# status of hide: $status\" >&3\n\n  [ $status -ne 0 ] # we expect failure here. Actual code is 2\n}\n\n\n@test \"run 'whoknows' using expired key\" {\n  run git secret whoknows\n  [ $status -eq 0 ]\n}\n\n@test \"run 'whoknows -l' on only expired user\" {\n  run git secret whoknows -l\n  [ \"$status\" -eq 0 ]\n\n  # diag output for bats-core\n  # echo \"$output\" | sed \"s/^/# '$BATS_TEST_DESCRIPTION' output: /\" >&3\n  # output should look like 'abort: problem encrypting file with gpg: exit code 2: space file'\n\n  # echo \"# $BATS_TEST_DESCRIPTION: $status\" >&3\n\n  # Now test the output, both users should be present:\n  [[ \"$output\" == *\"$TEST_EXPIRED_USER (expires: 2018-09-23)\"* ]]\n}\n\n\n@test \"run 'whoknows -l' on normal key and expired key\" {\n  install_fixture_key \"$TEST_DEFAULT_USER\"\n  set_state_secret_tell \"$TEST_DEFAULT_USER\"\n\n  run git secret whoknows -l\n  [ \"$status\" -eq 0 ]\n\n  #echo \"$output\" | sed \"s/^/# '$BATS_TEST_DESCRIPTION' output: /\" >&3\n\n  # Now test the output, both users should be present:\n  [[ \"$output\" == *\"$TEST_DEFAULT_USER (expires: never)\"* ]]\n  [[ \"$output\" == *\"$TEST_EXPIRED_USER (expires: 2018-09-23)\"* ]]\n\n  uninstall_fixture_key \"$TEST_DEFAULT_USER\"\n}\n"
  },
  {
    "path": "tests/test_hide.bats",
    "content": "#!/usr/bin/env bats\n\nload _test_base\n\nFILE_TO_HIDE=\"$TEST_DEFAULT_FILENAME\"\nFILE_CONTENTS=\"hidden content юникод\"\n\n\nfunction setup {\n  install_fixture_key \"$TEST_DEFAULT_USER\"\n\n  set_state_initial\n  set_state_git\n  set_state_secret_init\n  set_state_secret_tell \"$TEST_DEFAULT_USER\"\n  set_state_secret_add \"$FILE_TO_HIDE\" \"$FILE_CONTENTS\"\n}\n\n\nfunction teardown {\n  rm \"$FILE_TO_HIDE\"\n\n  uninstall_fixture_key \"$TEST_DEFAULT_USER\"\n  unset_current_state\n}\n\n\n@test \"run 'hide' normally\" {\n  run git secret hide\n\n  # echo \"$output\" | sed \"s/^/# '$BATS_TEST_DESCRIPTION' output: /\" >&3\n\n  # Command must execute normally:\n  [ \"$status\" -eq 0 ]\n  [[ \"$output\" == *\"git-secret: done. 1 of 1 files are hidden.\"* ]]\n\n  # New file must be created:\n  local new_file\n  new_file=\"$(_get_encrypted_filename \"$FILE_TO_HIDE\")\"\n  [ -f \"$new_file\" ]\n\n  # File must be a binary:\n  local mime\n  mime=\"$(file --mime-type --mime-encoding \"$new_file\" | grep 'charset=binary')\"\n  [ -n \"$mime\" ]\n}\n\n\n@test \"run 'hide' with SECRETS_GPG_ARMOR=1\" {\n  SECRETS_GPG_ARMOR=1 run git secret hide\n\n  # Command must execute normally:\n  [ \"$status\" -eq 0 ]\n  [[ \"$output\" == *\"git-secret: done. 1 of 1 files are hidden.\"* ]]\n\n  # New file must be created:\n  local new_file\n  new_file=\"$(_get_encrypted_filename \"$FILE_TO_HIDE\")\"\n  [ -f \"$new_file\" ]\n\n  # File must be a text:\n  local mime\n  mime=\"$(file --mime-type --mime-encoding \"$new_file\" | grep 'charset=us-ascii')\"\n  [ -n \"$mime\" ]\n}\n\n\n@test \"run 'hide' with extra filename\" {\n  run git secret hide extra_filename\n  [ \"$status\" -ne 0 ]\n}\n\n\n@test \"run 'hide' with bad arg\" {\n  run git secret hide -Z\n  [ \"$status\" -ne 0 ]\n}\n\n\n@test \"run 'hide' normally with SECRETS_VERBOSE=1\" {\n  SECRETS_VERBOSE=1 run git secret hide\n\n  # Command must execute normally.\n  [ \"$status\" -eq 0 ]\n  [[ \"$output\" == *\"git-secret: done. 1 of 1 files are hidden.\"* ]]\n}\n\n\n@test \"run 'hide' with '-P'\" {\n  # attempt to alter permissions on input file\n  chmod o-rwx \"$FILE_TO_HIDE\"\n\n  run git secret hide -P\n\n  # echo \"$output\" | sed \"s/^/# '$BATS_TEST_DESCRIPTION' output: /\" >&3\n\n  # Command must execute normally:\n  [ \"$status\" -eq 0 ]\n  [[ \"$output\" == *\"git-secret: done. 1 of 1 files are hidden.\"* ]]\n\n  # New files should be created:\n  local encrypted_file\n  encrypted_file=$(_get_encrypted_filename \"$FILE_TO_HIDE\")\n  [ -f \"$encrypted_file\" ]\n\n  ## permissions should match.\n  local secret_perm\n  local file_perm\n  file_perm=$($SECRETS_OCTAL_PERMS_COMMAND \"$FILE_TO_HIDE\")\n  secret_perm=$($SECRETS_OCTAL_PERMS_COMMAND \"$encrypted_file\")\n  # echo \"# '$BATS_TEST_DESCRIPTION': $secret_perm, file_perm: $file_perm\" >&3\n  [ \"$secret_perm\" = \"$file_perm\" ]\n}\n\n\n@test \"run 'hide' from inside subdirectory\" {\n  if [[ \"$BATS_RUNNING_FROM_GIT\" -eq 1 ]]; then\n    # See #334 for more about this\n    skip \"this test is skipped while 'git commit'\"\n  fi\n\n  # Preparations:\n  local root_dir='test_sub_dir'\n  mkdir -p \"$root_dir\"\n  local second_file=\"$root_dir/second_file.txt\"\n  local second_content=\"some content\"\n  set_state_secret_add \"$second_file\" \"$second_content\"\n\n  # Verify that the second file is there:\n  [ -f \"$second_file\" ]\n\n  ( # start subshell for following commands\n\n    # cd into the subdir\n    cd \"$root_dir\"\n\n    # Now it should hide 2 files:\n    run git secret hide\n    [ \"$status\" -eq 0 ]\n  ) # end subshell, return to ..\n\n  # clean up\n  rm -rf \"$root_dir\"\n}\n\n\n@test \"run 'hide' with missing file\" {\n  # Preparations:\n  local second_file=\"$TEST_SECOND_FILENAME\"\n  local second_content=\"some content\"\n  set_state_secret_add \"$second_file\" \"$second_content\"\n\n  # now remove the second file to cause failure\n  rm -f \"$second_file\"\n\n  # Now it should return an error because one file can't be found\n  run git secret hide\n  [ \"$status\" -ne 0 ]\n  [ \"$output\" != \"git-secret: done. 2 of 2 files are hidden.\" ]\n}\n\n\n@test \"run 'hide' with multiple files\" {\n  # Preparations:\n  local second_file=\"$TEST_SECOND_FILENAME\"\n  local second_content=\"some content\"\n  set_state_secret_add \"$second_file\" \"$second_content\"\n\n  # Now it should hide 2 files:\n  run git secret hide\n  #echo \"$output\" | sed \"s/^/# '$BATS_TEST_DESCRIPTION' output: /\" >&3\n  [ \"$status\" -eq 0 ]\n  [[ \"$output\" == *\"git-secret: done. 2 of 2 files are hidden.\"* ]]\n\n  # Cleaning up:\n  rm \"$second_file\"\n}\n\n\n@test \"run 'hide' with '-m'\" {\n  run git secret hide -m\n\n  # Command must execute normally:\n  [ \"$status\" -eq 0 ]\n  # git secret hide -m: uses temp file so cleaning should take place,\n  # but we only show tmp file cleanup in VERBOSE mode\n  [[ \"$output\" == *\"git-secret: done. 1 of 1 files are hidden.\"* ]]\n\n  # New files should be created:\n  [ -f \"$(_get_encrypted_filename \"$FILE_TO_HIDE\")\" ]\n}\n\n\n@test \"run 'hide' with '-m' twice\" {\n  local path_mappings\n  path_mappings=$(_get_secrets_dir_paths_mapping)\n  run git secret hide -m\n\n  # echo \"$output\" | sed \"s/^/# '$BATS_TEST_DESCRIPTION' output: /\" >&3\n\n  # Command must execute normally:\n  [ \"$status\" -eq 0 ]\n  # git secret hide -m: uses temp file so cleaning should take place,\n  # but we only show tmp file cleanup in VERBOSE mode\n  [[ \"$output\" == *\"git-secret: done. 1 of 1 files are hidden.\"* ]]\n\n  # back path mappings\n  cp \"${path_mappings}\" \"${path_mappings}.bak\"\n  # run hide again\n  run git secret hide -m\n  # compare\n  [ \"$status\" -eq 0 ]\n  [[ \"${#lines[@]}\" -eq 1 ]]\n\n  # output says 0 of 1 files are hidden because checksum didn't change\n  # and we didn't need to hide it again.\n  [[ \"$output\" == *\"git-secret: done. 0 of 1 files are hidden.\"* ]]\n  # no changes should occur to path_mappings files\n  cmp -s \"${path_mappings}\" \"${path_mappings}.bak\"\n\n  # New files should be created:\n  [ -f \"$(_get_encrypted_filename \"$FILE_TO_HIDE\")\" ]\n}\n\n\n@test \"run 'hide' without then with '-m'\" {\n  local path_mappings\n  path_mappings=$(_get_secrets_dir_paths_mapping)\n  run git secret hide\n\n  #echo \"$output\" | sed \"s/^/# '$BATS_TEST_DESCRIPTION' output: /\" >&3\n\n  # Command must execute normally:\n  [ \"$status\" -eq 0 ]\n  # git secret hide -m: uses temp file so cleaning should take place,\n  # but we only show tmp file cleanup in VERBOSE mode\n  [[ \"$output\" == *\"git-secret: done. 1 of 1 files are hidden.\"* ]]\n\n  # back path mappings\n  cp \"${path_mappings}\" \"${path_mappings}.bak\"\n  # run hide again\n  run git secret hide -m\n  # compare\n  [ \"$status\" -eq 0 ]\n  [[ \"${#lines[@]}\" -eq 1 ]]\n\n  # output says 0 of 1 files are hidden because checksum didn't change\n  # and we didn't need to hide it again.\n  [[ \"$output\" == *\"git-secret: done. 0 of 1 files are hidden.\"* ]]\n  # no changes should occur to path_mappings files\n  cmp -s \"${path_mappings}\" \"${path_mappings}.bak\"\n\n  # New files should be created:\n  [ -f \"$(_get_encrypted_filename \"$FILE_TO_HIDE\")\" ]\n}\n\n\n@test \"run 'hide' with '-c' and '-v'\" {\n  # Preparations:\n  local encrypted_filename\n  encrypted_filename=$(_get_encrypted_filename \"$FILE_TO_HIDE\")\n  set_state_secret_hide # so it would be data to clean\n\n  run git secret hide -v -c\n  [ \"$status\" -eq 0 ]\n\n  # File should be still there (it is not deletion):\n  [ -f \"$FILE_TO_HIDE\" ]\n\n  # Output should be verbose:\n  [[ \"$output\" == *\"deleted:\"* ]]\n  [[ \"$output\" == *\"$encrypted_filename\"* ]]\n}\n\n\n@test \"run 'hide' with '-d'\" {\n  run git secret hide -d\n  [ \"$status\" -eq 0 ]\n\n  # File must be removed:\n  [ ! -f \"$FILE_TO_HIDE\" ]\n}\n\n\n@test \"run 'hide' with '-d' and '-v'\" {\n  run git secret hide -v -d\n  [ \"$status\" -eq 0 ]\n\n  # File must be removed:\n  [ ! -f \"$FILE_TO_HIDE\" ]\n\n  # It should be verbose:\n  [[ \"$output\" == *\"removing unencrypted files\"* ]]\n  [[ \"$output\" == *\"$FILE_TO_HIDE\"* ]]\n}\n\n\n@test \"run 'hide' with '-d' and '-v' and files in subdirectories\" {\n  # Preparations:\n  local root_dir='test_sub_dir'\n  mkdir -p \"$root_dir\"\n  local second_file=\"$root_dir/$TEST_SECOND_FILENAME\"\n  local second_content=\"some content\"\n  set_state_secret_add \"$second_file\" \"$second_content\"\n\n  # Verify that the second file is there:\n  [ -f \"$second_file\" ]\n\n  # Now it should hide 2 files:\n  run git secret hide -v -d\n  [ \"$status\" -eq 0 ]\n\n  # File must be removed:\n  [ ! -f \"$FILE_TO_HIDE\" ]\n  [ ! -f \"$second_file\" ]\n\n  # It should be verbose:\n  [[ \"$output\" == *\"removing unencrypted files\"* ]]\n  [[ \"$output\" == *\"$FILE_TO_HIDE\"* ]]\n  [[ \"$output\" == *\"$second_file\"* ]]\n\n  rm -rf \"$root_dir\"\n}\n\n\n@test \"run 'hide' with multiple users\" {\n  install_fixture_key \"$TEST_SECOND_USER\"\n  set_state_secret_tell \"$TEST_SECOND_USER\"\n\n  run git secret hide\n  [ \"$status\" -eq 0 ]\n  [[ \"$output\" == *\"git-secret: done. 1 of 1 files are hidden.\"* ]]\n}\n"
  },
  {
    "path": "tests/test_hide_continue.bats",
    "content": "#!/usr/bin/env bats\n\nload _test_base\n\nFILE_TO_HIDE=\"$TEST_DEFAULT_FILENAME\"\nFILE_TO_HIDE2=\"$TEST_SECOND_FILENAME\"\nFILE_CONTENTS=\"hidden content юникод\"\n\n\nfunction setup {\n  install_fixture_key \"$TEST_DEFAULT_USER\"\n\n  set_state_initial\n  set_state_git\n  set_state_secret_init\n  set_state_secret_tell \"$TEST_DEFAULT_USER\"\n  set_state_secret_add \"$FILE_TO_HIDE\" \"$FILE_CONTENTS\"\n  set_state_secret_add \"$FILE_TO_HIDE2\" \"$FILE_CONTENTS\"\n}\n\n\nfunction teardown {\n  rm \"$FILE_TO_HIDE\"\n  rm \"$FILE_TO_HIDE2\"\n\n  uninstall_fixture_key \"$TEST_DEFAULT_USER\"\n  unset_current_state\n}\n\n\n@test \"run 'hide -F' with missing input file\" {\n  mv \"$FILE_TO_HIDE\" \"$FILE_TO_HIDE.was\"  # move the first file out of the way\n  run git secret hide -F\n\n  #echo \"# output of 'git secret hide -F' is: $output\" >&3\n\n  # Command must execute normally:\n  [ \"$status\" -eq 0 ]\n\n  # secret file for missing file should not be created:\n  local encrypted_file\n  encrypted_file=$(_get_encrypted_filename \"$FILE_TO_HIDE\")\n  [ ! -f \"$encrypted_file\" ]\n\n  # this secret file should be created:\n  local encrypted_file2\n  encrypted_file2=$(_get_encrypted_filename \"$FILE_TO_HIDE2\")\n  [ -f \"$encrypted_file2\" ]\n\n  # put back first file so teardown() succeeds\n  mv \"$FILE_TO_HIDE.was\" \"$FILE_TO_HIDE\"\n}\n"
  },
  {
    "path": "tests/test_init.bats",
    "content": "#!/usr/bin/env bats\n\nload _test_base\n\n\nfunction setup {\n  set_state_initial\n  set_state_git\n}\n\n\nfunction teardown {\n  unset_current_state\n}\n\n\n@test \"secrets dir env var set as expected\" {\n  _TEST_SECRETS_DIR=${SECRETS_DIR:-\".gitsecret\"}\n  [ \"${_TEST_SECRETS_DIR}\" = \"${_SECRETS_DIR}\" ]\n}\n\n\n@test \"run 'init' without '.git'\" {\n  remove_git_repository\n\n  run git secret init\n  [ \"$status\" -eq 1 ]\n}\n\n\n@test \"run 'init' normally\" {\n  run git secret init\n  [ \"$status\" -eq 0 ]\n\n  [[ -d \"${_SECRETS_DIR}\" ]]\n}\n\n\n@test \"run 'init' with extra filename\" {\n  run git secret init extra_filename\n  [ \"$status\" -ne 0 ]\n}\n\n\n@test \"run 'init' with bad arg\" {\n  run git secret init -Z\n  [ \"$status\" -ne 0 ]\n}\n\n\n@test \"run 'init' in subfolder\" {\n  # This test covers this issue:\n  # https://github.com/sobolevn/git-secret/issues/83\n\n  if [[ \"$BATS_RUNNING_FROM_GIT\" -eq 1 ]]; then\n    skip \"this test is skipped while 'git commit'. See #334\"\n  fi\n\n  # Preparations\n  local test_dir='test_dir'\n  local nested_dir=\"$test_dir/nested/dirs\"\n  local current_dir=\"$PWD\"\n\n  mkdir -p \"$nested_dir\"\n  cd \"$nested_dir\"\n\n  # Test:\n  run git secret init\n  [ \"$status\" -eq 0 ]\n\n  # It should not be created in the current folder:\n  [[ ! -d \"${_SECRETS_DIR}\" ]]\n\n  # It should be created here:\n  local secrets_dir\n  secrets_dir=$(_get_secrets_dir)\n  [[ -d \"$secrets_dir\" ]]\n\n  # Cleaning up:\n  cd \"$current_dir\"\n  rm -r \"$test_dir\"\n}\n\n\n@test \"run 'init' in directory with spaces in parent path\" {\n  # This test covers this issue:\n  # https://github.com/sobolevn/git-secret/issues/135\n\n  if [[ \"$BATS_RUNNING_FROM_GIT\" -eq 1 ]]; then\n    skip \"this test is skipped while 'git commit'. See #334\"\n  fi\n\n  local test_dir=\"$BATS_TMPDIR/path with spaces\"\n  local current_dir=\"$PWD\"\n\n  mkdir -p \"$test_dir\"\n  cd \"$test_dir\"\n\n  local has_initial_branch_option\n  has_initial_branch_option=$(is_git_version_ge_2_28_0)\n  if [[ \"$has_initial_branch_option\" == 0 ]]; then\n    git init --initial-branch=main >> \"$TEST_OUTPUT_FILE\" 2>&1\n  else\n    git init >> \"$TEST_OUTPUT_FILE\" 2>&1\n  fi\n\n  run git secret init\n  [ \"$status\" -eq 0 ]\n\n  local secrets_dir\n  secrets_dir=$(_get_secrets_dir)\n  [[ -d \"$secrets_dir\" ]]\n\n  # Cleaning up:\n  cd \"$current_dir\"\n  rm -rf \"$test_dir\"\n}\n\n\n@test \"run 'init' with '.gitsecret' already initialized\" {\n  local secrets_dir\n  secrets_dir=$(_get_secrets_dir)\n\n  mkdir \"$secrets_dir\"\n\n  run git secret init\n  [ \"$output\" = \"git-secret: abort: already initialized.\" ]\n  [ \"$status\" -eq 1 ]\n}\n"
  },
  {
    "path": "tests/test_list.bats",
    "content": "#!/usr/bin/env bats\n\nload _test_base\n\nFILE_TO_HIDE=\"file_to_hide\"\nFILE_CONTENTS=\"hidden content юникод\"\n\n\nfunction setup {\n  install_fixture_key \"$TEST_DEFAULT_USER\"\n\n  set_state_initial\n  set_state_git\n  set_state_secret_init\n  set_state_secret_tell \"$TEST_DEFAULT_USER\"\n  set_state_secret_add \"$FILE_TO_HIDE\" \"$FILE_CONTENTS\"\n}\n\n\nfunction teardown {\n  rm \"$FILE_TO_HIDE\"\n\n  uninstall_fixture_key \"$TEST_DEFAULT_USER\"\n  unset_current_state\n}\n\n\n@test \"run 'list' normally\" {\n  run git secret list\n  [ \"$status\" -eq 0 ]\n  [ \"$output\" = \"$FILE_TO_HIDE\" ]\n}\n\n\n@test \"run 'list' with extra filename\" {\n  run git secret list extra_filename\n  [ \"$status\" -ne 0 ]\n}\n\n\n@test \"run 'list' with bad arg\" {\n  run git secret list -Z\n  [ \"$status\" -ne 0 ]\n}\n\n\n@test \"run 'list' with multiple files\" {\n  # Preparations:\n  local second_file=\"second_file.txt\"\n  set_state_secret_add \"$second_file\" \"$FILE_CONTENTS\"\n\n  run git secret list\n  [ \"$status\" -eq 0 ]\n\n  # Now it should list two files:\n  [[ \"$output\" == *\"$FILE_TO_HIDE\"* ]]\n  [[ \"$output\" == *\"$second_file\"* ]]\n\n  # Cleaning up:\n  rm \"$second_file\"\n}\n\n\n@test \"run 'list' on empty repo\" {\n  git secret remove \"$FILE_TO_HIDE\"\n\n  # Running `list` on empty mapping should result an error:\n  run git secret list\n  [ \"$status\" -eq 1 ]\n}\n"
  },
  {
    "path": "tests/test_main.bats",
    "content": "#!/usr/bin/env bats\n\nload _test_base\n\n\nfunction setup {\n  set_state_initial\n  set_state_git\n}\n\n\nfunction teardown {\n  unset_current_state\n}\n\n\n@test \"run 'git secret' without command\" {\n  run git secret\n  [ \"$status\" -eq 126 ]\n}\n\n\n@test \"run 'git secret' with bad command\" {\n  run git secret notacommand\n  [ \"$status\" -eq 126 ]\n}\n\n\n@test \"run 'git secret --version'\" {\n  run git secret --version\n  [ \"$output\" == \"$GITSECRET_VERSION\" ]\n}\n\n\n@test \"run 'git secret --dry-run'\" {\n  # We will break things apart, so normally it won't run:\n  rm -r \"./.git\"\n\n  # test of 'git secret usage' here removed as it's duplicated in test_usage.bats\n\n  # Dry run won't fail:\n  run git secret --dry-run\n  [ \"$status\" -eq 0 ]\n}\n"
  },
  {
    "path": "tests/test_make_install.bats",
    "content": "#!/usr/bin/env bats\n\n: \"${TMPDIR:=/tmp}\"\n\nINSTALL_BASE=\"${TMPDIR}/git-secret-test-install\"\n\n\n@test \"install git-secret to DESTDIR='$INSTALL_BASE'\" {\n  rm -f \"$INSTALL_BASE/usr/bin/git-secret\"\n  cd \"$SECRETS_PROJECT_ROOT\"\n\n  # set DESTDIR for this command and 'run' make install\n  DESTDIR=\"$INSTALL_BASE\" run make install\n\n  [ -x \"$INSTALL_BASE/usr/bin/git-secret\" ]\n  rm -rf \"$INSTALL_BASE\"\n}\n"
  },
  {
    "path": "tests/test_noname.bats",
    "content": "#!/usr/bin/env bats\n\n# These tests using TEST_NONAME_USER, which has a email but no username.\n# This was originally based on test_remove.bats\n\nload _test_base\n\nFIRST_FILE=\"$TEST_DEFAULT_FILENAME\"\nSECOND_FILE=\"$TEST_SECOND_FILENAME\"\n\nfunction setup {\n  install_fixture_key \"$TEST_NONAME_USER\"\n\n  set_state_initial\n  set_state_git\n  set_state_secret_init\n  set_state_secret_tell \"$TEST_NONAME_USER\"\n  set_state_secret_add \"$FIRST_FILE\" \"somecontent\"\n  set_state_secret_add \"$SECOND_FILE\" \"somecontent2\"\n  set_state_secret_hide\n}\n\n\nfunction teardown {\n  rm \"$FIRST_FILE\" \"$SECOND_FILE\"\n\n  uninstall_fixture_key \"$TEST_NONAME_USER\"\n  unset_current_state\n}\n\n\nfunction _has_line {\n  local line=\"$1\"\n\n  local path_mappings\n  path_mappings=$(_get_secrets_dir_paths_mapping)\n  echo \"$(grep -q \"$line\" \"$path_mappings\"; echo $?)\"\n}\n\n\n@test \"run 'remove' for nameless user normally\" {\n  run git secret remove \"$SECOND_FILE\"\n  [ \"$status\" -eq 0 ]\n\n  # Test output:\n  [[ \"$output\" == *\"removed from index.\"* ]]\n  [[ \"$output\" == *\"ensure that files: [$SECOND_FILE] are now not ignored.\"* ]]\n\n  # Mapping should not contain the second file:\n  [ \"$(_has_line \"$SECOND_FILE\")\" -eq 1 ]\n\n  # But the first file must not change:\n  [ \"$(_has_line \"$FIRST_FILE\")\" -eq 0 ]\n\n  # Both files should be present:\n  [ -f \"$(_get_encrypted_filename \"$FIRST_FILE\")\" ]\n  [ -f \"$(_get_encrypted_filename \"$SECOND_FILE\")\" ]\n}\n"
  },
  {
    "path": "tests/test_remove.bats",
    "content": "#!/usr/bin/env bats\n\nload _test_base\n\nFIRST_FILE=\"$TEST_DEFAULT_FILENAME\"\nSECOND_FILE=\"$TEST_SECOND_FILENAME\"\n\n\nfunction setup {\n  install_fixture_key \"$TEST_DEFAULT_USER\"\n\n  set_state_initial\n  set_state_git\n  set_state_secret_init\n  set_state_secret_tell \"$TEST_DEFAULT_USER\"\n  set_state_secret_add \"$FIRST_FILE\" \"somecontent\"\n  set_state_secret_add \"$SECOND_FILE\" \"somecontent2\"\n  set_state_secret_hide\n}\n\n\nfunction teardown {\n  rm \"$FIRST_FILE\" \"$SECOND_FILE\"\n\n  uninstall_fixture_key \"$TEST_DEFAULT_USER\"\n  unset_current_state\n}\n\n\nfunction _has_line {\n  local line=\"$1\"\n\n  local path_mappings\n  path_mappings=$(_get_secrets_dir_paths_mapping)\n\n  echo \"$(grep -q \"$line\" \"$path_mappings\"; echo $?)\"\n}\n\n\n@test \"run 'remove' normally\" {\n  run git secret remove \"$SECOND_FILE\"\n  [ \"$status\" -eq 0 ]\n\n  # Test output:\n  [[ \"$output\" == *\"removed from index.\"* ]]\n  [[ \"$output\" == *\"ensure that files: [$SECOND_FILE] are now not ignored.\"* ]]\n\n  # Mapping should not contain the second file:\n  [ \"$(_has_line \"$SECOND_FILE\")\" -eq 1 ]\n\n  # But the first file must not change:\n  [ \"$(_has_line \"$FIRST_FILE\")\" -eq 0 ]\n\n  # Both files should be present:\n  [ -f \"$(_get_encrypted_filename \"$FIRST_FILE\")\" ]\n  [ -f \"$(_get_encrypted_filename \"$SECOND_FILE\")\" ]\n}\n\n\n@test \"run 'remove' with multiple arguments\" {\n  run git secret remove \"$FIRST_FILE\" \"$SECOND_FILE\"\n  [ \"$status\" -eq 0 ]\n\n  [ \"$(_has_line \"$FIRST_FILE\")\" -eq 1 ]\n  [ \"$(_has_line \"$SECOND_FILE\")\" -eq 1 ]\n\n  # Both files should be present:\n  [ -f \"$(_get_encrypted_filename \"$FIRST_FILE\")\" ]\n  [ -f \"$(_get_encrypted_filename \"$SECOND_FILE\")\" ]\n}\n\n\n@test \"run 'remove' with slashes in filename\" {\n  # There was a bug with `sed` an slashes:\n  # see https://github.com/sobolevn/git-secret/issues/23\n\n  # Preparations:\n  local folder=\"somedir\"\n  local file_in_folder=\"$folder/$TEST_THIRD_FILENAME\"\n\n  mkdir -p \"$folder\"\n  set_state_secret_add \"$file_in_folder\" \"somecontent3\"\n  set_state_secret_hide # running hide again to hide new data\n\n  # Now it should remove filename with slashes from the mapping:\n  run git secret remove \"$file_in_folder\"\n  [ \"$status\" -eq 0 ]\n\n  [ \"$(_has_line \"$file_in_folder\")\" -eq 1 ]\n  [ -f \"$(_get_encrypted_filename \"$file_in_folder\")\" ]\n\n  # Cleaning up:\n  rm -rf \"$folder\"\n}\n\n\n@test \"run 'remove' with '-c'\" {\n  set_state_secret_hide\n\n  run git secret remove -c \"$SECOND_FILE\"\n  [ \"$status\" -eq 0 ]\n\n  [ \"$(_has_line \"$SECOND_FILE\")\" -eq 1 ]\n  [ -f \"$(_get_encrypted_filename \"$FIRST_FILE\")\" ]\n  [ ! -f \"$(_get_encrypted_filename \"$SECOND_FILE\")\" ]\n}\n\n\n@test \"run 'remove' with bad arg\" {\n  set_state_secret_hide\n  run git secret remove -Z \"$SECOND_FILE\"\n  [ \"$status\" -ne 0 ]\n}\n"
  },
  {
    "path": "tests/test_removeperson.bats",
    "content": "#!/usr/bin/env bats\n\nload _test_base\n\n\nfunction setup {\n  install_fixture_key \"$TEST_DEFAULT_USER\"\n\n  set_state_initial\n  set_state_git\n  set_state_secret_init\n  set_state_secret_tell \"$TEST_DEFAULT_USER\"\n}\n\n\nfunction teardown {\n  uninstall_fixture_key \"$TEST_DEFAULT_USER\"\n  unset_current_state\n}\n\n\n@test \"run 'removeperson' without arguments\" {\n  run git secret removeperson\n  [ \"$status\" -eq 1 ]\n}\n\n\n@test \"run 'removeperson' with short name\" {\n  local name\n  # don't complain about sed\n  # shellcheck disable=SC2001 \n  name=$(echo \"$TEST_DEFAULT_USER\" | sed -e 's/@.*//')\n\n  # removeperson must use full email, not short name\n  run git secret removeperson \"$name\"\n  [ \"$status\" -eq 1 ]\n\n  # Then whoknows will be ok because user3@gitsecret.io still knows\n  run git secret whoknows\n  [ \"$status\" -eq 0 ]\n\n  # Testing output:\n  [[ \"$output\" == *\"$TEST_DEFAULT_USER\"* ]]\n}\n\n\n@test \"run 'removeperson' with email\" {\n  local email=\"$TEST_DEFAULT_USER\"\n\n  run git secret removeperson \"$email\"\n  [ \"$status\" -eq 0 ]\n\n  # Testing output:\n  [[ \"$output\" == *\"$email\"* ]]\n\n  # Then whoknows must return an error with status code 1:\n  run git secret whoknows\n  [ \"$status\" -eq 1 ]\n}\n\n\n@test \"run 'removeperson' with multiple arguments\" {\n  # Adding second user:\n  install_fixture_key \"$TEST_SECOND_USER\"\n  set_state_secret_tell \"$TEST_SECOND_USER\"\n\n  local default_email=\"$TEST_DEFAULT_USER\"\n  local second_email=\"$TEST_SECOND_USER\"\n\n  run git secret removeperson \"$default_email\" \"$second_email\"\n  [ \"$status\" -eq 0 ]\n\n  # Testing output:\n  [[ \"$output\" == *\"$default_email\"* ]]\n  [[ \"$output\" == *\"$second_email\"* ]]\n\n  # Nothing to show:\n  run git secret whoknows\n  [ \"$status\" -eq 1 ]\n}\n\n\n@test \"run 'removeperson' with bad arg\" {\n  local email=\"$TEST_DEFAULT_USER\"\n  run git secret removeperson -Z \"$email\"\n  [ \"$status\" -ne 0 ]\n}\n\n\n@test \"run the 'killperson' alias\" {\n  run git secret killperson\n  [ \"$status\" -eq 1 ]\n}\n\n@test \"run 'removeperson' with email added twice\" {\n  local email=\"$TEST_DEFAULT_USER\"\n\n  # This should fail because you can't add the same email twice\n  run git secret tell \"$email\"\n  [ \"$status\" -ne 0 ]\n\n  # Then test that the normal remove test runs\n  run git secret removeperson \"$email\"\n  [ \"$status\" -eq 0 ]\n\n  # Testing output:\n  [[ \"$output\" == *\"$email\"* ]]\n\n  # Then whoknows must return an error with status code 1, because no one is in list\n  run git secret whoknows\n  [ \"$status\" -eq 1 ]\n}\n\n\n@test \"run 'removeperson' with fingerprint\" {\n  local fingerprint\n  fingerprint=$(get_gpg_public_fingerprint_by_email \"$TEST_DEFAULT_USER\")\n\n  run git secret removeperson \"$fingerprint\"\n  [ \"$status\" -eq 0 ]\n\n  # Testing output:\n  [[ \"$output\" == *\"removed keys\"* ]]\n\n  # Then whoknows must return an error with status code 1:\n  run git secret whoknows\n  [ \"$status\" -eq 1 ]\n}\n\n"
  },
  {
    "path": "tests/test_reveal.bats",
    "content": "#!/usr/bin/env bats\n# shellcheck disable=SC2155\n\nload _test_base\n\nFILE_TO_HIDE=\"$TEST_DEFAULT_FILENAME\"\nFILE_CONTENTS=\"hidden content юникод\"\n\nFINGERPRINT=\"\"\n\n\nfunction setup {\n  FINGERPRINT=$(install_fixture_full_key \"$TEST_DEFAULT_USER\")\n\n  set_state_initial\n  set_state_git\n  set_state_secret_init\n  set_state_secret_tell \"$TEST_DEFAULT_USER\"\n  set_state_secret_add \"$FILE_TO_HIDE\" \"$FILE_CONTENTS\"\n  set_state_secret_hide\n}\n\n\nfunction teardown {\n  rm -f \"$FILE_TO_HIDE\"\n\n  uninstall_fixture_full_key \"$TEST_DEFAULT_USER\" \"$FINGERPRINT\"\n  unset_current_state\n}\n\n\n@test \"run 'reveal' with password argument\" {\n  cp \"$FILE_TO_HIDE\" \"${FILE_TO_HIDE}2\"\n  rm -f \"$FILE_TO_HIDE\"\n\n  local password=$(test_user_password \"$TEST_DEFAULT_USER\")\n  run git secret reveal -d \"$TEST_GPG_HOMEDIR\" -p \"$password\"\n\n  [ \"$status\" -eq 0 ]\n  [ -f \"$FILE_TO_HIDE\" ]\n\n  cmp -s \"$FILE_TO_HIDE\" \"${FILE_TO_HIDE}2\"\n\n  rm \"${FILE_TO_HIDE}2\"\n}\n\n\n@test \"run 'reveal' with bad arg\" {\n  local password=$(test_user_password \"$TEST_DEFAULT_USER\")\n  run git secret reveal -Z -d \"$TEST_GPG_HOMEDIR\" -p \"$password\"\n  [ \"$status\" -ne 0 ]\n}\n\n@test \"run 'reveal' on secret version of file\" {\n  local password=$(test_user_password \"$TEST_DEFAULT_USER\")\n  run git secret reveal -d \"$TEST_GPG_HOMEDIR\" -p \"$password\" \"$FILE_TO_HIDE$SECRETS_EXTENSION\"\n  [ \"$status\" -ne 0 ]\n}\n\n@test \"run 'reveal' on nonexistent file\" {\n  local password=$(test_user_password \"$TEST_DEFAULT_USER\")\n  run git secret reveal -d \"$TEST_GPG_HOMEDIR\" -p \"$password\" \"DOES-NOT-EXIST\"\n  [ \"$status\" -ne 0 ]\n}\n\n@test \"run 'reveal' with '-f'\" {\n  rm \"$FILE_TO_HIDE\"\n\n  local password=$(test_user_password \"$TEST_DEFAULT_USER\")\n  run git secret reveal -f -d \"$TEST_GPG_HOMEDIR\" -p \"$password\"\n\n  [ \"$status\" -eq 0 ]\n  [ -f \"$FILE_TO_HIDE\" ]\n}\n\n\n@test \"run 'reveal' binary with 'SECRETS_GPG_ARMOR=1'\" {\n  rm \"$FILE_TO_HIDE\"\n\n  local password=$(test_user_password \"$TEST_DEFAULT_USER\")\n  # Armor should not change anything here:\n  SECRETS_GPG_ARMOR=1 run git secret reveal -d \"$TEST_GPG_HOMEDIR\" -p \"$password\"\n\n  [ \"$status\" -eq 0 ]\n  [ -f \"$FILE_TO_HIDE\" ]\n}\n\n\n@test \"run 'reveal' armored with 'SECRETS_GPG_ARMOR=1'\" {\n  # We need to clean existing binary files:\n  git secret clean\n\n  # Now, let's hide files once again with `--armor` enabled:\n  set_state_secret_hide '1'\n\n  rm \"$FILE_TO_HIDE\"\n\n  local password=$(test_user_password \"$TEST_DEFAULT_USER\")\n  # Armor should not change anything here:\n  SECRETS_GPG_ARMOR=1 run git secret reveal -d \"$TEST_GPG_HOMEDIR\" -p \"$password\"\n\n  [ \"$status\" -eq 0 ]\n  [ -f \"$FILE_TO_HIDE\" ]\n}\n\n\n@test \"run 'reveal' armored with 'SECRETS_GPG_ARMOR=0'\" {\n  # We need to clean existing binary files:\n  git secret clean\n\n  # Now, let's hide files once again with `--armor` enabled:\n  set_state_secret_hide '1'\n\n  rm \"$FILE_TO_HIDE\"\n\n  local password=$(test_user_password \"$TEST_DEFAULT_USER\")\n  # Armor should not change anything here:\n  SECRETS_GPG_ARMOR=0 run git secret reveal -d \"$TEST_GPG_HOMEDIR\" -p \"$password\"\n\n  [ \"$status\" -eq 0 ]\n  [ -f \"$FILE_TO_HIDE\" ]\n}\n\n\n@test \"run 'reveal' with '-v'\" {\n  rm \"$FILE_TO_HIDE\"\n\n  local password=$(test_user_password \"$TEST_DEFAULT_USER\")\n  run git secret reveal -v -d \"$TEST_GPG_HOMEDIR\" -p \"$password\"\n\n  [ \"$status\" -eq 0 ]\n  [ -f \"$FILE_TO_HIDE\" ]\n}\n\n\n@test \"run 'reveal' with '-P'\" {\n  rm \"$FILE_TO_HIDE\"\n\n  local password=$(test_user_password \"$TEST_DEFAULT_USER\")\n\n  local secret_file=$(_get_encrypted_filename \"$FILE_TO_HIDE\")\n  chmod o-rwx \"$secret_file\"\n\n  run git secret reveal -P -d \"$TEST_GPG_HOMEDIR\" -p \"$password\"\n\n  [ \"$status\" -eq 0 ]\n\n  ## permissions should match.\n  local secret_perm\n  local file_perm\n  file_perm=$($SECRETS_OCTAL_PERMS_COMMAND \"$FILE_TO_HIDE\")\n  secret_perm=$($SECRETS_OCTAL_PERMS_COMMAND \"$FILE_TO_HIDE$SECRETS_EXTENSION\")\n  #echo \"# secret_perm: $secret_perm, file_perm: $file_perm\" >&3\n  [ \"$secret_perm\" = \"$file_perm\" ]\n\n  [ -f \"$FILE_TO_HIDE\" ]\n}\n\n\n@test \"run 'reveal' with wrong password\" {\n  rm \"$FILE_TO_HIDE\"\n\n  run git secret reveal -d \"$TEST_GPG_HOMEDIR\" -p \"WRONG\"\n  [ \"$status\" -eq 2 ]\n  [ ! -f \"$FILE_TO_HIDE\" ]\n}\n\n\n@test \"run 'reveal' for attacker\" {\n  # Preparations\n  rm \"$FILE_TO_HIDE\"\n\n  local attacker_fingerprint=$(install_fixture_full_key \"$TEST_ATTACKER_USER\")\n  local password=$(test_user_password \"$TEST_ATTACKER_USER\")\n\n  run git secret reveal -d \"$TEST_GPG_HOMEDIR\" -p \"$password\"\n\n  # This should fail, nothing should be created:\n  [ \"$status\" -eq 2 ]\n  [ ! -f \"$FILE_TO_HIDE\" ]\n\n  # Cleaning up:\n  uninstall_fixture_full_key \"$TEST_ATTACKER_USER\" \"$attacker_fingerprint\"\n}\n\n\n@test \"run 'reveal' for attacker with -F (force)\" {\n  # Preparations\n  rm \"$FILE_TO_HIDE\"\n\n  local attacker_fingerprint=$(install_fixture_full_key \"$TEST_ATTACKER_USER\")\n  local password=$(test_user_password \"$TEST_ATTACKER_USER\")\n\n  run git secret reveal -F -d \"$TEST_GPG_HOMEDIR\" -p \"$password\"\n\n  #echo \"# status is $status\" >&3\n\n  # This should return a status code of 1 also.  Not sure how to test that we don't die early\n  [ \"$status\" -eq 0 ]\n  [ ! -f \"$FILE_TO_HIDE\" ]\n\n  touch \"$FILE_TO_HIDE\"  #create this file so uninstall below works\n\n  # Cleaning up:\n  uninstall_fixture_full_key \"$TEST_ATTACKER_USER\" \"$attacker_fingerprint\"\n}\n\n\n@test \"run 'reveal' for multiple users (with key deletion)\" {\n  # Preparations:\n  local second_fingerprint=$(install_fixture_full_key \"$TEST_SECOND_USER\")\n  local password=$(test_user_password \"$TEST_SECOND_USER\")\n  set_state_secret_tell \"$TEST_SECOND_USER\"\n  set_state_secret_hide\n\n  # We are removing a secret key of the first user to be sure\n  # that it is not used in decryption:\n  uninstall_fixture_full_key \"$TEST_DEFAULT_USER\" \"$FINGERPRINT\"\n\n  # Testing:\n  run git secret reveal -d \"$TEST_GPG_HOMEDIR\" -p \"$password\"\n\n  [ \"$status\" -eq 0 ]\n  [ -f \"$FILE_TO_HIDE\" ]\n\n  # Cleaning up:\n  uninstall_fixture_full_key \"$TEST_SECOND_USER\" \"$second_fingerprint\"\n}\n\n\n@test \"run 'reveal' for multiple users (normally)\" {\n  # Preparations:\n  local second_fingerprint=$(install_fixture_full_key \"$TEST_SECOND_USER\")\n  # bug in gpg v2.0.22, need to use default password\n  local password=$(test_user_password \"$TEST_DEFAULT_USER\")\n  set_state_secret_tell \"$TEST_SECOND_USER\"\n  set_state_secret_hide\n\n  # Testing:\n  run git secret reveal -d \"$TEST_GPG_HOMEDIR\" -p \"$password\"\n\n  [ \"$status\" -eq 0 ]\n  [ -f \"$FILE_TO_HIDE\" ]\n\n  # Cleaning up:\n  uninstall_fixture_full_key \"$TEST_SECOND_USER\" \"$second_fingerprint\"\n}\n\n\n@test \"run 'reveal' with SECRETS_PINENTRY=loopback\" {\n  rm -f \"$FILE_TO_HIDE\"\n\n  local password=$(test_user_password \"$TEST_DEFAULT_USER\")\n  SECRETS_PINENTRY=loopback run git secret reveal \\\n    -d \"$TEST_GPG_HOMEDIR\" \\\n    -p \"$password\"\n  [ \"$status\" -eq 0 ]\n}\n\n\n@test \"run 'reveal' with SECRETS_PINENTRY=error\" {\n  if [[ \"$GPG_VER_MIN_21\" -ne 1 ]]; then\n    skip \"this test is skipped on gpg before version 2.1\"\n  fi\n\n  rm -f \"$FILE_TO_HIDE\"\n\n  local password=$(test_user_password \"$TEST_DEFAULT_USER\")\n  SECRETS_PINENTRY=error run git secret reveal \\\n    -d \"$TEST_GPG_HOMEDIR\" \\\n    -p \"$password\"\n  [ \"$status\" -ne 0 ]\n}\n\n@test \"run 'reveal' with named file from subdir\" {\n  local password\n  password=$(test_user_password \"$TEST_DEFAULT_USER\")\n\n  mkdir subdir\n  echo \"content2\" > subdir/new_filename.txt\n\n  ( # start subshell for subdir tests\n    cd subdir\n    run git secret add new_filename.txt\n    [ \"$status\" -eq 0 ]\n    run git secret hide\n    [ \"$status\" -eq 0 ]\n  \n    run git secret reveal -d \"$TEST_GPG_HOMEDIR\" -p \"$password\" new_filename.txt\n    [ \"$status\" -eq 0 ]\n  ) # end subshell\n\n  # clean up\n  rm -rf subdir\n}\n\n@test \"run 'reveal' for all files from subdir\" {\n  local password\n  password=$(test_user_password \"$TEST_DEFAULT_USER\")\n\n  mkdir -p subdir\n  echo \"content2\" > subdir/new_filename.txt\n\n  ( # start subshell for subdir tests\n    cd subdir\n    run git secret add new_filename.txt\n    [ \"$status\" -eq 0 ]\n    run git secret hide\n    [ \"$status\" -eq 0 ]\n  \n    run git secret reveal -d \"$TEST_GPG_HOMEDIR\" -p \"$password\"\n    [ \"$status\" -eq 0 ]\n  ) # end subshell\n\n  # clean up\n  rm -rf subdir\n}\n"
  },
  {
    "path": "tests/test_reveal_filename.bats",
    "content": "#!/usr/bin/env bats\n\nload _test_base\n\nFILE_TO_HIDE=\"$TEST_DEFAULT_FILENAME\"\nFILE_CONTENTS=\"hidden content юникод\"\n\nFINGERPRINT=\"\"\nOLD_SECRETS_EXTENSION=\"\"\n\n\nfunction setup {\n  FINGERPRINT=$(install_fixture_full_key \"$TEST_DEFAULT_USER\")\n\n  set_state_initial\n  set_state_git\n  set_state_secret_init\n  set_state_secret_tell \"$TEST_DEFAULT_USER\"\n  set_state_secret_add \"$FILE_TO_HIDE\" \"$FILE_CONTENTS\"\n\n  OLD_SECRETS_EXTENSION=\"$SECRETS_EXTENSION\"\n  export SECRETS_EXTENSION=\".new_secret\"\n\n  set_state_secret_hide\n}\n\n\nfunction teardown {\n  rm -f \"$FILE_TO_HIDE\"\n\n  uninstall_fixture_full_key \"$TEST_DEFAULT_USER\" \"$FINGERPRINT\"\n  unset_current_state\n\n  export SECRETS_EXTENSION=\"$OLD_SECRETS_EXTENSION\"\n}\n\n\n@test \"run 'reveal' with different file extension\" {\n  cp \"$FILE_TO_HIDE\" \"${FILE_TO_HIDE}2\"\n  rm \"$FILE_TO_HIDE\"\n\n  local password\n  password=$(test_user_password \"$TEST_DEFAULT_USER\")\n  run git secret reveal -d \"$TEST_GPG_HOMEDIR\" -p \"$password\"\n\n  [ \"$status\" -eq 0 ]\n  [ -f \"$FILE_TO_HIDE\" ]\n\n  cmp -s \"$FILE_TO_HIDE\" \"${FILE_TO_HIDE}2\"\n\n  rm \"${FILE_TO_HIDE}2\"\n}\n"
  },
  {
    "path": "tests/test_tell.bats",
    "content": "#!/usr/bin/env bats\n\nload _test_base\n\n\nfunction setup {\n  install_fixture_key \"$TEST_DEFAULT_USER\"\n\n  set_state_initial\n  set_state_git\n  set_state_secret_init\n}\n\n\nfunction teardown {\n  uninstall_fixture_key \"$TEST_DEFAULT_USER\"\n  unset_current_state\n}\n\n\n@test \"run 'tell' with '-v'\" {\n  run git secret tell -d \"$TEST_GPG_HOMEDIR\" -v \"$TEST_DEFAULT_USER\"\n  # echo \"$output\" | sed \"s/^/# '$BATS_TEST_DESCRIPTION' output: /\" >&3\n\n  [[ \"$output\" == *\"created\"* ]]\n  [[ \"$output\" == *\"gpg:\"* ]]\n  [[ \"$output\" == *\"$TEST_DEFAULT_USER\"* ]]\n  [ \"$status\" -eq 0 ]\n}\n\n\n@test \"run 'tell' without '-v'\" {\n  run git secret tell -d \"$TEST_GPG_HOMEDIR\"  \"$TEST_DEFAULT_USER\"\n  # echo \"$output\" | sed \"s/^/# '$BATS_TEST_DESCRIPTION' output: /\" >&3\n\n  [[ \"$output\" != *\"imported:\"* ]]\n  [[ \"$output\" == *\"$TEST_DEFAULT_USER\"* ]]\n  [ \"$status\" -eq 0 ]\n}\n\n\n@test \"run 'tell' on substring of emails\" {\n  run git secret tell -d \"$TEST_GPG_HOMEDIR\" user\n  # this should give an error because there is no user named 'user',\n  # even though there are users with the substring 'user'.\n  # See issue https://github.com/sobolevn/git-secret/issues/176\n  [ \"$status\" -eq 1 ]\n\n  run git secret whoknows\n  [ \"$status\" -eq 1 ]   # should error when there are no users told\n\n}\n\n\n@test \"run 'tell' on the same email twice\" {\n  # first time should succeed\n  git secret tell -d \"$TEST_GPG_HOMEDIR\" \"$TEST_DEFAULT_USER\"\n\n  # second time should fail because there's already a key for that email. See #634\n  run git secret tell -d \"$TEST_GPG_HOMEDIR\" \"$TEST_DEFAULT_USER\"\n  [ \"$status\" -ne 0 ]\n}\n\n\n@test \"fail on no users\" {\n  run _user_required\n  [ \"$status\" -eq 1 ]\n}\n\n\n@test \"constantly fail on no users\" {\n  # We had a serious bug with _user_required,\n  # see this link for the details:\n  # https://github.com/sobolevn/git-secret/issues/74\n\n  # Preparations:\n  git secret tell -d \"$TEST_GPG_HOMEDIR\" \"$TEST_DEFAULT_USER\"\n  git secret removeperson \"$TEST_DEFAULT_USER\"\n\n  # It was showing something like `tru::1:1289775241:0:2:1:6`\n  # after the preparations done and the error was not generated.\n  run _user_required\n  [ \"$status\" -eq 1 ]\n}\n\n\n@test \"run 'tell' with secret-key imported\" {\n  local secrets_dir_keys\n  secrets_dir_keys=$(_get_secrets_dir_keys)\n\n  local private_key=\"$secrets_dir_keys/secring.gpg\"\n  echo \"private key\" > \"$private_key\"\n  [ -s \"$private_key\" ]\n\n  run git secret tell -d \"$TEST_GPG_HOMEDIR\" \"$TEST_DEFAULT_USER\"\n  [ \"$status\" -eq 1 ]\n}\n\n\n@test \"run 'tell' without '.gitsecret'\" {\n  local secrets_dir\n  secrets_dir=$(_get_secrets_dir)\n\n  rm -r \"$secrets_dir\"\n\n  run git secret tell -d \"$TEST_GPG_HOMEDIR\" \"$TEST_DEFAULT_USER\"\n  [ \"$status\" -eq 1 ]\n}\n\n\n@test \"run 'tell' without arguments\" {\n  run git secret tell\n  [ \"$status\" -eq 1 ]\n}\n\n\n@test \"run 'init' with bad arg\" {\n  run git secret tell -Z -d \"$TEST_GPG_HOMEDIR\" \"$TEST_DEFAULT_USER\"\n  [ \"$status\" -ne 0 ]\n}\n\n\n@test \"run 'tell' normally\" {\n  run git secret tell -d \"$TEST_GPG_HOMEDIR\" \"$TEST_DEFAULT_USER\"\n  [ \"$status\" -eq 0 ]\n\n  # Testing that now user is found:\n  run _user_required\n  [ \"$status\" -eq 0 ]\n\n  # Testing that now user is in the list of people who knows the secret:\n  run git secret whoknows\n  [[ \"$output\" == *\"$TEST_DEFAULT_USER\"* ]]\n}\n\n\n@test \"run 'tell' with '-m'\" {\n  local email=\"$TEST_DEFAULT_USER\"\n\n  git_set_config_email \"$email\"\n  run git secret tell -d \"$TEST_GPG_HOMEDIR\" -m\n  [ \"$status\" -eq 0 ]\n}\n\n\n@test \"run 'tell' with '-m' (empty email)\" {\n  # Preparations:\n  git_set_config_email \"\" # now it should not allow to add yourself\n\n  run git secret tell -d \"$TEST_GPG_HOMEDIR\" -m\n  [ \"$status\" -eq 1 ]\n}\n\n\n@test \"run 'tell' with multiple emails\" {\n  # Preparations:\n  install_fixture_key \"$TEST_SECOND_USER\"\n\n  # Testing the command itself:\n  run git secret tell -d \"$TEST_GPG_HOMEDIR\" \\\n    \"$TEST_DEFAULT_USER\" \"$TEST_SECOND_USER\"\n\n  [ \"$status\" -eq 0 ]\n\n  # Testing that these users are presented in the\n  # list of people who knows secret:\n  run git secret whoknows\n\n  [[ \"$output\" == *\"$TEST_DEFAULT_USER\"* ]]\n  [[ \"$output\" == *\"$TEST_SECOND_USER\"* ]]\n\n  # Cleaning up:\n  uninstall_fixture_key \"$TEST_SECOND_USER\"\n}\n\n\n@test \"run 'tell' with key without email and with comment\" {\n  # install works because it works on filename, not contents of keyring\n  install_fixture_key \"$TEST_NOEMAIL_COMMENT_USER\"\n\n  # Testing the command itself fails because you have to use an email address\n  run git secret tell -d \"$TEST_GPG_HOMEDIR\" \"$TEST_NOEMAIL_COMMENT_USER\"\n\n  # this should not succeed because we only support addressing users by email\n  [ \"$status\" -ne 0 ]\n\n  # Testing that these users are presented in the\n  # list of people who knows secret:\n  run git secret whoknows\n\n  [[ \"$output\" != *\"$TEST_NOEMAIL_COMMENT_USER\"* ]]\n\n  # Cleaning up: can't clean up by email\n  # uninstall_fixture_key \"$TEST_NOEMAIL_COMMENT_USER\"\n}\n\n\n@test \"run 'tell' on non-email\" {\n  install_fixture_key \"$TEST_NOEMAIL_COMMENT_USER\"\n\n  local name\n  # don't complain about sed\n  # shellcheck disable=SC2001 \n  name=$(echo \"$TEST_NOEMAIL_COMMENT_USER\" | sed -e 's/@.*//')\n  # echo \"$name\" | sed \"s/^/# '$BATS_TEST_DESCRIPTION' name is: /\" >&3\n\n  # Testing the command itself, should fail because you must use email\n  run git secret tell -d \"$TEST_GPG_HOMEDIR\" \"$name\"\n\n  # this should not succeed because we only support addressing users by email\n  [ \"$status\" -ne 0 ]\n\n  # Testing that these users are presented in the\n  # list of people who knows secret:\n  run git secret whoknows\n\n  [[ \"$output\" != *\"$name\"* ]]\n\n  # Cleaning up: can't clean up by email because key doesn't hold it\n  # uninstall_fixture_key \"$TEST_NOEMAIL_COMMENT_USER\"\n}\n\n@test \"run 'tell' in subfolder\" {\n  if [[ \"$BATS_RUNNING_FROM_GIT\" -eq 1 ]]; then\n    skip \"this test is skipped while 'git commit'. See #334\"\n  fi\n\n  # Preparations\n  local root_dir='test_dir'\n  local test_dir=\"$root_dir/telling\"\n  local current_dir=\"$PWD\"\n\n  mkdir -p \"$test_dir\"\n  cd \"$test_dir\"\n\n  # Test:\n  run git secret tell -d \"$TEST_GPG_HOMEDIR\" \"$TEST_DEFAULT_USER\"\n  [ \"$status\" -eq 0 ]\n\n  # Testing that now user is found:\n  run _user_required\n  [ \"$status\" -eq 0 ]\n\n  # Testing that now user is in the list of people who knows the secret:\n  run git secret whoknows\n  [[ \"$output\" == *\"$TEST_DEFAULT_USER\"* ]]\n\n  # Cleaning up:\n  cd \"$current_dir\"\n  rm -r \"$root_dir\"\n}\n\n\n@test \"run 'tell' with fingerprint\" {\n  local fingerprint\n  fingerprint=$(get_gpg_public_fingerprint_by_email \"$TEST_DEFAULT_USER\")\n\n  run git secret tell -d \"$TEST_GPG_HOMEDIR\" \"$fingerprint\"\n  [ \"$status\" -eq 0 ]\n\n  # Testing that now user is found:\n  run _user_required\n  [ \"$status\" -eq 0 ]\n\n  # Testing that now user is in the list of people who knows the secret:\n  run git secret whoknows\n  [[ \"$output\" == *\"$TEST_DEFAULT_USER\"* ]]\n}\n\n\n@test \"run 'tell' with fingerprint on the same key twice\" {\n  local fingerprint\n  fingerprint=$(get_gpg_public_fingerprint_by_email \"$TEST_DEFAULT_USER\")\n\n  # first time should succeed\n  git secret tell -d \"$TEST_GPG_HOMEDIR\" \"$fingerprint\"\n\n  # second time should fail because the key is already in the keyring\n  run git secret tell -d \"$TEST_GPG_HOMEDIR\" \"$fingerprint\"\n  [ \"$status\" -ne 0 ]\n}\n\n\n@test \"run 'tell' with invalid fingerprint\" {\n  # A hex string that doesn't match any key\n  run git secret tell -d \"$TEST_GPG_HOMEDIR\" \"DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF\"\n  [ \"$status\" -eq 1 ]\n}\n"
  },
  {
    "path": "tests/test_usage.bats",
    "content": "#!/usr/bin/env bats\n\nload _test_base\n\n\nfunction setup {\n  set_state_initial\n  set_state_git\n}\n\n\nfunction teardown {\n  unset_current_state\n}\n\n\n@test \"run 'usage'\" {\n  run git secret usage\n  [ \"$status\" -eq 0 ]\n}\n\n\n@test \"run 'usage' without '.git'\" {\n  remove_git_repository\n\n  # It's ok for 'usage' to succeed when there's no .git directory, but it doesn't\n  run git secret usage\n  [ \"$status\" -eq 1 ]\n}\n\n\n#_SECRETS_DIR=${SECRETS_DIR:-\".gitsecret\"}\n@test \"run 'usage' with ignored '${_SECRETS_DIR}'\" {\n  echo \"${_SECRETS_DIR}\" >> \".gitignore\"\n\n  # below shows how to send 'diagnostic' messages to bats-core.\n  # echo \"# clear-line-output\" >&3\n  # echo \"# SECRETS_DIR is ${_SECRETS_DIR}\" >&3\n\n  # It's ok for 'usage' to succeed when the .gitsecret directory is ignored, but it doesn't\n  run git secret usage\n  # echo \"# git secret usage -> status $status\" >&3\n\n  [ \"$status\" -eq 1 ]\n}\n"
  },
  {
    "path": "tests/test_whoknows.bats",
    "content": "#!/usr/bin/env bats\n\nload _test_base\n\n\nfunction setup {\n  install_fixture_key \"$TEST_DEFAULT_USER\"\n  install_fixture_key \"$TEST_SECOND_USER\"\n\n  set_state_initial\n  set_state_git\n  set_state_secret_init\n  set_state_secret_tell \"$TEST_DEFAULT_USER\"\n  set_state_secret_tell \"$TEST_SECOND_USER\"\n}\n\n\nfunction teardown {\n  uninstall_fixture_key \"$TEST_DEFAULT_USER\"\n  uninstall_fixture_key \"$TEST_SECOND_USER\"\n  unset_current_state\n}\n\n\n@test \"run 'whoknows' normally\" {\n  run git secret whoknows\n  [ \"$status\" -eq 0 ]\n\n  # Now test the output, both users should be present:\n  [[ \"$output\" == *\"$TEST_DEFAULT_USER\"* ]]\n  [[ \"$output\" == *\"$TEST_SECOND_USER\"* ]]\n}\n\n@test \"run 'whoknows' with extra filename\" {\n  run git secret whoknows extra_filename\n  [ \"$status\" -ne 0 ]\n}\n\n@test \"run 'whoknows' with bad arg\" {\n  run git secret whoknows -Z\n  [ \"$status\" -ne 0 ]\n}\n\n@test \"run 'whoknows -l'\" {\n  run git secret whoknows -l\n  [ \"$status\" -eq 0 ]\n\n  # echo \"$output\" | sed \"s/^/# '$BATS_TEST_DESCRIPTION' output: /\" >&3\n  # output should look like\n  # 'abort: problem encrypting file with gpg: exit code 2: space file'\n  #echo \"# '$BATS_TEST_DESCRIPTION' status: $status\" >&3\n\n  # Now test the output, both users should be present and without expiration\n  [[ \"$output\" == *\"$TEST_DEFAULT_USER (expires: never)\"* ]]\n  [[ \"$output\" == *\"$TEST_SECOND_USER (expires: never)\"* ]]\n}\n\n@test \"run 'whoknows' in subfolder\" {\n  if [[ \"$BATS_RUNNING_FROM_GIT\" -eq 1 ]]; then\n    skip \"this test is skipped while 'git commit'. See #334\"\n  fi\n\n  # Preparations:\n  local current_dir=\"$PWD\"\n  local root_dir='test_dir'\n  local test_dir=\"$root_dir/subfolders/case\"\n\n  mkdir -p \"$test_dir\"\n  cd \"$test_dir\"\n\n  # Test:\n  run git secret whoknows\n  [ \"$status\" -eq 0 ]\n\n  # Now test the output, both users should be present:\n  [[ \"$output\" == *\"$TEST_DEFAULT_USER\"* ]]\n  [[ \"$output\" == *\"$TEST_SECOND_USER\"* ]]\n\n  # Cleaning up:\n  cd \"$current_dir\"\n  rm -r \"$root_dir\"\n}\n\n\n@test \"run 'whoknows' without any users\" {\n  # Preparations, removing users:\n  local email1=\"$TEST_DEFAULT_USER\"\n  local email2=\"$TEST_SECOND_USER\"\n  git secret removeperson \"$email1\" \"$email2\"\n\n  # Now whoknows should raise an error: there are no users.\n  run git secret whoknows\n  [ \"$status\" -eq 1 ]\n}\n"
  },
  {
    "path": "utils/apk/build.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\n# shellcheck disable=SC1090,SC1091\nsource \"$SECRETS_PROJECT_ROOT/utils/build-utils.sh\"\n# We need this export for `config.yml` to expand the version properly.\nexport SCRIPT_VERSION\n\n# shellcheck disable=SC1090,SC1091\nsource \"$SECRETS_PROJECT_ROOT/utils/apk/meta.sh\"\n\n# Create dest dir:\nmkdir -p \"$SCRIPT_DEST_DIR\"\n\nfor architecture in \"${ALPINE_ARCHITECTURES[@]}\"; do\n  ALPINE_ARCHITECTURE=\"$architecture\"\n  export ALPINE_ARCHITECTURE\n\n  config_file=\"$SCRIPT_BUILD_DIR/${architecture}.yml\"\n  envsubst < \"$SECRETS_PROJECT_ROOT/utils/apk/nfpm.yml\" > \"$config_file\"\n\n  # Here's the deal. We use a custom builder here,\n  # because `fpm` produces a broken package.\n  # It is possible to install it locally,\n  # but it used to fail when installed from our Artifactory.\n  # So, we switched to `nfpm` instead.\n  # But, we only switched one repo for now,\n  # because we are not sure that other affected packages will be fine.\n  # And also `fpm` supports more tools: like pacman.\n  nfpm package \\\n    --config \"$config_file\" \\\n    --packager 'apk' \\\n    --target \"$SCRIPT_DEST_DIR\"\ndone\n\n# Cleaning up:\nclean_up_files\n"
  },
  {
    "path": "utils/apk/deploy.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\nif [[ \"$SECRETS_DEPLOY_DRY_RUN\" == 1 ]]; then\n  echo 'dry-run finished'\n  exit 0\nfi\n\n# shellcheck disable=SC1090,SC1091\nsource \"$SECRETS_PROJECT_ROOT/utils/build-utils.sh\"\n# shellcheck disable=SC1090,SC1091\nsource \"$SECRETS_PROJECT_ROOT/utils/apk/meta.sh\"\n\nreadonly VERSION_NAME=\"git-secret-${SCRIPT_VERSION}.apk\"\n\n# Artifactory location:\nreadonly BASE_API_URL='https://gitsecret.jfrog.io/artifactory'\n\n\nfunction upload_with_architecture {\n  local arch=\"$1\"\n  local file_location\n  file_location=\"$(locate_release 'apk' \"$arch\")\"\n\n  curl -sS \\\n    -u \"$SECRETS_ARTIFACTORY_CREDENTIALS\" \\\n    --max-time 10 \\\n    --retry 3 \\\n    --retry-delay 5 \\\n    -XPUT \"$BASE_API_URL/git-secret-apk/latest-stable/main/$arch/$VERSION_NAME\" \\\n    -T \"$file_location\"\n}\n\nfor architecture in \"${ALPINE_ARCHITECTURES[@]}\"; do\n  upload_with_architecture \"$architecture\"\ndone\n\n# Now, we need to trigger metadata reindex:\ncurl -sS \\\n  -u \"$SECRETS_ARTIFACTORY_CREDENTIALS\" \\\n  --max-time 5 \\\n  --retry 3 \\\n  --retry-delay 5 \\\n  -XPOST \"$BASE_API_URL/api/alpine/git-secret-apk/reindex\"\n\necho\necho 'Done: released alpine packages'\n"
  },
  {
    "path": "utils/apk/install.sh",
    "content": "sh -c \"echo 'https://gitsecret.jfrog.io/artifactory/git-secret-apk/latest-stable/main'\" >> /etc/apk/repositories\nwget -O /etc/apk/keys/git-secret-apk.rsa.pub 'https://gitsecret.jfrog.io/artifactory/api/security/keypair/public/repositories/git-secret-apk'\napk add --update --no-cache git-secret\n\n# Testing, that it worked:\ngit secret --version\n"
  },
  {
    "path": "utils/apk/meta.sh",
    "content": "# Full list is here:\n# http://dl-cdn.alpinelinux.org/alpine/v3.13/main/\n# shellcheck disable=SC2034\nreadonly ALPINE_ARCHITECTURES=(\n  # We only support popular arches:\n  'x86'\n  'x86_64'\n)\n"
  },
  {
    "path": "utils/apk/nfpm.yml",
    "content": "# Name. (required)\nname: git-secret\n\n# Architecture. (required)\narch: $ALPINE_ARCHITECTURE\n\n# Platform.\n# Defaults to `linux`.\nplatform: linux\n\n# Version. (required)\n# This will expand any env var you set in the field, eg version: v${SEMVER}\nversion: $SCRIPT_VERSION\nversion_schema: none\n\n# Section.\nsection: default\n\n# Priority.\npriority: main\n\n# Maintainer.\nmaintainer: Nikita Sobolev <mail@sobolevn.me>\n\n# Description.\n# Defaults to `no description given`.\ndescription: Shell scripts to encrypt your private data inside a git repository.\n\n# Vendor.\nvendor: git-secret team\n\n# Package's homepage.\nhomepage: https://git-secret.io\n\n# License.\nlicense: MIT\n\n# Dependencies.\ndepends:\n  - git\n  - bash\n  - gnupg\n  - gawk\n  - coreutils\n\ncontents:\n  - src: git-secret\n    dst: /usr/bin/git-secret\n  - src: man/man1/*.1\n    dst: /usr/share/man/man1\n  - src: man/man7/*.7\n    dst: /usr/share/man/man7\n"
  },
  {
    "path": "utils/build-utils.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\n# shellcheck disable=SC1090,SC1091\nsource \"$SECRETS_PROJECT_ROOT/src/version.sh\"\n\n# Initializing and settings:\nreadonly READ_PERM=0644\nreadonly EXEC_PERM=0755\n\nreadonly SCRIPT_NAME='git-secret'\nreadonly SCRIPT_DESCRIPTION='Shell scripts to encrypt your private data inside a git repository.'\nreadonly SCRIPT_VERSION=\"$GITSECRET_VERSION\"\n\n# This may be overridden:\nif [[ -z \"$SCRIPT_BUILD_DIR\" ]]; then\n  SCRIPT_BUILD_DIR=\"$PWD/build\"\nfi\n\nreadonly SCRIPT_DEST_DIR=\"$SCRIPT_BUILD_DIR/buildroot\"\n\n\nfunction locate_release {\n  local release_type=\"$1\"\n  local arch=\"${2:-}\"\n\n  find \"$SCRIPT_DEST_DIR\" \\\n    -maxdepth 1 \\\n    -name \"*${arch}.$release_type\" | head -1\n}\n\n\nfunction preinstall_files {\n  # Only requires `-T` or `-c` depending on the OS\n  local dir_switch=\"$1\"\n\n  # Preparing the files:\n  rm -rf \"$SCRIPT_BUILD_DIR\"\n  mkdir -p \"$SCRIPT_DEST_DIR\"\n\n  # Coping the files inside the build folder:\n  install -D \"$dir_switch\" \\\n    -b -m \"$EXEC_PERM\" \"$dir_switch\" \"$SCRIPT_NAME\" \\\n    \"$SCRIPT_BUILD_DIR/usr/bin/$SCRIPT_NAME\"\n\n  # Install the manualls:\n  install -m \"$EXEC_PERM\" -d \"$SCRIPT_BUILD_DIR/usr/share/man/man1\"\n  install -m \"$EXEC_PERM\" -d \"$SCRIPT_BUILD_DIR/usr/share/man/man7\"\n  for file in man/man1/*.1 ; do\n    install -D \"$dir_switch\" \\\n      -b -m \"$READ_PERM\" \"$dir_switch\" \"$file\" \\\n      \"$SCRIPT_BUILD_DIR/usr/share/$file\"\n  done\n  install -D \"$dir_switch\" \\\n    -b -m \"$READ_PERM\" \"$dir_switch\" 'man/man7/git-secret.7' \\\n    \"$SCRIPT_BUILD_DIR/usr/share/man/man7/git-secret.7\"\n}\n\n\nfunction build_package {\n  # Only requires `rpm`, `apk`, or `deb` as first argument:\n  local build_type=\"$1\"\n  local arch_type=\"${2:-all}\"\n\n  # coreutils is for sha256sum\n  # See https://github.com/jordansissel/fpm for docs:\n  fpm \\\n    --input-type 'dir' \\\n    --output-type \"$build_type\" \\\n    --chdir \"$SCRIPT_BUILD_DIR\" \\\n    --architecture \"$arch_type\" \\\n    --name \"$SCRIPT_NAME\" \\\n    --version \"$SCRIPT_VERSION\" \\\n    --description \"$SCRIPT_DESCRIPTION\" \\\n    --url 'https://git-secret.io' \\\n    --maintainer 'Nikita Sobolev (mail@sobolevn.me)' \\\n    --license 'MIT' \\\n    --depends 'bash' \\\n    --depends 'coreutils' \\\n    --depends 'gawk' \\\n    --depends 'git' \\\n    --depends 'gnupg' \\\n    --deb-no-default-config-files \\\n    .\n}\n\n\nfunction clean_up_files {\n  # Pre-installed files:\n  rm -rf \"${SCRIPT_BUILD_DIR:?}/usr\"\n  # nfpm configs:\n  rm -rf \"$SCRIPT_BUILD_DIR\"/*.yml\n}\n"
  },
  {
    "path": "utils/deb/build.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\n# shellcheck disable=SC1090,SC1091\nsource \"$SECRETS_PROJECT_ROOT/utils/build-utils.sh\"\n\npreinstall_files '-c'\n\n# Building .deb package:\ncd \"$SCRIPT_DEST_DIR\" && build_package 'deb'\n\n# Cleaning up:\nclean_up_files\n"
  },
  {
    "path": "utils/deb/deploy.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\nif [[ \"$SECRETS_DEPLOY_DRY_RUN\" == 1 ]]; then\n  echo 'dry-run finished'\n  exit 0\nfi\n\n# shellcheck disable=SC1090,SC1091\nsource \"$SECRETS_PROJECT_ROOT/utils/build-utils.sh\"\n\n# Artifactory location:\nreadonly BASE_API_URL='https://gitsecret.jfrog.io/artifactory'\n\n# This folder should contain just one `.dev` file:\nDEB_FILE_LOCATION=\"$(locate_release 'deb')\"\nDEB_FILE_NAME=\"$(basename \"$DEB_FILE_LOCATION\")\"\n\n\ncurl -sS \\\n  -u \"$SECRETS_ARTIFACTORY_CREDENTIALS\" \\\n  -XPUT \"$BASE_API_URL/git-secret-deb/$DEB_FILE_NAME;deb.distribution=git-secret;deb.component=main;deb.architecture=all\" \\\n  -T \"$DEB_FILE_LOCATION\"\n\n# Now, we need to trigger metadata reindex:\ncurl -sS \\\n  -u \"$SECRETS_ARTIFACTORY_CREDENTIALS\" \\\n  -XPOST \"$BASE_API_URL/api/deb/reindex/git-secret-deb\"\n\necho\necho \"Done: released $DEB_FILE_NAME\"\n"
  },
  {
    "path": "utils/deb/install.sh",
    "content": "sudo sh -c \"echo 'deb https://gitsecret.jfrog.io/artifactory/git-secret-deb git-secret main' >> /etc/apt/sources.list\"\nwget -qO - 'https://gitsecret.jfrog.io/artifactory/api/gpg/key/public' | sudo apt-key add -\nsudo apt-get update && sudo apt-get install -y git-secret\n\n# Testing, that it worked:\ngit secret --version\n"
  },
  {
    "path": "utils/install.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\n\n# Credit goes to:\n# https://github.com/sstephenson/bats/blob/master/install.sh\nfunction resolve_link {\n  $(type -p greadlink readlink | head -1) \"$1\"\n}\n\n\nfunction abs_dirname {\n  local cwd\n  local path=\"$1\"\n\n  cwd=\"$(pwd)\"\n\n\n  while [ -n \"$path\" ]; do\n    cd \"${path%/*}\"\n    local name=\"${path##*/}\"\n    path=\"$(resolve_link \"$name\" || true)\"\n  done\n\n  pwd\n  cd \"$cwd\"\n}\n\n\nPREFIX=\"$1\"\nif [ -z \"$PREFIX\" ]; then\n  echo \"usage: $0 <prefix>\" >&2\n  exit 1\nfi\n\nSCRIPT_ROOT=\"$(dirname \"$(abs_dirname \"$0\")\")\"\n\nmkdir -p \"$PREFIX\"/bin \"$PREFIX\"/share/man/man1 \"$PREFIX\"/share/man/man7\ncp \"$SCRIPT_ROOT\"/git-secret \"$PREFIX\"/bin/git-secret\n\n# There was an issue with this line:\n# cp -R \"$SCRIPT_ROOT\"/man/man1/* \"$PREFIX\"/share/man/man1\n# see https://github.com/sobolevn/git-secret/issues/35 for reference.\nfind \"$SCRIPT_ROOT\"/man/man1 -name '*.1' -print0 | xargs -0 -I {} cp \\\n  -a {} \"$PREFIX\"/share/man/man1\ncp \"$SCRIPT_ROOT\"/man/man7/git-secret.7 \"$PREFIX\"/share/man/man7/git-secret.7\n\necho \"Installed git-secret to ${PREFIX}/bin/git-secret\"\n"
  },
  {
    "path": "utils/rpm/build.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\n# shellcheck disable=SC1090,SC1091\nsource \"$SECRETS_PROJECT_ROOT/utils/build-utils.sh\"\n\n# Copying all the required files to the build directory:\npreinstall_files '-c'\n\n# Building .rpm package:\ncd \"$SCRIPT_DEST_DIR\" && build_package 'rpm'\n\n# Cleaning up:\nclean_up_files\n"
  },
  {
    "path": "utils/rpm/deploy.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\nif [[ \"$SECRETS_DEPLOY_DRY_RUN\" == 1 ]]; then\n  echo 'dry-run finished'\n  exit 0\nfi\n\n# shellcheck disable=SC1090,SC1091\nsource \"$SECRETS_PROJECT_ROOT/utils/build-utils.sh\"\n\n# Artifactory location:\nreadonly BASE_API_URL='https://gitsecret.jfrog.io/artifactory'\n\n# This folder should contain just one `.rpm` file:\nRPM_FILE_LOCATION=\"$(locate_release 'rpm')\"\nRPM_FILE_NAME=\"$(basename \"$RPM_FILE_LOCATION\")\"\n\n\ncurl -sS \\\n  -u \"$SECRETS_ARTIFACTORY_CREDENTIALS\" \\\n  -XPUT \"$BASE_API_URL/git-secret-rpm/rpm/$RPM_FILE_NAME\" \\\n  -T \"$RPM_FILE_LOCATION\"\n\n# Now, we need to trigger metadata reindex:\ncurl -sS \\\n  -u \"$SECRETS_ARTIFACTORY_CREDENTIALS\" \\\n  -XPOST \"$BASE_API_URL/api/yum/git-secret-rpm?async=1\"\n\necho\necho \"Done: released $RPM_FILE_NAME\"\n"
  },
  {
    "path": "utils/rpm/git-secret.repo",
    "content": "[git-secret-rpm]\nname=git-secret-rpm\nbaseurl=https://gitsecret.jfrog.io/artifactory/git-secret-rpm\nenabled=1\ngpgcheck=0\n\n## Uncomment the following lines to enable repository-level GPG key check:\n# gpgkey=https://gitsecret.jfrog.io/artifactory/git-secret-rpm/repodata/repomd.xml.key\n# repo_gpgcheck=1\n"
  },
  {
    "path": "utils/rpm/install.sh",
    "content": "wget https://raw.githubusercontent.com/sobolevn/git-secret/master/utils/rpm/git-secret.repo -O git-secret-rpm.repo\n# Inspect what's inside! You can also enable `gpg` check on repo level.\nsudo mv git-secret-rpm.repo /etc/yum.repos.d/\nsudo yum install -y git-secret\n\n# Testing, that it worked:\ngit secret --version\n"
  },
  {
    "path": "utils/tests.sh",
    "content": "#!/usr/bin/env bash\n\n# `SECRETS_PROJECT_ROOT` must be set before running the script.\n\nset -e\n\nTEST_DIR=\"/tmp/git-secret-test/this dir has spaces\"\n\nrm -rf \"${TEST_DIR}\"\nmkdir -p \"${TEST_DIR}\"\necho \"# created dir: ${TEST_DIR}\"\n\nchmod 0700 \"${TEST_DIR}\"\n(\n    cd \"$TEST_DIR\"\n\n    # test with non-standard SECRETS_DIR (normally .gitsecret)\n    # and SECRETS_EXTENSION (normally .secret)\n    export SECRETS_DIR='.gitsec'\n    export SECRETS_EXTENSION='.sec'\n\n    export TMPDIR=\"$TEST_DIR\"\n    echo \"# TMPDIR is $TMPDIR\"\n\n    # bats expects diagnostic lines to be sent to fd 3, matching regex '^# '\n    #  (IE, like: `echo '# message here' >&3`).\n    # bats ... 3>&1 shows diagnostic output\n    bats \"${SECRETS_PROJECT_ROOT}/tests\" 3>&1\n)\n\nrm -rf \"${TEST_DIR}\"\n"
  },
  {
    "path": "utils/uninstall.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\n\nreadonly PREFIX=\"$1\"\nif [ -z \"$PREFIX\" ]; then\n  echo \"usage: $0 <prefix>\" >&2\n  exit 1\nfi\n\n# Binary:\nrm -f \"$PREFIX\"/bin/git-secret\n\n# Manuals:\nfind \"$PREFIX\"/share/man/man1 -type f -name 'git-secret-*.1' -exec rm -f {} \\;\nrm -f \"$PREFIX\"/share/man/man7/git-secret.7\n"
  },
  {
    "path": "vendor/README.md",
    "content": "README for git-secret/vendor directory\n\nWe import bats-core here for\nhttps://github.com/sobolevn/git-secret/issues/377,\n\"Don't depend on network during builds (re: bats-core)\"\n\nIf you want upgrade bats-core used by git-secret, replace the files in vendor/bats-core.\nThey must remain exactly as distributed by the chosen release of bats-core\n- see issue linked above for details.\n\n"
  },
  {
    "path": "vendor/bats-core/.devcontainer/Dockerfile",
    "content": "ARG bashver=latest\n\nFROM bash:${bashver}\n\n# Install parallel and accept the citation notice (we aren't using this in a\n# context where it make sense to cite GNU Parallel).\nRUN echo \"@edgecomm http://dl-cdn.alpinelinux.org/alpine/edge/community\"  >> /etc/apk/repositories && \\\n    apk update && \\\n    apk add --no-cache parallel ncurses shellcheck@edgecomm && \\\n    mkdir -p ~/.parallel && touch ~/.parallel/will-cite\n\nRUN ln -s /opt/bats/bin/bats /usr/sbin/bats\nCOPY . /opt/bats/\n\nENTRYPOINT [\"bash\", \"/usr/sbin/bats\"]\n"
  },
  {
    "path": "vendor/bats-core/.devcontainer/devcontainer.json",
    "content": "{\n    \"name\": \"Bats core development environment\",\n    \"dockerFile\": \"Dockerfile\",\n    \"build\": {\"args\": {\"bashver\": \"4.3\"}}\n}"
  },
  {
    "path": "vendor/bats-core/.editorconfig",
    "content": "root = true\n\n[*]\nend_of_line = lf\nindent_style = space\nindent_size = 2\ninsert_final_newline = true\nmax_line_length = 80\ntrim_trailing_whitespace = true\n\n# The JSON files contain newlines inconsistently\n[*.json]\nindent_size = 2\ninsert_final_newline = ignore\n\n# YAML\n[*.{yml,yaml}]\nindent_style = space\nindent_size = 2\n\n# Makefiles always use tabs for recipe indentation\n[{Makefile,*.mak}]\nindent_style = tab\n\n# Markdown\n[*.{md,rmd,mkd,mkdn,mdwn,mdown,markdown,litcoffee}]\nmax_line_length = 80\n# tabs behave as if they were replaced by spaces with a tab stop of 4 characters\ntab_width = 4\n# trailing spaces indicates word wrap\ntrim_trailing_spaces = false\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": "vendor/bats-core/.gitattributes",
    "content": "* text=auto\n*.sh eol=lf\nlibexec/* eol=lf\n"
  },
  {
    "path": "vendor/bats-core/.github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: 'Type: Bug'\nassignees: ''\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Environment (please complete the following information):**\n - Bats Version [e.g. 1.4.0 or commit hash]\n - OS: [e.g. Linux, FreeBSD, MacOS]\n - Bash version: [e.g. 5.1]\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": "vendor/bats-core/.github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: 'Type: Enhancement'\nassignees: ''\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context about the feature request here.\n"
  },
  {
    "path": "vendor/bats-core/.github/workflows/check_pr_label.sh",
    "content": "#!/usr/bin/bash\n\nget_pr_json() {\n    curl -s -H \"Accept: application/vnd.github.v3+json\" \"https://api.github.com/repos/bats-core/bats-core/pulls/$1\"\n}\n\nPR_NUMBER=\"$1\"\nLABEL=\"$2\"\n\nget_pr_json \"$PR_NUMBER\" | jq .labels[].name | grep \"$LABEL\"\n"
  },
  {
    "path": "vendor/bats-core/.github/workflows/release.yml",
    "content": "name: Release\n\non:\n  release: { types: [published] }\n  workflow_dispatch:\n\njobs:\n  npmjs:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - uses: actions/setup-node@v2\n        with:\n          registry-url: \"https://registry.npmjs.org\"\n      - run: npm publish --ignore-scripts\n        env:\n          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}\n\n  github-npm:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - uses: actions/setup-node@v2\n        with:\n          registry-url: \"https://npm.pkg.github.com\"\n      - name: scope package name as required by GHPR\n        run: npm init -y --scope ${{ github.repository_owner }}\n      - run: npm publish --ignore-scripts\n        env:\n          NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": "vendor/bats-core/.github/workflows/release_dockerhub.yml",
    "content": "name: Release to docker hub\n\non:\n  release: { types: [published] }\n  workflow_dispatch:\n    inputs:\n        version:\n          description: 'Version to simulate for deploy'\n          required: true\n\njobs:\n    dockerhub:\n        runs-on: ubuntu-latest\n        steps:\n        - uses: actions/checkout@v2\n        - id: version\n          run: |\n            EXPECTED_VERSION=${{ github.event.inputs.version }}\n            TAG_VERSION=${GITHUB_REF#refs/tags/v} # refs/tags/v1.2.3 -> 1.2.3\n            echo ::set-output name=version::${EXPECTED_VERSION:-$TAG_VERSION}\n        -\n          name: Set up QEMU\n          uses: docker/setup-qemu-action@v1\n        -\n          name: Login to DockerHub\n          uses: docker/login-action@v1 \n          with:\n            username: ${{ secrets.DOCKER_USERNAME }}\n            password: ${{ secrets.DOCKER_PASSWORD }}\n        -\n          name: Set up Docker Buildx\n          id: buildx\n          uses: docker/setup-buildx-action@v1\n        - uses: docker/build-push-action@v2\n          with:\n            platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/s390x,linux/386,linux/arm/v7,linux/arm/v6\n            tags: ${{ secrets.DOCKER_USERNAME }}/bats:${{ steps.version.outputs.version }},${{ secrets.DOCKER_USERNAME }}/bats:latest\n            push: true\n"
  },
  {
    "path": "vendor/bats-core/.github/workflows/tests.yml",
    "content": "name: Tests\n\n# Controls when the action will run. \non: [push, pull_request, workflow_dispatch]\n\njobs:\n  changelog:\n    runs-on: ubuntu-20.04\n    steps:\n      - uses: actions/checkout@v2\n      - name: Check that PR is mentioned in Changelog\n        run: |\n          if ! ./.github/workflows/check_pr_label.sh \"${{github.event.pull_request.number}}\" \"no changelog\"; then\n            grep \"#${{github.event.pull_request.number}}\" docs/CHANGELOG.md\n          fi\n    if: ${{github.event.pull_request}}\n  shellcheck:\n    runs-on: ubuntu-20.04\n    steps:\n      - uses: actions/checkout@v2\n      - name: Run shellcheck\n        run: |\n          sudo apt-get update -y\n          sudo apt-get install shellcheck\n          ./shellcheck.sh\n\n  linux:\n    strategy:\n      matrix:\n        os: ['ubuntu-20.04', 'ubuntu-18.04']\n        env_vars:\n          - ''\n          # allow for some parallelity without GNU parallel, since it is not installed by default\n          - 'BATS_NO_PARALLELIZE_ACROSS_FILES=1 BATS_NUMBER_OF_PARALLEL_JOBS=2'\n    runs-on: ${{ matrix.os }}\n    steps:\n      - uses: actions/checkout@v2\n      - name: Run test on OS ${{ matrix.os }}\n        shell: 'script -q -e -c \"bash {0}\"' # work around tty issues\n        env:\n          TERM: linux # fix tput for tty issue work around\n        run: |\n          bash --version\n          bash -c \"time ${{ matrix.env_vars }} bin/bats  --print-output-on-failure --formatter tap test\"\n\n  npm_on_linux:\n    strategy:\n      matrix:\n        os: ['ubuntu-20.04', 'ubuntu-18.04']\n    runs-on: ${{ matrix.os }}\n    steps:\n      - uses: actions/checkout@v2\n      - uses: actions/setup-node@v2\n      - name: Run test on OS ${{ matrix.os }}\n        shell: 'script -q -e -c \"bash {0}\"' # work around tty issues\n        env:\n          TERM: linux # fix tput for tty issue work around\n        run: |\n          npm pack ./\n          sudo npm install -g ./bats-*.tgz\n          bats test  \n\n  windows:\n    runs-on: windows-2019\n    steps:\n      - uses: actions/checkout@v2\n      - run: |\n          bash --version\n          bash -c \"time bin/bats  --print-output-on-failure --formatter tap test\"\n\n  npm_on_windows:\n    strategy:\n      matrix:\n        os: ['windows-2019']\n    runs-on: ${{ matrix.os }}\n    steps:\n      - uses: actions/checkout@v2\n      - uses: actions/setup-node@v2\n      - run: npm pack ./\n      - run: npm install -g (get-item .\\bats-*.tgz).FullName\n      - run: bats  -T --print-output-on-failure test        \n\n  macos:\n    strategy:\n      matrix:\n        os: ['macos-10.15']\n        env_vars:\n          - ''\n          # allow for some parallelity without GNU parallel, since it is not installed by default\n          - 'BATS_NO_PARALLELIZE_ACROSS_FILES=1 BATS_NUMBER_OF_PARALLEL_JOBS=2'\n    runs-on: ${{ matrix.os }}\n    steps:\n      - uses: actions/checkout@v2\n      - name: Install unbuffer via expect\n        run: brew install expect\n      - name: Run test on OS ${{ matrix.os }}\n        shell: 'unbuffer bash {0}' # work around tty issues\n        env:\n          TERM: linux # fix tput for tty issue work around\n        run: |\n          bash --version\n          bash -c \"time ${{ matrix.env_vars }} bin/bats  --print-output-on-failure --formatter tap test\"\n\n  npm_on_macos:\n    strategy:\n      matrix:\n        os: ['macos-10.15']\n    runs-on: ${{ matrix.os }}\n    steps:\n      - uses: actions/checkout@v2\n      - uses: actions/setup-node@v2\n      - name: Install unbuffer via expect\n        run: brew install expect\n      - name: Run test on OS ${{ matrix.os }}\n        shell: 'unbuffer bash {0}' # work around tty issues\n        env:\n          TERM: linux # fix tput for tty issue work around\n        run: |\n          npm pack ./\n          # somehow there is already an intalled bats version around\n          npm install --force -g ./bats-*.tgz\n          bats  --print-output-on-failure test  \n\n  bash-version:\n    strategy:\n      matrix:\n        version: ['3.2', '4.0', '4.1', '4.2', '4.3', '4.4', '4', '5.0', '5.1', '5', 'latest']\n        env_vars:\n            - ''\n            # also test running (recursively!) in parallel\n            - '-e BATS_NUMBER_OF_PARALLEL_JOBS=2'\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - name: Run test on bash version ${{ matrix.version }}\n        shell: 'script -q -e -c \"bash {0}\"' # work around tty issues\n        run: |\n          set -e\n          docker build --build-arg bashver=\"${{ matrix.version }}\" --tag \"bats/bats:bash-${{ matrix.version }}\" .\n          docker run -it \"bash:${{ matrix.version }}\" --version\n          time docker run -it ${{ matrix.env_vars }} \"bats/bats:bash-${{ matrix.version }}\"  --print-output-on-failure --tap /opt/bats/test\n  \n  alpine:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - name: Run test on bash version ${{ matrix.version }}\n        shell: 'script -q -e -c \"bash {0}\"' # work around tty issues\n        run: |\n          set -e\n          time docker run -it -v $PWD:/opt/bats alpine sh -c \"apk add bash ncurses; /opt/bats/bin/bats  --print-output-on-failure --tap /opt/bats/test\"\n\n  freebsd:\n    runs-on: macos-10.15\n    strategy:\n      matrix:\n        packages:\n          - flock\n          - \"\"\n    steps:\n      - uses: actions/checkout@v2\n      - uses: vmactions/freebsd-vm@v0.1.5\n        with:\n          prepare: pkg install -y bash parallel ${{ matrix.packages }}\n          run: |\n            time ./bin/bats --print-output-on-failure test/\n    \n"
  },
  {
    "path": "vendor/bats-core/.gitignore",
    "content": "/docker-compose.override.yml\n/docs/build\n\n# npm\n/bats-*.tgz\n# we don't have any deps; un-ignore if that changes\n/package-lock.json\n"
  },
  {
    "path": "vendor/bats-core/.readthedocs.yml",
    "content": "version: 2\n\nsphinx:\n  configuration: docs/source/conf.py\n\npython:\n  version: 3.7\n  install:\n    - requirements: docs/source/requirements.txt"
  },
  {
    "path": "vendor/bats-core/AUTHORS",
    "content": "Andrew Martin (https://control-plane.io/)\nBianca Tamayo <hi@biancatamayo.me> (https://biancatamayo.me/)\nJason Karns <jason.karns@gmail.com> (http://jasonkarns.com/)\nMike Bland <mbland@acm.org> (https://mike-bland.com/)\n"
  },
  {
    "path": "vendor/bats-core/Dockerfile",
    "content": "ARG bashver=latest\n\nFROM bash:${bashver}\nARG TINI_VERSION=v0.19.0\nARG TARGETPLATFORM\n\nCOPY ./docker /tmp/docker\n# default to amd64 when not running in buildx environment that provides target platform\nRUN /tmp/docker/install_tini.sh \"${TARGETPLATFORM-linux/amd64}\"\n    \n\n# Install parallel and accept the citation notice (we aren't using this in a\n# context where it make sense to cite GNU Parallel).\nRUN apk add --no-cache parallel ncurses && \\\n    mkdir -p ~/.parallel && touch ~/.parallel/will-cite\n\nRUN ln -s /opt/bats/bin/bats /usr/local/bin/bats\nCOPY . /opt/bats/\n\nRUN mkdir -p /code\nWORKDIR /code/\n\nENTRYPOINT [\"/tini\", \"--\", \"bash\", \"bats\"]\n"
  },
  {
    "path": "vendor/bats-core/LICENSE.md",
    "content": "Copyright (c) 2017 bats-core contributors\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---\n\n* [bats-core] is a continuation of [bats]. Copyright for portions of the\n  bats-core project are held by Sam Stephenson, 2014 as part of the project\n  [bats], licensed under MIT:\n\nCopyright (c) 2014 Sam Stephenson\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nFor details, please see the [version control history][commits].\n\n[bats-core]: https://github.com/bats-core/bats-core\n[bats]:https://github.com/sstephenson/bats\n[commits]:https://github.com/bats-core/bats-core/commits/master\n"
  },
  {
    "path": "vendor/bats-core/README.md",
    "content": "# Bats-core: Bash Automated Testing System (2018)\n\n[![Latest release](https://img.shields.io/github/release/bats-core/bats-core.svg)](https://github.com/bats-core/bats-core/releases/latest)\n[![npm package](https://img.shields.io/npm/v/bats.svg)](https://www.npmjs.com/package/bats)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/bats-core/bats-core/blob/master/LICENSE.md)\n[![Continuous integration status](https://github.com/bats-core/bats-core/workflows/Tests/badge.svg)](https://github.com/bats-core/bats-core/actions?query=workflow%3ATests)\n[![Read the docs status](https://readthedocs.org/projects/bats-core/badge/)](https://bats-core.readthedocs.io)\n\n[![Join the chat in bats-core/bats-core on gitter](https://badges.gitter.im/bats-core/bats-core.svg)][gitter]\n\nBats is a [TAP](https://testanything.org/)-compliant testing framework for Bash.  It provides a simple\nway to verify that the UNIX programs you write behave as expected.\n\nA Bats test file is a Bash script with special syntax for defining test cases.\nUnder the hood, each test case is just a function with a description.\n\n```bash\n#!/usr/bin/env bats\n\n@test \"addition using bc\" {\n  result=\"$(echo 2+2 | bc)\"\n  [ \"$result\" -eq 4 ]\n}\n\n@test \"addition using dc\" {\n  result=\"$(echo 2 2+p | dc)\"\n  [ \"$result\" -eq 4 ]\n}\n```\n\nBats is most useful when testing software written in Bash, but you can use it to\ntest any UNIX program.\n\nTest cases consist of standard shell commands. Bats makes use of Bash's\n`errexit` (`set -e`) option when running test cases. If every command in the\ntest case exits with a `0` status code (success), the test passes. In this way,\neach line is an assertion of truth.\n\n## Table of contents\n\n**NOTE** The documentation has moved to <https://bats-core.readthedocs.io>\n\n<!-- toc -->\n\n- [Testing](#testing)\n- [Support](#support)\n- [Contributing](#contributing)\n- [Contact](#contact)\n- [Version history](#version-history)\n- [Background](#background)\n  * [What's the plan and why?](#whats-the-plan-and-why)\n  * [Why was this fork created?](#why-was-this-fork-created)\n- [Copyright](#copyright)\n\n<!-- tocstop -->\n\n## Testing\n\n```sh\nbin/bats --tap test\n```\n\nSee also the [CI](./.github/workflows/tests.yml) settings for the current test environment and\nscripts.\n\n## Support\n\nThe Bats source code repository is [hosted on\nGitHub](https://github.com/bats-core/bats-core). There you can file bugs on the\nissue tracker or submit tested pull requests for review.\n\nFor real-world examples from open-source projects using Bats, see [Projects\nUsing Bats](https://github.com/bats-core/bats-core/wiki/Projects-Using-Bats) on\nthe wiki.\n\nTo learn how to set up your editor for Bats syntax highlighting, see [Syntax\nHighlighting](https://github.com/bats-core/bats-core/wiki/Syntax-Highlighting)\non the wiki.\n\n## Contributing\n\nFor now see the [`docs`](docs) folder for project guides, work with us on the wiki\nor look at the other communication channels.\n\n## Contact\n\n- You can find and chat with us on our [Gitter].\n\n## Version history\n\nSee `docs/CHANGELOG.md`.\n\n## Background\n\n<!-- markdownlint-disable MD026 -->\n### What's the plan and why?\n<!-- markdownlint-enable MD026 -->\n\n**Tuesday, September 19, 2017:** This was forked from [Bats][bats-orig] at\ncommit [0360811][].  It was created via `git clone --bare` and `git push\n--mirror`.\n\n[bats-orig]: https://github.com/sstephenson/bats\n[0360811]: https://github.com/sstephenson/bats/commit/03608115df2071fff4eaaff1605768c275e5f81f\n\nThis [bats-core repo](https://github.com/bats-core/bats-core) is the community-maintained Bats project.\n\n<!-- markdownlint-disable MD026 -->\n### Why was this fork created?\n<!-- markdownlint-enable MD026 -->\n\nThere was an initial [call for maintainers][call-maintain] for the original Bats repository, but write access to it could not be obtained. With development activity stalled, this fork allowed ongoing maintenance and forward progress for Bats.\n\n[call-maintain]: https://github.com/sstephenson/bats/issues/150\n\n## Copyright\n\n© 2017-2021 bats-core organization\n\n© 2011-2016 Sam Stephenson\n\nBats is released under an MIT-style license; see `LICENSE.md` for details.\n\nSee the [parent project](https://github.com/bats-core) at GitHub or the\n[AUTHORS](AUTHORS) file for the current project maintainer team.\n\n[gitter]: https://gitter.im/bats-core/bats-core\n"
  },
  {
    "path": "vendor/bats-core/bin/bats",
    "content": "#!/usr/bin/env bash\n\nset -euo pipefail\n\nif command -v greadlink >/dev/null; then\n  bats_readlinkf() {\n    greadlink -f \"$1\"\n  }\nelse\n  bats_readlinkf() {\n    readlink -f \"$1\"\n  }\nfi\n\nfallback_to_readlinkf_posix() {\n  bats_readlinkf() {\n    [ \"${1:-}\" ] || return 1\n    max_symlinks=40\n    CDPATH='' # to avoid changing to an unexpected directory\n\n    target=$1\n    [ -e \"${target%/}\" ] || target=${1%\"${1##*[!/]}\"} # trim trailing slashes\n    [ -d \"${target:-/}\" ] && target=\"$target/\"\n\n    cd -P . 2>/dev/null || return 1\n    while [ \"$max_symlinks\" -ge 0 ] && max_symlinks=$((max_symlinks - 1)); do\n      if [ ! \"$target\" = \"${target%/*}\" ]; then\n        case $target in\n          /*) cd -P \"${target%/*}/\" 2>/dev/null || break ;;\n          *) cd -P \"./${target%/*}\" 2>/dev/null || break ;;\n        esac\n        target=${target##*/}\n      fi\n\n      if [ ! -L \"$target\" ]; then\n        target=\"${PWD%/}${target:+/}${target}\"\n        printf '%s\\n' \"${target:-/}\"\n        return 0\n      fi\n\n      # `ls -dl` format: \"%s %u %s %s %u %s %s -> %s\\n\",\n      #   <file mode>, <number of links>, <owner name>, <group name>,\n      #   <size>, <date and time>, <pathname of link>, <contents of link>\n      # https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html\n      link=$(ls -dl -- \"$target\" 2>/dev/null) || break\n      target=${link#*\" $target -> \"}\n    done\n    return 1\n  }\n}\n\nif ! BATS_PATH=$(bats_readlinkf \"${BASH_SOURCE[0]}\" 2>/dev/null); then\n  fallback_to_readlinkf_posix\n  BATS_PATH=$(bats_readlinkf \"${BASH_SOURCE[0]}\")\nfi\n\nexport BATS_ROOT=${BATS_PATH%/*/*}\nexport -f bats_readlinkf\nexec env BATS_ROOT=\"$BATS_ROOT\" \"$BATS_ROOT/libexec/bats-core/bats\" \"$@\"\n"
  },
  {
    "path": "vendor/bats-core/contrib/release.sh",
    "content": "#!/usr/bin/env bash\n#\n# bats-core git releaser\n#\n## Usage: %SCRIPT_NAME% [options]\n##\n## Options:\n##   --major            Major version bump\n##   --minor            Minor version bump\n##   --patch            Patch version bump\n##\n##   -v, --version      Print version\n##   --debug            Enable debug mode\n##   -h, --help         Display this message\n##\n\nset -Eeuo pipefail\n\nDIR=$(cd \"$(dirname \"${0}\")\" && pwd)\nTHIS_SCRIPT=\"${DIR}/$(basename \"${0}\")\"\nBATS_VERSION=$(\n  # shellcheck disable=SC1090\n  source <(grep '^export BATS_VERSION=' libexec/bats-core/bats)\n  echo \"${BATS_VERSION}\"\n)\ndeclare -r DIR\ndeclare -r THIS_SCRIPT\ndeclare -r BATS_VERSION\n\nBUMP_INTERVAL=\"\"\nNEW_BATS_VERSION=\"\"\n\nmain() {\n  handle_arguments \"${@}\"\n\n  if [[ \"${BUMP_INTERVAL:-}\" == \"\" ]]; then\n    echo \"${BATS_VERSION}\"\n    exit 0\n  fi\n\n  local NEW_BATS_VERSION\n  NEW_BATS_VERSION=$(semver bump \"${BUMP_INTERVAL}\" \"${BATS_VERSION}\")\n  declare -r NEW_BATS_VERSION\n\n  local BATS_RELEASE_NOTES=\"/tmp/bats-release-${NEW_BATS_VERSION}\"\n\n  echo \"Releasing: ${BATS_VERSION} to ${NEW_BATS_VERSION}\"\n  echo\n\n  echo \"Ensure docs/CHANGELOG.md is correctly updated\"\n\n  replace_in_files\n\n  write_changelog\n\n  git diff --staged\n\n  cat <<EOF\n1. Version numbers have been updated. Commit the changes:\n\ngit commit -m \"feat: release Bats v${NEW_BATS_VERSION}\"\n\n2. Verify this autogenerated changelog (from docs/CHANGELOG.md):\n\n# changelog start\nEOF\n\nlocal DELIM\nDELIM=$(echo -en \"\\001\");\nsed -E -n \"\\\\${DELIM}^## \\[${NEW_BATS_VERSION}\\]${DELIM},\\\\${DELIM}^## ${DELIM}p\" docs/CHANGELOG.md \\\n  | head -n -1 \\\n  | sed -E \\\n    -e 's,^## \\[([0-9\\.]+)] - (.*),Bats \\1\\n\\nReleased: \\2,' \\\n    -e 's,^### (.*),\\1:,g' \\\n  | tee \"${BATS_RELEASE_NOTES}\"\n\n  cat <<EOF\n# changelog end\n\n3. Tag the release using the autogenerated changelog:\n\ngit tag -a -s \"v${NEW_BATS_VERSION}\" --message \"${BATS_RELEASE_NOTES}\"\n\n4. Push the changes:\n\ngit push --follow-tags\n\n5. Use Github hub to make a draft release:\n\nhub release create \"v${NEW_BATS_VERSION}\" --draft --file \"${BATS_RELEASE_NOTES}\"\n\n6. Navigate to the provided URL, verify changes, and release Bats ${NEW_BATS_VERSION}.\nEOF\n\n  exit 0\n}\n\nreplace_in_files() {\n  declare -a FILE_REPLACEMENTS=(\n    \"contrib/rpm/bats.spec,^Version:\"\n    \"libexec/bats-core/bats,^export BATS_VERSION=\"\n    \"package.json,^  \\\"version\\\":\"\n  )\n\n  for FILE_REPLACEMENT in \"${FILE_REPLACEMENTS[@]}\"; do\n    FILE=\"${FILE_REPLACEMENT/,*/}\"\n    MATCH=\"${FILE_REPLACEMENT/*,/}\"\n    sed -E -i.bak \"/${MATCH}/ { s,${BATS_VERSION},${NEW_BATS_VERSION},g; }\" \"${FILE}\"\n    rm \"${FILE}.bak\" || true\n    git add -f \"${FILE}\"\n  done\n}\n\nwrite_changelog() {\n  local FILE=\"docs/CHANGELOG.md\"\n  sed -E -i.bak \"/## \\[Unreleased\\]/ a \\\\\\n## [${NEW_BATS_VERSION}] - $(date +%Y-%m-%d)\" \"${FILE}\"\n\n  rm \"${FILE}.bak\" || true\n\n  cp \"${FILE}\" \"${FILE}.new\"\n  sed -E -i.bak '/## \\[Unreleased\\]/,+1d' \"${FILE}\"\n  git add -f \"${FILE}\"\n  mv \"${FILE}.new\" \"${FILE}\"\n}\n\nhandle_arguments() {\n  parse_arguments \"${@:-}\"\n}\n\nparse_arguments() {\n  local CURRENT_ARG\n\n  if [[ \"${#}\" == 1 && \"${1:-}\" == \"\" ]]; then\n    return 0\n  fi\n\n  while [[ \"${#}\" -gt 0 ]]; do\n    CURRENT_ARG=\"${1}\"\n\n    case ${CURRENT_ARG} in\n    --major)\n      BUMP_INTERVAL=\"major\"\n      ;;\n    # ---\n    --minor)\n      BUMP_INTERVAL=\"minor\"\n      ;;\n    --patch)\n      BUMP_INTERVAL=\"patch\"\n      ;;\n    -h | --help) usage ;;\n    -v | --version)\n      get_version\n      exit 0\n      ;;\n    --debug)\n      set -xe\n      ;;\n    -*) usage \"${CURRENT_ARG}: unknown option\" ;;\n    esac\n    shift\n  done\n}\n\nsemver() {\n  \"${DIR}/semver\" \"${@:-}\"\n}\n\nusage() {\n  sed -n '/^##/,/^$/s/^## \\{0,1\\}//p' \"${THIS_SCRIPT}\" | sed \"s/%SCRIPT_NAME%/$(basename \"${THIS_SCRIPT}\")/g\"\n  exit 2\n} 2>/dev/null\n\nget_version() {\n  echo \"${THIS_SCRIPT_VERSION:-0.1}\"\n}\n\nmain \"${@}\"\n"
  },
  {
    "path": "vendor/bats-core/contrib/rpm/bats.spec",
    "content": "%global provider        github.com\n%global project         bats-core\n%global repo            bats-core\n\nName:           bats\nVersion:        1.6.0\nRelease:        1%{?dist}\nSummary:        Bash Automated Testing System\n\nGroup:          Development/Libraries\nLicense:        MIT\nURL:            https://%{provider}/%{project}/%{repo}\nSource0:        https://%{provider}/%{project}/%{repo}/archive/v%{version}.tar.gz\n\nBuildArch:      noarch\n\nRequires:       bash\n\n%description\nBats is a TAP-compliant testing framework for Bash.\nIt provides a simple way to verify that the UNIX programs you write behave as expected.\nBats is most useful when testing software written in Bash, but you can use it to test any UNIX program.\n\n%prep\n%setup -q -n %{repo}-%{version}\n\n%install\nmkdir -p ${RPM_BUILD_ROOT}%{_prefix} ${RPM_BUILD_ROOT}%{_libexecdir} ${RPM_BUILD_ROOT}%{_mandir}\n./install.sh ${RPM_BUILD_ROOT}%{_prefix}\n\n%clean\nrm -rf $RPM_BUILD_ROOT\n\n%check\n\n%files\n%doc README.md LICENSE.md\n%{_bindir}/%{name}\n%{_libexecdir}/%{repo}\n%{_mandir}/man1/%{name}.1.gz\n%{_mandir}/man7/%{name}.7.gz\n\n%changelog\n* Tue Jul 08 2018 mbland <mbland@acm.org> - 1.1.0-1\n- Increase version to match upstream release\n\n* Mon Jun 18 2018 pixdrift <support@pixeldrift.net> - 1.0.2-1\n- Increase version to match upstream release\n- Relocate libraries to bats-core subdirectory\n\n* Sat Jun 09 2018 pixdrift <support@pixeldrift.net> - 1.0.1-1\n- Increase version to match upstream release\n\n* Fri Jun 08 2018 pixdrift <support@pixeldrift.net> - 1.0.0-1\n- Initial package build of forked (bats-core) github project\n"
  },
  {
    "path": "vendor/bats-core/contrib/semver",
    "content": "#!/usr/bin/env bash\n\n# v3.0.0\n# https://github.com/fsaintjacques/semver-tool\n\nset -o errexit -o nounset -o pipefail\n\nNAT='0|[1-9][0-9]*'\nALPHANUM='[0-9]*[A-Za-z-][0-9A-Za-z-]*'\nIDENT=\"$NAT|$ALPHANUM\"\nFIELD='[0-9A-Za-z-]+'\n\nSEMVER_REGEX=\"\\\n^[vV]?\\\n($NAT)\\\\.($NAT)\\\\.($NAT)\\\n(\\\\-(${IDENT})(\\\\.(${IDENT}))*)?\\\n(\\\\+${FIELD}(\\\\.${FIELD})*)?$\"\n\nPROG=semver\nPROG_VERSION=\"3.0.0\"\n\nUSAGE=\"\\\nUsage:\n  $PROG bump (major|minor|patch|release|prerel <prerel>|build <build>) <version>\n  $PROG compare <version> <other_version>\n  $PROG get (major|minor|patch|release|prerel|build) <version>\n  $PROG --help\n  $PROG --version\n\nArguments:\n  <version>  A version must match the following regular expression:\n             \\\"${SEMVER_REGEX}\\\"\n             In English:\n             -- The version must match X.Y.Z[-PRERELEASE][+BUILD]\n                where X, Y and Z are non-negative integers.\n             -- PRERELEASE is a dot separated sequence of non-negative integers and/or\n                identifiers composed of alphanumeric characters and hyphens (with\n                at least one non-digit). Numeric identifiers must not have leading\n                zeros. A hyphen (\\\"-\\\") introduces this optional part.\n             -- BUILD is a dot separated sequence of identifiers composed of alphanumeric\n                characters and hyphens. A plus (\\\"+\\\") introduces this optional part.\n\n  <other_version>  See <version> definition.\n\n  <prerel>  A string as defined by PRERELEASE above.\n\n  <build>   A string as defined by BUILD above.\n\nOptions:\n  -v, --version          Print the version of this tool.\n  -h, --help             Print this help message.\n\nCommands:\n  bump     Bump by one of major, minor, patch; zeroing or removing\n           subsequent parts. \\\"bump prerel\\\" sets the PRERELEASE part and\n           removes any BUILD part. \\\"bump build\\\" sets the BUILD part.\n           \\\"bump release\\\" removes any PRERELEASE or BUILD parts.\n           The bumped version is written to stdout.\n\n  compare  Compare <version> with <other_version>, output to stdout the\n           following values: -1 if <other_version> is newer, 0 if equal, 1 if\n           older. The BUILD part is not used in comparisons.\n\n  get      Extract given part of <version>, where part is one of major, minor,\n           patch, prerel, build, or release.\n\nSee also:\n  https://semver.org -- Semantic Versioning 2.0.0\"\n\nfunction error {\n  echo -e \"$1\" >&2\n  exit 1\n}\n\nfunction usage-help {\n  error \"$USAGE\"\n}\n\nfunction usage-version {\n  echo -e \"${PROG}: $PROG_VERSION\"\n  exit 0\n}\n\nfunction validate-version {\n  local version=$1\n  if [[ \"$version\" =~ $SEMVER_REGEX ]]; then\n    # if a second argument is passed, store the result in var named by $2\n    if [ \"$#\" -eq \"2\" ]; then\n      local major=${BASH_REMATCH[1]}\n      local minor=${BASH_REMATCH[2]}\n      local patch=${BASH_REMATCH[3]}\n      local prere=${BASH_REMATCH[4]}\n      local build=${BASH_REMATCH[8]}\n      eval \"$2=(\\\"$major\\\" \\\"$minor\\\" \\\"$patch\\\" \\\"$prere\\\" \\\"$build\\\")\"\n    else\n      echo \"$version\"\n    fi\n  else\n    error \"version $version does not match the semver scheme 'X.Y.Z(-PRERELEASE)(+BUILD)'. See help for more information.\"\n  fi\n}\n\nfunction is-nat {\n    [[ \"$1\" =~ ^($NAT)$ ]]\n}\n\nfunction is-null {\n    [ -z \"$1\" ]\n}\n\nfunction order-nat {\n    [ \"$1\" -lt \"$2\" ] && { echo -1 ; return ; }\n    [ \"$1\" -gt \"$2\" ] && { echo 1 ; return ; }\n    echo 0\n}\n\nfunction order-string {\n    [[ $1 < $2 ]] && { echo -1 ; return ; }\n    [[ $1 > $2 ]] && { echo 1 ; return ; }\n    echo 0\n}\n\n# given two (named) arrays containing NAT and/or ALPHANUM fields, compare them\n# one by one according to semver 2.0.0 spec. Return -1, 0, 1 if left array ($1)\n# is less-than, equal, or greater-than the right array ($2).  The longer array\n# is considered greater-than the shorter if the shorter is a prefix of the longer.\n#\nfunction compare-fields {\n    local l=\"$1[@]\"\n    local r=\"$2[@]\"\n    local leftfield=( \"${!l}\" )\n    local rightfield=( \"${!r}\" )\n    local left\n    local right\n\n    local i=$(( -1 ))\n    local order=$(( 0 ))\n\n    while true\n    do\n        [ $order -ne 0 ] && { echo $order ; return ; }\n\n        : $(( i++ ))\n        left=\"${leftfield[$i]}\"\n        right=\"${rightfield[$i]}\"\n\n        is-null \"$left\" && is-null \"$right\" && { echo 0  ; return ; }\n        is-null \"$left\"                     && { echo -1 ; return ; }\n                           is-null \"$right\" && { echo 1  ; return ; }\n\n        is-nat \"$left\" &&  is-nat \"$right\" && { order=$(order-nat \"$left\" \"$right\") ; continue ; }\n        is-nat \"$left\"                     && { echo -1 ; return ; }\n                           is-nat \"$right\" && { echo 1  ; return ; }\n                                              { order=$(order-string \"$left\" \"$right\") ; continue ; }\n    done\n}\n\n# shellcheck disable=SC2206     # checked by \"validate\"; ok to expand prerel id's into array\nfunction compare-version {\n  local order\n  validate-version \"$1\" V\n  validate-version \"$2\" V_\n\n  # compare major, minor, patch\n\n  local left=( \"${V[0]}\" \"${V[1]}\" \"${V[2]}\" )\n  local right=( \"${V_[0]}\" \"${V_[1]}\" \"${V_[2]}\" )\n\n  order=$(compare-fields left right)\n  [ \"$order\" -ne 0 ] && { echo \"$order\" ; return ; }\n\n  # compare pre-release ids when M.m.p are equal\n\n  local prerel=\"${V[3]:1}\"\n  local prerel_=\"${V_[3]:1}\"\n  local left=( ${prerel//./ } )\n  local right=( ${prerel_//./ } )\n\n  # if left and right have no pre-release part, then left equals right\n  # if only one of left/right has pre-release part, that one is less than simple M.m.p\n\n  [ -z \"$prerel\" ] && [ -z \"$prerel_\" ] && { echo 0  ; return ; }\n  [ -z \"$prerel\" ]                      && { echo 1  ; return ; }\n                      [ -z \"$prerel_\" ] && { echo -1 ; return ; }\n\n  # otherwise, compare the pre-release id's\n\n  compare-fields left right\n}\n\nfunction command-bump {\n  local new; local version; local sub_version; local command;\n\n  case $# in\n    2) case $1 in\n        major|minor|patch|release) command=$1; version=$2;;\n        *) usage-help;;\n       esac ;;\n    3) case $1 in\n        prerel|build) command=$1; sub_version=$2 version=$3 ;;\n        *) usage-help;;\n       esac ;;\n    *) usage-help;;\n  esac\n\n  validate-version \"$version\" parts\n  # shellcheck disable=SC2154\n  local major=\"${parts[0]}\"\n  local minor=\"${parts[1]}\"\n  local patch=\"${parts[2]}\"\n  local prere=\"${parts[3]}\"\n  local build=\"${parts[4]}\"\n\n  case \"$command\" in\n    major) new=\"$((major + 1)).0.0\";;\n    minor) new=\"${major}.$((minor + 1)).0\";;\n    patch) new=\"${major}.${minor}.$((patch + 1))\";;\n    release) new=\"${major}.${minor}.${patch}\";;\n    prerel) new=$(validate-version \"${major}.${minor}.${patch}-${sub_version}\");;\n    build) new=$(validate-version \"${major}.${minor}.${patch}${prere}+${sub_version}\");;\n    *) usage-help ;;\n  esac\n\n  echo \"$new\"\n  exit 0\n}\n\nfunction command-compare {\n  local v; local v_;\n\n  case $# in\n    2) v=$(validate-version \"$1\"); v_=$(validate-version \"$2\") ;;\n    *) usage-help ;;\n  esac\n\n  set +u                        # need unset array element to evaluate to null\n  compare-version \"$v\" \"$v_\"\n  exit 0\n}\n\n\n# shellcheck disable=SC2034\nfunction command-get {\n    local part version\n\n    if [[ \"$#\" -ne \"2\" ]] || [[ -z \"$1\" ]] || [[ -z \"$2\" ]]; then\n        usage-help\n        exit 0\n    fi\n\n    part=\"$1\"\n    version=\"$2\"\n\n    validate-version \"$version\" parts\n    local major=\"${parts[0]}\"\n    local minor=\"${parts[1]}\"\n    local patch=\"${parts[2]}\"\n    local prerel=\"${parts[3]:1}\"\n    local build=\"${parts[4]:1}\"\n    local release=\"${major}.${minor}.${patch}\"\n\n    case \"$part\" in\n        major|minor|patch|release|prerel|build) echo \"${!part}\" ;;\n        *) usage-help ;;\n    esac\n\n    exit 0\n}\n\ncase $# in\n  0) echo \"Unknown command: $*\"; usage-help;;\nesac\n\ncase $1 in\n  --help|-h) echo -e \"$USAGE\"; exit 0;;\n  --version|-v) usage-version ;;\n  bump) shift; command-bump \"$@\";;\n  get) shift; command-get \"$@\";;\n  compare) shift; command-compare \"$@\";;\n  *) echo \"Unknown arguments: $*\"; usage-help;;\nesac\n"
  },
  {
    "path": "vendor/bats-core/docker/install_tini.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\ncase ${1#linux/} in\n    386) \n        TINI_PLATFORM=i386 \n        ;;\n    arm/v7)\n        TINI_PLATFORM=armhf\n        ;;\n    arm/v6)\n        TINI_PLATFORM=armel\n        ;;\n    *)\n        TINI_PLATFORM=${1#linux/}\n        ;;\nesac\n\necho \"Installing tini for $TINI_PLATFORM\"\n\nwget \"https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-static-${TINI_PLATFORM}\" -O /tini\nwget \"https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-static-${TINI_PLATFORM}.asc\" -O /tini.asc\n\nchmod +x /tini\n\napk add gnupg\ngpg --import < /tmp/docker/tini.pubkey.gpg\ngpg --batch --verify /tini.asc /tini\napk del gnupg\n"
  },
  {
    "path": "vendor/bats-core/docker/tini.pubkey.gpg",
    "content": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBFANDtsBEACpb69Ul0Ko7D4XxRIvPGnDMuGdocb8PxR+EGbnHe0uS2tCbsfj\nTOoWWUrjufrWYxGlKNqOxbEhzFA2wSQ6VD6xROPQT5dAdKaGnSCiaUg7XTzcb9u3\na5Qbx99EDZWaYDNMnLZnIElDX+YmkkEyrrmjiML63m+1P88Bz7ag18hLkqpCiIVM\nTMRfQluBJVvndX7Stzm35utugN+xeTQryjLx74CO6TUWyC7hAjvQhR5IdAk4H0oT\nRsOKZ9OQmpO0CJ1XXpKkDdDc60WVrLp1jwq2M7fx/Nz+z13nTHa3fDw8j10+1k0+\nc2HafM+GLR5CHlXVMqveWJrimII1ZILxRj/86fFCEC8ZhVW1ym4j+mqEENrzP4I7\nL3OnyKLxNKIY9CFDhfzLhNAuNeuIp6KgynzuyxWnJO4q7m/B0zcRIBcjXPrpblIx\nQlT3qQ/vFdcylDDSdbgtjD+9URG6bFR9PVlRTllBDPGQEK8vjV44pxLCenm/TzdB\nY4RlEePf+3y7wVrkjg+l4rIDH57Vl188RODuWVGeLZ3IYWqvRUnYxHmta27UH6zY\n7FNN5p7H2VqP6v9GFhiHOCTKdUbQhOoPLmUTyBas0WsC8sXdwpTy3mJthzfUwgVN\n2SIXPnndz7RcHwZtW1x9ZtVMDr6ll99kT63+sdZJHmUdlnDr+EGEd/L61QARAQAB\ntCBUaG9tYXMgT3JvemNvIDx0aG9tYXNAb3JvemNvLmZyPokCOAQTAQIAIgUCUA0O\n2wIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQmoQVnXABpOViYA//dDQt\n4f7NGbZNnQ0DgOGgBQjAabeaup6HX1UBVMBmU3OEKkUQoA62Aix8kOz19HJcuOl0\nY3koZ7pOrf/39s+tlZKvVuX7F6RFiJpx1+8f+f4IfQEPJRiurwkEp2zwTQfEOlo4\nJzv57pLUtmyJVnxMDi2vFeUue+j9BePp20Z1ZEaMBJDjmMZao3iVCVvSHZnS28vk\nD5+y8VUbyhH4dyaDtu8sb06vCu2uD7ZsMfDTtdkDWRqOLs8FdamZLf8P8AD6AX2c\nPhhASMWF7Ty2kRvhzHriuplzDUBqod38iLxoC2l5xoDjNMZsY0q9dOXBS5RsKws2\nqxrJLa/F672lpxlMA9Xnm0LMCNMcnXreldUhl18zVNofIDGex5yP20djOxl7WsQ6\n0VBAzbbiGLaKyfko5CuSmulzTJNOUNxHTiXjSi6Qz5+5lh0wYnHFulhiYE16EX25\n/rhvDzN5BgsT3Kdyk/XT/klIB5k4eLXK8PgMsRzp+FDVUL7HKM1HpHMY65gdSR8y\nZuXzKXVC43MFPYJMrjdxoEJXJjnzhf+KO6jkyrna0OQoM1YTH6/5X9XoXzQz8TDe\n7pJt4S27PZCv1NhuqNv7nPhUANr7nFMRzrbx2DNHyxUrxPvuyNmYx/KkoAzw3yaT\nfrbFXU6ccwsXWW6zdcyLEYI2ZqGDfLS7zkjmRsa5AQ0EUzNVzQEIAKxWZf55R676\nM3IURgx8Ovt8+F3M4Tj+ifePcpY5JHSj9sGkJRugW9Nye5WehuJjFYOEhKrljCTP\n/mjnE7iQqVTyYC1Ar+cTtNQpadWvQR2MW/UzimdZjBtZxdtGFCWR203jtnG+LGRs\nR7HyR6A8OBKLl0heTSHx92f+dJCGESZJeVgY49xNOlG4ILl8NseYhaD36QQZReLn\nCazy2aOep2H/jz7vnzye38QMkdHcjaw/WfQHWDKzM5Wlf+5TLF/2VTPlKcmtn0QF\nRw/vw6kjwsv9eCQ3ThIn/FV/ycdUkhOfz9Su2aIbwYC4C6Xi82RxJKbnqUGOExeC\nPG2luuWnyQcAEQEAAYkDRAQYAQIADwUCUzNVzQIbAgUJA8JnAAEpCRCahBWdcAGk\n5cBdIAQZAQIABgUCUzNVzQAKCRAqiuDav/LlpshzCACnQxndwXLZYWwiXOiYvmUI\nU9mPKynUW2vfTwaIpFBIYnqLAjVsPspwfx7zYCoMtQ+UK9d+Jhyts8vCaPwJHPqC\nCrBbP/y9K2zRdcDA1DYW/cuubwcstypmO6Eh6iC6xRxa5IHZogK6U+Trqf/EGfI/\nY/sc3KBVYSdLkngASdVr5TQltVH9LsxDUo7Ba382Ci0g/VmKkUht/aFRkEfvMrrj\nONEGbyCwk2hZuwK1aE6Yweq3tbzrByOF4wqIIe6e1pwPz7lchoGYm7XJ7uckpbGi\nlZojvu9ruxbGl8tirY/Bj0UZYjASDNCcXXRMvri2FZhDyWMMoeRLj7Mw8xpeWjr7\nNhoP/2AA16HHwRjfPQo5fDXe7eGXIebwWhbr1nAYQtL2PHFeHG/imEVozcftENNt\ntVwq/JcfjyiIcKA0niGZmroQCO0HRzRs7T85ITWfWcn/Hqaok6gmLh6QJ6daC7E9\nMse07zYM52S2/cS4osfzZj4JEC2n82VuqK9fqzR58GCkPn9rshwljEkMgEfYfTvA\nk/tm8jACpSdH3bCpSP2rL6FBtm+RuL8zbAucg8BCaVPoOhtp3326MWCnxH7QdiHl\n1dT4Dgmq4UluXOvyMZY7HI1cq4RXW5eXG5mG0ATQh1JIhIJUaEPzdaEtP5LOVqKE\n4220MVCWWak/27O9mAFm+lBA5d8O8MWW2ERqpwyYMWg/DVvQP/pB/D6wO4Dp7CMD\nMLl1LszHab9oRo8vW2cWNVS6mQ/56jgS10nRe8o/VQROfd1De6sk5k9ypk2y2iC7\npp7sime3MsnzjR0fKcxjCDAX1Sopi9QzkypM66WHO46Uamn0GeL7OhcwjcoURzJc\ny5ue1jeeKmmR7ATexlgE87rA4nuMZak1uVz0s6Fsb1ekYIKFEFqwEpqNnyKgBrvt\nGA8yn9Zp4wF+6luaKMqwptx0q1PmMZacN9E62XdOyGBaVXPq599F3R6049zo04oW\nWMW7s7V10Vn/pqRkB4bhhUzatiUHWVuamhpR8SligZ4kWPHZuQINBFANDtsBEADJ\nMvBhyWEBoLgi9nO9hgbbLxiLjKnotKzRpu5m79rhpmtqEN2k0APmoRdUUrE2Y8sd\nZ551jT0TE2O1j70qLV9c5puK6qyV3BZb9OgQ8wqyCFFjmIdPQAEgnD3K92SOh8Mu\nlqJW++EsxSqDBt2iVbLyzQuklbIJOg4nVK8ZgswIyewiHVeh3xgcGxJtVb3QjKSz\nxhj0GYM6X7mo5rjzxEFVyiJXd8ZH79y4FHUr+tJQEzJbvWAGJClPx9czh9Drw2r+\nTgq+2v/EkAoyXdv3z7uChh/9s33oQtssJ5TVfAbC06QsPp55RJCkGbTrBQgRB8Xa\nidPJhG9sIbhVgrRejn5kmK5L/8ACngbSU4zO1NTaquLZGZMzI7Jbx/QeG2DbVqjV\n6BLA3X+WieM9IUa1vi/CXiKedzlOMv7+CX9N76y4Wls4zsTwXTIzmPCDoysG+75D\nAoFZW1XJlMeEOGPhBDlR6X47qdLGzOI14NJZELni14+Iih6VvxhvUWmJfTnT+zE+\nPWb03C0EHsF8uTYqBPag9LYw2cDqvP31bUSiV+Z5YR+4sDcfiVT40rXECd1752Ia\nyANeL7uG/gBvl+6LHzb3VhI5ILkknVummVY0ry8YpAA0r1GfBE/mFLE3jwTqYkMx\nnr/SDa3HIql7qBh9k9AhTMId8tXX6p3lO6jd6TeewQARAQABiQIfBBgBAgAJBQJQ\nDQ7bAhsMAAoJEJqEFZ1wAaTlTeIP/R6/0EAqKyISxnx/6+VCy2j5mj4v8b+KauTT\ndeXJhP37i2EMsosGqUD1LMo8Wv9Az7XOSA/2lW4v8UHQolGwssLFm9L4DDTZBH8M\ngOFzB++wHNxgIoD2u9vC2eehhMfVlCcH+YWtzTSs94+5gI9xcy8rejkO+AHhXYDR\n0nr5MM076CWEjWtORgZdHbXWilmr/SdKnIdvkXDXvNcd7tC6izIfnDxN7/4beWOF\nnv/1s0JLzIFIutFtqqYDC8Y/4JxoMcALhmop+FyYk+RUHT5uGeDauJunjwdBS3VY\n5NrMcw4LxapV0OQExxu8RAMcYXx6FZmoBMlFI+J6R5ZMS6y1TKLKIpq46CsOSz2V\nX1SAactdOpXuNOXLe2cv0mYswWGAURebcmcmN49n9JEn1IN8hhawFgFuYdUWjpYx\nK2K6NZ0vFgRHkRnei9xrf2mW7ob1vKwzeBYGvZj/xIEu/Fv3kizS6t1IeMJKUKlp\nsemAObW+sEO0jLOelL+ZfUO+fImL+0fFxQyzkfNKk5dpxztPlNmv3DY6KTddc1L1\nuOGCznAmsg8Jp0v0OmCB2Xl15WPwwnYi3CkLGbEcK9stFmu2pZuEeR2DuVGlz3Nr\nBu1W/34cXeyudUTxveehuvfkjYBMXVfEM35BHEUqgCtA49b5ZM8SpYgqU3omVsNz\n7RjMAIe3uQINBFaoGQEBEACypQbnC5fMhpCft6augXnnVzmEh0Se2wBxUum3DMFl\nU48DJYNlEsKQYsgzEvaayTI0gA1ZyeDg3E4Fnk6ysQmzW9BJ/3Q2pa0GKIkvXOgL\nnwvSXSnTTqK3zCDuJI0Nj4u9gI8bX7d4PHqQyyFzPWjiIbg9tWHbhT8wwCaay1iG\nqCZsTa8Iwyve0WaV+7YtRJQeXEfY9Z6oEGqjis7QJNef1MKy1gS1Kq+4sqvdwgo3\nf3AFSNR14gagYv2myA30ehf4EzzIi8dh9DATc4T86CBuK3TszILLSUwFnrUVT00j\n3sr2WiqWrxIq/paky8zNEV3Q0vaf2kheLSZRSZsoVH1AfCsVHj4OoWH3BOAzdr5w\nsTPsV2HVR0O9K98NoA0f45eqfMFBiGVsFuJamBJatPsTVVXZ6fR9aDDKySSB540W\negHoABwai+s4FhUtjjZarLPJo47/gFmxF7HHUyNIYYKj5j99h00zcM7XOtKeyHzH\nvfZvmu150u2DccY9XX5xdzDsWuBeQJQ7VdyVVTPoZGIBZ1Mw3EIfFyAzYvglTCKo\nMMHH6912PnsMLcbcmF/7pJ4rrehp8bkfS7R3BBNMglLWtoZIYBSWoK8Nl0OyBzQ5\nlsPvRdUHuMe6rxwA11gRnx4yLd91bWRw/xIBwxz6Jq/lk0ySgdum/hIcOmrNdg73\nswARAQABiQQ+BBgBAgAJBQJWqBkBAhsCAikJEJqEFZ1wAaTlwV0gBBkBAgAGBQJW\nqBkBAAoJEAtYjf8FJ6m3uPQP/jonQ5QrOEN+B7ddYmotAwj6wL9whs7rcgb+TJfI\nrJskyBQG+kHymWEBiODo/AcqkKglGzTNcaDG153l38/IQ/Lo9mxZmkNHtLD6Srkb\nGjNrBIksRSR+hWbr8UjA/WuqAmDQvFWebmyF4p6deEAf3Rsv2Ml/a0lvC6TyWRds\ndMyWlDPtlKYn9q2qHjCVX4e2m4uB38Vq3fo8+Ypags5KRC9KyGgZFEGy3F37p+4U\n/rDT+t/6oKuo5/8RWAixeWNWIli7DQ9DbA4w9qdwL4KGwcnOCcCClT9KqKA3MOds\nr+dcAF+LkNrG3yvnp+eZ7LHF6PVJAkXnSLOzuEZzXp90pA+1Sw7QWGWpyV/v6CSP\nsxZInLPjBPJmdVhjMrma2s9SGKs2k4eivDeK4Gr6oF3GRK3VQzsRPDYk9vr8wSbA\nBR4Qh6Fy/WiME1SyEdcs2UWc+eGZ0ya7QEkQqz7Cvjp6VezUtXWFgy28pVkgEORE\nsqogypjbSnybeis6Rzvxf0g681fWjWSTcMBGXKTvgW7XnLqG9XMWdx0n6pa6s5yL\nnkoM5zYcjL+V6wDVQwnF9uoallcO11PEjsEMeK3gz0Y81EmLuHN6411IK1cWfxAI\nHunwOoPe7nzGOH2EX1+IkCv4PPJqMloEcIIPlwP0ILxTaPuy17wed0pH3dvRZglv\nJ7qQU/AP/3Nhh5AjUtMRI+mDgJpXpYuMy7tNdgKAvgGIL1bP+1LnLtP2+7uy1Pok\n3938/eAJwAT9sOhpG3qRPs15zj4tc20/Jsypbk4032EhRFWGL5TBtYf9LVl9doFY\nhGHUgAzREWcw8l7h0/p5VNPm9K0kElCw2fN3z7xwreSPa1WGVsqMdM3nc/B44ocZ\nHFqrd9kg6N4al6IxkbL7DYAUjfhjkhOQXZXU+MLPVA9lflF4694lbrr7F4GwnzfF\n8/SOw9LHVh9K3agno6jHB64P/Vqtka4a5+9AKcEkojWEHDoLU8BMUXDZZu9OkFSJ\ntzqByAzti0dsLE+8GGfas47b3/rjf6qyKvh2+iPw+I6zHH4k7LKpIiK+MkQ2+ZfM\nzB3jQ9NPNAc63AL/YbnF5XDSFxGBRkcFZo50rZJV5WHA3p+UMISsjoNizE7agLqI\n2JPnKBzB3aQFFpI3QiivWhKfsO02Vtzl+1TjqReWu4qS1uwJbSsLectAy+4K2WFn\nRNZ1m/r9/enzEhyKo8zOmUBUzVLhRR/GG7S1MmxB8FSOZh7aHg1xbTYVvq62AW6a\n0PKvEpn1g0wvPEoKQ+41/dc/ieWgnkZiKJJFxDshKGmxfDznWnZqnOESLz/3hbGy\nU41nk0UPzHlkUZwsLo9UBdr9fUVYvlYUylBp2dV0jEc5qL62gypA\n=4tCW\n-----END PGP PUBLIC KEY BLOCK-----\n"
  },
  {
    "path": "vendor/bats-core/docker-compose.override.dist",
    "content": "# Copy this file to docker-compose.override.yml\nversion: '3.6'\nservices:\n    bats:\n        entrypoint:\n            - \"bash\"\nnetworks:\n    default:\n"
  },
  {
    "path": "vendor/bats-core/docker-compose.yml",
    "content": "version: '3.6'\nservices:\n    bats:\n        build:\n            context: \".\"\n            dockerfile: \"Dockerfile\"\n        networks:\n            - \"default\"\n        user: \"root\"\n        volumes:\n            - \"./:/opt/bats\"\nnetworks:\n    default:\n"
  },
  {
    "path": "vendor/bats-core/docs/.markdownlint.json",
    "content": "{\n  \"MD024\": { \"siblings_only\": true }\n}\n"
  },
  {
    "path": "vendor/bats-core/docs/CHANGELOG.md",
    "content": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog][kac] and this project adheres to\n[Semantic Versioning][semver].\n\n[kac]: https://keepachangelog.com/en/1.0.0/\n[semver]: https://semver.org/\n\n## [Unreleased]\n\n## [1.6.0] - 2022-02-24\n\n### Added\n\n* new flag `--code-quote-style` (and `$BATS_CODE_QUOTE_STYLE`) to customize\nquotes around code blocks in error output (#506)\n* an example/regression test for running background tasks without blocking the\n  test run (#525, #535)\n* `bats_load_library` for loading libraries from the search path\n  `$BATS_LIB_PATH` (#548)\n\n### Fixed\n\n* improved error trace for some broken cases (#279)\n* removed leftover debug file `/tmp/latch` in selftest suite\n  (single use latch) (#516)\n* fix recurring errors on CTRL+C tests with NPM on Windows in selftest suite (#516)\n* fixed leaking of local variables from debug trap (#520)\n* don't mark FD3 output from `teardown_file` as `<failure>` in junit output (#532)\n* fix unbound variable error with Bash pre 4.4 (#550)\n\n#### Documentation\n\n* remove links to defunct freenode IRC channel (#515)\n* improved grammar (#534)\n* fixed link to TAP spec (#537)\n\n## [1.5.0] - 2021-10-22\n\n### Added\n\n* new command line flags (#488)\n  * `--verbose-run`: Make `run` print `$output` by default\n  * `-x`, `--trace`: Print test commands as they are executed (like `set -x`)`\n  * `--show-output-of-passing-tests`: Print output of passing tests\n  * `--print-output-on-failure`: Automatically print the value of  `$output` on\n    failed tests\n  * `--gather-test-outputs-in <directory>`: Gather the output of failing **and**\n    passing tests as files in directory\n* Experimental: add return code checks to `run` via `!`/`-<N>` (#367, #507)\n* `install.sh` and `uninstall.sh` take an optional second parameter for the lib\n  folder name to allow for multilib install, e.g. into lib64 (#452)\n* add `run` flag `--keep-empty-lines` to retain empty lines in `${lines[@]}` (#224,\n  a894fbfa)\n* add `run` flag `--separate-stderr` which also fills `$stderr` and\n  `$stderr_lines` (#47, 5c9b173d, #507)\n\n### Fixed\n\n* don't glob `run`'s `$output` when splitting into `${lines[@]}`\n  (#151, #152, #158, #156, #281, #289)\n* remove empty line after test with pretty formatter on some terminals (#481)\n* don't run setup_file/teardown_file on files without tests, e.g. due to\n  filtering (#484)\n* print final line without newline on Bash 3.2 for midtest (ERREXIT) failures\n  too (#495, #145)\n* abort with error on missing flock/shlock when running in parallel mode  (#496)\n* improved `set -u` test and fixed some unset variable accesses (#498, #501)\n* shorten suite/file/test temporary folder paths to leave enough space even on\n  restricted systems (#503)\n\n#### Documentation\n\n* minor edits (#478)\n\n## [1.4.1] - 2021-07-24\n\n### Added\n\n* Docker image architectures amd64, 386, arm64, arm/v7, arm/v6, ppc64le, s390x (#438)\n\n### Fixed\n\n* automatic push to Dockerhub (#438)\n\n## [1.4.0] - 2021-07-23\n\n### Added\n\n* added BATS_TEST_TMPDIR, BATS_FILE_TMPDIR, BATS_SUITE_TMPDIR (#413)\n* added checks and improved documentation for `$BATS_TMPDIR` (#410)\n* the docker container now uses [tini](https://github.com/krallin/tini) as the\n  container entrypoint to improve signal forwarding (#407)\n* script to uninstall bats from a given prefix (#400)\n* replace preprocessed file path (e.g. `/tmp/bats-run-22908-NP0f9h/bats.23102.src`)\n  with original filename in stdout/err (but not FD3!) (#429)\n* print aborted command on SIGINT/CTRL+C (#368)\n* print error message when BATS_RUN_TMPDIR could not be created (#422)\n\n#### Documentation\n\n* added tutorial for new users (#397)\n* fixed example invocation of docker container (#440)\n* minor edits (#431, #439, #445, #463, #464, #465)\n\n### Fixed\n\n* fix `bats_tap_stream_unknown: command not found` with pretty formatter, when\n  writing non compliant extended output (#412)\n* avoid collisions on `$BATS_RUN_TMPDIR` with `--no-tempdir-cleanup` and docker\n  by using `mktemp` additionally to PID (#409)\n* pretty printer now puts text that is printed to FD 3 below the test name (#426)\n* `rm semaphores/slot-: No such file or directory` in parallel mode on MacOS\n  (#434, #433)\n* fix YAML blocks in TAP13 formatter using `...` instead of `---` to start\n  a block (#442)\n* fixed some typos in comments (#441, #447)\n* ensure `/code` exists in docker container, to make examples work again  (#440)\n* also display error messages from free code (#429)\n* npm installed version on Windows: fix broken internal LIBEXEC paths (#459)\n\n## [1.3.0] - 2021-03-08\n\n### Added\n\n* custom test-file extension via `BATS_FILE_EXTENSION` when searching for test\n  files in a directory (#376)\n* TAP13 formatter, including millisecond timing (#337)\n* automatic release to NPM via Github Actions (#406)\n\n#### Documentation\n\n* added documentation about overusing `run` (#343)\n* improved documentation of `load` (#332)\n\n### Changed\n\n* recursive suite mode will follow symlinks now (#370)\n* split options for (file-) `--report-formatter` and (stdout) `--formatter` (#345)\n  * **WARNING**: This changes the meaning of `--formatter junit`.\n    stdout will now show unified xml instead of TAP. From now on, please use\n    `--report-formatter junit` to obtain the `.xml` report file!\n* removed `--parallel-preserve-environment` flag, as this is the default\n  behavior (#324)\n* moved CI from Travis/Appveyor to Github Actions (#405)\n* preprocessed files are no longer removed if `--no-tempdir-cleanup` is\n  specified (#395)\n\n#### Documentation\n\n* moved documentation to [readthedocs](https://bats-core.readthedocs.io/en/latest/)\n\n### Fixed\n\n#### Correctness\n\n* fix internal failures due to unbound variables when test files use `set -u` (#392)\n* fix internal failures due to changes to `$PATH` in test files (#387)\n* fix test duration always being 0 on busybox installs (#363)\n* fix hangs on CTRL+C (#354)\n* make `BATS_TEST_NUMBER` count per file again (#326)\n* include `lib/` in npm package (#352)\n\n#### Performance\n\n* don't fork bomb in parallel mode (#339)\n* preprocess each file only once (#335)\n* avoid running duplicate files n^2 times (#338)\n\n#### Documentation\n\n* fix documentation for `--formatter junit` (#334)\n* fix documentation for `setup_file` variables (#333)\n* fix link to examples page (#331)\n* fix link to \"File Descriptor 3\" section (#301)\n\n## [1.2.1] - 2020-07-06\n\n### Added\n\n* JUnit output and extensible formatter rewrite (#246)\n* `load` function now reads from absolute and relative paths, and $PATH (#282)\n* Beginner-friendly examples in /docs/examples (#243)\n* @peshay's `bats-file` fork contributed to `bats-core/bats-file` (#276)\n\n### Changed\n\n* Duplicate test names now error (previous behaviour was to issue a warning) (#286)\n* Changed default formatter in Docker to pretty by adding `ncurses` to\n  Dockerfile, override with `--tap` (#239)\n* Replace \"readlink -f\" dependency with Bash solution (#217)\n\n## [1.2.0] - 2020-04-25\n\nSupport parallel suite execution and filtering by test name.\n\n### Added\n\n* docs/CHANGELOG.md and docs/releasing.md (#122)\n* The `-f, --filter` flag to run only the tests matching a regular expression  (#126)\n* Optimize stack trace capture (#138)\n* `--jobs n` flag to support parallel execution of tests with GNU parallel (#172)\n\n### Changed\n\n* AppVeyor builds are now semver-compliant (#123)\n* Add Bash 5 as test target (#181)\n* Always use upper case signal names to avoid locale dependent err… (#215)\n* Fix for tests reading from stdin (#227)\n* Fix wrong line numbers of errors in bash < 4.4 (#229)\n* Remove preprocessed source after test run (#232)\n\n## [1.1.0] - 2018-07-08\n\nThis is the first release with new features relative to the original Bats 0.4.0.\n\n### Added\n\n* The `-r, --recursive` flag to scan directory arguments recursively for\n  `*.bats` files (#109)\n* The `contrib/rpm/bats.spec` file to build RPMs (#111)\n\n### Changed\n\n* Travis exercises latest versions of Bash from 3.2 through 4.4 (#116, #117)\n* Error output highlights invalid command line options (#45, #46, #118)\n* Replaced `echo` with `printf` (#120)\n\n### Fixed\n\n* Fixed `BATS_ERROR_STATUS` getting lost when `bats_error_trap` fired multiple\n  times under Bash 4.2.x (#110)\n* Updated `bin/bats` symlink resolution, handling the case on CentOS where\n  `/bin` is a symlink to `/usr/bin` (#113, #115)\n\n## [1.0.2] - 2018-06-18\n\n* Fixed sstephenson/bats#240, whereby `skip` messages containing parentheses\n  were truncated (#48)\n* Doc improvements:\n  * Docker usage (#94)\n  * Better README badges (#101)\n  * Better installation instructions (#102, #104)\n* Packaging/installation improvements:\n  * package.json update (#100)\n  * Moved `libexec/` files to `libexec/bats-core/`, improved `install.sh` (#105)\n\n## [1.0.1] - 2018-06-09\n\n* Fixed a `BATS_CWD` bug introduced in #91 whereby it was set to the parent of\n  `PWD`, when it should've been set to `PWD` itself (#98). This caused file\n  names in stack traces to contain the basename of `PWD` as a prefix, when the\n  names should've been purely relative to `PWD`.\n* Ensure the last line of test output prints when it doesn't end with a newline\n  (#99). This was a quasi-bug introduced by replacing `sed` with `while` in #88.\n\n## [1.0.0] - 2018-06-08\n\n`1.0.0` generally preserves compatibility with `0.4.0`, but with some Bash\ncompatibility improvements and a massive performance boost. In other words:\n\n* all existing tests should remain compatible\n* tests that might've failed or exhibited unexpected behavior on earlier\n  versions of Bash should now also pass or behave as expected\n\nChanges:\n\n* Added support for Docker.\n* Added support for test scripts that have the [unofficial strict\n  mode](http://redsymbol.net/articles/unofficial-bash-strict-mode/) enabled.\n* Improved stability on Windows and macOS platforms.\n* Massive performance improvements, especially on Windows (#8)\n* Workarounds for inconsistent behavior between Bash versions (#82)\n* Workaround for preserving stack info after calling an exported function under\n  Bash < 4.4 (#87)\n* Fixed TAP compliance for skipped tests\n* Added support for tabs in test names.\n* `bin/bats` and `install.sh` now work reliably on Windows (#91)\n\n## [0.4.0] - 2014-08-13\n\n* Improved the display of failing test cases. Bats now shows the source code of\n  failing test lines, along with full stack traces including function names,\n  filenames, and line numbers.\n* Improved the display of the pretty-printed test summary line to include the\n  number of skipped tests, if any.\n* Improved the speed of the preprocessor, dramatically shortening test and suite\n  startup times.\n* Added support for absolute pathnames to the `load` helper.\n* Added support for single-line `@test` definitions.\n* Added bats(1) and bats(7) manual pages.\n* Modified the `bats` command to default to TAP output when the `$CI` variable\n  is set, to better support environments such as Travis CI.\n\n## [0.3.1] - 2013-10-28\n\n* Fixed an incompatibility with the pretty formatter in certain environments\n  such as tmux.\n* Fixed a bug where the pretty formatter would crash if the first line of a test\n  file's output was invalid TAP.\n\n## [0.3.0] - 2013-10-21\n\n* Improved formatting for tests run from a terminal. Failing tests are now\n  colored in red, and the total number of failing tests is displayed at the end\n  of the test run. When Bats is not connected to a terminal (e.g. in CI runs),\n  or when invoked with the `--tap` flag, output is displayed in standard TAP\n  format.\n* Added the ability to skip tests using the `skip` command.\n* Added a message to failing test case output indicating the file and line\n  number of the statement that caused the test to fail.\n* Added \"ad-hoc\" test suite support. You can now invoke `bats` with multiple\n  filename or directory arguments to run all the specified tests in aggregate.\n* Added support for test files with Windows line endings.\n* Fixed regular expression warnings from certain versions of Bash.\n* Fixed a bug running tests containing lines that begin with `-e`.\n\n## [0.2.0] - 2012-11-16\n\n* Added test suite support. The `bats` command accepts a directory name\n  containing multiple test files to be run in aggregate.\n* Added the ability to count the number of test cases in a file or suite by\n  passing the `-c` flag to `bats`.\n* Preprocessed sources are cached between test case runs in the same file for\n  better performance.\n\n## [0.1.0] - 2011-12-30\n\n* Initial public release.\n\n[Unreleased]: https://github.com/bats-core/bats-core/compare/v1.1.0...HEAD\n[1.1.0]: https://github.com/bats-core/bats-core/compare/v1.0.2...v1.1.0\n[1.0.2]: https://github.com/bats-core/bats-core/compare/v1.0.1...v1.0.2\n[1.0.1]: https://github.com/bats-core/bats-core/compare/v1.0.0...v1.0.1\n[1.0.0]: https://github.com/bats-core/bats-core/compare/v0.4.0...v1.0.0\n[0.4.0]: https://github.com/bats-core/bats-core/compare/v0.3.1...v0.4.0\n[0.3.1]: https://github.com/bats-core/bats-core/compare/v0.3.0...v0.3.1\n[0.3.0]: https://github.com/bats-core/bats-core/compare/v0.2.0...v0.3.0\n[0.2.0]: https://github.com/bats-core/bats-core/compare/v0.1.0...v0.2.0\n[0.1.0]: https://github.com/bats-core/bats-core/commits/v0.1.0\n"
  },
  {
    "path": "vendor/bats-core/docs/CODEOWNERS",
    "content": "# This enables automatic code review requests per:\n# - https://help.github.com/articles/about-codeowners/\n# - https://help.github.com/articles/enabling-required-reviews-for-pull-requests/\n* @bats-core/bats-core\n"
  },
  {
    "path": "vendor/bats-core/docs/CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, gender identity and expression, level of experience,\nnationality, personal appearance, race, religion, or sexual identity and\norientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\nadvances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n  address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting one of the current [project maintainers](#project-maintainers) listed below. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Project Maintainers\n\n### Current Maintainers\n\n* [Bianca Tamayo][bt-gh]\n* [Mike Bland][mb-gh]\n* [Jason Karns][jk-gh]\n* [Andrew Martin][am-gh]\n\n### Past Maintainers\n\n* Sam Stephenson <<sstephenson@gmail.com>> (Original author)\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at [http://contributor-covenant.org/version/1/4][version]\n\n[bt-gh]: https://github.com/btamayo\n[mb-gh]: https://github.com/mbland\n[jk-gh]: https://github.com/jasonkarns\n[am-gh]: https://github.com/sublimino\n\n[homepage]: https://contributor-covenant.org\n[version]: https://contributor-covenant.org/version/1/4/\n"
  },
  {
    "path": "vendor/bats-core/docs/CONTRIBUTING.md",
    "content": "# Contributing Guidelines\n\n## Welcome!\n\nThank you for considering contributing to the development of this project's \ndevelopment and/or documentation. Just a reminder: if you're new to this project\nor to OSS and want to find issues to work on, please check the following labels \non issues:\n\n- [help wanted][helpwantedlabel]\n- [docs][docslabel]\n- [good first issue][goodfirstissuelabel]\n\n[docslabel]:           https://github.com/bats-core/bats-core/labels/docs\n[helpwantedlabel]:     https://github.com/bats-core/bats-core/labels/help%20wanted\n[goodfirstissuelabel]: https://github.com/bats-core/bats-core/labels/good%20first%20issue\n\nTo see all labels and their meanings, [check this wiki page][labelswiki].\n\nThis guide borrows **heavily** from [@mbland's go-script-bash][gsb] (with some \nsections directly quoted), which in turn was\ndrafted with tips from [Wrangling Web Contributions: How to Build\na CONTRIBUTING.md][moz] and with some inspiration from [the Atom project's\nCONTRIBUTING.md file][atom].\n\n[gsb]:  https://github.com/mbland/go-script-bash/blob/master/CONTRIBUTING.md\n[moz]:  https://mozillascience.github.io/working-open-workshop/contributing/\n[atom]: https://github.com/atom/atom/blob/master/CONTRIBUTING.md\n\n[labelswiki]: https://github.com/bats-core/bats-core/wiki/GitHub-Issue-Labels\n\n## Table of contents\n\n* [Contributing Guidelines](#contributing-guidelines)\n  * [Welcome!](#welcome)\n  * [Table of contents](#table-of-contents)\n  * [Quick links <g-emoji alias=\"link\" fallback-src=\"https://assets-cdn.github.com/images/icons/emoji/unicode/1f517.png\" ios-version=\"6.0\">🔗</g-emoji>](#quick-links-)\n  * [Contributor License Agreement](#contributor-license-agreement)\n  * [Code of conduct](#code-of-conduct)\n  * [Asking questions and reporting issues](#asking-questions-and-reporting-issues)\n  * [Updating documentation](#updating-documentation)\n  * [Environment setup](#environment-setup)\n  * [Workflow](#workflow)\n  * [Testing](#testing)\n  * [Coding conventions](#coding-conventions)\n      * [Formatting](#formatting)\n      * [Naming](#naming)\n      * [Function declarations](#function-declarations)\n      * [Variable and parameter declarations](#variable-and-parameter-declarations)\n      * [Command substitution](#command-substitution)\n      * [Process substitution](#process-substitution)\n      * [Conditionals and loops](#conditionals-and-loops)\n      * [Generating output](#generating-output)\n      * [Gotchas](#gotchas)\n  * [Open Source License](#open-source-license)\n  * [Credits](#credits)\n\n## Quick links &#x1f517;\n\n- [Gitter channel →][gitterurl]: Feel free to come chat with us on Gitter\n- [README →][README]\n- [Code of conduct →][CODE_OF_CONDUCT]\n- [License information →][LICENSE]\n- [Original repository →][repohome]\n- [Issues →][repoissues]\n- [Pull requests →][repoprs]\n- [Milestones →][repomilestones]\n- [Projects →][repoprojects]\n\n[README]: https://github.com/bats-core/bats-core/blob/master/README.md\n[CODE_OF_CONDUCT]: https://github.com/bats-core/bats-core/blob/master/docs/CODE_OF_CONDUCT.md\n[LICENSE]: https://github.com/bats-core/bats-core/blob/master/LICENSE.md\n\n## Contributor License Agreement\n\nPer the [GitHub Terms of Service][gh-tos], be aware that by making a\ncontribution to this project, you agree:\n\n* to license your contribution under the same terms as [this project's\n  license][osmit], and\n* that you have the right to license your contribution under those terms.\n\nSee also: [\"Does my project need an additional contributor agreement? Probably\n  not.\"][cla-needed]\n\n[gh-tos]:     https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license\n[osmit]:      #open-source-license\n[cla-needed]: https://opensource.guide/legal/#does-my-project-need-an-additional-contributor-agreement\n\n\n## Code of conduct\n\nHarrassment or rudeness of any kind will not be tolerated, period. For\nspecifics, see the [CODE_OF_CONDUCT][] file.\n\n## Asking questions and reporting issues\n\n### Asking questions\n\nPlease check the [README][] or existing [issues][repoissues] first.\n\nIf you cannot find an answer to your question, please feel free to hop on our \n[Gitter][gitterurl]. [![Gitter](https://badges.gitter.im/bats-core/bats-core.svg)](https://gitter.im/bats-core/bats-core)\n\n### Reporting issues\n\nBefore reporting an issue, please use the search feature on the [issues\npage][repoissues] to see if an issue matching the one you've observed has already\nbeen filed.\n\n### Updating or filing a new issue\n\n#### Information to include\n\nTry to be as specific as possible about your environment and the problem you're\nobserving. At a minimum, include:\n\n#### Installation issues\n\n1. State the version of Bash you're using `bash --version`\n1. State your operating system and its version\n1. If you're installing through homebrew, run `brew doctor`, and attach the \noutput of `brew info bats-core`\n\n#### Bugs/usage issues\n\n1. State the version of Bash you're using `bash --version`\n1. State your operating system and its version\n1. Command line steps or code snippets that reproduce the issue\n1. Any apparently relevant information from the [Bash changelog][bash-changes]\n\n[bash-changes]: https://tiswww.case.edu/php/chet/bash/CHANGES\n\nAlso consider using:\n\n- Bash's `time` builtin to collect running times\n- a regression test to add to the suite\n- memory usage as reported by a tool such as\n  [memusg](https://gist.github.com/netj/526585)\n\n### On existing issues\n\n1. DO NOT add a +1 comment: Use the reactions provided instead\n1. DO add information if you're facing a similar issue to someone else, but \nwithin a different context (e.g. different steps needed to reproduce the issue \nthan previous stated, different version of Bash or BATS, different OS, etc.) \nYou can read on how to do that here: [Information to include][#information-to-include]\n1. DO remember that you can use the *Subscribe* button on the right side of the\npage to receive notifications of further conversations or a resolution.\n\n## Updating documentation\n\nWe love documentation and people who love documentation!\n\nIf you love writing clear, accessible docs, please don't be shy about pull \nrequests. Remember: docs are just as important as code.\n\nAlso: _no typo is too small to fix!_ Really. Of course, batches of fixes are\npreferred, but even one nit is one nit too many.\n\n## Environment setup\n\nMake sure you have Bash installed per the [Environment setup in the\nREADME][env-setup].\n\n[env-setup]: https://github.com/bats-core/bats-core/blob/master/README.md#environment-setup\n\n## Workflow\n\nThe basic workflow for submitting changes resembles that of the [GitHub Git\nFlow][github-flow] (a.k.a. GitHub Flow), except that you will be working with \nyour own fork of the repository and issuing pull requests to the original.\n\n[github-flow]: https://guides.github.com/introduction/flow/\n\n1. Fork the repo on GitHub (look for the \"Fork\" button)\n1. Clone your forked repo to your local machine\n1. Create your feature branch (`git checkout -b my-new-feature`)\n1. Develop _and [test](#testing)_ your changes as necessary.\n1. Commit your changes (`git commit -am 'Add some feature'`)\n1. Push to the branch (`git push origin my-new-feature`)\n1. Create a new [GitHub pull request][gh-pr] for your feature branch based\n   against the original repository's `master` branch\n1. If your request is accepted, you can [delete your feature branch][rm-branch]\n   and pull the updated `master` branch from the original repository into your\n   fork. You may even [delete your fork][rm-fork] if you don't anticipate making\n   further changes.\n\n[gh-pr]:     https://help.github.com/articles/using-pull-requests/\n[rm-branch]: https://help.github.com/articles/deleting-unused-branches/\n[rm-fork]:   https://help.github.com/articles/deleting-a-repository/\n\n## Testing\n\n- Continuous integration status: [![Tests](https://github.com/bats-core/bats-core/workflows/Tests/badge.svg)](https://github.com/bats-core/bats-core/actions?query=workflow%3ATests)\n\n## Coding conventions\n\n- [Formatting](#formatting)\n- [Naming](#naming)\n- [Variable and parameter declarations](#variable-and-parameter-declarations)\n- [Command substitution](#command-substitution)\n- [Conditions and loops](#conditionals-and-loops)\n- [Gotchas](#gotchas)\n\n### Formatting\n\n- Keep all files 80 characters wide.\n- Indent using two spaces.\n- Enclose all variables in double quotes when used to avoid having them\n  interpreted as glob patterns (unless the variable contains a glob pattern)\n  and to avoid word splitting when the value contains spaces. Both scenarios\n  can introduce errors that often prove difficult to diagnose.\n  - **This is especially important when the variable is used to generate a\n    glob pattern**, since spaces may appear in a path value.\n  - If the variable itself contains a glob pattern, make sure to set\n    `IFS=$'\\n'` before using it so that the pattern itself and any matching\n    file names containing spaces are not split apart.\n  - Exceptions: Quotes are not required within math contexts, i.e. `(( ))` or\n    `$(( ))`, and must not be used for variables on the right side of the `=~`\n    operator.\n- Enclose all string literals in single quotes.\n  - Exception: If the string contains an apostrophe, use double quotes.\n- Use quotes around variables and literals even inside of `[[ ]]` conditions.\n  - This is because strings that contain '[' or ']' characters may fail to\n    compare equally when they should.\n  - Exception: Do not quote variables that contain regular expression patterns\n    appearing on the right side of the `=~` operator.\n- _Only_ quote arguments to the right of `=~` if the expression is a literal\n  match without any metacharacters.\n\nThe following are intended to prevent too-compact code:\n\n- Declare only one item per `declare`, `local`, `export`, or `readonly` call.\n  - _Note:_ This also helps avoid subtle bugs, as trying to initialize one\n    variable using the value of another declared in the same statement will\n    not do what you may expect. The initialization of the first variable will\n    not yet be complete when the second variable is declared, so the first\n    variable will have an empty value.\n- Do not use one-line `if`, `for`, `while`, `until`, `case`, or `select`\n  statements.\n- Do not use `&&` or `||` to avoid writing `if` statements.\n- Do not write functions entirely on one line.\n- For `case` statements: put each pattern on a line by itself; put each command\n  on a line by itself; put the `;;` terminator on a line by itself.\n\n### Naming\n\n- Use `snake_case` for all identifiers.\n\n### Function declarations\n\n- Declare functions without the `function` keyword.\n- Strive to always use `return`, never `exit`, unless an error condition is\n  severe enough to warrant it.\n  - Calling `exit` makes it difficult for the caller to recover from an error,\n    or to compose new commands from existing ones.\n\n### Variable and parameter declarations\n\n- _Gotcha:_ Never initialize an array on the same line as an `export` or\n  `declare -g` statement. See [the Gotchas section](#gotchas) below for more\n  details.\n- Declare all variables inside functions using `local`.\n- Declare temporary file-level variables using `declare`. Use `unset` to remove\n  them when finished.\n- Don't use `local -r`, as a readonly local variable in one scope can cause a\n  conflict when it calls a function that declares a `local` variable of the same\n  name.\n- Don't use type flags with `declare` or `local`. Assignments to integer\n  variables in particular may behave differently, and it has no effect on array\n  variables.\n- For most functions, the first lines should use `local` declarations to\n  assign the original positional parameters to more meaningful names, e.g.:\n  ```bash\n  format_summary() {\n    local cmd_name=\"$1\"\n    local summary=\"$2\"\n    local longest_name_len=\"$3\"\n  ```\n  For very short functions, this _may not_ be necessary, e.g.:\n  ```bash\n  has_spaces() {\n    [[ \"$1\" != \"${1//[[:space:]]/}\" ]]\n  }\n  ```\n\n### Command substitution\n\n- If possible, don't. While this capability is one of Bash's core strengths,\n  every new process created by Bats makes the framework slower, and speed is\n  critical to encouraging the practice of automated testing. (This is especially\n  true on Windows, [where process creation is one or two orders of magnitude\n  slower][win-slow]. See [bats-core/bats-core#8][pr-8] for an illustration of\n  the difference avoiding subshells makes.) Bash is quite powerful; see if you\n  can do what you need in pure Bash first.\n- If you need to capture the output from a function, store the output using\n  `printf -v` instead if possible. `-v` specfies the name of the variable into\n  which to write the result; the caller can supply this name as a parameter.\n- If you must use command substituion, use `$()` instead of backticks, as it's\n  more robust, more searchable, and can be nested.\n\n[win-slow]: https://rufflewind.com/2014-08-23/windows-bash-slow\n[pr-8]: https://github.com/bats-core/bats-core/pull/8\n\n### Process substitution\n\n- If possible, don't use it. See the advice on avoiding subprocesses and using\n  `printf -v` in the **Command substitution** section above.\n- Use wherever necessary and possible, such as when piping input into a `while`\n  loop (which avoids having the loop body execute in a subshell) or running a\n  command taking multiple filename arguments based on output from a function or\n  pipeline (e.g.  `diff`).\n- *Warning*: It is impossible to directly determine the exit status of a process\n  substitution; emitting an exit status as the last line of output is a possible\n  workaround.\n\n### Conditionals and loops\n\n- Always use `[[` and `]]` for evaluating variables. Per the guideline under\n  **Formatting**, quote variables and strings within the brackets, but not\n  regular expressions (or variables containing regular expressions) appearing\n  on the right side of the `=~` operator.\n\n### Generating output\n\n- Use `printf` instead of `echo`. Both are Bash builtins, and there's no\n  perceptible performance difference when running Bats under the `time` builtin.\n  However, `printf` provides a more consistent experience in general, as `echo`\n  has limitations to the arguments it accepts, and even the same version of Bash\n  may produce different results for `echo` based on how the binary was compiled.\n  See [Stack Overflow: Why is printf better than echo?][printf-vs-echo] for\n  excruciating details.\n\n[printf-vs-echo]: https://unix.stackexchange.com/a/65819\n\n### Signal names\n\nAlways use upper case signal names (e.g. `trap - INT EXIT`) to avoid locale \ndependent errors. In some locales (for example Turkish, see \n[Turkish dotless i](https://en.wikipedia.org/wiki/Dotted_and_dotless_I)) lower \ncase signal names cause Bash to error. An example of the problem:\n\n```bash\n$ echo \"tr_TR.UTF-8 UTF-8\" >> /etc/locale.gen && locale-gen tr_TR.UTF-8 # Ubuntu derivatives\n$ LC_CTYPE=tr_TR.UTF-8 LC_MESSAGES=C bash -c 'trap - int && echo success'\nbash: line 0: trap: int: invalid signal specification\n$ LC_CTYPE=tr_TR.UTF-8 LC_MESSAGES=C bash -c 'trap - INT && echo success'\nsuccess\n```\n\n### Gotchas\n\n- If you wish to use command substitution to initialize a `local` variable, and\n  then check the exit status of the command substitution, you _must_ declare the\n  variable on one line and perform the substitution on another. If you don't,\n  the exit status will always indicate success, as it is the status of the\n  `local` declaration, not the command substitution.\n- To work around a bug in some versions of Bash whereby arrays declared with\n  `declare -g` or `export` and initialized in the same statement eventually go\n  out of scope, always `export` the array name on one line and initialize it the\n  next line. See:\n  - https://lists.gnu.org/archive/html/bug-bash/2012-06/msg00068.html\n  - ftp://ftp.gnu.org/gnu/bash/bash-4.2-patches/bash42-025\n  - http://lists.gnu.org/archive/html/help-bash/2012-03/msg00078.html\n- [ShellCheck](https://www.shellcheck.net/) can help to identify many of these issues\n\n\n## Open Source License\n\nThis software is made available under the [MIT License][osmit].\nFor the text of the license, see the [LICENSE][] file.\n\n## Credits\n\n- This guide was heavily written by BATS-core member [@mbland](https://github.com/mbland) \nfor [go-script-bash](https://github.com/mbland/go-script-bash), tweaked for [BATS-core][repohome]\n- Table of Contents created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)\n- The [official bash logo](https://github.com/odb/official-bash-logo) is copyrighted\nby the [Free Software Foundation](https://www.fsf.org/), 2016 under the [Free Art License](http://artlibre.org/licence/lal/en/)\n\n\n\n[repoprojects]:   https://github.com/bats-core/bats-core/projects\n[repomilestones]: https://github.com/bats-core/bats-core/milestones\n[repoprs]:        https://github.com/bats-core/bats-core/pulls\n[repoissues]:     https://github.com/bats-core/bats-core/issues\n[repohome]:       https://github.com/bats-core/bats-core\n\n[osmit]:          https://opensource.org/licenses/MIT\n\n[gitterurl]:      https://gitter.im/bats-core/bats-core\n"
  },
  {
    "path": "vendor/bats-core/docs/Makefile",
    "content": "# Minimal makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line, and also\n# from the environment for the first two.\nSPHINXOPTS    ?=\nSPHINXBUILD   ?= sphinx-build\nSOURCEDIR     = source\nBUILDDIR      = build\n\n# Put it first so that \"make\" without argument is like \"make help\".\nhelp:\n\t@$(SPHINXBUILD) -M help \"$(SOURCEDIR)\" \"$(BUILDDIR)\" $(SPHINXOPTS) $(O)\n\n.PHONY: help Makefile\n\n# Catch-all target: route all unknown targets to Sphinx using the new\n# \"make mode\" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).\n%: Makefile\n\t@$(SPHINXBUILD) -M $@ \"$(SOURCEDIR)\" \"$(BUILDDIR)\" $(SPHINXOPTS) $(O)\n"
  },
  {
    "path": "vendor/bats-core/docs/PULL_REQUEST_TEMPLATE.md",
    "content": "- [ ] I have reviewed the [Contributor Guidelines][contributor].\n- [ ] I have reviewed the [Code of Conduct][coc] and agree to abide by it\n\n[contributor]: https://github.com/bats-core/bats-core/blob/master/docs/CONTRIBUTING.md\n[coc]:         https://github.com/bats-core/bats-core/blob/master/docs/CODE_OF_CONDUCT.md\n"
  },
  {
    "path": "vendor/bats-core/docs/examples/README.md",
    "content": "# Examples\n\nThis directory contains example .bats files.\nSee the [bats-core wiki][examples] for more details.\n\n[examples]: https://github.com/bats-core/bats-core/wiki/Examples"
  },
  {
    "path": "vendor/bats-core/docs/examples/package-tarball",
    "content": "#!/usr/bin/env bash\n\n# \"unofficial\" bash strict mode\n# See: http://redsymbol.net/articles/unofficial-bash-strict-mode\nset -o errexit  # Exit when simple command fails               'set -e'\nset -o errtrace # Exit on error inside any functions or subshells.\nset -o nounset  # Trigger error when expanding unset variables 'set -u'\nset -o pipefail # Do not hide errors within pipes              'set -o pipefail'\nset -o xtrace   # Display expanded command and arguments       'set -x'\nIFS=$'\\n\\t'     # Split words on \\n\\t rather than spaces\n\nmain() {\n  tar -czf \"$dst_tarball\" -C \"$src_dir\" .\n}\n\nmain \"$@\"\n"
  },
  {
    "path": "vendor/bats-core/docs/examples/package-tarball.bats",
    "content": "#!/usr/bin/env bats\n\nsetup() {\n  export dst_tarball=\"${BATS_TMPDIR}/dst.tar.gz\"\n  export src_dir=\"${BATS_TMPDIR}/src_dir\"\n\n  rm -rf \"${dst_tarball}\" \"${src_dir}\"\n  mkdir \"${src_dir}\"\n  touch \"${src_dir}\"/{a,b,c}\n}\n\nmain() {\n  bash \"${BATS_TEST_DIRNAME}\"/package-tarball\n}\n\n@test \"fail when \\$src_dir and \\$dst_tarball are unbound\" {\n  unset src_dir dst_tarball\n\n  run main\n  [ \"${status}\" -ne 0 ]\n}\n\n@test \"fail when \\$src_dir is a non-existent directory\" {\n  # shellcheck disable=SC2030\n  src_dir='not-a-dir'\n\n  run main\n  [ \"${status}\" -ne 0 ]\n}\n\n# shellcheck disable=SC2016\n@test \"pass when \\$src_dir directory is empty\" {\n  # shellcheck disable=SC2031,SC2030\n  rm -rf \"${src_dir:?}/*\"\n\n  run main\n  echo \"$output\"\n  [ \"${status}\" -eq 0 ]\n}\n\n# shellcheck disable=SC2016\n@test \"files in \\$src_dir are added to tar archive\" {\n  run main\n  [ \"${status}\" -eq 0 ]\n\n  run tar tf \"$dst_tarball\"\n  [ \"${status}\" -eq 0 ]\n  [[ \"${output}\" =~ a ]]\n  [[ \"${output}\" =~ b ]]\n  [[ \"${output}\" =~ c ]]\n}\n"
  },
  {
    "path": "vendor/bats-core/docs/make.bat",
    "content": "@ECHO OFF\n\npushd %~dp0\n\nREM Command file for Sphinx documentation\n\nif \"%SPHINXBUILD%\" == \"\" (\n\tset SPHINXBUILD=sphinx-build\n)\nset SOURCEDIR=source\nset BUILDDIR=build\n\nif \"%1\" == \"\" goto help\n\n%SPHINXBUILD% >NUL 2>NUL\nif errorlevel 9009 (\n\techo.\n\techo.The 'sphinx-build' command was not found. Make sure you have Sphinx\n\techo.installed, then set the SPHINXBUILD environment variable to point\n\techo.to the full path of the 'sphinx-build' executable. Alternatively you\n\techo.may add the Sphinx directory to PATH.\n\techo.\n\techo.If you don't have Sphinx installed, grab it from\n\techo.http://sphinx-doc.org/\n\texit /b 1\n)\n\n%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%\ngoto end\n\n:help\n%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%\n\n:end\npopd\n"
  },
  {
    "path": "vendor/bats-core/docs/releasing.md",
    "content": "# Releasing a new Bats version\n\nThese notes reflect the current process. There's a lot more we could do, in\nterms of automation and expanding the number of platforms to which we formally\nrelease (see #103).\n\n## Update docs/CHANGELOG.md\n\nCreate a new entry at the top of `docs/CHANGELOG.md` that enumerates the\nsignificant updates to the new version.\n\n## Bumping the version number\n\nBump the version numbers in the following files:\n\n- contrib/rpm/bats.spec\n- libexec/bats-core/bats\n- package.json\n\nCommit these changes (including the `docs/CHANGELOG.md` changes) in a commit\nwith the message `Bats <VERSION>`, where `<VERSION>` is the new version number.\n\nCreate a new signed, annotated tag with:\n\n```bash\n$ git tag -a -s <VERSION>\n```\n\nInclude the `docs/CHANGELOG.md` notes corresponding to the new version as the\ntag annotation, except the first line should be: `Bats <VERSION> - YYYY-MM-DD`\nand any Markdown headings should become plain text, e.g.:\n\n```md\n### Added\n```\n\nshould become:\n\n```md\nAdded:\n```\n\n## Create a GitHub release\n\nPush the new version commit and tag to GitHub via the following:\n\n```bash\n$ git push --follow-tags\n```\n\nThen visit https://github.com/bats-core/bats-core/releases, and:\n\n* Click **Draft a new release**.\n* Select the new version tag.\n* Name the release: `Bats <VERSION>`.\n* Paste the same notes from the version tag annotation as the description,\n  except change the first line to read: `Released: YYYY-MM-DD`.\n* Click **Publish release**.\n\nFor more on `git push --follow-tags`, see:\n\n* [git push --follow-tags in the online manual][ft-man]\n* [Stack Overflow: How to push a tag to a remote repository using Git?][ft-so]\n\n[ft-man]: https://git-scm.com/docs/git-push#git-push---follow-tags\n[ft-so]: https://stackoverflow.com/a/26438076\n\n## NPM\n\n`npm publish`. Pretty easy!\n\nFor the paranoid, use `npm pack` and install the resulting tarball locally with\n`npm install` before publishing.\n\n## Homebrew\n\nThe basic instructions are in the [Submit a new version of an existing\nformula][brew] section of the Homebrew docs.\n\n[brew]: https://github.com/Homebrew/brew/blob/master/docs/How-To-Open-a-Homebrew-Pull-Request.md#submit-a-new-version-of-an-existing-formula\n\nAn example using v1.1.0 (notice that this uses the sha256 sum of the tarball):\n\n```bash\n$ curl -LOv https://github.com/bats-core/bats-core/archive/v1.1.0.tar.gz\n$ openssl sha256 v1.1.0.tar.gz\nSHA256(v1.1.0.tar.gz)=855d8b8bed466bc505e61123d12885500ef6fcdb317ace1b668087364717ea82\n\n# Add the --dry-run flag to see the individual steps without executing.\n$ brew bump-formula-pr \\\n  --url=https://github.com/bats-core/bats-core/archive/v1.1.0.tar.gz \\\n  --sha256=855d8b8bed466bc505e61123d12885500ef6fcdb317ace1b668087364717ea82\n```\nThis resulted in https://github.com/Homebrew/homebrew-core/pull/29864, which was\nautomatically merged once the build passed.\n\n## Alpine Linux\n\nAn example using v1.1.0 (notice that this uses the sha512 sum of the Zip file):\n\n```bash\n$ curl -LOv https://github.com/bats-core/bats-core/archive/v1.1.0.zip\n$ openssl sha512 v1.1.0.zip\nSHA512(v1.1.0.zip)=accd83cfec0025a2be40982b3f9a314c2bbf72f5c85daffa9e9419611904a8d34e376919a5d53e378382e0f3794d2bd781046d810225e2a77812474e427bed9e\n```\n\nAfter cloning alpinelinux/aports, I used the above information to create:\nhttps://github.com/alpinelinux/aports/pull/4696\n\n**Note:** Currently users must enable the `edge` branch of the `community` repo\nby adding/uncommenting the corresponding entry in `/etc/apk/repositories`.\n\n## Announce\n\nIt's worth making a brief announcement like [the v1.1.0 announcement via\nGitter][gitter]:\n\n[gitter]: https://gitter.im/bats-core/bats-core?at=5b42c9a57b811a6d63daacb5\n\n```\nv1.1.0 is now available via Homebrew and npm:\nhttps://github.com/bats-core/bats-core/releases/tag/v1.1.0\n\nIt'll eventually be available in Alpine via the edge branch of the community\nrepo once alpinelinux/aports#4696 gets merged. (Check /etc/apk/repositories to\nensure this repo is enabled.)\n```\n"
  },
  {
    "path": "vendor/bats-core/docs/source/_static/.gitkeep",
    "content": ""
  },
  {
    "path": "vendor/bats-core/docs/source/_templates/.gitkeep",
    "content": ""
  },
  {
    "path": "vendor/bats-core/docs/source/conf.py",
    "content": "# Configuration file for the Sphinx documentation builder.\n#\n# This file only contains a selection of the most common options. For a full\n# list see the documentation:\n# https://www.sphinx-doc.org/en/master/usage/configuration.html\n\n# -- Path setup --------------------------------------------------------------\n\n# If extensions (or modules to document with autodoc) are in another directory,\n# add these directories to sys.path here. If the directory is relative to the\n# documentation root, use os.path.abspath to make it absolute, like shown here.\n#\n# import os\n# import sys\n# sys.path.insert(0, os.path.abspath('.'))\n\n\n# -- Project information -----------------------------------------------------\n\nproject = 'bats-core'\ncopyright = '2021, bats-core organization'\nauthor = 'bats-core organization'\n\n# The full version, including alpha/beta/rc tags\nrelease = '1'\n\n\n# -- General configuration ---------------------------------------------------\n\n# Add any Sphinx extension module names here, as strings. They can be\n# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom\n# ones.\nextensions = [\n    'recommonmark',\n    'sphinxcontrib.programoutput'\n]\n\n# Add any paths that contain templates here, relative to this directory.\ntemplates_path = ['_templates']\n\nhtml_sidebars = {  '**': [\n        'about.html',\n        'navigation.html',\n        'relations.html',\n        'searchbox.html',\n        'donate.html'] }\n\n# List of patterns, relative to source directory, that match files and\n# directories to ignore when looking for source files.\n# This pattern also affects html_static_path and html_extra_path.\nexclude_patterns = []\n\n\n# -- Options for HTML output -------------------------------------------------\n\n# The theme to use for HTML and HTML Help pages.  See the documentation for\n# a list of builtin themes.\n#\n#html_theme = 'alabaster'\n\n# Add any paths that contain custom static files (such as style sheets) here,\n# relative to this directory. They are copied after the builtin static files,\n# so a file named \"default.css\" will overwrite the builtin \"default.css\".\nhtml_static_path = ['_static']\n\n#man_pages = [ ('man.1', 'bats', 'bats documentation', ['bats-core Contributors'], 1)]\n\ndef setup(app):\n    app.add_config_value('recommonmark_config', {'enable_eval_rst': True}, True)\n    import recommonmark\n    from recommonmark.transform import AutoStructify\n    app.add_transform(AutoStructify)\n"
  },
  {
    "path": "vendor/bats-core/docs/source/docker-usage.md",
    "content": "# Docker Usage Guide\n\n- [Docker Usage Guide](#docker-usage-guide)\n  * [Basic Usage](#basic-usage)\n  * [Docker Gotchas](#docker-gotchas)\n  * [Extending from the base image](#extending-from-the-base-image)\n  \n## Basic Usage\n\nTo build and run `bats`' own tests:\n```bash\n$ git clone https://github.com/bats-core/bats-core.git\nCloning into 'bats-core'...\nremote: Counting objects: 1222, done.\nremote: Compressing objects: 100% (53/53), done.\nremote: Total 1222 (delta 34), reused 55 (delta 21), pack-reused 1146\nReceiving objects: 100% (1222/1222), 327.28 KiB | 1.70 MiB/s, done.\nResolving deltas: 100% (661/661), done.\n\n$ cd bats-core/\n$ docker build --tag bats/bats:latest .\n...\n$ docker run -it bats/bats:latest --formatter tap /opt/bats/test\n```\n\nTo mount your tests into the container, first build the image as above. Then, for example with `bats`:\n```bash\n$ docker run -it -v \"$PWD:/opt/bats\" bats/bats:latest /opt/bats/test\n```\nThis runs the `test/` directory from the bats-core repository inside the bats Docker container.\n\nFor test suites that are intended to run in isolation from the project (i.e. the tests do not depend on project files outside of the test directory), you can mount the test directory by itself and execute the tests like so:\n\n```bash\n$ docker run -it -v \"$PWD:/code\" bats/bats:latest /code/test\n```\n\n## Docker Gotchas\n\nRelying on functionality provided by your environment (ssh keys or agent, installed binaries, fixtures outside the mounted test directory) will fail when running inside Docker. \n\n`--interactive`/`-i` attaches an interactive terminal and is useful to kill hanging processes (otherwise has to be done via docker stop command). `--tty`/`-t` simulates a tty (often not used, but most similar to test runs from a Bash prompt). Interactivity is important to a user, but not a build, and TTYs are probably more important to a headless build. Everything's least-surprising to a new Docker use if both are used.\n\n## Extending from the base image\n\nDocker operates on a principle of isolation, and bundles all dependencies required into the Docker image. These can be mounted in at runtime (for test files, configuration, etc). For binary dependencies it may be better to extend the base Docker image with further tools and files.\n\n```dockerfile\nFROM bats/bats\n\nRUN \\ \n  apk \\\n  --no-cache \\\n  --update \\\n  add \\\n  openssh \n\n```\n"
  },
  {
    "path": "vendor/bats-core/docs/source/faq.rst",
    "content": "FAQ\n===\n\nHow do I set the working directory?\n-----------------------------------\n\nThe working directory is simply the directory where you started when executing bats.\nIf you want to enforce a specific directory, you can use `cd` in the `setup_file`/`setup` functions.\nHowever, be aware that code outside any function will run before any of these setup functions and might interfere with bats' internals.\n\n\nHow do I see the output of the command under `run` when a test fails?\n---------------------------------------------------------------------\n\n`run` captures stdout and stderr of its command and stores it in the `$output` and `${lines[@]}` variables.\nIf you want to see this output, you need to print it yourself, or use functions like `assert_output` that will reproduce it on failure.\n\nCan I use `--filter` to exclude files/tests?\n--------------------------------------------\n\nNo, not directly. `--filter` uses a regex to match against test names. So you could try to invert the regex.\nThe filename won't be part of the strings that are tested, so you cannot filter against files.\n\nHow can I exclude a single test from a test run?\n------------------------------------------------\n\nIf you want to exclude only few tests from a run, you can either `skip` them:\n\n.. code-block:: bash\n\n    @test \"Testname\" {\n        # yadayada\n    }\n\nbecomes \n\n.. code-block:: bash\n\n    @test \"Testname\" {\n        skip 'Optional skip message'\n        # yadayada\n    }\n\nor comment them out, e.g.:\n\n.. code-block:: bash\n\n    @test \"Testname\" {\n\nbecomes \n\n.. code-block:: bash\n\n    disabled() { # @test \"Testname\" {\n\nFor multiple tests or all tests of a file, this becomes tedious, so read on.\n\nHow can I exclude all tests of a file from a test run?\n--------------------------------------------------------\n\nIf you run your test suite by naming individual files like:\n\n.. code-block:: bash\n\n    $ bats test/a.bats test/b.bats ...\n\nyou can simply omit your file. When running a folder like\n\n\n.. code-block:: bash\n\n    $ bats test/\n\nyou can prevent test files from being picked up by changing their extension to something other than `.bats`.\n\nIt is also possible to `skip` in `setup_file`/`setup` which will skip all tests in the file.\n\nHow can I include my own `.sh` files for testing?\n-------------------------------------------------\n\nYou can simply `source <your>.sh` files. However, be aware that `source`ing files with errors outside of any function (or inside `setup_file`) will trip up bats\nand lead to hard to diagnose errors.\nTherefore, it is safest to only `source` inside `setup` or the test functions themselves.\n\nHow can I debug a failing test?\n-------------------------------\n\nShort of using a bash debugger you should make sure to use appropriate asserts for your task instead of raw bash comparisons, e.g.:\n\n.. code-block:: bash\n\n    @test test {\n        run echo test failed\n        assert_output \"test\"\n        # instead of \n        [ \"$output\" = \"test\" ]\n    }\n\nBecause the former will print the output when the test fails while the latter won't.\nSimilarly, you should use `assert_success`/`assert_failure` instead of `[ \"$status\" -eq 0 ]` for return code checks.\n\nIs there a mechanism to add file/test specific functionality to a common setup function?\n----------------------------------------------------------------------------------------\n\nOften the setup consists of parts that are common between different files of a test suite and parts that are specific to each file.\nThere is no suite wide setup functionality yet, so you should extract these common setup steps into their own file (e.g. `common-test-setup.sh`) and function (e.g. `commonSetup() {}`),\nwhich can be `source`d or `load`ed and call it in `setup_file` or `setup`.\n\nHow can I use helper libraries like bats-assert?\n------------------------------------------------\n\nThis is a short reproduction of https://github.com/ztombol/bats-docs.\n\nAt first, you should make sure the library is installed. This is usually done in the `test_helper/` folders alongside the `.bats` files, giving you a filesystem layout like this:\n\n.. code-block::\n\n    test/\n        test.bats\n        test_helper/\n            bats-support/\n            bats-assert/\n\nNext, you should load those helper libraries:\n\n.. code-block:: bash\n\n    setup() {\n        load 'test_helper/bats-support/load' # this is required by bats-assert!\n        load 'test_helper/bats-assert/load'\n    }    \n\nNow, you should be able to use the functions from these helpers inside your tests, e.g.:\n\n.. code-block:: bash\n\n    @test \"test\" {\n        run echo test\n        assert_output \"test\"\n    }\n\nNote that you obviously need to load the library before using it.\nIf you need the library inside `setup_file` or `teardown_file` you need to load it in `setup_file`.\n\nHow to set a test timeout in bats?\n----------------------------------\n\nUnfortunately, this is not possible yet. Please contribute to issue `#396 <https://github.com/bats-core/bats-core/issues/396>`_ for further progress.\n\nHow can I lint/shell-format my bats tests?\n------------------------------------------\n\nDue to their custom syntax (`@test`), `.bats` files are not standard bash. This prevents most tools from working with bats.\nHowever, there is an alternative syntax `function_name { # @test` to declare tests in a bash compliant manner.\n\n- shellcheck support since version 0.7\n- shfmt support since version 3.2.0 (using `-ln bats`)\n\n\nHow can I check if a test failed/succeeded during teardown?\n-----------------------------------------------------------\n\nYou can check `BATS_TEST_COMPLETED` which will be set to 1 if the test was successful or empty if it was not.\nThere is also `BATS_TEST_SKIPPED` which will be non-empty (contains the skip message or -1) when `skip` was called.\n\nHow can I setup/cleanup before/after all tests?\n-----------------------------------------------\n\nCurrently, this is not supported. Please contribute your usecase to issue `#39 <https://github.com/bats-core/bats-core/issues/39>`_.\n"
  },
  {
    "path": "vendor/bats-core/docs/source/gotchas.rst",
    "content": "Gotchas\n=======\n\nMy test fails although I return true?\n-------------------------------------\n\nUsing `return 1` to signify `true` for a success as is done often in other languages does not mesh well with Bash's \nconvention of using return code 0 to signify success and everything non-zero to indicate a failure.\n\nPlease adhere to this idiom while using bats, or you will constantly work against your environment.\n\nMy negated statement (e.g. ! true) does not fail the test, even when it should.\n-------------------------------------------------------------------------------\n\nBash deliberately excludes negated return values from causing a pipeline to exit (see bash's `-e` option). You'll need to use the form `! x || false` or (recommended) use `run` and check for `[ $status != 0 ]`.\n\nIf the negated command is the final statement in a test, that final statement's (negated) exit status will propagate through to the test's return code as usual.\nNegated statements of the form `! x || false` will explicitly fail the test when the pipeline returns true, regardless of where they occur in the test.\n\nI cannot register a test multiple times via for loop.\n-----------------------------------------------------\n\nThe usual bats tests (`@test`) are preprocessed into functions.\nWrapping them into a for loop only redeclares this function.\n\nIf you are interested in registering multiple calls to the same function, contribute your wishes to issue `#306 <https://github.com/bats-core/bats-core/issues/306>`_.\n\nI cannot pass parameters to test or .bats files.\n------------------------------------------------\n\nEspecially while using bats via shebang:\n\n.. code-block:: bash\n\n    #!/usr/bin/env bats\n\n    @test \"test\" {\n        # ...\n    }\n\nYou could be tempted to pass parameters to the test invocation like `./test.bats param1 param2`.\nHowever, bats does not support passing parameters to files or tests.\nIf you need such a feature, please let us know about your usecase.\n\nAs a workaround you can use environment variables to pass parameters.\n\nWhy can't my function return results via a variable when using `run`?\n---------------------------------------------------------------------\n\nThe `run` function executes its command in a subshell which means the changes to variables won't be available in the calling shell.\n\nIf you want to test these functions, you should call them without `run`.\n\n`run` doesn't fail, although the same command without `run` does.\n-----------------------------------------------------------------\n\n`run` is a wrapper that always succeeds. The wrapped command's exit code is stored in `$status` and the stdout/stderr in `$output`.\nIf you want to fail the test, you should explicitly check `$status` or omit `run`. See also `when not to use run <writing-tests.html#when-not-to-use-run>`_.\n\n`load` won't load my `.sh` files.\n---------------------------------\n\n`load` is intended as an internal helper function that always loads `.bash` files (by appending this suffix).\nIf you want to load an `.sh` file, you can simple `source` it.\n\nI can't lint/shell-format my bats tests.\n----------------------------------------\n\nBats uses a custom syntax for annotating tests (`@test`) that is not bash compliant.\nTherefore, standard bash tooling won't be able to interact directly with `.bats` files.\nShellcheck supports bats' native syntax as of version 0.7.\n\nAdditionally, there is bash compatible syntax for tests: \n\n.. code-block:: bash \n\n    function bash_compliant_function_name_as_test_name { # @test\n        # your code\n    }\n\n\nThe output (stdout/err) from commands under `run` is not visible in failed tests.\n---------------------------------------------------------------------------------\n\nBy default, `run` only stores stdout/stderr in `$output` (and `${lines[@]}`).\nIf you want to see this output, you either should use bat-assert's assertions or have to print `$output` before the check that fails.\n\nMy piped command does not work under run.\n-----------------------------------------\n\nBe careful with using pipes and with `run`. While your mind model of `run` might wrap the whole command behind it, bash's parser won't\n\n.. code-block:: bash\n\n    run echo foo | grep bar\n\nWon't `run (echo foo | grep bar)` but will `(run echo foo) | grep bar`. If you need to incorporate pipes, you either should do\n\n.. code-block:: bash\n\n    run bash -c 'echo foo | grep bar'\n\nor use a function to wrap the pipe in:\n\n.. code-block:: bash\n\n    fun_with_pipes() {\n        echo foo | grep bar\n    }\n\n    run fun_with_pipes\n\n`[[ ]]` (or `(( ))` did not fail my test\n----------------------------------------\n\nThe `set -e` handling of `[[ ]]` and `(( ))` changed in Bash 4.1. Older versions, like 3.2 on MacOS,\ndon't abort the test when they fail, unless they are the last command before the (test) function returns,\nmaking their exit code the return code.\n\n`[ ]`  does not suffer from this, but is no replacement for all `[[ ]]` usecases. Appending ` || false` will work in all cases.\n\nBackground tasks prevent the test run from terminating when finished\n--------------------------------------------------------------------\n\nWhen running a task in background, it will inherit the opened FDs of the process it was forked from.\nThis means that the background task forked from a Bats test will hold the FD for the pipe to the formatter that prints to the terminal,\nthus keeping it open until the background task finished.\nDue to implementation internals of Bats and bash, this pipe might be held in multiple FDs which all have to be closed by the background task.\n\nYou can use `close_non_std_fds from `test/fixtures/bats/issue-205.bats` in the background job to close all FDs except stdin, stdout and stderr, thus solving the problem.\nMore details about the issue can be found in [#205](https://github.com/bats-core/bats-core/issues/205#issuecomment-973572596).\n"
  },
  {
    "path": "vendor/bats-core/docs/source/index.rst",
    "content": "Welcome to bats-core's documentation!\n=====================================\n\nVersions before v1.2.1 are documented over `there <https://github.com/bats-core/bats-core/blob/master/docs/versions.md>`_.\n\n.. toctree::\n   :maxdepth: 2\n   :caption: Contents:\n\n   tutorial\n   installation\n   usage\n   docker-usage\n   writing-tests\n   gotchas\n   faq\n\n"
  },
  {
    "path": "vendor/bats-core/docs/source/installation.rst",
    "content": "\nInstallation\n============\n\nSupported Bash versions\n^^^^^^^^^^^^^^^^^^^^^^^\n\nThe following is a list of Bash versions that are currently supported by Bats.\nThis list is composed of platforms that Bats has been tested on and is known to\nwork on without issues.\n\n\n* \n  Bash versions:\n\n\n  * Everything from ``3.2.57(1)`` and higher (macOS's highest version)\n\n* \n  Operating systems:\n\n\n  * Arch Linux\n  * Alpine Linux\n  * Ubuntu Linux\n  * FreeBSD ``10.x`` and ``11.x``\n  * macOS\n  * Windows 10\n\n* \n  Latest version for the following Windows platforms:\n\n\n  * Git for Windows Bash (MSYS2 based)\n  * Windows Subsystem for Linux\n  * MSYS2\n  * Cygwin\n\nHomebrew\n^^^^^^^^\n\nOn macOS, you can install `Homebrew <https://brew.sh/>`_ if you haven't already,\nthen run:\n\n.. code-block:: bash\n\n   $ brew install bats-core\n\nnpm\n^^^\n\nYou can install the `Bats npm package <https://www.npmjs.com/package/bats>`_ via:\n\n.. code-block::\n\n   # To install globally:\n   $ npm install -g bats\n\n   # To install into your project and save it as one of the \"devDependencies\" in\n   # your package.json:\n   $ npm install --save-dev bats\n\nInstalling Bats from source\n^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nCheck out a copy of the Bats repository. Then, either add the Bats ``bin``\ndirectory to your ``$PATH``\\ , or run the provided ``install.sh`` command with the\nlocation to the prefix in which you want to install Bats. For example, to\ninstall Bats into ``/usr/local``\\ ,\n\n.. code-block::\n\n   $ git clone https://github.com/bats-core/bats-core.git\n   $ cd bats-core\n   $ ./install.sh /usr/local\n\n\n**Note:** You may need to run ``install.sh`` with ``sudo`` if you do not have\npermission to write to the installation prefix.\n\nInstalling Bats from source onto Windows Git Bash\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nCheck out a copy of the Bats repository and install it to ``$HOME``. This\nwill place the ``bats`` executable in ``$HOME/bin``\\ , which should already be\nin ``$PATH``.\n\n.. code-block::\n\n   $ git clone https://github.com/bats-core/bats-core.git\n   $ cd bats-core\n   $ ./install.sh $HOME\n\n\nRunning Bats in Docker\n^^^^^^^^^^^^^^^^^^^^^^\n\nThere is an official image on the Docker Hub:\n\n.. code-block::\n\n   $ docker run -it bats/bats:latest --version\n\n\nBuilding a Docker image\n~~~~~~~~~~~~~~~~~~~~~~~\n\nCheck out a copy of the Bats repository, then build a container image:\n\n.. code-block::\n\n   $ git clone https://github.com/bats-core/bats-core.git\n   $ cd bats-core\n   $ docker build --tag bats/bats:latest .\n\n\nThis creates a local Docker image called ``bats/bats:latest`` based on `Alpine\nLinux <https://github.com/gliderlabs/docker-alpine/blob/master/docs/usage.md>`_\n(to push to private registries, tag it with another organisation, e.g.\n``my-org/bats:latest``\\ ).\n\nTo run Bats' internal test suite (which is in the container image at\n``/opt/bats/test``\\ ):\n\n.. code-block::\n\n   $ docker run -it bats/bats:latest /opt/bats/test\n\n\nTo run a test suite from a directory called ``test`` in the current directory of\nyour local machine, mount in a volume and direct Bats to its path inside the\ncontainer:\n\n.. code-block::\n\n   $ docker run -it -v \"${PWD}:/code\" bats/bats:latest test\n\n\n..\n\n   ``/code`` is the working directory of the Docker image. \"${PWD}/test\" is the\n   location of the test directory on the local machine.\n\n\nThis is a minimal Docker image. If more tools are required this can be used as a\nbase image in a Dockerfile using ``FROM <Docker image>``.  In the future there may\nbe images based on Debian, and/or with more tools installed (\\ ``curl`` and ``openssl``\\ ,\nfor example). If you require a specific configuration please search and +1 an\nissue or `raise a new issue <https://github.com/bats-core/bats-core/issues>`_.\n\nFurther usage examples are in\n`the wiki <https://github.com/bats-core/bats-core/wiki/Docker-Usage-Examples>`_.\n"
  },
  {
    "path": "vendor/bats-core/docs/source/requirements.txt",
    "content": "sphinxcontrib-programoutput\nrecommonmark"
  },
  {
    "path": "vendor/bats-core/docs/source/tutorial.rst",
    "content": "Tutorial\n========\n\nThis tutorial is intended for beginners with bats and possibly bash.\nMake sure to also read the list of gotchas and the faq.\n\nFor this tutorial we are assuming you already have a project in a git repository and want to add tests.\nUltimately they should run in the CI environment but will also be started locally during development.\n\n..\n    TODO: link to example repository?\n\nQuick installation\n------------------\n\nSince we already have an existing git repository, it is very easy to include bats and its libraries as submodules.\nWe are aiming for following filesystem structure:\n\n.. code-block:: \n\n    src/\n        project.sh\n        ...\n    test/\n        bats/               <- submodule\n        test_helper/\n            bats-support/   <- submodule\n            bats-assert/    <- submodule\n        test.bats\n        ...\n\nSo we start from the project root:\n\n.. code-block:: console\n    \n    git submodule add https://github.com/bats-core/bats-core.git test/bats\n    git submodule add https://github.com/bats-core/bats-support.git test/test_helper/bats-support\n    git submodule add https://github.com/bats-core/bats-assert.git test/test_helper/bats-assert\n\nYour first test\n---------------\n\nNow we want to add our first test.\n\nIn the tutorial repository, we want to build up our project in a TDD fashion.\nThus, we start with an empty project and our first test is to just run our (non existing) shell script.\n\nWe start by creating a new test file `test/test.bats`\n\n.. code-block:: bash\n\n    @test \"can run our script\" {\n        ./project.sh\n    }\n\nand run it by\n\n.. code-block:: console\n\n    $ ./test/bats/bin/bats test/test.bats\n     ✗ can run our script\n       (in test file test/test.bats, line 2)\n         `./project.sh' failed with status 127\n       /tmp/bats-run-19605/bats.19627.src: line 2: ./project.sh: No such file or directory\n\n    1 test, 1 failure\n\nOkay, our test is red. Obviously, the project.sh doesn't exist, so we create the file `src/project.sh`:\n\n.. code-block:: console\n\n    mkdir src/\n    echo '#!/usr/bin/env bash' > src/project.sh\n    chmod a+x src/project.sh\n\nA new test run gives us\n\n.. code-block:: console\n\n    $ ./test/bats/bin/bats test/test.bats\n     ✗ can run our script\n       (in test file test/test.bats, line 2)\n         `./project.sh' failed with status 127\n       /tmp/bats-run-19605/bats.19627.src: line 2: ./project.sh: No such file or directory\n\n    1 test, 1 failure\n\nOh, we still used the wrong path. No problem, we just need to use the correct path to `project.sh`.\nSince we're still in the same directory as when we started `bats`, we can simply do:\n\n.. code-block:: bash\n\n    @test \"can run our script\" {\n        ./src/project.sh\n    }\n\nand get:\n\n.. code-block:: console\n\n    $ ./test/bats/bin/bats test/test.bats \n     ✓ can run our script\n\n    1 test, 0 failures\n\nYesss! But that victory feels shallow: What if somebody less competent than us starts bats from another directory?\n\nLet's do some setup\n-------------------\n\nThe obvious solution to becoming independent of `$PWD` is using some fixed anchor point in the filesystem.\nWe can use the path to the test file itself as an anchor and rely on the internal project structure.\nSince we are lazy people and want to treat our project's files as first class citizens in the executable world, we will also put them on the `$PATH`.\nOur new `test/test.bats` now looks like this:\n\n.. code-block:: bash\n\n    setup() {\n        # get the containing directory of this file\n        # use $BATS_TEST_FILENAME instead of ${BASH_SOURCE[0]} or $0,\n        # as those will point to the bats executable's location or the preprocessed file respectively\n        DIR=\"$( cd \"$( dirname \"$BATS_TEST_FILENAME\" )\" >/dev/null 2>&1 && pwd )\"\n        # make executables in src/ visible to PATH\n        PATH=\"$DIR/../src:$PATH\"\n    }\n\n    @test \"can run our script\" {\n        # notice the missing ./ \n        # As we added src/ to $PATH, we can omit the relative path to `src/project.sh`.\n        project.sh\n    }\n\nstill giving us:\n\n.. code-block:: console\n\n    $ ./test/bats/bin/bats test/test.bats \n     ✓ can run our script\n\n    1 test, 0 failures\n\nIt still works as expected. This is because the newly added `setup` function put the absolute path to `src/` onto `$PATH`.\nThis setup function is automatically called before each test.\nTherefore, our test could execute `project.sh` directly, without using a (relative) path.\n\n.. important::\n\n    The `setup` function will be called before each individual test in the file. \n    Each file can only define one setup function for all tests in the file.\n    However, the setup functions can differ between different files.\n\nDealing with output\n-------------------\n\nOkay, we have a green test but our executable does not do anything useful.\nTo keep things simple, let us start with an error message. Our new `src/project.sh` now reads:\n\n.. code-block:: bash\n\n    #!/usr/bin/env bash\n\n    echo \"Welcome to our project!\"\n\n    echo \"NOT IMPLEMENTED!\" >&2\n    exit 1\n\nAnd gives is this test output:\n\n.. code-block:: console\n\n    $ ./test/bats/bin/bats test/test.bats \n     ✗ can run our script\n       (in test file test/test.bats, line 11)\n         `project.sh' failed\n       Welcome to our project!\n       NOT IMPLEMENTED!\n\n    1 test, 1 failure\n\nOkay, our test failed, because we now exit with 1 instead of 0.\nAdditionally, we see the stdout and stderr of the failing program.\n\nOur goal now is to retarget our test and check that we get the welcome message.\nbats-assert gives us some help with this, so we should now load it (and its dependency bats-support),\nso we change `test/test.bats` to\n\n.. code-block:: bash\n\n    setup() {\n        load 'test_helper/bats-support/load'\n        load 'test_helper/bats-assert/load'\n        # ... the remaining setup is unchanged\n\n        # get the containing directory of this file\n        # use $BATS_TEST_FILENAME instead of ${BASH_SOURCE[0]} or $0,\n        # as those will point to the bats executable's location or the preprocessed file respectively\n        DIR=\"$( cd \"$( dirname \"$BATS_TEST_FILENAME\" )\" >/dev/null 2>&1 && pwd )\"\n        # make executables in src/ visible to PATH\n        PATH=\"$DIR/../src:$PATH\"\n    }\n\n    @test \"can run our script\" {\n        run project.sh # notice `run`!\n        assert_output 'Welcome to our project!'\n    }\n\nwhich gives us the following test output:\n\n.. code-block:: console\n\n    $ LANG=C ./test/bats/bin/bats test/test.bats \n     ✗ can run our script\n       (from function `assert_output' in file test/test_helper/bats-assert/src/assert_output.bash, line 194,\n        in test file test/test.bats, line 14)\n         `assert_output 'Welcome to our project!'' failed\n    \n       -- output differs --\n       expected (1 lines):\n         Welcome to our project!\n       actual (2 lines):\n         Welcome to our project!\n         NOT IMPLEMENTED!\n       --\n    \n\n    1 test, 1 failure\n\nThe first change in this output is the failure description. We now fail on assert_output instead of the call itself.\nWe prefixed our call to `project.sh` with `run`, which is a function provided by bats that executes the command it gets passed as parameters.\nThen, `run` sucks up the stdout and stderr of the command it ran and stores it in `$output`, stores the exit code in `$status` and returns 0.\nThis means `run` never fails the test and won't generate any context/output in the log of a failed test on its own.\n\nMarking the test as failed and printing context information is up to the consumers of `$status` and `$output`. \n`assert_output` is such a consumer, it compares `$output` to the the parameter it got and tells us quite succinctly that it did not match in this case.\n\nFor our current test we don't care about any other output or the error message, so we want it gone.\n`grep` is always at our fingertips, so we tape together this ramshackle construct\n\n.. code-block:: bash\n\n    run project.sh 2>&1 | grep Welcome\n\nwhich gives us the following test result:\n\n.. code-block:: console\n\n    $ ./test/bats/bin/bats test/test.bats \n     ✗ can run our script\n       (in test file test/test.bats, line 13)\n         `run project.sh | grep Welcome' failed\n\n    1 test, 1 failure\n\nHuh, what is going on? Why does it fail the `run` line again?\n\nThis is a common mistake that can happen when our mind parses the file differently than the bash parser.\n`run` is just a function, so the pipe won't actually be forwarded into the function. Bash reads this as `(run project.sh) | grep Welcome`, \ninstead of our intended `run (project.sh | grep Welcome)`.\n\nUnfortunately, the latter is no valid bash syntax, so we have to work around it, e.g. by using a function:\n\n.. code-block:: bash\n\n    get_projectsh_welcome_message() {\n        project.sh  2>&1 | grep Welcome\n    }\n\n    @test \"Check welcome message\" {\n        run get_projectsh_welcome_message\n        assert_output 'Welcome to our project!'\n    }\n\nNow our test passes again but having to write a function each time we want only a partial match does not accommodate our laziness.\nIsn't there an app for that? Maybe we should look at the documentation?\n\n    Partial matching can be enabled with the --partial option (-p for short). When used, the assertion fails if the expected substring is not found in $output.\n\n    -- the documentation for `assert_output <https://github.com/bats-core/bats-assert#partial-matching>`_\n\nOkay, so maybe we should try that:\n\n.. code-block:: bash\n\n    @test \"Check welcome message\" {\n        run project.sh\n        assert_output --partial 'Welcome to our project!'\n    }\n\nAaannnd ... the test stays green. Yay!\n\nThere are many other asserts and options but this is not the place for all of them.\nSkimming the documentation of `bats-assert <https://github.com/bats-core/bats-assert>`_ will give you a good idea what you can do.\nYou should also have a look at the other helper libraries `here <https://github.com/bats-core>`_ like `bats-file <https://github.com/bats-core/bats-file>`_, \nto avoid reinventing the wheel.\n\n\nCleaning up your mess\n---------------------\n\nOften our setup or tests leave behind some artifacts that clutter our test environment.\nYou can define a `teardown` function which will be called after each test, regardless whether it failed or not.\n\nFor example, we now want our project.sh to only show the welcome message on the first invocation.\nSo we change our test to this:\n\n.. code-block:: bash\n\n    @test \"Show welcome message on first invocation\" {\n        run project.sh\n        assert_output --partial 'Welcome to our project!'\n\n        run project.sh\n        refute_output --partial 'Welcome to our project!'\n    }\n\nThis test fails as expected:\n\n.. code-block:: console\n\n    $ ./test/bats/bin/bats test/test.bats \n     ✗ Show welcome message on first invocation\n       (from function `refute_output' in file test/test_helper/bats-assert/src/refute_output.bash, line 189,\n        in test file test/test.bats, line 17)\n         `refute_output --partial 'Welcome to our project!'' failed\n    \n       -- output should not contain substring --\n       substring (1 lines):\n         Welcome to our project!\n       output (2 lines):\n         Welcome to our project!\n         NOT IMPLEMENTED!\n       --\n    \n\n    1 test, 1 failure\n\nNow, to get the test green again, we want to store the information that we already ran in the file `/tmp/bats-tutorial-project-ran`,\nso our `src/project.sh` becomes:\n\n.. code-block:: bash\n\n    #!/usr/bin/env bash\n\n    FIRST_RUN_FILE=/tmp/bats-tutorial-project-ran\n\n    if [[ ! -e \"$FIRST_RUN_FILE\" ]]; then\n        echo \"Welcome to our project!\"\n        touch \"$FIRST_RUN_FILE\"\n    fi\n\n    echo \"NOT IMPLEMENTED!\" >&2\n    exit 1\n\nAnd our test says:\n\n.. code-block:: console\n\n    $ ./test/bats/bin/bats test/test.bats \n     ✓ Show welcome message on first invocation\n\n    1 test, 0 failures\n\nNice, we're done, or are we? Running the test again now gives:\n\n.. code-block:: console\n\n    $ ./test/bats/bin/bats test/test.bats \n     ✗ Show welcome message on first invocation\n       (from function `assert_output' in file test/test_helper/bats-assert/src/assert_output.bash, line 186,\n        in test file test/test.bats, line 14)\n         `assert_output --partial 'Welcome to our project!'' failed\n    \n       -- output does not contain substring --\n       substring : Welcome to our project!\n       output    : NOT IMPLEMENTED!\n       --\n    \n\n    1 test, 1 failure\n\nNow the first assert failed, because of the leftover `$FIRST_RUN_FILE` from the last test run.\n\nLuckily, bats offers the `teardown` function, which can take care of that, we add the following code to `test/test.bats`:\n\n.. code-block:: bash\n\n    teardown() {\n        rm -f /tmp/bats-tutorial-project-ran\n    }\n\nNow running the test again first give us the same error, as the teardown has not run yet. \nOn the second try we get a clean `/tmp` folder again and our test passes consistently now.\n\nIt is worth noting that we could do this `rm` in the test code itself but it would get skipped on failures.\n\n.. important::\n\n    A test ends at its first failure. None of the subsequent commands in this test will be executed.\n    The `teardown` function runs after each individual test in a file, regardless of test success or failure.\n    Similarly to `setup`, each `.bats` file can have its own `teardown` function which will be the same for all tests in the file.\n\nTest what you can\n-----------------\n\nSometimes tests rely on the environment to provide infrastructure that is needed for the test.\nIf not all test environments provide this infrastructure but we still want to test on them,\nit would be unhelpful to get errors on parts that are not testable.\n\nBats provides you with the `skip` command which can be used in `setup` and `test`.\n\n.. tip::    \n    \n    You should `skip` as early as you know it does not make sense to continue.\n\nIn our example project we rewrite the welcome message test to `skip` instead of doing cleanup:\n\n.. code-block:: bash\n\n    teardown() {\n        : # Look Ma! No cleanup!\n    } \n\n    @test \"Show welcome message on first invocation\" {\n        if [[ -e /tmp/bats-tutorial-project-ran ]]; then\n            skip 'The FIRST_RUN_FILE already exists'\n        fi\n        \n        run project.sh\n        assert_output --partial 'Welcome to our project!'\n\n        run project.sh\n        refute_output --partial 'Welcome to our project!'\n    }\n\nThe first test run still works due to the cleanup from the last round. However, our second run gives us:\n\n.. code-block:: console\n\n    $ ./test/bats/bin/bats test/test.bats \n     - Show welcome message on first invocation (skipped: The FIRST_RUN_FILE already exists)\n\n    1 test, 0 failures, 1 skipped\n\n.. important::\n\n    Skipped tests won't fail a test suite and are counted separately.\n    No test command after `skip` will be executed. If an error occurs before `skip`, the test will fail.\n    An optional reason can be passed to `skip` and will be printed in the test output.\n\nSetting up a multifile test suite\n---------------------------------\n\nWith a growing project, putting all tests into one file becomes unwieldy.\nFor our example project, we will extract functionality into the additional file `src/helper.sh`:\n\n.. code-block:: bash\n\n    #!/usr/bin/env bash\n\n    _is_first_run() {\n        local FIRST_RUN_FILE=/tmp/bats-tutorial-project-ran\n        if [[ ! -e \"$FIRST_RUN_FILE\" ]]; then\n            touch \"$FIRST_RUN_FILE\"\n            return 0\n        fi\n        return 1\n    }\n\nThis allows for testing it separately in a new file `test/helper.bats`:\n\n.. code-block:: bash\n\n    setup() {\n        load 'test_helper/common-setup'\n        _common_setup\n\n        source \"$PROJECT_ROOT/src/helper.sh\"\n    }\n\n    teardown() {\n        rm -f \"$NON_EXISTANT_FIRST_RUN_FILE\"\n        rm -f \"$EXISTING_FIRST_RUN_FILE\"\n    }\n\n    @test \"Check first run\" {\n        NON_EXISTANT_FIRST_RUN_FILE=$(mktemp -u) # only create the name, not the file itself\n\n        assert _is_first_run\n        refute _is_first_run\n        refute _is_first_run\n\n        EXISTING_FIRST_RUN_FILE=$(mktemp)\n        refute _is_first_run\n        refute _is_first_run\n    }\n\nSince the setup function would have duplicated much of the other files', we split that out into the file `test/test_helper/common-setup.bash`:\n\n.. code-block:: bash\n\n    #!/usr/bin/env bash\n\n    _common_setup() {\n        load 'test_helper/bats-support/load'\n        load 'test_helper/bats-assert/load'\n        # get the containing directory of this file\n        # use $BATS_TEST_FILENAME instead of ${BASH_SOURCE[0]} or $0,\n        # as those will point to the bats executable's location or the preprocessed file respectively\n        PROJECT_ROOT=\"$( cd \"$( dirname \"$BATS_TEST_FILENAME\" )/..\" >/dev/null 2>&1 && pwd )\"\n        # make executables in src/ visible to PATH\n        PATH=\"$PROJECT_ROOT/src:$PATH\"\n    }\n\nwith the following `setup` in `test/test.bats`:\n\n.. code-block:: bash\n\n    setup() {\n        load 'test_helper/common-setup'\n        _common_setup\n    }\n\nPlease note, that we gave our helper the extension `.bash`, which is automatically appended by `load`.\n\n.. important:: \n\n    `load` automatically tries to append `.bash` to its argument.\n\nIn our new `test/helper.bats` we can see, that loading `.sh` is simply done via `source`.\n\n.. tip::\n\n    Avoid using `load` and `source` outside of any functions.\n    If there is an error in the test file's \"free code\", the diagnostics are much worse than for code in `setup` or `@test`.\n\nWith the new changes in place, we can run our tests again. However, our previous run command does not include the new file.\nYou could add the new file to the parameter list, e.g. by running `./test/bats/bin/bats test/*.bats`.\nHowever, bats also can handle directories:\n\n.. code-block:: console\n\n    $ ./test/bats/bin/bats test/\n     ✓ Check first run\n     - Show welcome message on first invocation (skipped: The FIRST_RUN_FILE already exists)\n\n    2 tests, 0 failures, 1 skipped\n\nIn this mode, bats will pick up all `.bats` files in the directory it was given. There is an additional `-r` switch that will recursively search for more `.bats` files.\nHowever, in our project layout this would pick up the test files of bats itself from `test/bats/test`. We don't have test subfolders anyways, so we can do without `-r`.\n\n\nAvoiding costly repeated setups\n-------------------------------\n\nWe already have seen the `setup` function in use, which is called before each test.\nSometimes our setup is very costly, such as booting up a service just for testing. \nIf we can reuse the same setup across multiple tests, we might want to do only one setup before all these tests.\n\nThis usecase is exactly what the `setup_file` function was created for.\nIt can be defined per file and will run before all tests of the respective file.\nSimilarly, we have `teardown_file`, which will run after all tests of the file, even when you abort a test run or a test failed.\n\nAs an example, we want to add an echo server capability to our project. First, we add the following `server.bats` to our suite:\n\n.. code-block:: bash\n\n    setup_file() {\n        load 'test_helper/common-setup'\n        _common_setup\n        PORT=$(project.sh start-echo-server >/dev/null 2>&1)\n        export PORT\n    }\n\n    @test \"server is reachable\" {\n        nc -z localhost \"$PORT\"\n    }\n\nWhich will obviously fail:\n\nNote that `export PORT` to make it visible to the test!\nRunning this gives us:\n\n..\n    TODO: Update this example with fixed test name reporting from setup_file? (instead of \"✗ \")\n\n.. code-block:: console\n\n   $ ./test/bats/bin/bats test/server.bats \n     ✗ \n       (from function `setup_file' in test file test/server.bats, line 4)\n         `PORT=$(project.sh start-echo-server >/dev/null 2>&1)' failed\n\n    1 test, 1 failure \n\nNow that we got our red test, we need to get it green again.\nOur new `project.sh` now ends with:\n\n.. code-block:: bash\n\n    case $1 in\n        start-echo-server)\n            echo \"Starting echo server\"\n            PORT=2000\n            ncat -l $PORT -k -c 'xargs -n1 echo' 2>/dev/null & # don't keep open this script's stderr\n            echo $! > /tmp/project-echo-server.pid\n            echo \"$PORT\" >&2\n        ;;\n        *)\n            echo \"NOT IMPLEMENTED!\" >&2\n            exit 1\n        ;;\n    esac\n\nand the tests now say\n\n.. code-block:: console\n\n    $ LANG=C ./test/bats/bin/bats test/server.bats \n     ✓ server is reachable\n\n    1 test, 0 failures\n\nHowever, running this a second time gives:\n\n.. code-block:: console\n\n    $ ./test/bats/bin/bats test/server.bats\n     ✗ server is reachable\n       (in test file test/server.bats, line 14)\n         `nc -z -w 2 localhost \"$PORT\"' failed\n       2000\n       Ncat: bind to :::2000: Address already in use. QUITTING.\n       nc: port number invalid: 2000\n       Ncat: bind to :::2000: Address already in use. QUITTING.\n\n    1 test, 1 failure\n\nObviously, we did not turn off our server after testing.\nThis is a task for `teardown_file` in `server.bats`:\n\n.. code-block:: bash\n\n    teardown_file() {\n        project.sh stop-echo-server\n    }\n\nOur `project.sh` should also get the new command:\n\n.. code-block:: bash\n\n    stop-echo-server)\n        kill \"$(< \"/tmp/project-echo-server.pid\")\"\n        rm /tmp/project-echo-server.pid\n    ;;\n\nNow starting our tests again will overwrite the .pid file with the new instance's, so we have to do manual cleanup once.\nFrom now on, our test should clean up after itself.\n\n.. note:: \n\n    `teardown_file` will run regardless of tests failing or succeeding.\n"
  },
  {
    "path": "vendor/bats-core/docs/source/usage.md",
    "content": "# Usage\n\nBats comes with two manual pages. After installation you can view them with `man\n1 bats` (usage manual) and `man 7 bats` (writing test files manual). Also, you\ncan view the available command line options that Bats supports by calling Bats\nwith the `-h` or `--help` options. These are the options that Bats currently\nsupports:\n\n``` eval_rst\n.. program-output:: ../../bin/bats --help\n```\n\nTo run your tests, invoke the `bats` interpreter with one or more paths to test\nfiles ending with the `.bats` extension, or paths to directories containing test\nfiles. (`bats` will only execute `.bats` files at the top level of each\ndirectory; it will not recurse unless you specify the `-r` flag.)\n\nTest cases from each file are run sequentially and in isolation. If all the test\ncases pass, `bats` exits with a `0` status code. If there are any failures,\n`bats` exits with a `1` status code.\n\nWhen you run Bats from a terminal, you'll see output as each test is performed,\nwith a check-mark next to the test's name if it passes or an \"X\" if it fails.\n\n```text\n$ bats addition.bats\n ✓ addition using bc\n ✓ addition using dc\n\n2 tests, 0 failures\n```\n\nIf Bats is not connected to a terminal—in other words, if you run it from a\ncontinuous integration system, or redirect its output to a file—the results are\ndisplayed in human-readable, machine-parsable [TAP format][https://testanything.org].\n\nYou can force TAP output from a terminal by invoking Bats with the `--formatter tap`\noption.\n\n```text\n$ bats --formatter tap addition.bats\n1..2\nok 1 addition using bc\nok 2 addition using dc\n```\n\nWith `--formatter junit`, it is possible\nto output junit-compatible report files.\n\n```text\n$ bats --formatter junit addition.bats\n1..2\nok 1 addition using bc\nok 2 addition using dc\n```\n\nTest reports will be output in the executing directory, but may be placed elsewhere\nby specifying the `--output` flag.\n\n```text\n$ bats --formatter junit addition.bats --output /tmp\n1..2\nok 1 addition using bc\nok 2 addition using dc\n```\n\n## Parallel Execution\n\n``` eval_rst\n.. versionadded:: 1.0.0\n```\n\nBy default, Bats will execute your tests serially. However, Bats supports\nparallel execution of tests (provided you have [GNU parallel][gnu-parallel] or\na compatible replacement installed) using the `--jobs` parameter. This can\nresult in your tests completing faster (depending on your tests and the testing\nhardware).\n\nOrdering of parallised tests is not guaranteed, so this mode may break suites\nwith dependencies between tests (or tests that write to shared locations). When\nenabling `--jobs` for the first time be sure to re-run bats multiple times to\nidentify any inter-test dependencies or non-deterministic test behaviour.\n\nWhen parallelizing, the results of a file only become visible after it has been finished.\nYou can use `--no-parallelize-across-files` to get immediate output at the cost of reduced\noverall parallelity, as parallelization will only happen within files and files will be run\nsequentially.\n\nIf you have files where tests within the file would interfere with each other, you can use\n`--no-parallelize-within-files` to disable parallelization within all files.\nIf you want more finegrained control, you can `export BATS_NO_PARALLELIZE_WITHIN_FILE=true` in `setup_file()`\nor outside any function to disable parallelization only within the containing file.\n\n[gnu-parallel]: https://www.gnu.org/software/parallel/\n"
  },
  {
    "path": "vendor/bats-core/docs/source/writing-tests.md",
    "content": "# Writing tests\n\nEach Bats test file is evaluated _n+1_ times, where _n_ is the number of\ntest cases in the file. The first run counts the number of test cases,\nthen iterates over the test cases and executes each one in its own\nprocess.\n\nFor more details about how Bats evaluates test files, see [Bats Evaluation\nProcess][bats-eval] on the wiki.\n\nFor sample test files, see [examples](https://github.com/bats-core/bats-core/tree/master/docs/examples).\n\n[bats-eval]: https://github.com/bats-core/bats-core/wiki/Bats-Evaluation-Process\n\n## Comment syntax\n\nExternal tools (like `shellcheck`, `shfmt`, and various IDE's) may not support\nthe standard `.bats` syntax.  Because of this, we provide a valid `bash`\nalternative:\n\n```bash\nfunction invoking_foo_without_arguments_prints_usage { #@test\n  run foo\n  [ \"$status\" -eq 1 ]\n  [ \"${lines[0]}\" = \"usage: foo <filename>\" ]\n}\n```\n\nWhen using this syntax, the function name will be the title in the result output\nand the value checked when using `--filter`.\n\n## `run`: Test other commands\n\nMany Bats tests need to run a command and then make assertions about its exit\nstatus and output. Bats includes a `run` helper that invokes its arguments as a\ncommand, saves the exit status and output into special global variables, and\nthen returns with a `0` status code so you can continue to make assertions in\nyour test case.\n\nFor example, let's say you're testing that the `foo` command, when passed a\nnonexistent filename, exits with a `1` status code and prints an error message.\n\n```bash\n@test \"invoking foo with a nonexistent file prints an error\" {\n  run foo nonexistent_filename\n  [ \"$status\" -eq 1 ]\n  [ \"$output\" = \"foo: no such file 'nonexistent_filename'\" ]\n  [ \"$BATS_RUN_COMMAND\" = \"foo nonexistent_filename\" ]\n\n}\n```\n\nThe `$status` variable contains the status code of the command, the\n`$output` variable contains the combined contents of the command's standard\noutput and standard error streams, and the `$BATS_RUN_COMMAND` string contains the\ncommand and command arguments passed to `run` for execution.\n\nIf invoked with one of the following as the first argument, `run`\nwill perform an implicit check on the exit status of the invoked command:\n\n```pre\n    =N  expect exit status N (0-255), fail if otherwise\n    ! expect nonzero exit status (1-255), fail if command succeeds\n```\n\nWe can then write the above more elegantly as:\n\n```bash\n@test \"invoking foo with a nonexistent file prints an error\" {\n  run -1 foo nonexistent_filename\n  [ \"$output\" = \"foo: no such file 'nonexistent_filename'\" ]\n}\n```\n\nA third special variable, the `$lines` array, is available for easily accessing\nindividual lines of output. For example, if you want to test that invoking `foo`\nwithout any arguments prints usage information on the first line:\n\n```bash\n@test \"invoking foo without arguments prints usage\" {\n  run -1 foo\n  [ \"${lines[0]}\" = \"usage: foo <filename>\" ]\n}\n```\n\n__Note:__ The `run` helper executes its argument(s) in a subshell, so if\nwriting tests against environmental side-effects like a variable's value\nbeing changed, these changes will not persist after `run` completes.\n\nBy default `run` leaves out empty lines in `${lines[@]}`. Use\n`run --keep-empty-lines` to retain them.\n\nAdditionally, you can use `--separate-stderr` to split stdout and stderr\ninto `$output`/`$stderr` and `${lines[@]}`/`${stderr_lines[@]}`.\n\nAll additional parameters to run should come before the command.\nIf you want to run a command that starts with `-`, prefix it with `--` to\nprevent `run` from parsing it as an option.\n\n## `load`: Share common code\n\nYou may want to share common code across multiple test files. Bats\nincludes a convenient `load` command for sourcing a Bash source files\nrelative to the current test file and from absolute paths.\n\nFor example, if you have a Bats test in `test/foo.bats`, the command\n\n```bash\nload test_helper.bash\n```\n\nwill source the script `test/test_helper.bash` in your test file (limitations\napply, see below). This can be useful for sharing functions to set up your\nenvironment or load fixtures. `load` delegates to Bash's `source` command after\nresolving paths.\n\nIf `load` encounters errors - e.g. because the targeted source file\nerrored - it will print a message with the failing library and Bats\nexits.\n\nTo allow to use `load` in conditions `bats_load_safe` has been added.\n`bats_load_safe` prints a message and returns `1` if a source file cannot be\nloaded instead of exiting Bats.\nAside from that `bats_load_safe` acts exactly like `load`.\n\nAs pointed out by @iatrou in https://www.tldp.org/LDP/abs/html/declareref.html,\nusing the `declare` builtin restricts scope of a variable. Thus, since actual\n`source`-ing is performed in context of the `load` function, `declare`d symbols\nwill _not_ be made available to callers of `load`.\n\n### `load` argument resolution\n\n`load` supports the following arguments:\n\n- absolute paths\n- relative paths (to the current test file)\n\n> For backwards compatibility `load` first searches for a file ending in\n> `.bash` (e.g. `load test_helper` searches for `test_helper.bash` before\n> it looks for `test_helper`). This behaviour is deprecated and subject to\n> change, please use exact filenames instead.\n\nIf `argument` is an absolute path `load` tries to determine the load\npath directly.\n\nIf `argument` is a relative path or a name `load` looks for a matching\npath in the directory of the current test.\n\n## `bats_load_library`: Load system wide libraries\n\nSome libraries are installed on the system, e.g. by `npm` or `brew`.\nThese should not be `load`ed, as their path depends on the installation method.\nInstead, one should use `bats_load_library` together with setting\n`BATS_LIB_PATH`, a `PATH`-like colon-delimited variable.\n\n`bats_load_library` has two modes of resolving requests:\n\n1. by relative path from the `BATS_LIB_PATH` to a file in the library\n2. by library name, expecting libraries to have a `load.bash` entrypoint\n\nFor example if your `BATS_LIB_PATH` is set to\n`~/.bats/libs:/usr/lib/bats`, then `bats_load_library test_helper`\nwould look for existing files with the following paths:\n\n- `~/.bats/libs/test_helper`\n- `~/.bats/libs/test_helper/load.bash`\n- `/usr/lib/bats/test_helper`\n- `/usr/lib/bats/test_helper/load.bash`\n\nThe first existing file in this list will be sourced.\n\nIf you want to load only part of a library or the entry point is not named `load.bash`,\nyou have to include it in the argument:\n`bats_load_library library_name/file_to_load` will try\n\n- `~/.bats/libs/library_name/file_to_load`\n- `~/.bats/libs/library_name/file_to_load/load.bash`\n- `/usr/lib/bats/library_name/file_to_load`\n- `/usr/lib/bats/library_name/file_to_load/load.bash`\n\nApart from the changed lookup rules, `bats_load_library` behaves like `load`.\n\n__Note:__ As seen above `load.bash` is the entry point for libraries and\nmeant to load more files from its directory or other libraries.\n\n__Note:__ Obviously, the actual `BATS_LIB_PATH` is highly dependant on the environment.\nTo maintain a uniform location across systems, (distribution) package maintainers\nare encouraged to use `/usr/lib/bats/` as the install path for libraries where possible.\nHowever, if the package manager has another preferred location, like `npm` or `brew`,\nyou should use this instead.\n\n## `skip`: Easily skip tests\n\nTests can be skipped by using the `skip` command at the point in a test you wish\nto skip.\n\n```bash\n@test \"A test I don't want to execute for now\" {\n  skip\n  run foo\n  [ \"$status\" -eq 0 ]\n}\n```\n\nOptionally, you may include a reason for skipping:\n\n```bash\n@test \"A test I don't want to execute for now\" {\n  skip \"This command will return zero soon, but not now\"\n  run foo\n  [ \"$status\" -eq 0 ]\n}\n```\n\nOr you can skip conditionally:\n\n```bash\n@test \"A test which should run\" {\n  if [ foo != bar ]; then\n    skip \"foo isn't bar\"\n  fi\n\n  run foo\n  [ \"$status\" -eq 0 ]\n}\n```\n\n__Note:__ `setup` and `teardown` hooks still run for skipped tests.\n\n## `setup` and `teardown`: Pre- and post-test hooks\n\nYou can define special `setup` and `teardown` functions, which run before and\nafter each test case, respectively. Use these to load fixtures, set up your\nenvironment, and clean up when you're done.\n\nYou can also define `setup_file` and `teardown_file`, which will run once before the first test's `setup` and after the last test's `teardown` for the containing file. Variables that are exported in `setup_file` will be visible to all following functions (`setup`, the test itself, `teardown`, `teardown_file`).\n\n<!-- markdownlint-disable  MD033 -->\n<details>\n  <summary>Example of setup/setup_file/teardown/teardown_file call order</summary>\nFor example the following call order would result from two files (file 1 with tests 1 and 2, and file 2 with test3) beeing tested:\n\n```text\nsetup_file # from file 1, on entering file 1\n  setup\n    test1\n  teardown\n  setup\n    test2\n  teardown\nteardown_file # from file 1, on leaving file 1\nsetup_file # from file 2,  on enter file 2\n  setup\n    test3\n  teardown\nteardown_file # from file 2,  on leaving file 2\n```\n\n</details>\n<!-- markdownlint-enable MD033 -->\n\n## Code outside of test cases\n\nYou can include code in your test file outside of `@test` functions.  For\nexample, this may be useful if you want to check for dependencies and fail\nimmediately if they're not present. However, any output that you print in code\noutside of `@test`, `setup` or `teardown` functions must be redirected to\n`stderr` (`>&2`). Otherwise, the output may cause Bats to fail by polluting the\nTAP stream on `stdout`.\n\n## File descriptor 3 (read this if Bats hangs)\n\nBats makes a separation between output from the code under test and output that\nforms the TAP stream (which is produced by Bats internals). This is done in\norder to produce TAP-compliant output. In the [Printing to the\nterminal](#printing-to-the-terminal) section, there are details on how to use\nfile descriptor 3 to print custom text properly.\n\nA side effect of using file descriptor 3 is that, under some circumstances, it\ncan cause Bats to block and execution to seem dead without reason. This can\nhappen if a child process is spawned in the background from a test. In this\ncase, the child process will inherit file descriptor 3. Bats, as the parent\nprocess, will wait for the file descriptor to be closed by the child process\nbefore continuing execution. If the child process takes a lot of time to\ncomplete (eg if the child process is a `sleep 100` command or a background\nservice that will run indefinitely), Bats will be similarly blocked for the same\namount of time.\n\n**To prevent this from happening, close FD 3 explicitly when running any command\nthat may launch long-running child processes**, e.g. `command_name 3>&-` .\n\n## Printing to the terminal\n\nBats produces output compliant with [version 12 of the TAP protocol](https://testanything.org/tap-specification.html). The\nproduced TAP stream is by default piped to a pretty formatter for human\nconsumption, but if Bats is called with the `-t` flag, then the TAP stream is\ndirectly printed to the console.\n\nThis has implications if you try to print custom text to the terminal. As\nmentioned in [File descriptor 3](#file-descriptor-3-read-this-if-bats-hangs),\nbats provides a special file descriptor, `&3`, that you should use to print\nyour custom text. Here are some detailed guidelines to refer to:\n\n- Printing **from within a test function**:\n  - First you should consider if you want the text to be always visible or only\n    when the test fails. Text that is output directly to stdout or stderr (file\n    descriptor 1 or 2), ie `echo 'text'` is considered part of the test function\n    output and is printed only on test failures for diagnostic purposes,\n    regardless of the formatter used (TAP or pretty).\n  - To have text printed unconditionally from within a test function you need to\n    redirect the output to file descriptor 3, eg `echo 'text' >&3`. This output\n    will become part of the TAP stream. You are encouraged to prepend text printed\n    this way with a hash (eg `echo '# text' >&3`) in order to produce 100% TAP compliant\n    output. Otherwise, depending on the 3rd-party tools you use to analyze the\n    TAP stream, you can encounter unexpected behavior or errors.\n\n- Printing **from within the `setup` or `teardown` functions**: The same hold\n  true as for printing with test functions.\n\n- Printing **outside test or `setup`/`teardown` functions**:\n  - Regardless of where text is redirected to (stdout, stderr or file descriptor\n    3) text is immediately visible in the terminal.\n\n  - Text printed in such a way, will disable pretty formatting. Also, it will\n    make output non-compliant with the TAP spec. The reason for this is that\n    each test file is evaluated n+1 times (as mentioned\n    [earlier](#writing-tests)). The first run will cause such output to be\n    produced before the [_plan line_][tap-plan] is printed, contrary to the spec\n    that requires the _plan line_ to be either the first or the last line of the\n    output.\n\n  - Due to internal pipes/redirects, output to stderr is always printed first.\n\n[tap-plan]: https://testanything.org/tap-specification.html#the-plan\n\n## Special variables\n\nThere are several global variables you can use to introspect on Bats tests:\n\n- `$BATS_RUN_COMMAND` is the run command used in your test case.\n- `$BATS_TEST_FILENAME` is the fully expanded path to the Bats test file.\n- `$BATS_TEST_DIRNAME` is the directory in which the Bats test file is located.\n- `$BATS_TEST_NAMES` is an array of function names for each test case.\n- `$BATS_TEST_NAME` is the name of the function containing the current test case.\n- `$BATS_TEST_DESCRIPTION` is the description of the current test case.\n- `$BATS_TEST_NUMBER` is the (1-based) index of the current test case in the test file.\n- `$BATS_SUITE_TEST_NUMBER` is the (1-based) index of the current test case in the test suite (over all files).\n- `$BATS_TMPDIR` is the base temporary directory used by bats to create its\n   temporary files / directories.\n   (default: `$TMPDIR`. If `$TMPDIR` is not set, `/tmp` is used.)\n- `$BATS_RUN_TMPDIR` is the location to the temporary directory used by bats to\n   store all its internal temporary files during the tests.\n   (default: `$BATS_TMPDIR/bats-run-$BATS_ROOT_PID-XXXXXX`)\n- `$BATS_FILE_EXTENSION` (default: `bats`) specifies the extension of test files that should be found when running a suite (via `bats [-r] suite_folder/`)\n- `$BATS_SUITE_TMPDIR` is a temporary directory common to all tests of a suite.\n  Could be used to create files required by multiple tests.\n- `$BATS_FILE_TMPDIR` is a temporary directory common to all tests of a test file.\n  Could be used to create files required by multiple tests in the same test file.\n- `$BATS_TEST_TMPDIR` is a temporary directory unique for each test.\n  Could be used to create files required only for specific tests.\n\n## Libraries and Add-ons\n\nBats supports loading external assertion libraries and helpers. Those under `bats-core` are officially supported libraries (integration tests welcome!):\n\n- <https://github.com/bats-core/bats-assert> - common assertions for Bats\n- <https://github.com/bats-core/bats-support> - supporting library for Bats test helpers\n- <https://github.com/bats-core/bats-file> - common filesystem assertions for Bats\n- <https://github.com/bats-core/bats-detik> - e2e tests of applications in K8s environments\n\nand some external libraries, supported on a \"best-effort\" basis:\n\n- <https://github.com/ztombol/bats-docs> (still relevant? Requires review)\n- <https://github.com/grayhemp/bats-mock> (as per #147)\n- <https://github.com/jasonkarns/bats-mock> (how is this different from grayhemp/bats-mock?)\n"
  },
  {
    "path": "vendor/bats-core/docs/versions.md",
    "content": "Here are the docs of following versions:\n\n* [v1.2.0](../../v1.2.0/README.md)\n* [v1.1.0](../../v1.1.0/README.md)\n* [v1.0.2](../../v1.0.2/README.md)\n* [v0.4.0](../../v0.4.0/README.md)\n* [v0.3.1](../../v0.3.1/README.md)\n* [v0.2.0](../../v0.2.0/README.md)\n* [v0.1.0](../../v0.1.0/README.md)\n"
  },
  {
    "path": "vendor/bats-core/install.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\nBATS_ROOT=\"${0%/*}\"\nPREFIX=\"$1\"\nLIBDIR=\"${2:-lib}\"\n\nif [[ -z \"$PREFIX\" ]]; then\n  printf '%s\\n' \\\n    \"usage: $0 <prefix>\" \\\n    \"  e.g. $0 /usr/local\" >&2\n  exit 1\nfi\n\ninstall -d -m 755 \"$PREFIX\"/{bin,libexec/bats-core,\"${LIBDIR}\"/bats-core,share/man/man{1,7}}\ninstall -m 755 \"$BATS_ROOT/bin\"/* \"$PREFIX/bin\"\ninstall -m 755 \"$BATS_ROOT/libexec/bats-core\"/* \"$PREFIX/libexec/bats-core\"\ninstall -m 755 \"$BATS_ROOT/lib/bats-core\"/* \"$PREFIX/${LIBDIR}/bats-core\"\ninstall -m 644 \"$BATS_ROOT/man/bats.1\" \"$PREFIX/share/man/man1\"\ninstall -m 644 \"$BATS_ROOT/man/bats.7\" \"$PREFIX/share/man/man7\"\n\necho \"Installed Bats to $PREFIX/bin/bats\"\n"
  },
  {
    "path": "vendor/bats-core/lib/bats-core/common.bash",
    "content": "#!/usr/bin/env bash\n\nbats_prefix_lines_for_tap_output() {\n    while IFS= read -r line; do\n      printf '# %s\\n' \"$line\" || break # avoid feedback loop when errors are redirected into BATS_OUT (see #353)\n    done\n    if [[ -n \"$line\" ]]; then\n      printf '# %s\\n' \"$line\"\n    fi\n}\n\nfunction bats_replace_filename() {\n  local line\n  while read -r line; do\n    printf \"%s\\n\" \"${line//$BATS_TEST_SOURCE/$BATS_TEST_FILENAME}\"\n  done\n  if [[ -n \"$line\" ]]; then\n    printf \"%s\\n\" \"${line//$BATS_TEST_SOURCE/$BATS_TEST_FILENAME}\"\n  fi\n}\n\nbats_quote_code() { # <var> <code>\n\tprintf -v \"$1\" -- \"%s%s%s\" \"$BATS_BEGIN_CODE_QUOTE\" \"$2\" \"$BATS_END_CODE_QUOTE\"\n}\n"
  },
  {
    "path": "vendor/bats-core/lib/bats-core/formatter.bash",
    "content": "#!/usr/bin/env bash\n\n# reads (extended) bats tap streams from stdin and calls callback functions for each line\n# bats_tap_stream_plan <number of tests>                                      -> when the test plan is encountered\n# bats_tap_stream_begin <test index> <test name>                              -> when a new test is begun WARNING: extended only\n# bats_tap_stream_ok [--duration <milliseconds] <test index> <test name>      -> when a test was successful\n# bats_tap_stream_not_ok [--duration <milliseconds>] <test index> <test name> -> when a test has failed\n# bats_tap_stream_skipped <test index> <test name> <skip reason>              -> when a test was skipped\n# bats_tap_stream_comment <comment text without leading '# '> <scope>         -> when a comment line was encountered, \n#                                                                                scope tells the last encountered of plan, begin, ok, not_ok, skipped, suite\n# bats_tap_stream_suite <file name>                                           -> when a new file is begun WARNING: extended only\n# bats_tap_stream_unknown <full line> <scope>                                 -> when a line is encountered that does not match the previous entries,\n#                                                                                scope @see bats_tap_stream_comment\n# forwards all input as is, when there is no TAP test plan header\nfunction bats_parse_internal_extended_tap() {\n    local header_pattern='[0-9]+\\.\\.[0-9]+'\n    IFS= read -r header\n\n    if [[ \"$header\" =~ $header_pattern ]]; then\n        bats_tap_stream_plan \"${header:3}\"\n    else\n        # If the first line isn't a TAP plan, print it and pass the rest through\n        printf '%s\\n' \"$header\"\n        exec cat\n    fi\n\n    ok_line_regexpr=\"ok ([0-9]+) (.*)\"\n    skip_line_regexpr=\"ok ([0-9]+) (.*) # skip( (.*))?$\"\n    not_ok_line_regexpr=\"not ok ([0-9]+) (.*)\"\n\n    timing_expr=\"in ([0-9]+)ms$\"\n    local test_name begin_index ok_index not_ok_index index scope\n    begin_index=0\n    index=0\n    scope=plan\n    while IFS= read -r line; do\n        case \"$line\" in\n        'begin '*) # this might only be called in extended tap output\n            ((++begin_index))\n            scope=begin\n            test_name=\"${line#* $begin_index }\"\n            bats_tap_stream_begin \"$begin_index\" \"$test_name\"\n            ;;\n        'ok '*)\n            ((++index))\n            if [[ \"$line\" =~ $ok_line_regexpr ]]; then\n                ok_index=\"${BASH_REMATCH[1]}\"\n                test_name=\"${BASH_REMATCH[2]}\"\n                if [[ \"$line\" =~ $skip_line_regexpr ]]; then\n                    scope=skipped\n                    test_name=\"${BASH_REMATCH[2]}\" # cut off name before \"# skip\"\n                    local skip_reason=\"${BASH_REMATCH[4]}\"\n                    bats_tap_stream_skipped \"$ok_index\" \"$test_name\" \"$skip_reason\"\n                else\n                    scope=ok\n                    if [[ \"$line\" =~ $timing_expr ]]; then\n                        bats_tap_stream_ok --duration \"${BASH_REMATCH[1]}\" \"$ok_index\" \"$test_name\"\n                    else\n                        bats_tap_stream_ok \"$ok_index\" \"$test_name\"\n                    fi\n                fi\n            else\n                printf \"ERROR: could not match ok line: %s\" \"$line\" >&2\n                exit 1\n            fi\n            ;;\n        'not ok '*)\n            ((++index))\n            scope=not_ok\n            if [[ \"$line\" =~ $not_ok_line_regexpr ]]; then\n                not_ok_index=\"${BASH_REMATCH[1]}\"\n                test_name=\"${BASH_REMATCH[2]}\"\n                if [[ \"$line\" =~ $timing_expr ]]; then\n                    bats_tap_stream_not_ok --duration \"${BASH_REMATCH[1]}\" \"$not_ok_index\" \"$test_name\"\n                else\n                    bats_tap_stream_not_ok \"$not_ok_index\" \"$test_name\"\n                fi\n            else\n                printf \"ERROR: could not match not ok line: %s\" \"$line\" >&2\n                exit 1\n            fi\n            ;;\n        '# '*)\n            bats_tap_stream_comment \"${line:2}\" \"$scope\"\n            ;;\n        'suite '*) \n            scope=suite\n            # pass on the\n            bats_tap_stream_suite \"${line:6}\"\n        ;;\n        *)\n            bats_tap_stream_unknown \"$line\" \"$scope\"\n        ;;\n        esac\n    done\n}\n\n# given a prefix and a path, remove the prefix if the path starts with it\n# e.g. \n# remove_prefix /usr/bin /usr/bin/bash -> bash\n# remove_prefix /usr /usr/lib/bash -> lib/bash\n# remove_prefix /usr/bin /usr/local/bin/bash -> /usr/local/bin/bash\nremove_prefix() {\n  base_path=\"$1\"\n  path=\"$2\"\n  if [[ \"$path\" == \"$base_path\"* ]]; then\n    # cut off the common prefix\n    printf \"%s\" \"${path:${#base_path}}\"\n  else\n    printf \"%s\" \"$path\"\n  fi\n}\n\nnormalize_base_path() { # <target variable> <base path>\n    # the relative path root to use for reporting filenames\n    # this is mainly intended for suite mode, where this will be the suite root folder\n    local base_path=\"$2\"\n    # use the containing directory when --base-path is a file\n    if [[ ! -d \"$base_path\" ]]; then\n        base_path=\"$(dirname \"$base_path\")\"\n    fi\n    # get the absolute path\n    base_path=\"$(cd \"$base_path\" && pwd)\"\n    # ensure the path ends with / to strip that later on\n    if [[ \"${base_path}\" != *\"/\" ]]; then\n        base_path=\"$base_path/\"\n    fi\n    printf -v \"$1\" \"%s\" \"$base_path\"\n}\n"
  },
  {
    "path": "vendor/bats-core/lib/bats-core/preprocessing.bash",
    "content": "#!/usr/bin/env bash\n\nBATS_TMPNAME=\"$BATS_RUN_TMPDIR/bats.$$\"\nBATS_PARENT_TMPNAME=\"$BATS_RUN_TMPDIR/bats.$PPID\"\n# shellcheck disable=SC2034\nBATS_OUT=\"${BATS_TMPNAME}.out\" # used in bats-exec-file\n\nbats_preprocess_source() {\n\t# export to make it visible to bats_evaluate_preprocessed_source\n\t# since the latter runs in bats-exec-test's bash while this runs in bats-exec-file's\n\texport BATS_TEST_SOURCE=\"${BATS_TMPNAME}.src\"\n\tbats-preprocess \"$BATS_TEST_FILENAME\" >\"$BATS_TEST_SOURCE\"\n}\n\nbats_evaluate_preprocessed_source() {\n\tif [[ -z \"${BATS_TEST_SOURCE:-}\" ]]; then\n\t\tBATS_TEST_SOURCE=\"${BATS_PARENT_TMPNAME}.src\"\n\tfi\n\t# Dynamically loaded user files provided outside of Bats.\n\t# shellcheck disable=SC1090\n\tsource \"$BATS_TEST_SOURCE\"\n}\n"
  },
  {
    "path": "vendor/bats-core/lib/bats-core/semaphore.bash",
    "content": "#!/usr/bin/env bash\n\n# setup the semaphore environment for the loading file\nbats_semaphore_setup() {\n    export -f bats_semaphore_get_free_slot_count\n    export -f bats_semaphore_acquire_while_locked\n    export BATS_SEMAPHORE_DIR=\"$BATS_RUN_TMPDIR/semaphores\"\n\n    if command -v flock >/dev/null; then\n    bats_run_under_lock() {\n        flock \"$BATS_SEMAPHORE_DIR\" \"$@\"\n    }\n    elif command -v shlock >/dev/null; then\n        bats_run_under_lock() {\n            local lockfile=\"$BATS_SEMAPHORE_DIR/shlock.lock\"\n            while ! shlock -p $$ -f \"$lockfile\"; do\n                sleep 1\n            done\n            # we got the lock now, execute the command\n            \"$@\"\n            local status=$?\n            # free the lock\n            rm -f \"$lockfile\"\n            return $status\n        }\n    else\n        printf \"ERROR: flock/shlock is required for parallelization within files!\\n\" >&2\n        exit 1\n    fi\n}\n\n# $1 - output directory for stdout/stderr\n# $@ - command to run\n# run the given command in a semaphore\n# block when there is no free slot for the semaphore\n# when there is a free slot, run the command in background\n# gather the output of the command in files in the given directory\nbats_semaphore_run() {\n    local output_dir=$1\n    shift\n    local semaphore_slot\n    semaphore_slot=$(bats_semaphore_acquire_slot)\n    bats_semaphore_release_wrapper \"$output_dir\" \"$semaphore_slot\" \"$@\" &\n    printf \"%d\\n\" \"$!\"\n}\n\n# $1 - output directory for stdout/stderr\n# $@ - command to run\n# this wraps the actual function call to install some traps on exiting\nbats_semaphore_release_wrapper() {\n    local output_dir=\"$1\"\n    local semaphore_name=\"$2\"\n    shift 2 # all other parameters will be use for the command to execute\n\n    # shellcheck disable=SC2064 # we want to expand the semaphore_name right now!\n    trap \"status=$?; bats_semaphore_release_slot '$semaphore_name'; exit $status\" EXIT\n\n    mkdir -p \"$output_dir\"\n    \"$@\" 2>\"$output_dir/stderr\" >\"$output_dir/stdout\"\n    local status=$?\n\n    # bash bug: the exit trap is not called for the background process\n    bats_semaphore_release_slot \"$semaphore_name\"\n    trap - EXIT # avoid calling release twice\n    return $status\n}\n\nbats_semaphore_acquire_while_locked() {\n    if [[ $(bats_semaphore_get_free_slot_count) -gt 0 ]]; then\n        local slot=0\n        while [[ -e \"$BATS_SEMAPHORE_DIR/slot-$slot\" ]]; do\n            (( ++slot ))\n        done\n        if [[ $slot -lt $BATS_SEMAPHORE_NUMBER_OF_SLOTS ]]; then\n            touch \"$BATS_SEMAPHORE_DIR/slot-$slot\" && printf \"%d\\n\" \"$slot\" && return 0\n        fi\n    fi\n    return 1\n}\n\n# block until a semaphore slot becomes free\n# prints the number of the slot that it received\nbats_semaphore_acquire_slot() {\n    mkdir -p \"$BATS_SEMAPHORE_DIR\"\n    # wait for a slot to become free\n    # TODO: avoid busy waiting by using signals -> this opens op prioritizing possibilities as well\n    while true; do\n        # don't lock for reading, we are fine with spuriously getting no free slot\n        if [[ $(bats_semaphore_get_free_slot_count) -gt 0 ]]; then\n            bats_run_under_lock bash -c bats_semaphore_acquire_while_locked && break\n        fi\n        sleep 1\n    done\n}\n\nbats_semaphore_release_slot() {\n    # we don't need to lock this, since only our process owns this file\n    # and freeing a semaphore cannot lead to conflicts with others\n    rm \"$BATS_SEMAPHORE_DIR/slot-$1\" # this will fail if we had not aqcuired a semaphore!\n}\n\nbats_semaphore_get_free_slot_count() {\n    # find might error out without returning something useful when a file is deleted,\n    # while the directory is traversed ->  only continue when there was no error\n    until used_slots=$(find \"$BATS_SEMAPHORE_DIR\" -name 'slot-*' 2>/dev/null | wc -l); do :; done\n    echo $(( BATS_SEMAPHORE_NUMBER_OF_SLOTS - used_slots ))\n}\n"
  },
  {
    "path": "vendor/bats-core/lib/bats-core/test_functions.bash",
    "content": "#!/usr/bin/env bash\n\nBATS_TEST_DIRNAME=\"${BATS_TEST_FILENAME%/*}\"\nBATS_TEST_NAMES=()\n\n# find_in_bats_lib_path echoes the first recognized load path to\n# a library in BATS_LIB_PATH or relative to BATS_TEST_DIRNAME.\n#\n# Libraries relative to BATS_TEST_DIRNAME take precedence over\n# BATS_LIB_PATH.\n#\n# Library load paths are recognized using find_library_load_path.\n#\n# If no library is found find_in_bats_lib_path returns 1.\nfind_in_bats_lib_path() { # <return-var> <library-name>\n  local return_var=\"${1:?}\"\n  local library_name=\"${2:?}\"\n\n  local -a bats_lib_paths\n  IFS=: read -ra bats_lib_paths <<< \"$BATS_LIB_PATH\"\n\n  for path in \"${bats_lib_paths[@]}\"; do\n    if [[ -f \"$path/$library_name\" ]]; then\n      printf -v \"$return_var\" \"%s\" \"$path/$library_name\" \n      # A library load path was found, return\n      return\n    elif [[ -f \"$path/$library_name/load.bash\" ]]; then\n      printf -v \"$return_var\" \"%s\" \"$path/$library_name/load.bash\" \n      # A library load path was found, return\n      return\n    fi\n  done\n\n  return 1\n}\n\n# bats_internal_load expects an absolute path that is a library load path.\n#\n# If the library load path points to a file (a library loader) it is\n# sourced.\n#\n# If it points to a directory all files ending in .bash inside of the\n# directory are sourced.\n#\n# If the sourcing of the library loader or of a file in a library\n# directory fails bats_internal_load prints an error message and returns 1.\n#\n# If the passed library load path is not absolute or is not a valid file\n# or directory bats_internal_load prints an error message and returns 1.\nbats_internal_load() {\n  local library_load_path=\"${1:?}\"\n\n  if [[ \"${library_load_path:0:1}\" != / ]]; then\n    printf \"Passed library load path is not an absolute path: %s\\n\" \"$library_load_path\" >&2\n    return 1\n  fi\n\n  # library_load_path is a library loader\n  if [[ -f \"$library_load_path\" ]]; then\n      # shellcheck disable=SC1090\n      if ! source \"$library_load_path\"; then\n          printf \"Error while sourcing library loader at '%s'\\n\" \"$library_load_path\" >&2\n          return 1\n      fi\n      return\n  fi\n\n  printf \"Passed library load path is neither a library loader nor library directory: %s\\n\" \"$library_load_path\" >&2\n  return 1\n}\n\n# bats_load_safe accepts an argument called 'slug' and attempts to find and\n# source a library based on the slug.\n#\n# A slug can be an absolute path, a library name or a relative path.\n#\n# If the slug is an absolute path bats_load_safe attempts to find the library\n# load path using find_library_load_path.\n# What is considered a library load path is documented in the\n# documentation for find_library_load_path.\n#\n# If the slug is not an absolute path it is considered a library name or\n# relative path. bats_load_safe attempts to find the library load path using\n# find_in_bats_lib_path.\n#\n# If bats_load_safe can find a library load path it is passed to bats_internal_load.\n# If bats_internal_load fails bats_load_safe returns 1.\n#\n# If no library load path can be found bats_load_safe prints an error message\n# and returns 1.\nbats_load_safe() {\n  local slug=\"${1:?}\"\n  if [[ ${slug:0:1} != / ]]; then # relative paths are relative to BATS_TEST_DIRNAME\n    slug=\"$BATS_TEST_DIRNAME/$slug\"\n  fi\n\n  if [[ -f \"$slug.bash\" ]]; then\n    bats_internal_load \"$slug.bash\"\n    return \n  elif [[ -f \"$slug\" ]]; then\n    bats_internal_load \"$slug\"\n    return\n  fi\n\n  # loading from PATH (retained for backwards compatibility)\n  if [[ ! -f \"$1\" ]] && type -P \"$1\" >/dev/null; then\n    # shellcheck disable=SC1090\n    source \"$1\"\n    return\n  fi\n\n  # No library load path can be found\n  printf \"bats_load_safe: Could not find '%s'[.bash]\\n\" \"$slug\" >&2\n  return 1\n}\n\nbats_require_lib_path() {\n  if [[ -z \"${BATS_LIB_PATH:-}\" ]]; then\n    printf \"%s: requires BATS_LIB_PATH to be set!\\n\" \"${FUNCNAME[1]}\" >&2\n    exit 1\n  fi\n}\n\nbats_load_library_safe() { # <slug>\n  local slug=\"${1:?}\" library_path\n\n  bats_require_lib_path\n\n  # Check for library load paths in BATS_TEST_DIRNAME and BATS_LIB_PATH\n  if [[ ${slug:0:1} != / ]]; then\n    find_in_bats_lib_path library_path \"$slug\"\n    if [[ -z \"$library_path\" ]]; then\n      printf \"Could not find library '%s' relative to test file or in BATS_LIB_PATH\\n\" \"$slug\" >&2\n      return 1\n    fi\n  else\n    # absolute paths are taken as is\n    library_path=\"$slug\"\n    if [[ ! -f \"$library_path\" ]]; then\n      printf \"Could not find library on absolute path '%s'\\n\" \"$library_path\" >&2\n      return 1\n    fi\n  fi\n\n  bats_internal_load \"$library_path\"\n  return $?\n}\n\n# immediately exit on error, use bats_load_library_safe to catch and handle errors\nbats_load_library() { # <slug>\n  bats_require_lib_path\n  if ! bats_load_library_safe \"$@\"; then\n    exit 1\n  fi\n}\n\n# load acts like bats_load_safe but exits the shell instead of returning 1.\nload() {\n    if ! bats_load_safe \"$@\"; then\n        exit 1\n    fi\n}\n\nbats_redirect_stderr_into_file() {\n  \"$@\" 2>>\"$bats_run_separate_stderr_file\" # use >> to see collisions' content\n}\n\nbats_merge_stdout_and_stderr() {\n  \"$@\" 2>&1\n}\n\n# write separate lines from <input-var> into <output-array>\nbats_separate_lines() { # <output-array> <input-var>\n  local output_array_name=\"$1\"\n  local input_var_name=\"$2\"\n  if [[ $keep_empty_lines ]]; then\n    local bats_separate_lines_lines=()\n    while IFS= read -r line; do\n      bats_separate_lines_lines+=(\"$line\")\n    done <<<\"${!input_var_name}\"\n    eval \"${output_array_name}=(\\\"\\${bats_separate_lines_lines[@]}\\\")\"\n  else\n    # shellcheck disable=SC2034,SC2206\n    IFS=$'\\n' read -d '' -r -a \"$output_array_name\" <<<\"${!input_var_name}\" || true # don't fail due to EOF\n  fi\n}\n\nrun() { # [!|-N] [--keep-empty-lines] [--separate-stderr] [--] <command to run...>\n  # This has to be restored on exit from this function to avoid leaking our trap INT into surrounding code.\n  # Non zero exits won't restore under the assumption that they will fail the test before it can be aborted,\n  # which allows us to avoid duplicating the restore code on every exit path\n  trap bats_interrupt_trap_in_run INT\n  local expected_rc=\n  local keep_empty_lines=\n  local output_case=merged\n  # parse options starting with -\n  while [[ $# -gt 0 ]] && [[ $1 == -* || $1 == '!' ]]; do\n    case \"$1\" in\n      '!')\n        expected_rc=-1\n      ;;\n      -[0-9]*)\n        expected_rc=${1#-}\n        if [[ $expected_rc =~ [^0-9] ]]; then\n          printf \"Usage error: run: '=NNN' requires numeric NNN (got: %s)\\n\" \"$expected_rc\" >&2\n          return 1\n        elif [[ $expected_rc -gt 255 ]]; then\n          printf \"Usage error: run: '=NNN': NNN must be <= 255 (got: %d)\\n\" \"$expected_rc\" >&2\n          return 1\n        fi\n      ;;\n      --keep-empty-lines)\n        keep_empty_lines=1\n      ;;\n      --separate-stderr)\n        output_case=\"separate\"\n      ;;\n      --)\n        shift # eat the -- before breaking away\n        break\n      ;;\n      *)\n        printf \"Usage error: unknown flag '%s'\" \"$1\" >&2\n        return 1\n      ;;\n    esac\n    shift\n  done\n\n  local pre_command=\n\n  case \"$output_case\" in\n    merged) # redirects stderr into stdout and fills only $output/$lines\n      pre_command=bats_merge_stdout_and_stderr\n    ;;\n    separate) # splits stderr into own file and fills $stderr/$stderr_lines too\n      local bats_run_separate_stderr_file\n      bats_run_separate_stderr_file=\"$(mktemp \"${BATS_TEST_TMPDIR}/separate-stderr-XXXXXX\")\"\n      pre_command=bats_redirect_stderr_into_file\n    ;;\n  esac\n\n  local origFlags=\"$-\"\n  set +eET\n  local origIFS=\"$IFS\"\n  if [[ $keep_empty_lines ]]; then\n    # 'output', 'status', 'lines' are global variables available to tests.\n    # preserve trailing newlines by appending . and removing it later\n    # shellcheck disable=SC2034\n    output=\"$($pre_command \"$@\"; status=$?; printf .; exit $status)\" && status=0 || status=$?\n    output=\"${output%.}\"\n  else\n    # 'output', 'status', 'lines' are global variables available to tests.\n    # shellcheck disable=SC2034\n    output=\"$($pre_command \"$@\")\" && status=0 || status=$?\n  fi\n\n  bats_separate_lines lines output\n\n  if [[ \"$output_case\" == separate ]]; then\n      # shellcheck disable=SC2034\n      read -d '' -r stderr < \"$bats_run_separate_stderr_file\"\n      bats_separate_lines stderr_lines stderr\n  fi\n\n  # shellcheck disable=SC2034\n  BATS_RUN_COMMAND=\"${*}\"\n  IFS=\"$origIFS\"\n  set \"-$origFlags\"\n\n  if [[ ${BATS_VERBOSE_RUN:-} ]]; then\n    printf \"%s\\n\" \"$output\" \n  fi\n\n  if [[ -n \"$expected_rc\" ]]; then\n    if [[ \"$expected_rc\" = \"-1\" ]]; then\n      if [[ \"$status\" -eq 0 ]]; then\n        BATS_ERROR_SUFFIX=\", expected nonzero exit code!\"\n        return 1\n      fi\n    elif [ \"$status\" -ne \"$expected_rc\" ]; then\n      # shellcheck disable=SC2034\n      BATS_ERROR_SUFFIX=\", expected exit code $expected_rc, got $status\"\n      return 1\n    fi\n  fi\n  # don't leak our trap into surrounding code\n  trap bats_interrupt_trap INT\n}\n\nsetup() {\n  return 0\n}\n\nteardown() {\n  return 0\n}\n\nskip() {\n  # if this is a skip in teardown ...\n  if [[ -n \"${BATS_TEARDOWN_STARTED-}\" ]]; then\n    # ... we want to skip the rest of teardown.\n    # communicate to bats_exit_trap that the teardown was completed without error\n    # shellcheck disable=SC2034\n    BATS_TEARDOWN_COMPLETED=1\n    # if we are already in the exit trap (e.g. due to previous skip) ...\n    if [[ \"$BATS_TEARDOWN_STARTED\" == as-exit-trap ]]; then\n      # ... we need to do the rest of the tear_down_trap that would otherwise be skipped after the next call to exit\n      bats_exit_trap\n      # and then do the exit (at the end of this function)\n    fi\n    # if we aren't in exit trap, the normal exit handling should suffice\n  else\n    # ... this is either skip in test or skip in setup.\n    # Following variables are used in bats-exec-test which sources this file\n    # shellcheck disable=SC2034\n    BATS_TEST_SKIPPED=\"${1:-1}\"\n    # shellcheck disable=SC2034\n    BATS_TEST_COMPLETED=1\n  fi\n  exit 0\n}\n\nbats_test_begin() {\n  BATS_TEST_DESCRIPTION=\"$1\"\n  if [[ -n \"$BATS_EXTENDED_SYNTAX\" ]]; then\n    printf 'begin %d %s\\n' \"$BATS_SUITE_TEST_NUMBER\" \"$BATS_TEST_DESCRIPTION\" >&3\n  fi\n  setup\n}\n\nbats_test_function() {\n  local test_name=\"$1\"\n  BATS_TEST_NAMES+=(\"$test_name\")\n}\n"
  },
  {
    "path": "vendor/bats-core/lib/bats-core/tracing.bash",
    "content": "#!/usr/bin/env bash\n\nbats_capture_stack_trace() {\n\tlocal test_file\n\tlocal funcname\n\tlocal i\n\n\tBATS_DEBUG_LAST_STACK_TRACE=()\n\n\tfor ((i = 2; i != ${#FUNCNAME[@]}; ++i)); do\n\t\t# Use BATS_TEST_SOURCE if necessary to work around Bash < 4.4 bug whereby\n\t\t# calling an exported function erases the test file's BASH_SOURCE entry.\n\t\ttest_file=\"${BASH_SOURCE[$i]:-$BATS_TEST_SOURCE}\"\n\t\tfuncname=\"${FUNCNAME[$i]}\"\n\t\tBATS_DEBUG_LAST_STACK_TRACE+=(\"${BASH_LINENO[$((i-1))]} $funcname $test_file\")\n\t\tcase \"$funcname\" in\n\t\t\"$BATS_TEST_NAME\" | setup | teardown | setup_file | teardown_file)\n\t\t\tbreak\n\t\t\t;;\n\t\tesac\n\t\tif [[ \"${BASH_SOURCE[$i + 1]:-}\" == *\"bats-exec-file\" ]] && [[ \"$funcname\" == 'source' ]]; then\n\t\t\tbreak\n\t\tfi\n\tdone\n}\n\nbats_get_failure_stack_trace() {\n\tlocal stack_trace_var\n\t# See bats_debug_trap for details.\n\tif [[ -n \"${BATS_DEBUG_LAST_STACK_TRACE_IS_VALID}\" ]]; then\n\t\tstack_trace_var=BATS_DEBUG_LAST_STACK_TRACE\n\telse\n\t\tstack_trace_var=BATS_DEBUG_LASTLAST_STACK_TRACE\n\tfi\n\t# shellcheck disable=SC2016\n\teval \"$(printf \\\n\t\t'%s=(${%s[@]+\"${%s[@]}\"})' \\\n\t\t\"${1}\" \\\n\t\t\"${stack_trace_var}\" \\\n\t\t\"${stack_trace_var}\")\"\n}\n\nbats_print_stack_trace() {\n\tlocal frame\n\tlocal index=1\n\tlocal count=\"${#@}\"\n\tlocal filename\n\tlocal lineno\n\n\tfor frame in \"$@\"; do\n\t\tbats_frame_filename \"$frame\" 'filename'\n\t\tbats_trim_filename \"$filename\" 'filename'\n\t\tbats_frame_lineno \"$frame\" 'lineno'\n\n\t\tif [[ $index -eq 1 ]]; then\n\t\t\tprintf '# ('\n\t\telse\n\t\t\tprintf '#  '\n\t\tfi\n\n\t\tlocal fn\n\t\tbats_frame_function \"$frame\" 'fn'\n\t\tif [[ \"$fn\" != \"$BATS_TEST_NAME\" ]] && \n\t\t\t# don't print \"from function `source'\"\",\n\t\t\t# when failing in free code during `source $test_file` from bats-exec-file\n\t\t\t! [[ \"$fn\" == 'source' &&  $index -eq $count ]]; then \n\t\t\tlocal quoted_fn\n\t\t\tbats_quote_code quoted_fn \"$fn\"\n\t\t\tprintf \"from function %s \" \"$quoted_fn\"\n\t\tfi\n\n\t\tif [[ $index -eq $count ]]; then\n\t\t\tprintf 'in test file %s, line %d)\\n' \"$filename\" \"$lineno\"\n\t\telse\n\t\t\tprintf 'in file %s, line %d,\\n' \"$filename\" \"$lineno\"\n\t\tfi\n\n\t\t((++index))\n\tdone\n}\n\nbats_print_failed_command() {\n\tlocal stack_trace=(\"${@}\")\n\tif [[ ${#stack_trace[@]} -eq 0 ]]; then\n\t\treturn \n\tfi\n\tlocal frame=\"${stack_trace[${#stack_trace[@]} - 1]}\"\n\tlocal filename\n\tlocal lineno\n\tlocal failed_line\n\tlocal failed_command\n\n\tbats_frame_filename \"$frame\" 'filename'\n\tbats_frame_lineno \"$frame\" 'lineno'\n\tbats_extract_line \"$filename\" \"$lineno\" 'failed_line'\n\tbats_strip_string \"$failed_line\" 'failed_command'\n\tlocal quoted_failed_command\n\tbats_quote_code quoted_failed_command \"$failed_command\"\n\tprintf '#   %s ' \"${quoted_failed_command}\"\n\n\tif [[ \"$BATS_ERROR_STATUS\" -eq 1 ]]; then\n\t\tprintf 'failed%s\\n' \"$BATS_ERROR_SUFFIX\"\n\telse\n\t\tprintf 'failed with status %d%s\\n' \"$BATS_ERROR_STATUS\" \"$BATS_ERROR_SUFFIX\"\n\tfi\n}\n\nbats_frame_lineno() {\n\tprintf -v \"$2\" '%s' \"${1%% *}\"\n}\n\nbats_frame_function() {\n\tlocal __bff_function=\"${1#* }\"\n\tprintf -v \"$2\" '%s' \"${__bff_function%% *}\"\n}\n\nbats_frame_filename() {\n\tlocal __bff_filename=\"${1#* }\"\n\t__bff_filename=\"${__bff_filename#* }\"\n\n\tif [[ \"$__bff_filename\" == \"$BATS_TEST_SOURCE\" ]]; then\n\t\t__bff_filename=\"$BATS_TEST_FILENAME\"\n\tfi\n\tprintf -v \"$2\" '%s' \"$__bff_filename\"\n}\n\nbats_extract_line() {\n\tlocal __bats_extract_line_line\n\tlocal __bats_extract_line_index=0\n\n\twhile IFS= read -r __bats_extract_line_line; do\n\t\tif [[ \"$((++__bats_extract_line_index))\" -eq \"$2\" ]]; then\n\t\t\tprintf -v \"$3\" '%s' \"${__bats_extract_line_line%$'\\r'}\"\n\t\t\tbreak\n\t\tfi\n\tdone <\"$1\"\n}\n\nbats_strip_string() {\n\t[[ \"$1\" =~ ^[[:space:]]*(.*)[[:space:]]*$ ]]\n\tprintf -v \"$2\" '%s' \"${BASH_REMATCH[1]}\"\n}\n\nbats_trim_filename() {\n\tprintf -v \"$2\" '%s' \"${1#$BATS_CWD/}\"\n}\n\n# normalize a windows path from e.g. C:/directory to /c/directory\n# The path must point to an existing/accessable directory, not a file!\nbats_normalize_windows_dir_path() { # <output-var> <path>\n\tlocal output_var=\"$1\" path=\"$2\"\n\tif [[ \"$output_var\" != NORMALIZED_INPUT ]]; then\n\t\tlocal NORMALIZED_INPUT\n\tfi\n\tif [[ $path == ?:* ]]; then\n\t\tNORMALIZED_INPUT=\"$(cd \"$path\" || exit 1; pwd)\"\n\telse\n\t\tNORMALIZED_INPUT=\"$path\"\n\tfi\n\tprintf -v \"$output_var\" \"%s\" \"$NORMALIZED_INPUT\"\n}\n\nbats_emit_trace() {\n\tif [[ $BATS_TRACE_LEVEL -gt 0 ]]; then\n\t\tlocal line=${BASH_LINENO[1]}\n\t\t# shellcheck disable=SC2016\n\t\tif [[ $BASH_COMMAND != '\"$BATS_TEST_NAME\" >> \"$BATS_OUT\" 2>&1 4>&1' && $BASH_COMMAND != \"bats_test_begin \"* ]] && # don't emit these internal calls\n\t\t\t[[ $BASH_COMMAND != \"$BATS_LAST_BASH_COMMAND\" || $line != \"$BATS_LAST_BASH_LINENO\" ]] &&\n\t\t\t# avoid printing a function twice (at call site and at definiton site)\n\t\t\t[[ $BASH_COMMAND != \"$BATS_LAST_BASH_COMMAND\" || ${BASH_LINENO[2]} != \"$BATS_LAST_BASH_LINENO\" || ${BASH_SOURCE[3]} != \"$BATS_LAST_BASH_SOURCE\" ]]; then\n\t\t\tlocal file=\"${BASH_SOURCE[2]}\" # index 2: skip over bats_emit_trace and bats_debug_trap\n\t\t\tif [[ $file == \"${BATS_TEST_SOURCE}\" ]]; then\n\t\t\t\tfile=\"$BATS_TEST_FILENAME\"\n\t\t\tfi\n\t\t\tlocal padding='$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$'\n\t\t\tif (( BATS_LAST_STACK_DEPTH != ${#BASH_LINENO[@]} )); then\n\t\t\t\tprintf '%s [%s:%d]\\n' \"${padding::${#BASH_LINENO[@]}-4}\" \"${file##*/}\" \"$line\" >&4\n\t\t\tfi\n\t\t\tprintf '%s %s\\n'  \"${padding::${#BASH_LINENO[@]}-4}\" \"$BASH_COMMAND\"  >&4\n\t\t\tBATS_LAST_BASH_COMMAND=\"$BASH_COMMAND\"\n\t\t\tBATS_LAST_BASH_LINENO=\"$line\"\n\t\t\tBATS_LAST_BASH_SOURCE=\"${BASH_SOURCE[2]}\"\n\t\t\tBATS_LAST_STACK_DEPTH=\"${#BASH_LINENO[@]}\"\n\t\tfi\n\tfi\n}\n\n# bats_debug_trap tracks the last line of code executed within a test. This is\n# necessary because $BASH_LINENO is often incorrect inside of ERR and EXIT\n# trap handlers.\n#\n# Below are tables describing different command failure scenarios and the\n# reliability of $BASH_LINENO within different the executed DEBUG, ERR, and EXIT\n# trap handlers. Naturally, the behaviors change between versions of Bash.\n#\n# Table rows should be read left to right. For example, on bash version\n# 4.0.44(2)-release, if a test executes `false` (or any other failing external\n# command), bash will do the following in order:\n# 1. Call the DEBUG trap handler (bats_debug_trap) with $BASH_LINENO referring\n#    to the source line containing the `false` command, then\n# 2. Call the DEBUG trap handler again, but with an incorrect $BASH_LINENO, then\n# 3. Call the ERR trap handler, but with a (possibly-different) incorrect\n#    $BASH_LINENO, then\n# 4. Call the DEBUG trap handler again, but with $BASH_LINENO set to 1, then\n# 5. Call the EXIT trap handler, with $BASH_LINENO set to 1.\n#\n# bash version 4.4.20(1)-release\n#  command     | first DEBUG | second DEBUG | ERR     | third DEBUG | EXIT\n# -------------+-------------+--------------+---------+-------------+--------\n#  false       | OK          | OK           | OK      | BAD[1]      | BAD[1]\n#  [[ 1 = 2 ]] | OK          | BAD[2]       | BAD[2]  | BAD[1]      | BAD[1]\n#  (( 1 = 2 )) | OK          | BAD[2]       | BAD[2]  | BAD[1]      | BAD[1]\n#  ! true      | OK          | ---          | BAD[4]  | ---         | BAD[1]\n#  $var_dne    | OK          | ---          | ---     | BAD[1]      | BAD[1]\n#  source /dne | OK          | ---          | ---     | BAD[1]      | BAD[1]\n#\n# bash version 4.0.44(2)-release\n#  command     | first DEBUG | second DEBUG | ERR     | third DEBUG | EXIT\n# -------------+-------------+--------------+---------+-------------+--------\n#  false       | OK          | BAD[3]       | BAD[3]  | BAD[1]      | BAD[1]\n#  [[ 1 = 2 ]] | OK          | ---          | BAD[3]  | ---         | BAD[1]\n#  (( 1 = 2 )) | OK          | ---          | BAD[3]  | ---         | BAD[1]\n#  ! true      | OK          | ---          | BAD[3]  | ---         | BAD[1]\n#  $var_dne    | OK          | ---          | ---     | BAD[1]      | BAD[1]\n#  source /dne | OK          | ---          | ---     | BAD[1]      | BAD[1]\n#\n# [1] The reported line number is always 1.\n# [2] The reported source location is that of the beginning of the function\n#     calling the command.\n# [3] The reported line is that of the last command executed in the DEBUG trap\n#     handler.\n# [4] The reported source location is that of the call to the function calling\n#     the command.\nbats_debug_trap() {\n\t# on windows we sometimes get a mix of paths (when install via nmp install -g)\n\t# which have C:/... or /c/... comparing them is going to be problematic.\n\t# We need to normalize them to a common format!\n\tlocal NORMALIZED_INPUT\n\tbats_normalize_windows_dir_path NORMALIZED_INPUT \"${1%/*}\"\n\tlocal file_excluded='' path\n\tfor path in \"${BATS_DEBUG_EXCLUDE_PATHS[@]}\"; do\n\t\tif [[ \"$NORMALIZED_INPUT\" == \"$path\"* ]]; then\n\t\t\tfile_excluded=1\n\t\t\tbreak\n\t\tfi\n\tdone\n\t\n\t# don't update the trace within library functions or we get backtraces from inside traps\n\t# also don't record new stack traces while handling interruptions, to avoid overriding the interrupted command\n\tif [[ -z \"$file_excluded\" && \"${BATS_INTERRUPTED-NOTSET}\" == NOTSET ]]; then\n\t\tBATS_DEBUG_LASTLAST_STACK_TRACE=(\n\t\t\t${BATS_DEBUG_LAST_STACK_TRACE[@]+\"${BATS_DEBUG_LAST_STACK_TRACE[@]}\"}\n\t\t)\n\n\t\tBATS_DEBUG_LAST_LINENO=(${BASH_LINENO[@]+\"${BASH_LINENO[@]}\"})\n\t\tBATS_DEBUG_LAST_SOURCE=(${BASH_SOURCE[@]+\"${BASH_SOURCE[@]}\"})\n\t\tbats_capture_stack_trace\n\t\tbats_emit_trace\n\tfi\n}\n\n# For some versions of Bash, the `ERR` trap may not always fire for every\n# command failure, but the `EXIT` trap will. Also, some command failures may not\n# set `$?` properly. See #72 and #81 for details.\n#\n# For this reason, we call `bats_check_status_from_trap` at the very beginning\n# of `bats_teardown_trap` and check the value of `$BATS_TEST_COMPLETED` before\n# taking other actions. We also adjust the exit status value if needed.\n#\n# See `bats_exit_trap` for an additional EXIT error handling case when `$?`\n# isn't set properly during `teardown()` errors.\nbats_check_status_from_trap() {\n\tlocal status=\"$?\"\n\tif [[ -z \"$BATS_TEST_COMPLETED\" ]]; then\n\t\tBATS_ERROR_STATUS=\"${BATS_ERROR_STATUS:-$status}\"\n\t\tif [[ \"$BATS_ERROR_STATUS\" -eq 0 ]]; then\n\t\t\tBATS_ERROR_STATUS=1\n\t\tfi\n\t\ttrap - DEBUG\n\tfi\n}\n\nbats_add_debug_exclude_path() { # <path>\n\tif [[ -z \"$1\" ]]; then # don't exclude everything\n\t\tprintf \"bats_add_debug_exclude_path: Exclude path must not be empty!\\n\" >&2\n\t\treturn 1\n\tfi\n\tif [[ \"$OSTYPE\" == cygwin || \"$OSTYPE\" == msys ]]; then\n\t\tlocal normalized_dir\n\t\tbats_normalize_windows_dir_path normalized_dir \"$1\"\n\t\tBATS_DEBUG_EXCLUDE_PATHS+=(\"$normalized_dir\")\n\telse\n\t\tBATS_DEBUG_EXCLUDE_PATHS+=(\"$1\")\n\tfi\n}\n\nbats_setup_tracing() {\n\tBATS_DEBUG_EXCLUDE_PATHS=()\n\t# exclude some paths by default\n\tbats_add_debug_exclude_path \"$BATS_ROOT/lib/\"\n\tbats_add_debug_exclude_path \"$BATS_ROOT/libexec/\"\n\n\n\texec 4<&1 # used for tracing\n\tif [[ \"${BATS_TRACE_LEVEL:-0}\" -gt 0 ]]; then\n\t\t# avoid undefined variable errors\n\t\tBATS_LAST_BASH_COMMAND=\n\t\tBATS_LAST_BASH_LINENO=\n\t\tBATS_LAST_BASH_SOURCE=\n\t\tBATS_LAST_STACK_DEPTH=\n\t\t# try to exclude helper libraries if found, this is only relevant for tracing\n\t\twhile read -r path; do\n\t\t\tbats_add_debug_exclude_path \"$path\"\n\t\tdone < <(find \"$PWD\" -type d -name bats-assert -o -name bats-support)\n\tfi\n\n\tlocal exclude_paths path\n\t# exclude user defined libraries\n\tIFS=':' read -r exclude_paths <<< \"${BATS_DEBUG_EXCLUDE_PATHS:-}\"\n\tfor path in \"${exclude_paths[@]}\"; do\n\t\tif [[ -n \"$path\" ]]; then\n\t\t\tbats_add_debug_exclude_path \"$path\"\n\t\tfi\n\tdone\n\n\t# turn on traps after setting excludedes to avoid tracing the exclude setup\n\ttrap 'bats_debug_trap \"$BASH_SOURCE\"' DEBUG\n  \ttrap 'bats_error_trap' ERR\n}\n\nbats_error_trap() {\n  bats_check_status_from_trap\n\n  # If necessary, undo the most recent stack trace captured by bats_debug_trap.\n  # See bats_debug_trap for details.\n  if [[ \"${BASH_LINENO[*]}\" = \"${BATS_DEBUG_LAST_LINENO[*]:-}\"\n     && \"${BASH_SOURCE[*]}\" = \"${BATS_DEBUG_LAST_SOURCE[*]:-}\" \n\t && -z \"$BATS_DEBUG_LAST_STACK_TRACE_IS_VALID\" ]]; then\n    BATS_DEBUG_LAST_STACK_TRACE=(\n      ${BATS_DEBUG_LASTLAST_STACK_TRACE[@]+\"${BATS_DEBUG_LASTLAST_STACK_TRACE[@]}\"}\n    )\n  fi\n  BATS_DEBUG_LAST_STACK_TRACE_IS_VALID=1\n}\n\nbats_interrupt_trap() {\n  # mark the interruption, to handle during exit\n  BATS_INTERRUPTED=true\n  BATS_ERROR_STATUS=130\n  # debug trap fires before interrupt trap but gets wrong linenumber (line 1)\n  # -> use last last stack trace\n  exit $BATS_ERROR_STATUS\n}\n\n# this is used inside run()\nbats_interrupt_trap_in_run() {\n  # mark the interruption, to handle during exit\n  BATS_INTERRUPTED=true\n  BATS_ERROR_STATUS=130\n  BATS_DEBUG_LAST_STACK_TRACE_IS_VALID=true\n  exit $BATS_ERROR_STATUS\n}\n"
  },
  {
    "path": "vendor/bats-core/lib/bats-core/validator.bash",
    "content": "#!/usr/bin/env bash\n\nbats_test_count_validator() {\n  trap '' INT # continue forwarding\n  header_pattern='[0-9]+\\.\\.[0-9]+'\n  IFS= read -r header\n  # repeat the header\n  printf \"%s\\n\" \"$header\"\n\n  # if we detect a TAP plan\n  if [[ \"$header\" =~ $header_pattern ]]; then\n    # extract the number of tests ...\n    local expected_number_of_tests=\"${header:3}\"\n    # ... count the actual number of [not ] oks...\n    local actual_number_of_tests=0\n    while IFS= read -r line; do\n        # forward line\n        printf \"%s\\n\" \"$line\"\n        case \"$line\" in\n        'ok '*)\n        (( ++actual_number_of_tests ))\n        ;;\n        'not ok'*)\n        (( ++actual_number_of_tests ))\n        ;;\n        esac\n    done\n    # ... and error if they are not the same\n    if [[ \"${actual_number_of_tests}\" != \"${expected_number_of_tests}\" ]]; then\n        printf '# bats warning: Executed %s instead of expected %s tests\\n' \"$actual_number_of_tests\" \"$expected_number_of_tests\"\n        return 1\n    fi\n  else\n    # forward output unchanged\n    cat\n  fi\n}"
  },
  {
    "path": "vendor/bats-core/libexec/bats-core/bats",
    "content": "#!/usr/bin/env bash\nset -e\n\nexport BATS_VERSION='1.6.0'\nVALID_FORMATTERS=\"pretty, junit, tap, tap13\"\n\nversion() {\n  printf 'Bats %s\\n' \"$BATS_VERSION\"\n}\n\nabort() {\n  printf 'Error: %s\\n' \"$1\" >&2\n  usage >&2\n  exit 1\n}\n\nusage() {\n  local cmd=\"${0##*/}\"\n  local line\n\n  cat <<HELP_TEXT_HEADER\nUsage: ${cmd} [OPTIONS] <tests>\n       ${cmd} [-h | -v]\n\nHELP_TEXT_HEADER\n\n  cat <<'HELP_TEXT_BODY'\n  <tests> is the path to a Bats test file, or the path to a directory\n  containing Bats test files (ending with \".bats\")\n\n  -c, --count               Count test cases without running any tests\n  --code-quote-style <style>\n                            A two character string of code quote delimiters\n                            or 'custom' which requires setting $BATS_BEGIN_CODE_QUOTE and \n                            $BATS_END_CODE_QUOTE. Can also be set via $BATS_CODE_QUOTE_STYLE\n  -f, --filter <regex>      Only run tests that match the regular expression\n  -F, --formatter <type>    Switch between formatters: pretty (default),\n                              tap (default w/o term), tap13, junit\n  --gather-test-outputs-in <directory>\n                            Gather the output of failing *and* passing tests \n                            as files in directory\n  -h, --help                Display this help message\n  -j, --jobs <jobs>         Number of parallel jobs (requires GNU parallel)\n  --no-tempdir-cleanup      Preserve test output temporary directory\n  --no-parallelize-across-files\n                            Serialize test file execution instead of running\n                            them in parallel (requires --jobs >1)\n  --no-parallelize-within-files\n                            Serialize test execution within files instead of\n                            running them in parallel (requires --jobs >1)\n  --report-formatter <type> Switch between reporters (same options as --formatter)\n  -o, --output <dir>        Directory to write report files\n  -p, --pretty              Shorthand for \"--formatter pretty\"\n  --print-output-on-failure Automatically print the value of `$output` on failed tests\n  -r, --recursive           Include tests in subdirectories\n  --show-output-of-passing-tests\n                            Print output of passing tests\n  -t, --tap                 Shorthand for \"--formatter tap\"\n  -T, --timing              Add timing information to tests\n  -x, --trace               Print test commands as they are executed (like `set -x`)\n  --verbose-run             Make `run` print `$output` by default\n  -v, --version             Display the version number\n\n  For more information, see https://github.com/bats-core/bats-core\nHELP_TEXT_BODY\n}\n\nexpand_path() {\n  local path=\"${1%/}\"\n  local dirname=\"${path%/*}\"\n  local result=\"$2\"\n\n  if [[ \"$dirname\" == \"$path\" ]]; then\n    dirname=\"$PWD\"\n  else\n    cd \"$dirname\"\n    dirname=\"$PWD\"\n    cd \"$OLDPWD\"\n  fi\n  printf -v \"$result\" '%s/%s' \"$dirname\" \"${path##*/}\"\n}\n\nBATS_LIBEXEC=\"$(cd \"$(dirname \"$(bats_readlinkf \"${BASH_SOURCE[0]}\")\")\"; pwd)\"\nexport BATS_LIBEXEC\nexport BATS_CWD=\"$PWD\"\nexport BATS_TEST_FILTER=\nexport PATH=\"$BATS_LIBEXEC:$PATH\"\nexport BATS_ROOT_PID=$$\nexport BATS_TMPDIR=\"${TMPDIR:-/tmp}\"\nexport BATS_RUN_TMPDIR=\n\nif [[ ! -d \"${BATS_TMPDIR}\" ]];then\n  printf \"Error: BATS_TMPDIR (%s) does not exist or is not a directory\" \"${BATS_TMPDIR}\" >&2\n  exit 1\nelif [[ ! -w \"${BATS_TMPDIR}\" ]];then\n  printf \"Error: BATS_TMPDIR (%s) is not writable\" \"${BATS_TMPDIR}\" >&2\n  exit 1\nfi\n\narguments=()\n\n# Unpack single-character options bundled together, e.g. -cr, -pr.\nfor arg in \"$@\"; do\n  if [[ \"$arg\" =~ ^-[^-]. ]]; then\n    index=1\n    while option=\"${arg:$((index++)):1}\"; do\n      if [[ -z \"$option\" ]]; then\n        break\n      fi\n      arguments+=(\"-$option\")\n    done\n  else\n    arguments+=(\"$arg\")\n  fi\n  shift\ndone\n\nset -- \"${arguments[@]}\"\narguments=()\n\nunset flags recursive formatter_flags\nflags=('--dummy-flag') # add a dummy flag to prevent unset variable errors on empty array expansion in old bash versions\nformatter_flags=('--dummy-flag') # add a dummy flag to prevent unset variable errors on empty array expansion in old bash versions\nformatter='tap'\nreport_formatter=''\nrecursive=\nexport BATS_TEMPDIR_CLEANUP=1\noutput=\nif [[ -z \"${CI:-}\" && -t 0 && -t 1 ]] && command -v tput >/dev/null; then\n  formatter='pretty'\nfi\n\nwhile [[ \"$#\" -ne 0 ]]; do\n  case \"$1\" in\n  -h | --help)\n    version\n    usage\n    exit 0\n    ;;\n  -v | --version)\n    version\n    exit 0\n    ;;\n  -c | --count)\n    flags+=('-c')\n    ;;\n  -f | --filter)\n    shift\n    flags+=('-f' \"$1\")\n    ;;\n  -F | --formatter)\n    shift\n    # allow cat formatter to see extended output but don't advertise to users\n    if [[ $1 =~ ^(pretty|junit|tap|tap13|cat)$ ]]; then\n      formatter=\"$1\"\n    else\n      printf \"Unknown formatter '%s', valid options are %s\\n\" \"$1\" \"${VALID_FORMATTERS}\"\n      exit 1\n    fi\n    ;;\n  --report-formatter)\n    shift\n    if [[ $1 =~ ^(pretty|junit|tap|tap13)$ ]]; then\n      report_formatter=\"$1\"\n    else\n      printf \"Unknown report formatter '%s', valid options are %s\\n\" \"$1\" \"${VALID_FORMATTERS}\"\n      exit 1\n    fi\n    ;;\n  -o | --output)\n    shift\n    output=\"$1\"\n    ;;\n  -p | --pretty)\n    formatter='pretty'\n    ;;\n  -j | --jobs)\n    shift\n    flags+=('-j' \"$1\")\n    ;;\n  -r | --recursive)\n    recursive=1\n    ;;\n  -t | --tap)\n    formatter='tap'\n    ;;\n  -T | --timing)\n    flags+=('-T')\n    formatter_flags+=('-T')\n    ;;\n  # this flag is now a no-op, as it is the parallel default\n  --parallel-preserve-environment)\n    ;;\n  --no-parallelize-across-files)\n    flags+=(\"--no-parallelize-across-files\")\n    ;;\n  --no-parallelize-within-files)\n    flags+=(\"--no-parallelize-within-files\")\n    ;;\n  --no-tempdir-cleanup)\n    BATS_TEMPDIR_CLEANUP=''\n    ;;\n  --tempdir) # for internal test consumption only!\n    BATS_RUN_TMPDIR=\"$2\"\n    shift\n    ;;\n  -x | --trace)\n    flags+=(--trace)\n    ;;\n  --print-output-on-failure)\n    flags+=(--print-output-on-failure)\n    ;;\n  --show-output-of-passing-tests)\n    flags+=(--show-output-of-passing-tests)\n    ;;\n  --verbose-run)\n    flags+=(--verbose-run)\n    ;;\n  --gather-test-outputs-in)\n    shift\n    output_dir=\"$1\"\n    if ! mkdir \"$output_dir\"; then\n      abort \"Could not create $output_dir for --gather-test-outputs-in\"\n    fi\n    flags+=(--gather-test-outputs-in \"$output_dir\")\n    ;;\n  --code-quote-style)\n    shift\n    BATS_CODE_QUOTE_STYLE=\"$1\"\n  ;;\n  -*)\n    abort \"Bad command line option '$1'\"\n    ;;\n  *)\n    arguments+=(\"$1\")\n    ;;\n  esac\n  shift\ndone\n\nif [[ -n \"${BATS_RUN_TMPDIR:-}\" ]];then\n  if [[ -d \"$BATS_RUN_TMPDIR\" ]]; then\n    printf \"Error: BATS_RUN_TMPDIR (%s) already exists\\n\" \"$BATS_RUN_TMPDIR\" >&2\n    printf \"Reusing old run directories can lead to unexpected results ... aborting!\\n\" >&2\n    exit 1\n  elif ! mkdir -p \"$BATS_RUN_TMPDIR\" ;then\n    printf \"Error: Failed to create BATS_RUN_TMPDIR (%s)\\n\" \"$BATS_RUN_TMPDIR\" >&2\n    exit 1\n  fi\nelif ! BATS_RUN_TMPDIR=$(mktemp -d \"${BATS_TMPDIR}/bats-run-XXXXXX\");then\n  printf \"Error: Failed to create BATS_RUN_TMPDIR (%s) with mktemp\\n\" \"${BATS_TMPDIR}/bats-run-XXXXXX\" >&2\n  exit 1\nfi\n\nif [[ -n \"$BATS_TEMPDIR_CLEANUP\" ]]; then\n  trap 'rm -rf \"$BATS_RUN_TMPDIR\"' ERR EXIT\nelse\n  trap 'printf \"BATS_RUN_TMPDIR: $BATS_RUN_TMPDIR\\n\">&2' EXIT\nfi\n\nif [[ \"$formatter\" != \"tap\" ]]; then\n  flags+=('-x')\nfi\n\nif [[ -n \"$report_formatter\" && \"$report_formatter\" != \"tap\" ]]; then\n  flags+=('-x')\nfi\n\nif [[ \"$formatter\" == \"junit\" ]]; then\n  flags+=('-T')\n  formatter_flags+=('--base-path' \"${arguments[0]}\")\nfi\nif [[ \"$report_formatter\" == \"junit\" ]]; then\n  flags+=('-T')\n  report_formatter_flags+=('--base-path' \"${arguments[0]}\")\nfi\n\nif [[ \"$formatter\" == \"pretty\" ]]; then\n  formatter_flags+=('--base-path' \"${arguments[0]}\")\nfi\n\n# if we don't need to filter extended syntax, use the faster formatter\nif [[ \"$formatter\" == tap && -z \"$report_formatter\" ]]; then\n  formatter=\"cat\"\nfi\n\nif [[ \"${#arguments[@]}\" -eq 0 ]]; then\n  abort 'Must specify at least one <test>'\nfi\n\nif [[ -n \"$report_formatter\" ]]; then\n  # default to the current directory for output\n  if [[ -z \"$output\" ]]; then\n    output=.\n  fi\n  case \"$report_formatter\" in\n    tap|tap13)\n      BATS_REPORT_FILE_NAME=\"report.tap\"\n      ;;\n    junit)\n      BATS_REPORT_FILE_NAME=\"report.xml\"\n      ;;\n    pretty)\n      BATS_REPORT_FILE_NAME=\"report.log\"\n      ;;\n  esac\nfi\n\nif [[ \"${BATS_CODE_QUOTE_STYLE-BATS_CODE_QUOTE_STYLE_UNSET}\" == BATS_CODE_QUOTE_STYLE_UNSET ]]; then\n  BATS_CODE_QUOTE_STYLE=\"\\`'\"\nfi\n\ncase \"${BATS_CODE_QUOTE_STYLE}\" in\n  ??)\n    BATS_BEGIN_CODE_QUOTE=\"${BATS_CODE_QUOTE_STYLE::1}\"\n    BATS_END_CODE_QUOTE=\"${BATS_CODE_QUOTE_STYLE:1:1}\"\n    export BATS_BEGIN_CODE_QUOTE BATS_END_CODE_QUOTE\n  ;;\n  custom)\n    if [[ ${BATS_BEGIN_CODE_QUOTE-BATS_BEGIN_CODE_QUOTE_UNSET} == BATS_BEGIN_CODE_QUOTE_UNSET \n        || ${BATS_END_CODE_QUOTE-BATS_BEGIN_CODE_QUOTE_UNSET} == BATS_BEGIN_CODE_QUOTE_UNSET ]]; then\n      printf \"ERROR: BATS_CODE_QUOTE_STYLE=custom requires BATS_BEGIN_CODE_QUOTE and BATS_END_CODE_QUOTE to be set\\n\" >&2\n      exit 1\n    fi\n  ;;\n  *)\n    printf \"ERROR: Unknown BATS_CODE_QUOTE_STYLE: %s\\n\" \"$BATS_CODE_QUOTE_STYLE\" >&2\n    exit 1\n  ;;\nesac\n\nif [[ -n \"$output\" ]]; then\n  if [[ ! -w \"${output}\" ]]; then\n    abort \"Output path ${output} is not writeable\"\n  fi\n  export BATS_REPORT_OUTPUT_PATH=\"$output\"\nfi\n\nfilenames=()\nfor filename in \"${arguments[@]}\"; do\n  expand_path \"$filename\" 'filename'\n\n  if [[ -d \"$filename\" ]]; then\n    shopt -s nullglob\n    if [[ \"$recursive\" -eq 1 ]]; then\n      while IFS= read -r -d $'\\0' file; do\n        filenames+=(\"$file\")\n      done < <(find -L \"$filename\" -type f -name \"*.${BATS_FILE_EXTENSION:-bats}\" -print0 | sort -z)\n    else\n      for suite_filename in \"$filename\"/*.\"${BATS_FILE_EXTENSION:-bats}\"; do\n        filenames+=(\"$suite_filename\")\n      done\n    fi\n    shopt -u nullglob\n  else\n    filenames+=(\"$filename\")\n  fi\ndone\n\n# shellcheck source=lib/bats-core/validator.bash\nsource \"$BATS_ROOT/lib/bats-core/validator.bash\"\n\ntrap 'BATS_INTERRUPTED=true' INT # let the lower levels handle the interruption\n\nset -o pipefail execfail\n\nif [[ -n \"$report_formatter\" ]]; then\n  exec bats-exec-suite \"${flags[@]}\" \"${filenames[@]}\" | tee >(\"bats-format-${report_formatter}\" \"${report_formatter_flags[@]}\" >\"${BATS_REPORT_OUTPUT_PATH}/${BATS_REPORT_FILE_NAME}\") | bats_test_count_validator | \"bats-format-${formatter}\" \"${formatter_flags[@]}\"\nelse\n  exec bats-exec-suite \"${flags[@]}\" \"${filenames[@]}\" | bats_test_count_validator | \"bats-format-${formatter}\" \"${formatter_flags[@]}\"\nfi\n"
  },
  {
    "path": "vendor/bats-core/libexec/bats-core/bats-exec-file",
    "content": "#!/usr/bin/env bash\nset -eET\n\nexport flags=('--dummy-flag')\nnum_jobs=${BATS_NUMBER_OF_PARALLEL_JOBS:-1}\nfilter=''\nextended_syntax=''\nBATS_TRACE_LEVEL=\"${BATS_TRACE_LEVEL:-0}\"\n\nwhile [[ \"$#\" -ne 0 ]]; do\n  case \"$1\" in\n  -c) ;;\n\n  -f)\n    shift\n    filter=\"$1\"\n    flags+=('-f' \"$filter\")\n    ;;\n  -j)\n    shift\n    num_jobs=\"$1\"\n    ;;\n  -T)\n    flags+=('-T')\n    ;;\n  -x)\n    flags+=('-x')\n    extended_syntax=1\n    ;;\n  --no-parallelize-within-files)\n    # use singular to allow for users to override in file\n    BATS_NO_PARALLELIZE_WITHIN_FILE=1\n    ;;\n  --dummy-flag)\n    ;;\n  --trace)\n    flags+=('--trace')\n    ;;\n  --print-output-on-failure)\n    flags+=(--print-output-on-failure)\n    ;;\n  --show-output-of-passing-tests)\n    flags+=(--show-output-of-passing-tests)\n    ;;\n  --verbose-run)\n    flags+=(--verbose-run)\n    ;;\n  --gather-test-outputs-in)\n    shift\n    flags+=(--gather-test-outputs-in \"$1\")\n    ;;\n  *)\n    break\n    ;;\n  esac\n  shift\ndone\n\nfilename=\"$1\"\nTESTS_FILE=\"$2\"\n\nif [[ ! -f \"$filename\" ]]; then\n  printf 'Testfile \"%s\" not found\\n' \"$filename\" >&2\n  exit 1\nfi\n\nexport BATS_TEST_FILENAME=\"$filename\"\n\n# shellcheck source=lib/bats-core/preprocessing.bash\n# shellcheck disable=SC2153\nsource \"$BATS_ROOT/lib/bats-core/preprocessing.bash\"\n\nbats_run_setup_file() {\n  # shellcheck source=lib/bats-core/tracing.bash\n  # shellcheck disable=SC2153\n  source \"$BATS_ROOT/lib/bats-core/tracing.bash\"\n  # shellcheck source=lib/bats-core/test_functions.bash\n  # shellcheck disable=SC2153\n  source \"$BATS_ROOT/lib/bats-core/test_functions.bash\"\n\n  exec 3<&1\n\n  # these are defined only to avoid errors when referencing undefined variables down the line\n  # shellcheck disable=2034\n  BATS_TEST_NAME=      # used in tracing.bash\n  # shellcheck disable=2034\n  BATS_TEST_COMPLETED= # used in tracing.bash\n\n  BATS_SOURCE_FILE_COMPLETED=\n  BATS_SETUP_FILE_COMPLETED=\n  BATS_TEARDOWN_FILE_COMPLETED=\n  # shellcheck disable=2034\n  BATS_ERROR_STATUS= # used in tracing.bash\n  touch \"$BATS_OUT\"\n  bats_setup_tracing\n  trap 'bats_file_teardown_trap' EXIT\n\n  local status=0\n  # get the setup_file/teardown_file functions for this file (if it has them)\n  # shellcheck disable=SC1090\n  source \"$BATS_TEST_SOURCE\"  >>\"$BATS_OUT\" 2>&1\n\n  BATS_SOURCE_FILE_COMPLETED=1\n\n  setup_file >>\"$BATS_OUT\" 2>&1\n\n  BATS_SETUP_FILE_COMPLETED=1\n}\n\nbats_run_teardown_file() {\n  # avoid running the therdown trap due to errors in teardown_file\n  trap 'bats_file_exit_trap' EXIT\n  # rely on bats_error_trap to catch failures\n  teardown_file >>\"$BATS_OUT\" 2>&1\n\n  BATS_TEARDOWN_FILE_COMPLETED=1\n}\n\nbats_file_teardown_trap() {\n  bats_run_teardown_file\n  local status=0\n  bats_file_exit_trap\n}\n\n# shellcheck source=lib/bats-core/common.bash\nsource \"$BATS_ROOT/lib/bats-core/common.bash\"\n\nbats_file_exit_trap() {\n  trap - ERR EXIT\n  if [[ -z \"$BATS_SETUP_FILE_COMPLETED\" || -z \"$BATS_TEARDOWN_FILE_COMPLETED\" ]]; then\n    if [[ -z \"$BATS_SETUP_FILE_COMPLETED\" ]]; then\n      FAILURE_REASON='setup_file'\n    elif [[ -z \"$BATS_TEARDOWN_FILE_COMPLETED\" ]]; then\n      FAILURE_REASON='teardown_file'\n    elif [[ -z \"$BATS_SOURCE_FILE_COMPLETED\" ]]; then\n      FAILURE_REASON='source'\n    else\n      FAILURE_REASON='unknown internal'\n    fi\n    printf \"not ok %d %s\\n\" \"$((test_number_in_suite + 1))\" \"$FAILURE_REASON failed\" >&3\n    local stack_trace\n    bats_get_failure_stack_trace stack_trace\n    bats_print_stack_trace \"${stack_trace[@]}\" >&3\n    bats_print_failed_command \"${stack_trace[@]}\" >&3\n    bats_prefix_lines_for_tap_output < \"$BATS_OUT\" | bats_replace_filename >&3\n    rm -rf \"$BATS_OUT\"\n    status=1\n  fi\n  exit $status\n}\n\nfunction setup_file() {\n  return 0\n}\n\nfunction teardown_file() {\n  return 0\n}\n\nbats_forward_output_of_parallel_test() {\n  local test_number_in_suite=$1\n  local status=0\n  wait \"$(cat \"$output_folder/$test_number_in_suite/pid\")\" || status=1\n  cat \"$output_folder/$test_number_in_suite/stdout\"\n  cat \"$output_folder/$test_number_in_suite/stderr\" >&2\n  return $status\n}\n\nbats_is_next_parallel_test_finished() {\n  local PID\n  # get the pid of the next potentially finished test\n  PID=$(cat \"$output_folder/$(( test_number_in_suite_of_last_finished_test + 1 ))/pid\")\n  # try to send a signal to this process\n  # if it fails, the process exited,\n  # if it succeeds, the process is still running\n  if kill -0 \"$PID\" 2>/dev/null; then\n    return 1\n  fi\n}\n\n# prints output from all tests in the order they were started\n# $1 == \"blocking\": wait for a test to finish before printing\n#    != \"blocking\": abort printing, when a test has not finished\nbats_forward_output_for_parallel_tests() {\n  local status=0\n  # was the next test already started?\n  while [[ $(( test_number_in_suite_of_last_finished_test + 1 )) -le $test_number_in_suite ]]; do\n    # if we are okay with waiting or if the test has already been finished\n    if [[ \"$1\" == \"blocking\" ]] || bats_is_next_parallel_test_finished ; then\n      (( ++test_number_in_suite_of_last_finished_test ))\n      bats_forward_output_of_parallel_test \"$test_number_in_suite_of_last_finished_test\" || status=1\n    else\n      # non-blocking and the process has not finished -> abort the printing\n      break\n    fi\n  done\n  return $status\n}\n\nbats_run_tests_in_parallel() {\n  local output_folder=\"$BATS_RUN_TMPDIR/parallel_output\"\n  local status=0\n  mkdir -p \"$output_folder\"\n  # shellcheck source=lib/bats-core/semaphore.bash\n  source \"$BATS_ROOT/lib/bats-core/semaphore.bash\"\n  bats_semaphore_setup\n  # the test_number_in_file is not yet incremented -> one before the next test to run\n  local test_number_in_suite_of_last_finished_test=\"$test_number_in_suite\" # stores which test was printed last\n  for test_name in \"${tests_to_run[@]}\"; do\n    # Only handle non-empty lines\n    if [[ $test_name ]]; then\n      ((++test_number_in_suite))\n      ((++test_number_in_file))\n      mkdir -p \"$output_folder/$test_number_in_suite\"\n      bats_semaphore_run \"$output_folder/$test_number_in_suite\" \\\n                          \"$BATS_LIBEXEC/bats-exec-test\" \"${flags[@]}\" \"$filename\" \"$test_name\" \"$test_number_in_suite\" \"$test_number_in_file\" \\\n                          > \"$output_folder/$test_number_in_suite/pid\"\n    fi\n    # print results early to get interactive feedback\n    bats_forward_output_for_parallel_tests non-blocking || status=1 # ignore if we did not finish yet\n  done\n  bats_forward_output_for_parallel_tests blocking || status=1\n  return $status\n}\n\nbats_read_tests_list_file() {\n  local line_number=0\n  tests_to_run=()\n  # the global test number must be visible to traps -> not local\n  first_test_number_in_suite=''\n  while read -r test_line; do\n    # check if the line begins with filename\n    # filename might contain some hard to parse characters,\n    # use simple string operations to work around that issue\n    if [[ \"$filename\" == \"${test_line::${#filename}}\" ]]; then\n      # get the rest of the line without the separator \\t\n      test_name=${test_line:$((1 + ${#filename} ))}\n      tests_to_run+=(\"$test_name\")\n      # save the first test's number for later iteration\n      # this assumes that tests for a file are stored consecutive in the file!\n      if [[ -z \"$first_test_number_in_suite\" ]]; then\n        first_test_number_in_suite=$line_number\n      fi\n    fi\n    ((++line_number))\n  done <\"$TESTS_FILE\"\n\n  test_number_in_suite=\"$first_test_number_in_suite\"\n  test_number_in_file=0\n}\n\nbats_run_tests() {\n  status=0\n\n  if [[ \"$num_jobs\" != 1 && \"${BATS_NO_PARALLELIZE_WITHIN_FILE-False}\" == False ]]; then\n    export BATS_SEMAPHORE_NUMBER_OF_SLOTS=\"$num_jobs\"\n    bats_run_tests_in_parallel \"$BATS_RUN_TMPDIR/parallel_output\" || status=1\n  else\n    for test_name in \"${tests_to_run[@]}\"; do\n      if [[ \"${BATS_INTERRUPTED-NOTSET}\" != NOTSET ]]; then\n        status=130 # bash's code for SIGINT exits\n        break\n      fi\n      # Only handle non-empty lines\n      if [[ $test_name ]]; then\n        ((++test_number_in_suite))\n        ((++test_number_in_file))\n        # deal with empty flags to avoid spurious \"unbound variable\" errors on Bash 4.3 and lower\n        if [[ \"${#flags[@]}\" -gt 0 ]]; then\n          \"$BATS_LIBEXEC/bats-exec-test\" \"${flags[@]}\" \"$filename\" \"$test_name\" \"$test_number_in_suite\" \"$test_number_in_file\" || status=1\n        else\n          \"$BATS_LIBEXEC/bats-exec-test\" \"$filename\" \"$test_name\" \"$test_number_in_suite\" \"$test_number_in_file\" || status=1\n        fi\n      fi\n    done\n  fi\n  export status\n}\n\nbats_create_file_tempdirs() {\n  local bats_files_tmpdir=\"${BATS_RUN_TMPDIR}/file\"\n  if ! mkdir -p \"$bats_files_tmpdir\"; then\n    printf 'Failed to create %s\\n' \"$bats_files_tmpdir\" >&2\n    exit 1\n  fi\n  BATS_FILE_TMPDIR=\"$bats_files_tmpdir/$first_test_number_in_suite\"\n  if ! mkdir \"$BATS_FILE_TMPDIR\"; then\n    printf 'Failed to create BATS_FILE_TMPDIR=%s\\n' \"$BATS_FILE_TMPDIR\" >&2\n    exit 1\n  fi\n  ln -s \"$BATS_TEST_FILENAME\" \"$BATS_FILE_TMPDIR-$(basename \"$BATS_TEST_FILENAME\").source_file\"\n  export BATS_FILE_TMPDIR\n}\n\ntrap 'BATS_INTERRUPTED=true' INT\n\nif [[ -n \"$extended_syntax\" ]]; then\n  printf \"suite %s\\n\" \"$filename\"\nfi\n\nbats_read_tests_list_file\n\n# don't run potentially expensive setup/teardown_file\n# when there are no tests to run\nif [[ ${#tests_to_run[@]} -eq 0 ]]; then\n  exit 0\nfi\n\n# requires the test list to be read but not empty\nbats_create_file_tempdirs\n\nbats_preprocess_source \"$filename\"\n\ntrap bats_interrupt_trap INT\nbats_run_setup_file\n\n# during tests, we don't want to get backtraces from this level\n# just wait for the test to be interrupted and display their trace\ntrap 'BATS_INTERRUPTED=true' INT\nbats_run_tests\n\ntrap bats_interrupt_trap INT\nbats_run_teardown_file\n\nexit $status\n"
  },
  {
    "path": "vendor/bats-core/libexec/bats-core/bats-exec-suite",
    "content": "#!/usr/bin/env bash\nset -e\n\ncount_only_flag=''\nfilter=''\nnum_jobs=${BATS_NUMBER_OF_PARALLEL_JOBS:-1}\nbats_no_parallelize_across_files=${BATS_NO_PARALLELIZE_ACROSS_FILES-}\nbats_no_parallelize_within_files=\nflags=('--dummy-flag') # add a dummy flag to prevent unset varialeb errors on empty array expansion in old bash versions\n\nabort() {\n  printf 'Error: %s\\n' \"$1\" >&2\n  exit 1\n}\n\nwhile [[ \"$#\" -ne 0 ]]; do\n  case \"$1\" in\n  -c)\n    count_only_flag=1\n    ;;\n  -f)\n    shift\n    filter=\"$1\"\n    flags+=('-f' \"$filter\")\n    ;;\n  -j)\n    shift\n    num_jobs=\"$1\"\n    flags+=('-j' \"$num_jobs\")\n    ;;\n  -T)\n    flags+=('-T')\n    ;;\n  -x)\n    flags+=('-x')\n    ;;\n  --no-parallelize-across-files)\n    bats_no_parallelize_across_files=1\n    ;;\n  --no-parallelize-within-files)\n    bats_no_parallelize_within_files=1\n    flags+=(\"--no-parallelize-within-files\")\n    ;;\n  --dummy-flag)\n    ;;\n  --trace)\n    flags+=('--trace')\n    ;;\n  --print-output-on-failure)\n    flags+=(--print-output-on-failure)\n    ;;\n  --show-output-of-passing-tests)\n    flags+=(--show-output-of-passing-tests)\n    ;;\n  --verbose-run)\n    flags+=(--verbose-run)\n    ;;\n  --gather-test-outputs-in)\n    shift\n    flags+=(--gather-test-outputs-in \"$1\")\n    ;;\n  *)\n    break\n    ;;\n  esac\n  shift\ndone\n\nif [[ \"$num_jobs\" != 1 ]]; then\n  if ! type -p parallel >/dev/null && [[ -z \"$bats_no_parallelize_across_files\" ]]; then\n    abort \"Cannot execute \\\"${num_jobs}\\\" jobs without GNU parallel\"\n    exit 1\n  fi\n  # shellcheck source=lib/bats-core/semaphore.bash\n  source \"${BATS_ROOT}/lib/bats-core/semaphore.bash\"\n  bats_semaphore_setup\nfi\n\n# create a file that contains all (filtered) tests to run from all files\nTESTS_LIST_FILE=\"${BATS_RUN_TMPDIR}/test_list_file.txt\"\n\nall_tests=()\nfor filename in \"$@\"; do\n  if [[ ! -f \"$filename\" ]]; then\n    abort \"Test file \\\"${filename}\\\" does not exist\"\n  fi\n\n  test_names=()\n  test_dupes=()\n  while read -r line; do\n    if [[ ! \"$line\" =~ ^bats_test_function\\  ]]; then\n      continue\n    fi\n    line=\"${line%$'\\r'}\"\n    line=\"${line#* }\"\n    test_line=$(printf \"%s\\t%s\" \"$filename\" \"$line\")\n    all_tests+=(\"$test_line\")\n    printf \"%s\\n\" \"$test_line\" >>\"$TESTS_LIST_FILE\"\n    # avoid unbound variable errors on empty array expansion with old bash versions\n    if [[ ${#test_names[@]} -gt 0 && \" ${test_names[*]} \" == *\" $line \"* ]]; then\n      test_dupes+=(\"$line\")\n      continue\n    fi\n    test_names+=(\"$line\")\n  done < <(BATS_TEST_FILTER=\"$filter\" bats-preprocess \"$filename\")\n\n  if [[ \"${#test_dupes[@]}\" -ne 0 ]]; then\n    abort \"Duplicate test name(s) in file \\\"${filename}\\\": ${test_dupes[*]}\"\n  fi\ndone\n\ntest_count=\"${#all_tests[@]}\"\n\nif [[ -n \"$count_only_flag\" ]]; then\n  printf '%d\\n' \"${test_count}\"\n  exit\nfi\n\nif [[ -n \"$bats_no_parallelize_across_files\" ]] && [[ ! \"$num_jobs\" -gt 1 ]]; then\n  abort \"The flag --no-parallelize-across-files requires at least --jobs 2\"\n  exit 1\nfi\n\nif [[ -n \"$bats_no_parallelize_within_files\" ]] && [[ ! \"$num_jobs\" -gt 1 ]]; then\n  abort \"The flag --no-parallelize-across-files requires at least --jobs 2\"\n  exit 1\nfi\n\n# only abort on the lowest levels\ntrap 'BATS_INTERRUPTED=true' INT\n\ntrap bats_exit_trap EXIT\n\nbats_exit_trap() {\n  if [[ ${BATS_INTERRUPTED-NOTSET} != NOTSET ]]; then\n    printf \"\\n# Received SIGINT, aborting ...\\n\\n\"\n  fi\n  exit \"$status\"\n}\n\nstatus=0\nprintf '1..%d\\n' \"${test_count}\"\n\n# No point on continuing if there's no tests.\nif [[ \"${test_count}\" == 0 ]]; then\n  exit\nfi\n\nexport BATS_SUITE_TMPDIR=\"${BATS_RUN_TMPDIR}/suite\"\nif ! mkdir \"$BATS_SUITE_TMPDIR\"; then\n  printf '%s\\n' \"Failed to create BATS_SUITE_TMPDIR\" >&2\n  exit 1\nfi\n\n# Deduplicate filenames (without reordering) to avoid running duplicate tests n by n times.\n# (see https://github.com/bats-core/bats-core/issues/329)\n# If a file was specified multiple times, we already got it repeatedly in our TESTS_LIST_FILE.\n# Thus, it suffices to bats-exec-file it once to run all repeated tests on it.\nIFS=$'\\n' read -d '' -r -a  BATS_UNIQUE_TEST_FILENAMES < <(printf \"%s\\n\" \"$@\"| nl | sort -k 2 | uniq -f 1 | sort -n | cut -f 2-) || true\n\nif [[ \"$num_jobs\" -gt 1 ]] && [[ -z \"$bats_no_parallelize_across_files\" ]]; then\n  # run files in parallel to get the maximum pool of parallel tasks\n  # shellcheck disable=SC2086,SC2068\n  # we need to handle the quoting of ${flags[@]} ourselves,\n  # because parallel can only quote it as one\n  parallel --keep-order --jobs \"$num_jobs\" bats-exec-file \"$(printf \"%q \" \"${flags[@]}\")\" \"{}\" \"$TESTS_LIST_FILE\"  ::: \"${BATS_UNIQUE_TEST_FILENAMES[@]}\" 2>&1 || status=1\nelse\n  for filename in \"${BATS_UNIQUE_TEST_FILENAMES[@]}\"; do\n    if [[ \"${BATS_INTERRUPTED-NOTSET}\" != NOTSET ]]; then\n      status=130 # bash's code for SIGINT exits\n      break\n    fi\n    bats-exec-file \"${flags[@]}\" \"$filename\" \"${TESTS_LIST_FILE}\" || status=1\n  done\nfi\n\nexit \"$status\"\n"
  },
  {
    "path": "vendor/bats-core/libexec/bats-core/bats-exec-test",
    "content": "#!/usr/bin/env bash\nset -eET\n\n# Variables used in other scripts.\nBATS_COUNT_ONLY=''\nBATS_TEST_FILTER=''\nBATS_ENABLE_TIMING=''\nBATS_EXTENDED_SYNTAX=''\nBATS_TRACE_LEVEL=\"${BATS_TRACE_LEVEL:-0}\"\nBATS_PRINT_OUTPUT_ON_FAILURE=\"${BATS_PRINT_OUTPUT_ON_FAILURE:-}\"\nBATS_SHOW_OUTPUT_OF_SUCCEEDING_TESTS=\"${BATS_SHOW_OUTPUT_OF_SUCCEEDING_TESTS:-}\"\nBATS_VERBOSE_RUN=\"${BATS_VERBOSE_RUN:-}\"\nBATS_GATHER_TEST_OUTPUTS_IN=\"${BATS_GATHER_TEST_OUTPUTS_IN:-}\"\n\nwhile [[ \"$#\" -ne 0 ]]; do\n  case \"$1\" in\n  -c)\n    # shellcheck disable=SC2034\n    BATS_COUNT_ONLY=1\n    ;;\n  -f)\n    shift\n    # shellcheck disable=SC2034\n    BATS_TEST_FILTER=\"$1\"\n    ;;\n  -T)\n    BATS_ENABLE_TIMING='-T'\n    ;;\n  -x)\n    # shellcheck disable=SC2034\n    BATS_EXTENDED_SYNTAX='-x'\n    ;;\n  --dummy-flag)\n    ;;\n  --trace)\n    (( ++BATS_TRACE_LEVEL )) # avoid returning 0\n    ;;\n  --print-output-on-failure)\n    BATS_PRINT_OUTPUT_ON_FAILURE=1\n    ;;\n  --show-output-of-passing-tests)\n    BATS_SHOW_OUTPUT_OF_SUCCEEDING_TESTS=1\n    ;;\n  --verbose-run)\n    BATS_VERBOSE_RUN=1\n    ;;\n  --gather-test-outputs-in)\n    shift\n    BATS_GATHER_TEST_OUTPUTS_IN=\"$1\"\n    ;;\n  *)\n    break\n    ;;\n  esac\n  shift\ndone\n\nexport BATS_TEST_FILENAME=\"$1\"\nexport BATS_TEST_NAME=\"$2\"\nexport BATS_SUITE_TEST_NUMBER=\"$3\"\nexport BATS_TEST_NUMBER=\"$4\"\n\nif [[ -z \"$BATS_TEST_FILENAME\" ]]; then\n  printf 'usage: bats-exec-test <filename>\\n' >&2\n  exit 1\nelif [[ ! -f \"$BATS_TEST_FILENAME\" ]]; then\n  printf 'bats: %s does not exist\\n' \"$BATS_TEST_FILENAME\" >&2\n  exit 1\nfi\n\nbats_create_test_tmpdirs() {\n  local tests_tmpdir=\"${BATS_RUN_TMPDIR}/test/\"\n  if ! mkdir -p \"$tests_tmpdir\"; then\n    printf 'Failed to create: %s\\n' \"$tests_tmpdir\" >&2\n    exit 1\n  fi\n\n  BATS_TEST_TMPDIR=\"$tests_tmpdir/$BATS_SUITE_TEST_NUMBER\"\n  if ! mkdir \"$BATS_TEST_TMPDIR\"; then\n    printf 'Failed to create BATS_TEST_TMPDIR: %s\\n' \"$BATS_TEST_TMPDIR\" >&2\n    exit 1\n  fi\n\n  printf \"%s\\n\" \"$BATS_TEST_NAME\" > \"$BATS_TEST_TMPDIR.name\"\n\n  export BATS_TEST_TMPDIR\n}\n\n# load the test helper functions like `load` or `run` that are needed to run a (preprocessed) .bats file without bash errors\n# shellcheck source=lib/bats-core/test_functions.bash disable=SC2153\nsource \"$BATS_ROOT/lib/bats-core/test_functions.bash\"\n# shellcheck source=lib/bats-core/tracing.bash disable=SC2153\nsource \"$BATS_ROOT/lib/bats-core/tracing.bash\"\n\nbats_teardown_trap() {\n  bats_check_status_from_trap\n  local status=0\n  # mark the start of this function to distinguish where skip is called\n  # parameter 1 will signify the reason why this function was called\n  # this is used to identify when this is called as exit trap function\n  BATS_TEARDOWN_STARTED=${1:-1}\n  teardown >>\"$BATS_OUT\" 2>&1 || status=\"$?\"\n\n  if [[ $status -eq 0 ]]; then\n    BATS_TEARDOWN_COMPLETED=1\n  elif [[ -n \"$BATS_TEST_COMPLETED\" ]]; then\n    BATS_DEBUG_LAST_STACK_TRACE_IS_VALID=1\n    BATS_ERROR_STATUS=\"$status\"\n  fi\n\n  bats_exit_trap\n}\n\n# shellcheck source=lib/bats-core/common.bash\nsource \"$BATS_ROOT/lib/bats-core/common.bash\"\n\nbats_exit_trap() {\n  local status\n  local skipped=''\n  trap - ERR EXIT\n\n  if [[ -n \"$BATS_TEST_SKIPPED\" ]]; then\n    skipped=' # skip'\n    if [[ \"$BATS_TEST_SKIPPED\" != '1' ]]; then\n      skipped+=\" $BATS_TEST_SKIPPED\"\n    fi\n  fi\n\n  BATS_TEST_TIME=''\n  if [[ -z \"${skipped}\" && -n \"$BATS_ENABLE_TIMING\" ]]; then\n    BATS_TEST_TIME=\" in \"$(( $(get_mills_since_epoch) - BATS_TEST_START_TIME ))\"ms\"\n  fi\n\n  local print_bats_out=\"${BATS_SHOW_OUTPUT_OF_SUCCEEDING_TESTS}\"\n\n  if [[ -z \"$BATS_TEST_COMPLETED\" || -z \"$BATS_TEARDOWN_COMPLETED\" || \"${BATS_INTERRUPTED-NOTSET}\" != NOTSET ]]; then\n    if [[ \"$BATS_ERROR_STATUS\" -eq 0 ]]; then\n      # For some versions of bash, `$?` may not be set properly for some error\n      # conditions before triggering the EXIT trap directly (see #72 and #81).\n      # Thanks to the `BATS_TEARDOWN_COMPLETED` signal, this will pinpoint such\n      # errors if they happen during `teardown()` when `bats_perform_test` calls\n      # `bats_teardown_trap` directly after the test itself passes.\n      #\n      # If instead the test fails, and the `teardown()` error happens while\n      # `bats_teardown_trap` runs as the EXIT trap, the test will fail with no\n      # output, since there's no way to reach the `bats_exit_trap` call.\n      BATS_ERROR_STATUS=1\n    fi\n    printf 'not ok %d %s\\n' \"$BATS_SUITE_TEST_NUMBER\" \"${BATS_TEST_DESCRIPTION}${BATS_TEST_TIME}\" >&3\n    local stack_trace\n    bats_get_failure_stack_trace stack_trace\n    bats_print_stack_trace \"${stack_trace[@]}\" >&3\n    bats_print_failed_command \"${stack_trace[@]}\" >&3\n\n    if [[ $BATS_PRINT_OUTPUT_ON_FAILURE && -n \"${output:-}\" ]]; then\n      printf \"Last output:\\n%s\\n\" \"$output\" >> \"$BATS_OUT\"\n    fi \n\n    print_bats_out=1\n    status=1\n  else\n    printf 'ok %d %s%s\\n' \"$BATS_SUITE_TEST_NUMBER\" \"${BATS_TEST_DESCRIPTION}${BATS_TEST_TIME}\" \\\n      \"$skipped\" >&3\n    status=0\n  fi\n\n  if [[ $print_bats_out ]]; then\n    bats_prefix_lines_for_tap_output < \"$BATS_OUT\" | bats_replace_filename >&3\n  fi\n\n  if [[ $BATS_GATHER_TEST_OUTPUTS_IN ]]; then\n    cp \"$BATS_OUT\" \"$BATS_GATHER_TEST_OUTPUTS_IN/$BATS_SUITE_TEST_NUMBER-$BATS_TEST_DESCRIPTION.log\"\n  fi\n\n  rm -f \"$BATS_OUT\"\n  exit \"$status\"\n}\n\nget_mills_since_epoch() {\n  local ms_since_epoch\n  ms_since_epoch=$(date +%s%N)\n  if [[ \"$ms_since_epoch\" == *N || \"${#ms_since_epoch}\" -lt 19 ]]; then\n        ms_since_epoch=$(( $(date +%s) * 1000 ))\n  else\n        ms_since_epoch=$(( ms_since_epoch / 1000000 ))\n  fi\n\n  printf \"%d\\n\" \"$ms_since_epoch\"\n}\n\nbats_perform_test() {\n  if ! declare -F \"$BATS_TEST_NAME\" &>/dev/null; then\n    local quoted_test_name\n    bats_quote_code quoted_test_name \"$BATS_TEST_NAME\"\n    printf \"bats: unknown test name %s\\n\" \"$quoted_test_name\" >&2\n    exit 1\n  fi\n\n  # Variables for capturing accurate stack traces. See bats_debug_trap for\n  # details.\n  #\n  # BATS_DEBUG_LAST_LINENO, BATS_DEBUG_LAST_SOURCE, and\n  # BATS_DEBUG_LAST_STACK_TRACE hold data from the most recent call to\n  # bats_debug_trap.\n  #\n  # BATS_DEBUG_LASTLAST_STACK_TRACE holds data from two bats_debug_trap calls\n  # ago.\n  #\n  # BATS_DEBUG_LAST_STACK_TRACE_IS_VALID indicates that\n  # BATS_DEBUG_LAST_STACK_TRACE contains the stack trace of the test's error. If\n  # unset, BATS_DEBUG_LAST_STACK_TRACE is unreliable and\n  # BATS_DEBUG_LASTLAST_STACK_TRACE should be used instead.\n  BATS_DEBUG_LASTLAST_STACK_TRACE=()\n  BATS_DEBUG_LAST_LINENO=()\n  BATS_DEBUG_LAST_SOURCE=()\n  BATS_DEBUG_LAST_STACK_TRACE=()\n  BATS_DEBUG_LAST_STACK_TRACE_IS_VALID=\n\n  BATS_TEST_COMPLETED=\n  BATS_TEST_SKIPPED=\n  BATS_TEARDOWN_COMPLETED=\n  BATS_ERROR_STATUS=\n  BATS_ERROR_SUFFIX=\n  bats_setup_tracing\n  # mark this call as trap call\n  trap 'bats_teardown_trap as-exit-trap' EXIT\n\n  BATS_TEST_START_TIME=$(get_mills_since_epoch)\n  \"$BATS_TEST_NAME\" >>\"$BATS_OUT\" 2>&1 4>&1\n\n  BATS_TEST_COMPLETED=1\n  trap 'bats_exit_trap' EXIT\n  bats_teardown_trap \"\" # pass empty parameter to signify call outside trap\n}\n\ntrap bats_interrupt_trap INT\n\n# shellcheck source=lib/bats-core/preprocessing.bash\nsource \"$BATS_ROOT/lib/bats-core/preprocessing.bash\"\n\nexec 3<&1\n\nbats_create_test_tmpdirs\n# Run the given test.\nbats_evaluate_preprocessed_source\nbats_perform_test\n"
  },
  {
    "path": "vendor/bats-core/libexec/bats-core/bats-format-cat",
    "content": "#!/usr/bin/env bash\nset -e\n\ntrap '' INT\n\ncat\n"
  },
  {
    "path": "vendor/bats-core/libexec/bats-core/bats-format-junit",
    "content": "#!/usr/bin/env bash\nset -euo pipefail\n\n# shellcheck source=lib/bats-core/formatter.bash\nsource \"$BATS_ROOT/lib/bats-core/formatter.bash\"\n\nBASE_PATH=.\n\n\nwhile [[ \"$#\" -ne 0 ]]; do\n  case \"$1\" in\n    --base-path)\n      shift\n      normalize_base_path BASE_PATH \"$1\"\n    ;;\n  esac\n  shift\ndone\n\ninit_suite() {\n  suite_test_exec_time=0\n  # since we have to print the suite header before its contents but we don't know the contents before the header, \n  # we have to buffer the contents\n  _suite_buffer=\"\"\n  test_result_state=\"\" # declare for the first flush, when no test has been encountered\n}\n\n_buffer_log=\ninit_file() {\n  file_count=0\n  file_failures=0\n  file_skipped=0\n  file_exec_time=0\n  test_exec_time=0\n  _buffer=\"\"\n  _buffer_log=\"\"\n  _system_out_log=\"\"\n  test_result_state=\"\" # mark that no test has run in this file so far\n}\n\nhost() {\n  local hostname=\"${HOST:-}\"\n  [[ -z \"$hostname\" ]] && hostname=\"${HOSTNAME:-}\"\n  [[ -z \"$hostname\" ]] && hostname=\"$(uname -n)\"\n  [[ -z \"$hostname\" ]] && hostname=\"$(hostname -f)\"\n\n  echo \"$hostname\"\n}\n\n# convert $1 (time in milliseconds) to seconds\nmilliseconds_to_seconds() {\n  # we cannot rely on having bc for this calculation\n  full_seconds=$(($1 / 1000))\n  remaining_milliseconds=$(($1 % 1000))\n  if [[ $remaining_milliseconds -eq 0 ]]; then\n    printf \"%d\" \"$full_seconds\"\n  else\n    printf \"%d.%03d\" \"$full_seconds\" \"$remaining_milliseconds\"\n  fi\n}\n\nsuite_header() {\n  printf \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\n<testsuites time=\\\"%s\\\">\\n\" \"$(milliseconds_to_seconds \"${suite_test_exec_time}\")\"\n}\n\nfile_header() {\n  timestamp=$(date -u +\"%Y-%m-%dT%H:%M:%S\")\n  printf \"<testsuite name=\\\"%s\\\" tests=\\\"%s\\\" failures=\\\"%s\\\" errors=\\\"0\\\" skipped=\\\"%s\\\" time=\\\"%s\\\" timestamp=\\\"%s\\\" hostname=\\\"%s\\\">\\n\" \\\n                     \"$(xml_escape \"${class}\")\" \"${file_count}\" \"${file_failures}\" \"${file_skipped}\" \"$(milliseconds_to_seconds \"${file_exec_time}\")\" \"${timestamp}\" \"$(host)\"\n}\n\nfile_footer() {\n  printf \"</testsuite>\\n\"\n}\n\nsuite_footer() {\n  printf \"</testsuites>\\n\"\n}\n\nprint_test_case() {\n  if [[ \"$test_result_state\" == ok && -z \"$_system_out_log\" && -z \"$_buffer_log\" ]]; then\n    # pass and no output can be shortened\n    printf \"    <testcase classname=\\\"%s\\\" name=\\\"%s\\\" time=\\\"%s\\\" />\\n\" \"$(xml_escape \"${class}\")\" \"$(xml_escape \"${name}\")\" \"$(milliseconds_to_seconds \"${test_exec_time}\")\"\n  else\n    printf \"    <testcase classname=\\\"%s\\\" name=\\\"%s\\\" time=\\\"%s\\\">\\n\" \"$(xml_escape \"${class}\")\" \"$(xml_escape \"${name}\")\" \"$(milliseconds_to_seconds \"${test_exec_time}\")\"\n    if [[ -n \"$_system_out_log\" ]]; then\n      printf \"        <system-out>%s</system-out>\\n\" \"$(xml_escape \"${_system_out_log}\")\"\n    fi\n    if [[ -n \"$_buffer_log\" || \"$test_result_state\" == not_ok ]]; then\n      printf \"        <failure type=\\\"failure\\\">%s</failure>\\n\" \"$(xml_escape \"${_buffer_log}\")\"\n    fi\n    if [[ \"$test_result_state\" == skipped ]]; then\n      printf \"        <skipped>%s</skipped>\\n\" \"$(xml_escape \"$test_skip_message\")\"\n    fi\n    printf \"    </testcase>\\n\"\n  fi\n}\n\nxml_escape() {\n  output=${1//&/&amp;}\n  output=${output//</&lt;}\n  output=${output//>/&gt;}\n  output=${output//'\"'/&quot;}\n  output=${output//\\'/&#39;}\n  local CONTROL_CHAR=$'\\033'\n  output=\"${output//$CONTROL_CHAR/&#27;}\"\n  printf \"%s\" \"$output\"\n}\n\nsuite_buffer() {\n  local output\n  output=\"$(\"$@\"; printf \"x\")\" # use x marker to avoid losing trailing newlines\n  _suite_buffer=\"${_suite_buffer}${output%x}\"\n}\n\nsuite_flush() {\n  echo -n \"${_suite_buffer}\"\n  _suite_buffer=\"\"\n}\n\nbuffer() {\n  local output\n  output=\"$(\"$@\"; printf \"x\")\" # use x marker to avoid losing trailing newlines\n  _buffer=\"${_buffer}${output%x}\"\n}\n\nflush() {\n  echo -n \"${_buffer}\"\n  _buffer=\"\"\n}\n\nlog() {\n  if [[ -n \"$_buffer_log\" ]]; then\n    _buffer_log=\"${_buffer_log}\n$1\"\n  else\n    _buffer_log=\"$1\"\n  fi\n}\n\nflush_log() {\n  if [[ -n \"$test_result_state\" ]]; then\n    buffer print_test_case\n  fi\n  _buffer_log=\"\"\n  _system_out_log=\"\"\n}\n\nlog_system_out() {\n  if [[ -n \"$_system_out_log\" ]]; then\n    _system_out_log=\"${_system_out_log}\n$1\"\n  else\n    _system_out_log=\"$1\"\n  fi\n}\n\nfinish_file() {\n  if [[ \"${class-JUNIT_FORMATTER_NO_FILE_ENCOUNTERED}\" != JUNIT_FORMATTER_NO_FILE_ENCOUNTERED ]]; then\n    file_header\n    printf \"%s\\n\" \"${_buffer}\"\n    file_footer\n  fi\n}\n\nfinish_suite() {\n  flush_log\n  suite_header\n  suite_flush\n  finish_file # must come after suite flush to not print the last file before the others\n  suite_footer\n}\n\nbats_tap_stream_plan() { #  <number of tests>\n  :\n}\n\ninit_suite\ntrap finish_suite EXIT\ntrap '' INT\n\nbats_tap_stream_begin() { # <test index> <test name>\n  flush_log\n  # set after flushing to avoid overriding name of test\n  name=\"$2\"\n}\n\nbats_tap_stream_ok() { # [--duration <milliseconds] <test index> <test name>\n  if [[ \"$1\" == \"--duration\" ]]; then\n    test_exec_time=\"${BASH_REMATCH[1]}\"\n  else\n    test_exec_time=0\n  fi\n  ((file_count += 1))\n  test_result_state='ok'\n  file_exec_time=\"$((file_exec_time + test_exec_time))\"\n  suite_test_exec_time=$((suite_test_exec_time + test_exec_time))\n}\n\nbats_tap_stream_skipped() { # <test index> <test name> <skip reason>\n  ((file_count += 1))\n  ((file_skipped += 1))\n  test_result_state='skipped'\n  test_exec_time=0\n  test_skip_message=\"$3\"\n}\n\nbats_tap_stream_not_ok() { # [--duration <milliseconds>] <test index> <test name>\n  ((file_count += 1))\n  ((file_failures += 1))\n  if [[ \"$1\" == \"--duration\" ]]; then\n    test_exec_time=\"${BASH_REMATCH[1]}\"\n  else\n    test_exec_time=0\n  fi\n  test_result_state=not_ok\n  file_exec_time=\"$((file_exec_time + test_exec_time))\"\n  suite_test_exec_time=$((suite_test_exec_time + test_exec_time))\n}\n\nbats_tap_stream_comment() { # <comment text without leading '# '> <scope>\n  local comment=\"$1\" scope=\"$2\"\n  case \"$scope\" in\n    begin)\n      # everything that happens between begin and [not] ok is FD3 output from the test\n      log_system_out \"$comment\"\n    ;;\n    ok)\n      # non failed tests can produce FD3 output\n      log_system_out \"$comment\"\n    ;;\n    *)\n      # everything else is considered error output\n      log \"$1\"\n    ;;\n  esac\n}\n\nbats_tap_stream_suite() { # <file name>\n  flush_log\n  suite_buffer finish_file\n  init_file\n  class=\"$(remove_prefix \"$BASE_PATH\" \"$1\")\"\n}\n\nbats_tap_stream_unknown() { # <full line>\n  :\n}\n\nbats_parse_internal_extended_tap\n"
  },
  {
    "path": "vendor/bats-core/libexec/bats-core/bats-format-pretty",
    "content": "#!/usr/bin/env bash\nset -e\n\n# shellcheck source=lib/bats-core/formatter.bash\nsource \"$BATS_ROOT/lib/bats-core/formatter.bash\"\n\nBASE_PATH=.\nBATS_ENABLE_TIMING=\n\nwhile [[ \"$#\" -ne 0 ]]; do\n  case \"$1\" in\n  -T)\n    BATS_ENABLE_TIMING=\"-T\"\n    ;;\n  --base-path)\n    shift\n    normalize_base_path BASE_PATH \"$1\"\n    ;;\n  esac\n  shift\ndone\n\nupdate_count_column_width() {\n  count_column_width=$((${#count} * 2 + 2))\n  if [[ -n \"$BATS_ENABLE_TIMING\" ]]; then\n    # additional space for ' in %s sec'\n    count_column_width=$((count_column_width + ${#SECONDS} + 8))\n  fi\n  # also update dependent value\n  update_count_column_left\n}\n\nupdate_screen_width() {\n  screen_width=\"$(tput cols)\"\n  # also update dependent value\n  update_count_column_left\n}\n\nupdate_count_column_left() {\n  count_column_left=$((screen_width - count_column_width))\n}\n\n# avoid unset variables\ncount=0\nscreen_width=80\nupdate_count_column_width\nupdate_screen_width\n\ntrap update_screen_width WINCH\n\nbegin() {\n  line_backoff_count=0\n  go_to_column 0\n  update_count_column_width\n  buffer_with_truncation $((count_column_left - 1)) '   %s' \"$name\"\n  clear_to_end_of_line\n  go_to_column $count_column_left\n  if [[ -n \"$BATS_ENABLE_TIMING\" ]]; then\n    buffer \"%${#count}s/${count} in %s sec\" \"$index\" \"$SECONDS\"\n  else\n    buffer \"%${#count}s/${count}\" \"$index\"\n  fi\n  go_to_column 1\n}\n\nfinish_test() {\n  move_up $line_backoff_count\n  go_to_column 0\n  buffer \"$@\"\n  if [[ -n \"$BATS_ENABLE_TIMING\" ]]; then\n    set_color 2\n    buffer ' [%s]' \"$TIMING\"\n  fi\n  advance\n  move_down $(( line_backoff_count - 1 ))\n}\n\npass() {\n  TIMING=\"${1:-}\"\n  finish_test ' ✓ %s' \"$name\"\n  test_result=pass\n}\n\nskip() {\n  local reason=\"$1\"\n  if [[ -n \"$reason\" ]]; then\n    reason=\": $reason\"\n  fi\n  BATS_ENABLE_TIMING='' finish_test ' - %s (skipped%s)' \"$name\" \"$reason\"\n  test_result=skip\n}\n\nfail() {\n  set_color 1 bold\n  TIMING=\"${1:-}\"\n  finish_test ' ✗ %s' \"$name\"\n  test_result=fail\n}\n\nlog() {\n  case $test_result in\n    pass)\n    clear_color\n    ;;\n    fail)\n    set_color 1\n    ;;\n  esac\n  buffer '   %s\\n' \"$1\"\n  clear_color\n}\n\nsummary() {\n  if  [ \"$failures\" -eq 0 ] ; then\n    set_color 2 bold\n  else\n    set_color 1 bold\n  fi\n\n  buffer '\\n%d test' \"$count\"\n  if [[ \"$count\" -ne 1 ]]; then\n    buffer 's'\n  fi\n\n  buffer ', %d failure' \"$failures\"\n  if [[ \"$failures\" -ne 1 ]]; then\n    buffer 's'\n  fi\n\n  if [[ \"$skipped\" -gt 0 ]]; then\n    buffer ', %d skipped' \"$skipped\"\n  fi\n\n  not_run=$((count - passed - failures - skipped))\n  if [[ \"$not_run\" -gt 0 ]]; then\n    buffer ', %d not run' \"$not_run\"\n  fi\n\n  if [[ -n \"$BATS_ENABLE_TIMING\" ]]; then\n    buffer \" in $SECONDS seconds\"\n  fi\n\n  buffer '\\n'\n  clear_color\n}\n\nbuffer_with_truncation() {\n  local width=\"$1\"\n  shift\n  local string\n\n  # shellcheck disable=SC2059\n  printf -v 'string' -- \"$@\"\n\n  if [[ \"${#string}\" -gt \"$width\" ]]; then\n    buffer '%s...' \"${string:0:$((width - 4))}\"\n  else\n    buffer '%s' \"$string\"\n  fi\n}\n\nmove_up() {\n  if [[ $1 -gt 0 ]]; then # avoid moving if we got 0\n    buffer '\\x1B[%dA' \"$1\"\n  fi\n}\n\nmove_down() {\n  if [[ $1 -gt 0 ]]; then # avoid moving if we got 0\n    buffer '\\x1B[%dB' \"$1\"\n  fi\n}\n\ngo_to_column() {\n  local column=\"$1\"\n  buffer '\\x1B[%dG' $((column + 1))\n}\n\nclear_to_end_of_line() {\n  buffer '\\x1B[K'\n}\n\nadvance() {\n  clear_to_end_of_line\n  buffer '\\n'\n  clear_color\n}\n\nset_color() {\n  local color=\"$1\"\n  local weight=22\n\n  if [[ \"${2:-}\" == 'bold' ]]; then\n    weight=1\n  fi\n  buffer '\\x1B[%d;%dm' \"$((30 + color))\" \"$weight\"\n}\n\nclear_color() {\n  buffer '\\x1B[0m'\n}\n\n_buffer=\n\nbuffer() {\n  local content\n  # shellcheck disable=SC2059\n  printf -v content -- \"$@\"\n  _buffer+=\"$content\"\n}\n\nprefix_buffer_with() {\n  local old_buffer=\"$_buffer\"\n  _buffer=''\n  \"$@\"\n  _buffer=\"$_buffer$old_buffer\"\n}\n\nflush() {\n  printf '%s' \"$_buffer\"\n  _buffer=\n}\n\nfinish() {\n  flush\n  printf '\\n'\n}\n\ntrap finish EXIT\ntrap '' INT\n\nbats_tap_stream_plan() {\n  count=\"$1\"\n  index=0\n  passed=0\n  failures=0\n  skipped=0\n  name=\n  update_count_column_width\n}\n\nbats_tap_stream_begin() {\n  index=\"$1\"\n  name=\"$2\"\n  begin\n  flush\n}\n\nbats_tap_stream_ok() {\n  index=\"$1\"\n  ((++passed))\n  if [[ \"$1\" == \"--duration\" ]]; then\n    pass \"$2\"\n  else\n    pass\n  fi\n}\n\nbats_tap_stream_skipped() {\n  index=\"$1\"\n  ((++skipped))\n  skip \"$3\"\n}\n\nbats_tap_stream_not_ok() {\n  index=\"$1\"\n  ((++failures))\n  if [[ \"$1\" == \"--duration\" ]]; then\n    fail \"$2\"\n  else\n    fail\n  fi\n}\n\nbats_tap_stream_comment() { # <comment> <scope>\n  local scope=$2\n  # count the lines we printed after the begin text,\n  if [[ $line_backoff_count -eq 0 && $scope == begin ]]; then\n    # if this is the first line after begin, go down one line\n    buffer \"\\n\"\n    (( ++line_backoff_count )) # prefix-increment to avoid \"error\" due to returning 0\n  fi\n\n  (( ++line_backoff_count ))\n  (( line_backoff_count += ${#1} / screen_width)) # account for linebreaks due to length\n  log \"$1\"\n}\n\nbats_tap_stream_suite() {\n  #test_file=\"$1\"\n  line_backoff_count=0\n  index=\n  # indicate filename for failures\n  name=\"File $(remove_prefix \"$BASE_PATH\" \"$1\")\"\n}\n\nline_backoff_count=0\nbats_tap_stream_unknown() { # <full line> <scope>\n    local scope=$2\n    # count the lines we printed after the begin text, (or after suite, in case of syntax errors)\n    if [[ $line_backoff_count -eq 0 && ( $scope == begin ||  $scope == suite )]]; then\n      # if this is the first line after begin, go down one line\n      buffer \"\\n\"\n      (( ++line_backoff_count )) # prefix-increment to avoid \"error\" due to returning 0\n    fi\n\n    (( ++line_backoff_count ))\n    (( line_backoff_count += ${#1} / screen_width)) # account for linebreaks due to length\n    buffer \"%s\\n\" \"$1\"\n    flush\n}\n\nbats_parse_internal_extended_tap\n\nsummary\n"
  },
  {
    "path": "vendor/bats-core/libexec/bats-core/bats-format-tap",
    "content": "#!/usr/bin/env bash\nset -e\ntrap '' INT\n\n# shellcheck source=lib/bats-core/formatter.bash\nsource \"$BATS_ROOT/lib/bats-core/formatter.bash\"\n\nbats_tap_stream_plan() {\n    printf \"1..%d\\n\" \"$1\"\n}\n\nbats_tap_stream_begin() { #<test index> <test name>\n    :\n}\n\nbats_tap_stream_ok() { # [--duration <milliseconds] <test index> <test name>\n    if [[ \"$1\" == \"--duration\" ]]; then\n        printf \"ok %d %s # in %d ms\\n\" \"$3\" \"$4\" \"$2\"\n    else\n        printf \"ok %d %s\\n\" \"$1\" \"$2\"\n    fi\n}\n\nbats_tap_stream_not_ok() { # [--duration <milliseconds>] <test index> <test name>\n    if [[ \"$1\" == \"--duration\" ]]; then\n        printf \"not ok %d %s # in %d ms\\n\" \"$3\" \"$4\" \"$2\"\n    else\n        printf \"not ok %d %s\\n\" \"$1\" \"$2\"\n    fi\n}\n\nbats_tap_stream_skipped() { # <test index> <test name> <reason>\n    if [[ -n \"$3\" ]]; then\n        printf \"ok %d %s # skip %s\\n\" \"$1\" \"$2\" \"$3\"\n    else\n        printf \"ok %d %s # skip\\n\" \"$1\" \"$2\" \n    fi\n}\n\nbats_tap_stream_comment() { # <comment text without leading '# '>\n    printf \"# %s\\n\" \"$1\"\n}\n\nbats_tap_stream_suite() { # <file name>\n    :\n}\n\nbats_tap_stream_unknown() { # <full line>       \n    printf \"%s\\n\" \"$1\"\n}\n\nbats_parse_internal_extended_tap"
  },
  {
    "path": "vendor/bats-core/libexec/bats-core/bats-format-tap13",
    "content": "#!/usr/bin/env bash\nset -e\n\nwhile [[ \"$#\" -ne 0 ]]; do\n  case \"$1\" in\n  -T)\n    BATS_ENABLE_TIMING=\"-T\"\n    ;;\n  esac\n  shift\ndone\n\nheader_pattern='[0-9]+\\.\\.[0-9]+'\nIFS= read -r header\n\nif [[ \"$header\" =~ $header_pattern ]]; then\n  printf \"TAP version 13\\n\"\n  printf \"%s\\n\" \"$header\"\nelse\n  # If the first line isn't a TAP plan, print it and pass the rest through\n  printf '%s\\n' \"$header\"\n  exec cat\nfi\n\nyaml_block_open=''\nadd_yaml_entry() {\n  if [[ -z \"$yaml_block_open\" ]]; then\n    printf \"  ---\\n\"\n  fi\n  printf \"  %s: %s\\n\" \"$1\" \"$2\"\n  yaml_block_open=1\n}\n\nclose_previous_yaml_block() {\n  if [[ -n \"$yaml_block_open\" ]]; then\n    printf \"  ...\\n\"\n    yaml_block_open=''\n  fi\n}\n\ntrap '' INT\n\nwhile IFS= read -r line; do\n  case \"$line\" in\n  'begin '*) ;;\n  'ok '*)\n    close_previous_yaml_block\n    number_of_printed_log_lines_for_this_test_so_far=0\n    if [[ -n \"$BATS_ENABLE_TIMING\" ]]; then\n      timing_expr=\"(ok [0-9]+ .+) in ([0-9]+)ms$\"\n      if [[ \"$line\" =~ $timing_expr ]]; then\n        printf \"%s\\n\" \"${BASH_REMATCH[1]}\"\n        add_yaml_entry \"duration_ms\" \"${BASH_REMATCH[2]}\"\n      else\n        echo \"Could not match output line to timing regex: $line\" >&2\n        exit 1\n      fi\n    else\n      printf \"%s\\n\" \"${line}\"\n    fi\n    ;;\n  'not ok '*)\n    close_previous_yaml_block\n    number_of_printed_log_lines_for_this_test_so_far=0\n    timing_expr=\"not ok [0-9]+ (.)+ in ([0-9])+ms$\"\n    if [[ -n \"$BATS_ENABLE_TIMING\" ]]; then\n      if [[ \"$line\" =~ $timing_expr ]]; then\n        printf \"%s\\n\" \"${BATS_REMATCH[1]}\"\n        add_yaml_entry \"duration_ms\" \"${BASH_REMATCH[2]}\"\n      else\n        echo \"Could not match failure line to timing regex: $line\" >&2\n        exit 1\n      fi\n    else\n      printf \"%s\\n\" \"${line}\"\n    fi\n    ;;\n  '# '*)\n    if [[ $number_of_printed_log_lines_for_this_test_so_far -eq 0 ]]; then\n      add_yaml_entry \"message\" \"|\" # use a multiline string for this entry\n    fi\n    ((++number_of_printed_log_lines_for_this_test_so_far))\n    printf \"    %s\\n\" \"$(echo \"\\\"${line}\\\"\" | cut -b 3-)\"\n    ;;\n  'suite '*) ;;\n  esac\ndone\n# close the final block if there was one\nclose_previous_yaml_block\n"
  },
  {
    "path": "vendor/bats-core/libexec/bats-core/bats-preprocess",
    "content": "#!/usr/bin/env bash\nset -e\n\nbats_encode_test_name() {\n  local name=\"$1\"\n  local result='test_'\n  local hex_code\n\n  if [[ ! \"$name\" =~ [^[:alnum:]\\ _-] ]]; then\n    name=\"${name//_/-5f}\"\n    name=\"${name//-/-2d}\"\n    name=\"${name// /_}\"\n    result+=\"$name\"\n  else\n    local length=\"${#name}\"\n    local char i\n\n    for ((i = 0; i < length; i++)); do\n      char=\"${name:$i:1}\"\n      if [[ \"$char\" == ' ' ]]; then\n        result+='_'\n      elif [[ \"$char\" =~ [[:alnum:]] ]]; then\n        result+=\"$char\"\n      else\n        printf -v 'hex_code' -- '-%02x' \\'\"$char\"\n        result+=\"$hex_code\"\n      fi\n    done\n  fi\n\n  printf -v \"$2\" '%s' \"$result\"\n}\n\nBATS_TEST_PATTERN=\"^[[:blank:]]*@test[[:blank:]]+(.*[^[:blank:]])[[:blank:]]+\\{(.*)\\$\"\nBATS_TEST_PATTERN_COMMENT=\"[[:blank:]]*([^[:blank:]()]+)[[:blank:]]*\\(?\\)?[[:blank:]]+\\{[[:blank:]]+#[[:blank:]]*@test[[:blank:]]*\\$\"\n\ntest_file=\"$1\"\ntests=()\n{\n  while IFS= read -r line; do\n    line=\"${line//$'\\r'/}\"\n    if [[ \"$line\" =~ $BATS_TEST_PATTERN ]] || [[ \"$line\" =~ $BATS_TEST_PATTERN_COMMENT ]]; then\n      name=\"${BASH_REMATCH[1]#[\\'\\\"]}\"\n      name=\"${name%[\\'\\\"]}\"\n      body=\"${BASH_REMATCH[2]}\"\n      bats_encode_test_name \"$name\" 'encoded_name'\n      printf '%s() { bats_test_begin \"%s\"; %s\\n' \"${encoded_name:?}\" \"$name\" \"$body\" || :\n\n      if [[ -z \"$BATS_TEST_FILTER\" || \"$name\" =~ $BATS_TEST_FILTER ]]; then\n        tests+=(\"$encoded_name\")\n      fi\n    else\n      printf '%s\\n' \"$line\"\n    fi\n  done\n} <<<\"$(<\"$test_file\")\"$'\\n'\n\nfor test_name in \"${tests[@]}\"; do\n  printf 'bats_test_function %s\\n' \"$test_name\"\ndone\n"
  },
  {
    "path": "vendor/bats-core/man/Makefile",
    "content": "# Makefile\n#\n# bats-core manpages\n#\nRONN := ronn -W\nPAGES := bats.1 bats.7\nORG := bats-core\nMANUAL := 'Bash Automated Testing System'\nISOFMT := $(shell date -I)\nRM := rm -f\n\n.PHONY: all clean\n\nall: $(PAGES)\n\nbats.1: bats.1.ronn\n\t$(RONN) --date=$(ISOFMT) --manual=$(MANUAL) --organization=$(ORG) --roff $<\n\nbats.7: bats.7.ronn\n\t$(RONN) --date=$(ISOFMT) --manual=$(MANUAL) --organization=$(ORG) --roff $<\n\nclean:\n\t$(RM) $(PAGES)\n"
  },
  {
    "path": "vendor/bats-core/man/README.md",
    "content": "Bats man pages are generated with [Ronn](http://rtomayko.github.io/ronn/).\n\nAfter making changes to `bats.1.ronn` or `bats.7.ronn`, run `make` in\nthis directory to generate `bats.1` and `bats.7`. **Do not edit the\n`bats.1` or `bats.7` files directly.**\n"
  },
  {
    "path": "vendor/bats-core/man/bats.1",
    "content": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"BATS\" \"1\" \"November 2021\" \"bats-core\" \"Bash Automated Testing System\"\n.\n.SH \"NAME\"\n\\fBbats\\fR \\- Bash Automated Testing System\n.\n.SH \"SYNOPSIS\"\nUsage: bats [OPTIONS] \\fItests\\fR bats [\\-h | \\-v]\n.\n.P\n\\fItests\\fR is the path to a Bats test file, or the path to a directory containing Bats test files (ending with \"\\.bats\")\n.\n.SH \"DESCRIPTION\"\nBats is a TAP\\-compliant testing framework for Bash\\. It provides a simple way to verify that the UNIX programs you write behave as expected\\.\n.\n.P\nA Bats test file is a Bash script with special syntax for defining test cases\\. Under the hood, each test case is just a function with a description\\.\n.\n.P\nTest cases consist of standard shell commands\\. Bats makes use of Bash\\'s \\fBerrexit\\fR (\\fBset \\-e\\fR) option when running test cases\\. If every command in the test case exits with a \\fB0\\fR status code (success), the test passes\\. In this way, each line is an assertion of truth\\.\n.\n.P\nSee \\fBbats\\fR(7) for more information on writing Bats tests\\.\n.\n.SH \"RUNNING TESTS\"\nTo run your tests, invoke the \\fBbats\\fR interpreter with a path to a test file\\. The file\\'s test cases are run sequentially and in isolation\\. If all the test cases pass, \\fBbats\\fR exits with a \\fB0\\fR status code\\. If there are any failures, \\fBbats\\fR exits with a \\fB1\\fR status code\\.\n.\n.P\nYou can invoke the \\fBbats\\fR interpreter with multiple test file arguments, or with a path to a directory containing multiple \\fB\\.bats\\fR files\\. Bats will run each test file individually and aggregate the results\\. If any test case fails, \\fBbats\\fR exits with a \\fB1\\fR status code\\.\n.\n.SH \"OPTIONS\"\n.\n.IP \"\\(bu\" 4\n\\fB\\-c\\fR, \\fB\\-\\-count\\fR: Count the number of test cases without running any tests\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-code\\-quote\\-style <style>\\fR: A two character string of code quote delimiters or \\fBcustom\\fR which requires setting \\fB$BATS_BEGIN_CODE_QUOTE\\fR and \\fB$BATS_END_CODE_QUOTE\\fR\\. Can also be set via \\fB$BATS_CODE_QUOTE_STYLE\\fR\\.\n.\n.IP \"\\(bu\" 4\n\\fB\\-f\\fR, \\fB\\-\\-filter <regex>\\fR: Filter test cases by names matching the regular expression\n.\n.IP \"\\(bu\" 4\n\\fB\\-F\\fR, \\fB\\-\\-formatter <type>\\fR: Switch between formatters: pretty (default), tap (default w/o term), tap13, junit\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-gather\\-test\\-outputs\\-in <directory>\\fR: Gather the output of failing \\fIand\\fR passing tests as files in directory\n.\n.IP \"\\(bu\" 4\n\\fB\\-h\\fR, \\fB\\-\\-help\\fR: Display this help message\n.\n.IP \"\\(bu\" 4\n\\fB\\-j\\fR, \\fB\\-\\-jobs <jobs>\\fR: Number of parallel jobs (requires GNU parallel)\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-no\\-tempdir\\-cleanup\\fR: Preserve test output temporary directory\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-no\\-parallelize\\-across\\-files\\fR Serialize test file execution instead of running them in parallel (requires \\-\\-jobs >1)\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-no\\-parallelize\\-within\\-files\\fR Serialize test execution within files instead of running them in parallel (requires \\-\\-jobs >1)\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-report\\-formatter <type>\\fR: Switch between reporters (same options as \\-\\-formatter)\n.\n.IP \"\\(bu\" 4\n\\fB\\-o\\fR, \\fB\\-\\-output <dir>\\fR: Directory to write report files\n.\n.IP \"\\(bu\" 4\n\\fB\\-p\\fR, \\fB\\-\\-pretty\\fR: Shorthand for \"\\-\\-formatter pretty\"\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-print\\-output\\-on\\-failure\\fR: Automatically print the value of \\fB$output\\fR on failed tests\n.\n.IP \"\\(bu\" 4\n\\fB\\-r\\fR, \\fB\\-\\-recursive\\fR: Include tests in subdirectories\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-show\\-output\\-of\\-passing\\-tests\\fR Print output of passing tests\n.\n.IP \"\\(bu\" 4\n\\fB\\-t\\fR, \\fB\\-\\-tap\\fR: Shorthand for \"\\-\\-formatter tap\"\n.\n.IP \"\\(bu\" 4\n\\fB\\-T\\fR, \\fB\\-\\-timing\\fR: Add timing information to tests\n.\n.IP \"\\(bu\" 4\n\\fB\\-x\\fR, \\fB\\-\\-trace\\fR: Print test commands as they are executed (like \\fBset \\-x\\fR)\n.\n.IP \"\\(bu\" 4\n\\fB\\-\\-verbose\\-run\\fR: Make \\fBrun\\fR print \\fB$output\\fR by default\n.\n.IP \"\\(bu\" 4\n\\fB\\-v\\fR, \\fB\\-\\-version\\fR: Display the version number\n.\n.IP \"\" 0\n.\n.SH \"OUTPUT\"\nWhen you run Bats from a terminal, you\\'ll see output as each test is performed, with a check\\-mark next to the test\\'s name if it passes or an \"X\" if it fails\\.\n.\n.IP \"\" 4\n.\n.nf\n\n$ bats addition\\.bats\n ✓ addition using bc\n ✓ addition using dc\n\n2 tests, 0 failures\n.\n.fi\n.\n.IP \"\" 0\n.\n.P\nIf Bats is not connected to a terminal\\-\\-in other words, if you run it from a continuous integration system or redirect its output to a file\\-\\-the results are displayed in human\\-readable, machine\\-parsable TAP format\\. You can force TAP output from a terminal by invoking Bats with the \\fB\\-\\-tap\\fR option\\.\n.\n.IP \"\" 4\n.\n.nf\n\n$ bats \\-\\-tap addition\\.bats\n1\\.\\.2\nok 1 addition using bc\nok 2 addition using dc\n.\n.fi\n.\n.IP \"\" 0\n.\n.SH \"EXIT STATUS\"\nThe \\fBbats\\fR interpreter exits with a value of \\fB0\\fR if all test cases pass, or \\fB1\\fR if one or more test cases fail\\.\n.\n.SH \"SEE ALSO\"\nBats wiki: \\fIhttps://github\\.com/bats\\-core/bats\\-core/wiki/\\fR\n.\n.P\n\\fBbash\\fR(1), \\fBbats\\fR(7)\n.\n.SH \"COPYRIGHT\"\n(c) 2017\\-2021 bats\\-core organization\n.\n.br\n(c) 2011\\-2016 Sam Stephenson\n.\n.P\nBats is released under the terms of an MIT\\-style license\\.\n"
  },
  {
    "path": "vendor/bats-core/man/bats.1.ronn",
    "content": "bats(1) -- Bash Automated Testing System\n========================================\n\n\nSYNOPSIS\n--------\n\nUsage: bats [OPTIONS] <tests>\n       bats [-h | -v]\n\n  <tests> is the path to a Bats test file, or the path to a directory\n  containing Bats test files (ending with \".bats\")\n\n\nDESCRIPTION\n-----------\n\nBats is a TAP-compliant testing framework for Bash. It provides a simple\nway to verify that the UNIX programs you write behave as expected.\n\nA Bats test file is a Bash script with special syntax for defining\ntest cases. Under the hood, each test case is just a function with a\ndescription.\n\nTest cases consist of standard shell commands. Bats makes use of\nBash's `errexit` (`set -e`) option when running test cases. If every\ncommand in the test case exits with a `0` status code (success), the\ntest passes. In this way, each line is an assertion of truth.\n\nSee `bats`(7) for more information on writing Bats tests.\n\n\nRUNNING TESTS\n-------------\n\nTo run your tests, invoke the `bats` interpreter with a path to a test\nfile. The file's test cases are run sequentially and in isolation. If\nall the test cases pass, `bats` exits with a `0` status code. If there\nare any failures, `bats` exits with a `1` status code.\n\nYou can invoke the `bats` interpreter with multiple test file arguments,\nor with a path to a directory containing multiple `.bats` files. Bats\nwill run each test file individually and aggregate the results. If any\ntest case fails, `bats` exits with a `1` status code.\n\n\nOPTIONS\n-------\n\n  * `-c`, `--count`:\n    Count the number of test cases without running any tests\n  * `--code-quote-style <style>`:\n    A two character string of code quote delimiters or `custom`\n    which requires setting `$BATS_BEGIN_CODE_QUOTE` and \n    `$BATS_END_CODE_QUOTE`. \n    Can also be set via `$BATS_CODE_QUOTE_STYLE`.\n  * `-f`, `--filter <regex>`:\n    Filter test cases by names matching the regular expression\n  * `-F`, `--formatter <type>`:\n    Switch between formatters: pretty (default), tap (default w/o term), tap13, junit\n  * `--gather-test-outputs-in <directory>`:\n    Gather the output of failing *and* passing tests as files in directory\n  * `-h`, `--help`:\n    Display this help message\n  * `-j`, `--jobs <jobs>`:\n    Number of parallel jobs (requires GNU parallel)\n  * `--no-tempdir-cleanup`:\n    Preserve test output temporary directory\n  * `--no-parallelize-across-files`\n    Serialize test file execution instead of running them in parallel (requires --jobs >1)\n  * `--no-parallelize-within-files`\n    Serialize test execution within files instead of running them in parallel (requires --jobs >1)\n  * `--report-formatter <type>`:\n    Switch between reporters (same options as --formatter)\n  * `-o`, `--output <dir>`:\n    Directory to write report files\n  * `-p`, `--pretty`:\n    Shorthand for \"--formatter pretty\"\n  * `--print-output-on-failure`:\n    Automatically print the value of `$output` on failed tests\n  * `-r`, `--recursive`:\n    Include tests in subdirectories\n  * `--show-output-of-passing-tests`\n    Print output of passing tests\n  * `-t`, `--tap`:\n    Shorthand for \"--formatter tap\"\n  * `-T`, `--timing`:\n    Add timing information to tests\n  * `-x`, `--trace`:\n    Print test commands as they are executed (like `set -x`)\n  * `--verbose-run`:\n    Make `run` print `$output` by default\n  * `-v`, `--version`:\n    Display the version number\n\nOUTPUT\n------\n\nWhen you run Bats from a terminal, you'll see output as each test is\nperformed, with a check-mark next to the test's name if it passes or\nan \"X\" if it fails.\n\n    $ bats addition.bats\n     ✓ addition using bc\n     ✓ addition using dc\n\n    2 tests, 0 failures\n\nIf Bats is not connected to a terminal--in other words, if you run it\nfrom a continuous integration system or redirect its output to a\nfile--the results are displayed in human-readable, machine-parsable\nTAP format. You can force TAP output from a terminal by invoking Bats\nwith the `--tap` option.\n\n    $ bats --tap addition.bats\n    1..2\n    ok 1 addition using bc\n    ok 2 addition using dc\n\n\nEXIT STATUS\n-----------\n\nThe `bats` interpreter exits with a value of `0` if all test cases pass,\nor `1` if one or more test cases fail.\n\n\nSEE ALSO\n--------\n\nBats wiki: _https://github.com/bats\\-core/bats\\-core/wiki/_\n\n`bash`(1), `bats`(7)\n\n\nCOPYRIGHT\n---------\n\n(c) 2017-2021 bats-core organization<br/>\n(c) 2011-2016 Sam Stephenson\n\nBats is released under the terms of an MIT-style license.\n\n\n\n"
  },
  {
    "path": "vendor/bats-core/man/bats.7",
    "content": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"BATS\" \"7\" \"November 2021\" \"bats-core\" \"Bash Automated Testing System\"\n.\n.SH \"NAME\"\n\\fBbats\\fR \\- Bats test file format\n.\n.SH \"DESCRIPTION\"\nA Bats test file is a Bash script with special syntax for defining test cases\\. Under the hood, each test case is just a function with a description\\.\n.\n.IP \"\" 4\n.\n.nf\n\n#!/usr/bin/env bats\n\n@test \"addition using bc\" {\n  result=\"$(echo 2+2 | bc)\"\n  [ \"$result\" \\-eq 4 ]\n}\n\n@test \"addition using dc\" {\n  result=\"$(echo 2 2+p | dc)\"\n  [ \"$result\" \\-eq 4 ]\n}\n.\n.fi\n.\n.IP \"\" 0\n.\n.P\nEach Bats test file is evaluated n+1 times, where \\fIn\\fR is the number of test cases in the file\\. The first run counts the number of test cases, then iterates over the test cases and executes each one in its own process\\.\n.\n.SH \"THE RUN HELPER\"\nUsage: run [OPTIONS] [\\-\\-] <command\\.\\.\\.> Options: ! check for non zero exit code \\-\\fIN\\fR check that exit code is \\fIN\\fR \\-\\-separate\\-stderr split stderr and stdout \\-\\-keep\\-empty\\-lines retain emtpy lines in \\fB${lines[@]}\\fR/\\fB${stderr_lines[@]}\\fR\n.\n.P\nMany Bats tests need to run a command and then make assertions about its exit status and output\\. Bats includes a \\fBrun\\fR helper that invokes its arguments as a command, saves the exit status and output into special global variables, and (optionally) checks exit status against a given expected value\\. If successful, \\fBrun\\fR returns with a \\fB0\\fR status code so you can continue to make assertions in your test case\\.\n.\n.P\nFor example, let\\'s say you\\'re testing that the \\fBfoo\\fR command, when passed a nonexistent filename, exits with a \\fB1\\fR status code and prints an error message\\.\n.\n.IP \"\" 4\n.\n.nf\n\n@test \"invoking foo with a nonexistent file prints an error\" {\n  run \\-1 foo nonexistent_filename\n  [ \"$output\" = \"foo: no such file \\'nonexistent_filename\\'\" ]\n}\n.\n.fi\n.\n.IP \"\" 0\n.\n.P\nThe \\fB\\-1\\fR as first argument tells \\fBrun\\fR to expect 1 as an exit status, and to fail if the command exits with any other value\\. On failure, both actual and expected values will be displayed, along with the invoked command and its output:\n.\n.IP \"\" 4\n.\n.nf\n\n(in test file test\\.bats, line 2)\n `run \\-1 foo nonexistent_filename\\' failed, expected exit code 1, got 127\n.\n.fi\n.\n.IP \"\" 0\n.\n.P\nThis error indicates a possible problem with the installation or configuration of \\fBfoo\\fR; note that a simple \\fB[ $status != 0 ]\\fR test would not have caught this kind of failure\\.\n.\n.P\nThe \\fB$status\\fR variable contains the status code of the command, and the \\fB$output\\fR variable contains the combined contents of the command\\'s standard output and standard error streams\\.\n.\n.P\nA third special variable, the \\fB$lines\\fR array, is available for easily accessing individual lines of output\\. For example, if you want to test that invoking \\fBfoo\\fR without any arguments prints usage information on the first line:\n.\n.IP \"\" 4\n.\n.nf\n\n@test \"invoking foo without arguments prints usage\" {\n  run \\-1 foo\n  [ \"${lines[0]}\" = \"usage: foo <filename>\" ]\n}\n.\n.fi\n.\n.IP \"\" 0\n.\n.P\nBy default \\fBrun\\fR leaves out empty lines in \\fB${lines[@]}\\fR\\. Use \\fBrun \\-\\-keep\\-empty\\-lines\\fR to retain them\\.\n.\n.P\nAdditionally, you can use \\fB\\-\\-separate\\-stderr\\fR to split stdout and stderr into \\fB$output\\fR/\\fB$stderr\\fR and \\fB${lines[@]}\\fR/\\fB${stderr_lines[@]}\\fR\\.\n.\n.P\nAll additional parameters to run should come before the command\\. If you want to run a command that starts with \\fB\\-\\fR, prefix it with \\fB\\-\\-\\fR to prevent \\fBrun\\fR from parsing it as an option\\.\n.\n.SH \"THE LOAD COMMAND\"\nYou may want to share common code across multiple test files\\. Bats includes a convenient \\fBload\\fR command for sourcing a Bash source file relative to the location of the current test file\\. For example, if you have a Bats test in \\fBtest/foo\\.bats\\fR, the command\n.\n.IP \"\" 4\n.\n.nf\n\nload test_helper\n.\n.fi\n.\n.IP \"\" 0\n.\n.P\nwill source the script \\fBtest/test_helper\\.bash\\fR in your test file\\. This can be useful for sharing functions to set up your environment or load fixtures\\.\n.\n.SH \"THE SKIP COMMAND\"\nTests can be skipped by using the \\fBskip\\fR command at the point in a test you wish to skip\\.\n.\n.IP \"\" 4\n.\n.nf\n\n@test \"A test I don\\'t want to execute for now\" {\n  skip\n  run \\-0 foo\n}\n.\n.fi\n.\n.IP \"\" 0\n.\n.P\nOptionally, you may include a reason for skipping:\n.\n.IP \"\" 4\n.\n.nf\n\n@test \"A test I don\\'t want to execute for now\" {\n  skip \"This command will return zero soon, but not now\"\n  run \\-0 foo\n}\n.\n.fi\n.\n.IP \"\" 0\n.\n.P\nOr you can skip conditionally:\n.\n.IP \"\" 4\n.\n.nf\n\n@test \"A test which should run\" {\n  if [ foo != bar ]; then\n    skip \"foo isn\\'t bar\"\n  fi\n\n  run \\-0 foo\n}\n.\n.fi\n.\n.IP \"\" 0\n.\n.SH \"SETUP AND TEARDOWN FUNCTIONS\"\nYou can define special \\fBsetup\\fR and \\fBteardown\\fR functions which run before and after each test case, respectively\\. Use these to load fixtures, set up your environment, and clean up when you\\'re done\\.\n.\n.SH \"CODE OUTSIDE OF TEST CASES\"\nYou can include code in your test file outside of \\fB@test\\fR functions\\. For example, this may be useful if you want to check for dependencies and fail immediately if they\\'re not present\\. However, any output that you print in code outside of \\fB@test\\fR, \\fBsetup\\fR or \\fBteardown\\fR functions must be redirected to \\fBstderr\\fR (\\fB>&2\\fR)\\. Otherwise, the output may cause Bats to fail by polluting the TAP stream on \\fBstdout\\fR\\.\n.\n.SH \"SPECIAL VARIABLES\"\nThere are several global variables you can use to introspect on Bats tests:\n.\n.IP \"\\(bu\" 4\n\\fB$BATS_TEST_FILENAME\\fR is the fully expanded path to the Bats test file\\.\n.\n.IP \"\\(bu\" 4\n\\fB$BATS_TEST_DIRNAME\\fR is the directory in which the Bats test file is located\\.\n.\n.IP \"\\(bu\" 4\n\\fB$BATS_TEST_NAMES\\fR is an array of function names for each test case\\.\n.\n.IP \"\\(bu\" 4\n\\fB$BATS_TEST_NAME\\fR is the name of the function containing the current test case\\.\n.\n.IP \"\\(bu\" 4\n\\fB$BATS_TEST_DESCRIPTION\\fR is the description of the current test case\\.\n.\n.IP \"\\(bu\" 4\n\\fB$BATS_TEST_NUMBER\\fR is the (1\\-based) index of the current test case in the test file\\.\n.\n.IP \"\\(bu\" 4\n\\fB$BATS_SUITE_TEST_NUMBER\\fR is the (1\\-based) index of the current test case in the test suite (over all files)\\.\n.\n.IP \"\\(bu\" 4\n\\fB$BATS_TMPDIR\\fR is the base temporary directory used by bats to create its temporary files / directories\\. (default: \\fB$TMPDIR\\fR\\. If \\fB$TMPDIR\\fR is not set, \\fB/tmp\\fR is used\\.)\n.\n.IP \"\\(bu\" 4\n\\fB$BATS_RUN_TMPDIR\\fR is the location to the temporary directory used by bats to store all its internal temporary files during the tests\\. (default: \\fB$BATS_TMPDIR/bats\\-run\\-$BATS_ROOT_PID\\-XXXXXX\\fR)\n.\n.IP \"\\(bu\" 4\n\\fB$BATS_FILE_EXTENSION\\fR (default: \\fBbats\\fR) specifies the extension of test files that should be found when running a suite (via \\fBbats [\\-r] suite_folder/\\fR)\n.\n.IP \"\\(bu\" 4\n\\fB$BATS_SUITE_TMPDIR\\fR is a temporary directory common to all tests of a suite\\. Could be used to create files required by multiple tests\\.\n.\n.IP \"\\(bu\" 4\n\\fB$BATS_FILE_TMPDIR\\fR is a temporary directory common to all tests of a test file\\. Could be used to create files required by multiple tests in the same test file\\.\n.\n.IP \"\\(bu\" 4\n\\fB$BATS_TEST_TMPDIR\\fR is a temporary directory unique for each test\\. Could be used to create files required only for specific tests\\.\n.\n.IP \"\" 0\n.\n.SH \"SEE ALSO\"\n\\fBbash\\fR(1), \\fBbats\\fR(1)\n"
  },
  {
    "path": "vendor/bats-core/man/bats.7.ronn",
    "content": "bats(7) -- Bats test file format\n================================\n\n\nDESCRIPTION\n-----------\n\nA Bats test file is a Bash script with special syntax for defining\ntest cases. Under the hood, each test case is just a function with a\ndescription.\n\n    #!/usr/bin/env bats\n\n    @test \"addition using bc\" {\n      result=\"$(echo 2+2 | bc)\"\n      [ \"$result\" -eq 4 ]\n    }\n\n    @test \"addition using dc\" {\n      result=\"$(echo 2 2+p | dc)\"\n      [ \"$result\" -eq 4 ]\n    }\n\n\nEach Bats test file is evaluated n+1 times, where _n_ is the number of\ntest cases in the file. The first run counts the number of test cases,\nthen iterates over the test cases and executes each one in its own\nprocess.\n\n\nTHE RUN HELPER\n--------------\n\nUsage: run [OPTIONS] [--] <command...>\nOptions:\n       !        check for non zero exit code\n       -<N>     check that exit code is <N>\n       --separate-stderr\n                split stderr and stdout\n       --keep-empty-lines\n                retain emtpy lines in `${lines[@]}`/`${stderr_lines[@]}`\n\nMany Bats tests need to run a command and then make assertions about\nits exit status and output. Bats includes a `run` helper that invokes\nits arguments as a command, saves the exit status and output into\nspecial global variables, and (optionally) checks exit status against\na given expected value. If successful, `run` returns with a `0` status\ncode so you can continue to make assertions in your test case.\n\nFor example, let's say you're testing that the `foo` command, when\npassed a nonexistent filename, exits with a `1` status code and prints\nan error message.\n\n    @test \"invoking foo with a nonexistent file prints an error\" {\n      run -1 foo nonexistent_filename\n      [ \"$output\" = \"foo: no such file 'nonexistent_filename'\" ]\n    }\n\nThe `-1` as first argument tells `run` to expect 1 as an exit\nstatus, and to fail if the command exits with any other value.\nOn failure, both actual and expected values will be displayed,\nalong with the invoked command and its output:\n\n    (in test file test.bats, line 2)\n     `run -1 foo nonexistent_filename' failed, expected exit code 1, got 127\n\nThis error indicates a possible problem with the installation or\nconfiguration of `foo`; note that a simple `[ $status != 0 ]`\ntest would not have caught this kind of failure.\n\nThe `$status` variable contains the status code of the command, and\nthe `$output` variable contains the combined contents of the command's\nstandard output and standard error streams.\n\nA third special variable, the `$lines` array, is available for easily\naccessing individual lines of output. For example, if you want to test\nthat invoking `foo` without any arguments prints usage information on\nthe first line:\n\n    @test \"invoking foo without arguments prints usage\" {\n      run -1 foo\n      [ \"${lines[0]}\" = \"usage: foo <filename>\" ]\n    }\n\nBy default `run` leaves out empty lines in `${lines[@]}`. Use `run --keep-empty-lines` to retain them.\n\nAdditionally, you can use `--separate-stderr` to split stdout and stderr\ninto `$output`/`$stderr` and `${lines[@]}`/`${stderr_lines[@]}`.\n\nAll additional parameters to run should come before the command.\nIf you want to run a command that starts with `-`, prefix it with `--` to\nprevent `run` from parsing it as an option.\n\nTHE LOAD COMMAND\n----------------\n\nYou may want to share common code across multiple test files. Bats\nincludes a convenient `load` command for sourcing a Bash source file\nrelative to the location of the current test file. For example, if you\nhave a Bats test in `test/foo.bats`, the command\n\n    load test_helper\n\nwill source the script `test/test_helper.bash` in your test file. This\ncan be useful for sharing functions to set up your environment or load\nfixtures.\n\n\nTHE SKIP COMMAND\n----------------\n\nTests can be skipped by using the `skip` command at the point in a\ntest you wish to skip.\n\n    @test \"A test I don't want to execute for now\" {\n      skip\n      run -0 foo\n    }\n\nOptionally, you may include a reason for skipping:\n\n    @test \"A test I don't want to execute for now\" {\n      skip \"This command will return zero soon, but not now\"\n      run -0 foo\n    }\n\nOr you can skip conditionally:\n\n    @test \"A test which should run\" {\n      if [ foo != bar ]; then\n        skip \"foo isn't bar\"\n      fi\n\n      run -0 foo\n    }\n\n\nSETUP AND TEARDOWN FUNCTIONS\n----------------------------\n\nYou can define special `setup` and `teardown` functions which run\nbefore and after each test case, respectively. Use these to load\nfixtures, set up your environment, and clean up when you're done.\n\n\nCODE OUTSIDE OF TEST CASES\n--------------------------\n\nYou can include code in your test file outside of `@test` functions.\nFor example, this may be useful if you want to check for dependencies\nand fail immediately if they're not present. However, any output that\nyou print in code outside of `@test`, `setup` or `teardown` functions\nmust be redirected to `stderr` (`>&2`). Otherwise, the output may\ncause Bats to fail by polluting the TAP stream on `stdout`.\n\n\nSPECIAL VARIABLES\n-----------------\n\nThere are several global variables you can use to introspect on Bats\ntests:\n\n* `$BATS_TEST_FILENAME` is the fully expanded path to the Bats test\nfile.\n* `$BATS_TEST_DIRNAME` is the directory in which the Bats test file is\nlocated.\n* `$BATS_TEST_NAMES` is an array of function names for each test case.\n* `$BATS_TEST_NAME` is the name of the function containing the current\ntest case.\n* `$BATS_TEST_DESCRIPTION` is the description of the current test\ncase.\n* `$BATS_TEST_NUMBER` is the (1-based) index of the current test case\nin the test file.\n* `$BATS_SUITE_TEST_NUMBER` is the (1-based) index of the current test \n  case in the test suite (over all files).\n* `$BATS_TMPDIR` is the base temporary directory used by bats to create its\n  temporary files / directories.\n  (default: `$TMPDIR`. If `$TMPDIR` is not set, `/tmp` is used.)\n* `$BATS_RUN_TMPDIR` is the location to the temporary directory used by\n  bats to store all its internal temporary files during the tests.\n  (default: `$BATS_TMPDIR/bats-run-$BATS_ROOT_PID-XXXXXX`)\n* `$BATS_FILE_EXTENSION` (default: `bats`) specifies the extension of \ntest files that should be found when running a suite (via \n`bats [-r] suite_folder/`)\n* `$BATS_SUITE_TMPDIR` is a temporary directory common to all tests of a suite.\n  Could be used to create files required by multiple tests.\n* `$BATS_FILE_TMPDIR` is a temporary directory common to all tests of a test file.\n  Could be used to create files required by multiple tests in the same test file.\n* `$BATS_TEST_TMPDIR` is a temporary directory unique for each test.\n  Could be used to create files required only for specific tests.\n\n\nSEE ALSO\n--------\n\n`bash`(1), `bats`(1)\n"
  },
  {
    "path": "vendor/bats-core/package.json",
    "content": "{\n  \"name\": \"bats\",\n  \"version\": \"1.6.0\",\n  \"description\": \"Bash Automated Testing System\",\n  \"homepage\": \"https://github.com/bats-core/bats-core#readme\",\n  \"license\": \"MIT\",\n  \"author\": \"Sam Stephenson <sstephenson@gmail.com> (http://sstephenson.us/)\",\n  \"repository\": \"github:bats-core/bats-core\",\n  \"bugs\": \"https://github.com/bats-core/bats-core/issues\",\n  \"files\": [\n    \"bin\",\n    \"libexec\",\n    \"lib\",\n    \"man\",\n    \"install.sh\",\n    \"uninstall.sh\"\n  ],\n  \"directories\": {\n    \"bin\": \"bin\",\n    \"doc\": \"docs\",\n    \"man\": \"man\",\n    \"test\": \"test\"\n  },\n  \"scripts\": {\n    \"test\": \"bin/bats test\"\n  },\n  \"keywords\": [\n    \"bats\",\n    \"bash\",\n    \"shell\",\n    \"test\",\n    \"unit\"\n  ]\n}\n"
  },
  {
    "path": "vendor/bats-core/shellcheck.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\ntargets=()\nwhile IFS=  read -r -d $'\\0'; do\n    targets+=(\"$REPLY\")\ndone < <(\n  find . -type f \\( -name \\*.bash -o -name \\*.sh \\) -print0; \\\n  find . -name '*.bats' -not -name '*_no_shellcheck*' -print0; \\\n  find libexec -type f -print0;\n  find bin -type f -print0)\n\nif [[ $1 == --list ]]; then\n\tprintf \"%s\\n\" \"${targets[@]}\"\n\texit 0\nfi\n\nLC_ALL=C.UTF-8 shellcheck \"${targets[@]}\"\n\nexit $?\n"
  },
  {
    "path": "vendor/bats-core/test/bats.bats",
    "content": "#!/usr/bin/env bats\n\nsetup() {\n  load test_helper\n  fixtures bats\n}\n\n@test \"no arguments prints message and usage instructions\" {\n  run bats\n  [ $status -eq 1 ]\n  [ \"${lines[0]}\" == 'Error: Must specify at least one <test>' ]\n  [ \"${lines[1]%% *}\" == 'Usage:' ]\n}\n\n@test \"invalid option prints message and usage instructions\" {\n  run bats --invalid-option\n  [ $status -eq 1 ]\n  [ \"${lines[0]}\" == \"Error: Bad command line option '--invalid-option'\" ]\n  [ \"${lines[1]%% *}\" == 'Usage:' ]\n}\n\n@test \"-v and --version print version number\" {\n  run bats -v\n  [ $status -eq 0 ]\n  [ \"$(expr \"$output\" : \"Bats [0-9][0-9.]*\")\" -ne 0 ]\n}\n\n@test \"-h and --help print help\" {\n  run bats -h\n  [ $status -eq 0 ]\n  [ \"${#lines[@]}\" -gt 3 ]\n}\n\n@test \"invalid filename prints an error\" {\n  run bats nonexistent\n  [ $status -eq 1 ]\n  [ \"$(expr \"$output\" : \".*does not exist\")\" -ne 0 ]\n}\n\n@test \"empty test file runs zero tests\" {\n  run bats \"$FIXTURE_ROOT/empty.bats\"\n  [ $status -eq 0 ]\n  [ \"$output\" = \"1..0\" ]\n}\n\n@test \"one passing test\" {\n  run bats \"$FIXTURE_ROOT/passing.bats\"\n  [ $status -eq 0 ]\n  [ \"${lines[0]}\" = \"1..1\" ]\n  [ \"${lines[1]}\" = \"ok 1 a passing test\" ]\n}\n\n@test \"summary passing tests\" {\n  run filter_control_sequences bats -p \"$FIXTURE_ROOT/passing.bats\"\n  echo \"$output\"\n  [ $status -eq 0 ]\n  [ \"${lines[1]}\" = \"1 test, 0 failures\" ]\n}\n\n@test \"summary passing and skipping tests\" {\n  run filter_control_sequences bats -p \"$FIXTURE_ROOT/passing_and_skipping.bats\"\n  [ $status -eq 0 ]\n  [ \"${lines[3]}\" = \"3 tests, 0 failures, 2 skipped\" ]\n}\n\n@test \"tap passing and skipping tests\" {\n  run filter_control_sequences bats --formatter tap \"$FIXTURE_ROOT/passing_and_skipping.bats\"\n  [ $status -eq 0 ]\n  [ \"${lines[0]}\" = \"1..3\" ]\n  [ \"${lines[1]}\" = \"ok 1 a passing test\" ]\n  [ \"${lines[2]}\" = \"ok 2 a skipped test with no reason # skip\" ]\n  [ \"${lines[3]}\" = \"ok 3 a skipped test with a reason # skip for a really good reason\" ]\n}\n\n@test \"summary passing and failing tests\" {\n  run filter_control_sequences bats -p \"$FIXTURE_ROOT/failing_and_passing.bats\"\n  [ $status -eq 0 ]\n  [ \"${lines[4]}\" = \"2 tests, 1 failure\" ]\n}\n\n@test \"summary passing, failing and skipping tests\" {\n  run filter_control_sequences bats -p \"$FIXTURE_ROOT/passing_failing_and_skipping.bats\"\n  [ $status -eq 0 ]\n  [ \"${lines[5]}\" = \"3 tests, 1 failure, 1 skipped\" ]\n}\n\n@test \"tap passing, failing and skipping tests\" {\n  run filter_control_sequences bats --formatter tap \"$FIXTURE_ROOT/passing_failing_and_skipping.bats\"\n  [ $status -eq 0 ]\n  [ \"${lines[0]}\" = \"1..3\" ]\n  [ \"${lines[1]}\" = \"ok 1 a passing test\" ]\n  [ \"${lines[2]}\" = \"ok 2 a skipping test # skip\" ]\n  [ \"${lines[3]}\" = \"not ok 3 a failing test\" ]\n}\n\n@test \"BATS_CWD is correctly set to PWD as validated by bats_trim_filename\" {\n  local trimmed\n  bats_trim_filename \"$PWD/foo/bar\" 'trimmed'\n  printf 'ACTUAL: %s\\n' \"$trimmed\" >&2\n  [ \"$trimmed\" = 'foo/bar' ]\n}\n\n@test \"one failing test\" {\n  run bats \"$FIXTURE_ROOT/failing.bats\"\n  [ $status -eq 1 ]\n  [ \"${lines[0]}\" = '1..1' ]\n  [ \"${lines[1]}\" = 'not ok 1 a failing test' ]\n  [ \"${lines[2]}\" = \"# (in test file $RELATIVE_FIXTURE_ROOT/failing.bats, line 4)\" ]\n  [ \"${lines[3]}\" = \"#   \\`eval \\\"( exit \\${STATUS:-1} )\\\"' failed\" ]\n}\n\n@test \"one failing and one passing test\" {\n  run bats \"$FIXTURE_ROOT/failing_and_passing.bats\"\n  [ $status -eq 1 ]\n  [ \"${lines[0]}\" = '1..2' ]\n  [ \"${lines[1]}\" = 'not ok 1 a failing test' ]\n  [ \"${lines[2]}\" = \"# (in test file $RELATIVE_FIXTURE_ROOT/failing_and_passing.bats, line 2)\" ]\n  [ \"${lines[3]}\" = \"#   \\`false' failed\" ]\n  [ \"${lines[4]}\" = 'ok 2 a passing test' ]\n}\n\n@test \"failing test with significant status\" {\n  STATUS=2 run bats \"$FIXTURE_ROOT/failing.bats\"\n  [ $status -eq 1 ]\n  [ \"${lines[3]}\" = \"#   \\`eval \\\"( exit \\${STATUS:-1} )\\\"' failed with status 2\" ]\n}\n\n@test \"failing helper function logs the test case's line number\" {\n  run bats \"$FIXTURE_ROOT/failing_helper.bats\"\n  [ $status -eq 1 ]\n  [ \"${lines[1]}\" = 'not ok 1 failing helper function' ]\n  [ \"${lines[2]}\" = \"# (from function \\`failing_helper' in file $RELATIVE_FIXTURE_ROOT/test_helper.bash, line 6,\" ]\n  [ \"${lines[3]}\" = \"#  in test file $RELATIVE_FIXTURE_ROOT/failing_helper.bats, line 5)\" ]\n  [ \"${lines[4]}\" = \"#   \\`failing_helper' failed\" ]\n}\n\n@test \"failing bash condition logs correct line number\" {\n  run bats \"$FIXTURE_ROOT/failing_with_bash_cond.bats\"\n  [ \"$status\" -eq 1 ]\n  [ \"${#lines[@]}\" -eq 4 ]\n  [ \"${lines[1]}\" = 'not ok 1 a failing test' ]\n  [ \"${lines[2]}\" = \"# (in test file $RELATIVE_FIXTURE_ROOT/failing_with_bash_cond.bats, line 4)\" ]\n  [ \"${lines[3]}\" = \"#   \\`[[ 1 == 2 ]]' failed\" ]\n}\n\n@test \"failing bash expression logs correct line number\" {\n  run bats \"$FIXTURE_ROOT/failing_with_bash_expression.bats\"\n  [ \"$status\" -eq 1 ]\n  [ \"${#lines[@]}\" -eq 4 ]\n  [ \"${lines[1]}\" = 'not ok 1 a failing test' ]\n  [ \"${lines[2]}\" = \"# (in test file $RELATIVE_FIXTURE_ROOT/failing_with_bash_expression.bats, line 3)\" ]\n  [ \"${lines[3]}\" = \"#   \\`(( 1 == 2 ))' failed\" ]\n}\n\n@test \"failing negated command logs correct line number\" {\n  run bats \"$FIXTURE_ROOT/failing_with_negated_command.bats\"\n  [ \"$status\" -eq 1 ]\n  [ \"${#lines[@]}\" -eq 4 ]\n  [ \"${lines[1]}\" = 'not ok 1 a failing test' ]\n  [ \"${lines[2]}\" = \"# (in test file $RELATIVE_FIXTURE_ROOT/failing_with_negated_command.bats, line 3)\" ]\n  [ \"${lines[3]}\" = \"#   \\`! true' failed\" ]\n}\n\n@test \"test environments are isolated\" {\n  run bats \"$FIXTURE_ROOT/environment.bats\"\n  [ $status -eq 0 ]\n}\n\n@test \"setup is run once before each test\" {\n  # shellcheck disable=SC2031,SC2030\n  export BATS_TEST_SUITE_TMPDIR=\"${BATS_TEST_TMPDIR}\"\n  run bats \"$FIXTURE_ROOT/setup.bats\"\n  [ $status -eq 0 ]\n  run cat \"$BATS_TEST_SUITE_TMPDIR/setup.log\"\n  [ ${#lines[@]} -eq 3 ]\n}\n\n@test \"teardown is run once after each test, even if it fails\" {\n  # shellcheck disable=SC2031,SC2030\n  export BATS_TEST_SUITE_TMPDIR=\"${BATS_TEST_TMPDIR}\"\n  run bats \"$FIXTURE_ROOT/teardown.bats\"\n  [ $status -eq 1 ]\n  run cat \"$BATS_TEST_SUITE_TMPDIR/teardown.log\"\n  [ ${#lines[@]} -eq 3 ]\n}\n\n@test \"setup failure\" {\n  run bats \"$FIXTURE_ROOT/failing_setup.bats\"\n  [ $status -eq 1 ]\n  [ \"${lines[1]}\" = 'not ok 1 truth' ]\n  [ \"${lines[2]}\" = \"# (from function \\`setup' in test file $RELATIVE_FIXTURE_ROOT/failing_setup.bats, line 2)\" ]\n  [ \"${lines[3]}\" = \"#   \\`false' failed\" ]\n}\n\n@test \"passing test with teardown failure\" {\n  PASS=1 run bats \"$FIXTURE_ROOT/failing_teardown.bats\"\n  [ $status -eq 1 ]\n  echo \"$output\"\n  [ \"${lines[1]}\" = 'not ok 1 truth' ]\n  [ \"${lines[2]}\" = \"# (from function \\`teardown' in test file $RELATIVE_FIXTURE_ROOT/failing_teardown.bats, line 2)\" ]\n  [ \"${lines[3]}\" = \"#   \\`eval \\\"( exit \\${STATUS:-1} )\\\"' failed\" ]\n}\n\n@test \"failing test with teardown failure\" {\n  PASS=0 run bats \"$FIXTURE_ROOT/failing_teardown.bats\"\n  [ $status -eq 1 ]\n  [ \"${lines[1]}\" =  'not ok 1 truth' ]\n  [ \"${lines[2]}\" =  \"# (in test file $RELATIVE_FIXTURE_ROOT/failing_teardown.bats, line 6)\" ]\n  [ \"${lines[3]}\" = $'#   `[ \"$PASS\" = 1 ]\\' failed' ]\n}\n\n@test \"teardown failure with significant status\" {\n  PASS=1 STATUS=2 run bats \"$FIXTURE_ROOT/failing_teardown.bats\"\n  [ $status -eq 1 ]\n  [ \"${lines[3]}\" = \"#   \\`eval \\\"( exit \\${STATUS:-1} )\\\"' failed with status 2\" ]\n}\n\n@test \"failing test file outside of BATS_CWD\" {\n  cd \"${BATS_TEST_TMPDIR}\"\n  run bats \"$FIXTURE_ROOT/failing.bats\"\n  [ $status -eq 1 ]\n  [ \"${lines[2]}\" = \"# (in test file $FIXTURE_ROOT/failing.bats, line 4)\" ]\n}\n\n@test \"output is discarded for passing tests and printed for failing tests\" {\n  run bats \"$FIXTURE_ROOT/output.bats\"\n  [ $status -eq 1 ]\n  [ \"${lines[6]}\"  = '# failure stdout 1' ]\n  [ \"${lines[7]}\"  = '# failure stdout 2' ]\n  [ \"${lines[11]}\" = '# failure stderr' ]\n}\n\n@test \"-c prints the number of tests\" {\n  run bats -c \"$FIXTURE_ROOT/empty.bats\"\n  [ $status -eq 0 ]\n  [ \"$output\" = 0 ]\n\n  run bats -c \"$FIXTURE_ROOT/output.bats\"\n  [ $status -eq 0 ]\n  [ \"$output\" = 4 ]\n}\n\n@test \"dash-e is not mangled on beginning of line\" {\n  run bats \"$FIXTURE_ROOT/intact.bats\"\n  [ $status -eq 0 ]\n  [ \"${lines[1]}\" = \"ok 1 dash-e on beginning of line\" ]\n}\n\n@test \"dos line endings are stripped before testing\" {\n  run bats \"$FIXTURE_ROOT/dos_line_no_shellcheck.bats\"\n  [ $status -eq 0 ]\n}\n\n@test \"test file without trailing newline\" {\n  run bats \"$FIXTURE_ROOT/without_trailing_newline.bats\"\n  [ $status -eq 0 ]\n  [ \"${lines[1]}\" = \"ok 1 truth\" ]\n}\n\n@test \"skipped tests\" {\n  run bats \"$FIXTURE_ROOT/skipped.bats\"\n  [ $status -eq 0 ]\n  [ \"${lines[1]}\" = \"ok 1 a skipped test # skip\" ]\n  [ \"${lines[2]}\" = \"ok 2 a skipped test with a reason # skip a reason\" ]\n}\n\n@test \"skipped test with parens (pretty formatter)\" {\n  run bats --pretty \"$FIXTURE_ROOT/skipped_with_parens.bats\"\n  [ $status -eq 0 ]\n\n  # Some systems (Alpine, for example) seem to emit an extra whitespace into\n  # entries in the 'lines' array when a carriage return is present from the\n  # pretty formatter.  This is why a '+' is used after the 'skipped' note.\n  [[ \"${lines[*]}\" =~ \"- a skipped test with parentheses in the reason (skipped: \"+\"a reason (with parentheses))\" ]]\n}\n\n@test \"extended syntax\" {\n  emulate_bats_env\n  run bats-exec-suite -x \"$FIXTURE_ROOT/failing_and_passing.bats\"\n  echo \"$output\"\n  [ $status -eq 1 ]\n  [ \"${lines[1]}\" = \"suite $FIXTURE_ROOT/failing_and_passing.bats\" ]\n  [ \"${lines[2]}\" = 'begin 1 a failing test' ]\n  [ \"${lines[3]}\" = 'not ok 1 a failing test' ]\n  [ \"${lines[6]}\" = 'begin 2 a passing test' ]\n  [ \"${lines[7]}\" = 'ok 2 a passing test' ]\n}\n\n@test \"timing syntax\" {\n  run bats -T \"$FIXTURE_ROOT/failing_and_passing.bats\"\n  echo \"$output\"\n  [ $status -eq 1 ]\n  regex='not ok 1 a failing test in [0-9]+ms'\n  [[ \"${lines[1]}\" =~ $regex ]]\n  regex='ok 2 a passing test in [0-9]+ms'\n  [[ \"${lines[4]}\" =~ $regex ]]\n}\n\n@test \"extended timing syntax\" {\n  emulate_bats_env\n  run bats-exec-suite -x -T \"$FIXTURE_ROOT/failing_and_passing.bats\"\n  echo \"$output\"\n  [ $status -eq 1 ]\n  regex=\"not ok 1 a failing test in [0-9]+ms\"\n  [ \"${lines[2]}\" = 'begin 1 a failing test' ]\n  [[ \"${lines[3]}\" =~ $regex ]]\n  [ \"${lines[6]}\" = 'begin 2 a passing test' ]\n  regex=\"ok 2 a passing test in [0-9]+ms\"\n  [[ \"${lines[7]}\" =~ $regex ]]\n}\n\n@test \"time is greater than 0ms for long test\" {\n  emulate_bats_env\n  run bats-exec-suite -x -T \"$FIXTURE_ROOT/run_long_command.bats\"\n  echo \"$output\"\n  [ $status -eq 0 ]\n  regex=\"ok 1 run long command in [1-9][0-9]*ms\"\n  [[ \"${lines[3]}\" =~ $regex ]]\n}\n\n@test \"pretty and tap formats\" {\n  run bats --formatter tap \"$FIXTURE_ROOT/passing.bats\"\n  tap_output=\"$output\"\n  [ $status -eq 0 ]\n\n  run bats --pretty \"$FIXTURE_ROOT/passing.bats\"\n  pretty_output=\"$output\"\n  [ $status -eq 0 ]\n\n  [ \"$tap_output\" != \"$pretty_output\" ]\n}\n\n@test \"pretty formatter bails on invalid tap\" {\n  run bats-format-pretty < <(printf \"This isn't TAP!\\nGood day to you\\n\")\n  [ $status -eq 0 ]\n  [ \"${lines[0]}\" = \"This isn't TAP!\" ]\n  [ \"${lines[1]}\" = \"Good day to you\" ]\n}\n\n@test \"single-line tests\" {\n  run bats \"$FIXTURE_ROOT/single_line_no_shellcheck.bats\"\n  [ $status -eq 1 ]\n  [ \"${lines[1]}\" =  'ok 1 empty' ]\n  [ \"${lines[2]}\" =  'ok 2 passing' ]\n  [ \"${lines[3]}\" =  'ok 3 input redirection' ]\n  [ \"${lines[4]}\" =  'not ok 4 failing' ]\n  [ \"${lines[5]}\" =  \"# (in test file $RELATIVE_FIXTURE_ROOT/single_line_no_shellcheck.bats, line 9)\" ]\n  [ \"${lines[6]}\" = $'#   `@test \"failing\" { false; }\\' failed' ]\n}\n\n@test \"testing IFS not modified by run\" {\n  run bats \"$FIXTURE_ROOT/loop_keep_IFS.bats\"\n  [ $status -eq 0 ]\n  [ \"${lines[1]}\" = \"ok 1 loop_func\" ]\n}\n\n@test \"expand variables in test name\" {\n  SUITE='test/suite' run bats \"$FIXTURE_ROOT/expand_var_in_test_name.bats\"\n  [ $status -eq 0 ]\n  [ \"${lines[1]}\" = \"ok 1 test/suite: test with variable in name\" ]\n}\n\n@test \"handle quoted and unquoted test names\" {\n  run bats \"$FIXTURE_ROOT/quoted_and_unquoted_test_names_no_shellcheck.bats\"\n  [ $status -eq 0 ]\n  [ \"${lines[1]}\" = \"ok 1 single-quoted name\" ]\n  [ \"${lines[2]}\" = \"ok 2 double-quoted name\" ]\n  [ \"${lines[3]}\" = \"ok 3 unquoted name\" ]\n}\n\n@test 'ensure compatibility with unofficial Bash strict mode' {\n  local expected='ok 1 unofficial Bash strict mode conditions met'\n\n  if [[ -n \"$BATS_NUMBER_OF_PARALLEL_JOBS\" ]]; then\n    if [[ -z \"$BATS_NO_PARALLELIZE_ACROSS_FILES\" ]]; then\n      type -p parallel &>/dev/null || skip \"Don't check file parallelized without GNU parallel\"\n    fi\n    (type -p flock &>/dev/null || type -p shlock &>/dev/null) || skip \"Don't check parallelized without flock/shlock \"\n  fi\n\n  # PATH required for windows\n  # HOME required to avoid error from GNU Parallel\n  # Run Bats under SHELLOPTS=nounset (recursive `set -u`) to catch \n  # as many unset variable accesses as possible.\n  run env - \\\n          \"PATH=$PATH\" \\\n          \"HOME=$HOME\" \\\n          \"BATS_NO_PARALLELIZE_ACROSS_FILES=$BATS_NO_PARALLELIZE_ACROSS_FILES\" \\\n          \"BATS_NUMBER_OF_PARALLEL_JOBS=$BATS_NUMBER_OF_PARALLEL_JOBS\" \\\n          SHELLOPTS=nounset \\\n      \"${BATS_ROOT}/bin/bats\" \"$FIXTURE_ROOT/unofficial_bash_strict_mode.bats\"\n  if [[ \"$status\" -ne 0 || \"${lines[1]}\" != \"$expected\" ]]; then\n    cat <<END_OF_ERR_MSG\n\nThis test failed because the Bats internals are violating one of the\nconstraints imposed by:\n\n--------\n$(< \"$FIXTURE_ROOT/unofficial_bash_strict_mode.bash\")\n--------\n\nSee:\n- https://github.com/sstephenson/bats/issues/171\n- http://redsymbol.net/articles/unofficial-bash-strict-mode/\n\nIf there is no error output from the test fixture, run the following to\ndebug the problem:\n\n  $ SHELLOPTS=nounset bats $RELATIVE_FIXTURE_ROOT/unofficial_bash_strict_mode.bats\n\nIf there's no error output even with this command, make sure you're using the\nlatest version of Bash, as versions before 4.1-alpha may not produce any error\noutput for unset variable accesses.\n\nIf there's no output even when running the latest Bash, the problem may reside\nin the DEBUG trap handler. A particularly sneaky issue is that in Bash before\n4.1-alpha, an expansion of an empty array, e.g. \"\\${FOO[@]}\", is considered\nan unset variable access. The solution is to add a size check before the\nexpansion, e.g. [[ \"\\${#FOO[@]}\" -ne 0 ]].\n\nEND_OF_ERR_MSG\n    emit_debug_output && return 1\n  fi\n}\n\n@test \"parse @test lines with various whitespace combinations\" {\n  run bats \"$FIXTURE_ROOT/whitespace_no_shellcheck.bats\"\n  [ $status -eq 0 ]\n  [ \"${lines[1]}\" = 'ok 1 no extra whitespace' ]\n  [ \"${lines[2]}\" = 'ok 2 tab at beginning of line' ]\n  [ \"${lines[3]}\" = 'ok 3 tab before description' ]\n  [ \"${lines[4]}\" = 'ok 4 tab before opening brace' ]\n  [ \"${lines[5]}\" = 'ok 5 tabs at beginning of line and before description' ]\n  [ \"${lines[6]}\" = 'ok 6 tabs at beginning, before description, before brace' ]\n  [ \"${lines[7]}\" = 'ok 7 extra whitespace around single-line test' ]\n  [ \"${lines[8]}\" = 'ok 8 no extra whitespace around single-line test' ]\n  [ \"${lines[9]}\" = 'ok 9 parse unquoted name between extra whitespace' ]\n  [ \"${lines[10]}\" = 'ok 10 {' ]  # unquoted single brace is a valid description\n  [ \"${lines[11]}\" = 'ok 11 ' ]   # empty name from single quote\n}\n\n@test \"duplicate tests error and generate a warning on stderr\" {\n  run bats --tap \"$FIXTURE_ROOT/duplicate-tests_no_shellcheck.bats\"\n  [ $status -eq 1 ]\n\n  local expected='Error: Duplicate test name(s) in file '\n  expected+=\"\\\"${FIXTURE_ROOT}/duplicate-tests_no_shellcheck.bats\\\": test_gizmo_test\"\n\n  printf 'expected: \"%s\"\\n' \"$expected\" >&2\n  printf 'actual:   \"%s\"\\n' \"${lines[0]}\" >&2\n  [ \"${lines[0]}\" = \"$expected\" ]\n\n  printf 'num lines: %d\\n' \"${#lines[*]}\" >&2\n  [ \"${#lines[*]}\" = \"1\" ]\n}\n\n@test \"sourcing a nonexistent file in setup produces error output\" {\n  run bats \"$FIXTURE_ROOT/source_nonexistent_file_in_setup.bats\"\n  [ $status -eq 1 ]\n  [ \"${lines[1]}\" = 'not ok 1 sourcing nonexistent file fails in setup' ]\n  [ \"${lines[2]}\" = \"# (from function \\`setup' in test file $RELATIVE_FIXTURE_ROOT/source_nonexistent_file_in_setup.bats, line 3)\" ]\n  [ \"${lines[3]}\" = \"#   \\`source \\\"nonexistent file\\\"' failed\" ]\n}\n\n@test \"referencing unset parameter in setup produces error output\" {\n  run bats \"$FIXTURE_ROOT/reference_unset_parameter_in_setup.bats\"\n  [ $status -eq 1 ]\n  [ \"${lines[1]}\" = 'not ok 1 referencing unset parameter fails in setup' ]\n  [ \"${lines[2]}\" = \"# (from function \\`setup' in test file $RELATIVE_FIXTURE_ROOT/reference_unset_parameter_in_setup.bats, line 4)\" ]\n  [ \"${lines[3]}\" = \"#   \\`echo \\\"\\$unset_parameter\\\"' failed\" ]\n}\n\n@test \"sourcing a nonexistent file in test produces error output\" {\n  run bats \"$FIXTURE_ROOT/source_nonexistent_file.bats\"\n  [ $status -eq 1 ]\n  [ \"${lines[1]}\" = 'not ok 1 sourcing nonexistent file fails' ]\n  [ \"${lines[2]}\" = \"# (in test file $RELATIVE_FIXTURE_ROOT/source_nonexistent_file.bats, line 3)\" ]\n  [ \"${lines[3]}\" = \"#   \\`source \\\"nonexistent file\\\"' failed\" ]\n}\n\n@test \"referencing unset parameter in test produces error output\" {\n  run bats \"$FIXTURE_ROOT/reference_unset_parameter.bats\"\n  [ $status -eq 1 ]\n  [ \"${lines[1]}\" = 'not ok 1 referencing unset parameter fails' ]\n  [ \"${lines[2]}\" = \"# (in test file $RELATIVE_FIXTURE_ROOT/reference_unset_parameter.bats, line 4)\" ]\n  [ \"${lines[3]}\" = \"#   \\`echo \\\"\\$unset_parameter\\\"' failed\" ]\n}\n\n@test \"sourcing a nonexistent file in teardown produces error output\" {\n  run bats \"$FIXTURE_ROOT/source_nonexistent_file_in_teardown.bats\"\n  [ $status -eq 1 ]\n  [ \"${lines[1]}\" = 'not ok 1 sourcing nonexistent file fails in teardown' ]\n  [ \"${lines[2]}\" = \"# (from function \\`teardown' in test file $RELATIVE_FIXTURE_ROOT/source_nonexistent_file_in_teardown.bats, line 3)\" ]\n  [ \"${lines[3]}\" = \"#   \\`source \\\"nonexistent file\\\"' failed\" ]\n}\n\n@test \"referencing unset parameter in teardown produces error output\" {\n  run bats \"$FIXTURE_ROOT/reference_unset_parameter_in_teardown.bats\"\n  [ $status -eq 1 ]\n  [ \"${lines[1]}\" = 'not ok 1 referencing unset parameter fails in teardown' ]\n  [ \"${lines[2]}\" = \"# (from function \\`teardown' in test file $RELATIVE_FIXTURE_ROOT/reference_unset_parameter_in_teardown.bats, line 4)\" ]\n  [ \"${lines[3]}\" = \"#   \\`echo \\\"\\$unset_parameter\\\"' failed\" ]\n}\n\n@test \"execute exported function without breaking failing test output\" {\n  exported_function() { return 0; }\n  export -f exported_function\n  run bats \"$FIXTURE_ROOT/exported_function.bats\"\n  [ $status -eq 1 ]\n  [ \"${lines[0]}\" = \"1..1\" ]\n  [ \"${lines[1]}\" = \"not ok 1 failing test\" ]\n  [ \"${lines[2]}\" = \"# (in test file $RELATIVE_FIXTURE_ROOT/exported_function.bats, line 7)\" ]\n  [ \"${lines[3]}\" = \"#   \\`false' failed\" ]\n  [ \"${lines[4]}\" = \"# a='exported_function'\" ]\n}\n\n@test \"output printed even when no final newline\" {\n  run bats \"$FIXTURE_ROOT/no-final-newline.bats\"\n  printf 'num lines: %d\\n' \"${#lines[@]}\" >&2\n  printf 'LINE: %s\\n' \"${lines[@]}\" >&2\n  [ \"$status\" -eq 1 ]\n  [ \"${#lines[@]}\" -eq 11 ]\n  [ \"${lines[1]}\" = 'not ok 1 error in test' ]\n  [ \"${lines[2]}\" = \"# (in test file $RELATIVE_FIXTURE_ROOT/no-final-newline.bats, line 3)\" ]\n  [ \"${lines[3]}\" = \"#   \\`false' failed\" ]\n  [ \"${lines[4]}\" = '# foo' ]\n  [ \"${lines[5]}\" = '# bar' ]\n  [ \"${lines[6]}\" = 'not ok 2 test function returns nonzero' ]\n  [ \"${lines[7]}\" = \"# (in test file $RELATIVE_FIXTURE_ROOT/no-final-newline.bats, line 8)\" ]\n  [ \"${lines[8]}\" = \"#   \\`return 1' failed\" ]\n  [ \"${lines[9]}\" = '# foo' ]\n  [ \"${lines[10]}\" = '# bar' ]\n}\n\n@test \"run tests which consume stdin (see #197)\" {\n  run bats \"$FIXTURE_ROOT/read_from_stdin.bats\"\n  [ \"$status\" -eq 0 ]\n  [[ \"${lines[0]}\" == \"1..3\" ]]\n  [[ \"${lines[1]}\" == \"ok 1 test 1\" ]]\n  [[ \"${lines[2]}\" == \"ok 2 test 2 with\tTAB in name\" ]]\n  [[ \"${lines[3]}\" == \"ok 3 test 3\" ]]\n}\n\n@test \"report correct line on unset variables\" {\n  LANG=C run bats \"$FIXTURE_ROOT/unbound_variable.bats\"\n  [ \"$status\" -eq 1 ]\n  [ \"${#lines[@]}\" -eq 9 ]\n  [ \"${lines[1]}\" = 'not ok 1 access unbound variable' ]\n  [ \"${lines[2]}\" = \"# (in test file $RELATIVE_FIXTURE_ROOT/unbound_variable.bats, line 9)\" ]\n  [ \"${lines[3]}\" = \"#   \\`foo=\\$unset_variable' failed\" ]\n  # shellcheck disable=SC2076\n  [[ \"${lines[4]}\" =~ \".bats: line 9:\" ]]\n  [ \"${lines[5]}\" = 'not ok 2 access second unbound variable' ]\n  [ \"${lines[6]}\" = \"# (in test file $RELATIVE_FIXTURE_ROOT/unbound_variable.bats, line 15)\" ]\n  [ \"${lines[7]}\" = \"#   \\`foo=\\$second_unset_variable' failed\" ]\n  # shellcheck disable=SC2076\n  [[ \"${lines[8]}\" =~ \".bats: line 15:\" ]]\n}\n\n@test \"report correct line on external function calls\" {\n  run bats \"$FIXTURE_ROOT/external_function_calls.bats\"\n  [ \"$status\" -eq 1 ]\n\n  expectedNumberOfTests=12\n  linesPerTest=5\n\n  outputOffset=1\n  currentErrorLine=9\n\n  for t in $(seq $expectedNumberOfTests); do\n    # shellcheck disable=SC2076\n    [[ \"${lines[$outputOffset]}\" =~ \"not ok $t \" ]]\n\n    [[ \"${lines[$outputOffset]}\" =~ stackdepth=([0-9]+) ]]\n    stackdepth=\"${BASH_REMATCH[1]}\"\n    case \"${stackdepth}\" in\n      1)\n        [ \"${lines[$((outputOffset + 1))]}\" = \"# (in test file $RELATIVE_FIXTURE_ROOT/external_function_calls.bats, line $currentErrorLine)\" ]\n        outputOffset=$((outputOffset + 3))\n        ;;\n      2)\n        [[ \"${lines[$((outputOffset + 1))]}\" =~ ^'# (from function `'.*\\'' in file '.*'/test_helper.bash, line '[0-9]+,$ ]]\n        [ \"${lines[$((outputOffset + 2))]}\" = \"#  in test file $RELATIVE_FIXTURE_ROOT/external_function_calls.bats, line $currentErrorLine)\" ]\n        outputOffset=$((outputOffset + 4))\n        ;;\n      *)\n        printf 'error: stackdepth=%s not implemented\\n' \"${stackdepth}\" >&2\n        return 1\n    esac\n    currentErrorLine=$((currentErrorLine + linesPerTest))\n  done\n}\n\n@test \"test count validator catches mismatch and returns non zero\" {\n  # shellcheck source=lib/bats-core/validator.bash\n  source \"$BATS_ROOT/lib/bats-core/validator.bash\"\n  export -f bats_test_count_validator\n  run bash -c \"echo $'1..1\\n' | bats_test_count_validator\"\n  [[ $status -ne 0 ]]\n\n  run bash -c \"echo $'1..1\\nok 1\\nok 2' | bats_test_count_validator\"\n  [[ $status -ne 0 ]]\n\n  run bash -c \"echo $'1..1\\nok 1' | bats_test_count_validator\"\n  [[ $status -eq 0 ]]\n}\n\n@test \"running the same file twice runs its tests twice without errors\" {\n  run bats \"$FIXTURE_ROOT/passing.bats\" \"$FIXTURE_ROOT/passing.bats\"\n  echo \"$output\"\n  [[ $status -eq 0 ]]\n  [[ \"${lines[0]}\" == \"1..2\" ]] # got 2x1 tests\n}\n\n@test \"Don't use unbound variables inside bats (issue #340)\" {\n  run bats \"$FIXTURE_ROOT/set_-eu_in_setup_and_teardown.bats\"\n  echo \"$output\"\n  [[ \"${lines[0]}\" == \"1..4\" ]]\n  [[ \"${lines[1]}\" == \"ok 1 skipped test # skip\" ]]\n  [[ \"${lines[2]}\" == \"ok 2 skipped test with reason # skip reason\" ]]\n  [[ \"${lines[3]}\" == \"ok 3 passing test\" ]]\n  [[ \"${lines[4]}\" == \"not ok 4 failing test\" ]]\n  [[ \"${lines[5]}\" == \"# (in test file $RELATIVE_FIXTURE_ROOT/set_-eu_in_setup_and_teardown.bats, line 22)\" ]]\n  [[ \"${lines[6]}\" == \"#   \\`false' failed\" ]]\n  [[ \"${#lines[@]}\" -eq 7 ]]\n}\n\n@test \"filenames with tab can be used\" {\n  [[ \"$OSTYPE\" == \"linux\"* ]] || skip \"FS cannot deal with tabs in filenames\"\n\n  cp \"${FIXTURE_ROOT}/tab in filename.bats\" \"${BATS_TEST_TMPDIR}/tab\"$'\\t'\"in filename.bats\"\n  bats \"${BATS_TEST_TMPDIR}/tab\"$'\\t'\"in filename.bats\"\n}\n\n@test \"each file is evaluated n+1 times\" {\n  # shellcheck disable=SC2031,SC2030\n  export TEMPFILE=\"$BATS_TEST_TMPDIR/$BATS_TEST_NAME.log\"\n  run bats \"$FIXTURE_ROOT/evaluation_count/\"\n\n  cat \"$TEMPFILE\"\n\n  run grep \"file1\" \"$TEMPFILE\"\n  [[ ${#lines[@]} -eq 2 ]]\n\n  run grep \"file2\" \"$TEMPFILE\"\n  [[ ${#lines[@]} -eq 3 ]]\n}\n\n@test \"Don't hang on CTRL-C (issue #353)\" {\n  if [[ \"$BATS_NUMBER_OF_PARALLEL_JOBS\" -gt 1 ]]; then\n    skip \"Aborts don't work in parallel mode\"\n  fi\n  load 'concurrent-coordination'\n  # shellcheck disable=SC2031,SC2030\n  export SINGLE_USE_LATCH_DIR=\"${BATS_TEST_TMPDIR}\"\n\n  # guarantee that background processes get their own process group -> pid=pgid\n  set -m\n  bats \"$FIXTURE_ROOT/hang_in_test.bats\" & # don't block execution, or we cannot send signals\n  SUBPROCESS_PID=$!\n\n  single-use-latch::wait hang_in_test 1\n\n  # emulate CTRL-C by sending SIGINT to the whole process group\n  kill -SIGINT -- -$SUBPROCESS_PID\n\n  sleep 1 # wait for the signal to be acted upon\n\n  # when the process is gone, we cannot deliver a signal anymore, getting non-zero from kill\n  run kill -0 -- -$SUBPROCESS_PID\n  [[ $status -ne 0 ]] \\\n    || (kill -9 -- -$SUBPROCESS_PID; false)\n    #   ^ kill the process for good when SIGINT failed,\n    #     to avoid waiting endlessly for stuck children to finish\n}\n\n@test \"test comment style\" {\n  run bats \"$FIXTURE_ROOT/comment_style.bats\"\n  [ $status -eq 0 ]\n  [ \"${lines[0]}\" = '1..6' ]\n  [ \"${lines[1]}\" = 'ok 1 should_be_found' ]\n  [ \"${lines[2]}\" = 'ok 2 should_be_found_with_trailing_whitespace' ]\n  [ \"${lines[3]}\" = 'ok 3 should_be_found_with_parens' ]\n  [ \"${lines[4]}\" = 'ok 4 should_be_found_with_parens_and_whitespace' ]\n  [ \"${lines[5]}\" = 'ok 5 should_be_found_with_function_and_parens' ]\n  [ \"${lines[6]}\" = 'ok 6 should_be_found_with_function_parens_and_whitespace' ]\n}\n\n@test \"test works even if PATH is reset\" {\n  run bats \"$FIXTURE_ROOT/update_path_env.bats\"\n  [ \"$status\" -eq 1 ]\n  [ \"${lines[4]}\" = \"# /usr/local/bin:/usr/bin:/bin\" ]\n}\n\n@test \"Test nounset does not trip up bats' internals (see #385)\" {\n  # don't export nounset within this file or we might trip up the testsuite itself,\n  # getting bad diagnostics\n  run bash -c \"set -o nounset; export SHELLOPTS; bats --tap '$FIXTURE_ROOT/passing.bats'\"\n  echo \"$output\"\n  [ \"${lines[0]}\" = \"1..1\" ]\n  [ \"${lines[1]}\" = \"ok 1 a passing test\" ]\n  [ ${#lines[@]} = 2 ]\n}\n\n@test \"run tmpdir is cleaned up by default\" {\n  TEST_TMPDIR=\"${BATS_TEST_TMPDIR}/$BATS_TEST_NAME\"\n  bats --tempdir \"$TEST_TMPDIR\" \"$FIXTURE_ROOT/passing.bats\"\n\n  [ ! -d \"$TEST_TMPDIR\" ]\n}\n\n@test \"run tmpdir is not cleanup up with --no-cleanup-tempdir\" {\n  TEST_TMPDIR=\"${BATS_TEST_TMPDIR}/$BATS_TEST_NAME\"\n  bats --tempdir \"$TEST_TMPDIR\" --no-tempdir-cleanup \"$FIXTURE_ROOT/passing.bats\"\n\n  [ -d \"$TEST_TMPDIR\" ]\n\n  # should also find preprocessed files!\n  [ \"$(find \"$TEST_TMPDIR\" -name '*.src' | wc -l)\" -eq 1 ]\n}\n\n@test \"All formatters (except cat) implement the callback interface\" {\n  cd \"$BATS_ROOT/libexec/bats-core/\"\n  for formatter in bats-format-*; do\n    # the cat formatter is not expected to implement this interface\n    if [[ \"$formatter\" == *\"bats-format-cat\" ]]; then\n      continue\n    fi\n    tested_at_least_one_formatter=1\n    echo \"Formatter: ${formatter}\"\n    # the replay should be possible without errors\n    \"$formatter\" >/dev/null <<EOF\n1..1\nsuite \"$BATS_FIXTURE_ROOT/failing.bats\"\nbegin 1 test_a_failing_test\nnot ok 1 a failing test\n# (in test file test/fixtures/bats/failing.bats, line 4)\n#   \\`eval \"( exit ${STATUS:-1} )\"' failed\nbegin 2 test_a_successful_test\nok 2 a succesful test\nunknown line\nEOF\n  done\n\n  [[ -n \"$tested_at_least_one_formatter\" ]]\n}\n\n@test \"run should exit if tmpdir exist\" {\n  local dir\n  dir=$(mktemp -d \"${BATS_RUN_TMPDIR}/BATS_RUN_TMPDIR_TEST.XXXXXX\")\n  run bats --tempdir \"${dir}\" \"$FIXTURE_ROOT/passing.bats\"\n  [ \"$status\" -eq 1 ]\n  [ \"${lines[0]}\" == \"Error: BATS_RUN_TMPDIR (${dir}) already exists\" ]\n  [ \"${lines[1]}\" == \"Reusing old run directories can lead to unexpected results ... aborting!\" ]\n}\n\n@test \"run should exit if TMPDIR can't be created\" {\n  local dir\n  dir=$(mktemp \"${BATS_RUN_TMPDIR}/BATS_RUN_TMPDIR_TEST.XXXXXX\")\n  run bats --tempdir \"${dir}\" \"$FIXTURE_ROOT/passing.bats\"\n  [ \"$status\" -eq 1 ]\n  [ \"${lines[1]}\" == \"Error: Failed to create BATS_RUN_TMPDIR (${dir})\" ]\n}\n\n@test \"Fail if BATS_TMPDIR does not exist or is not writable\" {\n  # shellcheck disable=SC2031,SC2030\n  export TMPDIR\n  TMPDIR=$(mktemp -u \"${BATS_RUN_TMPDIR}/donotexist.XXXXXX\")\n  run bats \"$FIXTURE_ROOT/BATS_TMPDIR.bats\"\n  echo \"$output\"\n  [ \"$status\" -eq 1 ]\n  [ \"${lines[0]}\" = \"Error: BATS_TMPDIR (${TMPDIR}) does not exist or is not a directory\" ]\n}\n\n@test \"Setting BATS_TMPDIR is ignored\" {\n  unset TMPDIR # ensure we don't have a predefined value\n  expected=\"/tmp\" run bats \"$FIXTURE_ROOT/BATS_TMPDIR.bats\"\n  echo \"$output\"\n  [ \"$status\" -eq 0 ]\n  BATS_TMPDIR=\"${BATS_RUN_TMPDIR}\" expected=\"/tmp\" run bats \"$FIXTURE_ROOT/BATS_TMPDIR.bats\"\n  [ \"$status\" -eq 0 ]\n}\n\n@test \"Parallel mode works on MacOS with over subscription (issue #433)\" {\n  type -p parallel &>/dev/null || skip \"--jobs requires GNU parallel\"\n  (type -p flock &>/dev/null || type -p shlock &>/dev/null) || skip \"--jobs requires flock/shlock\"\n  run bats -j 2 \"$FIXTURE_ROOT/issue-433\"\n\n  [ \"$status\" -eq 0 ]\n  [[ \"$output\" != *\"No such file or directory\"* ]] || exit 1 # ensure failures are detected with old bash\n}\n\n@test \"Failure in free code (see #399)\" {\n  run bats --tap \"$FIXTURE_ROOT/failure_in_free_code.bats\"\n  echo \"$output\"\n  [ \"$status\" -ne 0 ]\n  [ \"${lines[0]}\" == 1..1 ]\n  [ \"${lines[1]}\" == 'not ok 1 setup_file failed' ]\n  [ \"${lines[2]}\" == \"# (from function \\`helper' in file $RELATIVE_FIXTURE_ROOT/failure_in_free_code.bats, line 4,\" ]\n  [ \"${lines[3]}\" == \"#  in test file $RELATIVE_FIXTURE_ROOT/failure_in_free_code.bats, line 7)\" ]\n  [ \"${lines[4]}\" == \"#   \\`helper' failed\" ]\n}\n\n@test \"CTRL-C aborts and fails the current test\" {\n  if [[ \"$BATS_NUMBER_OF_PARALLEL_JOBS\" -gt 1 ]]; then\n    skip \"Aborts don't work in parallel mode\"\n  fi\n  \n  # shellcheck disable=SC2031,SC2030\n  export TEMPFILE=\"$BATS_TEST_TMPDIR/$BATS_TEST_NAME.log\"\n\n  # guarantee that background processes get their own process group -> pid=pgid\n  set -m\n  \n  load 'concurrent-coordination'\n  # shellcheck disable=SC2031,SC2030\n  export SINGLE_USE_LATCH_DIR=\"${BATS_SUITE_TMPDIR}\"\n  # we cannot use run for a background task, so we have to store the output for later\n  bats \"$FIXTURE_ROOT/hang_in_test.bats\" --tap  >\"$TEMPFILE\" 2>&1 & # don't block execution, or we cannot send signals\n\n  SUBPROCESS_PID=$!\n\n  single-use-latch::wait hang_in_test 1 10 || (cat \"$TEMPFILE\"; false) # still forward output on timeout\n\n  # emulate CTRL-C by sending SIGINT to the whole process group\n  kill -SIGINT -- -$SUBPROCESS_PID || (cat \"$TEMPFILE\"; false)\n\n  # the test suite must be marked as failed!\n  wait $SUBPROCESS_PID && return 1\n\n  run cat \"$TEMPFILE\"\n  echo \"$output\"\n\n  [ \"${lines[1]}\" == \"not ok 1 test\" ]\n  # due to scheduling the exact line will vary but we should exit with 130\n  [[ \"${lines[3]}\" == *\"failed with status 130\" ]] || false\n  [ \"${lines[4]}\" == \"# Received SIGINT, aborting ...\" ]\n}\n\n@test \"CTRL-C aborts and fails the current run\" {\n  if [[ \"$BATS_NUMBER_OF_PARALLEL_JOBS\" -gt 1 ]]; then\n    skip \"Aborts don't work in parallel mode\"\n  fi\n\n  # shellcheck disable=SC2031,2030\n  export TEMPFILE=\"$BATS_TEST_TMPDIR/$BATS_TEST_NAME.log\"\n\n  # guarantee that background processes get their own process group -> pid=pgid\n  set -m\n  \n  load 'concurrent-coordination'\n  # shellcheck disable=SC2031,SC2030\n  export SINGLE_USE_LATCH_DIR=\"${BATS_SUITE_TMPDIR}\"\n  # we cannot use run for a background task, so we have to store the output for later\n  bats \"$FIXTURE_ROOT/hang_in_run.bats\" --tap  >\"$TEMPFILE\" 2>&1 & # don't block execution, or we cannot send signals\n\n  SUBPROCESS_PID=$!\n  \n  single-use-latch::wait hang_in_run 1 10\n\n  # emulate CTRL-C by sending SIGINT to the whole process group\n  kill -SIGINT -- -$SUBPROCESS_PID || (cat \"$TEMPFILE\"; false)\n\n  # the test suite must be marked as failed!\n  wait $SUBPROCESS_PID && return 1\n\n  run cat \"$TEMPFILE\"\n  \n  [ \"${lines[1]}\" == \"not ok 1 test\" ]\n  # due to scheduling the exact line will vary but we should exit with 130\n  [[ \"${lines[3]}\" == *\"failed with status 130\" ]] || false\n  [ \"${lines[4]}\" == \"# Received SIGINT, aborting ...\" ]\n}\n\n@test \"CTRL-C aborts and fails after run\" {\n  if [[ \"$BATS_NUMBER_OF_PARALLEL_JOBS\" -gt 1 ]]; then\n    skip \"Aborts don't work in parallel mode\"\n  fi\n\n  # shellcheck disable=SC2031,2030\n  export TEMPFILE=\"$BATS_TEST_TMPDIR/$BATS_TEST_NAME.log\"\n\n  # guarantee that background processes get their own process group -> pid=pgid\n  set -m\n  \n  load 'concurrent-coordination'\n  # shellcheck disable=SC2031,SC2030\n  export SINGLE_USE_LATCH_DIR=\"${BATS_SUITE_TMPDIR}\"\n  # we cannot use run for a background task, so we have to store the output for later\n  bats \"$FIXTURE_ROOT/hang_after_run.bats\" --tap  >\"$TEMPFILE\" 2>&1 & # don't block execution, or we cannot send signals\n\n  SUBPROCESS_PID=$!\n  \n  single-use-latch::wait hang_after_run 1 10\n\n  # emulate CTRL-C by sending SIGINT to the whole process group\n  kill -SIGINT -- -$SUBPROCESS_PID || (cat \"$TEMPFILE\"; false)\n\n  # the test suite must be marked as failed!\n  wait $SUBPROCESS_PID && return 1\n\n  run cat \"$TEMPFILE\"\n  \n  [ \"${lines[1]}\" == \"not ok 1 test\" ]\n  # due to scheduling the exact line will vary but we should exit with 130\n  [[ \"${lines[3]}\" == *\"failed with status 130\" ]] || false\n  [ \"${lines[4]}\" == \"# Received SIGINT, aborting ...\" ]\n}\n\n@test \"CTRL-C aborts and fails the current teardown\" {\n  if [[ \"$BATS_NUMBER_OF_PARALLEL_JOBS\" -gt 1 ]]; then\n    skip \"Aborts don't work in parallel mode\"\n  fi\n\n  # shellcheck disable=SC2031,SC2030\n  export TEMPFILE=\"$BATS_TEST_TMPDIR/$BATS_TEST_NAME.log\"\n\n  # guarantee that background processes get their own process group -> pid=pgid\n  set -m\n  \n  load 'concurrent-coordination'\n  # shellcheck disable=SC2031,SC2030\n  export SINGLE_USE_LATCH_DIR=\"${BATS_SUITE_TMPDIR}\"\n  # we cannot use run for a background task, so we have to store the output for later\n  bats \"$FIXTURE_ROOT/hang_in_teardown.bats\" --tap  >\"$TEMPFILE\" 2>&1 & # don't block execution, or we cannot send signals\n\n  SUBPROCESS_PID=$!\n  \n  single-use-latch::wait hang_in_teardown 1 10\n\n  # emulate CTRL-C by sending SIGINT to the whole process group\n  kill -SIGINT -- -$SUBPROCESS_PID || (cat \"$TEMPFILE\"; false)\n\n  # the test suite must be marked as failed!\n  wait $SUBPROCESS_PID && return 1\n\n  run cat \"$TEMPFILE\"\n  echo \"$output\"\n\n  [ \"${lines[1]}\" == \"not ok 1 empty\" ]\n  # due to scheduling the exact line will vary but we should exit with 130\n  [[ \"${lines[3]}\" == *\"failed with status 130\" ]] || false\n  [ \"${lines[4]}\" == \"# Received SIGINT, aborting ...\" ]\n}\n\n@test \"CTRL-C aborts and fails the current setup_file\" {\n  if [[ \"$BATS_NUMBER_OF_PARALLEL_JOBS\" -gt 1 ]]; then\n    skip \"Aborts don't work in parallel mode\"\n  fi\n\n  # shellcheck disable=SC2031,SC2030\n  export TEMPFILE=\"$BATS_TEST_TMPDIR/$BATS_TEST_NAME.log\"\n\n  # guarantee that background processes get their own process group -> pid=pgid\n  set -m\n  \n  load 'concurrent-coordination'\n  # shellcheck disable=SC2031,SC2030\n  export SINGLE_USE_LATCH_DIR=\"${BATS_SUITE_TMPDIR}\"\n  # we cannot use run for a background task, so we have to store the output for later\n  bats \"$FIXTURE_ROOT/hang_in_setup_file.bats\" --tap  >\"$TEMPFILE\" 2>&1 & # don't block execution, or we cannot send signals\n\n  SUBPROCESS_PID=$!\n  \n  single-use-latch::wait hang_in_setup_file 1 10\n\n  # emulate CTRL-C by sending SIGINT to the whole process group\n  kill -SIGINT -- -$SUBPROCESS_PID || (cat \"$TEMPFILE\"; false)\n\n  # the test suite must be marked as failed!\n  wait $SUBPROCESS_PID && return 1\n\n  run cat \"$TEMPFILE\"\n  echo \"$output\"\n\n  [ \"${lines[1]}\" == \"not ok 1 setup_file failed\" ]\n  # due to scheduling the exact line will vary but we should exit with 130\n  [[ \"${lines[3]}\" == *\"failed with status 130\" ]] || false\n  [ \"${lines[4]}\" == \"# Received SIGINT, aborting ...\" ]\n}\n\n@test \"CTRL-C aborts and fails the current teardown_file\" {\n  if [[ \"$BATS_NUMBER_OF_PARALLEL_JOBS\" -gt 1 ]]; then\n    skip \"Aborts don't work in parallel mode\"\n  fi\n  # shellcheck disable=SC2031\n  export TEMPFILE=\"${BATS_TEST_TMPDIR}/$BATS_TEST_NAME.log\"\n\n  # guarantee that background processes get their own process group -> pid=pgid\n  set -m\n  \n  load 'concurrent-coordination'\n  # shellcheck disable=SC2031\n  export SINGLE_USE_LATCH_DIR=\"${BATS_SUITE_TMPDIR}\"\n  # we cannot use run for a background task, so we have to store the output for later\n  bats \"$FIXTURE_ROOT/hang_in_teardown_file.bats\" --tap  >\"$TEMPFILE\" 2>&1 & # don't block execution, or we cannot send signals\n\n  SUBPROCESS_PID=$!\n  \n  single-use-latch::wait hang_in_teardown_file 1 10\n\n  # emulate CTRL-C by sending SIGINT to the whole process group\n  kill -SIGINT -- -$SUBPROCESS_PID || (cat \"$TEMPFILE\"; false)\n\n  # the test suite must be marked as failed!\n  wait $SUBPROCESS_PID && return 1\n\n  run cat \"$TEMPFILE\"\n  echo \"$output\"\n\n  [ \"${lines[0]}\" == \"1..1\" ]\n  [ \"${lines[1]}\" == \"ok 1 empty\" ]\n  [ \"${lines[2]}\" == \"not ok 2 teardown_file failed\" ]\n  # due to scheduling the exact line will vary but we should exit with 130\n  [[ \"${lines[4]}\" == *\"failed with status 130\" ]] || false\n  [ \"${lines[5]}\" == \"# Received SIGINT, aborting ...\" ]\n  [ \"${lines[6]}\" == \"# bats warning: Executed 2 instead of expected 1 tests\" ]\n}\n\n\n@test \"single star in output is not treated as a glob\" {\n  star(){ echo '*'; }\n  \n  run star\n  [ \"${lines[0]}\" = '*' ]\n}\n\n@test \"multiple stars in output are not treated as a glob\" {\n  stars(){ echo '**'; }\n  \n  run stars\n  [ \"${lines[0]}\" = '**' ]\n}\n\n@test \"ensure all folders are shellchecked\" {\n  if [[ ! -f \"$BATS_ROOT/shellcheck.sh\" ]]; then\n    skip \"\\$BATS_ROOT/shellcheck.sh is required for this test\"\n  fi\n  cd \"$BATS_ROOT\"\n  run \"./shellcheck.sh\" --list\n  echo \"$output\"\n\n  grep bin/bats <<< \"$output\"\n  grep contrib/ <<< \"$output\"\n  grep docker/ <<< \"$output\"\n  grep lib/bats-core/ <<< \"$output\"\n  grep libexec/bats-core/ <<< \"$output\"\n  grep test/fixtures <<< \"$output\"\n  grep install.sh <<< \"$output\"\n}\n\n@test \"BATS_RUN_COMMAND: test content of variable\" {\n  run bats -v\n  [[ \"${BATS_RUN_COMMAND}\" == \"bats -v\" ]]\n  run bats \"${BATS_TEST_DESCRIPTION}\"\n  echo \"$BATS_RUN_COMMAND\"\n  [[ \"$BATS_RUN_COMMAND\" == \"bats BATS_RUN_COMMAND: test content of variable\" ]]\n}\n\n@test \"pretty formatter summary is colorized red on failure\" {\n  run -1 bats --pretty \"$FIXTURE_ROOT/failing.bats\"\n  \n  [ \"${lines[3]}\" == $'\\033[0m\\033[31;1m' ] # TODO: avoid checking for the leading reset too\n  [ \"${lines[4]}\" == '1 test, 1 failure' ]\n  [ \"${lines[5]}\" == $'\\033[0m' ]\n}\n\n@test \"pretty formatter summary is colorized green on success\" {\n  run -0 bats --pretty \"$FIXTURE_ROOT/passing.bats\"\n\n  [ \"${lines[1]}\" == $'\\033[0m\\033[32;1m' ] # TODO: avoid checking for the leading reset too\n  [ \"${lines[2]}\" == '1 test, 0 failures' ]\n  [ \"${lines[3]}\" == $'\\033[0m' ]\n}\n\n@test \"--print-output-on-failure works as expected\" {\n  run bats --print-output-on-failure --show-output-of-passing-tests \"$FIXTURE_ROOT/print_output_on_failure.bats\"\n  [ \"${lines[0]}\" == '1..3' ]\n  [ \"${lines[1]}\" == 'ok 1 no failure prints no output' ]\n  # ^ no output despite --show-output-of-passing-tests, because there is no failure\n  [ \"${lines[2]}\" == 'not ok 2 failure prints output' ]\n  [ \"${lines[3]}\" == \"# (in test file $RELATIVE_FIXTURE_ROOT/print_output_on_failure.bats, line 6)\" ]\n  [ \"${lines[4]}\" == \"#   \\`run -1 echo \\\"fail hard\\\"' failed, expected exit code 1, got 0\" ]\n  [ \"${lines[5]}\" == '# Last output:' ]\n  [ \"${lines[6]}\" == '# fail hard' ]\n  [ \"${lines[7]}\" == 'not ok 3 empty output on failure' ]\n  [ \"${lines[8]}\" == \"# (in test file $RELATIVE_FIXTURE_ROOT/print_output_on_failure.bats, line 10)\" ]\n  [ \"${lines[9]}\" == \"#   \\`false' failed\" ]\n  [ ${#lines[@]} -eq 10 ]\n}\n\n@test \"--show-output-of-passing-tests works as expected\" {\n  run -0 bats --show-output-of-passing-tests \"$FIXTURE_ROOT/show-output-of-passing-tests.bats\"\n  [ \"${lines[0]}\" == '1..1' ]\n  [ \"${lines[1]}\" == 'ok 1 test' ]\n  [ \"${lines[2]}\" == '# output' ]\n  [ ${#lines[@]} -eq 3 ]\n}\n\n@test \"--verbose-run prints output\" {\n  run -1 bats --verbose-run \"$FIXTURE_ROOT/verbose-run.bats\"\n  [ \"${lines[0]}\" == '1..1' ]\n  [ \"${lines[1]}\" == 'not ok 1 test' ]\n  [ \"${lines[2]}\" == \"# (in test file $RELATIVE_FIXTURE_ROOT/verbose-run.bats, line 2)\" ]\n  [ \"${lines[3]}\" == \"#   \\`run ! echo test' failed, expected nonzero exit code!\" ]\n  [ \"${lines[4]}\" == '# test' ]\n  [ ${#lines[@]} -eq 5 ]\n}\n\n@test \"BATS_VERBOSE_RUN=1 also prints output\" {\n  run -1 env BATS_VERBOSE_RUN=1 bats \"$FIXTURE_ROOT/verbose-run.bats\"\n  [ \"${lines[0]}\" == '1..1' ]\n  [ \"${lines[1]}\" == 'not ok 1 test' ]\n  [ \"${lines[2]}\" == \"# (in test file $RELATIVE_FIXTURE_ROOT/verbose-run.bats, line 2)\" ]\n  [ \"${lines[3]}\" == \"#   \\`run ! echo test' failed, expected nonzero exit code!\" ]\n  [ \"${lines[4]}\" == '# test' ]\n  [ ${#lines[@]} -eq 5 ]\n}\n\n@test \"--gather-test-outputs-in gathers outputs of all tests (even succeeding!)\" {\n  local OUTPUT_DIR=\"$BATS_TEST_TMPDIR/logs\"\n  run bats --verbose-run --gather-test-outputs-in \"$OUTPUT_DIR\" \"$FIXTURE_ROOT/print_output_on_failure.bats\"\n\n  [ -d \"$OUTPUT_DIR\" ] # will be generated!\n\n  # even outputs of successful tests are generated\n  OUTPUT=$(<\"$OUTPUT_DIR/1-no failure prints no output.log\") # own line to trigger failure if file does not exist\n  [ \"$OUTPUT\" ==  \"success\" ]\n  \n  OUTPUT=$(<\"$OUTPUT_DIR/2-failure prints output.log\")\n  [ \"$OUTPUT\" == \"fail hard\" ]\n\n  # even empty outputs are generated\n  OUTPUT=$(<\"$OUTPUT_DIR/3-empty output on failure.log\")\n  [ \"$OUTPUT\" == \"\" ]\n\n  [ \"$(find \"$OUTPUT_DIR\" -type f | wc -l)\" -eq 3 ]\n}\n\n@test \"Tell about missing flock and shlock\" {\n  if ! command -v parallel; then\n    skip \"this test requires GNU parallel to be installed\"\n  fi\n  if command -v flock; then\n    skip \"this test requires flock not to be installed\"\n  fi\n  if command -v shlock; then\n    skip \"this test requires flock not to be installed\"\n  fi\n\n  run ! bats --jobs 2 \"$FIXTURE_ROOT/parallel.bats\"\n  [ \"${lines[0]}\" == \"ERROR: flock/shlock is required for parallelization within files!\" ]\n  [ \"${#lines[@]}\" -eq 1 ]\n}\n\n@test \"Test with a name that is waaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaay too long\" {\n  skip \"This test should only check if the long name chokes bats' internals during execution\"\n}\n\n@test \"BATS_CODE_QUOTE_STYLE works with any two characters (even unicode)\" {\n  BATS_CODE_QUOTE_STYLE='``' run -1 bats --tap \"${FIXTURE_ROOT}/failing.bats\"\n  # shellcheck disable=SC2016\n  [ \"${lines[3]}\" == '#   `eval \"( exit ${STATUS:-1} )\"` failed' ]\n\n  \n  export BATS_CODE_QUOTE_STYLE='😁😂'\n  if [[ ${#BATS_CODE_QUOTE_STYLE} -ne 2 ]]; then\n    # for example, this happens on windows!\n    skip 'Unicode chars are not counted as one char in this system'\n  fi\n  run -1 bats --tap \"${FIXTURE_ROOT}/failing.bats\"\n  # shellcheck disable=SC2016\n  [ \"${lines[3]}\" == '#   😁eval \"( exit ${STATUS:-1} )\"😂 failed' ]\n}\n\n@test \"BATS_CODE_QUOTE_STYLE=custom requires BATS_CODE_QUOTE_BEGIN/END\" {\n  # unset because they are set in the surrounding scope\n  unset BATS_BEGIN_CODE_QUOTE BATS_END_CODE_QUOTE\n\n  BATS_CODE_QUOTE_STYLE=custom run -1 bats --tap \"${FIXTURE_ROOT}/passing.bats\"\n  [ \"${lines[0]}\" == 'ERROR: BATS_CODE_QUOTE_STYLE=custom requires BATS_BEGIN_CODE_QUOTE and BATS_END_CODE_QUOTE to be set' ]\n\n  # shellcheck disable=SC2016\n  BATS_CODE_QUOTE_STYLE=custom \\\n  BATS_BEGIN_CODE_QUOTE='$(' \\\n  BATS_END_CODE_QUOTE=')' \\\n    run -1 bats --tap \"${FIXTURE_ROOT}/failing.bats\"\n  # shellcheck disable=SC2016\n  [ \"${lines[3]}\" == '#   $(eval \"( exit ${STATUS:-1} )\") failed' ]\n}\n\n@test \"Warn about invalid BATS_CODE_QUOTE_STYLE\" {\n  BATS_CODE_QUOTE_STYLE='' run -1 bats --tap \"${FIXTURE_ROOT}/passing.bats\"\n  [ \"${lines[0]}\" == 'ERROR: Unknown BATS_CODE_QUOTE_STYLE: ' ]\n\n  BATS_CODE_QUOTE_STYLE='1' run -1 bats --tap \"${FIXTURE_ROOT}/passing.bats\"\n  [ \"${lines[0]}\" == 'ERROR: Unknown BATS_CODE_QUOTE_STYLE: 1' ]\n\n  BATS_CODE_QUOTE_STYLE='three' run -1 bats --tap \"${FIXTURE_ROOT}/passing.bats\"\n  [ \"${lines[0]}\" == 'ERROR: Unknown BATS_CODE_QUOTE_STYLE: three' ]\n}\n\n@test \"Debug trap must only override variables that are prefixed with bats_ (issue #519)\" {\n  # use declare -p to gather variables in pristine bash and bats @test environment\n  # then compare which ones are introduced in @test compared to bash\n\n  # make declare's output more readable and suitable for `comm`\n  if [[ \"${BASH_VERSINFO[0]}\" -eq 3 ]]; then\n    normalize_variable_list() {\n      # `declare -p`: VAR_NAME=\"VALUE\"\n      # will also contain function definitions!\n      while read -r line; do\n        # Skip variable assignments in function definitions!\n        # (They will be indented.)\n        declare_regex='^declare -[^[:space:]]+ ([^=]+)='\n        plain_regex='^([^=[:space]]+)='\n        if [[ $line =~ $declare_regex ]]; then\n          printf \"%s\\n\" \"${BASH_REMATCH[1]}\"\n        elif [[ $line =~ $plain_regex ]]; then\n          printf \"%s\\n\" \"${BASH_REMATCH[1]}\"\n        fi\n      done | sort\n    }\n  else\n    normalize_variable_list() {\n      # `declare -p`: declare -X VAR_NAME=\"VALUE\"\n      while IFS=' =' read -r _declare _ variable _; do\n          if [[ \"$_declare\" == declare ]]; then # skip multiline variables' values\n            printf \"%s\\n\" \"$variable\"\n          fi\n      done | sort\n    }\n  fi\n\n  # get the bash baseline\n  # add variables that should be ignored like PIPESTATUS here\n  BASH_DECLARED_VARIABLES=$(env -i PIPESTATUS= \"$BASH\" -c \"declare -p\")\n  local BATS_DECLARED_VARIABLES_FILE=\"${BATS_TEST_TMPDIR}/variables.log\"\n  # now capture bats @test environment\n  run -0 env -i PATH=\"$PATH\" BATS_DECLARED_VARIABLES_FILE=\"$BATS_DECLARED_VARIABLES_FILE\"  bash \"${BATS_ROOT}/bin/bats\" \"${FIXTURE_ROOT}/issue-519.bats\"\n  # use function to allow failing via !, run is a bit unwiedly with the pipe and subshells\n  check_no_new_variables() {\n    # -23 -> only look at additions on the bats list\n    ! comm -23 <(normalize_variable_list <\"$BATS_DECLARED_VARIABLES_FILE\") \\\n               <(normalize_variable_list <<< \"$BASH_DECLARED_VARIABLES\" ) \\\n               | grep -v '^BATS_' # variables that are prefixed with BATS_ don't count\n  }\n  check_no_new_variables\n}\n\n@test \"Don't wait for disowned background jobs to finish because of open FDs (#205)\" {\n    SECONDS=0\n    export LOG_FILE=\"$BATS_TEST_TMPDIR/fds.log\"\n    run -0 bats --show-output-of-passing-tests --tap \"${FIXTURE_ROOT}/issue-205.bats\"\n    echo \"Whole suite took: $SECONDS seconds\"\n    FDS_LOG=$(<\"$LOG_FILE\")\n    echo \"$FDS_LOG\"\n    [ $SECONDS -lt 10 ]\n    [[ $FDS_LOG == *'otherfunc fds after: (0 1 2)'* ]] || false\n    [[ $FDS_LOG == *'setup_file fds after: (0 1 2)'* ]] || false\n}\n"
  },
  {
    "path": "vendor/bats-core/test/concurrent-coordination.bash",
    "content": "# block until at least <barrier-size> processes of this barrier group entered the barrier\n# once this happened, all latecomers will go through immediately!\n# WARNING: a barrier group consists of all processes with the same barrier name *and* size!\nsingle-use-barrier() { # <barrier-name> <barrier-size> [<timeout-in-seconds> [<sleep-cycle-time>]]\n    local barrier_name=\"$1\"\n    local barrier_size=\"$2\"\n    local timeout_in_seconds=\"${3:-0}\"\n    local sleep_cycle_time=\"${4:-1}\"\n    # use name and size to distinguish between invocations\n    # this will block inconsistent sizes on the same name!\n    local BARRIER_SUFFIX=${barrier_name//\\//_}-$barrier_size\n    local BARRIER_FILE=\"$BATS_SUITE_TMPDIR/barrier-$BARRIER_SUFFIX\"\n    # mark our entry for all others\n    # concurrent writes may interleave but should not lose their newlines\n    echo \"in-$$\" >> \"$BARRIER_FILE\"\n    local start=\"$SECONDS\"\n    # wait for others to enter\n    while [[ $(wc -l <\"$BARRIER_FILE\" ) -lt $barrier_size ]]; do\n        if [[ $timeout_in_seconds -ne 0 && $(( SECONDS - start )) -gt $timeout_in_seconds ]]; then\n            mv \"$BARRIER_FILE\" \"$BARRIER_FILE-timeout\"\n            printf \"ERROR: single-use-barrier %s timed out\\n\" \"$BARRIER_SUFFIX\" >&2\n            return 1\n        fi\n        sleep \"$sleep_cycle_time\"\n    done\n    # mark our exit\n    echo \"out-$$\" >> \"$BARRIER_FILE\"\n}\n\n# block until at least <latch-size> signalling threads have passed the latch\n# SINGLE_USE_LATCH_DIR must be exported!\nsingle-use-latch::wait() { # <latch-name> <latch-size> [<timeout-in-seconds> [<sleep-cycle-time>]]\n    local latch_name=\"$1\"\n    local latch_size=\"$2\"\n    local timeout_in_seconds=\"${3:-0}\"\n    local sleep_cycle_time=\"${4:-1}\"\n    \n    local LATCH_FILE\n    LATCH_FILE=\"$(single-use-latch::_filename \"$latch_name\")\"\n    local start=\"$SECONDS\"\n    while [[ (! -e \"$LATCH_FILE\") || $(wc -l <\"$LATCH_FILE\" ) -lt $latch_size ]]; do\n        if [[ $timeout_in_seconds -ne 0 && $(( SECONDS - start )) -gt $timeout_in_seconds ]]; then\n            printf \"ERROR: single-use-latch %s timed out\\n\" \"$latch_name\" >&2\n            mv \"$LATCH_FILE\" \"$LATCH_FILE-timeout\"\n            return 1\n        fi\n        sleep \"$sleep_cycle_time\"\n    done\n}\n\n# signal the waiting process that the latch was passed\n# this does not block\n# SINGLE_USE_LATCH_DIR must be exported!\nsingle-use-latch::signal() { # <latch-name>\n    local latch_name=\"$1\"\n    local LATCH_FILE\n    LATCH_FILE=\"$(single-use-latch::_filename \"$latch_name\")\"\n    # mark our passing\n    # concurrent process might interleave but will still post their newline\n    echo \"passed-$$\" >> \"$LATCH_FILE\"\n}\n\nsingle-use-latch::_filename() { # <latch-name> \n    printf \"%s\\n\" \"${SINGLE_USE_LATCH_DIR?}/latch-${1//\\//_}\"\n}\n"
  },
  {
    "path": "vendor/bats-core/test/file_setup_teardown.bats",
    "content": "load 'test_helper'\nfixtures file_setup_teardown\n\nsetup_file() {\n  export SETUP_FILE_EXPORT_TEST=true\n}\n\n@test \"setup_file is run once per file\" {\n    # shellcheck disable=SC2031,SC2030\n    export LOG=\"$BATS_TEST_TMPDIR/setup_file_once.log\"\n    bats \"$FIXTURE_ROOT/setup_file.bats\"\n}\n\n@test \"teardown_file is run once per file\" {\n  # shellcheck disable=SC2031,SC2030\n  export LOG=\"$BATS_TEST_TMPDIR/teardown_file_once.log\"\n  run bats \"$FIXTURE_ROOT/teardown_file.bats\"\n  [[ $status -eq 0 ]]\n  # output the log for faster debugging\n  cat \"$LOG\"\n  # expect to find an entry for the tested file\n  grep 'teardown_file.bats' \"$LOG\"\n  # it should be the only entry\n  run wc -l < \"$LOG\"\n  [[ $output -eq 1 ]]\n}\n\n@test \"setup_file is called correctly in multi file suite\" {\n    # shellcheck disable=SC2031,SC2030\n    export LOG=\"$BATS_TEST_TMPDIR/setup_file_multi_file_suite.log\"\n    run bats \"$FIXTURE_ROOT/setup_file.bats\" \"$FIXTURE_ROOT/no_setup_file.bats\" \"$FIXTURE_ROOT/setup_file2.bats\"\n    [[ $status -eq 0 ]]\n    run wc -l < \"$LOG\"\n    # each setup_file[2].bats is in the log exactly once!\n    [[ $output -eq 2 ]]\n    grep setup_file.bats \"$LOG\"\n    grep setup_file2.bats \"$LOG\"\n}\n\n@test \"teardown_file is called correctly in multi file suite\" {\n  # shellcheck disable=SC2031,SC2030\n  export LOG=\"$BATS_TEST_TMPDIR/teardown_file_multi_file_suite.log\"\n  run bats \"$FIXTURE_ROOT/teardown_file.bats\" \"$FIXTURE_ROOT/no_teardown_file.bats\" \"$FIXTURE_ROOT/teardown_file2.bats\"\n  [[ $status -eq 0 ]]\n  run wc -l < \"$LOG\"\n  # each teardown_file[2].bats is in the log exactly once!\n  [[ $output -eq 2 ]]\n  grep teardown_file.bats \"$LOG\"\n  grep teardown_file2.bats \"$LOG\"\n\n}\n\n@test \"setup_file failure aborts tests for this file\" {\n  # this might need to mark them as skipped as the test count is already determined at this point\n  run bats \"$FIXTURE_ROOT/setup_file_failed.bats\"\n  echo \"$output\"\n  [[ \"${lines[0]}\" == \"1..2\" ]]\n  [[ \"${lines[1]}\" == \"not ok 1 setup_file failed\" ]]\n  [[ \"${lines[2]}\" == \"# (from function \\`setup_file' in test file $RELATIVE_FIXTURE_ROOT/setup_file_failed.bats, line 2)\" ]]\n  [[ \"${lines[3]}\" == \"#   \\`false' failed\" ]]\n  [[ \"${lines[4]}\" == \"# bats warning: Executed 1 instead of expected 2 tests\" ]] # this warning is expected\n  # to appease the count validator, we would have to reduce the expected number of tests (retroactively?) or \n  # output even those tests that should be skipped due to a failed setup_file.\n  # Since we are already in a failure mode, the additional error does not hurt and is less verbose than\n  # printing all the failed/skipped tests due to the setup failure.\n}\n\n@test \"teardown_file failure fails at least one test from the file\" {\n  run bats \"$FIXTURE_ROOT/teardown_file_failed.bats\"\n  [[ $status -ne 0 ]]\n  echo \"$output\"\n  [[ \"${lines[0]}\" == \"1..1\" ]]\n  [[ \"${lines[1]}\" == \"ok 1 test\" ]]\n  [[ \"${lines[2]}\" == \"not ok 2 teardown_file failed\" ]]\n  [[ \"${lines[3]}\" == \"# (from function \\`teardown_file' in test file $RELATIVE_FIXTURE_ROOT/teardown_file_failed.bats, line 3)\" ]]\n  [[ \"${lines[4]}\" == \"#   \\`false' failed\" ]]\n  [[ \"${lines[5]}\" == \"# bats warning: Executed 2 instead of expected 1 tests\" ]] # for now this warning is expected\n  # for a failed teardown_file not to change the number of tests being reported, we would have to alter at least one provious test result report\n  # this would require arbitrary amounts of buffering so we simply add our own line with a fake test number\n  # tripping the count validator won't change the overall result, as we already are in a failure mode\n}\n\n@test \"teardown_file runs even if any test in the file failed\" {\n  # shellcheck disable=SC2031,SC2030\n  export LOG=\"$BATS_TEST_TMPDIR/teardown_file_failed.log\"\n  run bats \"$FIXTURE_ROOT/teardown_file_after_failing_test.bats\"\n  [[ $status -ne 0 ]]\n  grep teardown_file_after_failing_test.bats \"$LOG\"\n  echo \"$output\"\n  [[ $output == \"1..1\nnot ok 1 failing test\n# (in test file $RELATIVE_FIXTURE_ROOT/teardown_file_after_failing_test.bats, line 6)\n#   \\`false' failed\" ]]\n}\n\n@test \"teardown_file should run even after user abort via CTRL-C\" {\n  if [[ \"$BATS_NUMBER_OF_PARALLEL_JOBS\" -gt 1 ]]; then\n    skip \"Aborts don't work in parallel mode\"\n  fi\n  # shellcheck disable=SC2031,SC2030\n  export LOG=\"$BATS_TEST_TMPDIR/teardown_file_abort.log\"\n  # guarantee that background processes get their own process group -> pid=pgid\n  set -m\n  SECONDS=0\n  # run testsubprocess in background to not avoid blocking this test\n  bats \"$FIXTURE_ROOT/teardown_file_after_long_test.bats\"&\n  SUBPROCESS_PID=$!\n  # wait until we enter the test\n  sleep 2\n  # fake sending SIGINT (CTRL-C) to the process group of the background subprocess\n  kill -SIGINT -- -$SUBPROCESS_PID\n  wait # for the test to finish either way (SIGINT or normal execution)\n  echo \"Waited: $SECONDS seconds\"\n  [[ $SECONDS -lt 10 ]] # make sure we really cut it short with SIGINT\n  # check that teardown_file ran and created the log file\n  [[ -f \"$LOG\" ]]\n  grep teardown_file_after_long_test.bats \"$LOG\"\n  # but the test must not have run to the end!\n  run ! grep \"test finished successfully\" \"$LOG\"\n}\n\n@test \"setup_file runs even if all tests in the file are skipped\" {\n  # shellcheck disable=SC2031,SC2030\n  export LOG=\"$BATS_TEST_TMPDIR/setup_file_skipped.log\" \n  run bats \"$FIXTURE_ROOT/setup_file_even_if_all_tests_are_skipped.bats\"\n  [[ -f \"$LOG\" ]]\n  grep setup_file_even_if_all_tests_are_skipped.bats \"$LOG\"\n}\n\n@test \"teardown_file runs even if all tests in the file are skipped\" {\n  # shellcheck disable=SC2031,SC2030\n  export LOG=\"$BATS_TEST_TMPDIR/teardown_file_skipped.log\" \n  run bats \"$FIXTURE_ROOT/teardown_file_even_if_all_tests_are_skipped.bats\"\n  [[ $status -eq 0 ]]\n  [[ -f \"$LOG\" ]]\n  grep teardown_file_even_if_all_tests_are_skipped.bats \"$LOG\"\n}\n\n@test \"setup_file must not leak context between tests in the same suite\" {\n  # example: BATS_ROOT was unset in one test but used in others, therefore, the suite failed\n  # Simulate leaking env var from first to second test by: export SETUP_FILE_VAR=\"LEAK!\"\n  run bats \"$FIXTURE_ROOT/setup_file_does_not_leak_env.bats\" \"$FIXTURE_ROOT/setup_file_does_not_leak_env2.bats\"\n  echo \"$output\"\n  [[ $status -eq 0 ]]\n}\n\n@test \"teardown_file must not leak context between tests in the same suite\" {\n  # example: BATS_ROOT was unset in one test but used in others, therefore, the suite failed\n  run bats \"$FIXTURE_ROOT/teardown_file_does_not_leak.bats\" \"$FIXTURE_ROOT/teardown_file_does_not_leak2.bats\"\n  echo \"$output\"\n  [[ $status -eq 0 ]]\n  [[ $output == \"1..2\nok 1 test\nok 2 must not see variable from first run\" ]]\n}\n\n@test \"halfway setup_file errors are caught and reported\" {\n  run bats \"$FIXTURE_ROOT/setup_file_halfway_error.bats\"\n  [ $status -ne 0 ]\n  echo \"$output\"\n  [ \"${lines[0]}\" == \"1..1\" ]\n  [ \"${lines[1]}\" == \"not ok 1 setup_file failed\" ]\n  [ \"${lines[2]}\" == \"# (from function \\`setup_file' in test file $RELATIVE_FIXTURE_ROOT/setup_file_halfway_error.bats, line 3)\" ]\n  [ \"${lines[3]}\" == \"#   \\`false' failed\" ]\n}\n\n@test \"halfway teardown_file errors are caught and reported\" {\n  run bats \"$FIXTURE_ROOT/teardown_file_halfway_error.bats\"\n  echo \"$output\"\n  [[ $status -ne 0 ]]\n  [[ \"${lines[0]}\" == \"1..1\" ]]\n  [[ \"${lines[1]}\" == \"ok 1 empty\" ]]\n  [[ \"${lines[2]}\" == \"not ok 2 teardown_file failed\" ]]\n  [[ \"${lines[3]}\" == \"# (from function \\`teardown_file' in test file $RELATIVE_FIXTURE_ROOT/teardown_file_halfway_error.bats, line 3)\" ]]\n  [[ \"${lines[4]}\" == \"#   \\`false' failed\" ]]\n  [[ \"${lines[5]}\" == \"# bats warning: Executed 2 instead of expected 1 tests\" ]] # for now this warning is expected\n}\n\n@test \"variables exported in setup_file are visible in tests\" {\n  [[ $SETUP_FILE_EXPORT_TEST == \"true\" ]]\n}\n\n@test \"Don't run setup_file for files without tests\" {\n  # shellcheck disable=SC2031\n  export LOG=\"$BATS_TEST_TMPDIR/setup_file.log\"\n  # only select the test from no_setup_file\n  run bats -f test \"$FIXTURE_ROOT/setup_file.bats\" \"$FIXTURE_ROOT/no_setup_file.bats\"\n\n  [ ! -f \"$LOG\" ] # setup_file must not have been executed!\n  [ \"${lines[0]}\" == '1..1' ] # but at least one test should have been run\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/BATS_TMPDIR.bats",
    "content": "@test \"BATS_TMPDIR is set\" {\n  [ \"${BATS_TMPDIR}\" == \"${expected:-}\" ]\n}\n\n@test \"BATS_RUN_TMPDIR has BATS_TMPDIR as a prefix\" {\n  local regex=\"^${BATS_TMPDIR}/.+\"\n  [[ ${BATS_RUN_TMPDIR} =~ ${regex} ]]\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/cmd_using_stdin.bash",
    "content": "#!/usr/bin/env bash\n\n# Fractional timeout supported in bash 4+\nif [ \"${BASH_VERSINFO[0]}\" -lt 4 ]; then\n  timeout=1\nelse\n  timeout=0.01\nfi\n\n# Just reading from stdin\nwhile read -r -t $timeout foo; do\n  if [ \"$foo\" == \"EXIT\" ]; then\n    echo \"Found\"\n    exit 0\n  fi\ndone\n\necho \"Not found\"\nexit 1\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/comment_style.bats",
    "content": "function should_be_found { # @test\n  true\n}\n\nfunction should_be_found_with_trailing_whitespace { # @test   \n  true\n}\n\nshould_be_found_with_parens() { #@test\n  true\n}\n\nshould_be_found_with_parens_and_whitespace () { #@test\n  true\n}\n\nfunction should_be_found_with_function_and_parens() { #@test\n  true\n}\n\nfunction should_be_found_with_function_parens_and_whitespace () { #@test\n  true\n}\n\nshould_not_be_found() { \n  false                                          \n  #@test                                        \n}                                               \n\nshould_not_be_found() {  \n  false                   \n} #@test   \n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/dos_line_no_shellcheck.bats",
    "content": "@test \"foo\" {\r\r\n  echo \"foo\"\r\r\n}\r\r\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/duplicate-tests_no_shellcheck.bats",
    "content": "# This does not fail as expected\n@test \"gizmo test\" {\n  false\n}\n\n@test \"gizmo test\" \"this does fail, as expected\" {\n  false\n}\n\n# This overrides any previous test from the suite with the same description\n@test \"gizmo test\" {\n  true\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/empty.bats",
    "content": ""
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/environment.bats",
    "content": "@test \"setting a variable\" {\n  # shellcheck disable=SC2030\n  variable=1\n  [ $variable -eq 1 ]\n}\n\n@test \"variables do not persist across tests\" {\n  # shellcheck disable=SC2031\n  [ -z \"$variable\" ]\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/evaluation_count/file1.bats",
    "content": "echo \"file1\" >> \"$TEMPFILE\"\n\n@test \"test1\" {\n    :\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/evaluation_count/file2.bats",
    "content": "echo \"file2\" >> \"$TEMPFILE\"\n\n@test \"test 1\" {\n    :\n}\n\n@test \"test 2\" {\n    :\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/expand_var_in_test_name.bats",
    "content": "@test \"$SUITE: test with variable in name\" {\n  true\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/exported_function.bats",
    "content": "if exported_function; then\n  a='exported_function'\nfi\n\n@test \"failing test\" {\n  echo \"a='$a'\"\n  false\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/external_function_calls.bats",
    "content": "load test_helper\n\n# Test various combinations that may fail line number detection in stack trace\n# Tests are designed so the first statement succeeds and 2nd fails\n# All tests fail on the same line so checking can be automated\n\n@test \"Call true function && false stackdepth=1\" {\n    help_me\n    help_me && false\n}\n\n@test \"Call true function && return 1 stackdepth=1\" {\n    help_me\n    help_me && return 1\n}\n\n@test \"Call true function and invert stackdepth=2\" {\n    help_me\n    ! help_me\n}\n\n@test \"Call false function || false stackdepth=1\" {\n    ! failing_helper\n    failing_helper || false\n}\n\n@test \"Call false function && return 1 stackdepth=1\" {\n    ! failing_helper\n    failing_helper || return 1\n}\n\n@test \"Call false function stackdepth=2\" {\n    ! failing_helper\n    failing_helper\n}\n\n@test \"Call return_0 function && false stackdepth=1\" {\n    return_0\n    return_0 && false\n}\n\n@test \"Call return_0 function && return 1 stackdepth=1\" {\n    return_0\n    return_0 && return 1\n}\n\n@test \"Call return_0 function and invert stackdepth=2\" {\n    return_0\n    ! return_0\n}\n\n@test \"Call return_1 function || false stackdepth=1\" {\n    ! return_1\n    return_1 || false\n}\n\n@test \"Call return_1 function && return 1 stackdepth=1\" {\n    ! return_1\n    return_1 || return 1\n}\n\n@test \"Call return_1 function stackdepth=2\" {\n    ! return_1\n    return_1\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/external_functions.bash",
    "content": "setup() {\n    true\n}\n\nteardown() {\n    true\n}\n\nsetup_file() {\n    true\n}\n\nteardown_file() {\n    true\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/external_functions.bats",
    "content": "load external_functions\n\n@test test {\n    true\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/failing.bats",
    "content": "@test \"a failing test\" {\n  true\n  true\n  eval \"( exit ${STATUS:-1} )\"\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/failing_and_passing.bats",
    "content": "@test \"a failing test\" {\n  false\n}\n\n@test \"a passing test\" {\n  true\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/failing_helper.bats",
    "content": "load \"test_helper\"\n\n@test \"failing helper function\" {\n  true\n  failing_helper\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/failing_setup.bats",
    "content": "setup() {\n  false\n}\n\n@test \"truth\" {\n  true\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/failing_teardown.bats",
    "content": "teardown() {\n  eval \"( exit ${STATUS:-1} )\"\n}\n\n@test \"truth\" {\n  [ \"$PASS\" = 1 ]\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/failing_with_bash_cond.bats",
    "content": "@test \"a failing test\" {\n  true\n  # shellcheck disable=SC2050\n  [[ 1 == 2 ]]\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/failing_with_bash_expression.bats",
    "content": "@test \"a failing test\" {\n  true\n  (( 1 == 2 ))\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/failing_with_negated_command.bats",
    "content": "@test \"a failing test\" {\n  true\n  ! true\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/failure_in_free_code.bats",
    "content": "\n\nhelper() {\n  false\n}\n\nhelper\n\n@test \"everything is ok\" {\n  true\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/hang_after_run.bats",
    "content": "setup() {\n    load '../../concurrent-coordination'\n}\n\n@test \"test\" {\n    single-use-latch::signal hang_after_run\n    run true\n    sleep 10\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/hang_in_run.bats",
    "content": "setup() {\n    load '../../concurrent-coordination'\n}\n\n@test \"test\" {\n    single-use-latch::signal hang_in_run\n    run sleep 10\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/hang_in_setup_file.bats",
    "content": "setup_file() {\n    load '../../concurrent-coordination'\n    single-use-latch::signal hang_in_setup_file\n    sleep 10\n}\n\n@test \"empty\" {\n    :\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/hang_in_teardown.bats",
    "content": "teardown() {\n    load '../../concurrent-coordination'\n    single-use-latch::signal hang_in_teardown\n    sleep 10\n}\n\n@test \"empty\" {\n    :\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/hang_in_teardown_file.bats",
    "content": "teardown_file() {\n    load '../../concurrent-coordination'\n    single-use-latch::signal hang_in_teardown_file\n    sleep 10\n}\n\n@test \"empty\" {\n    :\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/hang_in_test.bats",
    "content": "setup() {\n    load '../../concurrent-coordination'\n}\n\n@test \"test\" {\n    single-use-latch::signal hang_in_test\n    sleep 10\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/intact.bats",
    "content": "@test \"dash-e on beginning of line\" {\n  run cat - <<INPUT\n-e\nINPUT\n  test \"$output\" = \"-e\"\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/issue-205.bats",
    "content": "#!/usr/bin/env bats\n\nfunction bgfunc {\n    get_open_fds\n    echo \"${FUNCNAME[1]} fds before: (${open_fds[*]})\" >>\"${LOG_FILE}\"\n    close_non_std_fds\n    get_open_fds\n    echo \"${FUNCNAME[1]} fds after: (${open_fds[*]})\" >>\"${LOG_FILE}\"\n    sleep 10\n    echo \"bgfunc done\"\n    return 0\n}\n\n# store the list of open FDs in array open_fds\nfunction get_open_fds() {\n    open_fds=() # reset output array in case it was already set\n    if [[ ${BASH_VERSINFO[0]} == 3 ]]; then\n        local BASHPID\n        BASHPID=$(bash -c 'echo $PPID')\n    fi\n    local tmpfile\n    tmpfile=$(mktemp \"$BATS_SUITE_TMPDIR/fds-XXXXXX\")\n    # Avoid opening a new fd to read fds: Don't use <(), glob expansion.\n    # Instead, redirect stdout to file which does not create an extra FD.\n    if [[ -d /proc/$BASHPID/fd ]]; then # Linux\n        ls -1 \"/proc/$BASHPID/fd\" > \"$tmpfile\"\n        IFS=$'\\n' read -d '' -ra open_fds <\"$tmpfile\" || true\n    elif command -v lsof >/dev/null ; then # MacOS\n        local -a fds\n        lsof -F f -p \"$BASHPID\" >\"$tmpfile\"\n        IFS=$'\\n' read -d '' -ra fds < \"$tmpfile\" || true\n        for fd in \"${fds[@]}\"; do\n            case $fd in \n                f[0-9]*) # filter non fd entries (mainly pid?)\n                    open_fds+=(\"${fd#f}\") # cut off f prefix\n                ;;\n            esac\n        done\n    elif command -v procstat >/dev/null ; then # BSDs\n        local -a columns header\n        procstat fds \"$BASHPID\" > \"$tmpfile\"\n        {\n            read -r -a header\n            local fd_column_index=-1\n            for ((i=0; i<${#header[@]}; ++i)); do\n                if [[ ${header[$i]} == *FD* ]]; then\n                    fd_column_index=$i\n                    break\n                fi\n            done\n            if [[ $fd_column_index -eq -1 ]]; then\n                printf \"Could not find FD column in procstat\" >&2\n                exit 1\n            fi\n            while read -r -a columns; do\n                local fd=${columns[$fd_column_index]}\n                if [[ $fd == [0-9]* ]]; then # only take up numeric entries\n                    open_fds+=(\"$fd\")\n                fi\n            done\n        } < \"$tmpfile\"\n    else\n        # TODO: MSYS (Windows)\n        printf \"Neither FD discovery mechanism available\\n\" >&2\n        exit 1\n    fi\n}\n\nfunction close_non_std_fds() {\n    local open_fds non_std_fds=()\n    get_open_fds\n    for fd in \"${open_fds[@]}\"; do\n        if [[ $fd -gt 2 ]]; then\n            non_std_fds+=(\"$fd\")\n        fi\n    done\n    close_fds \"${non_std_fds[@]}\"\n}\n\nfunction close_fds() { # <fds...>\n    for fd in \"$@\"; do\n            eval \"exec $fd>&-\"\n    done\n}\n\nfunction otherfunc {\n    bgfunc &\n    PID=$!\n    disown\n    return 0\n}\n\nsetup_file (){ # see issue #530\n    bgfunc &\n}\n\n@test \"min bg\" {\n    echo \"sec: $SECONDS\"\n    otherfunc\n    sleep 1 # leave some space for the background job to print/fail early\n    kill -s 0 -- $PID # fail it the process already finished due to error!\n    echo \"sec: $SECONDS\"\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/issue-433/repro1.bats",
    "content": "@test \"1\" {\n        sleep 1\n}\n\n@test \"2\" {\n        sleep 1\n}\n\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/issue-433/repro2.bats",
    "content": "@test \"11\" {\n        sleep 1\n}\n\n@test \"12\" {\n        sleep 1\n}\n\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/issue-519.bats",
    "content": "@test \"no unprefixed variables\" {\n    declare -p >\"${BATS_DECLARED_VARIABLES_FILE?}\"\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/load.bats",
    "content": "[ -n \"$HELPER_NAME\" ] || HELPER_NAME=\"test_helper\"\nload \"$HELPER_NAME\"\n\n@test \"calling a loaded helper\" {\n  help_me\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/loop_keep_IFS.bats",
    "content": "# see issue #89\nloop_func() {\n  local search=\"none one two tree\"\n  local d\n\n  for d in $search ; do\n    echo \"$d\"\n  done\n}\n\n@test \"loop_func\" {\n  run loop_func\n  [[ \"${lines[3]}\" == 'tree' ]]\n  run loop_func\n  [[ \"${lines[2]}\" == 'two' ]]\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/no-final-newline.bats",
    "content": "@test \"error in test\" {\n  printf 'foo\\nbar'\n  false\n}\n\n@test \"test function returns nonzero\" {\n  printf 'foo\\nbar'\n  return 1\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/output.bats",
    "content": "@test \"success writing to stdout\" {\n  echo \"success stdout 1\"\n  echo \"success stdout 2\"\n}\n\n@test \"success writing to stderr\" {\n  echo \"success stderr\" >&2\n}\n\n@test \"failure writing to stdout\" {\n  echo \"failure stdout 1\"\n  echo \"failure stdout 2\"\n  false\n}\n\n@test \"failure writing to stderr\" {\n  echo \"failure stderr\" >&2\n  false\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/parallel.bats",
    "content": "@test \"slow test 1\" {\n  sleep 3s\n}\n\n@test \"slow test 2\" {\n  sleep 3s\n}\n\n@test \"slow test 3\" {\n  sleep 3s\n}\n\n@test \"slow test 4\" {\n  sleep 3s\n}\n\n@test \"slow test 5\" {\n  sleep 3s\n}\n\n@test \"slow test 6\" {\n  sleep 3s\n}\n\n@test \"slow test 7\" {\n  sleep 3s\n}\n\n@test \"slow test 8\" {\n  sleep 3s\n}\n\n@test \"slow test 9\" {\n  sleep 3s\n}\n\n@test \"slow test 10\" {\n  sleep 3s\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/passing.bats",
    "content": "@test \"a passing test\" {\n  true\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/passing_and_failing.bats",
    "content": "@test \"a passing test\" {\n  true\n}\n\n@test \"a failing test\" {\n  false\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/passing_and_skipping.bats",
    "content": "@test \"a passing test\" {\n  true\n}\n\n@test \"a skipped test with no reason\" {\n  skip\n}\n\n@test \"a skipped test with a reason\" {\n  skip \"for a really good reason\"\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/passing_failing_and_skipping.bats",
    "content": "@test \"a passing test\" {\n  true\n}\n\n@test \"a skipping test\" {\n  skip\n}\n\n@test \"a failing test\" {\n  false\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/print_output_on_failure.bats",
    "content": "@test \"no failure prints no output\" {\n    run echo success\n}\n\n@test \"failure prints output\" {\n    run -1 echo \"fail hard\"\n}\n\n@test \"empty output on failure\" {\n    false\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/quoted_and_unquoted_test_names_no_shellcheck.bats",
    "content": "@test 'single-quoted name' {\n  true\n}\n\n@test \"double-quoted name\" {\n  true\n}\n\n@test unquoted name {\n  true\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/read_from_stdin.bats",
    "content": "#!/usr/bin/env bats\n\n@test \"test 1\" {\n    # Don't print anything\n    run bash -c \"$BATS_TEST_DIRNAME/cmd_using_stdin.bash\"\n    [ \"$status\" -eq 1 ]\n    [ \"$output\" = \"Not found\" ]\n}\n\n@test \"test 2 with\tTAB in name\" {\n    run bash -c \"echo EXIT | $BATS_TEST_DIRNAME/cmd_using_stdin.bash\"\n    [ \"$status\" -eq 0 ]\n    echo \"$output\"\n    [ \"$output\" = \"Found\" ]\n}\n\n@test \"test 3\" {\n    run bash -c \"echo EXIT | $BATS_TEST_DIRNAME/cmd_using_stdin.bash\"\n    [ \"$status\" -eq 0 ]\n    [ \"$output\" = \"Found\" ]\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/reference_unset_parameter.bats",
    "content": "@test \"referencing unset parameter fails\" {\n  set -u\n  # shellcheck disable=SC2154\n  echo \"$unset_parameter\"\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/reference_unset_parameter_in_setup.bats",
    "content": "setup() {\n  set -u\n  # shellcheck disable=SC2154\n  echo \"$unset_parameter\"\n}\n\nteardown() {\n  echo \"should not capture the next line\"\n  false\n}\n\n@test \"referencing unset parameter fails in setup\" {\n  :\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/reference_unset_parameter_in_teardown.bats",
    "content": "teardown() {\n  set -u\n  # shellcheck disable=SC2154\n  echo \"$unset_parameter\"\n}\n\n@test \"referencing unset parameter fails in teardown\" {\n  :\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/run_long_command.bats",
    "content": "@test \"run long command\" {\n    run sleep 3\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/set_-eu_in_setup_and_teardown.bats",
    "content": "setup() {\n    set -eu\n}\n\nteardown() {\n    set -eu\n}\n\n@test \"skipped test\" {\n    skip\n}\n\n@test \"skipped test with reason\" {\n    skip \"reason\"\n}\n\n@test \"passing test\" {\n    run true\n}\n\n@test \"failing test\" {\n    false\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/setup.bats",
    "content": "LOG=\"$BATS_TEST_SUITE_TMPDIR/setup.log\"\n\nsetup() {\n  echo \"$BATS_TEST_NAME\" >> \"$LOG\"\n}\n\n@test \"one\" {\n  [ \"$(tail -n 1 \"$LOG\")\" = \"test_one\" ]\n}\n\n@test \"two\" {\n  [ \"$(tail -n 1 \"$LOG\")\" = \"test_two\" ]\n}\n\n@test \"three\" {\n  [ \"$(tail -n 1 \"$LOG\")\" = \"test_three\" ]\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/show-output-of-passing-tests.bats",
    "content": "@test \"test\" {\n    echo output\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/single_line_no_shellcheck.bats",
    "content": "@test \"empty\" { }\n\n@test \"passing\" { true; }\n\n@test \"input redirection\" { diff - <( echo hello ); } <<EOS\nhello\nEOS\n\n@test \"failing\" { false; }\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/skipped.bats",
    "content": "@test \"a skipped test\" {\n  skip\n}\n\n@test \"a skipped test with a reason\" {\n  skip \"a reason\"\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/skipped_with_parens.bats",
    "content": "@test \"a skipped test with parentheses in the reason\" {\n  skip \"a reason (with parentheses)\"\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/source_nonexistent_file.bats",
    "content": "@test \"sourcing nonexistent file fails\" {\n  # shellcheck disable=SC1091\n  source \"nonexistent file\"\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/source_nonexistent_file_in_setup.bats",
    "content": "setup() {\n  # shellcheck disable=SC1091\n  source \"nonexistent file\"\n}\n\nteardown() {\n  echo \"should not capture the next line\"\n  false\n}\n\n@test \"sourcing nonexistent file fails in setup\" {\n  :\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/source_nonexistent_file_in_teardown.bats",
    "content": "teardown() {\n  # shellcheck disable=SC1091\n  source \"nonexistent file\"\n}\n\n@test \"sourcing nonexistent file fails in teardown\" {\n  :\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/tab in filename.bats",
    "content": "@test \"test\" {\n\t:\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/teardown.bats",
    "content": "LOG=\"$BATS_TEST_SUITE_TMPDIR/teardown.log\"\n\nteardown() {\n  echo \"$BATS_TEST_NAME\" >> \"$LOG\"\n}\n\n@test \"one\" {\n  true\n}\n\n@test \"two\" {\n  false\n}\n\n@test \"three\" {\n  true\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/test_helper.bash",
    "content": "help_me() {\n  true\n}\n\nfailing_helper() {\n  false\n}\n\nreturn_0() {\n  # Just return 0. Intentional assignment to boost line numbers\n  result=0\n  return $result\n}\n\nreturn_1() {\n  # Just return 0. Intentional assignment to boost line numbers\n  result=1\n  return $result\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/unbound_variable.bats",
    "content": " set -u\n\n# This file is used to test line number offsets. Any changes to lines will affect tests\n\n@test \"access unbound variable\" {\n    unset unset_variable\n    # Add a line for checking line number\n    # shellcheck disable=SC2154\n    foo=$unset_variable\n}\n\n@test \"access second unbound variable\" {\n    unset second_unset_variable\n    # shellcheck disable=SC2034,SC2154\n    foo=$second_unset_variable\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/unofficial_bash_strict_mode.bash",
    "content": "#!/usr/bin/env bash\nset -euo pipefail\nIFS=$'\\n\\t'\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/unofficial_bash_strict_mode.bats",
    "content": "load unofficial_bash_strict_mode\n@test \"unofficial Bash strict mode conditions met\" {\n  :\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/update_path_env.bats",
    "content": "PATH=\"/usr/local/bin:/usr/bin:/bin\"\n\n@test \"PATH is reset\" {\n  echo \"$PATH\"\n  false\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/verbose-run.bats",
    "content": "@test \"test\" {\n    run ! echo test\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/whitespace_no_shellcheck.bats",
    "content": "@test \"no extra whitespace\" {\n  :\n}\n\n\t@test \"tab at beginning of line\" {\n\t  :\n\t}\n\n@test\t\"tab before description\" {\n  :\n}\n\n@test \"tab before opening brace\"\t{\n  :\n}\n\n\t@test\t\"tabs at beginning of line and before description\" {\n\t  :\n\t}\n\n\t@test\t\"tabs at beginning, before description, before brace\"\t{\n\t  :\n\t}\n\n\t @test\t \"extra whitespace around single-line test\"\t {\t :;\t }\t \n\n@test \"no extra whitespace around single-line test\" {:;}\n\n@test\t parse unquoted name between extra whitespace \t{:;}\n\n@test { {:;}  # unquote single brace is a valid description\n\n@test ' {:;}  # empty name from single quote\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/bats/without_trailing_newline.bats",
    "content": "@test \"truth\" {\n  true\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/file_setup_teardown/no_setup_file.bats",
    "content": "@test \"test\" {\n    true\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/file_setup_teardown/no_teardown_file.bats",
    "content": "@test \"first\" {\n    true\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/file_setup_teardown/setup_file.bats",
    "content": "setup_file() {\n    echo \"$BATS_TEST_FILENAME\" >> \"$LOG\"\n}\n\n@test \"Test 1\" {\n    true\n}\n\n@test \"Test 2\" {\n    true\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/file_setup_teardown/setup_file2.bats",
    "content": "setup_file() {\n    echo \"$BATS_TEST_FILENAME\" >> \"$LOG\"\n}\n\n@test \"test\" {\n    true\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/file_setup_teardown/setup_file_does_not_leak_env.bats",
    "content": "setup_file() {\n    export SETUP_FILE_VAR=\"$BATS_TEST_FILENAME\"\n}\n\n@test \"test\" {\n    true\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/file_setup_teardown/setup_file_does_not_leak_env2.bats",
    "content": "@test \"test\" {\n    [[ \"${SETUP_FILE_VAR-\"NOT_SET\"}\" == \"NOT_SET\" ]]\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/file_setup_teardown/setup_file_even_if_all_tests_are_skipped.bats",
    "content": "setup_file() {\n    echo \"$BATS_TEST_FILENAME\" >> \"$LOG\"\n}\n\n@test \"test\" {\n    skip \"We only want to see if setup file runs\"\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/file_setup_teardown/setup_file_failed.bats",
    "content": "setup_file() {\n    false\n}\n\n@test \"test 1\" {\n    true\n}\n\n@test \"test 2\" {\n    true\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/file_setup_teardown/setup_file_halfway_error.bats",
    "content": "setup_file() {\n    true\n    false\n    true\n}\n\n@test \"test\" {\n    true\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/file_setup_teardown/teardown_file.bats",
    "content": "teardown_file() {\n    echo \"$BATS_TEST_FILENAME\" >> \"$LOG\"\n}\n\n@test \"first\" {\n    true\n}\n\n@test \"second\" {\n    true\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/file_setup_teardown/teardown_file2.bats",
    "content": "teardown_file() {\n    echo \"$BATS_TEST_FILENAME\" >> \"$LOG\"\n}\n\n@test \"first\" {\n    true\n}\n\n@test \"second\" {\n    true\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/file_setup_teardown/teardown_file_after_failing_test.bats",
    "content": "teardown_file() {\n    echo \"$BATS_TEST_FILENAME\" >> \"$LOG\"\n}\n\n@test \"failing test\" {\n    false\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/file_setup_teardown/teardown_file_after_long_test.bats",
    "content": "teardown_file() {\n    echo \"$BATS_TEST_FILENAME\" >> \"$LOG\"\n}\n\n@test \"long running test\" {\n    sleep 10\n    echo \"test finished successfully\" >> \"$LOG\"\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/file_setup_teardown/teardown_file_does_not_leak.bats",
    "content": "teardown_file() {\n    export POTENTIALLY_LEAKING_VARIABLE=\"$BATS_TEST_FILENAME\"\n}\n\n@test \"test\" {\n    true\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/file_setup_teardown/teardown_file_does_not_leak2.bats",
    "content": "@test \"must not see variable from first run\" {\n    [[ -z \"$POTENTIALLY_LEAKING_VARIABLE\" ]]\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/file_setup_teardown/teardown_file_even_if_all_tests_are_skipped.bats",
    "content": "teardown_file() {\n    echo \"$BATS_TEST_FILENAME\" >> \"$LOG\"\n}\n\n@test \"skipped test\" {\n    skip 'All tests in this file are skipped! Teardown_file runs anyways'\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/file_setup_teardown/teardown_file_failed.bats",
    "content": "\nteardown_file() {\n    false\n}\n\n@test \"test\" {\n    true\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/file_setup_teardown/teardown_file_halfway_error.bats",
    "content": "teardown_file() {\n    true\n    false\n    true\n}\n\n@test \"empty\" {\n    true\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/junit-formatter/duplicate/first/file1.bats",
    "content": "@test \"test in duplicate file\" {\n    true\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/junit-formatter/duplicate/second/file1.bats",
    "content": "@test \"test in duplicate file\" {\n    true\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/junit-formatter/issue_360.bats",
    "content": "#!/usr/bin/env bats\n\nsetup() {\n    echo \"# setup stdout\"\n    echo \"# setup FD3\" >&3\n}\n\nteardown() {\n    echo \"# teardown stdout\" \n    echo \"# teardown FD3\" >&3\n}\n\n@test \"say hello to Biblo\" {\n    echo \"# hello stdout\"\n    echo \"# hello Bilbo\" >&3\n}\n\n@test \"fail to say hello to Biblo\" {\n    echo \"# hello stdout\"\n    echo \"# hello Bilbo\" >&3\n    false\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/junit-formatter/issue_531.bats",
    "content": "#!/usr/bin/env bats\n\nsetup_file() {\n    echo \"# setup_file stdout\"\n    echo \"# setup_file fd3\" >&3\n}\n\nteardown_file() {\n    echo \"# teardown_file stdout\"\n    echo \"# teardown_file fd3\" >&3\n}\n\n@test \"My test\" {\n    echo \"# test stdout\"\n    echo \"# test fd3\" >&3\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/junit-formatter/skipped.bats",
    "content": "#!/usr/bin/env bats\n\n@test \"a skipped test\" {\n  skip\n}\n\n@test \"a skipped test with a reason\" {\n  skip \"a reason\"\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/junit-formatter/suite/file1.bats",
    "content": "@test \"one test\" {\n    true\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/junit-formatter/suite/file2.bats",
    "content": "@test \"another test\" {\n    true\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/junit-formatter/xml-escape.bats",
    "content": "@test \"Successful test with escape characters: \\\"'<>&\u001b[0m (0x1b)\" {\n  true\n}\n\n@test \"Failed test with escape characters: \\\"'<>&\u001b[0m (0x1b)\" {\n  echo \"<>'&\u001b[0m\" && false\n}\n\n@test \"Skipped test with escape characters: \\\"'<>&\u001b[0m (0x1b)\" {\n  skip \"\\\"'<>&\u001b[0m\"\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/load/ambiguous",
    "content": "# Helper to detect regressions in load's lookup ordering.\n# An exact name match should be prioritized over name.bash.\n\necho \"Should not have loaded this file!\" >&2\nexit 1\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/load/ambiguous.bash",
    "content": "# Helper to detect regressions in load's lookup ordering.\n# An exact name match should be prioritized over name.bash.\n\necho \"This is the expected file to load.\"\n\nhelp_me() { :; }\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/load/bats_load_library.bats",
    "content": "[ -n \"$HELPER_NAME\" ] || HELPER_NAME=\"test_helper\"\nbats_load_library \"$HELPER_NAME\"\n\n@test \"calling a loaded helper\" {\n  help_me\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/load/exit1.bash",
    "content": "exit 1\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/load/failing_bats_load_library.bats",
    "content": "bats_load_library \"return1\"\n\n@test \"true\" {\n    true\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/load/failing_load.bats",
    "content": "load \"return1\"\n\n@test \"true\" {\n    true\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/load/find_library_helper.bats",
    "content": "@test \"find a library\" {\n    run find_in_bats_lib_path \"$LIBRARY_NAME\"\n    [ $status -eq 0 ]\n    [ \"${lines[0]}\" = \"$LIBRARY_PATH\" ]\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/load/find_library_helper_err.bats",
    "content": "@test \"does not find a library\" {\n    run find_in_bats_lib_path \"$LIBRARY_NAME\"\n    [ $status -eq 1 ]\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/load/load.bats",
    "content": "[ -n \"$HELPER_NAME\" ] || HELPER_NAME=\"test_helper\"\nload \"$HELPER_NAME\"\n\n@test \"calling a loaded helper\" {\n  help_me\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/load/return1.bash",
    "content": "return 1\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/load/test_helper.bash",
    "content": "help_me() {\n  true\n}\n\nfailing_helper() {\n  false\n}\n\nreturn_0() {\n  # Just return 0. Intentional assignment to boost line numbers\n  result=0\n  return $result\n}\n\nreturn_1() {\n  # Just return 0. Intentional assignment to boost line numbers\n  result=1\n  return $result\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/parallel/must_not_parallelize_across_files/file1.bats",
    "content": "setup() {\n    echo \"start $BATS_TEST_NAME\" >> \"$FILE_MARKER\"\n}\n\nteardown() {\n    echo \"end $BATS_TEST_NAME\" >> \"$FILE_MARKER\"\n}\n\n@test \"test 1\" {\n    # stretch the time this test runs to prevent accidental serialization by the scheduler\n    # if both tests could run in parallel, this will increase the likelihood of detecting it\n    # by delaying this test's teardown past the other's\n    sleep 3\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/parallel/must_not_parallelize_across_files/file2.bats",
    "content": "setup() {\n    echo \"start $BATS_TEST_NAME\" >> \"$FILE_MARKER\"\n}\n\nteardown() {\n    echo \"end $BATS_TEST_NAME\" >> \"$FILE_MARKER\"\n}\n\n@test \"test 2\" {\n    run cat \"$FILE_MARKER\"\n    echo \"$output\"\n\n    # assuming serialized, ordered execution we will always see the first test start and end before this runs\n    [[ \"${lines[0]}\" == \"start\"* ]]\n    OTHER_TEST_NAME=\"${lines[0]:6}\"\n    [[ \"$OTHER_TEST_NAME\" != \"$BATS_TEST_NAME\" ]]\n    [[ \"${lines[1]}\" == \"end $OTHER_TEST_NAME\" ]]\n    [[ \"${lines[2]}\" == \"start $BATS_TEST_NAME\" ]]\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/parallel/must_not_parallelize_within_file.bats",
    "content": "setup_file() {\n    export FILE_MARKER\n    FILE_MARKER=$(mktemp \"${BATS_RUN_TMPDIR}/file_marker.XXXXXX\")\n    if [[ -n \"${DISABLE_IN_SETUP_FILE_FUNCTION}\" ]]; then\n        export BATS_NO_PARALLELIZE_WITHIN_FILE=true\n        echo \"setup_file() sets BATS_NO_PARALLELIZE_WITHIN_FILE=true\" >&2\n    fi\n}\n\nif [[ -n \"${DISABLE_OUTSIDE_ALL_FUNCTIONS}\" ]]; then\n    export BATS_NO_PARALLELIZE_WITHIN_FILE=true\n    echo \"File sets BATS_NO_PARALLELIZE_WITHIN_FILE=true\" >&2\nfi\n\nteardown_file() {\n    rm \"$FILE_MARKER\"\n}\n\nsetup() {\n    if [[ -n \"${DISABLE_IN_SETUP_FUNCTION}\" ]]; then\n        export BATS_NO_PARALLELIZE_WITHIN_FILE=true\n        echo \"setup() sets BATS_NO_PARALLELIZE_WITHIN_FILE=true\" >&3\n    fi\n    echo \"start $BATS_TEST_NAME\" >> \"$FILE_MARKER\"\n}\n\nteardown() {\n    echo \"end $BATS_TEST_NAME\" >> \"$FILE_MARKER\"\n}\n\n@test \"test 1\" {\n    if [[ -n \"${DISABLE_IN_TEST_FUNCTION}\" ]]; then\n        export BATS_NO_PARALLELIZE_WITHIN_FILE=true\n        echo \"Test function sets BATS_NO_PARALLELIZE_WITHIN_FILE=true\" >&3\n    fi\n    # stretch the time this test runs to prevent accidental serialization by the scheduler\n    # if both tests could run in parallel, this will increase the likelyhood of detecting it\n    # by delaying this test's teardown past the other's\n    sleep 3\n}\n\n@test \"test 2\" {\n    run cat \"$FILE_MARKER\"\n    echo \"$output\"\n\n    # assuming serialized, ordered execution we will always see the first test start and end before this runs\n    [[ \"${lines[0]}\" == \"start\"* ]]\n    OTHER_TEST_NAME=\"${lines[0]:6}\"\n    [[ \"$OTHER_TEST_NAME\" != \"$BATS_TEST_NAME\" ]]\n    [[ \"${lines[1]}\" == \"end $OTHER_TEST_NAME\" ]]\n    [[ \"${lines[2]}\" == \"start $BATS_TEST_NAME\" ]]\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/parallel/parallel-preserve-environment.bats",
    "content": "setup_file() {\n    export OTHER_ENV_VARIABLE='my-value'\n}\n\n@test \"check env variables are set\" {\n    [[ \"$TEST_ENV_VARIABLE\" == \"test-value\" ]]\n    [[ \"$OTHER_ENV_VARIABLE\" == \"my-value\" ]]\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/parallel/parallel.bats",
    "content": "setup() {\n  load '../../concurrent-coordination'\n  echo \"start $BATS_TEST_NAME $BATS_TEST_FILENAME\" >> \"$FILE_MARKER\"\n}\n\nteardown() {\n  echo \"stop $BATS_TEST_NAME $BATS_TEST_FILENAME\" >> \"$FILE_MARKER\"\n}\n\n@test \"slow test 1\" {\n  single-use-barrier \"parallel\" \"$PARALLELITY\"\n}\n\n@test \"slow test 2\" {\n  single-use-barrier \"parallel\" \"$PARALLELITY\"\n}\n\n@test \"slow test 3\" {\n  single-use-barrier \"parallel\" \"$PARALLELITY\"\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/parallel/parallel_factor.bats",
    "content": "@test \"slow test 1\" {\n  sleep 3\n}\n\n@test \"slow test 2\" {\n  sleep 3\n}\n\n@test \"slow test 3\" {\n  sleep 3\n}\n\n@test \"slow test 4\" {\n  sleep 3\n}\n\n@test \"slow test 5\" {\n  sleep 3\n}\n\n@test \"slow test 6\" {\n  sleep 3\n}\n\n@test \"slow test 7\" {\n  sleep 3\n}\n\n@test \"slow test 8\" {\n  sleep 3\n}\n\n@test \"slow test 9\" {\n  sleep 3\n}\n\n@test \"slow test 10\" {\n  sleep 3\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/parallel/setup_file/setup_file.bats",
    "content": "setup_file() {\n    load '../../../concurrent-coordination'\n    echo \"start $BATS_TEST_FILENAME\" >> \"${FILE_MARKER?}\"\n    single-use-barrier setup-file \"${PARALLELITY?}\" 10\n}\n\nteardown_file() {\n    echo \"stop $BATS_TEST_FILENAME\" >> \"$FILE_MARKER\"\n}\n\n@test \"nothing\" {\n    true\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/parallel/suite/parallel1.bats",
    "content": "setup() {\n  load '../../../concurrent-coordination'\n  echo \"start $BATS_TEST_NAME $BATS_TEST_FILENAME\" >> \"$FILE_MARKER\"\n}\n\nteardown() {\n  echo \"stop $BATS_TEST_NAME $BATS_TEST_FILENAME\" >> \"$FILE_MARKER\"\n}\n\n@test \"slow test 1\" {\n  single-use-barrier \"parallel\" \"$PARALLELITY\"\n}\n\n@test \"slow test 2\" {\n  single-use-barrier \"parallel\" \"$PARALLELITY\"\n}\n\n@test \"slow test 3\" {\n  single-use-barrier \"parallel\" \"$PARALLELITY\"\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/run/failing.bats",
    "content": "@test \"run -0 false\" {\n  run -0 false\n}\n\n@test \"run -1 echo hi\" {\n  run -1 echo hi\n}\n\n@test \"run -2 exit 3\" {\n  run -2 exit 3\n}\n\n@test \"run ! true\" {\n  run ! true\n}\n\n@test \"run multiple pass/fails\" {\n  run ! false\n  run -0 echo hi\n  run -127 /no/such/cmd\n  run -1 /etc\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/run/invalid.bats",
    "content": "@test \"run '-4evah' echo hi\" {\n  run '-4evah' echo hi\n}\n\n@test \"run -256 echo hi\" {\n  run -256 echo hi\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/suite/empty/.gitkeep",
    "content": ""
  },
  {
    "path": "vendor/bats-core/test/fixtures/suite/filter/a.bats",
    "content": "@test 'foo in a' { true; }\n@test '--bar in a' { true; }\n@test 'baz in a' { true; }\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/suite/filter/b.bats",
    "content": "@test 'bar_in_b' { true; }\n@test '--baz_in_b' { true; }\n@test 'quux_in_b' { true; }\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/suite/filter/c.bats",
    "content": "@test 'quux_in c' { true; }\n@test 'xyzzy in c' { true; }\n@test 'plugh_in c' { true; }\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/suite/multiple/a.bats",
    "content": "@test \"truth\" {\n  true\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/suite/multiple/b.bats",
    "content": "@test \"more truth\" {\n  true\n}\n\n@test \"quasi-truth\" {\n  [ -z \"$FLUNK\" ]\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/suite/override_BATS_FILE_EXTENSION/subfolder/test.other_extension",
    "content": "@test \"test.other_extension\" {\n    true\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/suite/override_BATS_FILE_EXTENSION/test.bats",
    "content": "@test \"test.bats\" {\n    true\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/suite/override_BATS_FILE_EXTENSION/test.test",
    "content": "@test \"test.test\" {\n    true\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/suite/recursive/subsuite/test2.bats",
    "content": "@test \"another passing test\" {\n  true\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/suite/recursive/test.bats",
    "content": "@test \"a passing test\" {\n  true\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/suite/single/test.bats",
    "content": "@test \"a passing test\" {\n  true\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/suite/skip/skip-in-setup-and-teardown.bats",
    "content": "#!/usr/bin/env bats\n\nsetup () {\n\tskip \"This is not working (https://github.com/kata-containers/runtime/issues/175)\"\n}\n\n@test \"skip in setup and teardown\" {\n  true\n}\n\n@test \"skip in setup, test and teardown\" {\n  skip\n}\n\nteardown() {\n\tskip \"This is not working (https://github.com/clearcontainers/runtime/issues/1042)\"\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/suite/skip/skip-in-setup.bats",
    "content": "#!/usr/bin/env bats\n\nsetup() {\n  skip \"This is not working (https://github.com/kata-containers/runtime/issues/175)\"\n}\n\n@test \"skip in setup\" {\n  false\n}\n\n@test \"skip in setup and test\" {\n  skip\n}"
  },
  {
    "path": "vendor/bats-core/test/fixtures/suite/skip/skip-in-teardown.bats",
    "content": "#!/usr/bin/env bats\n\n@test \"skip in teardown\" {\n  true\n}\n\nteardown() {\n\tskip \"This is not working (https://github.com/clearcontainers/runtime/issues/1042)\"\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/suite/skip/skip-in-test-and-teardown.bats",
    "content": "#!/usr/bin/env bats\n\nteardown() {\n\tskip \"This is not working (https://github.com/clearcontainers/runtime/issues/1042)\"\n}\n\n@test \"skip in test and teardown\" {\n\tskip \"This is not working (https://github.com/clearcontainers/runtime/issues/1042)\"\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/suite/skip/skip-in-test.bats",
    "content": "#!/usr/bin/env bats\n\n@test \"skip in test\" {\n\tskip \"This is not working (https://github.com/clearcontainers/runtime/issues/1042)\"\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/suite/test_number/file1.bats",
    "content": "#!/usr/bin/env bats\n\n@test \"first test in file 1\" {\n    echo \"BATS_TEST_NUMBER=$BATS_TEST_NUMBER\"\n    [[ \"$BATS_TEST_NUMBER\" == 1 ]]\n    echo \"BATS_SUITE_TEST_NUMBER=$BATS_SUITE_TEST_NUMBER\"\n    [[ \"$BATS_SUITE_TEST_NUMBER\" == 1 ]]\n}\n\n@test \"second test in file 1\" {\n    [[ \"$BATS_TEST_NUMBER\" == 2 ]]\n    [[ \"$BATS_SUITE_TEST_NUMBER\" == 2 ]]\n}\n\n@test \"BATS_TEST_NAMES is per file\" {\n    echo \"${#BATS_TEST_NAMES[@]}\"\n    [[ \"${#BATS_TEST_NAMES[@]}\" == 3 ]]\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/suite/test_number/file2.bats",
    "content": "#!/usr/bin/env bats\n\n@test \"first test in file 2\" {\n    echo \"BATS_TEST_NUMBER=$BATS_TEST_NUMBER\"\n    [[ \"$BATS_TEST_NUMBER\" == 1 ]]\n    echo \"BATS_SUITE_TEST_NUMBER=$BATS_SUITE_TEST_NUMBER\"\n    [[ \"$BATS_SUITE_TEST_NUMBER\" == 4 ]]\n}\n\n@test \"second test in file 2\" {\n    [[ \"$BATS_TEST_NUMBER\" == 2 ]]\n    [[ \"$BATS_SUITE_TEST_NUMBER\" == 5 ]]\n}\n\n@test \"second test in file 3\" {\n    [[ \"$BATS_TEST_NUMBER\" == 3 ]]\n    [[ \"$BATS_SUITE_TEST_NUMBER\" == 6 ]]\n}\n\n@test \"BATS_TEST_NAMES is per file\" {\n    echo \"${#BATS_TEST_NAMES[@]}\"\n    [[ \"${#BATS_TEST_NAMES[@]}\" == 4 ]]\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/trace/failing_complex.bats",
    "content": "@test \"a complex failing test\" {\n  echo 123\n  run bats \"$BATS_TEST_DIRNAME/failing.bats\"\n  [ $status -eq 0 ]\n}\n"
  },
  {
    "path": "vendor/bats-core/test/fixtures/trace/failing_recursive.bats",
    "content": "fun() {\n  echo \"$1\"\n  if [[ $1 -gt 0 ]]; then\n    fun $(($1 - 1))\n  fi\n}\n\n@test \"a recursive failing test\" {\n  echo Outer\n  fun 2\n  run fun 2\n  false\n}\n"
  },
  {
    "path": "vendor/bats-core/test/install.bats",
    "content": "#!/usr/bin/env bats\n\nload test_helper\n\nINSTALL_DIR=\nPATH_TO_INSTALL_SHELL=\nPATH_TO_UNINSTALL_SHELL=\n\nsetup() {\n  INSTALL_DIR=\"$BATS_TEST_TMPDIR/bats-core\"\n  PATH_TO_INSTALL_SHELL=\"${BATS_TEST_DIRNAME%/*}/install.sh\"\n  PATH_TO_UNINSTALL_SHELL=\"${BATS_TEST_DIRNAME%/*}/uninstall.sh\"\n}\n\n@test \"install.sh creates a valid installation, and uninstall.sh undos it\" {\n  run \"$PATH_TO_INSTALL_SHELL\" \"$INSTALL_DIR\"\n  [ \"$status\" -eq 0 ]\n  [ \"$output\" == \"Installed Bats to $INSTALL_DIR/bin/bats\" ]\n  [ -x \"$INSTALL_DIR/bin/bats\" ]\n  [ -x \"$INSTALL_DIR/lib/bats-core/formatter.bash\" ]\n  [ -x \"$INSTALL_DIR/lib/bats-core/preprocessing.bash\" ]\n  [ -x \"$INSTALL_DIR/lib/bats-core/semaphore.bash\" ]\n  [ -x \"$INSTALL_DIR/lib/bats-core/test_functions.bash\" ]\n  [ -x \"$INSTALL_DIR/lib/bats-core/tracing.bash\" ]\n  [ -x \"$INSTALL_DIR/lib/bats-core/validator.bash\" ]\n  [ -x \"$INSTALL_DIR/libexec/bats-core/bats\" ]\n  [ -x \"$INSTALL_DIR/libexec/bats-core/bats-exec-suite\" ]\n  [ -x \"$INSTALL_DIR/libexec/bats-core/bats-exec-test\" ]\n  [ -x \"$INSTALL_DIR/libexec/bats-core/bats-format-junit\" ]\n  [ -x \"$INSTALL_DIR/libexec/bats-core/bats-format-pretty\" ]\n  [ -x \"$INSTALL_DIR/libexec/bats-core/bats-preprocess\" ]\n  [ -f \"$INSTALL_DIR/share/man/man1/bats.1\" ]\n  [ -f \"$INSTALL_DIR/share/man/man7/bats.7\" ]\n\n  run \"$INSTALL_DIR/bin/bats\" -v\n  [ \"$status\" -eq 0 ]\n  [ \"${output%% *}\" == 'Bats' ]\n\n  run \"$PATH_TO_UNINSTALL_SHELL\" \"$INSTALL_DIR\"\n  [ \"$status\" -eq 0 ]\n  [ ! -x \"$INSTALL_DIR/bin/bats\" ]\n  [ ! -x \"$INSTALL_DIR/lib/bats-core/formatter.bash\" ]\n  [ ! -x \"$INSTALL_DIR/lib/bats-core/preprocessing.bash\" ]\n  [ ! -x \"$INSTALL_DIR/lib/bats-core/semaphore.bash\" ]\n  [ ! -x \"$INSTALL_DIR/lib/bats-core/test_functions.bash\" ]\n  [ ! -x \"$INSTALL_DIR/lib/bats-core/tracing.bash\" ]\n  [ ! -x \"$INSTALL_DIR/lib/bats-core/validator.bash\" ]\n  [ ! -x \"$INSTALL_DIR/libexec/bats-core/bats\" ]\n  [ ! -x \"$INSTALL_DIR/libexec/bats-core/bats-exec-suite\" ]\n  [ ! -x \"$INSTALL_DIR/libexec/bats-core/bats-exec-test\" ]\n  [ ! -x \"$INSTALL_DIR/libexec/bats-core/bats-format-junit\" ]\n  [ ! -x \"$INSTALL_DIR/libexec/bats-core/bats-format-pretty\" ]\n  [ ! -x \"$INSTALL_DIR/libexec/bats-core/bats-preprocess\" ]\n  [ ! -x \"$INSTALL_DIR/libexec/bats-core\" ]\n  [ ! -x \"$INSTALL_DIR/share/man/man1/bats.1\" ]\n  [ ! -x \"$INSTALL_DIR/share/man/man7/bats.7\" ]\n}\n\n@test \"install.sh creates a multilib valid installation, and uninstall.sh undos it\" {\n  rm -rf \"$INSTALL_DIR\"\n  LIBDIR=\"lib64\"\n  run \"$PATH_TO_INSTALL_SHELL\" \"$INSTALL_DIR\" \"$LIBDIR\"\n  [ \"$status\" -eq 0 ]\n  [ \"$output\" == \"Installed Bats to $INSTALL_DIR/bin/bats\" ]\n  [ -x \"$INSTALL_DIR/bin/bats\" ]\n  [ -x \"$INSTALL_DIR/$LIBDIR/bats-core/formatter.bash\" ]\n  [ -x \"$INSTALL_DIR/$LIBDIR/bats-core/preprocessing.bash\" ]\n  [ -x \"$INSTALL_DIR/$LIBDIR/bats-core/semaphore.bash\" ]\n  [ -x \"$INSTALL_DIR/$LIBDIR/bats-core/test_functions.bash\" ]\n  [ -x \"$INSTALL_DIR/$LIBDIR/bats-core/tracing.bash\" ]\n  [ -x \"$INSTALL_DIR/$LIBDIR/bats-core/validator.bash\" ]\n  [ -x \"$INSTALL_DIR/libexec/bats-core/bats\" ]\n  [ -x \"$INSTALL_DIR/libexec/bats-core/bats-exec-suite\" ]\n  [ -x \"$INSTALL_DIR/libexec/bats-core/bats-exec-test\" ]\n  [ -x \"$INSTALL_DIR/libexec/bats-core/bats-format-junit\" ]\n  [ -x \"$INSTALL_DIR/libexec/bats-core/bats-format-pretty\" ]\n  [ -x \"$INSTALL_DIR/libexec/bats-core/bats-preprocess\" ]\n  [ -f \"$INSTALL_DIR/share/man/man1/bats.1\" ]\n  [ -f \"$INSTALL_DIR/share/man/man7/bats.7\" ]\n\n  run \"$INSTALL_DIR/bin/bats\" -v\n  [ \"$status\" -eq 0 ]\n  [ \"${output%% *}\" == 'Bats' ]\n\n  run \"$PATH_TO_UNINSTALL_SHELL\" \"$INSTALL_DIR\" \"$LIBDIR\"\n  [ \"$status\" -eq 0 ]\n  [ ! -x \"$INSTALL_DIR/bin/bats\" ]\n  [ ! -x \"$INSTALL_DIR/$LIBDIR/bats-core/formatter.bash\" ]\n  [ ! -x \"$INSTALL_DIR/$LIBDIR/bats-core/preprocessing.bash\" ]\n  [ ! -x \"$INSTALL_DIR/$LIBDIR/bats-core/semaphore.bash\" ]\n  [ ! -x \"$INSTALL_DIR/$LIBDIR/bats-core/test_functions.bash\" ]\n  [ ! -x \"$INSTALL_DIR/$LIBDIR/bats-core/tracing.bash\" ]\n  [ ! -x \"$INSTALL_DIR/$LIBDIR/bats-core/validator.bash\" ]\n  [ ! -x \"$INSTALL_DIR/libexec/bats-core/bats\" ]\n  [ ! -x \"$INSTALL_DIR/libexec/bats-core/bats-exec-suite\" ]\n  [ ! -x \"$INSTALL_DIR/libexec/bats-core/bats-exec-test\" ]\n  [ ! -x \"$INSTALL_DIR/libexec/bats-core/bats-format-junit\" ]\n  [ ! -x \"$INSTALL_DIR/libexec/bats-core/bats-format-pretty\" ]\n  [ ! -x \"$INSTALL_DIR/libexec/bats-core/bats-preprocess\" ]\n  [ ! -x \"$INSTALL_DIR/libexec/bats-core\" ]\n  [ ! -x \"$INSTALL_DIR/share/man/man1/bats.1\" ]\n  [ ! -x \"$INSTALL_DIR/share/man/man7/bats.7\" ]\n}\n\n@test \"uninstall.sh works even if nothing is installed\" {\n  mkdir -p \"$INSTALL_DIR\"/tmp\n  run \"$PATH_TO_UNINSTALL_SHELL\" \"$INSTALL_DIR\"\n  [ \"$status\" -eq 0 ]\n  rmdir \"$INSTALL_DIR\"/tmp\n}\n\n@test \"install.sh only updates permissions for Bats files\" {\n  mkdir -p \"$INSTALL_DIR\"/{bin,libexec/bats-core}\n\n  local dummy_bin=\"$INSTALL_DIR/bin/dummy\"\n  printf 'dummy' >\"$dummy_bin\"\n\n  local dummy_libexec=\"$INSTALL_DIR/libexec/bats-core/dummy\"\n  printf 'dummy' >\"$dummy_libexec\"\n\n  run \"$PATH_TO_INSTALL_SHELL\" \"$INSTALL_DIR\"\n  [ \"$status\" -eq 0 ]\n  [ -f \"$dummy_bin\" ]\n  [ ! -x \"$dummy_bin\" ]\n  [ -f \"$dummy_libexec\" ]\n  [ ! -x \"$dummy_libexec\" ]\n}\n\n@test \"bin/bats is resilient to symbolic links\" {\n  run \"$PATH_TO_INSTALL_SHELL\" \"$INSTALL_DIR\"\n  [ \"$status\" -eq 0 ]\n\n  # Simulate a symlink to bin/bats (without using a symlink, for Windows sake)\n  # by creating a wrapper script that executes bin/bats via a relative path.\n  #\n  # root.bats contains tests that use real symlinks on platforms that support\n  # them.\n  local bats_symlink=\"$INSTALL_DIR/bin/bats-link\"\n  printf '%s\\n' '#! /usr/bin/env bash' \\\n    \"cd '$INSTALL_DIR/bin'\" \\\n    './bats \"$@\"' >\"$bats_symlink\"\n  chmod 700 \"$bats_symlink\"\n\n  run \"$bats_symlink\" -v\n  [ \"$status\" -eq 0 ]\n  [ \"${output%% *}\" == 'Bats' ]\n}\n\nteardown() {\n  rm -rf \"$INSTALL_DIR\"\n}\n"
  },
  {
    "path": "vendor/bats-core/test/junit-formatter.bats",
    "content": "#!/usr/bin/env bats\n\nload test_helper\nfixtures junit-formatter\n\nFLOAT_REGEX='[0-9]+(\\.[0-9]+)?'\nTIMESTAMP_REGEX='[0-9]+-[0-1][0-9]-[0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-5][0-9]'\nTESTSUITES_REGEX=\"<testsuites time=\\\"$FLOAT_REGEX\\\">\"\n\n@test \"junit formatter with skipped test does not fail\" {\n  run bats --formatter junit \"$FIXTURE_ROOT/skipped.bats\"\n  echo \"$output\"\n  [[ $status -eq 0 ]]\n  [[ \"${lines[0]}\" == '<?xml version=\"1.0\" encoding=\"UTF-8\"?>' ]]\n  \n  [[ \"${lines[1]}\" =~ $TESTSUITES_REGEX ]]\n\n  TESTSUITE_REGEX=\"<testsuite name=\\\"skipped.bats\\\" tests=\\\"2\\\" failures=\\\"0\\\" errors=\\\"0\\\" skipped=\\\"2\\\" time=\\\"$FLOAT_REGEX\\\" timestamp=\\\"$TIMESTAMP_REGEX\\\" hostname=\\\".*\\\">\"\n  echo \"TESTSUITE_REGEX='$TESTSUITE_REGEX'\"\n  [[ \"${lines[2]}\" =~ $TESTSUITE_REGEX ]]\n\n  TESTCASE_REGEX=\"<testcase classname=\\\"skipped.bats\\\" name=\\\"a skipped test\\\" time=\\\"$FLOAT_REGEX\\\">\"\n  [[ \"${lines[3]}\" =~ $TESTCASE_REGEX ]]\n\n  [[ \"${lines[4]}\" == *\"<skipped></skipped>\"* ]]\n  [[ \"${lines[5]}\" == *\"</testcase>\"* ]]\n\n  TESTCASE_REGEX=\"<testcase classname=\\\"skipped.bats\\\" name=\\\"a skipped test with a reason\\\" time=\\\"$FLOAT_REGEX\\\">\"\n  [[ \"${lines[6]}\" =~ $TESTCASE_REGEX ]]\n  [[ \"${lines[7]}\" == *\"<skipped>a reason</skipped>\"* ]]\n  [[ \"${lines[8]}\" == *\"</testcase>\"* ]]\n  \n  [[ \"${lines[9]}\" == *\"</testsuite>\"* ]]\n  [[ \"${lines[10]}\" == *\"</testsuites>\"* ]]\n}\n\n@test \"junit formatter: escapes xml special chars\" {\n  case $OSTYPE in\n    linux*|darwin)\n      # their CI can handle special chars on filename\n      TEST_FILE_NAME=\"xml-escape-\\\"<>'&.bats\"\n      ESCAPED_TEST_FILE_NAME=\"xml-escape-&quot;&lt;&gt;&#39;&amp;.bats\"\n      TEST_FILE_PATH=\"$BATS_TEST_TMPDIR/$TEST_FILE_NAME\"\n      cp \"$FIXTURE_ROOT/xml-escape.bats\" \"$TEST_FILE_PATH\"\n    ;;\n    *)\n      # use the filename without special chars\n      TEST_FILE_NAME=\"xml-escape.bats\"\n      ESCAPED_TEST_FILE_NAME=\"$TEST_FILE_NAME\"\n      TEST_FILE_PATH=\"$FIXTURE_ROOT/$TEST_FILE_NAME\"\n    ;;\n  esac\n  run bats --formatter junit \"$TEST_FILE_PATH\"\n\n  echo \"$output\"\n  [[ \"${lines[2]}\" == \"<testsuite name=\\\"$ESCAPED_TEST_FILE_NAME\\\" tests=\\\"3\\\" failures=\\\"1\\\" errors=\\\"0\\\" skipped=\\\"1\\\" time=\\\"\"*\"\\\" timestamp=\\\"\"*\"\\\" hostname=\\\"\"*\"\\\">\" ]]\n  [[ \"${lines[3]}\" == \"    <testcase classname=\\\"$ESCAPED_TEST_FILE_NAME\\\" name=\\\"Successful test with escape characters: &quot;&#39;&lt;&gt;&amp;&#27;[0m (0x1b)\\\" time=\\\"\"*\"\\\" />\" ]]\n  [[ \"${lines[4]}\" == \"    <testcase classname=\\\"$ESCAPED_TEST_FILE_NAME\\\" name=\\\"Failed test with escape characters: &quot;&#39;&lt;&gt;&amp;&#27;[0m (0x1b)\\\" \"* ]]\n  [[ \"${lines[5]}\" == '        <failure type=\"failure\">(in test file '*\"$ESCAPED_TEST_FILE_NAME, line 6)\" ]]\n  [[ \"${lines[6]}\" == '  `echo &quot;&lt;&gt;&#39;&amp;&#27;[0m&quot; &amp;&amp; false&#39; failed'* ]]\n  [[ \"${lines[9]}\" == \"    <testcase classname=\\\"$ESCAPED_TEST_FILE_NAME\\\" name=\\\"Skipped test with escape characters: &quot;&#39;&lt;&gt;&amp;&#27;[0m (0x1b)\\\" time=\\\"\"*\"\\\">\" ]]\n  [[ \"${lines[10]}\" == \"        <skipped>&quot;&#39;&lt;&gt;&amp;&#27;[0m</skipped>\" ]]\n}\n\n@test \"junit formatter: test suites\" {\n  run bats --formatter junit \"$FIXTURE_ROOT/suite/\"\n  echo \"$output\"\n\n  [[ \"${lines[0]}\" == '<?xml version=\"1.0\" encoding=\"UTF-8\"?>' ]]\n  [[ \"${lines[1]}\" == *\"<testsuites \"* ]]\n  [[ \"${lines[2]}\" == *\"<testsuite name=\\\"file1.bats\\\"\"* ]]\n  [[ \"${lines[3]}\" == *\"<testcase \"* ]]\n  [[ \"${lines[4]}\" == *\"</testsuite>\"* ]]\n  [[ \"${lines[5]}\" == *\"<testsuite name=\\\"file2.bats\\\"\"* ]]\n  [[ \"${lines[6]}\" == *\"<testcase\"* ]]\n  [[ \"${lines[7]}\" == *\"</testsuite>\"* ]]\n  [[ \"${lines[8]}\" == *\"</testsuites>\"* ]]\n}\n\n@test \"junit formatter: test suites relative path\" {\n  cd \"$FIXTURE_ROOT\"\n  run bats --formatter junit \"suite/\"\n  echo \"$output\"\n\n  [[ \"${lines[0]}\" == '<?xml version=\"1.0\" encoding=\"UTF-8\"?>' ]]\n  [[ \"${lines[1]}\" == *\"<testsuites \"* ]]\n  [[ \"${lines[2]}\" == *\"<testsuite name=\\\"file1.bats\\\"\"* ]]\n  [[ \"${lines[3]}\" == *\"<testcase \"* ]]\n  [[ \"${lines[4]}\" == *\"</testsuite>\"* ]]\n  [[ \"${lines[5]}\" == *\"<testsuite name=\\\"file2.bats\\\"\"* ]]\n  [[ \"${lines[6]}\" == *\"<testcase\"* ]]\n  [[ \"${lines[7]}\" == *\"</testsuite>\"* ]]\n  [[ \"${lines[8]}\" == *\"</testsuites>\"* ]]\n}\n\n@test \"junit formatter: files with the same name are distinguishable\" {\n  run bats --formatter junit -r \"$FIXTURE_ROOT/duplicate/\"\n  echo \"$output\"\n\n  [[ \"${lines[2]}\" == *\"<testsuite name=\\\"first/file1.bats\\\"\"* ]]\n  [[ \"${lines[5]}\" == *\"<testsuite name=\\\"second/file1.bats\\\"\"* ]]\n}\n\n@test \"junit formatter as report formatter creates report.xml\" {\n  cd \"$BATS_TEST_TMPDIR\" # don't litter sources with output files\n  run bats --report-formatter junit \"$FIXTURE_ROOT/suite/\"\n  echo \"$output\"\n  [[ -e \"report.xml\" ]]\n  run cat \"report.xml\"\n  echo \"$output\"\n  [[ \"${lines[2]}\" == *\"<testsuite name=\\\"file1.bats\\\" tests=\\\"1\\\" failures=\\\"0\\\" errors=\\\"0\\\" skipped=\\\"0\\\"\"* ]]\n  [[ \"${lines[5]}\" == *\"<testsuite name=\\\"file2.bats\\\" tests=\\\"1\\\" failures=\\\"0\\\" errors=\\\"0\\\" skipped=\\\"0\\\"\"* ]]\n}\n\n@test \"junit does not mark tests with FD 3 output as failed (issue #360)\" {\n  run bats --formatter junit \"$FIXTURE_ROOT/issue_360.bats\"\n\n  echo \"$output\"\n\n  [[ \"${lines[2]}\" == '<testsuite name=\"issue_360.bats\" '*'>' ]]\n  [[ \"${lines[3]}\" == '    <testcase classname=\"issue_360.bats\" '*'>' ]]\n  # only the outputs on FD3 should be visible on a successful test\n  [[ \"${lines[4]}\" == '        <system-out>setup FD3' ]]\n  [[ \"${lines[5]}\" == 'hello Bilbo' ]]\n  [[ \"${lines[6]}\" == 'teardown FD3</system-out>' ]]\n  [[ \"${lines[7]}\" == '    </testcase>' ]]\n  [[ \"${lines[8]}\" == '    <testcase classname=\"issue_360.bats\" name=\"fail to say hello to Biblo\" time=\"'*'\">' ]]\n  # a failed test should show FD3 output first ...\n  [[ \"${lines[9]}\" == '        <system-out>setup FD3' ]]\n  [[ \"${lines[10]}\" == 'hello Bilbo' ]]\n  [[ \"${lines[11]}\" == 'teardown FD3</system-out>' ]]\n  [[ \"${lines[12]}\" == '        <failure type=\"failure\">(in test file '*'test/fixtures/junit-formatter/issue_360.bats, line 21)' ]]\n  [[ \"${lines[13]}\" == '  `false&#39; failed' ]]\n  # ... and then the stdout output\n  [[ \"${lines[14]}\" == '# setup stdout' ]]\n  [[ \"${lines[15]}\" == '# hello stdout' ]]\n  [[ \"${lines[16]}\" == '# teardown stdout</failure>' ]]\n  [[ \"${lines[17]}\" == '    </testcase>' ]]\n  [[ \"${lines[18]}\" == '</testsuite>' ]]\n}\n\n@test \"junit does not mark tests with FD 3 output in teardown_file as failed (issue #531)\" {\n  run -0 bats --formatter junit \"$FIXTURE_ROOT/issue_531.bats\"\n\n  [[ \"${lines[2]}\" == '<testsuite name=\"issue_531.bats\" '*'>' ]]\n  [[ \"${lines[3]}\" == '    <testcase classname=\"issue_531.bats\" '*'>' ]]\n  # only the outputs on FD3 should be visible on a successful test\n  [[ \"${lines[4]}\" == '        <system-out>test fd3' ]]\n  [[ \"${lines[5]}\" == 'teardown_file fd3</system-out>' ]]\n  [[ \"${lines[6]}\" == '    </testcase>' ]]\n  [[ \"${lines[7]}\" == '</testsuite>' ]]\n}\n"
  },
  {
    "path": "vendor/bats-core/test/load.bats",
    "content": "#!/usr/bin/env bats\n\nsetup() {\n  load test_helper\n  fixtures load\n}\n\n@test \"find_in_bats_lib_path recognizes files relative to test file\" {\n  test_dir=\"$BATS_TEST_TMPDIR/find_in_bats_lib_path/bats_test_dirname_priorty\"\n  mkdir -p \"$test_dir\"\n  cp \"$FIXTURE_ROOT/test_helper.bash\" \"$test_dir/\"\n  cp \"$FIXTURE_ROOT/find_library_helper.bats\" \"$test_dir\"\n\n  BATS_LIB_PATH=\"\" LIBRARY_NAME=\"test_helper\" LIBRARY_PATH=\"$test_dir/test_helper.bash\" run bats \"$test_dir/find_library_helper.bats\"\n}\n\n@test \"find_in_bats_lib_path recognizes files in BATS_LIB_PATH\" {\n  test_dir=\"$BATS_TEST_TMPDIR/find_in_bats_lib_path/bats_test_dirname_priorty\"\n  mkdir -p \"$test_dir\"\n  cp \"$FIXTURE_ROOT/test_helper.bash\" \"$test_dir/\"\n\n  BATS_LIB_PATH=\"$test_dir\" LIBRARY_NAME=\"test_helper\" LIBRARY_PATH=\"$test_dir/test_helper.bash\" run bats \"$FIXTURE_ROOT/find_library_helper.bats\"\n}\n\n@test \"find_in_bats_lib_path returns 1 if no load path is found\" {\n  test_dir=\"$BATS_TEST_TMPDIR/find_in_bats_lib_path/no_load_path_found\"\n  mkdir -p \"$test_dir\"\n  cp \"$FIXTURE_ROOT/test_helper.bash\" \"$test_dir/\"\n\n  BATS_LIB_PATH=\"$test_dir\" LIBRARY_NAME=\"test_helper\" run bats \"$FIXTURE_ROOT/find_library_helper_err.bats\"\n}\n\n@test \"find_in_bats_lib_path follows the priority of BATS_LIB_PATH\" {\n  test_dir=\"$BATS_TEST_TMPDIR/find_in_bats_lib_path/follows_priority\"\n\n  first_dir=\"$test_dir/first\"\n  mkdir -p \"$first_dir\"\n  cp \"$FIXTURE_ROOT/test_helper.bash\" \"$first_dir/target.bash\"\n\n  second_dir=\"$test_dir/second\"\n  mkdir -p \"$second_dir\"\n  cp \"$FIXTURE_ROOT/exit1.bash\" \"$second_dir/target.bash\"\n\n  BATS_LIB_PATH=\"$first_dir:$second_dir\" LIBRARY_NAME=\"target\" LIBRARY_PATH=\"$first_dir/target.bash\" run bats \"$FIXTURE_ROOT/find_library_helper.bats\"\n}\n\n@test \"load sources scripts relative to the current test file\" {\n  run bats \"$FIXTURE_ROOT/load.bats\"\n  [ $status -eq 0 ]\n}\n\n@test \"load sources relative scripts with filename extension\" {\n  HELPER_NAME=\"test_helper.bash\" run bats \"$FIXTURE_ROOT/load.bats\"\n  [ $status -eq 0 ]\n}\n\n@test \"load aborts if the specified script does not exist\" {\n  HELPER_NAME=\"nonexistent\" run bats \"$FIXTURE_ROOT/load.bats\"\n  [ $status -eq 1 ]\n}\n\n@test \"load sources scripts by absolute path\" {\n  HELPER_NAME=\"${FIXTURE_ROOT}/test_helper.bash\" run bats \"$FIXTURE_ROOT/load.bats\"\n  [ $status -eq 0 ]\n}\n\n@test \"load aborts if the script, specified by an absolute path, does not exist\" {\n  HELPER_NAME=\"${FIXTURE_ROOT}/nonexistent\" run bats \"$FIXTURE_ROOT/load.bats\"\n  [ $status -eq 1 ]\n}\n\n@test \"load relative script with ambiguous name\" {\n  HELPER_NAME=\"ambiguous\" run bats \"$FIXTURE_ROOT/load.bats\"\n  [ $status -eq 0 ]\n}\n\n@test \"load does not use the BATS_LIB_PATH\" {\n  path_dir=\"$BATS_TEST_TMPDIR/path\"\n  mkdir -p \"$path_dir/on_path\"\n  cp \"${FIXTURE_ROOT}/test_helper.bash\" \"${path_dir}/on_path/load.bash\"\n  # shellcheck disable=SC2030,SC2031\n  export BATS_LIB_PATH=\"${path_dir}\"  HELPER_NAME=\"on_path\" \n  run ! bats \"$FIXTURE_ROOT/load.bats\"\n  run -0 bats \"$FIXTURE_ROOT/bats_load_library.bats\"\n}\n\n@test \"load supports plain symbols\" {\n  local -r helper=\"${BATS_TEST_TMPDIR}/load_helper_plain\"\n  {\n    echo \"plain_variable='value of plain variable'\"\n    echo \"plain_array=(test me hard)\"\n  } > \"${helper}\"\n\n  load \"${helper}\"\n  # shellcheck disable=SC2154\n  [ \"${plain_variable}\" = 'value of plain variable' ]\n  # shellcheck disable=SC2154\n  [ \"${plain_array[2]}\" = 'hard' ]\n\n  rm \"${helper}\"\n}\n\n@test \"load doesn't support _declare_d symbols\" {\n  local -r helper=\"${BATS_TEST_TMPDIR}/load_helper_declared\"\n  {\n    echo \"declare declared_variable='value of declared variable'\"\n    echo \"declare -r a_constant='constant value'\"\n    echo \"declare -i an_integer=0x7e4\"\n    echo \"declare -a an_array=(test me hard)\"\n    echo \"declare -x exported_variable='value of exported variable'\"\n  } > \"${helper}\"\n\n  load \"${helper}\"\n\n  [ \"${declared_variable:-}\" != 'value of declared variable' ]\n  [ \"${a_constant:-}\" != 'constant value' ]\n  (( \"${an_integer:-2019}\" != 2020 ))\n  [ \"${an_array[2]:-}\" != 'hard' ]\n  [ \"${exported_variable:-}\" != 'value of exported variable' ]\n\n  rm \"${helper}\"\n}\n\n@test \"load supports scripts on the PATH\" {\n  path_dir=\"$BATS_TEST_TMPDIR/path\"\n  mkdir -p \"$path_dir\"\n  cp \"${FIXTURE_ROOT}/test_helper.bash\" \"${path_dir}/on_path\"\n  # shellcheck disable=SC2030,SC2031\n  export PATH=\"${path_dir}:$PATH\"  HELPER_NAME=\"on_path\"\n  run -0 bats \"$FIXTURE_ROOT/load.bats\"\n}\n\n@test \"bats_load_library requires BATS_LIB_PATH to be set\" {\n  unset BATS_LIB_PATH\n  run ! bats \"$FIXTURE_ROOT/bats_load_library.bats\"\n  [ \"${lines[4]}\" == '# bats_load_library: requires BATS_LIB_PATH to be set!' ]\n}\n\n@test \"bats_load_library supports libraries with loaders on the BATS_LIB_PATH\" {\n  path_dir=\"$BATS_TEST_TMPDIR/libraries/$BATS_TEST_NAME\"\n  mkdir -p \"$path_dir\"\n  cp \"${FIXTURE_ROOT}/test_helper.bash\" \"${path_dir}/load.bash\"\n  cp \"${FIXTURE_ROOT}/exit1.bash\" \"${path_dir}/exit1.bash\"\n  # shellcheck disable=SC2030,SC2031\n  export BATS_LIB_PATH=\"${BATS_TEST_TMPDIR}/libraries\" HELPER_NAME=\"$BATS_TEST_NAME\"\n  run -0 bats \"$FIXTURE_ROOT/bats_load_library.bats\"\n  run ! bats \"$FIXTURE_ROOT/bats_load.bats\" # load does not use BATS_LIB_PATH!\n}\n\n@test \"bats_load_library supports libraries with loaders on the BATS_LIB_PATH with multiple libraries\" {\n  path_dir=\"$BATS_TEST_TMPDIR/libraries/\"\n  for lib in liba libb libc; do\n      mkdir -p \"$path_dir/$lib\"\n      cp \"${FIXTURE_ROOT}/exit1.bash\" \"$path_dir/$lib/load.bash\"\n  done\n  mkdir -p \"$path_dir/$BATS_TEST_NAME\"\n  cp \"${FIXTURE_ROOT}/test_helper.bash\" \"$path_dir/$BATS_TEST_NAME/load.bash\"\n  # shellcheck disable=SC2030,SC2031\n  export BATS_LIB_PATH=\"$path_dir\" HELPER_NAME=\"$BATS_TEST_NAME\"\n  run -0 bats \"$FIXTURE_ROOT/bats_load_library.bats\"\n  run ! bats \"$FIXTURE_ROOT/load.bats\" # load does not use BATS_LIB_PATH!\n}\n\n@test \"bats_load_library can handle whitespaces in BATS_LIB_PATH\" {\n  path_dir=\"$BATS_TEST_TMPDIR/libraries with spaces/\"\n  for lib in liba libb libc; do\n      mkdir -p \"$path_dir/$lib\"\n      cp \"${FIXTURE_ROOT}/exit1.bash\" \"$path_dir/$lib/load.bash\"\n  done\n  mkdir -p \"$path_dir/$BATS_TEST_NAME\"\n  cp \"${FIXTURE_ROOT}/test_helper.bash\" \"$path_dir/$BATS_TEST_NAME/load.bash\"\n  # shellcheck disable=SC2030,SC2031\n  export BATS_LIB_PATH=\"$path_dir\" HELPER_NAME=\"$BATS_TEST_NAME\"\n  run -0 bats \"$FIXTURE_ROOT/bats_load_library.bats\"\n}\n\n@test \"bats_load_library errors when a library errors while sourcing\" {\n  path_dir=\"$BATS_TEST_TMPDIR/libraries_err_sourcing/\"\n  mkdir -p \"$path_dir/return1\"\n  cp \"${FIXTURE_ROOT}/return1.bash\" \"$path_dir/return1/load.bash\"\n\n  # shellcheck disable=SC2030,SC2031\n  export BATS_LIB_PATH=\"$path_dir\"\n  run -1 bats \"$FIXTURE_ROOT/failing_bats_load_library.bats\"\n}"
  },
  {
    "path": "vendor/bats-core/test/parallel.bats",
    "content": "#!/usr/bin/env bats\n\nload test_helper\nfixtures parallel\n\nsetup() {\n  type -p parallel &>/dev/null || skip \"--jobs requires GNU parallel\"\n  (type -p flock &>/dev/null && type -p shlock &>/dev/null) || skip \"--jobs requires flock/shlock\"\n}\n\ncheck_parallel_tests() { # <expected maximum parallelity>\n  local expected_maximum_parallelity=\"$1\"\n  local expected_number_of_lines=\"${2:-$((2 * expected_maximum_parallelity))}\"\n\n  max_parallel_tests=0\n  started_tests=0\n  read_lines=0\n  while IFS= read -r line; do\n    (( ++read_lines ))\n    case \"$line\" in\n      \"start \"*)\n        if (( ++started_tests > max_parallel_tests )); then\n          max_parallel_tests=\"$started_tests\"\n        fi\n      ;;\n      \"stop \"*)\n        (( started_tests-- ))\n      ;;\n    esac\n  done <\"$FILE_MARKER\"\n\n  echo \"max_parallel_tests: $max_parallel_tests\"\n  [[ $max_parallel_tests -eq $expected_maximum_parallelity ]]\n\n  echo \"read_lines: $read_lines\"\n  [[ $read_lines -eq $expected_number_of_lines ]]\n}\n\n@test \"parallel test execution with --jobs\" {\n  # shellcheck disable=SC2031,SC2030\n  export FILE_MARKER\n  # shellcheck disable=SC2030\n  FILE_MARKER=$(mktemp \"${BATS_RUN_TMPDIR}/file_marker.XXXXXX\")\n  # shellcheck disable=SC2030\n  export PARALLELITY=3\n  run bats --jobs $PARALLELITY \"$FIXTURE_ROOT/parallel.bats\"\n  \n  [ \"$status\" -eq 0 ]\n  # Make sure the lines are in-order.\n  [[ \"${lines[0]}\" == \"1..3\" ]]\n  for t in {1..3}; do\n    [[ \"${lines[$t]}\" == \"ok $t slow test $t\" ]]\n  done\n\n  check_parallel_tests $PARALLELITY\n}\n\n@test \"parallel can preserve environment variables\" {\n  export TEST_ENV_VARIABLE='test-value'\n  run bats --jobs 2 \"$FIXTURE_ROOT/parallel-preserve-environment.bats\"\n  echo \"$output\"\n  [[ \"$status\" -eq 0 ]]\n}\n\n@test \"parallel suite execution with --jobs\" {\n  # shellcheck disable=SC2031,SC2030\n  export FILE_MARKER\n  # shellcheck disable=SC2030\n  FILE_MARKER=$(mktemp \"${BATS_RUN_TMPDIR}/file_marker.XXXXXX\")\n  # shellcheck disable=SC2031,SC2030\n  export PARALLELITY=12\n\n  # file parallelization is needed for maximum parallelity!\n  # If we got over the skip (if no GNU parallel) in setup() we can reenable it safely!\n  unset BATS_NO_PARALLELIZE_ACROSS_FILES \n  run bash -c \"bats --jobs $PARALLELITY \\\"${FIXTURE_ROOT}/suite/\\\" 2> >(grep -v '^parallel: Warning: ')\"\n\n  echo \"$output\"\n  [ \"$status\" -eq 0 ]\n\n  # Make sure the lines are in-order.\n  [[ \"${lines[0]}\" == \"1..$PARALLELITY\" ]]\n  i=0\n  for _ in {1..4}; do\n    for t in {1..3}; do\n      ((++i))\n      [[ \"${lines[$i]}\" == \"ok $i slow test $t\" ]]\n    done\n  done\n\n  check_parallel_tests $PARALLELITY\n}\n\n@test \"setup_file is not over parallelized\" {\n  #shellcheck disable=SC2031\n  export FILE_MARKER\n  FILE_MARKER=$(mktemp \"${BATS_RUN_TMPDIR}/file_marker.XXXXXX\")\n  #shellcheck disable=SC2031\n  export PARALLELITY=2\n\n  # file parallelization is needed for this test!\n  # If we got over the skip (if no GNU parallel) in setup() we can reenable it safely!\n  unset BATS_NO_PARALLELIZE_ACROSS_FILES \n  # run 4 files with parallelity of 2 -> serialize 2\n  run bats --jobs $PARALLELITY \"$FIXTURE_ROOT/setup_file\"\n\n  [[ $status -eq 0 ]] || (echo \"$output\"; false)\n\n  cat \"$FILE_MARKER\"\n\n  [[ $(grep -c \"start \" \"$FILE_MARKER\") -eq 4 ]] # beware of grepping the filename as well!\n  [[ $(grep -c \"stop \" \"$FILE_MARKER\") -eq 4 ]]\n\n  check_parallel_tests $PARALLELITY 8\n}\n\n@test \"running the same file twice runs its tests twice without errors\" {\n  run bats --jobs 2 \"$FIXTURE_ROOT/../bats/passing.bats\" \"$FIXTURE_ROOT/../bats/passing.bats\"\n  echo \"$output\"\n  [[ $status -eq 0 ]]\n  [[ \"${lines[0]}\" == \"1..2\" ]] # got 2x1 tests\n  [[ \"${lines[1]}\" == \"ok 1 \"* ]]\n  [[ \"${lines[2]}\" == \"ok 2 \"* ]]\n  [[ \"${#lines[@]}\" -eq 3 ]]\n}\n\n@test \"parallelity factor is met exactly\" {\n  parallelity=5 # run the 10 tests in 2 batches with 5 test each\n  bats --jobs $parallelity \"$FIXTURE_ROOT/parallel_factor.bats\" & # run in background to avoid blocking\n  # give it some time to start the tests\n  sleep 2\n  # find how many semaphores are started in parallel; don't count grep itself\n  run bash -c \"ps -ef | grep bats-exec-test | grep parallel/parallel_factor.bats | grep -v grep\"\n  echo \"$output\"\n  \n  # This might fail spuriously if we got bad luck with the scheduler\n  # and hit the transition between the first and second batch of tests.\n  [[ \"${#lines[@]}\" -eq $parallelity  ]]\n}\n\n@test \"parallel mode correctly forwards failure return code\" {\n  run bats --jobs 2 \"$FIXTURE_ROOT/../bats/failing.bats\"\n  [[ \"$status\" -eq 1 ]]\n}\n\n@test \"--no-parallelize-across-files test file detects parallel execution\" {\n  # ensure that we really run parallelization across files!\n  # (setup should have skipped already, if there was no GNU parallel)\n  unset BATS_NO_PARALLELIZE_ACROSS_FILES\n  FILE_MARKER=$(mktemp \"${BATS_RUN_TMPDIR}/file_marker.XXXXXX\") \\\n    run ! bats --jobs 2 \"$FIXTURE_ROOT/must_not_parallelize_across_files/\"\n}\n\n@test \"--no-parallelize-across-files prevents parallelization across files\" {\n  FILE_MARKER=$(mktemp \"${BATS_RUN_TMPDIR}/file_marker.XXXXXX\") \\\n    bats --jobs 2 --no-parallelize-across-files \"$FIXTURE_ROOT/must_not_parallelize_across_files/\"\n}\n\n@test \"--no-parallelize-across-files does not prevent parallelization within files\" {\n  run ! bats --jobs 2 --no-parallelize-across-files \"$FIXTURE_ROOT/must_not_parallelize_within_file.bats\"\n}\n\n@test \"--no-parallelize-within-files test file detects parallel execution\" {\n  run ! bats --jobs 2 \"$FIXTURE_ROOT/must_not_parallelize_within_file.bats\"\n}\n\n@test \"--no-parallelize-within-files prevents parallelization within files\" {\n  bats --jobs 2 --no-parallelize-within-files \"$FIXTURE_ROOT/must_not_parallelize_within_file.bats\"\n}\n\n@test \"--no-parallelize-within-files does not prevent parallelization across files\" {\n  # ensure that we really run parallelization across files!\n  # (setup should have skipped already, if there was no GNU parallel)\n  unset BATS_NO_PARALLELIZE_ACROSS_FILES\n  FILEMARKER=$(mktemp \"${BATS_RUN_TMPDIR}/file_marker.XXXXXX\") \\\n    run ! bats --jobs 2 --no-parallelize-within-files \"$FIXTURE_ROOT/must_not_parallelize_across_files/\"\n}\n\n@test \"BATS_NO_PARALLELIZE_WITHIN_FILE works from inside setup_file()\" {\n  DISABLE_IN_SETUP_FILE_FUNCTION=1 bats --jobs 2 \"$FIXTURE_ROOT/must_not_parallelize_within_file.bats\"\n}\n\n@test \"BATS_NO_PARALLELIZE_WITHIN_FILE works from outside all functions\" {\n  DISABLE_OUTSIDE_ALL_FUNCTIONS=1 bats --jobs 2 \"$FIXTURE_ROOT/must_not_parallelize_within_file.bats\"\n}\n\n@test \"BATS_NO_PARALLELIZE_WITHIN_FILE does not work from inside setup()\" {\n  DISABLE_IN_SETUP_FUNCTION=1 run ! bats --jobs 2 \"$FIXTURE_ROOT/must_not_parallelize_within_file.bats\"\n}\n\n@test \"BATS_NO_PARALLELIZE_WITHIN_FILE does not work from inside test function\" {\n  DISABLE_IN_TEST_FUNCTION=1 run ! bats --jobs 2 \"$FIXTURE_ROOT/must_not_parallelize_within_file.bats\"\n}\n"
  },
  {
    "path": "vendor/bats-core/test/pretty-formatter.bats",
    "content": "\n@test \"Timing printout shows milliseconds\" {\n    format_example_stream() {\n        bats-format-pretty -T  <<HERE\n1..1\nsuite /test/path\nbegin 1 test\nok 1 test in 123ms\nHERE\n    }\n    run format_example_stream\n    echo \"$output\"\n    [[ \"${lines[0]}\" == *'[123]'* ]]\n}"
  },
  {
    "path": "vendor/bats-core/test/root.bats",
    "content": "#!/usr/bin/env bats\n#\n# This suite is dedicated to calculating BATS_ROOT when going through various\n# permutations of symlinks. It was inspired by the report in issue #113 that the\n# calculation was broken on CentOS, where /bin is symlinked to /usr/bin.\n#\n# The basic test environment is (all paths relative to BATS_TEST_TMPDIR):\n#\n# - /bin is a relative symlink to /usr/bin, exercising the symlink resolution of\n#   the `bats` parent directory (i.e. \"${0%/*}\")\n# - /usr/bin/bats is an absolute symlink to /opt/bats-core/bin/bats, exercising\n#   the symlink resolution of the `bats` executable itself (i.e. \"${0##*/}\")\n\nload test_helper\n\nsetup() {\n  # give each test their own tmpdir to allow for parallelization without interference\n  # shellcheck disable=SC2103,SC2164\n  cd \"$BATS_TEST_TMPDIR\"\n  mkdir -p {usr/bin,opt/bats-core}\n  ls -lR .\n  \"$BATS_ROOT/install.sh\" \"opt/bats-core\"\n\n  ln -s \"usr/bin\" \"bin\"\n\n  if [[ ! -L \"bin\" ]]; then\n    # shellcheck disable=SC2103,SC2164\n    cd - >/dev/null\n    skip \"symbolic links aren't functional on OSTYPE=$OSTYPE\"\n  fi\n\n  ln -s \"$BATS_TEST_TMPDIR/opt/bats-core/bin/bats\" \\\n    \"$BATS_TEST_TMPDIR/usr/bin/bats\"\n  # shellcheck disable=SC2103,SC2164\n  cd - >/dev/null\n}\n\n@test \"#113: set BATS_ROOT when /bin is a symlink to /usr/bin\" {\n  run \"$BATS_TEST_TMPDIR/bin/bats\" -v\n  [ \"$status\" -eq 0 ]\n  [ \"${output%% *}\" == 'Bats' ]\n}\n\n# The resolution scheme here is:\n#\n# Set in setup\n# - /bin => /usr/bin (relative directory)\n@test \"set BATS_ROOT with extreme symlink resolution\" {\n  # shellcheck disable=SC2103\n  cd \"$BATS_TEST_TMPDIR\"\n  mkdir -p \"opt/bats/bin2\"\n  pwd\n\n# - /usr/bin/foo => /usr/bin/bar (relative executable)\n  ln -s bar usr/bin/foo\n# - /usr/bin/bar => /opt/bats/bin0/bar (absolute executable)\n  ln -s \"$BATS_TEST_TMPDIR/opt/bats/bin0/bar\" usr/bin/bar\n# - /opt/bats/bin0 => /opt/bats/bin1 (relative directory)\n  ln -s bin1 opt/bats/bin0\n# - /opt/bats/bin1 => /opt/bats/bin2 (absolute directory)\n  ln -s \"$BATS_TEST_TMPDIR/opt/bats/bin2\" opt/bats/bin1\n# - /opt/bats/bin2/bar => /opt/bats-core/bin/bar (absolute executable)\n  ln -s \"$BATS_TEST_TMPDIR/opt/bats-core/bin/bar\" opt/bats/bin2/bar\n# - /opt/bats-core/bin/bar => /opt/bats-core/bin/baz (relative executable)\n  ln -s baz opt/bats-core/bin/bar\n# - /opt/bats-core/bin/baz => /opt/bats-core/bin/bats (relative executable)\n  ln -s bats opt/bats-core/bin/baz\n\n  # shellcheck disable=SC2103,SC2164\n  cd - >/dev/null\n  run \"$BATS_TEST_TMPDIR/bin/foo\" -v\n  echo \"$output\"\n  [ \"$status\" -eq 0 ]\n  [ \"${output%% *}\" == 'Bats' ]\n}\n\n@test \"set BATS_ROOT when calling from same dir\" {\n  cd \"$BATS_TEST_TMPDIR\"\n  run ./bin/bats -v\n  [ \"$status\" -eq 0 ]\n  [ \"${output%% *}\" == 'Bats' ]\n}\n\n@test \"set BATS_ROOT from PATH\" {\n  cd /tmp\n  # shellcheck disable=SC2031,SC2030\n  PATH=\"$PATH:$BATS_TEST_TMPDIR/bin\"\n  run bats -v\n  [ \"$status\" -eq 0 ]\n  [ \"${output%% *}\" == 'Bats' ]\n}\n\n@test \"#182 and probably #184 as well\" {\n  cd /tmp\n  # shellcheck disable=SC2031,SC2030\n  PATH=\"$PATH:$BATS_TEST_TMPDIR/bin\"\n  run bash bats -v\n  [ \"$status\" -eq 0 ]\n  [ \"${output%% *}\" == 'Bats' ]\n}\n"
  },
  {
    "path": "vendor/bats-core/test/run.bats",
    "content": "load test_helper\nfixtures run\n\n@test \"run --keep-empty-lines preserves leading empty lines\" {\n    run --keep-empty-lines -- echo -n $'\\na'\n    printf \"'%s'\\n\" \"${lines[@]}\"\n    [ \"${lines[0]}\" == '' ]\n    [ \"${lines[1]}\" == a ]\n    [ ${#lines[@]} -eq 2 ]\n}\n\n@test \"run --keep-empty-lines preserves inner empty lines\" {\n    run --keep-empty-lines -- echo -n $'a\\n\\nb'\n    printf \"'%s'\\n\" \"${lines[@]}\"\n    [ \"${lines[0]}\" == a ]\n    [ \"${lines[1]}\" == '' ]\n    [ \"${lines[2]}\" == b ]\n    [ ${#lines[@]} -eq 3 ]\n}\n\n@test \"run --keep-empty-lines preserves trailing empty lines\" {\n    run --keep-empty-lines -- echo -n $'a\\n'\n    printf \"'%s'\\n\" \"${lines[@]}\"\n    [ \"${lines[0]}\" == a ]\n    [ \"${lines[1]}\" == '' ]\n    [ ${#lines[@]} -eq 2 ]\n}\n\n@test \"run --keep-empty-lines preserves multiple trailing empty lines\" {\n    run --keep-empty-lines -- echo -n $'a\\n\\n'\n    printf \"'%s'\\n\" \"${lines[@]}\"\n    [ \"${lines[0]}\" == a ]\n    [ \"${lines[1]}\" == '' ]\n    [ \"${lines[2]}\" == '' ]\n    [ ${#lines[@]} -eq 3 ]\n}\n\n@test \"run --keep-empty-lines preserves non-empty trailing line\" {\n    run --keep-empty-lines -- echo -n $'a\\nb'\n    printf \"'%s'\\n\" \"${lines[@]}\"\n    [ \"${lines[0]}\" == a ]\n    [ \"${lines[1]}\" == b ]\n    [ ${#lines[@]} -eq 2 ]\n}\n\nprint-stderr-stdout() {\n    printf stdout\n    printf stderr >&2\n}\n\n@test \"run --separate-stderr splits output\" {\n    local stderr stderr_lines # silence shellcheck\n    run --separate-stderr -- print-stderr-stdout\n    echo \"output='$output' stderr='$stderr'\"\n    [ \"$output\" = stdout ]\n    [ ${#lines[@]} -eq 1 ]\n\n    [ \"$stderr\" = stderr ]\n    [ ${#stderr_lines[@]} -eq 1 ]\n}\n\n@test \"run does not change set flags\" {\n    old_flags=\"$-\"\n    run true\n    echo -- \"$-\" == \"$old_flags\"\n    [ \"$-\" == \"$old_flags\" ]\n}\n\n# Positive assertions: each of these should succeed\n@test \"basic return-code checking\" {\n  run      true\n  run -0   true\n  run '!'  false\n  run -1   false\n  run -3   exit 3\n  run -5   exit 5\n  run -111 exit 111\n  run -255 exit 255\n  run -127 /no/such/command\n}\n\n@test \"run exit code check output \" {\n  run ! bats --tap \"${FIXTURE_ROOT}/failing.bats\"\n  echo \"$output\"\n  [ \"${lines[0]}\" == 1..5 ]\n  [ \"${lines[1]}\" == \"not ok 1 run -0 false\" ]\n  [ \"${lines[2]}\" == \"# (in test file ${RELATIVE_FIXTURE_ROOT}/failing.bats, line 2)\" ]\n  [ \"${lines[3]}\" == \"#   \\`run -0 false' failed, expected exit code 0, got 1\" ]\n  [ \"${lines[4]}\" == \"not ok 2 run -1 echo hi\" ]\n  [ \"${lines[5]}\" == \"# (in test file ${RELATIVE_FIXTURE_ROOT}/failing.bats, line 6)\" ]\n  [ \"${lines[6]}\" == \"#   \\`run -1 echo hi' failed, expected exit code 1, got 0\" ]\n  [ \"${lines[7]}\" == \"not ok 3 run -2 exit 3\" ]\n  [ \"${lines[8]}\" == \"# (in test file ${RELATIVE_FIXTURE_ROOT}/failing.bats, line 10)\" ]\n  [ \"${lines[9]}\" == \"#   \\`run -2 exit 3' failed, expected exit code 2, got 3\" ]\n  [ \"${lines[10]}\" == \"not ok 4 run ! true\" ]\n  [ \"${lines[11]}\" == \"# (in test file ${RELATIVE_FIXTURE_ROOT}/failing.bats, line 14)\" ]\n  [ \"${lines[12]}\" == \"#   \\`run ! true' failed, expected nonzero exit code!\" ]\n  [ \"${lines[13]}\" == \"not ok 5 run multiple pass/fails\" ]\n  [ \"${lines[14]}\" == \"# (in test file ${RELATIVE_FIXTURE_ROOT}/failing.bats, line 21)\" ]\n  [ \"${lines[15]}\" == \"#   \\`run -1 /etc' failed, expected exit code 1, got 126\" ]\n}\n\n@test \"run invalid exit code check error message\" {\n  run ! bats --tap \"${FIXTURE_ROOT}/invalid.bats\"\n  echo \"$output\"\n  [ \"${lines[0]}\" == 1..2 ]\n  [ \"${lines[1]}\" == \"not ok 1 run '-4evah' echo hi\" ]\n  [ \"${lines[2]}\" == \"# (in test file ${RELATIVE_FIXTURE_ROOT}/invalid.bats, line 2)\" ]\n  [ \"${lines[3]}\" == \"#   \\`run '-4evah' echo hi' failed\" ]\n  [ \"${lines[4]}\" == \"# Usage error: run: '=NNN' requires numeric NNN (got: 4evah)\" ]\n  [ \"${lines[5]}\" == \"not ok 2 run -256 echo hi\" ]\n  [ \"${lines[6]}\" == \"# (in test file ${RELATIVE_FIXTURE_ROOT}/invalid.bats, line 6)\" ]\n  [ \"${lines[7]}\" == \"#   \\`run -256 echo hi' failed\" ]\n  [ \"${lines[8]}\" == \"# Usage error: run: '=NNN': NNN must be <= 255 (got: 256)\" ]\n}\n"
  },
  {
    "path": "vendor/bats-core/test/suite.bats",
    "content": "#!/usr/bin/env bats\n\nload test_helper\nfixtures suite\n\n@test \"running a suite with no test files\" {\n  run bats \"$FIXTURE_ROOT/empty\"\n  [ $status -eq 0 ]\n  [ \"$output\" = \"1..0\" ]\n}\n\n@test \"running a suite with one test file\" {\n  run bats \"$FIXTURE_ROOT/single\"\n  [ $status -eq 0 ]\n  [ \"${lines[0]}\" = \"1..1\" ]\n  [ \"${lines[1]}\" = \"ok 1 a passing test\" ]\n}\n\n@test \"counting tests in a suite\" {\n  run bats -c \"$FIXTURE_ROOT/single\"\n  [ $status -eq 0 ]\n  [ \"$output\" -eq 1 ]\n\n  run bats -c \"$FIXTURE_ROOT/multiple\"\n  [ $status -eq 0 ]\n  [ \"$output\" -eq 3 ]\n}\n\n@test \"aggregated output of multiple tests in a suite\" {\n  run bats \"$FIXTURE_ROOT/multiple\"\n  [ $status -eq 0 ]\n  [ \"${lines[0]}\" = \"1..3\" ]\n  echo \"$output\" | grep \"^ok . truth\"\n  echo \"$output\" | grep \"^ok . more truth\"\n  echo \"$output\" | grep \"^ok . quasi-truth\"\n}\n\n@test \"a failing test in a suite results in an error exit code\" {\n  FLUNK=1 run bats \"$FIXTURE_ROOT/multiple\"\n  [ $status -eq 1 ]\n  [ \"${lines[0]}\" = \"1..3\" ]\n  echo \"$output\" | grep \"^not ok . quasi-truth\"\n}\n\n@test \"running an ad-hoc suite by specifying multiple test files\" {\n  run bats \"$FIXTURE_ROOT/multiple/a.bats\" \"$FIXTURE_ROOT/multiple/b.bats\"\n  [ $status -eq 0 ]\n  [ \"${lines[0]}\" = \"1..3\" ]\n  echo \"$output\" | grep \"^ok . truth\"\n  echo \"$output\" | grep \"^ok . more truth\"\n  echo \"$output\" | grep \"^ok . quasi-truth\"\n}\n\n@test \"extended syntax in suite\" {\n  emulate_bats_env\n  FLUNK=1 run bats-exec-suite -x \"$FIXTURE_ROOT/multiple/\"*.bats\n  echo \"output: $output\"\n  [ $status -eq 1 ]\n  [ \"${lines[0]}\" = \"1..3\" ]\n  [ \"${lines[1]}\" = \"suite $FIXTURE_ROOT/multiple/a.bats\" ]\n  [ \"${lines[2]}\" = \"begin 1 truth\" ]\n  [ \"${lines[3]}\" = \"ok 1 truth\" ]\n  [ \"${lines[4]}\" = \"suite $FIXTURE_ROOT/multiple/b.bats\" ]\n  [ \"${lines[5]}\" = \"begin 2 more truth\" ]\n  [ \"${lines[6]}\" = \"ok 2 more truth\" ]\n  [ \"${lines[7]}\" = \"begin 3 quasi-truth\" ]\n  [ \"${lines[8]}\" = \"not ok 3 quasi-truth\" ]\n}\n\n@test \"timing syntax in suite\" {\n  emulate_bats_env\n  FLUNK=1 run bats-exec-suite -T \"$FIXTURE_ROOT/multiple/\"*.bats\n  echo \"$output\"\n  [ $status -eq 1 ]\n  [ \"${lines[0]}\" = \"1..3\" ]\n  regex=\"ok 1 truth in [0-9]+ms\"\n  [[ \"${lines[1]}\" =~ $regex ]]\n  regex=\"ok 2 more truth in [0-9]+ms\"\n  [[ \"${lines[2]}\" =~  $regex ]]\n  regex=\"not ok 3 quasi-truth in [0-9]+ms\"\n  [[ \"${lines[3]}\" =~  $regex ]]\n}\n\n@test \"extended timing syntax in suite\" {\n  emulate_bats_env\n  FLUNK=1 run bats-exec-suite -x -T \"$FIXTURE_ROOT/multiple/\"*.bats\n  echo \"$output\"\n  [ $status -eq 1 ]\n  [ \"${lines[0]}\" = \"1..3\" ]\n  [ \"${lines[1]}\" = \"suite $FIXTURE_ROOT/multiple/a.bats\" ]\n  [ \"${lines[2]}\" = \"begin 1 truth\" ]\n  regex=\"ok 1 truth in [0-9]+ms\"\n  [[ \"${lines[3]}\" =~ $regex ]]\n  [ \"${lines[4]}\" = \"suite $FIXTURE_ROOT/multiple/b.bats\" ]\n  [ \"${lines[5]}\" = \"begin 2 more truth\" ]\n  regex=\"ok 2 more truth in [0-9]+ms\"\n  [[ \"${lines[6]}\" =~ $regex ]]\n  [ \"${lines[7]}\" = \"begin 3 quasi-truth\" ]\n  regex=\"not ok 3 quasi-truth in [0-9]+ms\"\n  [[ \"${lines[8]}\" =~ $regex ]]\n}\n\n@test \"recursive support (short option)\" {\n  run bats -r \"${FIXTURE_ROOT}/recursive\"\n  [ $status -eq 0 ]\n  [ \"${lines[0]}\" = \"1..2\" ]\n  [ \"${lines[1]}\" = \"ok 1 another passing test\" ]\n  [ \"${lines[2]}\" = \"ok 2 a passing test\" ]\n}\n\n@test \"recursive support (long option)\" {\n  run bats --recursive \"${FIXTURE_ROOT}/recursive\"\n  [ $status -eq 0 ]\n  [ \"${lines[0]}\" = \"1..2\" ]\n  [ \"${lines[1]}\" = \"ok 1 another passing test\" ]\n  [ \"${lines[2]}\" = \"ok 2 a passing test\" ]\n}\n\n@test \"recursive support with symlinks\" {\n  if [[ ! -L \"${FIXTURE_ROOT}/recursive_with_symlinks/test.bats\" ]]; then\n    skip \"symbolic links aren't functional on OSTYPE=$OSTYPE\"\n  fi\n\n  run bats -r \"${FIXTURE_ROOT}/recursive_with_symlinks\"\n  [ $status -eq 0 ]\n  [ \"${lines[0]}\" = \"1..2\" ]\n  [ \"${lines[1]}\" = \"ok 1 another passing test\" ]\n  [ \"${lines[2]}\" = \"ok 2 a passing test\" ]\n}\n\n@test \"run entire suite when --filter isn't set\" {\n  run bats \"${FIXTURE_ROOT}/filter\"\n  [ \"$status\" -eq 0 ]\n  [ \"${lines[0]}\" = '1..9' ]\n  [ \"${lines[1]}\" = 'ok 1 foo in a' ]\n  [ \"${lines[2]}\" = 'ok 2 --bar in a' ]\n  [ \"${lines[3]}\" = 'ok 3 baz in a' ]\n  [ \"${lines[4]}\" = 'ok 4 bar_in_b' ]\n  [ \"${lines[5]}\" = 'ok 5 --baz_in_b' ]\n  [ \"${lines[6]}\" = 'ok 6 quux_in_b' ]\n  [ \"${lines[7]}\" = 'ok 7 quux_in c' ]\n  [ \"${lines[8]}\" = 'ok 8 xyzzy in c' ]\n  [ \"${lines[9]}\" = 'ok 9 plugh_in c' ]\n}\n\n@test \"use --filter to run subset of test cases from across the suite\" {\n  run bats -f 'ba[rz]' \"${FIXTURE_ROOT}/filter\"\n  [ \"$status\" -eq 0 ]\n  [ \"${lines[0]}\" = '1..4' ]\n  [ \"${lines[1]}\" = 'ok 1 --bar in a' ]\n  [ \"${lines[2]}\" = 'ok 2 baz in a' ]\n  [ \"${lines[3]}\" = 'ok 3 bar_in_b' ]\n  [ \"${lines[4]}\" = 'ok 4 --baz_in_b' ]\n\n  local prev_output=\"$output\"\n\n  run bats --filter 'ba[rz]' \"${FIXTURE_ROOT}/filter\"\n  [ \"$status\" -eq 0 ]\n  [ \"$output\" = \"$prev_output\" ]\n}\n\n@test \"--filter can handle regular expressions that contain [_- ]\" {\n  run bats -f '--ba[rz][ _]in' \"${FIXTURE_ROOT}/filter\"\n  [ \"$status\" -eq 0 ]\n  [ \"${lines[0]}\" = '1..2' ]\n  [ \"${lines[1]}\" = 'ok 1 --bar in a' ]\n  [ \"${lines[2]}\" = 'ok 2 --baz_in_b' ]\n}\n\n@test \"--filter can handle regular expressions that start with ^\" {\n  run bats -f '^ba[rz]' \"${FIXTURE_ROOT}/filter\"\n  [ \"$status\" -eq 0 ]\n  [ \"${lines[0]}\" = '1..2' ]\n  [ \"${lines[1]}\" = 'ok 1 baz in a' ]\n  [ \"${lines[2]}\" = 'ok 2 bar_in_b' ]\n}\n\n@test \"skip is handled correctly in setup, test, and teardown\" {\n  bats \"${FIXTURE_ROOT}/skip\"\n}\n\n@test \"BATS_TEST_NUMBER starts at 1 in each individual test file\" {\n  run bats \"${FIXTURE_ROOT}/test_number\"\n  echo \"$output\"\n  [ \"$status\" -eq 0 ]\n}\n\n@test \"Override BATS_FILE_EXTENSION with suite\" {\n  BATS_FILE_EXTENSION=\"test\" run bats \"${FIXTURE_ROOT}/override_BATS_FILE_EXTENSION\"\n  echo \"$output\"\n  [ \"$status\" -eq 0 ]\n  [ \"${#lines[@]}\" -eq 2 ]\n  [ \"${lines[0]}\" = \"1..1\" ]\n  [ \"${lines[1]}\" = \"ok 1 test.test\" ]\n}\n\n@test \"Override BATS_FILE_EXTENSION with suite recursive\" {\n  BATS_FILE_EXTENSION=\"other_extension\" run bats -r \"${FIXTURE_ROOT}/override_BATS_FILE_EXTENSION\"\n  echo \"$output\"\n  [ \"$status\" -eq 0 ]\n  [ \"${#lines[@]}\" -eq 2 ]\n  [ \"${lines[0]}\" = \"1..1\" ]\n  [ \"${lines[1]}\" = \"ok 1 test.other_extension\" ]\n}\n"
  },
  {
    "path": "vendor/bats-core/test/test_helper.bash",
    "content": "emulate_bats_env() {\n  export BATS_CWD=\"$PWD\"\n  export BATS_TEST_FILTER=\n  export BATS_ROOT_PID=$$\n  export BATS_RUN_TMPDIR\n  BATS_RUN_TMPDIR=$(mktemp -d \"${BATS_RUN_TMPDIR}/emulated-tmpdir-${BATS_ROOT_PID}-XXXXXX\")\n}\n\nfixtures() {\n  FIXTURE_ROOT=\"$BATS_TEST_DIRNAME/fixtures/$1\"\n  # shellcheck disable=SC2034\n  RELATIVE_FIXTURE_ROOT=\"${FIXTURE_ROOT#$BATS_CWD/}\"\n}\n\nfilter_control_sequences() {\n  \"$@\" | sed $'s,\\x1b\\\\[[0-9;]*[a-zA-Z],,g'\n}\n\nif ! command -v tput >/dev/null; then\n  tput() {\n    printf '1000\\n'\n  }\n  export -f tput\nfi\n\nemit_debug_output() {\n  # shellcheck disable=SC2154\n  printf '%s\\n' 'output:' \"$output\" >&2\n}\n"
  },
  {
    "path": "vendor/bats-core/test/trace.bats",
    "content": "#!/usr/bin/env bats\n\nsetup() {\n    load test_helper\n    fixtures trace\n}\n\n@test \"no --trace doesn't show anything on failure\" {\n  run -1 bats \"$FIXTURE_ROOT/failing_complex.bats\"\n  [ \"${lines[0]}\" = \"1..1\" ]\n  [ \"${lines[1]}\" = \"not ok 1 a complex failing test\" ]\n  [ \"${lines[2]}\" = \"# (in test file $RELATIVE_FIXTURE_ROOT/failing_complex.bats, line 4)\" ]\n  [ \"${lines[3]}\" = \"#   \\`[ \\$status -eq 0 ]' failed\" ]\n  [ \"${lines[4]}\" = \"# 123\" ]\n  [ ${#lines[@]} -eq 5 ]\n}\n\n@test \"--trace recurses into functions but not into run\" {\n    run -1 bats --trace \"$FIXTURE_ROOT/failing_recursive.bats\"\n    \n    [ \"${lines[0]}\" = '1..1' ]\n    [ \"${lines[1]}\" = 'not ok 1 a recursive failing test' ]\n    [ \"${lines[2]}\" = \"# (in test file $RELATIVE_FIXTURE_ROOT/failing_recursive.bats, line 12)\" ]\n    [ \"${lines[3]}\" = \"#   \\`false' failed\" ]\n    [ \"${lines[4]}\" = '# $ [failing_recursive.bats:9]' ]\n    [ \"${lines[5]}\" = '# $ echo Outer' ]\n    [ \"${lines[6]}\" = '# Outer' ]\n    [ \"${lines[7]}\" = '# $ fun 2' ]\n    [ \"${lines[8]}\" = '# $$ [failing_recursive.bats:2]' ]\n    # shellcheck disable=SC2016\n    [ \"${lines[9]}\" = '# $$ echo \"$1\"' ]\n    [ \"${lines[10]}\" = '# 2' ]\n    # shellcheck disable=SC2016\n    [ \"${lines[11]}\" = '# $$ [[ $1 -gt 0 ]]' ]\n    # shellcheck disable=SC2016\n    [ \"${lines[12]}\" = '# $$ fun $(($1 - 1))' ]\n    [ \"${lines[13]}\" = '# $$$ [failing_recursive.bats:2]' ]\n    # shellcheck disable=SC2016\n    [ \"${lines[14]}\" = '# $$$ echo \"$1\"' ]\n    [ \"${lines[15]}\" = '# 1' ]\n    # shellcheck disable=SC2016\n    [ \"${lines[16]}\" = '# $$$ [[ $1 -gt 0 ]]' ]\n    # shellcheck disable=SC2016\n    [ \"${lines[17]}\" = '# $$$ fun $(($1 - 1))' ]\n    [ \"${lines[18]}\" = '# $$$$ [failing_recursive.bats:2]' ]\n    # shellcheck disable=SC2016\n    [ \"${lines[19]}\" = '# $$$$ echo \"$1\"' ]\n    [ \"${lines[20]}\" = '# 0' ]\n    # shellcheck disable=SC2016\n    [ \"${lines[21]}\" = '# $$$$ [[ $1 -gt 0 ]]' ]\n    [ \"${lines[22]}\" = '# $ [failing_recursive.bats:11]' ]\n    [ \"${lines[23]}\" = '# $ run fun 2' ]\n    [ \"${lines[24]}\" = '# $ false' ]\n\n    # the trace on return from a function differs between bash versions\n    check_bash_5() {\n      [ ${#lines[@]} -eq 25 ]\n    }\n\n    # \"alias\" same behavior to have single point of truth\n    check_bash_4_4() { check_bash_5; }\n    check_bash_4_3() { check_bash_5; }\n    check_bash_4_2() { check_bash_4_0; }\n    check_bash_4_1() { check_bash_4_0; }\n\n    check_bash_4_0() {\n      # bash bug: the lineno from the debug_trap spills over -> ignore it\n      [ \"${lines[25]}\" = '# $ false' ]\n      [ ${#lines[@]} -eq 26 ]\n    }\n\n    check_bash_3_2() {\n      # lineno from function definition\n      [ \"${lines[25]}\" = '# $ false' ]\n      [ ${#lines[@]} -eq 26 ]\n    }\n\n    IFS=. read -r -a bash_version <<< \"${BASH_VERSION}\"\n    check_func=\"check_bash_${bash_version[0]}\"\n    if [[ $(type -t \"$check_func\") != function ]]; then\n      check_func=\"check_bash_${bash_version[0]}_${bash_version[1]}\"\n    fi\n    $check_func\n}"
  },
  {
    "path": "vendor/bats-core/uninstall.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\nBATS_ROOT=\"${0%/*}\"\nPREFIX=\"$1\"\nLIBDIR=\"${2:-lib}\"\n\nif [[ -z \"$PREFIX\" ]]; then\n  printf '%s\\n' \\\n    \"usage: $0 <prefix>\" \\\n    \"  e.g. $0 /usr/local\" >&2\n  exit 1\nfi\n\nd=\"$PREFIX/bin\"\nfor elt in \"$BATS_ROOT/bin\"/*; do\n  elt=${elt##*/}\n  rm -f \"$d/$elt\"\ndone\n\nd=\"$PREFIX/libexec/bats-core\"\nfor elt in \"$BATS_ROOT/libexec/bats-core\"/*; do\n  elt=${elt##*/}\n  rm -f \"$d/$elt\"\ndone\n[[ -d \"$d\" ]] && rmdir \"$d\"\n\nd=\"$PREFIX/${LIBDIR}/bats-core\"\nfor elt in \"$BATS_ROOT/lib/bats-core\"/*; do\n  elt=${elt##*/}\n  rm -f \"$d/$elt\"\ndone\n[[ -d \"$d\" ]] && rmdir \"$d\"\n\nrm -f \"$PREFIX\"/share/man/man1/bats.1\nrm -f \"$PREFIX\"/share/man/man7/bats.7\n\necho \"Uninstalled Bats from $PREFIX/bin/bats\"\n"
  }
]