pax_global_header00006660000000000000000000000064142470670060014520gustar00rootroot0000000000000052 comment=83e1e282f64367c5950dcb46ff39175b8abd1baa git-secret-0.5.0/000077500000000000000000000000001424706700600135705ustar00rootroot00000000000000git-secret-0.5.0/.ci/000077500000000000000000000000001424706700600142415ustar00rootroot00000000000000git-secret-0.5.0/.ci/docker-ci/000077500000000000000000000000001424706700600161015ustar00rootroot00000000000000git-secret-0.5.0/.ci/docker-ci/alma/000077500000000000000000000000001424706700600170135ustar00rootroot00000000000000git-secret-0.5.0/.ci/docker-ci/alma/Dockerfile000066400000000000000000000005271424706700600210110ustar00rootroot00000000000000FROM almalinux:8 LABEL maintainer="mail@sobolevn.me" LABEL vendor="git-secret team" RUN dnf -y update \ && dnf install -y \ # Direct dependencies: bash \ gawk \ git \ gnupg \ # Assumed to be present: diffutils \ file \ findutils \ procps \ make \ && dnf clean all \ && rm -rf /var/cache/yum git-secret-0.5.0/.ci/docker-ci/alpine/000077500000000000000000000000001424706700600173515ustar00rootroot00000000000000git-secret-0.5.0/.ci/docker-ci/alpine/Dockerfile000066400000000000000000000005151424706700600213440ustar00rootroot00000000000000FROM alpine:3.16.0 LABEL maintainer="mail@sobolevn.me" LABEL vendor="git-secret team" # Don't install coreutils on Alpine, # so we get busybox versions of ps, stat, and ls. See #475 RUN apk add --no-cache --update \ # Direct dependencies: bash \ gawk \ git \ gnupg \ # Assumed to be present: file \ make \ procps git-secret-0.5.0/.ci/docker-ci/arch/000077500000000000000000000000001424706700600170165ustar00rootroot00000000000000git-secret-0.5.0/.ci/docker-ci/arch/Dockerfile000066400000000000000000000004231424706700600210070ustar00rootroot00000000000000FROM archlinux:base-20220220.0.48372 LABEL maintainer="mail@sobolevn.me" LABEL vendor="git-secret team" RUN pacman -Syu --needed --noconfirm \ # Direct dependencies: bash \ gawk \ git \ gnupg \ # Assumed to be present: diffutils \ file \ make \ procps git-secret-0.5.0/.ci/docker-ci/debian-gnupg1/000077500000000000000000000000001424706700600205225ustar00rootroot00000000000000git-secret-0.5.0/.ci/docker-ci/debian-gnupg1/Dockerfile000066400000000000000000000010011424706700600225040ustar00rootroot00000000000000FROM debian:11.3-slim LABEL maintainer="mail@sobolevn.me" LABEL vendor="git-secret team" ENV DEBIAN_FRONTEND='noninteractive' ENV SECRETS_GPG_COMMAND='gpg1' RUN apt-get update \ && apt-get install --no-install-recommends -y \ # Direct dependencies: gawk \ git \ gnupg1 \ # Assumed to be present: file \ procps \ make \ # Cleaning cache: && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && apt-get clean -y && rm -rf /var/lib/apt/lists/* git-secret-0.5.0/.ci/docker-ci/debian-gnupg2/000077500000000000000000000000001424706700600205235ustar00rootroot00000000000000git-secret-0.5.0/.ci/docker-ci/debian-gnupg2/Dockerfile000066400000000000000000000007411424706700600225170ustar00rootroot00000000000000FROM debian:11.3-slim LABEL maintainer="mail@sobolevn.me" LABEL vendor="git-secret team" ENV DEBIAN_FRONTEND='noninteractive' RUN apt-get update \ && apt-get install --no-install-recommends -y \ # Direct dependencies: gawk \ git \ gnupg \ # Assumed to be present: file \ procps \ make \ # Cleaning cache: && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && apt-get clean -y && rm -rf /var/lib/apt/lists/* git-secret-0.5.0/.ci/docker-ci/fedora/000077500000000000000000000000001424706700600173415ustar00rootroot00000000000000git-secret-0.5.0/.ci/docker-ci/fedora/Dockerfile000066400000000000000000000005251424706700600213350ustar00rootroot00000000000000FROM fedora:36 LABEL maintainer="mail@sobolevn.me" LABEL vendor="git-secret team" RUN dnf -y update \ && dnf install -y \ # Direct dependencies: bash \ gawk \ git \ gnupg \ # Assumed to be present: diffutils \ file \ findutils \ procps \ make \ && dnf clean all \ && rm -rf /var/cache/yum git-secret-0.5.0/.ci/docker-ci/rocky/000077500000000000000000000000001424706700600172305ustar00rootroot00000000000000git-secret-0.5.0/.ci/docker-ci/rocky/Dockerfile000066400000000000000000000005301424706700600212200ustar00rootroot00000000000000FROM rockylinux:8 LABEL maintainer="mail@sobolevn.me" LABEL vendor="git-secret team" RUN dnf -y update \ && dnf install -y \ # Direct dependencies: bash \ gawk \ git \ gnupg \ # Assumed to be present: diffutils \ file \ findutils \ procps \ make \ && dnf clean all \ && rm -rf /var/cache/yum git-secret-0.5.0/.ci/docker-ci/ubuntu/000077500000000000000000000000001424706700600174235ustar00rootroot00000000000000git-secret-0.5.0/.ci/docker-ci/ubuntu/Dockerfile000066400000000000000000000007351424706700600214220ustar00rootroot00000000000000FROM ubuntu:22.04 LABEL maintainer="mail@sobolevn.me" LABEL vendor="git-secret team" ENV DEBIAN_FRONTEND="noninteractive" RUN apt-get update \ && apt-get install --no-install-recommends -y \ # Direct dependencies: gawk \ git \ gnupg \ # Assumed to be present: file \ procps \ make \ # Cleaning cache: && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && apt-get clean -y && rm -rf /var/lib/apt/lists/* git-secret-0.5.0/.ci/github_release_script.sh000077500000000000000000000020201424706700600211400ustar00rootroot00000000000000#!/usr/bin/env sh set -e # Installing additional deps: apk add --no-cache curl jq # https://gist.github.com/Jaskaranbir/d5b065173b3a6f164e47a542472168c1 USER="$(echo "$GITHUB_REPOSITORY" | cut -d "/" -f1)" PROJECT="$(echo "$GITHUB_REPOSITORY" | cut -d "/" -f2)" LAST_RELEASE_TAG=$(curl \ --header "authorization: Bearer $GITHUB_TOKEN" \ --url "https://api.github.com/repos/$GITHUB_REPOSITORY/releases/latest" \ | jq .tag_name | sed 's/"//g' ) echo "LAST_RELEASE_TAG=$LAST_RELEASE_TAG" if [ "$LAST_RELEASE_TAG" = 'null' ]; then # Most likely, we are facing rate-limiting problems, # just try again later. exit 1 fi NEW_CHANGELOG='CHANGELOG-RELEASE.md' # Generate new CHANGELOG.md with just the last changes github_changelog_generator \ --user "$USER" \ --project "$PROJECT" \ --token "$GITHUB_OAUTH_TOKEN" \ --since-tag "$LAST_RELEASE_TAG" \ --max-issues 100 \ --no-issues \ --release-branch 'master' \ --token "$GITHUB_TOKEN" \ --output "$NEW_CHANGELOG" echo 'Done! Changelog:' cat "$NEW_CHANGELOG" git-secret-0.5.0/.ci/release-ci/000077500000000000000000000000001424706700600162525ustar00rootroot00000000000000git-secret-0.5.0/.ci/release-ci/alma/000077500000000000000000000000001424706700600171645ustar00rootroot00000000000000git-secret-0.5.0/.ci/release-ci/alma/Dockerfile000066400000000000000000000003551424706700600211610ustar00rootroot00000000000000FROM almalinux:8 LABEL maintainer="mail@sobolevn.me" LABEL vendor="git-secret team" RUN dnf -y update \ && dnf install -y \ # Required for our install script: wget \ sudo \ && dnf clean all \ && rm -rf /var/cache/yum git-secret-0.5.0/.ci/release-ci/alpine/000077500000000000000000000000001424706700600175225ustar00rootroot00000000000000git-secret-0.5.0/.ci/release-ci/alpine/Dockerfile000066400000000000000000000002571424706700600215200ustar00rootroot00000000000000FROM alpine:3.15.4 LABEL maintainer="mail@sobolevn.me" LABEL vendor="git-secret team" RUN apk add --no-cache --update \ # Required for our install script: bash \ wget git-secret-0.5.0/.ci/release-ci/debian/000077500000000000000000000000001424706700600174745ustar00rootroot00000000000000git-secret-0.5.0/.ci/release-ci/debian/Dockerfile000066400000000000000000000012671424706700600214740ustar00rootroot00000000000000FROM debian:11.3-slim LABEL maintainer="mail@sobolevn.me" LABEL vendor="git-secret team" ENV DEBIAN_FRONTEND='noninteractive' RUN apt-get update \ && apt-get install --no-install-recommends -y \ # Required to work with https-based repos and custom signed packages: apt-transport-https \ ca-certificates \ # Required for our install script: gnupg \ sudo \ wget \ # Cleaning cache: && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && apt-get clean -y && rm -rf /var/lib/apt/lists/* \ && adduser --disabled-password nonroot \ && adduser nonroot sudo \ && echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers USER nonroot git-secret-0.5.0/.ci/release-ci/fedora/000077500000000000000000000000001424706700600175125ustar00rootroot00000000000000git-secret-0.5.0/.ci/release-ci/fedora/Dockerfile000066400000000000000000000005631424706700600215100ustar00rootroot00000000000000FROM fedora:36 LABEL maintainer="mail@sobolevn.me" LABEL vendor="git-secret team" RUN dnf -y update \ && dnf install -y \ # Required for our install script: wget \ sudo \ && dnf clean all \ && rm -rf /var/cache/yum \ && adduser --password='' -m nonroot \ && echo 'nonroot ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers USER nonroot WORKDIR /home/nonroot git-secret-0.5.0/.ci/release-ci/rocky/000077500000000000000000000000001424706700600174015ustar00rootroot00000000000000git-secret-0.5.0/.ci/release-ci/rocky/Dockerfile000066400000000000000000000003561424706700600213770ustar00rootroot00000000000000FROM rockylinux:8 LABEL maintainer="mail@sobolevn.me" LABEL vendor="git-secret team" RUN dnf -y update \ && dnf install -y \ # Required for our install script: wget \ sudo \ && dnf clean all \ && rm -rf /var/cache/yum git-secret-0.5.0/.ci/release-ci/ubuntu/000077500000000000000000000000001424706700600175745ustar00rootroot00000000000000git-secret-0.5.0/.ci/release-ci/ubuntu/Dockerfile000066400000000000000000000012631424706700600215700ustar00rootroot00000000000000FROM ubuntu:22.04 LABEL maintainer="mail@sobolevn.me" LABEL vendor="git-secret team" ENV DEBIAN_FRONTEND='noninteractive' RUN apt-get update \ && apt-get install --no-install-recommends -y \ # Required to work with https-based repos and custom signed packages: apt-transport-https \ ca-certificates \ # Required for our install script: gnupg \ sudo \ wget \ # Cleaning cache: && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && apt-get clean -y && rm -rf /var/lib/apt/lists/* \ && adduser --disabled-password nonroot \ && adduser nonroot sudo \ && echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers USER nonroot git-secret-0.5.0/.ci/releaser/000077500000000000000000000000001424706700600160435ustar00rootroot00000000000000git-secret-0.5.0/.ci/releaser/alpine/000077500000000000000000000000001424706700600173135ustar00rootroot00000000000000git-secret-0.5.0/.ci/releaser/alpine/Dockerfile000066400000000000000000000017411424706700600213100ustar00rootroot00000000000000# Initially copied from # https://github.com/jordansissel/fpm/blob/master/Dockerfile FROM alpine:3.16.0 SHELL ["/bin/ash", "-eo", "pipefail", "-c"] ENV CODE_DIR='/code' ENV SECRETS_PROJECT_ROOT="$CODE_DIR" ENV NFPM_VERSION='2.15.1' RUN apk add --no-cache --update \ # fpm deps: ruby \ ruby-dev \ ruby-etc \ gcc \ libffi-dev \ make \ libc-dev \ rpm \ tar \ # Direct dependencies: bash \ gawk \ git \ gnupg \ # Assumed to be present: curl \ # envsubst for `nfpm`: gettext \ # Installing `nfpm`, it builds alpine packages: && curl -sfL "https://github.com/goreleaser/nfpm/releases/download/v${NFPM_VERSION}/nfpm_${NFPM_VERSION}_Linux_x86_64.tar.gz" --output 'nfpm.tar.gz' \ && tar -xf 'nfpm.tar.gz' nfpm \ && mv nfpm '/usr/local/bin' \ && chmod 755 '/usr/local/bin/nfpm' \ && rm -rf 'nfpm.tar.gz' \ # Installing `fpm`, it builds all other packages: && gem install --no-document fpm WORKDIR $CODE_DIR git-secret-0.5.0/.editorconfig000066400000000000000000000004501424706700600162440ustar00rootroot00000000000000# Check http://editorconfig.org for more information # This is the main config file for this project: root = true [*] charset = utf-8 indent_style = space trim_trailing_whitespace = true end_of_line = lf insert_final_newline = true indent_size = 2 [Makefile] indent_style = tab indent_size = 4 git-secret-0.5.0/.gitattributes000066400000000000000000000002741424706700600164660ustar00rootroot00000000000000# Excluding from GitHub languages: vendor/ linguist-vendored # Excluding from GitHub diff: *.1 linguist-generated *.7 linguist-generated # Excluding from `git diff`: *.1 -diff *.7 -diff git-secret-0.5.0/.github/000077500000000000000000000000001424706700600151305ustar00rootroot00000000000000git-secret-0.5.0/.github/FUNDING.yml000066400000000000000000000001431424706700600167430ustar00rootroot00000000000000# These are supported funding model platforms github: wemake-services open_collective: git-secret git-secret-0.5.0/.github/ISSUE_TEMPLATE.md000066400000000000000000000020121424706700600176300ustar00rootroot00000000000000 What are the steps to reproduce this issue? ------------------------------------------- 1. … 2. … 3. … What happens? ------------- … What were you expecting to happen? ---------------------------------- … Any logs, error output, etc? ---------------------------- (If it’s long, please paste to https://ghostbin.com/ and insert the link here.) Any other comments? ------------------- … What versions of software are you using? ---------------------------------------- **Operating system:** (`uname -a`) … **`git-secret` path:** (`which git-secret`) … **`git-secret` version:** (`git secret --version`) … **`git` version:** (`git --version`) … **Shell type and version:** (`$SHELL --version`) … **`gpg` version:** (`gpg --version`) … git-secret-0.5.0/.github/PULL_REQUEST_TEMPLATE.md000066400000000000000000000027671424706700600207450ustar00rootroot00000000000000 What does this implement/fix? Explain your changes. --------------------------------------------------- … Does this close any currently open issues? ------------------------------------------ … Any relevant logs, error output, etc? ------------------------------------- (If it’s long, please paste to https://ghostbin.com/ and insert the link here.) Any other comments? ------------------- … git-secret-0.5.0/.github/dependabot.yml000066400000000000000000000032251424706700600177620ustar00rootroot00000000000000# GitHub-native dependabot setup, configuration: # https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/configuration-options-for-dependency-updates version: 2 updates: # Docs and GitHub Actions: - package-ecosystem: bundler directory: "/docs" schedule: interval: daily - package-ecosystem: github-actions directory: "/" schedule: interval: daily # Our CI and release docker images: - package-ecosystem: docker directory: ".ci/releaser/alpine" schedule: interval: weekly # Release CI: - package-ecosystem: docker directory: ".ci/release-ci/alpine" schedule: interval: weekly - package-ecosystem: docker directory: ".ci/release-ci/debian" schedule: interval: weekly - package-ecosystem: docker directory: ".ci/release-ci/ubuntu" schedule: interval: weekly - package-ecosystem: docker directory: ".ci/release-ci/centos" schedule: interval: weekly - package-ecosystem: docker directory: ".ci/release-ci/fedora" schedule: interval: weekly # Docker CI: - package-ecosystem: docker directory: ".ci/docker-ci/alpine" schedule: interval: weekly - package-ecosystem: docker directory: ".ci/docker-ci/debian-gnupg1" schedule: interval: weekly - package-ecosystem: docker directory: ".ci/docker-ci/debian-gnupg2" schedule: interval: weekly - package-ecosystem: docker directory: ".ci/docker-ci/ubuntu" schedule: interval: weekly - package-ecosystem: docker directory: ".ci/docker-ci/centos" schedule: interval: weekly - package-ecosystem: docker directory: ".ci/docker-ci/fedora" schedule: interval: weekly git-secret-0.5.0/.github/workflows/000077500000000000000000000000001424706700600171655ustar00rootroot00000000000000git-secret-0.5.0/.github/workflows/build-man.yml000066400000000000000000000006471424706700600215670ustar00rootroot00000000000000 name: build-man on: push: branches: - master paths: - 'docs/**/*' pull_request: paths: - 'docs/**/*' workflow_dispatch: concurrency: group: ${{ github.head_ref || github.run_id }}-build-man cancel-in-progress: true jobs: build-man: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Checks that manual generation works run: make build-man git-secret-0.5.0/.github/workflows/github-pages.yml000066400000000000000000000013141424706700600222660ustar00rootroot00000000000000name: github-pages on: push: branches: - master paths: - 'man/**/*' - 'docs/**/*' - 'utils/*/install.sh' concurrency: group: ${{ github.head_ref || github.run_id }} cancel-in-progress: true jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Build docs run: make build-docs - name: Deploy to Pages uses: JamesIves/github-pages-deploy-action@v4.3.3 with: token: ${{ secrets.GITHUB_TOKEN }} branch: gh-pages # The branch the action should deploy to. folder: docs # The folder the action should deploy. clean: true # Automatically remove deleted files from the deploy branch git-secret-0.5.0/.github/workflows/release-ci.yml000066400000000000000000000047371424706700600217340ustar00rootroot00000000000000name: release-ci on: workflow_dispatch: schedule: - cron: '0 0 * * *' # In case we change the some build scripts: push: branches: - master paths: - 'utils/**' - '.ci/release-ci/**' - 'Makefile' - '.github/workflows/release-ci.yml' pull_request: paths: - 'utils/**' - '.ci/release-ci/**' - 'Makefile' - '.github/workflows/release-ci.yml' concurrency: group: ${{ github.head_ref || github.run_id }} cancel-in-progress: true jobs: existing: runs-on: ubuntu-latest strategy: matrix: include: - release-type: deb release-env: debian - release-type: deb release-env: ubuntu - release-type: rpm release-env: fedora - release-type: rpm release-env: rocky - release-type: rpm release-env: alma - release-type: apk release-env: alpine steps: - uses: actions/checkout@v3 - name: Run checks run: | SECRETS_RELEASE_ENV="${{ matrix.release-env }}" \ SECRETS_RELEASE_TYPE="${{ matrix.release-type }}" \ make release-ci # Keep in sync with `release.yml`: dryrun: runs-on: ubuntu-latest strategy: matrix: release-type: - apk - deb - rpm steps: - uses: actions/checkout@v3 - name: Run dry run of the release process run: | SECRETS_RELEASE_TYPE="${{ matrix.release-type }}" \ SECRETS_DEPLOY_DRY_RUN=1 \ SECRETS_ARTIFACTORY_CREDENTIALS='fake' \ make release # https://github.community/t/run-github-actions-job-only-if-previous-job-has-failed/174786/2 create-issue-on-failure: name: Create an issue if release-ci cron failed runs-on: ubuntu-latest needs: [existing, dryrun] if: ${{ github.event_name == 'schedule' && github.repository == 'sobolevn/git-secret' && always() && (needs.existing.result == 'failure' || needs.dryrun.result == 'failure') }} permissions: issues: write steps: - uses: actions/github-script@v6 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | await github.rest.issues.create({ owner: "sobolevn", repo: "git-secret", title: `release-ci failure on ${new Date().toDateString()}`, body: "Details: https://github.com/sobolevn/git-secret/actions/workflows/release-ci.yml", }) git-secret-0.5.0/.github/workflows/release.yml000066400000000000000000000020051424706700600213250ustar00rootroot00000000000000name: release on: push: tags: - 'v*' workflow_dispatch: concurrency: group: ${{ github.head_ref || github.run_id }} jobs: release-packages: environment: name: artifactory url: https://gitsecret.jfrog.io/artifactory runs-on: ubuntu-latest strategy: matrix: release-type: - apk - deb - rpm steps: - uses: actions/checkout@v3 - name: Run checks run: SECRETS_RELEASE_TYPE="${{ matrix.release-type }}" make release env: SECRETS_ARTIFACTORY_CREDENTIALS: ${{ secrets.SECRETS_ARTIFACTORY_CREDENTIALS }} github-release: runs-on: ubuntu-latest needs: ['release-packages'] steps: - uses: actions/checkout@v3 - run: make changelog env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - uses: softprops/action-gh-release@v1 with: # Generated above by `make changelog`: body_path: CHANGELOG-RELEASE.md env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} git-secret-0.5.0/.github/workflows/test.yml000066400000000000000000000033531424706700600206730ustar00rootroot00000000000000name: test on: push: branches: - master paths-ignore: - 'docs/**' pull_request: paths-ignore: - 'docs/**' workflow_dispatch: concurrency: group: ${{ github.head_ref || github.run_id }}-test cancel-in-progress: true jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Shellcheck and Hadolint run: make lint docker-ci: runs-on: ubuntu-latest strategy: matrix: docker-env: - alma - alpine - arch - debian-gnupg1 # We need to test legacy version of gnupg - debian-gnupg2 - fedora - rocky - ubuntu steps: - uses: actions/checkout@v3 - name: Run checks run: SECRETS_DOCKER_ENV="${{ matrix.docker-env }}" make docker-ci osx-ci: runs-on: macos-latest strategy: matrix: test-verbose: [0, 1] steps: - uses: actions/checkout@v3 - name: Install deps run: brew install gawk gnupg - name: Run checks run: SECRETS_TEST_VERBOSE=${{ matrix.test-verbose }} make test freebsd-ci: runs-on: macos-10.15 steps: - uses: actions/checkout@v3 - name: Run checks id: test uses: vmactions/freebsd-vm@v0.1.6 with: usesh: true prepare: pkg install -y gnupg bash gmake git gawk run: | which -a bash which -a shell gmake test windows-wsl-ci: runs-on: windows-latest steps: - uses: Vampire/setup-wsl@v1 with: update: 'true' additional-packages: gnupg make man git gawk file - run: git config --global core.autocrlf input - uses: actions/checkout@v3 - shell: wsl-bash {0} run: make test git-secret-0.5.0/.gitignore000066400000000000000000000043151424706700600155630ustar00rootroot00000000000000#### joe made this: http://goel.io/joe #####=== Windows ===##### # Windows image file caches Thumbs.db ehthumbs.db # Folder config file Desktop.ini # Recycle Bin used on file shares $RECYCLE.BIN/ # Windows Installer files *.cab *.msi *.msm *.msp # Windows shortcuts *.lnk #####=== Linux ===##### *~ # KDE directory preferences .directory # Linux trash folder which might appear on any partition or disk .Trash-* #####=== MacOS ===##### .DS_Store .AppleDouble .LSOverride # Icon must end with two \r Icon # Thumbnails ._* # Files that might appear on external disk .Spotlight-V100 .Trashes # Directories potentially created on remote AFP share .AppleDB .AppleDesktop Network Trash Folder Temporary Items .apdisk #####=== JetBrains ===##### # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm *.iml ## Directory-based project format: .idea/ # if you remove the above rule, at least ignore the following: # User-specific stuff: # .idea/workspace.xml # .idea/tasks.xml # .idea/dictionaries # Sensitive or high-churn files: # .idea/dataSources.ids # .idea/dataSources.xml # .idea/sqlDataSources.xml # .idea/dynamic.xml # .idea/uiDesigner.xml # Gradle: # .idea/gradle.xml # .idea/libraries # Mongo Explorer plugin: # .idea/mongoSettings.xml ## File-based project format: *.ipr *.iws ## Plugin-specific files: # IntelliJ out/ # mpeltonen/sbt-idea plugin .idea_modules/ # JIRA plugin atlassian-ide-plugin.xml # Crashlytics plugin (for Android Studio and IntelliJ) com_crashlytics_export_strings.xml crashlytics.properties crashlytics-build.properties #####=== SublimeText ===##### # cache files for sublime text *.tmlanguage.cache *.tmPreferences.cache *.stTheme.cache # workspace files are user-specific *.sublime-workspace # project files should be checked into the repository, unless a significant # proportion of contributors will probably not be using SublimeText # *.sublime-project # sftp configuration file sftp-config.json #####=== Jekyll ===##### _site/ .sass-cache/ #####=== Custom ===##### # Logic files: .gitsecret/ git-secret # Temporary packages: temp/ # Packaging: build/ *.deb *.fpm # Docs: docs/man docs/_posts docs/_includes/install-*.sh docs/_includes/version.txt CHANGELOG-RELEASE.md git-secret-0.5.0/CHANGELOG.md000066400000000000000000000303271424706700600154060ustar00rootroot00000000000000# Changelog ## {{Next Version}} ### Features - Adds `SECRETS_GPG_ARMOR` env variable to use `gpg --armor` when encrypting files, so secret files are stored in text format rather than binary (#631) - Allow gnupg permission warnings in `tell`, `hide`, `reveal`, and `removeperson` (#811) - `git secret init` now sets `.gitsecret/keys` permission to 0700 (#811) - Improve verbose and non-verbose output ### Bugfixes - Fix adding newlines to `.gitignore` entries (#643) - Fix `cat` and `reveal` on named files while in repo subdir (#710) - Fix `clean`, `hide`, `reveal` so they only remove marked secret files (#833) - Fix for `removeperson` if same email is present multiple times (#638) - Correct error message about files missing from .gitignore ### Misc - Rename `killperson` command to `removeperson` (#684) - Improve error messaging decrypting nonexistent files (#706) - Improve, expand, correct, and update docs (#699) - Update docs for use with CI/CD server (#675) - Upgrade bats-core to v1.6.0 (#755) - Test, and build RPMS, with Rocky and Alma Linux instead of CentOS (#765) - Automate testing code on windows using WSL (#846) - Automate testing code on FreeBSD (#455) - Improve testing of .gitignore contents (#792) - Automate running verbose tests with SECRETS_TEST_VERBOSE=1 (#794) - Improve documentation about installing on Windows (#843) ## 0.4.0 ### Bugfixes - Escape filenames with special characters before adding to `.gitignore` - Better error handling around telling an email twice (#634) - Fix for `-P` (#647) ### Misc - Removed `test-kitchen` - Moved from `travis` to GitHub Actions - Changed almost all infrastructure code - Moved away from Bintray to Artifactory - Changes how GitHub Pages work - Add security disclaimer for git-secret-killperson - Improve documentation about releases - Man page improvements ## Version 0.3.3 ### Bugfixes - In 'tell', warn about disabled, revoked, expired, or invalid keys (#552, #508, #317, #290, #283, #238) - Error if 'tell' is used on an email address with multiple keys (#552) - Don't let 'reveal' clobber secret files (#579) - Updated test key fixture that had expired (#607) ### Misc - Improve docs about using gpg with git-secret (#577) - Text improvements and More about security in git-secret.7 man page (#603) - Reflect changes in ruby bundler during build process - Upgrade build process to ansible 2.9 - Use shellcheck 0.7.1 with CI, not 'latest' (#609) - Improve output of `git-secret add` ## Version 0.3.2 ### Bugfixes - Fix mention of version in git-secret add man page (#544) ### Misc - Update developer docs, especially regarding mac, docker, and test-kitchen (#195) - Update man pages to mention version documented (#420) ## Version 0.3.1 ### Misc - Update man pages ## Version 0.3.0 ### Features - Support SECRETS_PINENTRY env var for gnupg --pinentry-mode parameter (#221) - Show output from gnupg if 'hide' fails (#516, #202, #317) - Add support for Busybox (#478) ### Bugfixes - Use OSX's mktemp on OSX, even if there's another version in PATH. (#485) - Make rsync a build requirement on debian (#500) - Use gnupg1, not gnupg2, when tests specify gnupg1 (#241) - Note dependencies gawk, bash, and coreutils in linux packages (#493) - Handle case of key having no email and a comment (#527) - Avoid blank lines from output of 'clean -v' ### Misc - Improve messaging and logic around deleting tmp files. - Add note about secrets and old keys (#499) - Transition build process from python 2 to python 3 (#487) - Upgrade build process from ansible 2.5 to ansible 2.8 - Fix build process when installing gnupg2 source deps on Ubuntu - Close file descriptor 3 when running gnupg subprocesses (#521) - Small optimization in 'hide' - Improve code comments - Update docs to note that git-secret repos modified by git-secret 0.2.3 and later are not backward compatible with pre-0.2.3 versions of git-secret. (#536) ## Version 0.2.6 ### Features - git-secret is now available in Fedora, link added to README.md. (#315) - Support automated testing on windows with Travis CI (#372) - Support SECRETS_VERBOSE env var to enable verbosity (#323) - Use gpg without --quiet when decrypting in verbose mode (#394) - Add -v options to 'tell' and 'reveal', showing gpg output (#320, #395) - Change 'init' to never ignore .secret files (#362) - 'add' appends filepaths to .gitignore by default (#225) - Automate the GitHub release (#411) ### Bugfixes - Fix 'hide -m' when used as first hide operation (#466) - Fix code to respect $TMPDIR when generating tmp files (#451) - Be more careful when deleting test files (#360) - Use separate directory when testing, instead of using $BATS_TMPDIR directly (#407) - Fix 'whoknows -l' and related tests on FreeBSD (#454) - Fix git-secret init when used on busybox (#475) - Update git-secret.io, fix utils/gh-branch.sh to use 'git all --add' (#344) - Fix link to homebrew's git-secret in README.md (#310) - Remove diagnostic output from test results (#324) - Remove un-needed redirection in 'reveal' (#325) - Fix link to current contributors in CONTRIBUTING.md (#331) - Fix tests when running from git hooks (#334) - Fix typo, remove temp directory in utils/tests.sh (#347) - Spelling fixes - Fix re: SECRETS_DIR in 'init' and SECRETS_EXTENSION in test_reveal.bats (#364) - git-secret will fail if you pass params or filenames that are not understood (#390) - Use SECRETS_GPG_COMMAND env var in gpg version check (#389) - Add header to git-secret.7 man page, for debian and doc improvement (#386) - Respect DESTDIR when installing as per GNU/debian/etc recommendations (#424) - Use git check-ignore to test for files ignored by git ### Misc - Improve docs about hide -m option (#467) - Document SECRETS_VERBOSE and improve env var docs (#396) - Setting SECRETS_TEST_VERBOSE env var shows debug info during tests (EXPERIMENTAL) - Add documentation about how to write tests. - Suppress 'cleaning up temp files' messages unless in a verbose mode. - Improve git-secret user messaging. - Update CHANGELOG.md to mention fix for #281 in v0.2.5 (#311) - Add text explaining git-secret Style Guide and Development Philosophy - Use Shellcheck on tests/ files, changes for Shellcheck in tests/ (#368) - Use Shellcheck on MacOS/osx travis tests (#403) - Show commands run by Makefile as per debian upstream recommendations (#386) - Upgrade bats-core to v1.1.0, import bats-core into vendor/bats-core (#377) - Use gawk to parse emails from gpg output - Optimize code that parses keyrings - Remove unused code ## Version 0.2.5 ### Features - Add support for FreeBSD (#244) - Add -l option to whoknows, which shows key expiration dates (#283) - Add -P option (preserve permissions) to reveal and hide (#172) - Add -F option (force, changing some errors to warnings) to hide and reveal (#253) - Allow user to specify name of secret dir at runtime using SECRETS_DIR env var, and test (#247, #250) ### Bugfixes - Fix issues with spaces in paths and filenames (#226, #135) - Fix issue when 'hide' used in subdir of repo (#230) - Fix issues in 'changes' with trailing newlines (#291) - Fix 'hide' to only count actually hidden files as hidden (#280) - Fixed bugs and improved error messages (#174) - Issue error message when unable to hide a secret (#202, #238) - Accept gpg key with no name, only an email (#227) - Require keys to be specified by email, as documented (#267) - Disallow 'git secret tell' or 'killperson' with emails that are not in keyring (also #267) ### Misc - Added notes about packages and for package maintainers (#281) - Improve documentation regarding operation with different versions of GPG (#274, #182) - Documentation improvements, error message and text improvements, and typo fixes (#254) - git-secret RFC#001 added, documenting a path towards independence from gpg binary formats (#208) - Add tests for expired gpg keys, and gpg keys with only emails (#276) ## Version 0.2.4 ### Features - Added `git secret cat` feature (#141) ### Bugfixes - `git secret hide` and `git secret changes` check for files more carefully (#153, #154) ### Misc - Documentation and error message improvements (#126, #136, #144, #150) - Build and CI fixes (#152, #179, #186, #188, #189) - Migrate to `bats-core` bash testing framework ## Version 0.2.3 ### Features - Added `-m` option to `hide` command, files will only be hidden when modifications are detected (#92) - Changed how path mappings file works: colon delimited FSDB in `.gitsecret/paths/mapping.cfg', so git-secret can store checksums of hidden files. Note this means git-secret repos modified by git-secret 0.2.3 or later are not backward compatible with pre-0.2.3 versions of git-secret. (#92) - `git secret init` now adds `random_seed` to `.gitignore` (#93) ### Bugfixes - Dropped `git check-ignore`, using `git add --dry-run` instead to check for ignored files (#105,#38) - Fixed `gnupg` >= 2.1 CI tests (#6) ### Misc - Now users can run local CI tests using test-kitchen (#6) - Migrated travis ci tests to test-kitchen for Linux platforms. - Added more `gpg` version to test matrix (#99) - Added CentOS to test matrix (#38,#91) - All tested Linux platforms now use latest release of `shellcheck` - Added Alpine to test matrix, and apk is now built. (#75) ## Version 0.2.2 ### Features - Change how the `usage` command works (#48) - Now `git-secret` works from any place inside `git-tree` (#56) - Added `-d` option to the `hide` command: it deletes unencrypted files (#62) - Added new command `changes` to see the diff between the secret files (#64) - Now it is possible to provide multiple emails to the `killperson` command (#73) - Now it is possible to provide multiple emails to the `tell` command (#72) ### Bugfixes - Fixed bug when `_user_required` was not working after re-importing keys (#74) - Refactored `hide` and `clean` commands to be shorter ### Misc - Now every doc in this project refer to `git-secret.io` instead of old `gh-pages` website (#71) - Now installation section is removed from main `man` file (#70) - Now "See also" sections in the `man` pages are clickable (#69) - Added "Manual" section to the manuals (#61) - Added `CentOS` container for `ci` testing (#38) - 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) - `shellcheck` is now supported with `make lint` ## Version 0.2.1 ### Misc - Added `CONTRIBUTING.md` and `LICENSE.md`. - New brand logo in the `README.md`. - Added autodeploy to `bintray` in `.travis.yml`. - Now everything is tested inside the `docker`-containers and `OSX` (MacOS) images on `travis`. - Added `.ci/` folder for continuous integration, refactored `utils/` folder. - Everything is `shellcheck`ed (except `tests/`). ## Version 0.2.0 ### Features - Added `changes` command to see the difference between current version of the hidden files and the committed one - Added `-f` option to the `reveal` command to remove prompts ### Bugfixes - Some bugs are fixed ### Misc - New installation instructions - Changed the way files were decrypted, now it is a separate function ## Version 0.1.2 ### Features - Added `-i` option to the `git-secret-add` command, which auto adds unignored files to the `.gitignore` ### Misc - `.github` templates added - Documentation improved with `Configuration` section - `Makefile` improvements with `.PHONY` and `install` target - Added extra tests: for custom filenames and new features ## Version 0.1.1 ### Features - Added `--dry-run` option to the `git secret` command, which prevents any actions. ### Misc - Removed animation from docs, now using `asciinema.org` - `install_full_fixture()` returns a fingerprint - `uninstall_full_fixture()` receives two args - Fixed bug when tests were failing with `gpg2` - New travis strategy: testing both `gpg` and `gpg2` ## Version 0.1.0 ### Features - Implementation of git secret add - Implementation of git secret clean, with -v option - Implementation of git secret hide, with -c 'clean' and -v option - Implementation of git secret init - Implementation of git secret killperson - Implementation of git secret list - Implementation of git secret remove, with -c option - Implementation of git secret reveal, with -d homedir and -p passphrase options - Implementation of git secret tell, with -m email and -d homedir options - Implementation of git secret usage git-secret-0.5.0/CONTRIBUTING.md000066400000000000000000000237031424706700600160260ustar00rootroot00000000000000# Contributing Your contributions are always welcome! ## Getting started 1. 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) 2. Fork the git-secret repo and then clone the repository using a command like `git clone https://github.com/${YOUR_NAME}/git-secret.git` 3. Make sure that everything works on the current platform by running `make test`. You can also try the experimental `SECRETS_TEST_VERBOSE=1 make test`, which will show you a lot of debug output while the tests are running. Note that 'experimental' features may change or be removed in a future version of `git-secret`. 4. If you want to test on multiple operating systems just push your PR, GitHub Actions will cover everything else Basically, our `make` file is the only thing you will need to work with this repo. ## Process ### Environment For development of `git-secret` you should have these tools locally: - git - bash - gawk - gnupg (or gnupg2), see below if not packaged by your distribution/OS (i.e. MacOS) - sha256sum (on freebsd and MacOS `shasum` is used instead) - make To test `git-secret` you will need: - [docker](https://www.docker.com/) ### Code style New features and changes should aim to be as clear, concise, simple, and consistent 1. clear: make it as obvious as possible what the code is doing 2. concise: your PR should be as few characters (not just lines) of changes as _reasonable_. However, generally choose clarity over being concise. Clarity and conciseness can be in conflict with each other. But it's more important for the code to be understandable than for it to be small. Therefore favor writing clear code over making shorter diffs in your PRs. 3. simple: this dovetails with the previous two items. git-secret is a security product, so it's best to have the code be easy to understand. This also aids future development and helps minimize bugs. 4. consistent: Write code that is consistent with the surrounding code and the rest of the git-secret code base. Every code base has its own conventions and style that develop and accrete over time. Consistency also means that the inputs and outputs of git-secret should be as consistent as reasonable with related Unix and git tools, and follow the 'rule of least surprise', also known as the 'principle of least astonishment': We wrote this to clarify our thinking about how git-secret should be written. Of course, these are philosophical goals, not necessities for releasing code, so balancing these four ideals _perfectly_ is both unwarranted and impossible. ### Writing PRs If you're planning a large change to `git-secret` (for example, a lot of lines/characters of diffs, affecting multiple commands, changing/adding a lot of behavior, or adding multiple command-line options), it's best to discuss the changes in an Issue first. Also it's often best to implement larger or complex changes as a series of planned-out, smaller PRs, each making a small set of specific changes. This facilitates discussions of implementation, which often come to light only after seeing the actual code used to perform a task. As mentioned above, we seek to be consistent with surrounding git and Unix tools, so when writing changes to git-secret, think about the input, output, and command-line options that similar Unix commands use. Our favor toward traditional Unix and git command-style inputs and outputs can also mean it's appropriate to lean heavily on git and widely-used Unix command features instead of re-implementing them in code. ### Development Process 1. Make changes to the git secret files that need to be changed 2. 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` 3. Run `shellcheck` against all your changes with `make lint`. You should also check your changes for spelling errors using 'aspell -c filename'. 4. Add an entry to CHANGELOG.md, referring to the related issue # if appropriate 5. Change the `man` source file(s) (we write them in markdown) in `man/man1` and `man/man7` to document your changes if appropriate 6. Now, add all your files to the commit with `git add --all` and commit changes with `git commit`. Write a good commit message which explains your work 7. When running `git commit` the tests will run automatically, your commit will be canceled if they fail. You can run the tests manually with `make clean build test`. 8. Push to your repository, and make a pull-request against `master` branch. It's ideal to have one commit per pull-request, but don't worry, it's easy to `squash` PRs into a small number of commits when they're merged. ### Branches We have two long-live branches: `master` for the git-secret code and man pages, and `gh-pages` for the static web site. The `gh-pages` branch tracks the `master` branch's `docs` folder, and is kept up-to-date using a GitHub Action. Development looks like this: > `your-branch` -> `master` - `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 By convention, you can name your branches like `issue-###-short-description`, but that's not required. The `gh-pages` branch is used for the pages at `git-secret.io`. See 'Release Process' below. ### Writing tests `git-secret` uses [bats-core](https://github.com/bats-core/bats-core) for testing. See the files in tests/ and the `bats-core` documentation for details. Because the output of many commands can be affected by the SECRETS_VERBOSE environment variable (which enables verbosity), it's best not to expect a particular number of lines of output from commands. ### Release process To create a new release, (you'll first need permission to commit to the repo, of course): Update the content of `CHANGELOG.md` for the release (this should be a matter of changing headers), and update the version string in `src/version.sh`. When creating a commit inside the `master` branch (it is usually a documentation and changelog update with the version bump inside `src/version.sh`). Then, push your code to GitHub. It will start the CI. After all the checks have executed, GitHub Actions will test and build releases for specific platforms. While CI is doing it's building and testing, finish the release on github by pushing the new tag with: ```bash git push --tags ``` and then go to https://github.com/sobolevn/git-secret/releases to see that the new release is created. It might take some time. #### GitHub automated releases We use GitHub actions to run the release process. We use `artifactory` as an environment for the release. You would need to get a review before release would be possible. It can be reproduced locally with `make release`, but you will need `SECRETS_ARTIFACTORY_CREDENTIALS`. After packages are released to https://gitsecret.jfrog.io we trigger `release-ci` workflow to test that installation works correctly. #### Manual releases Releases to `brew` are made manually, and involve opening a PR on the [Homebrew Core](https://github.com/Homebrew/homebrew-core) repo . To get started, see the [Homebrew docs about Formulae-related PRs](https://docs.brew.sh/How-To-Open-a-Homebrew-Pull-Request#formulae-related-pull-request) and `brew bump-formula-pr --help` ### Downstream Packages There 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). ### Notes to Downstream Packagers (Those who make packages for specific OSes/distributions) First of all, thank you for packaging git-secret for your platform! We appreciate it. We also would like to welcome you to collaborate or discuss any issues, ideas or thoughts you have about git-secret by submitting [issue report](https://github.com/sobolevn/git-secret/issues) (which can also be feature requests) or [pull requests](https://help.github.com/en/articles/creating-a-pull-request) via the git repo at [git-secret on github](https://github.com/sobolevn/git-secret) Please let us know if there are any changes you'd like to see to the source, packaging, testing, documentation, or other aspect of git-secret. We look forward to hearing from you. ## About GnuPG Here are some links to gnupg documentation that might be useful for those working with git-secret: - [GnuPG PDF Documentation](https://www.gnupg.org/documentation/manuals/gnupg.pdf) - [GnuPG doc/DETAILS File](https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/DETAILS) ## Financial contributions We also welcome financial contributions in full transparency on our [open collective](https://opencollective.com/git-secret). Anyone 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. ## Credits ### Contributors Thank you to all the people who have already contributed to `git-secret` via commits to our git repository! [![List of contributors](https://opencollective.com/git-secret/contributors.svg?width=890&button=0)](https://github.com/sobolevn/git-secret/contributors) ### Backers Thank you to all our backers! [[Become a backer](https://opencollective.com/git-secret#backer)] ### Sponsors Thank 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)) git-secret-0.5.0/LICENSE.md000066400000000000000000000020571424706700600152000ustar00rootroot00000000000000MIT License Copyright (c) 2016 Nikita Sobolev Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. git-secret-0.5.0/Makefile000066400000000000000000000107521424706700600152350ustar00rootroot00000000000000SHELL:=bash PREFIX?="/usr" DESTDIR?= # # Building: # .PHONY: all all: build .PHONY: clean clean: @rm -f git-secret .PHONY: build build: @cat src/version.sh > git-secret @cat src/_utils/*.sh src/commands/*.sh >> git-secret @cat src/main.sh >> git-secret @chmod +x git-secret; sync .PHONY: install install: "${SHELL}" ./utils/install.sh "${DESTDIR}${PREFIX}" .PHONY: uninstall uninstall: "${SHELL}" ./utils/uninstall.sh "${DESTDIR}${PREFIX}" # # Testing and linting: # # The $(shell echo $${PWD}) construct is to access *nix paths under windows # Under git for windows '$PATH' is set to windows paths, e.g. C:\Something # Using a sub-shell we get the raw *nix paths, e.g. /c/Something .PHONY: test test: clean build export SECRETS_PROJECT_ROOT="$(shell echo $${PWD})"; \ export PATH="$(shell echo $${PWD})/vendor/bats-core/bin:$(shell echo $${PWD}):$(shell echo $${PATH})"; \ "${SHELL}" ./utils/tests.sh # We use this script in CI and you can do this too! # What happens here? # 1. We pass `SECRETS_DOCKER_ENV` variable into this job # 2. Based on it, we select a proper `docker` image to run test on # 3. We execute `make test` inside the `docker` container .PHONY: docker-ci docker-ci: clean @[ -z "${SECRETS_DOCKER_ENV}" ] \ && echo 'SECRETS_DOCKER_ENV is unset' && exit 1 || true docker build \ -f ".ci/docker-ci/$${SECRETS_DOCKER_ENV}/Dockerfile" \ -t "gitsecret-$${SECRETS_DOCKER_ENV}:latest" . docker run --rm \ --volume="$${PWD}:/code" \ -w /code \ "gitsecret-$${SECRETS_DOCKER_ENV}" \ make test .PHONY: lint-shell lint-shell: docker pull koalaman/shellcheck:latest docker run \ --volume="$${PWD}:/code" \ -w /code \ -e SHELLCHECK_OPTS='-s bash -S style -a' \ --rm koalaman/shellcheck \ $$(find src .ci utils tests docs -type f \ -name '*.sh' -o -name '*.bash' -o -name '*.bats') .PHONY: lint-docker lint-docker: docker pull hadolint/hadolint:latest-alpine docker run \ --volume="$${PWD}:/code" \ -w /code \ --rm hadolint/hadolint \ hadolint \ --ignore=DL3008 --ignore=DL3018 --ignore=DL3041 --ignore=DL3028 \ .ci/*/**/Dockerfile .PHONY: lint lint: lint-shell lint-docker # # Manuals and docs: # .PHONY: clean-man clean-man: @find "man/" -type f ! -name "*.md" -delete .PHONY: build-man build-man: build docker pull msoap/ruby-ronn export GITSECRET_VERSION="$$(./git-secret --version)" && docker run \ --volume="$${PWD}:/code" \ -w /code \ --rm msoap/ruby-ronn \ ronn --roff \ --organization=sobolevn \ --manual="git-secret $${GITSECRET_VERSION}" \ man/*/*.md .PHONY: build-docs build-docs: build-man "${SHELL}" docs/build.sh .PHONY: docs docs: build-docs docker pull jekyll/jekyll docker run \ --volume="$${PWD}/docs:/code" \ -w /code \ -p 4000:4000 \ --rm jekyll/jekyll \ jekyll serve --safe --strict_front_matter .PHONY: changelog changelog: @[ -z "${GITHUB_REPOSITORY}" ] \ && echo 'GITHUB_REPOSITORY is unset' && exit 1 || true @[ -z "${GITHUB_TOKEN}" ] \ && echo 'GITHUB_TOKEN is unset' && exit 1 || true docker pull githubchangeloggenerator/github-changelog-generator docker run \ --volume="$${PWD}:/code" \ -w /code \ --entrypoint='' \ -e GITHUB_REPOSITORY \ -e GITHUB_TOKEN \ --rm githubchangeloggenerator/github-changelog-generator \ sh ".ci/github_release_script.sh" # # Packaging: # .PHONY: build-release build-release: clean build-man @[ -z "${SECRETS_RELEASE_TYPE}" ] \ && echo 'SECRETS_RELEASE_TYPE is unset' && exit 1 || true docker build \ -f ".ci/releaser/alpine/Dockerfile" \ -t "gitsecret-releaser:latest" . docker run \ --volume="$${PWD}:/code" \ --rm gitsecret-releaser \ bash "./utils/$${SECRETS_RELEASE_TYPE}/build.sh" .PHONY: release release: build-release @[ -z "${SECRETS_ARTIFACTORY_CREDENTIALS}" ] \ && echo 'SECRETS_ARTIFACTORY_CREDENTIALS is unset' && exit 1 || true docker run \ --volume="$${PWD}:/code" \ -e SECRETS_ARTIFACTORY_CREDENTIALS \ -e SECRETS_DEPLOY_DRY_RUN \ --rm gitsecret-releaser \ bash "./utils/$${SECRETS_RELEASE_TYPE}/deploy.sh" .PHONY: release-ci release-ci: @[ -z "${SECRETS_RELEASE_ENV}" ] \ && echo 'SECRETS_RELEASE_ENV is unset' && exit 1 || true @[ -z "${SECRETS_RELEASE_TYPE}" ] \ && echo 'SECRETS_RELEASE_TYPE is unset' && exit 1 || true docker build \ -f ".ci/release-ci/$${SECRETS_RELEASE_ENV}/Dockerfile" \ -t "gitsecret-release-$${SECRETS_RELEASE_ENV}:latest" . docker run --rm \ --volume="$${PWD}:/code" \ -w /code \ "gitsecret-release-$${SECRETS_RELEASE_ENV}" \ bash -c "set -e; bash "./utils/$${SECRETS_RELEASE_TYPE}/install.sh"" git-secret-0.5.0/README.md000066400000000000000000000120611424706700600150470ustar00rootroot00000000000000# git-secret [![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) [![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) [![Homebrew](https://img.shields.io/homebrew/v/git-secret.svg)](https://formulae.brew.sh/formula/git-secret) [![Supporters](https://img.shields.io/opencollective/all/git-secret.svg?color=gold&label=supporters)](https://opencollective.com/git-secret) [![git-secret](https://raw.githubusercontent.com/sobolevn/git-secret/gh-pages/images/git-secret-big.png)](https://git-secret.io/) ## What is `git-secret`? `git-secret` is a bash tool which stores private data inside a git repo. `git-secret` encrypts files with permitted users' public keys, allowing users you trust to access encrypted data using pgp and their secret keys. With `git-secret`, changes to access rights are simplified, and private-public key issues are handled for you. When someone's permission is revoked, secrets do not need to be changed with `git-secret` - just remove their key from the repo's keyring using `git secret removeperson their@email.com`, re-encrypt the files, and they won't be able to decrypt secrets anymore. If you think the user might have copied the secrets or keys when they had access, then you should also change the secrets. ## Preview [![git-secret terminal preview](git-secret.gif)](https://asciinema.org/a/41811?autoplay=1) ## Installation `git-secret` [supports `brew`](https://formulae.brew.sh/formula/git-secret), just type: `brew install git-secret` It also supports `apt` and `yum`. You can also use `make` if you want to. See the [installation section](https://git-secret.io/installation) for the details. ### Requirements `git-secret` relies on several external packages: - `bash` since `3.2.57` (it is hard to tell the correct `patch` release) - `gawk` since `4.0.2` - `git` since `1.8.3.1` - `gpg` since `gnupg 1.4` to `gnupg 2.X` - `sha256sum` since `8.21` (on freebsd and MacOS `shasum` is used instead) ## Contributing Do you want to help the project? Find an [issue](https://github.com/sobolevn/git-secret/issues) and send a PR. It is more than welcomed! See [CONTRIBUTING.md](CONTRIBUTING.md) on how to do that. ### Security In order to encrypt (git-secret hide -m) files only when modified, the path mappings file tracks sha256sum checksums of the files added (git-secret add) to git-secret's path mappings filesystem database. Although, the chances of encountering a sha collision are low, it is recommend that you pad files with random data for greater security. Or avoid using the `-m` option altogether. If your secret file holds more data than just a single password these precautions should not be necessary, but could be followed for greater security. If you found any security related issues, please do not disclose it in public. Send an email to `security@wemake.services` ## Changelog `git-secret` uses [semver](https://semver.org/). See [CHANGELOG.md](CHANGELOG.md). ## Packagers Thanks to all the people and groups who package `git-secret` for easier install on particular OSes and distributions! [![Packaging status](https://repology.org/badge/vertical-allrepos/git-secret.svg)](https://repology.org/project/git-secret/versions) Here are some packagings of `git-secret` that we're aware of: - https://formulae.brew.sh/formula/git-secret - https://packages.ubuntu.com/bionic/git-secret - https://src.fedoraproject.org/rpms/git-secret - https://aur.archlinux.org/packages/git-secret/ - https://pkgs.alpinelinux.org/package/edge/testing/x86/git-secret - https://packages.debian.org/sid/git-secret - https://github.com/void-linux/void-packages/blob/master/srcpkgs/git-secret/template Such packages are considered 'downstream' because the git-secret code 'flows' from the `git-secret` [repository](https://git-secret.io/installation) to the various rpm/deb/dpkg/etc packages that are created for specific OSes and distributions. We have also added notes specifically for packagers in [CONTRIBUTING.md](CONTRIBUTING.md). ## Sponsors Support 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)] [![Sponsors](https://opencollective.com/git-secret/tiers/sponsor.svg?width=890)](https://opencollective.com/git-secret) ## Backers Thanks to all our backers! [![Backers](https://opencollective.com/git-secret/tiers/backer.svg?width=890&avatarHeight=36)](https://opencollective.com/git-secret) ## Contributors This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. ## License MIT. See [LICENSE.md](LICENSE.md) for details. ## Thanks Special thanks to [Elio Qoshi](https://elioqoshi.me/sq/) from [ura](http://ura.design/) for the awesome logo. git-secret-0.5.0/RFC/000077500000000000000000000000001424706700600142025ustar00rootroot00000000000000git-secret-0.5.0/RFC/RFC001.md000066400000000000000000000146571424706700600153740ustar00rootroot00000000000000# RFC 0001 - A stable and forwards compatible public key storage format **Feature Name:** Stable public key storage **Status:** Final **Type:** Enhancement **Related components:** Core **Start Date:** 2018-06-14 **Author:** Simon Massey **GitHub issues:** * #136 GnuPG2 2.2 vs 2.1 conflicts in keybox format ## Summary A 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. ## Motivation GPG 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. ## Approach git-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. git-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. It is anticipated that `bash` and `gawk` will be sufficient to work efficiently with the new file formats. ## Design The new storage format will be implemented as follows: 1. 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 `.pub.gpg` (using Field 5 the "64-bit keyid" of the colon listings format) 1. Key meta data will be stored alongside the key file in the `gpg --keyid-format long --with-colons` format. The file name will be `.pub.cln` 1. 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. git-secret-tell will: 1. Scan the set of `*.pub.cln` files to find all currently told identities. If the given identity is in the list do nothing. 1. If the given identity isn't listed run `gpg --armor --export` against the users `$HOME` keyring to create the `.pub.gpg`. 1. Run `--keyid-format long --with-colons` of the exported key to create the `.pub.cln`. Note that the additional steps to ensure that older versions of git-secret know about the newly told identity will be outlined below. git-secret-hide will: 1. 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. 1. Checked this against the list of "64-bit keyid"s in the "keyring cache" at `~/.gitsecret/cache`. 1. Import any missing keys into the "keyring cache". It is anticipated that `gawk` will be sufficient to perform this calculation. 1. Run the current logic using the "keyring cache". Note that the additional steps to ensure that older versions of git-secret know about the newly told user will be outlined below. git-secret-whoknows will: 1. The list of identities will be loaded by parsing the `.pub.cln` files. Note that multiple identities can be listed against each key. git-secret-usage will: 1. Document the git-secret-migrate command discussed in the next section. git-secret-reveal will: * Be unchanged. git-secret-remove will: * Be unchanged. git-secret-list will: * Be unchanged. git-secret-killperson will: 1. Remove the key from the keyring cache. 1. Delete both `.pub.gpg` and `.pub.cln` files. git-secret-init will: 1. Add `~/.gitsecret/cache` into `.gitignore`. 1. Run any current logic using the ignored "keyring cache". git-secret-clean will: * Be unchanged. git-secret-changes will: 1. Show differences the `.pub.gpg` and `.pub.cln` files in `~/.gitsecret/keys`. git-secret-add will: * Be unchanged. A new command git-secret-migrate will: 1. Create the folder `~/.gitsecret/cache` and add it to the `.gitignore` file. 1. Extract all keys from the old keyring generating `.pub.gpg` and `.pub.cln` files in `~/.gitsecret/keys` ## Version Compatibility Backwards compatibility will the old keyring storage approach will be maintained as follows: 1. For each changed command a guard will be added that checks for the existence of `.gitsecret/cache`. 1. If the folder exists it proceeds as normal. 1. 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 Forwards compatibility with older versions of git-secret will be maintained as follows. git-secret-hide will: 1. 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. git-secret-tell will: 1. Will check for the existence of the old keyring. If it exists it will load the new public key into it. git-secret-killperson 1. Will check for the existence of the old keyring. If it exists it will delete the user from it. ## Drawbacks To 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. ## Alternatives What other designs have been considered? Unknown. What 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. ## Unresolved questions What parts of the design are still to be done? None. git-secret-0.5.0/docs/000077500000000000000000000000001424706700600145205ustar00rootroot00000000000000git-secret-0.5.0/docs/CNAME000066400000000000000000000000151424706700600152620ustar00rootroot00000000000000git-secret.iogit-secret-0.5.0/docs/Gemfile000066400000000000000000000001721424706700600160130ustar00rootroot00000000000000source "https://rubygems.org" group :jekyll_plugins do gem "jekyll", ">= 3.6.3" gem "jekyll-seo-tag", "~> 2.8.0" end git-secret-0.5.0/docs/Gemfile.lock000066400000000000000000000031741424706700600167470ustar00rootroot00000000000000GEM remote: https://rubygems.org/ specs: addressable (2.8.0) public_suffix (>= 2.0.2, < 5.0) colorator (1.1.0) concurrent-ruby (1.1.9) em-websocket (0.5.3) eventmachine (>= 0.12.9) http_parser.rb (~> 0) eventmachine (1.2.7) ffi (1.15.5) forwardable-extended (2.6.0) http_parser.rb (0.8.0) i18n (1.10.0) concurrent-ruby (~> 1.0) jekyll (4.2.2) addressable (~> 2.4) colorator (~> 1.0) em-websocket (~> 0.5) i18n (~> 1.0) jekyll-sass-converter (~> 2.0) jekyll-watch (~> 2.0) kramdown (~> 2.3) kramdown-parser-gfm (~> 1.0) liquid (~> 4.0) mercenary (~> 0.4.0) pathutil (~> 0.9) rouge (~> 3.0) safe_yaml (~> 1.0) terminal-table (~> 2.0) jekyll-sass-converter (2.2.0) sassc (> 2.0.1, < 3.0) jekyll-seo-tag (2.8.0) jekyll (>= 3.8, < 5.0) jekyll-watch (2.2.1) listen (~> 3.0) kramdown (2.3.1) rexml kramdown-parser-gfm (1.1.0) kramdown (~> 2.0) liquid (4.0.3) listen (3.7.1) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) mercenary (0.4.0) pathutil (0.16.2) forwardable-extended (~> 2.6) public_suffix (4.0.6) rb-fsevent (0.11.1) rb-inotify (0.10.1) ffi (~> 1.0) rexml (3.2.5) rouge (3.28.0) safe_yaml (1.0.5) sassc (2.4.0) ffi (~> 1.9) terminal-table (2.0.0) unicode-display_width (~> 1.1, >= 1.1.1) unicode-display_width (1.8.0) PLATFORMS x86_64-linux x86_64-linux-musl DEPENDENCIES jekyll (>= 3.6.3) jekyll-seo-tag (~> 2.8.0) BUNDLED WITH 2.2.2 git-secret-0.5.0/docs/_config.yml000066400000000000000000000007211424706700600166470ustar00rootroot00000000000000# Site settings title: git-secret email: mail@sobolevn.me description: Shell scripts to encrypt your private data inside a git repository. baseurl: "" # the subpath of your site, e.g. /blog url: "git-secret.io" # the base hostname & protocol for your site # Github links: github_username: sobolevn github_changelog: "https://github.com/sobolevn/git-secret/blob/master/CHANGELOG.md" # Seo settings: plugins: - jekyll-seo-tag # Build settings markdown: kramdown git-secret-0.5.0/docs/_includes/000077500000000000000000000000001424706700600164655ustar00rootroot00000000000000git-secret-0.5.0/docs/_includes/favicons.html000066400000000000000000000027311424706700600211660ustar00rootroot00000000000000 git-secret-0.5.0/docs/_includes/footer.html000066400000000000000000000017141424706700600206540ustar00rootroot00000000000000
git-secret-0.5.0/docs/_includes/head.html000066400000000000000000000014641424706700600202610ustar00rootroot00000000000000 {% if page.title %}{{ page.title }}{% else %}{{ site.title }}{% endif %} {% include favicons.html %} {% seo %} git-secret-0.5.0/docs/_includes/header.html000066400000000000000000000030661424706700600206100ustar00rootroot00000000000000 git-secret-0.5.0/docs/_includes/icon-github.html000066400000000000000000000002741424706700600215660ustar00rootroot00000000000000 {% include icon-github.svg %} {{ include.username }} git-secret-0.5.0/docs/_includes/icon-github.svg000066400000000000000000000016361424706700600214240ustar00rootroot00000000000000 git-secret-0.5.0/docs/_includes/icon-twitter.html000066400000000000000000000002771424706700600220110ustar00rootroot00000000000000 {{ include.username }} git-secret-0.5.0/docs/_includes/icon-twitter.svg000066400000000000000000000014231424706700600216360ustar00rootroot00000000000000 git-secret-0.5.0/docs/_includes/why.md000066400000000000000000000043631424706700600176240ustar00rootroot00000000000000 ## Intro There's a well known issue with deploying and configuring software on servers: generally you have to store your private data (such as database passwords, application secret-keys, OAuth secret keys, etc) outside of the git repository. If you do choose to store these secrets unencrypted in your git repo, even if the repository is private, it is a security risk to copy the secrets everywhere you check out your repo. What are some drawbacks of storing secrets separately from your git repo? 1. These files are not version controlled. Filenames, locations, and passwords change from time to time, or new information appears, and other information is removed. When secrets are stored separately from your repo, you can not tell for sure which version of the configuration file was used with each commit or deploy. 2. When building the automated deployment system there will be one extra step: download and place these secret-configuration files where they need to be. This also means you have to maintain extra secure servers where all your secrets are stored. ### How does `git-secret` solve these problems? 1. `git-secret` encrypts files and stores them inside your `git` repository, providing a history of changes for every commit. 2. `git-secret` doesn't require any extra deploy operations other than providing the appropriate private key (to allow decryption), and using `git secret reveal` to decrypt all the secret files. ### What is `git-secret`? `git-secret` is a bash tool to store your private data inside a `git` repo. How's that? Basically, it uses `gpg` to encrypt files with the public keys of the users that you trust, and which you have specified with `git secret tell email@address.id`. Then these users can decrypt these files using their personal secret key. Why deal with all this private/public key stuff? To make it easier to manage access rights. When you want to remove someone's access, use `git secret removeperson email@address.id` to delete their public key from your repo's git-secret keyring, and reencrypt the files. Then they won't be able to decrypt secrets anymore. [![git-secret terminal preview](https://raw.githubusercontent.com/sobolevn/git-secret/master/git-secret.gif)](https://asciinema.org/a/41811?autoplay=1) git-secret-0.5.0/docs/_layouts/000077500000000000000000000000001424706700600163575ustar00rootroot00000000000000git-secret-0.5.0/docs/_layouts/default.html000066400000000000000000000006221424706700600206710ustar00rootroot00000000000000 {% include head.html %} {% include header.html %}
{{ content }}
{% include footer.html %} git-secret-0.5.0/docs/_layouts/page.html000066400000000000000000000003211424706700600201550ustar00rootroot00000000000000--- layout: default ---

{{ page.title }}

{{ content }}
git-secret-0.5.0/docs/_layouts/post.html000066400000000000000000000014001424706700600202250ustar00rootroot00000000000000--- layout: default ---

{{ page.title }}

{{ content }}
git-secret-0.5.0/docs/_sass/000077500000000000000000000000001424706700600156305ustar00rootroot00000000000000git-secret-0.5.0/docs/_sass/_base.scss000066400000000000000000000055451424706700600176070ustar00rootroot00000000000000/** * Reset some basic elements */ body, h1, h2, h3, h4, h5, h6, p, blockquote, pre, hr, dl, dd, ol, ul, figure { margin: 0; padding: 0; } /** * Basic styling */ body { font: $base-font-weight #{$base-font-size}/#{$base-line-height} $base-font-family; color: $text-color; background-color: $background-color; -webkit-text-size-adjust: 100%; -webkit-font-feature-settings: "kern" 1; -moz-font-feature-settings: "kern" 1; -o-font-feature-settings: "kern" 1; font-feature-settings: "kern" 1; font-kerning: normal; } /** * Set `margin-bottom` to maintain vertical rhythm */ h1, h2, h3, h4, h5, h6, p, blockquote, pre, ul, ol, dl, figure, %vertical-rhythm { margin-bottom: $spacing-unit / 2; } /** * Images */ img { max-width: 100%; vertical-align: middle; } /** * Figures */ figure > img { display: block; } figcaption { font-size: $small-font-size; } /** * Lists */ ul, ol { margin-left: $spacing-unit; } li { > ul, > ol { margin-bottom: 0; } } /** * Headings */ h1, h2, h3, h4, h5, h6 { font-weight: $base-font-weight; } /** * Links */ a { color: $brand-color; text-decoration: none; &:visited { color: darken($brand-color, 15%); } &:hover { color: $text-color; text-decoration: underline; } } /** * Blockquotes */ blockquote { color: $purple-color; border-left: 4px solid $purple-color-light; padding-left: $spacing-unit / 2; font-size: 18px; letter-spacing: -1px; font-style: italic; > :last-child { margin-bottom: 0; } } /** * Code formatting */ pre, code { font-size: 15px; border: 1px solid $purple-color-light; border-radius: 3px; background-color: #eef; } code { padding: 1px 5px; } pre { padding: 8px 12px; overflow-x: auto; > code { border: 0; padding-right: 0; padding-left: 0; } } /** * Wrapper */ .wrapper { max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit} * 2)); max-width: calc(#{$content-width} - (#{$spacing-unit} * 2)); margin-right: auto; margin-left: auto; padding-right: $spacing-unit; padding-left: $spacing-unit; @extend %clearfix; @include media-query($on-laptop) { max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit})); max-width: calc(#{$content-width} - (#{$spacing-unit})); padding-right: $spacing-unit / 2; padding-left: $spacing-unit / 2; } } /** * Clearfix */ %clearfix { &:after { content: ""; display: table; clear: both; } } /** * Icons */ .icon { > svg { display: inline-block; width: 16px; height: 16px; vertical-align: middle; path { fill: $purple-color; } } } git-secret-0.5.0/docs/_sass/_layout.scss000066400000000000000000000112501424706700600202000ustar00rootroot00000000000000/** * Site header */ .site-header { border-top: 5px solid $purple-color-dark; border-bottom: 1px solid $purple-color-light; min-height: 56px; // Positioning context for the mobile navigation icon position: relative; } .site-title { font-size: 26px; font-weight: 300; line-height: 56px; letter-spacing: -1px; margin-bottom: 0; float: left; &, &:visited { color: $purple-color-dark; } } .site-nav { @extend %clearfix; float: right; line-height: 56px; .menu-icon { display: none; } .page-link { color: $text-color; line-height: $base-line-height; // Gaps between nav items, but not on the last one &:not(:last-child) { margin-right: 20px; } } @include media-query($on-palm) { position: absolute; top: 9px; right: $spacing-unit / 2; background-color: $background-color; border: 1px solid $purple-color-light; border-radius: 5px; text-align: right; .menu-icon { display: block; float: right; width: 36px; height: 26px; line-height: 0; padding-top: 10px; text-align: center; > svg { width: 18px; height: 15px; path { fill: $purple-color-dark; } } } .trigger { clear: both; display: none; } &:hover .trigger, &:active .trigger { display: block; padding-bottom: 5px; } .page-link { display: block; padding: 5px 10px; &:not(:last-child) { margin-right: 0; } margin-left: 20px; } } .trigger { padding-top: 13px; } } /** * Site footer */ .site-footer { border-top: 1px solid $purple-color-light; padding: $spacing-unit 0; } .footer-heading { font-size: 18px; margin-bottom: $spacing-unit / 2; } .contact-list, .social-media-list { list-style: none; margin-left: 0; } .footer-col-wrapper { font-size: 15px; color: $grey-color; margin-left: -$spacing-unit / 2; @extend %clearfix; } .footer-col { float: left; margin-bottom: $spacing-unit / 2; padding-left: $spacing-unit / 2; } .footer-col-1 { width: -webkit-calc(35% - (#{$spacing-unit} / 2)); width: calc(35% - (#{$spacing-unit} / 2)); } .footer-col-2 { width: -webkit-calc(20% - (#{$spacing-unit} / 2)); width: calc(20% - (#{$spacing-unit} / 2)); } .footer-col-3 { width: -webkit-calc(45% - (#{$spacing-unit} / 2)); width: calc(45% - (#{$spacing-unit} / 2)); } @include media-query($on-laptop) { .footer-col-1, .footer-col-2 { width: -webkit-calc(50% - (#{$spacing-unit} / 2)); width: calc(50% - (#{$spacing-unit} / 2)); } .footer-col-3 { width: -webkit-calc(100% - (#{$spacing-unit} / 2)); width: calc(100% - (#{$spacing-unit} / 2)); } } @include media-query($on-palm) { .footer-col { float: none; width: -webkit-calc(100% - (#{$spacing-unit} / 2)); width: calc(100% - (#{$spacing-unit} / 2)); } } /** * Page content */ .page-content { padding: $spacing-unit 0; } .page-heading { font-size: 20px; } .post-list { li { margin-bottom: 10px; } } .post-meta { font-size: $small-font-size; color: $grey-color; } .post-link { display: block; font-size: 24px; } /** * Posts */ .post-header { margin-bottom: $spacing-unit; } .post-title { font-size: 42px; letter-spacing: -1px; line-height: 1; @include media-query($on-laptop) { font-size: 36px; } } .post-content { margin-bottom: $spacing-unit; h2 { font-size: 32px; @include media-query($on-laptop) { font-size: 28px; } } h3 { font-size: 26px; @include media-query($on-laptop) { font-size: 22px; } } h4 { font-size: 20px; @include media-query($on-laptop) { font-size: 18px; } } } /** * Navigation */ .site-navigation { @extend .wrapper; display: flex; justify-content: space-between; flex-wrap: wrap; a { color: $purple-color-dark; @include media-query($on-laptop) { flex-basis: 100%; text-align: center; } } } /** * Homepage */ .home { .home-logo-image { margin-top: 50px; margin-bottom: 70px; } } git-secret-0.5.0/docs/_sass/_syntax-highlighting.scss000066400000000000000000000064331424706700600226630ustar00rootroot00000000000000/** * Syntax highlighting styles */ .highlight { background: #fff; @extend %vertical-rhythm; .highlighter-rouge & { background: #eef; } .c { color: #998; font-style: italic } // Comment .err { color: #a61717; background-color: #e3d2d2 } // Error .k { font-weight: bold } // Keyword .o { font-weight: bold } // Operator .cm { color: #998; font-style: italic } // Comment.Multiline .cp { color: #999; font-weight: bold } // Comment.Preproc .c1 { color: #998; font-style: italic } // Comment.Single .cs { color: #999; font-weight: bold; font-style: italic } // Comment.Special .gd { color: #000; background-color: #fdd } // Generic.Deleted .gd .x { color: #000; background-color: #faa } // Generic.Deleted.Specific .ge { font-style: italic } // Generic.Emph .gr { color: #a00 } // Generic.Error .gh { color: #999 } // Generic.Heading .gi { color: #000; background-color: #dfd } // Generic.Inserted .gi .x { color: #000; background-color: #afa } // Generic.Inserted.Specific .go { color: #888 } // Generic.Output .gp { color: #555 } // Generic.Prompt .gs { font-weight: bold } // Generic.Strong .gu { color: #aaa } // Generic.Subheading .gt { color: #a00 } // Generic.Traceback .kc { font-weight: bold } // Keyword.Constant .kd { font-weight: bold } // Keyword.Declaration .kp { font-weight: bold } // Keyword.Pseudo .kr { font-weight: bold } // Keyword.Reserved .kt { color: #458; font-weight: bold } // Keyword.Type .m { color: #099 } // Literal.Number .s { color: #d14 } // Literal.String .na { color: #008080 } // Name.Attribute .nb { color: #0086B3 } // Name.Builtin .nc { color: #458; font-weight: bold } // Name.Class .no { color: #008080 } // Name.Constant .ni { color: #800080 } // Name.Entity .ne { color: #900; font-weight: bold } // Name.Exception .nf { color: #900; font-weight: bold } // Name.Function .nn { color: #555 } // Name.Namespace .nt { color: #000080 } // Name.Tag .nv { color: #008080 } // Name.Variable .ow { font-weight: bold } // Operator.Word .w { color: #bbb } // Text.Whitespace .mf { color: #099 } // Literal.Number.Float .mh { color: #099 } // Literal.Number.Hex .mi { color: #099 } // Literal.Number.Integer .mo { color: #099 } // Literal.Number.Oct .sb { color: #d14 } // Literal.String.Backtick .sc { color: #d14 } // Literal.String.Char .sd { color: #d14 } // Literal.String.Doc .s2 { color: #d14 } // Literal.String.Double .se { color: #d14 } // Literal.String.Escape .sh { color: #d14 } // Literal.String.Heredoc .si { color: #d14 } // Literal.String.Interpol .sx { color: #d14 } // Literal.String.Other .sr { color: #009926 } // Literal.String.Regex .s1 { color: #d14 } // Literal.String.Single .ss { color: #990073 } // Literal.String.Symbol .bp { color: #999 } // Name.Builtin.Pseudo .vc { color: #008080 } // Name.Variable.Class .vg { color: #008080 } // Name.Variable.Global .vi { color: #008080 } // Name.Variable.Instance .il { color: #099 } // Literal.Number.Integer.Long } git-secret-0.5.0/docs/build.sh000066400000000000000000000034231424706700600161550ustar00rootroot00000000000000#!/usr/bin/env bash # Should be called from the root folder, not inside `docs/` folder # See `make build-docs` set -e MAN_LOCATION='man/man1' MAN7_LOCATION='man/man7' POSTS_LOCATION='docs/_posts' function checkout_manuals { cp -r man/ docs/man } function copy_to_posts { # Cleaning old files: rm -f "$POSTS_LOCATION/*.md" rm -rf "$POSTS_LOCATION" mkdir -p "$POSTS_LOCATION" # Moving new command files: local timestamp local current_date timestamp=$(date "+%Y-%m-%d %H:%M:%S %z") current_date=$(date "+%Y-%m-%d") # Creating command refernce: for com in "$MAN_LOCATION"/git-secret-*.1.md; do local short_name short_name=$(echo "$com" | sed -n "s|$MAN_LOCATION/\(.*\)\.1\.md|\1|p") local command_header="--- layout: post title: '${short_name}' date: ${timestamp} permalink: ${short_name} categories: command ---" local post_filename="$POSTS_LOCATION/${current_date}-${short_name}.md" echo "$command_header" > "$post_filename" cat "$com" >> "$post_filename" done # Creating main usage file: local usage_header="--- layout: post title: 'git-secret' date: ${timestamp} permalink: git-secret categories: usage ---" local usage_filename="$POSTS_LOCATION/${current_date}-git-secret.md" echo "$usage_header" > "$usage_filename" cat "$MAN7_LOCATION/git-secret.7.md" >> "$usage_filename" } function copy_install_scripts { # We test these scripts using `release-ci`, # so, installation instructions will always be up-to-date: cp utils/deb/install.sh docs/_includes/install-deb.sh cp utils/rpm/install.sh docs/_includes/install-rpm.sh cp utils/apk/install.sh docs/_includes/install-apk.sh } function copy_version { ./git-secret --version > docs/_includes/version.txt } checkout_manuals copy_to_posts copy_install_scripts copy_version git-secret-0.5.0/docs/css/000077500000000000000000000000001424706700600153105ustar00rootroot00000000000000git-secret-0.5.0/docs/css/main.scss000066400000000000000000000022711424706700600171330ustar00rootroot00000000000000--- # Only the main Sass file needs front matter (the dashes are enough) --- @charset "utf-8"; // Our variables $base-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; $base-font-size: 16px; $base-font-weight: 400; $small-font-size: $base-font-size * 0.875; $base-line-height: 1.5; $spacing-unit: 30px; $text-color: #111; $background-color: #fdfdfd; $grey-color: #828282; $grey-color-light: lighten($grey-color, 40%); $grey-color-dark: darken($grey-color, 25%); $purple-color: rgb(238, 81, 59); $purple-color-light: lighten($purple-color, 40%); $purple-color-dark: darken($purple-color, 25%); $brand-color: $purple-color; // Width of the content area $content-width: 800px; $on-palm: 600px; $on-laptop: 800px; // Use media queries like this: // @include media-query($on-palm) { // .wrapper { // padding-right: $spacing-unit / 2; // padding-left: $spacing-unit / 2; // } // } @mixin media-query($device) { @media screen and (max-width: $device) { @content; } } // Import partials from `sass_dir` (defaults to `_sass`) @import "base", "layout", "syntax-highlighting" ; git-secret-0.5.0/docs/feed.xml000066400000000000000000000024131424706700600161450ustar00rootroot00000000000000--- layout: null --- {{ site.title | xml_escape }} {{ site.description | xml_escape }} {{ site.url }}{{ site.baseurl }}/ {{ site.time | date_to_rfc822 }} {{ site.time | date_to_rfc822 }} Jekyll v{{ jekyll.version }} {% for post in site.posts limit:10 %} {{ post.title | xml_escape }} {{ post.content | xml_escape }} {{ post.date | date_to_rfc822 }} {{ post.url | prepend: site.baseurl | prepend: site.url }} {{ post.url | prepend: site.baseurl | prepend: site.url }} {% for tag in post.tags %} {{ tag | xml_escape }} {% endfor %} {% for cat in post.categories %} {{ cat | xml_escape }} {% endfor %} {% endfor %} git-secret-0.5.0/docs/images/000077500000000000000000000000001424706700600157655ustar00rootroot00000000000000git-secret-0.5.0/docs/images/favicons/000077500000000000000000000000001424706700600175755ustar00rootroot00000000000000git-secret-0.5.0/docs/images/favicons/android-icon-144x144.png000066400000000000000000000074511424706700600236070ustar00rootroot00000000000000PNG  IHDRИgAMA asRGB cHRMz&u0`:pQ<PLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P35QtRNS)LuwM 4gǞiW֢["hn&c@Evy0CGQYb`ޮ?.#%->V|1k\ d<897 JKнo(! m Zr/{BHl fTU'sґ}R2;je3S:xӔ5N=,_qppbKGD_Ϧ pHYs.#.#x?v IDATx_epewKd]Yܔh1t"W0#Q1pY,+5SRP#̢;(>OifgcfYKy|fƌ, Vq'$Y ,'ON*ǘxѴS26al̫^L8Ӳ\قVLqLw<q5;#ʓ_0'nD¢l\%Mv ozC"qzna#4D0)Tً}|ͷT0뭋<%U:HZxݦ3 $-+9nIT% o>ܭ+\+}uU;Q-D0K'Y97ll=^jqٴD˟e]dHnD6S޺5׶̂W[8A#H}.\qşZl]Qt~$&ĘȽ{~AE{5Հ{.ܹK"n64~zܴ?irQqʆ#hC+TaU9r}}RLO`SWDiYCu?} pXC *j ݥ!Tջt6Q8%d6mu0,/G(l0Mm ⧖ب?T5M:Qm[۬/$e>}AMn AMuCGGMse@櫩:NYǜ>EMo >.jǎy99 ~x?NӘ={  8MRg 񪝨,+\ԒUW i=d/ZJ쥡f,)9HXeP{*U-m*/T-[:yT j;UС ^ Qz5ӧ]Y9Q=C" R ݈x̶@tUoEXl%%Pw-|hy Mk[gҐW$sP_&PFsW_ŷ&{4ojK*O=Q ̙5{NDkeҋ.\8ѾÆ%& N$Z"@|ZTj/)kd+ IwMpsK"kAȪRMԀw~|X%ol!K7^Ρu"IHTނP ^ To7@ Q@R#1yIeA xՠsΉAw~~5cJ Z.V~Ĩ9B-:ӣѵ|+ 4&'>0XC'ie㌁D ϱKmmhLm3_Н/@]& ބ{-5{ Z |_A/2G;=}6 ej AeiԹvՕ1gvr{Iw²HxaK[HmOD0몢ʗ.TaA5\ ;v.?.nQ"e1$_&)^^1e\p a5^F b2f,15y}^FԬUacүf97ܫKvN: '2uC>_t`Gjh~C)2jf]w/oՐO\>H= {Y>F_Mz Z %i]L^,jkyͽe &aŠVڄoC. ^tgAf]-s_y- &VLXdj7 n]m^~\v/u 7"e]Mșwk&{(e]X+5N^ոyEU%ϑ5^r"v5^Djܽ9bSE-.^D,jq爦7/9Y-^DxzsWwH"xs3ZDU+U1/yzFjxE|&P(?7^DuDz;}HK 3 0`<Ֆ(Y%tEXtdate:create2017-02-26T20:06:39+00:00h%tEXtdate:modify2017-02-26T20:06:39+00:00j;FtEXtsoftwareImageMagick 6.7.8-9 2014-05-12 Q16 http://www.imagemagick.org܆tEXtThumb::Document::Pages1/tEXtThumb::Image::height192rtEXtThumb::Image::Width192Ӭ!tEXtThumb::Mimetypeimage/png?VNtEXtThumb::MTime1488139599%tEXtThumb::Size0BB>VtEXtThumb::URIfile:///mntlog/favicons/2017-02-26/36a23da25da7ec4be3ab43f2b158378c.ico.pngFIENDB`git-secret-0.5.0/docs/images/favicons/android-icon-192x192.png000066400000000000000000000073521424706700600236150ustar00rootroot00000000000000PNG  IHDRe5PLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3,tRNS 'ItY3Ld0 Zs =\N"Kw5^ z>n&C-_:uBׁȳmvE4a#G;qѧO{7V 2MXf1 <$(xgj!F[%PH*DWռ9ӓSU?~rQ6T8ûJA]郎lb,R)hy"p IDATx՝Mr ܅<)p&F& h`C!"ObA*|E,شjsD7|ggnwo~||vgf/II2"Օ6rT6 rƎ?abn׻ 'a4VsL1ȩ 3n*@ͷr"ns24LL- 9 VV?*Js,rJZ~V;n!>E5V>-eFҳOK]&-x6FZ~M_f';emJRߕl?SZM&?o#_YJ4M~{2 4֭'ަ5 ֮ZQ43Y;%5 |т;`Mm7 lޒY,bJVLߪq}yswlӝ@%@]cn0!4iW:-kwFvsz=rOGYП{|=bm2$܈x(G5$?A|aԭ1@h##(%MH?<$]WCF9⛩9(0 " =.heD@5Jw 5O'cK(W]_U.LYm,>""E3R>X]9S[mS`ea-.6BhK|ϐ7kGRzK6`D.QYheQtC9p5S,7$`$Qnl,u\4B9 e)ب0d{$Z"Vᆈa,)RU9 +1y'}eer& -0ulp*Z%."Zw0%9 7VW ^뇒."5WOsE_ j\&< ?➃1DG~nm *x'K|O7$BgVtX3\_p?=F&B7Q >?-3nc`I/[?6%>@7>#l8F5R)w"3YAiߐ`i96&uc7pQ3\<6q 0g}.YԳr# cP{> _QGǘ)9ҿa="@k ,-«u kU \` :#X*neY~5?*Pѝ m=8@e-@H2+E0.bz9@ XC*(,V9] "U09a1^)k-@E_a@ V&#s!X<>0f_ooU"໨.:9TDAL?~ۜ~M{gve9`^6Oz*>Zpx"⑃K!9+ ́TmD K`lA p9H r@Aۧt{#nLd/@ZQ Ai @4AJ?r?j ЯݺmN@t"}Ar ښg ^\į~\lme܄*0s} QB1kjDtW@$\a;^eZk¿dc@-1^-U4 nIFߝ ($ngmeWX]2, '1:>5Gu :@ouO{XM;~es>mB1nՊ+ANBCkp{Lᄄ$0Ц˽89T/<+@ ܛ109h]#"{U~kC;7-sH@sgIky?>_eI~贴hr7\*_UWu&p2A+#P`jU@i9U~Iͼg@e{W@aagHLe#MI7b^JVߤ./|(! m'? ¾E9 u+xg=sŗUEv>ofU+)Y{?|q~cЄrB9Oay'E\S3.Ŋ/L ;q9(gnAs۩Տv~ƫğˈ>?o8VA{'׏{iw׸`~&"*bE^Dq0K?,O^ЕՎяkCwA9ȿ/;m}X!3j 'ۡ_~-J l0ئ_QlԯE6_&ˁ%sR.08F8H)9 5a8N`_E0#?Lˁc#s`(9hG8A7t%Hs09H T% 5")V]N0b)po%f=-㺓]߼:IENDB`git-secret-0.5.0/docs/images/favicons/android-icon-36x36.png000066400000000000000000000033151424706700600234420ustar00rootroot00000000000000PNG  IHDR$$hgAMA asRGB cHRMz&u0`:pQ<PLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3e1 tRNS Qi:XP~ ;n E1uKLFxR,w ) 2*ģBZY!˜\ |cة%@j(zɷgvdfϸAObKGDhwv pHYs.#.#x?vIDAT8}iC@3B 4M,hVAQ@Axn$Sf<3+ID MGd? IA-am:ήE1Ƅ=q#ї^@PRC:1ktT·qq&5Q]!eR7{ i H6YQk5s# Xsy/y5eMmrBq\o3ҕ׮Ec0 eyyH!C7\f/nD8#vdXܹk@5aFJu% 3Rol>G`HxBSFBzJO_l R_ѫ<вycn]hS.H/e|f'桔Cl%6#_R[ъjK;?<w׌0zgVtEXtThumb::URIfile:///mntlog/favicons/2017-02-26/36a23da25da7ec4be3ab43f2b158378c.ico.pngFIENDB`git-secret-0.5.0/docs/images/favicons/android-icon-48x48.png000066400000000000000000000035431424706700600234530ustar00rootroot00000000000000PNG  IHDR00` gAMA asRGB cHRMz&u0`:pQ<PLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3tRNS6߬N/dޑyeȥ1 $i:0 P-Qǝ7"2= x%4}vo! ͲW՜.wsRm죀) T{ |+384C;;"=Ox96>6Dl2cn87~'fs2Qyٜ/~8.PEj"aNǪj_$r?}~5"Qٗ=AվKfEfQ4mOD\/%tEXtdate:create2017-02-26T20:06:39+00:00h%tEXtdate:modify2017-02-26T20:06:39+00:00j;FtEXtsoftwareImageMagick 6.7.8-9 2014-05-12 Q16 http://www.imagemagick.org܆tEXtThumb::Document::Pages1/tEXtThumb::Image::height192rtEXtThumb::Image::Width192Ӭ!tEXtThumb::Mimetypeimage/png?VNtEXtThumb::MTime1488139599%tEXtThumb::Size0BB>VtEXtThumb::URIfile:///mntlog/favicons/2017-02-26/36a23da25da7ec4be3ab43f2b158378c.ico.pngFIENDB`git-secret-0.5.0/docs/images/favicons/android-icon-72x72.png000066400000000000000000000044561424706700600234510ustar00rootroot00000000000000PNG  IHDRHHb3CugAMA asRGB cHRMz&u0`:pQ<PLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3JtRNS 9wʗYWχ1JG"dno3!'Bt*Q OZ: N X=+L-aÖ| 8@60 )(Hר[ΜEs.ޥTF5P`{zbbKGDl1 pHYs.#.#x?vIDATXå?TApgٵbc# abQYU+%wj !=CQzowgw3k>?3{ϙ93V\:L fKU%-YjONXi6I1P\%E d`uyb-(FZK@u(v;%()?>RZ>WpKVʵ,WnXU]SIxsX$oF;иEe׼u,?Ѳ=mYnՁԩJ{v)e S*9}nQY2Ьz@J |Y3%#Ȍ; B9YPu"R?PΪn0H?'-ݨ֮C%ieUTRxJ4<@;r?%(TGǸ(T:M29ŮΎT#seOr9Pp@+Spm3N>an]Q@t݌lR" |ᒙwy!Qcu&@eB) z1 f 5!иZQr.ڑlgɽ$IDuΊr9a$99l U I UԪ3;<չ4rQ%9. !78y0R w>HdNS{F$nGD֦%Oa0AOm|г A=9!Aۼ|yAN֨}*O6[y |^6CmcHT -94:q/1$o޾s7r^2H(zP+'D;,IFJ?gG'_ھ1GGzK̉[ b%yA:Tu?8;Co'q:9:F_]LNN9]"׳E:rNSmӁ8S%tEXtdate:create2017-02-26T20:06:39+00:00h%tEXtdate:modify2017-02-26T20:06:39+00:00j;FtEXtsoftwareImageMagick 6.7.8-9 2014-05-12 Q16 http://www.imagemagick.org܆tEXtThumb::Document::Pages1/tEXtThumb::Image::height192rtEXtThumb::Image::Width192Ӭ!tEXtThumb::Mimetypeimage/png?VNtEXtThumb::MTime1488139599%tEXtThumb::Size0BB>VtEXtThumb::URIfile:///mntlog/favicons/2017-02-26/36a23da25da7ec4be3ab43f2b158378c.ico.pngFIENDB`git-secret-0.5.0/docs/images/favicons/android-icon-96x96.png000066400000000000000000000052341424706700600234600ustar00rootroot00000000000000PNG  IHDR``F gAMA asRGB cHRMz&u0`:pQ<FPLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3{ OtRNS4hݼW&$gҙQ'dkѷJ1N,_7:lYS]tzG#8+ui= (mw/UI-%0޸? srDeHj[֚qyTد )^K  \VvE`. xCp>ZcڨUEbKGDdfn pHYs.#.#x?vIDATh޵CGpI$QBBX5( R!Z@6ŖjZAK[mibZ-^ؖbsf왝7n $Ph**^SbFY׮V`d}r**"qSE SkDJow \55oy(Rt lmClk!@u;Ҫ;NFEvYwwu!/}Ld@pD328B zp8& 8ēcoʡdI?u$̄N $ܿcYTHx:Lxd<[>pW?2j?8B*L(,]_`pݺf>YPIJa |Z'PuZݪԂ[Cu36sɤn|xOZ[Dl$^(y`t@@i~@epBʸ~~ Vn7U|f/B.K u|a?_y5>Wo΄ B(|}L7 OB@$@PQpT# P<#~e͟^&BLi (_zwV+T#Aq-!."g G=29?"-r3' "n-6!F&l>"оC=|_;‡f>,A:WlyYl]4_B % (_µGBCSN'nڴe mAor䋁`3wKb`Hn9UwGǹiykY|)]O:佟 hӊ7&BJ8QE*\q&yت"MSL[xt }vi&wݾ9U!4?=̗_5!V R9O<߆4IP'O,d}4$d]|"|m!~X~MI|uajwhՄODg'mpmIxv/ 4B>q-Wa=aP~MW;w] nX7_Q'{ C9u+ -J\u#ҿgW&S|"AW>3_SН!*" + +g ˄VtEXtThumb::URIfile:///mntlog/favicons/2017-02-26/36a23da25da7ec4be3ab43f2b158378c.ico.pngFIENDB`git-secret-0.5.0/docs/images/favicons/apple-icon-114x114.png000066400000000000000000000064101424706700600232540ustar00rootroot00000000000000PNG  IHDRrruOgAMA asRGB cHRMz&u0`:pQ<sPLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3ݛtRNS9hڻ_2:zn0 SܚG M=+UAw`u  dE5IiK WOCTNjݢ>H"XZYg#49Yyb:kL<6N4[ twbJiV!;9_3M^- 8ظ]>_ĭ]veL[-ACYa9ΗGEddYH@,6pRh)m%h5]U$~+Dql˱2|PNfzGLNEBVx"IiOqQzdzֱ*Q>7An5O[CMmevD|C:>5t'b("IG7Lr+Lbbݢ{7<;]EVY;b Ց^;YP#^Q?>y[!TՀ Es9QnqI>U!nEm jdHɸ̎ cn0&v MI:;NokjnI@nQ`aj|Ƞۛ ΁n2&P$F}q4BnH]oA)>~Y ӖC"Wh!ʑA\Y-`kDnօroCΑ^]H%bmއvDFm?VDB?$܁ Ut!c5cTz S6dHPzb,v \WAQH$HZľGHZbnAm8Sr\Aj2TOC;FFbB[MHzZjA!a5n#}*$;q[|J-Z*oE&ER#|=ݣ)[2Ͼ[SH<^j~k,nuWDV~Wgrwi+HUN3#L#j~vKU-WxW Zm.YU &V xܚ-*237al?{!b5F_n_6HsN]o1uqgA?[#-- Mtun5ƪFY*>gU[#nukU[u&Ӊv;VE#gv d Lۙ*23gϪϡ nwjym{٨1rm(O/;ZU>X%tEXtdate:create2017-02-26T20:06:39+00:00h%tEXtdate:modify2017-02-26T20:06:39+00:00j;FtEXtsoftwareImageMagick 6.7.8-9 2014-05-12 Q16 http://www.imagemagick.org܆tEXtThumb::Document::Pages1/tEXtThumb::Image::height192rtEXtThumb::Image::Width192Ӭ!tEXtThumb::Mimetypeimage/png?VNtEXtThumb::MTime1488139599%tEXtThumb::Size0BB>VtEXtThumb::URIfile:///mntlog/favicons/2017-02-26/36a23da25da7ec4be3ab43f2b158378c.ico.pngFIENDB`git-secret-0.5.0/docs/images/favicons/apple-icon-120x120.png000066400000000000000000000065651424706700600232610ustar00rootroot00000000000000PNG  IHDRxxgAMA asRGB cHRMz&u0`:pQ<yPLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3fcStRNS .YЮR) j`(Fҍ=C9'}E{!QU, 0Zg#*rw%6m?DAP"ߞ4< +-XTկfaⷭip_3O 2S h&b8tlusM1[GvLekK|q@]\73YbKGDخ pHYs.#.#x?vIDAThś_G@"G`XT"*ȡCT*FDh/[JbRmj{f$>>;; QQbELz.6.$yrBbR:085&%5nTA)s|´iDbgfʘem YT/ yaAgV|Ar' ڵpd (%hPl+1Xl+%+i+WV*V`fTrFAޒ \eNU5kkj׭jfAvnبnƂ-83F| Ud嫰U[e[ mmk mFU#Jٹt&a1~i}`ed/F\Dq)aE+Ls4ӓAxFSg(cr$GX fLV';].n6h:n_T3wRj13\8nQsf- R %cGV"Ӹ Vjwcy-2q±թO@I+SMt"a'Ua,aJS)#=zC-eIlfR:N7F1JԱW&0h&}>͡& VO(b Qkp\ 9A7:(ұ(I뚁W:eCIXһ~ ZBU /!㒗% ̾ x +^oGÎ"& XaAW=L?mDyorz \ez @$c k&[SFg{G An7KL̕iC E0>+jE&TC^ }) %L#Wyyq^KR}06WzU& -dc}$(+G/:z'W?& `Uy.(v}(zyMlL7l|^"ah6ozc>d3uD6j2Dc aŒ Li&' ~জQWBMϭ l )a/_X;.}|Ό'64X#{I3`g vl08uqwTw5dSX?S|  '{}(-@Ol}24gⷀ#* # ` Pk\M?qZu912X2XkX|Opa_- [PĪBw8uÅ"OlM{d*2,U9'C7b64pS?LJ'p%{ ' U,NBK0TdnS%ǥL.a"cOXzi{uXnw.ӟ5%㌸k}'k6s|̈́5XMNjVzufVl*e~.g??ӑq nFHܠn\lI&7ﺑר~2.Q3j'v!` sS$br2vO0J-Oz5/ fg V\ڝ>d;}vze Yq^Y2{1ͬ}uۭ׫vʚς9|>؄WD&,ze57Ps$|EJDV1^K$rzs?01 A%tEXtdate:create2017-02-26T20:06:39+00:00h%tEXtdate:modify2017-02-26T20:06:39+00:00j;FtEXtsoftwareImageMagick 6.7.8-9 2014-05-12 Q16 http://www.imagemagick.org܆tEXtThumb::Document::Pages1/tEXtThumb::Image::height192rtEXtThumb::Image::Width192Ӭ!tEXtThumb::Mimetypeimage/png?VNtEXtThumb::MTime1488139599%tEXtThumb::Size0BB>VtEXtThumb::URIfile:///mntlog/favicons/2017-02-26/36a23da25da7ec4be3ab43f2b158378c.ico.pngFIENDB`git-secret-0.5.0/docs/images/favicons/apple-icon-144x144.png000066400000000000000000000074511424706700600232700ustar00rootroot00000000000000PNG  IHDRИgAMA asRGB cHRMz&u0`:pQ<PLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P35QtRNS)LuwM 4gǞiW֢["hn&c@Evy0CGQYb`ޮ?.#%->V|1k\ d<897 JKнo(! m Zr/{BHl fTU'sґ}R2;je3S:xӔ5N=,_qppbKGD_Ϧ pHYs.#.#x?v IDATx_epewKd]Yܔh1t"W0#Q1pY,+5SRP#̢;(>OifgcfYKy|fƌ, Vq'$Y ,'ON*ǘxѴS26al̫^L8Ӳ\قVLqLw<q5;#ʓ_0'nD¢l\%Mv ozC"qzna#4D0)Tً}|ͷT0뭋<%U:HZxݦ3 $-+9nIT% o>ܭ+\+}uU;Q-D0K'Y97ll=^jqٴD˟e]dHnD6S޺5׶̂W[8A#H}.\qşZl]Qt~$&ĘȽ{~AE{5Հ{.ܹK"n64~zܴ?irQqʆ#hC+TaU9r}}RLO`SWDiYCu?} pXC *j ݥ!Tջt6Q8%d6mu0,/G(l0Mm ⧖ب?T5M:Qm[۬/$e>}AMn AMuCGGMse@櫩:NYǜ>EMo >.jǎy99 ~x?NӘ={  8MRg 񪝨,+\ԒUW i=d/ZJ쥡f,)9HXeP{*U-m*/T-[:yT j;UС ^ Qz5ӧ]Y9Q=C" R ݈x̶@tUoEXl%%Pw-|hy Mk[gҐW$sP_&PFsW_ŷ&{4ojK*O=Q ̙5{NDkeҋ.\8ѾÆ%& N$Z"@|ZTj/)kd+ IwMpsK"kAȪRMԀw~|X%ol!K7^Ρu"IHTނP ^ To7@ Q@R#1yIeA xՠsΉAw~~5cJ Z.V~Ĩ9B-:ӣѵ|+ 4&'>0XC'ie㌁D ϱKmmhLm3_Н/@]& ބ{-5{ Z |_A/2G;=}6 ej AeiԹvՕ1gvr{Iw²HxaK[HmOD0몢ʗ.TaA5\ ;v.?.nQ"e1$_&)^^1e\p a5^F b2f,15y}^FԬUacүf97ܫKvN: '2uC>_t`Gjh~C)2jf]w/oՐO\>H= {Y>F_Mz Z %i]L^,jkyͽe &aŠVڄoC. ^tgAf]-s_y- &VLXdj7 n]m^~\v/u 7"e]Mșwk&{(e]X+5N^ոyEU%ϑ5^r"v5^Djܽ9bSE-.^D,jq爦7/9Y-^DxzsWwH"xs3ZDU+U1/yzFjxE|&P(?7^DuDz;}HK 3 0`<Ֆ(Y%tEXtdate:create2017-02-26T20:06:39+00:00h%tEXtdate:modify2017-02-26T20:06:39+00:00j;FtEXtsoftwareImageMagick 6.7.8-9 2014-05-12 Q16 http://www.imagemagick.org܆tEXtThumb::Document::Pages1/tEXtThumb::Image::height192rtEXtThumb::Image::Width192Ӭ!tEXtThumb::Mimetypeimage/png?VNtEXtThumb::MTime1488139599%tEXtThumb::Size0BB>VtEXtThumb::URIfile:///mntlog/favicons/2017-02-26/36a23da25da7ec4be3ab43f2b158378c.ico.pngFIENDB`git-secret-0.5.0/docs/images/favicons/apple-icon-152x152.png000066400000000000000000000103011424706700600232520ustar00rootroot00000000000000PNG  IHDR/gAMA asRGB cHRMz&u0`:pQ<PLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3tRNS/T}ǨX2Duϫ{G 3t9 =٘FA$y҄+LVw*?SRQ1 .xÀ>:#sh0)kg-^z647,5&%]'~к" ZiK |䉩_@o`\BY 8lC喓Hr[ON!fcJdU;amIWq)bKGDlZ pHYs.#.#x?v IDATx͜[9+abYT"eU"USX*Q+ij ^Ikc-5mXBhI6m2gΜΒ><{;a;) VQmS?4!SD 3g}%efM=gnڼ "25?;'U r=5钞E-Û_PXm4sK}"y-Y*+ѰaͯdrAWV}6%UQ!B5XҨO̊:7;K}kf' T?KZtX6p+D\2!wU4L%.e&0 Ԯnо;!~[[56pdf d>Nⳟ)};kv쮏5{4.{2֊mZdF?Q7x_A)kIxB$@fZtrvLlɄuozw@9ǖ x^#˘%;ðZpJЯg`f64|e2ܜxA0>CȪtYf,~q"F$O>ӧ΋4XS}69%~ >ӥS\Sd&<2hKx7^)7qܬ)ߐRyeSkZ~y;g9w)dL>"77sp 38b}naBRI YU kki> En}h* [Lfd,ƄfZ[~|6 Ҳ)JqXYDDh!kUͤcRXl:4a'05#Xm?=JBeY3,iT_A;!K|}ULUЌpr!iR^/ y-ex4u]vIn[M75Gxk!^U51?8Hl"I9SF/ǒ1vy+ QPr_6@j]ڄ{>$8m7*9 }jܛ)hw{}OxӶ.%gUgwN+Bڇć?4$|Vm۪WY,lw s!EPr}0A2 :*hd?Ew!æA$g体L<3#M"W۠j}@>cwQ);ޡ=k$̹6泱:2/꧆$1CRGSCnjl13&1KDK!4r$VBZJqjBu4qخEw T'.2YP[R ;E'YF5_zh{n3بA8E64\u3T9cAM:GXQY61\%I&ן3,[`'DkYI?"J?"q #I= Ey~=>#QGΓL 3p]ό3n5 1~065[8,(p|>;W9cW_mN\ɧ?֎?Ow~CtTȘP7f㳇_8K6oο3: =̲ʙ9 o4#펺#6F曅r h\}F~. Q JPs61z 1##/)d'CRKH3/oږ oāq1>4xiBd}+VtEXtThumb::URIfile:///mntlog/favicons/2017-02-26/36a23da25da7ec4be3ab43f2b158378c.ico.pngFIENDB`git-secret-0.5.0/docs/images/favicons/apple-icon-180x180.png000066400000000000000000000120601424706700600232600ustar00rootroot00000000000000PNG  IHDR gAMA asRGB cHRMz&u0`:pQ<PLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3vtRNS (HoֽzS1  ?nЫ~M%@ĊQ$ )_޸t7,m͆i"/٣GRq-A.5[`^Ƭysu]Ӛj4ߴڥe!ݞ;Y Lhb>OX<&Bl8ܡ+'dx}{茍 :Ka#V9ɷ3pNW\k|C*w0PcI6UETvJbKGD2+M pHYs.#.#x?v IDATx͜_TU= 0a|٘Pp@!N"XH//[hDe/*f򦉽jֲ[m涭n{=3$\=>{g'> _Μ=;hr OtsH-Cra-x d1r>$j{qpv[1w3n\8N⊃I'@99%0A-SҦ!)8ҧg${_=)=s̩΀S#t_ȞȜ5:+mW9f92?87F2rֲJ˳kfƑR&y,8 /( 432 uQrt- ef-KKM,`3d25,\SGT=mF]sFQT ]\\8jWF4.=q媇CzMټayvf?QuJaY\ὓ)_tMMiGmdk߹^^IՑ5[t698ےkebcug^^O#Wb{j[Q O JyFSg='+Kz1c;vnڴ`cw.l۳%U)T|v7#"FR#׽:R\!~dj.; MǡA5:KJehykah2mS1Bmu U%2z|J{^4z+յbjޘ,[A[':#Fx.Y_OvzT#шᲯvRԙ]PY۵0{'Rd{M7uШ ҴmQKfJ֞icz[H!jBoa*)t,m>%}7!Iȭr19.=7K?3[&[ǐT=U.q=L먩N*7\KٞHԭԷإM:Y#"</jEfChS%S(<)OSq6v*4Mjf~\#/ʠ0j>yB|m$eS`XwGT-CifΝﻋ=Խ󭩆KZ5uvӞG}iYMoQTI#{ 3[|q[vwԾ3% '㢶ST# n3%]1L1kS$eaPGW{:" zf^Rμw ]i yCR"/Ek3gݼ1) 3NYm0"w'lmθ9A֮iM%Ir[<f<7S{TѸo- (wmϞi6UhZSEᲲ>P_S-쥖cWDATQyŋ;FQ\HM VnֲyXe EPA:SnDiHa"IA *aMli#g]ՙ{{'ELՒGBĺxRIzƃ{zÏ4^I:rBr/6iL:T41#WZm1'4)LFGv 5EөdIS*!HhFUs{EK}DWN,8QDHDTgU `jdz|-x/#L^16l(>|FuܨY$MlBM=m Tpx؎\Ff>jH2UdY\l{G藝{M 85ߤM%K_nPg‘0la!CKKBlK袄bA 4PJEk3TsW}\$Y-P 1-+%Sg|ZCL!SJ)btf~M^]+Z~b2U+ scyd: =5`zַo@[\G]CM *B|]%FM bhP.JOOBUFj @c(15} 8gB zG>ceQ+݁^2UL!'QD|mͭ'ASs*#ͅS+h2*/j 2U<. ؠ랪{-kK CckQݧ[ө*-[ap !X> +H?v]9>  B8'u瀄! #1̊BX ==m XyJZtqtqhJ e t?Ƒ.m՗;:Z{oGx 7B =ya: %m=:N%7в*N,$\B2a@OTF>)5}TѤY@Jr=>Or 2#dIqfC?B{v.#|ݙJ\ Ddht_;+3(Q$h@?_V2HDp|O}B-TVQЂ憳*QA;ޗ0 TMWܐYjA a-ZuGXj+X(جZZp,a$32{Stmۯ B(hĤks쪹Ly(ܕ0`{rʕo_*খٳ:(mB+5:*=FA:)k v7Tk919p ;!1!1{ _+e;05ط efx*gg/4z؞duq7XHm_ٲWӞ2>ˠLb~b^Pk\ė_T,:4ɬTKNM5d:Z:Z75*w3ŒHLS]l&=J;ipQT;O_ҕ5O>x%&Ɛ7ΑO=JŬE!j:S=pR\2!TgrQbnܦ+.4xƓ. T6Lme?M!z fD.aS e=JFu{@ Fe7jQiL>jELձ'$z,6r|Lc~[3߱^aS]rlϚ3ElTm?ڜfW. QS5 y0}/. QYS ]ֱWφ(Hw7.k2EE;]fl1̻:a?LpQZ\ֶ75Eaj1į. QS]2U(H ύpQM50.EPEh5S Jq2j&fV0(D-7TBzWKBm6쎦/R yD;g>K qLF%tEXtdate:create2017-02-26T20:06:39+00:00h%tEXtdate:modify2017-02-26T20:06:39+00:00j;FtEXtsoftwareImageMagick 6.7.8-9 2014-05-12 Q16 http://www.imagemagick.org܆tEXtThumb::Document::Pages1/tEXtThumb::Image::height192rtEXtThumb::Image::Width192Ӭ!tEXtThumb::Mimetypeimage/png?VNtEXtThumb::MTime1488139599%tEXtThumb::Size0BB>VtEXtThumb::URIfile:///mntlog/favicons/2017-02-26/36a23da25da7ec4be3ab43f2b158378c.ico.pngFIENDB`git-secret-0.5.0/docs/images/favicons/apple-icon-57x57.png000066400000000000000000000042571424706700600231370ustar00rootroot00000000000000PNG  IHDR99sgAMA asRGB cHRMz&u0`:pQ<PLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3tRNSMЍC PH%;ȿ1<6&௃u(,~4 Q@"$+޶/!.ò#0Iک ܨ*->V´Sc)E9NbmtĐRѭ 'XvӬq38^Z7O}bKGDW pHYs.#.#x?veIDATHǝCRAMʡ>M<3o$*CQHL-,n>,v<0;;ߝ 6ifdMr`Ρ1:7og~r(  -lI&-B*&Fv!$DVHKtJ-YcYiCMm74؛)V4FQ#W58@v~Q2]rvPDkբ@E^%w)HQM)3J#Dj!_-rf{d,+VL,:PaGdУnc8AENeձPͼNsNrzD精j!0c'S.gP{Q {,g[D^yk̕g[DԻ6JĨON.qh,ct-=q%A(NJ7e 4*gkL ʿNd|g!=`_3 0>ǹ_X? l?yЯau5W=j"I,:,Ir5)1A_Mm8*el$IЄ퐡)Nmq]M||' %tEXtdate:create2017-02-26T20:06:39+00:00h%tEXtdate:modify2017-02-26T20:06:39+00:00j;FtEXtsoftwareImageMagick 6.7.8-9 2014-05-12 Q16 http://www.imagemagick.org܆tEXtThumb::Document::Pages1/tEXtThumb::Image::height192rtEXtThumb::Image::Width192Ӭ!tEXtThumb::Mimetypeimage/png?VNtEXtThumb::MTime1488139599%tEXtThumb::Size0BB>VtEXtThumb::URIfile:///mntlog/favicons/2017-02-26/36a23da25da7ec4be3ab43f2b158378c.ico.pngFIENDB`git-secret-0.5.0/docs/images/favicons/apple-icon-60x60.png000066400000000000000000000043051424706700600231150ustar00rootroot00000000000000PNG  IHDR<< ")@gAMA asRGB cHRMz&u0`:pQ<PLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3EvtRNSX٬v4 %xB`~96_ߍA"0jD &Ԥ?JyVWN1QaSRUIT@h5Eڮ 7>}Pb=ȭ ^-ecH ;|ʑgY|bKGD+ pHYs.#.#x?vIDATHǕgCA)PB H@PPPlPTN/;C>s3޻ #LxDdT '3?lNX 㐚v҄q*A22,L9hG(03<^T\RZV^+ti5gjl &hnG8{?YyNhgtbh40{/{\NF_ďuЃwFG`o_, +OeE`|b;*PKK-bzdTS)*I&oW=]bSBillm-k@@MLJk&}b,64aa䤟TKrZA`x^MS@ -]os`=ňUL2Uk~3k yX=tx 0ӏLŨO2ih;™jѫĩw<;f6s'.^l=8ՓC;W Fylh]^;VtEXtThumb::URIfile:///mntlog/favicons/2017-02-26/36a23da25da7ec4be3ab43f2b158378c.ico.pngFIENDB`git-secret-0.5.0/docs/images/favicons/apple-icon-72x72.png000066400000000000000000000044561424706700600231320ustar00rootroot00000000000000PNG  IHDRHHb3CugAMA asRGB cHRMz&u0`:pQ<PLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3JtRNS 9wʗYWχ1JG"dno3!'Bt*Q OZ: N X=+L-aÖ| 8@60 )(Hר[ΜEs.ޥTF5P`{zbbKGDl1 pHYs.#.#x?vIDATXå?TApgٵbc# abQYU+%wj !=CQzowgw3k>?3{ϙ93V\:L fKU%-YjONXi6I1P\%E d`uyb-(FZK@u(v;%()?>RZ>WpKVʵ,WnXU]SIxsX$oF;иEe׼u,?Ѳ=mYnՁԩJ{v)e S*9}nQY2Ьz@J |Y3%#Ȍ; B9YPu"R?PΪn0H?'-ݨ֮C%ieUTRxJ4<@;r?%(TGǸ(T:M29ŮΎT#seOr9Pp@+Spm3N>an]Q@t݌lR" |ᒙwy!Qcu&@eB) z1 f 5!иZQr.ڑlgɽ$IDuΊr9a$99l U I UԪ3;<չ4rQ%9. !78y0R w>HdNS{F$nGD֦%Oa0AOm|г A=9!Aۼ|yAN֨}*O6[y |^6CmcHT -94:q/1$o޾s7r^2H(zP+'D;,IFJ?gG'_ھ1GGzK̉[ b%yA:Tu?8;Co'q:9:F_]LNN9]"׳E:rNSmӁ8S%tEXtdate:create2017-02-26T20:06:39+00:00h%tEXtdate:modify2017-02-26T20:06:39+00:00j;FtEXtsoftwareImageMagick 6.7.8-9 2014-05-12 Q16 http://www.imagemagick.org܆tEXtThumb::Document::Pages1/tEXtThumb::Image::height192rtEXtThumb::Image::Width192Ӭ!tEXtThumb::Mimetypeimage/png?VNtEXtThumb::MTime1488139599%tEXtThumb::Size0BB>VtEXtThumb::URIfile:///mntlog/favicons/2017-02-26/36a23da25da7ec4be3ab43f2b158378c.ico.pngFIENDB`git-secret-0.5.0/docs/images/favicons/apple-icon-76x76.png000066400000000000000000000046571424706700600231450ustar00rootroot00000000000000PNG  IHDRLLIgAMA asRGB cHRMz&u0`:pQ<PLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3StRNSAϟc)jٙE h92tN՞Y"#צ~e`n鵭! {:gǰdU8kVB}Q m'M;uK\(a+*DvˬZ^R/$>|%1iʾ߉zGOW=sCbKGDj pHYs.#.#x?vEIDATXí_G*B &/$ƫRZ"BZ{X-M[{Rz=aw3#|wyvޙٚR֭Po]}Co#j 7=h#͡VTCأss ()۶Kнc'aF4KQѽ;N\"ѓ;zm埲g:_GL`*)NCa[jOӑcqCPͨ@x)#%Z'O>@ævϣ:hXxڈ'&rxRxoOgҠyo q3hO7Ѵgʲ M;@v54o"북wy{ji9It]@2nB:Ě~>dh180B+$hk|e\ۋsCҬ$b)襅vJnAvv^䖾XEkpJWc+6n\[k]$A_7sNҋ;L/㸵SҋE~mW~a+Ux0;o:/fMe(LᾑV%xn^jܪrqCbnU{1t[m^-+}g>?VtEXtThumb::URIfile:///mntlog/favicons/2017-02-26/36a23da25da7ec4be3ab43f2b158378c.ico.pngFIENDB`git-secret-0.5.0/docs/images/favicons/apple-icon-precomposed.png000066400000000000000000000104461424706700600246550ustar00rootroot00000000000000PNG  IHDRe5gAMA asRGB cHRMz&u0`:pQ<PLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3~tRNS 'ItY3Ld0 Zs =\N"Kw5^ z>n&C-_:uBׁȳmvE4a#G;qѧO{7V 2MXf1 <$(xgj!F[%PH*DWռ9ӓSU?~rQ6T8ûJA]郎lb,R)hy"pbKGD! pHYs.#.#x?v IDATx՝Mr ܅<)p&F& h`C!"ObA*|E,شjsD7|ggnwo~||vgf/II2"Օ6rT6 rƎ?abn׻ 'a4VsL1ȩ 3n*@ͷr"ns24LL- 9 VV?*Js,rJZ~V;n!>E5V>-eFҳOK]&-x6FZ~M_f';emJRߕl?SZM&?o#_YJ4M~{2 4֭'ަ5 ֮ZQ43Y;%5 |т;`Mm7 lޒY,bJVLߪq}yswlӝ@%@]cn0!4iW:-kwFvsz=rOGYП{|=bm2$܈x(G5$?A|aԭ1@h##(%MH?<$]WCF9⛩9(0 " =.heD@5Jw 5O'cK(W]_U.LYm,>""E3R>X]9S[mS`ea-.6BhK|ϐ7kGRzK6`D.QYheQtC9p5S,7$`$Qnl,u\4B9 e)ب0d{$Z"Vᆈa,)RU9 +1y'}eer& -0ulp*Z%."Zw0%9 7VW ^뇒."5WOsE_ j\&< ?➃1DG~nm *x'K|O7$BgVtX3\_p?=F&B7Q >?-3nc`I/[?6%>@7>#l8F5R)w"3YAiߐ`i96&uc7pQ3\<6q 0g}.YԳr# cP{> _QGǘ)9ҿa="@k ,-«u kU \` :#X*neY~5?*Pѝ m=8@e-@H2+E0.bz9@ XC*(,V9] "U09a1^)k-@E_a@ V&#s!X<>0f_ooU"໨.:9TDAL?~ۜ~M{gve9`^6Oz*>Zpx"⑃K!9+ ́TmD K`lA p9H r@Aۧt{#nLd/@ZQ Ai @4AJ?r?j ЯݺmN@t"}Ar ښg ^\į~\lme܄*0s} QB1kjDtW@$\a;^eZk¿dc@-1^-U4 nIFߝ ($ngmeWX]2, '1:>5Gu :@ouO{XM;~es>mB1nՊ+ANBCkp{Lᄄ$0Ц˽89T/<+@ ܛ109h]#"{U~kC;7-sH@sgIky?>_eI~贴hr7\*_UWu&p2A+#P`jU@i9U~Iͼg@e{W@aagHLe#MI7b^JVߤ./|(! m'? ¾E9 u+xg=sŗUEv>ofU+)Y{?|q~cЄrB9Oay'E\S3.Ŋ/L ;q9(gnAs۩Տv~ƫğˈ>?o8VA{'׏{iw׸`~&"*bE^Dq0K?,O^ЕՎяkCwA9ȿ/;m}X!3j 'ۡ_~-J l0ئ_QlԯE6_&ˁ%sR.08F8H)9 5a8N`_E0#?Lˁc#s`(9hG8A7t%Hs09H T% 5")V]N0b)po%f=-㺓]߼:%tEXtdate:create2017-02-26T20:06:39+00:00h%tEXtdate:modify2017-02-26T20:06:39+00:00j;FtEXtsoftwareImageMagick 6.7.8-9 2014-05-12 Q16 http://www.imagemagick.org܆tEXtThumb::Document::Pages1/tEXtThumb::Image::height432$XtEXtThumb::Image::Width432/ itEXtThumb::Mimetypeimage/png?VNtEXtThumb::MTime1488139599%tEXtThumb::Size0BB>@tEXtThumb::URIfile:///tmp/favicons/36a23da25da7ec4be3ab43f2b158378cIIENDB`git-secret-0.5.0/docs/images/favicons/apple-icon.png000066400000000000000000000104461424706700600223370ustar00rootroot00000000000000PNG  IHDRe5gAMA asRGB cHRMz&u0`:pQ<PLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3~tRNS 'ItY3Ld0 Zs =\N"Kw5^ z>n&C-_:uBׁȳmvE4a#G;qѧO{7V 2MXf1 <$(xgj!F[%PH*DWռ9ӓSU?~rQ6T8ûJA]郎lb,R)hy"pbKGD! pHYs.#.#x?v IDATx՝Mr ܅<)p&F& h`C!"ObA*|E,شjsD7|ggnwo~||vgf/II2"Օ6rT6 rƎ?abn׻ 'a4VsL1ȩ 3n*@ͷr"ns24LL- 9 VV?*Js,rJZ~V;n!>E5V>-eFҳOK]&-x6FZ~M_f';emJRߕl?SZM&?o#_YJ4M~{2 4֭'ަ5 ֮ZQ43Y;%5 |т;`Mm7 lޒY,bJVLߪq}yswlӝ@%@]cn0!4iW:-kwFvsz=rOGYП{|=bm2$܈x(G5$?A|aԭ1@h##(%MH?<$]WCF9⛩9(0 " =.heD@5Jw 5O'cK(W]_U.LYm,>""E3R>X]9S[mS`ea-.6BhK|ϐ7kGRzK6`D.QYheQtC9p5S,7$`$Qnl,u\4B9 e)ب0d{$Z"Vᆈa,)RU9 +1y'}eer& -0ulp*Z%."Zw0%9 7VW ^뇒."5WOsE_ j\&< ?➃1DG~nm *x'K|O7$BgVtX3\_p?=F&B7Q >?-3nc`I/[?6%>@7>#l8F5R)w"3YAiߐ`i96&uc7pQ3\<6q 0g}.YԳr# cP{> _QGǘ)9ҿa="@k ,-«u kU \` :#X*neY~5?*Pѝ m=8@e-@H2+E0.bz9@ XC*(,V9] "U09a1^)k-@E_a@ V&#s!X<>0f_ooU"໨.:9TDAL?~ۜ~M{gve9`^6Oz*>Zpx"⑃K!9+ ́TmD K`lA p9H r@Aۧt{#nLd/@ZQ Ai @4AJ?r?j ЯݺmN@t"}Ar ښg ^\į~\lme܄*0s} QB1kjDtW@$\a;^eZk¿dc@-1^-U4 nIFߝ ($ngmeWX]2, '1:>5Gu :@ouO{XM;~es>mB1nՊ+ANBCkp{Lᄄ$0Ц˽89T/<+@ ܛ109h]#"{U~kC;7-sH@sgIky?>_eI~贴hr7\*_UWu&p2A+#P`jU@i9U~Iͼg@e{W@aagHLe#MI7b^JVߤ./|(! m'? ¾E9 u+xg=sŗUEv>ofU+)Y{?|q~cЄrB9Oay'E\S3.Ŋ/L ;q9(gnAs۩Տv~ƫğˈ>?o8VA{'׏{iw׸`~&"*bE^Dq0K?,O^ЕՎяkCwA9ȿ/;m}X!3j 'ۡ_~-J l0ئ_QlԯE6_&ˁ%sR.08F8H)9 5a8N`_E0#?Lˁc#s`(9hG8A7t%Hs09H T% 5")V]N0b)po%f=-㺓]߼:%tEXtdate:create2017-02-26T20:06:39+00:00h%tEXtdate:modify2017-02-26T20:06:39+00:00j;FtEXtsoftwareImageMagick 6.7.8-9 2014-05-12 Q16 http://www.imagemagick.org܆tEXtThumb::Document::Pages1/tEXtThumb::Image::height432$XtEXtThumb::Image::Width432/ itEXtThumb::Mimetypeimage/png?VNtEXtThumb::MTime1488139599%tEXtThumb::Size0BB>@tEXtThumb::URIfile:///tmp/favicons/36a23da25da7ec4be3ab43f2b158378cIIENDB`git-secret-0.5.0/docs/images/favicons/browserconfig.xml000066400000000000000000000004311424706700600231660ustar00rootroot00000000000000 #ffffffgit-secret-0.5.0/docs/images/favicons/favicon-16x16.png000066400000000000000000000022621424706700600225150ustar00rootroot00000000000000PNG  IHDR(-SgAMA asRGB cHRMz&u0`:pQ<PLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3DpRtRNSplE3/븪KKw{6Iě>tO ?Ūf#Iw'/˶VtEXtThumb::URIfile:///mntlog/favicons/2017-02-26/36a23da25da7ec4be3ab43f2b158378c.ico.pngFIENDB`git-secret-0.5.0/docs/images/favicons/favicon-32x32.png000066400000000000000000000030671424706700600225150ustar00rootroot00000000000000PNG  IHDR DgAMA asRGB cHRMz&u0`:pQ<}PLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3S}tRNSNd ,5c<7Y/$O r\m] wGZE(@ +sbo2p>D*C.;4M^&t}#'LbKGD~?As pHYs.#.#x?vIDAT8uC@a(fAeVeYaS{/[;~xb@A+KR0W>lvFr NEH/rkjFInLُ|K+m"yF{ iaE/עt"x1[ΘA%x{z|CW_z  0'z#& FFLBx 81 05MΈjtojDqh[Dn_FcV:$y5Gav֧66ե#- l7ĎRRfH&5S3jBJkrCPh';sy}a׽1Q}MzDq S%g;3r0zF?< ӂݳ⿮ ;>!ŝDzY}+%tEXtdate:create2017-02-26T20:06:39+00:00h%tEXtdate:modify2017-02-26T20:06:39+00:00j;FtEXtsoftwareImageMagick 6.7.8-9 2014-05-12 Q16 http://www.imagemagick.org܆tEXtThumb::Document::Pages1/tEXtThumb::Image::height192rtEXtThumb::Image::Width192Ӭ!tEXtThumb::Mimetypeimage/png?VNtEXtThumb::MTime1488139599%tEXtThumb::Size0BB>VtEXtThumb::URIfile:///mntlog/favicons/2017-02-26/36a23da25da7ec4be3ab43f2b158378c.ico.pngFIENDB`git-secret-0.5.0/docs/images/favicons/favicon-96x96.png000066400000000000000000000052341424706700600225370ustar00rootroot00000000000000PNG  IHDR``F gAMA asRGB cHRMz&u0`:pQ<FPLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3{ OtRNS4hݼW&$gҙQ'dkѷJ1N,_7:lYS]tzG#8+ui= (mw/UI-%0޸? srDeHj[֚qyTد )^K  \VvE`. xCp>ZcڨUEbKGDdfn pHYs.#.#x?vIDATh޵CGpI$QBBX5( R!Z@6ŖjZAK[mibZ-^ؖbsf왝7n $Ph**^SbFY׮V`d}r**"qSE SkDJow \55oy(Rt lmClk!@u;Ҫ;NFEvYwwu!/}Ld@pD328B zp8& 8ēcoʡdI?u$̄N $ܿcYTHx:Lxd<[>pW?2j?8B*L(,]_`pݺf>YPIJa |Z'PuZݪԂ[Cu36sɤn|xOZ[Dl$^(y`t@@i~@epBʸ~~ Vn7U|f/B.K u|a?_y5>Wo΄ B(|}L7 OB@$@PQpT# P<#~e͟^&BLi (_zwV+T#Aq-!."g G=29?"-r3' "n-6!F&l>"оC=|_;‡f>,A:WlyYl]4_B % (_µGBCSN'nڴe mAor䋁`3wKb`Hn9UwGǹiykY|)]O:佟 hӊ7&BJ8QE*\q&yت"MSL[xt }vi&wݾ9U!4?=̗_5!V R9O<߆4IP'O,d}4$d]|"|m!~X~MI|uajwhՄODg'mpmIxv/ 4B>q-Wa=aP~MW;w] nX7_Q'{ C9u+ -J\u#ҿgW&S|"AW>3_SН!*" + +g ˄VtEXtThumb::URIfile:///mntlog/favicons/2017-02-26/36a23da25da7ec4be3ab43f2b158378c.ico.pngFIENDB`git-secret-0.5.0/docs/images/favicons/favicon.ico000066400000000000000000000021761424706700600217240ustar00rootroot00000000000000 h(  #.#.3P3P3P,3P3P3P%3P3P3P3P3P&3P3P3P3P3P 3P3P3P3P3P&3P3P3P3P3P3P3P 3P3P3P3P3P&3P3P3P3PF3PI3P3P3P3P 3P3P3P3P3P&3P3P3P3P3P23P43P3P3P3P3P 3P3P3P3P&3P3P3P3P3P3P3P3P3P3P3P3P3P%3P3P3P3P3P3P3P3P3P3P3P3P33PI3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3PT3P3P3P3P3PV3P3P3P3P3P3P3P3PA3PM3P3P3P3P3P+3PK3P3P3PX3P3P3P3P3P03P 3P3P3P3P3P&3P3P3P3P03P3P33P3P3P3P3PV3P3P3P3P&3P3P3P3P3P3P3P3P63P3PJ3P3P3P3P3P&3P3P3P3P3P3P3P3P3P.3P3P3P3P3P&3P3P3P3P3PC3P3P3P03P3P3P3P3P&3P3P3P<3P3P3P3P3P3P3PU3P3P3P3P3P3P<3P3P3P3P3PK3P3P8?git-secret-0.5.0/docs/images/favicons/manifest.json000066400000000000000000000013201424706700600222720ustar00rootroot00000000000000{ "name": "App", "icons": [ { "src": "\/android-icon-36x36.png", "sizes": "36x36", "type": "image\/png", "density": "0.75" }, { "src": "\/android-icon-48x48.png", "sizes": "48x48", "type": "image\/png", "density": "1.0" }, { "src": "\/android-icon-72x72.png", "sizes": "72x72", "type": "image\/png", "density": "1.5" }, { "src": "\/android-icon-96x96.png", "sizes": "96x96", "type": "image\/png", "density": "2.0" }, { "src": "\/android-icon-144x144.png", "sizes": "144x144", "type": "image\/png", "density": "3.0" }, { "src": "\/android-icon-192x192.png", "sizes": "192x192", "type": "image\/png", "density": "4.0" } ] }git-secret-0.5.0/docs/images/favicons/ms-icon-144x144.png000066400000000000000000000074511424706700600226060ustar00rootroot00000000000000PNG  IHDRИgAMA asRGB cHRMz&u0`:pQ<PLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P35QtRNS)LuwM 4gǞiW֢["hn&c@Evy0CGQYb`ޮ?.#%->V|1k\ d<897 JKнo(! m Zr/{BHl fTU'sґ}R2;je3S:xӔ5N=,_qppbKGD_Ϧ pHYs.#.#x?v IDATx_epewKd]Yܔh1t"W0#Q1pY,+5SRP#̢;(>OifgcfYKy|fƌ, Vq'$Y ,'ON*ǘxѴS26al̫^L8Ӳ\قVLqLw<q5;#ʓ_0'nD¢l\%Mv ozC"qzna#4D0)Tً}|ͷT0뭋<%U:HZxݦ3 $-+9nIT% o>ܭ+\+}uU;Q-D0K'Y97ll=^jqٴD˟e]dHnD6S޺5׶̂W[8A#H}.\qşZl]Qt~$&ĘȽ{~AE{5Հ{.ܹK"n64~zܴ?irQqʆ#hC+TaU9r}}RLO`SWDiYCu?} pXC *j ݥ!Tջt6Q8%d6mu0,/G(l0Mm ⧖ب?T5M:Qm[۬/$e>}AMn AMuCGGMse@櫩:NYǜ>EMo >.jǎy99 ~x?NӘ={  8MRg 񪝨,+\ԒUW i=d/ZJ쥡f,)9HXeP{*U-m*/T-[:yT j;UС ^ Qz5ӧ]Y9Q=C" R ݈x̶@tUoEXl%%Pw-|hy Mk[gҐW$sP_&PFsW_ŷ&{4ojK*O=Q ̙5{NDkeҋ.\8ѾÆ%& N$Z"@|ZTj/)kd+ IwMpsK"kAȪRMԀw~|X%ol!K7^Ρu"IHTނP ^ To7@ Q@R#1yIeA xՠsΉAw~~5cJ Z.V~Ĩ9B-:ӣѵ|+ 4&'>0XC'ie㌁D ϱKmmhLm3_Н/@]& ބ{-5{ Z |_A/2G;=}6 ej AeiԹvՕ1gvr{Iw²HxaK[HmOD0몢ʗ.TaA5\ ;v.?.nQ"e1$_&)^^1e\p a5^F b2f,15y}^FԬUacүf97ܫKvN: '2uC>_t`Gjh~C)2jf]w/oՐO\>H= {Y>F_Mz Z %i]L^,jkyͽe &aŠVڄoC. ^tgAf]-s_y- &VLXdj7 n]m^~\v/u 7"e]Mșwk&{(e]X+5N^ոyEU%ϑ5^r"v5^Djܽ9bSE-.^D,jq爦7/9Y-^DxzsWwH"xs3ZDU+U1/yzFjxE|&P(?7^DuDz;}HK 3 0`<Ֆ(Y%tEXtdate:create2017-02-26T20:06:39+00:00h%tEXtdate:modify2017-02-26T20:06:39+00:00j;FtEXtsoftwareImageMagick 6.7.8-9 2014-05-12 Q16 http://www.imagemagick.org܆tEXtThumb::Document::Pages1/tEXtThumb::Image::height192rtEXtThumb::Image::Width192Ӭ!tEXtThumb::Mimetypeimage/png?VNtEXtThumb::MTime1488139599%tEXtThumb::Size0BB>VtEXtThumb::URIfile:///mntlog/favicons/2017-02-26/36a23da25da7ec4be3ab43f2b158378c.ico.pngFIENDB`git-secret-0.5.0/docs/images/favicons/ms-icon-150x150.png000066400000000000000000000103311424706700600225670ustar00rootroot00000000000000PNG  IHDR ߁gAMA asRGB cHRMz&u0`:pQ<PLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3tRNS ?fӷjA! *Yܼ\, K˕Q[cX`=Fpz08HSheryxЍwI'#E~2+|װD ĺGnT3oW4>֬NV]UguB}-lL(1Md.6CZRPOdz{)a^k"q_s&7:5}\bKGDlZ pHYs.#.#x?v IDATx͜_S=0"D-рj :-e(8-T5jP'bvJ͹>8W6g:S׍랺 $tv~== FT.HHLzdqT,!lXliFFӊ̫̕V %+{MNHf}'l'_Z{baQ#\d?UbQZVA.* FnzCPmgLVStdmW6AƊ8"ufSAXU\BTx|aKBF^*6mK?ϵZ lj&֮zsV|;:_եΕۦjZ2dm+{ܷ@ӫ5 8rn8.nV'u8C0`CZA17#}*6kn amȪ@]GQ*,;%un T.(F 'R0W#'1:z}d{;K-q“o^,Ts;$LBgoh(VصC8Tt-?-=LHzSѬ|E5ML1gB^+}ʼnl9\iӫ_5De/jj9ѺЯw(1 !͉~eSsm"}Cj金\1 \l\*PgGtӰ\*c+&Ĝ(p^>E-'u rErQsɯ?0H*P BE"Zo zwI\~يJ *g;:yR\ ˔}neW` \eaE*nC> ^# a]a r _`=S+xlA& Z4a\T__;ȼ7ѪOoF?1 舻(ƅ,d~H5~LZ1/}#q PD51ԀVs8z%~< 9_ ,tOc1_)XvGS=%_/֓r;B`诹aſ/9!ROy l뫙X$9sw>TN%.v_rf.aX Ay>bl,,V\6"Kf2(̱0X`9}?bQ]:Xe^0Ŋ͍}glbE˨kscUXgiD멋bEIP,K)Ximb`xo9'З٣spf,x.^-,jXu}>c| շ30XY¯cm.:`܃y {Xwa:jb{Rk5!NǂƸ g|c6&T>H=ZC&Ri2\3Ы+,BʉhFEU9MA9@syc'CV2vE߳ˁOXvbyrljsɎW~.x'8}%r1DΈJ ,et\lSlAg.褠E~~QDo6e|ˀmޒҪE1~+}]9A.Rus?pXu *U֋T8pM(Wb\_~r7Dt4v!o$:sb?;IEW* ̎T+0}Y*E2gFsI{Q~9c{.4ܾK}9|%rkE,_z)Ҥ~ qkuW0/_$__<:+''Ůcdt.6ENAcXε_& U$}%"+ p딪 /u.=N|\j:ΗD.d@WA.\;%^ v1~: rY7X}k*_:nZC`"%tEXtdate:create2017-02-26T20:06:39+00:00h%tEXtdate:modify2017-02-26T20:06:39+00:00j;FtEXtsoftwareImageMagick 6.7.8-9 2014-05-12 Q16 http://www.imagemagick.org܆tEXtThumb::Document::Pages1/tEXtThumb::Image::height192rtEXtThumb::Image::Width192Ӭ!tEXtThumb::Mimetypeimage/png?VNtEXtThumb::MTime1488139599%tEXtThumb::Size0BB>VtEXtThumb::URIfile:///mntlog/favicons/2017-02-26/36a23da25da7ec4be3ab43f2b158378c.ico.pngFIENDB`git-secret-0.5.0/docs/images/favicons/ms-icon-310x310.png000066400000000000000000000415701424706700600225740ustar00rootroot00000000000000PNG  IHDR66뼾gAMA asRGB cHRMz&u0`:pQ<bKGD pHYs.#.#x?v@IDATxv?:l8xp<{۽˝8NĎU/!NU%'9 nwTң'K=ó0,nVk0,^bF&|EC0p* "P]ʨ yۀP2r?at%^xlMdʣmB9B~~p>>ߡ6+o425lM j]<<MJ2=ߐ'g;|F'*l"cRh]EE>θqd ]ADgײc L)u;ND<76uT |ϩ9@cC'P{FA$^ C9m)Ru_ ܅inDIUUՕP78q>7Z E{F'|#)EIƼ6MíJAF+a (:J%4sia 5l%ts>y^,pt#MG+8n0U=3y!Mׂ֞2"m;Q[V4r i,G>?,C5t;VPhr^$98Awmxm)O 0^2XhB`gFŀ!SROyxPm=2p-ss 'D8WuLz3#u/4Yޱ2냏1rc1;r?Ƃ/&7D@nA9%@ʿ>KzyjN@x$ȞV? )ڃ(lC t3B[%EJPDc6}*܃>̈́PFƥ~T%ԆIv,~>d&$O\EֽSQ_Ȩ؎eԻWEW'C JU8Ens ?~h)C%( 7 [UA9crȽB>$F"f ՐM nCm,k{/7й:;g(AF@3m!t᳠.#FXF3un0ܞW--ѰEd.Pea=Lpܼ#ϝ(()U/H*ye4ϻ >0 HoMƨ(oG킻ݍe#|d7M"K>rɽ>,5QhedkSk~J8rVA7WO /tK,Qmʫ' ҷG|%VPp>t5V ѵv 7]*ꬶP>Hy1>7 >zPT |+(dM]v@3@Ics}[P*K*huᄂ g!umFQk§[;Gs yj5tZۭ΀ d']"r@5"om5_( & s'l؂YS!\媣?cBPʿ߭u>|6+' K?GȠYۭTQK!A-6!-I7P[[;M"J&}n!O-܌qP1s 9U-G54$Z:Dܜ|֔P.t(,=yKIDk6lShtP%VP<_eI rL9JYnjD) EBcvaCdpiHuGUjkNjy=DO*ކkPJ&lpO= D/:&#ʄki !@ N+Jȹv}nG7VGmLPHuaet5hm~5R&m4s֌ LmӗJXX!U'XF C/So72@L +(4 K\b'j_; 1"u'b5.sܲI$q6N f7ab2Ҭ~Q2ꀷ6Oh28PbnA!x0kE)#}4+uTmA<<bZµIҥUCa2pSYcVL fTPA Ā2 iNWMbQOE n^>4F=O20{I7CޚyN,,u{,cgB(k> XXU5jvb1ы)a1ƀUҡwsߤt@"_bR%iYye1cfu&32"s3°5Ѝ0fgܧQ%,էQ~uQ+GS[_םBo ԑA_}~>7"!p(Kz͕B]װ ip&dv!6 tqg<i22,ivAWPRAZK@zk(|/#{wlA2o`1a1 NN22lPR f>#5c  \As`C}n#a;>[q1~9`FUI9K( XD; ^ ,'-v+>oF ߔIlsp" sV&^ KC\s3FbI=֣.;ATYn({ }j;hާ.p Wh Qh*(p}n} 7ܬ03Uy ]dij \cm.\7a٬O]ۃ(ܭL M GbmcDDz,A:X ?_BFafSkWPxv_wzpc4461 s*p7PXV8ڇDq3lMQ`'K |X,F}n}ȫ/QXz  ϭ UT< 3l.WtwtNDjpͷ F>) ϗtneTP؋os ftϣ)Hbr=;,֬Om#~28vk7vg1@$.kyx/"=y`13F.\[' 齨( ~D?]C1NIdFPb=Uy2k@߫U9yn>x7w΄ bߍ):+S({/ݒo+yfs4_! z]EFb+_߀ 15Y$ztOF58dɦyI`JMQ/*$_c((b>fL?ۭ]@a x U]dM f\sJB7hX2ݹmA2l0UF]' @\ƲA4s 6lGhޛyaAkqO!t "A=נt-SMا#m2&θ|Ka)L+(4h/j"A2BȸKrY-b)lP96cmtǫS!3u%^qZZ}j(8VG݌Iԡ?*;QtbN f~K]Wym?5HE4%ڿ^ +QOm|TЭz*m Ĵ1n )2BQh&|mU?SIGOo(&QWdק.CsnmK in计& tm.X[3D܊nf GQu9Hs4lK݈?}j~me95n+ad܊Esut'U yI?MOfXgPbz(6[lcNjbvvx&z|C9" vT .R{i.Y5@@!z靪`ͩCNAᕼ]!.> DVYDBR܈/|[ܰP2{3إU.1ҕ LvWvaR[K ?F鏭ϰAq >*id`ݦv(} cGnJ"քWBT 94yg2>B[w7s *P= 4+\G9oQXG6[M\ȸ^B9m |BBCm<D*_дĽB%.B 4l'۩5CNv뚫F}m%a.h1C )2z ]'PܨI>n崧3]%䒫ߣCC/ hU>%(WPxea@Tb^uNq1nߓy*Iə8Atf妻0%FWрeEniMS0jm2*LA X 2ukdV8Of<1M [K{2xGR5ь_ѓ(dnҧ ΨdeHqBEy!61&I/n15\^b؜Jw.t}U%w#Yxn~rw𳨭-om&]ߏ3IJ*ZDs2}FwF7)taJt_vGװఴI G،<:_%@| =} 'dZm٘@{s+vYBK[)(Mx%MJoA7qpCG?#o1jym 2f; S ۰J N)2ğ {g[ӏ6FԆ~9-0Xs]LH|^;=DzkhxD^Dk/gԅ[ު bAt|f/g}Pjh#t_\GaםXX jQ[[7hĻYBYaDj^GL(4^Ew[9S(uSD dV*oQp=6z[E{(zsˊN{^FFbq3_E}^> G's[n#(Lrk*]hTD؅DybO[5jGTE)@LG>iWBUa࿡'^)qaa(fZgB^{(GZ=Ucۉ݅yn͘B? b?ώxluPyn ķss)np~ ]/ ,` Fm'\ZPEmfqҼ)bB7bǹ8>$YfA!C֞CoV_C;AJ {U(O d >2nڰ>[ ' V~:a15B>A7kkBa&Zf_q膍>-,NxB筌xO1֤ɭДB *㸭 +$\b$K.Ļ=!< [h( KPAa{c KTQ8>t疤 Oħ UA]n.w6Co%[)϶S[(2f7PQa-i&j[ [yn '[GA˖>s] #2*!{)Zbai^ův$s> 4 Xwbq+΃>;QԊ% ]] [CA6p+N f7) $fbN|ai3OɈR" #KPn ~3|>DF3hb KX[ZtC$bbai NVG{Q,nO:#J'n4d~ Ԃ΢> >TPnk98DA! eUG:PؐqEK'28o#nhAө@LbTƝbVx5bo oGVE-%՗Qu1=o ]!4".;a8Fj1Y5q{4kj978 y1;&i?uGlp9N f'὿IͰ5Ymz f j%y]o}:;:gxA}l7~u'VPy0~8}oKc)snrF)“sڏȞF ~n`}nq1=}naroo:.󸂂}n7VP2rb1|fIiTPp}Ln(=Dk>(Wbf1%dh:a5.^d} b>/WP!J@@̭>~d\A>7߼!MFGP }> ~ L xaؚ]hzv1GƬ<wUtӚ@LsAׁyakB895`2ܶ턛s}nqhA.[_)g)oE#*ӂb1lM&Q~ta̸-܆>B>sm /~Z~ntIAh6ۑgC=ư628#2r>Uotڤ426hB(0 m8 IjHҭCj{5BQj"9^|YakB}ocy*` #"1b]($3 78$\A_ud|D-,E**Qexa~zְO ;w O!FT hr[Y(4rǻb@< 3lzDٹֆet nvc?m ĴK-o[{xn>c\3\ΰEpIPg02 >Mivi3o֢"UJ!lف )kU=m^8l6wC=B( ia O݈֧k~=JPF MȰ: ((sV_ψw`30V c\ǰ B:9 ׸@ݽ: kl3ed̶Iv ?_wL3Ptwpb3hjxxQ˄xe؂<w+` |g} hxp- Tt+ЏB!

6-t a7@f:3+%d;VfR^B!1ckix 4P8:rhL0 _q,Ȩ5)>5Q>FOQjXWzF `ҰMd`תԀI rͺbNu}MTQ; ƀ>,5>TUڨ##C hWo0&fSxd3Ї6.{4#8Z4D1eu$iW-`ɜJ3D}VR1q(}Dw7>6ØEheJE#nHLs~aPChQ޹0`^? ף>Np )}|l g`zFOQsFq6"htdd70y#2=8 BOO8Zf}@1UnF Rf}@nC7/K0;E _!uq (* xX#%Tm܌toWf}@e^,0hPvDJzR>E2d7P\w/d< v8gf8\֖#A(2lJrN#r1Fb  6nemS@idp*mֶ!+: d%=Fϡ̴w9զQ zu"ΎmhaF ޶Ȱj:bt'[ PB{)w:4yj( ,)JZHČ8*nT.7XHo i~T,UCPfs ?Kݒڰ'[ു.ׯRBO(,5fBUFC^5o[6Kn< <<7UaPX8CME,gg׃R)ߡtYTp+w<n^#O{T|7G-=rcb4PAa ZO1>LyU%k#TT^iڣh`)ŹƁ/?!O햜Z\ 4N_6" Gn =kzӖ 3ӹ t> ۃ(\ϫS{ G< f si"4q}؅B"}FEh5py ?j'ѵG{P%KK+IՆ-F}nN fvC$p 5k~f]\+!QF{$.ґV0s;ŭ}n>$B^WȨciCA`-\ҲJa@LH;1NS.JPzJM e |~סԊӶJacFs@F,,uC,jӴͧW!p0 }YжJakB`b@ZX(:.<;$tF?|ck1z`ݍMJDŽW 8M isk(Ty UNqOw*&R 1$',DeI0VpQJwSgYAw>Y r\؍9 &QGSZw=Qشyѽ`$"fqa ,k"3N7Z"$rDNj)f1sZ;>D}j#@-{} y0 $}qnǒp~Ÿ'UHxXyH+I`mvL ff[;mccDW>5'Ҁ|yk`[RFa)fVʱMpe; y&*WnD0)x }.gd.f:LGU F{ȼi7+I`-y1ݐ,p{e1vSr̰%Hlp>綎Η8VF#5+YąW>%C$0Ö>7'^ | &a^I3l ѤP#)y/SA~ϦJ-8(a}j$h"@LXCq ed6 2[ i. |+I`-=1eT ނ q!I݃lF翨ؼ^IneJ4,  =Y0N -@L=Vr_F[%-P^mҨx0JhN.}֠ɄPLQ? ۇDƶ(EkL^9V9c.@9SC9`*Z-mFlRqu:x%͵JaLK@LQ<>^dP@<ϝ%V޿OBq+Okr$f<`1O!O926[5͓~ց^77z? !V4L\x r&f<"&@U(^nF^A y"uvм]yuE5,¹Vx% ̰Mb ĸ!tg޲ϑq;ŗQh55C^*4p/*Մ;JAW Dܢ}F^Kqn ږ#ݴߠӄ*RQm 2x% ,jkS lvo ̰n)!u/'> 9^B7SAͶPn%2B $A™IW;C f] IqbBW $?>:jVuJa+6')@L k:$Фb ys^I LpsL~>d+V4P,.2ZX(=c>5eJX(D* < E>HAS[1 9Px1>b+)c1>2O^I +tM ?aIટQᕋJݜf&ݨͮLxSB.bW2Ğ]1hp?!&f G\ $>l00fDbN1}p)m!'a3b0 ~@{FXI_c1sa+a1 Ÿ́W>Īc1q]H ƮWV( E@̜ti@Zn1`͘q W &* ?Mx3̰ss;Iw ąW`+^bX B׻ Enm&֧-Fm0@o_Ry^f,@g*@  Ev8K8~܊$c+9BQ%b}nw1] f#hJgdDb |LO Z>0fK[jϭ +m?$1W1B`i1p_k[:-&S&D .c+#fi@ 3lFDbƀ%c+ $b~ԄW 6#iZ秐 &XH@je)^yj،ĉ@}nH-.yۖb6gPX L۷1c>;ḮW ،hV SBB1J' E91cȊjxLx6wf+]6#"1'(ʹX6gPIH7Q\̰>pUIO#9!ȻmppE5 iˈ&V<02%RPyhp^佭ER/!/*pGϯQڤusG:2~{DF4Ҏ"vfF{zp{*j%tEXtdate:create2017-02-26T20:06:39+00:00h%tEXtdate:modify2017-02-26T20:06:39+00:00j;FtEXtsoftwareImageMagick 6.7.8-9 2014-05-12 Q16 http://www.imagemagick.org܆tEXtThumb::Document::Pages1/tEXtThumb::Image::height192rtEXtThumb::Image::Width192Ӭ!tEXtThumb::Mimetypeimage/png?VNtEXtThumb::MTime1488139599%tEXtThumb::Size0BB>VtEXtThumb::URIfile:///mntlog/favicons/2017-02-26/36a23da25da7ec4be3ab43f2b158378c.ico.pngFIENDB`git-secret-0.5.0/docs/images/favicons/ms-icon-70x70.png000066400000000000000000000044701424706700600224400ustar00rootroot00000000000000PNG  IHDRFFFgAMA asRGB cHRMz&u0`:pQ<PLTEP3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3P3YtRNSSۯt4 '{O s<1p EŸQ%69m J^&| 0:є"3?\݋;,q)!/5ː́7(}]Tw>_Xno*+eGWg,$bKGDWe pHYs.#.#x?vIDATXÝ_0pd!:0Tt&TQoTE "ҶilMӔ O^6yI.%E -I ȑ4sr'@[֊R•22P^U"cuQ5`Z"w]`D RD@c񔖕Wlke p;PI[CΒmxAzVQS J[u]D~箆(Sݸx?h*浯9!%~{[^'|][r(O=J#:iIrRspu'wq_1/s?ѳ -ka^xӔI~'˝ԗ}^ + dȩ#tLKpuϼ;_ zE3Gf:QXv*ύ $HNS4v<gsؔ<$ҏZqv>F z#҅yxdoRD41k9z4Tr4Z-\̫ט!S U loٙX gp}pbTjc`cC?q{gcwC2I;}_9 Ѥfft (2v2~_ќ!d|̈h|,)1OASjF1ThW힚KTf{M5yb4^3E*lEVtEXtThumb::URIfile:///mntlog/favicons/2017-02-26/36a23da25da7ec4be3ab43f2b158378c.ico.pngFIENDB`git-secret-0.5.0/docs/images/git-secret-big.png000066400000000000000000000662641424706700600213160ustar00rootroot00000000000000PNG  IHDR,l pHYs.#.#x?vtEXtSoftwareAdobe ImageReadyqe<lAIDATxq0Ƶ?F`o#`o `"`&ߩ:&5oX̥/y-u'߾}zr__.Or<lW L\Լp@K ;;~Z-x_g5A姯rXx\81Ĝ//L$`Z) 0 ̫p9 ] X!)CrRr[a`KQ.'R䗖˙mcXO♔z.5Z.$~XM9Ţ1_Ū .ϠlI}׾Ъ5u%ie>bÊ˹`PKʤ\WsI0\X T&-./?H ):`ywvZOJV'Tl8*/ɶg\~+.`ywv<ACٛ/b+IPbqtNe9k;;>V9/ze\U9gxV[(+*+jKeY>TՖ_%@޲ XޝU-`e姹W6[ޝOJXW+,Ύg-`y-b2t2W9>W卤G[*CIur2XR#ɀiXYy \ˉCrl'ƻ]H%;;>-4e]f mO}čsYB_~H4%eu髤HKKJ:Ƃi KJ:tX_=-`)XI-KR Z$y%XI-۷oewgǓ;N">xWIЏwgǧKINb-zI1}IN-zz2xS_ Z`c^ VPVcxVx.q [nVZtNK}Vը!Pft?VP2M#,ΎCl^YwoT<^7]|W8^ah<`WVjЫ-iai 0s@b:AX!9&R&˪Us,pue#V Y}=#l ỄE}3Ҧ+,=`eB:W@ѕ +wVZ][{ea++{TY@_e-`*+-lrZ3 VNI5Е++-ά²Օ Jo2g+-֭gLWZ잭Zq+9EF'9Zi#+-֬;X+59h:i姹Ne-V<;;?2~.ds-'h 4W+,'?:yL%Ш'߾}?ܝ?7gù߬\J$E~$VXf\+feXr3}޿4L%{wgǣI4L%VX[[G2y XN2|2 Z&Oʿq; |WYZ.A Zo8i&;'h>[]9<Cx3\aL%K?m;XgWe-GgvSYe-P_*7'rq#ؕag{Xؿsg{9#gX2߹, (\/}L8+sGnK+,ie- wu =)`B4M2y& hǙ^oemL%@!92ՙ3-Lu.he-2WOWt ½{eVXB$hr/9Ò_IprIВuZtk$ {գ:{Vx%%ַQdנ^I`咠%MK,]סdݝ_#ɽd`^I~rIВuZqee%:ͤBk&:]x'%AK!h .n }sY ; +%r:r$ʶcrIВuZsU_K{3Evv* |%~$PrIВuZĕׅ~64c, cKXzprIВuZĀ` B6{=]E`咠%hU4/4ݍ%r X.H%AK!h |_J47d(X$h:-7,Fj bX;؋_b,qrIВuZ4kVг\L8ۋ??grcYKC6﶐6}fmBvwܡˀm&/ӳ~a'UP%hɯ Z4g6VDoˀLM+-Y%@3muƏՕj`w(ǀD%`咠%hF8K*J@swۖH!`咠%ؽZiw)1`7n2SYăKC`n^5_7%` ;;;K:Ⱥ_АG2]AK!h {[7ͤ{_Dgt߶MXf%AK!h L[9[|qNHXn5`ۖW/=+-Y%@3wLv5+, `"Ғyr)Ǡ]vF`vk}>y=SЀ)a+/`K]!j2oE}Y'z&}h_Z5i%@3m_}wc,9$`|~y}fta[ؙlWaʥe2{.9LpU>"S8'Wr!C۷uu]:}ᣞIl7 M%A3|;;>\f a\V`*>-۴T)/-k‡6mXRobz\=tOq aETe+UöPakT-4 O6ۧ3n>pR[] I!`úN¶[ VjT-;?kzgʹM_W> 1w ^39 TCvtwv<֘wἼ̞cZx%T V.%qe+Pa_`wLKfۨ6W~m>vY΂'_'3,8wrJk*L˕ :TwLKRnoαv%//SRΰ r[-ͅףoR ;X 6alTs*`% =g>TCE-?姐߂` u" P2׭UW4H^C Z~; 5c}7`!4tJ6/bdZD%La{Ytrwv|.kw'Xϴ w"h _ְHAv'h @QKf=+r=.L\Vn]JZײygL@%A~g9 Yʝ~D7Bخvtwv< {4`)R Ωl^%T*6h}/!h @,:I{kY8+x[c+UJ˩m%];31}[Yޝ?l͋{(,&h @W=)hX4O_bśO+[5/ ,AK 1t %U6bM*6]Pn϶M%mV2n}vwv<킕ll@*HXco[6χuNT-voܿ΀yRsex2\3.rb4Ϲv{4 P|?W˅_?]c > Z Vvj>g\YAK.-ˁTxgOS˫ -ڢ}^m>.vYFUl0.y1yVc9}N 6YԱZV)+ qlO7_xm)_VPOj:J[:Hܗx۷M3d^r#n\Vꅠ%OWT :mpu) [?K6_TnAg²-^~8K|/cmqem\oD9#2,:Ϗ?z,9&-P_¥|4/}eví\7> w2ēwexSX9+:h)XBh\Mv-ɵxTxdr_ #|ZHf XB8a<w?V{\)ȣ7rzT:-qk$wyLJk::#\)RO\[L2fʬ*oeUAK~:uYi% Ϯ;o{fȷ7~vGYnE[m2,ljmĶX߸<Q22ZG, Gu]},о: 7N>lWV_ձu.fy1UZ Vۙ%֙ `!bG6+yNY~f7r:ua !3n;Mg4ղ[WC|磟]zShFf은%miȟȕ7)0$VMi L&_'. q2_IQ-S;m$9F91J!5qCks 6U/1r?Aɑ|OKc˘CpYhZeLPZ-飃w/+ ˬ&684PUVMuǴ2٢=nb9{.5e+SQ+.7{ p}867j/˱N\X Z %}uHy +AKL <; E@٩ ?.7*JJrr6*8%Y.74:Or0 ,anÇ1٬ߕ`YtS:)Oӷ([yM]osǽʹ8ۘւn9җ˜i,wR V'Gx̱%m_U=.DgRc+K2$P籌K1eu*)r@yeXfVgypyͅ4 sq&VXeX*|]rcjR2YGZda M7&~󍉷Yx_ؽ1x=1ekUXyg}qHuF')ShBH.5gMr Z V&JT'prWV~Mj 5r5Ӭ`ex\XSY$AK6mO.t 695m⺴\Y4JN rsrǰ Irzi[ˋJg}w'|sڲŸ96-h)Xz#ٛ,AKiK+8laYns26L%?5>WVUeGAO7(a5Z 䶄vB™ʹ姰D|:Z Vf%aY'KВG'*+8 vysŷ%Nk+)fzMqju-bvfoJx8ߟJ>pT`_OZҸ6VXJ, ^ : Z Vf]쨄gL{@< ܱVp@2X)0Z4)|-w԰b-lC9 ԃ։Wwk$U+}ʜk^~VgO`eŶH9d-teʴ˗5d.h_s]{cuרg׉)&&燂:`FkAK읔NLV@:Lݫ\'>r-Nh_LxVOGj23BAHF%?NY0@dU%X"en>sgV礲:x}|ڳž+cF˂Gv h@3k2/`e!i JHv9/W+3+y6`eeV>: d'{]%B@t砥`eR,AKD@2*oEƹʖ`er>C9e 㛩|#h^WQہAKbˬe6dD> lk(˪LVV!퇷(J$!hy54TƧU;(t%:W/ޡ{]eJp6'`eR2 [9 .Iפ^+1Z WX:h)XI&0ndF8AZ6땋݅fsV@٦ E}IJ0d5l}!opy/.BuA*^70РB1tK^m)hA˼ugDg}_]<\}imiLVWf"UCq͙N7T)DZmنv mn /$sޞ|-Nx_a1dwbz^r2;`P7o!JSò-A(e–cvhӞha:Sn_Ob.ߕ{}A mEA/\~mys>pȻUJ??{}wҮ-|ctqaK2˕M(P ]DpwXyS*hnQZ'-C uۙ0h =G36Ŵˣ߅<·o2YXWMu>?ccPbm>_+wt>ͼWsSx[y [خ5!v3Nbۖ\Fsq{r+3t 6ܖ>3nC&r^o׃-S r-ө(WwrR;,ϗCW7ԙ ܟ7 Z+daP EW@ţB<4u)qd%\iC/:!>3Ɂ0Qu+A]28yybUV$4 ޿*Igv R?mj݋>&NQet([.w)PN4Hz#,ȏ%tZ =WK?u>Dk@%c]ag]Ge&<%sq8ӳƒN Q\ cI}&+C:-~O9}PsZsBGƄ,5X Hޥ$߃11]|zI'ڨK8m8ڦw$ض]Tyͭ~[7&\В_LuiȤ?E~E2;~di*1Isbm~4!CY QUaauᴯ1p B<#u{SAuF$)|3I}vُ7U{IEGr+ˠS:xJ%Id+uQ NmI胧 mZdkciSZ ?Rm9[-*~YauxgBn>qAvT^mϊs|> wLm;s>4~ AK!h\&EoK9zH 1/Ӫq+hJ ^W`Tl=ULzIN+!J9>ewhyw3`hCGT9l_?_v|^7)digr\%9l({+bp)l8EDrEiϝ^cͬl_A˃bӂP'> \nSs+Y5kG!΋~W'^5Ve d@-Ye9|6 po̓8 LKnoճ<Ƕ>gC$UkY+WԤ#h9QN}3:1nYƄf|پtC"O3MlE*a1j/m\ d@-YeƙL:0fб{ [qE Wq0vZl:^!Os-:XR&3-Ohz$s|,_!pa?}A uؾۻ+--Օ^U*Wrl\Cq( ˠeoNzBв2M]e}B~m ݕw[Y=92]̻ Qnw29z<Օa+գRm JyoX-zW > mZA(!!<]K]nbw })Eڌw qrؖ&dep8 PRXI9Iߩa%M01h|L6'U˞&d_-!uwC |?N*YK=N;/ ]3֖ȜU#OQ-r B]ZGr_ i^!/۸Ȁ6 ZAЉIVtTC{n8LS2!1aQAP_m%jZxڵ/lM 'h:-Ys i &u?=n,;6r#L;(|z;7:b2{jAK!hپ'E׊Т΃Ե2rý(}qӘ T:gc[X Xt&C(dJ}Umav#_qb0[j(ftT84"<ēw:rm#Y{=@tBВuZ׍$j==Cʜ@brަVŀQͩθG 3eTP AK!h9L[4=νr0ՕKW ۸'1끖Yv(xnNNVc\IŠV5=^r Z:»%!ln+IƄ/ǒAaT2$އ9u1Ь w[f-QcY ioN|Wqy2x{%?W +-Yi8pISxqXsߑ|VU2G )0P :!h:-&וaӤly5O:xǙTC n;ض-7P 'h:-軳 < [+Qe_ή$o2}ѽ~ hFЉT_}}U_{rU?y:/b%h ͹IqKв_O%VjT1,CM9Wimہ߆!m_~hrcחJ+$K7;ieq#B2dYʥҾ%|o^v߆P'8{|0~`_uav"Vs 4$< 큭N$Ҳ.6 V>g]$_T/؝K}SJ"/o> -;6? nf_ua>mHuEGsT_9`!4ɞaC ZB'b*AgMfZn'Ia@2r?JeXmovAY_8h.qw2vv>gtڵFg1h9SUŞ2  oe-7/r{9B'y?qt~ \kѽ^ˮ>mgO}umN_ c94L XEZWr2 _YE}-7 R:)? D4AyP/pynA+ G/K}GϦC|Op~%A,;)6h-Fmw%hﯔ*l߲ U}ˍ ] G뫺m{f4u%VHVB:_iY-V9r7VZ>"S/cui!*-HҐO[/^2^&ȡ\6ChB8@jH3Sb;;YK3춉TEJg^ ^-9q.` GR([4jHOA*3RpUj]۸_*Ug\)L/,4T`= XB?FeAʒtH]ATuX  9y/%CXu9KPAl_\ZZ+bݙsXQ1 \'LtVU'i Ьp?8@SJ\ai"W֩3٫oCgeǸEӫ&j3=U\ 9 0Ž 2[K08S,~><\^&3뱠]ea~~ٕv\.?]mԇjq# ;6A˩>" ҍ$ Xp,ٗ;spoz[-~?NX92 1k `&bB%Y[I (qKC Y}$xдHb\_~IO¶γl_X>: ' ,wg5U;y PT}^.x-5"ixlCF?Uch iֻ,"wr e3p m,*KېI9^X]9 jgeZͶ*|Sz[pwW\eY嵣ܶ;2HW+,zDnߧ+ζN{pe} SXuAlm⟝ĮÔcUYuƺF ҵ7g A_B~ N/˃OevZmSak]S\uڦJrSmi뼑0#q׾uƚ| +>`+͉ܝ z[Bn}]$C7 m+!P9RVHl<κ/ }_O[;P1 q KF:]!uiKAxr;!d+n騾//+g+V3IE_k:Ϭ(4L7HAon3W$lo('-!/`Օ q\Y8}]_3* ? cTV˭okbwr)П>r0 m`Y=|'!Ӱ~ssy6'XM|ZUVJRfE8kb 1bKԡ *6 $CVZB~m}b`%+q+WpcuЫŖd {ij) hȘ*{}e[X~( ފAʱ+` dno-h +V5d++U| R0du;x;s/6.ac*_gvcimn{X$]fs_mD9I !xޙΑPnu+( k:Opvƶm\g ǘC{m]Bc\>.HoC~xAKNAWVmӱl|Ni^Ջ2y bɿ2tҡ} ;\cBy;_R!9F;TV ڶ\ꌰ"{3@B~zZBv Z@ˬf ,XM{k:},x ԡ"pV]HG=dzma)4mkKmm=ILKPZS:"~Y>+7%XM]"շqxZs3JÒ qt/,Xop5-!'Ἳ(UcM Vv*9qV$ blu%pG-,2UZN+XbUXw0.d`i}+Y1iv k|5g}}"2~m ;w8׏ mۺ& "`٬ܼۻNa uEXUi Vv$@~Ꮁ>¨tc.u̪)<2HY%h ٽ崍J\QꇿO`eR8@s8JVaeX-ٹ|6'a8nI t߶~WA\c0UJV^eX}yY-VKwG9;OhRa$;ٓGz:fVYU&f޳U؜`I- Jfᄐ\w9زv5n[X+0X`e¹Uz[6M {^1yc03^ֶ9 l@5-!Xٟizwv|$k2Ǜ6L SwC8 ȇP Z-_ J~1ple3Pцx-'x^tWK~~p' '-׺/2v-crZ7 +$!ؗכty^piyU,CcK\.EDv*νo^?Cȏ ˑ>-9ϕ`뼄:ɦ[JoRWr|kgQx!% VK,M˳8_Z8[r>L.O&wA'K"@eZP@*L@|2~Sݺew AK GyOeZUn v|e 5Ϳ? q򪭉VYo5on ´buijA0_N榲]Aβ\uX%QvuYAF/Hr?Y^%K}|ͼwi6?][olK؎+ϖM2v{= Li[کe{miΫ'zb囪,څ~Ϋ'ܷJ:=G[,UP-e&Ͱq,ס;(|mi;g)uv BީRZ|4kx.J9zc3-/S=Vme;d%Oy1#p)%NTcf.0}S{(^t1l2 p.Au:NI'vWeۚ9^3J^Uc]9ANEI9eTlǴC;'SE.cǏ.uSݿuػ7(X:%}+l_༭_3(&MЏ}\27&ج#q}z$ QZ86^n7O 셟 ex7s_ j@e//?RƾQzA?XҸa!}e5#:U J>VnQnV2I[)`_LAK XK2% IAv'4yza;r$߽P~R< ^q1Gnη>cCɭF)pɦ?sQuAq K޸hwG{ҫ,t._H !ep0qkX7ƺ\HW¥4Κ6owUR&bB޵.o縭p#˕ߗk&U(7RX3׹M-V̳JВ]k`eYmɬzSwgƝ(`#q7`W`bXy؎pGCϏOש7eZ(oC*w\)A͌v6mtjqټr7° V׮[>[MR{mKܳ&$uYoaeΏPųPVXfzquy=J|cbɸ%y'oDm{~Ouv^ǏeeZx x\_gʮa;Va@kr+0hጫ효|$`b> Rx9Y*u3b#Hn5J]>GSY3oRۚL; zAbxv,өC'SrB0,|SٻXl#9,ew'RblIJ>avNN($^N@݈VqP| ISF8-WhW}1eZL<8a FuA6e^x+%3-1Ʌ8~%X->!_di.jAKR5- ~Mma^J`|]xl̓,Ӭ-EoYn*A!Nb0VPU&J++yDh*%*Օcs7xS LЇΦeْ=@xk]A2 V3[:W AdZ$׾{'S-!>M3sZNV+stQ2]wG>4{+Wʟe+ٞxYvu*ARϤDB':l7;ɠ|Vy^VbacNs[1L_d^>Qezʷ ::©dl=~WށUqȾ\Ė1p%h9Y+WL,ʋ\Ⱥ]sV0yfl|{?̣c'hYΠ":.{v?HA;1LTyekeV: ǂUR,`%]cBQe>_2o:ϴl VCN.ՐyelKׯD&%ng((T,gM_} VCQeÝƝz|*){@5&LpG?׃*A;;9iy{M*诜?OA˼, W GܔK*fVA2@2?3܃>&"XɯR?oNBsl6@PFE/r;^sR Z梈Eˠ, [&t'PM ){7Y5+tz&EKZY0;te?KYy_ h֖Y3>J[i77d kvv(X2߁e>mA3Y *+@:"uy8 ?nX2 ]ZkGe%[Rݡj1>S>'q@`(1qL3ɨuq@ʤXnf3/B/X _09仸mJwPdm}9׉~MLAg500V'ٞ fBy[Y ܧedVwrx9 }?G}Cki˶7,ELϕg`%߭ï%A~Zo$W})˧zulLaeW[#Ж Zn^noI.`Y΋0-Sr]xI2`%8tU*Ä؟z땋$+LmlCxg[YYYw i%ާ X^o%e370nrƺ:+St^ho, ZҿHo+ɡWqj~U|bVmR>.NJ𧭲)p٬/Δ՝QLKdP0nqT1z2v[z":*mп۝$:.v< L0A2׳MăAA8g] jh5*).lчXqm祍;>n%VoT-snFko/`Y0-;^Dz7`%/3ɣXFoa4^% t:C}6A@%}kaדJp~@eieE:*Sx_6Ǖgޮ68#i@9z7H`ہ\A TR+X ذ /13s ɮ<41|nE}|s4o ~w2ӷ Ex>p:mVMU'6oyB'Wg ,xRoVǧ`&܄KyFn\FK~\C-(_ ]70t im%?qת)ο?_TbC x&R`IG' J\'&mO03:XpUO"77.)`jHo{ش_kzllY=/2w1x3溁wǶPה7)OsΏMqY%쵋z:q?l.JϽM"G ,)~7O" !o6_.O=S{h&ظm헎;q9Ҽ9vgLV/qxNB5dR׎ϻM-i9֦okr~V -{3'8S[4}Kդn]օʅ8|wL c~K:>u ,u=C\λ7aTUa]}kiї-]E8;a|5Ly ,=gв/~,9V{@ms[6 2XU%C\Gm5^}qcssm[cЇ>Ρ:>L;6zYUƪW+=H+w\۔{VR.Ⱥ֡.-m"R d+B˃]/Os]q qgJJ6˹nfW %[Z}U7חaopgJP9-@*DhyjVFݵM3a%c1-˟fuP9IFtkk %;Zu.߳{t)P)ևkncWJ"d/B˃zhYt_V[+a%]a,pn9вU7O|U?pH -C$VqY?C(5Jk;cX1F*ym 5RSO]hTBNXIkc¶T׫* L 5fXr03-ڼJl +a宄m̶\T}TB EfX3-ߓl^W^a%j3_mfm_6׋O @tJhyE=km5WƠԷ^ބfI:9 )K0>K:'ė3l敠J]Wc{a?Cymyzf 8(߅ٓH^-ʪr߀)կV}kYyU/!onU]WG&j)Xe/eFg&fE5A剮 US?ۗكW<%ZRa%CEX'P aFO9a%)6ꖰ\,В +I1x'B \x%,GdHXIt/ n ra%Gc%V.! 7KJhI&\GaVO7a|r#脖$NXIXƛ X2%VK ctVmWJ&d0BK#$S8' {K%$Jr7jhٵJJ^`pYX'56y]nu%0Ò$i@X&JJb%I1K#VRj DomYs@i$Gh+)ŲZYC,x%,jCz&_: (B܎gJJf%2Ӓ+[]z""ԫ+]@$MhIW^Rod^tc $yBK: D-̶WmO[K],ɂВ+[-"z#)1\pX %{VtZmWzcMZF: ,ɊВ+:C3*cPyF -قvg^mW, -yak /_μ6)~&$[BK jl3"=W=%$kBKZ_eӄߦ6}]؎ -p̚g^6K=u&2Ԡ[XR +ay9m1qn7jN`I1$jڄq&;\gM.zXR+!܄qyZfYjJƚJ8%Zʪ܄jȪ^6ߚUG`xK$, .D'?^=Qa%F`IV@MhY a%J`IV@2[J(ZfGX # dTVH,e0"KFIh,a%Z&GX #$dԄVH ,=0bKV ,&<:a% 6+/eWKxв7J;KxвsJ'Kxв3JAKx`JQK؂roJIKؒrgJYK؁rkJ`+KؑYJ`kK؃QJ`'Kؓ'J`gK8+a%%Hh)'8VXBGFZ + ,C# -@'бJ3KAzR`h):'Z +^,gJ7K8CKa%+%I(RX ,RX ph)J` I0VG'%Z +A,a`uh[hV]%^/O&W+Cׁ) ,,񯉳*'?80$%$m9 m^u\K @` [__EN :3*,!#󳰘6 shMR)w IENDB`git-secret-0.5.0/docs/images/git-secret-sm.png000066400000000000000000000152761424706700600211710ustar00rootroot00000000000000PNG  IHDRN0* pHYs.#.#x?vtEXtSoftwareAdobe ImageReadyqe<KIDATxqٺƵqVޚ0 "M#"O`"@#GpD"Y -1f6f%[yTf`uj=ߧFG6?9_˟ϫۿV%TgOݖ-#mifK4ӸIE"E5 Xʡ(:)ޖ- Xh=op :?K,Fr&NYLgs1lX:sKc6wÄk\xw%d `L[8Ẏ2]mFeښv.w*Ap Õ- Ld 0LdBp m:\|~wz#kZ.gZmqٹjh1`s\y'q>G4r0yzco9$^C+Nײg+S׼k1|/` 3u9նwes"XxuC0$_rNЮ0S&kŋ,}.fǪLyǙ~|̷ >J??O_ *b `?uwO Ԣ<}(˷u3.G@$ˎ;wy\b0%]!X_"&_-;yjcㅘ40V|x:=.sj`19(bPwʡU;|ƬL[U8SSA˓wjyښW?Z/ɑ>1jW 2jء|kbxӒ/i.+"[I]6?c$^ki9}%-mT &Gp7n{v9d9Vm1E5cnCl}uL~x{W+κD[ʄ7Wl;7s=wVƤpݵuN#Va~#a_uBF /[#N"۬L\|ms.jj9^ԗ6E,wR|t})=OpfVoomB^$vc·[#v 1vaރr,%V]o8}= RĎ˔5/}}s<4}WX|$6o,c K;w/y 4^&1jؤI,@Lb5U4}I^~>o l*^ĶĢݹ$F n|*rk(&1.wR/&1 ,s͇E | +61D6'khcj"F\ۿ˅=]~^$IvuE}"hʝ7΃>'/(ChxzOE E6fV!b4r4sϡ!b=>.1D xkfU"=nM_"xʽqCC0;|ܗ!`EfV!"&bXk1X_>E 71C=1C6s1lsç~oo b"ÕU-` 101/}? 1(w/DL`rb>|" 1nދX+ 1quau!b"&01C C8D΃.@1M`C01D 1'7V"a1 D C@1Ez")^y6="!`DכM?D #Jά*g?D ZUv!bAx"&`avf#KD ~n&^"U|ϖ!b|(LD 㫀EHҋ!b|0)^"5U/CĈ%b9&^" XzQE LD E0!b|(SC|/C* 2l /C0x"FC٩;Ӌ!b2}aՉ!bq!!b"0x"&`_D;8K16e6 )[[P"UzϭFSJ/pJ5o/?ޖ7wZmqwh~->]oU{Um[ZIyUBy9wW zljXĢ:?G j=9?MQ[֜;ty]=>dG~ ҭ"bR%bۅl~:XԀ+"nVxN|ZBN`4(^"6T91 6uC/p_La5)W'dPx"|E Xywޡ\[%b;X~C{c5X ,vZnNxnؠ|u3vhA~HMc*pFڗVN'S߿$֧k>+_xp+sD`O;b>-*}^-X 9WxeU&^ b=l"bDX{gU7bM|Q@wΉ1bfn;y o]}ƭN`9^n"v$vTr;dĮ;ö^9b,Fz/r(q;<V6:J?.*VKDl@.Ma[;YuX;bNakwwZ0D3`)|7|Vr.̇Wg6O CmsWrfBh|QVl;v}y\}}s [Z[Y&ʿP5&0翀󝛍b)ZChF?:0B\; @\1-`v |Ț s^֫/vn5o0@z6ar]mw ]YR/r[[yWNUAi;w ύ\nPmvi]CHT9|xbn5}-XجsE"DtR鹢Uw#k]7;L+FsW3+Oػ缲5;xWi_>ϗ\ nƛ:RoXNοCk\.k7`"a".,bqj.`"1_1O!$VdD BLpej{W1e-O[0%`"Mf'5"^8~0b ;/10/10/10/10/10/10/10/10/10/10/10cncf1 ^uv}z,&\iXw]Ӽ)Z)^ٓ;nR&"&>7*1{n5!bw%^]K1~oiq9,ǩU#^WBmBk\8@Noy6.;9K1//CxoC7"j!r,Īqv_>2akSbAeB2ak/=]c_ϭJ2akUxSR kˬm/J:Kv#^v[KT6}m̭Z0DnJE%`Xծ=7Khn*ߡx "VE*/C,0D2j/C[-leM!buis;Q0DdC%` ^x "!b8kyj0DEl ^ų3kZ sD h\y~Z%`y~%^ iRF? X  CeRJe !bˇ>U+^¢M_9Vx "V}yf!b4}x "yO*xsR kp +w:})j/C\|q4^_B0D]P/6qC2a^igwH,x/^e$zv͕!bģ}HYW)/ܜ)0݅,=w,TK@(ExDkܭšB0<2>|vks1Ȩ<6rax r=⅀!b ^"%` bx!`!^⅀!b ^"x!` bx!`!^⅀!b ^"x!` bx ⅀!^⅀!b"x!` b!^⅀!^x!^⅀!^"x!` b"x!` b⅀!^⅀"x!` b"&^ ` b⅀!^x"&b⅀!^x"x!` b"&^ b⅀x!`"&^ ` b"&^\ /01B/ DL@@  DL0x!`@x!`@x!`"t_Jݝų:=+cZ lI1K=O]%rȦ;ٻLZX]G+6q!`bv~cgC 0I;6IENDB`git-secret-0.5.0/docs/index.html000066400000000000000000000015531424706700600165210ustar00rootroot00000000000000--- layout: default ---

git-secret

Synopsis

{% capture markdown_file %} {% include why.md %} {% endcapture %} {{ markdown_file | markdownify }} {% for post in site.categories.usage %} {{ post.content }} {% endfor %}

Command Reference

subscribe via RSS

git-secret-0.5.0/docs/installation.md000066400000000000000000000130771424706700600175530ustar00rootroot00000000000000--- layout: default --- # Installation ## Dependencies `git-secret` relies on two dependencies: `git` and `gpg`. Download and install them before using this project. `git-secret` is tested to work with: ``` git version 2.7.0 gpg (GnuPG) 1.4.20 ``` ## Supported platforms `git-secret` is tested with `Mac OS X` >= 10.9, `Ubuntu` >= 14.04, `Debian` >= 8.3, `Fedora` / `Rocky Linux` / `AlmaLinux`, `FreeBSD`, `and `Windows` >= 10 using `WSL`. You can check the full list of automated test platforms [here](https://github.com/sobolevn/git-secret/blob/master/.github/workflows/test.yml). We are always interested in getting `git-secret` working and tested on additional systems. If you get `git-secret` working on a new system and the tests pass for you, you can add a Github Action to test your platform to that file. Also we welcome improvements to tests or `git-secret` code for any platform. ## Installation process There are several ways to install `git-secret`, depending on your OS and distribution. They generally all have different installation processes, so we only go into a short explanation of each. (We welcome documentation improvements.) --- ### Mac OS X / Homebrew This is a packaging system for OSX. To install `git-secret` on OSX, you can install `homebrew` and then use: ```bash brew install git-secret ```` --- ### Debian-Type Systems / `deb` package `deb` is a packaging system for [Debian](https://www.debian.org/) and related linux distributions. You can find the `deb` repository [here](https://gitsecret.jfrog.io/artifactory/git-secret-deb/). Pre-requirements: make sure you have installed `apt-transport-https` and `ca-certificates` ```bash {% include install-deb.sh %} ``` --- ### Red Hat Systems / `rpm` package `rpm` is a packaging system for Fedora, CentOS, and other Red Hat based linux distributions. You can find the `rpm` repository [here](https://gitsecret.jfrog.io/artifactory/git-secret-rpm/). ```bash {% include install-rpm.sh %} ``` --- ### Alpine Systems / `apk` package `apk` is a packaging system for Alpine. You can find the `apk` `git-secret` packaging [here](https://gitsecret.jfrog.io/artifactory/git-secret-apk/), and you can see a list of supported architectures [here](https://github.com/sobolevn/git-secret/blob/master/utils/apk/meta.sh) ```bash {% include install-apk.sh %} ``` --- ### Arch Linux / `PKGBUILD` or `AUR` The _Arch_ way to install git-secret is to use the directions for "Installing Packages" at [Arch User Repository Documentation](https://wiki.archlinux.org/index.php/Arch_User_Repository#Installing_packages) along with the `PKGBUILD` file from the [git-secret Arch Linux Package](https://aur.archlinux.org/packages/git-secret/) You can also install from the [AUR](https://aur.archlinux.org/) using your helper of choice by installing the package `git-secret`, for example using [yay](https://github.com/Jguer/yay) ```bash yay -S git-secret ``` --- ### Windows / `WSL`, `Cygwin`, `MSYS`, or `Mingw-w64` `git-secret` depends on many unix tools and features that Windows systems do not usually include by default. Therefore to get `git-secret` running on Windows you have to install these tools, probably using one of the toolkits described below. Each has a different install and setup process. There may also be other ways to install the unix prerequisites on Windows. Once the prerequisite unix tools are installed, you can use the Manual Installation instructions below to manually install `git-secret` (see below). Some ways to install the required unix tools on windows include WSL, CYGWIN, MSYS, and Mingw-w64 (internally, these tools may share some components). Documenting how each is installed and used is beyond the scope of this document, so we will cover the topic in broad strokes. Improvements to this documentation (or any other git-secret documentation) are welcome. Again, after you install the unix tools needed, you can install `git-secret` on windows using the `Manual Installation` steps below. #### WSL Perhaps the easiest way to get `git-secret` operating on windows is using `WSL` (if your system supports it). Here are instructions to install [WSL](https://docs.microsoft.com/en-us/windows/wsl/install) You'll need to install these additional packages: `gnupg`, `make`, `man`, `git`, `gawk`, `file`. We have successfully set up automated testing of `git-secret` on `WSL`, so we are confident this method works. #### Mingw-w64 Another way to install the prerequisites for `git-secret` on Windows is to use [Mingw-w64](https://www.mingw-w64.org/) and install the needed packages. By default, the `Mingw-w64` installation will be saved to `C:\msys64`. You'll need to install `make` and probably other tools such as `gnupg`, `make`, `man`, `git`, and `gawk`. (This list might not be complete). #### MSYS and Cygwin `git-secret` also works with [MSYS](https://www.msys2.org/) and [Cygwin](https://www.cygwin.com/), and we have gotten _most_ of the way to getting `git-secret`'s self-tests running on these setups with Windows (see [windows-related issues](https://github.com/sobolevn/git-secret/issues?q=is%3Aissue+is%3Aopen+windows)). We welcome contributions to `git-secret` and its documentation . --- ### Manual Installation ```bash git clone https://github.com/sobolevn/git-secret.git git-secret cd git-secret && make build PREFIX="/usr/local" make install ``` Note that you can change `PREFIX` to be any directory you subsequently include in in your `PATH` environment variable. We generally recommend you stick to the the default install locations for simplicity, but if you know what you're doing you are welcome to change it. git-secret-0.5.0/docs/plugins.md000066400000000000000000000004641424706700600165270ustar00rootroot00000000000000--- layout: default --- # External plugins Here's a list of external plugins for `git-secret` developed by other awesome developers: - [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 git-secret-0.5.0/git-secret.gif000066400000000000000000021257561424706700600163470ustar00rootroot00000000000000GIF89a}_w! NETSCAPE2.0! ,}_ """ڋ޼H扦ʶ;L .L*̦ JmƩjܮ N1 vHXhx8)I58iyɸ *9jzS +[:k{Y L\l|5,=M]m .=n~Z..?O_OZߌ r… k1D'ZDŒ;F1Ȁ G<9$ʕ,ǩl 3f2kYnwp?Xrɗ;tyѧ[OWvqٷ{xjǛoVzc׻|\ۏU~UB؀ 2UQ."& tb셨bb(chcVccG)d@id; dd0)e*Pie%`eeip)fiff f)t֩xb駗堄ZiR&6䣐)BVjf㦜2*⩨#ꇰƺ᬴^h냼(k&߲E+{V޵؞uwݸ^gӥs춻ܻ'ko۾￳,k£5gG_fœecw &ȅlr`(,Cˇ,]4LY8ym3f:'Deќ tI7PaJm5UXgMZ\gK-6j^%hڬvmǽtAڭL|M[ހ+n8n'#⌋-.yWG"jDN\k8 :r.!$̽nC.<=O]w4," KXc*\ZB0!! If,:T{زfw hDP 1;bⷄĸ,1"-a+ZDK/bc"hC1Q"7Rr H;zܣ2 $!GhC0L!#GB򅒜 +ib28$'wO0 ")KIDTfDQ+JXґe-#yK\撒e//K`S$f1;yLd&df3GLhFӔӤf5SyM2y#7Kwo͛\9p(\ 3?'=ߢ{? |& j 4(CYЇ E?+bݨ :Q4")IГrĤ*K[42.jSm4I)Oӷ4*Qy}5)SԧcRUU:'b[ \TZbUU%TT2UIeQJTU?+OST3+LRT'%,I RzTe,F[QJT,C-PT,@=OS$-=MOԺSd-:][N؊Sߤ-7mM^S4}M>S$2LSd0LR.KR,KR$*͋JRd'IfR$ I6R!KHR~$ GQrdFQf- F wQZ=LEGQN$1MDQCd1]CP71 mCP+1 }\B P$2A$[Pd2@(+P2@,O2\?0O#3̜>4Oc3=8kOף3=<;O3\<@ Oп#4 ;DNѳc4:HNҧ4,:L{Nӛ4<]9PKNԏ#5L8TNՃc5\7XMw5l7\Mk5|]6`M_#6׌5d[MSc6Ԝ4h+MG6Ѭ4lL;6μ]3pL/#7̝2tL#c71xkL71|;L 7]0 L"8 /Kb8.K8,.{K8<^-KK"9L,Kb9\+J淢9l+J7 }D/я+}LoӟK}Tկk}\׿}dz! ,  DDE&ݱr*(ηjyqinsk̼5!*, X!! $)-2389" &,(-$")&-),22-3;50:3 "+3# %!*%.( : <3,9/60;3!!#..0 =6 >84 >7@8A I(WQ+aX.jL@NA SE!WH"[K"`N$cQ$iV%mY&r]'s](v`'v`({c)EEFIIJzz{jt w x!~j6t99<>= > 5l7q7r8t:x;z=@A@ B D F!H!J!M!!=!!""$$%%%@ABCEGGHIJâLʧMͪOѭPԯPֱRڴS޸Sไj*n+q,u-x.|.|0@DRܹTៀ11224456Û6ŝ8ȟ8ˡ8Ѧ9ը:ܮ;H*\ȰÇ#JHŋ3jȱǏ CnLɓ*D\ɲ˗0cʜI͊j~s͟@ JѣH 'A H 2jTXjʵk̥Lw:(Y^/:0{P:(LniӖb A%8 AEB%]l_cCAAA8 HAР:5 :@s=u <ڶBD%ґ *SOBQuUQh勊DUB$ TJA.NLB4,!1Ds),9VdE A5eVj[t&VAxhP(9<!1'Z h \!%e eǞ`$[1X$9/tJCXbdEJJ$- `E-T Ҕ<'VAwXbaYfCrȃfGo)'dt> 7PG q)h$.+ چ d )DDGO`P GA2>x$aPRoB1 9DLI0/L^@fED ~` EDЅZ'h0*&p(@-|h(ŽJKS,ص\*\u/jVOP- 8x0 'hR-Nob@A0AndbFx@ "cA8.2!~Qj Ѐ$G#y)dpLqNAX3 (!Tx|!jwi< su2R!@lRs S E&& p,C% B<ʼnP-2d!;,v X١`9I @x4<-5{+p'EHlQ+n34 +_мɡ,GLX?%(VZp[ Z$lDo䎎l2߭yDܐ"fҪ2 ~ ,: QqZb4p2)ҹث g1ytH'`PHq ~O , E&JX6~@IJ8,Oa VakHn/vfuN,b/B}GD$X%ࡵp2h?,k²SăXRW9iRPB! ٚV9bF-6Y,|еCg 1c7"P/tB B!tg6l^ w!wC  6ewvR6%M-S' c9wm`WA0"BzP 0pzגzh$Tv/y"Q΂9K%@ o04R8WstIݔEQiuMivc (Ba ]3^s*H~7Q #%wWbRk3D'Y`x, By&0!WEP bIG&99(-|CWa!) B:VT{3$JK#0~9? q2U~#'r! `LL7*vlC_c7$T31u&M 6Qh#e%jKC|#?t5Dr]A$A+ƲLjGam-$`Ѣ')qEpcIr'2ea(T؎u%("!W""H%f su"`r ^6Y YJP YJP a PY p IH )[ ֒~# 0O}6$3# 46< ӕu:cOKRl5w_76 ZY ^)aО; r87О1 )CP CBO;#o"&Hvt(/t0#bm,)KhDCW$0/9 Fz09_TA/bUc-988?`HSAazC B| 1}  d}PIpZZ Lx@ هPI x 0 4 P  l PpCoj R Z c4_0*pC# NQ ȕUP Oy #jrtj=ڭehP XNЭZw 0z_ _P D`Wi-2"Aba96bw!, f%))x4A[aX1a $`{5@22Ay5:<[!=;=;D[F{H+HL۴N@P;T[V{ !X\۵^˳/!5,X ڋ޼!,X !!#..0EEFIIJzz{*1%Ibc} 9ں2p-/}^)!,X !#$%&&(++,33499;DDEJJKRST\]]eefgghkllvvw||| $P hepp,/m8]7;@>c QY !'BlbF-NĠ'3r[Zp04Refv#e4 # y_ io:7_D@ x5rI] &fvO" ĐNMN !!!,c! !"()*123;;;BCCQQRffgikkrrr{|}~ $Ph eDp,m8]7A!JhEɥg|f"H&P}@ i /su7qfsV}rs:  w  ?;~[t!!,n "#$&'(+,-//1.00456889EEFYYZ__`bbctuu $(he ]p,m8]7;@w7\&e.iERYxC- sBq ރ脒3W}zVD~b$s$ rW$ A"xL0F5SW!!,yDDEG 0FlxY iyӶXEL t4>ibWW! , !'')*+,123;;*hsaE$6! ,%&''()556;<=DDEHIIOPPSTTVVX[[[abbiijopppqqwxx||} $heK\p,Om8]7;@w>c b`DOOXd^ LbhHrA؋x # e"coc  # NAGJ.Nb!!6,$$&**+./0234;==DDERRS___ffgqrrwxxrIA08kQy`(*](YN'IޭC{0ai8`Ў&J*I SiJ61xx ~+k]tOug#>l! ,  &'(+{\!,%%&'')++-445==?DEFJKLOPPUVVYZZmmnvwwzz{} $qh*,\p,+-8]7뻞oJ" U*"\Q"bhGB!rY f9M:/sUC}_g# \w#0q$ ;93vg!!6,zX ! $)-2399! $*(-"!)%-),22-4<50:3# #**'+35"0:" %!*%.( <3,8/60;2""#&&(&((*+,..0'634 >7897@8AI;#F>>@#C%K(O'P)T+[!C;.c/h0j3r6z8}@LKYP_Vg]pe{$LB%QE&TH'XJ(VJ)[N*^P?@@,cU-fX.l[/q^0n^0p^1tb2xf4}iE)@6D9I=N -J> R .Z!2g$8u'=A%ML*[V-g|(@K@NA SE!WH"[K"`N$cQ$iV%mY&q\'s](u`'v`({c(BCDFGHFHHJKLNOPNPPRRSVVXVXXZ[[^_`_``cddfghfhhjkknnpopprsswwxvxx{{|ks w yj5t99<>= > 5m7p7r8r8t:x;|@@ B D F!H!J!M!!>!!"#?$$%ACF~IJâLɦMͪNѭPԯPհR۵S޸S่*E-K0N0O1S4Yj*n+q,u-x.{.}06]8a;gAEPԳQڹS01123456š6Ŝ8ȟ8̢8Ѧ9թ:ܮ;H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣHq XT@RL>JիXjZU)|*TX[( T!U*<d䕀W DYem&$"@=|* 6@a 4b AWM4@Q\QᤓNv$8JvEJcFHs(i`lw{<#}g xC8pDA.cN4AG!_}J= -C+R@"*BTƀWTJ:ʨcr$QIÌ@<*]D[~c dΘ d~Y^4_}f J+ Ya.*hE0*#=:'*I+}@AEGU o@)0\B-Јԣe(hAA3 |AP|1r< @P`aA`AJIS@猓p3ԑlAq LJҦ'sp=}P3|=в1 m)@&($sG3v|P3)zϡše>G}G:dη@'bpFP:P F qD ^R Hb ,: @}>`C/d?HA5CHB[/ ?(!?GD9:ODTWDS E+ZAȁ壇`)0"_xQ $0`d1L0vP)E1Yb98g$>c}f)cQ4M0&0G: JIXZP*y/et| Aعtc>S %$LF:Gj,ql"d98qi:a60E` QscGH}G.!O@r >ǼL`*h (2@(s{pD YL~_Ag(bŎĖ@Z' @&XAR:_M{@8P bhaZF18  DJ bCʈ `@ b,!-pNL hW+74;7ƀ8=fsF3!Fn DhA h $Ihlq`[UF dJ΀M+*`F:!W r [sxFbIFi *`BfC N1vq#;(3BMa,vьZa+Fn}Am,`L! ]6$:j0_j 5$4o Ր 4PL 57P/8LqWVဂW$ʦh' N,! [ "(0rRR 䤥hLb(F@J 0n RB1r:.Cdn@ARHpmZ` ([fNy frf7 -c dC'wWDZ؊c8G[yO$29x}]׿)>iN_Cʒ $@3A`9dQ#O$.TBK| $I@}w"4L}ILmx &H7T `l-րUBdW,YY*y~f`8\ %ceURP 0Յ@$1?H.pB!!%kJ r4-c7HLlbP.: kh1ێq8OΖ4 P@+;@맛{H4-Z c:"-fۺ3d֋Xxϻ*BT`Z4;+H&VT&_qi0LBN-EC @-cK$&3 &M\[ 6ِvkD:dy{C H/t,$ST 1䅁dTLx %!^PShbHEik$drFGtfUz+$YSh`(u@|v@F$a6&wXw 9$dhhk2%V6.@WFYFmU;p H `|#rn.G Ѕ^!Cj#10 `  1^'WF(0u>ϖMl7 q{S0 Nf;t> o {e 0+5PC HF g$DR}}2b@wpqUP h6TVf`5x0H7,^5ݐ}1V9qW~G Gr82r` ŃnYp7Ґ&TE4Z`/A) n2<Y8jAaH#Blh 8z_GUls'_zȇ{1{XaA WT##; cX1'o| q1TQ[ u} DG1C}~+4 !@AEY0Nav6AtTpt,͐XtfhV38b%g8-cvu,@Yу'dWVFLHFcA1#%S(bQ9+4a| DD 1la)Y(k!M{(}{({?69(B)Ɖa1"6!%e !"1'9D8E!VxYN`Cfq$9of*uYrH+$%I"g!%F!-2{W ĔOf.)B)0+ J`   ^t>.]% IԒyyI4^ *@ٞV5!ȅ#"Od F#~P H 7Ŋ  jQ€ z Q Сq c0 W dQ!h@V,7Nu5ѐ$}e69JB`;zq"VYc7s%X{9 Y'\@`Z$-#F k5v@ t,eHJ>q0>y x b;! #碪pK^l]0X ޅ.5PT$:JV#з~ N!J1}|5A`!a}+<=~/)"H B 'P  RY ] B D`1 v @kP !{ GJtDtpc`t9 yTYw-p pp3ISࠍ^ 1 Lܐu`- XHuPV v ;h&v0PBQOvGp };DR.}˴1Y 90Dl70PD?`0 5D!@|Ip hd !A(-@=j7M ƈ,) >P\nXƉ<ɔ\AP}ʢ<ʤ\ʦ,Ukʮʰ˴ ,˺˼˾<\|Ȝʼ<\|؜ڼ-}M @d50]}`L1``[a < ]}4R.0<2 !ެL4mLd Ѷf"]<δ.GM Z2pSlM< 2_aƉrM2q!U]R؅a90p\]B} ' _ atG%= 0A1^5@1 Gu" O"3ltM/]A<]^ q$>zM;mr_`-/. ^!1_1=|e5QC5a}2`! !5@_\<Eݱ=w- .Q 5ajM.^_!)^]5_ĭI  A31PԢ ^P`diP} [V~։Mc¤]4^ (P D@q>ZvmDn:Vf^MWd3ߪ]^L=plUZLdm]}]\W1mV~U;ɞ޲M$.p|=L2DCU/mmp=vh.N1ԭM]nצ7®]=R.(n׍pم qnj.?`9z8_m.?1O`˂8/}$r˒]hkLm8B~L$n~-q^zF _UL8Y.I-`KnKRtB'lDlp:_O(_yX ޿dX]"G!QKkw _- C_d(|P1!]㬧ʙL~(-0YLH/_mf Oס 30N?~ NX?x]Pv0BL֠K1eΤYM9u_($: p#F+'*e'562`@2@=.B#U070d0$Y#Bdf0ޛ.k F[*]4D.6< }(EKFObS;hrlϐM͐oZ$Umh@S?!D !t+<(Qs𩉌kn& ­H Ė0kl&*#j)H4H$Tr%Gl! ×ˡxK슢\r/_ %aSB~'Bbtb21It́8!6I4e(6 Kۑsͥ>l=2(=~uՙΣ\ "a"(cҁ*:muvkHBM̼b*:T"rځ͢hWȩ|ĝWOu/|l [GVb&3xc;IL9'Ҳ*.rYbj)s waK5Q;Rʲ.cwq0/l urҩ?Ӵ&N+1ГgVOwGZ JdhjV_ͦWL* l:H#V_ID`j>aBv0^!vhK'(fBױ-vIh꺡we,nɩ=vy裗ȑg({h^3>S2(䚖|LnRniAdki:/lPB5CGЕѵ )R m(B+p akU+lqNXH<~ N‚] #+xAQGE< R.5@BAbQ'b,(Vf|mI&X( 6n"I;ڛܶ̐$M D:āZO9=(H\+T3)#!qޒګVY1dq"wi=Dc1?.yK(#Lb quu]ME :8d@.J1b4W9 IF~HyۊyQfTzQ!IA%R Ƀ,QD ʆMS&2e*eH4W%7_"Ų! /#N\J1 ;-zb:DYdbՆА"vHB{M0c+*EԔEWgb p@m #~GO;PoKhGT4a1JAm*UrhEXQ_&Kvrv;:}nm5z[&[\! GWY! wRnb ?j?qBy8׹Q=Cp>G.RӪl_bD>| R g0h>Ż`7b\¸SkTr"}D!}hSHt|$hH=1A<<0nHa\J RRƼi\xfZ)p# ?}Էa'~|>t=[>TAVgfx Ȍ(B#{ f8eDkD4!"@v#F{PcKBeBt/b@!PV&"ij8"n֘)zF hPr˚炖y;&MmA88iD\ VflL! jj&"H"Ƽeo`[ jFm$~2_N0juq"IB:Ѿ?Te_$kjA gXU }vH=NǪ16~ bف(Vv$A{Eܡ-[G64kc喋#jB*.Fb]îA^+5~o~ A 5^e|P(Lj`AA>,Z]At"t15H #k: .)ye$cD  B? C bi{AAASR%8\B zA, K *D؇*B*B+$! h+졶C3H:2@DHOpPH&a p,4*$ț1ȃ(jd Fp hVxjDp| jdl#hlSj$ɘXDLXLT IIT ȅ,pHtK"1<st(J#yʨ Ls8lK4x;,K8˴NPtCDV0`V@&!V͸jXti)L;LMTɔd ИxLV@L UρIVLHMHM̆@OTH`r͚ \MMhMM"QNM4iHtQ&ÑL 4@$Vс`O\ObO,Bt?OHMm Tφp#82 E#F!'FЁ5˗Hjl|,QR\()+HRIv\肉/x\T-x]ԆȂOOYu YMp80tt]gn`3؃hhKL հ`n>8PflQ>`|  m>n>W ;XVg8VN4Ά>Xl$r s;`gHr`lxuiU;1V@#@UX#H#M p M@M8k5MNPY 404PccP7hPc Z5耉%4h40cjZcL=dP7[5Pe0-O/602%TtltUhjLUp Ol͗MhB 0I`b(bxI`(Ņ]b .Um 8]M٤QpZ(,Z[X[;H8<ՁRM>p1(5]сhtʁ4Ns8^$~5_H׆(D]ʘq#؁`N5}VO5ҁ MU6kT8q"hTQ7j['j`epjZXh4jX[ejPeXہ!a4h5x⛰*#Tƻha8K'u6vÅ \xSXV(Tج a((b`䁠_(*xb ,] ՉxbwaL΀m(e]]*Ttn8V2h]G}Vo}ށg0xQ&%f>0,R10N`_ ,_;8Ńt|Nt_$ufNLn]5f`KXR81N = $PNxܗOM)mL (L>9u* ahM0(j8Z%a7R~@j0a5P7(⛐Xj.bbَӆV`MVH4ҊD\?5}km f" k][\KօЂP^(X͆@e`ؒO(LdMlW뉐Mg@mph 6s8R<`3؆`m|9 fpinN;gop!|_np`n_Ѷ߆NdK`τ.O(^gމk . Ae6[VdplTƉjiiv c(jHږx駶''[xO-&kT@4!@2ͬ`LƓ~ĶOKC.lB&-b큐__RsH)&p't'6qp(sް\n58p_ntP: }J4Mo`tm`ns^ -W7εhw`FmoXgqxt`"vmSSH-$[ۖ鉸LUPUxP `7 )ja8i HEwZ/xn_} iAI` 2rhVPF!hNL ВcɔP lV (_d/buM\s_x٬az40r.tib˳T`uֆpgi:HmHuko_UXbUbM|oK$91svKt9P|;v9(O7`vnv&mrXn=|6omXkMSo;=&wMH~[끨$w'jxxMq&avo cXm6jHjYKxk,h BZ1@ȩ|B%q`V< Z8VF R8paāZ2y\Ŋ !t R@C+6`b 9J1\uJRͰb Kg tKg`ts2K码t _n#N:gǥS!0z̈́Mb:th'9 .;{VZ:f(=']*].;ǚ\M% pJ#+["dP`Y*A"(ڴUSՔ@SmY'1A^'y鉕-̲D`pQ;h!5!!8"%s=B$PA#"@q-@2Pau7J+4SM RMTżRT1 EV@EA#ASYOV5-pP\hSYg Zc@Sa|^| $ܣ#9Z8cpzeifco 67AFlq :t[nʪYq3l`@DP4y6eABaP^{|U@gyA›ЂLcr ,B0&e!F0Ks1^Ё_em& %<2b0*2̋1S# zޗußy> žq*p_d8ȟlrA C'@:A+&PMG8E*R "P H(2EUEH6 #,\ I:@J>#eZ.| 0 ^E/pJT.t@EPv xT] LU7IX4%ʚϋaKF ] gЃ"h#π$A q' qY&i3,g(/8Gvxa]VtuxZ-@ gVq |`b.P%3N~2,9S2-s^@ f>3Ӭ5Yd3,9ӹv:=w3-AІ>4E3ю~4#-ISҖ43MsӞ4C-QԦ>5SUծ~5c-YӺֶ5s]׾5-a>6e3~6-iS־6ms6-q>7ӭu~7-yӻ7}7.?838#.S83s8C.򑓼&?9S򕳼.9c.Ӽ69s>9Ѓ.F?:ғ3N:ԣ.SV:ֳs^:.f?;Ӯn;.ӽv;~;/?<3<#/S<3s3>/Sֿ>s>/??ӯ?/ӿ??  &. 6> FN V^ fn v~  Ơ ֠   !!&.!6>!FN!V^!fn!v~!!!!!ơ!֡!!!  "!!""&"."#6#>"$F$N"%V%^"&f&n"'v'~"(("))"**"++",Ƣ,"-֢-".."//"00#11#2&2.#363>#4F4N#5V5^#6f6n#7v7~#88#99#::#;;#<ƣ<#=֣=#>>#??#@@$AA$B&B.$C6C>$DFDN$EVE^$FfFn$GvG~$HH$II$JJ$KK$LƤL$M֤M$NN$OO$PP%QQ%R&R.%S6S>%TFTN%UVU^%VfVn%WvW~%XX%YY%ZZ%[[%\ƥ\%]֥]%^^%__%``&aa&b&b.&c6c>&dFdN&eVe^&fffn&gvfg~&hh&ii&jj&kk&lƦl&m֦m&nn&oo&pp'qq'r&r.'s6s>'tFtN'uVu^'vfvn'wvw]@!,8 ڋ޼!,8,,.//02337789:;CDEFHHKKLRSTVVX[\]deejkkooqsttwxxyyy h,up, -8]7뻞 }1 "29D'֐m:V t9-:,~ @o&#}ZDx#coa"xldfkuC4 1~["pH-oL  f3x2zP W#DMM!!,8()*344TTV]]___`ddegghhiiqqq} $phZ0찥3=`דeI~b bJ awvzm$d9mwTwoL9 . t>" q:S^T- !!,8##$''(>?@HHJOPQTTU]^_eefnoorssyyz| dhz, Xp,G-8]7뻞  o$D) >dFS lmu-ѻ݅Oa$HwV$ 1 f3, K;|0@5yA}t!!,8&&(==?>?@EEGeefRIA(8kR@`(](YN'+кή]i,##H!.4E4y.ꥁ<$|n!*,8##$*+,23389:>?@BCCIIJZZ[ddeghhjkkrss}~ $P,he`p,3m8]7;@χ>c Q@H!7,v[ 0ouLE. ő<@1 nDJ 0P\50p"`"_If  ~vAJtd6NNM !!,8$$%&((+,-113==>??@CEEKLLQRSZ[\eefghhllmuuv $4he qp,+m8]7;@>c 3"B0H&,L`BÀjNbtPc@`2xEi_40Kbr.: " "0# AGNabJK !!,8! $%&(**;<=BCCKLLRRSWWYdeellmopprss{{{ $4h6CRZ,Z0M2^ֆ"PS7DpL*@:"0LL 8LopF3r" <ysF<}pG" bbdLqCPKHDH!! ,8#$$,-.57789:BCDJKLOPPXXX^^`ddexxyy $(h&e Qp,Km8]7;@G>c `q07*P Yy)C`€g]~m݁)|syuf}dc !DOO(``B]JgB 80t6\ѣ 0a~E  4Kewy$"yr:a" AGNdeJ.NKp!!,8$$%<<>DEFGHIMNNTUVeefkklsttxxy $ he;Lp,3m8]7;@7 GL0ZaL4PBlyFTƳtzo# KF1% xLADF5YSk. !!,'82239::VWXYYZeefijjRIA(8kQ;A`(](YN'+кή]i,##H!.4E4y.ꥁ<$|^! ,28 !"*+,;<] MMh Q P2車tq9 ɛG$rwpu|: ?" b;t{x}V.!!,=8 !"**+122:;c 3a0D$3Y(2J@ȅ F`0e2ZXp<2JXyDr# I^"P]hMQfR #oEN]NJ.e6!!,H8())334;<7223778:;;9B6!@?%L>?@#C%K(O'P)T+\!B:#H>.c/h0k3s6z8}FRLZP_Te^qe{$MB%QF'TH'XJ(VJ)\N*^P,dU-fX.l[/q^0n^0p^1sb2xf4}i@'D)J+@7C9I=N -J= R .V 0[!2b#5e$8m%:s&=x'?y(?A%ML*[S,d|(@K@N@ SE!ZJ"aO$cQ$iV%mY&p\'s](u`'v`(|d(BCDGGIFHHJJKOPPRSTVVX[\]__`cdegghghhjkkooqopprsswwxwxxzz{kr yk5u99;>> > 5m8s;}@@ B D F!H!J!M!>!!"#?$$%@ABCEGHJĢLȦM̩NѭPԯPհR۵S޸Sใ)C+F,H-J.M0N0O0Q1S3V4X5[j*n+q,v-x.{/}06]8a9d;f;hBFP԰QֹS01123456š6Ŝ8ȟ8͢8Ѧ:թ:ܮ;H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ Jѣ X*DKqpJիXjJTS hӅf>ZJI S4L. \mSª :) sba :}*^l2 )bAV@PppWRCX#zlW!.+QC㎃k=!4! a6HK"9+&;п\dR!$d ٔ‹_0A @~ ^>؅uRlm yq ` @AVSxiB/z^ r د#DәomRhx#[q.0qo+G}rhnpG)>W4jJ?1ğC)w&rNpBz(sAql,@Mgވ _0 4##JUZAeB&e ' (#(e\)j8`. HU NM@@D$a 5 T|@ FrV1ū@p I ,hD<k>1#rGe\ J bL я di8ZB.="9 dSǖHl 2[X51HAK C0hrf|~5ybUjAdTAXXrH+[lB߁W*&~4b+ ]D fڵgݝq):T:Ձ ` H:hA瞧0wp:AzKH @3D%5(\A%6lpii*52ềAZS$)B k B-PN5i\tAM~uAAP5wB_Y3}W,!5@V%aoH  Y6;dE!E$H!~q~oWw3T "=0$6335e >"4}0&„ 5Gw]0 r tY sN 1sR:JpZPMPp"WG79 pNwdsP@P9;v0Qa]rQi Qޠd=ƈNrMp&QE'GQi:eSy_ Prpy P3 -MQ#twV:" 0 r3,U a"P V W׀ A0 p{'G ``G0jF5eu ԈUILX!F H~ qwpG0X@Xa~`d QRom1)"Eȕq 0=P @S. ",3]0,BK [066 > @K_V3 Pfi% 0i-1u8XwM0 &QC8AduݰA8r;8R6xSabt@`=]Bw2t` wctЉwU6RTFW2:< 5ny@ qa1$`27,!H PI-8Hqьa0VQThPV D 6BUP8w ĐyiV 0 Z !i~()~ *tEZ 4mnA! AZ0p *+1pQp #&󣻱"1Aq1JaR 15G]9 1@(@F8_I4TTSGg(h".e)a2&a z( }ay:7f.d w隟;xs=Ccy gRS~<(: q0 (YG ˠRI̷TQahPJA p ]1Y@tU@W '"ZU 0*)IT91)#) B*Q,qH/52qar&]:3e%eQ_Y0  LVP4!@RJW uᴭpR7pM'A栘ч||w(esuaqMCat-P%Mx d~IhXV+!9@8ȸzDI7qDT積j|QUZšj9឵BV qk67Ү6) X#mڠ1Y5d!*6R`*ڰQ =1=@-9`[I5 7I M\q\O: .?j=G P)DK ^Q^饕6g4B EE( tY *0tt&t˸ ]"8hҘ18)`*`sBb\Ҙ̀uqwdn"x_\yp!{ǧi2Xs<+I%i/HԜ" 3C B@-? T dP y橬ɠA!{ :U6]0jVgpp l  pEFtT".@X0D~0! *6f{L4нGw+;; kp>M>[S!zlhSP,7҂q i-[JJt: ;r ăA< < ^:^ʡҷ0Ka_e>|` ew;^˧fN^&@.'hӇq2'r0 ! N.ۃrbπyyv`7}8].: h ΰNА<@ Ϡda π Z\qhsޘvV~i ϰz  B 4?1BE` . 1q > D`ߕ,f0 l`Ð{0 0 p00 Mf N> S 3 %~`(j  !``-@QD@Pm>@3ÍH41@DM|lQI0:7!?8/01234678688:;<9C>?@#B%K(O'P(T+Z!C:.c0g1k3s6{8~IWScdz$LB'TH*^Q+bS-gX-jY0p^1tb3xf4|iA'D)M,P.@7C9H=L ,I> R .U!0\"3d#6t&=A&OC&QU,f_1s|(@c2xM@ SE!VH"\L"`N#cR$iV%lY%q\'zb(BCDFFHFHHKKLOOPOPQSSTWWX[[\__a_``bcdfghghhjkknopopprsswwxwxxz{{l{<9;>= > 5m7q7r8q8u9x;{<@@ B D F!H!J!M!!>"#?$$%@@@ACEGH~IJâLɦMͪOҭPүPֱQڴS޸Sโ*C+F,H,J.N0N/O0O1S3V4X5Zj*q,t-x.{.}016^7`8a:d;g;hBDIKǮOӴS۹Tៀ012234566Ŝ8ȟ8ˡ8ѥ9Ԩ:ܮ;H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH* ?TaA{ 2gA yKٳ>x_ )=%g?}EK:R}oa~naMH-ٓ]˘]F D~KPF?{f d^Hx%<áS !v[Isn 4 8PC1={ GҤ>ŨO!Xc<>1x$A/sТ>OH?Y%)a=c/3p>(gxx #> Oh;ȭk.b[JwH b K@(e$?dbzlѡHbJp]V AEr5ӏ@ymIcf+4ծ}$@{xǛ: !M$As!1pB>Xt@{65=zq!WP5+T\xM@B6nlRxAؗ8be# \R_ݾj$VP;V-vq.(sl~gN82$xB/bP?zWhm]<w ljnP[t>=к/D:緯} y?$di "0%$zWFv=$jZnVtp yaZp<0~ W7B8t.lRƿQK2{Ox5`=3whD?o2?ёU:`!@C, @Xc#ͬCP8j,gw"(  N#h9O/0p! 0෩q/-A p[R$P0&bXx(:`YzW0ֻ(y gġ sF g xA pnl2 Ֆ% "q $ս-(rP0 GB EI(!EЭuM_Ta"7-~ #pzUr\AN2;^dt;Apq;Qg ;`8y)@A, fiax"F$$Aţ`@C0 R|" @@Q  $2O(! kR.!դ3A0qEE>rp2ELπь!ȓL13p 0p8CHj4BY[ Eb 7(x 5I!i՟H- Rx DZߚ!$}dv#e$ Y *80l){ ur{lr'2BMt;!E7 uEQpxg"'ȼw/l!`w]Am~TY @ Uw(B R IлB-#o?d/|Kd|.61ԸE/`h-pD ZD S&41~\n {+p 8#A63 q{h[wpr;1A@zVȔ.vCPOm0`lw׶dmFttGah8Ҧ~ppU !$VoL *6g8xxq9( ' 6g8jPqq@ 0 d ؐ Pe ր ր \Pg@ ؀ 0 i' ˀІPQp `p`a`Aaoo1w FwF F\Dix Aawp Qbp ` 0c w Qcz  `GF@{ 1 ! { Mp >@vmstF}Ѱ l( fsA, sdkfV~7P^pllGwndxf+pl  qm 7_V@tvf kF  8 n0р}u % u!x(`[@ RI@a0 X\b !Ra qPv h |g p İ q`H 0 ذ pxp `H`(PXX'`h7&񙉸ohXC 18 0 0oFk'1 Z9oh֊ `<r@Pz` 6&5 7W  @P8 X  ' J؍@,`;~Pw~s_6Ge  ts)s2_РACA ҷǖ$b!n1pfj֐ts`_PGia@Qb(֚֕\) %P[G\` @n)_h' d\[0{JbgdP ؀ ~x& UHy_Hs  vvx% txhF v&pvu*ƛ0oQx҅ 0 g[trik :Q w I    S W @*J}0`~asP^1@_SFA^Ov~ !;`SHm! ";ڀH;Zf"yltCnzj6ܰK Pi7a(k/ૻz[hW,`ZGovZ `yZT&&` _h Yl  X |Dv1' @ʼnxw[P yG 9FabZk p̩ ᩥw6 f;  E \ ȕaa1c<& cښ 0|뼴Pŝ d @sdDj^ sre]FGkI=ia|׼sSVdqm،u .j,uA[FZPs'L!0!  ސ\VjƹQiIPKjfh[p Чᖂ@s_ g`U3M@_x @`Ѹ P Ov YVb[Gw p[Jq)PĨ P 5A ĸ񮕀ױYY 6A<ks@f-97'Sf #\;<do@:#ldž, ;5cƳI d]!<L' A fi"6ovVgɏ݅v*k҆ 0PQe~ `p1a_8 |مUOЍکxb| w5 .։aj*r6 盏ȸjHgq=-a ZֻR0 @> z;^ڍZJp"\t7n71텾^$e` AOFdͣ{fq}`( hI oX% ޷ں |9j >O\ Nf {\X vƨ WMnW[ D0\%F V!,fy- EYj@Ea,L`]UiEa``Q{,P@ĸ rΫ Q UԈ R8` Q7py+(T,^`W~n@d^A֐^615d,ס !0С |s;lA;̰p_Ceа0 A>yUq@ @Ȫi] KLs{հ lpX= _ @ 1 iП?Cٽbʥh.0rfbY' > vly ac6~5f< Xc;?4έ"$ זdP  X4c]Br)(s煢@hE|nȑڡl-a8,GqNduIH\gPyPgv1YUYG"*RaIdذAHhhY@0l&,6d a#M &H3Pq1ְY-Smt)M?ԩUHs> R6IDɑ(R%Gd7;I/j/o$AP ({H* MXqEӕ7LR%((dTECU#"?p).)4$l܈I$phbc"(8ވ fQ$ncCБ^Ī/H*CXx`r(CTx/#VxJ"h/lB:*R> j ;$8BPDOl2 c؂2 ("`C6(e 1<=A$2 KEJQZ:M5\YiPzV`^CDXdUvYfuYh%IHnZl6[qMMmw\r5\tVu]ep^|w_~_Z^ 6`Vxa8׆#xb+b}^ c;cCDJ6!0,j ڋ޼!*,j \\\oopopp-(Q&5ʬ1V^R_nZ{9aH,! ,j  !##'').//466:;<>?@ACCFHHKKMSSTZ[[^^`accgghfhhklloopopptttzz{@pHP*dRRlFh4,>RjuxB[@ ގ9[XS y"nF"u#{|T  pT#Ckq#C |#T##CC} PZ #dC  #nCB"hBQ B` DaFA!,j!##$..0334668BCCJKLRRSWXXZZ[oopoppuuvxyy dh,0Tp,O-8]7XhE Ɂ|zF`L]Mh;(Y&ma:Fm" V,yG;}?z !!,j"#$)*+/11567<<=>?@AABKLMNPPWXXabbghhkkloopopp $0>ZZ[ghhoopoppO Q0J88kR -#P:aЛFf }H$ 2\*ieaoڔz-H!6,j $$&+,-..0/00233:;c k H|<:%lE"<$\ݚCأ(DQ]"`0pDJ00"x  W: >Z# wPAhABCKLLRSSWXX^__``almmoopopprrsxyy $@@h*exp,Sm8]7;@>c kHlOe,U p< ѡ!ha`8*w K4 {.dpcO6 n>"  cJAYG& !!,'j!"#--/567=>>>?@DFFJKKVWWWXXYYZghiijjoopoppppq $@8he`p,7m8]7;@χ"G\bIhJЬ9c2'ߨt.Nͧn"=%Y0rQFBw#1% oA"`3zL0F5kA!!6,2j/11011CDDMOOoopopptuuRI(8kQA`(](YN'+кή]i,##H!.4E4y.ꥁ<$|!0,=j ڋ޼! ,>j#$$+,-//0.00233789==>AABJKKNPPQRRWXX_``fggkkkoopopp $h*,Pqp,-8]7뻞L,OwXßEa &` וH\8:M+nXjUxFۮ9[SahW}2uxp{ B NzPT} TzPd j   zZ X` y[ciLh[A!,Sj !"234EEFJKKQRRWXX^^_abbmmnoopoppvww}~~z $,h&eKpelS3=2 vrLKC0 |9$ G},1, 3;lxtmSq0i-!!), jh1!!  %*.2398"!$)(-"!)%-),43.74" !()!&#)/ (/*12!;%1:" %!)%.) 7 ; <3,;2"#$&'(&((+,-..0 >7!?8.00234668688;<=7A9B=H>K>?@#B%K(O'P(T+Z!C:.c0g1k3s6{8~DRIWKYScdz$LB'TH*^Q?@@+bS-gX-jY0p^1tb3xf4|iA'D)M,P.@7C9H=L ,I> R .U!0\"3d#6t&=A&OC&QU,f_1s|(@c2xM@ SE!VH"\L"`N#cR$iV%lY%q\'zb(BCCFHHJKKOOQNPPSSTWWXWXX\]]^^`_``abbghhkkloopsstwwxz{{l{<9;>= > 5m7q7r8q8u9x;{<@@ B D F!H!J!M!!>"#?$$%@@@ACEGHIJâLɦMͪOҭPүPֱQڴS޸Sโ*C+F,H,J.N0N/O0O1S3V4X5Zj*q,t-x.{.}016^7`8a:d;g;hBDIKǮOӴS۹Tៀ012234566Ŝ8ȟ8ˡ8ѥ9Ԩ:ܮ;H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣA4YDK(qJիXjݚ5/ p"& M!%B/(UPUDaY`WH^#h0$ >.ٝyXXj؅M[ x:jq=@u׃׸_LJ _EubT_Jp}^bR t$blpw o  ~G  A⼳GAtLAмSB}A<Çn`()y >q@(*?$1@$kj[H1%<~kǔL)bH)A$SqC(9K`-=j`y \VBޖ n1rMtZ)HA rWBo ^WTC.v1G.` À/\7^XAP[H s+\ )C<,U[8w 4\u2*@;X ֎) /Ћ"PQD ׸Aj- @P],Vq T @ND Qp \W'00ajU09U#ȎKE x ;=LiID-yH-H?|cD ◭Q6 kAjLnė"g 9> P,S8 H8A/K0PxynrbOE83b`B fyVKvX0 .cAI RF3>*`uZ) x0kt(јCifTt?1P>Gji"HR :0HjV'lV!mja"jUq (5!OGx_Z34 p6N"42|d z$%G@qE\ pEr`Fh׀ Elpu]7Pw S@R c VK53-e8aW9:`?' F a56 :0<5\gq-ew6c4cv" w_MSNtDweuc Swta'9 a `Q_` {fA[p{w&;yьQyze cٸ_xWķA͐) )m~s' T")2<*Wj !`|T!j!!rFm SԳ H`$IMgo^Z&'YF5$jWCx84QTp4G V:'[c!cD WBHTԔZYp[$q M\A p pr+r68uq !uւQyX`6Zgv^\6/vvlchn !cBe80 0 Ka "?&g21% 1 A ! Wz`PPhh [9k 0ˆ .|! z)9m`TB!qc |)2 b·*eEɟ{) Wm3XVΰy!I!p! 1nr'ZgB}Sq&L>zN0'Ro/a pQ[~d@:[ m|o{QtEq]Wd[t ДЄA0 !$Et TJA5g Q`KdHըabhӲsYWqn`5h7xW('4,aq.p' 2NdQxea[P!% P'X P 0w I: g[0fQ@!BW1 hБ|%2l5@Rl֑I)ǖig%XWɦ!mQѡ>Y%բ&hR'3YM(;.&abEoRZq|d NIbp q[LzgZlE0\YE`T$ A$ \{r :&b7ui;" cHAzqJ 1- cӔ a T 1N5'p"o.LVMid}M, ( y) zvQ Wq *{$ >R`kPf~23+SQ!֧k f0 1kb- l!W<`<( nCHf 9T1 W[0[: = å[GZ;Hi qOKl ]Xd G&w^3}8hڗ9g+LrA GtvK5$N6^,!"fj7>J0 Ga c{BO- twvACH` Ogq&>ya`V:# f:VPs` dQpV `p] Ӌ{{ ѝsdT>tP>yAUB1|UVqQ(jXA1P0j Ա1,)PdA(kP ?e@*S!Ѱ0 >M=vgx/C ,pTw&i@Di: C rpTa 2[ F8P  A bhTж1g;]݆0%=І 06 dWC`505J Q!l% ;୦m l9 |=caL0C.w ^`A˜ָYV ` W] PY:R p.t`w10wQs~uby prmn>+ Qsvh{ Q!{N@~Bw`k* Q?BuP eP @x."J& {~'Gsi kk 5r0 rPiR9/ mдp?a~@v}ZZE'Z@]3$+3 0_`0Q`_b?4`f^_/ Q 9 ,}s5;ŤX1ph?ȟʿEq: 3?_o~?_;_!I$XA .dC%NXE5nG!E$Ya)UgK1eΤYM9u'F+WYQI.eS= MI4UYnW4RYiծemñB˾[]y]w(_&\0L,/fctW\e̙5ǜofСE&]ҩUfiױeϦQ]&l۹uݻ/Už'^|4nɕ/gysѥOuٵ۴w+v_ѯg^zϗ }1!, ڋ!, "#$==>JJKS98ʅ`xp#)'ldҝ쪫%ߌFRx8$Чy@XsN;y{ݲ\܊0xMF!',"#$..//0100189:>>@CDEJJKRRSWXYZZ[aabkllopprss{{| $ h"DZ,0M2^ֆ"PS7N@,"Rx%A (s 4C( ~ ir`" C^hHsHDMQ/!! , "2$$&..//0100189:CDEFHHLLLRRSWXYZZ[bccghhjjjopprss~~ dihlp,tm(0"D9&+  A45hpfLW@C,8pfN57{}q7xzm~6m C4uGFX6EG5Q432ĩ1Ȱ0̫͹/һ67!!*, K ! $+-448""%*(.!!)%-()03-2:5093"!"(*&%3";%# %!*&.( <2,;2"#$&&(&((*+,..0 >6 ?8.005 >234668688;<<9B9"C>>@"B&L(O'P)T*Y!C:#H?.c0f1k3t6z8~COKYcx$LB&QF'TH(VJ)YL*^P>@@+aS-gX.l[0o^0p_1tb3xf4}j@'C)J+@6D9H=N -J> R .V!0[!2c#6g$8k%9u'=M*\R,c|(@M@ SE!UH![K"`O#cQ$iV%mY&r]'v`(|d)BCDFFHFHHJKKNNPOPPRSSVVXVXX[[\^^`^``bccffhfhhlllnopoppsstvwxvxx{||op z9<>= > 5m7p8t;|@@ B D F!H!I!M! >!#?$%&@@CCGJ~IJĢLȦM̩NѭPҮRڴT่*E-J.M1R3V4X5[f*k+n,q,u.x.{.~06]8a9d:f;h>DGJLȷS߹Tᤃ12234576Ĝ8ȟ7ȟ8̢8Ѧ:ը:ܮ;H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*%J^TL g"Wi@^JAطXXeZ㟻sKPкu!\G*~ރMof iiD td[Ͼ6УKS?z5֯"O6jۻ,q5Ҁ9b 㨯 fE ^lBl <طtir r T`2P#%\-p?:d&ޏj2 A#|\?4$r@g +C"c]2+ثpEN>1;]/%HO#=DS]J"Q'rN?,HgH9>P:W#=%"ģ È<'YbϡXZ#lf 2" <րsmB#Kbv=yC"$~fNhKr|@~;2*"ӏ3@P CKtӟ$-̸RkA |rF2 obQ= 2V1*Ȼ@r`ger O  ~@H@H]JBnFq~t>KylJ :t:N/\"_‡>Ho,u HS5 3+cQ'S cN '%gr%%FԚflh y7 A7Emk2*BPu5A)̧~$g5y vf2y [=# xFlHg2Q2]VPdo]wI2z5Z=0$UB# ? Bq G"9`Q RCiSAXn9 Xqyw‘ll[0G!՝$GҚ{CTٞ Zli漇KDa1_ȉi\;sG:w3:S}q$Fl7 y+mdU&A:q]᭾sOc=`j#Cg.I2*on .oWiE<2}t0tS'' +=z!m+?(_5=JLAWAZP D[27vS*uFk 2grsy yLyFP4TjQ: 6^VvWn%`z0ox{˕/5}0{ !xa|]F (-x}d-}\8] &K$biUh5|v@Ar a)jY?7mt:aD\!+L<ͅR;8BTlW#b.#Dw5ƣ^LcZ%/#jy{xTxA@T!?h`Lm@TX ^Y='"aq2m7 5ɡ]5d^֠{c~}{I2kXh5+]la1`+%YY#9+1F));ۃ52@t|12Rw'uٓ5 ʙS⠜?Gk~W~2ށ{XyBOפJ + (S됋 3Ypv:5ׂYdTZ7r q#3\r !qX6EZf4ƟSS^Jq+``qʫ'dS"H6 '#c@)40d{jJ,p.cy 9{zb(jj2vvj2r{ƱpR%'Qs#'t| Egq*!0JRS0c#:;R 1r+z{`|j j:+#1[|îSB ewbC6E !L;ֳm q5|@y'ת^;K/}1Z~0{: Ze;,4Elk[K+=Xsw۹>1;DA-E+;[{ۻ;[{țʻۼҫֻ=Zӻ۽;2"Zh[{Bu([{:s׵ziS !^[ƛ7`v8$Z.S`;v_@WCn*n1\-00"cJA;fCb?aXc4GrYƈ5tNĿ[H42"M4пw*<4y72k<Õ* bĂ5IL xǪK aŢD3<+q`W5RH G4"¨ǘɫ)&D`!-*3֦n)=ZA.W1BS#-?n1Ư25S1:;T/&}\]؆ }㢚yPa"SP@xaW\=ڣ Pށ %2_R9[O!e^`4A]x]v}ܐ{dM|}@nϝ=wؽ=ސkOPI=]}o!yv~7~-1V  ᢫,0 0 P @P!@ @ &q`pEs1sQd^t@_ )Pu0m.&*@a0wNn0P@bx0^.U(!~F0 P1> (0  . > > .OnZ0Q[E @) *pN0 l.o쿾 q0uPn@P 0qp @ PC m!nE@@CJ0 0(; 0 &oH!P^N NNw @qq 0%>o`@n^&`*N)@"ꢮ>  +> F/i/ 1$)$F_38f9亩hXzr@@7ro@oB;K7&pq rĩ1m(C 8;B/9"LG?#b4$-g¨RGk.JBRR/xp)1-E234`;B"Fd&ܚERBR`.  9*4%hb-xeiZPۀTVY%R];C g#:!Ǜ:"$P kf;!GG =*JOz֣]=dҮDDK DR|b(('d{%:%P#( Ȗ`Z!0p pf Ā҉#[hAZ -DZd)Nq$h䤧 Q:9FD@(#142#:@cjz"rDɈJ@4C 2zի֨A8";$BY7`U^T7FK3njq#`C:1=%`FC_Qm%3r ]AERKT5 3" RF dLkShwA mp3^#eDpۻޕye* F І9cgQ\LPtcȑQ{^yiRb떝s~x/r,tl[MH]EDV[j, ,@-5H)MhOscCEKHSG;1Pzp"Hh 5<z""r 2zV, vr aI5+l` ͇@*AG RV(@~@0k!~)Z'db*bedFуh|91ѰpĀ65ra>@p`\>L=D@{A xzRh!x>&!R*3?dqp":qЈCy\0&9 D`@: O}JyJ C]9@1;4\JDN4f3dr_Э!ĈI ؅e-f:; ^È&I l#8BO0$Q#JI0 C |{$l @Le>Px,\>[ -@i(0-@iiM ˅/]` r~lAŃxq(;Alm8qa8<#Y>U;I0؆\"rk Am a;FrLΌ؉Wሻ#0"(",hǠ#0s6GKXe؅4؅MsB(&qB:Q6P^`\g舉Ԉ4X`zcq+Qh.i #0PIQPI|C@jR6Ԩ0 J ZK+\H \;W(Z (@ 8RuK bˈPt?B~I!l0@*c? cg>?@BCCKKMQRSYYZbbbkklpppz{{ $pXhBe{0ے/ʳXۖX&K;(@Aba9߄ &cP XU zXib2-,8j))zzXF~WKGP# N8%9VC893!!,!!#$%'())**67778999:ABBIJKOOPSTTWWXZZ[ghhmmnoopsstxyy $ph>e{0ے/ʳX6 ˍ+R HtHIi(JFp( g3@JNeTH[х-8xOFz2" # jx#s^s}(" GZ{FYZB.%CQ4 !!,!""+--BCCLMMvvwL e0JꓘVvqԛyY+Аj ײ_5`3r&|A]LNI%@!, 344788BCCLMNkkkqrrxxyv $DhFAں$3-7+&(z8"A"FmlQ$tBZ F {94e]Ui}yoSt{I[}%y5afp!!,!(**688:;;>@@BCCZ[[eegppqlI{8gW;yb#i8 8< `K'b~p9ny|FBh ʔTMa3Xh:ޚC$: ~_ovfzQej!, /01233==>BCCHII]]^gggsstlI -[yj#ys4d$SVLnn!ݲ Jń@p8)R*=aϸU$|ӟmtPz|Ag!,!"$$'()*,,/01012678==>>>@>@@BCCHHITUVYZZghhjkloppstuwxx}~~@pHv@dSlJ%IFS;DA BCCHIJVVWZ[\bbcrst|}} $`hFe{0ے/ʳX'á( ("Jdn8R`j,KDr­^Ͳ4 BLDRL0i"H&<7h"gi$q;6<#1"|$+S:J.¾ő% !!,' $%&&'()++/01012==>?AABCCVVWYYZgghijjwwx||} $dh:e{0ے/ʳX31|KQa2`M3:!&|[)INڛ`0vdA P k#VK<7$4"#;6UWH^#> &>O9:9<>31+ŷ !! ,2  !$$&+,-/01456<<@@CDDIIKOPPSSTYY[bcckklqqqwwx~~~ $Pehe{0ے/ʳXW(HPYe027Z6ѩ0(*әJ{DrIQtc왥\La(Su"G&<7ik#hjo" t;6<#1+"%TÔhƔI.%S !!$,H(**/01011::;BCCGGHKKMRRS[\\`aannoopp}}~~~ $pehe{0ے/ʳX_B(LPFR<  AL3V{aHt[)Պ)L`T-u$98P V"XM<7WY#;684P#8mg1$ 5o+9:`9&>3?!!,S<==BCC[\\`aarrsz{{bI8ʳgG}8V,, 8gn]C E&(H 2Ek1L[r޽+w&!),^**+BCCoopI,0Fxu1ԛIҍvzif8>-:ϾPk 4))JQWVv`L. !, h2  ! $+-448""%*(."!)%-()03-2:5093"!"(*&%3";%# %!*&.( <2,70;2"#$&'('()*++./0 >6 ?8/115 >112668788;;<9B9"C>>@"B&L(O'P)T*Y!C:#H?.b/h0f1k3t6z8~COKYcx$LB&QF'TH(VJ)YL*^P>@@+aS-gX.l[0o^0p_1tb3xf4}j@'C)J+@6D9H=N -F; K> R .V!0[!2c#6g$8k%9s&= > 5m7p8t;|@@ B D F!H!I!M! >!#?$%&@@CCEFGHJ~IJĢLȦM̩NѭPҮPհRܶS޸Tใ)C+F,H-J.M0Q2T3V4X5[f*k+n,q,u.x.{.~06]8a9d:f;h>DGJLȷS߹Tᤃ12234576Ĝ8ȟ7ȟ8̢8Ѧ:ը:ܮ;H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣA+ZDKC}`Njʵׯ`~"R 9;P$(!1ElQ"{+) BBÈ JB,(2RԎ<豃i>{*NZ ,ѓ`v >kGZv:Xsn# ht86IHA0<,T Da}R( }bEeYlV9@,T8ETa;wQ8IdLJs!HxH|TG; q ю8 $))SuD_>P 2AJw;v%GeASv$B!{@HjV+!hP$PpV"D2: Ç =|HE i9(T, j3U=7R2U(F8<idژCJr/OH_ {@(=Ec øF5qb$1aN !P;ct@Fy հ扆]zI"҄4"?&Jt|dt>4"H$:}/=0-4 tGL51uG:Q*ii@/CL[2Bbԃ.T@QdPIzp)<J8ȝ&!60 $ R4 dA6_Ph#rf0z*∌,RD8:|$Z@^`BX-h#AI @G"2NĻƄ҉2hs!w1҆ D؈f`"ql^H"JP#d*AQ '*Ab=0zĆlࣄ$8w60\1jEʸ T @Pd  `TE|Ԫ }mC(dqC@nV6yer䒘1o!vY(AADI1[k `h7֔J VKNBTYv>(Ŷɂm.R+2$ds_TSqi :L +%QdH8<Vlk@E.A@@lZm`hw.S.sp.6QVxV pn ))Ap)A `ZA  b :spJEpFdD 2  F4wbi(+`5(sX!T3aw؇IBqt(2K pA~W! Kbw`!h!jWXhB1М (A1 0B0 @'II-(.Mq)3t N Hn` Q)N g1fDNUANifB%1 |T&.@0?sa%aC֒H"#kA 0R.ـlBUEOפyAWh8 8o[iW ^ R FH0~Hdp7YPz Wq5!Y4ljK`5S3-,9 I]#0T8Ztw*A9T#v JЛ4b, J뀉11H0&`!й X 1Meoi0bI MM d (W kn` k-z`Pzu 7fc )`P P  S!j9 #:&vj(z0ʢI!%2%2:TKiT;YPh% (C9v$%tjB0AadyQr'T >n*x*pQYP@+G PFX NO@aO3c\!JsGv[4y4a5~c'GR]gj, +V]qIq7#KV,1@ IɔU'BG0ZE$TgJ`Ff{j٘(<dE6 sPm0N P  [ AAهZ@ R˓2#9q1: \S*+T 2R<6#l)En = &UA _/oFC)T Ys 0F Y6( PDkFL<PDR@4so -ǰs巀*P^vb5$@"5~JgJO6aK]ap2IWZ$#Kw8bV:"~3'G[04E>D/$#/)M1aAcZx|0椟Ўd+Ni|׀ >VXADg@ |\~Dv+T&zV}Ie'[.@pQ <i (U#,Lrь1JBVUd) Ip@ J Mø CS  Y@Xf PK |XppFrux1 z [ P rEhܷ%|@ao }0U!G ~D"pG4#r[q ~@![u^DKts s tG0Lc J' HPMc H "IALI$ npO 0 +' 4 tP Ɛ O2O0hS` r~ZҐ =&-%@m&VU ]kMP kQ> `0 1oVפ pnU@?. 0-)  1dDg! f q _YTP IW Rp1EѦergZ xs*KH~""r`!׳Ev7!;_JsGIa,'ٙXɯK !"v\eunǭQ!搻C0mѤ`fC-FUx.E&;ɐm|kf oP ƬD m<Пq0`N^1f z.mT6hkQ1je 53R>.@GE%P&,Σ=IUD !M$O:)):9==* 1+y Q28X@Cq~IC[nCd10S/Ud ^u3c9*HdPAѤ/(=tL&g`@!a0>@`PGaA9qc0] UqZ31Oo 1bxa2_! ?_ȟʿ?_؟ڿ-4(_OT$XA .dC%NXE5nG! WҤ}"UdK1eΤYM9uIɔ<%ZQI.eF?K}ZUYnӨR~%[Yiծe2ϱmΥ[]y;_&\/‰/fqSO\eD#gСE3iԩUftkرeϦ\-umܹuvoWqɕ6sѽ6^u:g'_xկw{k_ω?~!0, "#$YYZoopoppM0F88kS )cihm#uc15o&wA2$ѩ=mN)ך  ! , ڋ޼!,!((*123;<=>>@ABCMMNRSS__aeefoopoppsst hdkTp,WNK\"ǎdwJ3"L#0FST& @6E$X(D|Z{0OUb4TXR=P ,"jDQ<.< !!,!()*/01334668;;=@AAGIIRSSWXXYY[ddegghjjjoopoppwwx $@8h:C*W,W0M2i ~Kr1AWC U'P &Ks ͊N+Ln]N;Kk|mq3B sBj:#=wX\xQ1y%!! ,, &((()*122778;<c +H̙(0t8(4M%Ht"gt`MN&|D0 IO6rs/ K4W w  M 2\0@  [ArJ.sA% !!,C&&(+--455688;<=EFGMMNRSSWXXYZ[eefgiihhioopopp~~ $EhBeqpkm2]7;@ q17DoT6AgSm+_F<l m9;IO x~DbytaH`\9j  Q 3A"\?I.6!!*,N!!#++-..0556678799::;CDDFHHMOORRTYZZabbllloopoppstuwyy~@pH @d@ШT$>XjUxFۮ9 X_u(`6 NpPT B z_P  pd  fd~jT  ^C iL[pocC[ A!,X!$%%'())*+==>FGGLLNRSSoopoppstt_IAQ8kTq`(6](YN'+кή]i,##H!. 0VVIm^0Hp<ǔz!,c-..557>??ABCKLMRSSWWXXXYcddjkkoopopptvv}}} $@4he`p,3m8]7;@χ i3Z0%GzFySmQ,]0[$$gPGV~1st}n{$zDF$1M%A3TdF5A!!,n ""#)**.00233779<<XjuxF[@+o^s SS6 D B"bd|F"!"eC!!oC"\fP`"Z z"}"B"dTC!" {PTD ̜ajNnin A!,y!$%&++,234BBCGHHJLLRSSVWXZ[[oopoppstu}~~ $0he+ip,m8]7;@ϧ "7h*e.iExB1p'hEX tBIC_ <;/VD@r$kW$ 2I~3% 4LA0@;Sz !!5,1!! %*.14""%**/$")%,(-32-073<60:3$ ")+"(. )03!;%#!%")%.( <3,8/:2#$%&&()*+..0 >6.003 =234678688;;<7A9B=G>I8!C??A"B%K(O'P)T+\ @7!C;#H>-b/h1k3s6{IWSdbw$MC%PE'UI(VJ(XL*^Q+cT-gX.kZ0n]1uc2xe4}jD(I+@6C9H=N -J= Q .T!0[!2c#6g$8k%9t&=u(={'?x(>M*\}(@a1uM@ SE!WH"[K"`N#dQ$iU%mY&r\'v`'v`({c(BCCFHHKLMNNPOPQRSSVWXVXXYZZ^^`ccdgghkllstuvxx|}}mp v z|<9<>= > 6n7p8q9u:x;{<@@ A D F!H!J!M! >"##$?$$&@@AADFJJĢLɦM̩NѭPӮPձR۵S޸Sโ)C+F,H-J.M0O1S3V4X5[g)j*m+q,u-x.|.}06]7`8`7`8a9d;g;h@DDRݹTៀ011234566Ɲ8Ȟ8̢8ѥ9ը:ܮ;H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH* c"PHh^Xjʵז5c8Մ(=Jݻx0Ѽ Ӯ}.˸ǐi`⁷ >8 ͚'0ȨS^a{w` |(X?ީx^o?1iٌH'iY}@F‚d ` xjT?`n:h+/dЬBB;qS T`i'P84At?@ΫcU)]]6oD?|l!wD%O iqu,D t(}X aúܓl@#H 8$O3[ЏG.Fot#~s|IGzܮl F8!ź-&ܮhZ37/ҋAߤnER`z!9$C C!0rH/.7p!{@: ) !/o觯/oC Gί?  <@A4t7(U0PL 0ւ1+ 1`!( 9 PP Hb$ RHCPC( (! Rx!%(Q,!$0 (4DŒh< ш30FF/H 4Ð u H!$4QJv8VLB =!@J# (BqB4d"$(DhL""D@~ BQ0a EH|ӊlcK>JdF0B-Ys)Q"1BIKFDg;Z:sC%`JTd E+cCw/J(€R#H(6{m$ 2s)BPAC B^=3G Z$$= Pwm%8&`TY9L sXpByt#nF$P"i'z ZLzlз !02 m]x{] awmp@ 03`@@_ V5=+6P!@2оh 0vI25 rvvIA3U f@Igf)$Qmr!)[ 2/@*"{7 `@A (^(a'Q"L Ū4 ]^CZW4 : pX c W"$-``0V8 ar+@I0 (TV#WI@(r% XPqv0(@p`X qs_Ђ=)=sAJ @Dp+ D'aP(C@)`aq= RJ LLM7 *P ~E !dW C`KD~z GvoPngf V W xoĀj] x j pxj$qx] d   y xb0Ā  @ yk1zA[0 f{gmHMK&"[l{M4|{)kKThm }R AoϷG n n0O46 7oD]T t )! DPPmPJ-Dhbl_>8 ;@P rg!P`5'QXE` sqJPD&71QX$y|p4r) ohȆBIKLQDR&ea爲aB5  l ]qG py 1 e𘄖 Xxi '] ja  3Ս%FHE|H!ISq$DUY!E J]y&eDU q4NWV X\A 7F~G0W q}F)PH@nϧ UOP*x~5-_+ @q5Joik(wc73(E)IOrI{q_쐣:P U!vO)`x;,O^)`yXWXhQkɅ| @t vYf:pMlye!Ep"ĝ"4 CKAԠ iPmGLʐ PYxp Pw x0 jh.eu7 𩁧 yxi]PwnW "`$P 0 hk"5ZxkvTl RLLG6~UaHpAn^ Z0PGV ɟ *\ m *qMP fV[H7 PX' OPKh谱˱y2x@Yv';% p۱p[ EQO5d8QKji-cH s)`SW)%TBGB6sZ@ wUCu([jʠxv I : $n iZ@0pxZ%o pǫU;7Evy)vuf|aZ0O~iG* UY *ڑ 麮,quC pgUs0UCٲ qrEId r rW蛕3;b7;C AqpY-0DG*цwi§[ܔr} !?7TAA .Ÿ֨dPti)Yyyqx!$| xhkij  MٹG *` @qMTv9ZJ CjggfqS~z&fq m+UQuoJzݪo  ɨ A`q5׃p 6=O AGK_CDWP!AqYvV{`sZiPqK(9su ۳;A |n KtszffV Y g \k۶ji'^ Ihh s'kP  =CjKU B9t{8v!LL [ UPX\TI$ ) @nxܻ 4)o!ׇmP 1@= H!%=.WJ 'PqXd(VqtЖ3JZ`\BipC qs*@&XJEr5V5|QvzsCE `u v(nYi@oPِ H,-| H6M%h žYgA!ćz!U|(BqMUb|Ӹ٤N } 1O|0-{ P Պ RЭp}G}F}0 ! ) #)J{V/gO8V=\ "W0Vs0mYpOYa+cl\(q08{͂mPeJ}Pes`U~UR9ell޴VST3U TF@l}(јI܍ ǀ W]vӠ *ڐ p ܤmj ;Q<L 40M|ſn@% ƶ`E h m M FD 1P % Yp p  l @ & 7P@  o`\8k͠|0Ip@t54P_99:kd `t0_0I P qPx4`P4 |hO4U/0@QR<]\J0 7`E LM49E` `1y7 } { ]~iƠËZp @ n ~ QJKKOOPQRR[\\bcdkklrrr}}~ $`he{ap[m2]7;@ q1-g@P>(@QO4<FkR30^b$x{{4  Jb n/# mY: 0]D# HMLMI.!!,""#&'(*+,667@ABOOPPQQ_``aabijjstu} hz,0Pp,C-8]7뻞 }1 $X Q#P`<0]`L~Di `|v:+6}:["eo:k#  MAM.!! , "345789>>>>?@CDEGGHOOPQRSeggmnnnopopppqq{{{ $0(he{hp,Km8]7囉 !6f\2IBdzE%>B0`4 t@VF {?TPS}U"XR:# ;<";5!!,$%&**,./0345;;c 3R2$0݁Y H8Q#aEUTE"#:j#"#_ _`@YJ.`NAG6ND!!6,%&'334LMMOOPvvwJ B0j18Q -#P:aЛFf }H$ 2\*ieaoڔn !, #$$+,,344<<=?@AABCGGHNOOOOPSSTZ[[abbnnowxx $p0h2ARY,0M2AAxgXJ0W5WTS"#y<=!!,$%%''(&((..0022==?>?@CCDJJLOOP\\]{ ,h*e DR,ˑ[\#ǻQQ ~A@1heg5`xg!`Q7u7$@N:sbgx; 1wth63 =344668;<=:D8!C>>@"B%K(O'P)T+\ @7!C;#H>-b/h1k3s6{IWSdbw$MC%PE'UI(VJ(XL*^Q>@@+cT-gX.kZ0n]1uc2xe4}jD(I+@6C9H=N -J= Q .T!0[!2c#6g$8k%9t&=u(={'?x(>M*\}(@a1uM@ SE!WH"[K"`N#dQ$iU%mY&r\'v`'v`({c(BCDGGHLMMNOPRSSWWXWXYZ[[^^`_``bbcfghghhjjknopoppsstwwxwxxzz{mp v z|<9<>= > 6n7p8q9u:x;{<@@ A D F!H!J!M! >"#?$$&@@AADFJJĢLɦM̩NѭPӮPձR۵S޸Sโ)C+F,H-J.M0O1S3V4X5[g)j*m+q,u-x.|.}06]7`8`7`8a9d;g;h@DDRݹTៀ011234566Ɲ8Ȟ8̢8ѥ9ը:ܮ;H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ Jѣ4X*ĥKJJիXUk t-%%&Nx 5Y|1@U|1p B 4X8 GyhZǂ;$M:PHԡ"DQ0%Q<"%j| k/*Z+HQeϚ|LoؿySEc8v[$n!YPC37۰N; s,0$ -e= B?xԎ?{,?,O?0 bq@A>2l)teCЕ(.DbuEPA&$nĕdr D4W93Ed)fa]x1fY|&B;XD)F@)x4D)<6DЄvta mءB´?L?$b]"J)0  )]!8\)b GJiy2A:jYNg+V%;L_Z&;&`Ywљ) Y't} ;@*::+Сvh<=G@hb (&K*ѨX@$2.@Wĺ@:L@ "$@m'\!CAA`  d\Oh= 'VhpU%`_0T5T`-\L3tKp(L2[~;81Ps0Ìp,C9A@s dB, 4p0sL3usN)rz} | 3PvlQ*-J@;0(/P4 qC1$Keh!L(00 PAX2(G@b0(` h 262DhwC"ޑ8B|C6<F$ C`c zh ~;1DCi p8dk=8Cq Q;ƃBp ANu \ApUdU:TW 9bX,XdUOT2B,'+}q @ Wk![A  _$H'T783Ya`ZR6%1I *p,`9sB:4]*wdnb:)&M[̡O?K @$V ƭwh6nD%Q>1!F%u6R iW~ PAA PhJR 5 5Z dP PbIZ>AW0U]( uG׺&v"nj 6G`"{GٺJ$ gZ/2{+ R[W  4—Q |6*N2U"@ AX ,p}*G \M"HD*RKj`.|B,w`Vk ,0*b|] v*Z $­fC0f<$ YFB}w-lh} =ȑ!$Y)FqWxPJt%fE@얌huUv!@` `M 5-ly T "́T&Y=Ȅ+|a k!X27ұh@FtTsMױӁoUH6ra 1.0\D c*FWH*Ch!l*!0B EP1Uv%Æ#qGS v0R$ug4 T4! 5A `a05 ^kgD}'KPKn PJn(.7* 0O gߢ's;J&fOz7Ѝ؍֡&k2%(`btQT|%'ʷ/nV'7gx 4R )!9r`j70E]]1 > A1Ҁ ePA!p PUP ƐTHU f@bI 0U MUhYTB5 3Ӏ@aIVЕ Yt1!Ux7HEfLG GAE=7OXY^^Is[r|5!{ XQZx2HWQ`a(2F\ext2HPS3I 1(GPiE14,0K6p V0`ER u hX K v*yaЋ'0-r4 `6d%!&bfPiuGt3Y"@p 0y䰎%xBSd3ABUT H1 E 5 7 #pBe A?Yՠl5pU=Y$PI0a {ٕ\#'1s;)K0#\XsDr ruYiXUHHc[yu GTSЅgSR]VP%Py_`) 6w @,U wyxY,ywC MےP)#bjcw N`g< O !P1A.:| J:z mpѸhAhgص3>  !:P2,! b@``O O*$PEqke[e!PUae h  -0aV[M uzʃ|$q H8o q)GPs 2xQZZp q.pZ9Zri/ZÑ0b ~ѕ\H$S~G0GI>H$kvQLR  U0 y'Y6˴L@pY 4a Gϋ Z y7(PT8Ae_b00O&{=Hfj=r E|=$f8/(F 078kfPQ?F 2hW9H ᇥACkWGUNЀlVdG[5 `VxTq/n J^!Yo2קG-uskYpKqMTyfx{[q)2G'W '<ņ)mC*P#t7E=\+H 12 uFC]rj!#*˺1Vapw1@0 w G2^: Q%0 { xf ؋y"`$|ʓ:ߢ/ɽ נNg9Sc Qz tz 5$|%Pz %|[0\tC>P R +2KH*+$ekPp S+7[ S4=L#f1Bnp E0*ZSDt1'sD ^P8,|rTYiFz iܷEYQd@{QvU-GKM?t-\1i[a,+i1#?cɛɌD;$^ `Q%]0X 0 i Up^E0_ VA0_ ((̍a-%{TF|p ykb$/p-o0f%9*;챯k['0O,0Nm0AP@󽎀z7,II@"›*@+, @+J&6h1[ ` [Y-}1-Tр )kp P YHCm3 '!0W`ZZ=gń}UpNZ^(G\q{XuMw}zU[nW~MW}_ 7.EPd \# MP#f)釼G@+I P A S <H=٫Q :+ p 61` ` vP S @ pk $ i5K  {0}skˀpx@а1pˀQt 0< 8p[ mc) bgvQ&\ xH/wW@q(l4E0  1G$`` M *] U:aZYiծep?qk[]yMV\|&\~ cȑ%O>xqcʙ5oٰ忘=&]ifk.Uύ]mܹ fo''Zqɕw%n|sѥm>uaVw'_|կg<}{~?}?p@ @Th[A#@ +B(pC;lHCCCC1 qEC !/,  ڋ~!0,  &2~(֕ϻax)jښ/K[!,  ڋ~!,  &2~(֕ϻax)jښ/K[!, !"#$**,223BCCJKKTTUXYYfghklmoppyyy~ $ah,@`p,Sm)]/뻞/ aG+D$`-q 07qA*I. hR4p"rRDy0 .y16G4 VyEi?EHOJ- !!/,((*;;=>>@BDD_``jjkoppsstXIP8keK( U I甪"/\R ˭' Gňc ! d,meRNdW%qls !$,! ڋ!0,!!##,..344RRSWXXYY[oppvww{||fIa8kF7M(MU I甪"/\R ˭' Gňc -Q.yFyRE79Č.)@06>)T'R=K|='!),,$%%&((--./00455668799;<"6Rucl~KJCԣ[ `f57uq4d vONU";}Ypgr !!6,C"##-//233FFGMNNYZZccdgiihiioppuuvwxxxxy $0QhJeKYpSm2]7;@DH 6lİJ *)h@ nl8`IBvWl{"  VD#gw#2\{%~A?ARW@; !!!,N ڋ~!,N !!#**+233SSTZZ[``aiijoppttu~~w 0h,0Pp,Gm)]/??>>@MNNRRSXXYbccjkkoppqqqxyz $Th6e\p,;m8]7;@w>c + 'X @8,0I v2@qhhpQR'z|~M`}L3"{]ET$A^A"J.6!!,n*,,/00122:;;ABCJKKNPPWXX[\\aabggijkkopptttvwxyyz $hh"e qp,'m8]7;@>c # s&TbhY8hf rp.Bbw4{4/$ w0j" qr|o Z2[ lJ.6ArRA!!,y$$&-./223<>>>?@NOOQQShiioppvwwz $HhePp,-8]7뻞 }EW+cn$ 1tFL&FeZP验REȗS6xtg|K~#sC:H;ISQ} !!',!"##13389:GIIIJKTUVYZ[_``aaboopoppqrr||| $`ih eqp,-8]7뻞 }EG %F6 2Ɇs2%8ULxxp2K}L |s&dF%rR, S"8K@ CI%\;ZH$ !!/,1 ! $*338!""()/#")&.*-41-2;61;4# #**%+. -52!=&" %"($.( <3,70;3"#$&'(&((++, =6/00233668:;<5@9B>>@#C&L(O'Q)T+[!C:#H?.c/h0g0j4t6{8~AMGTIWJXVfaudx$MC&RF'TH(WJ(YL*]P+cT-gY.k[0p_1sa3xf3{h@'E)J+P.@6C9I=K? Q .V 0["3d#6f$8l%:s&=v(=x(?@%LE&SU-f|)Ab3vN@ SE!VH"[K"`N#eR$iV%mY&q\&t^(v`'v`({d)BBCGIIKLLNPPTTUWXXZZ[_``bbcggiiijoopoppttuvwxwxxz{{mt t~=79<>< > 5n8r8u;{=@@ B D F H!J!M!=!###$?$$%%@@ABCEGFHJĢLȦNΫNѭOհPҮPְR۵S߸Sใ*C+F,H-J.M0N/P0O0Q2S3W4X5[j+n+q,t-x.z/}06^8a:e;g;h@EIOҹTៀ01223456ŝ8ȟ8ˡ8ѥ9ը:ܮ;H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]^-cJիXjeJӭhӪ]˶D2W(!F˷߿ iȘ.3ѢȀ3k̹3@wߠDGp eڢiد\& <{u]LSH N{N0gty(W-9zGzD@y9Z`hO\%O#6@fcE]i.A-5@;jz TÉ"<9Hh"F矀@ap~}(z#Ah@'\u$@YFcVgO ~] eAa"(jwychj \`kAYRóVhTP!xǬqiЭ,6JЮd7iyhTڨ7AhMD@' ٩c©خ@j&4i$|+ww@!0f]#" 0 #M @O!er t@Wi&g)lh!* f3'q m4/#A} 7׀.8F-0mh`y K 9MP 3LykR\C! Ү;H!<v-G-H.O=tHo#Oi?Tx4GR =E?'觯oP!o˯v c? :H`" cR@S@` TD =" )Ha dAf ly0SNpD yPBXpL3OP  (F*<%Fؐ\"(BA|P 0!(0*$$Z(&b?(J9֡@EЎFcF0HDl:!aA;DFA9,A pWAx>hO p2`%Y" RSЗ)J L8sO\(NaPdPA3S!KF0` ";${` @ER"(;ᎀ*#dDPP4yIA %AUr!{xG xc-F0OˎAcMV\@mBS &RxTHALĎfB'\wiO"'QJdà xÇD(RG6Q  a-%Ҿe;iꑛ';GFp S5d2TTBq0O|1=U!{ `=XRՃ$ \N" }%ЃЙv&؋_qZ $(0@ ƾ 0Mpd H-QBHA0. 7xheA_ 4D*-tl]*1v}GM>䀺CE Zx B^l@PW5B !UI&sl*ˏ<8[Qvy8Ng3xm"1l9ILe{vD6  7 nL1m` f6(8ݠ幡aF2ySfk^ A$  6pcT ) B-l"*feֶk&H (APeu0! `a }  5(H׏WP [P S@ `CqpW 0 P p0 @> qqq7q(PR~avEP sU*WKP{0URP MPEhPb`pC qt@Q@vyC|C\hDSR0WEuXPaShTvXq?Ct" sWw` pnqS` @YM$pfe BgY1 '@y\ސ fp 0y(e$Py^@jH{w@L]yҀ{AjhP Z|wT ]E9F8TeYRUSUuUĉQjTZ` AdUmV>۔  10 pP [0 oU 1q%(P "Xp ŀ^U A&h P& ve (Prd`fx-RDW7 &WEVC(uxTYT[zJwPYg5ouu`jIue1&E,R ArR9n0 0s7'G`$T PL5XSSh B($0zPhPj1XzQG`y  ) N?|LD9_ ATϦK;p Nt ~wTn UP@0?P 0o+pP QGq Lp 9`\(9 `[8HggaK}N bP+J@ew1@GI>7acwQUt\@bPD:v5a!WR}N KLZ p)ru>٠`W*w@h PvVjMgUt Md |}wBE7|k p 7y* ɀGIPy7yhFyjyLp* M|YZ xI@TF4uD@┙As  pP & ! 0 IJjU V ( @((A@HѤ.e PX|H17$>A& K+7s:PXHٰ˱+EQ r0KEHtб.[L QXUm.PzKyXqtנaej Fk@q`N_Th(%LpZ#zA)e ڀkJ0۰ yZʐz :'ȈfP Y` ` ڜ(lљz NjF E׹Ϻ9GEɟ 0Z i5WP 4I Bsmi**aAQ2TE78Zdxvc Q fXWZu u}z0J\$dM z'Yxm֩yж WƐz8}+j 1y* f hKжJ L@Ī Yx7՝|Z M'TlwYa|zVAHWȞ z$ ǒG {kL )10 ()^  Hp ;[fH.*>YH(kLhbKٔW5jkkXglXbbyJ7kDQt7ڡam KiF嬓 M&Nf y #\@  Aj+P˰ ( L~-F  AC@Wvt D' )lmm)` )9ld fg E^} 1W _ Ȁ8XP pp Q 1'( 2 fW0;8We@XI*z duXLWNWQzf056kJ%;<UT vAJf дApNPJxGѧ0 ] "zPzy¨ \W`LYA{Hp L  1A{Bwgf٦BlY4 #gߩx5a +VVoo ~t pGZ`p  V == Y w KZsˢ-r0v5ws9E?G'P}y\lrAnMa4-\vPVpD~̔EB0~v m ̦E ,P0zW yA,x{lz7zkqq_卹TAD9Pyw ]a;> p *E wv~n @. ndgv= Q P X ͵ БO OP]ٵ]]W ]`]  L{@ %kpSTTWXXYYZ^_`bccoopsstyzzp dh, Tp,K-8]7BbXʡhE |zF]mYt"`59ƪre&;<۫"Fr:  ;|Gn}z!!,.()*456:;;>?@CCDJKLRSS^____`abboopvwwvwx{{{ $ 0he[\p,Gm8]7;@w # .g|F̢\*0aQ,ڒ ϜPiV;ʳ8Muzsyw|$0x $2 0%tAF5A!!,.668=>>TTUZZ[`aaghhoopRIA88kQ;I`(](YN'+к ή]i,##H!.4E4y.ꥁ<$|^!),. !!"#$+,-..0/01122;;=ABCGHHKLLOOPRRSXYYeefllmoopvvvwxx}}~ $Hhe;}p,3m8]7;@>c Q d, !78E-Ap:G*<@ 1nP\$^0J#w ga:0oD:nINMNN !!$,. '')'()+,,/11335;<=JKKOOPRRSWXY\\\_`````ooprss~~~ $@hBAV\,Ϝ0M2^ֆ"PS7`*1( Xb"LPpo1J;mi{fGQeGt/gi <^`t$  HCMHdeP!!$,.! !#$%)*+345=>?MMNSUU[[\cddggiiijoopzz{ CDEIJKOPPQRSeegoopoppttt||| $`4h&e{hp,Gm8]7;@ϧ>c QQHOdP ]4`ۄBh2yEsxd|JYd4rt.fE :``RcNZ6NAG!!,'.667>??CCCRRSWXYYYZ_`acddijjooprrsz{{z $ ,he{Pp,+m8]7;@G 6D$E4 ,(dO_T!,=.#$$/00233779;==??@ABCQQRWWXZZ\^_`ghikmmoopsssyy{ $@he{yp,m8]7;@>c 3X':XF hA4xeRP[xD40Ie# ME#P\/" 0g 0af QNAs6$N\N!!,H."#$345<=>@@ALMMZ[\__`ceegghjjkoopuuvwwx|}} $8h,`ip,-8]7ZMhIeEMQ4 J,0e4gi `h,@^*hq"}k40#vuYxz"|c oqse0gib"[^9;< > 5n8t;{=@@ B D F H!J!M!="##$?$$%@@ABCEGFHJĢLȦNΫNѭOհPҮPְR۵S߸Sใ*C+F,H-J.M0N/P0O0Q2S3W4X5[j+n+q,t-x.z/}06^8a:e;g;h@EIOҹTៀ01223456ŝ8ȟ8ˡ8ѥ9ը:ܮ;(A*L`‡@ ċ0ЁS0)0 $^ 0cʜIE8vJ :+~ :&z*]ʴӧPJ}XPXbHD/FBcA8  dԨ Qxő 045DR{T dH 9@jBL&2)9uHNRSGRs|]k_~QnOBj(|Bk`Btw)Q ԁk #&y ZxN y 0|@=R&8Zr)ԗ@>^6&V b1P eEe3)-S:@rN与:hO9#q4Rx=14@ÅX}#H{( QFBKQa#>GA$`&Ob !) @r.8|x@z Ȋ$ /|A _$Fff1Ȍ-]c$3T .bbx"! R Xq&,0`5x!9=Cx#w r Z*@@wfrԎN6&5F.[9U3nZ:ue 5NBTZoˑs+֑r4 " Dt1H#"\) HD,AF7 X6 d RR7 flKm604HU@եvc @0A!!LRAM0Ϡ&V= G?aX{ a?0V"}|^?h1mb1Xp}4va>~^?l#bLJQ!() $<@FlbK## ~CH( dPk-I0 Ta J4@J',3ˬ/2`0 a$!D&1P ¸*@ ` 0>ӣ}+`!sS 45H)TҐ>&Q WaK!dHHRH@ a@! RLTwG#+`K& $.Hrb%lA Ia011"G%qm>Duw*蘕cGgPd=9&w@)h!xnn?I,XX%18ႃX;(3CNI[Z1`E 5j9uOxG.w66x P!&E'2)!7Q_"q(4 %wvPu x+a P9b0a$g(h&@ 8R7g qNMx{&pN17Ee 99&Lo+7ϑ# #Yy0erp+HNGgQ|{e xs6kП 6 $}!Hi6 Ej(}a)!ݐ dT Yզ ʀ G `TkU) 8l1Tΐ a   L e9#؁B)#XZnEX\B@^B:8G8@pVDb1ƃBk 2qr/<7x!t*u99׆$1M 4uxy}\G 9pT6x Q:{p3L8OS)@,3\T8̈^f왍w6-&P$9gGuk PfH 7+~끓u0 .)0 C9#> r0 Ѿu{ Ӑ(6`]0 QH : ]C(@A(q B <2!Ug` ` A m ` 6Y0 g @hR0&~04 c:Z  A;tQ;0@C?_`D3@"_?'$X?_q|@o?_ȟʿ!B;؟ڿQ ?_%.&o$XA .dC%NXE5nG!E$YR")UgK1eΤYM9uE+WYQI.eS< MI4UYnW3RYiծe-ñB˾[]yUw(_&\K,/fcoW\e̙5ÜofСE&ҩUfiױeϦJ]&l۹uݻ/Už'^\4nɕ/gysѥOuٵ״w)v_yѯg>zϏ!/, Gy ##$&'('))*+,//0.004457797889:;??ACDEFGHGHHJKLNNPNPPSTTVWXWXXYZ[^^`^``eefghhjkkoopsst{||@pH,Ȥrl:tJ<جv z_VxLF0v(3\8krhjBvy{X$/Z,/O_  |O%sRj EzB C DN (/ D-/K^jTD.S)B +T B //,/%CR.Mz_.@@ Ф`ʐ N'$- 4;EZ eD01 jZEt!4f#o)D Cmrzb#_,'[)fxa'#@8UȣTM3 CnBw_ 7ψ̉b٣6RpS Y ;(0'OX[Q*1M N|OG,ℯqʦTFbUjI]Tyn{x:[q~@vwm~ytnic^m!*, `1!  $*.2488#"%+).#")&-),20+1960:3# $(*'.. )12!;%19" %!)%.( ;3,:2"#$&'(&((**+./0 =6!?8.006 ?344668688::;8B8"C>>@#C%K(O'P)T+[!B:#H>.b/h0f1k3s6{8@LKYUf^qh~$LB%PE'SH)ZM*]P>@@+cT,gX.l[0n]0p_1sa2xf4}jA'C(K,Q/@6D9I=N -K> R .Z!2c#6f$8j%9q&;v(>x'>y(?L)\]1p|(@f3{L@NA SE!WH"ZJ"aO$dR$iU%mY&q['s^(v`({d)ABBFGHKMMNOPOPQSTUWWXWYYZ[[__`_``dddggighhjkkrsswwxzzzks {y;79<>> 5m6p7r8t:x;{=@@@ A D F!H!J!M!=!#?$$&@ABCFILȦNЭPӯPձRڵS޸Sใ*C+F,H-J.M0N1S2V4X5[k+n+r,t-x.{/}06^8a9d;f;h=ADDRݹTᤃ12244566Û8ȟ8ˡ8Ѧ9թ:ܮ;H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*BƁX:$;=Ȉ`ÊKlF*1ׂ95ß ]5MjO/{Nq͆h7!|9o?i1ŻMph߼~$]|e_Co@LRLZ'Csgf(s5T=;_<(?1;js=O;u? ?,`,~oa'ß_v`Dn=v@}ѳs c%hf18dHA@#,x" יH9=1jU榜vCc又})uj^ʸsO[D/C`w[eZZ*O-蠉~*~I,DeTZA -vn?:@8Տ=&z+EzahZelg>-AZD,2ɜc&7<ZU/f|v$G|@$D8X ;@ A?֟@#]ls$JXAU"@8 VpY)M0 Hi/c 0)"ߐAf`$ 7ei "q7y(D!U QY@'6D# ;{B1,1w:!b,'IO8dK+ "C VH< bgIO4E?Bv Ƀ]qv5A!*֮)욎_ )IM҅i;Q. pE*5D?3N.1_H2/~98Wd ~%~6u`qq   )Z 7-WD|@o17sQs} U GTFc@'Ufi]1CхT'QG aO0^ Y f'rVq lvrdV nruuߠ0 +Ї{)XpXhPi)`Wuxvk(hzEyx@v5QW _l`zk1R^fzw`Hqv sWeXLEda}J t J6# 6 ~؀aԀ ؐ a0~ZUWf @I%0p OKrDG 9$HocY @dFU<[[(XHGotquEAvQEuvA\ HhyvA0 l WG@` vgR`)_yz0thR)hv(}`k )WHxh0JeX%jViZ+Ջ9IYgʌu6J'X ٬Js%QCa`Iߔ Ic@>V%P oSp Ppǐ *I r07jW p ~!0!'~ưQa o[ PࢬŔ2&!oX|ƅ 1d \_iGvu yuif`O^0p CHYZ]tЦm at `*w@%x J) }xX0@; Wk{ka^X}@ *j{^Ggk꠶uqt𺯻 QZ!& I$:Ҕ PƻSBUWeQr~' J  0 #g 3I[ ݻ@ i&0q P a0J !JTż!j)Er% i֘wY 1 `\ s:R  OrddzGlv`zWzPQxPwG\lع~X{ -`k6ىKۜjM˺@ `U?0MqTJs?`Io Ā"* ؋I K+%k~[axg%` IP n  Da1O EI5+Xe 6c(AV"0V8( _ltХ0OKW7flwQ @nv`[OK \'  YˀJfE`^|ŇJQIh]ܷujYpWEa,uxY l5l Qx4 {tlȇ!5J"v}KJ%0O p {~L;Ya`qГ&W@9r 񿰀x M|C@%, M)mMCWUZ@o=s[ 6s:ڼ^`1rWpmW S EPt `+W-]O1yekR )x+SyzUxERig`5u;jo,!mv ƙ ҟ;)eaӀKzmX=m|]9 c|U犁E`+ <%krZr :oƀ J׀ h qHm1Q }˛Q}#DJ_ H77s%xU*蕘 \U_%nDGļ0 W V*W $ :hY躀pJc4U *L! ܕI=>gkǙ_v|@'ve'zl^-+xw Q_ꂛ .' `W`-5UW<s is.(MǢ b a'~Ք\Ԑ  ˮ>0G h̰ A!wP>LH-C $_˵mM J,@Q L`$ Ҥ e޼$o ^ L@1[ۼ pܧ =W Y `^| XP輐 ]S (  HP } Ӑ Qeh)i@һ0k0 QШAPѐ aŇQi/PqK RFΐ xBZФ B@_VLLPU  '5> +_J Xcɒ)`Mj֘0aC@!G!=WSbBK1eU4uOA%ZQRSQi?@DEELMMTUVWXXYY[cddiij{{{ $00h"ehp,Km8]7;@ϧi34%GzFySh.pYL4(4 Ҭ"uZU|Xz}DF~$0 E# F5AYEB.!!,x,,.012TUVZZ[ghhJ 10J*18R -#P:aЛFf }H$ 2\*ieaoڔn !,x$%%'((*+,/0034599:BBCFFHFHHLMMSTU\\]ffgjjkuuv~ $p4hemp,3m8]7;@Ϸ>c 3RCB@ BoDQڢ )6WX ((othb lDF eP[-0:"t _:NINAG||!!,x  !!#)++<==?@ADDETUV_``aabsuuxxy $(h*AJY,0M2^ֆ"PS7玔hD18zmX%xHeOd*wc||vbGQ</"^" G B  HabPHCM!!!,x ((*/00011<<=>@@AAAOOQOPQTUU\\]__a_``abbghhjjkwwwzz{~ 0h*e l],˛[\#;G| Sژ:QPG"ptCN Z4:{ t$rmgw0b"D;I""a#10kzJFs{FMN!! ,x!"#)*+123<=>EEGIJJTTUabbhhiuuv~v dhj, Pp,G-8]7뻞 }1 "0X8L<$ R$1ͥ@Xmb }soOru#y: CIHM.~!!,x !!!"+,-/01112<<>AABKLLTUV\\^^``bbcjklvvw{|| $@,h"epp,Om8]7;@>c !< OOT6 p*@ v`T(d/xE 4kKc c4#n: l# bNZJ.NAG!!,'x %&'+,-123AABGGILNNTUVYYZhiipqqxyz{ $0 heLp,+m8]7;@7 GHbIh©U$9@FQSyg;I{W$~q$ 0 pu64`3A"L0F5Ru!!0,2x'()567MOOTUVtuuJ B0j18Q -#P:aЛFf }H$ 2\*ieaoڔn !,=x ڋ޼!,>x""$)*+233::;?@AFFGLLMSTUWWXabblmmoopsss~~~ 䡜h*,0]p,-8]7] h%d6OCdKEV T%`(Weh\&2Z\ yFTP SO#R9"U3h # 3;_q?0:;Gh!!,Hx !"#+,-99;ACCKLLTUV^^`aacz $(h,Mp,-8]7曕èWJ^W"Ӊ.ˬVE]b`x>'R1Yy~{oi}M<p9" ;hzF;Ti!! ,Sx !"#'(())*//1123789DEFLLMSTUccdjkloopz{{ $Мhʔ,0Ɩph3 WpAmfD*fR8&)#X`t'p. T0b@a# \ozlHk{d~$un "a62"lct/58  9:<\Cn!!0,^x  !#$%'))**,335<==DEFTUVZ[[ccdoopsttxxx h,php,;-8]7뻞O }1 #cQ8D@ {ن(0r@'F Md+*Ec yy~D/F`40J\" j :M_XI,MA!!-,hx ڋ޼!,  cccijj-(2%J9bK}9j [vD;@`H$!0, J   %*.248""$)!!)%,)-43-3;71;4" "))+$)12!;%# %")%.( <3,;3"#$&&(&((+,,..0 =6!?8.00334668688:;<9C=#I>>@#C&L(O'P)S+Z!B:#I?.c/h0f1k3s6{8~AMKXWhau$KA&QF&UI(VJ(ZM*^P>@@+bT,fX.l[0q_1tb2xe3|i@'C(K,Q/@7C9I=I> P .X!1d#6g$8j%9t&=I)WY.k}(@K@MA SE!WH"[K"`N#dR$iV%mY&q\'t^(v`(zc(BCCFGHFHHKKLNNPNPPRSTVVXWXXZ[[^^`^``bcdfghfhhkklnnpnppsstvvxvxx{{|lp w9<>= > 6n8s:z@@ A C F!H!J!M!!>!"#?$%%@DF~IJĢMɧM̩OѭPԯPհRڵS޸S่*E-K0N/P0O0Q2T3V4X5[g*k+n,q,t-x.{.}016]8a:d;g;h?@FLɸTࣂ01234576Ɲ8ȟ8͢9Ѧ9֩:ܮ;H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣmPJEiޢigOBmhպgٳ:%3Ýhʝ0u+B qWǐKןȘ3GuBFÈ)u-Z6T9ԍ[wA6!LE&?w{\׸y _56|ac 8<, /`E6[4[t =\x݁  `rHq Ȟ{`CH]5HoG\. "H#,^h@o9APygc╻W4@&a\zGb ]FPr>$?? Ȣ}C\_!O9.P=?L1a,A|@ @q VT eӗ;0矂G)KZ_Yl_#]6e#u "v^rw6?%O*ۂPAn]k@n(5u B ܴ@ "lZ.>)|T @6p@y$ `-N/ aٳyU;kRwI̓HuIo#P H "B<}> u∲;4@T踃 }1U]NO 8YW֯})DY9y.r0&x]C;>c&:w>duظW쇶Cv̻䛞a" m]^`eR#m_0Oؖc.?h +Pu>€ #h %?Dh,_,y>c=in"{ "B1! %'W,jȫ=n_6LxX /xmfI/@X !rl |ʬI v)AN')oQ 5I\pզH60&]AǨ_c B= J-)M==@E'czx!,i#?Ė+Ȉq%Z<>R_KG1 ́TpJPm‹PXO{S0ǚ՗%%B‚K\սF#~" t (Z|>jkPFDY %˜WS~Ho:գce9 BKQ*5"-pCf[{wcNqױq,v}}c:vv0OQ?4:[BnNnrk1ni 6D nX_|4SdZ~xUq]w#LcRju V*"f434z,4=BeCuTz:a۰@Dymf<4eB|,Ỹ8YJgiO< 4J;Q9W%Zg~BÝ=6ϳ&܂b3y(GA"Іf4 %UOʜWg 5T5k>m/s`b[HGf= %"7?Z`rpg25=t#𾴲8!_ m鎎u i| ó7~N퍙;z_\ B{c/~*$ҍ8t2I:f7^b `BχWdBKM-e'y lb^hXP._{䴼 wCn'ȧ| qttnVr%NSgP~ry%@X]Sc%~2Y^u|\(yPi61_3Bw]k5i'Hexd|qoA^1Eawr7US|>/q(Rm܁r66'!cezi2@hz_E~JefvAnp&D,xIH(`F~%J=̇ηH}bb&Q=23Mm?|q}Dr04V;CaaTQsđ0إl(i 3h}aqC"(usuܵqG_SsЉn16Y(hQA$n&js;^ls 'W~.7.>u =Ɉg8i',_Q~RVYԘ]-"7!')訁?Eac|~dk"2[Pr06@FCwwt`?56/;EMyUe7zHc[Al-olF. 9$E~JAdoX!$zAJhuz-"aq¡,]Y  ,WjꍲEQ=*tY2drN~PT>!44a8Ȗ . @A:,60`0AD/:+c6n P|5pD=lAW46Q?=0Dz3@i;pH  ǑE %NXE5nG!E$YI)UdK1eΤYM9uOA%ZQI.eSQNZUYnWaŎ%[Yiծe[qΕ ]y_M%7aĉ/F90^/lʡ& Q!:&& 2i $L,t|. RԙÐN8%c}>:ڀ:!7PA61F"dq#<ȉ-^{L6hkNEDE1h;q"O 偍"'hOZ$;n,i+=!RamH2`J.B#7қ[cJnAFd$9&:lAJb@NVB a0D,FS<#t`@hEQ@N܁JDLTCM A 5ѥmGT*ATHX@"##OD WE&[ I+\O-_…:HxhA3@ED2\\#X*@G܏A%f pTqߐC=x7!o:~9\AQaQ &Ҹ :Ёj9fdr@b͉!ɐ}  ɍo0`q#$I5ɒ>D *`l[2hiw!`9m[۶6#@dEc t&䑁.lم.BGfΈ.P ЌF0paD&uw)J1glWuJb'Py0b0 VtCL H@bJoS")rL$I 5!W(I O X " MiGxStR pdcOYDq8k`S$đLnC͕ƱH7Ԝ2i&|)-ATI1*AX˹B߰D*4كo !ފ֑ ^55LZDY$ Q6^A@^99B#P{ (^"lR^YC{iR"d`/dyf #sF5rU 1$0&qQbvЁp 7D|-|a%~8 $G,FG0 r+t\уԦTC#AE-2qL*1oBHEJ1t!r%0$|x@D 8Dm0DJ Zr55Ij35]G(ډ\ #1;9J ҄ 'u"V~AiVHl;:8 *z8F`lx)G6`]Lt3 eS ӕ3b_tAٶD ބ&&Br!4HPƯ-[茧:Vl'+k30!#&8PM꤃9=V9Xȅ ڨ\ P;*ȅ9 : @Z Љ.{3iȢ8rc/>:h0>/jbch6h&(Y%i GxXsٰ8QTs,` $91\`+@x!쨋2 (V؉.08d$Axr< C@J1C HHÒ91ȨBIe C3mq45ēlI,Cj@" D)_sDac 98x"8I o[6LDNOjD؀3؅T>c&wh3`/fK;.xg@3*r·sE~{XD`=h M ۤ`=d6d8'Tȅ(pG ,A( 2! dRȅ&`L͍`Gx{|ˈz gg2g8<]Eggxh^m>3h@5r}n ߓfL5  Ш hTP zn PudC}^(hnfph Y0楨f !dH`9in"Ĕ niiiLiixiijj>jNjnjf j!6, ڋް!, #  P .U 0Z!2d#6g$8j%9s&= > 6n6p8t:x:z=@A@ A C F!H!J!M!!> """#$?$%%%@@BDEGHIJĢMɧM̩OѭPԯPհRڵS޸Sไ*C+F+H,J.L0N/P0O0Q2T3V4X5[g*k+n,q,t-x.{.}016]8^8`7a8a:d;g;h?@DGJ¦MʪNϸTࣂ01234576Ɲ8ȟ8͢9Ѧ9֩:ܮ;H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ʤ$ Xj*ҫ:\H@֯`Rt싏FABҠ`!CdIHGFHx>c @DAH eRK0,,<~'@cBcza$H)CԋVpZ; 3-#CK?yu~hG @Q<N~ԑ<~7( RAsrLPd[\6YdKg[SO=+‚\dCsDwT;ǂa3MA\={B=LDBPxD4cA?yvRxp ^ 7J(w<4(M5tj$'GYIbVQ,^`= .xwG i[D#|SO"R@'t! pG @ =ODjA0$T&t  '>(@g ߽:P-$h@Q> PZw_DHPX5Q`iUX`TX!پS`@03л#P<@رbp|132 @ y*AaG&n` ''a@-4/p9'4"փb+D함.BkPG ,[9dxx @c~ @@ P7}yow%|xF pgphPB`SDhDnP F7 ̔kb! ѓ4( eAwu -A;|)=yPp.M gP1P0z ą`qfl P&hA%CA Rd $A@ :T!x|SD !D~KHYH}_hA F.קX_.`ds  Xb 1(,n@*@H=MBcdyG1yC0B(h BCځw(CN yԊ2*P, HHE!KlGfֳyD#c=Ս"Fvp K@v  zrT ),`a|c1^ :XvX2wHl fp(n[ǁTP8ldXC7Zb8#vY)$UL7",>qA{;P;KR xo I@ 3 -+2v"(@4MhV`&R  @ X= _BЁ D zЄ Q ycF3ly0 {",f>ʃȣ5N;~̐(C <YC@Ńшq@3UA9YAՁg!@ES$ 8*׊; Q V>* sE V RB.Î@m @c!71Cz 2p(n ˪!`܆*}d *2^ <% `;{|G|t-p'+HF1pC$Ri``b @0O7^X▘E`} !E*Rbq=NDx  4Af!)Y֢y4 3/b?İF2t8O +4ް>@r*>yoP@؜? tNժљ\TG8q@4A#8;fw 8hZ"X1P ;2.ƧSZY2ĺ QQV !r3 2SK0+pgdcy\ ^H^-TV _Ţ(F!V/fo\C~р< } ``a0aG=`7 2S+r+S1!A! DEG$7wcuM)0GEBB` LwuIS2P V PvR-vvTU!uFqWwf''ᰅ[Hp5D=$Pr&@p<i&rK$%p7 qG G'H'^[Izq[GVIT0 [qIPP0 |Rm֑@}`~1 %9"H0 F> Qy~Z PO8O@7O X3 q 2b @3"UDt%8'KF"K$\0IO5wa! *B2Y1WՠLH5 gP#rga3#`0 `gHk(& mh!nFm7w P ^ JOYjP {W$qHftjp[t7_ P q %JX0`4VnxK`$ F)>x>IWim# Tǀcb@G P@OaPOl!@]*GerD!KD 9 '3"% "HvVfvb )Ci i3.( qf$S1KM"xRpR8Ro')yrВ/ P<!yze} $E0G6L销iDfyH zX|{ 1a@:8%p  0)KV;nrCLbKƳ Q=h_Q~Ғi.¸ qQ P6OO =IV 1Uq0aa,PP08/7!Lv >S8c@Ecp1H3|P4 :AHPC !ps b)Ue $DI kUQo0"#8j=-  `d-1%pY MI9 1k+ R9Ja0@[Ukjŀ  +d!aOw,j 1 >^qq}Fc_ ;^[R' O|0S Pa P  #! p W  y \ IPEa t` !rA"!R"A kg` !-c ;prvR941XTEp $4U2"B* @ 0D0(ѰA.k`` G`g#P=0 kaևit zdܰ  ZS ŠM 0 t \ V$ ib_qF SQ' *Qijanrh&%= #mP ܴ (`O r{bM !  (Wab /Щt p!h1 B  ke!K2 PgA v@eAR9w@COV ȘVs X4A$bɻ0%"jJP£ = -[}A{ ܠIh[ݠl9ƀ ްQĀؐ (z:np/qm LBT-q-]>2!2@d  ?-Tx5Rv1aI'. 97]9<6Qp˷R CQ}X>au^`b=d]f}hjlnpr=t]v}xz-׀ ؇ׄ]؆}؈Jْؐ֋ֱٜٚ-m٘٢=ڤ]/ٍڦڬڮ]تڴ]۶ڱJ}ۼ۾ ٹ}ٿ=]y܎mʽ̍Ƚ=}؝Aay0=]!]=߽>^} ^ >t~`"~$&~'#,!*, 2 !!%*.248" $)(.%#(%,(+13-2:72:3" !(*. +32!;%#!$!)%.) ;3,;2!"#&&(&((++,..0 =5.005!?234788:;<9C:"E>>@#D&L'P)T+[!C;.d/h0g1k4s6{8}COKXUff{$KA&QF'UI(YL*]P?@@+cT.kZ/p^0m]0p_0tb2xe4}iA'C(L,@6D9I=N -K> R .V 0\"3d#6g$8h$7k%9t&=v(>x'?x(?J(XW.h}(@NA SE!VH![J"`O$dR$iV%mY&q\&t^(zc(CCDFFHFHHJKKNNPNPPRSTVWXWXXZZ[__`^``bbcfghghhkkloopopprrswxx{{|nq {j5u9~~9<>< > 5m7p7r8t;|@A@ A D F!H!I!M!!>!#?$$%@@BCGILȦOҭPԮPձR۵S޸Sใ*C+F,H-J.M0O0P/P0O1R4Yg*j+n,q,t-x.{/}06]8a;h?@EERܹTៀ012234566ŝ8ȟ7Ȟ8̢8Ѧ9Ԩ:ܮ;H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*y#PݟX6}0 }Jٳh !u,&! )/Dx=8oǐm<=뾴"KYe†7{1>YM;d,L0BC9"I pp{O5gP;Ë9yP>ש[oFALj'ƽv?`: q=σd= t<#σ 2iG WP O}> Cy, F8!r_sf #"8Ă:O>`k9D<]  /#! f8ޟXe\9O ?z8J\vP=V "[H"ZOzE{ Ģie>ޤr=02G@*+r&6>@5:̅hWiR/NR(LxDS@TiX?ۇx}"AH{"⯁0 1f>_8.*$yqAkE/!J@<9B#&7iU{@ ?Xp$# R/~[`QvO Դ v_WC$LD,H_d!BrJ1(iA0H$yjnd3?)PLn (TRr?o6f0|i zzyў+L !$[e@: 8ȦFIDHÇD!) 1~LY󨄓'DܳihDj_\2/Ui0{yK=`\ ut-/ԩ5A^T/S>JҐe.b}Yͪ L[řm +^(" r~G#9|9N0-!Rp뮹DrãTK\"AdPDcA)@1 ҺerKbdp3wXWc 2 ^줗UAFX/AnZo1.\҂Q_A5HS4X\$ hAȐH>8" u$",0ɚ=wq!b6Ń Q=3=}HqBGU=Y Q^q[> --%l<Oǘ !DDV%A\J_WUKV5fDqe1'bZ:Y2Q0g[Ҙδ7N{ӠGMRԨNWVհgMZָε#e-;= kpNmc p H@H;`]go8S@0X Jͅ8t+&x 8`!*xýToܧPX"*1 qb~LdE0)DBA*!|zn\Rz^(؆6Bmlҽ fA#H$҅{cPH`t:$x:Aސf{B SD @t` Z8kHp > Źw@C@~SD/{dܕ(+׼$7D6Z(HG: 81w/{c$qy/{9D7u;f'Վ *HG7DCS Gp`< ^]ܟP<€d"B_ qP 7`  zQq0pz$z Gv{{||u|a{* p$w||a18ӷ:xٷ!"~0~~[Aw ` 䖀wr@Dhyw > w d8; WD 8p( KPL M@7GQ  a?W 0O`61` ϐ+`PA o  ߐ'& w`y `;(w&*8 {(w@P ws |'7r`H{җvaxh6tʐ]΀uԷ"h@} @CP ІE` 0نbh p yh  pf gP1 b0c0 ҀPI1h q:Y hA0~Tu8\&q!n}6wz(zp na< <  =s07w 1s@As  8 pᚯ{x^p8@|+`7{o(u ӈ8̩v{OgQ{ח'v XvgE ({9wٟѷm lA wnA0Xypoxnr zni  "c 0 d)[p .: k0b9 2*cR bQ8  JZ:fy~npy rit9z  ` W{y XyЅQ 0K  M0L xspty @ 0O Pp  7P%Xvπ+Ё G{ڰo+  {Ԙ`&0ù ؉ ѝ+ W`Ɍ *9&p1}0'p P1؂pP3 j !D0 z `w #"q nx }X8!8"'Ji!a0 d0 *2AV0!J2 !n@#[ДC:2n  :zBfpKAV :xɥ䷇kz  D@w yЧU a 7G  و1 I9 : T ׉O  jy {z (@ўbwn}& {9ٗ6 a{ r!{y`W7c'8Qa} q0| @Q x{WFp z) Pan0 nx/ 0 p7, +zMhIqS) N)L : $ @ X I맷wfk| 斄 ls1ǒ~i W 7* <+Ls0ɴ@ S  u IJ@J0j$ + v k'0`@I{tѰuaćt{:ݽۈtش:u+l7جornÉw0l̓8PͅQ1 l C}qn, Qq #,h2G9i0-:J\)jLF0 ` @ њ08.hi"n= 1=q) r_[ڥ1w #+h 0GP1g @xI1X`zv J~ oə7 Ǚ9  Ǯ eA1[{T\'r@1 v,cqu $(Nn C2pANCr҉'G;ߤkVY:80O:: |H[95SO%*0)R?OzPP)S!:ŀSU8flӎ #W o!1Pش5MKp4i9Cpl`ahXH`&]@AQ] YzP":ui&\(@7ԥ= V ^>M@H7S-\n H.Zzx:/ZsPV/\{uRH!;]n}J6W^A¡_(p1 F f>ґct`RL Hq>JI:>CtVtꠄ|b!Iǜaf(8(F%7NrCf`$h%ˉ :lĞ N,9*>0bQD:Х.)HJ!+-K2ಋi1:N`Fe0dk P1KA2 K҂=|,QvYKڡQeJA!"YlJRLePV\VZj #k+fEZ:4_MX[R`\=APdA*8BPd_UBP3a mxCa}C QC$bwh"&QKdb}PbxE,fQh!3, ڋ޼!6, JKLYY[*(@%bc} 9ں2p-/}^)!-, ڋ޼!6, JKLYY[*(@%bc} 9ں2p-/}^)!0, ڋ޼!0, JKLYY[*(@%bc} 9ں2p-/}^)!6, ڋ޼!6, JKLYY[*(@%bc} 9ں2p-/}^)!, ڋ޼! ,,--;;?@DEFHHJQQRYY[bcdllmuuu dh, `p,O-8]7뻞 }1 Y r. y LE(ĮPHoL 0  {]}d|~O.UoM[PAF{!!6,""$=>?>?@IJJYY[deeSIA(8kQ@`(](YN'+кή]i,# /‘:̃JRi92k7+*Qᶦܻ:F!/, ڋ޼!,!"#**,..0345<>>??A@AAGGIIIKQQRYYZfghghhjkltuuxxy #hZ,p찤3-7 U'sEh<È$C'f$&HQ- W:A Ź" DJFr h`mEU#~{"O}/TGu #  S:;ucR9:Mu!!,$$%&((()*66889:BBDLMMYY[``bfghvvw| $`$he@p,#m8]7Á盵WJoTXxD-EQ`0x$WP}~uZthF%[0 ~V ;zM0w6c!!0,d  !"#''(&((*+,..0/00244688::! <v/PI,<7bi8 '@(PlUp8/<ǟFL2BTcL],@N! ,$5'YX#d +`evCpVV@Lm% sň'lAXm馚r ƛkکgx})x!#,S ڋ޼!0, "! %*/238"#%)%"*&-),22-196092# #(* %%,. (/2!;%2;" %!*%.( < <3,70<3 >6!?87@9B"C%K(N'P)T+[!B:#H>.c/h0f0j3s6{8~BODQHULZTfbw$LB&QF'UI(VJ)[M*^P+cT-gX-hW.jZ/p^0n]0sa3xf4}j@'D(J+@6D:H<N -G; K> R .U 0Z!2d#6j%9s&y'?x(?D&SR,bX.j^1q|(@M@ SE!VH"ZJ"`N#cQ$iV%mY&r]&t^(u`'v`({c)STTdeelry{<9<>> > 5m6p9u:x;{<~@A@ B D F H!J!M!!>!"##$?$%%&@ABCEGFHJâLɦMͩNѭPӮPֱRڵS޸Sไ*C+F,H,J/M0Q2S2V4X5Zg*k*o,q,t-x.{/~06]8_7`8a9d;g;hCDIMɬOеSܹTៀ0/1123456š6Ŝ8̢9Ѧ9թ:ܮ;H*\ȰÇ#JHŋ3jȱǏ CIRq(S!B -` %@+b=h m,) U@Dg9p@F6T`? @!((`j63Tx rAHقA30@NeB cY@VTRHTAfSVm @ `s3*Պ $cZݕM_yetQ[-[`fYہW12r1-$.Em 2YH&BhSHoSI 9u+qJ' +W(i5HPb%]rI[N2U%6aϲ!ӫB& T"o D;,p_? ^$BU" ME8'-v:X  a8ԡ!.d.hw6٠T!Q5Ұ @C8?H CɠgT0u0Eqr.E0Ly82:*UiP"ַh"uGHP+;YBG] ]DȨ : 䋫ݖ$@ dp21],>ȣ G[dPcHGf+A$mE2'zO``!% H!%6Ş:w gkGd|SE"~ie@. UW d1[ /!fJzL`Q?$ 1‘@t w *T!"b sV Q 4@ B"CgdA*dd0D!CNWPe!WGm 2(Рuhwt&%?R &:vQEZjq6: Wx0iywx1kt Z1yYw$Fhk$!i@N~gEl&{o2vU[% tY46I# >#N|6^6}w}}nD p= p;`n4~@8Eg  TpX6A"0/h/ )815w@D/1 "$hSP01V3P . 0IKuvAfq]5 ِqknwy$Yyg3h iP$8Zhhx!Ya00izjtZ w`zPUPNG &kx[Vv\8V\6D-kA]461 OA,X%p<6Kn}Pn^>;@t nVFpG AG ^ !bC#qȀ)!*53 H0!qDxx tP  1rt/B@'4Xsh3cEA@ H!J)+ Aw6I )Th6 AG%piG3Y5Tn ОĆ D` HwxlScfG%J#Zbg`3]xF _)|[-i|0>0 雷p0 KPoVQE8[#9`q;X B>a YcW*Ƞ f0YU6 n`VaXd0 Px:>~`uf1\AJ1 í!m\gV 6:Dt-܅ "<`+0=”!{LWU=)*+~`=P`Hj @!0 `0Q "!` R@ )@*/Opjt@sA"70? Q,OtRq\?0:TK!ݱ=@+2QbwQA kD xq i`X`bt+iGetX CA I~&, \~ldȇ 5p ~6ZPz Jb/:ʊ90 I;@E_0b/< ˿(PB6r!xϒԜK*a6P)[bC֬Ŝ!C&1c |a4r: 6 gS qywbjy+cP9Qbz7}AZ+XAY2}8MA >MB=D]F}LHLNPݬxT]V}X=J\^`[d]f}d}l!6,  ڋ޼!0,  STTdee-HA&5ʬ1V^R_nZ{9`H,!0,  ڋ޼!,  STTdee-HA&5ʬ1V^R_nZ{9`H,!, !!! !"''(++-123CCDMMNQQRWWX\]^_``deeiijrrsz{{ $yhne}psm2]7;@ q1GJ(h9!4#UXMDz?g#`@3`8F yg4~^4t#DH"Lo_" jf" "oq{k kSzI.A˃!!, ""#())/00244BCCFHHJKLQRRWXXdeejkkttuxyy 0h , Pp,Gm)]/#Xẖ  XuJIpq@Q~o@Qrj:I in7Ӏ} k}xz`" n:e8<;{hs; !! ,  "&&('))*+,557:;<>?@CCD]^^cddlmmopq $XhBe\p,-8]7뻞4P"tHJ(0P8XG ۜhx\(4">@>@@DEFKLMOPQQQRZ\\deemmnuuvz|| $ih.emp,-8]7뻞o }EGo 522J 4rl4>@@@AFGHGIIJKKPQR[[\__`_``deejkkuuu{{{ $puhvDb^,^0M۷2^FD- -6M܉3CY<tuDK%GCG!!,  #$$'((+,-.00345779=>>BCDHHJSTUZ[[^``deemmnqqryyz mhje h\,ˬK\f# }E1$0LfkJ]8 QlX+BÚ3q- a|-w4"su~"j#pH#DfT#:L% =h@qx@]I}!!,  !")++<<=HIJSSTdde}~~x dAh,PTp,Km)]/뻞/ aЧ <J,q,,P0L12g+U ~CLw6`"iE.{uHEWA; !!,  "$$&((+,,..0/00234688<<>EFFTUUWWXXXY__`cddijksss||} $thVexp,-8]7뻞 }EG,17tbi M>@EFF[\\deellmuvv{|| $hjŖphǹ o4ŦB2l2ϡAI'l #ʆ17a1jEDd"}y{m68s qn#j>" /"$P$wEB9= !!,^  !"**,/0023466878999;ABCIJKQRR\\]__`cddjjkooprsszzz dh,Ptp,Km)]/뻞/ aЗ,0%N4 בY Ά 0ҙgAt.b#~9q-4$d[4 ^`" 2 " OFGIEZAE5 !! , h1 ! %*/238"#%)"!*&-),22-196092# #(*''2!;%2;" %!*%.( < <3,<3!!#''(&((*++..0 >6!?8.00334668688::;8A>>@"C%K(N'P)T+[!B:#H>.c/h0i3s6{8~BODQHULZTfbw$LB(WJ*^P+cT-gX-hW.jZ/p^0n]0sa3xf4}j@'D(J+@6D:H<N -G; K> R .U 0Z!2d#6j%9s&y'?x(?D&SU-f^1q|(@M@ SE!VH"ZJ"`N#cQ$iV%mY&r]&t^(u`'v`({c)BCDFGHFHHJJKOOPOPQRSSWWXWXX[[\__`_``ghhoopoppwxxlry{<9<>> > 5m8s;{@@ B D F H!J!M!!>!##$?$%&@ABCEGFHJâLɦMͩNѭPӮPֱRڵS޸Sไ*C+F,H,J/M0Q2S2V4X5Zg*k*o,q,t-x.{/~06]8_7`8a9d;g;hCDIMɬOеSܹTៀ0/1123456š6Ŝ8̢9Ѧ9թ:ܮ;H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣApZDK9MrJիXjݚS(Ncǂ)~);B Bć;z(`ӦPLJe]w)%q89+6:K: sY" +&]Vx\}N\d"|[vPB #P?>d 랚/L:\>%2&LzM&Z;9߁EFӅDq _8435o Np3Q&-I{Iv=m0-*Ĉ?>P=˅"^zE7;T: ^A)D'^P2!CZb&G_EWTph}ցGpQF!:uԑ:҅-(ІnHbB^QAZb'5_y$D(B5P` C?$z8@t Y{7k(qg@?\9Va9-u+@MATpN\P  ~ AARz:t_+@09 ^xA%1:2xl#{l@2);$m/q,s UJ' WJ;P:`@}VQ6F@ T\PA pE~o5lAl!8L4tt }p 9p z50 @ z :pC|: /  n{AAO]i kޥA(wP381'<${! Ƞ 3 ](PN v@X 2H,@X AЋK< hF!Y;N@5fDf ;9&@!@JA ACHءS%dfIGŽt́R !""BYi8%>C!@"M?s 9$;vLP62k!%@Z d˲O\G!S%$.֐5URq5V7dĠ57RD@60 ZR 50KkTÔ15`YhF$ ABD^pxs A$!2|>ȉG@vI>)ҵ#lCvS /`7aNHH 5y1;9|ABPPK J3܅;R@翄tKTS:Dp0[ $tZы]L@ ,]  8 Q*&  A bXA 8?b`Gx8؁pɸ/C8aM@QF>bHѱΞhCJ,9:t aY%hb>TDaڅ! B@΢C-;piC7H43"C/ INbR($!Xk(!$ "gJbb5l b@gX4g8C02@Dh o2jDF@ @#1&`cp9#e%?H8)0 RHA #`'CX0v"@nMx$(A,F$3Mz0banC ?DbG;EG")y~/xG;MaQiAP}AGkq}Nsk,dut=dU%󊁸Yj/tqbB v!'.xAW{Q 5{ū_qȎ ~_ر1)aY*"k@c .&r\ @8[H.0_~ Ŝc|"X)"P p!rAeHՃn M@~On gCw؇0Oa(>w=A2a>$r]PSuAdMp١%i'@`$-?xiGN*6gT AWyAUVIm0NW 6 Xpnz2` R@ m p#Q Jp+ Q{w0ppq`v sS|0 [K1 \p Z[HEhtZd@7bp&rblh4Z@ÕsGV5Bg*u`Ur px0wAl  6+dGr~6Ć1+T $c.7#Q\`!f 0` pywQL`hwdM|JƄ F p K` 1}A7{@+l=Mp#O`莤{|}MhRPe옏H90`iFJ)_r,!lS u^7B T A 0@oږq` @T B(i@F9 Ve!/,1g8(':dHD E\X_I1Gr*'!_o QE RD4gbt8':G"2чFBP {'(vN"# sh4J́u&kә!M 6Mp H'L(e@K >FX.LDMno@KdW w`NzqzzAzޤi,M OjV׏yfP 0Vp8' 3uHS)1'PEXZitv9b)aId f)i)\C2+b*3r박z9]&0pqrPpXcIt43Us'P SATxul;ک~Xg!b´vcxuW k !8Iw4Qbc0:t\p x0 vWLŝW·zz#j3pO O芮P7zԟ:}@t!~1@>^qŦ+$Dz^ 8p AJ;zF)V$x'LpE˳C:Si g4?ho2[6U:ӧ H a1zrj 't( "MEb!Gz!^: @9~:bA`y x0DaW4c 1be M"` [L ԍR ࣭KkzˮK@j Av SlQNz$;'vfu" %6S$VBvcSf - B0 ߖ  (8n=A&X0D<@ovUWze|Lo1P{2 8c \A5'pѧrPF'1tpEwijZ2?4WDbYy FyC7%a 'eLn 5U! &.* qQ$+x 3(Ig[ dw#6yq  :f= %j5=1O3p}:ٺ QO90@, }|E"\wVu/6;TIF-Q @7FAU@BUNYW@B,FnAp W>ݧC+b[ltT 2%XQE""\[S|PQaXd}„e^LH {1w(!BA4\%0HhC{%>,*$Qȥ$ڏ,IKLK԰ƺJJ \ ,@e'QPU}깾0RsPd]YQt a"`ܮP^ R /px g,=Pc!kC;P @4Op/+@O ` O A5 +IQnDr\n^0 b&p$P^ -&&4QpGD   A2k?+zߧX_l?2zbYO]ISB-6 PjS Q8c@\P`@[zs=qz>/@?/ 7 C;_ 70}pq~ =K/_0T.zaF\o+$XF8A@C%NXEi?CE$YI)UdK1eΤYM9g2g>$ZQI.eSQ"dO_vnWaŎ%[Yiծe[qFMݻ_/fcȑFXd̙5o3ʆ/{&]iԩ=ZkرeϦue׵uۖ'^#gs$^uǧ˝w3o.yْW{C/_}/p@ |O@TpdA#A +(pC;LCCqD@$DSD[tEFk%oqG Ҟ4ȁ!0, $ !"#+,-.00001DFFVVXYY[deemnnoopuuvyyz| Мh,@Tp,K-8]7뉇1*:HlR>@#C%K(O'P)T+[!@7!B:#H>.c0k3r6z8~BMJWO`Wi^rdy$LA'VJ*]P>@@-gW/p^0n]0q_2xeF*P.@6D9I=N -J> R .Y!2f$7t'=M*\U-e]0p|(@f3{L@M@ SE!VH![K"`N#dR$iV%mY&r]'zc(BCDFFHFHHKKLNNPNPPRSTVVXVXXZ[[^^`^``bccffhfhhjkknnpnppsstvvxvxxz{{mrv {k5r9y;~9<>= > 5l8s;{@@ A DD F H!J!M! =!#?$$%@@@BCFJ~ILǥNѭPӮRڵS้+E-K0N/O/P0O1R4Yf)k+n+q,u-x.{.}06^8a;h>?BEFJMɫNЭPҳQٸT01223456Û7̢8Ѧ9թ:ܮ;H*\ȰÇ#JHŋ3jȱǏ CIɓ(S^Q%5bI͛8sɳϟ@z(< ]ʴӧPJJ*w;2կ`ÊKٳgkl)۷pʝKn}%sZ]5` @z X :zCNA:|I2"qNz<мC`5%3۸sb~E| G7/99+%؎z>o /_C Qܹ=FOy:gFyp̀Q<}Ĥp/0?4V ŀs ? &@DUy獸^{Fmh?'4hO"Xqx@/cAE'?xjy \_2?G.z~28lre"WA٣:\.BN;C D?y@ݩVzs@/p"b*@W駠*HМhϪڳ3rNHhs@# ;4 }!bF+R  :Pu9[? $- @w L[N &  |cAVk'-t[@u gO:΋h¥:h[|!iR}"LEMm3u`H=iL 3O2pc?1OS=<נӿ<3 d<p:C Q|$QE&BZX Zp(lddD@0J.#1'M9ق6P9t y60Dq! *GpW.čn,~hG4<'D! g(ӑ6qNO,!8($1"3i, @+Zq \ *8hr"PDDZ U^D؂D0Q!iBAl#Q8Qcc 8`hcu1''N|#@_"?#G$6$Ts$ȁ8HuE5 "F' LT) qA#{2N!h+#$Gl`H$hEXaP*C!9A7`yьnTEBRZ(% цt!jF ‚qh.d+ rĞEp J#L?*idUUlu (M1 1(6!psVQB #d6I,.`TaA" ' m q1 @88kpIA b`tq 6"R"c mKa: )`gò a;0`GJP@ O@ `10 @mmEQ`l0P@̶` Kp' 9 Qq Sa"uSP@c€ P-\@ $S@ ŠPg0 ǠPld%R r!P$ % MS5 ( sq0ƀq'5sP &R1dvqP ŐPJp0@ b 0&e` @u<^iTFXVHjv@Fp~~`G uV a q&m ~ 0xc  pgxvɐ g0xu&wʐ Q7Y tGy`t6pTa O C@+a>\12\"CE->VMPr(!Z!)@ {|Iȧ# YC4-*<;T9wчGkFA jM8ܴ 7~v~?% [iGd$ 160mVlt a gy Q DP UlPp (a('؂P߰ aIF g+&bq!&r@l0K) 9([ R᠙ PKP@K)`JS(`b(sUbpp57*1dj`aDG25ad9 h?~jd5 sNpkEHeAy@mv"P(Yx5gytGif j&o  "wpGyvݸ a 0 "jF-{1<!#A,PcCUBȁ.#)g-bzE!'5Pjv? HF`RkpV+S 0 ue^\ ?I W) X]\5I薁Ɇ@ X&xy1 X)h+Ș P( S0I(k>pp0p"F ` (  rQِabRqrPj@Q -PZX:q޺zoY S)Z8f[!Kjp` [ 'OOO[uSoSPQauQЮ5s݀ 9i eRjHy8Q0K3uG6t կ pad'۔Or5dUNnkuC+`V^GxAyo g01Ä7 +Lgwxm A&2d9z-a:!1Gu@|\U7K8Tl#)=[ \99{D FHWT A ^&V}_A` # I {; Pʬv 6*м> o\фҙa+"լK>Xr S Kv\͠ąqԫP ,Ps!SRuJ[*j; @ 4`P LiVT!OA;GP$) c%pwaPm.K(˟ː (.;` wv:<RlFm|InPɀI , EmP KKht up=zϩ\b`<n ) S) rδZ!r]#&IufGj\O;=P1(w@% Jy>wv.+<(~a ЂΪ Q0$n=}w!1uLI#)Zek\S[QZ\#!1ԡٗ~Xl `Au%~^nZ+ E^[>WGOC[Ƀx QVPP{ PP0 Qn,xnQXl^aV`T Tz zm}'͋rŠmr߰p @(b ĐPM mk۰n`b:ݢ^5Fφd l S_yߛu`bmaS L$ H7Uo$ Ӊʠ (avpwY bP \Y.dhp 6<>tgǿ9  Y0DwA&Ex(33:ov~((<=tw2٧i ;7E-'Q U׮((u-1 l܂+a(.RJpI6[D㺅`ТoQ1ѫ^֐F*8RjѶ2t烨TZpȻCqP8nqm @ֽ 7M|Ac;aPt  qQkoG`.jco*8 R"q0hn9h (,(oqAnFkdQP < . 1 e Y ]r]4(-ԅ,r J2\&-~I:orA =uR 1@G:z< ZʠO lGP:(Q Z \s("*[H\hh !H&bWa gkvb`Vj *,\ ` 2 (I ֥b}k $hhV"=ڐ RآZи xK>7hp! ba 2bvfjf6P#|>Fcp6h犫eiؐVBr n`d{֠zYx`S,"qC!B1`!ijSrcHf=C=f룟=yݦ#,/-!|w}~P$` x@&P d`@FP`-xA fP`=AP#$a MxBP+da ]BP3a mxCP;a}C QC$bxD$&QKdbD!JpzPbE0"xZt<}e聊acxGi9MXYGD&RtG 42$#-yILfR~zAIΑ4f7uXA@vA"6^AP HR7!&)D"&Lr4Td5yMlRdR)?'4T ,D }PTZ*QSS#<{"%hA9Ɣ GB'1=%Fa#;aeO&kZr #3+8- .j !PLbdc(Ԇ`TS6CCg @ 6|)p7 _BE` V|ќ#E\|ڄa!\н#HH2#.XAtl#G8B[sqjdK\st';ZpXF6Dna A0CpO8(\%PwA(+PߣyZ^]tjdEr I!K<aA 0`ߜrc}gFď,vX lx¡2:ɽF0pc8q )pB6+ `Q Q:[  k胢kw:=:$`p7+`@͈ 쑨KŨ8!A 磑(`(:(p" +;!,B 8Bp膂[h5X[.hQ@ykhX/?H8 Y8AhCF7KD;DC?(D@DSU>8C @XP O0\kY h1A8\D,,(0g,X`o4idef<0P <; :Ѓ`$9PHH4ҙ }TpЃ<;@ 䈁`s<AI ط,4! P8<P+ Z8(J\(h \hԸ(8 XB8˂\@E`FKFcC3a`pHÔS1b@qJdDȉ|s x?A2(ɭ)({\(3Z0҃@҃=Ql҅MXf{AYR]4mJ!$A5U p (黄pZHĄx썱KC,[8WzFJUЃxLU@no؆X;m-8FLNIqWqp6@H$p@_^Ԃ 98xoI4ׂ8L>u=yīD[F) }:1:̐#EJ@Y4I[t 'Q@'Y0,=eH/H@+)m4cВ_O]0d-SPS@d|؝11h(5:,<ɪ(`dGQQ#{ 0 'B] <`&+:K^۵mMł7McmCh:0-%R J ,@`TsŅL0G-Z<ڨ˴ނ0Z^Ѝ$h)T@5SHh K߃78W|$h8hV5HA=biã; 1cDXNq=mx{-?nU:kjjc:P01P6ubQ"k% w[++1-&)<1>1Y]F;NlZ-c'ep@N%N 48Hh. s@`3m^[[9@`'{Xm5*.@ ;[mAm:0efp^JQ0io !1XI ^U:p6P=A(Ȅ*,"hg|΀?[@w޲ڨ Rgsޟh`o @`e4THL>69` hm89:8q5tWH V4ka`n2.riji&Q:ycPwst*^N8J@b6$05^0e>ZX>PE@^.[H*A[z+d3 : [ ȹX ݆Ho:U&A 8# pP^'!X[8S8G^ w}W y_`pD.@W(q+sqmwaxߏc!7 yW..^j&q 鿓5H,ri>fXqn7??@nkQhsϑ]')t2x(1FJ/0F{l03-eZFX%8|K(||,* 0fbx*s %"NHH8q#hErPLB <$IAW#]yWeD#/3b(M”3A2 A\HFj { an24K޸sH=1 G%r ~$ؚ#4:0aLjYKd"1.uBsiq)[A^eBCxa'Z8H#2-1D<DΛHyf$-@n1[Zh᥁̀K@D I ?':Pʴ["s$':iNSAN@,OQ$7WYD!dZbdTA@8($IPn%jNW+%2+pxUN@Z?B!7SY(pY r4NHWf™, "aŠ8&4cEXe)d0wc.SEdz%i}p8@#oߤ ho BBt @Hc04d@{a CF , q1@b@ )@eD91. ]hWbD81MZ8119P.YZ!q^w# ed! -dy 5R:W_3r$ @x4fp޹C}i/tAhsԨ>; @j\cu\#9&c3~6-iSGms6-q>7ӭu~7-yӻ7}7.?838#.S83s8C.򑓼&?9S򕳼.9c.ӼND$r>9Ѓ.*#z>N:g~1A=qA;Ps^gxՠI YIb[n: !:b `@0hw=䑔i Əvܠ Ρ|`w.ճ^ӅNdWY wG;oMY;L\G0A쀇{Rw L+wgHs^kdJg@Hv  CR]Δ^@zsqM V@"<@mMJUi+-rpA/@yȀ @ ԀrĞԤL(R  @ @(1 M' !w!`iΰ!!@VSw4!< ,(Z*@(W> D^x|@!$N踡%^"&6iGE!4a= fG- n! D. }b&/5 PZ\L Ό&*?qhM@G#a ?b ic$C. 09F9bocA _؀=#AHl!==.% 5b6>MC A57#%B :#Gv$&cAtm `!ΣxRJ@_,*7Ax!ߣG82`NzPeGD Hb pC [&W6ae~&hR #&M^j&kk&lƦl&m֦m&nn.:o2@q ܀B=[AENTgXͱ hTR!'\ LA%C&HAqH$@0@(l²Fp'P…`$|(P4LNhxB(|$d[Ab<)@H.Ӽ́1A1uOYM.(60ٱ1HY1hϭ`@,PRF \9A<@$<}[  hԨcEF\XGP_K$((Bab2 (~(ȍ8E0(,i;9gAA|HG86N8U0JKM PT5ixN܋@_ Zbպ@j@jD{H eiAZiZ @' > ȃ $F( Ѹ@,.'{=B+(]jLQOGGE ōbjo6 pAPձ8 Fw*Ы}YiˆUj$ڞ Ā kk!+A(kZ0l`XHR @Ȉvkᔓ˃gژވBW`A&`t@A pmF&`<D\&XD@DbF8@dȭ7 A41D K LC@p Oͪ@TD 1AC0P ΏŠJA.VQ|,*-4ys $h/gdh@@@.Ax@p`hpF2WLTQ./An!CA4 >>M=^vdcTX@CgFT<B DZ? 4GlѥF0R̀pcW1A(SUmH (t `kȚA1%|~ j %F|oa Z $`@`+hG )H@(f v ++iϝ6 `82 N79J8 GÞpL J8|AawvwAT @O LU@P59)ApZŧ6 <4XP,' @0FF\E[s(xBR쪴4ieF\2 @,lD=Dh4F2܋d DDFo pvRT!kAlo VeȠK4@XGRl?" 0]=/ u4Wb:A|\,6 D$:SH&N Hg 0=Ғq(\p ,P@6-.P@@sS'ĸ++pɵ_b<",k/*6E@1h6qm3nNA BE 9qe*p3B) j'tR5ibC Bq14*qS HN:S7XYd cڴy-ZgضmK"m܂DyZ1IԤGDPC c$%ŔDZ AI@|-"ܯ#-3ײ-P`/arrt_ˀUm~LBطyf) q%-YaET5D)|}a鉱v7h{[H@:s曇Xo!耮>,Bx:!.ƎX BK @D ,hT  ayzG3Gzh@&Ǟy <CԣZG+ePDkŸLO$+QXhx Q1{MDaQ!%?s(+͂f.N(MLls(pi%.ʡ@SMpe/ON8Bڧ QaƑ+J--hmdLR8!fjY(iap'f(-Arxޘ^.D؅ XL[pe#m|N?^zegWHհƷf/0H1 Hx@\Ѓ#bG ڈL!MiP0haɸ jb,caXHv#+!Mjxd*TX%Q R)f<1OxT=$bB؜r,QiHV!F$G_S,+BLl;KZAuA!fmav5gߑA@+}_X\FG:RaP8 mlRH`(j͒ 7 gB䲋!. Dl@WE[tEA'>BhBRvf *.j QϚ.Ҿ(Iw\KK8aO@rL;BhC"eD+C8O?KPU6T!lKhRUv(kzOj(&5@c?+l@" OTKTCPSRt=jBˁUh;p`0+FTX2SuL!. pZ(zVv ZUA+xBX\]Y/2D+VVb0A^y\i5Xa<`aYJ! .xDZT D=j~S$-=vadVeWeiUJg".Aaƒb^/<c;+z/bD ˈD_[klggAJ#?rjx^f=@+h ""DUl6pqnq>q>owA@ W?tsn67e J>vkvowsWwww{wxWxxxyWyyyzWzzz{W{#`k3-v^w{ח}g]l,-hG֬}XvKa =RѢTAx+؂ybgD'Kg5# #hJQ O<^ av : !c : Ub (؄XUGgl_q6Bg*MjV8-/v&ZvfgXx9S/BΦ֎wXW~y g`BB!W؁lClȬ!F@|Fa~(8Q5@>"=BF/zYAY%Ciz/C(5Yb+v@@ChufC5g'DB:a֢1ZWуYk6lL>͠?!sNOnas6.+⨢lۚx:WTQB=Y37c՛ AB@W$ح';wjhᲿ7. C<ի b &KmAc>( {=$vDY:XCl㠩V:V;. z=1-1-j9Qmo;HBعpqFF8- kFSVAhr,aoD!W:`b aa A~L0b`t{ȃ\ȇȋȏɓ\ɗɛɟʣ\ʧʫʯˋu>#1?2Q0|4'@*$A ~n!x $: b2j\%[ TOTJPg- |d'B=@ Iv: D= 1  `֡BR>-@82vt|)sf+ށNGI!/C/&1"ptCXmd,EAL\KNI, JX0- 槻hx\4OfA QlyA!L!Ia1i]Ȓ&ӌ2"$5_G%ۯ$F2-kG"1-&nd 0hodܝүM- . !v n ŠdGU` @ iG!R ^.Z  1h;~,?^2qsrW={bgТG +>!Dx/ `^Ȿ `n_޽ Z * `+ _!. l2hOxgb ڠ h}!R ܠ G Zx~'5,XԿ] Y$>K ė$-`A,2ׯ.Z̰xP/:A%$kW`L_1aK4`5OӎA.oT?s覛s!|VӎH09[No9{AL?Vݭ/m'*v gILgC}TwO '|" @Lڳ͂ )QHUP!)TxIh".ނ"Pr T!"tXDAJC Av *R.Bp1Œ0n8)!mFیGL~l~Y6t@8bM4fA(,$fAFr3hBs 5P6^Pp0YAAk'ɂ8ż>~ T)PhE  i$Pi9B Y!-ߙDa~1^bW(010!Y-,ȯ~3(YR 1/P2p(# !C`l/_It  @Ūp} r@a|8H0yaɻaΨc?iX>Cc8 ȑBe;)7sa@(S0H ȱ 7ǜtRJb0=BƓ3)N$A3I M,6;A0Lժ H0[L.Vo8.j0A Ap[ ` D1`dG(7 X.y9q`#aT‘-8, hG0o*ģh .`*AO֣A Y$)}IizLN+ Uh B4xl;B ԉLhF5 ZV Z2adtK&"xKR iZG,!`D]po_-BhKk A"FUm> ?j(zd^,nGB bxɺT%],%Lr LbU.ĺe7.a2])@综%wd€ fm w&8-SMǮUۦ` [p.Y  q[ 0=f#h( pԢlCSX%TT$K G|i䩉g.()RM*Tb̡oKaTb g6ȀU 2hM{ԧ^Cj2=Ah@(k{i`s$ H@C$6v g+ ^/"ĈZlAxUX`WZc_N"jҜQlok֦ ./o#xt 'GD^q]€Zρ Jj^1`#7_qVqrGPr*e_Oc5X usB5EgG ItM#uIPo ]u9gn2v)`mwv܃ &pgrgdPww dY A)`3&(cuH{Rrb Wg rn&U'hiL \ '?#ziFq*m !DL4gLX4G*Gs|yU!@CakkY%-"P+6+ HY0eDF$E`~5p8KX1/anb@/QX 12]Hhxܥ2a2'-E@:34p+AV=E+?1;Ӂq5)sTPOfaDGZ `.v}$a1!!"49MO@0O #1vQ:E&'Kk=@ aT3t=w 0=P3PBj9 q`?GjL" mg: E"I— P$@uN2="ۓ<$uyU00;rDť;̓%<郘$eh sQr; T# sP)~:Qa1QGKH4`E@`AvrG`qX*bʐ nj +}ɒ g07T2j2J`k21@PJ5".` 512@SKJ[\4vkB A]]K2 k*73/4b<+:*74Biؑ1~> 0a;h B =+!` b :Ha% T@ "N? 7K}O8@TtlPm4t0M=1.@؆mTjdMס `j1'ڧکګڭ1qʯM۵80.l۽ۿ -MmǍ c. -Mm׍٭=v`m -Mm .Nn .Nn #!3pU)>OM "NUIa1];Ml~0(]GsC/wO~/@Un]ꀮ//0)N )#W^t@0:onn\0r)6a10z0rzf.v>+Q{-ɜ̟ݤڦn|>}/05@@~/`rtt0 Iw@k2laC>J~n{G/@I  ^G, a[ C:⿝. 13~>N\ G8=ά@Alz2^02~Q߮LHLÁ071̾@^05g]\/^a j2@^/.0.@S@0୍!"0Ǒ&P2ڙmHꐽaRsb.px.+.01ίBZ/ Jw[!į2qN/>b NH)7!Q4~`DI%:ɎnfH碄ʇ6q<ƩzNEBI+Krpcѣ )!#!`jM#htRT,(36S0v ҨH(D(eM+|كWk7K7YRy+;Km|:@.z!!R; R# RGk(#uh℮ZбR=/6}]*ddOF9e2<;uTkn&ƌ@waQ&]Gz#|̣Nx@$isa΃)E3$hhx !5ĆX6L<;bN#%]DIfArӜMeӃY%!-n*| <>|+dF,e>Ij;<\V>ZD*jSqy]A ÉHn` أ0d'N%ji\PDTgf"^aS<>HP 5U"GfdqdXzDy JcM m{s,Bpe==[R,ebi;͜_l aX%aHЍ/i:U&uDmjUkC`VuJQ"Uv3#X[y-{ԡ?5SSc`Ƶ! M".Y_u M&p 60,*J%nk[4uh؇4RU|! :ړ1*9]fA8DbEF\6K0"k&|$ueB@0T 6}0Dυ[#@$M)+[#Y)lr79jռf6˄㫕 Rv;?B4F!K4L{'"{[2#*<~6֙]JW*e&Uwc_[ɏeȟ14e`L &v06:A0ɝFDf“0J/!!R,M7*Lud<šUj_lɍfkog_$TJ8r3#H)m/n'4rCH\<\e"x692ȃ}@(蹡.=Ar4K@IN"~'za2ɽ>eU+I򠎀ƚOk}Q:T4?".M r؁F-TĆ|ք$X':\ѿfo7IfBI4sUŜ.a?=#=h11hÆIkM!ƙAusbZriMh":#u8s;C;C `WOzux<;U<S8sD{9 t6ȳc z@.j.¬(;pH.>r`:sE@!8Jk t2Ø;Uk/P ٓ# Ejyӈoza뀺z r#!Bӈ3=KQ=ðh븫+74 QuKsTykik1SA h)8@[?̣67SʇcW< tI3^D>HhCЃqr< z=렃֡=sF:aԃ/Z~CHAEDc2GCˈ)D;rj ܁sԈ;: GF=Ȱݸ=(" C(He;ȃ8$0tDGD@ ~t8:?8 D/=0@)JIQd, s;QI2Ǎ{ȉāQIʨ j;ЦCH@0P|{ Ȫ?@A%BUM@qjăԪ:/B&Os:`̘؁ߐ:FCETUU}M8 =<8uPԹpB&Ph _܈ZdUeVuÁ9 ETb>OS(QamJ83:duevE'gQkݍVHiTQr TӒ du׃E؄0s?CA8DI9Rrؓ9;0s y-9vq@5( u-%S: تd背UF|`B&%D; r(z,AWh(Zs";s0Tط[C ЃTGJ5Y|F zmݍA9 rV!\c>+HU|\p\[EJɇ ɐT Ǻp Cwº0Đā r40 C:("0\ sQ8Ȼĝ:RvHA s 1B "G rQ$ś/ѐ\_ܵ S6YP%q-.15.^踩bm ]*LtqPWj=241>ȶiY5K]-4,SIҎQ&H *: ˈvލ8;WaK;T>:aHW8Bbsm$7 !rj7.Q>Sq S ,@ΩF I|PO9Vyccֲ٨ex\@`0 D*ǰFl*f M⌰*HpId01zORfv^ҫZBh xi= RAç^ f*Ƙ yD^2QS\VzIV1bX"~.u~Xw͜rpЍغ׺ T +?KeR2m[~u{؏-J޲iQڀ#q2 t6ab:!鸖kT2~ȉjAȌ 2OD! ޡ慎kjF>6 rpE! :Ʒx:Ǝ`mke"ɥߐBrhhx~@*6yRJPA`DsȎfI#J-*ˇvp }ˆj}hivY^>jy@> ,PDD/ ,qD3N [ 6(0$GbuSe4X͡8s,d@B@n$j8j48kX:8\F)Qnpo}& C @tVОi7(([7DB3:$P@IJ@.>X 8>2۸ͯ"aziKw+6x  š iLNKBD!C‰B4t Rtg%c BzEA, B  2js Bh,K%\hJ}R 7EH~@jT@!RL'Bd?" ` YQAxU,ç 5-"GDB I…+ R ;*Ȓ2`LkÚ-)H!\*bPK֦l8OnT64saa0n,$UMehdOoy;}cTLfMcPBo;ɡ Ui= )CP6U-5kVc]*VH(~*KHo&~IhI2  ' a02 r\t!eȽt!a kH . 3]aGr Ub m3<Ӆ8Q{c$5ldBF WHU=YƱT%(p K .2!5(w-^h$6ѓ 6[dWU[dsUn =8THNЗ!.m#uMtƱ / L$n<3q ܍͡5镠Av5+ $*"Rx eOէtnI+1D+e y$ (!|B e +ТBʅ/s!\^H̵B~#h"$S vD摈87H ԰Vb$IVkFy$(!q#)DHH3 rfZ pvW B3\1SRfmB 49!{JtnG/n$ j_)ĊxJYaβ\8!Xں8"2d F/3A4! (-T(~ӣ޾AD풔@`b`ȸst?X|̵ A #Cp/z)A.EKٷ1rsxk{ BЃQJ!Z?ycUʕ,RAL #^. ]AU)A`M9`a`]I,ABUݔJAeCZD42ulq8DbiʮpEC]CXJ0J/8 ZuDpIvBxCD\`hA|uAXHDȀ\^L.L =GB˿KA CDH4,%NVC>DD ?\ܷ$L-DT[R*Clw]Ib@+D4[[VH@.`9 ,$]&jt'- 9 ZAܠ8l \.N =j JH88i`NA@>] X 12g5M`W-jы0YHYʍ~՞ - #2BdKC˃-D X @ BG͋"J)XeQD> 0Q!!bYjL(PZn'OTYRBOw˴$C,Z'πQ(UʍD)P`A[X@[e(-\]@-YP+B-` aP)6,|&.Deҕc) 1t@f88`ʞ1g$@gLZtAb$$0JAN8@dC!C͠AR5g ;qRDgg`CEJAĉ=YC`KX$%|BK~x[_AQहa2 P*/A1 K$RR:S6D.E4"II!@A:PAcvvⳄ‘+2t]v'-.D_v R\0-*.+꡶EB1eVɐH*j I`P& g >p|C02J1n C6 1$iK`D{CDn|C:58xBt8 ʲ|duSApY^F8 VI֡C@A8\_dK܍NR߉5%KEe CAApeŌZ,sX(B&xjǪU,ʶUxɮl)lhDD@Ae`lXaIB$- 6dATF"lv`xmAv BzF u۪A@ޮ-D VJNrv.c-Эh)! 0m沭& nfޒ-3A|rFE`Fxl9횬ZɮHGA|,D(j|f@V @ XA)X^H,$o6$xLoop p#p+3p;CpKSp[cpksp{pp p p p p p#pBL2 LO qD'Sqǯ=D"D C!D@ED$lqXA[qaC?p1Dx1Cj3L9159 p;S3\K5CU@V[ XW W5@aOl9Pu[CAP3 sW9d6S'BG$=pe#@bOh Lq DX2\bBABif'p7'~5ChJ?t"?Wo%B?X@D2"u2u`{xqw7;7L@\P*7#vc$x<@ GB<{7`rOaxAԀQ\7T!Csmw B×p|Oxqx7K6?DB4B2!OLFuL|i%O U+[7Zwz;C=7"SP}:wձ!!s @Lc2r_A<9Hx3CG5 6|u> zS ]3\o'z6K +: X2Wu^W6Eu[[LA@ak9Cqv~/D(:@cXFT:P5E8/v/ĆD<\_;ȑr;mA|u5g:{gAAp%"3!S F39v_8?|8cC0?Az3A@Jse+ d|cOX?|ī3!DCG@aS 9dz%3İ7Ã8l3,ߘ7DDz2@;'/|P;D=/7D 8{7Dw<_ʇ\w|؋+=vOCuC0s%;4wK7}:sz':y#:U: :U? tPy##?A7ޫ|߳C8!>:HwCT<7!;ywmc>CP'{S1{AH=3ut' (j@0o^ j$s?}F$S.ztbI'QTeJ1^HD3>/1`_ЁF5=x=&31*:FodA]A|CTk CJh񀡜W3ߺ8dvlK˗1gּsgϟA=tiӧQw(A6tC~nbH7Q &zD]_ckzPlk~̚av@۷!pNA1}>ѹr諒vm`*"ꮫzfmڑ6 7ߢ!1`h9 XlaQi1Df;YDiC8 xbP28YfIx9.JǼJaD"I YYc6ad!1 1IYRI(RD`K0уL̄$5L8":䰃吋t(3GOCԁAQU$Xxȹ#WH$>=kVmo Wq-sMWumwWy{W}X .NXn!X)1X9AYI.QNYY6P``l x.ve塻= TbNDD.Z f( d#VlM IX 3 hmZ@IDE,pB(p!m7"6>Cq9XвgXX\7/[ 8:HqqPiqX" zޟY~r.6&fj@B{xH>Zz%ȓ ;o* ZFqa3دpM3[~Ӵ_.2b\S8wC B"Q܌4EE%eb?v%P "E| ( `E!OEz0< 8`lIEqEd{@{7ExgXsos807?A m88āor7Ԡ8c@ ٗ")hC@AmPAIX@}}B];J𪓬F- c4C GH%p&pxٌ ,`xiDd"C&1\p ^R> TrjBA AT dH:3 tg0Z8oQ~1MkxFqdH ^n`Dɿ`+_7ʾ*h0r)8B$,iKHpq)FQqEmNʅ+x O<轃$A#TJ0d%C ""0 #0I ,!%(AF5"%CDP@axEİR5H,Ġ}_vC''iC@Jѡt Se]P[ؠ;Pk 50.^Qq} U If$'En5 (p-2S{&J!oHj[D!x{-v/ -:PtA2 ,D" $Í@Kptao 8]9 pac4_d}&hDOS2\8Q  NAql9|qFiFSA=MC"oᥞEU!"Xƣ HuA^"iO/c }4pGG`Hd)iipkPc%I;|IuSȈC9G^nœ8$/C1(G=9 AT;6K t/bݒ  0B;.V .c"&.\!p ="P”J m`-RN~#$x&iƪJ @!` #H( {["0#p>`:l>nQ3k .a5W+4+ .L$j6 T1" n}Zɀ" }H,b}:!"N` Ő!$ %?$aH#ܯ$ќt%&&Sa JARaW*b !.fb#-V'΁!ޢN)%! D aO&|&`N]5LA$P F-")!W mxx2$ Z ~rp';F`5!P5\4UWI fVnA4eS}P 8wuNu=S~$ "")g1[7 aVVpM3-v`b!HϪFxli.b!3#@"ktr ""o:  .mNZv%anrZ*b"u'4( $() 8"VT[SY" lTfQgGaVGҬ48"82 `YB#94Z4F脎%"OjVMU„k2Å# h"i2mn֓8i,n/";B-%-Kp/xDL.DYq# CT9o\p pv5/ "n/(H5q%Je1f5Xu !!rGK8":-t!\M/@\8%$- r -% hZ!^\XM.|x;%g YV pzG0*[HZ"r.RB$]O NoN Ng,hrLͦ׷?Јڽ"༆>~Y2Qr!-J!MDHђa`R J*\!z?r԰DTſ(O)8e;xjc/e;bǯvCOyPVP(xàwy2kǯ`pE6BX "DHp ~ebmdE} @A!Zba 3 Q@!4L .*^N!@ `QB[ ^]:Ҭc5"*Ii"L[J(@,%& xG1C2g r˟O_IϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&@ēHXfc - @@&_ Dy<\ @wV(^D$ K i,TBf́ lm`) 'jpŁ q-2NU6 Y=C^d}Y Y (Yّ"{A Ke zPXނv38»ܔf i3r8́jsmA،BjS BƌFGsFB(3Lj!b d F-./jȞ' dB]E&RS0[1U LHK$iɂd2h,P)pɅ @`>#@>}q^@7F1"d o#;.#WolfAX8p ~I8ꆩ݈(fqvi(O50G5Yngd3G>^$Ę,1lԜY8s cB!FO#!8e(C ] e`@H.lj_H2lA1] `HFr "eL!#h  նO!恑T`h { kRv1͞R*a'9x{ bO:f$AD\OW{D%,X C:rpSP0pP=0aWсuvWa4Dbq[ !rAd 6I 4rh- 93<]& ;AxDGB?'D A "J  ]FWu@uu058pfHj`v_.(ys`w[04b0A$v ـKڠ-`dQ7qyV>/OH+ڠ % .g{g0XWGOc a{Cc -)0 8 ` l!l-+ g@5ŕujAd[ٗsgQU`k;1P1i˰~pT R aSj PS`k C V M P -o?(Vmmg`6D*N,  1ND|01[PZ`pДN)Łra$#}[_1\w|&f 'p$]btaEs^ೈHtXv@^_(X(0 0m1DJ [.- D CL7D*0L$0DV06p08PVVd/ cL1)xerM !{ !/H jՐU;r,0'c}Gp|QrBPrF; gUPSPiC-S1 bB"y+S$Z Sw_Q0F9vUFV&)E u9U _mkeS) h_z1 USȐ[F P Pv0 (p F6z #z 6./0o P.0 ڭV8y' s7 m@:P` ՠ=WGg(R? & pz!B|hYI6 bבTj.UA11Tc .?uk$! 6:1kB52g> O]BY:K.϶ЀT[^!IqPU`5'`KqdZRz5@oe~\hT'ŧ1-ZhWF B(' jd&@J P| YCғ{ HЙ@9JˉK!"8OY XD+ @Q7 /j`1`A a KTEx0/0LUƍ3LI'֟kM;f\# 9 nB|QC&ʱWUW;AZSB7˰T }QUː .01um0,`n%oG IK;E;Tc9a3[o o\C|0QtJXVaI9=5o̷x-<[yT^A8'4G;FqYVg68Hǜi||^fKHI 1]k!0`}g7Ri @ʿ+y2Mbz ) {J/k {{{"LމLK$  bbAcl`1 'aQ1E.\.jQU<[( S"|a l @raaW "; !Q G|xRDC!W၇@ ݦFzqj04l$ CC& A'5g,)|EC2+-=0G]04XM&E F<`J@X@ 幗vv,@xwwj@>2ݰ,ݰa"q)L\. Ä [@ߐf ˨ 0-@N(̸G ),ڠ7 K°_P hb| ' ,H+#< A ԡP<$.%03 YS \C ` z%2mQEh5@t,nDpu[:2nP8X`5e!"8wPuoyX4> Eo8`}\'?CN^iuX-B׸*g*W R,}*_ H䅈r^_ A{8VPwr1mg`w792Y90Pe)K-L$*$yI8=890P Ta0zmܸK‹F|2B<`|y1s,{&[/2dL.ZrР;2TyR5K1 t'ʟ}*DQ'Υ[nGp9I_&\aĉk$bȑ%O (ogСE&]iԩUޘ^Amܹuo?ϸ<•/gsѥO F Եowŏ'_yկg{ϧ_}p@=A(pAtd3+B 3B CqDK<MTqE[4E]qFkFsqGñG r~$H$T3#tI(I)$rK.~sL2E>TsM68~ѣM:>8k;A+i2$@'r&9@`tI{V>{`r0MGg8sB=矃JDg,x=.Y&e`^X8矎#D|hgNjs窧jꦭƺAxl%l曰3@h*.ī%rCydǐviGs!`:̱DڙrrY7' ghD r򙍜Ü: D,sڗ' :ƟG@PY*A쐈r@/l#G3i29m6`JB5s 3!0:f_;;GuX8( !DqylÏ8[-K!;K((vѽjg @CG*KGqE8ǿRfSwBLtGl(1R_?j:`L`$DQx$dm(m[Lz^sCDi>GEUㄵ$-<֙A^NJҳC\7B) g:jGl0QC+4ZLs'P©!2-0R`pKJ"D6rg'+ hk,Bj; {Zڷ6oZ+"qk}-Eai(12-d,Ext =^t )cIX%\B߫`3fD}]f0Ƕ-Un r8T>L{ǃm:KY%[LJLDhVk>iw$ ,;ez: t۩TQ 3;ѸD`Fՙ 145QXjN6l4{̄ })?q2ߵMkubzkb)͕߄0ԛ&ĝNfژOvp@i?|09J뷘 9=([¢{8N8ҸX!9CƩ;;;A16H:qE3!B#168yP0yy ۉ:R80sfb--p~xIY ¡.rp#@03ȋ=hbBSxpj+0D7 sO w;DЃZӪOs >#Z=( *ZK6; 0V,Ɉbuhh읋*®p{v =pCޫ3( BJ73HrC48$t\ #2 QcB:i +:H⇝p|y)@Y4Z|Lq KC s.KJ4O+I@EQ1Ps)9-tCP{8 ̍0KܗL<Ä@WusMڜMAL͔( F˃HI;4]lHLFs@IRˈ: M7!3F][pהʏ2+Yx|O?-O<Ѓoq*aIݜΫ|(W :ـ3Yu4qqAA8C){rXMEeRlEP|Hq@JK wʭ:0CNīL)̛)Yh2X9ˋHIbѹ\(p5CQ\N{4+bT+(DȬ99>;G͌dS0tý|EĩiTMhŹSÇTN98{ڈ@̵BJRp\fVŜ7idU{zQ ?lN; p:C| :=|2=pDM:ܶ#qF70I" #*@lUƂxTL*㴓l58s1:4VsAʳCʈ}%}v'5 (=B̸L$Ԉ,MC4Y/DJh=il<Dž)أq'P)sAy !I-b;W|*97Z m|ڿcTtLOu@0PQ%ZS])KCKEÄU\ȏxDը03Dž>p,{@ sxG,!GTŌ9y<??#I刦ҵ6<6MEwMU|ϡZ- 9P()lAs7JԃJA0V'8»R14{ ʳ*~\[1Ĉ,ॽ/D@ܴ|*CC]ܹ:I+|X{|p]y 9-@;<;"X !h4H>ČA;4S99 y>%DV 4ս #,;8a3c癚\5ęF Chb!U*FIib8 8n&w8Ae:nӝ7{ 1ݎ` %3)-Ol=BM|`h!^'^#Й)wޒ(6_c<ՏX_BU[ulCC6fH郇hsiXtҚ2[R ,``$'̠Ve] X3 6:ȃ =jh(7(N87N{ӕՃکR6hn\y4SY+De LE0zZRZDŢ(j=^zک9U9(y8QXWS<{ZKS PZꊁ49T,+]IOlYgfР"k^Cb^Amew=#* ̦ʲN̯ *E.m0읂q1Ҽ#~0 ٩Q8 %ۦ {0j8#CHZ<0 +rR292k?mЫΝj&[·DhBHOD`xPA"=uyIgK2K|7|yB DD@C8|HB=3ĀDh(OsH!vј rjx8 / (N;@X8I 䢉u%W|p9s=:=Or>tM K+R)q5A@1 pP=yM\$'_cC" ?B(D0 %`X:p;sҏ8drM)?9KG@tt\`vu`WsHLGuru0 9*tĢ,C§踙pBp >9D(G]`ZxD(":o:Ht/BtMx:Txh>AH9~#ZaIwxY単20 IX8sXWe0(NX Ljg / z :' ' e*h 8Aydɱ' ψ p {vѸ䶍8w8(g ف0 7 Ͽ}}}}}~0 Oo=@׈h'~GxNx, d ꯖhR `xCh{05踮{(h „ 2l!Ĉ'Rh"ƌ7r#Ȑ"G,)?{&WtB~ƀ6g(#wXM韺 m)ԨRRj*֦(U*ѧ p=XGtB2 myPƨE̙L@v .<lz̠ZA"|qN1pT#FA58878]LGX9ҧSn4mLA 5 /'ߜ' w&7h0?F^wT81@OueCB%4_w$wOO"ɤMPN8q5C_<~rJ-=#A 9I)%b;y!!uDw];.7 2 wXIAw!s tx<3W6CLyq=MSDMύN PO-i@ď z"D2rNz^IA69]N|D+ ;, iw-T@@) "{?]9T>iv)Av?#,|N]~D+)ig+ NY 8|,֐Z%|2)ғ yp q?Ё{Ӌ- 3yTn[P ?OB.r\æEHBD6?1'reB ;Gb-p++8;8C}!N @PT)vtALgЇ2vA;#?;/TPO1tM>AWιjdOg":K6@9髿>I^?/d?躣CYb"J^:Nw3B&7@%|h3 @#'Q ib=v x"ddg1 {GClBr9 J~l::#'^'!FH .h/CnB!BDD[L $W +ԓ΁Շ')d\lx1e1ʫ7bxD83MrR) o>Z+t3A0ť (!ӓ|Tp{RsB<)HPSd7fI!tL8YD[PA{6oG<6)M񇨒=UV3#x90ɘռ`!Ye[N |+=.r"D:֡Rֽ.vyv.x+񒷼=/zӫ}/|+ҷ/~/,Xn`sMd&]DMǝ!`MCx}DM 6š^4܍= .􇽀]ȳ!)y +f GBC ‹H!E>QNX&.a.JQN`bOEy/bxZC,Bl ]=c0TIO:PnCa3Ά,Cل=,$BP8êEĖ@c,\ Q b); PMb@j_>]3)<$= -Pl@DJO %ye0@UĬ`+ċX٥AHI<Wζx"d^:װ" *͇߂0 Y %!mfA O}L`Ea@nIH^Z&x&tǂD WlN (VLTaD*e<>ިnxb?L?"?FIf:D_Ʉ_ʄ|H>XDܥ%yDf~?ìQ,YH(Ap* foLŋ[qGW*QLeNJC" `>%cb%M^]LA&@T29ڐƈ(<@vM 5&HNG%PiA)4W.v\P0E) F*nDUM AjuJbDN ΐCf)CP&y:DnjD(ÇU2ӐV`flYFѣQ߈c>2Mfi pbԀRfBSj)D4UNg-&ڼ?=lLB 渕I1JRLTCkt!ge͹,ϺXPw鑮Xe6\B܄N(&)i@($CJ]9܈&TO5||aM5!9= uf.J @?ytr (L\nb$e ij`\̀ BǒS.DR|nGY ,F`F"y6l[dM0͠^A++mC빬vN DBҫAlQz*D *oBdJ Q':liBD¬ ށ5oMR>)em@欭APCaPB!(<+-HO $B+t POQ-mY U#\"0g?<.Ȣ[Qs=e^~V#3}>D3;Haz,}KԒ4Z?MCs4o pJIR-ԬPV5}2.C|K'=,MTyuD# qҢ9ptJP4^C q~ t`TYM4ߔ7b LA0s?BtaO te/gWmQ-eA׵a8`|o+m&ĉTen?>8d-ަLh$d'G`̔NXM@O'DV rjXWt{]/RCˋA$;03/P݁͢M8ˇ+hDG w0C\9 0R󉩜]BMU׎}\ ,ڀ!#M @ W@@H yCFMϒOOR_=?#fDqjB'"DDxC%B=#ynb|N)@"^OD7)Ly'޿AKt썜0xT"G 5H|qqP<0(pQUk:6.󘎋>]ݎ>#PwN;8p9_uPJ1IQ%/#Fȸ) z> :AK}B/J aW\Z4A3BHj>Y6)RR>D"PFa(tm& @qd1? t!Ɖ<  C=ԙO$G2 '򙁢HjQ@+oYjG*7 C%mQM,S:T+nsZ\9rr Ԓ lj*Ps;;g>КF˃P1K@ênF@v Ѫ3H05Cu${$2`pN"Oӻmr()h‘P@~N1הh3 z Jn0CCDR:u SK $,X" d:( R(CmSICjF_C.Y^{ Z{L3|Uz<ȱZǖL.;Bsc)'=C$HĨgf`n@BC=A1 {ҹ^ ͐ersa_[`q&GRsFHۯ<(ҿr#?rڦg'(Cp$)YIK^&9IO~(I YMk^J,Mo~]|Q YNs> Nw\ZgYm(/" 2P>TD)ZQ"F9Q8ң!HT)UJYR1LiZS9NySAPZTIURT>QTZU^YVU~aXZViUZVq\ZWy^W` [XUbX>d)[Y^69)f9St=lhIG@w@0DỵmDppG;q(ruC_V {#/!1r_wwA9o2߂@}x/9]Ou:ǜz+'hp!A0"pa]nt'B _Z/9s4Duky~(Crut@%f1Jċ^u!1jP$]\xT36RGNGA*c.tG"ZJ~H|pL ?q7tGZ=\֩. Ri$G{iΐx&|3예f2ݢ(4u^[fXMsd3(y&ASJK;{\X?8sjԡeYtYyPۑ̎g26SAGR9Id^fq:Oj2DTa$j] |Jr~Ltrs\n)<|1SNToXU]\0KˎBYirOia{#w,X&aIb!1eA:@!XOwk@~ fJa 1JM#f D!3s@L5E˘R 9CdI煉E}=g0WZmReJPx / +yA XzS (ޒiD"CzY7 zv zE֦P`"8y_<%=Cşd#ϱ%!IR'D%St"Hm=U 'RE&E!!b/c/)c$3@& RlCrm% 1#ա E}:va^$ohbc&5\T j@ v&\@!P;EaC"`#'e)-7bѼcCe@@Ev.VL@}M$*Jn#Fg  d9 +JJ!%fvR.W;s.jaiƳ<KbUNْjfBPpEYLBʄ3Bw:Q#-, MR1E2҃FMhG FBV.ҨàcW cS%BSMMK]3S.EDPLaj4=QbU$.wĠ[MِO |$BNJAƆ B#Ghr~ԚT+~&/)` ڡX ~DA|MjQ0ƴ@cƾ<!d;v#`VaQuq'f]2rakc;,c[ ab$ rMacb'd`'ȁe%A`M&aHH'eObG#6#(i=wR X.lu¶\;i][D 'r+"T؁0l'F 6bC7c!pEA9N(Aԃd`-a$-ۡ%`&3wB.8HsIss}#tGnJWxeqmITWHDTx7%B:@3(MQb}il}UH1zWF ,` \$`jX/L +(pB~/3X7H1k|;X$GaS؅ïkeiE_c$B;}i׆jkp$jx q`!~x:*'v$ʃx fk'$&X&Tؔx)WoN?jƇeAZF0#)d@XG9gV "ܴ$&k7gvK!vFDw"l~%>`#uirs\EDZ@i4#TU4:"@3F:tfS-Cfb8|m)v`$XHX[0 g&T N+I! 0x3G6p G$a7"8%Oz?t1.0afbtma aUR蕫;,l$pE``&HEҡ oœUՙjJ63#AOj<ʭ젒\0$,O9͘}"҉ҷn Wb8Bs"C{&*a8kģ/s]p—+LĢ!)BdWՁ1U$B?b9:ЁDun#6ZKC$c+ڵ % ?7mf&vm *)b(NFg/p쁜{󅚃wh3M_ϣ#\FH ^xKh-jߓ?_B՘!3,= ڋް!6,= MNOuvv#>@#C%K(O'P)T+[!C;.c0j3s6z8~AMIWVg^qdy$LB'UI*^P>@@+cT-fX.kZ/p^0m]0p^1tb2xf4|i@'D)J+P.@6C9H=M -J> Q .U 0["2c#6f$8k%9s&=v(=x'?x(>@%MH(VU-g_1s|(@b2wL@M@ SE!VH"[K"`N#dR$iV%mY&mZ(q\&s](u`'v`({c(BCDFFHFHHJKLNNPNPPWWX^^`^``fggnnpnppwwxmqx u zj5t9{<~~79<>= > 5m6p7r8q8t9x;|@A CD F!H!J!M!!>!##?$$%@@CFI~IKǥNѭOհPӮQڴSใ)C+F,H-K0N/O/P0O1S4Yg)j*n+q,u-x.{.}016]8a;g>ADFKǭOүPԴR۸S0234566ŝ8Ȟ8̢8ѥ9ը:ܮ; `A*\ȰÇ#Jhċ3jȱǏ CIɓ(S\ɲ˗0cRE3E̛ Tuʥ 6VXBtH&TŀRTpPxԇ&T8}ʵׯ`!$,xq ȳi`;r  BABC2:G Leڡt\)" Ĺ3g e`Q62pe4>FJuVtut+P|S tBޒ'NR7f>v>4CB1& 0×cd!¤! m`F0œ1@Za5Ԍ!? m@F0oo1/`!ڢ" ^v$A",hI?JQDh  `B`8!l`C AB@` ,0YJ8 (Ad9°CM6PIM41NH5 aCXƨSE BY + dF#(VLXH2CA@'TH+^0Dzĝ.<;^֑QH I]۶bt#QA|D`@R8`8%Ėc:s$pQGCdല.-0 XۮWBsdnH†oL"&#@$`'dž!.`,I& _DdD@pQn@ 500T@ ЈU@iS?$b?B(u jP+PPA`AGV~tRfe>hS2Q`}쑈0d Bl(.PlhC@R6McIDLA29NdX1 Q@ꨴ'ܑ E&` ^4@_Dm",“uk Pi` GP0qHmhF4lYbc+;1Ic]ѯ'vk&rr4䠸iA`:"nv`p8.@~1 D+x8@xX `XްgH!$!2@-XvBU!`&BȖw2AxL"J,@ e0B ad#(1bQa|a@|N"GP'kAYPHQbh qtİBj`!#e/y`  ԀXl B 4 >H* / =W`a>1pf@(1aA((PّL<]9 6 9pVBC΁`3S<;6x=B4 KBu-hnuK#,5:Uc C޵aXt$KA@ DZ1 Y!T%.HA+#V?yĆC&,TQWUB gy%"AAm}E c O&Y d0 Z. 2"f!B r a!.e OP3 +$K\67H] ut6WIM8tP bX 9"sp t T^lw>R\5g'\Ml*~p9$$'`d $vdO%`;IJvq,9!%'aK0ygcK1aے  zX!:a :*BP""n3a p yArp d |o>0| Đ !Ehvb̧ }U QwRdpڅ]P AB1fCpBUԀnJtCA (O X sYE ;%iFbroăZ/bZsZ%%]0#U0psr[;7%QZ| q7G]Vv MM@M1fyq#X9=$q$gPi>lU" yb}#^xx_r$7.KL 8 ) *D`!1h3e'r pcz"#*\) *%HXQU 0!ɷg'E @?+e "j g`' z5T0$m/0 a/aC~ 24( a(@E~"J#ѓ/%!D G)I3(8*iR; 'r1"'=-Z94`6wyIv酫Q ѦMsJaug \cb|@9B:XLb'\:ńad;L!M Q9#tP&)YNpb`dƩ76! ]!!I 8)f*( qqD0"p4xjPp~Ph g03:f Q gQU f0S ࡱp{ 5*BT]5C,hK5W":< 1 >9@I3FP1P6#s\yX&sEF. dО q"IPrrz lhH!ŧk J {Z@Ԗ aHT7y) N @ @d^9m3bu:*@ (Vw  ! 5,J}gӲ9bǂ3&ǩd 5 m`* EОfU !^2*'*V|J|JRag}! |7S#ic0Qᡯ0;Uk nU''W]a HEGTG  ?)2hO q)=Ȍ Y A)."1 q"Y,#O[S#G;#3qIJu4Vsu)9"1QDPU]])uu3V"-液s9ߤ83K\cic텷`cv!$# ;qR8*PMMZGNb.F$. q-1F<<<0eq5 qs抟7@Ǽ2UWf :b?L=<'SgP @\Ƽ2/DbqC~U, A@mÿ@+W,60(;I[CőW`!1@ F&XMh !(PEeAZ Z8!] !-'-PGP uYG 5@PG@;܅pO ]q] ^] =al#;xȪNm>M- $*p9|#aqKSPi7#s(bx";9\s 0M2`ٙH rٸ *" 0"͚'ФjĎ QqR@ Sڟʫ× ɷ 3a0l0[%RT,6T9T̝]eCNUNt٣T`pAU@e ӽm!DR)2?`m DP#c'fi *B` }< R1 ]G L( ;@0G  p xZj # dIb0vc p9 |0-PѐvSBx# _1 wp^Ƙ֘ -YeMynfn@%N nigP〨=Y9> 0}FA0Пq"D@p  {QZП9|\? f0P _ R^@|`蝑ZD, ApD~NE"iͭ/ѝ6 -O: P:A >-BقkP!O/%'g.ƭܪ-(<5/77);@22 ?HJ1;PR?T_VXZ\^`b?d_fhjlnpr?t_vxz|~?__ @m U0Z1\=,`0?_#Q@"H1Qk__3 >~-˿ !VA4 6me9'dTUA`5'<LE>~3H`5nG!E$YI)UdK1eΤYM9ut9?xj"hD7@jѼ,|&Dp#{Ԯ@08Tj&j'4_A<&\aĉ/fc(JUFJ.a RpFXzJ͗/aڹE%g|'^qɕ/uA@7fΈFô&ԝZ9_!ݿzi#Wf}|,m3P3H 4npDK4DSTq'i H X /7roʋsO>OLgj.Pn3 <`<7JK"D5TTSUuUqqP-1ĐfunIl H*(@ YH~!I'Y9e[pw>%PK 뫟kt BdX4/k. dL(|S#wavalbX316@Xs߄ZdZ@(K5zcN1t8 `hVzivizjjzkk{l6lV{mvm{nn@J! 7HQeqIo IX\Sv P Щj00PA.@$8q[vd?J}Ёr~ 2TOeHJQ BL0~qS 0 `@i `' ghX"cѨK. $8taCF1fDxF9F P/@DF 08NƠT41 <'yD a!`V| %cFм #>PE*8RP#KT1PQG\.# ")@}:a-9`MHvC,aM`H4y;##dFT=BF0ƙAg$j đ!&&:+WDc&pqО1y S,n A,Th$bFVITfؾB# Ad!ȒF$44ر~}&ɐ2%LMWR&pl˙@ Lz`"f(1UČe&Gʆ8`C)0ʄ aq?EU!9%!=) 75D/Y&4 ajQ *hdU`-@A@Xq6 \C d`m6>C0:A2G8t42XHv$ Q?@#*8m83Vϟ  gِ\r&?D (ckۅ ѽmBg ?ٌ:1#U!?*Q!@ #)B&0-'1I 2$F2N4a$CdhH! kT#+BFFPadyC p !5D\,Ð%G;tgw ɍ1y$ )#LؠNɍy+[&2#^0f*db/)Ȍ =,^vHzDoHTŒBɳˡ"#?1& I#&X$W/~ ^dD{50XECp Zz qgC.]ڎEF`'$8BY5$|;pI>@6! =h. f>u 0!\d"a9;x]BjFC$m"E # dc^A\ᅨsRO{8`8 >_CrJCQ1i71y0.w3HO8H拣H6 KgI e4=#hn'PCC ue8!K:ǰ?H" dH*-@ċ9ȈPd+Ovċ 63 *֒4)C$+ -vYBgz#H ~=UrtC^/>NO^jEUdR#I^h ~5 `@샧vov]U#F-FDŽ_uCHoXvPupPS,/hxS-2:ʪsK{0|((Z$h$O /~Cʃ8?=`sXKZ;s7K LPTJ(2f .$s 9"8L@5K؈W"4)/u"J:h3 X,k 0#C:3Hx>lX1(k`38-@1bĄ k`ExY0E HP )Ek@(x ~ 8@ FkpG4OaP8Έ hғ]2 0 jHTeR%!H64/sO3>*йT 4l]2YN5[KK ,';jk-`H+63^ӿj6j?ࣂg@q$rK$uSR~0@99:fȈ,K̤@2<g7q>:8"4K*!kO RRBT n@IhԆop9)))IgҨ3TH3jGCkk@dDjhؤDp3hXO ˈP:kк;IԴ$ G6$Y@ vL}! PyM__y0Xw@=X)injǜځ(k J#ҹKX`TkWR; `BICɆ`W۲*NHb&]]x5QH<җ@$H'M @$9Prh tHxˠRLt7 d캃Kt(ӒK$g角 ?MxKnK?D!s6(S%\8"L)\Ügs$v`URHQHs"4㫽JȌS8T&y*,DP:ML΄djHl1͌kVg5ձ1W\:$N$$h E (( vH ͘O0#lء0PxE4׵(  xL (oiE&B4U)9 QUЄx"̐XKHp@5*AQ @]>m]0I`]󻵌I$ZVZ _0JHt(6v i̠9 Ai;`p`:TPm®6eI\ƪ,m s:@A꣌\U~Sap"^Uކ0ZU!^!Wh3L$N #sڄQe[hdb{6)ЈYsIQ&5'6 YYh(6v0 s܄ӷ|cBe<%2IZ zʄ8wktꏠ 䍀4'v8E^T ,7H}ԕ.K[,D\-8I@>fXʳe<늒Luz]戼Dk5 lBX݌ >2\ ވhR"*y!`'iZ-0e[1Mb#N,X+2@uXmK]fߓx%H^'gPɇ#$ۡF|@@BW뮔 @0o vyP`|膠bАP}=ʼ;T5x"niZXW-_(*WxߵQ_I5`༄`?YXj 0c¶].x[dL$HBu.8IR-@M@#ވ8>(>HO]T.z'usXN$Bg2*xP3jRTލ$p*=^F pV%fOjk:Tuڜuވ[/ m{p`X'Ieϖ!.yְk@xgrWXG`vWfErƊ;wQCc?K72M0x宅R@R)URY~\B „.I%S0D(GUrt8 J[n]QJ]@DOnuP(tP(QU&6 'T"EzU Qyf !gw.ܝ:Ϻ$D,Y>_T?;0|TBbO/c[|1C1Gd%|2ʹp( r,$3 5' H.$@, hs22ц"C,y@ l u]{5׀1Bv6 > $ 'Z*w'`vGjmC8ҕte+ c(`͠hLv!X;BI"Ow Qؚ=no - K#`ӝDŇ5$D"Nzlw쮆=-hH" )HI ~3 ?{Yv Dc Q gsd шQ$*SJC. m!t$@G% $LVciRPY% `3d@M =N&r '# HbKU#%#1NT@xb"T7U&Lw^MZM"YOBI♼Pg| Lw@<-餢DћH# 09D`iC,c3"ĜJ*BFDx8$6r@hXeBsD!X*,:"e(.B B C0Ԃ@h>ZB$B8DX)#0]:DRENdF~Ƌ@:8 XJ wnXfΙC@0CIuP N9WȤ3 ZuC:V <VZIvG\P"Dq tب h\@ꅎYخ*l͉ tZ D@ ,f= XX:5G#h hBh=ff'C,D(GV$G\dBƋ@33)!D H$!˝8_8| 9$IrWBpEnF4!@ؤC)B,@%XP@hIAO*G*f8u6\r7eU8i1\ x$R}̉d "V fajC|.gZlr:D6,ZmaB&CBL*l,O!'G @ M<@EZT @  IR((L,B HBŜDcFcЦG4:^>ܿyar0(08mRXBD:@ٮ ?q`h9"k@#DvF3蚐jyn̽XЕƬ.$\Y Y.,X{8(e, ٕ)oBY.[C@C Z%l/5S7DcCqmBݛ@Uqђqe!T! 0d0pBa?nrD0s'Dq܀,\4F1]% ,p 2b=0NILDPGpMD9BVBE;$QV= vDJ sG@qOLZBƜB !`)fDžrY̪Ңq '؊BmޞتmcB(d!B_RnUF%1A3('Ü$ْE./G\6i6[8WO:p%9%vie),*3Jk8.sh Ĭ3kHes;w6|7耯2-ISKc9xws,\kGl!"f:=o5$ 45\!}\C䷁sBlCs5̇CX5 qD*ς@FpG0ѼtqHE m oz`PoѴK;$|@ H( Þ?t Rw*Ħٜ !-Ge uDW]-XsqT@`1X 5I-0p@-DF-r`]BVh$;*\1CueBB96Yeo*I> uIRgrGvG蚥 0w Ybjog%EMJ67ߵmvt ͒BeDy79#(,q73+=Ϸ5Bx DAz&B4Z{wD~R{‡q(D6gx H7 q,O|94wl @txHMB1yXghO T؜hC<*ۥ@|Y*pJ:mRo9ɟ (@tA- DC6C#sDC3%w! ,az-@=vQ 6Tr {B:GP:nW%1vm:p'G$z6~ռCP8ۂ}5#eZew=7}+BkO;{fr>C2hoba5a΂qޫq~ [7Rz( )uވ׏W??G4 9@>?K;R~8HAHaBU|c&L⒪SAHF!)na*B&rTTR)@J*+좢^W P~! 0`40@`hOj*Pt1. wi5XfJx֍*ɱ3qӱc8vX, 90ϝ=6]+ıfq]ʱcf6ؙ3X؋٭j]9*;Nq*6#l(Ú -R6ȂF2Tƚ`Q F "fjE140|gFY"hD!XH~Ȑ1 gM^,j@^|Sx|:牴7aAfJ@4@f@V"RTa@%&V!0RP(M%Dś&"Ur0ZT)(+ _`D٨|¢`%_|k`ˢNBL+0l2n:Hͺc ^L?3erPhʺN ͢Ppsn7[genc9/=/kvh^ᾟ̘WB(vhZLRۺUiZh,`#eFJ& iQ &ōl\ b1aTm|y}Q!U 7u}LcPrA+>m%YV]M_ M5YeL0|X}`!"yUч`"@Ё`C,Ld$@>! +e#x E@ d)[Y^f9Y~hI[ZӞUjYZ׾li[[Xe *+p["Jzh~5t[]YZIMϽx[^/PP{U-|[߲S= AZje`@4`#ϋԀ)bS DI\.᫣ AMX bǏ"+D $z Nw3d'd3F^ЫԎ-#^P x.p Ԕa 1!{SRָm@߱P-;*i˙t[ lZi\s~o燬d<A-Z;k/ygqU'I)l q;@#É(@ڽvܜJk+9ȤF-DiYz׿i_{y{_|W|?ї_۠l;+ <3<ɭ_~tR gۨBlauV_ 7m'4\*/Op1$ 0TȘeT.`@S2T77"f@  @Ȍl#'vk`e߄Vg#U`Rބ܄ӂ keQ8juW^0phaͭwnNHE EzV*QiC0*O SJxLNY{f Ɩ02B7VF@-k(x E bnQNTԄVep ꄻ$/ˏ d9o Qp,V<UTV9RPzg~N~뼑dQ2@| RjL ! tőw!S tޤj ݑ" D-Mr>$Q*O [QWmw@$MPg$'".XP#EVJҷQLrpEwF0d|w|(2|Rq#FEPpQ%IQwpGQ0ؒ϶Rp,sl б$Ni|@2S%Tr$o 30!QM`G k%ߐA1$O\ o1r! !mvg^*4.-v&@lMO,Bu`u4Rzs u9߳>k@>Sks# AV0ީ>I:}xCD#e'yE'cdbDžBY+Ja/awK(Ƃ'-ZMy0}#c|1>d㊳ckbfe: =69g~":@~C9!`V 6C#W ߭5\ЁV-=1|(]%9I (I_&MDp`TuB@]%Bj"|9]@FI̠p jd9[% G,"K{jU"t H2zG¿"D @0֟@3]QTO0oMG0ā## $4d *03!T sU2 AU&AT] JЇ*R?T A:v !5SP'  .!حVq"A_SZ$d żcx  5#py 9v&c'q#.:vuag69% Ǯ ;%4@ v.OH{`v9+G'"q mmwHBq lLhPaMJ頔_r%*Lt)ɔJ)Eb;\QSAXHX#FDX#X@$3g(CM5H1;CF}`2 iNh%;)RFm0d08"1,I)eK#ѝH4Þ8I02ELl*5hg%]e]T1nKBO`%.܋oU/C5 3jiHh߀eI%p5H8Mw: bN.&Gl54&<SsuЗP\aBtH~ (xѭ,S\GZFgyBTD#EJd#-D ; @ `(*K0+0W(BavQ,F|&aj0BaAH mBF( ǼґD2kf1B\VQw=q+w|JȱַJxA/ -! xQ~2@)Ů]% ZPK13' p QЁ ])@i8q/3ҁx1l3>ava6P:3Zb2aɘ]ԓfY@Lf?cY|լ:@=]f|!hkir7ʄLЗ&WG~QEth zq@PMTsH()7PH\a쉔N`HH-dFYvy.D*K(d#j"i~n$ v1Co~ !}ERKP!BD`HבC `  ? EEp+ 0zD MrQpQP U@QQ H.p pK8` %P S@`Mx R'&  0JP}p}epg ,xu@wq ̰8+ 0Pw "`0 Dx+ H@y! adgrXvzvu Hs] (zOBO0hEB@ GrA0V]3P8h&gĠ €X!H  b 0 I ɀWPQFb<`Б ,`0*ɒoA , @t@Ev000 ᣄ/ )jq3`Zn\j&zAIJ-njd:2|zo/P\J$s(,K/8ZdR: ~ TZC(3 A P꧗q:Z:Eꦨ JJ0@[-\ʭT6:jԺ::CJ(ګZ0NJ j ¨*\jK Zn|٪<4!*cJ(vڲ\a%\"*3498(ɲڗK -4 X0  ,Z0 J= Zp\`R;.qo;+۳ZU2[Aj~:+:mO#pF,*N`[W*[2 !1 \ 01)m3 A⳾C;qo1`)wbBek~y'+/q'((ؓ˔+⓼ A不bu+tZ{b3;ig, !l[8IӖr[ \(,)o{R# Lm;[k#(*V6+ !ÿSrw&Kk!k:ø+צɔ(%ȳ[0}&('+K:\k! An|K*(<6 I'jZa|;}[~|8;[ʨ׾lT;+](n)ro@]o+*ͥߩc<"r}h!\0,;*%:KtN+(+)o'vR|[K *?+0!gZk'q'*>KgL$|bm mBZ;KmI7^͵oٲ-k)St}ν<0mpٌ0qwn~@Y?* 겕 ݷ|)^>ėɀ5.< 0 ʸר^遞_n>.E߹\Ĕs;e:m`R 'į'Q}`=L۞=A+ojMA; EBDeƒ6H|Ԇ{B` ܽߜ(zܞ뫕<pu.dݹ/0*z -XO0}L+P ==”'G;t;[54ѭ_zaW6d%342:īb" )AIB *%~ O 2:8ҭ@Ыj,_*Dq4:)%j%!˻ɦrPC!bo) * )Ü,&FȆ&аS j(@{<;(T >nޫ"ddLU#TSOE5UNʮPhF*;S{$/tD9|d+~g-|J|LԬa+vta a&{(8CXH}Qn&xAjuJَ(8竲+j6G@+G~Ia$Pu+jv<w.z{U1A`X)0wؒ)/=̈́tG'6+oW|4&(\E=Y!`*0q=bט ( ԰?5\B дƳ8%Vڙƺ,.qh,-"鋠gc˨ԟ@97 JmR#<8ؙΎwcK;q%/b›q >L@Ϩ9I3j4Rb  ɳ  ҦCn%.sI(R#%)A Db-/8@0iOi䖼BIQc17UrqT3Wq Kb NҜ3}ќӛ o-{'>X24 6QsBxQ@e?YP5ȏ-GԤAF`㷎O{zAC&zRӰb<ESo\TՒ&44jRQTh<"j%*ժW*_ؐԟϲJATǺVSU1Kt@ u]f֒v2 fIR\ckxElb8y [f|Ulf5:|8f8Ɋ֨lRm:F&kL;[ֶmnu[ַnp;\׸Enr\6׹υnt;]V׺nv]v׻ox;^׼Eozջ^׽/ogw/|$"+Wа c=y}e[t_ Wš:΄pG}tf "ٰĻ-D9equ| -)<–"6v <|o;rl*qF\g ifar],094u6Q9.re?vˇF'yDrp=o2aSCbgvJz&Ge=B*\72;U(ʴhu={d6 VZ{Ґ-,jTW˭r+VM{b=E&V/ǫ`-@O ؙ(TNb7KCq<)$G H)q_ѐά W>Իl'CH7a|fc$GQxyۑ|F"NuC|M TDf2FDf-ɾ3biٳз5CJJJ(YZM#w~IQπ$~jyc"2eMмN\ A4 hPK/MMSy*K==M?h ;S3fPv&kptMG3j"x)- nH4`ߕ%>M4@_@xR m`qIH<͗4<"/> nNL"-)P%_g}jp;ӏ) Z3I ct@2p2P$Q@C4h*?(?5Í$Aa,ᇔxHCY0&ACB%a(˒Iz,B!2?8zP:8Y1"=)A7X8?7J?ӌi:6yi#'<4@k²8 ;*D0CnJ 1dn÷C^qd #79iAC@Lq2B A7,iBC<0HL*Ki̪ a=O\<٢kźh9CnlC Mc {G pA`&HBPG|A H)Eш*pfqa 3 k䤪\Fw`U݈͵ m݃؁b=  U2vܥ[6Y ]oш9S^+f`]fQ0'_^^pSqNf7WYgYPW?`}箝z}XPW/uPv@hPsWs.Hz 6C v WvXCOE~E`Xs0ԇ[0M=N%]ׁ&衾WTao=]Ucpl\h-֠}l5ݕ aadP.ke. dVNP&(Q.5@p 6Sa>XYEe\v ]>UUuڃfbc>5R ]YU]g. ^' `o `'&mSl&(%h k =w (_ fsntXY88YPWuhX9۹hPpXp ԯpahpPPg8P׬C\ov_z.pvH08~Vv( a@(qiO%h`q`qVgU0?$Q:@~SoPjSR nuXeS`2wRpM!82Y!( k8~(1kaD &7؀b ,PYk8 G,a``(E& y^[/S֓`lUslX ElUj*:YbXpmv]Pۮ'w`gn]fVsg8Wq=r> YxfZ Fo> u5pHuosjuT_a_?^q`ixfr9؃&׍0.XvgsyTNp`vR8`z׆orfW_-ҋ؍x]:og M`,jkHj8j x܍Uuk0tuHfLLU8#'S,lH _5.vyme歏n%j,X:}f[``n`hOxƔ*hgwX9nmw`hPGp݈F g[:@UfqnPMZ8Fh0p@.{&P`:v'c0Ba̘9>Gcgbavh針9`؍1I9 OBɅ)]LN9N^m+W!@Te8DU;TrnQRNkWT u*53'Y@5%[8X2e+ Lfڙ,~(ej^a5k"fl'^ѬYHG\g/˯cϮ};2I`T9 DU?T]xYuT) 0Bj"TP 0T0T 0@T0ܒWt0/Xwd;NQ:P=S:cQDPVё3q8A;< d9cI&sNyaIdEAJeINK5 Ď;SEAeQG%uRM:CUVy'^Vxgu}.dWyEI^`E!mUFfFg-$nsRjĘgz6@VY#N1u2K#2#5I3$b⛯''y`r*p*B؇_EoƷQ-6$ 0H =a#BSJ#V0e 0KxḒN % @G ;{,yGv)8SQU#` uXAy5Р@㨟N!SEE-z/|é EI:q*ڷ AveYf`FlcT,k5{E ^h[F 1miP+G8]eC"s:5ީW'0)l N\]ʿ >'ݗBsB@)|$뎈 Vc 10 7@QP$dBERV#xH" vVъV)'l 4`"LA~vc!hH6K\QC +i+JUܤ4vm4YR (ZoIDRb7/`x|p(gApg}yh*:`nXSB໓YـjR2406+@4bXLtB@v/{/@O C@ G*PtQ*Xp^\Lȏ,CBRf.&3p VK€]"r:K&T@'](vqP| -| Vs!/nQ!d 'bQxEUP@E` [8;8‚x 548- x3JpVc80/XG:±T0#\ 940L,& @.bg5KcQVh BƏ@1|c!1zB ?>7^F7={_;DXXo#?Nywsgsͯ+oc;??o?_???o??` `"`*2`:B`JR`Zb`jr`z`U@>Cb\`!. @> ڃ  "  Kb0jE""^; l=E%!V ;C , <؃``X #aEG- Xa^E?(v@Ea b ^ aE S@" !javDb-9!!j":b%J"%Z" !vvv@+*. U j@ S "c2R<B<3I@^blK>T#s<`O `tp :c;6a)JG@;32a3@;^E6C.` ps =#l؀juZ$=v@;chO.ad> 3V $d>B3, hlp[gptgQ`-"y¡DBgEDJ'hb-1$'("hbh@ŀ yFB,iB!!HVx%.k2i3Vg,OS@!# DMbd(+0.Jx+r§uc4k|kE$bZ +"fRl2+fvjctԀS + r<̃ B:F BjJ+it@l瞲lQ+,l#tc[l[b@n,f+ Zc-VŮ*{BT6b3B4Bk>*]R鷲*F &?XbM*kQff.Rڮƺ:bd DlB` f>VE^&@b@$nE?|,sLj#媩 ([(\rc#23Zi>eFۆeh;R:G"$¦}=HhJ^.mnﮩ 8e+m:!@/R:#]k^%B.ilMG"\.O* C;ʋ^1]:30s80(a'@:+ 1 @" ""  bX"@4'>",*b9 @(ir$r* Jp4!<2sH)[$:hrQ2袲(2*" %*" '/؀#3 B* B0"z9s::s;;s<>s??t@ @tAA#tBs @Cw_ @C@)tE[t[`ݾ/垴T]G\AJ_=y IxApUE pbhXB"J[ \BG\œ&T-B *uXwD䈴L?iȁXP9B9Cx^9v_9DuT3I,EVT1^O<P_RbEs,!'F BmT&Y<^h5~;sBU$מpa~WDZĹ@pS/?*tk''.,ȁ@zmȁ@Hȁ[ElI\W@}-DYTqPZElIcIKSuGN} Gh 9;,<:<:X W ÅEB|}@`;v aÅuؙ{np0,hChr. 0ܺu]óPs9Թ'6ߴ9hOT1`IUS0S bjz 馅 >UZeZ2 &w1rZ۰0Y[g^kaB2D,pX[iXe7<7z?E C:_Dh8c3-{4X^h٨";ujՋΧOVog:I%I) 9;z)iCTP.i~PL ;_~b `h `|L^ab!+ .&[* -p`4lhGV 3`C$/eYY:# ։&ujg.@a^s tqƤYa ЈfrqNJ: (.9$kZ38>!=(̩).ʨ!9騡`vvVr:ͅN( .Ie A=UR<hS+r6*cERˌ B kY1 ƚd-68݅>FFXK  ކ"cBd@xL-l!8(8J@+`^@ Pn!xJ`vJc`5@DcIvyarAiسJo,sϡBt@돡hU@{!v[O H=*4o`~`'Q*aZrq vBG]Ėn)q':7Iuʢ 2!A/wbu!;2 %vAzI*Ta9?N9g=>b!Lm 9T!RC>!UCnU<|gc%0Am|(@C0`B 9*-i9$AUYP1沯tY 0XaO60( 0 5f 48dؽC\o0O#0B $ j3 6 7:$g h^8H,7H6{4grylA`m=stt<ޚU`3→ R@*/D 4v="N0D0ƹOΗ6J Q.w7 \Cp9.tw $-G-ڂgs\HFI gĝ뷇l59efkZk5ODhCa@ dن2ӺC1CYLֆ@ VCܐda(JoH c.2 Ðn΢F:t4,b)FL+:,a̦V'?ڲ t띈<ɋkz'j !B"ԅAswd 5gc0Tin!.n]tC0g"b i1mB0N// qoVlP{.yfEE'a]~SEYT>_Eӯ#@e^! /nրPBifct.#BlTA. l.,L'Bp!,f^!Ίc!><ڎni!2(^ոFp4j!t"R9p! o($o! BG$:>Z@T`!,R@ d"AT\}*+v" @v),@z\D>bFPDEXcdFjF~!G f$*IvXabcwF!|2g!^ ~DM T ! e"d P. x"t2eSRxB %@"O2 .NG %R'tx)!T)f B)N<\B,n/p*ÉL ĠL'0,`Zc`!^)̓ Mz" xf⁏hl0&I7`Agd!VjPC:0!0o""n>)UA?ʞB2)Do!c(,$,2rvnAlvH$>z!El!$E0$E@'ERdZ$ER3ER!mI!Qj!mVG @zQH{%I " Bzs'^#MQy jj퍠^O0%=8S'|jؤ)1YX/C XNal.!DǮB -j")uC=b*.n yB+7FCiF<~#8#Z<R-Ԑ8FK wdc!cjt;;Hfc`t`4N>H.ACN,OMHH.aP`4QE2O >4/ Dn0:5b @a l onAO' 8HuTUV/@<Ĩ!!Y)20!)!`M5&e!!\,VZ< Z9+/Ƶ(Tf'aA ab! \ uaҕ!Yiaŵ:⤡Z WT"U bc23N5!B~R N%l@ RNAa" h V! A!i)yvdbr!0*A:h (M a!rao6``!^a !rAK 5A9Tܐ,l}`L F0@I ?hGh{7z lhl3*,%<rK'T&}Wzyk,M|S#eRa瘍M!ynb{?L6j02` 0` ` .` l!ڬUz'ͮOO4s Ov$ a`yLUBasԕx3%1T ҙG;s;meeV1 Z |_n! g{v`%+u~H8$ER@aD`ƀF >€ ` @ JF]a'}r `lB"ƀ !}f`@K(sg 6a8̶3{b*!~^ȠEDa ro!,D Brm 8!E ~ `Gs| `>K,QJw $c١`1a;`${.~3L 1 BA L,"T@~NәYy19/*Za9&`s!ao!*R*|I0A\LIt .( fa֊f-`%3YK&j js10G,Pm25 hMٙ3Ƙk"Li "| V& DgavptQ"{^[փ ؠ\cDH0?'/2^BRHͤjB!ґpGMRDG`"AT]Bx) R5G zt! p_R9u0OY. 0t 0U.0P-A6a0ЇP,rDT)rÎ 㘓N8(3AtP8aPsA&4:+dB*;(y:%$;NΰcΑ&8tЅ8E"d8 ASGhu @\d }LBа3`Vw(;t&d10j7ߴѩT? B>*%)ωwP{*j^"$2A5mAD3!$KQVsDQ20FMȼaG=1eKIu,`n&:fAhͣ`j%4fhin O>,/Af`4=qX$n11m#4@WrQ1\B>`* @;Av@tJwErDȊI&bA 0l8a1-"xЈ% 0t0Wmr'SAmP(Pqj+bDTb6}2GwAs32 D$;wԁ4EVI8e Ό9&d4<d!';Q&;h;P M vUx|$3't B-J*A B*pb> B^ !8:H | !X<2 0| iEAbdA*RH @CsY#% Rl% ;5w,^("bJ(vb( BFx1,ʤb/84^dhul4[< 3ȿ(tыx YŮ!7[z€STTQB(H@Gj0b&ƪ a;UA_b.0P mV8H^i Rҗ0H ^^nKA*w&@sV:$gx 9`MgX.e2/wAN7&ySMG8-olBhHN⃟  P8B$;uBhr& hFA*mң< O;&J&ir R`bbMK(!lȓBBb'EpCPD'QiIOM45br}2Ŋ#  C<qLc౯>fG2q Fv%azH4gTNEUMUy Aye 1Tr%-Q!ڛAzY046)hƨ*P5EW&YIۤCh n˥Þ0|;_%IQBσpPd8h:qpoJ2)ĚFV' (ꉎH ҝTvR## !)xjFB 0 WHh | " {ieXN2DZRƱSHV&, [[փT1~PXūVشN5-"5/@▒R  t0" e/xe$ K+)VH~-`m?m-6-DF,% nt08! `TIP0q+A0AɁ8NӞBˎm;}sS%:t0/]t#šj9ܻ^bB20B&;@҆oxqVl"V*UBLM9 AWK0bnqA<@pZ1*Bѓ,E^")('GJSzjEȝiHSL,!SJFF!1h ?8zeNЊ]{ݝyG h l9E@u84I"dйV A)Zs:Hmk;5V6[/8H`lFH8!3Im! E*bQH9ܭ[GK@MLV:6  Bӡ= S`_)pZp :R r _Z&rhNpag$@NUcaj&U٦  )ozq +I >,\WdIEOu@Bd1Q+!C5Pq9`@Q6ZiELi0Q9pd} &B?-iCh0 o;=ysmF-2| L-اԇ #1&06Z}!3i1ތv 6@-`G sטMddтM1-Mh}׈&tM1L-TkDط؀ؾ4͝܀ 0"u^}*v݂@ϝw1 3M1a Ԋ2]ςaEpIWV4!GP 0Y02YQnp6ptoW8th~.^Al}yWWVtExLWLqy@]qXQFF;YtUht:1Lg/RКϸE!W%NIΉ wF]ΙXgRa|q.hXQxG@]m߶}W5#&%>Ҍb1 TWJz%sbޢ. h<Y.1;N^b۔6Y,2xn8]2;}tZd> 0 qihDV X}wCni0)ZĚups&Ev%ߥ!/5^D h>GzƉ>#{E/ghos4#PpQT@^0Jni^x)h}VqY}4ɕO߽/CjMyEqJVhD sv/=y Eں8]1ehn@\abQ!W QϷyOUwE!h+z*F˙sa/2*ϟӱ!.2XGaiTs%9-`"?˼/FF`п|_޿v [`޿D"?@?2ZdJ$Ґ? b`1bMIm3| ws?TxsR#ڳ, c+Uʏ_;(#@4QĊvoH# eݼwnٳ 6Fr4y&;|vqO0vZ0⪻&Z.y>,5tk(2*nڋ)TK cL"{3äȨRLǔB`5.B3&bJ"{pX 1|FddL": 9 8˨Ƃ n$jj0t6ZJNшhi'ɜk.% 1(^oԎlΈܔͅ܂KG.mjԼP K Ϯdq 9Aߢ ):O0B2`3Ξ4ąrphKs _ԏ;h#m7VΨ?NS3lx,>Z$hw!P'e+U.J-D@$':]:MׅN3=FZ@4\J$|d H3##裪w\zԋm̐{[*1۳`x[/8sAEXkǢ"7*QXD٪Qqo! )V( ƊDgdr; J`N]*t NR)E9=6&xԡx"B:$:o$r$gJ6zfI>RMՈ#kIژQ-ͅTRDI6U-H]3ЯIvhaA11(Y|kAc~~ۼ `BƤ0KpOr6P`\W~vh!$Gk8zDp!0 -,4=Sxv`UDn"!c-0(o#UE=#Jb]`6]^^Gؚv:GaN6-/qy\'#pHY&_쎜E$^'c.$B! +uΌXi`A6q&)բf 1n}1ۙ$?Hʡ9LT*R y5NCq4=G=m8w{_D8eYsZHۖ_jPC.dT]Y& 6AFINrbrkiw m6W\p8k~O$BVPj4AM#&[h=PtΩKPau*+1(W@qE=&˒X65%8 )@l)S?S@ TATB-TC=TDMTE]TFmTG}THTITJTKTLTMTNTOTP UQU<6O8mDȢAUŮrӄܫ$U]U^UsSs"l1u"-әwUiVj`>9=(  ~(DQ'Zsg+VvmWw=T2Sr3duiV9M׎{W XxmvvwDx@(x@y0E"kS;,X X{0|@pSaT/X%xhF,Y Zdb dbv҅hXZeӂ= ׬9VPV<"kr@%*&|šL}M8~8\+LY|@ ܜ ʎZCZ-]5тX kAPyn&e1aY Ays0@Q ^/1ĽyX)=J\;(8 & 8Axӭ__-! Z>{@Cؖ r R<\B(hϸjLq?sm: hPx`n{ ]aa,XqGR1@yQz&ȚxL*"BօUnL/aI!N =he;KaI#c [6pR"~ jnli*+\A_8hhi,1Ƥ efDx ' %#s2p:2.lfem];i–`innUXm~]ħhO1DX=F uRz |xn`yXx4=Ax6}>b7kf FxH~npЩ`U/q?qAYWoqq_Bpˆqqqqqq r!r"/r#?r$Or%_r&or'r(r)o@ pcY)rtr5'x)33aFCp4GV25-oFX{R J@"YQ8S5f ْjTx01U3M c2tNg2HUv:DcNP9U7[Ʌʢ*[o26rEY34qvu7AճI-u}$vFP`.'hV vHU u% 8 }ک_ T w +#@g_vԟ1F}Bn7mTxkA*|ۡ 63 ڝ.cj!9` &sȋ߹U~BЇ wh%xph;7ԁgm$}AHy.,#YVc;k͖NJz& &<2*{$S"z \@`YɇůgXAxԸ+Dh'irm'2iH\||BJ袵Gz;S|ӬE-*_8.4ow;aa09FǫcѹU- Qѿ'fM, 2lІ #"^dD8 s0#*$a|[[ lp?C aп}"|޿ Y$ T 7!PX@eІWhXVJrg)6  C6|1Pg`DFK*0~5^\N M͝SpP>Cd u.RU0Xt: EhL,%!G3zq{ h}3 0y6h0Nqf%2w&_Eƞq9 }Qٔ*O>?u CP҄0\ HqtP=OtIyPw9O[ )vE[KsͰ"i8ugA5wA.)TN~RE2k JzRC67-mE`5`PH>N:b#tՎ) с R"L&-HI?̃u0Tep" Q Ni-+OZĥT K!TIgr65-LY?# 1)KQPUYyU+MoiܢMU&VJˆ SN.>T&JH:xK0F )_iX4yB#Kʮ@BnH GJzҗhBt\a+p؆ GGC^+?-(zSTQ%\1\>|1Q"WJJk6-)/񲉓RY:$:ahFfX"ACU܊Y6i p`v&&>NJr" ~dR*J,Bf 8wH%9qQmjF'9@AWeLG,0=u6unEpkUxfrXLZt4Q4|V1?Z0+fϕJ`! N# "$eWR\!A Ě;@GB:Zt i_DrL~3'(NbFԭSvΦ6Kt8Q.zqMcg,oa9LfuSB`E(:aW"j`ǺRE"D+CT{8Y](FE."`:-&hR X5['[{O}6C̙! h!$#H/! cVk*KfQ_TYdHh3$d*:ÎiN"J$h@ӬzKkvCʧT<0:rAPSAaNlPŒ8JkbRp%!BebYf8⚈6ʔm5bѸqRZ{rPdq}b1y2qN`[ת*.Z!DJ\&o 1eyl;DB  ELJULM**X)fc,4Phg9ow%VLhY8s1If(cFɥ38 f9υh3}Q%nOImK.G_ ̭ϭʫFɠEC\FdBB%w9ز<@$v[,'T['+lrbFHVr>;iDR38ݝL)!&4Q]o LanCv3lA*9]ҍ+6K7CFf}=`b)Z7"hs)i@+j1č?a-bx_s{17O+PPZ*Aqz~\8w1~uTfb79XXaCʮy+oPO\ټ e _Ƅ %DI[MĜ\ X$ Ƣy}Ha:RhD(-q p WI[A 1E]xة UiOhJie7J8pIMl!:0xa t8D̙I|A,{T ͘H1~il@=F>@@d)M19]QID .VVȞŊ N A%EDSuIgZhHH11w$bO ! IoQs oAa1 ,)Iť1lQoԅ2 ECy|Y|̋,RIݐW]H ^" l\!O$%"^LTc%=1!h8YS]<܅_o!DD8OP`¢mFrZrF"| QFL" @ࣨ?CVY y" 2D+_TH!(v<)b*vͼ̃P Jyj"Nl?Hŝ $aURKPtVPF:YHɅZ쨎:"#Y=cMpx$=aŎXxNNX S:k *?P|2fj:|$dD=* 6DkƚݒRDz= \+X렪C&lDȣSJЧJ"+R\CT-)+2H>T@?"  $bʦSqD㫹,E @ȊA cP*Af > t S|ND^ lvO @ ql̚UV4kGY @MAm~ lz p-ApD ,. @ .&..O| >.R+6dlfldl~.膮.閮DCҜ.ln.b $۶...//&./6>/FN/V^/fn/v~/////Ưί&P///0wo^0'/0n60GO0Pgo0#0v0"$ 0 G 0 ǰҤ װ 0+.M00V"1 ϗ'/s21G/%M_1oe1w~1G/#$l11DZ1ױ111  2!!2"'"/2#7#?2$G$O2%W%_2&g&o2'w'2((2))2**2++2,Dz,2-ײ-2..2//20031132'2/3373?34G4O35W5_36g6o37w738Gvg8˘9΀vh;˭D@DJG -O HEIeTR=a _ JG;S ?[,- v 3hi4 `-yG'BcGK |G4C @- DkB7  yTPL rE4Hc(aHk4yd4KTufUa UuR3@L\ W~]t2хFD2i PfߍzslL#, [g XM<, dhS =4FfHEQTYKj˪$ZW=3ZK bk'k8Et eK;R.Yo/xfފ %]yWCd@\IK۲|UI"$&J @tߑ' ˁbeh^_i1bIg\IjuNihDilFɑ(^N~գh1vzIXNNH1 .Yш3#ģ_u7VtKܓ`Vv2% DW<$BCg+sO/p[ꈉGvwq4b݅4J,v!GoIkg@P+:<9RHk'xe̠LI}k$gOS4&jKP}C ٺcwt M3: j=8pdbƥUKͶ?[T[]ZfIvԺ F^ PmaVTBd|y!T  2f?vDyDr(8@ `=Fڽƫjh7C -[~AP~f@8<į F7c`/A5_CBl_<|n84QD%Ό'v+]sCfxHfQ4PP×OUx @Ml9iˢ f'۸cReV-6ۖ/p:φ m$(\Aa!Uh!߅~y5}ujիYvvlٳi׶}[һ5Pϥ5H1p`\ҞL;0fk\/5ߞɒdI=6=>/< yh,&箁^4Ro-0H2&SȨ: KC+ i q#{h9j.53L\(Ep{(*Kʇ-D1h(aIJ,Ծr,*CT!~Qiý^';Zj:| ʹ)G F1(D 1(=b@\?D* 'ԨAcfӐDT!)L-%yz'-E4QPԩ@~ IJy4) 3BDɶǹ8EШ C4jZ' O~vͧ4/|HT9M3H뭮bh(8:&YB/)$֨GkI92vG[X]/A'gh* |Lĸc{"|(bm>@~z|SRlHi:Iw(/-w7slu &I%'x)Ĝ BLԈ̦`^4lgfxߨ ^ !dIPk~a>`†tOCmDž꫏a i:dKt$n9RyX$s7}_`h:2U/!^qBB0P#C*T@y  QXB,Ab)[@4M"rNX:By,Ey5$SzA0HE/~abx!8̉=1'(6ˇ¸!'P?y˙b":kD!>F("JN`?HK^ԤF 1ɕPBˉ"ȏ͆oc(@ĨrdM"&ym4;]0YLcT2Lg>є4YMk^6Mo~8YNsT:Nw HBSj YH*`d) 0FD)jA+u겚)C jOlHuhU1MEr8EHo IMj&Ғmu7r$XtLpT7ʼnNQC!GT/y&u5/uX*M_Il+|♮8xsKʈ[f{ <#dUGbYv<֟k^1^.P)NƈYF˭H'iE ϦV`baw|]:X\y@h ֺAq7Y7$WtMuпr$QVqK2ᇜpUYi ;IrC  !,Y{oZ᷇-b0"`~]-IH%:#K}YK`13薫(uȉ| *jຳtׯv?Zܱ%'m}i1JwF4-dxFdפ0$q᳗%H(rܣ41Q\b1yHEփݯ4ő"gB?B!6.DB>n$qj `&Oٰ}C4iՀĔ7(ਟ`)0D}"ZSS),3ik_[;A Zʂ7N/c7#8(/x\ܴ|> 9VEiN IeZEBT? CuLdz5FM52x%\byj4Ynɇ;\VQa9a i(eHM,Ǚ aC'P7SA6K[{q7-(g "9y1vNsݧ9s:-H GT:Vw\y4XaT LD-wq\/w6iȥs8Q(Ԁ<@2cs7֌=|e# ;ϢuV!ɐ<6~#'yqWɃf/ g62|GO51CJB$eG*Rv1^K^wT^GrAl` 'lZah.`a.)\+<- !p^@S~-r1DKn$bɐ a<"1g B Ģ*n` Хf9F,kvf:FNSjda jʭ%vnxCnޢ ;i<4/hϐϐce,cEQR 8bj\BNd2z2Poq# %ŷ!EJʍ uQ hZ4BS,i#}k\k#`"E_W8[ 5 'jaōa j}BKAC䑰G6RLk롴34Şp#?$CR$G$K$O%SR%W%[%_&c!-, =   $*-249"$#((.%#(%,(-41,072:70:3" #*!&&-. +23!;%" %!)%.( <3,70;2 >69;;7@9B?I;#F?$K#C%K(O(S+[!C:#H>-b/h0f1k3s5y8~@KHTKYVfZl]pf{$LB%QE'SH(VJ)ZM*]Q+bT-fX.l[0n]0p_1sa2xf3}i@'D)K,S/@6D9I=R .U 0["2c#6g$8k%9r&< > 5n6p7r8s8t:x;{=A@ B D F!H!J!M!>!""""#$?$%%&@ABCEFGHIKģLɦMͪNѬPүPձR۵S޸Sใ)C*F,H-J.N0N/P0Q1S3V4X5Zj*n+q,t-x.{/|006]8_8`7a8a9d;g;h??FIMάNѹT112244576Ŝ8Ȟ8̢8Ѧ:թ:ܮ;H*\ȰÇ#JHŋ3jȱǏ CIc9s(SD$H-Ț2ײv̥;y`Û"Eo=w"O/qQ 9`P99 ,Px^i}@z`Zhe~BTE AMDS\ܐC u!6 F, u a#AFud]wV dC:E8QdSyAU}U8$L@+aUQU T V C @UZIVQ("9zˉ)Fo#b 0'tސMH:"=8w G&%CLb@PJV&p|?}9Ƀ IgН +@ @ܐ)@9Pܶw D2#B0.YOX1Ef TV8QAb EU,0ApL Db8N8(pQ w@*\ EtH_@1$ Ѩ@H8ԹPBv3B:PP`6p) ^m㱭#7^4_ah =pBaCC: a8F%h1B`EYTfaAQFat0Pa8s>PQAZ^Z43 Jz;Pg"-AtN8TPR-栐 t/>+ AO,Q a)BA7:P*^ D A,?T8+1hRl#ǤTF#:A1X4,.P ]nPD4$ iwVD! T rUf$J x G8p3I ۨ|q4Sa$|8AQ_h9REy )AjB:c taB>)1 !@@L0ICҢ p)(  )1"H0K,ra!BR 3C Yp@ O,FbbXA0(,d BlH'@ #AMy!e7/LJ˹9A/!@젇m#.0U4J`ڀPGSB6(V+†r k 8V%R|&UŴq; @ -3ֺCpx4`#Fn t@$HI@`hNBSV` *Z{28%i 1 np, ]A `3>)[8+/l2 Ue [lA $AByB eXF)SI30t1FM\"&$АZ>4. YC$JH3 R;&C OB"d,"B?ECO(>Xb,US K) І>mHP p*AD|8@.H8B5qq8nꅘro 6R7 ""A6,de$!!m-wd9xkEDGG pV%H(Y9TV{bM8 XAJ d d<ȱ Z[u. IeuM :..ļzIB ʔ)ITQl$'q+ $7a Csh@RL 3x &G`AXаW Ž`n.q06Cfl/XeE q Hbe`hl?MY$/uʄ_@@:Kk`:@(ʹHA <\8N4"PD L@@ ,L%A(i&>Nyt$^ LT1 hV}H>ؘ! }@?tNT8p|9a@?@`b Ma-PQ1q9" dM*uFI;tBa$ jC##w*HCYY#TE(2FD97FXupE"6u" U!B,`Fy@P" %ZMZejH;)Q$hJ H3 Sf@U<] U^l (plcBmS+[!eP&Ӵ__ue" *u)` AXop0wP`y p 4 `bF( 0 1 &&~b 7cޠ#d R)%" db 1Ew0"PrC:" P*թ5Xd #p RWjөfv.8a 0 O4)o frhQ Q-5/"AP- C/@=Xz4٫ 0  ` n` z p ![@ H6zdI`GpkwdRW.Tp6@&{KK&0`G8d2Z1-ѽ[n%0 GPPV`pR~4o б B=D]{J!0,= ڋް!0,= # >@"C&K(O'P)T+[!@7!B:#H>.c1k3s6z8~BMJWP_O`Vg^rdy$LB'VJ*]P>@@-gX/p^0n]0p_2xeF)P.@6D9I=N -J> Q .Y!2g$7t'=@%LH(WV-g|(@d3yL@N@ SE!VH!ZJ"_P#`N#dR$iV%mY&oZ(r]'{c(BCDFFHFHHJKLNNPNPPRSTVVXVXXZ[[^^`^``ccdffhfhhjkknnpnppsssvvxvxx{{{mqv u {j5r9|<~~79<>< > 5m8s;{@@ B DD F!H!J!M! =!#?#$%@@ABCF~ILȥNѭOհPӮRڵS้+E-K0N/O/P0O1R4Yg)j+n+q,u-x.{.}006]8a;g>?ADFMɫOЭPҲQظT01223456Û7̢8ۮ;H*\ȰÇ#JHŋ3jȱǏ CIɓ(SZ<@#.B͛8sɳϟ@ Jtg wCa!|ƌ Xjʵׯ`Ê5x4¥sBY*KݻxbY,bM4ζ!Ɲ۷ǐ#KLyaY 9PEycМc$|h*b?B$Ն2U8 vLO tO8ߕkν#_4ʗOKМzkzϐ@>ۖ/$SÎ@yP~H;xVhfQCm1K4@R>AN mcgG  C R _:qTyG\v`D8Ea)U>TOb ? HA裐F*dG1ωW&ė$;餳) @z:B9[d5:+=@7Z7@ByTk\EKq2֖EOJc"1+P:!-Э*t[ٚ\F,?@:< @F p-P'q:P[[xh!¨yo_B dV|tr3,`/aig會Ă1Q <&EqI@I@ P~b( P@MR\Da"p+pMn\L8QƋlCXLcl $jf6 q g1 r qa!rG Bm2A vV4]hS)DH;;?c$ADMvR 9xJTR Y@%'уS DHbrBJD$Fڃ\KR[Ve08 qc΄4dLf3M`j 9raD (6(B2`'H+4#G:"Ѕ  =BuBE5@d T’ a"QpB 3+yAt e[CʁlbtMN'2 P|k SH@ilT_DPVט1 A8jpc)A ]<Z2Mql 5s`&c \mH99 %@TrQ|BpUPy<0$\=!0B@+^,! @A d1H\@6|}rWK`ӵ)R؉ V"H XdA>9ID!* }!I.HY"b((FQVx Q)D`H& 3ϴUKN/i}}359rAXho !]0 lpM) @ΆEӤ LL$~ &6$Q:mTNm)o)VV%JY^ŕ) 7 Ъڪj!7 O9 el&x@80B\fx 94@V] }Hq_aY' V`Wpg;wr# &qwլ Q pz v` vv'Nc.b)1!K5A=žA'# K/"-v=EV(3 8 z9xNJIyf3U' 0E: $ p0LzhPJ}0 6A-i@Q @Oglz&FE1[w5^nGMF ޔ\M5 NLeL4oFnZ^ 8]L V4놨ЩLGVZKMj` Z :(efv@I RJotZjF 6ai` W@s(787q@PYrjALJqfӗ`^W "|rK7 :<;;aXrR !|/05X -k #•wr>hxR aA*ZDd =PY׋p5 QU&eHY6nQ h3 @+ْ9 phdkhƱf|V hp5yq oZd*wy*MxʸogTk\~nݰ_bȐEdElp&4 qٔTaz_Ngv) P 0`` D{eEx=@ CxZqޫ@ `qѾq_0l:qqʾixԧ J1s0M$)*W *;[5,aXOaM}R'25qb=1jR) 35o3lZꃤIPּAIIyfbo_JM,6q6WKiq ^;p !QGpKi}-o<^Jk+fȈ0M䓉Mh:FϤL|lu^E%mn^yAQNaLM|ɷ;Rʔm7 VY q5! Lsܽټ8l!dJ'`8 n #dIָW:2Ptr ,)QsB/)s 4#ܞ}y`0Bqu04d6 e6|xX I;U4Q f)yY !\Pnٵ@>BzxFi!YBJiV|Q1}7Gr,ƄLဗ"(!XѵFtk)  \ДM~n]ڣ+Lql n)NPYAڨe>kV  fM/eѢV6Q9ueIJjÍZq ĉs>qq-kx("Gq }ƞ A*Cë5J(:&;T7M߲ʝ|"=A}BB -gb(Iy80Cx) 0=o8Y' B$pAySR,åW ! NSKt+B @j{Va|@aU03ZKM&.I}VZX:f glv~5 P E_ j@܀l`]] &Q^.fi \Ycu m LD *8`8 B0-: l&yQQ M߼-̰ j^pqVNA  !sG72vp3Q`2uWm+}@avAs'  ]9};x?JT>, 'iSP+iBF-e:JJMG "4KC2 CNZʃAKW ԴגiA=+W.pUY.^\QJV+oh- + LlU đXiB\Zn85%I$=;g}mF41%oc)M6\%h .Wҥhvifxye`|q`F0J DuYiFƃDPtPrI9h)))iP'ǎ .t:B靂J:L*I"(CjN*-*'rJ|TX)!'-MШO>q"uJz z!!ZYy$De>]zA(:e.h"*H( vڃ$A "3zp6 DŽRUЂjv%zk ߌS#5 (VJa`5_,vx,hc< 6. ,;#Rx(x Q;y%"f "9M$yM`ߛK#6Jh%z(F*;"8aaZJNUj J +n0[@r%+bpz$cC=" 9 ;ip!VZA@hn[gN8`Vzq>jǩvW$Bɉ: !RyXW_WpKqG/{7|W}w(KB9}~P$` x@&P d`@FP`-xA fP`=AP#$a MxBP+da ]BP3a mxCP;a}C QC$bxD$&QFt<`SbxE Ni_q\`Qc$cͨ>-]3Qsc6Q{c/h:`G:`B$` XDЉ,DB)z"QBx:X A!"UVQeQRAq ()*+nTI0F u:A5Dn*y dzA(Sd]J}ԣ&LWf!KDf] Y±$q-IZYJQ=AL -i*XԦVTDA\cLƖı,Q޸mv-*CY|$#+!H]tnuk&ybvԒ)SnȮDjq \Jes^W\z}W(iGU^t78x.-Ϡ=A,^p;]$}C~{bx%ٔWwY>l,c'/bǴ`0s( ߃k@[P*r<Je=ɉr,[A bZV lĠ@2 Y+쐎zR0dyԃru$yҔ!}iLgz}A Nvh:"VMZիV595um=BvhePBɷ&v}ld'[fvlhG[Ӧv}mlgE5BtH]m[ݞ1%(@Wk0 !|@'+AہV,+Cz+,X$9a1zP YL1-lqLpr7ae+ذ,e+BR &H {`Ubaob&{F5" !BPI& (M x ިTFaA*HKG΄H-rq:j) lᄃ䋛Nn|yJn󟒜A?B#6  V,@W#_Dz`E-<}H~)D.:]4$x,4@XN@Pp( =7Ŀn}~ϯbާ֊G9q`O6 ĢpH5pnH3q(ἠK6+ `h੭X&K2-; C[Q # `XJ8 K!ӷlS'p x'x};p&l'?+/, }<o8p8@;@4@5,0 @.H@1;B  C,EEDDX@Q+  [ O [N9n0aTKOc!Bd8Bgd 9++/@r+h`z|`t p q\ /`ٟ<'h%XHaZwhD< (NpQ;h YغPΫ .fؑfp!)QGᑒlfYϒ0п9.($X+')c&?@>. WÇ)$Ah-5I80}p.| Di*!s`[>+H[ 0<8H*#.BkZ\p's:@RPҕQ+|RX>Nr[B9. 0:Q` PQk8 ?L8¨rL8X;LZ{\^T ]P o`.r` % :A/(˨G6'K}x5ʨ&1,X|::郃ܕ调ر ݕ0]]PL8d<ۄ\]9&"t*XG^иWp\Єԃ\Lރ(Zy^ g1TH-Sg @tA-htu {p0iMhHJ`c8iF{a,E`4HifkMdVגσ a8 ^Hj=!`!8xPXA)IfҧU)_X1>(b-م=2 Ѐf0ЧM cU8hX#SF^ D EVW>&,]S3hey'HP>(1AH򬒘<"X. p:&[R `𐭮Ii +^ 7<@ ` qfg 8ޒq E=^(w6_t^q_X >(s̒XUb^ 똏kjM F_(؆m@9`G(<hW8@ ֕i # 0j W1'wiik%;cѕP#  Ne!Sk1*fkAcϒ^dfb|% mHcEȎ*J;MNRD@.b_B .d:bB16"'ݡӊnn:I!N@IAKX \S°oooH`Ⱦ*|;h '8n. pgr\sNS,T;Q%X%NM`MK8ߜg 썚`Q l::FM"cԨK U $<.>((Q@A cP@P)D!P2+`Ba.4@ВeK P e0@B .*qRԠ7@ t P!P  G6)ΓLj#N2p`i$ D 8eQ!68tR64YH8ِAqH"1DјDTd `PM=iR,`7V$_(yK3 Xe`m _5Z tV3 VZp@68;,3ju)@Q>,&huB* *i&A- ]@  e`qрG[tp3[ )@;! etvp%}BsxQ2wy詗 U s%߉2=~0&D4w'BPUB 2REtJ͡UD#?䒋&UbvDzり&E +#=UGpӒ3I91Q8g0iP6|NL#C Eqқq t8tg7G7xӠmPFhA{HΆ@!8ZI;.@(90Y:8oȡ?ASv 13O!D%25JE(Qlڍ.t%^%.[X Ҍ+Ѕ.XHe _ Vl$`0aA>x(Doĕ8@!&٤C}@N=$tAr} ؇601yk!AjAH AD!:z@㟁=ExOp IOD" O^x'Eb9U< Dĩ"јho{EP)֡& 4ۇfFN Oplno~ ]'EA.9 ݔU(p02H8!<&PH2i{ġ =$)7J48 ^)otB'"j )hA839(rPe'qF,P_JO~Rcv? -Y \Ak0_H0 D*3:f&VЅt4x:& 4XɢI& yk=04{eGk䬦c>9Wx6G̬OhI`R A0S 8O4 p @[W c$'$hƒ\44B2rdQ~^S}b.dI*%K`l YX@F,ؿI,l $ZШ~+L`KFKL /g(4(+Js\J0n0-|2ր|K B09"H5esy Зl1e> a. l1ϠsfO؁yș>ӈ9&?f1tT -I-=4C-QԦ>57=J8ծ~555ƥ95s]׾5-aƖ?~~6-iS־6mv(-q>7ӭu~7-yӻ7}7.?838#.S83st#Bs&?9SrPg`7qq͇qܙ1WӾ;r< Vn3Nzi&:?uO)^:nwx@wT@>X}CcFqPǛ@0M= 61<>ïh3?q@vXkdGoAcWj/!4`Dz^Df r@`_6Q`u^FVDB_En [ʄ@K! ` > "De!D f^?T`fr ! &  A@_i n!9UI!*?LLo\DHRDU@q˜&n"'Z Ȁ t"kPi B 9!"An;0Id#4ǰVk"aQR_!!e/#) VF=dK#8&c4#=֣> " ܜ d$ A "B>6#}Aa$ݡAG=J$KK$LƤL$M֤M$NN$OO$PP%QQ%R&R.%S6S>^8M}J AW~@8jA@&ۺ^D6Ƽ%]%cAo⧜MM1\ڥa&B @ _>``~Ja"&f%;(G1V;!AĀʸ$({ 8cZ8B0Z?k[o AnB@"lzFf^avh^Q8UYc 6 B^5L;gD^<Ly^[N5|g@5v'Tj'c!A d9 d#@ ;qBh4 C @(O"Ѐ Ā1 Hj L LaM! > L._FDdLցh l]=k4 >=q z*b$%F)eƑF`\. LM Dgn tOf: vgI*F=ȩ(iVjP)c)A$*V; gmi^g`j D Dm$ާg#ZPbVh@pjMGo )E̱ D#r@*T KʤFVg  6OTF k`^e^^'Aog^FºNLklE@1k@D+LOX%bY9RiĜLg8^%+m)m= jdD*مg>ZKn+!6*gM2Cmòa q`Bޮemg C@!,Q=;9,^$Ƀ" C?$ޘC\јCm&] >C 0#ޭ..//&./6>/FN/V2ݪUho%/fG(|n} @0AjEDD@d c/Q@A/0' v|JBP d@XpNqsAN7\V@s8 |0BdA7TOCxDt /K:.J_!M ڊ&M Ē-DySuD~xR '͂ZnP@)-3M[@$ϖS7 2Ӧ]D а@tGģ D tC1y0QutBW|Ž]fb;cTLڄuODU Dt@tq!|BX|Oz4U$,AvRRrO+1q@ؓNkʝCAHC6E! A0@42N01KOe%VD3y^(h0nO"*2WtNǧ uA͍!TόQM Hs \{U3̗@H@w5qDtZOwΤ 3@ hpE(c  9 @ ZCOs M賦󆩵TG 'H}d<@t @Ĵ(vD(t^Dx fKBt0ծ规*3T6(MH%FZF'.DEKnD FtHD~ -B$(( *,H D􁼒'q4״OH,.AP<0-5Q(탈^]M:6b ^=#!¦ aCf O:ȭ/X)` ֧3G#p))474(|@tqOM_@0@v(;Mߜ &B- ċͶwH~Wȍ`B +`‰BD7A8AB; ,`VS F8ĝtDh0A@1ABΖX08CAu8N8 9_V_D2$HT;CFP x\7D1"HXD1C8S@D7ԌNX@,G Ad E؏B)Q OʮY]@3P`h0 @t2Y.X.DY0p@/4vTB""B^& E"~itEiF! Q>C!-iȃ9?&qCtR#Q$tVj,zh ~eeCmGĮD # AL%G&3;AQ%Ҩ6%j(JV0 TE5ȅk@E @\U5\ʕZl#\NPIt 3jTVJuU#8o&ucHƮY'-C,$x{m viaF\8JM omܭok`o8Kb 9gf250m@7ψ384uC# G7n[145k6qԐɓF` G(Q4&{u`1ӨY͚qlB "+ e " 6@8@"q 80&bfPSV1eMA9wa#Dكv"H琊hL<񧐊b@}!'|"!!!s#[hIAc9Z8ѓNFa JFɁ BH4b@!xQ&O5hrxDD$P <0b\r%Pٵ"'rq\J 6Xډ2Yɧ\臏 MfbH(d["]*+~G̪,PCq` qa1q 5 X/ j,4qcH- x'-6 0a,.^91pCQn(d"߂h8 5g\9z䚦nښI ZȼMeoa+^e`?e r#HHٜ8:`!F 5S;IzM$"aӳ>*$%ҪHS!p < D!ִ\|bHL\M@6B&])0Β ^84^rP8f,_Po oo C2+@6"XS@6 nEL8 Fp&mj)5Gk44ʣADTp#$B6]hCB *2! A1GTJr?ȜFRğ-D%E` H$.HάN%|^69<iyQR:8r:nn3P ilth)uSET?mB:疼9JB|%>[EDlCr"0P"* ؉SP2\d`t "8A|`JaY&̅grk4op!Z ~l ~ R 6BAbR  )Cd*&D*B`J壚AG|@wgtML'#` * zj@A8b\a/5ۢowGt'IVg `PGC*B~()bD8S() b:A8"#"pH>0p!EW>Rlb(qZ("8*CbXWp\B#z6 bB/.l.J~1&Ɔ,*ʐ#ΰ"`,'C#0cf(f"&0n/1 c"4CҠB}UP&))%%" ;Ni1Djr8 R?K@gr7sDMXDNKG x*kN# SM쀞qKq#`p/42/>)wb=դT @ *8 6A!tRx&m#$j"#pBs$ (c~ 2'ER2@$ Fd"2@+@d4 8(H3 45&,4"J-I1"J R *Р "R@MҴ K" @ t96^ ¬:4#<H`M08´Qt 5TQLՀR9OCC94xr,*1!@CeM@> B`9C AB@| @jBWC` uEZ`T`Z`U[g"^ fr 3'`5 f2qµ[b^k^U[(([Sԕ]4*"v@bf"b7c;c?dCVd)v@AFeSVe9p/ydecVfgfkfogsVgwg{gq !AG]iViiijVj 4RhvjVkkklvgTllmVmזmmnVnnnoVooopWpp pqWqqqUMr b[$HVr_t܁!5tSWuk#iK8Gidsus7!AtWxli`-HU L*bamvMWNpxw2 {Ǘ|VLatDzqj|~Wu hZaW@؁a ;c!!h sw#F|5b*bv48$хfz =?\U+b#8 ҡhҁtx#dX>$5X~[bX#8j@q"Xs[!XLK\XCX:Y'X~ !V{dyG‘ҊsNZfu!׊o[`XX>Ę4Kؑ,&8\X"@;~Q֜Sv<񡾖DM)J*ٰSLG$Br:]*NXIv]H)4"?-Z#:ޡ z ~7B3ww`VL㨷)w"OKDZ>dKG:;?OXږd$uK":N׆"f9ѩuD! !Fӭio+"yDOw*NN yK=UDיWbioaxLzGv`:+cvsKtaNhNOv붷:e>kz@VzKjت):ei`dKz ]ܼA`F^F{#HyDQM!A҉$w[OZ@{NaaITL䦯!T BLVwa)?S#{o$$G~o{ZɛyL@IzdDGaI{Ο K Vڻ{Η$u{#z>sDPD$MgN'GwtVM|D̄C $bƭbyUݛZ@L"X=zKrwt^@+BGpwI)y!IʫD]Swtһ |^绐I>VGOOڨo4u%"XNҁd]G!fZvfduz{"Z:P+D\wzxfwy٫\#O!lLBG,wA}OLF}:\Nះ~v|[ Sy2^Ł߭2# }]"a,xGsud;ҷd$N'uTK}+'LG{{vu{+K:f@ Gd$`Kzv EUGWiptL=vjx;x+M*t}jV'L[{%]_ބ zLNaɛfZe?Y _ĚdIPzOLPwl!ku?-<0B9 A98!sCΡ}W  ֓?D;T At":ZH*0jT:A @q} "Nta @ ë2U+`_$\YȠ +*;`?sV=  FנdvV*>˛?>z9ؑL^X WySm94B7PY Y4>@ b%!!0Aafvdjͅ2tdI>(A'Y>J}Ҍ6^CQRstP{!t(]GDM8d@(iNSE6R' xЕ뭄ieA\5AAg[ߋp& QQ!`>?5.ҡX/ՓW܁RK6bYq]>l&}Qjny;l4׊Q<` VQT߭m~ n!OUE\MU`8UT>.S-BDD'iPq=uY@ $+jP`qUC|9V?"s@U9m: Q]?gj=z[ڔ-$ڌ@҃e+A}TV6R$H dBd vp;",B 5ѥ f/ZsVVuŁCE>q`ԴA+ .I9|lRb`+,oW+LIl B=ARw杸{7" Y6TcφrnekQ$J{VEM5JAV'hsBnO+TGȥIhE؎)?Gƒ3("SpxIN'z$z)S8ſ0 # $}QxjA) &Xl2=,.PO6FnYZhB`ogyIN8H dNcx0hsPpM3&RH2!4w;@ղhBZ7@ r ؁,9p#C DY襻+fb"dA@E}L/қ=֬1Y0e1(jH:$q`J(yMeE_h*Y?q.[ O"3 ;`ROdar}k+ "43SP jW $#[SpL+ɄdA0$4m:2*MTAm\MX"3*Fu%?LDSR q@\t8;X@CD,*3ȖZqeEccoLo yG~@GY @;4<rtLtɄ,$A Dk2^D$ IdE3 NZ BaJ>Az(aByGvHc=A@F,+hB#gYn)X:WNDٔPzgL56l '8aFShd@@PV(eBڙuTV\D y|MmAD5VT3-P:0Q'1CSh[Y)<6l-H_±`v, \d.Ő_Bm]WuG;)MO3zSsC{HdL ƛ ׂ1y s!`.8bhycuBsy$-\/dsґt`> >Ǔ ( -cevwٱ 8ZdAudD /;c7YhJ?C¥RO3ܓurƔ7zsBgptZxD/I1[U2}<̿_K\z+dk%w 1CB,r1Ȉh=0cpw`~=DwRtoZXH%襼O_z\2ɼ^Ӏ-D)Q$\cܗg§+P0J*8vtGř`? N;й/0}H`yp׳u4~ {X(Hh Ȁ (Hhȁ!(#H%h')qwI4 т.w.+h79(zp&iPq*}|@^ Qg%s7WhB:qؤ[ȅ]xz8b|Ty`wp/ Q/0JsX1f! Qs W|pjs-'f1$Sy}u !$tV+`yL188)^H+'ApF#ĶzX ҈9xٕQ;DQqK &Q! !8u+. UD,K~QO!@Q[sE$N4Q):/{0+R,[5OB(QrH,VdђPA-|@zy2IƸЖ `;T(n 1Vi!O )f%ك'+ߑJZh{PXG |S雿 s9(A_nU#6!-5he/Iui!t%  - >%0eE47A(Ӈ$3S"&DA$С+qj88b9>aT"A0`-paIR衝Qᝪ ?&t@oO:1xY'Т8UXbw_;$=zKKxwQ*1.UzD6K8c]dYQq[pBm3[TJit 1xpy C(46.@"@zp{CC3* C6Y[[CK4q8PT^s㱦 ?##_\ sP>6I?E(3Q_p9٪RD(<ե-!kPzQ5dW($jzغ@S#Ry:郅 @B Q }m=oAq (B.}"8i Vz?t*: AeTt2 1- R# T >9y{Rh Bo)_q(12B3IgSp/t1 &_Y&PӲ㡙, |T Y Nja[zT@(͡cH.9ۅAGlIZq k[b?d+Ki˼;t-<+!aDB@#s$F((u`Bke&!8}"I< Hui_!S%iCĊ$W%c.01`?W\8L ikmo q,sLulwy{} ȁ,ȃLȅlȇȉȋȍȏ tC@ @C ɝ<0 | !9 9`! 8< HM Np? `}$A-&@&P"؀alHla$0Ǡ ؀ǐ,Ǘ⼠\99̡ , ̔pCʓDPÂT ?z p$ݰ5-pܲ 6- :iȀ og Ɛ hr mp r`'0  0 .80 w dmK hm< c-, '  ʔ ]!<= 8H!= )-1=-} Ɛ @=M?` P:jPl; nSj Z( `A؝ .q @<  =v0 <0 @УM w~-ɣM -qOM/›Qq= A A.mY 1 @ p@ O ҹ A( Ҩ@ `Q  M0 p PҸq ɍo܀ ,}%`%`- a YX ~-_T멝 !N\6 ,F89&Acۼ384RǠmkspXᲽ8.3PN\Нe0JтC,uRjIr5ʁO>$RAR~jiQV02`͚ Lvm vP 0 .2׋]|iV.wb󔒂S#<௞q3Wk޽}\8p xZ͡ǥ ̑uNY& '!&1^HW. b劢*r% Mr) pZ徃,HZ*o> ZzKeUUjxѦpLP8cR(0H 0@ #Ң @b6*$ j"B_CCm jH !=2bIF J!p6"30҈rcRBh/"A tB@Pa("FB:):P :o ®̮BhfX1(/+  )ez`,2BA.f-0 tU@\E|m6hx4^y祷^;n.P5I&: "@;z3"*xϷ,DK6ȉ\^)hC%( 2 `LH4ETd1HF 9hRHQ pc(&?9! 8*t9NRwR* saV\BΛ`7=c,d!|AKe|;i_o,qMs\Bj#sg8ꄀ=%x0dE8,ɛ @6DXeQ!-Nh 0Dp!&$Â'QhF-4['` 66aHūcrbq V@r,@D I0TN]5GqPQ QHRPԢAN!8G0O7zBK:y@R2r8+\q ka8'#PPB>| E,S0KetoW,YVp^l _82Y3`BjU>"D<g 5AU0I!ir+r"<Ȃ!D'6LwLI= %s?#(@ yE.[&„A B/&&Zb( €P XFD-\C#q5:UK7=1& G 8قzr<t܃Bb% jODqiOމ"d8;NP*K L8Bȗl9I * аAPf N6IٞM7[ry}ֶ m Q-o B0*-yoąf@.O BhW \j\?J'*`SAF= *l"Fu{u(r|v| 8BR!.peʅ&2WTDNؙ \'' Nh @/kA#m!i-JkTYȆ "nphF7ġQhō`m*-ĭXBDDP 'nX&FԦ: M2j8..Ȃ kd1J'U:Y!xJpx(Qh8 ``96{9y%C h`++P9̸A+`9À :5{ SH'tuȃ;pBa/2%~)%R 2DX;QBC'R 2ȻН2L;QPZCʯ!\@:(2C=26ޠ=j[=P#1!;# 3oț;c{ * 3 d#iC(D9մI}HOC } %5EUeu !%"5#E$U%e&u'()*+,-./0: Phh:B1`3MSX6u<==l D<?B@SxQ.@TCMXTEԅNӞTA B5ԫ{}QGUTR BTTm MU<_/ U8S0UKUV}Gb=փUeUV`nմtYB0B8>@W>PD(\*}xZ;u%qQGŇm6m[0ԍ[HspĻ-.ҝĕ܂ȃ]ʵb]hTK+y .tB=(Bݵ썗X^TEЭ9hU;`C(SVUW ?HUsh^۰BHZbm9=`:(`z^3Te@5݇_H_z8&.(8`x2Ňn ֧˃P}U>0)(t@^PV tXW@P>؇}`a9) uЉQ= SB@CKcB6X֝qhCgm;.܃ՃB݂BM^CNTX?@VHHUM>]ehdU0d0a%F\Gec:ؽ:jމ%^x=HՌSՍzxr60ߪB[s~][V՝@fBfe@a[ey ԭ۟FFfs&|kEpl vq?xZ8 @ uU0߉.gPifkjΝcS-.w@g ^ghg.we䝰2ghumn~6JnHJ:mg݇i]8މ`-.| U%jxePx ]_xVci&Se_[uvjm~[y8}QX5h 6ܧS(k8klݝmމls9 BڮZ^ih\ ^ij)b)HZ>`:x`=ݠNoF.]oz[%TyhS<T/ p5r]-@f'p{(se;*/ȃX8lVGT#RARvJqhi(e|`^=wSF^kv`MgHvZQgR_^.#񻖇ܸ[= yU0N 潴P Z7SowhUW]Nb6߉mv^lusNvKO~z`E_v!X]jKGx7vPipIFw6bw8? }qxDwx)wrD}CSvhvq5^spw0?Hs=7qWew|xpw(B`_ybovꑭv Tvvuwk v dGqPfAzGt_Xw8&_kA8<8{ Oȗɧʷ'7GWgwׇؗ٧ڷ7!ONe޿7~#OE,z \hNx}IbN芡(N&P̂-N4>z1$f!,$B(-ZJDq`oqwf"7̐Lr%˖.sp)s&͚6o̩`zR{G\=;"Miz5*AR\iKN:)Ԧ4b\QfR(UVs"&NF(wi`0cq&L4#{Wm%9xFġ!)G\%,fQ .)OZgl (e=&xDͼ!uK *,Ղ9: ɑcR[8 5K+_]p T\uWMQAM#rt#N8D6YeF ` EAti!d㙂;z7A ؖXA(S8%IBRt)?d?([PrB%>J4f* Hu{EC{)U⛜V%L:AQ!?D rCDB )pQ Y8ZD IFKZPd8&bJ2tX°'y[D<@D @ TPD tdB/y -t ϵ JM  Ly 4(A-,쒕Xʤ%y#Ac{D'%%'\ULIufALq'z9`KԹbQKMKե -YKJ|IJE_mh)v &,)gd+ Fb (! vYAq4ͬ$A8@"c!((#HiF)t.g >iQ8exkJcH ݍg5 $(}ZWAҾ24S~3 AciP?^}[``/4c|1LjPCt%>aAv$9搇AQwC:Cs, !"68D&"'x?Q;j18R0dA0r d$K!H .5! x&8OFFXNAz0bI"Љ0 @'4:= ׋_4  3t]P~)_0^4c`_EzT H" 1cB/ @Av Z ns0Q9͡AJADÂ#C ǂ"`As `A#Nr>Q#a:T[EiA%` Z$WT'"ulSAijBHƊ2 ۻ'U;dd!A*UIAH hnHd&˗&ל@D;y3`Ȗr%*I" "ԩ^ ǍR52h6cVf-ӉsRx%.l X 1 J l t#'8 Y.uj0.@d5,+h6Ah(5b'23d !rĸj-^ 0-Hf|]jRC @ r> B1S\A 9B77:0NiD%t: Ņ{?D'i>d qMZx?Z`+Țs[ "Z‡ %KLn+BE\wiL pA.O,]k= |EysQ4  7Ai-' !!L-+*Vq#5!;9'$Ir[m5wy~$Z G;Eyp?^I!"A fٶ!m`<% n/ҐEU[x8 K<"&TJԄ yvADA.hB}RN$x}MȁM A6< ;g$ASj̜i`]F1<7ڑ`4Fj؉0ԥH84DLC54L GH ZGWAŘH%БAYKxP]TpAxOA^MAU$R"HJHP >CkݕA)GA?(AZA MPQ M?E!,][JB `ax^ш(XBKJ B4u% K8A) -pWl A-rA 0dC | x8<8 dp`A 8`gx  ixËYDM$FXSDPa͉A8Ç٤Mf0x!i312CdA H5LL¸0THŚDT\ZWPi IK}AϾ@$v IU(D'yPfADPD"Rݔ&ⱅ-D@ Ab00 1ʐ o34J#P9oJdA]k8RGn!z@Abw.o [B%[M@}D"&U B{1DyW*H\~R$D<\<((E 2A ΍.ae@K]`hdH(J$D䈃0Q `ȳ7l%BXEED;eA\BHA$bK|@Y`ag*IN DbAX_D#ɢjklFY>]MG1"D'q M d9@(A4gAEMTgeAPBt{D*QD^WT)`*ȵBA ~E-pgX`A<eAc-K)·(ApT(쒉`7ᠾBeC48I(Bg2lD( `R@ iBB8pM|@0l8~( r n-U@LG3\f`F՘N⛝#Ω tA^.UBO)aɑɚjbk"llcF9 ]فAs\?Dqv5t -3XHAHUU2,-A8-DD-B&D#"0h*ز.D梞-AsA@'>8m x>BAtx#YP;0 Ѧ l8n*,WȫEV[YzAt.[h/p-0|',,s32R? `!=}K+rmD؄:֭8Ve  Ԍl}Ӌ74F1d܈Ae &N$D cDJp73S1 CW,=-Ƞ2.0 Kl)D@o%8^EZ"-î,*J9mcBD5mfg.jq@5C ՃLM;@j4NW'CCtC<Gj!mq,E(–&`o `46c@Mb?e{OqbD8A8*@HHXvPkh]N wqJe  @ p7 eD s7yPwDڡA(VZDzm@wsS{7ww wApADDINc;z:L6[ aObxK Ax@g@틾ĊCS"[)~G8@@@Đ{c (9 "A0-'A<,DHyyV M8` $9NxR,O”z S$|z+3z;CzKSz[czksz{zzzzzzzz{ {#{+Syg zS{[:L#J,Y$Eфn0'3`\@6KPQ3;Gz AA\{c M,E['|Jzȕ^_E'Ul¶ @ǹDM'1z6,x8hM|6dJK/2\hLNA8hPKAKt:B>9pЪKPj&L[U%TxTJ0-Q(PK<} r\B'PBom{\L(,/:LPNJoDoc@F~Ap8h(YtD NNeA:eD:dz!D1"n:[vA,@T`=DXr=X ^J$D%X{(Ͱτ|5:ĆULTLp~KXSyg9à)dtg7iAؑ9y a;h8Gv0HB,'΂x'GAޑ4 x)PbQςZ$;ǹA!XRQ*(.Y( eɠmH*:ВFJ#LrɅZr Tʽ\W 2 \%$zH.ʗ^t*,Mr%0JeUPU,17 Np .Y3Jӎ4.>-ێctƊh Ҏ<ێ3Nq(;6!8lV6M6rY@a;pFKƸF'nHQV2蒠p0pn;،4tiF%2ə<˂{& ah~7`_~~xB BK!TV;9ڤ={{^Aa%B(L"e1YP1FPxuVLҷA(Bby  ̃ J F@/'"D3X.Jq{%`1 P4E E_Y'ЧglcBV6Q!^ʦCAJm-H nG`q-hB${K Ga+#70eBp9YW$bā,k-'߂ŀdnh Bى4@EA0x3$!D9%gB `$z6CI gBdĸ Ec? N2h$cBW+Jj&? @@o,@q⁩%q?ʑGA/‹iq[ W(ȳקP+F2i9)d[ ,& [`^E&bڂ8\64v.fxF%L@!Vj|Ƒ@Vf#li8zfl[)v]{cl̷8>\9>b]L4q$XAH8'2ԠQ3c9H5* !@ H Av@_)}Nr.!#]3D^e!(ҏY5cFQU@z<.=#*<qd[  Is3PJ+/ށTytB&k^ (,7RtCBa Z#pv~m} 0eY "8Ȳ}Kշ>$E h1nmn[;0F1#!=Y!? >4!PWû R+!L # p@Ԡᚫ pāXVh56%>@ X$KDK  b  Pf.(nӾ)#:gtȎrvaȂ$ 2 w ːj!@B4Taa&&n˲,n #쀦}Nj2%S ؤb|'!߄aU}Ha'|jq"bYp#0-Z b R4B/f jm B6%h-^! b غO#t O;fFmcoF Mjl#~!C!  Z4^ JdD (  !+Rpm`b%6y$ Xh!`f焑".ŊǦp:qĮr."rP!|rI.E.sv Hu(*M!G,`3 zPXMohS4"z .#݄p 1;LC6 +g>FI8HP A!<+j"Q;˾8!9Ò & ߴ!#$ #oF%>H0XvjB$: & Q&t!Pzrp )) P"JhBy '!*l"Ҭ, :NHExJ/Ol!.BxB.(A T! 4 |­ "%´ L" p2b´ DF4 4X8!P4B2T$+#@F`jِ̀\Q5k!^(@HaP~&k6hp!?9&N4KHcc# C:K#JC>pr!!2!0B d!2A/"dP7SXouBt!BbZ`.FdQ#)"' q w2tL,)ua `tF$ ɟZ , X $NA "e3GT GG R &b GxHEJrơT! t@g)I߬Mrxghd$D0*q2D%zMM9!q2 B-q\G.ha^b"]E_l\ @_" >g(P'udd&3 b+bǣ Gbk $.{{.%|6!g.% G&k$ڄBMOm'  CP(:a̷_ i@:&A4X3dz`@`_"b+\ v,bH  -ւ".C! 0!H-JA-悭^ 269"4"A Գ# !>3A4V`n6 ho ܀“edy"Pf!c! `::("D gF bK >cY*I0c w|"&Ԓ83O8,!E)| z@ 4$V$tcYDtFrI F ' dI~ 4! ߙ"hAdaZQ| "BKd@gޡO(dz!Kp x֦Feb Azڀ 1O1"Ă2z;@Š; JQq1$Z(;5{9)N1۳E{S@JI{Y]a;e{iZgڶy};{{` ;{;{;{ɻ;{ٻ;{黾T ھJz 'x$h9 -?4?tO>Y0?4tG4UEq3;(v9H# # xȓ?P*X#ftT?وxԈ+2 h#ve8砀sI Tvp9!:hOXbǎWY&|9Qt!Ϧ3"V<a\c: ]VܧG*j1`\xYT?ɘ?6kM-Cv:HC V$r.sNX&MGΈԒ >` 7{ȽzaЩ& a&&C蓤F{qv 6Dx6^=\ X ,``J`rQly,g sGl`=4%>ViC xh? ! A-H9EK."*́`TsS ܱgs )P pO>W0sS؂ H&>evW%vag;/wspayːq@ {<]M)<..tvD.#*]:G*Q2ct,g`%:C!p4 1Tp5 8 ɪiRY-PNL s1,'r"d`g^i?RHFkё._V!@pSUDCRb5޽Ղ)j, ѹtDDꈿ1/I&^# *aRiA0 8T Znz$v>r|"O}AjT tQTh2PxqKu `LZ7P&:a+A`Ca#Q͌*[*$QEF![>sA#! <ˆ4h[)WNSr"eKvPQQ Yq#~kmڲh̏ 8(%#䩒7]ZJΆRy#aqRF=*!(sX٥|`s("#M-$)8[kOlpzrT,CnʂA^j-a젚A"QIZuX-W FJEfuZ J뵙k w}K#x\A}Lmn#2dlTNp!Mx LiX2Oa#-(D:+"`q vDU>uc> PGd # tZ+"HYSljQBYKdn3Zo=: ]ag SՎqn#ZwwMxvQ8v ݑkC5,vG̐996`(Y#BiBHq?1](7C"ĿFQ>pDH9f) .#qiߋ6rkA$N鏵m 21vA>9uZY?q KĔ 2Z83:(#ZǍU<ƻA^W؁vi^uڮwCF ΃ZLlJ-Y08^9\]_* Σ#_P5'zPYW =v澒yY4d?Ӽ"+Ȃ^rHJX$]H)<%# ?Hd[vbp#qA""(D}X.eOC|^br$TCV4t,aF!xgqAj7Y**4s-f:rjLq:c2QD_t1p@b"!7̑ugZ1`r$MBWi4 J^q\:v]'#Nā,PBL/6'orVK5hQO4Cy;4Z'q\);a,vj/wzz"qpa -:*X@)wz B,bE+ANqJS RRA[uܗ1~$FrSv"7\MuYCbweq;m-$(A(ݘbEhRTg&Ǖ_s_{Au^GrʖasaY/b&Ujݷ1(XTRKHP,B)Pk·)g3C})U0vdDATik@w]dH~B@EL6mUrh&{?VCTD(t>v fzUKfUtzݷ(+=<}Y,R< hd:<!uZKLߔQaHu@%J!.R=&E`a)|t6nqS&26(ڤ\E.(`"75CG1MUK KZvJt#2((arRM5T)&TF!+I12:`vPW8' 2s*%&y|5>r5 ! 2B 1HB)gu!#x95We%)RkH-O/R(fFN]9]dV^w5ZQq!BB("W:o*%u.'uS !z Aw^isGsYJQ(=;h#USF6/''Ǘ>qnFt*&Vˁ*K%8# ĵ'!f_S"7la)f}zf }2'# %2_bB?Z[9E"Q*,g3n&j#PBzPR"j`4 |J1@ $jRCI㡫8rH"z555Q([5L2PhA.v2]W<¨F+OW=rROBfQww!Zza'Yѯʁmڪ5̑1.j$J1kдy"ϦpRz%+‰]Hٕ5/0A PuH.5~BPAe8RDˁ)sdbAps`. _0+y;ƪVrribj%P˪7B 7ʻs !"dg5rP[|> $UF,'y`(1W{nM׺;9nRYQQYk!{@P+ɼ[GB%l^v _@1vIO0k/,t7q@QNb1 9P#y$4sWpkP!Q.q*_HYfxH /& G81,+p) :E&[(;a5k9[ )5,A{YByĮ"AdM-6G+ {ū%gdū˪Y6uɪB2 Jzͧ%]\vBf̉",l,YjldϩfLA} jk<-L!+-@^*m*-h-m#U %6}8:-0Fӿ1F<VIv+F,>U8-/U^`b}\dmc+l;֩hIr~׀؂=؄]؆}؈؊،؎ْؐ=ٔ]ٖ}ٜ٘ٚٞ٠ڢ=ڤ]ڦ}ڨڪڬڮڰ۲=۴҉8i4PV\E Z%=@sq-*ᡙN=8i PUvn7<|5b244 P7N"7 $u']^F~H.>-d|u@;Pq"(*` 5{ #f - &vP%,>pNT^euMȲaR4V1䊾nKX]؂)oo-/0\{T8,w,.P+6"bxA5S v21璅!*αU7EV%bH+&:I p^ߍ>RZΑfkbw`'P8B*7s^>7'@+WB)ubZlT9&HC$#&.(8D0q~PY$c|M*,K||0(&})&onrey4M⻳^f 'qm!WY!AX% Z/`(+VN'/^V&8.-_v Qlӗ(Ls0"l_ eJ\l9go.xeMU+"/f*"41)+i9WcT4?&!^Ab+bup5rS:5M2(Grij9o5 t!ixMfA[T͸$XA .dCWp? Q=gn>H4#qF!珠 ';@c(Мʁ9isqTExWO!PD"oIang[dǡ;vȓnN/fcȑ%O\e̙5os,9` d8SlҧwI0]h&8P @s XN`}՚h@+ e wcb* lAq닶o%{zۛүNz3TpAtA#pB "C q6yCyh0vZ%`:qP7d: I  qzuP"Iii$DX"B(}㏧NH r .;,LЋ/>PNH UtQFuQH# ) ;n0`7@6=L4(m}!]:A8' P: )>ܯ?d[s$~ \tUw]vu׳Zh!c\RA^-J7=; n_W^.ha Pa#A6(;נh8bZ@;79!Ԃ=p>ڐm9`pVً_^w5hVzinIgB iizk]lV{mv{~{nn{oo|p 7pW|qwq#|r+r3|s;sGotNHpAtFgavܷ8yn1\!\Y?qyVȓEQGPV٠toa]ّGTS<p`Rz: ه;gHáAcGЇzC;H"3Fnz<oW?X;,* '8:sVX<ȯSB-0ЙB@Td10G=Ws1a8ؐr  ҿz)D\02T2 N] M"|/CGJ>pmw IB;NLB1HG=:.0N:ɦUl 8|85.j <*vZͧh&0H9 4':DB12LFtM,h0xYؕKvD164ʪ[Y5-LB+ْN!`1R&->0ݥŲk-ԧ8hwr8]6 @#U !EZ: 1WeJL$M=@<\8d c68TLq#`+IS%aBE J4ׁ?TLÒ @y(r[ѬHE{a^tƜ"% @vA!yi !@1gq4;`J:Si!-uP =RmWfR5z Ѭ?*&xhTSCK8YNG:'q4HXOq^sҝnyQҡaA9(_&$A^uʁDB qH%2|TY\;S " ](܁x:Yʰ:'dyH2W@;B$I by٧-Gp`ż@Ah&6 %&Ȏ茄1CQ$됭6e5`سKm)x2&'t ۥ0!,ȃdDKBP吮;q45 GGE9R)\FV!" tft"X TW 1&A"Pw ?ѵ-p̐1r$Lo⏀uSn@P's UYtn5COF`MHj ǒ@r% ;,'$G7?pi%A'fʷT>hy V#)wdȺBF:˗U66I՘"@f7M]a т>J0فܙ!@2n=qZ" I[pU\ur/ >nWWE6mCV샃Z;`nz,Oz2GxZ>=TG CJ{ =A :+g$' ]ᶕ=:j?@͝[  cEI}s-0TQ8'^JHҒ$|P[;Ø19h @CK7rC؊ ؍q 7z1lxf6"jۇ 9-:\qD`S蔔h  j;bI 01[ꓘ?bPBB1؈Cs;#< Aȫk ؊?K3 4"DĶ8;C%xBȃY@x˪۔z*+C#"D{!A17)ȍs3$ZT8| )/E#Dӓbk؇QĚ6a0ஞjyW6v j= I f7ƊA4mBB9%:y ; x dhAK9*+T ;Xk,H @;ۨ%,*džÂлyٱs:IsK0@P0DH;UHd@C+>37+p(ExT8 zGd'F-"\y"ƻ5%O)̥B̂-1E?隃Ո=AںKazS̅Mqy4LЦCTB8I䊧8g:R6A7b1H,P4PId42{}lɟD& S£ڈsBM!J>(L <0 ϭۋDBd:P#܄":d<=x,ÔscqE2L!<)pLxc[-39ғԄ0/ZXiip㘭жӳ/Iؤh ,Cݨ#ynЃ<( ȃ(4cRsU]htS'xx@NWI 8FoO:KO]Z< X v ̿e2.PAsNB9 ҅(Va;Ӭ a 8AxH9)QӨ-7Ѱ;=NXTd:a`Q$;Tr,Λ3JqUDCB4`}8FQ8=?R*1q<;˧qt@'ӻQm2=y;97M oE`)|8T;-@0 @WPQXЧ<(@X0.ȉ 5f:L"Lb}<qpհhJJ |PYА cMC!,;WOkQL:nFtNH9C1&;j]9,Μ.X5- 鉄BAA Wܥ1YU>*-SU-E!@KQRM}*JJTL˳ %d\Z ^E '1>Z,$bK.Z*B=W uN@lE(ȫN  "j\m3+԰PH؈BK-Pݑe}D5S79P B0#>?eɕ}W?biw#Ǻb?[? c<,q3h@U8,hA(K .j=t؇Bs1-=,}X>\6*Hň0 %ZKϚ8@CdJd*8- %R g,ʈ5kiΆ&̩}Md?q6M`s1' /g뒮YڊEY:$T*cDcyTV|rc|8^jڨxc;T@t?]EzhCB pMK"hwؗT*E\5*IHD+Z&4Yʝr k  G=F ,tL$+} xX  ۍ`LK`j@h& $iZępgVœث@@OJ;`'!x &Eުh&U&͂?Ax=ӽnv<1M6V="RJ|j'YQ u?bJb@lh#.Z7ciWy7tCh(%(6,h%7W ϞՓiqPyjQÿK6ݔ,l3WVq C[TpbnޑbhWT7`%ߔ'٭`' MWQ35= s pNG+ytamJt>4*K7Pq)a%Taf1L-X3Gyb)FFB΂f? Idںfy*@ovD6\}vsD(trjqFDHHaC@P)uoWHN 4Ds9BDp8|>Э)3u|O<t@ JSNί/`OOrakBerpU-x!*x,SLBÇK5eN$ZЂ*$x-3; :yx [pc |eASi쭑tÇ=OL菅4þ׈B @1EĂ6;(ɂȭb$JQ dcyb  ,G:pm#*ضLq B;VdmF8 ֒{EyA0ܡ{PQeE QjD?i{Gl2KvxN2~=łF*G<)ʁPmNۧ6dQ% dR˗bQqK@4߈;Q}qv!(Hr%z]rh8D:!aO8|N  v(!3P"9LU$" -_{ǽ.;y܋4K&~,{E{Z w4,yy>elXpjHo K-] N-rejYCX)Wr5$)_ΖAi B^#A,s0/0__ 70 FX!(F9,& mO ύpܟ !>,wۃ)>Ra`<>!&2;Sj`.k{M-{Bs/70rsr~j.l 8Ux "a!EFJ]%| f J7;6۽掏gDAe+-YAH?z%ʥKW]ђFH3Aڰk+BX5ã pg Qr=L畇luV`ZFr#i{B^HJAW14ExBF s )b:kDQ8}CcǮHyL ێmKkD!-Fv*UV1\̢V#M.pA[gjhlnu P0nm{G|Lulax+Bv }dp=K6xsRM⦯H̏^Xƹn(Ÿp;.nn95*n;v3"nXsԁ9E>"SADx;+PL9NyעIYG3bKWzYF!t+Z&MQw)ݐM= ߐSE9LKޓ_E >$aX T^&_AiY- X 2NA jVصAN̛E q _] ; Bܰ > T: r h ;QNbU ;C/] ">C!LA:Cٜ&Qb:pB0Ky);C1: b:Lb@% XcX"L;10NL:EL-VP8L`=˜: ;>J5Ͻ C@C=G,d#G^!^iaG1"^I!WC-HbAdj!Ā n8M@DI@@ DAdB"Ѐ },[GB >PNQ}RS@yȐTl%] vIn%B]HeV@#8b/AOďWa A! ¸'tFtN'uVu^'vfvn'wW܏fCxbEXrD"`CIx$hxF>]wfP}(Dh d:Ήf|6z~f'gXpbBMFTh H!5ɆmĆr 2Ȁn | OH 0A(B(F,9@-[S}nn=K ́҈K $SyHh*vͥP\)D|f!ف O N!݀!J1^9qP`эµQIC A()Fœ&1D]0 aiެ_E`@pA$O ff܏Ny+簃nހTAX%*l PkG!ͤF > }jĨZBpMkR} ".!C74H<yfB0\DFu14DNY  NC=c [p,n T:uJ+BՃMeθ_n)+I@P@UkA,F+FHCB(@S(A\BftfM:lNXG5dV<؄I D$R],S@pI}Bn @ę^ת %n莮);&E\%Ȧ {’?>n69N nD/nyV.-xN@ۀUZ\Nan-GExA.n[i`۬ oYy_PRr\H꩚N*cơI>Dnpѡo/+^  ڮ9&nWP X%cΡ\AaAĔ@ mNsV3l]@H\7ysB1H0A0 ZTVCCD19aV?f1z,WS2cP"B%{z:r1Yѹ7݇Qn㢲T*o,԰_ ^E綍w'C2RSD T9!n=彍܎Gm/nf"U5gʤqz(ȃn{MHe2{4;Av1l8 2˓ ;TKö3/)aVE+"r8E:ۼK'Ζ N{Ktk "On))SmG/bzrQfA f!,"AF"xkDG@OB-C U& ̪%s>GcpN;IGD/+tAOr2 'Xf XwP6WQ*2C /zdLk OHݡ9MS޵|RH TA=mrc 4ARPD`.ih+7<7y |wB@ѰH@ ttWh~OQIP(xA@@AH@y?7q8888ǸFԅ8x'F4F,$F<( TpdgtA A PDā H#BpG$9A,B(@A'L(Pd PB(A8@(FP(L9(A@|B(@zADDBpB68@8C6C8pC:Il8`FA8dC8 CAC8A8A8$Bȁ8HA@\<(|BDdEvxy'X;SpL'PszE8%LB;  zLz+:Xxkz77t8zz;ʓK8 =E}G0ՋS=K=Vl}׫D|8(@AW/DL$ADƏAzD8+AA}_:gD-+|u"!@}ןF}z=Ii_v ,Įe+ز`B0l2``Wf[9xeWҥt4|. #=ةv% #dHdHQvmQ.DJԐGIJa.!Fd#QHQ@0\pZzEHZp2%sehI2\0(! J\ )r\$-UV9#7Wa4'6Ĺ%o*ƫ ꌟ 3rѠ ؐP gѾ&,q-((A -O *TqK Pc0L: ɠl™tpEARBƸFЪ-0PD)1r04 ۂ6)PL,hrP4T΃`@Q/ F`nƽkF>ac eff?&/>a(@vA@S@f D!AGzv蠅 7p#d\Nʡ9qH1|M+"ybNJ!@\p( r"J S͉$H+) %`KԤ nY ԮIk8ݜ3J'm hiꧻ)Ȁa2W4ȤXi((q1*>UT - MJ"(Իup|ڋ!G}=L"t=ZR*a 3)jA[m'\Nq"6bF9Ak"b`(px AŹ"+`_(zB` [0 f,<xax:% ABpe htU(FDrn͡ *ѨXE+ C  9'>ῳU r ],H\l?"4"d[)֤D!(ȕ`TB SA.%IDDɹ N8ccP&GP<Z1V8d+hiuAqa eSh]6c$9 #2+)- Y|A+qS 6μV4IOa@zPP08b ?}Hʁ!d؝@%q؈[FD=D)%fɓ$$G#C:ʂ*6pcRA0c1*b3 |le6Vr5~`BU>=*G#EՐBG "](`0;[Fe ҍ d2`F3jJ# ^HDHf`THr7Fe#3*%j X bI5ȕ2(Ms{tQĖ|q`50k 9`M}"/Я"=͖h ihFc‚dT 2!s7CN+p;C!ta`{4Ip)&S\3I@DyT$ 5':(1Tq=JH[\ I(rъE֭ HڛA¿&)b+ʺW6rV :w8...zр ZLQVB Ř.O3+8 L0 "2֎$)W̩0KΰB >P,ֆl6jϠ^d40 F"2oڪMHH Jo#H.cF`.p`x8Ͽfhhd6$ ^pC ` Zdp@8 GF *!@N]B!QF&,2N4$J@Hj!O D"!)^@bnp \An bn!KhB('b0VI`i~SaJX @W ԧl8%W"Ӧx#H R.PV4 P.a X vX z {(H`%n$a#bF@*@19@vN`\@fB,T M >`a M6(@4rDr tNdS# 2 Qbk(RASlP9En.D$uxE$rWBWkd#gX BK#eKW"e:/C DJ3[D~  /)W fa,AdaH  78”cO9vf ߀g>_40`N@nG 9i8@pRB z GoHӋ80Q6n:ahtFer3; 2*@bA^0\a b(26b 0a !20DEC p# $@`'䀚$̀58@2CJU` S) y "AAr 펢T;`bWI !ծW- RT# LYu zzuRYM B `Y " ay [aT4iF!.az]`J+^^q#d Ȁ>@f4 t-:~v `@al v (3$] Z \\[ \VhjefogsVg5nghVh#d&rh!hViiBijjkVkkklVlǖllmVmזmmnVnnno-Eow/opWpp;covgpqqlqr+r/s3>%o5s?tCWt+sWttOuSWu1twu_vcWvurgwsWwwjkvyxWx/}xyWyxyz+Wzz7x{{wt{W|wq|}nW}}k~~Wi~WFW ؀Xos؁X'؀#/ׂ3;}7؃CXwJ؄OFXW{!&, gL ! %*-2498""$)(.!!)%-),32-74# #(*)$+33!;%0:" %!*%.( <3,;2"#$&&(&((*+,..0*424 =234668688:;<9C:#F>>@#C%K(N'P)T+Z!C;.c0j3s6z8}AMJXO`Vg]pcx$LB'VI*^P>@@+cT-fX-hW.k[/p^0n]0p^1tb2xf4}i@'D(J+Q.@6D9I=N -J> R .U 0[!2c#6f$8k%9u'=A%NJ)YT,f]0p|(@c2wK@M@ SE!VH"[K"`N#cQ$iV%mY&q\&s](u`'v`({d)h*BCDFFHFHHKKLNNPNPPVWW^^`^``fggnnpnppvwwmqy v zj5t9z<~~9<>= > 5m6p7r8r8t:x;|@A D F!H!J!M! >!"#?$$&@ACFJ~ILǥNѭPӮQڴSใ*C+F,H-K0N/O/P0O1R4Yf)k*n+q,u-x.{.}006]8a;h>?BDGIMʬNЯPԴR۹S0/234566Ŝ8Ȟ7Ȟ8̢8Ѧ9թ:ܮ;(`A*\ȰÇ#Jhċ3jȱǏ CIɓ(S\ɲ˗0cuf 8>yK @*l(9*‹% Mx ׯ`*<`6> 0D6ľ9$:yKHe1HQvؒ>*UR(@(R*9 H.𚲱 ӼȝgYʖ٬v3+DcE ͔1rŲesYFav2c'bvv@eJDt20A G@?x&?{zF3M%M5)6l:Uw4jZө9W*ˆըp? Д30M:!* av!Sg I<>OD(B)LL`/0 'FQMR1 bSҨ@Ҹ3( ?&D\4@]m",BѕuiGPpc` P q4kHF3Vi7]c+;19c_g\Hq37aA`:h~ 5(Mhi* D+82ewX JSXgH`!! Q<A “و@h/@P3A0|@B}D45A - )(0` %I7 ipa 2IK"4 fyA Ac6T UXϠDs_@˝ c@|h`Ox!M lȧOj;f0 ".<=` VAVC.դì`u$ j'zI X@,"'; '\P6/H 9a ,BoS% 4ĉڝft+]FF&G: !y!i8AuvT:'s!Bp[*xBu,]ֽ!euds ӡ/́\ CΎ 5!d'T&.d[ 94ŝ(!c t (< b0L4p-@pii~ w_o EDTW֗ |: GMo~ pO| "9")Wb"ۇ~>u'nnl/ q'@W1/~o o;3 G& 0 P Ipc 1]!!Y1aqo 51%5 Pp2 *}$L\'wG\ i'HCHsp X( ,2r  z$s FP]^g1BN4YMCM]*|8T#_T DuT8B2$p:ua+r8$'ӱJPxb`ʂP@y!;1 :)1c!a41 Ќr w5Q Z {n=P{ P ghܳ e h| 1FP`ȷQfpҕ ]{0URS 8jVC&pk'$7GWp7Ő ~4STN S{RS99X/8D1t!JTOE)W\bd ;y(7L /'ZaZ&r(' 7r[1 z r̵ Px4^dq9TJԔb'61$ׁ_J{* #@:RwYI`}wJ # 5 $x`%v0|7~'%:x qxҢx94`9yP !] 'OEyɨPY y׈c %HP Ɛ! yP>% "i i& Q"'/pS q./S}WБpIGTx("*HeIS;*?;S&A9 CyW)(.:\R}; 'q&UbF"Z ,3'xuI! NrJtYG Mbaz9R9KVbr'M#9at:1LqL a8#s%)Mac /V P!!AV /.(]( y apD!yiР0P}а( i3:Ə AP ̧P  h pk'H BSoG:yn1.E~ 0ɑBT>D/ 1x   Eun 1U!)A.CS{5J~5*" P2 ѓ w"E5 'p5+-eD 0R AHY1_$-It҃1P0~- Eh[R"b"2H\id4)' "t*0R\@ ]Itו+v"%8Դ7JMb奸`uƺ# [cb7*@Mz:bMjb,9$, ы-!Ee<<2p' QiƼjG?&5ŧAS| {&{ЮrV : a/S1 +PV, 6j604 U.μ$k4(+ QGSEئH 04a "e1H e̊ `W4eT'F/\pZ P87- 7=~u=-F iDqi `ri Z8S Ntcu/q͠_o84#581bㆮZ֨#@A`@6 6 U8 wa18v`V,J u4Pwd+Y.)ͳ[ ` :b P  p--  Kx&hj5U ,ɽY{Ű{qR 19 =fU XU s. 9U.YŐ6]SV Bm@YS PUPmmES@ooCpSA;=⭍"^O@;qXEpOa; = V$)`!6F B(`ɕ /%P@ V`WsF\@ ZΦ Q.+B pzIF0ID p6&  ȠL ". xp6t*Lp0`_  u8鋾 } ^N&ٮnx t Z.:#nEAѶp}!D0}P(gћ9n'    #_e U@/3`  ]@`V~<-/@lo9%@&O aRE;QEq!!MlX[*]%H9 aMo+ r/);`k(ȥC?,:+N?_?_?_?_ȟʿ ??U-1%:,!A'?Oa09V_bA .dC%NXE5nG!E$YI)'H|كBt;8?~;0yo΁:eYTvT<8 {A]*sJiծe[qΥ[nC漧2o [kvvV 7o&EBY:cck3BYN`X[mܹuo8䪑)<3' _\h LyH`!l/5?Wgoj{ϧ_}Ѳ@6obJO 23H3⋅P I;,kGJ2RTqE[tE5: DcRB׮ C2*pǠ\/F,rK.Ҥbd|nh"8$Z&I䠘bB EKDUtQFDҋ 1L)RGrS JNdN%q$Є, QZkV\s(,HqPN bCUI&=&_ tL][pÍў0 t99 q7&w B~q׹ҦB"-D(i;h1A -kB O[q+b3\6SbѪdACe @%XUgKvaj/85glaӃH#h>R:r0kN{fֆCBth{nK: jo|ptj'G0$q#\hZؑ'({psC} *HkGW}u[wuc}vkvs}w{w^t0^.0^wyꛗHE>zSHI)(4+ҷ‚ŰNCT腦YmK\0!'B:8H,a b H*AR!;E"B+|AAzP—,b a/| ̇@ q0C#G!fС#`*"'#XAI q v,!`v!!ĀQd h`He¢~dqWIA2i `z;8Na ROݫ'Kx! ē%w‡d|4)!!Jr]`@8;@F pLuPFhE,P48:@"F5nlyY")BV$en> cXQs$<!|$b=R%@0C`).-@ @lh R.D-TH=EA0@/uYS>L@Lgs <9ȣ+T`U9tX39'̀"MvfKݦ!,:atԛnU$GЍj9%`f7WdLAI{x,E6PBg c4#$/?H@ ycY <˰9 Ѓ@ZBR*8!(^`Jf8C)2 T{B!-+X;KX0/!,!)J8A[%wX=. ?"Y%OM:K,7& ]) ^0… (79BTY`&؅] PT8K0&Xfu'd0/rH#Af.J9`e0)j>0jk2cJ0:c9s*<8v( uXBx2C;eBCX#'.@8JJ(qR&L: n;(RuS}`|Bk$ O,Hا~<C X-i1#6C<<4p]JX2i`4H.h3`ȻFiPG`W0|ؽʙ A{Xv0W {)p|@zؗ`Iʋؗ*|[+M>irR*LCl3Ger&v@Vn8PHB"6U6@ţܿO"R(*<;QJFPA?0Nv p)- pӼeS78兇#\< ̅ȩ&T@̃T82#G%]XfRR#TՁhB<(Vvh4օp*U cRCMNC& g'W*MߍPT_,;S7>pR4h a@`]`#`c_D}!pZTjQT@HA`J9L<7y\p|cW0LxFԎsH&ئ sp]@d^e،n4L8+U+t*愀hJ)v:[+<9d*=1a]̝R@TfXmp/,ۅXۃھ@Wqgn`rNgx7<X `.NVHN Ֆ ]P+!хFeڈM!  Qї鰨iLh 7vCZS?B(lN!(y+O. 8S\ȀAD-KZA&p<9 aOr[lT^m]5UPc"/i].*/8nBcdhe;l+:FF8^VimQ-mcmރ cݪVqVIj87Sx,:ʨ Q҉ipPt^u(<^H=<-X+3hvs`%pw8@GF$%Fț05 <8!q lI 遈pu$<Ʋqƒg qNEXJ)^?$<Ij7Z7Z葜>㼕OS@!? @ L$7\7^ H93ǃA5krͅ0[&tɜ&#mu0TݦnR/cfPuPhB?&NJϺc*=HkMy0hu{T;u(tj&TW 8S(Sqmc}MMg݀ax}~snvcOOC ~ ExQ!VѼ8>C NjK}|=@ YHWxԀp.EC@;*1lX !FaBɘPRvdL@$(! <0EI$cB(ZP H,pYpʢYd]TNhmQp+GHʉׄ@j0j#Hl݌}aYy™gβ/Q(XOa6/Sƍ[#g);12t `2=w)3jYrؾ8#q@;& sv̓GPi< ؓO= H"c<$"Nbi [.! =dB/c=9CqD0$<_fD)#j*|):*z*jQ:+CH: :߮J{,*,),J+*"B!z-;.{..".;/{/&{  <0|0 +0 ;0K<1[|1k1{1!<2%|2)2-21L+"Y̼3=s]9?P6h?g4QKm pkia=6޲p6 tu")p oP`v /Ͽ/Hʂ1 C^6kڲ{`Do[:6?ryd>k亸3@v((ڧ@("b{؄<m~@] &qoxJ B{7NQ5&ܙ3; tj\;OQGV1`O%2qd)Lnvtv>,t 冟C?B5{@5* D[sC] 1 (ӛGE2#VuqE"n..<ulM,F5:| )4{zԳvFaR~ [ `udW=ڏvQLXR/Sֿ>s>/Y~a1%,N %VrT&  |AfЋ x |A  _@1Lm@w AЅ ADCD@F0DH{@0K%@{0NB%0@F%) $@P`/LA4/4!/A3FB,3$C3 8l!8,CƩ3@3GB;,G0;A`;lK XBx4@,᷌E2?䫈 Ad0)$4Dm'~mJEHM"K@\@,`Gd]dFe !F@BeO#{h'\_&&16'lYxDh'TAP&pfAZ@4A\@Fd@ '@#9:@5 o܁Tz F`#; 8$2 C |@!Uցm[ D#zcx 2xޅ9;X:2t <&xvh%s(%~*CP\άE%$!)Z d@ /XjBB$DxL/$DAH4>"xB/lGA&H ɿwy ۺ`]""O`%&@]F` @`-|MyzM,` XyD%DN`!&bcAVJ&gfDHVd)G@E`fB?O8aBF !fn.+(P:.fFG(@6 &&d(z+ E`4#vWf: e6zf ;@9h8(xfc8,~J!8eQhFhl<;C3hc<,Qpz@P;&D&8zF#=@{%"A7L)$) bIDK)kNZzPHB4ĭ1mmn@m$m1@-0m*@F#^Ly  t$m0͎NS &ƵH[uEXV{*KG0i)Kf+@,@ )$O Jk.ApE-d{H\EBh/sB.%zB4A2@L2.$@kFx/M./..B+,AQ`0, ,²=&3 Cw8 D#:=z A8Xl4v3;8C @6CB@c304R-=#uDeBdc2,hp: :p@`8v A!Zެ8m2aF С8{qNJ@hd pՂ]"Nf ]DN/. $ KEm/@ܖA-0܈n/l02AJC|ܭdp/Hz@rAB4n+B]tsm D@ Y@F% (J!!,؀ J]iC y ŵ ?[-ZDJ>P(? >SQ b)pmB?´Pff"IIFOc/'{BBl/+ a @4$D3BG@XW0 026cn2,gc48:8 Q8Z8.m6C<@͚`1vzgf,78AƒCFD#&D{A%C9@a%x;\eQ#Km;p@m_C7r)B, f)d?nkF$d]dlݺ@mF4HC1EwGCB@E^/HC/$Hx'DZ@r444BmܒA{,Bkm-lV&`- ]QjiV>f&>82DF)Dx]GtB@ ֎HDi D$O$@)bO3wgqۤkG3 % $TB'$D p9SV@0AʂKES9/(5/h5{,A#4 Ğ7a0uw7jz!mçwZdPVJF@hlƦN@::tc8ÇF&huh5Zci D;q1KG6Kt@0gJ56G{` |B $,=/r-%;M$+VgwfR@xB1{&P.KGJ@^.pƭ0\hG4'ƈk!@48{\ Y/n|F́Y fPH51߹XI@rǎ))>b`9)JФfP EFm0A.8!.9kmBp@doF|+UǫV=-+\5ԬSڵFv 21K\lBog(qvfg a6zvz~^_heGcF#>T6 7vfįe6f`H~=:qh: <[nOC )VBJNDR&kf+RS()“tG^wy;,m4'<|~f hҠsAi$$(Di6XG+XF&?y\ -["=mwhMp,"E?"g#tG{^|5!?tEQtjDM()O X锐)0ꔎ=EʯLK@@Ek ^Yj ^˓EYHlKOLJyrؙP 4e D.H (]8%.;%,N_=YG$rbe,bfV O `T`=SQn+f=l  Fe$x`!J9Ŕ d栎E0F`J Ȣ-H22!'2-J.& 0@%W4nj @v覘,I)*(d| i ,',JH,8u a*.rl~$(K.qR$2% MS,1DJ \ 3[ Re .5t-8p%@ m"!`k6Pv79HTQPV̘s뀝t";I@ I(K ӏ/ E a$9uB P> Ѣճjh ) ~iSxȒS|KRN{ _,4BN% NJ3"_f3K5?:TRE%kT)RɭY,raQK(TS'Rj}tbj\+ rtmL"&K$BLm?W~PRKsx8\*w@]3W4 ^l Y0E< H vQA] @9&D @aIB@Li,?9pdh@ tE[P20Gh/#HddQ.OC0<"H.!DJ{EƳ%$^c%$"oNQ %$[ )@ 䀄EwT(r7+aIK\ `q@&LO!4-ᓙ$0Ʌi +F H`ЖYLYjv8E*$gX49@Pd'";WYJ/@.B2$X'ȓUԬZy3&#'Y9Bgĥ"> @L𬬰`9 Eg FQUb5MiEq#M :@R&,a_$5(D-ґyd rb,$p 1F10J@ P@1b*=JpAOi*L(@;b)iQɓcIV7y'gPa}w?9:PT[ٝ:WΣ)C<ρn ?Ֆ#@)Vq"O ^VӘ D`HZ!Ց@EJ`GuGyE*2¤@@@)t@B2 \5"(hAN$x.h-ͽ j!'X@!KG P2V‚cv ıu8"v8TFdC8ؒ/Í"GG(iv~y53B®pՖ_pu=6ϩ]؜5A u0ז{$EzDBD) ¶Pbֲb 0*i ` 4'Lr N)+݄\|` 䶭 _x<%RxQ>EmI a,A@J;{eT Ӌ(p+a K1b& (Q"! B%@'(q,e ^X/e fL',jB,BlQGV,ed!ml`q$r0)n *\%cR2Qh@'bi 䢱VB -#MƢL)ڢڡSa> h s0StJځ))x! )AN5b,!+I[Vhj2!@Qs,r&s!W9B$='ah_n2)80. )(Jq.?e;% P+ rA"2ss4S$ 9FE(S-i&qׂ&-&[<<'w%i%2?EV:tT++ B*b,8Vz&nTbn*JUHI}+nb- s.y9^ D<[gTQ'jo-oYVZĚ=bE +wTDØ8S=avQ[ %6:! iq@g5Uc1t7,|S-*X` (yA,9voB,HpYDUAT5WXmYT8v(lhAY$L٪n]ՓiNT,OQɻϚ5e a'Q*nS!EA 54$OYb*W mTI"Hp<\$.["{0'i؄ssM!gG8tU\{j۶-7)2t^Sw<#u*W@5˜bT:uSa8veW-2]%L9o]| λGn7KuWfv2i$Q.Q''wgr=Ùu9޽;,~="Xx`T9u>3Rҳ)gqK>&>qJ?:RP5"Xa:,;k>3cH5^'?!_$f-d[,b` +!ѻ=W~W <0… :|1ĉ_a!_;6ͫ 3lX5jxȒ5Θ1EBq@`D[4bF -C0B 0X!"A2db˂/!13A@ $X@5 tf]Rwr-HwCiLkߋ*Ү^46(qeѢ-\@~He-B,"ǽc:vb J ݎF2$G.ASdEVBL(%Ae^~ &B3"։ #c;N) bgz/ 2O{䡊:D9 c' Σ맸#dN{dPtnm~ nKn枋nn oKoދoo pLpp /p? qU6Xl`\e\TP 7K-BT%T2L4pws)J;K4=p AN΂RjMSDuZo͵7ù- ,8ubKјNK<p) tQ/t@Us@YwMxᆇ5-!pg ͡ ~x袏~h!سHF`Ҏ= "<+ C/ b{M3B;t@;mB6,?3>PӈP4C#Aȵ NCfٻ@(< r}кws;ю-k^Nm/IHBp@LjgjBiNR0!!ᝒ& sKdHuÁTj^BVu|(=?-rx';|Ap.8$S..#`XE ll^p倃iT* DH3S$|p*RHUL|9^DfȬli<[A+~͜Hv"(Fv$?VJ4g0ѝtu-F&i,o-keP4z$[ mXTҖ1r [azՂ-O`AY9#2DGܡAzRA&2J [=~mHC|Bwp L3(lPp %U5:)ʇKT?P.gYt>a'B(NKD8) !,0K%O| iKy{Ј1YYMP4B4D+\$R38<4!w`r9DC|z^RId`[ Z&@T-ț. X*sP s9ZЀH-dWۡihg> _)Etm B|mcYspU!dN>GfWak:Z pbIYm} Q9.(k5M5*dD %Hx S"x ڋCC%B E}N9Msӷ.8$ ޴8dݫJE*HwZBBvxcA L3+7RHeQZ+80fC.yReF 9m9 )rE0GEU*yԤXS'Av3T.sÍM/;#gVm3/L?Dki5uU}YB/EgXc1U8^$5mMtoR{z_;lЎ~(@qZh"o n;x~`@E"k=q q>z,!p&JuS3{!8$:@,bmT@!s& J>ל\׿}d/ώ}lo}t}| ~/e R(>jI! [@W/ `E(NJ0 F?@ *Hd?ЁA"%NA &USHx}^[rb;ȁCx>xDT}<;:AW@0:Qec :/vudy7 0;@>x B:p hD@|@z@{$X|aY }2* +`!`?B~r688#tA~xPqP̰ `` y.` tVu H@Bx iw@Q 0 )؆wK‚͗!0Rq ;؃6Hr@`R r<؄?8QX'@_pY+@LH*a/&h"k؉q.UCq|H P>@ ?pP7{hp )0(xx  |ؐ1@M0}XM"&L18XQL"91 _R0at@g' u>D 堌єrpqLHH(78*0،abГ6Aa'X X8'ppY*@++ ޲( 8 P;{!:h x C"e e \`\e@0 ["P9`" If 'h>;kVvx q yHX lhXIX 1X2}@L ї M0,( }a }Aq  `  j 5 7p(E @gHg̀&@~?lY~AYq0xb wKNX5Жp vg6؅!IhR'?C!8p l%䙘~8<0XP:Q :Q* @ƠҰQ *i0"!gcp`AG0 4d$4P'QH(x鉧g8x w9cI q MB!  ,P  L`Y J jzM J !  p%_} (tPt途y@}Njև@3jwp8^`y>k~[hI[i6h?(}``}@WYtp3jA`5J:K~k*w}ǔ ױ^!k ܠA8GP dA؊C>`|9{g  n Z i a Ɛd`* @d0f``{PPe1PyP`  Oš* &Q!X Ȭ)h {X׊ڪ{;`` q Q z12[ "X  +Q5hP(E0q◦tJM:PoDkOZi 6E鳩(J IAe;tAnKZѱz! <з!IIֈ(Q(:ƻ @) 0@ эa0#ʮZKe` hʵ ƌd[;>` ~jYȸk0;XH|!| ,   % ) XX@ Q `Ѭ !y`w9 bpRۦHpFytO(]@C[>K@̀I]Is@6XV [ JRfm o4qaL_`RK~=K umu !gh A 8ܞq8@BBypzQZ pJ;Pi+ Qiۦ++ Y`ڒ f` `̯p r0Qz j' k &} K "\@Q *1 `"'`&p9I3z1mHcP$-;-Aj`0EcE-6HuG68[ pbMf g\i]km`@(P u -kH{ ?@ qѸ:PX DK <M Z KMk,zA0 p`̍0QQ4W=l8 a݉m ؏ ],8Py1]+- WyѰ: a"Zm +N~D}N అq>Z1A2>fj U `aX1&`RS z! h ^ Ɉ-"-CৣP  A`M`P *Z^OoQlk -)  {~1r'*"\NН*Q)g ;AΗ,, A yAqL@, Kp1>A(pL7*? )Z<]OH~l qθYoE/ۧk\ر!l ")` Hq(8@ _D0& iki ,P,EҌ]q HIh*8"5N6m'!TRM>uS l^:㢎:US2PS(u`>l8U dSB2-)4\L @,h + c^*LI`d&nr1ƀxڵKSW`i ؙ8ح3  ;vt`bř'/]}(*h]ڽ0r؁z3v89c`n>`gr#v vn ߤ@D(+N1E8EjQN"`!`Jhpɗ.H\2&I r @! X:h^hlV(N @ERPCE4Ѥq D-He*"",,HB”SShLD!FHuU]1M R`^f"]$5,ZP1bLPՄ^bH]^dr|n  vHcv>pndc #0=dġ'Hfm dO a>裏fg!g9dcsC> z(HQW~E D ND*ʲd!\| 1 2!r"i|IC3^e&2Ɨ^h(!hHH̬&6kB` %Rj| gDw{,˒1GӲ=u[ղ*^ WaLAN!٥,]P6Y% `4A~E9E^!np"'@TgÜq b9a2,A dXNvc6SGfDQX %G;MlEVpE%~;Q5q@N$Ue)ZO XBI{*RTIqH"CI "9h$Z+@rDe*mMHEȅ$D ,q ʞWt62+K&d&±@&@S!'T M1 VС +*I/K\CXCH/Lɧ_`l`ɻha $ 5#qV8GRBiD[Tn3iNuSTC}:TըGEjRT6թOjT:UVժWjVUvի_kX:VլgEkZպVխok\:Wծwk^Wկl`;XְElbX6ֱld%;YV֭G;Rx')-k(b h 1ZֵֶY=@P2(PLD=+ dJ$-RZBU]o_;]5BIJ!6-5 ~Uv(/p׾:@X%k_$uJx[M!p{Ab`B_*Pik6}UbU^}".R{Ԙy<>YA}‹<c-zAq4u6wGỵO=M[(Q?.x@^`&.JEmbo,A=\g%ua܍:vPm[n+wZ. >wuAk*^-/˙_5Wvq6f w 3 N]!GgM rܣC2';>PRfG/SuȠ"'3 JGs_F@sҗ>) Q"Hk^B]lO-u<(|lVx~qھou%Aok^ cG>I<ww$ 0\A&Js j76LCO#%RcP|h  $:8C/0@@R:K0/ @ d8?[kv-@- K<|>@B#@+A>A5(0ۢ@=1C+ A/A+:9#;5 C#A.ޫ|B6&\ ;k5DH[,<9{HDAh*4EBx3.2>KEkET䛝+;$l7+.C8 D[‹]\REnF_I?E7D{FE# ȁ,)<{T\<>`q E R`EmK D*cd e$1ʫDiBX@ _swHck>S 6sd9~8.ӿx $p`F|TJ;$[-B8.[.͢3J@PCPAA:Ϋ>kEx"+L5{JH39I4"˧ܱ\ެ=(T;RL3+H3?@A%B5CEDUEeFuGHIJKLMhOOR5R(+dBT&&&ЦZ1/ ]=նj@̤Jf+%؁JUS0QPE !Ra K Kz eƘhly*dhfh1*ppXpAy /xXp`>UYȃfɢ /x'ZK8(IVJ֢"-:9>`3J} x?NF Q9ъxK05_Sר u!X !~)"mXvx&ZP`՘'Rx5Yڡږ.mMbZZZpPv!9ڋ S (qV"a0{E]~-xۦd"[[00u '\v­8 2Y 8c52⣁0Q5J*ـͪ崟eЍ őuXݚ e"`݁"( v "W[佥V} Pؖ΂m*hO*Mk 等&Єqq&h)UЀ)x^Ut(u >Xe:@f8eP;eH:%;2 eX;9@e@sP߁;:Y;0M䍥;rT~'E'┗:RR ខЁ!" [Ke] .@.4(43 (^^08`p2@H$4@fj 32`@o uAحBhEheEȁB ;1 ۙJvZ:DvXhlPx@k8DH6S,C;Fۡӥ_ࡠ y#( ݞ^9}X^ȅȂ8 m " ^b ljЄbW`W Wؓ{a@~9QYؠ& Irx/'0V䁐):.R\^ ю⠒Mܢq(@nc,h"55IP%]VWZ>ai _J2ȜAc0:$v$(.|H2(vM^FJl9:<TP + RY0t"J4Ϡȁ NMÊ1 ؁e 䖑 V !Wn\P&] pe!ƨj  $k(Z ظ xx zٍ`Pf 99h_'(/ۃ`P_XXߐ^ʶl5/PVt@up^/p"!P@\ puVk8uPp00F>!"XńX`jSYH1(` !v Ј)702o)q #7؀` -@x8\iH `$ip$_؂-17a80i g~xk$^AABЬ>y|$pv[|Iܶ%r?P?JP:9 6!cױɡ|{/ˠ?9xVE߅Z[坦ilʥ~QhJHqݦʰbH 0PR+ ^hkb"sۀ 47pHup} (0|[Rup_B !qfd98KߚhcҎ p^v0f\_v7nPvy#Rqm &wʍ H-%m hlV ÆFkM?H3f/i&P4_E 4%74Bƚ QuR#6k.|7@~6la;#ڐ߿ g  [ҿ?`@Z'Cj xFQؼtjA:5jEm 8u!ѥErCϟkXm1AC3u>EqC\hMaq/& fW1k@+4Y C&~ C7%i=ؙÎ52N:PQp w82xCs`:/ rW*8 _Cx#c0;`(aQ"ZLq`ӂvl5Ї3${5UӍg˜=r CCBC;F5(:v gbԤZk` 4ƈTB L1P*C)AlFQ M1$ TF[t5*ͣHNI0+cAUT/"5Ch-[TV !;UCXy?pkVKU=-hӭD_66d5IFO - Z(8^l){@].QK| i .rEC vM.LK ]K.(.[tC: (2 ;Xn ;4`3 26$'$Cr1#;Z_~731$P:$ehote[ZBN+nX%Y̐cZħEh(hkQR4H\ @pJRC"Emds*C$TS3&+0+42?\u?05/_M{!60WCA#]Gbq1\A.&yGMe4|+2 Ę9D4*q !8L6?)) Ww>C09 @Hdž /!M,B&,f4`5! yp~F";@8v(!aђ1r ;Q66x~'G9I#;:rdH" }N Y@fD<@36C2@B ĔȐᭉ%ƀICRJy 4q+XS ZEj#Og$)qIאACVXqvb@~O1?e1+-gߵ!@R0ZW, 7Ҕ8!Bȯ$6&@ 2 ҍKRàRThځCR*4fUr 'P!"(Jf6!!j2Ph'A*TqtU\LHT,57@+`:B A,p RȚoedyGnk$9H0Av9D i8ʐ5pe~0[2D2>IF8`1L t1K/ 77 {a܆<(P" 23#dT!J7A'wO~ڄ CȐ AW"~!Uh+ ,+{qaZx59E^=,dNI)JA՘—-lQJt@f VfW/C @|S; *R'XCVXhH mb֧_%̪$@HA9 zt!ZR9mzx,8#@mE_6f,69F!]2Pidj4YTFQ'Y iT"PiS)؜XOj(1.M؝k/|(.2 -!j "3N.a$ 7.8DS +U]zW叾52$/ Xwh΀ɵп@0Z]."[+4ƥ&.pHRr]$0U!mQŴi7JXynSԸ!m9}37b*2Z7Tmo ^܂h-N Bdy,bL@.dv^!i쓍yΊ)+C¸u>:#[s`Rk6:gq܇? Y4;A( QAMҐ9 mԌF~fq#L$inƽpF:i~49C&.\ONQ}y,XB](:;Sbbj_$1M;$ޮ=bD}ϺmmD੗UГ=\>,XEx\คW `E>̃=p^T\ prD1ǽ\CCXPPT=4DPC ?P[DE8/ %f 5D Ɉ5D (TB5+1\(Λ=akPb &.(\C '~BU9,DA,B.]@-LMd',`CX(\t,Bޱ$t6DXq_,8 CyQ2:C8QCxb2.Q88\CA8C:1Āb(Y3 8Cc)$13|#/$8T4)9M"9C:(ßaFA%\(x)B%A+%d(H]TӫBG9J79D\CIB0 bB=C=,ÄARBCB=C=PeU",B=ł "L"x%R@= ̃Q=Х"\m"rbb>YX(^C,&\!ZD47D4),T3hi 7/lN%YhO TU[?qvDv|q<ѻohBT TGCC~CᙀGXRCgq~@ qQUGS"u aV_1~Cߚ@.u20c ^Q¦dҫ9DȐZM 8:@X9o6-5H)⚱ET.{qIIlCL L:CpCAFOnClOd:O,0wEiŸ.;`28o >Q>sFEXWaW71ǸWY6ZKE;Z \p.&:(paA`86khd E8DBZ„HGl/hz P-w/|]4'C .4A84U$6P&BWO85y^8Z ~ C$}gy;ZFm-uwM}=fٚ90;10}+,ڈ*I5H MC@ӁHL 7|/Nizlj?hvLCA4QJ/ԺCzCSļD!{D 4ܶb+;b f{^{C P>}r!3"25X^"ȿy3D1@RXhѿy 0߿ :#KvtĨ)"QBpF,  f) %P,u\IfMxDZ@ WA,@@QTPM ^ ╡h]vDZ3;(؉+x\_TJ} @, v0;(X:> ʅc#d}1a Շ+:vw#`R#/8|7l߿s-(6B)KQ"Iԯ#,3 BP"ʐƘ:E0FF !2cCc| Q|" 7Hɍ p'pF$`F'!pH i!"BHJ) "S*IRE0$ ZRJLD# "4OB)=L\%!N⼘JXQl"4H*ʫ]0B,̂YbV "כ2;L0 /Vh#: :0 Fιq"+sEر&v֙`bM ˆ 8d k xȹtK]a;X_SBB*ԇ-Sx>J9`R~S!C4TQB gA^a 1 5 )2zVP-I:4dXXb$zǂ|#"'M$iȆ ʛe!p%_@A"84N3(%@gaR2N~(Sƨ@S$M%I( jYx ]x,xɢVb-(^H%@#T% (?쁑)u Rk?$K3pH䠇tāPF3"`1渃qw0N:Zݨv!%尣v(9R0[1qy j80̀i epɎ8@HK}Kt).V% |SBm~̻bY8-h cpP_Q 3p "CG$T 4a)@t]4@#|"J^;I@AAۢr@!'RoC!{*sXD!#Q)N i?@[oH?@b$.Do#8m1‚4C!n7'u݅wEQnFTR~Lނt#a9. L"xYX\?EP3N좚i.Ҳ jzK 0rSɂճY;Rb=sm1?!R/Xba)qcu&5 ǝ;A8Vÿ neȁ$_aG`g$C8a V8]`'a_,:"1SgpvSI1XuFh EmhMːVLh+JP ՞L,?FODEz)HA@>?MPJTkNAJ,; #dJA! #OPgNJHqot@R@@HЕ_v|HЙdU"jP@p` 0B *@$ # `:b2@ "* b4@.(0`  ߐ;P`0B 8@@ `/0G ] #V *%,1%L o1U`Q1"`Oq K#*Qɯ#"|l mJ@6@D>o@ M Eq/{X*گ \`g 1@!` @$^`" oa"( j@ p!R$ ;1$@a@@(&m&q2'ur'y'{Fa|r(($())2*r***2+mr$BR+r,ɲ,,2-r-& !O2-..2/r/,ò/30s0 0 031s111!32%s2)2-21335s393=3A34Es4I4M4QS0 aXs)S5a36es66q37us7y*07s88LBs99369s::-3:3;s;S/;3CN>>=s??3@t@asIX# tAA#DtB)Ba(,C=CA4DEtDIDMDQ4EUtEYE]Ea4FetFiFmFq4GutGyG}G4HtHHH4ItIII4JtJJJ4KtKKK4LtLɴLL4MtMٴMM4NtNNN4OtOOO5PuP P P5QuQQQ!5R%uR)Rݓfa"1!(.,uP?ur^3$mT1o8!W۱r." ":raXגsNUP LMVq\a!G2&,+a).I<*b`k/5ZuZ N̷ȭ#. mBU]X޵#+%22&.c{1d^pX;"d?6jdo7oBdfY !s2AwAoh(̣Yguhe{iEBg}%cR_L[!bI5% Wiid0"a!"e7)>j+b+^5\G ҤIbFL6GT!bpV%p [,#bY v5!!O`o MPf &A.PLڡn"ko p brtv v7vKnctoWx+PpyWxowNXr 5y٤JWqAB򁕺7z1aw"^}".k y Y++!~A Xx÷mnH6T%-N*2q\.Z|)alz1}K- O.. Y-$}k8yUB-Nx Vv;@_$X"x[vB@XlWL P5o(.]kG6mW Vaum "sj0NJ7UA˸T)2?³>m`;;|ޘ a.CW>I?8DWᔐBsReg^)k4}4F=fZU!<By$xL$H;`CQWOɖ]5) =-bVrtH;? ! mtFOA1v]ltWȦnZWK`?!Z⨣I '] jFX_9Vŏd,V3xГS渀pVO&4VX${}ď2:իee"j)Btk*}lHI~݄fE0k=V߄~kf"xF. XlOF~L1I"A&ꕲB" MzPu"A 1Jm҂T+nUY9ͦ{J[uM&qb'73)vT?OikC ,YrGhh7S4)DJAA?sO=𦪛9 + ^Em4GNMPbWF`w<Պ-_•Fܞ>6ygymUXƕ!f+#IT*<fLE #B!tb" ZM#s>r.؜K/(AcC8ˑfG'o3RGeh:㻳I!cy8X`@fu-DQ>:QP'rlip,D=WS4'#yw ,KR@ؤ {&9q!g(.)V }7x5RS,)I_$c>)zW/ B\q{qLVY/#L>(%dtbiJɘ}U( `#NU# ["lpHEGa6'PId\2Sg:<!&q`z>deO1fFl1?&g@ r $ESApJ2%.?pJ @u1!"He""r*d6Zd A`DŽMD| 32*EKS?ZռSJV>ǙBPR bRcɩ$ UǡF)mka$AP"]g V3Q"Gu;D} LiB Qo?R1SAiɇ lp|/DPΠΙz#2803s,D>EOdu *j IB[9ANDG+W0 ~Xw'f` *8@qBЅ) *b|6DML:^cxXtYMUr s2rBI&@VY`~&DArRs/&}4U :OG7|\S5fgN4Ug7#\m $7pW6,t:;&*͈$bi`2:-:%f&%RQn~ PVPU$hF[D  R7#j2IRΤ0D3_lpvRC9V<}^Y-\lJVsI 4 @ĔbdXD 38"rF"3P8"]~38P u@D_0qD`$=bAE!œ: "u#/yvQ.y |A3D /.n^ ,(tޥ!.I7 ˙}7ozEC|1ZHo}$PGx̯3+n yAEzצ ^+ӝHul QGЂjǎWUBx}&|J&֗/)8[m`ɹ@:Em@X#~ψ)S4w rm& R'H̺ugֵΓ?/'57szs@eG}^o`Xk%bX zl#t$H>[Sȁ3(X-331sՂ_UI2X j6m%r9b =B8DXFxHvphHEb2xR@#rL-h}~2@UUXdfv}lr8tXvXPKwH.T~mj2؂8Ȇ4lwu؈GI:3t`8@Hx؊8Xx؋8XxȘʸ،8XH9P RA:b/`5w$"[Fy8.(rۈ0i$Yi,`D8 h@(\㲏H]9y " h!;'I.ؑGAk#y8Xہ@s׆#/,]o1p' S H17~Xl0ai2T r&ٵ(QmTOXlUQױ@ "@yxY!PG 4A6Y|(a-, uV$qz)xޢ'd9PJQ8)F<R@cL=B`.P\9t)U/P<. `җp6w,ڢ.2"J.2 1(tq{F"\3$Q710`g4(L-ANbC'*E/:tZGȓ,rQ9Be.Ms.R'9BtW;^agB&s8d)#4ՄCc2ˁ'FG +!0[ꐈiL<)oz#O)V#o@wH j8Rtqp ?H'd)dlp4)\Yqi$U;1 B dŹ["+XU%2'ɺR3aE1&B9HK6 ;i-JTN3)}e:C`ASr/h$ ZpB# aVA9IDJG&80Xʚc Qm($UQ+sF0{4?'0*)9paM"Vc29~d,5͙c䓔"̊+RHBr7dF#S5#DBFC5jI@Z%jlWUdBCuDBa{oa,A(b)kGͺk,I##A7q[O(uaXXpz(^ SQEpZ'8S̃\+̘zGɽ8}Zi1'(\sZl<5bqx&ۡ͘A/Hr#\|kLs'j̃άļtLXp ̋/iFBcmQiLΎb/Aτ8.#%71MW>'_q[hbN&N֙H&&cAre3(Lg/ЯkfF*}+e DMπ{F3mFlksҼf8unᲅwt5Y`7:Mb}:~H@tW\b$(P= ѭyrA3C%G4$EH ҭlŒH?2eh"RQ-ʅaTm]N$%34I֎CU1-Qם!Qssq@&B^,oMF A *?rF_V[UQC*q$z݁0U7}9clGkHRlw ^-%4(NLB-.jhR4N43ewl+;$2:h U1%b6^"(j;QR3 U@ Gf:RPHS1E"B/GJ+Tid9DtH1&KBD]}40@9Ac>M=֎E% 5 "C Y-*oC@MRƍ4Fڧ04Llhݚfuo6Λ1JqC`Imu=ACD.SFeKKLWWр56|l&36LHBiX#fQ&r bRXEL 4x/kK(tpw1*7:)=Zߏ9A*#p:<~ss@-4r2>0jSU!6\+變(E %:[VrMsMa9"H>v)2P*A.&pbbd);=IX?&d>s0i+0R_ $E $X $(="C!CQZqQA~,ЮA':k/enbJuc= jߌ4ߠlrJ%r 93u(d C0$IcidD XΰYOtDboAyAg!/,(*hs4r8dAEMA  R˅^brI3̅%("يp2?Je!j% 758CوbH\aMIF|Q~S|$:~ۗeǮ)*Ă0ev"'5rF8' sHP(8L Ty{P$A𦙳s;*24&5DZ#+rXCbIy#b!>uI eD4Z׉YcT+fx@ꔱ$t !0= ڈrfte#M@y^OpeQ"H=sOHTY@")".@GVQ\ZjX mxҦ~GmCᘋZ4E ̺īU:4- [? TqE!?D\Éepp4ZLa-5<iC%p uÐGD~$FrؒVhI@:[j@$!Pf Kk"F^: #6l}|H`ODM^Į8nA58UJ,QACj)6SIPқ)=3{f~̎y&O NKS܍I>͐. ŗHI7!%.OW#C&#`JQ\ R} [аnk.oh b$xߪKF]a٤oBBuBqAnO!A2bi (yѶ_*Qͯ䪺RSr +1}W+)(^m(;jq\o ;<]Dg |Iܫ`ҽVljH&Ze+% V KLZV5Z=aD'/NIqK!{dfP*e:*yRYem}gE̹;t˭6)o(d(;UBDCt_JE6*KdxHQ #WBvm-]5d x" 9c k2 %mBv>i>)ט33h*h <i%XTC D(m˽ˇ>y9ta"I `6 +iު>" 9$~ %32~{a$!z b>xH:;13(@ -"2"t0B1lu 17j*"2tL|» Ϻ9ژJhEÉ 9¥1ژ1CmbV&ÈElşLҎ3*jLd ):h9liTciVBU\bD𪂐Ad܎c 2D ;>A)S uxEhECHHxB   x:)B\D``<44 YxIItDAYJA CH6ȡ<xTq L3"nK"ꏸ*AHX+9BHJJT%`H@IɜʯK`< !ʯ$0 -Mt9<ǪKKD˩1&AK ݤ IKB07M9{iKe?6LOOOϢ}OOݙw PXLMP]PPbPP P P P Pѳ8PMPPp%PMQ]QmQ}QQdQ=PNQQQ R!R"-R#=R$MR%]R&mR'}R(R)R*R+R,R-R.R/R0 S1S2-S3=S4MS5]S6mS7}7S:S;S<S>S?S@5e TC=TDMTE=]TG}THTI%а(ITLTMTkTOTP ;M3Q-US=UTRJUVmUW} UZU[ 5:\U^U_ )UaVbU*VdMVe5U`e}VhVEuiVkV>lVn3M7kVqWrRrMWu]"Uv}WxWyWzW{W|W}W~WW XX-X=XMX]XmX}XXXXXXXXX YY-Y=YMY]YmY}YYYYYYYYY ZZ-Z=ZMZ]ZmZ}ZZZZZZZZZ]?h []F=[T,՘ϸCۻ [ܵMX m̳d`9% 1@`E{B:\z2X ؘx u҅܊h޺ q {ѕ zh3 ]!]ݪFFS^\Hݞht^t !3q1F&A($pX YQ'D*A:  _P{%ӥ3 xXQBpJB 3~yyh_-s11{a@ӿ |޵HyzrJ)TI4M';pӌxa}m߹Ķ]+Rb rD-yaٰDCfy!}@+ RcsiE`э 'cA#YXK/[)0A?!zXND !)a4{ ȑh^ŠIģe6×;cJs]ꙍ۪QI< M fbf)nŰ9JR]5$cY7`ʽ8 ys87@tʲRI"1 ^Ea~FC(61*fhaq ~FiUF뉍@) *6sp  ! Ac@#y@o-ڌR(Co[G8(xt{(e Ap M<Ъ9-ɶ4Z},N JkY:{W|*с[d[U$ȁBP\-4 [4v (Db@Y3$Á/ ($#p48 ;.j(gAAbA0@!,$`ǧg 9POD&u,ׂ6""ك聆.CdԠS$)ʿ٪ׁ]pm1Ȓ'Sl2̚7s3 E_ R0#B9&8_B4xʗ> [:s;Ƌ%J]uڛw/3遷u%?a6=iC[lUFqX NH>qp3O|z!!8")VzlpkMPv#B!F{XXy > d'9ϖ()3т|VDj`(?38$^Y=!Hxv@:q)$A aSPzyEyubiz4"1 $##IPd;9A',4Zj6<߰vRM >ڃ::!DM\^~?4Ԓq*h8IG@RF48R>4))3n}둄tdZb3GZR`1/s"ӂ50e?dJDŽ28?9!$iC %Ԑ-ZF6CJfx](Wʱ:WDzPQp-pCl#YELCfS3 I%9aM1WdSKOgAA: ,-j24(GBw-iP@uNJ .̜W#'[)P:E1ĖQ&2a"&3677nv¡f5zqejE68)m^|"YD"zE$|y\K(stXf>gqm]*L$(Źf&=!yY\GnppU%F-(Tjڴ1'?V24~Orip9Z<1} }$k@S4>eQyhADA-%]6 XA ܐ4*4ڑmXږs#S8*  `<ȇ{<+qq"b6DavL' ̖K; p$"v9j;w4z#~>9Ѓ.F?:ғ3N:ԣ.SV:ֳs^:.Af@`vQXbnDqD: "`C*À!| 0B t j;)\@2Lw*}Aq( Сt <ӌtĞ2'p=  *( }02qr otwƖ{S/S@2""Cx`Cp_ e\'x.M8;@fN ;p8TP(`8DA;,A0;<_c;AC@94á(BہB@C1JRI!`A9dD t_ d@ )܉5sb, $ ; ;@`fH`Ad`:pfdRF2;Cr^@A@,A rAZ؟]h)|4֙5!A_%8%x_cd՝)!@1:AB(aaceh8D0AA 8ZNDc9HA]G :bA @@D9(|LdCG#(ct*(aD(dA4c`b%ddC"IdDdHF$;,AԤ\(<#2D@ d%A<WU`f@ll@ApCp-n`6lA] ]A1eAE"Ae0FaC-R%_3I<4eD78J/&/BA@&.ԣ..0AA8q&-cAcC@As<@*_Ad/hd,#08Dx2?BF*;R.AdEN8@I$E "CA@3P`:"WdAE;Pb&$ ҧN`9Tdq@!;$C @t:h"!* 8x@V`#z TlG(^f0jU@,vI/HC4H4J^@/tAAl@1i48晊AAhiixC)eA| `eDf)hgv_&(j]-ٟ7@kN<@:AԦfd,H.,\Ag_o^AvB>not.xB@4AoD>\c,6D DF;1X{^h3d9{2z! I"CA D A:dDf@L9(2y.C8d.3lNA`A'f 쁼lb܁{gA7pÏnF@ 8!@ )Bmώv Uf% m0^APHĕCn))4A@p1pcAi4nB-hDB/B4A@%[m1d##W@fh! ӡD>)Dm@0,*kv_UW~#>kA$Aa yf& Dz' @6>Brnj/*/d@:D^+z 88{r@ (;@ %;@$@6@p%JD: ld@(@CH~ Gd (@EV T(Adž .:hAɢ"hKzhf[,f|)CXB1+aAbTU:h,vfe).4TDH4~)`.AbDHܢ"|4Fd.,"'Җ.AnA(h&.0),()”)d*c@&+/Ȃ(,+/tj/`#j.D\' &.%DpЭ1q";7ęuJk)1i1?8+ak;%AY@`rCD%c_1C\ݲmcppztf=j34DvBAL1GnB* jw; ڳzhC@8;^N>_LwA$R)*\2%Ă ;>H( @pNELDMHe5$xkOgWW[)΢CDA0)fw(%c8e1e[wYC.@ԩF0@B-_0r4Fqd`("-.{6-hjd0(g.nk6vmvtr@ ,du@p6x3AJC@27;87A4uc,vk7Ap7ƎzCHz/;s7ʲCJz+~~,@k:,dC #@8 ;f5tC6)+:VkxAp0{A@%p2WS.ܦxJKC%B[k`øApAw)0 6@d@#DkTFrClAO*83d@LYTKd#g®ODL5VRF(Bw=/L.@4p/,d`DOD0`/ /\*X4yr+X\ Jؙ8ة30p;vtzaE%v 9;g:]OBm.]Dp@]&Qc $Pn(\tؕG(;<&[f;9Tӱs&$NlDIMpN`RȩL& :S),8UŤKƤ 4z|i[|^$?X~rK$ m + L0EAĿ\KSjhJ*1P,|MS*BvLKPP@!H9*A͇Nd n<ŒPQ,|"H ]d Mv%%(Re ‚^hb]. .7NKP4b) Yx6y?Xri>p #uhf1v(3#uعCղ:*3zk-NB(d/ \SHY0USjQ# > eǩtt D`P~aR@F,z"@L?`9s:.2;oh;i0bH> Fc0hcS$7h bd'[aAEhu~=pˆbC S^Rv0iO1kkQp#ìX߬Q!S,ME:#bo^ra""0eɈK"q1< 3Ό0tNzP脜2'0rt'd*f? mw4e*vh,pUVZg8qjq,Yr6") s7AYvxêQJ "b [qC )e ~ {:Y vAD ̹@>@ "( % 1@ iXC'B0""M v?DID%&i=@I|$:h'7 С&4F5^P@(,P t L`o"I$'H@QH *'LP 9@$*5.(ȵp bLfr %(I&(Giej t0>@L Wt@#`:6vrp d(A. DI:? | d"z^Ax #B)ZQ ME+AHIZR!(ʙR1LiZS9NySAPZTIURT>QTZU^YVU~aXZViUZVq\ZWy^J,bp"$,}.}b)[Yˎ@ZDC%-"X Dv,Ь^(䳨hn|xF\>Z|O e%JgA.oݠAŭnrܪ:7=n\׻M}yv$= Z ైvHqߣE @"Chx~\W,` ^Ăᡈ#E* &氆b[ēEb@!1 wKg za ڣ?Uq_B@K BҒ4*iFӞ^%@ll4ܛE:"6_;^Ð [UwE3xD8 g bx>|~8қ>1٣.@ׂ\Z$` bx)m@՛rwV?>h}=Ql$wbx]d4y& ^/| ȅGC)sshY. ^ֻ6V}{D[%YZaX%ЕKU ?-2f}wA &|-ϼzA[ڌ+2"W;^FՏ7y{7 G7 `hW,WXi%*GMRfַ#!h/*AGC"⳸$̭"b|#4O@.Nn?h 8> %>+`CP@+2B_$3b@VhyP $#PP ,jO  @>  TM0Z` cf0 k Qj/Ob%p 8nhq f`$V\ %Rd$" ' Pp+ԫN1Nݐf MNbiBνh`1k$1f>(NF1̘KM5ndLbOMqj˵ r \и" af/h8"g HRk g !\p$AqQ1r2#"E%$/M-@Vq@JL .yrA@Ĭp%maQј.M ůЖ՞@VH"rKOp>li:夰%..m*O0( .3I))O1li< *-m13O+c0,O 1U/.S޼2i*h 8Ǭ$ K@ aAgc2N3 NZii'LOOOtt1B*a@x("2>tDPR$QKS-A*!(TOum`ls Ao4§#"$AW}tABVC~[ PEtt #C10P Se\gu$k&"|n4xlNkP eJ]э]}]{5H^" M?^gn@E3 "Psv@V`maDO".{*VA.6 `iXɢc zfdadMZYv-T v WjFu fo6gogAjJ~ UBF.TDg R DaN#j-BEjҴ\\#"kh5Z58 ` @,xK  )"2 4mQ"W4("*6h"%b9@OWR8whY 5" Z9(V"b+$bX37ppwBXOw QB85 Zx @X{7FuS@x%rwSUDc "D *fN Ѐ @a XLf"b Xd"=ʢ@JEwt%TDdcxk7"0,5Vm_tÊ֢lK 2, "gO ,Bf6"wFopA>",b"4 ATALUH&dy<}xG(*.) xf"V(wX|"y"cS(G(EU&%?Qz[Eh'fW}WQz (J7,nt^#"f _Qc ,9"ȃc 6:#"D,Hɣ#( "bF:|$(Ƃ9bf] I# &௣IC @/SCt r˗G"u4vVGl(LIXa8#oghKo5\Ա(I֎%J1 `r l ;M1l>ŀƻ! w Ю4)P? @6AE`=(xd@rN x"8)*Ih)Rh]dq$@}6WDtx T(hU Hb8"qwK >k=%AXaֿ}BM}ts ~/?oo0K~W=)k~n/Oԫh_!3,= ڋް!9,= # W+fP2( y8N4=V=9!!,= ##%+--34588:>?@CDDMNN\\\cdd $pXh2e{0ے/ʳX.F*X axLeAX;L[dc"Dba$΄#c[\ƛOtJ>AO%\ o(> v9&z~.V!!0,=&&()++DFFZZ[ghhJ d0ꓘVvqԛyY+Аj ײ_5`3r&|A]LNIZ@`@. !,= ڋް! ,="#$+,-?@@CEELMMOQQSTUVWX^__ccdnnouuv{{| $The{0ے/ʁ*2ZbA)m%0?qd$>+zT[ pTy`rM"~_P#{2  # d34V_2!!,= ''),,-./04669:;DFFIJKSUUuvv{ $HhJBں$3}. "-7J Ehp"4EB!r[w鲣y_E ( l"4{uypYgx*m%FO!!,= ""$+,-22399;CEEJJKNNPOQQSTT[\]fggqrs hahZe ʺ$sKbn‘4aE ,X  " #c)05H|2 kY#{a,' "J)Ppi?#l4#F=bK4!!*,=!"#')),....0/015676789:;??@DFFGGHJJKTUU[[\aabggituu}}}@pH$$es"SUVndxW(ВD!gJ C!W! !Gpz!byz !yDmKG! B H CTeLYΫpE]x A!0,=M! !"##&&('(()*+..0234678789:;;>?@?@@BCCGGIGIIKLLNNPOPPQQR\\]_``bbcgghfhhmmnsstwxx{||@pH,Ȥr k:tJXXRPxl;` EsV.`'։uH xz|~fQ   EU0)lCB 0#BrZ&O'M/N'S*`B C#fQ"{0})(0$S0* B-00-$l̲0/Zl `ܔAyDh EPro-(C8 C@!M&xL3ZDI % !!K"a &cƘ9PrH(#d@פE3Y` 0ũ!Rp!^ ||u&SkGR}wÈ}{Z>ƒ !/,^= ڋ~! ,^= ^&>҉NA^X&xJ䧦X!<, fK ! $*-3388""%*(.!!)%-)+22-74# "(*($,33!;%08" %!*%.( <3,;2"#$&&(&((*+,..0*424 >234668688:;<9B;#F>>@#C%K(N'P)T+[!C;.c0j3s6z8~AMJXP_Uf^rdz$LB'VJ*^P>@@+cT,fX-hW.k[/p^0n]0p^1tb2xf4}i@&D(J+Q-@6D9I=N -J> R .U 0[!2c#6f$8h%7k%9u'=A%NH(WU-f^1q|(@d3yL@NA SE!VH!ZJ"`N#cQ$iV%mY&r]&s](u`'v`({d)GGHNNPNPPRSTVVXVXXZ[[^^`^``gghnnpnpprssvvxvxxz{{lpw v zj6t9{<~~79<>< > 5m6p7r8q8t:x;{@A DD F!H!J!M! >!"#?$%%@@CGJ~IKǥNѭPӮRڴSใ*C+F,H-K0N/P0O1S4Yf*k*n+q,t-x.{.}006]8a;h>?BDGILǫNдR۹T0/23456š6Ŝ8ȟ7Ȟ8̢8Ѧ9ը:ܮ;`*\ȰÇ#J T3:Ɓdɓ(S<‹0c&4^l>4̟@ Jѡ,f 8ʴ)6X4daUdBDȄVB2 !R`` A.:l&"tg:{f89+@GsDŽϞIr9S~aEd""o W9Bp Bg0_8_ Q`܁>,ZԔQ~Vk AbD B >($bMaI4D.93bXJb}TiͱbQT!;p-;x807"TbA((c ̳eLCyǞ{}܀%=db '2@LnI!S:-i0#3& <q+hp#Q88@=*Dk N=L J|dE9%+UZ u>U )f'yy ^DPAn `Jl2C0>@!PbD`B)UB Є}|2E @1$T)xBL`!0)e$S@L@aAB@u @Ή3܁Bs#Ύ&u]ǎup3~H=Q ɘ@&8"u6 G3x(bס0^;N@'lM@0'Rn;tD o&äE[Ff C@0jAB! # EiXCMԃf {˗q@fXC3 -b@" R G!cO!# Q@ 2@ 1 p"A؀e_!(LI #aq2tĸ+u )HtB! œj "/$H@R,4!!`"!W cdXe@2 YBPGcdD0<R yE,bq,2hR;jE_|bv#QBd`X8t#x9h%Ĕ{;z_3D(Cpp~*ԫ!T瘜lOoGQgpT9@f`#` 2H$"^@d@pPn@ m501T@π @u>yRi>44^=nSDL$=<ݖ@ӄ`=R}:Ő.:؁V!Q! @ice";;N"hQRH/cb 0)QP0F&eP0c4 3.%!zL( &L Xi ы DfQZ!ŭE#%#5X7,@bE/`帍Ӝьhl V@wDc "O4(8aRmQ3 iȁm vw!;qh7@"1aƽ6E V rw* aΘACkCcO0ED\W|B HAA #``0dzaYH  c 51 c[ Zt9@aȒP`o1ф\C1`(50bTC Yd$5=t3(DL9H fT{AD,b ^d0;^{(թ=V@;\ 2;a=h?4Yj>0 _C jVN>öK!L2*fWVXRH@) zZBEЄ& }Yd9Zx&%h!@fKv Ye!' CPPHlb &2B#5.r܈`;24Ѭt5'HxuĠ7DF˽QHnUK7Mj7ue9x9uHpƙ8j"XJķ*K!2X7J'<n% `  m dғRp+jA #LK_F u *Ui0!KBlUl=fJ} f`%Zn SGln#0c>' Edp !0MX! r E' P1 x$L@[&'G@F%ar,Ãu Lx "r us0 E\]w!RM4Xw0>LN*}7T"^d S4uX22#9ua*X7A#~'aJ@xb_ϐ0y! :.CO2 ,( 'q `d z OChP
Example of setup/setup_file/teardown/teardown_file call order For example the following call order would result from two files (file 1 with tests 1 and 2, and file 2 with test3) beeing tested: ```text setup_file # from file 1, on entering file 1 setup test1 teardown setup test2 teardown teardown_file # from file 1, on leaving file 1 setup_file # from file 2, on enter file 2 setup test3 teardown teardown_file # from file 2, on leaving file 2 ```
## Code outside of test cases You can include code in your test file outside of `@test` 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 `@test`, `setup` or `teardown` functions must be redirected to `stderr` (`>&2`). Otherwise, the output may cause Bats to fail by polluting the TAP stream on `stdout`. ## File descriptor 3 (read this if Bats hangs) Bats makes a separation between output from the code under test and output that forms the TAP stream (which is produced by Bats internals). This is done in order to produce TAP-compliant output. In the [Printing to the terminal](#printing-to-the-terminal) section, there are details on how to use file descriptor 3 to print custom text properly. A side effect of using file descriptor 3 is that, under some circumstances, it can cause Bats to block and execution to seem dead without reason. This can happen if a child process is spawned in the background from a test. In this case, the child process will inherit file descriptor 3. Bats, as the parent process, will wait for the file descriptor to be closed by the child process before continuing execution. If the child process takes a lot of time to complete (eg if the child process is a `sleep 100` command or a background service that will run indefinitely), Bats will be similarly blocked for the same amount of time. **To prevent this from happening, close FD 3 explicitly when running any command that may launch long-running child processes**, e.g. `command_name 3>&-` . ## Printing to the terminal Bats produces output compliant with [version 12 of the TAP protocol](https://testanything.org/tap-specification.html). The produced TAP stream is by default piped to a pretty formatter for human consumption, but if Bats is called with the `-t` flag, then the TAP stream is directly printed to the console. This has implications if you try to print custom text to the terminal. As mentioned in [File descriptor 3](#file-descriptor-3-read-this-if-bats-hangs), bats provides a special file descriptor, `&3`, that you should use to print your custom text. Here are some detailed guidelines to refer to: - Printing **from within a test function**: - First you should consider if you want the text to be always visible or only when the test fails. Text that is output directly to stdout or stderr (file descriptor 1 or 2), ie `echo 'text'` is considered part of the test function output and is printed only on test failures for diagnostic purposes, regardless of the formatter used (TAP or pretty). - To have text printed unconditionally from within a test function you need to redirect the output to file descriptor 3, eg `echo 'text' >&3`. This output will become part of the TAP stream. You are encouraged to prepend text printed this way with a hash (eg `echo '# text' >&3`) in order to produce 100% TAP compliant output. Otherwise, depending on the 3rd-party tools you use to analyze the TAP stream, you can encounter unexpected behavior or errors. - Printing **from within the `setup` or `teardown` functions**: The same hold true as for printing with test functions. - Printing **outside test or `setup`/`teardown` functions**: - Regardless of where text is redirected to (stdout, stderr or file descriptor 3) text is immediately visible in the terminal. - Text printed in such a way, will disable pretty formatting. Also, it will make output non-compliant with the TAP spec. The reason for this is that each test file is evaluated n+1 times (as mentioned [earlier](#writing-tests)). The first run will cause such output to be produced before the [_plan line_][tap-plan] is printed, contrary to the spec that requires the _plan line_ to be either the first or the last line of the output. - Due to internal pipes/redirects, output to stderr is always printed first. [tap-plan]: https://testanything.org/tap-specification.html#the-plan ## Special variables There are several global variables you can use to introspect on Bats tests: - `$BATS_RUN_COMMAND` is the run command used in your test case. - `$BATS_TEST_FILENAME` is the fully expanded path to the Bats test file. - `$BATS_TEST_DIRNAME` is the directory in which the Bats test file is located. - `$BATS_TEST_NAMES` is an array of function names for each test case. - `$BATS_TEST_NAME` is the name of the function containing the current test case. - `$BATS_TEST_DESCRIPTION` is the description of the current test case. - `$BATS_TEST_NUMBER` is the (1-based) index of the current test case in the test file. - `$BATS_SUITE_TEST_NUMBER` is the (1-based) index of the current test case in the test suite (over all files). - `$BATS_TMPDIR` is the base temporary directory used by bats to create its temporary files / directories. (default: `$TMPDIR`. If `$TMPDIR` is not set, `/tmp` is used.) - `$BATS_RUN_TMPDIR` is the location to the temporary directory used by bats to store all its internal temporary files during the tests. (default: `$BATS_TMPDIR/bats-run-$BATS_ROOT_PID-XXXXXX`) - `$BATS_FILE_EXTENSION` (default: `bats`) specifies the extension of test files that should be found when running a suite (via `bats [-r] suite_folder/`) - `$BATS_SUITE_TMPDIR` is a temporary directory common to all tests of a suite. Could be used to create files required by multiple tests. - `$BATS_FILE_TMPDIR` 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. - `$BATS_TEST_TMPDIR` is a temporary directory unique for each test. Could be used to create files required only for specific tests. ## Libraries and Add-ons Bats supports loading external assertion libraries and helpers. Those under `bats-core` are officially supported libraries (integration tests welcome!): - - common assertions for Bats - - supporting library for Bats test helpers - - common filesystem assertions for Bats - - e2e tests of applications in K8s environments and some external libraries, supported on a "best-effort" basis: - (still relevant? Requires review) - (as per #147) - (how is this different from grayhemp/bats-mock?) git-secret-0.5.0/vendor/bats-core/docs/versions.md000066400000000000000000000004371424706700600220720ustar00rootroot00000000000000Here are the docs of following versions: * [v1.2.0](../../v1.2.0/README.md) * [v1.1.0](../../v1.1.0/README.md) * [v1.0.2](../../v1.0.2/README.md) * [v0.4.0](../../v0.4.0/README.md) * [v0.3.1](../../v0.3.1/README.md) * [v0.2.0](../../v0.2.0/README.md) * [v0.1.0](../../v0.1.0/README.md) git-secret-0.5.0/vendor/bats-core/install.sh000077500000000000000000000012241424706700600207500ustar00rootroot00000000000000#!/usr/bin/env bash set -e BATS_ROOT="${0%/*}" PREFIX="$1" LIBDIR="${2:-lib}" if [[ -z "$PREFIX" ]]; then printf '%s\n' \ "usage: $0 " \ " e.g. $0 /usr/local" >&2 exit 1 fi install -d -m 755 "$PREFIX"/{bin,libexec/bats-core,"${LIBDIR}"/bats-core,share/man/man{1,7}} install -m 755 "$BATS_ROOT/bin"/* "$PREFIX/bin" install -m 755 "$BATS_ROOT/libexec/bats-core"/* "$PREFIX/libexec/bats-core" install -m 755 "$BATS_ROOT/lib/bats-core"/* "$PREFIX/${LIBDIR}/bats-core" install -m 644 "$BATS_ROOT/man/bats.1" "$PREFIX/share/man/man1" install -m 644 "$BATS_ROOT/man/bats.7" "$PREFIX/share/man/man7" echo "Installed Bats to $PREFIX/bin/bats" git-secret-0.5.0/vendor/bats-core/lib/000077500000000000000000000000001424706700600175125ustar00rootroot00000000000000git-secret-0.5.0/vendor/bats-core/lib/bats-core/000077500000000000000000000000001424706700600213715ustar00rootroot00000000000000git-secret-0.5.0/vendor/bats-core/lib/bats-core/common.bash000066400000000000000000000012121424706700600235140ustar00rootroot00000000000000#!/usr/bin/env bash bats_prefix_lines_for_tap_output() { while IFS= read -r line; do printf '# %s\n' "$line" || break # avoid feedback loop when errors are redirected into BATS_OUT (see #353) done if [[ -n "$line" ]]; then printf '# %s\n' "$line" fi } function bats_replace_filename() { local line while read -r line; do printf "%s\n" "${line//$BATS_TEST_SOURCE/$BATS_TEST_FILENAME}" done if [[ -n "$line" ]]; then printf "%s\n" "${line//$BATS_TEST_SOURCE/$BATS_TEST_FILENAME}" fi } bats_quote_code() { # printf -v "$1" -- "%s%s%s" "$BATS_BEGIN_CODE_QUOTE" "$2" "$BATS_END_CODE_QUOTE" } git-secret-0.5.0/vendor/bats-core/lib/bats-core/formatter.bash000066400000000000000000000123761424706700600242440ustar00rootroot00000000000000#!/usr/bin/env bash # reads (extended) bats tap streams from stdin and calls callback functions for each line # bats_tap_stream_plan -> when the test plan is encountered # bats_tap_stream_begin -> when a new test is begun WARNING: extended only # bats_tap_stream_ok [--duration -> when a test was successful # bats_tap_stream_not_ok [--duration ] -> when a test has failed # bats_tap_stream_skipped -> when a test was skipped # bats_tap_stream_comment -> when a comment line was encountered, # scope tells the last encountered of plan, begin, ok, not_ok, skipped, suite # bats_tap_stream_suite -> when a new file is begun WARNING: extended only # bats_tap_stream_unknown -> when a line is encountered that does not match the previous entries, # scope @see bats_tap_stream_comment # forwards all input as is, when there is no TAP test plan header function bats_parse_internal_extended_tap() { local header_pattern='[0-9]+\.\.[0-9]+' IFS= read -r header if [[ "$header" =~ $header_pattern ]]; then bats_tap_stream_plan "${header:3}" else # If the first line isn't a TAP plan, print it and pass the rest through printf '%s\n' "$header" exec cat fi ok_line_regexpr="ok ([0-9]+) (.*)" skip_line_regexpr="ok ([0-9]+) (.*) # skip( (.*))?$" not_ok_line_regexpr="not ok ([0-9]+) (.*)" timing_expr="in ([0-9]+)ms$" local test_name begin_index ok_index not_ok_index index scope begin_index=0 index=0 scope=plan while IFS= read -r line; do case "$line" in 'begin '*) # this might only be called in extended tap output ((++begin_index)) scope=begin test_name="${line#* $begin_index }" bats_tap_stream_begin "$begin_index" "$test_name" ;; 'ok '*) ((++index)) if [[ "$line" =~ $ok_line_regexpr ]]; then ok_index="${BASH_REMATCH[1]}" test_name="${BASH_REMATCH[2]}" if [[ "$line" =~ $skip_line_regexpr ]]; then scope=skipped test_name="${BASH_REMATCH[2]}" # cut off name before "# skip" local skip_reason="${BASH_REMATCH[4]}" bats_tap_stream_skipped "$ok_index" "$test_name" "$skip_reason" else scope=ok if [[ "$line" =~ $timing_expr ]]; then bats_tap_stream_ok --duration "${BASH_REMATCH[1]}" "$ok_index" "$test_name" else bats_tap_stream_ok "$ok_index" "$test_name" fi fi else printf "ERROR: could not match ok line: %s" "$line" >&2 exit 1 fi ;; 'not ok '*) ((++index)) scope=not_ok if [[ "$line" =~ $not_ok_line_regexpr ]]; then not_ok_index="${BASH_REMATCH[1]}" test_name="${BASH_REMATCH[2]}" if [[ "$line" =~ $timing_expr ]]; then bats_tap_stream_not_ok --duration "${BASH_REMATCH[1]}" "$not_ok_index" "$test_name" else bats_tap_stream_not_ok "$not_ok_index" "$test_name" fi else printf "ERROR: could not match not ok line: %s" "$line" >&2 exit 1 fi ;; '# '*) bats_tap_stream_comment "${line:2}" "$scope" ;; 'suite '*) scope=suite # pass on the bats_tap_stream_suite "${line:6}" ;; *) bats_tap_stream_unknown "$line" "$scope" ;; esac done } # given a prefix and a path, remove the prefix if the path starts with it # e.g. # remove_prefix /usr/bin /usr/bin/bash -> bash # remove_prefix /usr /usr/lib/bash -> lib/bash # remove_prefix /usr/bin /usr/local/bin/bash -> /usr/local/bin/bash remove_prefix() { base_path="$1" path="$2" if [[ "$path" == "$base_path"* ]]; then # cut off the common prefix printf "%s" "${path:${#base_path}}" else printf "%s" "$path" fi } normalize_base_path() { # # the relative path root to use for reporting filenames # this is mainly intended for suite mode, where this will be the suite root folder local base_path="$2" # use the containing directory when --base-path is a file if [[ ! -d "$base_path" ]]; then base_path="$(dirname "$base_path")" fi # get the absolute path base_path="$(cd "$base_path" && pwd)" # ensure the path ends with / to strip that later on if [[ "${base_path}" != *"/" ]]; then base_path="$base_path/" fi printf -v "$1" "%s" "$base_path" } git-secret-0.5.0/vendor/bats-core/lib/bats-core/preprocessing.bash000066400000000000000000000013401424706700600251110ustar00rootroot00000000000000#!/usr/bin/env bash BATS_TMPNAME="$BATS_RUN_TMPDIR/bats.$$" BATS_PARENT_TMPNAME="$BATS_RUN_TMPDIR/bats.$PPID" # shellcheck disable=SC2034 BATS_OUT="${BATS_TMPNAME}.out" # used in bats-exec-file bats_preprocess_source() { # export to make it visible to bats_evaluate_preprocessed_source # since the latter runs in bats-exec-test's bash while this runs in bats-exec-file's export BATS_TEST_SOURCE="${BATS_TMPNAME}.src" bats-preprocess "$BATS_TEST_FILENAME" >"$BATS_TEST_SOURCE" } bats_evaluate_preprocessed_source() { if [[ -z "${BATS_TEST_SOURCE:-}" ]]; then BATS_TEST_SOURCE="${BATS_PARENT_TMPNAME}.src" fi # Dynamically loaded user files provided outside of Bats. # shellcheck disable=SC1090 source "$BATS_TEST_SOURCE" } git-secret-0.5.0/vendor/bats-core/lib/bats-core/semaphore.bash000066400000000000000000000073661424706700600242270ustar00rootroot00000000000000#!/usr/bin/env bash # setup the semaphore environment for the loading file bats_semaphore_setup() { export -f bats_semaphore_get_free_slot_count export -f bats_semaphore_acquire_while_locked export BATS_SEMAPHORE_DIR="$BATS_RUN_TMPDIR/semaphores" if command -v flock >/dev/null; then bats_run_under_lock() { flock "$BATS_SEMAPHORE_DIR" "$@" } elif command -v shlock >/dev/null; then bats_run_under_lock() { local lockfile="$BATS_SEMAPHORE_DIR/shlock.lock" while ! shlock -p $$ -f "$lockfile"; do sleep 1 done # we got the lock now, execute the command "$@" local status=$? # free the lock rm -f "$lockfile" return $status } else printf "ERROR: flock/shlock is required for parallelization within files!\n" >&2 exit 1 fi } # $1 - output directory for stdout/stderr # $@ - command to run # run the given command in a semaphore # block when there is no free slot for the semaphore # when there is a free slot, run the command in background # gather the output of the command in files in the given directory bats_semaphore_run() { local output_dir=$1 shift local semaphore_slot semaphore_slot=$(bats_semaphore_acquire_slot) bats_semaphore_release_wrapper "$output_dir" "$semaphore_slot" "$@" & printf "%d\n" "$!" } # $1 - output directory for stdout/stderr # $@ - command to run # this wraps the actual function call to install some traps on exiting bats_semaphore_release_wrapper() { local output_dir="$1" local semaphore_name="$2" shift 2 # all other parameters will be use for the command to execute # shellcheck disable=SC2064 # we want to expand the semaphore_name right now! trap "status=$?; bats_semaphore_release_slot '$semaphore_name'; exit $status" EXIT mkdir -p "$output_dir" "$@" 2>"$output_dir/stderr" >"$output_dir/stdout" local status=$? # bash bug: the exit trap is not called for the background process bats_semaphore_release_slot "$semaphore_name" trap - EXIT # avoid calling release twice return $status } bats_semaphore_acquire_while_locked() { if [[ $(bats_semaphore_get_free_slot_count) -gt 0 ]]; then local slot=0 while [[ -e "$BATS_SEMAPHORE_DIR/slot-$slot" ]]; do (( ++slot )) done if [[ $slot -lt $BATS_SEMAPHORE_NUMBER_OF_SLOTS ]]; then touch "$BATS_SEMAPHORE_DIR/slot-$slot" && printf "%d\n" "$slot" && return 0 fi fi return 1 } # block until a semaphore slot becomes free # prints the number of the slot that it received bats_semaphore_acquire_slot() { mkdir -p "$BATS_SEMAPHORE_DIR" # wait for a slot to become free # TODO: avoid busy waiting by using signals -> this opens op prioritizing possibilities as well while true; do # don't lock for reading, we are fine with spuriously getting no free slot if [[ $(bats_semaphore_get_free_slot_count) -gt 0 ]]; then bats_run_under_lock bash -c bats_semaphore_acquire_while_locked && break fi sleep 1 done } bats_semaphore_release_slot() { # we don't need to lock this, since only our process owns this file # and freeing a semaphore cannot lead to conflicts with others rm "$BATS_SEMAPHORE_DIR/slot-$1" # this will fail if we had not aqcuired a semaphore! } bats_semaphore_get_free_slot_count() { # find might error out without returning something useful when a file is deleted, # while the directory is traversed -> only continue when there was no error until used_slots=$(find "$BATS_SEMAPHORE_DIR" -name 'slot-*' 2>/dev/null | wc -l); do :; done echo $(( BATS_SEMAPHORE_NUMBER_OF_SLOTS - used_slots )) } git-secret-0.5.0/vendor/bats-core/lib/bats-core/test_functions.bash000066400000000000000000000236431424706700600253070ustar00rootroot00000000000000#!/usr/bin/env bash BATS_TEST_DIRNAME="${BATS_TEST_FILENAME%/*}" BATS_TEST_NAMES=() # find_in_bats_lib_path echoes the first recognized load path to # a library in BATS_LIB_PATH or relative to BATS_TEST_DIRNAME. # # Libraries relative to BATS_TEST_DIRNAME take precedence over # BATS_LIB_PATH. # # Library load paths are recognized using find_library_load_path. # # If no library is found find_in_bats_lib_path returns 1. find_in_bats_lib_path() { # local return_var="${1:?}" local library_name="${2:?}" local -a bats_lib_paths IFS=: read -ra bats_lib_paths <<< "$BATS_LIB_PATH" for path in "${bats_lib_paths[@]}"; do if [[ -f "$path/$library_name" ]]; then printf -v "$return_var" "%s" "$path/$library_name" # A library load path was found, return return elif [[ -f "$path/$library_name/load.bash" ]]; then printf -v "$return_var" "%s" "$path/$library_name/load.bash" # A library load path was found, return return fi done return 1 } # bats_internal_load expects an absolute path that is a library load path. # # If the library load path points to a file (a library loader) it is # sourced. # # If it points to a directory all files ending in .bash inside of the # directory are sourced. # # If the sourcing of the library loader or of a file in a library # directory fails bats_internal_load prints an error message and returns 1. # # If the passed library load path is not absolute or is not a valid file # or directory bats_internal_load prints an error message and returns 1. bats_internal_load() { local library_load_path="${1:?}" if [[ "${library_load_path:0:1}" != / ]]; then printf "Passed library load path is not an absolute path: %s\n" "$library_load_path" >&2 return 1 fi # library_load_path is a library loader if [[ -f "$library_load_path" ]]; then # shellcheck disable=SC1090 if ! source "$library_load_path"; then printf "Error while sourcing library loader at '%s'\n" "$library_load_path" >&2 return 1 fi return fi printf "Passed library load path is neither a library loader nor library directory: %s\n" "$library_load_path" >&2 return 1 } # bats_load_safe accepts an argument called 'slug' and attempts to find and # source a library based on the slug. # # A slug can be an absolute path, a library name or a relative path. # # If the slug is an absolute path bats_load_safe attempts to find the library # load path using find_library_load_path. # What is considered a library load path is documented in the # documentation for find_library_load_path. # # If the slug is not an absolute path it is considered a library name or # relative path. bats_load_safe attempts to find the library load path using # find_in_bats_lib_path. # # If bats_load_safe can find a library load path it is passed to bats_internal_load. # If bats_internal_load fails bats_load_safe returns 1. # # If no library load path can be found bats_load_safe prints an error message # and returns 1. bats_load_safe() { local slug="${1:?}" if [[ ${slug:0:1} != / ]]; then # relative paths are relative to BATS_TEST_DIRNAME slug="$BATS_TEST_DIRNAME/$slug" fi if [[ -f "$slug.bash" ]]; then bats_internal_load "$slug.bash" return elif [[ -f "$slug" ]]; then bats_internal_load "$slug" return fi # loading from PATH (retained for backwards compatibility) if [[ ! -f "$1" ]] && type -P "$1" >/dev/null; then # shellcheck disable=SC1090 source "$1" return fi # No library load path can be found printf "bats_load_safe: Could not find '%s'[.bash]\n" "$slug" >&2 return 1 } bats_require_lib_path() { if [[ -z "${BATS_LIB_PATH:-}" ]]; then printf "%s: requires BATS_LIB_PATH to be set!\n" "${FUNCNAME[1]}" >&2 exit 1 fi } bats_load_library_safe() { # local slug="${1:?}" library_path bats_require_lib_path # Check for library load paths in BATS_TEST_DIRNAME and BATS_LIB_PATH if [[ ${slug:0:1} != / ]]; then find_in_bats_lib_path library_path "$slug" if [[ -z "$library_path" ]]; then printf "Could not find library '%s' relative to test file or in BATS_LIB_PATH\n" "$slug" >&2 return 1 fi else # absolute paths are taken as is library_path="$slug" if [[ ! -f "$library_path" ]]; then printf "Could not find library on absolute path '%s'\n" "$library_path" >&2 return 1 fi fi bats_internal_load "$library_path" return $? } # immediately exit on error, use bats_load_library_safe to catch and handle errors bats_load_library() { # bats_require_lib_path if ! bats_load_library_safe "$@"; then exit 1 fi } # load acts like bats_load_safe but exits the shell instead of returning 1. load() { if ! bats_load_safe "$@"; then exit 1 fi } bats_redirect_stderr_into_file() { "$@" 2>>"$bats_run_separate_stderr_file" # use >> to see collisions' content } bats_merge_stdout_and_stderr() { "$@" 2>&1 } # write separate lines from into bats_separate_lines() { # local output_array_name="$1" local input_var_name="$2" if [[ $keep_empty_lines ]]; then local bats_separate_lines_lines=() while IFS= read -r line; do bats_separate_lines_lines+=("$line") done <<<"${!input_var_name}" eval "${output_array_name}=(\"\${bats_separate_lines_lines[@]}\")" else # shellcheck disable=SC2034,SC2206 IFS=$'\n' read -d '' -r -a "$output_array_name" <<<"${!input_var_name}" || true # don't fail due to EOF fi } run() { # [!|-N] [--keep-empty-lines] [--separate-stderr] [--] # This has to be restored on exit from this function to avoid leaking our trap INT into surrounding code. # Non zero exits won't restore under the assumption that they will fail the test before it can be aborted, # which allows us to avoid duplicating the restore code on every exit path trap bats_interrupt_trap_in_run INT local expected_rc= local keep_empty_lines= local output_case=merged # parse options starting with - while [[ $# -gt 0 ]] && [[ $1 == -* || $1 == '!' ]]; do case "$1" in '!') expected_rc=-1 ;; -[0-9]*) expected_rc=${1#-} if [[ $expected_rc =~ [^0-9] ]]; then printf "Usage error: run: '=NNN' requires numeric NNN (got: %s)\n" "$expected_rc" >&2 return 1 elif [[ $expected_rc -gt 255 ]]; then printf "Usage error: run: '=NNN': NNN must be <= 255 (got: %d)\n" "$expected_rc" >&2 return 1 fi ;; --keep-empty-lines) keep_empty_lines=1 ;; --separate-stderr) output_case="separate" ;; --) shift # eat the -- before breaking away break ;; *) printf "Usage error: unknown flag '%s'" "$1" >&2 return 1 ;; esac shift done local pre_command= case "$output_case" in merged) # redirects stderr into stdout and fills only $output/$lines pre_command=bats_merge_stdout_and_stderr ;; separate) # splits stderr into own file and fills $stderr/$stderr_lines too local bats_run_separate_stderr_file bats_run_separate_stderr_file="$(mktemp "${BATS_TEST_TMPDIR}/separate-stderr-XXXXXX")" pre_command=bats_redirect_stderr_into_file ;; esac local origFlags="$-" set +eET local origIFS="$IFS" if [[ $keep_empty_lines ]]; then # 'output', 'status', 'lines' are global variables available to tests. # preserve trailing newlines by appending . and removing it later # shellcheck disable=SC2034 output="$($pre_command "$@"; status=$?; printf .; exit $status)" && status=0 || status=$? output="${output%.}" else # 'output', 'status', 'lines' are global variables available to tests. # shellcheck disable=SC2034 output="$($pre_command "$@")" && status=0 || status=$? fi bats_separate_lines lines output if [[ "$output_case" == separate ]]; then # shellcheck disable=SC2034 read -d '' -r stderr < "$bats_run_separate_stderr_file" bats_separate_lines stderr_lines stderr fi # shellcheck disable=SC2034 BATS_RUN_COMMAND="${*}" IFS="$origIFS" set "-$origFlags" if [[ ${BATS_VERBOSE_RUN:-} ]]; then printf "%s\n" "$output" fi if [[ -n "$expected_rc" ]]; then if [[ "$expected_rc" = "-1" ]]; then if [[ "$status" -eq 0 ]]; then BATS_ERROR_SUFFIX=", expected nonzero exit code!" return 1 fi elif [ "$status" -ne "$expected_rc" ]; then # shellcheck disable=SC2034 BATS_ERROR_SUFFIX=", expected exit code $expected_rc, got $status" return 1 fi fi # don't leak our trap into surrounding code trap bats_interrupt_trap INT } setup() { return 0 } teardown() { return 0 } skip() { # if this is a skip in teardown ... if [[ -n "${BATS_TEARDOWN_STARTED-}" ]]; then # ... we want to skip the rest of teardown. # communicate to bats_exit_trap that the teardown was completed without error # shellcheck disable=SC2034 BATS_TEARDOWN_COMPLETED=1 # if we are already in the exit trap (e.g. due to previous skip) ... if [[ "$BATS_TEARDOWN_STARTED" == as-exit-trap ]]; then # ... we need to do the rest of the tear_down_trap that would otherwise be skipped after the next call to exit bats_exit_trap # and then do the exit (at the end of this function) fi # if we aren't in exit trap, the normal exit handling should suffice else # ... this is either skip in test or skip in setup. # Following variables are used in bats-exec-test which sources this file # shellcheck disable=SC2034 BATS_TEST_SKIPPED="${1:-1}" # shellcheck disable=SC2034 BATS_TEST_COMPLETED=1 fi exit 0 } bats_test_begin() { BATS_TEST_DESCRIPTION="$1" if [[ -n "$BATS_EXTENDED_SYNTAX" ]]; then printf 'begin %d %s\n' "$BATS_SUITE_TEST_NUMBER" "$BATS_TEST_DESCRIPTION" >&3 fi setup } bats_test_function() { local test_name="$1" BATS_TEST_NAMES+=("$test_name") } git-secret-0.5.0/vendor/bats-core/lib/bats-core/tracing.bash000066400000000000000000000300651424706700600236630ustar00rootroot00000000000000#!/usr/bin/env bash bats_capture_stack_trace() { local test_file local funcname local i BATS_DEBUG_LAST_STACK_TRACE=() for ((i = 2; i != ${#FUNCNAME[@]}; ++i)); do # Use BATS_TEST_SOURCE if necessary to work around Bash < 4.4 bug whereby # calling an exported function erases the test file's BASH_SOURCE entry. test_file="${BASH_SOURCE[$i]:-$BATS_TEST_SOURCE}" funcname="${FUNCNAME[$i]}" BATS_DEBUG_LAST_STACK_TRACE+=("${BASH_LINENO[$((i-1))]} $funcname $test_file") case "$funcname" in "$BATS_TEST_NAME" | setup | teardown | setup_file | teardown_file) break ;; esac if [[ "${BASH_SOURCE[$i + 1]:-}" == *"bats-exec-file" ]] && [[ "$funcname" == 'source' ]]; then break fi done } bats_get_failure_stack_trace() { local stack_trace_var # See bats_debug_trap for details. if [[ -n "${BATS_DEBUG_LAST_STACK_TRACE_IS_VALID}" ]]; then stack_trace_var=BATS_DEBUG_LAST_STACK_TRACE else stack_trace_var=BATS_DEBUG_LASTLAST_STACK_TRACE fi # shellcheck disable=SC2016 eval "$(printf \ '%s=(${%s[@]+"${%s[@]}"})' \ "${1}" \ "${stack_trace_var}" \ "${stack_trace_var}")" } bats_print_stack_trace() { local frame local index=1 local count="${#@}" local filename local lineno for frame in "$@"; do bats_frame_filename "$frame" 'filename' bats_trim_filename "$filename" 'filename' bats_frame_lineno "$frame" 'lineno' if [[ $index -eq 1 ]]; then printf '# (' else printf '# ' fi local fn bats_frame_function "$frame" 'fn' if [[ "$fn" != "$BATS_TEST_NAME" ]] && # don't print "from function `source'"", # when failing in free code during `source $test_file` from bats-exec-file ! [[ "$fn" == 'source' && $index -eq $count ]]; then local quoted_fn bats_quote_code quoted_fn "$fn" printf "from function %s " "$quoted_fn" fi if [[ $index -eq $count ]]; then printf 'in test file %s, line %d)\n' "$filename" "$lineno" else printf 'in file %s, line %d,\n' "$filename" "$lineno" fi ((++index)) done } bats_print_failed_command() { local stack_trace=("${@}") if [[ ${#stack_trace[@]} -eq 0 ]]; then return fi local frame="${stack_trace[${#stack_trace[@]} - 1]}" local filename local lineno local failed_line local failed_command bats_frame_filename "$frame" 'filename' bats_frame_lineno "$frame" 'lineno' bats_extract_line "$filename" "$lineno" 'failed_line' bats_strip_string "$failed_line" 'failed_command' local quoted_failed_command bats_quote_code quoted_failed_command "$failed_command" printf '# %s ' "${quoted_failed_command}" if [[ "$BATS_ERROR_STATUS" -eq 1 ]]; then printf 'failed%s\n' "$BATS_ERROR_SUFFIX" else printf 'failed with status %d%s\n' "$BATS_ERROR_STATUS" "$BATS_ERROR_SUFFIX" fi } bats_frame_lineno() { printf -v "$2" '%s' "${1%% *}" } bats_frame_function() { local __bff_function="${1#* }" printf -v "$2" '%s' "${__bff_function%% *}" } bats_frame_filename() { local __bff_filename="${1#* }" __bff_filename="${__bff_filename#* }" if [[ "$__bff_filename" == "$BATS_TEST_SOURCE" ]]; then __bff_filename="$BATS_TEST_FILENAME" fi printf -v "$2" '%s' "$__bff_filename" } bats_extract_line() { local __bats_extract_line_line local __bats_extract_line_index=0 while IFS= read -r __bats_extract_line_line; do if [[ "$((++__bats_extract_line_index))" -eq "$2" ]]; then printf -v "$3" '%s' "${__bats_extract_line_line%$'\r'}" break fi done <"$1" } bats_strip_string() { [[ "$1" =~ ^[[:space:]]*(.*)[[:space:]]*$ ]] printf -v "$2" '%s' "${BASH_REMATCH[1]}" } bats_trim_filename() { printf -v "$2" '%s' "${1#$BATS_CWD/}" } # normalize a windows path from e.g. C:/directory to /c/directory # The path must point to an existing/accessable directory, not a file! bats_normalize_windows_dir_path() { # local output_var="$1" path="$2" if [[ "$output_var" != NORMALIZED_INPUT ]]; then local NORMALIZED_INPUT fi if [[ $path == ?:* ]]; then NORMALIZED_INPUT="$(cd "$path" || exit 1; pwd)" else NORMALIZED_INPUT="$path" fi printf -v "$output_var" "%s" "$NORMALIZED_INPUT" } bats_emit_trace() { if [[ $BATS_TRACE_LEVEL -gt 0 ]]; then local line=${BASH_LINENO[1]} # shellcheck disable=SC2016 if [[ $BASH_COMMAND != '"$BATS_TEST_NAME" >> "$BATS_OUT" 2>&1 4>&1' && $BASH_COMMAND != "bats_test_begin "* ]] && # don't emit these internal calls [[ $BASH_COMMAND != "$BATS_LAST_BASH_COMMAND" || $line != "$BATS_LAST_BASH_LINENO" ]] && # avoid printing a function twice (at call site and at definiton site) [[ $BASH_COMMAND != "$BATS_LAST_BASH_COMMAND" || ${BASH_LINENO[2]} != "$BATS_LAST_BASH_LINENO" || ${BASH_SOURCE[3]} != "$BATS_LAST_BASH_SOURCE" ]]; then local file="${BASH_SOURCE[2]}" # index 2: skip over bats_emit_trace and bats_debug_trap if [[ $file == "${BATS_TEST_SOURCE}" ]]; then file="$BATS_TEST_FILENAME" fi local padding='$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$' if (( BATS_LAST_STACK_DEPTH != ${#BASH_LINENO[@]} )); then printf '%s [%s:%d]\n' "${padding::${#BASH_LINENO[@]}-4}" "${file##*/}" "$line" >&4 fi printf '%s %s\n' "${padding::${#BASH_LINENO[@]}-4}" "$BASH_COMMAND" >&4 BATS_LAST_BASH_COMMAND="$BASH_COMMAND" BATS_LAST_BASH_LINENO="$line" BATS_LAST_BASH_SOURCE="${BASH_SOURCE[2]}" BATS_LAST_STACK_DEPTH="${#BASH_LINENO[@]}" fi fi } # bats_debug_trap tracks the last line of code executed within a test. This is # necessary because $BASH_LINENO is often incorrect inside of ERR and EXIT # trap handlers. # # Below are tables describing different command failure scenarios and the # reliability of $BASH_LINENO within different the executed DEBUG, ERR, and EXIT # trap handlers. Naturally, the behaviors change between versions of Bash. # # Table rows should be read left to right. For example, on bash version # 4.0.44(2)-release, if a test executes `false` (or any other failing external # command), bash will do the following in order: # 1. Call the DEBUG trap handler (bats_debug_trap) with $BASH_LINENO referring # to the source line containing the `false` command, then # 2. Call the DEBUG trap handler again, but with an incorrect $BASH_LINENO, then # 3. Call the ERR trap handler, but with a (possibly-different) incorrect # $BASH_LINENO, then # 4. Call the DEBUG trap handler again, but with $BASH_LINENO set to 1, then # 5. Call the EXIT trap handler, with $BASH_LINENO set to 1. # # bash version 4.4.20(1)-release # command | first DEBUG | second DEBUG | ERR | third DEBUG | EXIT # -------------+-------------+--------------+---------+-------------+-------- # false | OK | OK | OK | BAD[1] | BAD[1] # [[ 1 = 2 ]] | OK | BAD[2] | BAD[2] | BAD[1] | BAD[1] # (( 1 = 2 )) | OK | BAD[2] | BAD[2] | BAD[1] | BAD[1] # ! true | OK | --- | BAD[4] | --- | BAD[1] # $var_dne | OK | --- | --- | BAD[1] | BAD[1] # source /dne | OK | --- | --- | BAD[1] | BAD[1] # # bash version 4.0.44(2)-release # command | first DEBUG | second DEBUG | ERR | third DEBUG | EXIT # -------------+-------------+--------------+---------+-------------+-------- # false | OK | BAD[3] | BAD[3] | BAD[1] | BAD[1] # [[ 1 = 2 ]] | OK | --- | BAD[3] | --- | BAD[1] # (( 1 = 2 )) | OK | --- | BAD[3] | --- | BAD[1] # ! true | OK | --- | BAD[3] | --- | BAD[1] # $var_dne | OK | --- | --- | BAD[1] | BAD[1] # source /dne | OK | --- | --- | BAD[1] | BAD[1] # # [1] The reported line number is always 1. # [2] The reported source location is that of the beginning of the function # calling the command. # [3] The reported line is that of the last command executed in the DEBUG trap # handler. # [4] The reported source location is that of the call to the function calling # the command. bats_debug_trap() { # on windows we sometimes get a mix of paths (when install via nmp install -g) # which have C:/... or /c/... comparing them is going to be problematic. # We need to normalize them to a common format! local NORMALIZED_INPUT bats_normalize_windows_dir_path NORMALIZED_INPUT "${1%/*}" local file_excluded='' path for path in "${BATS_DEBUG_EXCLUDE_PATHS[@]}"; do if [[ "$NORMALIZED_INPUT" == "$path"* ]]; then file_excluded=1 break fi done # don't update the trace within library functions or we get backtraces from inside traps # also don't record new stack traces while handling interruptions, to avoid overriding the interrupted command if [[ -z "$file_excluded" && "${BATS_INTERRUPTED-NOTSET}" == NOTSET ]]; then BATS_DEBUG_LASTLAST_STACK_TRACE=( ${BATS_DEBUG_LAST_STACK_TRACE[@]+"${BATS_DEBUG_LAST_STACK_TRACE[@]}"} ) BATS_DEBUG_LAST_LINENO=(${BASH_LINENO[@]+"${BASH_LINENO[@]}"}) BATS_DEBUG_LAST_SOURCE=(${BASH_SOURCE[@]+"${BASH_SOURCE[@]}"}) bats_capture_stack_trace bats_emit_trace fi } # For some versions of Bash, the `ERR` trap may not always fire for every # command failure, but the `EXIT` trap will. Also, some command failures may not # set `$?` properly. See #72 and #81 for details. # # For this reason, we call `bats_check_status_from_trap` at the very beginning # of `bats_teardown_trap` and check the value of `$BATS_TEST_COMPLETED` before # taking other actions. We also adjust the exit status value if needed. # # See `bats_exit_trap` for an additional EXIT error handling case when `$?` # isn't set properly during `teardown()` errors. bats_check_status_from_trap() { local status="$?" if [[ -z "$BATS_TEST_COMPLETED" ]]; then BATS_ERROR_STATUS="${BATS_ERROR_STATUS:-$status}" if [[ "$BATS_ERROR_STATUS" -eq 0 ]]; then BATS_ERROR_STATUS=1 fi trap - DEBUG fi } bats_add_debug_exclude_path() { # if [[ -z "$1" ]]; then # don't exclude everything printf "bats_add_debug_exclude_path: Exclude path must not be empty!\n" >&2 return 1 fi if [[ "$OSTYPE" == cygwin || "$OSTYPE" == msys ]]; then local normalized_dir bats_normalize_windows_dir_path normalized_dir "$1" BATS_DEBUG_EXCLUDE_PATHS+=("$normalized_dir") else BATS_DEBUG_EXCLUDE_PATHS+=("$1") fi } bats_setup_tracing() { BATS_DEBUG_EXCLUDE_PATHS=() # exclude some paths by default bats_add_debug_exclude_path "$BATS_ROOT/lib/" bats_add_debug_exclude_path "$BATS_ROOT/libexec/" exec 4<&1 # used for tracing if [[ "${BATS_TRACE_LEVEL:-0}" -gt 0 ]]; then # avoid undefined variable errors BATS_LAST_BASH_COMMAND= BATS_LAST_BASH_LINENO= BATS_LAST_BASH_SOURCE= BATS_LAST_STACK_DEPTH= # try to exclude helper libraries if found, this is only relevant for tracing while read -r path; do bats_add_debug_exclude_path "$path" done < <(find "$PWD" -type d -name bats-assert -o -name bats-support) fi local exclude_paths path # exclude user defined libraries IFS=':' read -r exclude_paths <<< "${BATS_DEBUG_EXCLUDE_PATHS:-}" for path in "${exclude_paths[@]}"; do if [[ -n "$path" ]]; then bats_add_debug_exclude_path "$path" fi done # turn on traps after setting excludedes to avoid tracing the exclude setup trap 'bats_debug_trap "$BASH_SOURCE"' DEBUG trap 'bats_error_trap' ERR } bats_error_trap() { bats_check_status_from_trap # If necessary, undo the most recent stack trace captured by bats_debug_trap. # See bats_debug_trap for details. if [[ "${BASH_LINENO[*]}" = "${BATS_DEBUG_LAST_LINENO[*]:-}" && "${BASH_SOURCE[*]}" = "${BATS_DEBUG_LAST_SOURCE[*]:-}" && -z "$BATS_DEBUG_LAST_STACK_TRACE_IS_VALID" ]]; then BATS_DEBUG_LAST_STACK_TRACE=( ${BATS_DEBUG_LASTLAST_STACK_TRACE[@]+"${BATS_DEBUG_LASTLAST_STACK_TRACE[@]}"} ) fi BATS_DEBUG_LAST_STACK_TRACE_IS_VALID=1 } bats_interrupt_trap() { # mark the interruption, to handle during exit BATS_INTERRUPTED=true BATS_ERROR_STATUS=130 # debug trap fires before interrupt trap but gets wrong linenumber (line 1) # -> use last last stack trace exit $BATS_ERROR_STATUS } # this is used inside run() bats_interrupt_trap_in_run() { # mark the interruption, to handle during exit BATS_INTERRUPTED=true BATS_ERROR_STATUS=130 BATS_DEBUG_LAST_STACK_TRACE_IS_VALID=true exit $BATS_ERROR_STATUS } git-secret-0.5.0/vendor/bats-core/lib/bats-core/validator.bash000066400000000000000000000020161424706700600242140ustar00rootroot00000000000000#!/usr/bin/env bash bats_test_count_validator() { trap '' INT # continue forwarding header_pattern='[0-9]+\.\.[0-9]+' IFS= read -r header # repeat the header printf "%s\n" "$header" # if we detect a TAP plan if [[ "$header" =~ $header_pattern ]]; then # extract the number of tests ... local expected_number_of_tests="${header:3}" # ... count the actual number of [not ] oks... local actual_number_of_tests=0 while IFS= read -r line; do # forward line printf "%s\n" "$line" case "$line" in 'ok '*) (( ++actual_number_of_tests )) ;; 'not ok'*) (( ++actual_number_of_tests )) ;; esac done # ... and error if they are not the same if [[ "${actual_number_of_tests}" != "${expected_number_of_tests}" ]]; then printf '# bats warning: Executed %s instead of expected %s tests\n' "$actual_number_of_tests" "$expected_number_of_tests" return 1 fi else # forward output unchanged cat fi }git-secret-0.5.0/vendor/bats-core/libexec/000077500000000000000000000000001424706700600203575ustar00rootroot00000000000000git-secret-0.5.0/vendor/bats-core/libexec/bats-core/000077500000000000000000000000001424706700600222365ustar00rootroot00000000000000git-secret-0.5.0/vendor/bats-core/libexec/bats-core/bats000077500000000000000000000244631424706700600231260ustar00rootroot00000000000000#!/usr/bin/env bash set -e export BATS_VERSION='1.6.0' VALID_FORMATTERS="pretty, junit, tap, tap13" version() { printf 'Bats %s\n' "$BATS_VERSION" } abort() { printf 'Error: %s\n' "$1" >&2 usage >&2 exit 1 } usage() { local cmd="${0##*/}" local line cat < ${cmd} [-h | -v] HELP_TEXT_HEADER cat <<'HELP_TEXT_BODY' is the path to a Bats test file, or the path to a directory containing Bats test files (ending with ".bats") -c, --count Count test cases without running any tests --code-quote-style

%}~R~1Z5 9;}U 93ՏqĐ;~3m1;e :$"XaD9$T .LK(r/L .'ZYr''7r1s0 h pr E3]de8Ȅ`Ja75!#z^|I|) "0R*Bw9~xJ " 4 #y@v {7}'$*x ax’xid_))y *q MV@c"0syJ ʨ %dHXPU !wE Y`=e u" i% }j{ aCjn7eB_ʡK~ !oڡ YM0SSqTǒ Q./I2C($9LRd; pWCʜ2Y0Y &喑f c)[*!Guq3z0L n*ct`w3SK&L~*bw7AHҚ 16(b*$>]2@c~)A' @E3$yy !pD` ۙ iɰ0|h j3 P gPU iS pJq iT:, 0SR\薰}3S}hr+&S>Zo Qp#q$su0Bd&7 ٩E !0F) `ud)Zk0R jHZuHAx a); @qtτ] O3zHaҕ}88*0 fv  3k*-rnW7a&G 3 m0* EQĂ N0NCi@{Z{f|[i  {#5V=   0PW5F:`}(#0F T ;KE8:;A4SOS$9 QU8o }' b p ?( P )0RD::;3!;ZR!b!1aHCdt3( !`*0 \5ÕC\aatz*ahK9yLl38$^3!]r &7W`[Ka b᷒*v *g#˄"ԩVM_ 3!L$+0MDyg"ćA#˷C|z"{f :0 K1J&/0S+ aS1;Sa-1d.0S! @aAJk.6SG~/'jjrC( @y0DtW1e\ i QPL^r Qb ٝ 9 ҋ p,m 3 |Kg`i5 (II{ɠ{1R 19=U0U~ː`!n'pSǶS19ޭ7jP0 .3c˱<;n D[dT W (: dڑ R$)0 T@d !$[R`57PӼ  fX iIHFHĵ! 5&P| y̰L Rx^ y5u)L ݥpz_Pnti,u7by ~P ^y.&p؜^x( uPwzWMnCRm B( q  e \H{|= i` a Qc9&T) 3-USd)60P&ۦM5p{0`;d;Bq1N1A43/\1ǼG@Ao3!HKoz0a &aPE1 a/(10ash);P[?nq_vxz.4_E1?_C?_?_?_ȟʿOm_؟n 䇾1*?VbC&1S20P bA`qP Nw@G!E$YI)UdK1eΤYM9u3|_>G <|+o<j =7_>zp?5]y_&\$-^$@?#$KN+;첉l0 :B 3pC;0j(H1E~ϡY">G rH"q q2 oAi5\tU8f@RNSGe$2PG,gֺ\wוxb+lxcbJDh8 Bd@ ᇊe҃fXX ի&W/Vzivizjjzkk{l6lV{mvm{nn{osSX(\^($P.p#;Bg[tAوa"DrS#I73}LW}w~b=)%{W~yyJjaQoДsdeKTf)*I-fXD/ yUO\Y gDq؆S0< <%P]I+E Yޕ6Ld\%E"Rq9l=$t a @`|ԉ(aϷOAa|bba?W 1XM0nw]W%oy{^Weo{^Wo}{_W2 ?H p*L$e0LNh|@B B& `<& tx;p4 Vb'SP҄`9@pPsh ;/;p<uXNN`;ty _ "v0!x?vAL?["eT#ēCc *X f4+@BW1a. FN D/s( d]@ֻ~;̒*_$s൬ar"w`^c.@3j۵g8?][f2؃^?H(:wh<50;p]{ǐP6t5k:pwps3es9Y(b5;|5vhȗm`x0{P3;4FD؁;4N$Ş<$18bjk(JkeJk`dKTJ<4lʁp)1(8˒*)[( ? v9 I 8% 2yD1I|#:bLoxߔPUSP YU@TV f[ޓ(cP7,^_uL5ԁbރމbzJbJ^u 43ʫ _Z8iQm7 `yWDP{k!i8 ējy0͑W_ I(2W,fb{98Q6kC }fIH&cbH>Q^Q-6qh Rh>h]Km"5[Z>ɕ]3eF6n8nXg(scC0UXrX߽T1"0gpKe)|ggT1d(DT`@hUPG ,xi&&r #)ЮPܹR遰>Ҧx T"j0aᒈX;4p"иCSNa$٭ \ F`@Z6Ŷ~kpO[+r`Ѐ+ދ[&c`Ii(&]\6?G8R~Jֿ҃Y&k[s@)SH~~@tHg\[6lЎ9leu(mfn!4X<4 Ul݌ \? ݃@Iuok^7赆4 <Pʇ~vM]hY2Ԩtl-J<wgZ<4Ŋ PdU `j#ȍ20t A,pS`$4 ˛zkS0, PÀ63$Tj:jQ7{g!wx΀/1b*}wtp΋A0ڡU: wxnV!23hݻ9;g<{Zh<}dw@v]aDw)g ʷ.X0dU6J4P D*C2-H5Y@5%ڰŬ7|QTjgF{l0́SK,|r6 `??‰CA," 8?h B ?? xrDsNn"Ϗ?H&JE I'Bti2 u8 CT4&CF P`BBb CɊur P"IL0\0t&cA@ )Wr*H# )SLf1l LUUTiU\W_X9x0[=c3y8d58AfP4;Aeaf y3z9đvfvhL8|9b19:yp =4eB@C 1 )BA*+&9D A|0¤ P2o! \l2|Xi짠vDa A `/7ωA,A:#U<y>""p~A"MH3¢Ⱥ iɥ#Mb&Ǯ?,FF>+a>*MW:FޱA:<*t IJ)F*@[WO<Q+`%&0 <@ N(ʯVd `ye`e[J rD5[K9Ӡgq!@u# eggQD=0$/LYvPýuc !Nw JNe9 .q&H QqŊ d][* p}H~PIVrhè棠 2f4@>QA6U@al`4w" C2%}Myi).hT#dK] "yHTio$Ɍz L=e '@@?AЀ^'NBCr pjTd $R  $E$`BҖ* @ HR*B1]T@@PbE@MF8/@ % :TV5$[WC0ZMSzndjMW9,h%^#r@rчFů2Tn` \e2d #lH" 86rIl^CITRԆ$4% @ AP?P!Jf*UoY\Ԯ6*-jt[`iC8hX.x+񒷼=/z0M6}/|Vhs2/~/,1~0#, S|c0C,&>1S.~1c,Ӹ61s>1,!F>2%3N~2,)SVry ^2a18s1ǛxC3@<9{%a:%>S |D3*/A&E >,it/J43 7 $Q I!H mтt5-?#v{V5̚~>] SRo kZԔ5Pd>HB:;Zv6﷍mڱ~p0U{0IsقyGd-?ȗD:=:m[ 59h^|k)Ii{,yVFH|87 쑈Cq\PYwl}w<7q$ E,߈m@0$H_kD<ɂ}< G)>>|}}Yp97꼞# "fqWIn=֟[+9(.Ϲ+7@[)DС ÙE1\y?XɎ!$-\CU݉]qSЭYHA@(08)e`4ߑ,`q8[` "]ē:pLIN堠D"8S ]69eA\"!qP\I a T! C8=ܾ;N&[= T Ϗ>N?<D vO$ʙݡuz+LJ;`TOB}#M@rJؕC 4A5eH(;R$!Ra h[A(:a2!YAEZZEVp2gfVqSb[&2!(eX&cR&>.&RF2Ubӝ3!@J)q'T!:,-\ N339I( h#mf~9WƟe8 S^'>v&?,`R`rqN6;5E &|;Sᡪč*F­:Qj?,hKI*XgY&phP5X%ͤ?Yj8kFZ!Щ2jT@f*"KݏZyr S m:Ok2NI*e߳έ2jT?ÉNIv;6;U RFjn\É|IH +|(e,Iʾj^S~"Fɶj1B:6 $b=yf.t-ai#BjdAbn,y y*jھkf%I::h6.C`'ګ 䯲@!xAg#z>! 4~n`-C@"$íkRq1-ݪ2(+g2*:.PnT)Rh0CӆBFL.Bmv ? ^:!Z~S9 ",:k\2)Z:^iD,r"Of0m\ @*NZ#D>3 2gd1׬%U%uu /$(j*A03!iua8JIiqÁpn[T >\--!nfJvpKdeg"2dOR k ;*+('TEC(Hg2hl^(!&qC%!@1qp AC!Zq e28q)oI 8'@ 82Ķ@#s#) wHH"G{ @ ":Z  ?093I-I A4/ $&Q AVD x" xJ" l*pi5 򰫭Nx O+2r& tj\1&ִ咽"쵆ޏWXTbC!t4^q:nͭbm*s1<5?W^)v%*A1.(Fh,@[D+ }*gWE% Z)‰")llF ?V1 Н4J Xb+4:#2H$bB%s;jCf3I / k2U&S5 Cxӭ2 H]ܶ_/-2ê37a2loYP)Osxfh+G `V_C<|涎U#-u.Za2+=tvY@ty$66(mL*9dɌX"x{4&Ө; no~W"Ȗ:a"t;B!uX;A!> !H 4< O@zs !LI/6#"tǺ>@"4Yzo SIp:n@ש !PF!a\:H!(@!D; ;X$S :sN ;{o! (BzwzHB8 ,#BK @@3 Aq<;@v]- iYv%`CX`m~ \BKsZ shK+Ԩ0 Av3lCB:Q t,0Ⱡ3-j3Qܚ[]dy\h*M̰|vC-d{|ulݖ[* @  3 ~́2D0ڐ>3v M 4"O (`XY B}pAR~lX2Yjl 'Q}E`6Evm+ 5jg6ꪵ#Pf3сFA3{{6x3= !"ʂ,(+[ h{6<F7x zy"U7_E Ac Nlr?>Dli B)T<3:NbMu %!@첅&*]6L$;'0y"~E@Ḭt,R q43 P򤳪-,+ 5 Ɯ4YT^9GK.(ԧOhuPz& M>*T\&3GEPOf3Ksrw"0"Lv҃$O i_C̭U h$©2V uҐKQI[Z Ì $j qk^֐ 6p=b`ָ_R'C.yĻ ~co`\".ECaXX*H%a!I\b)VYb1i\c9ycA\d# yPV%o"Gl V0H R0Ap v0LHI 'L t/4P|a1"G '؈3̑舘bXFb/D (5AP<BPUoG)rjL[9R Vy >WჇ,`6 T,!)؄iM`La"p+~ x u"PQK_dD@ouG!A| rx3 wa!~x rr8/;`)ST#>0{ec*QWk]L! BtlV  X$ȶ\o"07ՍVt7ߑ=(8H{ *`Fȁ + ظG|L_b:6 R V!BNW٬عB65BXů2m@ 4H ( @~~4I;nvԛ P ~;nvՃWB$H~Ci r7 O !& @/)RپlV #D`F F"GI0B@`!D` V0&( X,F,o 6O!rNB` ˶t>|ٔWA zL .". "r ! M z {"P d @ ޠ2!Ӏ $2h#%""%Ƞ " "2! D R"n` dR"t07XH@  " em  q z m( Var s!0rb|ۂ gH!"ji_&(rLU!ҴOp6rNvNt@R  8pqdAB/72BQ / * H!*s2i31 b1aU!dUޡp N `:b 97G9: WyzS`S ԍ7baW9 {`7 @!$<O `"*`"`2a@vvNVa@4bbڈ`&8 5p%tq"!r  c6 F @D!HR# f # jgd B8#fhb80E Ki!t`!mYO!m9B].0Pq +0S 5 "TP HS 9 !`BV{U[ёZu TQa{N d"ݦqaW1؁!ԭZq$.| N]}py 7_w j"9aj%َY!@m ؔsn~c!BD % b# $R% " ;Rf}x 2!!"&0aX zè!n/!X|Ma+P+ n,5RTU zq9.`r%dU|O  4[4 @Y *Hٔq|V:A\͡䀯/xaՍ >߁yuYO3 9 $1,4nz6 Yy |r:aX B" YfMea@ \Izkg¸;K%}X" bV b 3 ֻ@A|p ,&  X `7v xQAcDX"TBBURGa Z ֍  =!q "ƿy `& z TWܡ`! z S!z / ȕ!  / G [1 9ב]"@B$X bۼ l%FTca 8xG rv*d b! hө4JWi"wXKiA&c%6 5Iot`65Ran1X(7} Ps YA=(.lqVq@ă / d_ 5 HqWt]1}B [ o3@A4h3N3ww@:a+ B̛u"+aA03p;w+183*d.;8$7wy| 3̙4kڄUXi@|:V ١cU^>`jЪ7_HF#1k"(dXf˰hV3L5ke`R[̈&+3F24CV0-]aN0P/ь ߿?[~ ;4MbSXj=X;D?xJ3V0&>!1JZ`xx,z`P^fYx_ye|,rL rCe+ 3:p8QEȒ9 AFcG'C31QE83MHD3Ab::T; K,-iC9913/mj&*ESS)1InUYi5\t@e01q[jx$YJX]3qk *!" kve[*IWb;P>$waP#:e&`F dcL-+ 3.P"yꪯ+״9{{z&||/|?}OO}_}o}~O~柏~~Oߏ p,*p lJpD`Q5"lPAt,iBp,l!|DME8l a 7D oD찇? xCJq胡 m~8Q&8ԡNk~J?P"rTp=+(D9mxFlHxcEq ZQ@#*>3ڀ2It%)R+aŚ̥#v-L bG=zɪ嘼8-m Z!.cmDQi ̦?g׮O$8M=\/*S\DaZ.hu<ۺ `  Pic 2 , );  B;@!:@r-/A`'I, .S0R05/2+2yyr@4^*ГypDY6'2.riM3"#A /%l5aV'wc + ~gB: D-5!?:l-9aY 5i=+%,!q"(W)!(b4+I%/Or0Qr1$K +9A'֠ $7qKu;,Pp&]!E 0w 7E/psv7߱:9C}0ˀu0BCs0z)+i%;šcR_Ja<>A<+=y6!_;C$7`y9 p)1C 6f ?'9  P1 - p1.P2fMyQL1`dZLrf/;+0/22"v7%S&W)2s3Yc :Z1#Xs&p:Ji'@D222B:&*5Z1)5C p 7p 97p#*CЬj"e e8\ [P")Z0c@8#*:9C[o` ;ɠo! s!  ʠd`g(@dՀ9a` M f@ҊSkQi;t!ъq8Pp0Š  ӟXJuN݄5XpUGc8VCX6lDS4$lC@a8Z:1To}~dCC֞ao]0dz;*> 013ɒVR Ŏ ȡ n2Ҋ[[`3 ǟp 0s|1ite f/ |R`!i* _0z1r:L#!\#^p>#ͽ [9e4P&̭DRͳ!*]2{@ >ۀ,1>w9&'0W2(-:c1{ ` @c a/1Ќ!89oAe`m95  PW]>Y&S8$/RD֜tV mTLDFRpT+\6*VקRu9*;< p'R< p%ZL:  GqU7=X 3A  q}= X X ƭ `2 51!zx/!x˻ 2xPy3-$A#젩 ^I"@/ %~s L'1XyY13T%o%  A|W / :!;/EQ' ?k/n a((eo`ОŰ900qj m < PoQ fQ dPpqO6ACea1i5YQ}cIRFB"UYeow.x*htCW6oI O{ ⬠ԡnQ\QZ/I f@h >@ǜ /0NP    f;r,aNe"[%x@[ .#]ü,9 ~@/@ ;N…{ޡq (31qwwDx7Ndr 2S6l3} 6X*LdʔHU^@`,Of)I̚ʬ `-@5}+0 d\:~8+^ledEKvY U d!/l"R1߿m=޿<x-= _ę4g?Ms>}]UjHՐ?XeRuH,p&`,(`H`z`(@nY#(EO`^р`p0Ɵy)Grމf x材pƢ PȀH (9q*$vl3<9wD"@!Jà.H#0Ȝ>A!&L%:J/L0-e S?tj,XYEԎTXIAYgH!cH-܂K.Fˌ .>P#x6f#gE*Sf1hZ#8lF+@5_fAak3ι]~X:EI;O1.<+oˆ HY$\E5wJsB/|.w)wL֌<&7cbgyǏȀt A;"QޡU-G:4ATB&Ze0j> -#az+V dik1v hk,Hw1 w^Q Z`g@&|5^l ? x7ɍH"(9!L`l !Fpdq`S2Ho :@P VAgVIOLf!J )Jg-343F6 miBԀQxg|#"adki̊H 0U]1qW-n@aovr#@!^ N"Ѱ01NB@=e^ B:p'4~g'uJ>A@Zuwخ#x;%Ǖir,^ڀE?XQ*HEUxzv`<@a  {7}#0k#SF=R~?l@@1P"o({ƁZMk&( f`X`j#3`Aq31c4H0"Q$t@8. sBUNUaE:2WUs*VbF!BG3,x*^}+T`lڀ59W0 = 0 acI t R\A #Fi=`DAP+EJn@ZB<I;"HpG9&L`L'P\ Kc^,lӛDbIFCvS `2*v!oVߖyQb7zCv9UkwPA!*gT؄~0Utٝ7( 7he ՠ0kp nQ0cP j\PT$i@%ps0-iRH`9"1G9#XnSbRu?G&!Q;|skalG =.48&i9XANJD܌IQ r`U[%DK3A{lЊ|݋F/ [4Az| r^"IdmB#` hrHbʼn!&[L7uY-+or&;+9(8%ɚ (.Q9R_!t%TĽv2C|MKFH+^}VQXشZ#>ycdaXK]'T# "ӭ!Qlvq:F-#1.IhR}QP&&<8VDpX8SFG̃?0Yapv\B€@Dk@2/+D@BǼGON"T0!2? 1&?b$ HP`2q>u0n&Է>w L# BO`RG<($K}G}{oha _Op1 i?>k@>[ @zh?? Ax? l![A !#D$T%d&t'()*+,-./01$243D4T5d6t789:;<=>?@A$B4CDDTEdFtGHIJDF4PQ$@XV؁<Y=NЁۼ]X /"?&n eą0AkD>>lDrC?j>Xhx7pங|CRBAG੪Z8"PCE,Є#N4PZC"C? \ȅY6,\71葑phƑw5a8/X>hC(ҕHLũҁL(7C `=Bxp4.G9XXz+h0"oB0 =$?+\7;`Gg15agxȾĈTOtbGBQrb`H l0(PؖMP-(AA +  !͑ %up!hT@%WISS!RQX RΊNRh^W_pA3\=yOh@ 8Qd6#S?= 9(ICfI9 傆Miwu3X)ԀY{ȇA: {EBb~!HB`*h< h4>۬\ѯS Q++qbаNVHJR0 TŢi>A^ $^ , #^S]`( >a什`H\H]p-F:-txt0hL^#y9ɅhfUw Lf%.0uȩ8qH[DI*IrIEP8ՌPh/li-p`9K`hЎXTH"2x(  @12(q sj%;i(W(i( ɸ C F4X*xH؀BPd@x@J< T9@`cذ?sX* :`cGv[4kJxL@J@RÈ큌&Br A ́_nx^gD>U o 4j+.fյ-?8#qZM '$ AK:P_p/Yv__}j՝j$J`g%ӉJߏ`fJq >nq@x\\oǗƈ-@XYP៍k(l(cq y0q1ػHy #pWH; G ⛢k|hFgpJmXBc D XtŻGLjxLn" (ehrI eOR!&(>H2# #5 mŞpbnf^q oB&K g.8q_0pqU ݱuv gpsih &:a¸Q/znFh`{ py`њY[#4e<S5I '`Y :;X+3Wshs€s8j1kkHZ7XCtYC l ?B t30ٸ!Cȡ{|pzZ_mdNuXT4X Ȃk?_n@ Аbvm(_5rzH?:sqO(HfQ< /XZrHO'y*Y7<&ꃏhE^QOUg`wݩ/b,`lྭ(b T a Lbu"V.c'O Ij˅AXq5k\,&2kXKCdiʘiLզ6,`MjԘ+A7 kW Y"Z1d0 7.ΐ< xvTƿ|NTp?A"GY2j5/.FT􀂕`gtTmO86q#w\( ,\@ާEY}%@L0Mtˀ1L.a(`A*`PXd  %H3Ed_AhAqcB(S NAF8cAscb$P9|@;:!H︃Q;1#:9a+ B3cT.k7) ?D&\u PAP21Bb?Ё2 A&5†,:( &6!}BB!@A&,2TW @40fpł@!hb  Ř zƂ8MBQZ hmF5*ȕ/lS9Ġ9C7rУw!K $iIX@(oH:80LiS;mQArD`+h*WP xێ,̉0C[+ș!/TGP >3R>`&F! 3h(:0ݱ" IJVm*` cA6T*kV nKVP 28yŒR"#El82O'&kpe< ֺr0@9c Xe~ `!@jWOB^|\dPv \ypv`C'P/Н%=P!8ڴ CJ>uhh;O QLESE=2! Y" ((-#B0Od Єe3G802#@{0`Bꀨ` VPgBn~Ѓ B:[+?ԁ3߂|!9A0!J"ÿ-=@J!8B:rx bmvF 8@spRs,@]A!!.Ȩ:OFPl )òna d0ʠa)PpoHC <9 aH ;s)UL G bA!B(>@"@A,p!tC[X7cWC SGEo#?_>u;ϟ>o"_ȱ>??o?wD>C?o??}DX`"`*Ā JR`Zb`jr`z`` ` ` ` ` ` ` aJ`cܙ*2a:!RaZb!fazn!a aa*a!a]a qa!"b"*":#BbDb%Z%g&rb'z" hC>@') <=a*b,,b--b..b//c0 0c11"c2*22c3:3Bc4J4Rc5Z5bc6j6rc7z7c88c99c::c;;c<>c??d@ @dAA"dB*B2dC:CBdDJDRdEZEbdFjFrdGzGdHHdI#-<`KFߙ$E[ B!Dn!EE؀! `" `,B>l_AC>dJJEl!bA>(Bx&YDcE0c\YYiXRFMnFegt@Q`U^Ef%luFnȟ-XY*"XTSb<F]2 ^.^ޏT%`fEaՓ-eo4HH&}R\F?`%؃=8BJ,gVuRފ # tfeF#t.=ÐRJ 8fv*eun!hc ("Hջ=kaIY"?aHHlkiƻA aO\fAXKnFf ,d\ٶɺ%F !]Pk5\e? ؏lQF^kYj,?l>Uckpv*MYAlu%?tЛ}Tdbl>\l*H(aYÕٻ^P>řTZ_ŋ*bOcl߰l@oÊ +.?BAbHf.2۲R"B==mRek. |FY(Y氲= !FC=0&?8- kq'΃"NY@# [Պ?!^AO*n'^a6F^F@3?, |  ݬmihP!AЦuqk lZK.kj$log>I*׮_O 8kOfOņk/Fe bfnfDYd%oY ad6TlRKNC~_&?,G/enF< .'KHZrg۬"!.3&l`^# m[B Lq(/jsqAeަEt[f2ڥ si,PgFUAFjFOhgKe\ATnA y2o kcĮpn¾0elOQfrUjH.>C3%FV@ M4D a:At*,mI.Y2;҆';KNnʧ) Ts+VC;g`n@fl +F!&WEg",=\mOn5GZT2` )_c$uF$Bg"[I.kfR-P [ALN3&6-:敝y3 WuO>F9/97!|9D;cFbj* < h@lTolze,VmnAr&Z$"73+Jnte~F+  "Ueeg *ҭg<,g&qSt.· 78s1Rr4"Ѓu. G 4q%DwÃPNRfm8:dvu#7mlo7afU`T]1/5fy;tT&-^+Іjg@d|OF*RL:k8mFVQM.s!kl-Gsgvv. C=kB pqb"@"xgxYUmocT&ocb?cr˕D0xACnp{qrȶ x7iB [뼐AATRO 475/}Mk>n.u8w.Xgoj41?{<{Ua gOaS1;XN+t/3E@?AunƲҶ:[s?joen;iH >f;sQSKS6BN@!KDP&ۏ- /!C*SDFjlHʀkDO2C4/дcC42|j)Tɀ *2nK(tfB`W}L !c(A&T0dDþĎd)ɾu?Oɏ(W"3^zO0JN:p> p)ۤ-jdLF'ߥ!fX9D`Lދ3TjdM^#k'.֥r@QzT^=;Ӻl@65{H,JQ )$~+,*dvqi r:eM2$4*NQZX$5*=ZpQ!0ZʨV\VU$kg:)H\&[xu7ׅw~O귮b[qdمu]ת%$TF!be:,&>!RXs<—i+Md":x̗ IPڣ Rdo=C1䡮)C:8)ɪ|GfK[E!h "оT(Ch)& \dH*pj{[=F,o b&|oHF"( zY̞Bt O9F4KLj/s_isp!Bt$TSFP h>QsQ<|'T*Br?1)o>xX*c>R?=Lr2iLF5Q I,ź$!k?m-fx'!R2|QC 'd6yIcvႄ<-}0$GQ!bZpDF-£Mo;!b\Dwp z,^BKl(ilXىu!xC"4]p3SOSpd3X%&k8Bh ӏCJ !YvZABVަEFsTRu^f !dMUwy8|E!Kha=#>BX Ԅ075H"VUD &z7M[XmT䴟)"񪶏UHoKOvZm BB]Aac nDR_ AU n%eY.y$vtI]fd'viьsq mv6ϱI3R"-WtW$D/эv!iI̾9Z6O9K9ϡ- OZ!buiA:-@hk]׽:2s:m<{^ Yڟ<]k-#nq !ܦ9 Rnys O`> !_{7p/ w!qO1qoAr%7Qr-wasa#ns? ogE7u΁'36$fpfi>؃S>v:;'[zߕr vXe\! oZyz3}-xs i}fxǻ̼wOBf z 3 8+&`D O `83IW7|ɝZ ^% њaE6?Pzth~_@BOVH_y!we+~ǝ?3Ǻr.?/+j/N+)7h COEtnoA,"C/tb `0ePO9A Aլ%qA{j5!ABtXj$,!0:d"!* r?n@%B~Dd)!d j@3TRrN j)ib0|Bx*l!q;\gq$Q1D+{&Sd̒)fWLn*8*n)qLnj!"b /Q"GP.lZFm!&C~"lBR#W.h++v -5"B="*q0" OӌB"#D&uNC6j*8b)QD)#;jG,EB$C.%!і A2$ERhHuTqܢ.Z c*Fh k/;b@)ڄ@bi)h.FCTrD gG>N$Ra"#,"\鏄ݤi$2,5JR$.,Sc4>!D."&1CA N(!nr"s`'AObtFqĊFRR(-/fSe*k R2#">2Hzn,Q35R-A:<44_G.9dq! !xL)1}jdX761:0S* u$Z34S3Cr:3+#"$,):Q#Ts=ZN.j@NL%R9lq7 8[ .b@e $M#&hU֣[l`SR&Q~R"0"#uX@=bI=]Ea%ʫ~Q6 IRP7s-!NHti* dY7HcH}9ت?ҟ(#¬iC%LKMDFDóD9PlY6`4O,Fb2Щ"EeL5"bCF"",ⷰ)lOV%F5cqB-+C//D&"+9N#jOq5Wa0l@>l`elMLbTdrWWRtmfUWu[X>ʪ[ɵ\U%\]5^u^^^5_u___6`v` ` `6avaaaZcX bbmX@4A̘OX0n M- TVH$!l@ārlWzm@j^dR6MS_%L@nTHcx:g<**:,I"讴1yL ,v'I}|©FMobC#7DY GYg@h#RWviQjgOCQ&S(9Iu]cq&7A Ew /r8?S"bzYvYf("/uuoN"..¨a9L +X[W 匪$*hGqI brˮJBت z1$鷣#.F,3yAbbÕ&JR6J;8smq<"%8"*>"%JhO2Z.PL*Wf|L)3ЂR>LJ ^ h!D=f'تg|Hк!Ü"`EժRP Km42)PgѢ( f#NH-(ֆhg =j`/(lVC!0AAчb58"ւ$ON"˅{hZ;Z(b)e`eGr}S4( b,AqÆ6{xD :??~ 6aPJd48?w/iߢKl/J{ Ly3㌌pz@拃#0G3"XY_:Xh0P7x6 DSpՐiO-cq#H::XFȣۂ<ygu(3AE_02=x4!#0c聑ExÞw-U9AUCZcY 8 D}3u ?54PA5<XoYXFLɤCCQu@ԁJEgB } W?ȌTr(TÐAͣK6`C*CTm4"LCGm(PkX! R晊QTAKԂJXM)~@I!Z %Ev\TvA{gF$9B iӘhxE[G u%Htdb~zj:dfPmRqȴ2CtE/߲@դ'`#`9=HҙEmwemG;Ę8nYE @DU*k5i\%d ~LQ>0ErCYM5qH0R$+ OUwcV6H!cUP 5AwГc}6M2)װ`Zl j[n]*q-iIr6kaYr&,""5IO-J}(F)U}ozۑ#1T1H`(2^J E라EZ5촎4#\O>HNQD:4P>N;wp0KndRiPIa3kR,WzVu W?,<1#V@=O=@S.Ր֡iy&#ufpyJ !Sً R*U0)L d qnDq}p(!MA~d# tMY.#JH䔆G+ |E?3LFxq;#A4@yHRw7yq@V5JOV:%,b KuI{0P!HIRlDn7E׍,IΦbznCbU J=9 E&4#T,{Zrq}+a/U5k ;m(%yGDɮ]ĉB: ;@0=)Z2_0Hd i pc{vxG7k̃6MFDC%'$9P- " U5c:ղlgzؐŅN!H E&q<vh Q>ʰBɃ0!e,UGtƪQ ꅤTE4j'"w2<ς΀CGAQ ix0lfe?2ܘABؠ ^:"DiJ}Q\ Fjof#ne"6:ΕĀr I4SAp'fr1Te CD'}d6MȮ PRa]S=8Bm3_QԽL.Qm G1!?x;8A%30X*E+lfr=BDE/3#"NdI3 $F"9x-,d6J%A!uQ 1D S;%2Sq :䝎{_I"D&2WdV$dJijE< A,dC"y sIP%GwckCXjJp\TD84H5]='gSVm3]).Kٲh`Ct`rTfڄJŔX:KlTƋu 蘤OM?îcHpG I.{*2\LjrʙUV`pDě;(WMi4VCp6,x>$bm^2TDv)",5 bdOȊr{b5wpnICTN $DOreBY^o!=SA0b_l浺a xgţBP9c@_ i3;1&/sW\`}ȝoc{ I|oq|%c5[j{}wrBcw$yFrz QW}Cg"a|WC}w)٧fgfdEdW!-{0`4~8}7[rw'N1;pz/Wfxhji2lp/WB&pg|؇~`e8XxlԈHс)v,P{؉8X(GxH)z8Xx؋8XxȘʸ،8Xxؘڸ؍☆,x蘎긎h{8Xֈ؏uYy ! ِIYyّh" 9$Y&ir*,ْ.294T5:9<@ 9+(FyHIoLٔN-R9T 11j/GrˣjmZ*1gEScU]ozR3>H%(V$uzJ!MBzJAR)zz `ӑEf61e6 3B/djs1`^DS"9Z;fCVe+!RWt2^d:xx5Y&q$*n,b#ױSjkm"hss)FT8DQSo8EҘT,]@q]ѯ"P|=6.]ie-KB{WO" qHPeC*ARqcWD,k.ku](HM8=_lF'aK\![QRf$ZwE(e:e+& FEUn+VoY( sCNDj!@rX'is32+6Q7Kc%UV2l2fe EYHS3ûAی,4!Jeɢ+aRD&u>j4OѡH? e KDd:'k %W4&.[0U!SQ 6m,l_ ޓrm,cƼ;&,_ZITI'FGF%%/EWţ=Gt4?pigSb#HK  bl67riSp2J*peSFl2%&\ {԰BTu\3ܳVD,d> hqSΘV!YO͢92!?[TB9"jQ$L1Jk̚3!43E̊qV|U\|DڌbOSQz&ܻ4XSL? !C>k=xi/ 1롶ҴlC4pX{#@\5k˺sFel?-{?<e@@P/PT"pH>׶[ʾ!RoNA*l~p7g, #Ț.o1=}hJ*m!jѳ*۵?! 6k=WS@kT2dl]݌qS6FˤpqUڪȁ8>O6#|̉\q0ŀ/ ڥ{,fsjqjrcǚ9|; jkKrfOq NC^=Sٳ]m;̘0; n630-cNpmKcG/[ }fcfꅦ3-ª1K<`z2@<#Zbe^,}YZ%I5>K_\I^ `%ꑺP6GCDaH%>H "R$-cX!N Df(;j-dfMaĐo((^O=1?bJ)c212TL1a#a@h4XTKW枆P5Ϥ(㥥|#)pP6JXeo&py@<|X17N6@s,FW(H|#{Cs?FOR?T_VXZ\^x+e bqv._o >2T1h"Q=WjOk\Ry˽YZ1iJV`j(x1TkQ)f$~%o#QHQ*wb=y}"䞶ۙudM/%>/?$bA&dEO PhPI!q@! F Tˋ xF4Q+=a\C6h:%2SeEQ4*8+O_a{% <,9Kksa3E<˹n(t'f@(*Q$#BaVơ`QKdȒ]5-J'+Qf7yÂch0ԔRHќcSP)8*{|EQD>PDJUk )Ǵ 4tgÞyh:JgK̀<<&jcb2A6r,Ї$݌#4⣭ARx$jQzT\8!xH/b՗Vj0IG `LTӺDj]zWU{k_WV%la {X&VelcXFVle-{YfVlg=YІV%miM{ZԦVZۓ?><нq=o۵2h|w r#e;@[?>6#>tH;K_{iw@5c+i s 0>FkpqFӿ7zLa6n0+!;VXL [N-VpTȄM~ KKlj #B*@TdC2(50Bd0&BaH-B3(*dUCX37T"`CLD{MAUF;DxS  W1`D+ R[. 0E 9Y,  ۞ C^`Eb\ ;vt\Smux3`H5+k#zdD`K3f9 /N`G#{20t@/f93gCt6264Kw6X3, əpK[˼T{D80Uh.uT.-\7#dB#b 282xA%$.1Ad`'L#J0JbxX%K6} ˂-Ux3807KP,L>-."8NǦk͋W(M[(&T(ټ9JXOϓ`p`HκalN2w`Ph@>[Oq`>^Sxt`*#>?S9HWuMW2vH|+pܳ>gx=u[S=-??>u 6i/P 7nnpɷ [KHuTA4+ HYBQ|ʋP(jx3.mB  %BR7Y0®2hj8B ҂("LM$VZh׻$ֲSӽKP7VQD뭁4DmX1LsX \]$Md O lS1]]U[EPu hË0] ے /0H\32hi}" 0hW=;whdH۵2%C<0#뀋h9ql^#[3v @3%S?e3}Ƃܳ2 KXo Q[<.;OM;ZN-}*Y04B}#Tb(%ZB340 a`4ZGa^ ${Ax:e- ۸TUPZQpL"[J;O˅1LWUUȀȭPd[܂hE\9Ǔ3 V2]xc<(K>A 7;/Vq_8vgNNv*+2 !]cg/dV~d|Ճ%5(˵U htg(3@Zbp6 S[IRb0".sfm.(dv`}-0BY  Y T3(CuJ4.}4gNCe xa45R8_\#6="CbB[8f{K7&\DsAHUKkUԗ*0] `\P(b0ŮUO܂``({ 8j h >.@޵h#p5[*3iF{%૿D3+R[^8P7vƺZ.32&]fӶI։D@sAX8%&ً-. i~Qk0StfJuf,-C&w (K|fRpRh縴2Ajڜap%GhaɈhӰ@dLG`L in \W%OEѽՂD(Ǔ<@j\b|]?+*[,xϒKw9=eVwع)] -㳃KXǂxV#+F@wxǂxls܃k`l lHfH&KTpN fەJk ־`| y2]=‹S87 3P%\K<3A^5Ah1tl4"fM6iHӁHT:# ۄlvY^ (e_MW)(0EEQȀ& 7>E&Y^h&8Ue */.- `md>0W8;0 ܵ;@F(3jǂhP`+D[c9@5k < ξ%9hh4?ddaoWhξ_!GA`EbfILﭜWLîÛ8uXzKo[W 4\^<}U1`8\Uo` ^_erwe2w0F ]%vXHx_j[2r.62hXǻfi`sx߹5k^kC^edw+ 2l!Ĉb#VYQcF#M!LlX`!1k"(d Yḯ|LFjJžTeKFXB 7+ڴjײm6)V2L޼>HC"A4\"z/1H S୫0BB|04؇d 2ib*)HeRX\+ECQ4l @d!؟X`xG p:-ah+xF<ذ8H <0 $^B/ -SB HW8>HB|˞2?>Շϳ 5x M^9טk^y矇H<󠞕 :"J4pԺsz, PB,  @:ip0?|ew 9 X4m)^@dAިA{Osy3 "=ȏES$,p&?i5(BRIUc}!6JM"PL f,(D l,Xࠪ=h[<p!I[H5͇,,7?BʐȗӪcG !:Bb3!1D7X[v*wk;<C̃ܓS.WuC A\|Xy߻=S BHDyC a{G>fsk9#*9ԫs(#FrZW:"b{s>/??ӯ?/ӿ?? 0H F`E2FB@ epEJCDlƮ$g ixJḿ,́ȃ<ȎD;(!WցZHBPB:C0;aD: J 5[]׉K\ @+!IpdF4D*!Da)JE i| (B0`@@B@[A:;xZA*8@Bb0304BCw0 C4\B,@*<@*"l5@EHi9W 7E!\Bj'hDHDCIf) PF*(DE<NT%-t";"cA@++;|0@C@"b*0C|8(LZKE, 04JpD|OKD#d9J (8SBHb&8DD' C*RCB@F>![FDI TDD$%Zh8D0p,Ej-fs8DFzfb*hgJd ():CH8`!*;$pԇCm&+bB@JN,e }BĦD$Q*N|gCB B|'x';'C\*hJ(:;z>j~:b9`gB@zm*$*A xFC*.$;P:r.;B;ԁ@dBԁj梯>.îHwGC3#1&,+@@HB,$ ;q dJ)BF)@BnD&$F(DIBĄSOl05OTË,.EBlZ0DOQ,$ņ2r( XC}PI92ѱ-0# 騠 [ɐ<ڣi Ri>!^.D?nC;j_bE B:,lR+*t6ĠEނP+BHd$0PU%"*0t&*)\A&*CtB@A0(T&D BpqM,B- mCn-@V,Cn&F+B;0Cj&I&'3xjaB8k:"#wdxbv&A38; 3ACv,JqvB8k0.x;!+&cB|o:)ꢴ8|CH@ H@d+B aB D&p'lΰJl ArEXQlN5ɪ,MP0 *CɾhV +5DAOAT5I5I2̉(U$D1$fE,DV2F^]-!.L,Cۘ&+j(DX*O2QTET)[BBFBᮩF-jBeES&.j0o`Hd#D*4.e*D%Bdd$D%v'$DF* 'jg*DB0n0`.W:oK 9C9jr@ ,A4;` <4&D|A)0zoVd++m"+2O:IzkB$1Rk;B#+D7<'*EUS6 E?3;DiPlB(%4.DS1I,nBX!C4*LX>qBqB5PB1@\3BpAT*DO(Vth[0D5qB2|ZB-x6hgEp(UJ&J0h9ht@H%RWCtekR |YeX/+*hCaiX-*4Bt#e ɚD]%Er^As03-s0B0>o'<'BLsBB0\AB|w6-2DAOAH2if"oP@,9(/+ĺt&j>Meb!'bv;uBl+#Ag9 ,/4 G*P˫+~gȏ3 p8+%9^Ed7J{+*X7JD%_^<[(I vBAKEB0pCvCD1ID6*+aSNx,k_ɶCvy%riXB X#!5@ 6M{=WK(CT-t /+Du3DXK*D\ZbWC6O6(lj3/xBd7+8{"Ż8'6&H' ,B+SmJA8oxA+(k**aFϢ3#88PCɢw0Zw <*J릳y#.jtYb(*:+ڊ>eU 6jKSV!XNdhDaV`(ɌaڬB 5f@dy!j1!a 35hZh9[Ξl8kB$&pC܃Ϡo>k pL0Fdy9BpY6CTiR :? TI!akw'^ PԎ<+Ԛ4B54W MKUzօdjG+j2yyG:Xk e?/o_h"iP ( `/,]hHwa`k"k\!"llA:#b ŰYh>yd 3H2&3 >C*ADeAsB[ B3@|=Y2(Ax 8&;D&UAY@k4B&5Exф`5!p6Vh ?8"? mBPq*4F B` aFޢd)T0H("t5)0Hቾ` 503β-OsD2:RY@;r;q@3*P e<8B",2* Auq Ltj(C ep5$ j! e ¨ š,o(N !hd ې p-Pa x& f aF !c -ki lBhf_c@=B #- @|@aBABv1AQdQ@a  cf`-2cBi"=쁌*f0Q,hHi>kV&d!2&#R"' -H:@ [TD"@F"[%_R ]BBJg#A&~(?r%Q! &R)rj=be+'wRr"(R,ǒ,]0@b-2r C 2%2,+$R//;ah<C-Bj"q!+r3;3U͎Bn ȱ+!Z`؈3k6ozba<!/q2Ac74a 97S>>>?S??SLm$?@@Gr+ TA[ɑblX/*c2C3`CNOLDsA!Ao BC2a@ `:^iHt`(iFEZ"~@4G l6MIks8|:xLɴHTXTLwjRTb g"+!`HdߊP#F[T^K ϦCxj;d!@ZbIaJ/JM*` HƄE~J!LtP"jHdbOn"@*·VOݧWUɓ Z.\,6lU+#RR /D"t/-- FX!߮B`TBoUGIdui{b WF' !a|X;DQ UlňLYM@Ba W`Fp4fԲPU@1\, jj/R La^jkhLnbX ` ,k o g 2 " D,2`l=G`2D<FW9` EW@)PDO b &Xմ¢@y Hb "V n94cb!T%t!V %|v zs M90B6nR T6G} ~@hÆD` @ e @ B d&` ~? adCw`TofQl\Ѣg hEv!%/+TjϢ_σ .  ,JI!DK{A`Bn"`ؿz@M.g!*qc^>!(uv?bUxHQb ll:h!!P4*Aw8C ->&$  U%&$@>.LHJz9:XuLց!vB#!$"tuAXTL!v2^ N,dN!"icD"S:OObWBZ!ȍ-ڏ"chC*/ Z}D|!C2]@ 9B2w!.gc_h"a!^Լ7|!2! ϋᶗj"(e(R@zUj3Z 25π>[U$KH{I)pp[4go!蛙DEqлKt}oXu9F숉؈O! A$# B'QZQH"bT.%ʪwݗ' V<bTn-#b"*ƗǛVkZ|!N5̚+~$0TȚ BgFIJ&`B>0+Aa +u`CAM(cM1cA@5@c,T5 m`F1YECX5֌@@9D] T#LR -G0I-R*eZnɥK8O>P =0nUD9&B> CB'EBUYٕM B(B [0t.L    AKW ƴ$`Hc14YeP9!D[4fB P:DvCѰR+):2;~TBhu]CV96t^zD較Cͷe%Et&BPe/106UƘ"X>fT5¼DXSF.~hfX@5#T5Hh.QYIWv uROҗ;` 2CQDQ a:@CP0FegVrR(Lʐ_vu[c_q(_TiZ y ( 5!8B 0Q-GdTK7XC0;%GZg yh!tNlc F׾-Ξ뒷#Ѷ.c˝woehkY@-ZBT#*f!Rh!oZX@ FT2C$e&3e!BCV!;;HАbP3+hCZ-i)ٟDX!?@ś DTV'c&PѠ *211mq'^щdWdR" ~2Lg GQb,BԀXn̵e"ka-wxACIͤtHjuy:ڑ4`l;ҘzG;>( KgvB@ݵzYzH3f_,IWpE9<A8 y͏Z8SqҡW4p rΠ|%8e%]`NG-BDTzլ^V˺՗Ҭo\z׼ `cEd+{n+Ml>{Ԯ2lk{6I p{.o|n x-oM!-,= ڋް!,,= # 234668688:;<9C;#F>>@"B%K(O'P)T+Z!C;.c1k3s6{8}ANJWO`Vh^qdy$LB&QF&TH'XJ(VJ)ZM*]P>@@+cT-fX.k[/p^0n]0p^2weF)Q.@6D9I=N -J> Q .U 0[!2f$7u'=A%MI)XV-g]0p|(@f4{K@N@ SE!VH![J"_P#`N#cQ$iV%mY&nZ(q\&s^({c(BCDFFHFHHJKLNNPNPPRSTVVXVXXZ[[^^`^``bcdffhfhhkklnnpnpprssvvxvxx{{{mr zj5u9x;~~9<>= > 5m8s;|@@ A D F!H!J!M! >!"#?$$%@@@BCFIILȥNѭPӮRڵS้+E-K0N0P/O/P0O1R4Yk+q,u-x.{.}016]8a;g>ADFJLȯPԵRܸS013456Û7̢8Ѧ9թ:ܮ;H*\ȰÇ#JHŋ3jȱǏ CIɓ(S>L3XI͛8sɳϟ@ -H!{ҥD0JJիXj5aѣ .i9ʶ۷pʝK7#H,{Vbڵu LÈYGfw`@x ЌCfX@(PE@5zG@} k|^NLȓ+诹Qɫ `p\[0xoz2(:ϟ<7 |"."l N z`?-tTUTO=0!^{P9ߍ8aiͱhf6裐FŖUϦvK)ΰB#Of!DYp1*鬴jQ @!Xӹg3j4'bZ+&Vkؚ`ZYY0޺\| ]-AeJPeyIPZek拜IՃ >6& "U@en\A5bp@ZΚ,$o;h2XuG;eƖ ƃ I| c}AEI%G-T"e۞ mKJD8sC7P yAKÈ2" DiAXH.A@TG_7 p(Laq@0A(iPP#aߣ0@\gPK!``?'F8؃D:TH2a9̑5bb8Ɓgk^0>Asơ%0!؇9E d:hx;mM$*9hHRA- $zXChpXCf :v6*IceLQMIjfQeAX9bπZo`A;  *.$MP$QD.`R[BBBFՏH \Fcrf$;A |7 H,1 I l, bH@%BaK AMr]La"I؅wу c d\H87 7h$ЂDpnh(:p8A c`B 8naL;a@ 9!AT,&"JBbcf8 #f@A|PmI ; (-O,;! IQ{iRݤ@ iP|(KR{V!ql(6.bƒ1qG$8"rP (WBXy@7LH0)|@ 8A-A>i%"IgDޒDگ>P 6Q̞}(Q|!඄@퉹w%i"V_r$CWxxqQyx 0yg'G{{{7|`ɇgGBs@ wbW{@;& @w7vঃAs&iygvmq 'J  ` O@Vj VPp oveS` P! jq9c  np ِ w ـ "x(r0Őw q wk Wqv`w0h y07rpxxxŰAH(sP P hƀQ_?@ A0<' A@&` >u;P ` @@i9x x~   Àc 98X)! ) @) cP390  :0XJSP[@Q%W\9l000p[\Dtz7= -)p2t[ٕQCoi!o`s!iR瘴GbG 9&u1m1ЅQo  ` Qo  1Ywqiw   Dp 7g(者w (('Zy y@k!08zy)h x(wq0Xx j(xןa 4iPmR'0vV{c XMXu2J@* Fz`@ H@)`ФP 0'٤FZG>+8.)Q ZQY;5bqHC!/&q[q\$,f!R0P7!Bat !ka=)QI{jC~Yi&?vl !ᣖ G)i) iڄ7w{W0o= ` M v Q`9&xX jJ iIAx'Ȑ z`[Pr6'Q`xw` qwz s "pXk zސ!*x"+7phr[z'p` )!B w {Wfun}Z'7vALJf X 1H*9Jh qFP @G 0#0+  C; A[i92ts#|!p10(2{0RN=Ii"5<01A5(!q,"GZ1DJZvR870 ~)i!Hv@^KAྵ Ygsƶmv: 1 00 1*j G: ڭ ǀy #Н z0@8#zi[ APšx r` 1Ax QܠЀ.az'rjzI { [5 xp )zMu/Cn[}"84Jw ƅ]{͐Dj p{0X*` I٥lc` W F˭`v2wO1I"8ESlK" Z4=!,});K<q{i6wG ;}ly j*,Y,Koҷ \LFpGG0*!ykPÕX )r,WO $ǁ+*WxP y@ 5_- ,y(ph,j\Ǔǯ(I{ ӛ |׀љu  i -?l[* Lڸ8 0ə+ `ډgLڂ-F*k;ىLqly  S%!tq̩5Uȵ"bw$̝24m."/5)F͜UB m-<(&Zw ux !ov yWijP} |^I* @` ,~W:0 1lߐ:- ʐ +r(סXp n r|-ȍM-{-p\rTna/WxyI\rpM;Q $sua PSNPN{| `Mi9 vbKՖ ppu'ףL]]}^jzʳ]꽐9FJɼ=p !R&ЭҭGrP &æj q0l18yR*D䎕=qa1!v4Li6S(qO f=pJyyMP Kp6yk0'rGKenxGM-sPqquⰌ#k1(:on ms(W #yxzD_0edlj~,1}vrlW~,c ۧ^ڪ>N +ZA/\PEs1 ` 4ݝV-܂ӱ.A ajU$mٻ3[!ggS wI(Qm=H iϜ. /wf& ѭyTPI5NO /\XaPą88B6}3H87ӆq #'5Re6qZУG64(.ϋk &WA7fT1!D& ^"#.G^ gqIݟp`p)D)x"e R?{A^< gq6 gup3f{#*{0 LƑ%䏝F=Fw=F}މ6NԏF'7v<<;,v@x<hxX xX F H!%h Fy HE#eD.! 8:! !H 6Ѡ fe ](]vi | MvEE R 0H]8q 6I|UZilj G- 2&VFVB:Ah鎂>T trK(Z(~*k BSB cJ%,уpV*-Zlǧ4!GxHFdB)$lp43D b φ6 *@ r`63^ L>,9 ;:g !X;`A E :ozЛr8H!. ZVv͝ :wz9hD ֐ſ&E2#氠E adAI D%P\b\ɤc€Jb. Qx$,4L,@\!,N4a&* lO*pNp 4i'|<"q H grc 8Pmx#qp1U# Jqc; n{2 c u8J …Sa  F2S@ U0zJAi@wrT q(1QTLtw1|@**Ov!ToA.C8 /Z Ћ\5 b0E 7b[hXX;q}c YC&r &cFfrd(GYSr{=B處e0Yc&s|f4Ykfsf8Yss|gS)7 ‚xHy\? xCY08v@8?y881}"&-"vA`S 6(GA{8?8rSTKrHL?cBDA0 l D$3$3H;Ao{0|`&:6H趘o{#$莂Ȣa%ÃXH9T{{H x@}p4?x tn[qXz=P|H%8Ck} ?*2d"_Ծk@5'2C.Z1 3"xzBv@_l|h@F6ԚC Dm3*>`yhAX?`0.r= A@28rFJ ćX|-C0TkE#E E} h#\#,2Cɦ3-h| C5$59Yt"@`x" ĀFx%sF@H0;$cBIC?I&ɕ C2,p"BHIK3DpCnCЏÌHǒ1hP؇-܃C.dİ9!΂pƠ9iJJXË+nC$)u$H\R8A_[CyмE@:ųC҄?ՃxtV48ɼ IvD6ZJuċn >$rHItЏTcμ`\_EPU0i5U1ml.Kl zUΌ&j7c5hWGD'20@5 Ƌջ)&OM[ؤQXUۧAZ)=K9Z6tRVihŨH9 R6$#> ,ZT]ޓM2 \$DY3$cY<4]&BTq#ZńW6\pRcnsD(W]\8ӧ%>H"Slע}8d᧰TCX6c}|uPk]>a eS6Zx?v[.^#?}`9 Kɚ{5c|">bMb]w"Px՜%3V:R7&XD獋>Δ&]qB8{Ř̃ P3Xe&߅mٓ6d!.>R.%Y肸iR|Aь;U2R9LR_Wb}^B_C݀tr邥CiW4V?}cT۟mfA8-B\P+@tְٸf"Ď} TO|n܌+c>-Liq`C Hy9A }ee?8<^B=4>[d^G5]9rcZ]C #i vjfCp<;٩d5 aq0M S{<_6dfCXL^ pХ8:MD= \<| A$!Ŷc0&q&hMH;X&tܕ ŵqH>`" eB h"fcYy8B}Pm〥U\;\_TSvYVJy8ltNJF/XJduXfϜN$iQ^sUY\6eh=<8ey|kZXo=Z\`\K-啋#EPJ75zsh-j4'fZ2|l>,Om*z@A-%or ;s|`-?H SR=:\6=Z#SsDv㶙i(ҢL 8q#\xATs3^Io].J ri\p*>B2&Io]c"=r=["@R++q{!ALGb;GECçƗiq%2&s 5o>]d1w<܇$,B$ޕN|Afn&2ɿE$΃؃h o"|kDZ$#h/zjX}d.m,E3=F;H#;7F=Pr`=hEf8 0@၈Y虑A5f4cnjŒ<00h%/9",@Ra̗KԥqLTqPcSaL!?S ͺVtan:kFƞ"؍j/oݬQ۞3:0ǧ?^7<$'BH!q k{4W" B?ȃ"Kx4$ - 9$N=I!!;y%Y6<+dׂ<0◖ O#eIC-̋Zf&#Wsc?{1.6X/Bv@M'<[9 9;Ɍ. 0U1=̢As7A$lSO;T V4Ѱll3dG9CtCk3mݰEbз; O"Vϛ$) G:?CKJĴl~TԀ!O`nB~e=QO(Y}kQF%Q"O !:ct7;}P !Hj09$o{=:_菉A56^=餃ڵ9hC9X#⹒dtAJן=@f Lt D!oW29x{:@%3xw( !\:*1:9l6bč, v UD)X RK`iLOC , V (i8 ʗʁ4UJaʧ:a_&s-`M AQ!m)efm=+ZQb S ~ГS)t;0ԍ-iA(,yŔ@̡ q, -(TJ2 j1OhSY *Vs¦AP 0&P:RarL=*֓񡇪``t"}l؃$Gz +#6:4#@@>UN.iDQ TSK+x}}x^3<#/S<3sD&AA6Qb%: @(Ccmhp&\A(\CdeLb7|8Lb& ԁ1$CAl86C A1$:B"(dlRhD1+p&`b87d8Adgp"G"gfgvvuzCn ̦1CbEn%L~$,%B(8cVZ~B D</P( D83Alb(FAAA"8MOP%A@eL4C6QV&e4D9lDAr .8.BrB @>v.4FC(,.%h.hCp=F*+K0*+`@lL"n(2aeb'Cm'?r"i_|8*7t"7'hr6xAܦ`6&KC*H8C2t"H+'rk7`mjA|z,@rCG&%:!B&)V'{v?bG\$HXVAx b)B@纒imC3+1k l,  (0Ak/lMhl8#L6)BTE֑bD>x($B7rez<Ėv)K|)Bc'6ʆNXAh.aF.cnB,&ALA&j.:&,,B.HB.0_lB+Dං$b1 C88T&dC@%*f6hp6*i1(82Pg6 `2 $&Nbb *."B88p&'x1~rn8pCz+{Ģ*n 1"B 62 lx`G X2\ll4@K0@0B^9A+lZ,k@/ؤB8,/ltA/@z@z3M,8~8n@ƞA1m*ȨlҨL >D:.(k>i,!@}:Dz))l%19 hl-& DbA\)$>B@b<@."$eB, .$@6|C8(<.L(ô7*r"8kG8hBe+uznrj78%P'F>tҮ:+Bar86CjCk0'94\_(C6K>TBt(D`mlvA63@1Kc3 3(W$F\0B8;A8,3dlj&3lB+BJl$F~]1;NCAX"D$ϣpK?OuҮCg82p u=JF#D,DB x5|:D"@p`,u,)A.l #6ۢb2`7vn@:Gtwn xc+) %8)0bDK~C^y{%$"@DtD,30A0w1ƨ1b2C3,o8`+0  FTA8FxlA!8Sz!"l4@.8q$#Xς#D.+چ5B,$&wH'xaĪZ'VA8c9B8$*u a BjB gl=L2Fp3o3=.6&z6yImRUoF^C2NA`?Dxc>`(7md7D{M;EC w;0(3d>Kh~_MKO Q7#LCx[ygPC%pw/Kund5^"WA|%. #]+C$9W-'$)A)PβCy H:iԎB2aWrFL_9@0cYřxd/gbF>1HJ ("+U2o@~Rj"a]NFu*e)b]\` ]`QH]v`$MI?M@sUZiVlrRjF!P(pZ( #h +ZC`!H2谜$RZ#-Ol,I\h+5R$pI"Czhk`c`G$QF#`!3 1FS$@  "L$0iWC$F F zRgQJBp͸H⮺tIϸ@N$wեH^3o QUH>Z Y`!X(5o ,% 7 uzY,\p!Xv٥Wlc kFl&'lZZ#-!(Pq~T,~iK8Sk0SDɛlT5Ej'F:*-ᆛRBǝ|| >=SK2xL,OFJu~?YdK%22bi&Wy^/b8SȗȆcW‚x`|6IGVθ[hOvW$䗮rBqn!?rD.p!8' ܀:6!3""'( gSE`adXhNbXHLA ] 'Tp@Hx  %!߸l!Y4l#S6.$zˆSV C${Z?25X2 w GΑx3B6pl,r!whI8m$n}bB;Bx ԉ[ |g$';QR1*+W K#< D"W5Z6/4+|D:=(Gtl]IVQδ UB 襡DrP^&Fp]pHIZR4;0QR1LiZS9NySAPZTIURT>QTZU^YVU~aXZViUZVq\zȃ`!;?[u3J >=Q4ZZ^"Jw7kRSPYP"Yo:w k%Y6VhU;AFݭV{v7 %.h}ӽNnIu ̠a=7;#Quaޅ !qk\Қ Z՚7zޓWanu+9@]"nO~ -f`);E2juo]H ŽzA!xGN9<߅i{P!7c|1F2aTJBX}OnXWy1c@,$BlX7&pcعaql #+lm׶SVr9TR'pq|ך<ш Ւ"lOCfw V+VfЈF<.snC!~0mU޵SpTkծkYzM+Yy($vc?^q `SB!>}P;[Ӛ{s:hR65GA+9?ơoOu`g`BT0Oʜڞ:cC[CB$)x2'a7[~|rt s*d{Uϻ) 1:_<3YnmJ/ BPZ `0T  ۞r?8&?d$,n[>kqe~`Ԡ}+DH1}\`@\=S`]u7[ RDǟ"Ͻ5_U{|+~1>>ƁVH!~kvOrT+L\7މ[R@lVJL$N$%do@xC~[* O n!5lM,˜LN0H0/$K!XEBgf  0! 芋&jF̴"o!(p!,7{p Ϯag W Pj#!'{!+0 w0O7px jAp!S$́m$K0PPc$PplKW"h~q$nHq Q$o$@NN"@1+4<xԞLb]qQJ,! G"|DDp .XK7N$ o!@`%""aA阐{1[TM7QD0[20kl@$`$d2m@Ϟ\{/Nq` =a !WBA*Zća&*7RDr܊,R2ݢ_q2.Z`$2/ǻ b)y7rd*rr*s Qk a.Wb{Dy-/*ĬR mHȎlބ ,-2RP!AWL$$*:w[P$`r#BȐ,̠;K<%ADK-4W"JMZl>Ebs3W1@H4O)i4ALEm bdX@nGe"Xd` @DHK"FK0- n4flJkJ.dƋK*F,GqtGYG+ I[rH*K-IIF12鮴Tþt$TTr HME@/K&R@lq$P_TCUTGTKTOUSUUWU[U_VcUVgVkVoWsUWwW{WXUXXpYYYq}Z.B:JQurj>RIz#\j FnJ MDb `Ou`8&@o+ZI|@Y.!Fajb$ sD2h!2aF6'_4[A7fnƈb*a"a8zi84Z zg(i\q@$q|(BPBONB,h\`D @ dǫLWZv2*2H#_ק\Fv`_>b#]FB_F].cC!e.raaRie* v!fa*iM&8AHAgKz#"!,J&MAV@#P F$jh* j/(uą; .0mn1OnZ/<>Sio:*]w"PpBpGC$~-ƃ;#,r]$6We D8^Ate*iD,uCjB']Ch}#Ld(AMdb!z7؂uT'\w\<X|z#r77w!9C+fI!L~8%swl#=F"k L8?D" @$\c! b`%xte Tax!`z`5i,rB nv!BAIbF!NU!P@@$.J*8+28j, F >49+lb'!$D8Jlx!] ^WQdyJ~Z6:~x>!ʂaH/€`zxjE!<` I`w zx`4xA yayJ.Zz&ҁT2f@: ́nx!AXo0!oi!L!f"ظEŇGB]:eX! BqX$X$z ֕R5:,DnBvAAr!AnFdT?:{hh$x$.Ath!XBEXEVD"' l(M,"jw jw'j"D!-*xvCKBjfjVM›ę@o$$"7knfjjWy !RZ}u̥pFz%@2:Px`i+6Ufw.|3)2xgWz% 6ee0<2C!™ᢕÀXv`g[ÉkSCG`EM#E|kE3><KL|:&Iߌ8L+b|#9$pDU _&{!$w_66_/,$f5euzvA f8d\?t\_;Ea?D..c>D,fzDgd!H)*f Y!@H5jZ0B#fn6A I@!Fx/tyu;B # MXy%*w{!"(6 P i$v$Lx$FbZJ7F*(+`OQFa9bf7օ z/b%22zA! x6` :wW$< 24wbE44D40f\3:/RZWJ 7p4/+[X`Nt#ƞ+|f "&AP$tx,̜oE`.wƯWW&W$r /_$>|@ca\b"B ]C}XB@X!le´wcB?X?NFwaC && kuApm6PF.bK܀I,c#"l"_$rXp _n)[!jiE޵( <8̤ ]-‰/8@; EA>DAF |@ E>RΤ衙31y93 CXY3B=P,J`/gc&JU|ڌ'AB,U#9Kz_: :W^\w`X \ H_#pevLМ=p8Z9.߸ּ~"")#o2xk $%*Q}&JI `֮[T((> f KA 5 M_QK@S DoDaQhq#Nl## Akd7߄#!@7-88[88# $@ N91|H8ɄP"Ģ!N10z xdAPD0q >"2)X&xAPr`(A7H'%A @ &]A*i$(1դxhA>9EPIE0ӌNX03(WDePJkhA Af[ݮ՚\E n!!Fttd30f]CZg3 ?,/>"kÿqPn5@)gEQR1W?b2oYGLu]o7. t.xrFW.E)WЂuS T. =! # j1|X#Ad*Z͎0I6B2 "8d@6?8zZpixS&⡋#gAtt8'8w"7qIx<``p. Bulf !敘kbx?$.|c,`g$S#ar Y1H"&Gq.cLp =ޠ kJZ՚DeP@X3X C=@2'?GOAŁ3. cf+8.$;:S"%1]D<A$"Y I:p5D $E<&lA܈Ӝĺ2@q+ȞH 2OEZ" yIbAXpIlb18P+(#Ƶ`+bTR+P$B1"oV="Â\J׺ڵAt MR|`y! *,I0! kA4Q8#HM$hm$CFȈuJQ Bc{J::t{;ŠWrkִ[gix@Y .}@W&HUc(A FY:D`#Ž DR!&/ ǐ⹾Z>nutdQhp J|vf\ ?Ҏ4jQOyUEI5 IHHa a{4[I(nt\_|%_Wj?Y?}~@ C3wgeqAq@AP/@3 R"Q`7gr0..R?TB1'\>`E7EhA%& ` <`dEGXP$? N=E؅V@ M>PY00  WV  ICJ J 0 xX @ f!W P1W N= hxw` f #  m` 7"P ( s &P uǰ ` 7[ (P _7 gƐZQ Vp( 7lk(#pp`nP Hl `[` 1@vdEmpBц}b@P1a y2 b@ p`0 !`p(I 0pHp9|0)U0.017є Y9 0+87Aq)P@YXq@ttB)3uB5əٙO䙡)Ii yӦٚ)I9piɛ雿 )Iiljɩɜ )Ii׉٩ɝ )Ii牞驞ɞ )Iiɟi D L y֟  P ; b?`=?c<0Ayi>,pH}U S]6 alq0lc3I:r66e('sVt"P(P\Z:gvz#PkJ6Gg7)N'cpqt3J7 tTtcWvN U <pW4n՛"&17%0%T [ lQ|31[~~bL1>N)@1ƹwaGݓT7P 8t:wj*}*~q281#O @(e8Zt:6p*##%nnjY*VS9u#bZ"X7[n`jЩ\)!٫9pQqJ @FDE. `Mv uQF/;PG BLQ HyبKQI.qQq 0n^z"pEYmq$}R9Ո8Vz'1{z'% ^0auI"N +YK{= +x(Ln 8(zEq'kg(@aMb7XnDF 4a{DQx^ҫ~+HA, 0ۗ3{}q +xѱ{1P)?U{,`~+V-VI}lt-@)Oua*гڲ[76D~h𣸰eG 4OPV`Ż` ȵ@[< HU` { Ɛ!6y'ehG%@7Bj5I2l@HS M{l1{#4C&SA:SR&rzT6UKV$ZK&#:2%BT`9\AMN\ J9Pqt{a`>C-B-Z כ- o֬o,ZApt^s!Ox(8CC])9` BS1 `h`Mb~Fb̼o2;p ,@ %%bYo9 mj5g0J@%^%}&4p//z0a1/2 ~ 0!@UT=АuSfXHdA;ͭT^'8sM3kUEnh5UF^fSV~ viMclxn! n e$JP"pii٘ J6'!~U +{>($`E B6$X&Ikl6J3#4y76~QdvWq}#HcBJ S?: ,T Lq>Oq,ە@Q@Ka},t^^ _!a5(a)o&a0c^/47-Pr$k(&Tn*;Q0P45/(qMW~a p1 m8uao nI d\vԈ]we Qw1f~jGn~Xq C oLfK 5^ m8tK8 "n0A KJ!Z9|C9AP o/9im%##od&E7Ϊؗ;K[[c (2'c<]sP?c)"Ń  D s6C^< @ 73 1Xq3b_9円,P,fb(!bE Z"SЏ?vDתK bX%J4;WU*b M!*8EyMt01[![ṗ"EŠH TD txTR; UCK<(OI.Lih8kvbxeוKC)8M|(7.Z q :FDن!I0Bq`qȀ hq qq(qqq@21B.PB Ad#l9&pCdF  <9&ZCc&BFB +J2N'6FI h\kf#4⡁QFI$&!C eMCE b t@jBia2&Әة":b)t4Viőz6sY!<Ț諰&+4i/JR`(f틡_h+s(ڶjȰ9l-hwt`|E!X5تځL &xB@An#6 YtQ/@!@<2kh ]`Qfh]4HbYC5XA'60--9dHD1E$!QTL\1$!!fms*q¡J ho`#RoFppFR/'3n,f \i8<Hh6=vnB5R@y647J=I$MؠZbh10ɡjmg( {b0GUbHeXDVZ!MAVYX4h0 8X XxG#Z ÂsƁl!k,  xt58@R,8`Nn|Q`(X83WCx>`AX,(0xBCXe ]\!DL$8EYģ N좉2@ )Ӗw%)kH@EZk!m 0̭" R q1c@ 5JlHP!m4qS-'Qhsi~9Xo~p".@dsK8 jk6$516‹i,U]߹*:Ɛ3 @#E Xpdх5d:S_G 6eP&ḿma:xh56&ǒ($Mɐ,}J[fK$Ek;(lI[pwH"8Y:(AG@]lcC$3KJo-ty)Ep?r]@4k ~+U[^4b9B "C;EDxr| !}l 5 dV,c[(!unj" C1c-84!걾C\ '}]S A-P-1L7Di7 ye_KiK,2$8o ֢6@0Mb-&!RXqHAo ZLhp-CHI3@yCO*DM'蔆( '/(4@^h?D0t(81oh ¨ x2i y;R~hy1B@؇t@)Pt(m›flJ;y(<@C)3Y0 1St#WETdEPEUQ˄9,Q<<?8 !%"5#E$U%e&u'()*+,-./01%253E4U5e6u789:;<=>?@A%B5CEDUEeFuGHIJKLMNOPQ%R5SETUUPIV=(IaA){=8LwXxw@Jǣy(b BjMH BtBh2atvDPԠr VK= sي `e= =@ D'<fDx W8tȨ@œz{D͛fy~EE X(5dH4 r݊ѭ 4C`܆iAV5B}Dp;n3FF`^%krcm >\݊z33t麐j"Ft 9C(@nA qe)`J0t8g`DNSnE(dv˼msnsf)C &Jq81HnӶU jiNF`O>0 =F Fz`(iycɎZFu gtC`tu9 yxk05^FC^v euuf) Y7y~nJ u2a>qa.bb6h y+f1㺠o4Y(smti+K&[srxDډHbAnBqvy2hA03 #CtX tFfyc&b#K=OD8Ќ!+ B0D$sl̾!bS4f:8ڨxhgQ~_ 2dlh JftɗBц<- mqoƌz(KNY>X~ uU}a7#=fqD(ƀC8n8OVt0K_L^tJh^?x? $6a@n< mEptqV/[_(x3݇I?q8el Z#v<@v,UF߃x?' @m V= z-Giqrѥ1y/Ehfsxz9F;Yt{Su^؃@e-pU|fŃg fVxL7)LLF1e6{l~ubc1rcWmq%V_b c2)dyojg×msx(r7c]vto8CH9ZCxw6 C DP'9 LP!z;}<{ w cA"M2m"dB0'O!}%_-0CjŽ) "B @g=P"|5.LtB-t(NR̬)2;RX'4c;1lBBFi j2!⡻?#P}2M4 Qg.ф5:gQF9a =^E'8yQy¼s_ᾏd)S1${_EONp;Br6BUB"%?=UOx %;,B@F5BpPP:0Q BbБOBSZxtBǎyV%DAF{RMi! aq?8 S!=Xr` @b)%B~PAA"̥k 0'MK !}mɞq1]dK&]f, K1 rzLh! B$]9% JEUu3V:#<a7I(*fnQ\-!d] 24B҈CR:{L,{x[./&ETQ"x@kkircNGIi4 ^F/wfvAi%FxVe8`TOA (>F#T B^{&B|,QÒ:qgV]8`BUbN фkXtFد< VgB~d;603xzL[["4!ruV>g*w6B ˹tН;EoB,2&6͕Kvd$J |DfHK0о9/Z} (e''(4r+%XT^rȮo[7>J:R-SNî%$ `({J(-OAD!D>buJ₌D;}1RΡԘՕAJ:#|ރĬ73CB)%2zEfkh’,`9OzjR#UCDyI Ob-T+fbDhD P ZL1;93}#4&5nyMBհ-%P@*)+E3EEJm&OJ!R%2vDhi/LH"$>I/!j ԯ$R_F5F #rvLgԣF?8zbbD͇"@q1pofLfxNDh vfOЉ>覍Q3j_A0 .@9xCj 5p+ě1dEl,cxfR%rPMY2E=e2NF|QrYuS  'Tkf=q7(#Bi(Rh*jyn!LQ\L"iMpLa'Qtd&2W$hgL)!H/ȁ hi)BV@,di* !KzEΧ/H^H6E#8! >1Bbm>wГ3E(ӖTRL W]CyPaAKG_^O^moTvm4 6 P0'W q=ćJCQ4T߇ ؘ&eouw KS*J?.ϰB퍂)1#@AIS3-nA*/`dAT| bKO7NJ# uӭz;BFɽ9,ךMV$ue^(yɕ$?OV?5`WınvXSZt w\QmN>;B w(Eͱ@ A Aa `a, i iXZue,Ÿ*tCL8!B  -H dBB`k[j`ꁪ` BTv$ VGɂ|HF 0`B|aߥ! `X`aiMB` EN ޅiab& @2I~b^vzPj,BLl_^k)MN>hW>C :XcJdRfeZebffjfrfgzgfhhfiifjjfkkfllfmmfnnfoogp pgqq"gr*r2k"@'^^f Bt*R$ a `"tgjhx6gzz'Lyf dRΗ=ul%C U{h (ppyBOF Jz} @&"hz&\&  T4LkQ(@~rh2!%;4 8Hr9 ; @g L;L)A*9Vv;H;Yj(IHy Nk2)  ;pio8"J;"H Bjr*fh EbuLS,!d'=xეp btH $ =Lx@B,cAPlGŝ"`Hɒ\0I2 HgG`EIBauj빊姪Qi/9O_rG@ƴǰg>@BNDG jD)PTDf@h/-X=DbRQPA`űZQ``| tdH}}xZEB@PAmЖ䧶YG]ޅ!(|BeF=0BgoHAYF2![ XLF_HUAt !TFXIxc7qbkH| `=%*2k}ja$F>jET]]:T^G J̀EtEl QFd#- mRq쩐GErx1L'}S7C4nZrǧ;Cz/u8+-@|tD_ Da %D֎X 0_N@ .ĝ!Jܦ>x֤%LyKwo@ NX*p WPE:k#zn6NCE<`N힣qfM_*0I$ p#EI/w9,*28bPQ'wM񎸯N]J lg8@?lم9F_eF H앉 ^BQ,|@j ;@k$jD}2sLQ!A.r>DDNUl,3].<= ^YM8Dt!(BkB kQ=`p%1X8cPx:{ӆ;R탔V>uP7g d %hQ:B B-k@-xH`dD Ž% BXS uf <<{\a<2F MDC}Sst 6; ৄ4kMt^0A>k_h9GȱI'?w,B@>cl\WI$AwЄxc޲IڲNjȺ?Neq:Ai@ Ͷj{%ĺ*+gAH4^ ; d;! ;\O{{eG^DqG=`XA ǖ^NMapFC8| >|ƿ&ElK@C$D-@2b38٠w(> D;GuE,{ ZNRL( <̈vDqC{'*D/1 L_$<D9pkH![)D$ǯ\ċeFd@QEa S ̣ #ta*  x$9c,`6!@4;]PB@"h>L'_ E$DXuix,|4/IPjhJ=rt@ " h !`&B ά @q@A0 &T0B< KXoF)LAB' W0? 'K'Ob @K'?R‰Ӝ??8{Q)FU^@@~`Px* a3a_&Txi8Ua -Hcbcӂ ` SgzM(QAC.g<4:}W?vgsP4>l]㢄CϥzX`z ի,/,& \v_Hɥw.!ykI)RD D!+A /L I(z֫na' 0@NL((g +raI{??d(%|,I\N?xKlB2H.1j*īl?@?yB}Q: J;]jD1Jt PTŧsR,2ع A JoNQo <ϖPT"iH.BѢ#$Z&!29HHd BNBT]T*`|ȟ ҉:CN`CR[@AE նNKƄ8Tȶ.H< 6lhPRuG/$XVpj#Y$j|'C( Q?Ĥ; @ȟ>Զ4].JfS$BFpVPFRd J J SMH: V"S2zcZҴB=ӄ\7BvOqpg'*VS@P&\jdAXBBA-t "t}wdjU *эI#.R9_هb+!~>"7,Q擅 f"y~԰=-t BS`ӎ>V]q=2~Cݬ'*P8Ç; '7xBDn8E2r4ZP$" 'є´PѨ=#h*VP>jIM\UL)L "FyUΕ hIBRTakiRjkX&SǷP{PUB|u ipTf0UA^7Ə(G3vKSjFhR?(?tH$1l_شqSuGj2*E=4z@?k&+h tcxȸ0"Ģ#aKS/e.$,jW1yTu^;ٕsᷘ@8hZ'&F 6U4󁁃 g@]Y"ѥ%YN~]íDL:?>":햡cB%/\#[MVH2Ok;F8[!Wd ].;(WJ3PyۓhƋIѪ֜u'@_;8DQa3>$ i+pTG83|iouW{Q738zjsh͎c<`f,\SHO,Jޒ4r&.-I cW5UIU P,8^00$4,:04"%!"B(}l "^N!̧FBqA.p%zB)n0.*BX!f!emD60JDlu4p| xlp:Ōl"^c:a/f2RzR'NimXPpXo*> 䙦&,Bpbz-ڦ: "APb/;6Mpk嚬钂滠%MIn.N[B2g(PD)}VߎfPEDp&†B NKc|P4B"A4e^L-**4#!GGLNJLj(0":K0G20b(sWN{PXp`n#OhIC 0OetCʣR ObG¦V}@_gd$n.(鴅FL6M&dWA=n"'J ?-vJhM AjA/&ǏN&$&eG2 (rؐ$0( 'KsdKTNP#eHhAz/!pb MA-rX "s *?M\]V$:ŏV5MB ,lcF;X*.| !50a,37r\OBbA"vT-ew0yQ>Jb:d@ƶ G7$M!be6ӡDc l#B0RN7)|'/\H~D@̡>+Q$I4:"Zd.v2E> qr!E)n (MΒB xK (R@!GY'r#74G8|}+l~0z6GV(!*Vg8$ O|R\Fd|3*fl~fBP> C8/ô>f0/ AYTKSgb(3\4cRB\1NqB8@.4CR25^)ញ"ށRKl!n "Ρ(malpsƳ:AQT%aEDC=/jL-#mCr$fT e?A2:߾q6" ڪ&ڱ!D@LLxŠ9!47$"GYcj(ZDi(Qs IR*>!BU <6_'*<Sc:TVH%Tc+cȪL:!/!NjBoXjj"*tCv"DvT6j]F#*jD4b,&H!lFM 6k.!QE!$BOU".V@dbZhȈ :.tE`vt:W]P7vftE70 \uO"btKCU!)0fsm($ u,h8׳djWw3|'8s*d@xc=z!/u@s&f{7yO7 {4` we1淵j}7~ $R#_2$FmXd 1u+9=A8ExI/&bUA g@xmq8uxy}8x8x8x8x8xɸ8xٸ8x鸎8xj8y 8)Ӑy%y)-][5y9-=yIM9%UyYX\9eyi9q9uyQ]y99%Yٔ{뒹yɚyYh9yXi9%\XنA+9y:z :z!:%z)-1:5z9=A:EzIMQ:UzY]a:ezimq:uzy}:z:z:z:z:zɺ:8lzlo®u7x[~*dJ `yvu}c&d«@Hl"7+WC%Ѯ"a5* wcl+l$+$X5Kz`Ƴ[ͷ[ {崴YD4HE`?Ty*G%ԏ@Cd",MgI ".@7 Bn^J^=h0;ށMBŅTRjR%2Cκn)C ]]D1#ECFC;^ܿxݏv•"Ci '`(|8M+@ֆ]Pyƶ!9SxkFB>E&~6b`@Gc&hCdKJ~! ,A4e>%ʣurpa|mMԏLhGy$wpPR*"54#|SG  8co/Ğ?hU@r_nQù߉%^Ne>+Ls}fO!s4jAGAvvmN ^SL3ӗCH!S]9 IRw"2VYR @h(L WHMARAJ= )p@ ҷlq! 9Ńꂹ$ ,>C o(L.Hl Be Y-u Y^G'1Be%hćzM!@ nb=uqW"~8Nr<h42|)>6<-;Ȣ-򕰌, lKa0\.6@vw }.6"@ \NIهiZI`LTh.)hŽzoD7Gtd!6cSM?.U( 6ypSL=>~eJz $SI:ЂPcCUJY:P [ ; )# |/CL,M5-_\CͧT:0ZFb?d@׾ezTY>a/99<d70;P3ϾcHVUVh} Tf`jgK6I~Pw!;0+(ڗ#$xG YV PWB֣Mv[<.wKMz|Kͯ~LN;疂C6PA=lصGJqDjPN|: sq/38O'LXkM TD/)(\=xѴVGIF. lL*Dz<Ե@ x @㚬`%ǔHA˔L:˳L uq2=˜FW80?C?阮:;aY(}>(}r}A<oKt\8=ڡ=$;TBCx=rC1()Lq R8lxj8IBw,OBr1Z J#:us`\z\r=h;V Yy\Y}ciۢ 3JwV$_q.~9(gG5`8pJ 0'&;./ Gop9Bz$q&{1A'ǣ2D#TfAr5\cUD)ѷxBE(7A.w/{q(E IEx%axw~u~%~)qh+8#*jrEw|iV>AtT,,q))5vM5 ؁nr!5*Xra.HXP !Ww~"~zt$%qhQ8\dO5D;X[(D${U#i09t6鐊! xJ 7pqkP*}(P{<zdWMl6hX=_tWBQSBXa"Z#~td!~8<$q/'Q!BfȄ 3m8]8W](؇ȇoD/saU(qtrqr!A(5d’e=8abvSx-R]mr641jC0A(ZI+0"PT IoD.@(#ijQ|j*P+$*023P0d)363"gGC\#f&"s%{ <9c&+p@BD!2PXR+r{̷+bՐWb|bm%]gByBcCǁA5{RIW6oiXE$1^|i~y<,AIwCs4vYW*\E(1@8I"eERuX8DAeYAU$I)Yȹii0R0F,H YL*p/j3 R`3 h,Fx@HJ$kIYb`{P!2鐥)J(3op %$~IayX:m2H_/j{48ZG$:Zzک:Zzڪ:Zz:a0 j: $ @\vzȚ`EкO$  P A%>j A` 7<Z7p >@ $W SJ = KnPr@sPnww`n zq{sE2uP[@lP(Pk P l0w {^>Moz 0@ 8@;PK @p8KJvK @?0 K;J{QV`ల 'p(00|+г"lзs 1+$n0@ ;2+PȀ:+q# p[<@ @ @ `>@ AB ĐZx@;IFKd۴a@p K r WK88@ ZB& j;R[Gr $pQ xs[7! [r и˷9{[!kYql0)q{[@  kBۺ58! p L+˛!% P?p?l &0 zf[۫S I@\SOp)qN=ЬYS.@QN$r p ␷akq ,l  (nP$pu!k(۹tKu{x"y|Y |<lʮ|'s\ɖL[rTO p)l<G{  R\ XX @b,Y_ 0LP  \b -f{8|$Bqƻ K %A^=!ܽP΀0 aPXc ӊla _ A Ġ N =p 6*bT8B' ~~ O[ N~)aFҲB ` ԛ/]!O 1 j{ok$Q! U=Ի@ BIxAFEu!! q K)fǝͷ!0z03 r.[p`tQ"wm1P!M-1l%n|~5p/ }qK{ % p:\O*/ wA> p~`h-^%> -M _Pt   VMo Kk npAHB`Q U ! &d)Q&6A H Cdi׮M=Fڵ`] ^yǮYup畍v+&biRvMiTTCP+BnB'.qpSXn W nA& [iC+7!`6qiri[mo,A l0ٸFܱӊv'p\cfg>Vݺu[2 %(}*h#ى% ,L`XR}axqq @4(a p !f$ )g68D,F"` Id&@?&8Vh[)'B01(B&҅hX|ؖ^pR M3Y (@bPɌœ R /+.u)p&IZXQŠb,`+BD_>F8 9*.!@8opͫ&kG繌0L8Vm+kP C l EWIʅ , '79P-^,Ŀ!, {Iщ%$HԖftkrm5c0lLdA$Aݧ7Q h!}F5OK|S2 pC p7Q T?$0<9`R? \- L D8&#|`X8#§I#SB(B)B**B-B.B/B0 C1C2,C3C?C@ DADB,DCERx8yJs0Bq8HxPDCCyIɛɍPLxʄ*J8ʤ\rhʧ,?JʰBfd(x/JB/~ !DHsh`̃LdE8JJlI!\|;LCdGyJ!ăAyMLڔwpyJ8 Fv0CO Ow7|,ΥI\N8GNvMeԃ댷z`M$jOxOvlKh(|8 P==@zP<H/}B tN"-ҧXd" `dN Fy8NF`JL7D4r ؍pPb)݇M5M  ubecﱁx\uѥT=HR\a N(?@x'a<~KQEuXR`qp4\cE#}{HF8bk@!Q>nj.kV8YB0C8=HqPZ=`lklۡmmmnn.n>nNn^nnn~nnnnnnnnnoHl8sC8o0~ofDc7ܿ p3R D-hX 6X85(Dc؃_?0;0KSHX )X ؗO8"N 1K`eq! %F-4l м&)׆l0P{3$ق)b@ϠjɆ+:K;]*-wKoSBC˾<  %eQn2ڰ 0OpQK'l ;[Sr& $+J%Ӏ&r%q+R:;Bp 36jOl? {= n?=o_p)bg&`#9 X :()Rz#s8Q8RX0MhPM *S;:(S-x{+op+0J n0LJ P15(eH;%/jx4= ;@d D0cՒx;R͊d\c|o+G4ѱ~78o-d@cgh( &\"Jh H#KhBG,0^؀11`^b (X^x1f /gP`1zXPLG1l(ƙE*Wl#D)ba!s%!0ʘ]l\&)(Qi+Ch{g1.N0@ЃnK n.W JdG ঋAgA2K<.q\bGDyѐ8'(L8(Wla3`3(ds(c1L!TAv]PZl2yHvAZ`A݁ (8ޠ`$F{ö85-iЎl! B11^dFk  Tܲ5OFzAJ%߮%')$0| `ƃ @DAieA0 HR/cXA/μYРbˢD 1o=FrAu>F ^l`R Ҿ2)]s߼=M%GPb=N'6 n EΙ Ӹ3A`K_jZ16Q>v?IJ{(P"!$A$0J 0PQe>3$bgW!yh71bhi#i- X+6ǠF.j0"TǮBXD_ڃJXq`+Y25X^t!%kԃFW0Hq;- \$ )E@Xֶ.r! 0 p@o಑(&p ϸAɸ6N¸ E:fl8~<8ā (PI}r'nqŵ i`SF)E4,`}h4TndE RXbikVBdX:1+af@9}W2LL# "H!D!|>^eAp>̀Gɟ*Q"%c@亜pėD](L_$Ig fE@$ .Z\-m^@q,/,QLxn-&dȟBoHI.Gw1=@(\P)D|{ŗ>r<'@#Q#KGtΆ<޴2{GBB&FjJGID|ԇF>VGX.f -i1hX1]D0MrITLAϘdA I3 TeApBb#2 a`Е?t ʤ@ E<h| UK&@#0?xZ\@ tiAeZK!ؐCViA@=m=ťC Kë\*bAfNEj^ >BAP_$KښQc%tZ˜@%~Ĩ t.L|~T(|ׁ]"0|-:F-&@h΂&Ԗp-'(ETwDt,blB,L,*#B)h7E1e7Ad $Al%C1`Alyxe2T(jQXƮ2eþE ͰdCR2HӰ Ɂ7dDlOj@%`%Xb.,'@TBbS&A0 3 H0`aA00ÚNBH)+F CڲC@Cښ "xNWpAB:K))0;B#ԡZC3@@@d4B'B/4C7C?4DGDO4EWE_4FgFo4GwG4HH4II4JJ4KK4LǴL4M״M4NN4OO4PP5QQ5R'R/5S7S?5TGTO5UWU_5V{4W_#ԃ dX5Y5QPʟY[5\+t FĀ@^UE쬐\\u P\O6eWe'2 J2#5˗Į8 [Àh[E#>J^6m׶m߶JQHA o߅?5$ >(pO3Q<] ;(^EC^6xx]CmAAA>$Ƭh/7*_jR$]QßxTӃ?l6`hav5}A JA7 4K?58P ]9xqojZ *h%z8ǴÉ븊AE Cyuo%_Ď8gV CA+xz׷GJ]]pea万9DE]{'@ea8 e8){|۹?:3J!B:V|"C 8WyD`C#F׺:76|UAh{ApP8!-Ww{Ī%GOA쁴  w8_AT L^ P;׻;绾;;<<'/<7?)J0# {:o4ݥ#&B%$@$ $TH\J #HP@Q "e) $xeʂWvMQծ/iִi8qfӹE: DN}jYF\]ZӍNqC86WJmZUq`Ok- n^[Ѓ 6|qbH1p%RQ !JxC@ɆI(yrA\R#AX2)n݊re,WVi֬M J@~ 1gt> WLUHΨ l*(uu,ƲyV)jmq ᆛcN0d jj IF) bB0o?_p٠'qc|`cE}d|&(4 eRƎ (,z6~$Q6䆂pOH ~$P,L<L4ƃ^e0ff#1zgz腘Gq,^6`SÙH2o Z\u1.2B!E5$ b1ŒJ2͠>R֢H2Mv;]p)(ooeYb sw9*]v" ʀ^]%*v]iVZ!"[8ę8) F5Z 5tPeqFp e&1d^ MHkÁy7.F;rmA/'d2ɯo6n҆03K\`,e#RD^Kh#Q>dXF[_mڀDf:\ϝ UGwT_LwCsgW sg #-`z >S @]zz= Xn<1cm8J`ׄ(H,[D6tE,%v%5x;j?h] @w``rA?X`~@m5La{INDedf gj|"Y8@ j1ze%GZ8ɤF Dc,N J|p%YVDeY+DYdd+Y@Tc@NDPcnuC2A P % Eb)* @xs )`SC2g @9""<RIυa0aX+,0w3Txf4WMk^ UjQ< &(X!]*Is fWm݆[5,pSg]0E5(wT *C3d';hY%dȈ$a.#I1xDavbEN6wY.QGEjt(%fW޹Sj3A>kΔdEV`ΐM0$4H)m'd;;]2|ɦw&M SY ]/]/-ط-6Qlcp.`pK0tb@2: BaLL*IW-*@TI+* >"S0D'17A[Iư8x >NHVG l5Tb-7&!-:@'Rl E [T19&08l'+<W|y(^Ԏ ] P>s:]Uڋuس2n{n+]vENs }ClHtn!(wgu څ~;xA̋]w-]"%|zlLHaVe&NPY Y7< )yIbvnEE l )G;fT+X˱K> $~Be1+On~4Cv)j7+ęfotx :xn bt P.цj@aN?0%Ҏ .[NX˜0͐k# gJv n0ՖZb zX" vj 8taN`Ể@l =k`FF ndB`cjj)hC"rbHjOsD'Qbk()2DҰ H&|bԢ c#n0Vа.&'Z/\  \iv,b %tQ!t` یszpK1n#~ IL {"1 eZPMnkUBT! / e&z O|PEt f.".ρ@ `br^xM  B,pA6ʭEHJaD ` )J ꈉ'&`"z"fAN` j*(nHFǾH$6@|BjR'6q.%eBc 4"~6 "6͖+L0Dorp LG 6 pwA 6`p08` zq4MxUљ)ssn!"1ˏ ,/_p7IlE\^KL2$;u b\.\.\. . .fi . .SH "DESCRIPTION" \fBgit secret add\fR \- tells \fBgit secret\fR which files hold secrets\. . .P Adds filepath(s) into \fB\.gitsecret/paths/mapping\.cfg\fR\. (It is not recommended to alter \fB\.gitsecret/paths/mapping\.cfg\fR manually\.) . .P As 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\. . .P The \fBadd\fR action will fail unless there are already users in \fBgit\-secret\fR\'s keyring\. . .P (See git\-secret(7) \fIhttps://git\-secret\.io/git\-secret\fR for information about renaming the \.gitsecret folder using the SECRETS_DIR environment variable\. . .SH "OPTIONS" . .nf \-v \- verbose, shows extra information\. \-i \- does nothing, adding paths to \.gitignore is now the default behavior\. \-h \- shows this help\. . .fi . .SH "MANUAL" Run \fBman git\-secret\-add\fR to see this document\. . .SH "SEE ALSO" git\-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 git-secret-0.5.0/man/man1/git-secret-add.1.md000066400000000000000000000023541424706700600204600ustar00rootroot00000000000000git-secret-add - starts to track added files. ============================================= ## SYNOPSIS git secret add [-v] [-i] ... ## DESCRIPTION `git secret add` - tells `git secret` which files hold secrets. Adds filepath(s) into `.gitsecret/paths/mapping.cfg`. (It is not recommended to alter `.gitsecret/paths/mapping.cfg` manually.) As of 0.2.6, this command also ensures the filepath is in `.gitignore` as the contents are now considered secret and should not be committed into the repository unencrypted. The `add` action will fail unless there are already users in `git-secret`'s keyring. (See [git-secret(7)](https://git-secret.io/git-secret) for information about renaming the .gitsecret folder using the SECRETS_DIR environment variable. ## OPTIONS -v - verbose, shows extra information. -i - does nothing, adding paths to .gitignore is now the default behavior. -h - shows this help. ## MANUAL Run `man git-secret-add` to see this document. ## SEE ALSO [git-secret-init(1)](https://git-secret.io/git-secret-init), [git-secret-tell(1)](https://git-secret.io/git-secret-tell), [git-secret-hide(1)](https://git-secret.io/git-secret-hide), [git-secret-reveal(1)](https://git-secret.io/git-secret-reveal) git-secret-0.5.0/man/man1/git-secret-cat.1000066400000000000000000000027111424706700600200750ustar00rootroot00000000000000.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "GIT\-SECRET\-CAT" "1" "April 2022" "sobolevn" "git-secret 0.5.0-alpha2" . .SH "NAME" \fBgit\-secret\-cat\fR \- decrypts files passed on command line to stdout\. . .SH "SYNOPSIS" . .nf git secret cat [\-d dir] [\-p password] filename [filenames] . .fi . .SH "DESCRIPTION" \fBgit\-secret\-cat\fR \- prints the decrypted contents of the passed files\. . .P As 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\. . .P Note 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\. . .SH "OPTIONS" . .nf \-d \- specifies `\-\-homedir` option for the `gpg`, use this option if you store your keys in a custom location\. \-p \- specifies password for noinput mode, adds `\-\-passphrase` option for `gpg`\. \-h \- shows help\. . .fi . .SH "MANUAL" Run \fBman git\-secret\-cat\fR to see this document\. . .SH "SEE ALSO" git\-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 git-secret-0.5.0/man/man1/git-secret-cat.1.md000066400000000000000000000023011424706700600204670ustar00rootroot00000000000000git-secret-cat - decrypts files passed on command line to stdout. ============================================= ## SYNOPSIS git secret cat [-d dir] [-p password] filename [filenames] ## DESCRIPTION `git-secret-cat` - prints the decrypted contents of the passed files. As with `git-secret-reveal`, you'll need to have the private key for one of the emails allowed to decrypt this repo in your personal keyring. Note this command can be affected by the `SECRETS_PINENTRY` environment variable. See (See [git-secret(7)](https://git-secret.io/git-secret) for information using `SECRETS_PINENTRY`. ## OPTIONS -d - specifies `--homedir` option for the `gpg`, use this option if you store your keys in a custom location. -p - specifies password for noinput mode, adds `--passphrase` option for `gpg`. -h - shows help. ## MANUAL Run `man git-secret-cat` to see this document. ## SEE ALSO [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) git-secret-0.5.0/man/man1/git-secret-changes.1000066400000000000000000000033241424706700600207370ustar00rootroot00000000000000.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "GIT\-SECRET\-CHANGES" "1" "April 2022" "sobolevn" "git-secret 0.5.0-alpha2" . .SH "NAME" \fBgit\-secret\-changes\fR \- view diff of the hidden files\. . .SH "SYNOPSIS" . .nf git secret changes [\-h] [\-d dir] [\-p password] [pathspec]\.\.\. . .fi . .SH "DESCRIPTION" \fBgit\-secret\-changes\fR \- shows changes between the current versions of secret files and encrypted versions\. . .P If 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\. . .P Note 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)\. . .P Note 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\. . .SH "OPTIONS" . .nf \-d \- specifies `\-\-homedir` option for the `gpg`\. Use this option if your store your keys in a custom location\. \-p \- specifies password for noinput mode, adds `\-\-passphrase` option for `gpg`\. \-h \- shows help\. . .fi . .SH "MANUAL" Run \fBman git\-secret\-changes\fR to see this document\. . .SH "SEE ALSO" git\-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 git-secret-0.5.0/man/man1/git-secret-changes.1.md000066400000000000000000000027011424706700600213340ustar00rootroot00000000000000git-secret-changes - view diff of the hidden files. =================================================== ## SYNOPSIS git secret changes [-h] [-d dir] [-p password] [pathspec]... ## DESCRIPTION `git-secret-changes` - shows changes between the current versions of secret files and encrypted versions. If 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. Note files must be specified by their unencrypted names, without the `.secret` suffix, (or whatever is specified by the `SECRETS_EXTENSION` environment variable). Note also this command can be affected by the `SECRETS_PINENTRY` environment variable. See (See [git-secret(7)](https://git-secret.io/git-secret) for information using `SECRETS_PINENTRY`. ## OPTIONS -d - specifies `--homedir` option for the `gpg`. Use this option if your store your keys in a custom location. -p - specifies password for noinput mode, adds `--passphrase` option for `gpg`. -h - shows help. ## MANUAL Run `man git-secret-changes` to see this document. ## SEE ALSO [git-secret-add(1)](https://git-secret.io/git-secret-add), [git-secret-tell(1)](https://git-secret.io/git-secret-tell), [git-secret-hide(1)](https://git-secret.io/git-secret-hide), [git-secret-reveal(1)](https://git-secret.io/git-secret-reveal), [git-secret-cat(1)](https://git-secret.io/git-secret-cat) git-secret-0.5.0/man/man1/git-secret-clean.1000066400000000000000000000027161424706700600204150ustar00rootroot00000000000000.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "GIT\-SECRET\-CLEAN" "1" "April 2022" "sobolevn" "git-secret 0.5.0-alpha2" . .SH "NAME" \fBgit\-secret\-clean\fR \- removes all the hidden files\. . .SH "SYNOPSIS" . .nf git secret clean [\-v] . .fi . .SH "DESCRIPTION" \fBgit\-secret\-clean\fR \- deletes all files in the current \fBgit\-secret\fR repo that end with \fB\.secret\fR\. . .P You can change the extension \fBgit\-secret\fR uses for encrypted files with the \fBSECRETS_EXTENSION\fR environment variable\. . .P Note that it will delete any files ending in \fB\.secret\fR, even if they are not tracked by \fBgit\-secret\fR\. . .P Also note that this command does not delete unencrypted versions of files\. . .P Verbose mode, enabled with the \fB\-v\fR option, displays the filenames deleted\. . .SH "OPTIONS" . .nf \-v \- verbose mode, shows which files are deleted\. \-h \- shows this help\. . .fi . .P You can also enable verbosity using the SECRETS_VERBOSE environment variable, as documented at git\-secret(7) \fIhttps://git\-secret\.io/\fR . .SH "MANUAL" Run \fBman git\-secret\-clean\fR to see this document\. . .SH "SEE ALSO" git\-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 git-secret-0.5.0/man/man1/git-secret-clean.1.md000066400000000000000000000022651424706700600210130ustar00rootroot00000000000000git-secret-clean - removes all the hidden files. ================================================ ## SYNOPSIS git secret clean [-v] ## DESCRIPTION `git-secret-clean` - deletes all files in the current `git-secret` repo that end with `.secret`. You can change the extension `git-secret` uses for encrypted files with the `SECRETS_EXTENSION` environment variable. Note that it will delete any files ending in `.secret`, even if they are not tracked by `git-secret`. Also note that this command does not delete unencrypted versions of files. Verbose mode, enabled with the `-v` option, displays the filenames deleted. ## OPTIONS -v - verbose mode, shows which files are deleted. -h - shows this help. You can also enable verbosity using the SECRETS_VERBOSE environment variable, as documented at [git-secret(7)](https://git-secret.io/) ## MANUAL Run `man git-secret-clean` to see this document. ## SEE ALSO [git-secret-whoknows(1)](https://git-secret.io/git-secret-whoknows), [git-secret-add(1)](https://git-secret.io/git-secret-add), [git-secret-remove(1)](https://git-secret.io/git-secret-remove), [git-secret-removeperson(1)](https://git-secret.io/git-secret-removeperson) git-secret-0.5.0/man/man1/git-secret-hide.1000066400000000000000000000071571424706700600202500ustar00rootroot00000000000000.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "GIT\-SECRET\-HIDE" "1" "April 2022" "sobolevn" "git-secret 0.5.0-alpha2" . .SH "NAME" \fBgit\-secret\-hide\fR \- encrypts all added files with repo keyring\. . .SH "SYNOPSIS" . .nf git secret hide [\-c] [\-F] [\-P] [\-v] [\-d] [\-m] . .fi . .SH "DESCRIPTION" \fBgit\-secret\-hide\fR \- writes an encrypted version of each file added by \fBgit\-secret\-add\fR command\. . .P Then anyone enabled via \fBgit secret tell\fR can decrypt these files\. . .P Under 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\. . .P Later permitted users can use their secret key (typically from their home directory) to \fIdecrypt\fR files\. . .P It is recommended to encrypt (or re\-encrypt) all the files in a \fBgit\-secret\fR repo each time \fBgit secret hide\fR is run\. . .br Otherwise 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\. . .P In 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\. . .P If 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\. . .SH "OPTIONS" . .nf \-v \- verbose, shows extra information\. \-c \- deletes encrypted files before creating new ones\. \-F \- forces hide to continue if a file to encrypt is missing\. \-P \- preserve permissions of unencrypted file in encrypted file\. \-d \- deletes unencrypted files after encryption\. \-m \- encrypt files only when modified\. \-h \- shows help\. . .fi . .SH "ENV VARIABLES" . .IP "\(bu" 4 \fBSECRETS_GPG_COMMAND\fR changes the default \fBgpg\fR command to anything else . .IP "\(bu" 4 \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 . .IP "\(bu" 4 \fBSECRETS_DIR\fR changes the default \fB\.gitsecret/\fR folder to another name as documented at git\-secret(7) \fIhttps://git\-secret\.io/\fR . .IP "\(bu" 4 \fBSECRETS_EXTENSION\fR changes the default \fB\.secret\fR file extension . .IP "\(bu" 4 \fBSECRETS_VERBOSE\fR changes the output verbosity as documented at git\-secret(7) \fIhttps://git\-secret\.io/\fR . .IP "\(bu" 4 \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 . .IP "" 0 . .SH "MANUAL" Run \fBman git\-secret\-hide\fR to see this document\. . .SH "SEE ALSO" git\-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 git-secret-0.5.0/man/man1/git-secret-hide.1.md000066400000000000000000000061731424706700600206440ustar00rootroot00000000000000git-secret-hide - encrypts all added files with repo keyring. ================================================================== ## SYNOPSIS git secret hide [-c] [-F] [-P] [-v] [-d] [-m] ## DESCRIPTION `git-secret-hide` - writes an encrypted version of each file added by `git-secret-add` command. Then anyone enabled via `git secret tell` can decrypt these files. Under the hood, `git-secret` uses the keyring of public keys in `.gitsecret/keys` to _encrypt_ files, encrypted versions are typically called `filename.txt.secret`. Later permitted users can use their secret key (typically from their home directory) to _decrypt_ files. It is recommended to encrypt (or re-encrypt) all the files in a `git-secret` repo each time `git secret hide` is run. Otherwise the keyring (the one stored in `.gitsecret/keys/*.gpg`), 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 `git secret whoknows` 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. In other words, unless you re-encrypt all the files in a repo each time you `hide` 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. If 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 `-F` or `-m` options. The `-F` option forces `git secret hide` to skip any hidden files where the unencrypted versions aren't present. The `-m` option skips any hidden files that have not be been modified since the last time they were encrypted. ## OPTIONS -v - verbose, shows extra information. -c - deletes encrypted files before creating new ones. -F - forces hide to continue if a file to encrypt is missing. -P - preserve permissions of unencrypted file in encrypted file. -d - deletes unencrypted files after encryption. -m - encrypt files only when modified. -h - shows help. ## ENV VARIABLES - `SECRETS_GPG_COMMAND` changes the default `gpg` command to anything else - `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 - `SECRETS_DIR` changes the default `.gitsecret/` folder to another name as documented at [git-secret(7)](https://git-secret.io/) - `SECRETS_EXTENSION` changes the default `.secret` file extension - `SECRETS_VERBOSE` changes the output verbosity as documented at [git-secret(7)](https://git-secret.io/) - `SECRETS_PINENTRY` changes the [`gpg --pinentry` mode](https://github.com/gpg/pinentry) as documented at [git-secret(7)](https://git-secret.io/) ## MANUAL Run `man git-secret-hide` to see this document. ## SEE ALSO [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-reveal(1)](https://git-secret.io/git-secret-reveal), [git-secret-cat(1)](https://git-secret.io/git-secret-cat) git-secret-0.5.0/man/man1/git-secret-init.1000066400000000000000000000032761424706700600203000ustar00rootroot00000000000000.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "GIT\-SECRET\-INIT" "1" "April 2022" "sobolevn" "git-secret 0.5.0-alpha2" . .SH "NAME" \fBgit\-secret\-init\fR \- initializes git\-secret repository\. . .SH "SYNOPSIS" . .nf git secret init . .fi . .SH "DESCRIPTION" \fBgit\-secret\-init\fR \- initializes a \fBgit\-secret\fR repo by setting up a \fB\.gitsecret\fR directory\. . .P \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\. . .P If a \fB\.gitsecret\fR directory already exists, \fBgit\-secret\-init\fR exits without making any changes\. Otherwise, . .IP "\(bu" 4 \fB\.gitignore\fR is modified to ignore \fBgit\-secret\fR\'s \fBrandom_seed_file\fR, and to not ignore \fB\.secret\fR files, . .IP "\(bu" 4 a \.gitsecret directory is created with the sub\-directories /keys and /paths, . .IP "\(bu" 4 The \fB\.gitsecret/keys\fR subdirectory permission is set to 700 to make gnupg happy\. . .IP "" 0 . .P See 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\. . .SH "OPTIONS" . .nf \-h \- shows this help\. . .fi . .SH "MANUAL" Run \fBman git\-secret\-init\fR to see this document\. . .SH "SEE ALSO" git\-secret\-usage(1) \fIhttps://git\-secret\.io/git\-secret\-usage\fR, git\-secret\-tell(1) \fIhttps://git\-secret\.io/git\-secret\-tell\fR git-secret-0.5.0/man/man1/git-secret-init.1.md000066400000000000000000000025371424706700600206760ustar00rootroot00000000000000git-secret-init - initializes git-secret repository. ==================================================== ## SYNOPSIS git secret init ## DESCRIPTION `git-secret-init` - initializes a `git-secret` repo by setting up a `.gitsecret` directory. `git-secret-init` should be run inside a `git` repo, to create the `.gitsecret` directory and initialize the repo for git-secret. Until a repository is initialized with `git secret init`, all other `git-secret` commands are unavailable. If a `.gitsecret` directory already exists, `git-secret-init` exits without making any changes. Otherwise, * `.gitignore` is modified to ignore `git-secret`'s `random_seed_file`, and to not ignore `.secret` files, * a .gitsecret directory is created with the sub-directories /keys and /paths, * The `.gitsecret/keys` subdirectory permission is set to 700 to make gnupg happy. See [git-secret(7)](https://git-secret.io/git-secret) for information about renaming the .gitsecret folder with the `SECRETS_DIR` environment variable, and changing the extension `git-secret` uses for secret files with the `SECRETS_EXTENSION` environment variable. ## OPTIONS -h - shows this help. ## MANUAL Run `man git-secret-init` to see this document. ## SEE ALSO [git-secret-usage(1)](https://git-secret.io/git-secret-usage), [git-secret-tell(1)](https://git-secret.io/git-secret-tell) git-secret-0.5.0/man/man1/git-secret-list.1000066400000000000000000000022511424706700600203000ustar00rootroot00000000000000.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "GIT\-SECRET\-LIST" "1" "April 2022" "sobolevn" "git-secret 0.5.0-alpha2" . .SH "NAME" \fBgit\-secret\-list\fR \- prints all the added files\. . .SH "SYNOPSIS" . .nf git secret list . .fi . .SH "DESCRIPTION" \fBgit\-secret\-list\fR \- print the files currently considered secret in this repo\. . .P Shows tracked files from \fB\.gitsecret/paths/mapping\.cfg\fR\. . .P (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\. . .SH "OPTIONS" . .nf \-h \- shows this help\. . .fi . .SH "MANUAL" Run \fBman git\-secret\-list\fR to see this document\. . .SH "SEE ALSO" git\-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 git-secret-0.5.0/man/man1/git-secret-list.1.md000066400000000000000000000016401424706700600207000ustar00rootroot00000000000000git-secret-list - prints all the added files. ============================================= ## SYNOPSIS git secret list ## DESCRIPTION `git-secret-list` - print the files currently considered secret in this repo. Shows tracked files from `.gitsecret/paths/mapping.cfg`. (See [git-secret(7)](https://git-secret.io/git-secret) for information about renaming the .gitsecret folder using the `SECRETS_DIR` environment variable. ## OPTIONS -h - shows this help. ## MANUAL Run `man git-secret-list` to see this document. ## SEE ALSO [git-secret-whoknows(1)](https://git-secret.io/git-secret-whoknows), [git-secret-add(1)](https://git-secret.io/git-secret-add), [git-secret-remove(1)](https://git-secret.io/git-secret-remove), [git-secret-hide(1)](https://git-secret.io/git-secret-hide), [git-secret-reveal(1)](https://git-secret.io/git-secret-reveal), [git-secret-cat(1)](https://git-secret.io/git-secret-cat) git-secret-0.5.0/man/man1/git-secret-remove.1000066400000000000000000000026511424706700600206260ustar00rootroot00000000000000.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "GIT\-SECRET\-REMOVE" "1" "April 2022" "sobolevn" "git-secret 0.5.0-alpha2" . .SH "NAME" \fBgit\-secret\-remove\fR \- removes files from index\. . .SH "SYNOPSIS" . .nf git secret remove [\-c] \.\.\. . .fi . .SH "DESCRIPTION" \fBgit\-secret\-remove\fR \- stops files from being tracked by \fBgit\-secret\fR\. . .P This 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\. . .P There\'s also a \-c option to delete existing encrypted versions of the files provided\. . .P Note unlike \fBadd\fR, which automatically add pathnames to \fB\.gitignore\fR, \fBremove\fR does not delete pathnames from \fB\.gitignore\fR\. . .P (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\. . .SH "OPTIONS" . .nf \-c \- deletes existing real encrypted files\. \-h \- shows help\. . .fi . .SH "MANUAL" Run \fBman git\-secret\-remove\fR to see this document\. . .SH "SEE ALSO" git\-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 git-secret-0.5.0/man/man1/git-secret-remove.1.md000066400000000000000000000022131424706700600212170ustar00rootroot00000000000000git-secret-remove - removes files from index. ============================================= ## SYNOPSIS git secret remove [-c] ... ## DESCRIPTION `git-secret-remove` - stops files from being tracked by `git-secret`. This deletes filenames from `.gitsecret/paths/mapping.cfg`, which stops these files from being tracked by `git-secret`, and from being encrypted to, or decrypted from, `.secret` encrypted versions. There's also a -c option to delete existing encrypted versions of the files provided. Note unlike `add`, which automatically add pathnames to `.gitignore`, `remove` does not delete pathnames from `.gitignore`. (See [git-secret(7)](https://git-secret.io/git-secret) for information about renaming the .gitsecret folder using the `SECRETS_DIR` environment variable. ## OPTIONS -c - deletes existing real encrypted files. -h - shows help. ## MANUAL Run `man git-secret-remove` to see this document. ## SEE ALSO [git-secret-add(1)](https://git-secret.io/git-secret-add), [git-secret-clean(1)](https://git-secret.io/git-secret-clean), [git-secret-removeperson(1)](https://git-secret.io/git-secret-removeperson) git-secret-0.5.0/man/man1/git-secret-removeperson.1000066400000000000000000000022411424706700600220500ustar00rootroot00000000000000.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "GIT\-SECRET\-REMOVEPERSON" "1" "April 2022" "sobolevn" "git-secret 0.5.0-alpha2" . .SH "NAME" \fBgit\-secret\-removeperson\fR \- removes user\'s public key from repo keyring\. . .SH "SYNOPSIS" . .nf git secret removeperson \.\.\. . .fi . .SH "DESCRIPTION" \fBgit\-secret\-removeperson\fR \- removes public keys for passed email addresses from repo\'s \fBgit\-secret\fR keyring\. . .P This command is used to begin the process of disallowing a user from encrypting and decrypting secrets with \fBgit\-secret\fR\. . .P If 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\. . .SH "OPTIONS" . .nf \-h \- shows this help\. . .fi . .SH "MANUAL" Run \fBman git\-secret\-removeperson\fR to see this document\. . .SH "SEE ALSO" git\-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 git-secret-0.5.0/man/man1/git-secret-removeperson.1.md000066400000000000000000000016771424706700600224630ustar00rootroot00000000000000git-secret-removeperson - removes user's public key from repo keyring. ================================================================================== ## SYNOPSIS git secret removeperson ... ## DESCRIPTION `git-secret-removeperson` - removes public keys for passed email addresses from repo's `git-secret` keyring. This command is used to begin the process of disallowing a user from encrypting and decrypting secrets with `git-secret`. If you remove a user's access with `git-secret-removeperson`, and then run `git-secret-reveal` and `git-secret-hide -r`, that user will no longer be able user to decrypt the hidden files. ## OPTIONS -h - shows this help. ## MANUAL Run `man git-secret-removeperson` to see this document. ## SEE ALSO [git-secret-tell(1)](https://git-secret.io/git-secret-tell), [git-secret-remove(1)](https://git-secret.io/git-secret-remove), [git-secret-clean(1)](https://git-secret.io/git-secret-clean) git-secret-0.5.0/man/man1/git-secret-reveal.1000066400000000000000000000052551424706700600206120ustar00rootroot00000000000000.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "GIT\-SECRET\-REVEAL" "1" "April 2022" "sobolevn" "git-secret 0.5.0-alpha2" . .SH "NAME" \fBgit\-secret\-reveal\fR \- decrypts all added files\. . .SH "SYNOPSIS" . .nf git secret reveal [\-f] [\-F] [\-P] [\-v] [\-d dir] [\-p password] [pathspec]\.\.\. . .fi . .SH "DESCRIPTION" \fBgit\-secret\-reveal\fR \- decrypts passed files, or all files considered secret by \fBgit\-secret\fR\. . .P Under 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\. . .P Therefore, 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\. . .SH "OPTIONS" . .nf \-f \- forces gpg to overwrite existing files without prompt\. \-F \- forces reveal to continue even if a file fails to decrypt\. \-d \- specifies `\-\-homedir` option for the `gpg`, basically use this option if you store your keys in a custom location\. \-v \- verbose, shows extra information\. \-p \- specifies password for noinput mode, adds `\-\-passphrase` option for `gpg`\. \-P \- preserve permissions of encrypted file in unencrypted file\. \-h \- shows help\. . .fi . .SH "ENV VARIABLES" . .IP "\(bu" 4 \fBSECRETS_GPG_COMMAND\fR changes the default \fBgpg\fR command to anything else . .IP "\(bu" 4 \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 . .IP "\(bu" 4 \fBSECRETS_DIR\fR changes the default \fB\.gitsecret/\fR folder to another name as documented at git\-secret(7) \fIhttps://git\-secret\.io/\fR . .IP "\(bu" 4 \fBSECRETS_EXTENSION\fR changes the default \fB\.secret\fR file extension . .IP "\(bu" 4 \fBSECRETS_VERBOSE\fR changes the output verbosity as documented at git\-secret(7) \fIhttps://git\-secret\.io/\fR . .IP "\(bu" 4 \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 . .IP "" 0 . .SH "MANUAL" Run \fBman git\-secret\-reveal\fR to see this document\. . .SH "SEE ALSO" git\-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 git-secret-0.5.0/man/man1/git-secret-reveal.1.md000066400000000000000000000043631424706700600212100ustar00rootroot00000000000000git-secret-reveal - decrypts all added files. ============================================= ## SYNOPSIS git secret reveal [-f] [-F] [-P] [-v] [-d dir] [-p password] [pathspec]... ## DESCRIPTION `git-secret-reveal` - decrypts passed files, or all files considered secret by `git-secret`. Under the hood, `reveal` uses the `gpg --decrypt` command and your private key (typically from your personal keyring in your home directory) to _decrypt_ files. Therefore, 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 `git-secret` keyring when the file was encrypted. ## OPTIONS -f - forces gpg to overwrite existing files without prompt. -F - forces reveal to continue even if a file fails to decrypt. -d - specifies `--homedir` option for the `gpg`, basically use this option if you store your keys in a custom location. -v - verbose, shows extra information. -p - specifies password for noinput mode, adds `--passphrase` option for `gpg`. -P - preserve permissions of encrypted file in unencrypted file. -h - shows help. ## ENV VARIABLES - `SECRETS_GPG_COMMAND` changes the default `gpg` command to anything else - `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 - `SECRETS_DIR` changes the default `.gitsecret/` folder to another name as documented at [git-secret(7)](https://git-secret.io/) - `SECRETS_EXTENSION` changes the default `.secret` file extension - `SECRETS_VERBOSE` changes the output verbosity as documented at [git-secret(7)](https://git-secret.io/) - `SECRETS_PINENTRY` changes the [`gpg --pinentry` mode](https://github.com/gpg/pinentry) as documented at [git-secret(7)](https://git-secret.io/) ## MANUAL Run `man git-secret-reveal` to see this document. ## SEE ALSO [git-secret-init(1)](https://git-secret.io/git-secret-init), [git-secret-cat(1)](https://git-secret.io/git-secret-cat), [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-0.5.0/man/man1/git-secret-tell.1000066400000000000000000000047051424706700600202730ustar00rootroot00000000000000.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "GIT\-SECRET\-TELL" "1" "April 2022" "sobolevn" "git-secret 0.5.0-alpha2" . .SH "NAME" \fBgit\-secret\-tell\fR \- adds person who can access private data\. . .SH "SYNOPSIS" . .nf git secret tell [\-m] [\-d dir] [emails]\.\.\. . .fi . .SH "DESCRIPTION" \fBgit\-secret tell\fR \- adds user(s) to the list of those able to encypt/decrypt secrets\. . .P This 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\. . .P \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\. . .P Under 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\. . .P Versions 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\. . .P \fBDo not manually import secret keys into \fBgit\-secret\fR\fR\. It won\'t work with imported secret keys anyway\. . .P For 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\. . .SH "OPTIONS" . .nf \-m \- uses your current `git config user\.email` setting as an identifier for the key\. \-d \- specifies `\-\-homedir` option for `gpg`, basically use this option if your store your keys in a custom location\. \-h \- shows help\. . .fi . .SH "MANUAL" Run \fBman git\-secret\-tell\fR to see this document\. . .SH "SEE ALSO" git\-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 git-secret-0.5.0/man/man1/git-secret-tell.1.md000066400000000000000000000042021424706700600206620ustar00rootroot00000000000000git-secret-tell - adds person who can access private data. =============================================================== ## SYNOPSIS git secret tell [-m] [-d dir] [emails]... ## DESCRIPTION `git-secret tell` - adds user(s) to the list of those able to encypt/decrypt secrets. This 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. `git-secret tell` 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 `git-secret` repo's keyring. Under the hood, `git-secret-tell` searches in the current user's `gnupg` keyring for public key(s) of passed email(s), then imports the corresponding public key(s) into your `git-secret` repo's keyring. Versions of `git-secret tell` after `0.3.2` 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. **Do not manually import secret keys into `git-secret`**. It won't work with imported secret keys anyway. For more details about how `git-secret` uses public and private keys, see the documentation for `git-secret-hide` and `git-secret-reveal`. ## OPTIONS -m - uses your current `git config user.email` setting as an identifier for the key. -d - specifies `--homedir` option for `gpg`, basically use this option if your store your keys in a custom location. -h - shows help. ## MANUAL Run `man git-secret-tell` to see this document. ## SEE ALSO [git-secret-init(1)](https://git-secret.io/git-secret-init), [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-reveal), [git-secret-cat(1)](https://git-secret.io/git-secret-cat), [git-secret-removeperson(1)](https://git-secret.io/git-secret-removeperson) git-secret-0.5.0/man/man1/git-secret-usage.1000066400000000000000000000015551424706700600204370ustar00rootroot00000000000000.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "GIT\-SECRET\-USAGE" "1" "April 2022" "sobolevn" "git-secret 0.5.0-alpha2" . .SH "NAME" \fBgit\-secret\-usage\fR \- prints all the available commands\. . .SH "SYNOPSIS" . .nf git secret usage . .fi . .SH "DESCRIPTION" \fBgit\-secret\-usage\fR \- prints all the available \fBgit\-secret\fR commands\. . .SH "OPTIONS" . .nf \-h \- shows this help\. . .fi . .SH "MANUAL" Run \fBman git\-secret\-usage\fR to see this document\. . .SH "SEE ALSO" git\-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-0.5.0/man/man1/git-secret-usage.1.md000066400000000000000000000012131424706700600210250ustar00rootroot00000000000000git-secret-usage - prints all the available commands. ===================================================== ## SYNOPSIS git secret usage ## DESCRIPTION `git-secret-usage` - prints all the available `git-secret` commands. ## OPTIONS -h - shows this help. ## MANUAL Run `man git-secret-usage` to see this document. ## SEE ALSO [git-secret-init(1)](https://git-secret.io/git-secret-init), [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-reveal), [git-secret-cat(1)](https://git-secret.io/git-secret-cat) git-secret-0.5.0/man/man1/git-secret-whoknows.1000066400000000000000000000017071424706700600212110ustar00rootroot00000000000000.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "GIT\-SECRET\-WHOKNOWS" "1" "April 2022" "sobolevn" "git-secret 0.5.0-alpha2" . .SH "NAME" \fBgit\-secret\-whoknows\fR \- print email for each key in the keyring\. . .SH "SYNOPSIS" . .nf git secret whoknows . .fi . .SH "DESCRIPTION" \fBgit\-secret\-whoknows\fR \- print email addresses allowed to access the secrets in this repo\. . .SH "OPTIONS" . .nf \-l \- \'long\' output, shows key expiration dates\. \-h \- shows this help\. . .fi . .SH "MANUAL" Run \fBman git\-secret\-whoknows\fR to see this document\. . .SH "SEE ALSO" git\-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 git-secret-0.5.0/man/man1/git-secret-whoknows.1.md000066400000000000000000000013671424706700600216120ustar00rootroot00000000000000git-secret-whoknows - print email for each key in the keyring. ====================================================================== ## SYNOPSIS git secret whoknows ## DESCRIPTION `git-secret-whoknows` - print email addresses allowed to access the secrets in this repo. ## OPTIONS -l - 'long' output, shows key expiration dates. -h - shows this help. ## MANUAL Run `man git-secret-whoknows` to see this document. ## SEE ALSO [git-secret-list(1)](https://git-secret.io/git-secret-list), [git-secret-tell(1)](https://git-secret.io/git-secret-tell), [git-secret-hide(1)](https://git-secret.io/git-secret-hide), [git-secret-reveal(1)](https://git-secret.io/git-secret-reveal), [git-secret-cat(1)](https://git-secret.io/git-secret-cat) git-secret-0.5.0/man/man7/000077500000000000000000000000001424706700600152055ustar00rootroot00000000000000git-secret-0.5.0/man/man7/git-secret.7000066400000000000000000000300531424706700600173440ustar00rootroot00000000000000.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "GIT\-SECRET" "7" "April 2022" "sobolevn" "git-secret 0.5.0-alpha2" . .SH "NAME" \fBgit\-secret\fR \- bash tool to store private data inside a git repo\. . .SH "Usage: Setting up git\-secret in a repository" These 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\. . .IP "1." 4 Before 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\. . .IP "2." 4 Begin with an existing or new git repository\. . .IP "3." 4 Initialize 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\. . .IP "" 0 . .P \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\. . .IP "1." 4 Add the first user to the \fBgit\-secret\fR repo keyring by running \fBgit secret tell your@email\.id\fR\. . .IP "2." 4 Now 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 \fR command, which will also (as of 0\.2\.6) add entries to \fB\.gitignore\fR, stopping those files from being be added or committed to the repo unencrypted\. . .IP "3." 4 Then 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\. . .IP "" 0 . .P After 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\. . .IP "1." 4 Later 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! . .IP "" 0 . .SS "Usage: Adding someone to a repository using git\-secret" . .IP "1." 4 \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: . .IP "" 0 . .P \fBgpg \-\-armor \-\-export their@email\.com > public_key\.txt\fR \fB# armor here makes it ascii\fR . .IP "1." 4 Import this key into your \fBgpg\fR keyring (in \fB~/\.gnupg\fR or similar) by running \fBgpg \-\-import public_key\.txt\fR . .IP "2." 4 Now 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) . .IP "3." 4 Now remove the other user\'s public key from your personal keyring with \fBgpg \-\-delete\-keys their@email\.id\fR . .IP "4." 4 The 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\. . .IP "" 0 . .P Note 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\. . .P If you do not want unexpected keys added, you can configure some server\-side security policy with the \fBpre\-receive\fR hook\. . .SS "Using gpg" You 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: . .P To generate a RSA key\-pair, run: . .IP "" 4 . .nf gpg \-\-gen\-key . .fi . .IP "" 0 . .P To export your public key, run: . .IP "" 4 . .nf gpg \-\-armor \-\-export your\.email@address\.com > public\-key\.gpg . .fi . .IP "" 0 . .P To import the public key of someone else (to share the secret with them for instance), run: . .IP "" 4 . .nf gpg \-\-import public\-key\.gpg . .fi . .IP "" 0 . .P To 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! . .SS "Using git\-secret for Continuous Integration / Continuous Deployment (CI/CD)" When 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\. . .P One way of doing it is the following: . .IP "1." 4 \fIcreate a gpg key\fR for your CI/CD environment\. You can chose any name and email address you want: for instance \fBMyApp Example \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\. . .IP "2." 4 run \fBgpg \-\-armor \-\-export\-secret\-key myapp@example\.com\fR to get your private key value . .IP "3." 4 Create 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\. . .IP "4." 4 Then write your Continuous Deployment build script\. For instance: . .IP "" 0 . .IP "" 4 . .nf # As the first step: install git\-secret, # see: https://git\-secret\.io/installation # Create private key file echo "$GPG_PRIVATE_KEY" > \./private_key\.gpg # Import private key and avoid the "Inappropriate ioctl for device" error gpg \-\-batch \-\-yes \-\-pinentry\-mode loopback \-\-import private_key\.gpg # Reveal secrets without user interaction and with passphrase\. If no passphrase # is created for the key, remove `\-p $GPG_PASSPHRASE` git secret reveal \-p "$GPG_PASSPHRASE" # carry on with your build script, secret files are available \.\.\. . .fi . .IP "" 0 . .P Note: your CI/CD might not allow you to create a multiline value\. In that case, you can export it on one line with . .IP "" 4 . .nf gpg \-\-armor \-\-export\-secret\-key myapp@example\.com | tr \'\en\' \',\' . .fi . .IP "" 0 . .P You can then create your private key file with: . .IP "" 4 . .nf echo "$GPG_PRIVATE_KEY" | tr \',\' \'\en\' > \./private_key\.gpg . .fi . .IP "" 0 . .P Also 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\. . .SH "Environment Variables and Configuration" You 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\. . .P The settings available to be changed are: . .IP "\(bu" 4 \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\. . .IP "\(bu" 4 \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\. . .IP "\(bu" 4 \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\. . .IP "\(bu" 4 \fB$SECRETS_EXTENSION\fR \- sets the secret files extension, defaults to \fB\.secret\fR\. It can be changed to any valid file extension\. . .IP "\(bu" 4 \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\. . .IP "\(bu" 4 \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\. . .IP "" 0 . .SH "The \.gitsecret folder (can be overridden with SECRETS_DIR)" This folder contains information about the files encrypted by git\-secret, and about which public/private key sets can access the encrypted data\. . .P You can change the name of this directory using the SECRETS_DIR environment variable\. . .P Use the various \fBgit\-secret\fR commands to manipulate the files in \fB\.gitsecret\fR, you should not change the data in these files directly\. . .P Exactly 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\. . .P For 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\')\. . .P This 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\. . .P The \fBgit\-secret\fR internal data is separated into two directories: . .SS "\.gitsecret/paths" This directory currently contains only the file \fBmapping\.cfg\fR, which lists all the files your storing encrypted\. In other words, the path mappings: what files are tracked to be hidden and revealed\. . .P All the other internal data is stored in the directory: . .SS "\.gitsecret/keys" This directory contains data used by \fBgit\-secret\fR and \fBgpg\fR to encrypt files to be accessed by the permitted users\. . .P In particular, this directory contains a \fBgnupg keyring\fR with public keys for the emails used with \fBtell\fR\. . .P This is the keyring used to encrypt files with \fBgit\-secret\-hide\fR\. . .P \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\. . .P Generally 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\. . .P Again, you can change the name of this directory using the SECRETS_DIR environment variable\. git-secret-0.5.0/man/man7/git-secret.7.md000066400000000000000000000252511424706700600177470ustar00rootroot00000000000000git-secret - bash tool to store private data inside a git repo. ============================================= ## Usage: Setting up git-secret in a repository These steps cover the basic process of using `git-secret` to specify users and files that will interact with `git-secret`, and to encrypt and decrypt secrets. 0. Before starting, [make sure you have created a `gpg` RSA key-pair](#using-gpg): 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. 1. Begin with an existing or new git repository. 2. Initialize the `git-secret` repository by running `git secret init`. The `.gitsecret/` folder will be created, with subdirectories `keys/` and `paths/`, `.gitsecret/keys/random_seed` will be added to `.gitignore`, and `.gitignore` will be configured to _not_ ignore `.secret` files. **Note** all the contents of the `.gitsecret/` folder should be checked in, **/except/** the `random_seed` file. This also means that of all the files in `.gitsecret/`, only the `random_seed` file should be mentioned in your `.gitignore` file. 3. Add the first user to the `git-secret` repo keyring by running `git secret tell your@email.id`. 4. Now it's time to add files you wish to encrypt inside the `git-secret` repository. This can be done by running `git secret add ` command, which will also (as of 0.2.6) add entries to `.gitignore`, stopping those files from being be added or committed to the repo unencrypted. 5. Then run `git secret hide` to encrypt the files you added with `git secret add`. 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 `tell`. After using `git secret hide` to encrypt your data, it is safe to commit your changes. **NOTE:** It's recommended to add the `git secret hide` command to your `pre-commit` hook, so you won't miss any changes. 6. Later you can decrypt files with the `git secret reveal` command, or print their contents to stdout with the `git secret cat` command. If you used a password on your GPG key (always recommended), it will ask you for your password. And you're done! ### Usage: Adding someone to a repository using git-secret 1. [Get their `gpg` public-key](#using-gpg). **You won't need their secret key.** They can export their public key for you using a command like: `gpg --armor --export their@email.com > public_key.txt` `# armor here makes it ascii` 2. Import this key into your `gpg` keyring (in `~/.gnupg` or similar) by running `gpg --import public_key.txt` 3. Now add this person to your secrets repo by running `git secret tell their@email.id` (this will be the email address associated with their public key) 4. Now remove the other user's public key from your personal keyring with `gpg --delete-keys their@email.id` 5. The newly added user cannot yet read the encrypted files. Now, re-encrypt the files using `git secret reveal; git secret hide -d`, 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 `git-secret reveal`. Note 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. If you do not want unexpected keys added, you can configure some server-side security policy with the `pre-receive` hook. ### Using gpg You can follow a quick `gpg` tutorial at [devdungeon](https://www.devdungeon.com/content/gpg-tutorial). Here are the most useful commands to get started: To generate a RSA key-pair, run: ```shell gpg --gen-key ``` To export your public key, run: ```shell gpg --armor --export your.email@address.com > public-key.gpg ``` To import the public key of someone else (to share the secret with them for instance), run: ```shell gpg --import public-key.gpg ``` To 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! ### Using git-secret for Continuous Integration / Continuous Deployment (CI/CD) When using `git-secret` 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. One way of doing it is the following: 1. [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 ` 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. 2. run `gpg --armor --export-secret-key myapp@example.com` to get your private key value 3. 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. 4. Then write your Continuous Deployment build script. For instance: ```shell # As the first step: install git-secret, # see: https://git-secret.io/installation # Create private key file echo "$GPG_PRIVATE_KEY" > ./private_key.gpg # Import private key and avoid the "Inappropriate ioctl for device" error gpg --batch --yes --pinentry-mode loopback --import private_key.gpg # Reveal secrets without user interaction and with passphrase. If no passphrase # is created for the key, remove `-p $GPG_PASSPHRASE` git secret reveal -p "$GPG_PASSPHRASE" # carry on with your build script, secret files are available ... ``` Note: your CI/CD might not allow you to create a multiline value. In that case, you can export it on one line with ```shell gpg --armor --export-secret-key myapp@example.com | tr '\n' ',' ``` You can then create your private key file with: ```shell echo "$GPG_PRIVATE_KEY" | tr ',' '\n' > ./private_key.gpg ``` Also 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. ## Environment Variables and Configuration You can configure the version of `gpg` 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 `git-secret` command. See below, or the man page of `git-secret` for an explanation of the environment variables `git-secret` uses. The settings available to be changed are: * `$SECRETS_VERBOSE` - sets the verbose flag to on for all `git-secret` commands; is identical to using `-v` on each command that supports it. * `$SECRETS_GPG_COMMAND` - sets the `gpg` alternatives, defaults to `gpg`. It can be changed to `gpg`, `gpg2`, `pgp`, `/usr/local/gpg` or any other value. After doing so rerun the tests to be sure that it won't break anything. Tested with `gpg` and `gpg2`. * `$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. * `$SECRETS_EXTENSION` - sets the secret files extension, defaults to `.secret`. It can be changed to any valid file extension. * `$SECRETS_DIR` - sets the directory where `git-secret` stores its files, defaults to `.gitsecret`. It can be changed to any valid directory name. * `$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. ## The `.gitsecret` folder (can be overridden with `SECRETS_DIR`) This folder contains information about the files encrypted by git-secret, and about which public/private key sets can access the encrypted data. You can change the name of this directory using the SECRETS_DIR environment variable. Use the various `git-secret` commands to manipulate the files in `.gitsecret`, you should not change the data in these files directly. Exactly which files exist in the `.gitsecret` 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 `SECRETS_GPG_COMMAND` environment variable. For example, there is an issue between `gpg` 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'). This is not the only issue it is possible to encounter sharing files between different versions of `gpg`. Generally you are most likely to encounter issues between `gpg` versions if you use `git-secret tell` or `git-secret removeperson` to modify your repo's `git-secret` keyring using a newer version of `gpg`, and then try to operate on that keyring using an older version of `gpg`. The `git-secret` internal data is separated into two directories: ### `.gitsecret/paths` This directory currently contains only the file `mapping.cfg`, which lists all the files your storing encrypted. In other words, the path mappings: what files are tracked to be hidden and revealed. All the other internal data is stored in the directory: ### `.gitsecret/keys` This directory contains data used by `git-secret` and `gpg` to encrypt files to be accessed by the permitted users. In particular, this directory contains a `gnupg keyring` with public keys for the emails used with `tell`. This is the keyring used to encrypt files with `git-secret-hide`. `git-secret-reveal` and `git-secret-cat`, which decrypt secrets, instead use the user's _private keys_ (which probably reside somewhere like ~/.gnupg/). Note that user's private keys, needed for decryption, are _not_ in the `.gitsecret/keys` directory. Generally speaking, all the files in this directory *except* `random_seed` should be checked into your repo. By default, `git secret init` will add the file `.gitsecret/keys/random_seed` to your `.gitignore` file. Again, you can change the name of this directory using the SECRETS_DIR environment variable. git-secret-0.5.0/src/000077500000000000000000000000001424706700600143575ustar00rootroot00000000000000git-secret-0.5.0/src/_utils/000077500000000000000000000000001424706700600156565ustar00rootroot00000000000000git-secret-0.5.0/src/_utils/_git_secret_tools.sh000066400000000000000000000472441424706700600217340ustar00rootroot00000000000000#!/usr/bin/env bash # Folders: _SECRETS_DIR=${SECRETS_DIR:-".gitsecret"} # if SECRETS_DIR env var is set, use that instead of .gitsecret # for full path to secrets dir, use _get_secrets_dir() # from _git_secret_tools.sh _SECRETS_DIR_KEYS="${_SECRETS_DIR}/keys" _SECRETS_DIR_PATHS="${_SECRETS_DIR}/paths" # Files: _SECRETS_DIR_KEYS_TRUSTDB="${_SECRETS_DIR_KEYS}/trustdb.gpg" _SECRETS_DIR_PATHS_MAPPING="${_SECRETS_DIR_PATHS}/mapping.cfg" # shellcheck disable=SC2153 if [[ -n "$SECRETS_VERBOSE" ]] && [[ "$SECRETS_VERBOSE" -ne 0 ]]; then # shellcheck disable=SC2034 _SECRETS_VERBOSE='1' # _SECRETS_VERBOSE is empty or '1'. # Empty means 'off', any other value means 'on'. fi : "${SECRETS_EXTENSION:=".secret"}" # Commands: : "${SECRETS_GPG_COMMAND:="gpg"}" : "${SECRETS_CHECKSUM_COMMAND:="_os_based __sha256"}" : "${SECRETS_OCTAL_PERMS_COMMAND:="_os_based __get_octal_perms"}" : "${SECRETS_EPOCH_TO_DATE:="_os_based __epoch_to_date"}" # Temp Dir: : "${TMPDIR:=/tmp}" # AWK scripts: # shellcheck disable=SC2016 AWK_FSDB_HAS_RECORD=' BEGIN { FS=":"; OFS=":"; cnt=0; } { if ( key == $1 ) { cnt++ } } END { if ( cnt > 0 ) print "0"; else print "1"; } ' # shellcheck disable=SC2016 AWK_FSDB_RM_RECORD=' BEGIN { FS=":"; OFS=":"; } { if ( key != $1 ) { print $1,$2; } } ' # shellcheck disable=SC2016 AWK_FSDB_CLEAR_HASHES=' BEGIN { FS=":"; OFS=":"; } { print $1,""; } ' # shellcheck disable=SC2016 AWK_GPG_VER_CHECK=' /^gpg/{ version=$3 n=split(version,array,".") if( n >= 2) { if(array[1] >= 2) { if(array[2] >= 1) { print 1 } else { print 0 } } else { print 0 } } else if(array[1] >= 2) { print 1 } else { print 0 } } ' # This is 1 for gpg version 2.1 or greater, otherwise 0 GPG_VER_MIN_21="$($SECRETS_GPG_COMMAND --version | gawk "$AWK_GPG_VER_CHECK")" # Bash: # echos 0 if function exists, otherwise non-zero function _function_exists { local function_name="$1" # required declare -f -F "$function_name" > /dev/null 2>&1 echo $? } # OS based: function _os_based { # Pass function name as first parameter. # It will be invoked as os-based function with the postfix. case "$(uname -s)" in Darwin) "$1_osx" "${@:2}" ;; Linux) "$1_linux" "${@:2}" ;; MINGW*) "$1_linux" "${@:2}" ;; MSYS*) "$1_linux" "${@:2}" ;; CYGWIN*) "$1_linux" "${@:2}" ;; FreeBSD) "$1_freebsd" "${@:2}" ;; # TODO: add MS Windows support. # MINGW32*|MSYS*) # $1_ms ${@:2} # ;; *) _abort 'unsupported OS.' ;; esac } # File System: function _clean_windows_path { # This function transforms windows paths to *nix paths # such as c:\this\that.file -> /c/this/that/file # shellcheck disable=SC2001 echo "$1" | sed 's#^\([a-zA-Z]\):/#/\1/#' } function _set_config { # This function creates a line in the config, or alters it. local key="$1" # required local value="$2" # required local filename="$3" # required # The exit status is 0 (true) if the name was found, 1 (false) if not: local contains contains=$(grep -Fq "$key" "$filename"; echo "$?") # Append or alter? if [[ "$contains" -eq 0 ]]; then _os_based __replace_in_file "$@" elif [[ "$contains" -eq 1 ]]; then echo "${key} = ${value}" >> "$filename" fi } # this sets the global variable 'temporary_filename' # currently this function is only used by 'hide' function _temporary_file { # This function creates temporary file # which will be removed on system exit. temporary_filename=$(_os_based __temp_file) # is not `local` on purpose. 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 } # Helper function function _gawk_inplace { local parms="$*" local dest_file dest_file="$(echo "$parms" | gawk -v RS="'" -v FS="'" 'END{ gsub(/^\s+/,""); print $1 }')" _temporary_file bash -c "gawk ${parms}" > "$temporary_filename" mv "$temporary_filename" "$dest_file" } # File System Database (fsdb): function _get_record_filename { # Returns 1st field from passed record local record="$1" local filename filename=$(echo "$record" | awk -F: '{print $1}') echo "$filename" } function _get_record_hash { # Returns 2nd field from passed record local record="$1" local hash hash=$(echo "$record" | awk -F: '{print $2}') echo "$hash" } function _fsdb_has_record { # First parameter is the key # Second is the fsdb local key="$1" # required local fsdb="$2" # required # 0 on contains, 1 for error. gawk -v key="$key" "$AWK_FSDB_HAS_RECORD" "$fsdb" } function _fsdb_rm_record { # First parameter is the key (filename) # Second is the path to fsdb local key="$1" # required local fsdb="$2" # required _gawk_inplace -v key="'$key'" "'$AWK_FSDB_RM_RECORD'" "$fsdb" } function _fsdb_clear_hashes { # First parameter is the path to fsdb local fsdb="$1" # required _gawk_inplace "'$AWK_FSDB_CLEAR_HASHES'" "$fsdb" } # Manuals: function _show_manual_for { local function_name="$1" # required man "git-secret-${function_name}" exit 0 } # Invalid options function _invalid_option_for { local function_name="$1" # required man "git-secret-${function_name}" exit 1 } # VCS: function _check_ignore { local filename="$1" # required local result result="$(git check-ignore -q "$filename"; echo $?)" # returns 1 when not ignored, and 0 when ignored echo "$result" } function _git_normalize_filename { local filename="$1" # required local result result=$(git ls-files --full-name -o "$filename") echo "$result" } function _maybe_create_gitignore { # This function creates '.gitignore' if it was missing. local full_path full_path=$(_prepend_root_path '.gitignore') if [[ ! -f "$full_path" ]]; then touch "$full_path" fi } function _add_ignored_file { # This function adds a line with the filename into the '.gitignore' file. # It also creates '.gitignore' if it's not there local filename="$1" # required _maybe_create_gitignore local full_path full_path=$(_prepend_root_path '.gitignore') printf '%q\n' "$filename" >> "$full_path" } function _is_inside_git_tree { # Checks if we are working inside the `git` tree. local result result=$(git rev-parse --is-inside-work-tree > /dev/null 2>&1; echo $?) echo "$result" } function _is_tracked_in_git { local filename="$1" # required local result result="$(git ls-files --error-unmatch "$filename" >/dev/null 2>&1; echo $?)" if [[ "$result" -eq 0 ]]; then echo "1" else echo "0" fi } # This can give unexpected .git dir when used in a _subdirectory_ # of another git repo; See #431 and #433. function _get_git_root_path { # We need this function to get the location of the `.git` folder, # since `.gitsecret` (or value set by SECRETS_DIR env var) # must be in the same dir. local result result=$(_clean_windows_path "$(git rev-parse --show-toplevel)") echo "$result" } # Relative paths: function _prepend_root_path { # This function adds root path to any other path. local path="$1" # required local root_path root_path=$(_get_git_root_path) echo "$root_path/$path" } # if passed a name like 'filename.txt', returns a full path in the repo # For #710: if we are in a subdir, fixup the path with the subdir function _prepend_relative_root_path { local path="$1" # required local full_path full_path=$(_prepend_root_path "$path") local subdir subdir=$(git rev-parse --show-prefix) # get the subdir of repo, like "subdir/" if [ -n "$subdir" ]; then full_path="$(dirname "$full_path")/${subdir}/$(basename "$full_path")" fi echo "$full_path" } function _get_secrets_dir { _prepend_root_path "${_SECRETS_DIR}" } function _get_secrets_dir_keys { _prepend_root_path "${_SECRETS_DIR_KEYS}" } function _get_secrets_dir_path { _prepend_root_path "${_SECRETS_DIR_PATHS}" } function _get_secrets_dir_keys_trustdb { _prepend_root_path "${_SECRETS_DIR_KEYS_TRUSTDB}" } function _get_secrets_dir_paths_mapping { _prepend_root_path "${_SECRETS_DIR_PATHS_MAPPING}" } # Logic: function _message { local message="$1" # required echo "git-secret: $message" } function _abort { local message="$1" # required local exit_code=${2:-"1"} # defaults to 1 >&2 echo "git-secret: abort: $message" exit "$exit_code" } # _warn() sends warnings to stdout so user sees them function _warn { local message="$1" # required >&2 echo "git-secret: warning: $message" } # _warn_or_abort "$error_message" "$exit_code" "$error_ok" function _warn_or_abort { local message="$1" # required local exit_code=${2:-"1"} # defaults to 1 local error_ok=${3:-0} # can be 0 or 1 if [[ "$error_ok" -eq "0" ]]; then if [[ "$exit_code" -eq "0" ]]; then # if caller sends an exit_code of 0, we change it to 1 before aborting. exit_code=1 fi _abort "$message" "$exit_code" else _warn "$message" "$exit_code" fi } function _find_and_remove_secrets_formatted { local filenames _list_all_added_files # sets array variable 'filenames' for filename in "${filenames[@]}"; do local path # absolute path encrypted_filename=$(_get_encrypted_filename "$filename") if [[ -f "$encrypted_filename" ]]; then rm "$encrypted_filename" if [[ -n "$_SECRETS_VERBOSE" ]]; then echo "git-secret: deleted: $encrypted_filename" fi fi done } # this sets the global array variable 'filenames' function _list_all_added_files { local path_mappings path_mappings=$(_get_secrets_dir_paths_mapping) if [[ ! -s "$path_mappings" ]]; then _abort "path_mappings file is missing or empty: $path_mappings" fi local filename filenames=() # not local while read -r line; do filename=$(_get_record_filename "$line") filenames+=("$filename") done < "$path_mappings" declare -a filenames # so caller can get list from filenames array } function _secrets_dir_exists { # This function checks if "$_SECRETS_DIR" exists and. local full_path full_path=$(_get_secrets_dir) if [[ ! -d "$full_path" ]]; then local name name=$(basename "$full_path") _abort "directory '$name' does not exist. Use 'git secret init' to initialize git-secret" fi } function _secrets_dir_is_not_ignored { # This function checks that "$_SECRETS_DIR" is not ignored. local git_secret_dir git_secret_dir=$(_get_secrets_dir) local ignores ignores=$(_check_ignore "$git_secret_dir") if [[ ! $ignores -eq 1 ]]; then _abort "entry already in .gitignore: $git_secret_dir" fi } function _exe_is_busybox { local exe exe="$1" # we assume stat is from busybox if it's a symlink local is_busybox=0 local stat_path stat_path=$(command -v "$exe") if [ -L "$stat_path" ]; then is_busybox=1 fi echo "$is_busybox" } # this is used by just about every command function _user_required { # This function does a bunch of validations: # 1. It calls `_secrets_dir_exists` to verify that "$_SECRETS_DIR" exists. # 2. It ensures that "$_SECRETS_DIR_KEYS_TRUSTDB" exists. # 3. It ensures that there are added public keys. _secrets_dir_exists local trustdb trustdb=$(_get_secrets_dir_keys_trustdb) local error_message="no public keys for users found. run 'git secret tell email@address'." if [[ ! -f "$trustdb" ]]; then _abort "$error_message" fi local secrets_dir_keys secrets_dir_keys=$(_get_secrets_dir_keys) # see https://github.com/bats-core/bats-core#file-descriptor-3-read-this-if-bats-hangs for info about 3>&- local keys_exist keys_exist=$($SECRETS_GPG_COMMAND --homedir "$secrets_dir_keys" --no-permission-warning -n --list-keys 3>&-) local exit_code=$? if [[ -z "$keys_exist" ]]; then _abort "$error_message" fi if [[ "$exit_code" -ne 0 ]]; then # this might catch corner case where gpg --list-keys shows # 'gpg: skipped packet of type 12 in keybox' warnings but succeeds? # See #136 echo "$keys_exist" # show whatever _did_ come out of gpg _abort "problem listing public keys with gpg: exit code $exit_code" fi } # note: this has the same 'username matching' issue described in # https://github.com/sobolevn/git-secret/issues/268 # where it will match emails that have other emails as substrings. # we need to use fingerprints for a unique key id with gpg. function _get_user_key_expiry { # This function returns the user's key's expiry, as an epoch. # It will return the empty string # if there is no expiry date for the user's key local username="$1" local line local secrets_dir_keys secrets_dir_keys=$(_get_secrets_dir_keys) # 3>&- closes fd 3 for bats, see https://github.com/bats-core/bats-core#file-descriptor-3-read-this-if-bats-hangs line=$($SECRETS_GPG_COMMAND --homedir "$secrets_dir_keys" --no-permission-warning --list-public-keys --with-colon --fixed-list-mode "$username" | grep ^pub: 3>&-) local expiry_epoch expiry_epoch=$(echo "$line" | cut -d: -f7) echo "$expiry_epoch" } function _assert_keyring_contains_emails { local homedir="$1" local keyring_name="$2" local emails="$3" # 1 here means 'expect $emails in keyring': _assert_keyring_emails "$homedir" "$keyring_name" "$emails" 1 } function _assert_keyring_doesnt_contain_emails { local homedir="$1" local keyring_name="$2" local emails="$3" # 0 here means 'don't expect $emails in keyring': _assert_keyring_emails "$homedir" "$keyring_name" "$emails" 0 } function _assert_keyring_contains_emails_at_least_once { local homedir=$1 local keyring_name=$2 local emails=$3 _assert_keyring_emails "$homedir" "$keyring_name" "$emails" 1 1 # expect the email at least once in the keyring } function _assert_keyring_emails { local homedir="$1" local keyring_name="$2" local emails="$3" # set this to: # 0 to not expect the email in the keyring; # 1 to expect the email in the keyring local expected="$4" local allow_duplicates=$5 # set this to 0 to not allow duplicate emails in the keyring when processing assertion (optional) local gpg_uids gpg_uids=$(_get_users_in_gpg_keyring "$homedir") for email in "${emails[@]}"; do if [[ $email != *"@"* ]]; then _abort "does not appear to be an email: $email" fi local emails_found=0 for uid in $gpg_uids; do if [[ "$uid" == "$email" ]]; then emails_found=$((emails_found+1)) fi done if [[ $expected -eq 1 ]]; then if [[ $emails_found -eq 0 ]]; then _abort "no key found in gpg $keyring_name for: $email" elif [[ $emails_found -gt 1 ]]; then if [[ $allow_duplicates -ne 1 ]]; then _abort "$emails_found keys found in gpg $keyring_name for: $email" fi fi else if [[ $emails_found -gt 0 ]]; then _abort "$emails_found keys found in gpg $keyring_name for: $email" fi fi done } function _get_encrypted_filename { local filename filename="$(dirname "$1")/$(basename "$1" "$SECRETS_EXTENSION")" echo "${filename}${SECRETS_EXTENSION}" | sed -e 's#^\./##' } # this is used throughout this file, and in 'whoknows' function _get_users_in_gpg_keyring { # show the users in the gpg keyring. # `whoknows` command uses it internally. # parses the `gpg` public keys local homedir=$1 local result local args=() if [[ -n "$homedir" ]]; then args+=( "--homedir" "$homedir" ) fi ## We use --fixed-list-mode so older versions of gpg emit 'uid:' lines. ## Gawk splits on colon as --with-colon, matches field 1 as 'uid', result=$($SECRETS_GPG_COMMAND "${args[@]}" --no-permission-warning --list-public-keys --with-colon --fixed-list-mode | \ gawk -F: '$1=="uid"' ) local emails emails=$(_extract_emails_from_gpg_output "$result") # For #508 / #552: warn user if gpg indicates keys are one of: # i=invalid, d=disabled, r=revoked, e=expired, n=not valid # See https://github.com/gpg/gnupg/blob/master/doc/DETAILS#field-2---validity # for more on gpg 'validity codes'. local invalid_lines invalid_lines=$(echo "$result" | gawk -F: '$2=="i" || $2=="d" || $2=="r" || $2=="e" || $2=="n"') local emails_with_invalid_keys emails_with_invalid_keys=$(_extract_emails_from_gpg_output "$invalid_lines") if [[ -n "$emails_with_invalid_keys" ]]; then _warn "at least one key for email(s) is revoked, expired, or otherwise invalid: $emails_with_invalid_keys" fi echo "$emails" } function _extract_emails_from_gpg_output { local result=$1 # gensub() outputs email from <> within field 10, "User-ID". If there's no <>, then field is just an email address # (and maybe a comment) and we pass it through. # Sed at the end removes any 'comment' that appears in parentheses, for #530 # 3>&- closes fd 3 for bats, see https://github.com/bats-core/bats-core#file-descriptor-3-read-this-if-bats-hangs local emails emails=$(echo "$result" | gawk -F: '{print gensub(/.*<(.*)>.*/, "\\1", "g", $10); }' | sed 's/([^)]*)//g' 3>&-) echo "$emails" } function _get_users_in_gitsecret_keyring { # show the users in the gitsecret keyring. local secrets_dir_keys secrets_dir_keys=$(_get_secrets_dir_keys) local result result=$(_get_users_in_gpg_keyring "$secrets_dir_keys") echo "$result" } function _get_recipients { # This function is required to create an encrypted file for different users. # These users are called 'recipients' in the `gpg` terms. # It basically just parses the `gpg` public keys local result # put -r before each user: result=$(_get_users_in_gitsecret_keyring | sed 's/^/-r/') echo "$result" } function _decrypt { # required: local filename="$1" # optional: local write_to_file=${2:-1} # can be 0 or 1 local force=${3:-0} # can be 0 or 1 local homedir=${4:-""} local passphrase=${5:-""} local error_ok=${6:-0} # can be 0 or 1 local encrypted_filename encrypted_filename=$(_get_encrypted_filename "$filename") if [ ! -f "$encrypted_filename" ]; then _warn_or_abort "cannot find file to decrypt: $encrypted_filename" "1" "$error_ok" else local args=( "--use-agent" "--decrypt" ) if [[ "$write_to_file" -eq 1 ]]; then args+=( "-o" "$filename" ) fi if [[ "$force" -eq 1 ]]; then args+=( "--yes" ) fi if [[ -n "$homedir" ]]; then args+=( "--homedir" "$homedir" ) fi if [[ "$GPG_VER_MIN_21" -eq 1 ]]; then if [[ -n "$SECRETS_PINENTRY" ]]; then args+=( "--pinentry-mode" "$SECRETS_PINENTRY" ) else args+=( "--pinentry-mode" "loopback" ) fi fi if [[ -z "$_SECRETS_VERBOSE" ]]; then # we no longer use --no-permission-warning here, for #811 args+=( "--quiet" ) fi set +e # disable 'set -e' so we can capture exit_code #echo "# gpg passphrase: $passphrase" >&3 local exit_code if [[ -n "$passphrase" ]]; then exec 5<<<"$passphrase" # use 5, because descriptors 3 and 4 are used by bats $SECRETS_GPG_COMMAND "${args[@]}" --batch --yes --no-tty --passphrase-fd 5 "$encrypted_filename" exit_code=$? exec 5>&- # close file descriptor 5 else $SECRETS_GPG_COMMAND "${args[@]}" "$encrypted_filename" exit_code=$? fi set -e # re-enable set -e # note that according to https://github.com/sobolevn/git-secret/issues/238 , # it's possible for gpg to return a 0 exit code but not have decrypted the file #echo "# gpg exit code: $exit_code, error_ok: $error_ok" >&3 if [[ "$exit_code" -ne "0" ]]; then local msg="problem decrypting file with gpg: exit code $exit_code: $filename" _warn_or_abort "$msg" "$exit_code" "$error_ok" fi fi # at this point the file should be written to disk or output to stdout } git-secret-0.5.0/src/_utils/_git_secret_tools_freebsd.sh000066400000000000000000000024551424706700600234210ustar00rootroot00000000000000#!/usr/bin/env bash # support for freebsd. Mostly the same as MacOS. # shellcheck disable=SC1117 function __replace_in_file_freebsd { sed -i.bak "s/^\($1[[:space:]]*=[[:space:]]*\).*\$/\1$2/" "$3" } function __temp_file_freebsd { local filename # man mktemp on FreeBSD: # ... # If the -t prefix option is given, mktemp will generate a template string # based on the prefix and the TMPDIR environment variable if set. The # default location if TMPDIR is not set is /tmp. " filename=$(mktemp -t _git_secret ) echo "$filename"; } function __sha256_freebsd { # this is in a different location than MacOS /usr/local/bin/shasum -a256 "$1" } function __get_octal_perms_freebsd { local filename filename=$1 local perms perms=$(stat -f "%04OLp" "$filename") # perms is a string like '0644'. # In the "%04OLp': # the '04' means 4 digits, 0 padded. So we get 0644, not 644. # the 'O' means Octal. # the 'Lp' means 'low subfield of file type and permissions (st_mode).' # (without 'L' you get 6 digits like '100644'.) echo "$perms" } function __epoch_to_date_freebsd { local epoch=$1; if [ -z "$epoch" ]; then echo '' else local cmd="date -I -r $epoch" #echo "# running: $cmd" >&3 local datetime datetime=$($cmd) echo "$datetime" fi } git-secret-0.5.0/src/_utils/_git_secret_tools_linux.sh000066400000000000000000000027761424706700600231540ustar00rootroot00000000000000#!/usr/bin/env bash # shellcheck disable=SC1117 function __replace_in_file_linux { sed -i.bak "s/^\($1\s*=\s*\).*\$/\1$2/" "$3" } function __temp_file_linux { local filename # man mktemp on CentOS 7: # mktemp [OPTION]... [TEMPLATE] # ... # -p DIR, --tmpdir[=DIR] # interpret TEMPLATE relative to DIR; if DIR is not specified, # use $TMPDIR if set, else /tmp. With this option, TEMPLATE # must not be an absolute name; unlike with -t, TEMPLATE may # contain slashes, but mktemp creates only the final component # ... # -t interpret TEMPLATE as a single file name component, # relative to a directory: $TMPDIR, if set; else the directory # specified via -p; else /tmp [deprecated] filename=$(mktemp -p "${TMPDIR}" _git_secret.XXXXXX ) # makes a filename like /$TMPDIR/_git_secret.ONIHo echo "$filename" } function __sha256_linux { sha256sum "$1" } function __get_octal_perms_linux { local filename filename=$1 local stat_is_busybox stat_is_busybox=$(_exe_is_busybox "stat") local perms # a string like '644' if [ "$stat_is_busybox" -eq 1 ]; then # special case for busybox, which doesn't understand --format perms=$(stat -c '%a' "$filename") else perms=$(stat --format '%a' "$filename") fi echo "$perms" } function __epoch_to_date_linux { local epoch=$1; if [ -z "$epoch" ]; then echo '' else local cmd="date +%F -d @$epoch" local datetime datetime=$($cmd) echo "$datetime" fi } git-secret-0.5.0/src/_utils/_git_secret_tools_osx.sh000066400000000000000000000023511424706700600226130ustar00rootroot00000000000000#!/usr/bin/env bash # shellcheck disable=SC1117 function __replace_in_file_osx { sed -i.bak "s/^\($1[[:space:]]*=[[:space:]]*\).*\$/\1$2/" "$3" } function __temp_file_osx { local filename # man mktemp on OSX: # ... # "If the -t prefix option is given, mktemp will generate a template string # based on the prefix and the _CS_DARWIN_USER_TEMP_DIR configuration vari- # able if available. Fallback locations if _CS_DARWIN_USER_TEMP_DIR is not # available are TMPDIR and /tmp." # we use /usr/bin/mktemp in case there's another mktemp available. See #485 filename=$(/usr/bin/mktemp -t _git_secret ) # On OSX this can make a filename like # '/var/folders/nz/vv4_91234569k3tkvyszvwg90009gn/T/_git_secret.HhvUPlUI' echo "$filename"; } function __sha256_osx { /usr/bin/shasum -a256 "$1" } function __get_octal_perms_osx { local filename filename=$1 local perms perms=$(stat -f "%04OLp" "$filename") # see _git_secret_tools_freebsd.sh for more about stat's format string echo "$perms" } function __epoch_to_date_osx { local epoch=$1; if [ -z "$epoch" ]; then echo '' else #date -r 234234234 +"%Y-%m-%d" local datetime datetime=$(date -r "$epoch" +'%Y-%m-%d') echo "$datetime" fi } git-secret-0.5.0/src/commands/000077500000000000000000000000001424706700600161605ustar00rootroot00000000000000git-secret-0.5.0/src/commands/git_secret_add.sh000066400000000000000000000042441424706700600214600ustar00rootroot00000000000000#!/usr/bin/env bash function add { OPTIND=1 while getopts "ihv" opt; do case "$opt" in i) ;; # this doesn't change anything h) _show_manual_for "add";; v) _SECRETS_VERBOSE=1;; *) _invalid_option_for "add";; esac done shift $((OPTIND-1)) [ "$1" = "--" ] && shift _user_required # Checking if all files are correct (ignored and inside the repo): local not_ignored=() local items=( "$@" ) # Checking if all files in options are ignored: for item in "${items[@]}"; do local path # absolute path local normalized_path # relative to the .git dir normalized_path=$(_git_normalize_filename "$item") path=$(_prepend_root_path "$normalized_path") # check that the file is not tracked local in_git in_git=$(_is_tracked_in_git "$item") if [[ "$in_git" -ne 0 ]]; then _abort "file tracked in git, consider using 'git rm --cached $item'" fi # Checking that file is valid: if [[ ! -f "$path" ]]; then _abort "file not found: $item" fi # Checking that it is ignored: local ignored ignored=$(_check_ignore "$path") if [[ "$ignored" -ne 0 ]]; then # Collect unignored files: not_ignored+=("$normalized_path") fi done # Are there any unignored files? if [[ ! "${#not_ignored[@]}" -eq 0 ]]; then # Add these files to `.gitignore` automatically: # see https://github.com/sobolevn/git-secret/issues/18 for more. for item in "${not_ignored[@]}"; do _message "file not in .gitignore, adding: $item" _add_ignored_file "$item" done fi # Adding files to path mappings: local fsdb fsdb=$(_get_secrets_dir_paths_mapping) local count count=0 for item in "${items[@]}"; do local path local key path=$(_git_normalize_filename "$item") key="$path" # Adding files into system, skipping duplicates. local already_in already_in=$(_fsdb_has_record "$key" "$fsdb") if [[ "$already_in" -eq 1 ]]; then echo "$key" >> "$fsdb" if [[ -n "$_SECRETS_VERBOSE" ]]; then _message "adding file: $key" fi ((count=count+1)) fi done _message "$count item(s) added." } git-secret-0.5.0/src/commands/git_secret_cat.sh000066400000000000000000000013601424706700600214730ustar00rootroot00000000000000#!/usr/bin/env bash function cat { local homedir='' local passphrase='' OPTIND=1 while getopts 'hd:p:' opt; do case "$opt" in h) _show_manual_for 'cat';; p) passphrase=$OPTARG;; d) homedir=$(_clean_windows_path "$OPTARG");; *) _invalid_option_for 'cat';; esac done shift $((OPTIND-1)) [ "$1" = '--' ] && shift _user_required # Command logic: for line in "$@" do local filename local path filename=$(_get_record_filename "$line") path=$(_prepend_relative_root_path "$filename") # this uses the _relative version because of #710 # The parameters are: filename, write-to-file, force, homedir, passphrase _decrypt "$path" "0" "0" "$homedir" "$passphrase" done } git-secret-0.5.0/src/commands/git_secret_changes.sh000066400000000000000000000036151424706700600223410ustar00rootroot00000000000000#!/usr/bin/env bash function changes { local passphrase="" OPTIND=1 while getopts 'hd:p:' opt; do case "$opt" in h) _show_manual_for 'changes';; p) passphrase=$OPTARG;; d) homedir=$(_clean_windows_path "$OPTARG");; *) _invalid_option_for 'changes';; esac done shift $((OPTIND-1)) [ "$1" = '--' ] && shift _user_required filenames=("$@") # list of positional parameters. global. if [[ ${#filenames[@]} -eq 0 ]]; then # Checking if no filenames are passed, show diff for all files. _list_all_added_files # this sets the array variable 'filenames' fi IFS=' ' for filename in "${filenames[@]}"; do local path # absolute path local normalized_path # relative to the .git dir local encrypted_filename normalized_path=$(_git_normalize_filename "$filename") encrypted_filename=$(_get_encrypted_filename "$filename") if [[ ! -f "$encrypted_filename" ]]; then _abort "cannot find encrypted version of file: $filename" fi if [[ -n "$normalized_path" ]]; then path=$(_prepend_root_path "$normalized_path") else # Path was already normalized path=$(_prepend_root_path "$filename") fi if [[ ! -f "$path" ]]; then _abort "file not found. Consider using 'git secret reveal': $filename" fi # Now we have all the data required to do the last encryption and compare results: # now do a two-step to protect trailing newlines from the $() construct. local decrypted_x local decrypted decrypted_x=$(_decrypt "$path" "0" "0" "$homedir" "$passphrase"; echo x$?) decrypted="${decrypted_x%x*}" # we ignore the exit code because _decrypt will abort_ if appropriate. _message "changes in ${path}:" # diff the result: # we have the '|| true' because `diff` returns error code if files differ. diff -u <(echo -n "$decrypted") "$path" || true done } git-secret-0.5.0/src/commands/git_secret_clean.sh000066400000000000000000000006701424706700600220110ustar00rootroot00000000000000#!/usr/bin/env bash function clean { OPTIND=1 # shellcheck disable=SC2034 while getopts 'vh' opt; do case "$opt" in v) _SECRETS_VERBOSE=1;; h) _show_manual_for 'clean';; *) _invalid_option_for 'clean';; esac done shift $((OPTIND-1)) [ "$1" = '--' ] && shift if [ $# -ne 0 ]; then _abort "clean does not understand params: $*" fi _user_required _find_and_remove_secrets_formatted } git-secret-0.5.0/src/commands/git_secret_hide.sh000066400000000000000000000131611424706700600216370ustar00rootroot00000000000000#!/usr/bin/env bash # shellcheck disable=SC2016 AWK_FSDB_UPDATE_HASH=' BEGIN { FS=":"; OFS=":"; } { if ( key == $1 ) { print key,hash; } else { print $1,$2; } } ' function _optional_delete { local delete="$1" if [[ $delete -eq 1 ]]; then local path_mappings path_mappings=$(_get_secrets_dir_paths_mapping) # We use custom formatting here: if [[ -n "$_SECRETS_VERBOSE" ]]; then _message 'removing unencrypted files' fi while read -r line; do # each line is a record like: filename: or filename:hash local filename filename=$(_get_record_filename "$line") if [[ -e "$filename" ]]; then rm "$filename" if [[ -n "$_SECRETS_VERBOSE" ]]; then _message "deleted: $filename" fi fi done < "$path_mappings" fi } function _get_checksum_local { local checksum="$SECRETS_CHECKSUM_COMMAND" echo "$checksum" } function _get_file_hash { local input_path="$1" # Required local checksum_local local file_hash checksum_local="$(_get_checksum_local)" file_hash=$($checksum_local "$input_path" | gawk '{print $1}') echo "$file_hash" } function _fsdb_update_hash { local key="$1" local hash="$2" local fsdb # path_mappings fsdb=$(_get_secrets_dir_paths_mapping) _gawk_inplace -v key="'$key'" -v hash="$hash" "'$AWK_FSDB_UPDATE_HASH'" "$fsdb" } function hide { local clean=0 local preserve=0 local delete=0 local update_only_modified=0 local force_continue=0 OPTIND=1 while getopts 'cFPdmvh' opt; do case "$opt" in c) clean=1;; F) force_continue=1;; P) preserve=1;; d) delete=1;; m) update_only_modified=1;; v) _SECRETS_VERBOSE=1;; h) _show_manual_for 'hide';; *) _invalid_option_for 'hide';; esac done shift $((OPTIND-1)) [ "$1" = '--' ] && shift if [ $# -ne 0 ]; then _abort "hide does not understand params: $*" fi # We need user to continue: _user_required # If -c option was provided, clean the hidden files # before creating new ones. if [[ $clean -eq 1 ]]; then _find_and_remove_secrets_formatted fi # Encrypting files: local path_mappings path_mappings=$(_get_secrets_dir_paths_mapping) local num_mappings num_mappings=$(gawk 'END{print NR}' "$path_mappings") # make sure all the unencrypted files needed are present local to_hide=() while read -r record; do to_hide+=("$record") # add record to array done < "$path_mappings" local recipients recipients=$(_get_recipients) local secrets_dir_keys secrets_dir_keys=$(_get_secrets_dir_keys) local counter=0 for record in "${to_hide[@]}"; do local filename local fsdb_file_hash local encrypted_filename filename=$(_get_record_filename "$record") fsdb_file_hash=$(_get_record_hash "$record") encrypted_filename=$(_get_encrypted_filename "$filename") local input_path local output_path input_path=$(_prepend_root_path "$filename") output_path=$(_prepend_root_path "$encrypted_filename") # Checking that file is valid: if [[ ! -f "$input_path" ]]; then # this catches the case where some decrypted files don't exist _warn_or_abort "file not found: $input_path" "1" "$force_continue" else file_hash=$(_get_file_hash "$input_path") # encrypt file only if required if [[ "$update_only_modified" -eq 0 ]] || [[ "$fsdb_file_hash" != "$file_hash" ]]; then local args=( --homedir "$secrets_dir_keys" --use-agent --yes '--trust-model=always' --encrypt ) # SECRETS_GPG_ARMOR is expected to be empty or '1'. # Empty means 'off', any other value means 'on'. # See: https://github.com/sobolevn/git-secret/pull/661 # shellcheck disable=SC2153 if [[ -n "$SECRETS_GPG_ARMOR" ]] && [[ "$SECRETS_GPG_ARMOR" -ne 0 ]]; then args+=( '--armor' ) fi # we no longer use --no-permission-warning here in non-verbose mode, for #811 # we depend on $recipients being split on whitespace # shellcheck disable=SC2206 args+=( $recipients -o "$output_path" "$input_path" ) set +e # disable 'set -e' so we can capture exit_code # For info about `3>&-` see: # https://github.com/bats-core/bats-core#file-descriptor-3-read-this-if-bats-hangs local gpg_output gpg_output=$($SECRETS_GPG_COMMAND "${args[@]}" 3>&-) # we leave stderr alone local exit_code=$? set -e # re-enable set -e local error=0 if [[ "$exit_code" -ne 0 ]] || [[ ! -f "$output_path" ]]; then error=1 fi if [[ "$error" -ne 0 ]] || [[ -n "$_SECRETS_VERBOSE" ]]; then if [[ -n "$gpg_output" ]]; then echo "$gpg_output" fi fi if [[ ! -f "$output_path" ]]; then # if gpg can't encrypt a file we asked it to, that's an error unless in force_continue mode. _warn_or_abort "problem encrypting file with gpg: exit code $exit_code: $filename" "$exit_code" "$force_continue" else counter=$((counter+1)) if [[ "$preserve" == 1 ]]; then local perms perms=$($SECRETS_OCTAL_PERMS_COMMAND "$input_path") chmod "$perms" "$output_path" fi fi # Update file hash for future use of -m local key="$filename" local hash="$file_hash" _fsdb_update_hash "$key" "$hash" fi fi done # If -d option was provided, it would delete the source files # after we have already hidden them. _optional_delete "$delete" _message "done. $counter of $num_mappings files are hidden." } git-secret-0.5.0/src/commands/git_secret_init.sh000066400000000000000000000032741424706700600216750ustar00rootroot00000000000000#!/usr/bin/env bash # shellcheck disable=SC2016 AWK_ADD_TO_GITIGNORE=' BEGIN { cnt=0 } function check_print_line(line){ if (line == pattern) { cnt++ } print line } # main function { check_print_line($0) # check and print first line while (getline == 1) { # check and print all other check_print_line($0) } } END { if ( cnt == 0) { # if file did not contain pattern add print pattern } } ' function gitignore_add_pattern { local pattern local gitignore_file_path pattern="$1" gitignore_file_path=$(_prepend_root_path '.gitignore') _maybe_create_gitignore _gawk_inplace -v pattern="$pattern" "'$AWK_ADD_TO_GITIGNORE'" "$gitignore_file_path" } function init { OPTIND=1 while getopts 'h' opt; do case "$opt" in h) _show_manual_for 'init';; *) _invalid_option_for 'init';; esac done shift $((OPTIND-1)) [ "$1" = '--' ] && shift if [ $# -ne 0 ]; then _abort "init does not understand params: $*" fi # Check if '.gitsecret/' already exists: local git_secret_dir git_secret_dir=$(_get_secrets_dir) if [[ -d "$git_secret_dir" ]]; then _abort 'already initialized.' fi # Check if it is ignored: _secrets_dir_is_not_ignored # Create internal files: mkdir "$git_secret_dir" "$(_get_secrets_dir_keys)" "$(_get_secrets_dir_path)" chmod 700 "$(_get_secrets_dir_keys)" # for #811, set to rwx------ touch "$(_get_secrets_dir_paths_mapping)" _message "init created: '$git_secret_dir/'" local random_seed_file random_seed_file="${_SECRETS_DIR}/keys/random_seed" gitignore_add_pattern "$random_seed_file" gitignore_add_pattern "!*$SECRETS_EXTENSION" # TODO: git attributes to view diffs } git-secret-0.5.0/src/commands/git_secret_list.sh000066400000000000000000000010401424706700600216720ustar00rootroot00000000000000#!/usr/bin/env bash function list { OPTIND=1 while getopts 'h' opt; do case "$opt" in h) _show_manual_for 'list';; *) _invalid_option_for 'list';; esac done shift $((OPTIND-1)) [ "$1" = '--' ] && shift if [ $# -ne 0 ]; then _abort "list does not understand params: $*" fi _user_required # Command logic: filenames=() _list_all_added_files # exports 'filenames' array local filename for filename in "${filenames[@]}"; do echo "$filename" # do not prepend 'git-secret: ' done } git-secret-0.5.0/src/commands/git_secret_remove.sh000066400000000000000000000026141424706700600222240ustar00rootroot00000000000000#!/usr/bin/env bash function remove { local clean=0 OPTIND=1 while getopts 'ch' opt; do case "$opt" in c) clean=1;; h) _show_manual_for 'remove';; *) _invalid_option_for 'remove';; esac done shift $((OPTIND-1)) [ "$1" = '--' ] && shift # Validate if user exists: _user_required # Command logic: local path_mappings path_mappings=$(_get_secrets_dir_paths_mapping) for item in "$@"; do local path # absolute path local normalized_path # relative to .git folder normalized_path=$(_git_normalize_filename "$item") path=$(_prepend_root_path "$normalized_path") # Checking if file exists: if [[ ! -f "$path" ]]; then _abort "file not found: $item" fi # Deleting it from path mappings: # Remove record from fsdb with matching key local key key="$normalized_path" fsdb="$path_mappings" _fsdb_rm_record "$key" "$fsdb" rm -f "${path_mappings}.bak" # not all systems create '.bak' # Optional clean: if [[ "$clean" -eq 1 ]]; then local encrypted_filename encrypted_filename=$(_get_encrypted_filename "$path") rm "$encrypted_filename" # fail on error if [[ -n "$_SECRETS_VERBOSE" ]]; then _message "deleted: $encrypted_filename" fi fi done echo 'git-secret: removed from index.' echo "git-secret: ensure that files: [$*] are now not ignored." } git-secret-0.5.0/src/commands/git_secret_removeperson.sh000066400000000000000000000027751424706700600234630ustar00rootroot00000000000000#!/usr/bin/env bash function removeperson { OPTIND=1 while getopts 'h' opt; do case "$opt" in h) _show_manual_for 'removeperson';; *) _invalid_option_for 'removeperson';; esac done shift $((OPTIND-1)) [ "$1" = "--" ] && shift _user_required # Command logic: local emails=( "$@" ) if [[ ${#emails[@]} -eq 0 ]]; then _abort "at least one email is required for removeperson." fi # Getting the local git-secret `gpg` key directory: local secrets_dir_keys secrets_dir_keys=$(_get_secrets_dir_keys) _assert_keyring_contains_emails_at_least_once "$secrets_dir_keys" "git-secret keyring" "${emails[@]}" local args=( --homedir "$secrets_dir_keys" --batch --yes ) # we no longer use --no-permission-warning here in non-verbose mode, for #811 for email in "${emails[@]}"; do # see https://github.com/bats-core/bats-core#file-descriptor-3-read-this-if-bats-hangs for info about 3>&- $SECRETS_GPG_COMMAND "${args[@]}" --delete-key "$email" 3>&- local exit_code=$? if [[ "$exit_code" -ne 0 ]]; then _abort "problem deleting key for '$email' with gpg: exit code $exit_code" fi done _message 'removed keys.' _message "now [$*] do not have an access to the repository." _message 'make sure to hide the existing secrets again.' } function killperson { echo "Warning: 'killperson' has been renamed to 'removeperson'. This alias will be removed in the future versions, please switch to call 'removeperson' going forward." removeperson "$@" } git-secret-0.5.0/src/commands/git_secret_reveal.sh000066400000000000000000000040021424706700600221760ustar00rootroot00000000000000#!/usr/bin/env bash function reveal { local homedir='' local passphrase='' local force=0 # this means 'clobber without warning' local force_continue=0 # this means 'continue if we have decryption errors' local preserve=0 OPTIND=1 while getopts 'hfFPd:p:v' opt; do # line below is for _SECRETS_VERBOSE # shellcheck disable=SC2034 case "$opt" in h) _show_manual_for 'reveal';; f) force=1;; F) force_continue=1;; P) preserve=1;; p) passphrase=$OPTARG;; d) homedir=$(_clean_windows_path "$OPTARG");; v) _SECRETS_VERBOSE=1;; *) _invalid_option_for 'reveal';; esac done shift $((OPTIND-1)) [ "$1" = '--' ] && shift _user_required # Command logic: local path_mappings path_mappings=$(_get_secrets_dir_paths_mapping) local counter=0 local to_show=( "$@" ) if [ ${#to_show[@]} -eq 0 ]; then while read -r record; do to_show+=("$record") # add record to array done < "$path_mappings" fi for line in "${to_show[@]}"; do local filename local path filename=$(_get_record_filename "$line") path=$(_prepend_relative_root_path "$filename") # this uses the _relative version because of #710 if [[ "$filename" == *"$SECRETS_EXTENSION" ]]; then _abort "cannot decrypt to secret version of file: $filename" fi # The parameters are: filename, write-to-file, force, homedir, passphrase, error_ok _decrypt "$path" "1" "$force" "$homedir" "$passphrase" "$force_continue" if [[ ! -f "$path" ]]; then _warn_or_abort "cannot find decrypted version of file: $filename" "2" "$force_continue" else counter=$((counter+1)) local secret_file secret_file=$(_get_encrypted_filename "$path") if [[ "$preserve" == 1 ]] && [[ -f "$secret_file" ]]; then local perms perms=$($SECRETS_OCTAL_PERMS_COMMAND "$secret_file") chmod "$perms" "$path" fi fi done _message "done. $counter of ${#to_show[@]} files are revealed." } git-secret-0.5.0/src/commands/git_secret_tell.sh000066400000000000000000000072511424706700600216710ustar00rootroot00000000000000#!/usr/bin/env bash # shellcheck disable=SC2016 AWK_GPG_KEY_CNT=' BEGIN { cnt=0; OFS=":"; FS=":"; } flag=0; $1 == "pub" { cnt++ } END { print cnt } ' function get_gpg_key_count { local secrets_dir_keys secrets_dir_keys=$(_get_secrets_dir_keys) # 3>&- closes fd 3 for bats, see https://github.com/bats-core/bats-core#file-descriptor-3-read-this-if-bats-hangs $SECRETS_GPG_COMMAND --homedir "$secrets_dir_keys" --no-permission-warning --list-public-keys --with-colon | gawk "$AWK_GPG_KEY_CNT" 3>&- local exit_code=$? if [[ "$exit_code" -ne 0 ]]; then _abort "problem counting keys with gpg: exit code $exit_code" fi } function tell { local emails local self_email=0 local homedir # A POSIX variable # Reset in case getopts has been used previously in the shell. OPTIND=1 while getopts "vhmd:" opt; do case "$opt" in v) _SECRETS_VERBOSE=1;; h) _show_manual_for "tell";; m) self_email=1;; d) homedir=$(_clean_windows_path "$OPTARG");; *) _invalid_option_for 'tell';; esac done shift $((OPTIND-1)) [ "$1" = "--" ] && shift # Validates that application is initialized: _secrets_dir_exists # Command logic: emails=( "$@" ) local git_email if [[ "$self_email" -eq 1 ]]; then git_email=$(git config user.email) if [[ -z "$git_email" ]]; then _abort "'git config user.email' is not set." fi emails+=("$git_email") fi if [[ "${#emails[@]}" -eq 0 ]]; then # If after possible addition of git_email, emails are still empty, # we should raise an exception. _abort "you must use -m or provide at least one email address." fi local secrets_dir_keys secrets_dir_keys=$(_get_secrets_dir_keys) _assert_keyring_contains_emails "$homedir" "user keyring" "${emails[@]}" _assert_keyring_doesnt_contain_emails "$secrets_dir_keys" "git-secret keyring" "${emails[@]}" local start_key_cnt start_key_cnt=$(get_gpg_key_count) for email in "${emails[@]}"; do _temporary_file # note that `_temporary_file` will export `temporary_filename` var. # shellcheck disable=SC2154 local keyfile="$temporary_filename" # 3>&- closes fd 3 for bats, see https://github.com/bats-core/bats-core#file-descriptor-3-read-this-if-bats-hangs local exit_code if [[ -z "$homedir" ]]; then $SECRETS_GPG_COMMAND --export -a "$email" > "$keyfile" 3>&- exit_code=$? else # This means that homedir is set as an extra argument via `-d`: # we no longer use --no-permission-warning here, for #811 $SECRETS_GPG_COMMAND --homedir="$homedir" \ --export -a "$email" > "$keyfile" 3>&- exit_code=$? fi if [[ "$exit_code" -ne 0 ]]; then _abort "problem exporting public key for '$email' with gpg: exit code $exit_code" fi if [[ ! -s "$keyfile" ]]; then _abort "no keyfile found for '$email'. Check your key name: 'gpg --list-keys'." fi # Importing public key to the local keyring: local args=( --homedir "$secrets_dir_keys" --import "$keyfile" ) if [[ -z "$_SECRETS_VERBOSE" ]]; then $SECRETS_GPG_COMMAND "${args[@]}" > /dev/null 2>&1 3>&- else $SECRETS_GPG_COMMAND "${args[@]}" 3>&- fi exit_code=$? rm -f "$keyfile" || _abort "error removing temporary keyfile: $keyfile" if [[ "$exit_code" -ne 0 ]]; then _abort "problem importing public key for '$email' with gpg: exit code $exit_code" fi done _message "done. ${emails[*]} added as user(s) who know the secret." # force re-encrypting of files if required local fsdb local end_key_cnt fsdb=$(_get_secrets_dir_paths_mapping) end_key_cnt=$(get_gpg_key_count) [[ $start_key_cnt -ne $end_key_cnt ]] && _fsdb_clear_hashes "$fsdb" } git-secret-0.5.0/src/commands/git_secret_usage.sh000066400000000000000000000027411424706700600220340ustar00rootroot00000000000000#!/usr/bin/env bash function usage { OPTIND=1 while getopts "h?" opt; do case "$opt" in h) _show_manual_for "usage";; *) _invalid_option_for "usage";; esac done shift $((OPTIND-1)) [ "$1" = "--" ] && shift echo "usage: git secret [--version] [command] [command-options]" echo "" echo "options:" echo " --version - prints the version number" echo "" echo "commands:" echo "see 'git secret [command] -h' for more info about commands and their options" echo " add [file.txt] - adds file to be hidden to the list" echo " cat [file.txt] - decrypts and prints contents of the file" echo " changes [file.txt.secret] - indicates if the file changed since last commit" echo " clean - deletes all encrypted files" echo " hide - encrypts (or re-encrypts) the files to be hidden" echo " init - initializes the git-secret repository" echo " removeperson [emails] - deletes a person's public key from the keyring" echo " list - prints all the added files" echo " remove [files] - removes files from the list of hidden files" echo " reveal - decrypts all hidden files" echo " tell [email] - imports a person's public key into the keyring" echo " usage - prints this message" echo " whoknows - prints list of authorized email addresses" } git-secret-0.5.0/src/commands/git_secret_whoknows.sh000066400000000000000000000017401424706700600226050ustar00rootroot00000000000000#!/usr/bin/env bash function whoknows { OPTIND=1 local long_display=0 while getopts "hl?" opt; do case "$opt" in h) _show_manual_for "whoknows";; l) long_display=1;; # like ls -l *) _invalid_option_for "whoknows";; esac done shift $((OPTIND-1)) [ "$1" = "--" ] && shift if [ $# -ne 0 ]; then _abort "whoknows does not understand params: $*" fi # Validating, that we have a user: _user_required local users # Getting the users from gpg: users=$(_get_users_in_gitsecret_keyring) for user in $users; do echo -n "$user" if [[ "$long_display" -eq 1 ]]; then local expiration expiration=$(_get_user_key_expiry "$user") if [[ -n "$expiration" ]]; then local expiration_date expiration_date=$($SECRETS_EPOCH_TO_DATE "$expiration") echo -n " (expires: $expiration_date)" else echo -n " (expires: never)" fi fi echo done } git-secret-0.5.0/src/main.sh000077500000000000000000000033611424706700600156450ustar00rootroot00000000000000#!/usr/bin/env bash set -e function _check_setup { # Checking git and secret-plugin setup: local is_tree is_tree=$(_is_inside_git_tree) if [[ "$is_tree" -ne 0 ]]; then _abort "not in dir with git repo. Use 'git init' or 'git clone', then in repo use 'git secret init'" fi # Checking if the '.gitsecret' dir (or as set by SECRETS_DIR) is not ignored: _secrets_dir_is_not_ignored # Checking gpg setup: local keys_dir keys_dir=$(_get_secrets_dir_keys) local secring="$keys_dir/secring.gpg" if [[ -f $secring ]] && [[ -s $secring ]]; then # secring.gpg exists and is not empty, # someone has imported a private key. _abort 'it seems that someone has imported a secret key.' fi } function _incorrect_usage { local message="$1" local exitcode="$2" shift 2 echo "git-secret: abort: ${message}" usage "$@" exit "${exitcode}" } function _show_version { echo "$GITSECRET_VERSION" exit 0 } function _init_script { if [[ $# == 0 ]]; then _incorrect_usage 'no input parameters provided.' 126 "$@" fi # Parse plugin-level options: local dry_run=0 while [[ $# -gt 0 ]]; do local opt="$1" case "$opt" in # Options for quick-exit strategy: --dry-run) dry_run=1 shift;; --version) _show_version;; *) break;; # do nothing esac done if [[ "$dry_run" == 0 ]]; then # Checking for proper set-up: _check_setup # Routing the input command: local function_exists function_exists=$(_function_exists "$1") if [[ "$function_exists" == 0 ]] && [[ ! $1 == _* ]]; then $1 "${@:2}" else # TODO: elif [[ $(_plugin_exists $1) == 0 ]]; then _incorrect_usage "command $1 not found." 126 "$@" fi fi } _init_script "$@" git-secret-0.5.0/src/version.sh000066400000000000000000000001131424706700600163730ustar00rootroot00000000000000#!/usr/bin/env bash # shellcheck disable=SC2034 GITSECRET_VERSION='0.5.0' git-secret-0.5.0/tests/000077500000000000000000000000001424706700600147325ustar00rootroot00000000000000git-secret-0.5.0/tests/_test_base.bash000066400000000000000000000240461424706700600177070ustar00rootroot00000000000000#!/usr/bin/env bash # This file is following a name convention defined in: # https://github.com/bats-core/bats-core # shellcheck disable=SC1090 source "$SECRETS_PROJECT_ROOT/src/version.sh" # shellcheck disable=SC1090 source "$SECRETS_PROJECT_ROOT/src/_utils/_git_secret_tools.sh" source "$SECRETS_PROJECT_ROOT/src/_utils/_git_secret_tools_freebsd.sh" source "$SECRETS_PROJECT_ROOT/src/_utils/_git_secret_tools_linux.sh" source "$SECRETS_PROJECT_ROOT/src/_utils/_git_secret_tools_osx.sh" # Constants: FIXTURES_DIR="$BATS_TEST_DIRNAME/fixtures" TEST_GPG_HOMEDIR="$BATS_TMPDIR" # TODO: factor out tempdir creation. # On osx TEST_OUTPUT_FILE, still has 'XXXXXX's, like # /var/folders/mm/_f0j67x10l92b4zznyx4ylzh00017w/T/gitsecret_output.XXXXXX.RaqyGYqL TEST_OUTPUT_FILE=$( TMPDIR="$BATS_TMPDIR" mktemp -t 'gitsecret_output.XXXXXX' ) # shellcheck disable=SC2016 AWK_GPG_GET_FP=' BEGIN { OFS=":"; FS=":"; } { if ( $1 == "fpr" ) { print $10 exit } } ' # git >= 2.28.0 supports --initial-branch=main function is_git_version_ge_2_28_0 { # based on code from github autopilot # shellcheck disable=SC2155 local git_version=$(git --version | awk '{print $3}') # shellcheck disable=SC2155 local git_version_major=$(echo "$git_version" | awk -F. '{print $1}') # shellcheck disable=SC2155 local git_version_minor=$(echo "$git_version" | awk -F. '{print $2}') # shellcheck disable=SC2155 local git_version_patch=$(echo "$git_version" | awk -F. '{print $3}') if [[ "$git_version_major" -ge 2 ]] && [[ "$git_version_minor" -ge 28 ]] && [[ "$git_version_patch" -ge 0 ]]; then echo 0 else echo 1 fi } # GPG-based stuff: : "${SECRETS_GPG_COMMAND:='gpg'}" # This command is used with absolute homedir set and disabled warnings: GPGTEST="$SECRETS_GPG_COMMAND --homedir=$TEST_GPG_HOMEDIR --no-permission-warning --batch" # Test key fixture data. Fixtures are at tests/fixtures/gpg/$email # See tests/fixtures/gpg/README.md for more # on key fixtures 'user[1-5]@gitsecret.io' # these two are 'normal' keys. export TEST_DEFAULT_USER='user1@gitsecret.io' export TEST_SECOND_USER='user2@gitsecret.io' # TEST_NONAME_USER (user3) created with '--quick-key-generate' # and has only an email, no username. export TEST_NONAME_USER='user3@gitsecret.io' # TEST_EXPIRED_USER (user4) has expired export TEST_EXPIRED_USER='user4@gitsecret.io' # this key expires 2018-09-24 # fixture filename is named this, # but key has no email and a comment, as per #527 export TEST_NOEMAIL_COMMENT_USER='user5@gitsecret.io' export TEST_ATTACKER_USER='attacker1@gitsecret.io' export TEST_DEFAULT_FILENAME='space file' # has spaces export TEST_SECOND_FILENAME='space file two' # has spaces export TEST_THIRD_FILENAME='space file three' # has spaces export TEST_FOURTH_FILENAME='space file three [] * $' # has spaces and special chars function test_user_password { # Password for 'user3@gitsecret.io' is 'user3pass' # As it was set on key creation. # shellcheck disable=SC2001 echo "$1" | sed -e 's/@.*/pass/' } # Files: function file_has_line { # First parameter is the key, second is the filename. local line="$1" # required local filename="$2" # required local exit_code # -F means 'Interpret PATTERN as a list of fixed strings' (not regexen) # -x means 'Select only those matches that exactly match the whole line' exit_code=$(grep -Fx "$line" "$filename" 2>&1 > /dev/null; echo $?) # 0 means contains, 1 means not contains, and probably >1 for errors. echo "$exit_code" } # GPG: function stop_gpg_agent { local username username=$(id -u -n) if [[ "$SECRETS_DOCKER_ENV" == 'windows' ]]; then ps -l -u "$username" | gawk \ '/gpg-agent/ { if ( $0 !~ "awk" ) { system("kill "$1) } }' >> "$TEST_OUTPUT_FILE" 2>&1 else local ps_is_busybox ps_is_busybox=_exe_is_busybox 'ps' if [[ $ps_is_busybox -eq '1' ]]; then echo '# git-secret: tests: not stopping gpg-agent on busybox' >&3 else ps -wx -U "$username" | gawk \ '/gpg-agent --homedir/ { if ( $0 !~ "awk" ) { system("kill "$1) } }' >> "$TEST_OUTPUT_FILE" 2>&1 fi fi } function get_gpgtest_prefix { if [[ $GPG_VER_21 -eq 1 ]]; then # shellcheck disable=SC2086 echo "echo \"$(test_user_password $1)\" | " else echo '' fi } function get_gpg_fingerprint_by_email { local email="$1" local fingerprint fingerprint=$($GPGTEST --with-fingerprint \ --with-colon \ --list-secret-key "$email" | gawk "$AWK_GPG_GET_FP") echo "$fingerprint" } function install_fixture_key { local public_key="$BATS_TMPDIR/public-${1}.key" cp "$FIXTURES_DIR/gpg/${1}/public.key" "$public_key" $GPGTEST --import "$public_key" >> "$TEST_OUTPUT_FILE" 2>&1 rm -f "$public_key" || _abort "Couldn't delete public key: $public_key" } function install_fixture_full_key { local private_key="$BATS_TMPDIR/private-${1}.key" local gpgtest_prefix gpgtest_prefix=$(get_gpgtest_prefix "$1") local gpgtest_import="$gpgtest_prefix $GPGTEST" local email local fingerprint email="$1" cp "$FIXTURES_DIR/gpg/${1}/private.key" "$private_key" bash -c "$gpgtest_import --allow-secret-key-import \ --import \"$private_key\"" >> "${TEST_OUTPUT_FILE}" 2>&1 # since 0.1.2 fingerprint is returned: fingerprint=$(get_gpg_fingerprint_by_email "$email") install_fixture_key "$1" rm -f "$private_key" || _abort "Couldn't delete private key: $private_key" # return fingerprint to delete it later: echo "$fingerprint" } function uninstall_fixture_key { local email email="$1" $GPGTEST --yes --delete-key "$email" >> "$TEST_OUTPUT_FILE" 2>&1 } function uninstall_fixture_full_key { local email email="$1" local fingerprint="$2" if [[ -z "$fingerprint" ]]; then # see issue_12, fingerprint on `gpg2` has different format: fingerprint=$(get_gpg_fingerprint_by_email "$email") fi $GPGTEST --yes --delete-secret-keys "$fingerprint" >> "$TEST_OUTPUT_FILE" 2>&1 uninstall_fixture_key "$1" } # Git: function git_set_config_email { git config --local user.email "$1" } function git_commit { git_set_config_email "$1" local user_name local commit_gpgsign user_name=$(git config user.name) commit_gpgsign=$(git config commit.gpgsign) git config --local user.name "$TEST_DEFAULT_USER" git config --local commit.gpgsign false git add --all git commit -m "$2" git config --local user.name "$user_name" git config --local commit.gpgsign "$commit_gpgsign" } function remove_git_repository { rm -rf ".git" } # Git Secret: function set_state_initial { cd "$BATS_TMPDIR" || exit 1 rm -rf "${BATS_TMPDIR:?}/*" } function set_state_git { local has_initial_branch_option has_initial_branch_option=$(is_git_version_ge_2_28_0) # 0 for true if [[ "$has_initial_branch_option" == 0 ]]; then git init --initial-branch=main | sed 's/^/git: /' >> "$TEST_OUTPUT_FILE" 2>&1 else git init | sed 's/^/git: /' >> "$TEST_OUTPUT_FILE" 2>&1 fi } function set_state_secret_init { git secret init >> "$TEST_OUTPUT_FILE" 2>&1 } function set_state_secret_tell { local email email="$1" git secret tell -d "$TEST_GPG_HOMEDIR" "$email" >> "$TEST_OUTPUT_FILE" 2>&1 } function set_state_secret_add { local filename="$1" local content="$2" echo "$content" > "$filename" # we add a newline git secret add "$filename" >> "$TEST_OUTPUT_FILE" 2>&1 } function set_state_secret_add_without_newline { local filename="$1" local content="$2" echo -n "$content" > "$filename" # we do not add a newline git secret add "$filename" >> "$TEST_OUTPUT_FILE" 2>&1 } function set_state_secret_hide { local armor="$1" SECRETS_GPG_ARMOR="$armor" git secret hide >> "$TEST_OUTPUT_FILE" 2>&1 } function unset_current_state { # states order: # initial, git, secret_init, secret_tell, secret_add, secret_hide # unsets `secret_hide` # removes .secret files: git secret clean >> "$TEST_OUTPUT_FILE" 2>&1 # unsets `secret_add`, `secret_tell` and `secret_init` by removing $_SECRETS_DIR local secrets_dir secrets_dir=$(_get_secrets_dir) rm -rf "$secrets_dir" rm -rf '.gitignore' # unsets `git` state remove_git_repository # stop gpg-agent stop_gpg_agent # SECRETS_TEST_VERBOSE is experimental if [[ "$SECRETS_TEST_VERBOSE" == 1 ]]; then # display the captured output as bats diagnostic (fd3, preceded by '# ') sed "s/^/# $BATS_TEST_DESCRIPTION: VERBOSE OUTPUT: /" < "$TEST_OUTPUT_FILE" >&3 # display the last $output # shellcheck disable=SC2001,SC2154 echo "$output" | sed "s/^/# $BATS_TEST_DESCRIPTION: FINAL OUTPUT: /" >&3 fi rm -f "$TEST_OUTPUT_FILE" # new code to remove temporary gpg homedir artifacts. # For #360, 'find and rm only relevant files when test fails'. # ${VAR:?} will cause command to fail if VAR is 0 length, as per shellcheck SC2115 rm -vrf "${TEST_GPG_HOMEDIR:?}/private-keys*" 2>&1 | sed 's/^/# unset_current_state: rm /' rm -vrf "${TEST_GPG_HOMEDIR:?}/*.kbx" 2>&1 | sed 's/^/# unset_current_state: rm /' rm -vrf "${TEST_GPG_HOMEDIR:?}/*.kbx~" 2>&1 | sed 's/^/# unset_current_state: rm /' rm -vrf "${TEST_GPG_HOMEDIR:?}/*.gpg" 2>&1 | sed 's/^/# unset_current_state: rm /' rm -vrf "${TEST_GPG_HOMEDIR:?}/${TEST_DEFAULT_FILENAME}" 2>&1 | sed 's/^/# unset_current_state: rm /' rm -vrf "${TEST_GPG_HOMEDIR:?}/${TEST_SECOND_FILENAME}" 2>&1 | sed 's/^/# unset_current_state: rm /' rm -vrf "${TEST_GPG_HOMEDIR:?}/${TEST_THIRD_FILENAME}" 2>&1 | sed 's/^/# unset_current_state: rm /' rm -vrf "${TEST_GPG_HOMEDIR:?}/${TEST_FOURTH_FILENAME}" 2>&1 | sed 's/^/# unset_current_state: rm /' # return to the base dir: cd "$SECRETS_PROJECT_ROOT" || exit 1 } # show output if we wind up manually removing the test output file in a trap trap '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 function bats_diag_file { local filename=$1 echo "# DEBUG: begin contents: $filename" >&3 sed -e 's/^/# DEBUG: /' < "$filename" >&3 echo "# DEBUG: end contents: $filename" >&3 } git-secret-0.5.0/tests/fixtures/000077500000000000000000000000001424706700600166035ustar00rootroot00000000000000git-secret-0.5.0/tests/fixtures/gpg/000077500000000000000000000000001424706700600173605ustar00rootroot00000000000000git-secret-0.5.0/tests/fixtures/gpg/README.md000066400000000000000000000027261424706700600206460ustar00rootroot00000000000000== public/private key pairs for test keys * git-secret test keys are named user1@gitsecret.io through user5@gitsecret.io * All test keysets have the passphrases 'userNpass' I.E., 'user3pass' for user3@gitsecret.io. * The public/private key sets were exported with (for example) `gpg --export --armor user4 > tests/fixtures/gpg/user4/public.key` and `gpg --export-secret-keys --armor user4 > tests/fixtures/gpg/user4/private.key` * user1 and user2 are normal gpg key sets for user1@gitsecret.io and user2@gitsecret.io, and have the passphrases 'user1pass' and 'user2pass'. * user3 was created by `gpg --quick-generate user3@gitsecret.io` and therefore has only an email associated with it (no username). This user was created to fix https://github.com/sobolevn/git-secret/issues/227, "keys with email address but no name not recognized by whoknows". The passphrase is 'user3pass'. * user4 was created with `gpg --gen-key`, using the name 'user4' and the email address user4@gitsecret.io, and is also set to expire on 2018-09-23. To set the key's expiry, I used the `gpg --edit-key user@email` command's `expiry` function. The passphrase is 'user4pass'. * user5 was created for issue #527, where keys were being rejected if they didn't have an email address, and had whitespace in their 'comment'. using `gpg --full-generate-key` with name 'user5', no email address, the comment 'comment comment', and the passphrase 'user5pass'. git-secret-0.5.0/tests/fixtures/gpg/attacker1@gitsecret.io/000077500000000000000000000000001424706700600236575ustar00rootroot00000000000000git-secret-0.5.0/tests/fixtures/gpg/attacker1@gitsecret.io/private.key000066400000000000000000000067611424706700600260550ustar00rootroot00000000000000-----BEGIN PGP PRIVATE KEY BLOCK----- Version: GnuPG v1 lQO+BFaigVQBCADC5dJ0xweZ+6L0owo2wpKSbQFGQoRJxYVcc1dWe3zNZ5yBrJDV N79rYV5AmHnIGDAJrHHV9rYM4+C8obKka7P3ROm0RMsYKDhpQXWFjsOrl1rjWL86 6D4X7Q5uuJWluPp1+hbzpBmNCX3Y5sr1fmCazvR5iIAvY3EkYbqDt2+BtGTqlevY ivWiOoPKRY9Dc44rKQh8GmaVJzcO3D21IF70i3GnOtjUSK8DWXdD4BrtYTE/9Ua4 bmT2pOPmGMcI38pQHZQXqMPTzloakZk9qIbBoB3FS/UFxQr3R3V+tXPm1Eca/75G +U4VCRLUFWsDU5d+oTCFCa0qNjGnLFOE85C7ABEBAAH+AwMCW7i8uGNVEnRgGKI3 2g1TXbUxgqg8ayjCkE2m99KmtbzxAAGJfuETnpxMo9U5JDOk68UC4jgArfWFOad5 Q3waxbCmKOTuSKqiA1FjXVoL5CtSzziygJ2XSLFh+fOsyeXWSdsmHjIQsXmwSnEm 9TJxNHNA5AL53lX+ike78cP8fNNlZSFWzfqGSe2nHgLICqMAk8hDUO6s/zFrHmbb 6Bu7azLTe4r9oEHcD8XsGlxhUUntK8WFPnrZlAdo++E8Ax4VQA/KXaU7STNutMQu tvuIOB+E6RRH/lKesIwt2Hrbin/AQKzyyedUJOVqW/UCsXBN9dnpbdR5pSn3eXxy LLb3S7whUVUE3HSrVqTRoyupyX10lAecpHPJMB6qq054x1xStPAkcsuVGrewznjD Zywicif6QzbBc6ZN1tS7fOxxJ9vn5qT9et0xnIJqFc++eofJHJ/Wl9eBtg5XTis7 69ERbU6GjqVJhAmPPQNoEVUhS1hJimQxAF/oqhEO8yTEJhmGZIzYTrQ1GcLh/AiH qkZ5LVwraTrXOJJaRzBL+bzfJa91MJVIpfS9wDTpW/CFvFp9Og/dYmTDfE1zLgSv tPSD6RcFxiOTkAeLRN7X5RdFqHjWdhgu2hyd87jpfGt3u0BK1iWW6CptSeNrSFXy lEsU3VuBFMRIjdUAXDefN8/99LdSgO7FkLyJsTeTxGOgrdp9fJF3ZEnk5wYRj6Im /3NyEq5gdeow02LPIgBGqsXi5iHSAaSJEZnpguCsJqeDnzsGmiLBfy2/MS03+XzU FW4OxbNxprDJdheHYqJ6k2z7xchkPedk0s9JpDVe/5ShMyrJI0THP2psPm+EVlKK 7lDpNf4hRj2by8HYLa/X21AgS8WLTWd+osyO5HQxqhMlDqtpKkOJ4q6ylb3QgDNU GrQiYXR0YWNrZXIxIDxhdHRhY2tlcjFAZ2l0c2VjcmV0LmlvPokBOAQTAQIAIgUC VqKBVAIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQiAEDMVPMIKV1RwgA sQAQmjtDpyKS/+zzFgVuOqu5QffqylFMXw8zrchiBLTeTCEKoixNj5cccpAG9xDU ZcMwMw/lSAz1MXSfQ6GGvl4ErlZrlx9SSacqPwDNoKWMci9PDb3JpaXZtQQCrDmw nZpSE6bKvhAoTIaA6Tn8g4uOo3vTyDuX1DznrcUFrMCW7vw5ztttA1hvg5iHrs4d ia/FaRX0SOf9y/0u9kQW2pkWlVL2pRgQaYwHl7FQRGnrwibxyEpTQ8x+d8uU87DN aaiUZ5GcsZT2U6cmhuz/k0IFGL408huF5h50KVFTYQNQc3Le3v9wrh88Obn4ciX/ 2YizefDo5WGt5/mvlUfp750DvQRWooFUAQgAv54OkX9n0+L/59UUWWtqz+siBF3o 3wMU0AKoATIZbilxoOPHzvv8iWpSlShTNsY4HqsZf7tIqfJLq91EigV0uQs0v6zw zFC31t8lQaQy0g0uv04xnMIvYw4xRhUa7dBphokeuuSCU7uJzq6za3Ia1hoNZEfd lEG/1LdGMzMLURxUlWWwpzRJdPEpEd6/InavNiffiGaiJXfTUQfpicz0k7eyXgK5 Pat07UaIW80gol+fghu4BhEHAWAfAV6ocd/YfUn7Hax55l0/npC3Y72JMhhSW11H gOE1iz33INGF9pfNL+VQwQj9gUQCOcczquD4NQ7RgQAdZQ2K9k4caOzbxQARAQAB /gMDAlu4vLhjVRJ0YNV0uVpXwCia2Vq2WMzxN0UyvAeF9QwkV8LAJt3O/VwzdJDg jWALHfUHysylbmE3nwAL6gOznL+XQ/Sf1v0dzDZZi8S64t4DNGnk7wRuui2/ZRVd 3jM2tiW/Y7ijWIpEaRwH8jtrV6+zoUt76YgBcgun+nhUzcGbdvh11Ygu5VHYxNU3 J7p4E80gClGsciNO9B+hgR8kg+wGc+C0LBey1mh5A0AWqO0NwFlF8YlpleC09Pld I3+NJ4miZUMS6ue5Me1QvBcAvaY3Vuh2U0RPICI2Athx0xpILktnuANqjxg4BiZI Lelaxxl12ycdO5Im1IUXiLBgMOBRFvRQ/6iEb/oTGRN8aY5W93LQ7nSyKdn6B6V5 HzDfuwrDJP6Q+sMi3SCEFgaNpNTRPu11gvMAj1V+4zwgsflZHVgkKSwvg2pRXAPp rNfJo6d0bfImF9w2J/2d/gYSOoWsC92VG0KY8hVWkHOBUVZFyRl4zv8UNoCtBPkM Wq00X0J3ZNAjnPE8hl2OK4q+4r0Q3CecVgK0tlTMqVfgNVgG0X6LV7xmbViY4HuA kvfmLkTFwL3NzpGVtm4S2DjMUQQygjS2GOfOM4TrNd9Jn5WMCP/7HX5K/3VjL4ai mpAoz0A2UeA116KaniW8PnZCm9A+ZFVALjsikgi1gBEuJC2+mgUfhbPtni41qcio mhN9si+BE7HhiFk8I/+xg7bAmNcw6hk/zESfKKxqqV4iiauQBy9zEtA7Gg8chcK+ 08eaunF2abkF8xbYPOF8p71sHo2UeJ1gK1lGMzTt1p7NSZm0F9VmPcy8WWjzna1z oRy44TyWcW90abV5gCerAhSDAlrdwZfcRG6NXT/wG0TjoCMgiIhR1X1gjpozV6NB 3fB9sc/NDhhibsqA0i0JiYkBHwQYAQIACQUCVqKBVAIbDAAKCRCIAQMxU8wgpQqe CACBDi7KrqQzdzeipLadUsaTptvFBlwavpCLRtNbJI8v5i4kr8cLmyqGAwCS8Yem 3SCI/K4ujln8an6XrhsOE/uwfyQz5iUcP7BN9sIEp/ITOIXu0q0kzxThmpJqHzvf bvkPemFEiwYwGZn87cFXmd7FMEoFIt/s/bCnPCuBkxvUMj/D65Sb5x1X+FzWjK2m OVJGpTHAixns+DDHOfXEkghQTfj1pX/LBV9nXKlSZtpDO/p/kx+xITxXA/a4EDtD 2JpZBYmSTcbyVamQEMTzMIfEUhMbSrhKRYcm6g5Jbu5oy0ci/5qIhsR45pA7JSc0 0Vjcr8GgU7JyYnSqF2Ua8YA6 =Ygfi -----END PGP PRIVATE KEY BLOCK----- git-secret-0.5.0/tests/fixtures/gpg/attacker1@gitsecret.io/public.key000066400000000000000000000032461424706700600256540ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1 mQENBFaigVQBCADC5dJ0xweZ+6L0owo2wpKSbQFGQoRJxYVcc1dWe3zNZ5yBrJDV N79rYV5AmHnIGDAJrHHV9rYM4+C8obKka7P3ROm0RMsYKDhpQXWFjsOrl1rjWL86 6D4X7Q5uuJWluPp1+hbzpBmNCX3Y5sr1fmCazvR5iIAvY3EkYbqDt2+BtGTqlevY ivWiOoPKRY9Dc44rKQh8GmaVJzcO3D21IF70i3GnOtjUSK8DWXdD4BrtYTE/9Ua4 bmT2pOPmGMcI38pQHZQXqMPTzloakZk9qIbBoB3FS/UFxQr3R3V+tXPm1Eca/75G +U4VCRLUFWsDU5d+oTCFCa0qNjGnLFOE85C7ABEBAAG0ImF0dGFja2VyMSA8YXR0 YWNrZXIxQGdpdHNlY3JldC5pbz6JATgEEwECACIFAlaigVQCGwMGCwkIBwMCBhUI AgkKCwQWAgMBAh4BAheAAAoJEIgBAzFTzCCldUcIALEAEJo7Q6cikv/s8xYFbjqr uUH36spRTF8PM63IYgS03kwhCqIsTY+XHHKQBvcQ1GXDMDMP5UgM9TF0n0Ohhr5e BK5Wa5cfUkmnKj8AzaCljHIvTw29yaWl2bUEAqw5sJ2aUhOmyr4QKEyGgOk5/IOL jqN708g7l9Q8563FBazAlu78Oc7bbQNYb4OYh67OHYmvxWkV9Ejn/cv9LvZEFtqZ FpVS9qUYEGmMB5exUERp68Im8chKU0PMfnfLlPOwzWmolGeRnLGU9lOnJobs/5NC BRi+NPIbheYedClRU2EDUHNy3t7/cK4fPDm5+HIl/9mIs3nw6OVhref5r5VH6e+5 AQ0EVqKBVAEIAL+eDpF/Z9Pi/+fVFFlras/rIgRd6N8DFNACqAEyGW4pcaDjx877 /IlqUpUoUzbGOB6rGX+7SKnyS6vdRIoFdLkLNL+s8MxQt9bfJUGkMtINLr9OMZzC L2MOMUYVGu3QaYaJHrrkglO7ic6us2tyGtYaDWRH3ZRBv9S3RjMzC1EcVJVlsKc0 SXTxKRHevyJ2rzYn34hmoiV301EH6YnM9JO3sl4CuT2rdO1GiFvNIKJfn4IbuAYR BwFgHwFeqHHf2H1J+x2seeZdP56Qt2O9iTIYUltdR4DhNYs99yDRhfaXzS/lUMEI /YFEAjnHM6rg+DUO0YEAHWUNivZOHGjs28UAEQEAAYkBHwQYAQIACQUCVqKBVAIb DAAKCRCIAQMxU8wgpQqeCACBDi7KrqQzdzeipLadUsaTptvFBlwavpCLRtNbJI8v 5i4kr8cLmyqGAwCS8Yem3SCI/K4ujln8an6XrhsOE/uwfyQz5iUcP7BN9sIEp/IT OIXu0q0kzxThmpJqHzvfbvkPemFEiwYwGZn87cFXmd7FMEoFIt/s/bCnPCuBkxvU Mj/D65Sb5x1X+FzWjK2mOVJGpTHAixns+DDHOfXEkghQTfj1pX/LBV9nXKlSZtpD O/p/kx+xITxXA/a4EDtD2JpZBYmSTcbyVamQEMTzMIfEUhMbSrhKRYcm6g5Jbu5o y0ci/5qIhsR45pA7JSc00Vjcr8GgU7JyYnSqF2Ua8YA6 =CU3L -----END PGP PUBLIC KEY BLOCK----- git-secret-0.5.0/tests/fixtures/gpg/user1@gitsecret.io/000077500000000000000000000000001424706700600230375ustar00rootroot00000000000000git-secret-0.5.0/tests/fixtures/gpg/user1@gitsecret.io/private.key000066400000000000000000000067511424706700600252340ustar00rootroot00000000000000-----BEGIN PGP PRIVATE KEY BLOCK----- Version: GnuPG v1 lQO+BFaigO0BCACwtBp5eg1d68f9WhmYew/4eU5zjaJsNj1DHsHokxsUt9QpIdVq DuPxlW8pTOUrhqQZd0ozaaDMswwFpzkblelQJzt/juqy/lkK2StlQfK2YRk7zehV HA6YOtTFyYbyheCeSFNJ4bfy3nn1lSDTtSmDpQBz19hVBP9JapI8K96nTSuK0NAb FEZ7ZdFLdXbtEkXHtTL+eqrys8UI7Ou+iZZ+dBlwTl9Jszg/b6IjYCYFT/LKuLX3 ss9fI/ypuwjB+1zys9WNDiNrrb8e26GDeOjfTH0vPuV9nU2gqLVzlssTLiWkrjSW g3OhO3jBBa59oEf60eBreL0FZ74LqRsPT8NVABEBAAH+AwMCDb97GbFDRhZgU4Gp 0YHMOv/Fy3ENidzrv+jbviH170EKpIgizpIpzen4SwTT+dbks+MM9vPvvaDbJPBo qTkPYOm9ON6jBRTzAF0ITiioSjhXhpYHJ4eLCUPt+qSTtFLPQChSAOmmUKQD2zUP cLG0gjKUiapu0klbcyF8mpKIuUuQUFG0fdlEWNoKzxKF0nlQ9Fn2CTCLaJK/a8tp FdoO0naGBYsCUMFHIs+ntaCoQZcUl52JfcLVq0HteISCqybX13lrJIlVGRLB4YYj CcIsymAc2/sbKpPHRcQQHcaiPL6z20P9yo8DyLwSB1j/RnqMJU4XBY7wS7sOeJMy d5QhTbq3i4kgpqh59q0uJamVKJNLEb/qVZDycdgj3EIU1C7HEukaiefPnvqDFWwx o88VOZoeqKCvf2QQgM1a4AgwpkZ20jvDK3ydeGWA9d+BsqgfKUOfjbhxc2J5W3Fk J/tpjQQErEPRbRZNi9aEYNNBNZeZ1NVsu32kO3FJfj2bgAsTduHK6PAoHT3M2gXW EzshsMqeFabWgMLfgXA65oOmcBkCQpcRXJHEwghLS6qGkNgB9R+tWBdnfpLgCELa k+aYUf28szbzMyxfBfCUoMFT052oNQmeerHg4BgTQNaWMuFG9qsI5DzxFmmXLhBs uMZ15oOgJHaT19zW9xMV6REnnHLFrwQ6pm0bO+kDrHBiOLGG7YcjoVb1aqMRaFSu Po8pFNLKuLSJ35wWrGms4N9MQH1jOSWMsmOnYvJofakpA2JAXIkitNjQuo2UbA8N bx+klajhlBJDdyO6Z6o2dndr+XHg5tKfK+6XSuK50Xr9CdV7R6hpZG2Ek+OUNewD M+1DuXC/9EVOs8H1bdBd2WuGOwAgUhNND/YGqcYBqCxplvVIYeMzhgR4O3ZUNodG wLQadXNlcjEgPHVzZXIxQGdpdHNlY3JldC5pbz6JATgEEwECACIFAlaigO0CGwMG CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJENKAWkGC6Z/0fskH/RIZyEdxw80P qyNRVg79wrhut63y7ovseavqN6wpECgkK4urqVNBErzA1LqEQONGLUjcgStCdSGA YJlw5ZJ67K7oRidzODnZovLndT4D1WYkf4v4jnl95CblJUkPSMHKny+uw0Mrgl3Q Kri5BxBggMHu330cgthpyUC0P+yqi1YRHde+2P107IdkpLYgJ1qJz3loAgm6AmG0 kwiK6wIZzbIwvnEtZDVxvofrM1o5lAXgH+puxyC7lZaU8gnJqXGM5rYJAEPC3E6M m45f3JkEjnbd5ruJ07SQJ0DGklKGKL5zTG0lX30Mb28EXX0OAK1MODIHvd3LcSqb VJ6lMXUJehKdA74EVqKA7QEIANqD9vGoR651Kdn0z0FOVkSgZQG43KtXsoj0ifC/ eC58JqPhRCTFcSLb55AIGLsAHcu+yRwkSwBrCisTIHqO15dSbYbbj+1LfYX0lOBN tGEXZA4NZ02hGOmsC2ND4+1qQ5afBIjDlMd5ceQY3MipdWHn0mi5CF04iaLDmMPE iy6C7NKofuSs+4+kyzg49RdnjP/Oe4cIsiEe4B6CvMPrnOoOXyMck6DmZz/Hj8+p keGh+vaT3/sbTyCrOEPmaC+HmLf2jCycr6wxVkOjwEY1V1ZhVVi+27uN2FskmEJm qeQhsDhwKhqLWmez9kWAz9TbqAVB5E5yatJMmxc6pcIkbpEAEQEAAf4DAwINv3sZ sUNGFmAjXQZ3NwRZ0DnvYj9t1cHfdaWtD/hKj2rlsRdgbcuANeZ5gcrZL6iXEvns SMuSNGx3moQBDZytbRPGVP3s5LWaZqsCj/BiCePWepVYaJTYNxXZ40bGTEy7VDL5 rnRw9KwJzG3NNg5siKHBDbQNZZhdN1Q1PLHyxK5JnDspXtvTuYmHy0mVveY2WviE cnaGq07PtchE0tYIyRQgrJ3szJoh17Z/aLGR77zWLGzqF4UVQIBRLuCxrUeUTEUU 3CHbveY0AKa5SQIu0fKyYBkeyWuWgX1JdPGFiFlPaiwId3ba+0DlXNwlHKJgWCGP GtGcNVo/AyUdTwQncNsXiwxJ3RG2AsqASRINQLsbUqKUE20WHBFbyRnHQcJby2si hjruM6mXLI4jqyMxtER9JXv1B/MTfLH8uxEOVYma3Wmp41vkICqH0LygHQ1tTKUf bMh0A517s53YFvkrbd110p7bfQcqpeAfZ2vUNKW/G7pUt+4sFeTPJ8A6XrBEt3rk H7kMjU7wI3PSm3UzEnMzxNFga40qwzclPOa1ka9KvJpH60E7pSLwf9AaYOJfuKST n/6uk/q+UONZZgcbtrPCaRptd86lInxHu9R8s7T7/ZK3/oPmU7M5leg7NmuAWshG eb+XGBO/QugLVdMz9Dc/3YELzPe+CqjRUiVpBoNfAGurZ0ou7o1KgeOQovcuh1wt cpHM55XeuxRvM5Xz5FgKinU0pw9t7uuASOF1Y3d7PncBkfkpvxjbPqyspVHEbloA JvDB7Eim8KcSIS+/DVPMdohfRdcLQLeUU7FSQ10HxERSgD4HQ70jQLYyHEsOqZv2 04U/cwpD1EfdzITb8LQNPIPyPsgehbaMNonYiTXFW2uUBgPriAtqPSG7wF/FJbN0 TT9N9PWFVoNciQEfBBgBAgAJBQJWooDtAhsMAAoJENKAWkGC6Z/0DY0H/A14kv3S l0CBUkAn6XtfsEvdBKyeOZjPNlK1HzgNwPCkbpOR4g9mTqA4tr/XzpJk/A2VE5y0 /DIaRnxivy9trnjQG7eNdymm08My+GRCPWOkceIlSV7IBZh2iMvYpFVXELOcjH6x ldc+RQiJ0irRXs28XbXYc7T4JYZr7xgDQIb6yyaAAdd6//k1oHGQf2uTsNWZzs43 OBAN2ze3DdYWXMtsskHVvnnFJSAR+03rg92VMSAfh6GKq0aFF12qTUAAWVEkoAFH gRBQRqVFT9RgKOgk7VRlytO1sv5bP5ZlvE5IvN9HCTHLOYCr/sTgOb3oYYQ/zZAm Bh9SiS8oRa1I+f4= =PunG -----END PGP PRIVATE KEY BLOCK----- git-secret-0.5.0/tests/fixtures/gpg/user1@gitsecret.io/public.key000066400000000000000000000032361424706700600250330ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1 mQENBFaigO0BCACwtBp5eg1d68f9WhmYew/4eU5zjaJsNj1DHsHokxsUt9QpIdVq DuPxlW8pTOUrhqQZd0ozaaDMswwFpzkblelQJzt/juqy/lkK2StlQfK2YRk7zehV HA6YOtTFyYbyheCeSFNJ4bfy3nn1lSDTtSmDpQBz19hVBP9JapI8K96nTSuK0NAb FEZ7ZdFLdXbtEkXHtTL+eqrys8UI7Ou+iZZ+dBlwTl9Jszg/b6IjYCYFT/LKuLX3 ss9fI/ypuwjB+1zys9WNDiNrrb8e26GDeOjfTH0vPuV9nU2gqLVzlssTLiWkrjSW g3OhO3jBBa59oEf60eBreL0FZ74LqRsPT8NVABEBAAG0GnVzZXIxIDx1c2VyMUBn aXRzZWNyZXQuaW8+iQE4BBMBAgAiBQJWooDtAhsDBgsJCAcDAgYVCAIJCgsEFgID AQIeAQIXgAAKCRDSgFpBgumf9H7JB/0SGchHccPND6sjUVYO/cK4bret8u6L7Hmr 6jesKRAoJCuLq6lTQRK8wNS6hEDjRi1I3IErQnUhgGCZcOWSeuyu6EYnczg52aLy 53U+A9VmJH+L+I55feQm5SVJD0jByp8vrsNDK4Jd0Cq4uQcQYIDB7t99HILYaclA tD/sqotWER3Xvtj9dOyHZKS2ICdaic95aAIJugJhtJMIiusCGc2yML5xLWQ1cb6H 6zNaOZQF4B/qbscgu5WWlPIJyalxjOa2CQBDwtxOjJuOX9yZBI523ea7idO0kCdA xpJShii+c0xtJV99DG9vBF19DgCtTDgyB73dy3Eqm1SepTF1CXoSuQENBFaigO0B CADag/bxqEeudSnZ9M9BTlZEoGUBuNyrV7KI9Inwv3gufCaj4UQkxXEi2+eQCBi7 AB3LvskcJEsAaworEyB6jteXUm2G24/tS32F9JTgTbRhF2QODWdNoRjprAtjQ+Pt akOWnwSIw5THeXHkGNzIqXVh59JouQhdOImiw5jDxIsuguzSqH7krPuPpMs4OPUX Z4z/znuHCLIhHuAegrzD65zqDl8jHJOg5mc/x4/PqZHhofr2k9/7G08gqzhD5mgv h5i39owsnK+sMVZDo8BGNVdWYVVYvtu7jdhbJJhCZqnkIbA4cCoai1pns/ZFgM/U 26gFQeROcmrSTJsXOqXCJG6RABEBAAGJAR8EGAECAAkFAlaigO0CGwwACgkQ0oBa QYLpn/QNjQf8DXiS/dKXQIFSQCfpe1+wS90ErJ45mM82UrUfOA3A8KRuk5HiD2ZO oDi2v9fOkmT8DZUTnLT8MhpGfGK/L22ueNAbt413KabTwzL4ZEI9Y6Rx4iVJXsgF mHaIy9ikVVcQs5yMfrGV1z5FCInSKtFezbxdtdhztPglhmvvGANAhvrLJoAB13r/ +TWgcZB/a5Ow1ZnOzjc4EA3bN7cN1hZcy2yyQdW+ecUlIBH7TeuD3ZUxIB+HoYqr RoUXXapNQABZUSSgAUeBEFBGpUVP1GAo6CTtVGXK07Wy/ls/lmW8Tki830cJMcs5 gKv+xOA5vehhhD/NkCYGH1KJLyhFrUj5/g== =0Q64 -----END PGP PUBLIC KEY BLOCK----- git-secret-0.5.0/tests/fixtures/gpg/user2@gitsecret.io/000077500000000000000000000000001424706700600230405ustar00rootroot00000000000000git-secret-0.5.0/tests/fixtures/gpg/user2@gitsecret.io/private.key000066400000000000000000000067511424706700600252350ustar00rootroot00000000000000-----BEGIN PGP PRIVATE KEY BLOCK----- Version: GnuPG v1 lQO9BFaigRUBCACgb+7xhV1nJZim3noxozslfrWXPYEVQt7Is8QjATaKg6ULqImi tpgnlUNCaEAd3PMufVSqd416KyytwUOBVaFIEej/SJcJ2UU4nFvJsvo4bNmInOc3 cNSqJ5VcI7D++wdHSecr2YayWtsh85jt6xI2oGBN334Yl6sHnNGC/vmE0pWovpib rwAW7bWSOYOQxpzANm9O+9oJ6WsTGVVWkZ/SAaRo+VYDA5rwCI6STt+rEcKalr5C sbtqELDDDrYYviU4kZx6WYdiDcF5ATSiuGZrQTjEdBFc+GmFxbW+aumeC+Y1jYOp aYUhbDKffnrxvFjm5+3PBbrPmJ5rFWr1f00bABEBAAH+AwMC33BVxMhK6IpgUYTN 9Se4Ys+bykytIN9jRVRzshJ/qYWU1L2wWwEc99P+4Yfi85x++KF8iD2jlym+/KKp 27La2ke3Bx7IvWK3YMwyUalxw/ri8C08g8XHlOZeUJW894dYaTRq2vYMBUW0F10J uGF1HGWqUYO4NlOMbs9W+RmUXWlItjlpdCTJdRKRPYzokrKh232NH188mYUscx62 trLq28nNZZ9WOFhsAiMji0qpUilPg8Pt/XupwiDscPYbVEXfTDRjkDbVbz+/Gpfx Hbt7aWT/2rFTp0lV2EVVp+e9je0qQaGSAED8cy3mw4lVJcTUcTWfSHauEJBN3FOI BV7bltO4UwIToSDvUV7zZR7u9CcnpuVWXcMWppHPc6383dJ+siTG5+zHLOG99eWA nwsnw1w/4j64uywJKPteMkSNGO+aFCawzMMi3LPwokVtmr8gklvb2v9wmWRVf1j6 TKeWPhzBC2kkrymuttMZyeOkyZhAPR3097v9S8CyTKbjBi4hEREt2CI2Q1GpSYLJ c/6RMCKh7Y+4ODw/encswL71eY4c3HqELz+GS0nzaumdIH57t/pBj1dbl63Z6gjz EJaOtS5I/otayLjcXQtIlV8xQwXcsgzFUYejVeb5n5IXWxxYn0Qh6uBB0GxffBQD lI6R58Rygmd1JOwe6WL1eFc319qfxoaDlhxxkOctUeyRB3fU/K4/KAjlVUGCfdCe VTJqwNMyKUNhbPoSWamMHFoJRk5O7bSlvfct6LcUcjRmK+z5SowUYC5ZeyfoeEES r8wX/UCFCP+syWFAICU96U9jmQeE310YF32TgI9BZiwkB9WXoiDdwcCdlBHqEOW8 7OISrpawan9hu1dV88P1LM13TcwJEt1yhzHHqDf6ZOopOt+LciBUlZ4wLLlsc+H/ tBp1c2VyMiA8dXNlcjJAZ2l0c2VjcmV0LmlvPokBOAQTAQIAIgUCVqKBFQIbAwYL CQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQ6qDk62szbIs/ewgAi4L2kIJEtqC0 ZUFGV9GJmvj/guEyY5buUKVXUMpNd8NhZ9uRLBFmG68mtjIlN8twNucXUTO2lLWY hMJpUhjobdRPzw887rNqswSIpWavPZreMKgXJ72/2md9m7cr9FmEZ9fZx80tBwdL 2+cYa1Iixuo2vk2Un0LD42qCbh0nRxSDf3g6yDtSHYZ4i6I89XwA5TSG1/C0uIcr RKGDBkhd05sqCJ9t/m6oAxk3A8nZM+i2uS0+dmOVwAmDv6/A64+Aff5hYsx87UeA dU76ni3rw0pZXTn90wv/aY0deicDlmSUattSNg/G6KoE6RERL47ityU07D4yUvTB GL5gVveBX50DvgRWooEVAQgAtDzDXdJSOwmDj/JhAk0wD+RBjxIzO/V/FXCotHaq iSSRvZ0Jn6CMrGa0EKksGXjqY6+jhC/HLb9hXjR+ciU/E64IVNJdtGp77rjVUygr sY0f0ZUSQufTC9lcVAP8wNx59Bk0nluO0zeH0lMRU/cLdyGCs7C3odO5xVvFl5IJ 6jH/95y6BdRGSDNTnzeQXT+fUHxLZbPG6AbLIXDOAK2OAHnUY62uGLF8l69x1Hym LVqD9TYTU9VpYq9Il8e18O6fqE1MEp4zHkyTf6IvCgZrOFL+XApwHYy1NskKi9WN DdQCvpDqvNSPZSqrajTdeJ4NzuVip+ccDT/tZVTA8A+0aQARAQAB/gMDAt9wVcTI SuiKYDgqOvDcasfFXeOTZdQn9tXs5VFeauKvovg1B6yVSE9SM/dg0vnIpIQ+b2nV Wm7IZXYsI6CpYWzQeAbp25Jg2lqCgmcbh9vpF5d+y/Unu1Mn8gbCRAjrwx9QLwzE KWUL7mt2vjesZM883iwC6PKYZnEtTuxXF5STnhjZLr5yjrAX7dEQy4m03FfXoGj0 tNo+sR+EE2zTSgrVD3VhUFmPTiND8wWUssjQHEMgjYJOc8C05HE2ftqI6GSF8pUP dZag3da0OwZVI8ww2Qcu8Dkkgblv3AulLv/oaiSrS7oJvDZC+aQw+3X91FFlwn+A Aiwa9bL6iAJb7KjgLIV4HDXLAC8FqiM5pPFu+fvPKsqP2x/iDvkJlAD8ZqXKHFQF 9F/jKUXgQ7+7vmQy6SJ3RCB7pMS5tCo6kE184C5htppYuKztRVlkePmK8ioT0sJE 1wpW6AGwaJsnXk1tza0C9yrl9TArO3R+JpImHj4AbOZ//WweOODHJFJQP6TcRZC9 FOkEIBbPGq4cHKXwYSUlD5hGFCPhTI+EYPxGxKJcw73hYDAWRVtVTb2vdC20FiRM uSXBaMa6zisawidYo7+HLSICn1n9swP8YhBLWdQkxIW9dwA37AXbDfbJDxkWSJl8 sGW+P5cTlhh+hA2sD28daBtFrbYOBVsIHQg6ozYk5RLR1Vddif8XN/tWEl2mvhKs 5QYW31M496B/tD63JQt1N6ilMLodBho1R6++2hIthF+10gjKjUmC10cGbrRx8cgl wlRrHiVzLNL+co0WMAnEnCC9fA4gruN/mVCSkbMDkvv1VywXl5ogzRq3OjPXDXft 4UgYKfNC5tTmWx+uFc9KcPFN7CS/hFovjRIV+grmWbJkG4HvGrK9AG/a84ufQ/si ZjprbtOy6amJAR8EGAECAAkFAlaigRUCGwwACgkQ6qDk62szbIvUZQf/adIYw+fH M1zlGJH+C/lEFoGi0AXOTqBH13T+haoykwrxnBOdaTGY196bj+uiSbtFqQWcuMNr OWNNH6NAl30Ujya/ltLv7FJ3DOuUyIU/3Bhp1t1+jEppMJRYk2pkRmmTg2lrOgSv PiqNgmK/FBx3t+JCtmQxtrTBBnJcmx5/8YGdOCEsiGJ2jl+5Im4XgT0OhQX320o8 2XrK7/Pp+ttmc7ExT6pc53sSYRUfEyObpCYVIz1nWK1FujfW+ojFFUvhHPwSL3ny dkJORg8lcQm/zXjbgCeMZ/l3ynkvSA+X9/Q7aQWGrpU0LRLGAeA9PZZDYx9JTQUY FfGupHnbRtqsqQ== =7tcw -----END PGP PRIVATE KEY BLOCK----- git-secret-0.5.0/tests/fixtures/gpg/user2@gitsecret.io/public.key000066400000000000000000000032361424706700600250340ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1 mQENBFaigRUBCACgb+7xhV1nJZim3noxozslfrWXPYEVQt7Is8QjATaKg6ULqImi tpgnlUNCaEAd3PMufVSqd416KyytwUOBVaFIEej/SJcJ2UU4nFvJsvo4bNmInOc3 cNSqJ5VcI7D++wdHSecr2YayWtsh85jt6xI2oGBN334Yl6sHnNGC/vmE0pWovpib rwAW7bWSOYOQxpzANm9O+9oJ6WsTGVVWkZ/SAaRo+VYDA5rwCI6STt+rEcKalr5C sbtqELDDDrYYviU4kZx6WYdiDcF5ATSiuGZrQTjEdBFc+GmFxbW+aumeC+Y1jYOp aYUhbDKffnrxvFjm5+3PBbrPmJ5rFWr1f00bABEBAAG0GnVzZXIyIDx1c2VyMkBn aXRzZWNyZXQuaW8+iQE4BBMBAgAiBQJWooEVAhsDBgsJCAcDAgYVCAIJCgsEFgID AQIeAQIXgAAKCRDqoOTrazNsiz97CACLgvaQgkS2oLRlQUZX0Yma+P+C4TJjlu5Q pVdQyk13w2Fn25EsEWYbrya2MiU3y3A25xdRM7aUtZiEwmlSGOht1E/PDzzus2qz BIilZq89mt4wqBcnvb/aZ32btyv0WYRn19nHzS0HB0vb5xhrUiLG6ja+TZSfQsPj aoJuHSdHFIN/eDrIO1IdhniLojz1fADlNIbX8LS4hytEoYMGSF3TmyoIn23+bqgD GTcDydkz6La5LT52Y5XACYO/r8Drj4B9/mFizHztR4B1TvqeLevDSlldOf3TC/9p jR16JwOWZJRq21I2D8boqgTpEREvjuK3JTTsPjJS9MEYvmBW94FfuQENBFaigRUB CAC0PMNd0lI7CYOP8mECTTAP5EGPEjM79X8VcKi0dqqJJJG9nQmfoIysZrQQqSwZ eOpjr6OEL8ctv2FeNH5yJT8TrghU0l20anvuuNVTKCuxjR/RlRJC59ML2VxUA/zA 3Hn0GTSeW47TN4fSUxFT9wt3IYKzsLeh07nFW8WXkgnqMf/3nLoF1EZIM1OfN5Bd P59QfEtls8boBsshcM4ArY4AedRjra4YsXyXr3HUfKYtWoP1NhNT1Wlir0iXx7Xw 7p+oTUwSnjMeTJN/oi8KBms4Uv5cCnAdjLU2yQqL1Y0N1AK+kOq81I9lKqtqNN14 ng3O5WKn5xwNP+1lVMDwD7RpABEBAAGJAR8EGAECAAkFAlaigRUCGwwACgkQ6qDk 62szbIvUZQf/adIYw+fHM1zlGJH+C/lEFoGi0AXOTqBH13T+haoykwrxnBOdaTGY 196bj+uiSbtFqQWcuMNrOWNNH6NAl30Ujya/ltLv7FJ3DOuUyIU/3Bhp1t1+jEpp MJRYk2pkRmmTg2lrOgSvPiqNgmK/FBx3t+JCtmQxtrTBBnJcmx5/8YGdOCEsiGJ2 jl+5Im4XgT0OhQX320o82XrK7/Pp+ttmc7ExT6pc53sSYRUfEyObpCYVIz1nWK1F ujfW+ojFFUvhHPwSL3nydkJORg8lcQm/zXjbgCeMZ/l3ynkvSA+X9/Q7aQWGrpU0 LRLGAeA9PZZDYx9JTQUYFfGupHnbRtqsqQ== =HLsH -----END PGP PUBLIC KEY BLOCK----- git-secret-0.5.0/tests/fixtures/gpg/user3@gitsecret.io/000077500000000000000000000000001424706700600230415ustar00rootroot00000000000000git-secret-0.5.0/tests/fixtures/gpg/user3@gitsecret.io/private.key000066400000000000000000000071031424706700600252260ustar00rootroot00000000000000-----BEGIN PGP PRIVATE KEY BLOCK----- Version: GnuPG v2.0.22 (GNU/Linux) lQPGBFtLVc0BCACwGHyefi/z8xeH6KpLN2k9+PlHAPpwJaW+8siaWjbQenkbWX6/ cVBFBwLNVCY+UacKNKVPxYDgS9UkAGlqD1GRGISh9uvIKW/w4T2LBxDQBGlYsTdL KhOY1eTb5c7fa3ai17CqNam384+fqD9WCiK3PnO/1QLW48E8Q3R7JgyxmFB96FCb PZuRAMcBmKR7aa2yp493gGoI6Ts04gd33zDex0Qywz7u1rKNp/Sirb35nJUZ7Q63 fof2LXSaJXEnHMdE6BFMkIhSluMAICxnb8uD57QilPSh3dkd5VmZAwd0dFV9orLA zlBnRu/VOmQA3bXaT8/g+F0XiA/r+4ARLnyRABEBAAH+BwMClcCGX/kaiEXsI8qd O+lPmY0IPpbYpG943Uo11Y2H2kCNEMu0m+jDanUH3uc3Cxuytfnq9kxzqetJgkw+ sbYADZR7eWD9w2Su0hlJjMDWK0GXIsTLdf9KYwUi5g2CCqfglb7OJxpfQWd8gQiJ 3QmxTLH54WVzEuFb3GbjeAnAVk8AgyP4zsMtBJbo4NuSZ3W/jVaNiJgdeWe9YWFx mngTLST+LgostcgAew/372zH8UM82uVC0pxk+FDfInFrnd9s6QZla2iGJgi8nwby kA0Kys9wRbO4ItWU/IdtLecv+FL8CKeZJf1ZirAU3MFQOg/snEfd56o0wFLt1mhC UIH+QwWGUolvihuXoI138bD67lE0dBiPuUjb+E4lgT8P0h2NYKtIwtWAO5xYdYtA cDOkFbTEOOtw4ylHTv3yx5866t5ddbl8G5P2+JGHKlNlfKxRQR71vy82ndbUz2V4 59ImSNZUgFP43Q8YH78sZhrhNec15+Ek8jqZSfVajRotTc1reYeNU+qu8gKln3Uz yKAyci0DvIjG0IW+mbiXEf49yiYMZHoyGrFYpTBAp709yFufr8wQv0h/BN3UdGqI gwbJ6kjQrm0S48Vw+A8YkxeaiahpCpbAiwoDa5PN5NZvFwXmXwQkx5fCeyhRkxdf UtPV5uDa1WznIt2gHP2NKTP54nEfLq4eLcwjvLcyjXn9aAZRmNMwbOBJ9Uf4x06S xzBI5FUL+2aqHrEedCeyW4AsndVaKOWNfzqjY7Y8cDuqpQj3o6yWbGy8u1kGDPK+ v6gCe3Ub+y801kqN2IyegSyjK6t2H+j0y7Y+I2J33SBKgztiEcWgM4N70zaCV+vj 5ekYXwp4N2w1yWkejk0heIiDdaxRWejs6WImDMOvinXot/arbqwEKkr3nNhbFNoq CRWZ45DsnlkxtBJ1c2VyM0BnaXRzZWNyZXQuaW+JAU4EEwEIADgWIQRz/JOETMGC St9zD7Gz/JMICuU7UQIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAUCX2X3vwAK CRCz/JMICuU7URxqB/0ZqQ6tZh5mnZ/kC2TLb4GQJqZbZOyb4I6uI2LH3di43EX9 UMtJvXBsl5rR68jCpJfrzC/nCWkVLC9meNydUgDXGNJyEyp22dXJoSvfzcI1WFOT OK7JdHi9TtsmqEKZk9YC0rliaisb886vXrB4LsbyLqRYYc0+9oRLZnWbY9mc+44B rnFOWpMayELnJMhNq5awSJhwc983VEwExyHdCStj94Q2SBM/v9xpo+xjjbJVe8qt IJXvA5aJPi1HObpWBJq+3ZWVqKfWY8wUojPn+N7PUuUvBGzUanfpbdKs025XjO4Y 0zbh+2/W8JcFs1nL5fEALZ6LVy0clldLB+Rco3c4nQPGBFtLVc0BCAD2b/acD8ik PMeu+TSRz1xkwrxjMh14kx5bWLWmhAdFK3FkpRzRy/u7URMYyc1e4k1Vd+srScc6 PHfAyW5dP7kyuV/I3qGVJTGDtp3YDcXg9TSToYp65Vo+RTTlGE3GVeVs/KVs3Ipf 2oBgxbXZi+twrQ6ZUr+Ak7M9oWimNyGkYr/kOC/8zO5haxsYNamOtBmcedlkctHx h3auZ57XGDHCt1h5fMRMzNoVqhyWmg+XW7O30HY8f5AX37rHgtpuCku7ejzX35NX +jLelR5a2f2Q+SVs02pGmOF6n4PKJA3pPXYfouR8wuiiFjifxVq1AQQm0J1MJeMi tHu+VcXx8KBrABEBAAH+BwMCaZaMo90qa/DsAWmMT3aso9qu+MdYX8RB3ZSLiTG7 xAA8B1bzNJ4NUpjyaPiVbxP6VCau6rUzgbzw7HC7w3w7FIfuPT4KTQACsHcyXMzQ bAeK5C4u6vbeFJGa0j7oNJm9prwGg6QDOMdyuS9LCz2i997ZMt/uvs22xw+nDzdU 1UzV6zXQ0iB87zejnmyWYJfELr13N7TvyOsQdIaeeIsoNkPnoNFCFaUOj8WUABfk MjijXZin9neyoXBIoFQg093QeArWzIrtXGcMFjk4EacboUpPOE4/Ybxy7Jsd/AxM JGwT6Ptqx6TDg/epAuaQhUNbivS4N4TcDKIoKsXBdKXgGGuhp7zajxShaNC1GQmZ 9+Gz7jiFiQl0hJVeK83lK5w4BguNcpIAomN5rvA8R9pOAcC5r84C4QBHGXvD3Upn yXda+EgJ5M2v8sk79vliPbZbKHLpq97PrHj8TUJ1jRD7QmpW0ko6KOuFZSItW7Tp u1zXNmFpLIEJovkZiHrsypCwSQefjcQ44G1AdYncTOVj64+nduJnqB6IiisziI1U X9VUl9Q1v+EArdIjxUjAQSz1Ykcw6Jg6X+6AzfNSX0Yoy/PrCId10JjAqIkuHFiG 4Q3IvM+1/irI0izc2LAwqiuSIXWgiOIT2hslVixEo9Kbm9ZIoVPaEIOC1KnC4cGg Fjemal2kuZmZ7EzOh8i9slFGyVFYYCLg/03TVmM13Do3e0DJ18da3H2zhgjyQul+ VQbAWnZxNExPyKwfTsFkXxZk7dTlO7VbL6iCDCZwDAQfZt27zIvOKpvMw7TSKLw1 afDX9wj0XzQ70d3CfPzVayjfbgw727C6O8tjUDJJC/vI5e7II5uFd8oiq+iwj/Hc lAsZO9VabmX/BZ9rh+JppQExGr/+0qnxJI+6TYCvxe712rBsCpO+iQE2BBgBCAAg FiEEc/yThEzBgkrfcw+xs/yTCArlO1EFAltLVc0CGwwACgkQs/yTCArlO1E9Zwf/ crn9d7qCZGpgQbaQj1lIr1LtLHzscl60Ug/9mL3u7Tc9ys5qg+EB+Y0zl6Y7MpNH t/XTFbLU0oqK1JVM7pJVZxqFHnKq5StpWtiCQ7v3wtpdziub1S1kmtiIW3VRMMqQ GW/CjkRj1532KqaeefM8rDXKP4l/AB8gvfXs+Xh4tgET49jh/COIh8aKVAMcEe2R 8yz8eCtmk7AcwcyYGDZdpiHk99MPM9ACi6Aqp55fmPKuslMjL1LvWjlGEDzmOZQY tfwMTb5idXqfbmC9Qo7kSRZAW34rAoTDwHh5E6591UEV7wkBhU34w3WUt8BLVRdO iK5wCW5ErIHh7mpgpvRK4Q== =wl8Z -----END PGP PRIVATE KEY BLOCK----- git-secret-0.5.0/tests/fixtures/gpg/user3@gitsecret.io/public.key000066400000000000000000000033401424706700600250310ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v2.0.22 (GNU/Linux) mQENBFtLVc0BCACwGHyefi/z8xeH6KpLN2k9+PlHAPpwJaW+8siaWjbQenkbWX6/ cVBFBwLNVCY+UacKNKVPxYDgS9UkAGlqD1GRGISh9uvIKW/w4T2LBxDQBGlYsTdL KhOY1eTb5c7fa3ai17CqNam384+fqD9WCiK3PnO/1QLW48E8Q3R7JgyxmFB96FCb PZuRAMcBmKR7aa2yp493gGoI6Ts04gd33zDex0Qywz7u1rKNp/Sirb35nJUZ7Q63 fof2LXSaJXEnHMdE6BFMkIhSluMAICxnb8uD57QilPSh3dkd5VmZAwd0dFV9orLA zlBnRu/VOmQA3bXaT8/g+F0XiA/r+4ARLnyRABEBAAG0EnVzZXIzQGdpdHNlY3Jl dC5pb4kBTgQTAQgAOBYhBHP8k4RMwYJK33MPsbP8kwgK5TtRAhsDBQsJCAcCBhUK CQgLAgQWAgMBAh4BAheABQJfZfe/AAoJELP8kwgK5TtRHGoH/RmpDq1mHmadn+QL ZMtvgZAmpltk7Jvgjq4jYsfd2LjcRf1Qy0m9cGyXmtHryMKkl+vML+cJaRUsL2Z4 3J1SANcY0nITKnbZ1cmhK9/NwjVYU5M4rsl0eL1O2yaoQpmT1gLSuWJqKxvzzq9e sHguxvIupFhhzT72hEtmdZtj2Zz7jgGucU5akxrIQuckyE2rlrBImHBz3zdUTATH Id0JK2P3hDZIEz+/3Gmj7GONslV7yq0gle8Dlok+LUc5ulYEmr7dlZWop9ZjzBSi M+f43s9S5S8EbNRqd+lt0qzTbleM7hjTNuH7b9bwlwWzWcvl8QAtnotXLRyWV0sH 5Fyjdzi5AQ0EW0tVzQEIAPZv9pwPyKQ8x675NJHPXGTCvGMyHXiTHltYtaaEB0Ur cWSlHNHL+7tRExjJzV7iTVV36ytJxzo8d8DJbl0/uTK5X8jeoZUlMYO2ndgNxeD1 NJOhinrlWj5FNOUYTcZV5Wz8pWzcil/agGDFtdmL63CtDplSv4CTsz2haKY3IaRi v+Q4L/zM7mFrGxg1qY60GZx52WRy0fGHdq5nntcYMcK3WHl8xEzM2hWqHJaaD5db s7fQdjx/kBffuseC2m4KS7t6PNffk1f6Mt6VHlrZ/ZD5JWzTakaY4Xqfg8okDek9 dh+i5HzC6KIWOJ/FWrUBBCbQnUwl4yK0e75VxfHwoGsAEQEAAYkBNgQYAQgAIBYh BHP8k4RMwYJK33MPsbP8kwgK5TtRBQJbS1XNAhsMAAoJELP8kwgK5TtRPWcH/3K5 /Xe6gmRqYEG2kI9ZSK9S7Sx87HJetFIP/Zi97u03PcrOaoPhAfmNM5emOzKTR7f1 0xWy1NKKitSVTO6SVWcahR5yquUraVrYgkO798LaXc4rm9UtZJrYiFt1UTDKkBlv wo5EY9ed9iqmnnnzPKw1yj+JfwAfIL317Pl4eLYBE+PY4fwjiIfGilQDHBHtkfMs /HgrZpOwHMHMmBg2XaYh5PfTDzPQAougKqeeX5jyrrJTIy9S71o5RhA85jmUGLX8 DE2+YnV6n25gvUKO5EkWQFt+KwKEw8B4eROufdVBFe8JAYVN+MN1lLfAS1UXToiu cAluRKyB4e5qYKb0SuE= =ccTC -----END PGP PUBLIC KEY BLOCK----- git-secret-0.5.0/tests/fixtures/gpg/user4@gitsecret.io/000077500000000000000000000000001424706700600230425ustar00rootroot00000000000000git-secret-0.5.0/tests/fixtures/gpg/user4@gitsecret.io/private.key000066400000000000000000000070021424706700600252250ustar00rootroot00000000000000-----BEGIN PGP PRIVATE KEY BLOCK----- Version: GnuPG v2.0.22 (GNU/Linux) lQO+BFumzaQBCADp6MO1IRBIbdJoABK3EUWxBjZKE/jAcAYGizfXh3rLm3QjBumR EHET67sfOJUIbqGbhfw+/PbpxKG1um3BcV85gXWcqW77ch/YupyJH0NNP3sBZ76W JqJXASGKR2JkBM5KSgNkS13LdMXTaXM9zwZuCOU1T4geapV/Zj4W614qzO8mRlOt gIl8/moxP0IwZneJvBhYLCCQg8i+zedIUvF5eneW9kwEtS84/PLXQ/HfbEuDaq0O dHmkXBNwp41PsnriMc78lahEXU9Xh9VUPwBYGs/kyXhhLEdhSBq/5zKdDldg2lc8 yKqZyenvoS5iKzJJU9QDjHP6gsYlhJ3c5WM5ABEBAAH+AwMCaxzgsFgqaQDj7Pbz L6zsxufuY59yw7vrae83yVai2erjJY4nZekvvB5ckZc83egDzkQjQIIMScwV4cJx TKiU1+dW+u3hcO1Qo4LDPCb3LFNiIfOoqKytDePZlfbL94VyANiGp6YLG4Z8rGrj pD7uINdCAIYK8EcXhJDwBnu7CaWkel+zeF3QCvppvKCcRN3RTabziXwcRaFcDnA3 5FfUssPU6X3bGMGiZnu3P6HDVksHfbsTjNIfsbvuejkbZxIvj52mTnDhSTkL0/uh ZAB6b4QWdY7+Df0ePPuRu/d1RCovx4HGI1Fi0YemcZ1AOet8y/LcEN9gs0jkL2Ux EevYDFVVd0J5MFISrmu7PTPBWn9TV7no2Tr3i21HIocNSWwkpK0uMI6ezMEPSCIb YTR6lSfeuVnQyUkLDGVvO4QGENra2unJRrXXrIwQk8qZK3p0PJ1Vss7kvR2RepIJ WsaSALHEyvHNeMtdlgyp10mBGmN9a+f2Wa5fqGsdLIDCOhztOnpEhJWNo4Rbjbov 8jx404sQvs84CN+VLvoXt6uSalzcxgWhyYMHhkmHc5X54pLACM1HL0EDfFtzb/rm rxXRzCxBxVMjFlCkZHt0SEYjP8bRDmqzyiHe1er3AuJCyY2VoiIfoc9iy2OkcONs bTrppNPe07v9UFcYjPiOWRuzPaEryBArteiT9u9x4eTi5QfYAqGChOHBIRKwnRgS TTJQnKoIWvwxaQ/o7fzfveS1NKnWdahZr7dE/+pA3DFvBWBLkrPQSXYHpbzPjx3t HB5AOJXQHWMFb2FUggu+uFANvUljc33AqHiJLD6eV3y7AQLIxJyol/S5kCkZ6f+I jnOg2V0VvuxFgx7WNnAomhq8d2JDi9WagqdjwmmT5qJbeixHZBvhg1hgZyaJLMep rLQadXNlcjQgPHVzZXI0QGdpdHNlY3JldC5pbz6JAT8EEwECACkCGwMHCwkIBwMC AQYVCAIJCgsEFgIDAQIeAQIXgAUCW6bPFQUJAAFS8QAKCRDm1MhM34HEJVd3CACA segF3UqDH3LuupOageZDKlmxRv9VSze7TC1p300eulvi4MsE/LlYoPGcS3BYxh7f W0ADOrLQA2mxL3cMuLB2L7gMByt7/wjmMmc0uTW1iCXQxMcRbn28ppBGEm4gRvP2 n7rI0cu/xNKc/zFIPZOdaykf+yfWZZZ22qWvbKlWi5MDQZYH9CsGvs6DKoTXKMxv fJCywZIfIPTPfQLHBKfXClyCUtj8FpFTGGmzthcAc95MhXASqWyAqlVHhXcTiOs1 jbedNQDG9og0qPkwJLu6yMPKZGEpg0qTtTCZlizblS8vvPHWYht/e/W6MX0sfZmO kweoudVozcBptiMq5vKHnQO+BFumzaQBCAC0qy+0Htba6RbLJymI69kIN6jQhUUD mRPwj+87QilUTNUYFalyPMT6e3oiZpr/o1a75oeZm/8Ys8+npipUrt4XByfO4zQ+ fF8U6+2YqCNnyYInFECDI9Csotlj3HXULb02A6dRKC9hvvGHoIoL2B0sIZUarXaS 6shUUJqxH1Z86I5V//cMVYndqvvTWkc3I1HIT4RHJUGbLHM5ePnbNisMDxnCAb+S dp95M7LflZtH0GqO7RRKvCXi17lC352U8MdId/OtN4auu7IhDW2eOBUO486cerDL YYVlqhXC9o5tJfxPwtDQiIQCw1PmrtPnMtLhXRRg6H/3eVY9tZ/W4C9PABEBAAH+ AwMCaxzgsFgqaQDjxHj0GMNo74Zls1gLk+o6HyjlvgnCtp7m5n8rkgaDKhRtaTkm AQBtKXhxfzFzQ1/RJfz3hBpYetAoW/HOE2ZQvLAigsbsHGRr+LF6W4i/8SG06jDW 2eyAKCbe45PWgcNzRqoyxWjOQXJc3UMXK3pX1oiyrt8WcsckGZxpsF24YUAxoNjz YlVFisqgpnBV6tCeD5L/68ibQvfiK2Eh7VtBPCf4yesZ6HjjVCAXkb4dbEhuuGCH ezlPfAQhtlqwuoLFlI8HCR/qOEhCgd6u9aoVd5xYxHYa6DQ7sM/04iH79XTr7KGz 07ltAgknRxEgq8EGYXUzEJ4fzqwbYxmo7iJjUbZApO+tKWYcpC4jSfITNOGOCrHC aQ/KzrtV0imm/RIhG/ZRZidWHf9gntjgc4kLKQuJZZUlUd1LHYqd7+5keiiDRxMr 1ddsMW1VBsKunZ6ryREkwzgbFzxT+ZWJlggHR15+h0+koWVvSiIj91s3Uw7PtrDe bOllsIQw0GnutJ08MVhduuk8M8vNapG3ZGrvXBD25qyV3EHSHoCagdBqtG8NxDpE /lQFk13kdeyXAPBneuGgvNAwbjWHn3qL23qsHTae1hslXcVTSIFxqrMuuENjuQc4 7k4Ma/JhXLjj0/avA+mrLJC4c6/HzN16bBcVlKqLF3r/g8xUyE17WQETzL2AMOOn UrKycP6d/VKGTr5VrlJl14dEACNya7anucSMv+4cat0DNOeYg3fB6hNRpR8bjOF+ fHuXkurLo/zH1wNCKBA6wV1/B9+E+EdBSwr1a1/79u+IqsLZh4piHxl6nIUAtkdV UwZXpuA9XuXP5RmxTwPuutnsYJz/LQKzI7B71PJjGzQqkfsl7jx9KsPkkqtd+RRY lFieM3t7hY9fcBmIO4eaYIkBHwQYAQIACQUCW6bNpAIbDAAKCRDm1MhM34HEJdaU B/9RH9XEO/f2ntmmYEJ1sYheUeKw0ZvOxaMz2poWrEJABY4C/slNpQL5rSeZ5jQf 4Gpe/IUWYd/Q24b4cDvYvngGQ+c63DlM2pVtcVKkyvWyLYmimr4WaLLyk1JYgqrW uLfXwsd2x7O42Cm4sevfPQS1hfgaWIfg9Gb1CVtlbJhq7iO5BBY5xPAXG70MksSq X/PO1ah3/ZBWuzd66nXBC/oX0tTj5W0hBuXrOkjHhXh42v26BX1xrHgq2ivuiqw/ PDHGFJ4K5x3A6Pz8UuAOlESJRPemOT++pV1LvFlkGSGTxrOIS/wvPT3skNeXsyDN VJ97gZKyfwWA4E3gTZGuYr3s =1Mtg -----END PGP PRIVATE KEY BLOCK----- git-secret-0.5.0/tests/fixtures/gpg/user4@gitsecret.io/public.key000066400000000000000000000032671424706700600250420ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v2.0.22 (GNU/Linux) mQENBFumzaQBCADp6MO1IRBIbdJoABK3EUWxBjZKE/jAcAYGizfXh3rLm3QjBumR EHET67sfOJUIbqGbhfw+/PbpxKG1um3BcV85gXWcqW77ch/YupyJH0NNP3sBZ76W JqJXASGKR2JkBM5KSgNkS13LdMXTaXM9zwZuCOU1T4geapV/Zj4W614qzO8mRlOt gIl8/moxP0IwZneJvBhYLCCQg8i+zedIUvF5eneW9kwEtS84/PLXQ/HfbEuDaq0O dHmkXBNwp41PsnriMc78lahEXU9Xh9VUPwBYGs/kyXhhLEdhSBq/5zKdDldg2lc8 yKqZyenvoS5iKzJJU9QDjHP6gsYlhJ3c5WM5ABEBAAG0GnVzZXI0IDx1c2VyNEBn aXRzZWNyZXQuaW8+iQE/BBMBAgApAhsDBwsJCAcDAgEGFQgCCQoLBBYCAwECHgEC F4AFAlumzxUFCQABUvEACgkQ5tTITN+BxCVXdwgAgLHoBd1Kgx9y7rqTmoHmQypZ sUb/VUs3u0wtad9NHrpb4uDLBPy5WKDxnEtwWMYe31tAAzqy0ANpsS93DLiwdi+4 DAcre/8I5jJnNLk1tYgl0MTHEW59vKaQRhJuIEbz9p+6yNHLv8TSnP8xSD2TnWsp H/sn1mWWdtqlr2ypVouTA0GWB/QrBr7OgyqE1yjMb3yQssGSHyD0z30CxwSn1wpc glLY/BaRUxhps7YXAHPeTIVwEqlsgKpVR4V3E4jrNY23nTUAxvaINKj5MCS7usjD ymRhKYNKk7UwmZYs25UvL7zx1mIbf3v1ujF9LH2ZjpMHqLnVaM3AabYjKubyh7kB DQRbps2kAQgAtKsvtB7W2ukWyycpiOvZCDeo0IVFA5kT8I/vO0IpVEzVGBWpcjzE +nt6Imaa/6NWu+aHmZv/GLPPp6YqVK7eFwcnzuM0PnxfFOvtmKgjZ8mCJxRAgyPQ rKLZY9x11C29NgOnUSgvYb7xh6CKC9gdLCGVGq12kurIVFCasR9WfOiOVf/3DFWJ 3ar701pHNyNRyE+ERyVBmyxzOXj52zYrDA8ZwgG/knafeTOy35WbR9Bqju0USrwl 4te5Qt+dlPDHSHfzrTeGrruyIQ1tnjgVDuPOnHqwy2GFZaoVwvaObSX8T8LQ0IiE AsNT5q7T5zLS4V0UYOh/93lWPbWf1uAvTwARAQABiQEfBBgBAgAJBQJbps2kAhsM AAoJEObUyEzfgcQl1pQH/1Ef1cQ79/ae2aZgQnWxiF5R4rDRm87FozPamhasQkAF jgL+yU2lAvmtJ5nmNB/gal78hRZh39DbhvhwO9i+eAZD5zrcOUzalW1xUqTK9bIt iaKavhZosvKTUliCqta4t9fCx3bHs7jYKbix6989BLWF+BpYh+D0ZvUJW2VsmGru I7kEFjnE8BcbvQySxKpf887VqHf9kFa7N3rqdcEL+hfS1OPlbSEG5es6SMeFeHja /boFfXGseCraK+6KrD88McYUngrnHcDo/PxS4A6URIlE96Y5P76lXUu8WWQZIZPG s4hL/C89PeyQ15ezIM1Un3uBkrJ/BYDgTeBNka5ivew= =L85k -----END PGP PUBLIC KEY BLOCK----- git-secret-0.5.0/tests/fixtures/gpg/user5@gitsecret.io/000077500000000000000000000000001424706700600230435ustar00rootroot00000000000000git-secret-0.5.0/tests/fixtures/gpg/user5@gitsecret.io/private.key000066400000000000000000000070441424706700600252340ustar00rootroot00000000000000-----BEGIN PGP PRIVATE KEY BLOCK----- lQPGBF1yX48BCAC7TVKvW81RjJKcGI21cI1iUEPkpWCqXwUjt9UsJ8g+2BW45gmX 9tLKPp5ax6hJoLQpcSkOsKcNdigSwHeB+TjIgGshAQOgOXLgnU6oETkobxrv3TcQ L0gF09jgnUvdzaCSgqtLndgejG1g5SsYIzzHYSTAj/7t5WY2AQKVsiE9pELxUqLB QQQ97YHklp26sNXT9FYBNZvLN661PvTB2fgMxMrLkE0i8brAC51zyp0/PCy7huDz 9zjryMCReKkwfVIpevBJspHx1P2HLNe+b+O28C4U0r8CuWSk116itbfKGCtWL8LL khMUBD4j+6zO1E33HVeRR6hypU8ZhbDIX9BzABEBAAH+BwMCrMDlojZX/jjr0l3U 8acJEKVGWAq8dxt+UKNm5PSNZksQdcsz4E1JL/4JitfRhvrH24OGJnGrmMYeQJjH Dw+dHUf8UDD8KpRigihCug44VM36ZtiCxfQ8+x01DQ8G6dntZmphg6B0dJbvhUJa YEuRk1n5rVH1lMEitq3ZcnvnU4hJxWfKdo8qI+MReaiVtODk42y0kA6/7y+w+a1j 7wWtVsdHvvC5f698Z0FKzSGxHWGgE2bFWaRxhuX0WIBMgDsr2H+jcvb51c3SIWkd eCTupBomcv99FYcBUHf4VnjJGgBn4ibU49BZtMbmTHeB4bNb/hTCwhWuW50mr2yt GZ/Ued2y6khcaDXlsQGdqUn7/4KEe3vpwVU6RzKrxBMhaY2zZdwVEAb9c/2szSt6 +YOhopOmH23lWF5iu2pdRcU9pJtj614tpIGOLC4H8e+im+buy+jOIvj6eECH50zK zHchOvrCWAG4qcVTSAv2J2Ywa1wzKxUfoPbpCZJ7pJvt2pjxa2Mh1vjlydle4/Tq 6qcu4OONdJPiDu2n0DvThfZXxWPqYrQKNPok/uIuOyux3U3JKgBdCKW9wj6wXvik TakIRvsPjMsTkyP5J7GoFokw/7tTd8fww6+HK7o171+bT1/oEmp+ulE/U5mcaVTw uabWtLt9gignidle6R4GlVI/xo/J/szcQyiv9/MA1z0tC5FIM2HYF4ADg2de8MbE dQKyNZxkAoFtofE8WDsMVf/C2BzTpLp9yqTGhZptCWlkU+OpBxLaVIa1tlw0mbt0 PWujKEatkdFOHhuutjLCWGiB84FKkPPti0YkfJxPxbXDMa2p7KvCSSrrkZM2mKBq 13hcLm4ANUWQCFJHpCriMg79xLSL6zEL4Lt6V+Soi1dDtH5jwox+SsC273BZXyq8 rjOisteYwarjtBd1c2VyNSAoY29tbWVudCBjb21tZW50KYkBTgQTAQgAOBYhBPbR jRmpf0xIpd59km5RnYONIUgfBQJdcl+PAhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4B AheAAAoJEG5RnYONIUgfhQQH/38uO9hvFdc72UnYjCADZXvdSa1T+vSKJfF9Sa+D Se2F3JlwYPvpDnEovMmi7RuUJ1n7mGzTFJ6HLHs4Z26P6VtmC2e3ue2/OltK24zd zeH80WfGmFfJ1cFShO5mGEk+ga3HhhCHPE9zkEM+HO+Dn+IDBuJL4PAvu6c6buVo K9GDbo7tkCFB1+vw39CmEmnPuIoGygliJxKqiqHsS/Jn4KkNyecT8z5xaA41lGdA Zbda6og4u0vsj7Uctder22tdVKDWg1Jwr23ORBYCD2ssQKUq31G/kvQeZxCTdZD8 t/V3pQz0uru/c/NvVLX1eZDXwM+viR/Ck5oyTETkHF9LZNedA8YEXXJfjwEIAMxn JVMiOyZfPclOt1oQv51vrmbWyiKHSNn9OwtW2HQIWXT5cpA76ojceLxF2Gz3Lr8k 5ZqJQZb2jTB/HGDeJMVOQobsfJLD2llM99PFFdE/lAlu+/jQp90hu/gLo9egu+aI ZP6YRmvJMLseB8t22dWGb8OpnZgTzAL9uk8vhYzMLGCiOezC0pzxKCDsIfBtpHDy b9Z06cD4hywvtaRCJOXanUhv2rbPEcNRoYqY3kFlaV37NxMRyCplODq6HmrsxsUp hJmHA227HtBHJzJtRcewyOcvHE3TovynDPDNtk+KtvZfiqvvKDwEXjrygYiB/xZP iFvT5f4xB6hicJq8+78AEQEAAf4HAwJRNs0fBsU0LOueT8yhsPFyxg+XYBeAR5Hx NyCFrIXaDSTY+TrTpbY0o2wrBgZtI+YAuVCgqkmQDzp8Dhb21Dcx2Zg4xJ92KHcE dwq/VMz9l5l6JgfEg7Dt8XUCeetYKEkX/li9Q9urwBpZ3oPIjjhZoK74zfGA0Qtk qRYCXHhBVme7pxAfirmX0jiLbDv5nV+fzJXqTzY/Zsaodw0w9CiuzZ5ftM7kk7QH TGEeGB0yaEgm7LPupGxfkHnY7IU7f1g4e7QhQcFSHady2HrtEVYFgsdlxxCxSFzK G3zctVTTTQKb67zVNKtblizSHRq21gx/uutReh+RZUhTJewfpOpup7e9oNDxpkSW nkiHU91vNaOfdfuID7V6eIYKM3yCvrc5z9NKBYklGX2wYm9qEObBF1LrQD2c/M/+ Rn6gnJLdUo0Q95URwngCrchz1i7MVWje3VfsuiHRsB62NFLOGeDqkdoJ7PPCRHeS WXaZUK7/a7B6wZuf4fafEVWSpgonWvL3bxCLlPau5zYvo40WLzFtIVT6gBCR/TBY AhUVrrvn1Ssqrz1RRD7ebbFR59yDsEyJaL4cdJzVidB4+tp9XAJ0yjiGJyCJW5NR eW0dR1jHDacBPMnxgqKtXpn7d0PMx0oghD0wFiQsGqi6aWJs8+qGWugCoHZUiJB2 R/N0MO7l4CuJYECSIiVqgu08h7ZQ3CgROGEFVYaBmkX50DFwLe9FkurOE83jNiJE d7QKhc2IE6RQ0j9bS7GcBkNjED7jUCryLbwI8ITekHnSt0BiFnVb9rZ3cMYNArcS 5rDZ4JQYsqGiGb03VZqW9VXD/40tTtkLU5EaN9tgroQiHovCfLiug4WbRYz26wZF cnMHaQCPHYAKme72bAypjzooN4KT5KE8uyNQo3/1eEwd2AKRFEl4f2uBTNqJATYE GAEIACAWIQT20Y0ZqX9MSKXefZJuUZ2DjSFIHwUCXXJfjwIbDAAKCRBuUZ2DjSFI H+agCACVQyt3pbCPgJ8CXXhMaaH0Y16DJDxy/AXzQL7hxHzgqIrHuOygADCXvMcH pb6kznMG4pVfeNZtm+FDoQ7rDPcY9T9eSQD6Fw2hzemysdWAoD9ZUNwynw125Og7 nmOmXIJLQ58J0bDVfb34zwYfdE45LTaQXO2ODx4foMpzCv86XUE4GboQSnUrU1VN afrbVTSZ7Zna6yNzgtCVomSjxDhCZ+nnYQsTwXqERqby8v2KpgWM3yVV84q2ED2N 51JUIdXFjejFyHWjDHYfYPo4s/I75gYKsTCFo9lGqkcVKX13HMCI7J4KGrmxLVJq swK2XO60K8/knDo78U2RvVf+Goat =9tu1 -----END PGP PRIVATE KEY BLOCK----- git-secret-0.5.0/tests/fixtures/gpg/user5@gitsecret.io/public.key000066400000000000000000000033051424706700600250340ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- mQENBF1yX48BCAC7TVKvW81RjJKcGI21cI1iUEPkpWCqXwUjt9UsJ8g+2BW45gmX 9tLKPp5ax6hJoLQpcSkOsKcNdigSwHeB+TjIgGshAQOgOXLgnU6oETkobxrv3TcQ L0gF09jgnUvdzaCSgqtLndgejG1g5SsYIzzHYSTAj/7t5WY2AQKVsiE9pELxUqLB QQQ97YHklp26sNXT9FYBNZvLN661PvTB2fgMxMrLkE0i8brAC51zyp0/PCy7huDz 9zjryMCReKkwfVIpevBJspHx1P2HLNe+b+O28C4U0r8CuWSk116itbfKGCtWL8LL khMUBD4j+6zO1E33HVeRR6hypU8ZhbDIX9BzABEBAAG0F3VzZXI1IChjb21tZW50 IGNvbW1lbnQpiQFOBBMBCAA4FiEE9tGNGal/TEil3n2SblGdg40hSB8FAl1yX48C GwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQblGdg40hSB+FBAf/fy472G8V 1zvZSdiMIANle91JrVP69Iol8X1Jr4NJ7YXcmXBg++kOcSi8yaLtG5QnWfuYbNMU nocsezhnbo/pW2YLZ7e57b86W0rbjN3N4fzRZ8aYV8nVwVKE7mYYST6BrceGEIc8 T3OQQz4c74Of4gMG4kvg8C+7pzpu5Wgr0YNuju2QIUHX6/Df0KYSac+4igbKCWIn EqqKoexL8mfgqQ3J5xPzPnFoDjWUZ0Blt1rqiDi7S+yPtRy116vba11UoNaDUnCv bc5EFgIPayxApSrfUb+S9B5nEJN1kPy39XelDPS6u79z829UtfV5kNfAz6+JH8KT mjJMROQcX0tk17kBDQRdcl+PAQgAzGclUyI7Jl89yU63WhC/nW+uZtbKIodI2f07 C1bYdAhZdPlykDvqiNx4vEXYbPcuvyTlmolBlvaNMH8cYN4kxU5Chux8ksPaWUz3 08UV0T+UCW77+NCn3SG7+Auj16C75ohk/phGa8kwux4Hy3bZ1YZvw6mdmBPMAv26 Ty+FjMwsYKI57MLSnPEoIOwh8G2kcPJv1nTpwPiHLC+1pEIk5dqdSG/ats8Rw1Gh ipjeQWVpXfs3ExHIKmU4OroeauzGxSmEmYcDbbse0EcnMm1Fx7DI5y8cTdOi/KcM 8M22T4q29l+Kq+8oPAReOvKBiIH/Fk+IW9Pl/jEHqGJwmrz7vwARAQABiQE2BBgB CAAgFiEE9tGNGal/TEil3n2SblGdg40hSB8FAl1yX48CGwwACgkQblGdg40hSB/m oAgAlUMrd6Wwj4CfAl14TGmh9GNegyQ8cvwF80C+4cR84KiKx7jsoAAwl7zHB6W+ pM5zBuKVX3jWbZvhQ6EO6wz3GPU/XkkA+hcNoc3psrHVgKA/WVDcMp8NduToO55j plyCS0OfCdGw1X29+M8GH3ROOS02kFztjg8eH6DKcwr/Ol1BOBm6EEp1K1NVTWn6 21U0me2Z2usjc4LQlaJko8Q4Qmfp52ELE8F6hEam8vL9iqYFjN8lVfOKthA9jedS VCHVxY3oxch1owx2H2D6OLPyO+YGCrEwhaPZRqpHFSl9dxzAiOyeChq5sS1SarMC tlzutCvP5Jw6O/FNkb1X/hqGrQ== =ghZU -----END PGP PUBLIC KEY BLOCK----- git-secret-0.5.0/tests/test_add.bats000066400000000000000000000144641424706700600174050ustar00rootroot00000000000000#!/usr/bin/env bats load _test_base function setup { install_fixture_key "$TEST_DEFAULT_USER" set_state_initial set_state_git set_state_secret_init set_state_secret_tell "$TEST_DEFAULT_USER" } function teardown { uninstall_fixture_key "$TEST_DEFAULT_USER" unset_current_state } @test "run 'add' normally" { # Preparations: local filename="$TEST_DEFAULT_FILENAME" echo "content" > "$filename" run git secret add "$filename" [ "$status" -eq 0 ] # Ensuring that path mappings was set correctly: local path_mappings path_mappings=$(_get_secrets_dir_paths_mapping) local files_list files_list=$(cat "$path_mappings") [ "$files_list" = "$filename" ] # Cleaning up: rm "$filename" ".gitignore" } @test "run 'add' with bad arg" { local test_file="$TEST_DEFAULT_FILENAME" touch "$test_file" echo "content" > "$test_file" run git secret add -Z "$test_file" [ "$status" -ne 0 ] rm "$test_file" } @test "run 'add' for file ignored by default" { local test_file="$TEST_DEFAULT_FILENAME" touch "$test_file" echo "content" > "$test_file" run git secret add "$test_file" [ "$status" -eq 0 ] rm "$test_file" } @test "run 'add' for file ignored with '-i' and '.gitignore' contents" { local test_file="$TEST_DEFAULT_FILENAME" touch "$test_file" echo "content" > "$test_file" local quoted_name quoted_name=$(printf '%q' "$test_file") # add -i is now a no-op (See #225) so this tests that -i does nothing. run git secret add -i "$test_file" [ "$status" -eq 0 ] run file_has_line "$quoted_name" ".gitignore" [ "$output" = '0' ] local expected=.gitsec/keys/random_seed$'\n'\!\*.sec$'\n'$quoted_name echo "$expected" > '.expected' [ "$(cmp '.expected' '.gitignore'; echo $?)" -eq 0 ] rm "$test_file" '.expected' } @test "run 'add' for file ignored by default and with '-i' in subfolder" { # This test covers this issue: # https://github.com/sobolevn/git-secret/issues/85 task 1 if [[ "$BATS_RUNNING_FROM_GIT" -eq 1 ]]; then # See #334 for more about this skip "this test is skipped while 'git commit'" fi # Preparations: local test_dir='test_dir' local nested_dir="$test_dir/adding" local current_dir="$PWD" mkdir -p "$nested_dir" cd "$nested_dir" local test_file='test_file.auto_ignore' touch "$test_file" echo "content" > "$test_file" # Test commands: run git secret add -i "$test_file" [ "$status" -eq 0 ] [[ -f "$current_dir/.gitignore" ]] run file_has_line "$nested_dir/$test_file" "$current_dir/.gitignore" [ "$output" = '0' ] # .gitignore was not created: [[ ! -f ".gitignore" ]] # Cleaning up: cd "$current_dir" rm -r "$test_dir" } @test "run 'add' for relative path" { if [[ "$BATS_RUNNING_FROM_GIT" -eq 1 ]]; then skip "this test is skipped while 'git commit'. See #334" fi # Preparations: local root='test_dir' local node="$root/node" local sibling="$root/sibling" local test_file="$node/$TEST_DEFAULT_FILENAME" local current_dir="$PWD" mkdir -p "$node" mkdir -p "$sibling" echo "content" > "$test_file" cd "$sibling" # Testing: run git secret add "../node/$TEST_DEFAULT_FILENAME" [ "$status" -eq 0 ] [[ "$output" == *"git-secret: 1 item(s) added."* ]] # Testing mappings content: local path_mappings path_mappings=$(_get_secrets_dir_paths_mapping) local files_list files_list=$(cat "$path_mappings") [ "$files_list" = "$test_file" ] # Cleaning up: cd "$current_dir" rm -r "$root" } @test "run 'add' for file in subfolder" { if [[ "$BATS_RUNNING_FROM_GIT" -eq 1 ]]; then # See #334 for more about this skip "this test is skipped while 'git commit'" fi # Preparations: local test_file="$TEST_DEFAULT_FILENAME" local test_dir='test_dir' mkdir -p "$test_dir" touch "$test_dir/$test_file" echo "content" > "$test_dir/$test_file" # Testing: run git secret add "$test_dir/$test_file" [ "$status" -eq 0 ] [[ "$output" == *"git-secret: 1 item(s) added."* ]] # Cleaning up: rm -r "$test_dir" } @test "run 'add' twice for one file" { # Preparations: local filename="$TEST_DEFAULT_FILENAME" echo "content" > "$filename" # Testing: run git secret add "$filename" run git secret add "$filename" [ "$status" -eq 0 ] [[ "$output" = *"git-secret: 0 item(s) added."* ]] # Ensuring that path mappings was set correctly: local path_mappings path_mappings=$(_get_secrets_dir_paths_mapping) local files_list files_list=$(cat "$path_mappings") [ "$files_list" = "$filename" ] # Cleaning up: rm "$filename" ".gitignore" } @test "run 'add' for multiple files, and test .gitignore contents" { # Preparations: local filename1="$TEST_DEFAULT_FILENAME" echo "content1" > "$filename1" local filename2="$TEST_SECOND_FILENAME" echo "content2" > "$filename2" # Testing: run git secret add "$filename1" "$filename2" [ "$status" -eq 0 ] [[ "$output" = *"git-secret: 2 item(s) added."* ]] # there may be additional lines too # test .gitignore has 4 lines as expected local gitignore_linecount gitignore_linecount=$(wc -l < .gitignore) [ "$gitignore_linecount" -eq 4 ] # two added by `git secret init`, and one for each `added` file # Cleaning up: rm "$filename1" "$filename2" ".gitignore" } @test "run 'add -v' for multiple files" { # Preparations: local filename1="$TEST_DEFAULT_FILENAME" echo "content1" > "$filename1" local filename2="$TEST_SECOND_FILENAME" echo "content2" > "$filename2" # Testing: run git secret add -v "$filename1" "$filename2" [ "$status" -eq 0 ] [[ "$output" == *"git-secret: adding file: ${TEST_DEFAULT_FILENAME}"* ]] [[ "$output" == *"git-secret: adding file: ${TEST_SECOND_FILENAME}"* ]] [[ "$output" == *"git-secret: 2 item(s) added."* ]] # Cleaning up: rm "$filename1" "$filename2" ".gitignore" } @test "run 'add' for file with special chars" { # Preparations: local filename="$TEST_FOURTH_FILENAME" echo "content" > "$filename" run git secret add "$filename" [ "$status" -eq 0 ] # Ensuring that path mappings was set correctly: local path_mappings path_mappings=$(_get_secrets_dir_paths_mapping) local files_list files_list=$(cat "$path_mappings") [ "$files_list" = "$filename" ] # Ensuring the file is correctly git-ignored run git check-ignore "$filename" [ "$status" -eq 0 ] # Cleaning up: rm "$filename" ".gitignore" } git-secret-0.5.0/tests/test_cat.bats000066400000000000000000000041571424706700600174220ustar00rootroot00000000000000#!/usr/bin/env bats # shellcheck disable=SC2030,SC2031 # above is to avoid shellcheck info warnings that we don't understand load _test_base FILE_TO_HIDE="$TEST_DEFAULT_FILENAME" FILE_CONTENTS="hidden content юникод" FINGERPRINT="" function setup { FINGERPRINT=$(install_fixture_full_key "$TEST_DEFAULT_USER") set_state_initial set_state_git set_state_secret_init set_state_secret_tell "$TEST_DEFAULT_USER" set_state_secret_add "$FILE_TO_HIDE" "$FILE_CONTENTS" set_state_secret_hide } function teardown { uninstall_fixture_full_key "$TEST_DEFAULT_USER" "$FINGERPRINT" unset_current_state } @test "run 'cat' with password argument" { local password password=$(test_user_password "$TEST_DEFAULT_USER") run git secret cat -d "$TEST_GPG_HOMEDIR" -p "$password" "$FILE_TO_HIDE" [ "$status" -eq 0 ] # $output is the output from 'git secret cat' above [ "$FILE_CONTENTS" == "$output" ] } @test "run 'cat' with password argument and SECRETS_VERBOSE=1" { local password password=$(test_user_password "$TEST_DEFAULT_USER") SECRETS_VERBOSE=1 run git secret cat -d "$TEST_GPG_HOMEDIR" -p "$password" "$FILE_TO_HIDE" [ "$status" -eq 0 ] # $output _contains_ the output from 'git secret cat', # may have extra output from gpg [[ "$output" == *"$FILE_CONTENTS"* ]] } @test "run 'cat' with wrong filename" { run git secret cat -d "$TEST_GPG_HOMEDIR" -p "$password" NO_SUCH_FILE [ "$status" -eq 1 ] } @test "run 'cat' with bad arg" { local password password=$(test_user_password "$TEST_DEFAULT_USER") run git secret cat -Z -d "$TEST_GPG_HOMEDIR" -p "$password" "$FILE_TO_HIDE" [ "$status" -ne 0 ] } @test "run 'cat' from subdir" { local password password=$(test_user_password "$TEST_DEFAULT_USER") mkdir subdir echo "content2" > subdir/new_filename.txt ( # start subshell for subdir tests cd subdir run git secret add new_filename.txt [ "$status" -eq 0 ] run git secret hide [ "$status" -eq 0 ] run git secret cat -d "$TEST_GPG_HOMEDIR" -p "$password" new_filename.txt [ "$status" -eq 0 ] ) # end subshell, cd back up # clean up rm -rf subdir } git-secret-0.5.0/tests/test_changes.bats000066400000000000000000000130271424706700600202570ustar00rootroot00000000000000#!/usr/bin/env bats load _test_base FILE_TO_HIDE="$TEST_DEFAULT_FILENAME" SECOND_FILE_TO_HIDE="$TEST_SECOND_FILENAME" THIRD_FILE_TO_HIDE="$TEST_THIRD_FILENAME" FILE_NON_EXISTENT="NO-SUCH-FILE" FILE_CONTENTS="hidden content юникод" FINGERPRINT="" function setup { FINGERPRINT=$(install_fixture_full_key "$TEST_DEFAULT_USER") set_state_initial set_state_git set_state_secret_init set_state_secret_tell "$TEST_DEFAULT_USER" set_state_secret_add "$FILE_TO_HIDE" "$FILE_CONTENTS" set_state_secret_add "$SECOND_FILE_TO_HIDE" "$FILE_CONTENTS" set_state_secret_hide } function teardown { rm "$FILE_TO_HIDE" "$SECOND_FILE_TO_HIDE" uninstall_fixture_full_key "$TEST_DEFAULT_USER" "$FINGERPRINT" unset_current_state } @test "run 'changes' on one file with no file changed" { local password password=$(test_user_password "$TEST_DEFAULT_USER") run git secret changes -d "$TEST_GPG_HOMEDIR" -p "$password" "$FILE_TO_HIDE" [ "$status" -eq 0 ] local num_lines num_lines=$(echo "$output" | wc -l) [[ "$num_lines" -eq 1 ]] } @test "run 'changes' with one file changed" { local new_content='new content' echo "$new_content" >> "$FILE_TO_HIDE" local password password=$(test_user_password "$TEST_DEFAULT_USER") run git secret changes -d "$TEST_GPG_HOMEDIR" -p "$password" "$FILE_TO_HIDE" [ "$status" -eq 0 ] # Testing that output has both filename and changes: local fullpath fullpath=$(_prepend_root_path "$FILE_TO_HIDE") [[ "$output" == *"changes in $fullpath"* ]] [[ "$output" == *"hidden content юникод"* ]] [[ "$output" == *"+$new_content"* ]] local num_lines num_lines=$(echo "$output" | wc -l) [[ "$num_lines" -eq 6 ]] } @test "run 'changes' with source file missing" { local password password=$(test_user_password "$TEST_DEFAULT_USER") rm "$FILE_TO_HIDE" || _abort "error removing: $FILE_TO_HIDE" run git secret changes -d "$TEST_GPG_HOMEDIR" -p "$password" "$FILE_TO_HIDE" [ "$status" -ne 0 ] } @test "run 'changes' with hidden file missing" { local password local encrypted_file password=$(test_user_password "$TEST_DEFAULT_USER") encrypted_file=$(_get_encrypted_filename "$FILE_TO_HIDE") rm "$encrypted_file" || _abort "error removing: $encrypted_file" run git secret changes -d "$TEST_GPG_HOMEDIR" -p "$password" "$FILE_TO_HIDE" [ "$status" -ne 0 ] } @test "run 'changes' with one file changed (with deletions)" { local new_content='replace' local password password=$(test_user_password "$TEST_DEFAULT_USER") echo "$new_content" > "$FILE_TO_HIDE" run git secret changes -d "$TEST_GPG_HOMEDIR" -p "$password" "$FILE_TO_HIDE" [ "$status" -eq 0 ] # Testing that output has both filename and changes: local fullpath fullpath=$(_prepend_root_path "$FILE_TO_HIDE") [[ "$output" == *"changes in $fullpath"* ]] [[ "$output" == *"-$FILE_CONTENTS"* ]] [[ "$output" == *"+$new_content"* ]] } @test "run 'changes' on two files with no file changed" { local password password=$(test_user_password "$TEST_DEFAULT_USER") run git secret changes -d "$TEST_GPG_HOMEDIR" -p "$password" [ "$status" -eq 0 ] local num_lines num_lines=$(echo "$output" | wc -l) [[ "$num_lines" -eq 2 ]] } @test "run 'changes' with multiple files changed" { local new_content='new content' local second_new_content='something different' local password password=$(test_user_password "$TEST_DEFAULT_USER") echo "$new_content" >> "$FILE_TO_HIDE" echo "$second_new_content" >> "$SECOND_FILE_TO_HIDE" run git secret changes -d "$TEST_GPG_HOMEDIR" -p "$password" [ "$status" -eq 0 ] # Testing that output has both filename and changes: local fullpath fullpath=$(_prepend_root_path "$FILE_TO_HIDE") [[ "$output" == *"changes in $fullpath"* ]] [[ "$output" == *"+$new_content"* ]] local second_path second_path=$(_prepend_root_path "$SECOND_FILE_TO_HIDE") [[ "$output" == *"changes in $second_path"* ]] [[ "$output" == *"+$second_new_content"* ]] } @test "run 'changes' with multiple selected files changed" { local new_content='new content' local second_new_content='something different' echo "$new_content" >> "$FILE_TO_HIDE" echo "$second_new_content" >> "$SECOND_FILE_TO_HIDE" local password password=$(test_user_password "$TEST_DEFAULT_USER") run git secret changes -d "$TEST_GPG_HOMEDIR" -p "$password" \ "$FILE_TO_HIDE" "$SECOND_FILE_TO_HIDE" [ "$status" -eq 0 ] # Testing that output has both filename and changes: local fullpath fullpath=$(_prepend_root_path "$FILE_TO_HIDE") [[ "$output" == *"changes in $fullpath"* ]] [[ "$output" == *"+$new_content"* ]] local second_path second_path=$(_prepend_root_path "$SECOND_FILE_TO_HIDE") [[ "$output" == *"changes in $second_path"* ]] [[ "$output" == *"+$second_new_content"* ]] } @test "run 'changes' on file that does not exist" { local password password=$(test_user_password "$TEST_DEFAULT_USER") run git secret changes \ -d "$TEST_GPG_HOMEDIR" \ -p "$password" \ "$FILE_NON_EXISTENT" [ "$status" -ne 0 ] } @test "run 'changes' on one file without newlines" { set_state_secret_add_without_newline "$THIRD_FILE_TO_HIDE" "$FILE_CONTENTS" set_state_secret_hide local password password=$(test_user_password "$TEST_DEFAULT_USER") run git secret changes \ -d "$TEST_GPG_HOMEDIR" \ -p "$password" \ "$THIRD_FILE_TO_HIDE" [ "$status" -eq 0 ] local num_lines num_lines=$(echo "$output" | wc -l) [[ "$num_lines" -eq 1 ]] rm -f "$THIRD_FILE_TO_HIDE" } @test "run 'changes' with bad arg" { run git secret changes -Z [ "$status" -ne 0 ] } git-secret-0.5.0/tests/test_clean.bats000066400000000000000000000037731424706700600177400ustar00rootroot00000000000000#!/usr/bin/env bats load _test_base FIRST_FILE="$TEST_DEFAULT_FILENAME" SECOND_FILE="$TEST_SECOND_FILENAME" function setup { install_fixture_key "$TEST_DEFAULT_USER" set_state_initial set_state_git set_state_secret_init set_state_secret_tell "$TEST_DEFAULT_USER" set_state_secret_add "$FIRST_FILE" "somecontent" set_state_secret_add "$SECOND_FILE" "somecontent2" set_state_secret_hide } function teardown { # This also needs to be cleaned: rm "$FIRST_FILE" "$SECOND_FILE" uninstall_fixture_key "$TEST_DEFAULT_USER" unset_current_state } function _secret_files_exists { echo "$(find . -type f -name "*.$SECRETS_EXTENSION" \ -print0 2>/dev/null | grep -q .; echo "$?")" } @test "run 'clean' normally" { run git secret clean [ "$status" -eq 0 ] # There must be no .secret files: [ "$(_secret_files_exists)" -ne 0 ] } @test "run 'clean' with extra filename" { run git secret clean extra_filename [ "$status" -ne 0 ] } @test "run 'clean' with bad arg" { run git secret clean -Z [ "$status" -ne 0 ] } @test "run 'clean' with '-v'" { run git secret clean -v [ "$status" -eq 0 ] # There must be no .secret files: [ "$(_secret_files_exists)" -ne 0 ] local first_filename local second_filename first_filename=$(_get_encrypted_filename "$FIRST_FILE") second_filename=$(_get_encrypted_filename "$SECOND_FILE") # Output must be verbose: [[ "$output" == *"deleted"* ]] [[ "$output" == *"$first_filename"* ]] [[ "$output" == *"$second_filename"* ]] } # this test is like above, but uses SECRETS_VERBOSE env var @test "run 'clean' with 'SECRETS_VERBOSE=1'" { SECRETS_VERBOSE=1 run git secret clean [ "$status" -eq 0 ] # Output must be verbose: [[ "$output" == *"deleted:"* ]] } # this test is like above, but sets SECRETS_VERBOSE env var to 0 # and expected non-verbose output @test "run 'clean' with 'SECRETS_VERBOSE=0'" { SECRETS_VERBOSE=0 run git secret clean [ "$status" -eq 0 ] # Output must not be verbose: [[ "$output" != *"cleaning"* ]] } git-secret-0.5.0/tests/test_expiration.bats000066400000000000000000000036071424706700600210340ustar00rootroot00000000000000#!/usr/bin/env bats export TZ="GMT" load _test_base function setup { install_fixture_key "$TEST_EXPIRED_USER" set_state_initial set_state_git set_state_secret_init set_state_secret_tell "$TEST_EXPIRED_USER" } function teardown { uninstall_fixture_key "$TEST_EXPIRED_USER" unset_current_state } @test "run 'hide' using expired key" { FILE_TO_HIDE="$TEST_DEFAULT_FILENAME" FILE_CONTENTS="hidden content юникод" set_state_secret_add "$FILE_TO_HIDE" "$FILE_CONTENTS" run git secret hide # this will fail, because we're using an expired key # echo "$output" | sed "s/^/# '$BATS_TEST_DESCRIPTION' output: /" >&3 # output will look like: # 'abort: problem encrypting file with gpg: exit code 2: space file' # echo "# status of hide: $status" >&3 [ $status -ne 0 ] # we expect failure here. Actual code is 2 } @test "run 'whoknows' using expired key" { run git secret whoknows [ $status -eq 0 ] } @test "run 'whoknows -l' on only expired user" { run git secret whoknows -l [ "$status" -eq 0 ] # diag output for bats-core # echo "$output" | sed "s/^/# '$BATS_TEST_DESCRIPTION' output: /" >&3 # output should look like 'abort: problem encrypting file with gpg: exit code 2: space file' # echo "# $BATS_TEST_DESCRIPTION: $status" >&3 # Now test the output, both users should be present: [[ "$output" == *"$TEST_EXPIRED_USER (expires: 2018-09-23)"* ]] } @test "run 'whoknows -l' on normal key and expired key" { install_fixture_key "$TEST_DEFAULT_USER" set_state_secret_tell "$TEST_DEFAULT_USER" run git secret whoknows -l [ "$status" -eq 0 ] #echo "$output" | sed "s/^/# '$BATS_TEST_DESCRIPTION' output: /" >&3 # Now test the output, both users should be present: [[ "$output" == *"$TEST_DEFAULT_USER (expires: never)"* ]] [[ "$output" == *"$TEST_EXPIRED_USER (expires: 2018-09-23)"* ]] uninstall_fixture_key "$TEST_DEFAULT_USER" } git-secret-0.5.0/tests/test_hide.bats000066400000000000000000000204541424706700600175620ustar00rootroot00000000000000#!/usr/bin/env bats load _test_base FILE_TO_HIDE="$TEST_DEFAULT_FILENAME" FILE_CONTENTS="hidden content юникод" function setup { install_fixture_key "$TEST_DEFAULT_USER" set_state_initial set_state_git set_state_secret_init set_state_secret_tell "$TEST_DEFAULT_USER" set_state_secret_add "$FILE_TO_HIDE" "$FILE_CONTENTS" } function teardown { rm "$FILE_TO_HIDE" uninstall_fixture_key "$TEST_DEFAULT_USER" unset_current_state } @test "run 'hide' normally" { run git secret hide # echo "$output" | sed "s/^/# '$BATS_TEST_DESCRIPTION' output: /" >&3 # Command must execute normally: [ "$status" -eq 0 ] [[ "$output" == *"git-secret: done. 1 of 1 files are hidden."* ]] # New file must be created: local new_file new_file="$(_get_encrypted_filename "$FILE_TO_HIDE")" [ -f "$new_file" ] # File must be a binary: local mime mime="$(file --mime-type --mime-encoding "$new_file" | grep 'charset=binary')" [ -n "$mime" ] } @test "run 'hide' with SECRETS_GPG_ARMOR=1" { SECRETS_GPG_ARMOR=1 run git secret hide # Command must execute normally: [ "$status" -eq 0 ] [[ "$output" == *"git-secret: done. 1 of 1 files are hidden."* ]] # New file must be created: local new_file new_file="$(_get_encrypted_filename "$FILE_TO_HIDE")" [ -f "$new_file" ] # File must be a text: local mime mime="$(file --mime-type --mime-encoding "$new_file" | grep 'charset=us-ascii')" [ -n "$mime" ] } @test "run 'hide' with extra filename" { run git secret hide extra_filename [ "$status" -ne 0 ] } @test "run 'hide' with bad arg" { run git secret hide -Z [ "$status" -ne 0 ] } @test "run 'hide' normally with SECRETS_VERBOSE=1" { SECRETS_VERBOSE=1 run git secret hide # Command must execute normally. [ "$status" -eq 0 ] [[ "$output" == *"git-secret: done. 1 of 1 files are hidden."* ]] } @test "run 'hide' with '-P'" { # attempt to alter permissions on input file chmod o-rwx "$FILE_TO_HIDE" run git secret hide -P # echo "$output" | sed "s/^/# '$BATS_TEST_DESCRIPTION' output: /" >&3 # Command must execute normally: [ "$status" -eq 0 ] [[ "$output" == *"git-secret: done. 1 of 1 files are hidden."* ]] # New files should be created: local encrypted_file encrypted_file=$(_get_encrypted_filename "$FILE_TO_HIDE") [ -f "$encrypted_file" ] ## permissions should match. local secret_perm local file_perm file_perm=$($SECRETS_OCTAL_PERMS_COMMAND "$FILE_TO_HIDE") secret_perm=$($SECRETS_OCTAL_PERMS_COMMAND "$encrypted_file") # echo "# '$BATS_TEST_DESCRIPTION': $secret_perm, file_perm: $file_perm" >&3 [ "$secret_perm" = "$file_perm" ] } @test "run 'hide' from inside subdirectory" { if [[ "$BATS_RUNNING_FROM_GIT" -eq 1 ]]; then # See #334 for more about this skip "this test is skipped while 'git commit'" fi # Preparations: local root_dir='test_sub_dir' mkdir -p "$root_dir" local second_file="$root_dir/second_file.txt" local second_content="some content" set_state_secret_add "$second_file" "$second_content" # Verify that the second file is there: [ -f "$second_file" ] ( # start subshell for following commands # cd into the subdir cd "$root_dir" # Now it should hide 2 files: run git secret hide [ "$status" -eq 0 ] ) # end subshell, return to .. # clean up rm -rf "$root_dir" } @test "run 'hide' with missing file" { # Preparations: local second_file="$TEST_SECOND_FILENAME" local second_content="some content" set_state_secret_add "$second_file" "$second_content" # now remove the second file to cause failure rm -f "$second_file" # Now it should return an error because one file can't be found run git secret hide [ "$status" -ne 0 ] [ "$output" != "git-secret: done. 2 of 2 files are hidden." ] } @test "run 'hide' with multiple files" { # Preparations: local second_file="$TEST_SECOND_FILENAME" local second_content="some content" set_state_secret_add "$second_file" "$second_content" # Now it should hide 2 files: run git secret hide #echo "$output" | sed "s/^/# '$BATS_TEST_DESCRIPTION' output: /" >&3 [ "$status" -eq 0 ] [[ "$output" == *"git-secret: done. 2 of 2 files are hidden."* ]] # Cleaning up: rm "$second_file" } @test "run 'hide' with '-m'" { run git secret hide -m # Command must execute normally: [ "$status" -eq 0 ] # git secret hide -m: uses temp file so cleaning should take place, # but we only show tmp file cleanup in VERBOSE mode [[ "$output" == *"git-secret: done. 1 of 1 files are hidden."* ]] # New files should be created: [ -f "$(_get_encrypted_filename "$FILE_TO_HIDE")" ] } @test "run 'hide' with '-m' twice" { local path_mappings path_mappings=$(_get_secrets_dir_paths_mapping) run git secret hide -m # echo "$output" | sed "s/^/# '$BATS_TEST_DESCRIPTION' output: /" >&3 # Command must execute normally: [ "$status" -eq 0 ] # git secret hide -m: uses temp file so cleaning should take place, # but we only show tmp file cleanup in VERBOSE mode [[ "$output" == *"git-secret: done. 1 of 1 files are hidden."* ]] # back path mappings cp "${path_mappings}" "${path_mappings}.bak" # run hide again run git secret hide -m # compare [ "$status" -eq 0 ] [[ "${#lines[@]}" -eq 1 ]] # output says 0 of 1 files are hidden because checksum didn't change # and we didn't need to hide it again. [[ "$output" == *"git-secret: done. 0 of 1 files are hidden."* ]] # no changes should occur to path_mappings files cmp -s "${path_mappings}" "${path_mappings}.bak" # New files should be created: [ -f "$(_get_encrypted_filename "$FILE_TO_HIDE")" ] } @test "run 'hide' without then with '-m'" { local path_mappings path_mappings=$(_get_secrets_dir_paths_mapping) run git secret hide #echo "$output" | sed "s/^/# '$BATS_TEST_DESCRIPTION' output: /" >&3 # Command must execute normally: [ "$status" -eq 0 ] # git secret hide -m: uses temp file so cleaning should take place, # but we only show tmp file cleanup in VERBOSE mode [[ "$output" == *"git-secret: done. 1 of 1 files are hidden."* ]] # back path mappings cp "${path_mappings}" "${path_mappings}.bak" # run hide again run git secret hide -m # compare [ "$status" -eq 0 ] [[ "${#lines[@]}" -eq 1 ]] # output says 0 of 1 files are hidden because checksum didn't change # and we didn't need to hide it again. [[ "$output" == *"git-secret: done. 0 of 1 files are hidden."* ]] # no changes should occur to path_mappings files cmp -s "${path_mappings}" "${path_mappings}.bak" # New files should be created: [ -f "$(_get_encrypted_filename "$FILE_TO_HIDE")" ] } @test "run 'hide' with '-c' and '-v'" { # Preparations: local encrypted_filename encrypted_filename=$(_get_encrypted_filename "$FILE_TO_HIDE") set_state_secret_hide # so it would be data to clean run git secret hide -v -c [ "$status" -eq 0 ] # File should be still there (it is not deletion): [ -f "$FILE_TO_HIDE" ] # Output should be verbose: [[ "$output" == *"deleted:"* ]] [[ "$output" == *"$encrypted_filename"* ]] } @test "run 'hide' with '-d'" { run git secret hide -d [ "$status" -eq 0 ] # File must be removed: [ ! -f "$FILE_TO_HIDE" ] } @test "run 'hide' with '-d' and '-v'" { run git secret hide -v -d [ "$status" -eq 0 ] # File must be removed: [ ! -f "$FILE_TO_HIDE" ] # It should be verbose: [[ "$output" == *"removing unencrypted files"* ]] [[ "$output" == *"$FILE_TO_HIDE"* ]] } @test "run 'hide' with '-d' and '-v' and files in subdirectories" { # Preparations: local root_dir='test_sub_dir' mkdir -p "$root_dir" local second_file="$root_dir/$TEST_SECOND_FILENAME" local second_content="some content" set_state_secret_add "$second_file" "$second_content" # Verify that the second file is there: [ -f "$second_file" ] # Now it should hide 2 files: run git secret hide -v -d [ "$status" -eq 0 ] # File must be removed: [ ! -f "$FILE_TO_HIDE" ] [ ! -f "$second_file" ] # It should be verbose: [[ "$output" == *"removing unencrypted files"* ]] [[ "$output" == *"$FILE_TO_HIDE"* ]] [[ "$output" == *"$second_file"* ]] rm -rf "$root_dir" } @test "run 'hide' with multiple users" { install_fixture_key "$TEST_SECOND_USER" set_state_secret_tell "$TEST_SECOND_USER" run git secret hide [ "$status" -eq 0 ] [[ "$output" == *"git-secret: done. 1 of 1 files are hidden."* ]] } git-secret-0.5.0/tests/test_hide_continue.bats000066400000000000000000000023571424706700600214700ustar00rootroot00000000000000#!/usr/bin/env bats load _test_base FILE_TO_HIDE="$TEST_DEFAULT_FILENAME" FILE_TO_HIDE2="$TEST_SECOND_FILENAME" FILE_CONTENTS="hidden content юникод" function setup { install_fixture_key "$TEST_DEFAULT_USER" set_state_initial set_state_git set_state_secret_init set_state_secret_tell "$TEST_DEFAULT_USER" set_state_secret_add "$FILE_TO_HIDE" "$FILE_CONTENTS" set_state_secret_add "$FILE_TO_HIDE2" "$FILE_CONTENTS" } function teardown { rm "$FILE_TO_HIDE" rm "$FILE_TO_HIDE2" uninstall_fixture_key "$TEST_DEFAULT_USER" unset_current_state } @test "run 'hide -F' with missing input file" { mv "$FILE_TO_HIDE" "$FILE_TO_HIDE.was" # move the first file out of the way run git secret hide -F #echo "# output of 'git secret hide -F' is: $output" >&3 # Command must execute normally: [ "$status" -eq 0 ] # secret file for missing file should not be created: local encrypted_file encrypted_file=$(_get_encrypted_filename "$FILE_TO_HIDE") [ ! -f "$encrypted_file" ] # this secret file should be created: local encrypted_file2 encrypted_file2=$(_get_encrypted_filename "$FILE_TO_HIDE2") [ -f "$encrypted_file2" ] # put back first file so teardown() succeeds mv "$FILE_TO_HIDE.was" "$FILE_TO_HIDE" } git-secret-0.5.0/tests/test_init.bats000066400000000000000000000031611424706700600176100ustar00rootroot00000000000000#!/usr/bin/env bats load _test_base function setup { set_state_initial set_state_git } function teardown { unset_current_state } @test "secrets dir env var set as expected" { _TEST_SECRETS_DIR=${SECRETS_DIR:-".gitsecret"} [ "${_TEST_SECRETS_DIR}" = "${_SECRETS_DIR}" ] } @test "run 'init' without '.git'" { remove_git_repository run git secret init [ "$status" -eq 1 ] } @test "run 'init' normally" { run git secret init [ "$status" -eq 0 ] [[ -d "${_SECRETS_DIR}" ]] } @test "run 'init' with extra filename" { run git secret init extra_filename [ "$status" -ne 0 ] } @test "run 'init' with bad arg" { run git secret init -Z [ "$status" -ne 0 ] } @test "run 'init' in subfolder" { # This test covers this issue: # https://github.com/sobolevn/git-secret/issues/83 if [[ "$BATS_RUNNING_FROM_GIT" -eq 1 ]]; then skip "this test is skipped while 'git commit'. See #334" fi # Preparations local test_dir='test_dir' local nested_dir="$test_dir/nested/dirs" local current_dir="$PWD" mkdir -p "$nested_dir" cd "$nested_dir" # Test: run git secret init [ "$status" -eq 0 ] # It should not be created in the current folder: [[ ! -d "${_SECRETS_DIR}" ]] # It should be created here: local secrets_dir secrets_dir=$(_get_secrets_dir) [[ -d "$secrets_dir" ]] # Cleaning up: cd "$current_dir" rm -r "$test_dir" } @test "run 'init' with '.gitsecret' already initialized" { local secrets_dir secrets_dir=$(_get_secrets_dir) mkdir "$secrets_dir" run git secret init [ "$output" = "git-secret: abort: already initialized." ] [ "$status" -eq 1 ] } git-secret-0.5.0/tests/test_list.bats000066400000000000000000000024011424706700600176140ustar00rootroot00000000000000#!/usr/bin/env bats load _test_base FILE_TO_HIDE="file_to_hide" FILE_CONTENTS="hidden content юникод" function setup { install_fixture_key "$TEST_DEFAULT_USER" set_state_initial set_state_git set_state_secret_init set_state_secret_tell "$TEST_DEFAULT_USER" set_state_secret_add "$FILE_TO_HIDE" "$FILE_CONTENTS" } function teardown { rm "$FILE_TO_HIDE" uninstall_fixture_key "$TEST_DEFAULT_USER" unset_current_state } @test "run 'list' normally" { run git secret list [ "$status" -eq 0 ] [ "$output" = "$FILE_TO_HIDE" ] } @test "run 'list' with extra filename" { run git secret list extra_filename [ "$status" -ne 0 ] } @test "run 'list' with bad arg" { run git secret list -Z [ "$status" -ne 0 ] } @test "run 'list' with multiple files" { # Preparations: local second_file="second_file.txt" set_state_secret_add "$second_file" "$FILE_CONTENTS" run git secret list [ "$status" -eq 0 ] # Now it should list two files: [[ "$output" == *"$FILE_TO_HIDE"* ]] [[ "$output" == *"$second_file"* ]] # Cleaning up: rm "$second_file" } @test "run 'list' on empty repo" { git secret remove "$FILE_TO_HIDE" # Running `list` on empty mapping should result an error: run git secret list [ "$status" -eq 1 ] } git-secret-0.5.0/tests/test_main.bats000066400000000000000000000013061424706700600175700ustar00rootroot00000000000000#!/usr/bin/env bats load _test_base function setup { set_state_initial set_state_git } function teardown { unset_current_state } @test "run 'git secret' without command" { run git secret [ "$status" -eq 126 ] } @test "run 'git secret' with bad command" { run git secret notacommand [ "$status" -eq 126 ] } @test "run 'git secret --version'" { run git secret --version [ "$output" == "$GITSECRET_VERSION" ] } @test "run 'git secret --dry-run'" { # We will break things apart, so normally it won't run: rm -r "./.git" # test of 'git secret usage' here removed as it's duplicated in test_usage.bats # Dry run won't fail: run git secret --dry-run [ "$status" -eq 0 ] } git-secret-0.5.0/tests/test_make_install.bats000066400000000000000000000006111424706700600213050ustar00rootroot00000000000000#!/usr/bin/env bats : "${TMPDIR:=/tmp}" INSTALL_BASE="${TMPDIR}/git-secret-test-install" @test "install git-secret to DESTDIR='$INSTALL_BASE'" { rm -f "$INSTALL_BASE/usr/bin/git-secret" cd "$SECRETS_PROJECT_ROOT" # set DESTDIR for this command and 'run' make install DESTDIR="$INSTALL_BASE" run make install [ -x "$INSTALL_BASE/usr/bin/git-secret" ] rm -rf "$INSTALL_BASE" } git-secret-0.5.0/tests/test_noname.bats000066400000000000000000000025611424706700600201250ustar00rootroot00000000000000#!/usr/bin/env bats # These tests using TEST_NONAME_USER, which has a email but no username. # This was originally based on test_remove.bats load _test_base FIRST_FILE="$TEST_DEFAULT_FILENAME" SECOND_FILE="$TEST_SECOND_FILENAME" function setup { install_fixture_key "$TEST_NONAME_USER" set_state_initial set_state_git set_state_secret_init set_state_secret_tell "$TEST_NONAME_USER" set_state_secret_add "$FIRST_FILE" "somecontent" set_state_secret_add "$SECOND_FILE" "somecontent2" set_state_secret_hide } function teardown { rm "$FIRST_FILE" "$SECOND_FILE" uninstall_fixture_key "$TEST_NONAME_USER" unset_current_state } function _has_line { local line="$1" local path_mappings path_mappings=$(_get_secrets_dir_paths_mapping) echo "$(grep -q "$line" "$path_mappings"; echo $?)" } @test "run 'remove' for nameless user normally" { run git secret remove "$SECOND_FILE" [ "$status" -eq 0 ] # Test output: [[ "$output" == *"removed from index."* ]] [[ "$output" == *"ensure that files: [$SECOND_FILE] are now not ignored."* ]] # Mapping should not contain the second file: [ "$(_has_line "$SECOND_FILE")" -eq 1 ] # But the first file must not change: [ "$(_has_line "$FIRST_FILE")" -eq 0 ] # Both files should be present: [ -f "$(_get_encrypted_filename "$FIRST_FILE")" ] [ -f "$(_get_encrypted_filename "$SECOND_FILE")" ] } git-secret-0.5.0/tests/test_remove.bats000066400000000000000000000051571424706700600201510ustar00rootroot00000000000000#!/usr/bin/env bats load _test_base FIRST_FILE="$TEST_DEFAULT_FILENAME" SECOND_FILE="$TEST_SECOND_FILENAME" function setup { install_fixture_key "$TEST_DEFAULT_USER" set_state_initial set_state_git set_state_secret_init set_state_secret_tell "$TEST_DEFAULT_USER" set_state_secret_add "$FIRST_FILE" "somecontent" set_state_secret_add "$SECOND_FILE" "somecontent2" set_state_secret_hide } function teardown { rm "$FIRST_FILE" "$SECOND_FILE" uninstall_fixture_key "$TEST_DEFAULT_USER" unset_current_state } function _has_line { local line="$1" local path_mappings path_mappings=$(_get_secrets_dir_paths_mapping) echo "$(grep -q "$line" "$path_mappings"; echo $?)" } @test "run 'remove' normally" { run git secret remove "$SECOND_FILE" [ "$status" -eq 0 ] # Test output: [[ "$output" == *"removed from index."* ]] [[ "$output" == *"ensure that files: [$SECOND_FILE] are now not ignored."* ]] # Mapping should not contain the second file: [ "$(_has_line "$SECOND_FILE")" -eq 1 ] # But the first file must not change: [ "$(_has_line "$FIRST_FILE")" -eq 0 ] # Both files should be present: [ -f "$(_get_encrypted_filename "$FIRST_FILE")" ] [ -f "$(_get_encrypted_filename "$SECOND_FILE")" ] } @test "run 'remove' with multiple arguments" { run git secret remove "$FIRST_FILE" "$SECOND_FILE" [ "$status" -eq 0 ] [ "$(_has_line "$FIRST_FILE")" -eq 1 ] [ "$(_has_line "$SECOND_FILE")" -eq 1 ] # Both files should be present: [ -f "$(_get_encrypted_filename "$FIRST_FILE")" ] [ -f "$(_get_encrypted_filename "$SECOND_FILE")" ] } @test "run 'remove' with slashes in filename" { # There was a bug with `sed` an slashes: # see https://github.com/sobolevn/git-secret/issues/23 # Preparations: local folder="somedir" local file_in_folder="$folder/$TEST_THIRD_FILENAME" mkdir -p "$folder" set_state_secret_add "$file_in_folder" "somecontent3" set_state_secret_hide # running hide again to hide new data # Now it should remove filename with slashes from the mapping: run git secret remove "$file_in_folder" [ "$status" -eq 0 ] [ "$(_has_line "$file_in_folder")" -eq 1 ] [ -f "$(_get_encrypted_filename "$file_in_folder")" ] # Cleaning up: rm -rf "$folder" } @test "run 'remove' with '-c'" { set_state_secret_hide run git secret remove -c "$SECOND_FILE" [ "$status" -eq 0 ] [ "$(_has_line "$SECOND_FILE")" -eq 1 ] [ -f "$(_get_encrypted_filename "$FIRST_FILE")" ] [ ! -f "$(_get_encrypted_filename "$SECOND_FILE")" ] } @test "run 'remove' with bad arg" { set_state_secret_hide run git secret remove -Z "$SECOND_FILE" [ "$status" -ne 0 ] } git-secret-0.5.0/tests/test_removeperson.bats000066400000000000000000000045711424706700600213770ustar00rootroot00000000000000#!/usr/bin/env bats load _test_base function setup { install_fixture_key "$TEST_DEFAULT_USER" set_state_initial set_state_git set_state_secret_init set_state_secret_tell "$TEST_DEFAULT_USER" } function teardown { uninstall_fixture_key "$TEST_DEFAULT_USER" unset_current_state } @test "run 'removeperson' without arguments" { run git secret removeperson [ "$status" -eq 1 ] } @test "run 'removeperson' with short name" { local name # don't complain about sed # shellcheck disable=SC2001 name=$(echo "$TEST_DEFAULT_USER" | sed -e 's/@.*//') # removeperson must use full email, not short name run git secret removeperson "$name" [ "$status" -eq 1 ] # Then whoknows will be ok because user3@gitsecret.io still knows run git secret whoknows [ "$status" -eq 0 ] # Testing output: [[ "$output" == *"$TEST_DEFAULT_USER"* ]] } @test "run 'removeperson' with email" { local email="$TEST_DEFAULT_USER" run git secret removeperson "$email" [ "$status" -eq 0 ] # Testing output: [[ "$output" == *"$email"* ]] # Then whoknows must return an error with status code 1: run git secret whoknows [ "$status" -eq 1 ] } @test "run 'removeperson' with multiple arguments" { # Adding second user: install_fixture_key "$TEST_SECOND_USER" set_state_secret_tell "$TEST_SECOND_USER" local default_email="$TEST_DEFAULT_USER" local second_email="$TEST_SECOND_USER" run git secret removeperson "$default_email" "$second_email" [ "$status" -eq 0 ] # Testing output: [[ "$output" == *"$default_email"* ]] [[ "$output" == *"$second_email"* ]] # Nothing to show: run git secret whoknows [ "$status" -eq 1 ] } @test "run 'removeperson' with bad arg" { local email="$TEST_DEFAULT_USER" run git secret removeperson -Z "$email" [ "$status" -ne 0 ] } @test "run the 'killperson' alias" { run git secret killperson [ "$status" -eq 1 ] } @test "run 'removeperson' with email added twice" { local email="$TEST_DEFAULT_USER" # This should fail because you can't add the same email twice run git secret tell "$email" [ "$status" -ne 0 ] # Then test that the normal remove test runs run git secret removeperson "$email" [ "$status" -eq 0 ] # Testing output: [[ "$output" == *"$email"* ]] # Then whoknows must return an error with status code 1, because no one is in list run git secret whoknows [ "$status" -eq 1 ] } git-secret-0.5.0/tests/test_reveal.bats000066400000000000000000000166711424706700600201350ustar00rootroot00000000000000#!/usr/bin/env bats # shellcheck disable=SC2155 load _test_base FILE_TO_HIDE="$TEST_DEFAULT_FILENAME" FILE_CONTENTS="hidden content юникод" FINGERPRINT="" function setup { FINGERPRINT=$(install_fixture_full_key "$TEST_DEFAULT_USER") set_state_initial set_state_git set_state_secret_init set_state_secret_tell "$TEST_DEFAULT_USER" set_state_secret_add "$FILE_TO_HIDE" "$FILE_CONTENTS" set_state_secret_hide } function teardown { rm "$FILE_TO_HIDE" uninstall_fixture_full_key "$TEST_DEFAULT_USER" "$FINGERPRINT" unset_current_state } @test "run 'reveal' with password argument" { cp "$FILE_TO_HIDE" "${FILE_TO_HIDE}2" rm -f "$FILE_TO_HIDE" local password=$(test_user_password "$TEST_DEFAULT_USER") run git secret reveal -d "$TEST_GPG_HOMEDIR" -p "$password" [ "$status" -eq 0 ] [ -f "$FILE_TO_HIDE" ] cmp -s "$FILE_TO_HIDE" "${FILE_TO_HIDE}2" rm "${FILE_TO_HIDE}2" } @test "run 'reveal' with bad arg" { cp "$FILE_TO_HIDE" "${FILE_TO_HIDE}2" rm -f "$FILE_TO_HIDE" local password=$(test_user_password "$TEST_DEFAULT_USER") run git secret reveal -Z -d "$TEST_GPG_HOMEDIR" -p "$password" [ "$status" -ne 0 ] } @test "run 'reveal' on secret version of file" { local password=$(test_user_password "$TEST_DEFAULT_USER") run git secret reveal -d "$TEST_GPG_HOMEDIR" -p "$password" "$FILE_TO_HIDE$SECRETS_EXTENSION" [ "$status" -ne 0 ] } @test "run 'reveal' on nonexistent file" { local password=$(test_user_password "$TEST_DEFAULT_USER") run git secret reveal -d "$TEST_GPG_HOMEDIR" -p "$password" "DOES-NOT-EXIST" [ "$status" -ne 0 ] } @test "run 'reveal' with '-f'" { rm "$FILE_TO_HIDE" local password=$(test_user_password "$TEST_DEFAULT_USER") run git secret reveal -f -d "$TEST_GPG_HOMEDIR" -p "$password" [ "$status" -eq 0 ] [ -f "$FILE_TO_HIDE" ] } @test "run 'reveal' binary with 'SECRETS_GPG_ARMOR=1'" { rm "$FILE_TO_HIDE" local password=$(test_user_password "$TEST_DEFAULT_USER") # Armor should not change anything here: SECRETS_GPG_ARMOR=1 run git secret reveal -d "$TEST_GPG_HOMEDIR" -p "$password" [ "$status" -eq 0 ] [ -f "$FILE_TO_HIDE" ] } @test "run 'reveal' armored with 'SECRETS_GPG_ARMOR=1'" { # We need to clean existing binary files: git secret clean # Now, let's hide files once again with `--armor` enabled: set_state_secret_hide '1' rm "$FILE_TO_HIDE" local password=$(test_user_password "$TEST_DEFAULT_USER") # Armor should not change anything here: SECRETS_GPG_ARMOR=1 run git secret reveal -d "$TEST_GPG_HOMEDIR" -p "$password" [ "$status" -eq 0 ] [ -f "$FILE_TO_HIDE" ] } @test "run 'reveal' armored with 'SECRETS_GPG_ARMOR=0'" { # We need to clean existing binary files: git secret clean # Now, let's hide files once again with `--armor` enabled: set_state_secret_hide '1' rm "$FILE_TO_HIDE" local password=$(test_user_password "$TEST_DEFAULT_USER") # Armor should not change anything here: SECRETS_GPG_ARMOR=0 run git secret reveal -d "$TEST_GPG_HOMEDIR" -p "$password" [ "$status" -eq 0 ] [ -f "$FILE_TO_HIDE" ] } @test "run 'reveal' with '-v'" { rm "$FILE_TO_HIDE" local password=$(test_user_password "$TEST_DEFAULT_USER") run git secret reveal -v -d "$TEST_GPG_HOMEDIR" -p "$password" [ "$status" -eq 0 ] [ -f "$FILE_TO_HIDE" ] } @test "run 'reveal' with '-P'" { rm "$FILE_TO_HIDE" local password=$(test_user_password "$TEST_DEFAULT_USER") local secret_file=$(_get_encrypted_filename "$FILE_TO_HIDE") chmod o-rwx "$secret_file" run git secret reveal -P -d "$TEST_GPG_HOMEDIR" -p "$password" [ "$status" -eq 0 ] ## permissions should match. local secret_perm local file_perm file_perm=$($SECRETS_OCTAL_PERMS_COMMAND "$FILE_TO_HIDE") secret_perm=$($SECRETS_OCTAL_PERMS_COMMAND "$FILE_TO_HIDE$SECRETS_EXTENSION") #echo "# secret_perm: $secret_perm, file_perm: $file_perm" >&3 [ "$secret_perm" = "$file_perm" ] [ -f "$FILE_TO_HIDE" ] } @test "run 'reveal' with wrong password" { rm "$FILE_TO_HIDE" run git secret reveal -d "$TEST_GPG_HOMEDIR" -p "WRONG" [ "$status" -eq 2 ] [ ! -f "$FILE_TO_HIDE" ] } @test "run 'reveal' for attacker" { # Preparations rm "$FILE_TO_HIDE" local attacker_fingerprint=$(install_fixture_full_key "$TEST_ATTACKER_USER") local password=$(test_user_password "$TEST_ATTACKER_USER") run git secret reveal -d "$TEST_GPG_HOMEDIR" -p "$password" # This should fail, nothing should be created: [ "$status" -eq 2 ] [ ! -f "$FILE_TO_HIDE" ] # Cleaning up: uninstall_fixture_full_key "$TEST_ATTACKER_USER" "$attacker_fingerprint" } @test "run 'reveal' for attacker with -F (force)" { # Preparations rm "$FILE_TO_HIDE" local attacker_fingerprint=$(install_fixture_full_key "$TEST_ATTACKER_USER") local password=$(test_user_password "$TEST_ATTACKER_USER") run git secret reveal -F -d "$TEST_GPG_HOMEDIR" -p "$password" #echo "# status is $status" >&3 # This should return a status code of 1 also. Not sure how to test that we don't die early [ "$status" -eq 0 ] [ ! -f "$FILE_TO_HIDE" ] touch "$FILE_TO_HIDE" #create this file so uninstall below works # Cleaning up: uninstall_fixture_full_key "$TEST_ATTACKER_USER" "$attacker_fingerprint" } @test "run 'reveal' for multiple users (with key deletion)" { # Preparations: local second_fingerprint=$(install_fixture_full_key "$TEST_SECOND_USER") local password=$(test_user_password "$TEST_SECOND_USER") set_state_secret_tell "$TEST_SECOND_USER" set_state_secret_hide # We are removing a secret key of the first user to be sure # that it is not used in decryption: uninstall_fixture_full_key "$TEST_DEFAULT_USER" "$FINGERPRINT" # Testing: run git secret reveal -d "$TEST_GPG_HOMEDIR" -p "$password" [ "$status" -eq 0 ] [ -f "$FILE_TO_HIDE" ] # Cleaning up: uninstall_fixture_full_key "$TEST_SECOND_USER" "$second_fingerprint" } @test "run 'reveal' for multiple users (normally)" { # Preparations: local second_fingerprint=$(install_fixture_full_key "$TEST_SECOND_USER") # bug in gpg v2.0.22, need to use default password local password=$(test_user_password "$TEST_DEFAULT_USER") set_state_secret_tell "$TEST_SECOND_USER" set_state_secret_hide # Testing: run git secret reveal -d "$TEST_GPG_HOMEDIR" -p "$password" [ "$status" -eq 0 ] [ -f "$FILE_TO_HIDE" ] # Cleaning up: uninstall_fixture_full_key "$TEST_SECOND_USER" "$second_fingerprint" } @test "run 'reveal' with SECRETS_PINENTRY=loopback" { rm -f "$FILE_TO_HIDE" local password=$(test_user_password "$TEST_DEFAULT_USER") SECRETS_PINENTRY=loopback run git secret reveal \ -d "$TEST_GPG_HOMEDIR" \ -p "$password" [ "$status" -eq 0 ] } @test "run 'reveal' with SECRETS_PINENTRY=error" { if [[ "$GPG_VER_MIN_21" -ne 1 ]]; then skip "this test is skipped on gpg before version 2.1" fi rm -f "$FILE_TO_HIDE" local password=$(test_user_password "$TEST_DEFAULT_USER") SECRETS_PINENTRY=error run git secret reveal \ -d "$TEST_GPG_HOMEDIR" \ -p "$password" [ "$status" -ne 0 ] } @test "run 'reveal' with named file from subdir" { local password password=$(test_user_password "$TEST_DEFAULT_USER") mkdir subdir echo "content2" > subdir/new_filename.txt ( # start subshell for subdir tests cd subdir run git secret add new_filename.txt [ "$status" -eq 0 ] run git secret hide [ "$status" -eq 0 ] run git secret reveal -d "$TEST_GPG_HOMEDIR" -p "$password" new_filename.txt [ "$status" -eq 0 ] ) # end subshell # clean up rm -rf subdir } git-secret-0.5.0/tests/test_reveal_filename.bats000066400000000000000000000020631424706700600217630ustar00rootroot00000000000000#!/usr/bin/env bats load _test_base FILE_TO_HIDE="$TEST_DEFAULT_FILENAME" FILE_CONTENTS="hidden content юникод" FINGERPRINT="" OLD_SECRETS_EXTENSION="" function setup { FINGERPRINT=$(install_fixture_full_key "$TEST_DEFAULT_USER") set_state_initial set_state_git set_state_secret_init set_state_secret_tell "$TEST_DEFAULT_USER" set_state_secret_add "$FILE_TO_HIDE" "$FILE_CONTENTS" OLD_SECRETS_EXTENSION="$SECRETS_EXTENSION" export SECRETS_EXTENSION=".new_secret" set_state_secret_hide } function teardown { rm "$FILE_TO_HIDE" uninstall_fixture_full_key "$TEST_DEFAULT_USER" "$FINGERPRINT" unset_current_state export SECRETS_EXTENSION="$OLD_SECRETS_EXTENSION" } @test "run 'reveal' with different file extension" { cp "$FILE_TO_HIDE" "${FILE_TO_HIDE}2" rm "$FILE_TO_HIDE" local password password=$(test_user_password "$TEST_DEFAULT_USER") run git secret reveal -d "$TEST_GPG_HOMEDIR" -p "$password" [ "$status" -eq 0 ] [ -f "$FILE_TO_HIDE" ] cmp -s "$FILE_TO_HIDE" "${FILE_TO_HIDE}2" rm "${FILE_TO_HIDE}2" } git-secret-0.5.0/tests/test_tell.bats000066400000000000000000000142161424706700600176100ustar00rootroot00000000000000#!/usr/bin/env bats load _test_base function setup { install_fixture_key "$TEST_DEFAULT_USER" set_state_initial set_state_git set_state_secret_init } function teardown { uninstall_fixture_key "$TEST_DEFAULT_USER" unset_current_state } @test "run 'tell' with '-v'" { run git secret tell -d "$TEST_GPG_HOMEDIR" -v "$TEST_DEFAULT_USER" # echo "$output" | sed "s/^/# '$BATS_TEST_DESCRIPTION' output: /" >&3 [[ "$output" == *"created"* ]] [[ "$output" == *"gpg:"* ]] [[ "$output" == *"$TEST_DEFAULT_USER"* ]] [ "$status" -eq 0 ] } @test "run 'tell' without '-v'" { run git secret tell -d "$TEST_GPG_HOMEDIR" "$TEST_DEFAULT_USER" # echo "$output" | sed "s/^/# '$BATS_TEST_DESCRIPTION' output: /" >&3 [[ "$output" != *"imported:"* ]] [[ "$output" == *"$TEST_DEFAULT_USER"* ]] [ "$status" -eq 0 ] } @test "run 'tell' on substring of emails" { run git secret tell -d "$TEST_GPG_HOMEDIR" user # this should give an error because there is no user named 'user', # even though there are users with the substring 'user'. # See issue https://github.com/sobolevn/git-secret/issues/176 [ "$status" -eq 1 ] run git secret whoknows [ "$status" -eq 1 ] # should error when there are no users told } @test "run 'tell' on the same email twice" { # first time should succeed git secret tell -d "$TEST_GPG_HOMEDIR" "$TEST_DEFAULT_USER" # second time should fail because there's already a key for that email. See #634 run git secret tell -d "$TEST_GPG_HOMEDIR" "$TEST_DEFAULT_USER" [ "$status" -ne 0 ] } @test "fail on no users" { run _user_required [ "$status" -eq 1 ] } @test "constantly fail on no users" { # We had a serious bug with _user_required, # see this link for the details: # https://github.com/sobolevn/git-secret/issues/74 # Preparations: git secret tell -d "$TEST_GPG_HOMEDIR" "$TEST_DEFAULT_USER" git secret removeperson "$TEST_DEFAULT_USER" # It was showing something like `tru::1:1289775241:0:2:1:6` # after the preparations done and the error was not generated. run _user_required [ "$status" -eq 1 ] } @test "run 'tell' with secret-key imported" { local secrets_dir_keys secrets_dir_keys=$(_get_secrets_dir_keys) local private_key="$secrets_dir_keys/secring.gpg" echo "private key" > "$private_key" [ -s "$private_key" ] run git secret tell -d "$TEST_GPG_HOMEDIR" "$TEST_DEFAULT_USER" [ "$status" -eq 1 ] } @test "run 'tell' without '.gitsecret'" { local secrets_dir secrets_dir=$(_get_secrets_dir) rm -r "$secrets_dir" run git secret tell -d "$TEST_GPG_HOMEDIR" "$TEST_DEFAULT_USER" [ "$status" -eq 1 ] } @test "run 'tell' without arguments" { run git secret tell [ "$status" -eq 1 ] } @test "run 'init' with bad arg" { run git secret tell -Z -d "$TEST_GPG_HOMEDIR" "$TEST_DEFAULT_USER" [ "$status" -ne 0 ] } @test "run 'tell' normally" { run git secret tell -d "$TEST_GPG_HOMEDIR" "$TEST_DEFAULT_USER" [ "$status" -eq 0 ] # Testing that now user is found: run _user_required [ "$status" -eq 0 ] # Testing that now user is in the list of people who knows the secret: run git secret whoknows [[ "$output" == *"$TEST_DEFAULT_USER"* ]] } @test "run 'tell' with '-m'" { local email="$TEST_DEFAULT_USER" git_set_config_email "$email" run git secret tell -d "$TEST_GPG_HOMEDIR" -m [ "$status" -eq 0 ] } @test "run 'tell' with '-m' (empty email)" { # Preparations: git_set_config_email "" # now it should not allow to add yourself run git secret tell -d "$TEST_GPG_HOMEDIR" -m [ "$status" -eq 1 ] } @test "run 'tell' with multiple emails" { # Preparations: install_fixture_key "$TEST_SECOND_USER" # Testing the command itself: run git secret tell -d "$TEST_GPG_HOMEDIR" \ "$TEST_DEFAULT_USER" "$TEST_SECOND_USER" [ "$status" -eq 0 ] # Testing that these users are presented in the # list of people who knows secret: run git secret whoknows [[ "$output" == *"$TEST_DEFAULT_USER"* ]] [[ "$output" == *"$TEST_SECOND_USER"* ]] # Cleaning up: uninstall_fixture_key "$TEST_SECOND_USER" } @test "run 'tell' with key without email and with comment" { # install works because it works on filename, not contents of keyring install_fixture_key "$TEST_NOEMAIL_COMMENT_USER" # Testing the command itself fails because you have to use an email address run git secret tell -d "$TEST_GPG_HOMEDIR" "$TEST_NOEMAIL_COMMENT_USER" # this should not succeed because we only support addressing users by email [ "$status" -ne 0 ] # Testing that these users are presented in the # list of people who knows secret: run git secret whoknows [[ "$output" != *"$TEST_NOEMAIL_COMMENT_USER"* ]] # Cleaning up: can't clean up by email # uninstall_fixture_key "$TEST_NOEMAIL_COMMENT_USER" } @test "run 'tell' on non-email" { install_fixture_key "$TEST_NOEMAIL_COMMENT_USER" local name # don't complain about sed # shellcheck disable=SC2001 name=$(echo "$TEST_NOEMAIL_COMMENT_USER" | sed -e 's/@.*//') # echo "$name" | sed "s/^/# '$BATS_TEST_DESCRIPTION' name is: /" >&3 # Testing the command itself, should fail because you must use email run git secret tell -d "$TEST_GPG_HOMEDIR" "$name" # this should not succeed because we only support addressing users by email [ "$status" -ne 0 ] # Testing that these users are presented in the # list of people who knows secret: run git secret whoknows [[ "$output" != *"$name"* ]] # Cleaning up: can't clean up by email because key doesn't hold it # uninstall_fixture_key "$TEST_NOEMAIL_COMMENT_USER" } @test "run 'tell' in subfolder" { if [[ "$BATS_RUNNING_FROM_GIT" -eq 1 ]]; then skip "this test is skipped while 'git commit'. See #334" fi # Preparations local root_dir='test_dir' local test_dir="$root_dir/telling" local current_dir="$PWD" mkdir -p "$test_dir" cd "$test_dir" # Test: run git secret tell -d "$TEST_GPG_HOMEDIR" "$TEST_DEFAULT_USER" [ "$status" -eq 0 ] # Testing that now user is found: run _user_required [ "$status" -eq 0 ] # Testing that now user is in the list of people who knows the secret: run git secret whoknows [[ "$output" == *"$TEST_DEFAULT_USER"* ]] # Cleaning up: cd "$current_dir" rm -r "$root_dir" } git-secret-0.5.0/tests/test_usage.bats000066400000000000000000000015641424706700600177560ustar00rootroot00000000000000#!/usr/bin/env bats load _test_base function setup { set_state_initial set_state_git } function teardown { unset_current_state } @test "run 'usage'" { run git secret usage [ "$status" -eq 0 ] } @test "run 'usage' without '.git'" { remove_git_repository # It's ok for 'usage' to succeed when there's no .git directory, but it doesn't run git secret usage [ "$status" -eq 1 ] } #_SECRETS_DIR=${SECRETS_DIR:-".gitsecret"} @test "run 'usage' with ignored '${_SECRETS_DIR}'" { echo "${_SECRETS_DIR}" >> ".gitignore" # below shows how to send 'diagnostic' messages to bats-core. # echo "# clear-line-output" >&3 # echo "# SECRETS_DIR is ${_SECRETS_DIR}" >&3 # It's ok for 'usage' to succeed when the .gitsecret directory is ignored, but it doesn't run git secret usage # echo "# git secret usage -> status $status" >&3 [ "$status" -eq 1 ] } git-secret-0.5.0/tests/test_whoknows.bats000066400000000000000000000043141424706700600205250ustar00rootroot00000000000000#!/usr/bin/env bats load _test_base function setup { install_fixture_key "$TEST_DEFAULT_USER" install_fixture_key "$TEST_SECOND_USER" set_state_initial set_state_git set_state_secret_init set_state_secret_tell "$TEST_DEFAULT_USER" set_state_secret_tell "$TEST_SECOND_USER" } function teardown { uninstall_fixture_key "$TEST_DEFAULT_USER" uninstall_fixture_key "$TEST_SECOND_USER" unset_current_state } @test "run 'whoknows' normally" { run git secret whoknows [ "$status" -eq 0 ] # Now test the output, both users should be present: [[ "$output" == *"$TEST_DEFAULT_USER"* ]] [[ "$output" == *"$TEST_SECOND_USER"* ]] } @test "run 'whoknows' with extra filename" { run git secret whoknows extra_filename [ "$status" -ne 0 ] } @test "run 'whoknows' with bad arg" { run git secret whoknows -Z [ "$status" -ne 0 ] } @test "run 'whoknows -l'" { run git secret whoknows -l [ "$status" -eq 0 ] # echo "$output" | sed "s/^/# '$BATS_TEST_DESCRIPTION' output: /" >&3 # output should look like # 'abort: problem encrypting file with gpg: exit code 2: space file' #echo "# '$BATS_TEST_DESCRIPTION' status: $status" >&3 # Now test the output, both users should be present and without expiration [[ "$output" == *"$TEST_DEFAULT_USER (expires: never)"* ]] [[ "$output" == *"$TEST_SECOND_USER (expires: never)"* ]] } @test "run 'whoknows' in subfolder" { if [[ "$BATS_RUNNING_FROM_GIT" -eq 1 ]]; then skip "this test is skipped while 'git commit'. See #334" fi # Preparations: local current_dir="$PWD" local root_dir='test_dir' local test_dir="$root_dir/subfolders/case" mkdir -p "$test_dir" cd "$test_dir" # Test: run git secret whoknows [ "$status" -eq 0 ] # Now test the output, both users should be present: [[ "$output" == *"$TEST_DEFAULT_USER"* ]] [[ "$output" == *"$TEST_SECOND_USER"* ]] # Cleaning up: cd "$current_dir" rm -r "$root_dir" } @test "run 'whoknows' without any users" { # Preparations, removing users: local email1="$TEST_DEFAULT_USER" local email2="$TEST_SECOND_USER" git secret removeperson "$email1" "$email2" # Now whoknows should raise an error: there are no users. run git secret whoknows [ "$status" -eq 1 ] } git-secret-0.5.0/utils/000077500000000000000000000000001424706700600147305ustar00rootroot00000000000000git-secret-0.5.0/utils/apk/000077500000000000000000000000001424706700600155035ustar00rootroot00000000000000git-secret-0.5.0/utils/apk/build.sh000066400000000000000000000021601424706700600171350ustar00rootroot00000000000000#!/usr/bin/env bash set -e # shellcheck disable=SC1090,SC1091 source "$SECRETS_PROJECT_ROOT/utils/build-utils.sh" # We need this export for `config.yml` to expand the version properly. export SCRIPT_VERSION # shellcheck disable=SC1090,SC1091 source "$SECRETS_PROJECT_ROOT/utils/apk/meta.sh" # Create dest dir: mkdir -p "$SCRIPT_DEST_DIR" for architecture in "${ALPINE_ARCHITECTURES[@]}"; do ALPINE_ARCHITECTURE="$architecture" export ALPINE_ARCHITECTURE config_file="$SCRIPT_BUILD_DIR/${architecture}.yml" envsubst < "$SECRETS_PROJECT_ROOT/utils/apk/nfpm.yml" > "$config_file" # Here's the deal. We use a custom builder here, # because `fpm` produces a broken package. # It is possible to install it locally, # but it used to fail when installed from our Artifactory. # So, we switched to `nfpm` instead. # But, we only switched one repo for now, # because we are not sure that other affected packages will be fine. # And also `fpm` supports more tools: like pacman. nfpm package \ --config "$config_file" \ --packager 'apk' \ --target "$SCRIPT_DEST_DIR" done # Cleaning up: clean_up_files git-secret-0.5.0/utils/apk/deploy.sh000066400000000000000000000021471424706700600173370ustar00rootroot00000000000000#!/usr/bin/env bash set -e if [[ "$SECRETS_DEPLOY_DRY_RUN" == 1 ]]; then echo 'dry-run finished' exit 0 fi # shellcheck disable=SC1090,SC1091 source "$SECRETS_PROJECT_ROOT/utils/build-utils.sh" # shellcheck disable=SC1090,SC1091 source "$SECRETS_PROJECT_ROOT/utils/apk/meta.sh" readonly VERSION_NAME="git-secret-${SCRIPT_VERSION}.apk" # Artifactory location: readonly BASE_API_URL='https://gitsecret.jfrog.io/artifactory' function upload_with_architecture { local arch="$1" local file_location file_location="$(locate_release 'apk' "$arch")" curl -sS \ -u "$SECRETS_ARTIFACTORY_CREDENTIALS" \ --max-time 10 \ --retry 3 \ --retry-delay 5 \ -XPUT "$BASE_API_URL/git-secret-apk/all/main/$arch/$VERSION_NAME" \ -T "$file_location" } for architecture in "${ALPINE_ARCHITECTURES[@]}"; do upload_with_architecture "$architecture" done # Now, we need to trigger metadata reindex: curl -sS \ -u "$SECRETS_ARTIFACTORY_CREDENTIALS" \ --max-time 5 \ --retry 3 \ --retry-delay 5 \ -XPOST "$BASE_API_URL/api/alpine/git-secret-apk/reindex" echo echo 'Done: released alpine packages' git-secret-0.5.0/utils/apk/install.sh000066400000000000000000000005151424706700600175060ustar00rootroot00000000000000sh -c "echo 'https://gitsecret.jfrog.io/artifactory/git-secret-apk/all/main'" >> /etc/apk/repositories wget -O /etc/apk/keys/git-secret-apk.rsa.pub 'https://gitsecret.jfrog.io/artifactory/api/security/keypair/public/repositories/git-secret-apk' apk add --update --no-cache git-secret # Testing, that it worked: git secret --version git-secret-0.5.0/utils/apk/meta.sh000066400000000000000000000003321424706700600167630ustar00rootroot00000000000000# Full list is here: # http://dl-cdn.alpinelinux.org/alpine/v3.13/main/ # shellcheck disable=SC2034 readonly ALPINE_ARCHITECTURES=( 'aarch64' 'armhf' 'armv7' 'mips64' 'ppc64le' 's390x' 'x86' 'x86_64' ) git-secret-0.5.0/utils/apk/nfpm.yml000066400000000000000000000015751424706700600171760ustar00rootroot00000000000000# Name. (required) name: git-secret # Architecture. (required) arch: $ALPINE_ARCHITECTURE # Platform. # Defaults to `linux`. platform: linux # Version. (required) # This will expand any env var you set in the field, eg version: v${SEMVER} version: $SCRIPT_VERSION version_schema: none # Section. section: default # Priority. priority: main # Maintaner. maintainer: Nikita Sobolev # Description. # Defaults to `no description given`. description: Shell scripts to encrypt your private data inside a git repository. # Vendor. vendor: git-secret team # Package's homepage. homepage: https://git-secret.io # License. license: MIT # Dependencies. depends: - git - bash - gnupg - gawk - coreutils contents: - src: git-secret dst: /usr/bin/git-secret - src: man/man1/*.1 dst: /usr/share/man/man1 - src: man/man7/*.7 dst: /usr/share/man/man7 git-secret-0.5.0/utils/build-utils.sh000077500000000000000000000045631424706700600175340ustar00rootroot00000000000000#!/usr/bin/env bash set -e # shellcheck disable=SC1090,SC1091 source "$SECRETS_PROJECT_ROOT/src/version.sh" # Initializing and settings: readonly READ_PERM=0644 readonly EXEC_PERM=0755 readonly SCRIPT_NAME='git-secret' readonly SCRIPT_DESCRIPTION='Shell scripts to encrypt your private data inside a git repository.' readonly SCRIPT_VERSION="$GITSECRET_VERSION" # This may be overridden: if [[ -z "$SCRIPT_BUILD_DIR" ]]; then SCRIPT_BUILD_DIR="$PWD/build" fi readonly SCRIPT_DEST_DIR="$SCRIPT_BUILD_DIR/buildroot" function locate_release { local release_type="$1" local arch="${2:-}" find "$SCRIPT_DEST_DIR" \ -maxdepth 1 \ -name "*${arch}.$release_type" | head -1 } function preinstall_files { # Only requires `-T` or `-c` depending on the OS local dir_switch="$1" # Preparing the files: rm -rf "$SCRIPT_BUILD_DIR" mkdir -p "$SCRIPT_DEST_DIR" # Coping the files inside the build folder: install -D "$dir_switch" \ -b -m "$EXEC_PERM" "$dir_switch" "$SCRIPT_NAME" \ "$SCRIPT_BUILD_DIR/usr/bin/$SCRIPT_NAME" # Install the manualls: install -m "$EXEC_PERM" -d "$SCRIPT_BUILD_DIR/usr/share/man/man1" install -m "$EXEC_PERM" -d "$SCRIPT_BUILD_DIR/usr/share/man/man7" for file in man/man1/*.1 ; do install -D "$dir_switch" \ -b -m "$READ_PERM" "$dir_switch" "$file" \ "$SCRIPT_BUILD_DIR/usr/share/$file" done install -D "$dir_switch" \ -b -m "$READ_PERM" "$dir_switch" 'man/man7/git-secret.7' \ "$SCRIPT_BUILD_DIR/usr/share/man/man7/git-secret.7" } function build_package { # Only requires `rpm`, `apk`, or `deb` as first argument: local build_type="$1" local arch_type="${2:-all}" # coreutils is for sha256sum # See https://github.com/jordansissel/fpm for docs: fpm \ --input-type 'dir' \ --output-type "$build_type" \ --chdir "$SCRIPT_BUILD_DIR" \ --architecture "$arch_type" \ --name "$SCRIPT_NAME" \ --version "$SCRIPT_VERSION" \ --description "$SCRIPT_DESCRIPTION" \ --url 'https://git-secret.io' \ --maintainer 'Nikita Sobolev (mail@sobolevn.me)' \ --license 'MIT' \ --depends 'bash' \ --depends 'coreutils' \ --depends 'gawk' \ --depends 'git' \ --depends 'gnupg' \ --deb-no-default-config-files \ . } function clean_up_files { # Pre-installed files: rm -rf "${SCRIPT_BUILD_DIR:?}/usr" # nfpm configs: rm -rf "$SCRIPT_BUILD_DIR"/*.yml } git-secret-0.5.0/utils/deb/000077500000000000000000000000001424706700600154625ustar00rootroot00000000000000git-secret-0.5.0/utils/deb/build.sh000077500000000000000000000003611424706700600171200ustar00rootroot00000000000000#!/usr/bin/env bash set -e # shellcheck disable=SC1090,SC1091 source "$SECRETS_PROJECT_ROOT/utils/build-utils.sh" preinstall_files '-c' # Building .deb package: cd "$SCRIPT_DEST_DIR" && build_package 'deb' # Cleaning up: clean_up_files git-secret-0.5.0/utils/deb/deploy.sh000077500000000000000000000015041424706700600173150ustar00rootroot00000000000000#!/usr/bin/env bash set -e if [[ "$SECRETS_DEPLOY_DRY_RUN" == 1 ]]; then echo 'dry-run finished' exit 0 fi # shellcheck disable=SC1090,SC1091 source "$SECRETS_PROJECT_ROOT/utils/build-utils.sh" # Artifactory location: readonly BASE_API_URL='https://gitsecret.jfrog.io/artifactory' # This folder should contain just one `.dev` file: DEB_FILE_LOCATION="$(locate_release 'deb')" DEB_FILE_NAME="$(basename "$DEB_FILE_LOCATION")" curl -sS \ -u "$SECRETS_ARTIFACTORY_CREDENTIALS" \ -XPUT "$BASE_API_URL/git-secret-deb/$DEB_FILE_NAME;deb.distribution=git-secret;deb.component=main;deb.architecture=all" \ -T "$DEB_FILE_LOCATION" # Now, we need to trigger metadata reindex: curl -sS \ -u "$SECRETS_ARTIFACTORY_CREDENTIALS" \ -XPOST "$BASE_API_URL/api/deb/reindex/git-secret-deb" echo echo "Done: released $DEB_FILE_NAME" git-secret-0.5.0/utils/deb/install.sh000066400000000000000000000004761424706700600174730ustar00rootroot00000000000000sudo sh -c "echo 'deb https://gitsecret.jfrog.io/artifactory/git-secret-deb git-secret main' >> /etc/apt/sources.list" wget -qO - 'https://gitsecret.jfrog.io/artifactory/api/gpg/key/public' | sudo apt-key add - sudo apt-get update && sudo apt-get install -y git-secret # Testing, that it worked: git secret --version git-secret-0.5.0/utils/install.sh000077500000000000000000000020541424706700600167360ustar00rootroot00000000000000#!/usr/bin/env bash set -e # Credit goes to: # https://github.com/sstephenson/bats/blob/master/install.sh function resolve_link { $(type -p greadlink readlink | head -1) "$1" } function abs_dirname { local cwd local path="$1" cwd="$(pwd)" while [ -n "$path" ]; do cd "${path%/*}" local name="${path##*/}" path="$(resolve_link "$name" || true)" done pwd cd "$cwd" } PREFIX="$1" if [ -z "$PREFIX" ]; then echo "usage: $0 " >&2 exit 1 fi SCRIPT_ROOT="$(dirname "$(abs_dirname "$0")")" mkdir -p "$PREFIX"/bin "$PREFIX"/share/man/man1 "$PREFIX"/share/man/man7 cp "$SCRIPT_ROOT"/git-secret "$PREFIX"/bin/git-secret # There was an issue with this line: # cp -R "$SCRIPT_ROOT"/man/man1/* "$PREFIX"/share/man/man1 # see https://github.com/sobolevn/git-secret/issues/35 for reference. find "$SCRIPT_ROOT"/man/man1 -name '*.1' -print0 | xargs -0 -I {} cp \ -a {} "$PREFIX"/share/man/man1 cp "$SCRIPT_ROOT"/man/man7/git-secret.7 "$PREFIX"/share/man/man7/git-secret.7 echo "Installed git-secret to ${PREFIX}/bin/git-secret" git-secret-0.5.0/utils/rpm/000077500000000000000000000000001424706700600155265ustar00rootroot00000000000000git-secret-0.5.0/utils/rpm/build.sh000077500000000000000000000004521424706700600171650ustar00rootroot00000000000000#!/usr/bin/env bash set -e # shellcheck disable=SC1090,SC1091 source "$SECRETS_PROJECT_ROOT/utils/build-utils.sh" # Copying all the required files to the build directory: preinstall_files '-c' # Building .rpm package: cd "$SCRIPT_DEST_DIR" && build_package 'rpm' # Cleaning up: clean_up_files git-secret-0.5.0/utils/rpm/deploy.sh000066400000000000000000000014041424706700600173550ustar00rootroot00000000000000#!/usr/bin/env bash set -e if [[ "$SECRETS_DEPLOY_DRY_RUN" == 1 ]]; then echo 'dry-run finished' exit 0 fi # shellcheck disable=SC1090,SC1091 source "$SECRETS_PROJECT_ROOT/utils/build-utils.sh" # Artifactory location: readonly BASE_API_URL='https://gitsecret.jfrog.io/artifactory' # This folder should contain just one `.rpm` file: RPM_FILE_LOCATION="$(locate_release 'rpm')" RPM_FILE_NAME="$(basename "$RPM_FILE_LOCATION")" curl -sS \ -u "$SECRETS_ARTIFACTORY_CREDENTIALS" \ -XPUT "$BASE_API_URL/git-secret-rpm/rpm/$RPM_FILE_NAME" \ -T "$RPM_FILE_LOCATION" # Now, we need to trigger metadata reindex: curl -sS \ -u "$SECRETS_ARTIFACTORY_CREDENTIALS" \ -XPOST "$BASE_API_URL/api/yum/git-secret-rpm?async=1" echo echo "Done: released $RPM_FILE_NAME" git-secret-0.5.0/utils/rpm/git-secret.repo000066400000000000000000000004551424706700600204670ustar00rootroot00000000000000[git-secret-rpm] name=git-secret-rpm baseurl=https://gitsecret.jfrog.io/artifactory/git-secret-rpm enabled=1 gpgcheck=0 ## Uncomment the following lines to enable repository-level GPG key check: # gpgkey=https://gitsecret.jfrog.io/artifactory/git-secret-rpm/repodata/repomd.xml.key # repo_gpgcheck=1 git-secret-0.5.0/utils/rpm/install.sh000066400000000000000000000004711424706700600175320ustar00rootroot00000000000000wget https://raw.githubusercontent.com/sobolevn/git-secret/master/utils/rpm/git-secret.repo -O git-secret-rpm.repo # Inspect what's inside! You can also enable `gpg` check on repo level. sudo mv git-secret-rpm.repo /etc/yum.repos.d/ sudo yum install -y git-secret # Testing, that it worked: git secret --version git-secret-0.5.0/utils/tests.sh000077500000000000000000000013311424706700600164270ustar00rootroot00000000000000#!/usr/bin/env bash # `SECRETS_PROJECT_ROOT` must be set before running the script. set -e TEST_DIR=/tmp/git-secret-test rm -rf "${TEST_DIR}" mkdir "${TEST_DIR}" echo "# created dir: ${TEST_DIR}" chmod 0700 "${TEST_DIR}" ( cd "$TEST_DIR" # test with non-standard SECRETS_DIR (normally .gitsecret) # and SECRETS_EXTENSION (normally .secret) export SECRETS_DIR='.gitsec' export SECRETS_EXTENSION='.sec' export TMPDIR="$TEST_DIR" echo "# TMPDIR is $TMPDIR" # bats expects diagnostic lines to be sent to fd 3, matching regex '^# ' # (IE, like: `echo '# message here' >&3`). # bats ... 3>&1 shows diagnostic output bats "${SECRETS_PROJECT_ROOT}/tests" 3>&1 ) rm -rf "${TEST_DIR}" git-secret-0.5.0/utils/uninstall.sh000077500000000000000000000004521424706700600173010ustar00rootroot00000000000000#!/usr/bin/env bash set -e readonly PREFIX="$1" if [ -z "$PREFIX" ]; then echo "usage: $0 " >&2 exit 1 fi # Binary: rm -f "$PREFIX"/bin/git-secret # Manuals: find "$PREFIX"/share/man/man1 -type f -name 'git-secret-*.1' -exec rm -f {} \; rm -f "$PREFIX"/share/man/man7/git-secret.7 git-secret-0.5.0/vendor/000077500000000000000000000000001424706700600150655ustar00rootroot00000000000000git-secret-0.5.0/vendor/README.md000066400000000000000000000005741424706700600163520ustar00rootroot00000000000000README for git-secret/vendor directory We import bats-core here for https://github.com/sobolevn/git-secret/issues/377, "Don't depend on network during builds (re: bats-core)" If you want upgrade bats-core used by git-secret, replace the files in vendor/bats-core. They must remain exactly as distributed by the chosen release of bats-core - see issue linked above for details. git-secret-0.5.0/vendor/bats-core/000077500000000000000000000000001424706700600167445ustar00rootroot00000000000000git-secret-0.5.0/vendor/bats-core/.devcontainer/000077500000000000000000000000001424706700600215035ustar00rootroot00000000000000git-secret-0.5.0/vendor/bats-core/.devcontainer/Dockerfile000066400000000000000000000010071424706700600234730ustar00rootroot00000000000000ARG bashver=latest FROM bash:${bashver} # Install parallel and accept the citation notice (we aren't using this in a # context where it make sense to cite GNU Parallel). RUN echo "@edgecomm http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories && \ apk update && \ apk add --no-cache parallel ncurses shellcheck@edgecomm && \ mkdir -p ~/.parallel && touch ~/.parallel/will-cite RUN ln -s /opt/bats/bin/bats /usr/sbin/bats COPY . /opt/bats/ ENTRYPOINT ["bash", "/usr/sbin/bats"] git-secret-0.5.0/vendor/bats-core/.devcontainer/devcontainer.json000066400000000000000000000001761424706700600250630ustar00rootroot00000000000000{ "name": "Bats core development environment", "dockerFile": "Dockerfile", "build": {"args": {"bashver": "4.3"}} }git-secret-0.5.0/vendor/bats-core/.editorconfig000066400000000000000000000012571424706700600214260ustar00rootroot00000000000000root = true [*] end_of_line = lf indent_style = space indent_size = 2 insert_final_newline = true max_line_length = 80 trim_trailing_whitespace = true # The JSON files contain newlines inconsistently [*.json] indent_size = 2 insert_final_newline = ignore # YAML [*.{yml,yaml}] indent_style = space indent_size = 2 # Makefiles always use tabs for recipe indentation [{Makefile,*.mak}] indent_style = tab # Markdown [*.{md,rmd,mkd,mkdn,mdwn,mdown,markdown,litcoffee}] max_line_length = 80 # tabs behave as if they were replaced by spaces with a tab stop of 4 characters tab_width = 4 # trailing spaces indicates word wrap trim_trailing_spaces = false trim_trailing_whitespace = false git-secret-0.5.0/vendor/bats-core/.gitattributes000077500000000000000000000000511424706700600216360ustar00rootroot00000000000000* text=auto *.sh eol=lf libexec/* eol=lf git-secret-0.5.0/vendor/bats-core/.github/000077500000000000000000000000001424706700600203045ustar00rootroot00000000000000git-secret-0.5.0/vendor/bats-core/.github/ISSUE_TEMPLATE/000077500000000000000000000000001424706700600224675ustar00rootroot00000000000000git-secret-0.5.0/vendor/bats-core/.github/ISSUE_TEMPLATE/bug_report.md000066400000000000000000000011741424706700600251640ustar00rootroot00000000000000--- name: Bug report about: Create a report to help us improve title: '' labels: 'Type: Bug' assignees: '' --- **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error **Expected behavior** A clear and concise description of what you expected to happen. **Environment (please complete the following information):** - Bats Version [e.g. 1.4.0 or commit hash] - OS: [e.g. Linux, FreeBSD, MacOS] - Bash version: [e.g. 5.1] **Additional context** Add any other context about the problem here. git-secret-0.5.0/vendor/bats-core/.github/ISSUE_TEMPLATE/feature_request.md000066400000000000000000000011251424706700600262130ustar00rootroot00000000000000--- name: Feature request about: Suggest an idea for this project title: '' labels: 'Type: Enhancement' assignees: '' --- **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] **Describe the solution you'd like** A clear and concise description of what you want to happen. **Describe alternatives you've considered** A clear and concise description of any alternative solutions or features you've considered. **Additional context** Add any other context about the feature request here. git-secret-0.5.0/vendor/bats-core/.github/workflows/000077500000000000000000000000001424706700600223415ustar00rootroot00000000000000git-secret-0.5.0/vendor/bats-core/.github/workflows/check_pr_label.sh000077500000000000000000000003601424706700600256140ustar00rootroot00000000000000#!/usr/bin/bash get_pr_json() { curl -s -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/bats-core/bats-core/pulls/$1" } PR_NUMBER="$1" LABEL="$2" get_pr_json "$PR_NUMBER" | jq .labels[].name | grep "$LABEL" git-secret-0.5.0/vendor/bats-core/.github/workflows/release.yml000066400000000000000000000014251424706700600245060ustar00rootroot00000000000000name: Release on: release: { types: [published] } workflow_dispatch: jobs: npmjs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 with: registry-url: "https://registry.npmjs.org" - run: npm publish --ignore-scripts env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} github-npm: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 with: registry-url: "https://npm.pkg.github.com" - name: scope package name as required by GHPR run: npm init -y --scope ${{ github.repository_owner }} - run: npm publish --ignore-scripts env: NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} git-secret-0.5.0/vendor/bats-core/.github/workflows/release_dockerhub.yml000066400000000000000000000024121424706700600265310ustar00rootroot00000000000000name: Release to docker hub on: release: { types: [published] } workflow_dispatch: inputs: version: description: 'Version to simulate for deploy' required: true jobs: dockerhub: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - id: version run: | EXPECTED_VERSION=${{ github.event.inputs.version }} TAG_VERSION=${GITHUB_REF#refs/tags/v} # refs/tags/v1.2.3 -> 1.2.3 echo ::set-output name=version::${EXPECTED_VERSION:-$TAG_VERSION} - name: Set up QEMU uses: docker/setup-qemu-action@v1 - name: Login to DockerHub uses: docker/login-action@v1 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Set up Docker Buildx id: buildx uses: docker/setup-buildx-action@v1 - uses: docker/build-push-action@v2 with: platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/s390x,linux/386,linux/arm/v7,linux/arm/v6 tags: ${{ secrets.DOCKER_USERNAME }}/bats:${{ steps.version.outputs.version }},${{ secrets.DOCKER_USERNAME }}/bats:latest push: true git-secret-0.5.0/vendor/bats-core/.github/workflows/tests.yml000066400000000000000000000125111424706700600242260ustar00rootroot00000000000000name: Tests # Controls when the action will run. on: [push, pull_request, workflow_dispatch] jobs: changelog: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 - name: Check that PR is mentioned in Changelog run: | if ! ./.github/workflows/check_pr_label.sh "${{github.event.pull_request.number}}" "no changelog"; then grep "#${{github.event.pull_request.number}}" docs/CHANGELOG.md fi if: ${{github.event.pull_request}} shellcheck: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 - name: Run shellcheck run: | sudo apt-get update -y sudo apt-get install shellcheck ./shellcheck.sh linux: strategy: matrix: os: ['ubuntu-20.04', 'ubuntu-18.04'] env_vars: - '' # allow for some parallelity without GNU parallel, since it is not installed by default - 'BATS_NO_PARALLELIZE_ACROSS_FILES=1 BATS_NUMBER_OF_PARALLEL_JOBS=2' runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 - name: Run test on OS ${{ matrix.os }} shell: 'script -q -e -c "bash {0}"' # work around tty issues env: TERM: linux # fix tput for tty issue work around run: | bash --version bash -c "time ${{ matrix.env_vars }} bin/bats --print-output-on-failure --formatter tap test" npm_on_linux: strategy: matrix: os: ['ubuntu-20.04', 'ubuntu-18.04'] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 - name: Run test on OS ${{ matrix.os }} shell: 'script -q -e -c "bash {0}"' # work around tty issues env: TERM: linux # fix tput for tty issue work around run: | npm pack ./ sudo npm install -g ./bats-*.tgz bats test windows: runs-on: windows-2019 steps: - uses: actions/checkout@v2 - run: | bash --version bash -c "time bin/bats --print-output-on-failure --formatter tap test" npm_on_windows: strategy: matrix: os: ['windows-2019'] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 - run: npm pack ./ - run: npm install -g (get-item .\bats-*.tgz).FullName - run: bats -T --print-output-on-failure test macos: strategy: matrix: os: ['macos-10.15'] env_vars: - '' # allow for some parallelity without GNU parallel, since it is not installed by default - 'BATS_NO_PARALLELIZE_ACROSS_FILES=1 BATS_NUMBER_OF_PARALLEL_JOBS=2' runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 - name: Install unbuffer via expect run: brew install expect - name: Run test on OS ${{ matrix.os }} shell: 'unbuffer bash {0}' # work around tty issues env: TERM: linux # fix tput for tty issue work around run: | bash --version bash -c "time ${{ matrix.env_vars }} bin/bats --print-output-on-failure --formatter tap test" npm_on_macos: strategy: matrix: os: ['macos-10.15'] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 - name: Install unbuffer via expect run: brew install expect - name: Run test on OS ${{ matrix.os }} shell: 'unbuffer bash {0}' # work around tty issues env: TERM: linux # fix tput for tty issue work around run: | npm pack ./ # somehow there is already an intalled bats version around npm install --force -g ./bats-*.tgz bats --print-output-on-failure test bash-version: strategy: matrix: version: ['3.2', '4.0', '4.1', '4.2', '4.3', '4.4', '4', '5.0', '5.1', '5', 'latest'] env_vars: - '' # also test running (recursively!) in parallel - '-e BATS_NUMBER_OF_PARALLEL_JOBS=2' runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Run test on bash version ${{ matrix.version }} shell: 'script -q -e -c "bash {0}"' # work around tty issues run: | set -e docker build --build-arg bashver="${{ matrix.version }}" --tag "bats/bats:bash-${{ matrix.version }}" . docker run -it "bash:${{ matrix.version }}" --version time docker run -it ${{ matrix.env_vars }} "bats/bats:bash-${{ matrix.version }}" --print-output-on-failure --tap /opt/bats/test alpine: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Run test on bash version ${{ matrix.version }} shell: 'script -q -e -c "bash {0}"' # work around tty issues run: | set -e 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" freebsd: runs-on: macos-10.15 strategy: matrix: packages: - flock - "" steps: - uses: actions/checkout@v2 - uses: vmactions/freebsd-vm@v0.1.5 with: prepare: pkg install -y bash parallel ${{ matrix.packages }} run: | time ./bin/bats --print-output-on-failure test/ git-secret-0.5.0/vendor/bats-core/.gitignore000066400000000000000000000002031424706700600207270ustar00rootroot00000000000000/docker-compose.override.yml /docs/build # npm /bats-*.tgz # we don't have any deps; un-ignore if that changes /package-lock.json git-secret-0.5.0/vendor/bats-core/.readthedocs.yml000066400000000000000000000002141424706700600220270ustar00rootroot00000000000000version: 2 sphinx: configuration: docs/source/conf.py python: version: 3.7 install: - requirements: docs/source/requirements.txtgit-secret-0.5.0/vendor/bats-core/AUTHORS000066400000000000000000000003331424706700600200130ustar00rootroot00000000000000Andrew Martin (https://control-plane.io/) Bianca Tamayo (https://biancatamayo.me/) Jason Karns (http://jasonkarns.com/) Mike Bland (https://mike-bland.com/) git-secret-0.5.0/vendor/bats-core/Dockerfile000066400000000000000000000012101424706700600207300ustar00rootroot00000000000000ARG bashver=latest FROM bash:${bashver} ARG TINI_VERSION=v0.19.0 ARG TARGETPLATFORM COPY ./docker /tmp/docker # default to amd64 when not running in buildx environment that provides target platform RUN /tmp/docker/install_tini.sh "${TARGETPLATFORM-linux/amd64}" # Install parallel and accept the citation notice (we aren't using this in a # context where it make sense to cite GNU Parallel). RUN apk add --no-cache parallel ncurses && \ mkdir -p ~/.parallel && touch ~/.parallel/will-cite RUN ln -s /opt/bats/bin/bats /usr/local/bin/bats COPY . /opt/bats/ RUN mkdir -p /code WORKDIR /code/ ENTRYPOINT ["/tini", "--", "bash", "bats"] git-secret-0.5.0/vendor/bats-core/LICENSE.md000066400000000000000000000047471424706700600203640ustar00rootroot00000000000000Copyright (c) 2017 bats-core contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --- * [bats-core] is a continuation of [bats]. Copyright for portions of the bats-core project are held by Sam Stephenson, 2014 as part of the project [bats], licensed under MIT: Copyright (c) 2014 Sam Stephenson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For details, please see the [version control history][commits]. [bats-core]: https://github.com/bats-core/bats-core [bats]:https://github.com/sstephenson/bats [commits]:https://github.com/bats-core/bats-core/commits/master git-secret-0.5.0/vendor/bats-core/README.md000066400000000000000000000104011424706700600202170ustar00rootroot00000000000000# Bats-core: Bash Automated Testing System (2018) [![Latest release](https://img.shields.io/github/release/bats-core/bats-core.svg)](https://github.com/bats-core/bats-core/releases/latest) [![npm package](https://img.shields.io/npm/v/bats.svg)](https://www.npmjs.com/package/bats) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/bats-core/bats-core/blob/master/LICENSE.md) [![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) [![Read the docs status](https://readthedocs.org/projects/bats-core/badge/)](https://bats-core.readthedocs.io) [![Join the chat in bats-core/bats-core on gitter](https://badges.gitter.im/bats-core/bats-core.svg)][gitter] Bats is a [TAP](https://testanything.org/)-compliant testing framework for Bash. It provides a simple way to verify that the UNIX programs you write behave as expected. A 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. ```bash #!/usr/bin/env bats @test "addition using bc" { result="$(echo 2+2 | bc)" [ "$result" -eq 4 ] } @test "addition using dc" { result="$(echo 2 2+p | dc)" [ "$result" -eq 4 ] } ``` Bats is most useful when testing software written in Bash, but you can use it to test any UNIX program. Test cases consist of standard shell commands. Bats makes use of Bash's `errexit` (`set -e`) option when running test cases. If every command in the test case exits with a `0` status code (success), the test passes. In this way, each line is an assertion of truth. ## Table of contents **NOTE** The documentation has moved to - [Testing](#testing) - [Support](#support) - [Contributing](#contributing) - [Contact](#contact) - [Version history](#version-history) - [Background](#background) * [What's the plan and why?](#whats-the-plan-and-why) * [Why was this fork created?](#why-was-this-fork-created) - [Copyright](#copyright) ## Testing ```sh bin/bats --tap test ``` See also the [CI](./.github/workflows/tests.yml) settings for the current test environment and scripts. ## Support The Bats source code repository is [hosted on GitHub](https://github.com/bats-core/bats-core). There you can file bugs on the issue tracker or submit tested pull requests for review. For real-world examples from open-source projects using Bats, see [Projects Using Bats](https://github.com/bats-core/bats-core/wiki/Projects-Using-Bats) on the wiki. To learn how to set up your editor for Bats syntax highlighting, see [Syntax Highlighting](https://github.com/bats-core/bats-core/wiki/Syntax-Highlighting) on the wiki. ## Contributing For now see the [`docs`](docs) folder for project guides, work with us on the wiki or look at the other communication channels. ## Contact - You can find and chat with us on our [Gitter]. ## Version history See `docs/CHANGELOG.md`. ## Background ### What's the plan and why? **Tuesday, September 19, 2017:** This was forked from [Bats][bats-orig] at commit [0360811][]. It was created via `git clone --bare` and `git push --mirror`. [bats-orig]: https://github.com/sstephenson/bats [0360811]: https://github.com/sstephenson/bats/commit/03608115df2071fff4eaaff1605768c275e5f81f This [bats-core repo](https://github.com/bats-core/bats-core) is the community-maintained Bats project. ### Why was this fork created? There 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. [call-maintain]: https://github.com/sstephenson/bats/issues/150 ## Copyright © 2017-2021 bats-core organization © 2011-2016 Sam Stephenson Bats is released under an MIT-style license; see `LICENSE.md` for details. See the [parent project](https://github.com/bats-core) at GitHub or the [AUTHORS](AUTHORS) file for the current project maintainer team. [gitter]: https://gitter.im/bats-core/bats-core git-secret-0.5.0/vendor/bats-core/bin/000077500000000000000000000000001424706700600175145ustar00rootroot00000000000000git-secret-0.5.0/vendor/bats-core/bin/bats000077500000000000000000000032131424706700600203720ustar00rootroot00000000000000#!/usr/bin/env bash set -euo pipefail if command -v greadlink >/dev/null; then bats_readlinkf() { greadlink -f "$1" } else bats_readlinkf() { readlink -f "$1" } fi fallback_to_readlinkf_posix() { bats_readlinkf() { [ "${1:-}" ] || return 1 max_symlinks=40 CDPATH='' # to avoid changing to an unexpected directory target=$1 [ -e "${target%/}" ] || target=${1%"${1##*[!/]}"} # trim trailing slashes [ -d "${target:-/}" ] && target="$target/" cd -P . 2>/dev/null || return 1 while [ "$max_symlinks" -ge 0 ] && max_symlinks=$((max_symlinks - 1)); do if [ ! "$target" = "${target%/*}" ]; then case $target in /*) cd -P "${target%/*}/" 2>/dev/null || break ;; *) cd -P "./${target%/*}" 2>/dev/null || break ;; esac target=${target##*/} fi if [ ! -L "$target" ]; then target="${PWD%/}${target:+/}${target}" printf '%s\n' "${target:-/}" return 0 fi # `ls -dl` format: "%s %u %s %s %u %s %s -> %s\n", # , , , , # , , , # https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html link=$(ls -dl -- "$target" 2>/dev/null) || break target=${link#*" $target -> "} done return 1 } } if ! BATS_PATH=$(bats_readlinkf "${BASH_SOURCE[0]}" 2>/dev/null); then fallback_to_readlinkf_posix BATS_PATH=$(bats_readlinkf "${BASH_SOURCE[0]}") fi export BATS_ROOT=${BATS_PATH%/*/*} export -f bats_readlinkf exec env BATS_ROOT="$BATS_ROOT" "$BATS_ROOT/libexec/bats-core/bats" "$@" git-secret-0.5.0/vendor/bats-core/contrib/000077500000000000000000000000001424706700600204045ustar00rootroot00000000000000git-secret-0.5.0/vendor/bats-core/contrib/release.sh000077500000000000000000000072731424706700600223740ustar00rootroot00000000000000#!/usr/bin/env bash # # bats-core git releaser # ## Usage: %SCRIPT_NAME% [options] ## ## Options: ## --major Major version bump ## --minor Minor version bump ## --patch Patch version bump ## ## -v, --version Print version ## --debug Enable debug mode ## -h, --help Display this message ## set -Eeuo pipefail DIR=$(cd "$(dirname "${0}")" && pwd) THIS_SCRIPT="${DIR}/$(basename "${0}")" BATS_VERSION=$( # shellcheck disable=SC1090 source <(grep '^export BATS_VERSION=' libexec/bats-core/bats) echo "${BATS_VERSION}" ) declare -r DIR declare -r THIS_SCRIPT declare -r BATS_VERSION BUMP_INTERVAL="" NEW_BATS_VERSION="" main() { handle_arguments "${@}" if [[ "${BUMP_INTERVAL:-}" == "" ]]; then echo "${BATS_VERSION}" exit 0 fi local NEW_BATS_VERSION NEW_BATS_VERSION=$(semver bump "${BUMP_INTERVAL}" "${BATS_VERSION}") declare -r NEW_BATS_VERSION local BATS_RELEASE_NOTES="/tmp/bats-release-${NEW_BATS_VERSION}" echo "Releasing: ${BATS_VERSION} to ${NEW_BATS_VERSION}" echo echo "Ensure docs/CHANGELOG.md is correctly updated" replace_in_files write_changelog git diff --staged cat </dev/null get_version() { echo "${THIS_SCRIPT_VERSION:-0.1}" } main "${@}" git-secret-0.5.0/vendor/bats-core/contrib/rpm/000077500000000000000000000000001424706700600212025ustar00rootroot00000000000000git-secret-0.5.0/vendor/bats-core/contrib/rpm/bats.spec000066400000000000000000000030471424706700600230130ustar00rootroot00000000000000%global provider github.com %global project bats-core %global repo bats-core Name: bats Version: 1.6.0 Release: 1%{?dist} Summary: Bash Automated Testing System Group: Development/Libraries License: MIT URL: https://%{provider}/%{project}/%{repo} Source0: https://%{provider}/%{project}/%{repo}/archive/v%{version}.tar.gz BuildArch: noarch Requires: bash %description Bats is a TAP-compliant testing framework for Bash. It provides a simple way to verify that the UNIX programs you write behave as expected. Bats is most useful when testing software written in Bash, but you can use it to test any UNIX program. %prep %setup -q -n %{repo}-%{version} %install mkdir -p ${RPM_BUILD_ROOT}%{_prefix} ${RPM_BUILD_ROOT}%{_libexecdir} ${RPM_BUILD_ROOT}%{_mandir} ./install.sh ${RPM_BUILD_ROOT}%{_prefix} %clean rm -rf $RPM_BUILD_ROOT %check %files %doc README.md LICENSE.md %{_bindir}/%{name} %{_libexecdir}/%{repo} %{_mandir}/man1/%{name}.1.gz %{_mandir}/man7/%{name}.7.gz %changelog * Tue Jul 08 2018 mbland - 1.1.0-1 - Increase version to match upstream release * Mon Jun 18 2018 pixdrift - 1.0.2-1 - Increase version to match upstream release - Relocate libraries to bats-core subdirectory * Sat Jun 09 2018 pixdrift - 1.0.1-1 - Increase version to match upstream release * Fri Jun 08 2018 pixdrift - 1.0.0-1 - Initial package build of forked (bats-core) github project git-secret-0.5.0/vendor/bats-core/contrib/semver000077500000000000000000000174451424706700600216460ustar00rootroot00000000000000#!/usr/bin/env bash # v3.0.0 # https://github.com/fsaintjacques/semver-tool set -o errexit -o nounset -o pipefail NAT='0|[1-9][0-9]*' ALPHANUM='[0-9]*[A-Za-z-][0-9A-Za-z-]*' IDENT="$NAT|$ALPHANUM" FIELD='[0-9A-Za-z-]+' SEMVER_REGEX="\ ^[vV]?\ ($NAT)\\.($NAT)\\.($NAT)\ (\\-(${IDENT})(\\.(${IDENT}))*)?\ (\\+${FIELD}(\\.${FIELD})*)?$" PROG=semver PROG_VERSION="3.0.0" USAGE="\ Usage: $PROG bump (major|minor|patch|release|prerel |build ) $PROG compare $PROG get (major|minor|patch|release|prerel|build) $PROG --help $PROG --version Arguments: A version must match the following regular expression: \"${SEMVER_REGEX}\" In English: -- The version must match X.Y.Z[-PRERELEASE][+BUILD] where X, Y and Z are non-negative integers. -- PRERELEASE is a dot separated sequence of non-negative integers and/or identifiers composed of alphanumeric characters and hyphens (with at least one non-digit). Numeric identifiers must not have leading zeros. A hyphen (\"-\") introduces this optional part. -- BUILD is a dot separated sequence of identifiers composed of alphanumeric characters and hyphens. A plus (\"+\") introduces this optional part. See definition. A string as defined by PRERELEASE above. A string as defined by BUILD above. Options: -v, --version Print the version of this tool. -h, --help Print this help message. Commands: bump Bump by one of major, minor, patch; zeroing or removing subsequent parts. \"bump prerel\" sets the PRERELEASE part and removes any BUILD part. \"bump build\" sets the BUILD part. \"bump release\" removes any PRERELEASE or BUILD parts. The bumped version is written to stdout. compare Compare with , output to stdout the following values: -1 if is newer, 0 if equal, 1 if older. The BUILD part is not used in comparisons. get Extract given part of , where part is one of major, minor, patch, prerel, build, or release. See also: https://semver.org -- Semantic Versioning 2.0.0" function error { echo -e "$1" >&2 exit 1 } function usage-help { error "$USAGE" } function usage-version { echo -e "${PROG}: $PROG_VERSION" exit 0 } function validate-version { local version=$1 if [[ "$version" =~ $SEMVER_REGEX ]]; then # if a second argument is passed, store the result in var named by $2 if [ "$#" -eq "2" ]; then local major=${BASH_REMATCH[1]} local minor=${BASH_REMATCH[2]} local patch=${BASH_REMATCH[3]} local prere=${BASH_REMATCH[4]} local build=${BASH_REMATCH[8]} eval "$2=(\"$major\" \"$minor\" \"$patch\" \"$prere\" \"$build\")" else echo "$version" fi else error "version $version does not match the semver scheme 'X.Y.Z(-PRERELEASE)(+BUILD)'. See help for more information." fi } function is-nat { [[ "$1" =~ ^($NAT)$ ]] } function is-null { [ -z "$1" ] } function order-nat { [ "$1" -lt "$2" ] && { echo -1 ; return ; } [ "$1" -gt "$2" ] && { echo 1 ; return ; } echo 0 } function order-string { [[ $1 < $2 ]] && { echo -1 ; return ; } [[ $1 > $2 ]] && { echo 1 ; return ; } echo 0 } # given two (named) arrays containing NAT and/or ALPHANUM fields, compare them # one by one according to semver 2.0.0 spec. Return -1, 0, 1 if left array ($1) # is less-than, equal, or greater-than the right array ($2). The longer array # is considered greater-than the shorter if the shorter is a prefix of the longer. # function compare-fields { local l="$1[@]" local r="$2[@]" local leftfield=( "${!l}" ) local rightfield=( "${!r}" ) local left local right local i=$(( -1 )) local order=$(( 0 )) while true do [ $order -ne 0 ] && { echo $order ; return ; } : $(( i++ )) left="${leftfield[$i]}" right="${rightfield[$i]}" is-null "$left" && is-null "$right" && { echo 0 ; return ; } is-null "$left" && { echo -1 ; return ; } is-null "$right" && { echo 1 ; return ; } is-nat "$left" && is-nat "$right" && { order=$(order-nat "$left" "$right") ; continue ; } is-nat "$left" && { echo -1 ; return ; } is-nat "$right" && { echo 1 ; return ; } { order=$(order-string "$left" "$right") ; continue ; } done } # shellcheck disable=SC2206 # checked by "validate"; ok to expand prerel id's into array function compare-version { local order validate-version "$1" V validate-version "$2" V_ # compare major, minor, patch local left=( "${V[0]}" "${V[1]}" "${V[2]}" ) local right=( "${V_[0]}" "${V_[1]}" "${V_[2]}" ) order=$(compare-fields left right) [ "$order" -ne 0 ] && { echo "$order" ; return ; } # compare pre-release ids when M.m.p are equal local prerel="${V[3]:1}" local prerel_="${V_[3]:1}" local left=( ${prerel//./ } ) local right=( ${prerel_//./ } ) # if left and right have no pre-release part, then left equals right # if only one of left/right has pre-release part, that one is less than simple M.m.p [ -z "$prerel" ] && [ -z "$prerel_" ] && { echo 0 ; return ; } [ -z "$prerel" ] && { echo 1 ; return ; } [ -z "$prerel_" ] && { echo -1 ; return ; } # otherwise, compare the pre-release id's compare-fields left right } function command-bump { local new; local version; local sub_version; local command; case $# in 2) case $1 in major|minor|patch|release) command=$1; version=$2;; *) usage-help;; esac ;; 3) case $1 in prerel|build) command=$1; sub_version=$2 version=$3 ;; *) usage-help;; esac ;; *) usage-help;; esac validate-version "$version" parts # shellcheck disable=SC2154 local major="${parts[0]}" local minor="${parts[1]}" local patch="${parts[2]}" local prere="${parts[3]}" local build="${parts[4]}" case "$command" in major) new="$((major + 1)).0.0";; minor) new="${major}.$((minor + 1)).0";; patch) new="${major}.${minor}.$((patch + 1))";; release) new="${major}.${minor}.${patch}";; prerel) new=$(validate-version "${major}.${minor}.${patch}-${sub_version}");; build) new=$(validate-version "${major}.${minor}.${patch}${prere}+${sub_version}");; *) usage-help ;; esac echo "$new" exit 0 } function command-compare { local v; local v_; case $# in 2) v=$(validate-version "$1"); v_=$(validate-version "$2") ;; *) usage-help ;; esac set +u # need unset array element to evaluate to null compare-version "$v" "$v_" exit 0 } # shellcheck disable=SC2034 function command-get { local part version if [[ "$#" -ne "2" ]] || [[ -z "$1" ]] || [[ -z "$2" ]]; then usage-help exit 0 fi part="$1" version="$2" validate-version "$version" parts local major="${parts[0]}" local minor="${parts[1]}" local patch="${parts[2]}" local prerel="${parts[3]:1}" local build="${parts[4]:1}" local release="${major}.${minor}.${patch}" case "$part" in major|minor|patch|release|prerel|build) echo "${!part}" ;; *) usage-help ;; esac exit 0 } case $# in 0) echo "Unknown command: $*"; usage-help;; esac case $1 in --help|-h) echo -e "$USAGE"; exit 0;; --version|-v) usage-version ;; bump) shift; command-bump "$@";; get) shift; command-get "$@";; compare) shift; command-compare "$@";; *) echo "Unknown arguments: $*"; usage-help;; esac git-secret-0.5.0/vendor/bats-core/docker-compose.override.dist000066400000000000000000000002231424706700600243560ustar00rootroot00000000000000# Copy this file to docker-compose.override.yml version: '3.6' services: bats: entrypoint: - "bash" networks: default: git-secret-0.5.0/vendor/bats-core/docker-compose.yml000066400000000000000000000003641424706700600224040ustar00rootroot00000000000000version: '3.6' services: bats: build: context: "." dockerfile: "Dockerfile" networks: - "default" user: "root" volumes: - "./:/opt/bats" networks: default: git-secret-0.5.0/vendor/bats-core/docker/000077500000000000000000000000001424706700600202135ustar00rootroot00000000000000git-secret-0.5.0/vendor/bats-core/docker/install_tini.sh000077500000000000000000000012201424706700600232360ustar00rootroot00000000000000#!/usr/bin/env bash set -e case ${1#linux/} in 386) TINI_PLATFORM=i386 ;; arm/v7) TINI_PLATFORM=armhf ;; arm/v6) TINI_PLATFORM=armel ;; *) TINI_PLATFORM=${1#linux/} ;; esac echo "Installing tini for $TINI_PLATFORM" wget "https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-static-${TINI_PLATFORM}" -O /tini wget "https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-static-${TINI_PLATFORM}.asc" -O /tini.asc chmod +x /tini apk add gnupg gpg --import < /tmp/docker/tini.pubkey.gpg gpg --batch --verify /tini.asc /tini apk del gnupg git-secret-0.5.0/vendor/bats-core/docker/tini.pubkey.gpg000066400000000000000000000151521424706700600231570ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- mQINBFANDtsBEACpb69Ul0Ko7D4XxRIvPGnDMuGdocb8PxR+EGbnHe0uS2tCbsfj TOoWWUrjufrWYxGlKNqOxbEhzFA2wSQ6VD6xROPQT5dAdKaGnSCiaUg7XTzcb9u3 a5Qbx99EDZWaYDNMnLZnIElDX+YmkkEyrrmjiML63m+1P88Bz7ag18hLkqpCiIVM TMRfQluBJVvndX7Stzm35utugN+xeTQryjLx74CO6TUWyC7hAjvQhR5IdAk4H0oT RsOKZ9OQmpO0CJ1XXpKkDdDc60WVrLp1jwq2M7fx/Nz+z13nTHa3fDw8j10+1k0+ c2HafM+GLR5CHlXVMqveWJrimII1ZILxRj/86fFCEC8ZhVW1ym4j+mqEENrzP4I7 L3OnyKLxNKIY9CFDhfzLhNAuNeuIp6KgynzuyxWnJO4q7m/B0zcRIBcjXPrpblIx QlT3qQ/vFdcylDDSdbgtjD+9URG6bFR9PVlRTllBDPGQEK8vjV44pxLCenm/TzdB Y4RlEePf+3y7wVrkjg+l4rIDH57Vl188RODuWVGeLZ3IYWqvRUnYxHmta27UH6zY 7FNN5p7H2VqP6v9GFhiHOCTKdUbQhOoPLmUTyBas0WsC8sXdwpTy3mJthzfUwgVN 2SIXPnndz7RcHwZtW1x9ZtVMDr6ll99kT63+sdZJHmUdlnDr+EGEd/L61QARAQAB tCBUaG9tYXMgT3JvemNvIDx0aG9tYXNAb3JvemNvLmZyPokCOAQTAQIAIgUCUA0O 2wIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQmoQVnXABpOViYA//dDQt 4f7NGbZNnQ0DgOGgBQjAabeaup6HX1UBVMBmU3OEKkUQoA62Aix8kOz19HJcuOl0 Y3koZ7pOrf/39s+tlZKvVuX7F6RFiJpx1+8f+f4IfQEPJRiurwkEp2zwTQfEOlo4 Jzv57pLUtmyJVnxMDi2vFeUue+j9BePp20Z1ZEaMBJDjmMZao3iVCVvSHZnS28vk D5+y8VUbyhH4dyaDtu8sb06vCu2uD7ZsMfDTtdkDWRqOLs8FdamZLf8P8AD6AX2c PhhASMWF7Ty2kRvhzHriuplzDUBqod38iLxoC2l5xoDjNMZsY0q9dOXBS5RsKws2 qxrJLa/F672lpxlMA9Xnm0LMCNMcnXreldUhl18zVNofIDGex5yP20djOxl7WsQ6 0VBAzbbiGLaKyfko5CuSmulzTJNOUNxHTiXjSi6Qz5+5lh0wYnHFulhiYE16EX25 /rhvDzN5BgsT3Kdyk/XT/klIB5k4eLXK8PgMsRzp+FDVUL7HKM1HpHMY65gdSR8y ZuXzKXVC43MFPYJMrjdxoEJXJjnzhf+KO6jkyrna0OQoM1YTH6/5X9XoXzQz8TDe 7pJt4S27PZCv1NhuqNv7nPhUANr7nFMRzrbx2DNHyxUrxPvuyNmYx/KkoAzw3yaT frbFXU6ccwsXWW6zdcyLEYI2ZqGDfLS7zkjmRsa5AQ0EUzNVzQEIAKxWZf55R676 M3IURgx8Ovt8+F3M4Tj+ifePcpY5JHSj9sGkJRugW9Nye5WehuJjFYOEhKrljCTP /mjnE7iQqVTyYC1Ar+cTtNQpadWvQR2MW/UzimdZjBtZxdtGFCWR203jtnG+LGRs R7HyR6A8OBKLl0heTSHx92f+dJCGESZJeVgY49xNOlG4ILl8NseYhaD36QQZReLn Cazy2aOep2H/jz7vnzye38QMkdHcjaw/WfQHWDKzM5Wlf+5TLF/2VTPlKcmtn0QF Rw/vw6kjwsv9eCQ3ThIn/FV/ycdUkhOfz9Su2aIbwYC4C6Xi82RxJKbnqUGOExeC PG2luuWnyQcAEQEAAYkDRAQYAQIADwUCUzNVzQIbAgUJA8JnAAEpCRCahBWdcAGk 5cBdIAQZAQIABgUCUzNVzQAKCRAqiuDav/LlpshzCACnQxndwXLZYWwiXOiYvmUI U9mPKynUW2vfTwaIpFBIYnqLAjVsPspwfx7zYCoMtQ+UK9d+Jhyts8vCaPwJHPqC CrBbP/y9K2zRdcDA1DYW/cuubwcstypmO6Eh6iC6xRxa5IHZogK6U+Trqf/EGfI/ Y/sc3KBVYSdLkngASdVr5TQltVH9LsxDUo7Ba382Ci0g/VmKkUht/aFRkEfvMrrj ONEGbyCwk2hZuwK1aE6Yweq3tbzrByOF4wqIIe6e1pwPz7lchoGYm7XJ7uckpbGi lZojvu9ruxbGl8tirY/Bj0UZYjASDNCcXXRMvri2FZhDyWMMoeRLj7Mw8xpeWjr7 NhoP/2AA16HHwRjfPQo5fDXe7eGXIebwWhbr1nAYQtL2PHFeHG/imEVozcftENNt tVwq/JcfjyiIcKA0niGZmroQCO0HRzRs7T85ITWfWcn/Hqaok6gmLh6QJ6daC7E9 Mse07zYM52S2/cS4osfzZj4JEC2n82VuqK9fqzR58GCkPn9rshwljEkMgEfYfTvA k/tm8jACpSdH3bCpSP2rL6FBtm+RuL8zbAucg8BCaVPoOhtp3326MWCnxH7QdiHl 1dT4Dgmq4UluXOvyMZY7HI1cq4RXW5eXG5mG0ATQh1JIhIJUaEPzdaEtP5LOVqKE 4220MVCWWak/27O9mAFm+lBA5d8O8MWW2ERqpwyYMWg/DVvQP/pB/D6wO4Dp7CMD MLl1LszHab9oRo8vW2cWNVS6mQ/56jgS10nRe8o/VQROfd1De6sk5k9ypk2y2iC7 pp7sime3MsnzjR0fKcxjCDAX1Sopi9QzkypM66WHO46Uamn0GeL7OhcwjcoURzJc y5ue1jeeKmmR7ATexlgE87rA4nuMZak1uVz0s6Fsb1ekYIKFEFqwEpqNnyKgBrvt GA8yn9Zp4wF+6luaKMqwptx0q1PmMZacN9E62XdOyGBaVXPq599F3R6049zo04oW WMW7s7V10Vn/pqRkB4bhhUzatiUHWVuamhpR8SligZ4kWPHZuQINBFANDtsBEADJ MvBhyWEBoLgi9nO9hgbbLxiLjKnotKzRpu5m79rhpmtqEN2k0APmoRdUUrE2Y8sd Z551jT0TE2O1j70qLV9c5puK6qyV3BZb9OgQ8wqyCFFjmIdPQAEgnD3K92SOh8Mu lqJW++EsxSqDBt2iVbLyzQuklbIJOg4nVK8ZgswIyewiHVeh3xgcGxJtVb3QjKSz xhj0GYM6X7mo5rjzxEFVyiJXd8ZH79y4FHUr+tJQEzJbvWAGJClPx9czh9Drw2r+ Tgq+2v/EkAoyXdv3z7uChh/9s33oQtssJ5TVfAbC06QsPp55RJCkGbTrBQgRB8Xa idPJhG9sIbhVgrRejn5kmK5L/8ACngbSU4zO1NTaquLZGZMzI7Jbx/QeG2DbVqjV 6BLA3X+WieM9IUa1vi/CXiKedzlOMv7+CX9N76y4Wls4zsTwXTIzmPCDoysG+75D AoFZW1XJlMeEOGPhBDlR6X47qdLGzOI14NJZELni14+Iih6VvxhvUWmJfTnT+zE+ PWb03C0EHsF8uTYqBPag9LYw2cDqvP31bUSiV+Z5YR+4sDcfiVT40rXECd1752Ia yANeL7uG/gBvl+6LHzb3VhI5ILkknVummVY0ry8YpAA0r1GfBE/mFLE3jwTqYkMx nr/SDa3HIql7qBh9k9AhTMId8tXX6p3lO6jd6TeewQARAQABiQIfBBgBAgAJBQJQ DQ7bAhsMAAoJEJqEFZ1wAaTlTeIP/R6/0EAqKyISxnx/6+VCy2j5mj4v8b+KauTT deXJhP37i2EMsosGqUD1LMo8Wv9Az7XOSA/2lW4v8UHQolGwssLFm9L4DDTZBH8M gOFzB++wHNxgIoD2u9vC2eehhMfVlCcH+YWtzTSs94+5gI9xcy8rejkO+AHhXYDR 0nr5MM076CWEjWtORgZdHbXWilmr/SdKnIdvkXDXvNcd7tC6izIfnDxN7/4beWOF nv/1s0JLzIFIutFtqqYDC8Y/4JxoMcALhmop+FyYk+RUHT5uGeDauJunjwdBS3VY 5NrMcw4LxapV0OQExxu8RAMcYXx6FZmoBMlFI+J6R5ZMS6y1TKLKIpq46CsOSz2V X1SAactdOpXuNOXLe2cv0mYswWGAURebcmcmN49n9JEn1IN8hhawFgFuYdUWjpYx K2K6NZ0vFgRHkRnei9xrf2mW7ob1vKwzeBYGvZj/xIEu/Fv3kizS6t1IeMJKUKlp semAObW+sEO0jLOelL+ZfUO+fImL+0fFxQyzkfNKk5dpxztPlNmv3DY6KTddc1L1 uOGCznAmsg8Jp0v0OmCB2Xl15WPwwnYi3CkLGbEcK9stFmu2pZuEeR2DuVGlz3Nr Bu1W/34cXeyudUTxveehuvfkjYBMXVfEM35BHEUqgCtA49b5ZM8SpYgqU3omVsNz 7RjMAIe3uQINBFaoGQEBEACypQbnC5fMhpCft6augXnnVzmEh0Se2wBxUum3DMFl U48DJYNlEsKQYsgzEvaayTI0gA1ZyeDg3E4Fnk6ysQmzW9BJ/3Q2pa0GKIkvXOgL nwvSXSnTTqK3zCDuJI0Nj4u9gI8bX7d4PHqQyyFzPWjiIbg9tWHbhT8wwCaay1iG qCZsTa8Iwyve0WaV+7YtRJQeXEfY9Z6oEGqjis7QJNef1MKy1gS1Kq+4sqvdwgo3 f3AFSNR14gagYv2myA30ehf4EzzIi8dh9DATc4T86CBuK3TszILLSUwFnrUVT00j 3sr2WiqWrxIq/paky8zNEV3Q0vaf2kheLSZRSZsoVH1AfCsVHj4OoWH3BOAzdr5w sTPsV2HVR0O9K98NoA0f45eqfMFBiGVsFuJamBJatPsTVVXZ6fR9aDDKySSB540W egHoABwai+s4FhUtjjZarLPJo47/gFmxF7HHUyNIYYKj5j99h00zcM7XOtKeyHzH vfZvmu150u2DccY9XX5xdzDsWuBeQJQ7VdyVVTPoZGIBZ1Mw3EIfFyAzYvglTCKo MMHH6912PnsMLcbcmF/7pJ4rrehp8bkfS7R3BBNMglLWtoZIYBSWoK8Nl0OyBzQ5 lsPvRdUHuMe6rxwA11gRnx4yLd91bWRw/xIBwxz6Jq/lk0ySgdum/hIcOmrNdg73 swARAQABiQQ+BBgBAgAJBQJWqBkBAhsCAikJEJqEFZ1wAaTlwV0gBBkBAgAGBQJW qBkBAAoJEAtYjf8FJ6m3uPQP/jonQ5QrOEN+B7ddYmotAwj6wL9whs7rcgb+TJfI rJskyBQG+kHymWEBiODo/AcqkKglGzTNcaDG153l38/IQ/Lo9mxZmkNHtLD6Srkb GjNrBIksRSR+hWbr8UjA/WuqAmDQvFWebmyF4p6deEAf3Rsv2Ml/a0lvC6TyWRds dMyWlDPtlKYn9q2qHjCVX4e2m4uB38Vq3fo8+Ypags5KRC9KyGgZFEGy3F37p+4U /rDT+t/6oKuo5/8RWAixeWNWIli7DQ9DbA4w9qdwL4KGwcnOCcCClT9KqKA3MOds r+dcAF+LkNrG3yvnp+eZ7LHF6PVJAkXnSLOzuEZzXp90pA+1Sw7QWGWpyV/v6CSP sxZInLPjBPJmdVhjMrma2s9SGKs2k4eivDeK4Gr6oF3GRK3VQzsRPDYk9vr8wSbA BR4Qh6Fy/WiME1SyEdcs2UWc+eGZ0ya7QEkQqz7Cvjp6VezUtXWFgy28pVkgEORE sqogypjbSnybeis6Rzvxf0g681fWjWSTcMBGXKTvgW7XnLqG9XMWdx0n6pa6s5yL nkoM5zYcjL+V6wDVQwnF9uoallcO11PEjsEMeK3gz0Y81EmLuHN6411IK1cWfxAI HunwOoPe7nzGOH2EX1+IkCv4PPJqMloEcIIPlwP0ILxTaPuy17wed0pH3dvRZglv J7qQU/AP/3Nhh5AjUtMRI+mDgJpXpYuMy7tNdgKAvgGIL1bP+1LnLtP2+7uy1Pok 3938/eAJwAT9sOhpG3qRPs15zj4tc20/Jsypbk4032EhRFWGL5TBtYf9LVl9doFY hGHUgAzREWcw8l7h0/p5VNPm9K0kElCw2fN3z7xwreSPa1WGVsqMdM3nc/B44ocZ HFqrd9kg6N4al6IxkbL7DYAUjfhjkhOQXZXU+MLPVA9lflF4694lbrr7F4GwnzfF 8/SOw9LHVh9K3agno6jHB64P/Vqtka4a5+9AKcEkojWEHDoLU8BMUXDZZu9OkFSJ tzqByAzti0dsLE+8GGfas47b3/rjf6qyKvh2+iPw+I6zHH4k7LKpIiK+MkQ2+ZfM zB3jQ9NPNAc63AL/YbnF5XDSFxGBRkcFZo50rZJV5WHA3p+UMISsjoNizE7agLqI 2JPnKBzB3aQFFpI3QiivWhKfsO02Vtzl+1TjqReWu4qS1uwJbSsLectAy+4K2WFn RNZ1m/r9/enzEhyKo8zOmUBUzVLhRR/GG7S1MmxB8FSOZh7aHg1xbTYVvq62AW6a 0PKvEpn1g0wvPEoKQ+41/dc/ieWgnkZiKJJFxDshKGmxfDznWnZqnOESLz/3hbGy U41nk0UPzHlkUZwsLo9UBdr9fUVYvlYUylBp2dV0jEc5qL62gypA =4tCW -----END PGP PUBLIC KEY BLOCK----- git-secret-0.5.0/vendor/bats-core/docs/000077500000000000000000000000001424706700600176745ustar00rootroot00000000000000git-secret-0.5.0/vendor/bats-core/docs/.markdownlint.json000066400000000000000000000000511424706700600233520ustar00rootroot00000000000000{ "MD024": { "siblings_only": true } } git-secret-0.5.0/vendor/bats-core/docs/CHANGELOG.md000066400000000000000000000315371424706700600215160ustar00rootroot00000000000000# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog][kac] and this project adheres to [Semantic Versioning][semver]. [kac]: https://keepachangelog.com/en/1.0.0/ [semver]: https://semver.org/ ## [Unreleased] ## [1.6.0] - 2022-02-24 ### Added * new flag `--code-quote-style` (and `$BATS_CODE_QUOTE_STYLE`) to customize quotes around code blocks in error output (#506) * an example/regression test for running background tasks without blocking the test run (#525, #535) * `bats_load_library` for loading libraries from the search path `$BATS_LIB_PATH` (#548) ### Fixed * improved error trace for some broken cases (#279) * removed leftover debug file `/tmp/latch` in selftest suite (single use latch) (#516) * fix recurring errors on CTRL+C tests with NPM on Windows in selftest suite (#516) * fixed leaking of local variables from debug trap (#520) * don't mark FD3 output from `teardown_file` as `` in junit output (#532) * fix unbound variable error with Bash pre 4.4 (#550) #### Documentation * remove links to defunct freenode IRC channel (#515) * improved grammar (#534) * fixed link to TAP spec (#537) ## [1.5.0] - 2021-10-22 ### Added * new command line flags (#488) * `--verbose-run`: Make `run` print `$output` by default * `-x`, `--trace`: Print test commands as they are executed (like `set -x`)` * `--show-output-of-passing-tests`: Print output of passing tests * `--print-output-on-failure`: Automatically print the value of `$output` on failed tests * `--gather-test-outputs-in `: Gather the output of failing **and** passing tests as files in directory * Experimental: add return code checks to `run` via `!`/`-` (#367, #507) * `install.sh` and `uninstall.sh` take an optional second parameter for the lib folder name to allow for multilib install, e.g. into lib64 (#452) * add `run` flag `--keep-empty-lines` to retain empty lines in `${lines[@]}` (#224, a894fbfa) * add `run` flag `--separate-stderr` which also fills `$stderr` and `$stderr_lines` (#47, 5c9b173d, #507) ### Fixed * don't glob `run`'s `$output` when splitting into `${lines[@]}` (#151, #152, #158, #156, #281, #289) * remove empty line after test with pretty formatter on some terminals (#481) * don't run setup_file/teardown_file on files without tests, e.g. due to filtering (#484) * print final line without newline on Bash 3.2 for midtest (ERREXIT) failures too (#495, #145) * abort with error on missing flock/shlock when running in parallel mode (#496) * improved `set -u` test and fixed some unset variable accesses (#498, #501) * shorten suite/file/test temporary folder paths to leave enough space even on restricted systems (#503) #### Documentation * minor edits (#478) ## [1.4.1] - 2021-07-24 ### Added * Docker image architectures amd64, 386, arm64, arm/v7, arm/v6, ppc64le, s390x (#438) ### Fixed * automatic push to Dockerhub (#438) ## [1.4.0] - 2021-07-23 ### Added * added BATS_TEST_TMPDIR, BATS_FILE_TMPDIR, BATS_SUITE_TMPDIR (#413) * added checks and improved documentation for `$BATS_TMPDIR` (#410) * the docker container now uses [tini](https://github.com/krallin/tini) as the container entrypoint to improve signal forwarding (#407) * script to uninstall bats from a given prefix (#400) * replace preprocessed file path (e.g. `/tmp/bats-run-22908-NP0f9h/bats.23102.src`) with original filename in stdout/err (but not FD3!) (#429) * print aborted command on SIGINT/CTRL+C (#368) * print error message when BATS_RUN_TMPDIR could not be created (#422) #### Documentation * added tutorial for new users (#397) * fixed example invocation of docker container (#440) * minor edits (#431, #439, #445, #463, #464, #465) ### Fixed * fix `bats_tap_stream_unknown: command not found` with pretty formatter, when writing non compliant extended output (#412) * avoid collisions on `$BATS_RUN_TMPDIR` with `--no-tempdir-cleanup` and docker by using `mktemp` additionally to PID (#409) * pretty printer now puts text that is printed to FD 3 below the test name (#426) * `rm semaphores/slot-: No such file or directory` in parallel mode on MacOS (#434, #433) * fix YAML blocks in TAP13 formatter using `...` instead of `---` to start a block (#442) * fixed some typos in comments (#441, #447) * ensure `/code` exists in docker container, to make examples work again (#440) * also display error messages from free code (#429) * npm installed version on Windows: fix broken internal LIBEXEC paths (#459) ## [1.3.0] - 2021-03-08 ### Added * custom test-file extension via `BATS_FILE_EXTENSION` when searching for test files in a directory (#376) * TAP13 formatter, including millisecond timing (#337) * automatic release to NPM via Github Actions (#406) #### Documentation * added documentation about overusing `run` (#343) * improved documentation of `load` (#332) ### Changed * recursive suite mode will follow symlinks now (#370) * split options for (file-) `--report-formatter` and (stdout) `--formatter` (#345) * **WARNING**: This changes the meaning of `--formatter junit`. stdout will now show unified xml instead of TAP. From now on, please use `--report-formatter junit` to obtain the `.xml` report file! * removed `--parallel-preserve-environment` flag, as this is the default behavior (#324) * moved CI from Travis/Appveyor to Github Actions (#405) * preprocessed files are no longer removed if `--no-tempdir-cleanup` is specified (#395) #### Documentation * moved documentation to [readthedocs](https://bats-core.readthedocs.io/en/latest/) ### Fixed #### Correctness * fix internal failures due to unbound variables when test files use `set -u` (#392) * fix internal failures due to changes to `$PATH` in test files (#387) * fix test duration always being 0 on busybox installs (#363) * fix hangs on CTRL+C (#354) * make `BATS_TEST_NUMBER` count per file again (#326) * include `lib/` in npm package (#352) #### Performance * don't fork bomb in parallel mode (#339) * preprocess each file only once (#335) * avoid running duplicate files n^2 times (#338) #### Documentation * fix documentation for `--formatter junit` (#334) * fix documentation for `setup_file` variables (#333) * fix link to examples page (#331) * fix link to "File Descriptor 3" section (#301) ## [1.2.1] - 2020-07-06 ### Added * JUnit output and extensible formatter rewrite (#246) * `load` function now reads from absolute and relative paths, and $PATH (#282) * Beginner-friendly examples in /docs/examples (#243) * @peshay's `bats-file` fork contributed to `bats-core/bats-file` (#276) ### Changed * Duplicate test names now error (previous behaviour was to issue a warning) (#286) * Changed default formatter in Docker to pretty by adding `ncurses` to Dockerfile, override with `--tap` (#239) * Replace "readlink -f" dependency with Bash solution (#217) ## [1.2.0] - 2020-04-25 Support parallel suite execution and filtering by test name. ### Added * docs/CHANGELOG.md and docs/releasing.md (#122) * The `-f, --filter` flag to run only the tests matching a regular expression (#126) * Optimize stack trace capture (#138) * `--jobs n` flag to support parallel execution of tests with GNU parallel (#172) ### Changed * AppVeyor builds are now semver-compliant (#123) * Add Bash 5 as test target (#181) * Always use upper case signal names to avoid locale dependent err… (#215) * Fix for tests reading from stdin (#227) * Fix wrong line numbers of errors in bash < 4.4 (#229) * Remove preprocessed source after test run (#232) ## [1.1.0] - 2018-07-08 This is the first release with new features relative to the original Bats 0.4.0. ### Added * The `-r, --recursive` flag to scan directory arguments recursively for `*.bats` files (#109) * The `contrib/rpm/bats.spec` file to build RPMs (#111) ### Changed * Travis exercises latest versions of Bash from 3.2 through 4.4 (#116, #117) * Error output highlights invalid command line options (#45, #46, #118) * Replaced `echo` with `printf` (#120) ### Fixed * Fixed `BATS_ERROR_STATUS` getting lost when `bats_error_trap` fired multiple times under Bash 4.2.x (#110) * Updated `bin/bats` symlink resolution, handling the case on CentOS where `/bin` is a symlink to `/usr/bin` (#113, #115) ## [1.0.2] - 2018-06-18 * Fixed sstephenson/bats#240, whereby `skip` messages containing parentheses were truncated (#48) * Doc improvements: * Docker usage (#94) * Better README badges (#101) * Better installation instructions (#102, #104) * Packaging/installation improvements: * package.json update (#100) * Moved `libexec/` files to `libexec/bats-core/`, improved `install.sh` (#105) ## [1.0.1] - 2018-06-09 * Fixed a `BATS_CWD` bug introduced in #91 whereby it was set to the parent of `PWD`, when it should've been set to `PWD` itself (#98). This caused file names in stack traces to contain the basename of `PWD` as a prefix, when the names should've been purely relative to `PWD`. * Ensure the last line of test output prints when it doesn't end with a newline (#99). This was a quasi-bug introduced by replacing `sed` with `while` in #88. ## [1.0.0] - 2018-06-08 `1.0.0` generally preserves compatibility with `0.4.0`, but with some Bash compatibility improvements and a massive performance boost. In other words: * all existing tests should remain compatible * tests that might've failed or exhibited unexpected behavior on earlier versions of Bash should now also pass or behave as expected Changes: * Added support for Docker. * Added support for test scripts that have the [unofficial strict mode](http://redsymbol.net/articles/unofficial-bash-strict-mode/) enabled. * Improved stability on Windows and macOS platforms. * Massive performance improvements, especially on Windows (#8) * Workarounds for inconsistent behavior between Bash versions (#82) * Workaround for preserving stack info after calling an exported function under Bash < 4.4 (#87) * Fixed TAP compliance for skipped tests * Added support for tabs in test names. * `bin/bats` and `install.sh` now work reliably on Windows (#91) ## [0.4.0] - 2014-08-13 * Improved the display of failing test cases. Bats now shows the source code of failing test lines, along with full stack traces including function names, filenames, and line numbers. * Improved the display of the pretty-printed test summary line to include the number of skipped tests, if any. * Improved the speed of the preprocessor, dramatically shortening test and suite startup times. * Added support for absolute pathnames to the `load` helper. * Added support for single-line `@test` definitions. * Added bats(1) and bats(7) manual pages. * Modified the `bats` command to default to TAP output when the `$CI` variable is set, to better support environments such as Travis CI. ## [0.3.1] - 2013-10-28 * Fixed an incompatibility with the pretty formatter in certain environments such as tmux. * Fixed a bug where the pretty formatter would crash if the first line of a test file's output was invalid TAP. ## [0.3.0] - 2013-10-21 * Improved formatting for tests run from a terminal. Failing tests are now colored in red, and the total number of failing tests is displayed at the end of the test run. When Bats is not connected to a terminal (e.g. in CI runs), or when invoked with the `--tap` flag, output is displayed in standard TAP format. * Added the ability to skip tests using the `skip` command. * Added a message to failing test case output indicating the file and line number of the statement that caused the test to fail. * Added "ad-hoc" test suite support. You can now invoke `bats` with multiple filename or directory arguments to run all the specified tests in aggregate. * Added support for test files with Windows line endings. * Fixed regular expression warnings from certain versions of Bash. * Fixed a bug running tests containing lines that begin with `-e`. ## [0.2.0] - 2012-11-16 * Added test suite support. The `bats` command accepts a directory name containing multiple test files to be run in aggregate. * Added the ability to count the number of test cases in a file or suite by passing the `-c` flag to `bats`. * Preprocessed sources are cached between test case runs in the same file for better performance. ## [0.1.0] - 2011-12-30 * Initial public release. [Unreleased]: https://github.com/bats-core/bats-core/compare/v1.1.0...HEAD [1.1.0]: https://github.com/bats-core/bats-core/compare/v1.0.2...v1.1.0 [1.0.2]: https://github.com/bats-core/bats-core/compare/v1.0.1...v1.0.2 [1.0.1]: https://github.com/bats-core/bats-core/compare/v1.0.0...v1.0.1 [1.0.0]: https://github.com/bats-core/bats-core/compare/v0.4.0...v1.0.0 [0.4.0]: https://github.com/bats-core/bats-core/compare/v0.3.1...v0.4.0 [0.3.1]: https://github.com/bats-core/bats-core/compare/v0.3.0...v0.3.1 [0.3.0]: https://github.com/bats-core/bats-core/compare/v0.2.0...v0.3.0 [0.2.0]: https://github.com/bats-core/bats-core/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/bats-core/bats-core/commits/v0.1.0 git-secret-0.5.0/vendor/bats-core/docs/CODEOWNERS000066400000000000000000000003231424706700600212650ustar00rootroot00000000000000# This enables automatic code review requests per: # - https://help.github.com/articles/about-codeowners/ # - https://help.github.com/articles/enabling-required-reviews-for-pull-requests/ * @bats-core/bats-core git-secret-0.5.0/vendor/bats-core/docs/CODE_OF_CONDUCT.md000066400000000000000000000070731424706700600225020ustar00rootroot00000000000000# Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting one of the current [project maintainers](#project-maintainers) listed below. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Project Maintainers ### Current Maintainers * [Bianca Tamayo][bt-gh] * [Mike Bland][mb-gh] * [Jason Karns][jk-gh] * [Andrew Martin][am-gh] ### Past Maintainers * Sam Stephenson <> (Original author) ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] [bt-gh]: https://github.com/btamayo [mb-gh]: https://github.com/mbland [jk-gh]: https://github.com/jasonkarns [am-gh]: https://github.com/sublimino [homepage]: https://contributor-covenant.org [version]: https://contributor-covenant.org/version/1/4/ git-secret-0.5.0/vendor/bats-core/docs/CONTRIBUTING.md000066400000000000000000000413121424706700600221260ustar00rootroot00000000000000# Contributing Guidelines ## Welcome! Thank you for considering contributing to the development of this project's development and/or documentation. Just a reminder: if you're new to this project or to OSS and want to find issues to work on, please check the following labels on issues: - [help wanted][helpwantedlabel] - [docs][docslabel] - [good first issue][goodfirstissuelabel] [docslabel]: https://github.com/bats-core/bats-core/labels/docs [helpwantedlabel]: https://github.com/bats-core/bats-core/labels/help%20wanted [goodfirstissuelabel]: https://github.com/bats-core/bats-core/labels/good%20first%20issue To see all labels and their meanings, [check this wiki page][labelswiki]. This guide borrows **heavily** from [@mbland's go-script-bash][gsb] (with some sections directly quoted), which in turn was drafted with tips from [Wrangling Web Contributions: How to Build a CONTRIBUTING.md][moz] and with some inspiration from [the Atom project's CONTRIBUTING.md file][atom]. [gsb]: https://github.com/mbland/go-script-bash/blob/master/CONTRIBUTING.md [moz]: https://mozillascience.github.io/working-open-workshop/contributing/ [atom]: https://github.com/atom/atom/blob/master/CONTRIBUTING.md [labelswiki]: https://github.com/bats-core/bats-core/wiki/GitHub-Issue-Labels ## Table of contents * [Contributing Guidelines](#contributing-guidelines) * [Welcome!](#welcome) * [Table of contents](#table-of-contents) * [Quick links 🔗](#quick-links-) * [Contributor License Agreement](#contributor-license-agreement) * [Code of conduct](#code-of-conduct) * [Asking questions and reporting issues](#asking-questions-and-reporting-issues) * [Updating documentation](#updating-documentation) * [Environment setup](#environment-setup) * [Workflow](#workflow) * [Testing](#testing) * [Coding conventions](#coding-conventions) * [Formatting](#formatting) * [Naming](#naming) * [Function declarations](#function-declarations) * [Variable and parameter declarations](#variable-and-parameter-declarations) * [Command substitution](#command-substitution) * [Process substitution](#process-substitution) * [Conditionals and loops](#conditionals-and-loops) * [Generating output](#generating-output) * [Gotchas](#gotchas) * [Open Source License](#open-source-license) * [Credits](#credits) ## Quick links 🔗 - [Gitter channel →][gitterurl]: Feel free to come chat with us on Gitter - [README →][README] - [Code of conduct →][CODE_OF_CONDUCT] - [License information →][LICENSE] - [Original repository →][repohome] - [Issues →][repoissues] - [Pull requests →][repoprs] - [Milestones →][repomilestones] - [Projects →][repoprojects] [README]: https://github.com/bats-core/bats-core/blob/master/README.md [CODE_OF_CONDUCT]: https://github.com/bats-core/bats-core/blob/master/docs/CODE_OF_CONDUCT.md [LICENSE]: https://github.com/bats-core/bats-core/blob/master/LICENSE.md ## Contributor License Agreement Per the [GitHub Terms of Service][gh-tos], be aware that by making a contribution to this project, you agree: * to license your contribution under the same terms as [this project's license][osmit], and * that you have the right to license your contribution under those terms. See also: ["Does my project need an additional contributor agreement? Probably not."][cla-needed] [gh-tos]: https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license [osmit]: #open-source-license [cla-needed]: https://opensource.guide/legal/#does-my-project-need-an-additional-contributor-agreement ## Code of conduct Harrassment or rudeness of any kind will not be tolerated, period. For specifics, see the [CODE_OF_CONDUCT][] file. ## Asking questions and reporting issues ### Asking questions Please check the [README][] or existing [issues][repoissues] first. If you cannot find an answer to your question, please feel free to hop on our [Gitter][gitterurl]. [![Gitter](https://badges.gitter.im/bats-core/bats-core.svg)](https://gitter.im/bats-core/bats-core) ### Reporting issues Before reporting an issue, please use the search feature on the [issues page][repoissues] to see if an issue matching the one you've observed has already been filed. ### Updating or filing a new issue #### Information to include Try to be as specific as possible about your environment and the problem you're observing. At a minimum, include: #### Installation issues 1. State the version of Bash you're using `bash --version` 1. State your operating system and its version 1. If you're installing through homebrew, run `brew doctor`, and attach the output of `brew info bats-core` #### Bugs/usage issues 1. State the version of Bash you're using `bash --version` 1. State your operating system and its version 1. Command line steps or code snippets that reproduce the issue 1. Any apparently relevant information from the [Bash changelog][bash-changes] [bash-changes]: https://tiswww.case.edu/php/chet/bash/CHANGES Also consider using: - Bash's `time` builtin to collect running times - a regression test to add to the suite - memory usage as reported by a tool such as [memusg](https://gist.github.com/netj/526585) ### On existing issues 1. DO NOT add a +1 comment: Use the reactions provided instead 1. DO add information if you're facing a similar issue to someone else, but within a different context (e.g. different steps needed to reproduce the issue than previous stated, different version of Bash or BATS, different OS, etc.) You can read on how to do that here: [Information to include][#information-to-include] 1. DO remember that you can use the *Subscribe* button on the right side of the page to receive notifications of further conversations or a resolution. ## Updating documentation We love documentation and people who love documentation! If you love writing clear, accessible docs, please don't be shy about pull requests. Remember: docs are just as important as code. Also: _no typo is too small to fix!_ Really. Of course, batches of fixes are preferred, but even one nit is one nit too many. ## Environment setup Make sure you have Bash installed per the [Environment setup in the README][env-setup]. [env-setup]: https://github.com/bats-core/bats-core/blob/master/README.md#environment-setup ## Workflow The basic workflow for submitting changes resembles that of the [GitHub Git Flow][github-flow] (a.k.a. GitHub Flow), except that you will be working with your own fork of the repository and issuing pull requests to the original. [github-flow]: https://guides.github.com/introduction/flow/ 1. Fork the repo on GitHub (look for the "Fork" button) 1. Clone your forked repo to your local machine 1. Create your feature branch (`git checkout -b my-new-feature`) 1. Develop _and [test](#testing)_ your changes as necessary. 1. Commit your changes (`git commit -am 'Add some feature'`) 1. Push to the branch (`git push origin my-new-feature`) 1. Create a new [GitHub pull request][gh-pr] for your feature branch based against the original repository's `master` branch 1. If your request is accepted, you can [delete your feature branch][rm-branch] and pull the updated `master` branch from the original repository into your fork. You may even [delete your fork][rm-fork] if you don't anticipate making further changes. [gh-pr]: https://help.github.com/articles/using-pull-requests/ [rm-branch]: https://help.github.com/articles/deleting-unused-branches/ [rm-fork]: https://help.github.com/articles/deleting-a-repository/ ## Testing - 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) ## Coding conventions - [Formatting](#formatting) - [Naming](#naming) - [Variable and parameter declarations](#variable-and-parameter-declarations) - [Command substitution](#command-substitution) - [Conditions and loops](#conditionals-and-loops) - [Gotchas](#gotchas) ### Formatting - Keep all files 80 characters wide. - Indent using two spaces. - Enclose all variables in double quotes when used to avoid having them interpreted as glob patterns (unless the variable contains a glob pattern) and to avoid word splitting when the value contains spaces. Both scenarios can introduce errors that often prove difficult to diagnose. - **This is especially important when the variable is used to generate a glob pattern**, since spaces may appear in a path value. - If the variable itself contains a glob pattern, make sure to set `IFS=$'\n'` before using it so that the pattern itself and any matching file names containing spaces are not split apart. - Exceptions: Quotes are not required within math contexts, i.e. `(( ))` or `$(( ))`, and must not be used for variables on the right side of the `=~` operator. - Enclose all string literals in single quotes. - Exception: If the string contains an apostrophe, use double quotes. - Use quotes around variables and literals even inside of `[[ ]]` conditions. - This is because strings that contain '[' or ']' characters may fail to compare equally when they should. - Exception: Do not quote variables that contain regular expression patterns appearing on the right side of the `=~` operator. - _Only_ quote arguments to the right of `=~` if the expression is a literal match without any metacharacters. The following are intended to prevent too-compact code: - Declare only one item per `declare`, `local`, `export`, or `readonly` call. - _Note:_ This also helps avoid subtle bugs, as trying to initialize one variable using the value of another declared in the same statement will not do what you may expect. The initialization of the first variable will not yet be complete when the second variable is declared, so the first variable will have an empty value. - Do not use one-line `if`, `for`, `while`, `until`, `case`, or `select` statements. - Do not use `&&` or `||` to avoid writing `if` statements. - Do not write functions entirely on one line. - For `case` statements: put each pattern on a line by itself; put each command on a line by itself; put the `;;` terminator on a line by itself. ### Naming - Use `snake_case` for all identifiers. ### Function declarations - Declare functions without the `function` keyword. - Strive to always use `return`, never `exit`, unless an error condition is severe enough to warrant it. - Calling `exit` makes it difficult for the caller to recover from an error, or to compose new commands from existing ones. ### Variable and parameter declarations - _Gotcha:_ Never initialize an array on the same line as an `export` or `declare -g` statement. See [the Gotchas section](#gotchas) below for more details. - Declare all variables inside functions using `local`. - Declare temporary file-level variables using `declare`. Use `unset` to remove them when finished. - Don't use `local -r`, as a readonly local variable in one scope can cause a conflict when it calls a function that declares a `local` variable of the same name. - Don't use type flags with `declare` or `local`. Assignments to integer variables in particular may behave differently, and it has no effect on array variables. - For most functions, the first lines should use `local` declarations to assign the original positional parameters to more meaningful names, e.g.: ```bash format_summary() { local cmd_name="$1" local summary="$2" local longest_name_len="$3" ``` For very short functions, this _may not_ be necessary, e.g.: ```bash has_spaces() { [[ "$1" != "${1//[[:space:]]/}" ]] } ``` ### Command substitution - If possible, don't. While this capability is one of Bash's core strengths, every new process created by Bats makes the framework slower, and speed is critical to encouraging the practice of automated testing. (This is especially true on Windows, [where process creation is one or two orders of magnitude slower][win-slow]. See [bats-core/bats-core#8][pr-8] for an illustration of the difference avoiding subshells makes.) Bash is quite powerful; see if you can do what you need in pure Bash first. - If you need to capture the output from a function, store the output using `printf -v` instead if possible. `-v` specfies the name of the variable into which to write the result; the caller can supply this name as a parameter. - If you must use command substituion, use `$()` instead of backticks, as it's more robust, more searchable, and can be nested. [win-slow]: https://rufflewind.com/2014-08-23/windows-bash-slow [pr-8]: https://github.com/bats-core/bats-core/pull/8 ### Process substitution - If possible, don't use it. See the advice on avoiding subprocesses and using `printf -v` in the **Command substitution** section above. - Use wherever necessary and possible, such as when piping input into a `while` loop (which avoids having the loop body execute in a subshell) or running a command taking multiple filename arguments based on output from a function or pipeline (e.g. `diff`). - *Warning*: It is impossible to directly determine the exit status of a process substitution; emitting an exit status as the last line of output is a possible workaround. ### Conditionals and loops - Always use `[[` and `]]` for evaluating variables. Per the guideline under **Formatting**, quote variables and strings within the brackets, but not regular expressions (or variables containing regular expressions) appearing on the right side of the `=~` operator. ### Generating output - Use `printf` instead of `echo`. Both are Bash builtins, and there's no perceptible performance difference when running Bats under the `time` builtin. However, `printf` provides a more consistent experience in general, as `echo` has limitations to the arguments it accepts, and even the same version of Bash may produce different results for `echo` based on how the binary was compiled. See [Stack Overflow: Why is printf better than echo?][printf-vs-echo] for excruciating details. [printf-vs-echo]: https://unix.stackexchange.com/a/65819 ### Signal names Always use upper case signal names (e.g. `trap - INT EXIT`) to avoid locale dependent errors. In some locales (for example Turkish, see [Turkish dotless i](https://en.wikipedia.org/wiki/Dotted_and_dotless_I)) lower case signal names cause Bash to error. An example of the problem: ```bash $ echo "tr_TR.UTF-8 UTF-8" >> /etc/locale.gen && locale-gen tr_TR.UTF-8 # Ubuntu derivatives $ LC_CTYPE=tr_TR.UTF-8 LC_MESSAGES=C bash -c 'trap - int && echo success' bash: line 0: trap: int: invalid signal specification $ LC_CTYPE=tr_TR.UTF-8 LC_MESSAGES=C bash -c 'trap - INT && echo success' success ``` ### Gotchas - If you wish to use command substitution to initialize a `local` variable, and then check the exit status of the command substitution, you _must_ declare the variable on one line and perform the substitution on another. If you don't, the exit status will always indicate success, as it is the status of the `local` declaration, not the command substitution. - To work around a bug in some versions of Bash whereby arrays declared with `declare -g` or `export` and initialized in the same statement eventually go out of scope, always `export` the array name on one line and initialize it the next line. See: - https://lists.gnu.org/archive/html/bug-bash/2012-06/msg00068.html - ftp://ftp.gnu.org/gnu/bash/bash-4.2-patches/bash42-025 - http://lists.gnu.org/archive/html/help-bash/2012-03/msg00078.html - [ShellCheck](https://www.shellcheck.net/) can help to identify many of these issues ## Open Source License This software is made available under the [MIT License][osmit]. For the text of the license, see the [LICENSE][] file. ## Credits - This guide was heavily written by BATS-core member [@mbland](https://github.com/mbland) for [go-script-bash](https://github.com/mbland/go-script-bash), tweaked for [BATS-core][repohome] - Table of Contents created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc) - The [official bash logo](https://github.com/odb/official-bash-logo) is copyrighted by the [Free Software Foundation](https://www.fsf.org/), 2016 under the [Free Art License](http://artlibre.org/licence/lal/en/) [repoprojects]: https://github.com/bats-core/bats-core/projects [repomilestones]: https://github.com/bats-core/bats-core/milestones [repoprs]: https://github.com/bats-core/bats-core/pulls [repoissues]: https://github.com/bats-core/bats-core/issues [repohome]: https://github.com/bats-core/bats-core [osmit]: https://opensource.org/licenses/MIT [gitterurl]: https://gitter.im/bats-core/bats-core git-secret-0.5.0/vendor/bats-core/docs/Makefile000066400000000000000000000011761424706700600213410ustar00rootroot00000000000000# Minimal makefile for Sphinx documentation # # You can set these variables from the command line, and also # from the environment for the first two. SPHINXOPTS ?= SPHINXBUILD ?= sphinx-build SOURCEDIR = source BUILDDIR = build # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) git-secret-0.5.0/vendor/bats-core/docs/PULL_REQUEST_TEMPLATE.md000066400000000000000000000004751424706700600235030ustar00rootroot00000000000000- [ ] I have reviewed the [Contributor Guidelines][contributor]. - [ ] I have reviewed the [Code of Conduct][coc] and agree to abide by it [contributor]: https://github.com/bats-core/bats-core/blob/master/docs/CONTRIBUTING.md [coc]: https://github.com/bats-core/bats-core/blob/master/docs/CODE_OF_CONDUCT.md git-secret-0.5.0/vendor/bats-core/docs/examples/000077500000000000000000000000001424706700600215125ustar00rootroot00000000000000git-secret-0.5.0/vendor/bats-core/docs/examples/README.md000066400000000000000000000002571424706700600227750ustar00rootroot00000000000000# Examples This directory contains example .bats files. See the [bats-core wiki][examples] for more details. [examples]: https://github.com/bats-core/bats-core/wiki/Examplesgit-secret-0.5.0/vendor/bats-core/docs/examples/package-tarball000066400000000000000000000011341424706700600244460ustar00rootroot00000000000000#!/usr/bin/env bash # "unofficial" bash strict mode # See: http://redsymbol.net/articles/unofficial-bash-strict-mode set -o errexit # Exit when simple command fails 'set -e' set -o errtrace # Exit on error inside any functions or subshells. set -o nounset # Trigger error when expanding unset variables 'set -u' set -o pipefail # Do not hide errors within pipes 'set -o pipefail' set -o xtrace # Display expanded command and arguments 'set -x' IFS=$'\n\t' # Split words on \n\t rather than spaces main() { tar -czf "$dst_tarball" -C "$src_dir" . } main "$@" git-secret-0.5.0/vendor/bats-core/docs/examples/package-tarball.bats000077500000000000000000000017401424706700600254040ustar00rootroot00000000000000#!/usr/bin/env bats setup() { export dst_tarball="${BATS_TMPDIR}/dst.tar.gz" export src_dir="${BATS_TMPDIR}/src_dir" rm -rf "${dst_tarball}" "${src_dir}" mkdir "${src_dir}" touch "${src_dir}"/{a,b,c} } main() { bash "${BATS_TEST_DIRNAME}"/package-tarball } @test "fail when \$src_dir and \$dst_tarball are unbound" { unset src_dir dst_tarball run main [ "${status}" -ne 0 ] } @test "fail when \$src_dir is a non-existent directory" { # shellcheck disable=SC2030 src_dir='not-a-dir' run main [ "${status}" -ne 0 ] } # shellcheck disable=SC2016 @test "pass when \$src_dir directory is empty" { # shellcheck disable=SC2031,SC2030 rm -rf "${src_dir:?}/*" run main echo "$output" [ "${status}" -eq 0 ] } # shellcheck disable=SC2016 @test "files in \$src_dir are added to tar archive" { run main [ "${status}" -eq 0 ] run tar tf "$dst_tarball" [ "${status}" -eq 0 ] [[ "${output}" =~ a ]] [[ "${output}" =~ b ]] [[ "${output}" =~ c ]] } git-secret-0.5.0/vendor/bats-core/docs/make.bat000066400000000000000000000013741424706700600213060ustar00rootroot00000000000000@ECHO OFF pushd %~dp0 REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set SOURCEDIR=source set BUILDDIR=build if "%1" == "" goto help %SPHINXBUILD% >NUL 2>NUL if errorlevel 9009 ( echo. echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.installed, then set the SPHINXBUILD environment variable to point echo.to the full path of the 'sphinx-build' executable. Alternatively you echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.http://sphinx-doc.org/ exit /b 1 ) %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% goto end :help %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% :end popd git-secret-0.5.0/vendor/bats-core/docs/releasing.md000066400000000000000000000075731424706700600222030ustar00rootroot00000000000000# Releasing a new Bats version These notes reflect the current process. There's a lot more we could do, in terms of automation and expanding the number of platforms to which we formally release (see #103). ## Update docs/CHANGELOG.md Create a new entry at the top of `docs/CHANGELOG.md` that enumerates the significant updates to the new version. ## Bumping the version number Bump the version numbers in the following files: - contrib/rpm/bats.spec - libexec/bats-core/bats - package.json Commit these changes (including the `docs/CHANGELOG.md` changes) in a commit with the message `Bats `, where `` is the new version number. Create a new signed, annotated tag with: ```bash $ git tag -a -s ``` Include the `docs/CHANGELOG.md` notes corresponding to the new version as the tag annotation, except the first line should be: `Bats - YYYY-MM-DD` and any Markdown headings should become plain text, e.g.: ```md ### Added ``` should become: ```md Added: ``` ## Create a GitHub release Push the new version commit and tag to GitHub via the following: ```bash $ git push --follow-tags ``` Then visit https://github.com/bats-core/bats-core/releases, and: * Click **Draft a new release**. * Select the new version tag. * Name the release: `Bats `. * Paste the same notes from the version tag annotation as the description, except change the first line to read: `Released: YYYY-MM-DD`. * Click **Publish release**. For more on `git push --follow-tags`, see: * [git push --follow-tags in the online manual][ft-man] * [Stack Overflow: How to push a tag to a remote repository using Git?][ft-so] [ft-man]: https://git-scm.com/docs/git-push#git-push---follow-tags [ft-so]: https://stackoverflow.com/a/26438076 ## NPM `npm publish`. Pretty easy! For the paranoid, use `npm pack` and install the resulting tarball locally with `npm install` before publishing. ## Homebrew The basic instructions are in the [Submit a new version of an existing formula][brew] section of the Homebrew docs. [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 An example using v1.1.0 (notice that this uses the sha256 sum of the tarball): ```bash $ curl -LOv https://github.com/bats-core/bats-core/archive/v1.1.0.tar.gz $ openssl sha256 v1.1.0.tar.gz SHA256(v1.1.0.tar.gz)=855d8b8bed466bc505e61123d12885500ef6fcdb317ace1b668087364717ea82 # Add the --dry-run flag to see the individual steps without executing. $ brew bump-formula-pr \ --url=https://github.com/bats-core/bats-core/archive/v1.1.0.tar.gz \ --sha256=855d8b8bed466bc505e61123d12885500ef6fcdb317ace1b668087364717ea82 ``` This resulted in https://github.com/Homebrew/homebrew-core/pull/29864, which was automatically merged once the build passed. ## Alpine Linux An example using v1.1.0 (notice that this uses the sha512 sum of the Zip file): ```bash $ curl -LOv https://github.com/bats-core/bats-core/archive/v1.1.0.zip $ openssl sha512 v1.1.0.zip SHA512(v1.1.0.zip)=accd83cfec0025a2be40982b3f9a314c2bbf72f5c85daffa9e9419611904a8d34e376919a5d53e378382e0f3794d2bd781046d810225e2a77812474e427bed9e ``` After cloning alpinelinux/aports, I used the above information to create: https://github.com/alpinelinux/aports/pull/4696 **Note:** Currently users must enable the `edge` branch of the `community` repo by adding/uncommenting the corresponding entry in `/etc/apk/repositories`. ## Announce It's worth making a brief announcement like [the v1.1.0 announcement via Gitter][gitter]: [gitter]: https://gitter.im/bats-core/bats-core?at=5b42c9a57b811a6d63daacb5 ``` v1.1.0 is now available via Homebrew and npm: https://github.com/bats-core/bats-core/releases/tag/v1.1.0 It'll eventually be available in Alpine via the edge branch of the community repo once alpinelinux/aports#4696 gets merged. (Check /etc/apk/repositories to ensure this repo is enabled.) ``` git-secret-0.5.0/vendor/bats-core/docs/source/000077500000000000000000000000001424706700600211745ustar00rootroot00000000000000git-secret-0.5.0/vendor/bats-core/docs/source/_static/000077500000000000000000000000001424706700600226225ustar00rootroot00000000000000git-secret-0.5.0/vendor/bats-core/docs/source/_static/.gitkeep000066400000000000000000000000001424706700600242410ustar00rootroot00000000000000git-secret-0.5.0/vendor/bats-core/docs/source/_templates/000077500000000000000000000000001424706700600233315ustar00rootroot00000000000000git-secret-0.5.0/vendor/bats-core/docs/source/_templates/.gitkeep000066400000000000000000000000001424706700600247500ustar00rootroot00000000000000git-secret-0.5.0/vendor/bats-core/docs/source/conf.py000066400000000000000000000045621424706700600225020ustar00rootroot00000000000000# Configuration file for the Sphinx documentation builder. # # This file only contains a selection of the most common options. For a full # list see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html # -- Path setup -------------------------------------------------------------- # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # # import os # import sys # sys.path.insert(0, os.path.abspath('.')) # -- Project information ----------------------------------------------------- project = 'bats-core' copyright = '2021, bats-core organization' author = 'bats-core organization' # The full version, including alpha/beta/rc tags release = '1' # -- General configuration --------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'recommonmark', 'sphinxcontrib.programoutput' ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] html_sidebars = { '**': [ 'about.html', 'navigation.html', 'relations.html', 'searchbox.html', 'donate.html'] } # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. exclude_patterns = [] # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # #html_theme = 'alabaster' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] #man_pages = [ ('man.1', 'bats', 'bats documentation', ['bats-core Contributors'], 1)] def setup(app): app.add_config_value('recommonmark_config', {'enable_eval_rst': True}, True) import recommonmark from recommonmark.transform import AutoStructify app.add_transform(AutoStructify) git-secret-0.5.0/vendor/bats-core/docs/source/docker-usage.md000066400000000000000000000044731424706700600240770ustar00rootroot00000000000000# Docker Usage Guide - [Docker Usage Guide](#docker-usage-guide) * [Basic Usage](#basic-usage) * [Docker Gotchas](#docker-gotchas) * [Extending from the base image](#extending-from-the-base-image) ## Basic Usage To build and run `bats`' own tests: ```bash $ git clone https://github.com/bats-core/bats-core.git Cloning into 'bats-core'... remote: Counting objects: 1222, done. remote: Compressing objects: 100% (53/53), done. remote: Total 1222 (delta 34), reused 55 (delta 21), pack-reused 1146 Receiving objects: 100% (1222/1222), 327.28 KiB | 1.70 MiB/s, done. Resolving deltas: 100% (661/661), done. $ cd bats-core/ $ docker build --tag bats/bats:latest . ... $ docker run -it bats/bats:latest --formatter tap /opt/bats/test ``` To mount your tests into the container, first build the image as above. Then, for example with `bats`: ```bash $ docker run -it -v "$PWD:/opt/bats" bats/bats:latest /opt/bats/test ``` This runs the `test/` directory from the bats-core repository inside the bats Docker container. For 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: ```bash $ docker run -it -v "$PWD:/code" bats/bats:latest /code/test ``` ## Docker Gotchas Relying on functionality provided by your environment (ssh keys or agent, installed binaries, fixtures outside the mounted test directory) will fail when running inside Docker. `--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. ## Extending from the base image Docker 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. ```dockerfile FROM bats/bats RUN \ apk \ --no-cache \ --update \ add \ openssh ``` git-secret-0.5.0/vendor/bats-core/docs/source/faq.rst000066400000000000000000000135571424706700600225100ustar00rootroot00000000000000FAQ === How do I set the working directory? ----------------------------------- The working directory is simply the directory where you started when executing bats. If you want to enforce a specific directory, you can use `cd` in the `setup_file`/`setup` functions. However, be aware that code outside any function will run before any of these setup functions and might interfere with bats' internals. How do I see the output of the command under `run` when a test fails? --------------------------------------------------------------------- `run` captures stdout and stderr of its command and stores it in the `$output` and `${lines[@]}` variables. If you want to see this output, you need to print it yourself, or use functions like `assert_output` that will reproduce it on failure. Can I use `--filter` to exclude files/tests? -------------------------------------------- No, not directly. `--filter` uses a regex to match against test names. So you could try to invert the regex. The filename won't be part of the strings that are tested, so you cannot filter against files. How can I exclude a single test from a test run? ------------------------------------------------ If you want to exclude only few tests from a run, you can either `skip` them: .. code-block:: bash @test "Testname" { # yadayada } becomes .. code-block:: bash @test "Testname" { skip 'Optional skip message' # yadayada } or comment them out, e.g.: .. code-block:: bash @test "Testname" { becomes .. code-block:: bash disabled() { # @test "Testname" { For multiple tests or all tests of a file, this becomes tedious, so read on. How can I exclude all tests of a file from a test run? -------------------------------------------------------- If you run your test suite by naming individual files like: .. code-block:: bash $ bats test/a.bats test/b.bats ... you can simply omit your file. When running a folder like .. code-block:: bash $ bats test/ you can prevent test files from being picked up by changing their extension to something other than `.bats`. It is also possible to `skip` in `setup_file`/`setup` which will skip all tests in the file. How can I include my own `.sh` files for testing? ------------------------------------------------- You can simply `source .sh` files. However, be aware that `source`ing files with errors outside of any function (or inside `setup_file`) will trip up bats and lead to hard to diagnose errors. Therefore, it is safest to only `source` inside `setup` or the test functions themselves. How can I debug a failing test? ------------------------------- Short of using a bash debugger you should make sure to use appropriate asserts for your task instead of raw bash comparisons, e.g.: .. code-block:: bash @test test { run echo test failed assert_output "test" # instead of [ "$output" = "test" ] } Because the former will print the output when the test fails while the latter won't. Similarly, you should use `assert_success`/`assert_failure` instead of `[ "$status" -eq 0 ]` for return code checks. Is there a mechanism to add file/test specific functionality to a common setup function? ---------------------------------------------------------------------------------------- Often the setup consists of parts that are common between different files of a test suite and parts that are specific to each file. There 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() {}`), which can be `source`d or `load`ed and call it in `setup_file` or `setup`. How can I use helper libraries like bats-assert? ------------------------------------------------ This is a short reproduction of https://github.com/ztombol/bats-docs. At 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: .. code-block:: test/ test.bats test_helper/ bats-support/ bats-assert/ Next, you should load those helper libraries: .. code-block:: bash setup() { load 'test_helper/bats-support/load' # this is required by bats-assert! load 'test_helper/bats-assert/load' } Now, you should be able to use the functions from these helpers inside your tests, e.g.: .. code-block:: bash @test "test" { run echo test assert_output "test" } Note that you obviously need to load the library before using it. If you need the library inside `setup_file` or `teardown_file` you need to load it in `setup_file`. How to set a test timeout in bats? ---------------------------------- Unfortunately, this is not possible yet. Please contribute to issue `#396 `_ for further progress. How can I lint/shell-format my bats tests? ------------------------------------------ Due to their custom syntax (`@test`), `.bats` files are not standard bash. This prevents most tools from working with bats. However, there is an alternative syntax `function_name { # @test` to declare tests in a bash compliant manner. - shellcheck support since version 0.7 - shfmt support since version 3.2.0 (using `-ln bats`) How can I check if a test failed/succeeded during teardown? ----------------------------------------------------------- You can check `BATS_TEST_COMPLETED` which will be set to 1 if the test was successful or empty if it was not. There is also `BATS_TEST_SKIPPED` which will be non-empty (contains the skip message or -1) when `skip` was called. How can I setup/cleanup before/after all tests? ----------------------------------------------- Currently, this is not supported. Please contribute your usecase to issue `#39 `_. git-secret-0.5.0/vendor/bats-core/docs/source/gotchas.rst000066400000000000000000000133411424706700600233600ustar00rootroot00000000000000Gotchas ======= My test fails although I return true? ------------------------------------- Using `return 1` to signify `true` for a success as is done often in other languages does not mesh well with Bash's convention of using return code 0 to signify success and everything non-zero to indicate a failure. Please adhere to this idiom while using bats, or you will constantly work against your environment. My negated statement (e.g. ! true) does not fail the test, even when it should. ------------------------------------------------------------------------------- Bash 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 ]`. If 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. Negated statements of the form `! x || false` will explicitly fail the test when the pipeline returns true, regardless of where they occur in the test. I cannot register a test multiple times via for loop. ----------------------------------------------------- The usual bats tests (`@test`) are preprocessed into functions. Wrapping them into a for loop only redeclares this function. If you are interested in registering multiple calls to the same function, contribute your wishes to issue `#306 `_. I cannot pass parameters to test or .bats files. ------------------------------------------------ Especially while using bats via shebang: .. code-block:: bash #!/usr/bin/env bats @test "test" { # ... } You could be tempted to pass parameters to the test invocation like `./test.bats param1 param2`. However, bats does not support passing parameters to files or tests. If you need such a feature, please let us know about your usecase. As a workaround you can use environment variables to pass parameters. Why can't my function return results via a variable when using `run`? --------------------------------------------------------------------- The `run` function executes its command in a subshell which means the changes to variables won't be available in the calling shell. If you want to test these functions, you should call them without `run`. `run` doesn't fail, although the same command without `run` does. ----------------------------------------------------------------- `run` is a wrapper that always succeeds. The wrapped command's exit code is stored in `$status` and the stdout/stderr in `$output`. If you want to fail the test, you should explicitly check `$status` or omit `run`. See also `when not to use run `_. `load` won't load my `.sh` files. --------------------------------- `load` is intended as an internal helper function that always loads `.bash` files (by appending this suffix). If you want to load an `.sh` file, you can simple `source` it. I can't lint/shell-format my bats tests. ---------------------------------------- Bats uses a custom syntax for annotating tests (`@test`) that is not bash compliant. Therefore, standard bash tooling won't be able to interact directly with `.bats` files. Shellcheck supports bats' native syntax as of version 0.7. Additionally, there is bash compatible syntax for tests: .. code-block:: bash function bash_compliant_function_name_as_test_name { # @test # your code } The output (stdout/err) from commands under `run` is not visible in failed tests. --------------------------------------------------------------------------------- By default, `run` only stores stdout/stderr in `$output` (and `${lines[@]}`). If you want to see this output, you either should use bat-assert's assertions or have to print `$output` before the check that fails. My piped command does not work under run. ----------------------------------------- Be 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 .. code-block:: bash run echo foo | grep bar Won't `run (echo foo | grep bar)` but will `(run echo foo) | grep bar`. If you need to incorporate pipes, you either should do .. code-block:: bash run bash -c 'echo foo | grep bar' or use a function to wrap the pipe in: .. code-block:: bash fun_with_pipes() { echo foo | grep bar } run fun_with_pipes `[[ ]]` (or `(( ))` did not fail my test ---------------------------------------- The `set -e` handling of `[[ ]]` and `(( ))` changed in Bash 4.1. Older versions, like 3.2 on MacOS, don't abort the test when they fail, unless they are the last command before the (test) function returns, making their exit code the return code. `[ ]` does not suffer from this, but is no replacement for all `[[ ]]` usecases. Appending ` || false` will work in all cases. Background tasks prevent the test run from terminating when finished -------------------------------------------------------------------- When running a task in background, it will inherit the opened FDs of the process it was forked from. This 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, thus keeping it open until the background task finished. Due 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. You 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. More details about the issue can be found in [#205](https://github.com/bats-core/bats-core/issues/205#issuecomment-973572596). git-secret-0.5.0/vendor/bats-core/docs/source/index.rst000066400000000000000000000005271424706700600230410ustar00rootroot00000000000000Welcome to bats-core's documentation! ===================================== Versions before v1.2.1 are documented over `there `_. .. toctree:: :maxdepth: 2 :caption: Contents: tutorial installation usage docker-usage writing-tests gotchas faq git-secret-0.5.0/vendor/bats-core/docs/source/installation.rst000066400000000000000000000073621424706700600244370ustar00rootroot00000000000000 Installation ============ Supported Bash versions ^^^^^^^^^^^^^^^^^^^^^^^ The following is a list of Bash versions that are currently supported by Bats. This list is composed of platforms that Bats has been tested on and is known to work on without issues. * Bash versions: * Everything from ``3.2.57(1)`` and higher (macOS's highest version) * Operating systems: * Arch Linux * Alpine Linux * Ubuntu Linux * FreeBSD ``10.x`` and ``11.x`` * macOS * Windows 10 * Latest version for the following Windows platforms: * Git for Windows Bash (MSYS2 based) * Windows Subsystem for Linux * MSYS2 * Cygwin Homebrew ^^^^^^^^ On macOS, you can install `Homebrew `_ if you haven't already, then run: .. code-block:: bash $ brew install bats-core npm ^^^ You can install the `Bats npm package `_ via: .. code-block:: # To install globally: $ npm install -g bats # To install into your project and save it as one of the "devDependencies" in # your package.json: $ npm install --save-dev bats Installing Bats from source ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Check out a copy of the Bats repository. Then, either add the Bats ``bin`` directory to your ``$PATH``\ , or run the provided ``install.sh`` command with the location to the prefix in which you want to install Bats. For example, to install Bats into ``/usr/local``\ , .. code-block:: $ git clone https://github.com/bats-core/bats-core.git $ cd bats-core $ ./install.sh /usr/local **Note:** You may need to run ``install.sh`` with ``sudo`` if you do not have permission to write to the installation prefix. Installing Bats from source onto Windows Git Bash ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Check out a copy of the Bats repository and install it to ``$HOME``. This will place the ``bats`` executable in ``$HOME/bin``\ , which should already be in ``$PATH``. .. code-block:: $ git clone https://github.com/bats-core/bats-core.git $ cd bats-core $ ./install.sh $HOME Running Bats in Docker ^^^^^^^^^^^^^^^^^^^^^^ There is an official image on the Docker Hub: .. code-block:: $ docker run -it bats/bats:latest --version Building a Docker image ~~~~~~~~~~~~~~~~~~~~~~~ Check out a copy of the Bats repository, then build a container image: .. code-block:: $ git clone https://github.com/bats-core/bats-core.git $ cd bats-core $ docker build --tag bats/bats:latest . This creates a local Docker image called ``bats/bats:latest`` based on `Alpine Linux `_ (to push to private registries, tag it with another organisation, e.g. ``my-org/bats:latest``\ ). To run Bats' internal test suite (which is in the container image at ``/opt/bats/test``\ ): .. code-block:: $ docker run -it bats/bats:latest /opt/bats/test To run a test suite from a directory called ``test`` in the current directory of your local machine, mount in a volume and direct Bats to its path inside the container: .. code-block:: $ docker run -it -v "${PWD}:/code" bats/bats:latest test .. ``/code`` is the working directory of the Docker image. "${PWD}/test" is the location of the test directory on the local machine. This is a minimal Docker image. If more tools are required this can be used as a base image in a Dockerfile using ``FROM ``. In the future there may be images based on Debian, and/or with more tools installed (\ ``curl`` and ``openssl``\ , for example). If you require a specific configuration please search and +1 an issue or `raise a new issue `_. Further usage examples are in `the wiki `_. git-secret-0.5.0/vendor/bats-core/docs/source/requirements.txt000066400000000000000000000000501424706700600244530ustar00rootroot00000000000000sphinxcontrib-programoutput recommonmarkgit-secret-0.5.0/vendor/bats-core/docs/source/tutorial.rst000066400000000000000000000520301424706700600235710ustar00rootroot00000000000000Tutorial ======== This tutorial is intended for beginners with bats and possibly bash. Make sure to also read the list of gotchas and the faq. For this tutorial we are assuming you already have a project in a git repository and want to add tests. Ultimately they should run in the CI environment but will also be started locally during development. .. TODO: link to example repository? Quick installation ------------------ Since we already have an existing git repository, it is very easy to include bats and its libraries as submodules. We are aiming for following filesystem structure: .. code-block:: src/ project.sh ... test/ bats/ <- submodule test_helper/ bats-support/ <- submodule bats-assert/ <- submodule test.bats ... So we start from the project root: .. code-block:: console git submodule add https://github.com/bats-core/bats-core.git test/bats git submodule add https://github.com/bats-core/bats-support.git test/test_helper/bats-support git submodule add https://github.com/bats-core/bats-assert.git test/test_helper/bats-assert Your first test --------------- Now we want to add our first test. In the tutorial repository, we want to build up our project in a TDD fashion. Thus, we start with an empty project and our first test is to just run our (non existing) shell script. We start by creating a new test file `test/test.bats` .. code-block:: bash @test "can run our script" { ./project.sh } and run it by .. code-block:: console $ ./test/bats/bin/bats test/test.bats ✗ can run our script (in test file test/test.bats, line 2) `./project.sh' failed with status 127 /tmp/bats-run-19605/bats.19627.src: line 2: ./project.sh: No such file or directory 1 test, 1 failure Okay, our test is red. Obviously, the project.sh doesn't exist, so we create the file `src/project.sh`: .. code-block:: console mkdir src/ echo '#!/usr/bin/env bash' > src/project.sh chmod a+x src/project.sh A new test run gives us .. code-block:: console $ ./test/bats/bin/bats test/test.bats ✗ can run our script (in test file test/test.bats, line 2) `./project.sh' failed with status 127 /tmp/bats-run-19605/bats.19627.src: line 2: ./project.sh: No such file or directory 1 test, 1 failure Oh, we still used the wrong path. No problem, we just need to use the correct path to `project.sh`. Since we're still in the same directory as when we started `bats`, we can simply do: .. code-block:: bash @test "can run our script" { ./src/project.sh } and get: .. code-block:: console $ ./test/bats/bin/bats test/test.bats ✓ can run our script 1 test, 0 failures Yesss! But that victory feels shallow: What if somebody less competent than us starts bats from another directory? Let's do some setup ------------------- The obvious solution to becoming independent of `$PWD` is using some fixed anchor point in the filesystem. We can use the path to the test file itself as an anchor and rely on the internal project structure. Since 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`. Our new `test/test.bats` now looks like this: .. code-block:: bash setup() { # get the containing directory of this file # use $BATS_TEST_FILENAME instead of ${BASH_SOURCE[0]} or $0, # as those will point to the bats executable's location or the preprocessed file respectively DIR="$( cd "$( dirname "$BATS_TEST_FILENAME" )" >/dev/null 2>&1 && pwd )" # make executables in src/ visible to PATH PATH="$DIR/../src:$PATH" } @test "can run our script" { # notice the missing ./ # As we added src/ to $PATH, we can omit the relative path to `src/project.sh`. project.sh } still giving us: .. code-block:: console $ ./test/bats/bin/bats test/test.bats ✓ can run our script 1 test, 0 failures It still works as expected. This is because the newly added `setup` function put the absolute path to `src/` onto `$PATH`. This setup function is automatically called before each test. Therefore, our test could execute `project.sh` directly, without using a (relative) path. .. important:: The `setup` function will be called before each individual test in the file. Each file can only define one setup function for all tests in the file. However, the setup functions can differ between different files. Dealing with output ------------------- Okay, we have a green test but our executable does not do anything useful. To keep things simple, let us start with an error message. Our new `src/project.sh` now reads: .. code-block:: bash #!/usr/bin/env bash echo "Welcome to our project!" echo "NOT IMPLEMENTED!" >&2 exit 1 And gives is this test output: .. code-block:: console $ ./test/bats/bin/bats test/test.bats ✗ can run our script (in test file test/test.bats, line 11) `project.sh' failed Welcome to our project! NOT IMPLEMENTED! 1 test, 1 failure Okay, our test failed, because we now exit with 1 instead of 0. Additionally, we see the stdout and stderr of the failing program. Our goal now is to retarget our test and check that we get the welcome message. bats-assert gives us some help with this, so we should now load it (and its dependency bats-support), so we change `test/test.bats` to .. code-block:: bash setup() { load 'test_helper/bats-support/load' load 'test_helper/bats-assert/load' # ... the remaining setup is unchanged # get the containing directory of this file # use $BATS_TEST_FILENAME instead of ${BASH_SOURCE[0]} or $0, # as those will point to the bats executable's location or the preprocessed file respectively DIR="$( cd "$( dirname "$BATS_TEST_FILENAME" )" >/dev/null 2>&1 && pwd )" # make executables in src/ visible to PATH PATH="$DIR/../src:$PATH" } @test "can run our script" { run project.sh # notice `run`! assert_output 'Welcome to our project!' } which gives us the following test output: .. code-block:: console $ LANG=C ./test/bats/bin/bats test/test.bats ✗ can run our script (from function `assert_output' in file test/test_helper/bats-assert/src/assert_output.bash, line 194, in test file test/test.bats, line 14) `assert_output 'Welcome to our project!'' failed -- output differs -- expected (1 lines): Welcome to our project! actual (2 lines): Welcome to our project! NOT IMPLEMENTED! -- 1 test, 1 failure The first change in this output is the failure description. We now fail on assert_output instead of the call itself. We prefixed our call to `project.sh` with `run`, which is a function provided by bats that executes the command it gets passed as parameters. Then, `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. This means `run` never fails the test and won't generate any context/output in the log of a failed test on its own. Marking the test as failed and printing context information is up to the consumers of `$status` and `$output`. `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. For our current test we don't care about any other output or the error message, so we want it gone. `grep` is always at our fingertips, so we tape together this ramshackle construct .. code-block:: bash run project.sh 2>&1 | grep Welcome which gives us the following test result: .. code-block:: console $ ./test/bats/bin/bats test/test.bats ✗ can run our script (in test file test/test.bats, line 13) `run project.sh | grep Welcome' failed 1 test, 1 failure Huh, what is going on? Why does it fail the `run` line again? This is a common mistake that can happen when our mind parses the file differently than the bash parser. `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`, instead of our intended `run (project.sh | grep Welcome)`. Unfortunately, the latter is no valid bash syntax, so we have to work around it, e.g. by using a function: .. code-block:: bash get_projectsh_welcome_message() { project.sh 2>&1 | grep Welcome } @test "Check welcome message" { run get_projectsh_welcome_message assert_output 'Welcome to our project!' } Now our test passes again but having to write a function each time we want only a partial match does not accommodate our laziness. Isn't there an app for that? Maybe we should look at the documentation? 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. -- the documentation for `assert_output `_ Okay, so maybe we should try that: .. code-block:: bash @test "Check welcome message" { run project.sh assert_output --partial 'Welcome to our project!' } Aaannnd ... the test stays green. Yay! There are many other asserts and options but this is not the place for all of them. Skimming the documentation of `bats-assert `_ will give you a good idea what you can do. You should also have a look at the other helper libraries `here `_ like `bats-file `_, to avoid reinventing the wheel. Cleaning up your mess --------------------- Often our setup or tests leave behind some artifacts that clutter our test environment. You can define a `teardown` function which will be called after each test, regardless whether it failed or not. For example, we now want our project.sh to only show the welcome message on the first invocation. So we change our test to this: .. code-block:: bash @test "Show welcome message on first invocation" { run project.sh assert_output --partial 'Welcome to our project!' run project.sh refute_output --partial 'Welcome to our project!' } This test fails as expected: .. code-block:: console $ ./test/bats/bin/bats test/test.bats ✗ Show welcome message on first invocation (from function `refute_output' in file test/test_helper/bats-assert/src/refute_output.bash, line 189, in test file test/test.bats, line 17) `refute_output --partial 'Welcome to our project!'' failed -- output should not contain substring -- substring (1 lines): Welcome to our project! output (2 lines): Welcome to our project! NOT IMPLEMENTED! -- 1 test, 1 failure Now, to get the test green again, we want to store the information that we already ran in the file `/tmp/bats-tutorial-project-ran`, so our `src/project.sh` becomes: .. code-block:: bash #!/usr/bin/env bash FIRST_RUN_FILE=/tmp/bats-tutorial-project-ran if [[ ! -e "$FIRST_RUN_FILE" ]]; then echo "Welcome to our project!" touch "$FIRST_RUN_FILE" fi echo "NOT IMPLEMENTED!" >&2 exit 1 And our test says: .. code-block:: console $ ./test/bats/bin/bats test/test.bats ✓ Show welcome message on first invocation 1 test, 0 failures Nice, we're done, or are we? Running the test again now gives: .. code-block:: console $ ./test/bats/bin/bats test/test.bats ✗ Show welcome message on first invocation (from function `assert_output' in file test/test_helper/bats-assert/src/assert_output.bash, line 186, in test file test/test.bats, line 14) `assert_output --partial 'Welcome to our project!'' failed -- output does not contain substring -- substring : Welcome to our project! output : NOT IMPLEMENTED! -- 1 test, 1 failure Now the first assert failed, because of the leftover `$FIRST_RUN_FILE` from the last test run. Luckily, bats offers the `teardown` function, which can take care of that, we add the following code to `test/test.bats`: .. code-block:: bash teardown() { rm -f /tmp/bats-tutorial-project-ran } Now running the test again first give us the same error, as the teardown has not run yet. On the second try we get a clean `/tmp` folder again and our test passes consistently now. It is worth noting that we could do this `rm` in the test code itself but it would get skipped on failures. .. important:: A test ends at its first failure. None of the subsequent commands in this test will be executed. The `teardown` function runs after each individual test in a file, regardless of test success or failure. Similarly to `setup`, each `.bats` file can have its own `teardown` function which will be the same for all tests in the file. Test what you can ----------------- Sometimes tests rely on the environment to provide infrastructure that is needed for the test. If not all test environments provide this infrastructure but we still want to test on them, it would be unhelpful to get errors on parts that are not testable. Bats provides you with the `skip` command which can be used in `setup` and `test`. .. tip:: You should `skip` as early as you know it does not make sense to continue. In our example project we rewrite the welcome message test to `skip` instead of doing cleanup: .. code-block:: bash teardown() { : # Look Ma! No cleanup! } @test "Show welcome message on first invocation" { if [[ -e /tmp/bats-tutorial-project-ran ]]; then skip 'The FIRST_RUN_FILE already exists' fi run project.sh assert_output --partial 'Welcome to our project!' run project.sh refute_output --partial 'Welcome to our project!' } The first test run still works due to the cleanup from the last round. However, our second run gives us: .. code-block:: console $ ./test/bats/bin/bats test/test.bats - Show welcome message on first invocation (skipped: The FIRST_RUN_FILE already exists) 1 test, 0 failures, 1 skipped .. important:: Skipped tests won't fail a test suite and are counted separately. No test command after `skip` will be executed. If an error occurs before `skip`, the test will fail. An optional reason can be passed to `skip` and will be printed in the test output. Setting up a multifile test suite --------------------------------- With a growing project, putting all tests into one file becomes unwieldy. For our example project, we will extract functionality into the additional file `src/helper.sh`: .. code-block:: bash #!/usr/bin/env bash _is_first_run() { local FIRST_RUN_FILE=/tmp/bats-tutorial-project-ran if [[ ! -e "$FIRST_RUN_FILE" ]]; then touch "$FIRST_RUN_FILE" return 0 fi return 1 } This allows for testing it separately in a new file `test/helper.bats`: .. code-block:: bash setup() { load 'test_helper/common-setup' _common_setup source "$PROJECT_ROOT/src/helper.sh" } teardown() { rm -f "$NON_EXISTANT_FIRST_RUN_FILE" rm -f "$EXISTING_FIRST_RUN_FILE" } @test "Check first run" { NON_EXISTANT_FIRST_RUN_FILE=$(mktemp -u) # only create the name, not the file itself assert _is_first_run refute _is_first_run refute _is_first_run EXISTING_FIRST_RUN_FILE=$(mktemp) refute _is_first_run refute _is_first_run } Since the setup function would have duplicated much of the other files', we split that out into the file `test/test_helper/common-setup.bash`: .. code-block:: bash #!/usr/bin/env bash _common_setup() { load 'test_helper/bats-support/load' load 'test_helper/bats-assert/load' # get the containing directory of this file # use $BATS_TEST_FILENAME instead of ${BASH_SOURCE[0]} or $0, # as those will point to the bats executable's location or the preprocessed file respectively PROJECT_ROOT="$( cd "$( dirname "$BATS_TEST_FILENAME" )/.." >/dev/null 2>&1 && pwd )" # make executables in src/ visible to PATH PATH="$PROJECT_ROOT/src:$PATH" } with the following `setup` in `test/test.bats`: .. code-block:: bash setup() { load 'test_helper/common-setup' _common_setup } Please note, that we gave our helper the extension `.bash`, which is automatically appended by `load`. .. important:: `load` automatically tries to append `.bash` to its argument. In our new `test/helper.bats` we can see, that loading `.sh` is simply done via `source`. .. tip:: Avoid using `load` and `source` outside of any functions. If there is an error in the test file's "free code", the diagnostics are much worse than for code in `setup` or `@test`. With the new changes in place, we can run our tests again. However, our previous run command does not include the new file. You could add the new file to the parameter list, e.g. by running `./test/bats/bin/bats test/*.bats`. However, bats also can handle directories: .. code-block:: console $ ./test/bats/bin/bats test/ ✓ Check first run - Show welcome message on first invocation (skipped: The FIRST_RUN_FILE already exists) 2 tests, 0 failures, 1 skipped In 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. However, 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`. Avoiding costly repeated setups ------------------------------- We already have seen the `setup` function in use, which is called before each test. Sometimes our setup is very costly, such as booting up a service just for testing. If we can reuse the same setup across multiple tests, we might want to do only one setup before all these tests. This usecase is exactly what the `setup_file` function was created for. It can be defined per file and will run before all tests of the respective file. Similarly, we have `teardown_file`, which will run after all tests of the file, even when you abort a test run or a test failed. As an example, we want to add an echo server capability to our project. First, we add the following `server.bats` to our suite: .. code-block:: bash setup_file() { load 'test_helper/common-setup' _common_setup PORT=$(project.sh start-echo-server >/dev/null 2>&1) export PORT } @test "server is reachable" { nc -z localhost "$PORT" } Which will obviously fail: Note that `export PORT` to make it visible to the test! Running this gives us: .. TODO: Update this example with fixed test name reporting from setup_file? (instead of "✗ ") .. code-block:: console $ ./test/bats/bin/bats test/server.bats ✗ (from function `setup_file' in test file test/server.bats, line 4) `PORT=$(project.sh start-echo-server >/dev/null 2>&1)' failed 1 test, 1 failure Now that we got our red test, we need to get it green again. Our new `project.sh` now ends with: .. code-block:: bash case $1 in start-echo-server) echo "Starting echo server" PORT=2000 ncat -l $PORT -k -c 'xargs -n1 echo' 2>/dev/null & # don't keep open this script's stderr echo $! > /tmp/project-echo-server.pid echo "$PORT" >&2 ;; *) echo "NOT IMPLEMENTED!" >&2 exit 1 ;; esac and the tests now say .. code-block:: console $ LANG=C ./test/bats/bin/bats test/server.bats ✓ server is reachable 1 test, 0 failures However, running this a second time gives: .. code-block:: console $ ./test/bats/bin/bats test/server.bats ✗ server is reachable (in test file test/server.bats, line 14) `nc -z -w 2 localhost "$PORT"' failed 2000 Ncat: bind to :::2000: Address already in use. QUITTING. nc: port number invalid: 2000 Ncat: bind to :::2000: Address already in use. QUITTING. 1 test, 1 failure Obviously, we did not turn off our server after testing. This is a task for `teardown_file` in `server.bats`: .. code-block:: bash teardown_file() { project.sh stop-echo-server } Our `project.sh` should also get the new command: .. code-block:: bash stop-echo-server) kill "$(< "/tmp/project-echo-server.pid")" rm /tmp/project-echo-server.pid ;; Now starting our tests again will overwrite the .pid file with the new instance's, so we have to do manual cleanup once. From now on, our test should clean up after itself. .. note:: `teardown_file` will run regardless of tests failing or succeeding. git-secret-0.5.0/vendor/bats-core/docs/source/usage.md000066400000000000000000000065321424706700600226300ustar00rootroot00000000000000# Usage Bats comes with two manual pages. After installation you can view them with `man 1 bats` (usage manual) and `man 7 bats` (writing test files manual). Also, you can view the available command line options that Bats supports by calling Bats with the `-h` or `--help` options. These are the options that Bats currently supports: ``` eval_rst .. program-output:: ../../bin/bats --help ``` To run your tests, invoke the `bats` interpreter with one or more paths to test files ending with the `.bats` extension, or paths to directories containing test files. (`bats` will only execute `.bats` files at the top level of each directory; it will not recurse unless you specify the `-r` flag.) Test cases from each file are run sequentially and in isolation. If all the test cases pass, `bats` exits with a `0` status code. If there are any failures, `bats` exits with a `1` status code. When 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. ```text $ bats addition.bats ✓ addition using bc ✓ addition using dc 2 tests, 0 failures ``` If 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][https://testanything.org]. You can force TAP output from a terminal by invoking Bats with the `--formatter tap` option. ```text $ bats --formatter tap addition.bats 1..2 ok 1 addition using bc ok 2 addition using dc ``` With `--formatter junit`, it is possible to output junit-compatible report files. ```text $ bats --formatter junit addition.bats 1..2 ok 1 addition using bc ok 2 addition using dc ``` Test reports will be output in the executing directory, but may be placed elsewhere by specifying the `--output` flag. ```text $ bats --formatter junit addition.bats --output /tmp 1..2 ok 1 addition using bc ok 2 addition using dc ``` ## Parallel Execution ``` eval_rst .. versionadded:: 1.0.0 ``` By default, Bats will execute your tests serially. However, Bats supports parallel execution of tests (provided you have [GNU parallel][gnu-parallel] or a compatible replacement installed) using the `--jobs` parameter. This can result in your tests completing faster (depending on your tests and the testing hardware). Ordering of parallised tests is not guaranteed, so this mode may break suites with dependencies between tests (or tests that write to shared locations). When enabling `--jobs` for the first time be sure to re-run bats multiple times to identify any inter-test dependencies or non-deterministic test behaviour. When parallelizing, the results of a file only become visible after it has been finished. You can use `--no-parallelize-across-files` to get immediate output at the cost of reduced overall parallelity, as parallelization will only happen within files and files will be run sequentially. If you have files where tests within the file would interfere with each other, you can use `--no-parallelize-within-files` to disable parallelization within all files. If you want more finegrained control, you can `export BATS_NO_PARALLELIZE_WITHIN_FILE=true` in `setup_file()` or outside any function to disable parallelization only within the containing file. [gnu-parallel]: https://www.gnu.org/software/parallel/ git-secret-0.5.0/vendor/bats-core/docs/source/writing-tests.md000066400000000000000000000365161424706700600243540ustar00rootroot00000000000000# Writing tests Each Bats test file is evaluated _n+1_ times, where _n_ 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. For more details about how Bats evaluates test files, see [Bats Evaluation Process][bats-eval] on the wiki. For sample test files, see [examples](https://github.com/bats-core/bats-core/tree/master/docs/examples). [bats-eval]: https://github.com/bats-core/bats-core/wiki/Bats-Evaluation-Process ## Comment syntax External tools (like `shellcheck`, `shfmt`, and various IDE's) may not support the standard `.bats` syntax. Because of this, we provide a valid `bash` alternative: ```bash function invoking_foo_without_arguments_prints_usage { #@test run foo [ "$status" -eq 1 ] [ "${lines[0]}" = "usage: foo " ] } ``` When using this syntax, the function name will be the title in the result output and the value checked when using `--filter`. ## `run`: Test other commands Many Bats tests need to run a command and then make assertions about its exit status and output. Bats includes a `run` helper that invokes its arguments as a command, saves the exit status and output into special global variables, and then returns with a `0` status code so you can continue to make assertions in your test case. For example, let's say you're testing that the `foo` command, when passed a nonexistent filename, exits with a `1` status code and prints an error message. ```bash @test "invoking foo with a nonexistent file prints an error" { run foo nonexistent_filename [ "$status" -eq 1 ] [ "$output" = "foo: no such file 'nonexistent_filename'" ] [ "$BATS_RUN_COMMAND" = "foo nonexistent_filename" ] } ``` The `$status` variable contains the status code of the command, the `$output` variable contains the combined contents of the command's standard output and standard error streams, and the `$BATS_RUN_COMMAND` string contains the command and command arguments passed to `run` for execution. If invoked with one of the following as the first argument, `run` will perform an implicit check on the exit status of the invoked command: ```pre =N expect exit status N (0-255), fail if otherwise ! expect nonzero exit status (1-255), fail if command succeeds ``` We can then write the above more elegantly as: ```bash @test "invoking foo with a nonexistent file prints an error" { run -1 foo nonexistent_filename [ "$output" = "foo: no such file 'nonexistent_filename'" ] } ``` A third special variable, the `$lines` array, is available for easily accessing individual lines of output. For example, if you want to test that invoking `foo` without any arguments prints usage information on the first line: ```bash @test "invoking foo without arguments prints usage" { run -1 foo [ "${lines[0]}" = "usage: foo " ] } ``` __Note:__ The `run` helper executes its argument(s) in a subshell, so if writing tests against environmental side-effects like a variable's value being changed, these changes will not persist after `run` completes. By default `run` leaves out empty lines in `${lines[@]}`. Use `run --keep-empty-lines` to retain them. Additionally, you can use `--separate-stderr` to split stdout and stderr into `$output`/`$stderr` and `${lines[@]}`/`${stderr_lines[@]}`. All additional parameters to run should come before the command. If you want to run a command that starts with `-`, prefix it with `--` to prevent `run` from parsing it as an option. ## `load`: Share common code You may want to share common code across multiple test files. Bats includes a convenient `load` command for sourcing a Bash source files relative to the current test file and from absolute paths. For example, if you have a Bats test in `test/foo.bats`, the command ```bash load test_helper.bash ``` will source the script `test/test_helper.bash` in your test file (limitations apply, see below). This can be useful for sharing functions to set up your environment or load fixtures. `load` delegates to Bash's `source` command after resolving paths. If `load` encounters errors - e.g. because the targeted source file errored - it will print a message with the failing library and Bats exits. To allow to use `load` in conditions `bats_load_safe` has been added. `bats_load_safe` prints a message and returns `1` if a source file cannot be loaded instead of exiting Bats. Aside from that `bats_load_safe` acts exactly like `load`. As pointed out by @iatrou in https://www.tldp.org/LDP/abs/html/declareref.html, using the `declare` builtin restricts scope of a variable. Thus, since actual `source`-ing is performed in context of the `load` function, `declare`d symbols will _not_ be made available to callers of `load`. ### `load` argument resolution `load` supports the following arguments: - absolute paths - relative paths (to the current test file) > For backwards compatibility `load` first searches for a file ending in > `.bash` (e.g. `load test_helper` searches for `test_helper.bash` before > it looks for `test_helper`). This behaviour is deprecated and subject to > change, please use exact filenames instead. If `argument` is an absolute path `load` tries to determine the load path directly. If `argument` is a relative path or a name `load` looks for a matching path in the directory of the current test. ## `bats_load_library`: Load system wide libraries Some libraries are installed on the system, e.g. by `npm` or `brew`. These should not be `load`ed, as their path depends on the installation method. Instead, one should use `bats_load_library` together with setting `BATS_LIB_PATH`, a `PATH`-like colon-delimited variable. `bats_load_library` has two modes of resolving requests: 1. by relative path from the `BATS_LIB_PATH` to a file in the library 2. by library name, expecting libraries to have a `load.bash` entrypoint For example if your `BATS_LIB_PATH` is set to `~/.bats/libs:/usr/lib/bats`, then `bats_load_library test_helper` would look for existing files with the following paths: - `~/.bats/libs/test_helper` - `~/.bats/libs/test_helper/load.bash` - `/usr/lib/bats/test_helper` - `/usr/lib/bats/test_helper/load.bash` The first existing file in this list will be sourced. If you want to load only part of a library or the entry point is not named `load.bash`, you have to include it in the argument: `bats_load_library library_name/file_to_load` will try - `~/.bats/libs/library_name/file_to_load` - `~/.bats/libs/library_name/file_to_load/load.bash` - `/usr/lib/bats/library_name/file_to_load` - `/usr/lib/bats/library_name/file_to_load/load.bash` Apart from the changed lookup rules, `bats_load_library` behaves like `load`. __Note:__ As seen above `load.bash` is the entry point for libraries and meant to load more files from its directory or other libraries. __Note:__ Obviously, the actual `BATS_LIB_PATH` is highly dependant on the environment. To maintain a uniform location across systems, (distribution) package maintainers are encouraged to use `/usr/lib/bats/` as the install path for libraries where possible. However, if the package manager has another preferred location, like `npm` or `brew`, you should use this instead. ## `skip`: Easily skip tests Tests can be skipped by using the `skip` command at the point in a test you wish to skip. ```bash @test "A test I don't want to execute for now" { skip run foo [ "$status" -eq 0 ] } ``` Optionally, you may include a reason for skipping: ```bash @test "A test I don't want to execute for now" { skip "This command will return zero soon, but not now" run foo [ "$status" -eq 0 ] } ``` Or you can skip conditionally: ```bash @test "A test which should run" { if [ foo != bar ]; then skip "foo isn't bar" fi run foo [ "$status" -eq 0 ] } ``` __Note:__ `setup` and `teardown` hooks still run for skipped tests. ## `setup` and `teardown`: Pre- and post-test hooks You can define special `setup` and `teardown` 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. You 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`).