Full Code of borgbackup/borg for AI

master 8eff8270c038 cached
450 files
3.8 MB
1.0M tokens
2871 symbols
1 requests
Download .txt
Showing preview only (4,090K chars total). Download the full file or copy to clipboard to get everything.
Repository: borgbackup/borg
Branch: master
Commit: 8eff8270c038
Files: 450
Total size: 3.8 MB

Directory structure:
gitextract_845rfasc/

├── .editorconfig
├── .git-blame-ignore-revs
├── .gitattributes
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── dependabot.yml
│   └── workflows/
│       ├── backport.yml
│       ├── black.yaml
│       ├── canary.yml
│       ├── ci.yml
│       └── codeql-analysis.yml
├── .gitignore
├── .mailmap
├── .pre-commit-config.yaml
├── .readthedocs.yaml
├── AUTHORS
├── Brewfile
├── LICENSE
├── MANIFEST.in
├── README.rst
├── SECURITY.md
├── Vagrantfile
├── docs/
│   ├── 3rd_party/
│   │   └── README
│   ├── Makefile
│   ├── _static/
│   │   ├── Makefile
│   │   └── logo_font.txt
│   ├── _templates/
│   │   ├── globaltoc.html
│   │   ├── layout.html
│   │   ├── logo-text.html
│   │   └── versionselector.html
│   ├── authors.rst
│   ├── binaries/
│   │   └── 00_README.txt
│   ├── book.rst
│   ├── borg_theme/
│   │   └── css/
│   │       └── borg.css
│   ├── changes.rst
│   ├── changes_0.x.rst
│   ├── changes_1.x.rst
│   ├── conf.py
│   ├── deployment/
│   │   ├── automated-local.rst
│   │   ├── central-backup-server.rst
│   │   ├── hosting-repositories.rst
│   │   ├── image-backup.rst
│   │   ├── non-root-user.rst
│   │   └── pull-backup.rst
│   ├── deployment.rst
│   ├── development.rst
│   ├── faq.rst
│   ├── global.rst.inc
│   ├── index.rst
│   ├── installation.rst
│   ├── internals/
│   │   ├── data-structures.rst
│   │   ├── encryption-aead.odg
│   │   ├── frontends.rst
│   │   ├── object-graph.odg
│   │   ├── security.rst
│   │   └── structure.odg
│   ├── internals.rst
│   ├── introduction.rst
│   ├── man/
│   │   ├── borg-analyze.1
│   │   ├── borg-benchmark-cpu.1
│   │   ├── borg-benchmark-crud.1
│   │   ├── borg-benchmark.1
│   │   ├── borg-break-lock.1
│   │   ├── borg-check.1
│   │   ├── borg-common.1
│   │   ├── borg-compact.1
│   │   ├── borg-completion.1
│   │   ├── borg-compression.1
│   │   ├── borg-config.1
│   │   ├── borg-create.1
│   │   ├── borg-delete.1
│   │   ├── borg-diff.1
│   │   ├── borg-export-tar.1
│   │   ├── borg-extract.1
│   │   ├── borg-import-tar.1
│   │   ├── borg-info.1
│   │   ├── borg-key-change-algorithm.1
│   │   ├── borg-key-change-location.1
│   │   ├── borg-key-change-passphrase.1
│   │   ├── borg-key-export.1
│   │   ├── borg-key-import.1
│   │   ├── borg-key-migrate-to-repokey.1
│   │   ├── borg-key.1
│   │   ├── borg-list.1
│   │   ├── borg-match-archives.1
│   │   ├── borg-mount.1
│   │   ├── borg-patterns.1
│   │   ├── borg-placeholders.1
│   │   ├── borg-prune.1
│   │   ├── borg-recreate.1
│   │   ├── borg-rename.1
│   │   ├── borg-repo-compress.1
│   │   ├── borg-repo-create.1
│   │   ├── borg-repo-delete.1
│   │   ├── borg-repo-info.1
│   │   ├── borg-repo-list.1
│   │   ├── borg-repo-space.1
│   │   ├── borg-serve.1
│   │   ├── borg-tag.1
│   │   ├── borg-transfer.1
│   │   ├── borg-umount.1
│   │   ├── borg-undelete.1
│   │   ├── borg-upgrade.1
│   │   ├── borg-version.1
│   │   ├── borg-with-lock.1
│   │   ├── borg.1
│   │   └── borgfs.1
│   ├── man_intro.rst
│   ├── misc/
│   │   ├── asciinema/
│   │   │   ├── README
│   │   │   ├── Vagrantfile
│   │   │   ├── advanced.json
│   │   │   ├── advanced.tcl
│   │   │   ├── basic.json
│   │   │   ├── basic.tcl
│   │   │   ├── install.json
│   │   │   ├── install.tcl
│   │   │   └── sample-wallpapers.txt
│   │   ├── benchmark-crud.txt
│   │   ├── borg-data-flow.odg
│   │   ├── create_chunker-params.txt
│   │   ├── internals-picture.txt
│   │   ├── logging.conf
│   │   └── prune-example.txt
│   ├── quickstart.rst
│   ├── quickstart_example.rst.inc
│   ├── support.rst
│   ├── usage/
│   │   ├── analyze.rst
│   │   ├── analyze.rst.inc
│   │   ├── benchmark.rst
│   │   ├── benchmark_cpu.rst.inc
│   │   ├── benchmark_crud.rst.inc
│   │   ├── borgfs.rst
│   │   ├── borgfs.rst.inc
│   │   ├── break-lock.rst.inc
│   │   ├── check.rst
│   │   ├── check.rst.inc
│   │   ├── common-options.rst.inc
│   │   ├── compact.rst
│   │   ├── compact.rst.inc
│   │   ├── completion.rst
│   │   ├── completion.rst.inc
│   │   ├── create.rst
│   │   ├── create.rst.inc
│   │   ├── debug.rst
│   │   ├── delete.rst
│   │   ├── delete.rst.inc
│   │   ├── diff.rst
│   │   ├── diff.rst.inc
│   │   ├── export-tar.rst.inc
│   │   ├── extract.rst
│   │   ├── extract.rst.inc
│   │   ├── general/
│   │   │   ├── archive-specification.rst.inc
│   │   │   ├── config.rst.inc
│   │   │   ├── date-time.rst.inc
│   │   │   ├── environment.rst.inc
│   │   │   ├── file-metadata.rst.inc
│   │   │   ├── file-systems.rst.inc
│   │   │   ├── logging.rst.inc
│   │   │   ├── positional-arguments.rst.inc
│   │   │   ├── repository-locations.rst.inc
│   │   │   ├── repository-urls.rst.inc
│   │   │   ├── resources.rst.inc
│   │   │   ├── return-codes.rst.inc
│   │   │   └── units.rst.inc
│   │   ├── general.rst
│   │   ├── help.rst
│   │   ├── help.rst.inc
│   │   ├── import-tar.rst.inc
│   │   ├── info.rst
│   │   ├── info.rst.inc
│   │   ├── key.rst
│   │   ├── key_change-location.rst.inc
│   │   ├── key_change-passphrase.rst.inc
│   │   ├── key_export.rst.inc
│   │   ├── key_import.rst.inc
│   │   ├── list.rst
│   │   ├── list.rst.inc
│   │   ├── lock.rst
│   │   ├── mount.rst
│   │   ├── mount.rst.inc
│   │   ├── notes.rst
│   │   ├── prune.rst
│   │   ├── prune.rst.inc
│   │   ├── recreate.rst
│   │   ├── recreate.rst.inc
│   │   ├── rename.rst
│   │   ├── rename.rst.inc
│   │   ├── repo-compress.rst
│   │   ├── repo-compress.rst.inc
│   │   ├── repo-create.rst
│   │   ├── repo-create.rst.inc
│   │   ├── repo-delete.rst
│   │   ├── repo-delete.rst.inc
│   │   ├── repo-info.rst
│   │   ├── repo-info.rst.inc
│   │   ├── repo-list.rst
│   │   ├── repo-list.rst.inc
│   │   ├── repo-space.rst
│   │   ├── repo-space.rst.inc
│   │   ├── serve.rst
│   │   ├── serve.rst.inc
│   │   ├── tag.rst
│   │   ├── tag.rst.inc
│   │   ├── tar.rst
│   │   ├── transfer.rst
│   │   ├── transfer.rst.inc
│   │   ├── umount.rst.inc
│   │   ├── undelete.rst
│   │   ├── undelete.rst.inc
│   │   ├── usage_general.rst.inc
│   │   ├── version.rst
│   │   ├── version.rst.inc
│   │   └── with-lock.rst.inc
│   ├── usage.rst
│   └── usage_general.rst.inc
├── pyproject.toml
├── requirements.d/
│   ├── codestyle.txt
│   ├── development.lock.txt
│   ├── development.txt
│   ├── docs.txt
│   └── pyinstaller.txt
├── scripts/
│   ├── Dockerfile.linux-run
│   ├── borg.exe.spec
│   ├── errorlist.py
│   ├── fetch-binaries
│   ├── glibc_check.py
│   ├── linux-run
│   ├── make-testdata/
│   │   └── test_transfer_upgrade.sh
│   ├── make.py
│   ├── msys2-install-deps
│   ├── sdist-sign
│   ├── shell_completions/
│   │   └── fish/
│   │       └── borg.fish
│   ├── sign-binaries
│   └── upload-pypi
├── setup.py
└── src/
    └── borg/
        ├── __init__.py
        ├── __main__.py
        ├── _item.c
        ├── archive.py
        ├── archiver/
        │   ├── __init__.py
        │   ├── _common.py
        │   ├── analyze_cmd.py
        │   ├── benchmark_cmd.py
        │   ├── check_cmd.py
        │   ├── compact_cmd.py
        │   ├── completion_cmd.py
        │   ├── create_cmd.py
        │   ├── debug_cmd.py
        │   ├── delete_cmd.py
        │   ├── diff_cmd.py
        │   ├── extract_cmd.py
        │   ├── help_cmd.py
        │   ├── info_cmd.py
        │   ├── key_cmds.py
        │   ├── list_cmd.py
        │   ├── lock_cmds.py
        │   ├── mount_cmds.py
        │   ├── prune_cmd.py
        │   ├── recreate_cmd.py
        │   ├── rename_cmd.py
        │   ├── repo_compress_cmd.py
        │   ├── repo_create_cmd.py
        │   ├── repo_delete_cmd.py
        │   ├── repo_info_cmd.py
        │   ├── repo_list_cmd.py
        │   ├── repo_space_cmd.py
        │   ├── serve_cmd.py
        │   ├── tag_cmd.py
        │   ├── tar_cmds.py
        │   ├── transfer_cmd.py
        │   ├── undelete_cmd.py
        │   └── version_cmd.py
        ├── cache.py
        ├── checksums.pyi
        ├── checksums.pyx
        ├── chunkers/
        │   ├── __init__.py
        │   ├── buzhash.pyi
        │   ├── buzhash.pyx
        │   ├── buzhash64.pyi
        │   ├── buzhash64.pyx
        │   ├── failing.py
        │   ├── fixed.py
        │   ├── reader.pyi
        │   └── reader.pyx
        ├── cockpit/
        │   ├── __init__.py
        │   ├── app.py
        │   ├── cockpit.tcss
        │   ├── runner.py
        │   ├── theme.py
        │   ├── translator.py
        │   └── widgets.py
        ├── compress.pyi
        ├── compress.pyx
        ├── conftest.py
        ├── constants.py
        ├── crypto/
        │   ├── __init__.py
        │   ├── file_integrity.py
        │   ├── key.py
        │   ├── keymanager.py
        │   ├── low_level.pyi
        │   └── low_level.pyx
        ├── fslocking.py
        ├── fuse.py
        ├── fuse_impl.py
        ├── hashindex.pyi
        ├── hashindex.pyx
        ├── helpers/
        │   ├── __init__.py
        │   ├── argparsing.py
        │   ├── datastruct.py
        │   ├── errors.py
        │   ├── fs.py
        │   ├── lrucache.py
        │   ├── misc.py
        │   ├── msgpack.py
        │   ├── nanorst.py
        │   ├── parseformat.py
        │   ├── passphrase.py
        │   ├── process.py
        │   ├── progress.py
        │   ├── shellpattern.py
        │   ├── time.py
        │   └── yes_no.py
        ├── hlfuse.py
        ├── item.pyi
        ├── item.pyx
        ├── legacyremote.py
        ├── legacyrepository.py
        ├── logger.py
        ├── manifest.py
        ├── paperkey.html
        ├── patterns.py
        ├── platform/
        │   ├── __init__.py
        │   ├── base.py
        │   ├── darwin.pyx
        │   ├── freebsd.pyx
        │   ├── linux.pyx
        │   ├── netbsd.pyx
        │   ├── posix.pyx
        │   ├── posix_ug.py
        │   ├── syncfilerange.pyx
        │   ├── windows.pyx
        │   ├── windows_ug.py
        │   └── xattr.py
        ├── platformflags.py
        ├── remote.py
        ├── repoobj.py
        ├── repository.py
        ├── selftest.py
        ├── storelocking.py
        ├── testsuite/
        │   ├── __init__.py
        │   ├── archive_test.py
        │   ├── archiver/
        │   │   ├── __init__.py
        │   │   ├── analyze_cmd_test.py
        │   │   ├── argparsing_test.py
        │   │   ├── benchmark_cmd_test.py
        │   │   ├── check_cmd_test.py
        │   │   ├── checks_test.py
        │   │   ├── compact_cmd_test.py
        │   │   ├── completion_cmd_test.py
        │   │   ├── corruption_test.py
        │   │   ├── create_cmd_test.py
        │   │   ├── debug_cmds_test.py
        │   │   ├── delete_cmd_test.py
        │   │   ├── diff_cmd_test.py
        │   │   ├── disk_full_test.py
        │   │   ├── extract_cmd_test.py
        │   │   ├── help_cmd_test.py
        │   │   ├── info_cmd_test.py
        │   │   ├── key_cmds_test.py
        │   │   ├── list_cmd_test.py
        │   │   ├── lock_cmds_test.py
        │   │   ├── mount_cmds_test.py
        │   │   ├── patterns_test.py
        │   │   ├── prune_cmd_test.py
        │   │   ├── recreate_cmd_test.py
        │   │   ├── remote_repo_test.py
        │   │   ├── rename_cmd_test.py
        │   │   ├── repo_compress_cmd_test.py
        │   │   ├── repo_create_cmd_test.py
        │   │   ├── repo_delete_cmd_test.py
        │   │   ├── repo_info_cmd_test.py
        │   │   ├── repo_list_cmd_test.py
        │   │   ├── repo_space_cmd_test.py
        │   │   ├── restricted_permissions_test.py
        │   │   ├── return_codes_test.py
        │   │   ├── serve_cmd_test.py
        │   │   ├── tag_cmd_test.py
        │   │   ├── tar_cmds_test.py
        │   │   ├── transfer_cmd_test.py
        │   │   └── undelete_cmd_test.py
        │   ├── benchmark_test.py
        │   ├── cache_test.py
        │   ├── checksums_test.py
        │   ├── chunkers/
        │   │   ├── __init__.py
        │   │   ├── buzhash64_self_test.py
        │   │   ├── buzhash64_test.py
        │   │   ├── buzhash_self_test.py
        │   │   ├── buzhash_test.py
        │   │   ├── failing_test.py
        │   │   ├── fixed_self_test.py
        │   │   ├── fixed_test.py
        │   │   ├── interaction_test.py
        │   │   └── reader_test.py
        │   ├── cockpit_test.py
        │   ├── compress_test.py
        │   ├── crypto/
        │   │   ├── __init__.py
        │   │   ├── crypto_test.py
        │   │   ├── csprng_test.py
        │   │   ├── file_integrity_test.py
        │   │   └── key_test.py
        │   ├── fslocking_test.py
        │   ├── hashindex_test.py
        │   ├── helpers/
        │   │   ├── __init__.py
        │   │   ├── __init__test.py
        │   │   ├── datastruct_test.py
        │   │   ├── efficient_collection_queue_test.py
        │   │   ├── fs_test.py
        │   │   ├── lrucache_test.py
        │   │   ├── misc_test.py
        │   │   ├── msgpack_test.py
        │   │   ├── nanorst_test.py
        │   │   ├── parseformat_test.py
        │   │   ├── passphrase_test.py
        │   │   ├── process_test.py
        │   │   ├── progress_test.py
        │   │   ├── shellpattern_test.py
        │   │   ├── time_test.py
        │   │   └── yes_no_test.py
        │   ├── item_test.py
        │   ├── legacyrepository_test.py
        │   ├── logger_test.py
        │   ├── patterns_test.py
        │   ├── platform/
        │   │   ├── __init__.py
        │   │   ├── all_test.py
        │   │   ├── darwin_test.py
        │   │   ├── freebsd_test.py
        │   │   ├── linux_test.py
        │   │   ├── platform_test.py
        │   │   └── windows_test.py
        │   ├── remote_test.py
        │   ├── repoobj_test.py
        │   ├── repository_test.py
        │   ├── shell_completions_test.py
        │   ├── storelocking_test.py
        │   ├── version_test.py
        │   └── xattr_test.py
        ├── upgrade.py
        ├── version.py
        └── xattr.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
# EditorConfig is awesome: https://editorconfig.org/

root = true

[*]
end_of_line = lf
charset = utf-8
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true


================================================
FILE: .git-blame-ignore-revs
================================================
# Migrate code style to Black
7957af562d5ce8266b177039783be4dc8bdd7898


================================================
FILE: .gitattributes
================================================
borg/_version.py export-subst

*.py diff=python
docs/usage/*.rst.inc merge=ours
docs/man/* merge=ours


================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

github: borgbackup
liberapay: borgbackup
open_collective: borgbackup
custom: ['https://www.borgbackup.org/support/fund.html']


================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
<!--
Thank you for reporting an issue.

*IMPORTANT* – Before creating a new issue, please look around:
 - BorgBackup documentation: https://borgbackup.readthedocs.io/en/stable/index.html
 - FAQ: https://borgbackup.readthedocs.io/en/stable/faq.html
 - Open issues in the GitHub tracker: https://github.com/borgbackup/borg/issues

If you cannot find a similar problem, then create a new issue.

Please fill in as much of the template as possible.
-->

## Have you checked the BorgBackup docs, FAQ, and open GitHub issues?

No

## Is this a bug/issue report or a question?

Bug/Issue/Question

## System information. For client/server mode, post info for both machines.

#### Your Borg version (borg -V).

#### Operating system (distribution) and version.

#### Hardware/network configuration and filesystems used.

#### How much data is handled by Borg?

#### Full Borg command line that led to the problem (leave out excludes and passwords).


## Describe the problem you're observing.

#### Can you reproduce the problem? If so, describe how. If not, describe troubleshooting steps you took before opening the issue.

#### Include any warnings/errors/backtraces from the system logs

<!--

If this complaint relates to Borg performance, please include CRUD benchmark
results and any steps you took to troubleshoot.
How to run the benchmark: https://borgbackup.readthedocs.io/en/stable/usage/benchmark.html

*IMPORTANT* – Please mark logs and terminal command output, otherwise GitHub will not display them correctly.
An example is provided below.

Example:
```
this is an example of how log text should be marked (wrap it with ```)
```
-->


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
<!--
Thank you for contributing to BorgBackup!

Please make sure your PR complies with our contribution guidelines:
https://borgbackup.readthedocs.io/en/latest/development.html#contributions
-->

## Description

<!-- What does this PR do? Reference any related issues with "fixes #XXXX". -->


## Checklist

- [ ] PR is against `master` (or maintenance branch if only applicable there)
- [ ] New code has tests and docs where appropriate
- [ ] Tests pass (run `tox` or the relevant test subset)
- [ ] Commit messages are clean and reference related issues


================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"
    groups:
      actions:
        patterns:
          - "*"
  - package-ecosystem: "pip"
    directory: "/requirements.d"
    ignore:
    - dependency-name: "black"
    schedule:
      interval: "weekly"
    cooldown:
      semver-major-days: 90
      semver-minor-days: 30
    groups:
      pip-dependencies:
        patterns:
          - "*"



================================================
FILE: .github/workflows/backport.yml
================================================
name: Backport pull request

on:
  pull_request_target:
    types: [closed]
  issue_comment:
    types: [created]

permissions:
  contents: write # so it can comment
  pull-requests: write # so it can create pull requests

jobs:
  backport:
    name: Backport pull request
    runs-on: ubuntu-24.04
    timeout-minutes: 5

    # Only run when pull request is merged
    # or when a comment starting with `/backport` is created by someone other than the
    # https://github.com/backport-action bot user (user id: 97796249). Note that if you use your
    # own PAT as `github_token`, that you should replace this id with yours.
    if: >
        (
          github.event_name == 'pull_request_target' &&
          github.event.pull_request.merged
        ) || (
          github.event_name == 'issue_comment' &&
          github.event.issue.pull_request &&
          github.event.comment.user.id != 97796249 &&
          startsWith(github.event.comment.body, '/backport')
        )
    steps:
        - uses: actions/checkout@v6
        - name: Create backport pull requests
          uses: korthout/backport-action@v4
          with:
            label_pattern: '^port/(.+)$'


================================================
FILE: .github/workflows/black.yaml
================================================
# https://black.readthedocs.io/en/stable/integrations/github_actions.html#usage
# See also what we use locally in requirements.d/codestyle.txt — this should be the same version here.

name: Lint

on:
  push:
    paths:
      - '**.py'
      - 'pyproject.toml'
      - '.github/workflows/black.yaml'
  pull_request:
    paths:
      - '**.py'
      - 'pyproject.toml'
      - '.github/workflows/black.yaml'

concurrency:
  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
  lint:
    runs-on: ubuntu-22.04
    timeout-minutes: 5
    steps:
      - uses: actions/checkout@v6
      - uses: psf/black@c6755bb741b6481d6b3d3bb563c83fa060db96c9  # 26.3.1
        with:
            version: "~= 24.0"


================================================
FILE: .github/workflows/canary.yml
================================================
name: Canary (Unlocked Requirements)

on:
  schedule:
    - cron: '0 7 * * *'  # Run at 07:00 UTC
  workflow_dispatch:      # Allow manual trigger

permissions:
  contents: read

jobs:
  canary_tests:
    name: Canary (${{ matrix.os }}, ${{ matrix.python-version }}, ${{ matrix.toxenv }})
    runs-on: ${{ matrix.os }}
    timeout-minutes: 360
    strategy:
      fail-fast: false
      matrix:
        include:
          # A representative subset of environments
          - os: ubuntu-22.04
            python-version: '3.10'
            toxenv: py310-llfuse
          - os: ubuntu-24.04
            python-version: '3.12'
            toxenv: py312-pyfuse3
          - os: ubuntu-24.04
            python-version: '3.14'
            toxenv: py314-mfusepy
          - os: macos-15
            python-version: '3.14'
            toxenv: py314-none

    steps:
    - uses: actions/checkout@v6
      with:
        fetch-depth: 0
        fetch-tags: true

    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v6
      with:
        python-version: ${{ matrix.python-version }}

    - name: Install Linux packages
      if: ${{ runner.os == 'Linux' }}
      shell: bash
      run: |
        sudo apt-get update
        sudo apt-get install -y pkg-config build-essential
        sudo apt-get install -y libssl-dev libacl1-dev liblz4-dev
        if [[ "${{ matrix.toxenv }}" == *"llfuse"* ]]; then
          sudo apt-get install -y libfuse-dev fuse
        elif [[ "${{ matrix.toxenv }}" == *"pyfuse3"* || "${{ matrix.toxenv }}" == *"mfusepy"* ]]; then
          sudo apt-get install -y libfuse3-dev fuse3
        fi

    - name: Install macOS packages
      if: ${{ runner.os == 'macOS' }}
      shell: bash
      run: |
        brew bundle install || true

    - name: Install Python requirements (UNLOCKED)
      shell: bash
      run: |
        python -m pip install --upgrade pip setuptools wheel
        # Use UNLOCKED requirements to catch upstream breakages
        pip install -r requirements.d/development.txt

    - name: Install borgbackup
      shell: bash
      run: |
        if [[ "${{ matrix.toxenv }}" == *"llfuse"* ]]; then
          pip install -e ".[llfuse,cockpit]"
        elif [[ "${{ matrix.toxenv }}" == *"pyfuse3"* ]]; then
          pip install -e ".[pyfuse3,cockpit]"
        elif [[ "${{ matrix.toxenv }}" == *"mfusepy"* ]]; then
          pip install -e ".[mfusepy,cockpit]"
        else
          pip install -e ".[cockpit]"
        fi

    - name: Run tests (Canary)
      shell: bash
      run: |
        if [[ "${{ matrix.toxenv }}" == *"-windows" ]]; then
          python -m pytest -n4 --benchmark-skip -vv -rs -k "not remote" --cov=borg --cov-config=pyproject.toml --cov-report=xml --junitxml=test-results.xml
        else
          # Force tox to use the unlocked requirements in its environment creation
          # by overriding the deps if possible, or just trusting it uses development.txt
          # which we already installed in the root. Actually tox creates its own venv.
          # We need to tell tox to use the unlocked file.
          tox -e ${{ matrix.toxenv }} --override "env_run_base.deps=[-rrequirements.d/development.txt]"
        fi

  windows_canary:

    if: true  # can be used to temporarily disable the build
    name: Canary (Windows)
    runs-on: windows-latest
    timeout-minutes: 180

    env:
      PY_COLORS: 1

    defaults:
      run:
        shell: msys2 {0}

    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - uses: msys2/setup-msys2@v2
        with:
          msystem: UCRT64
          update: true

      - name: Install system packages
        run: ./scripts/msys2-install-deps development

      - name: Build python venv
        run: |
          # building cffi / argon2-cffi in the venv fails, so we try to use the system packages
          python -m venv --system-site-packages env
          . env/bin/activate
          # python -m pip install --upgrade pip
          # pip install --upgrade setuptools build wheel
          pip install -r requirements.d/pyinstaller.txt

      - name: Build
        run: |
          # build borg.exe
          . env/bin/activate
          pip install -e ".[cockpit,s3,sftp,rest,rclone]"
          mkdir -p dist/binary
          pyinstaller -y --clean --distpath=dist/binary scripts/borg.exe.spec
          # build sdist and wheel in dist/...
          python -m build

      - name: Run tests
        run: |
          # Ensure locally built binary in ./dist/binary/borg-dir is found during tests
          export PATH="$GITHUB_WORKSPACE/dist/binary/borg-dir:$PATH"
          borg.exe -V
          . env/bin/activate
          python -m pytest -n4 --benchmark-skip -vv -rs -k "not remote" --cov=borg --cov-config=pyproject.toml --cov-report=xml --junitxml=test-results.xml


================================================
FILE: .github/workflows/ci.yml
================================================
# badge: https://github.com/borgbackup/borg/workflows/CI/badge.svg?branch=master

name: CI

on:
  push:
    branches: [ master ]
    tags:
    - '2.*'
  pull_request:
    branches: [ master ]
    paths:
    - '**.py'
    - '**.pyx'
    - '**.c'
    - '**.h'
    - '**.yml'
    - '**.toml'
    - '**.cfg'
    - '**.ini'
    - 'requirements.d/*'
    - '!docs/**'

concurrency:
  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}

permissions:
  contents: read

jobs:
  lint:

    runs-on: ubuntu-22.04
    timeout-minutes: 5

    steps:
    - uses: actions/checkout@v6
    - uses: astral-sh/ruff-action@v3

  security:

    runs-on: ubuntu-24.04
    timeout-minutes: 5

    steps:
    - uses: actions/checkout@v6
    - name: Set up Python
      uses: actions/setup-python@v6
      with:
        python-version: '3.10'
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install bandit[toml]
    - name: Run Bandit
      run: |
        bandit -r src/borg -c pyproject.toml

  asan_ubsan:

    runs-on: ubuntu-24.04
    timeout-minutes: 25
    needs: [lint]

    steps:
    - uses: actions/checkout@v6
      with:
        # Just fetching one commit is not enough for setuptools-scm, so we fetch all.
        fetch-depth: 0
        fetch-tags: true

    - name: Set up Python
      uses: actions/setup-python@v6
      with:
        python-version: '3.12'

    - name: Install system packages
      run: |
        sudo apt-get update
        sudo apt-get install -y pkg-config build-essential
        sudo apt-get install -y libssl-dev libacl1-dev liblz4-dev

    - name: Install Python dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.d/development.lock.txt

    - name: Build Borg with ASan/UBSan
      # Build the C/Cython extensions with AddressSanitizer and UndefinedBehaviorSanitizer enabled.
      # How this works:
      # - The -fsanitize=address,undefined flags inject runtime checks into our native code. If a bug is hit
      #   (e.g., buffer overflow, use-after-free, out-of-bounds, or undefined behavior), the sanitizer prints
      #   a detailed error report to stderr, including a stack trace, and forces the process to exit with
      #   non-zero status. In CI, this will fail the step/job so you will notice.
      # - ASAN_OPTIONS/UBSAN_OPTIONS configure the sanitizers' runtime behavior (see below for meanings).
      env:
        CFLAGS: "-O1 -g -fno-omit-frame-pointer -fsanitize=address,undefined"
        CXXFLAGS: "-O1 -g -fno-omit-frame-pointer -fsanitize=address,undefined"
        LDFLAGS: "-fsanitize=address,undefined"
        # ASAN_OPTIONS controls AddressSanitizer runtime tweaks:
        # - detect_leaks=0: Disable LeakSanitizer to avoid false positives with CPython/pymalloc in short-lived tests.
        # - strict_string_checks=1: Make invalid string operations (e.g., over-reads) more likely to be detected.
        # - check_initialization_order=1: Catch uses that depend on static initialization order (C++).
        # - detect_stack_use_after_return=1: Detect stack-use-after-return via stack poisoning (may increase overhead).
        ASAN_OPTIONS: "detect_leaks=0:strict_string_checks=1:check_initialization_order=1:detect_stack_use_after_return=1"
        # UBSAN_OPTIONS controls UndefinedBehaviorSanitizer runtime:
        # - print_stacktrace=1: Include a stack trace for UB reports to ease debugging.
        #   Note: UBSan is recoverable by default (process may continue after reporting). If you want CI to
        #   abort immediately and fail on the first UB, add `halt_on_error=1` (e.g., UBSAN_OPTIONS="print_stacktrace=1:halt_on_error=1").
        UBSAN_OPTIONS: "print_stacktrace=1"
        # PYTHONDEVMODE enables additional Python runtime checks and warnings.
        PYTHONDEVMODE: "1"
      run: pip install -e .

    - name: Run tests under sanitizers
      env:
        ASAN_OPTIONS: "detect_leaks=0:strict_string_checks=1:check_initialization_order=1:detect_stack_use_after_return=1"
        UBSAN_OPTIONS: "print_stacktrace=1"
        PYTHONDEVMODE: "1"
      # Ensure the ASan runtime is loaded first to avoid "ASan runtime does not come first" warnings.
      # We discover libasan/libubsan paths via gcc and preload them for the Python test process.
      # the remote tests are slow and likely won't find anything useful
      run: |
        set -euo pipefail
        export LD_PRELOAD="$(gcc -print-file-name=libasan.so):$(gcc -print-file-name=libubsan.so)"
        echo "Using LD_PRELOAD=$LD_PRELOAD"
        pytest -v --benchmark-skip -k "not remote"

  native_tests:

    needs: [lint]
    permissions:
      contents: read
      id-token: write
      attestations: write
    strategy:
      fail-fast: true
      # noinspection YAMLSchemaValidation
      matrix: >-
        ${{ fromJSON(
          github.event_name == 'pull_request' && '{
            "include": [
              {"os": "ubuntu-22.04", "python-version": "3.10", "toxenv": "mypy"},
              {"os": "ubuntu-22.04", "python-version": "3.11", "toxenv": "docs"},
              {"os": "ubuntu-22.04", "python-version": "3.10", "toxenv": "py310-llfuse"},
              {"os": "ubuntu-24.04", "python-version": "3.12", "toxenv": "py312-pyfuse3"},
              {"os": "ubuntu-24.04", "python-version": "3.14", "toxenv": "py314-mfusepy"}
            ]
          }' || '{
            "include": [
              {"os": "ubuntu-22.04", "python-version": "3.11", "toxenv": "py311-pyfuse3", "binary": "borg-linux-glibc235-x86_64-gh"},
              {"os": "ubuntu-22.04-arm", "python-version": "3.11", "toxenv": "py311-pyfuse3", "binary": "borg-linux-glibc235-arm64-gh"},
              {"os": "ubuntu-24.04", "python-version": "3.12", "toxenv": "py312-llfuse"},
              {"os": "ubuntu-24.04", "python-version": "3.13", "toxenv": "py313-pyfuse3"},
              {"os": "ubuntu-24.04", "python-version": "3.14", "toxenv": "py314-mfusepy"},
              {"os": "macos-15", "python-version": "3.11", "toxenv": "py311-none", "binary": "borg-macos-15-arm64-gh"},
              {"os": "macos-15-intel", "python-version": "3.11", "toxenv": "py311-none", "binary": "borg-macos-15-x86_64-gh"}
            ]
          }'
        ) }}
    env:
      TOXENV: ${{ matrix.toxenv }}

    runs-on: ${{ matrix.os }}
    # macOS machines can be slow, if overloaded.
    timeout-minutes: 360

    steps:
    - uses: actions/checkout@v6
      with:
        # Just fetching one commit is not enough for setuptools-scm, so we fetch all.
        fetch-depth: 0
        fetch-tags: true

    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v6
      with:
        python-version: ${{ matrix.python-version }}

    - name: Cache pip
      uses: actions/cache@v5
      with:
        path: ~/.cache/pip
        key: ${{ runner.os }}-${{ runner.arch }}-pip-${{ hashFiles('requirements.d/development.lock.txt') }}
        restore-keys: |
            ${{ runner.os }}-${{ runner.arch }}-pip-
            ${{ runner.os }}-${{ runner.arch }}-

    - name: Cache tox environments
      uses: actions/cache@v5
      with:
        path: .tox
        key: ${{ runner.os }}-${{ runner.arch }}-tox-${{ matrix.toxenv }}-${{ hashFiles('requirements.d/development.lock.txt', 'pyproject.toml') }}
        restore-keys: |
          ${{ runner.os }}-${{ runner.arch }}-tox-${{ matrix.toxenv }}-
          ${{ runner.os }}-${{ runner.arch }}-tox-

    - name: Install Linux packages
      if: ${{ runner.os == 'Linux' }}
      run: |
        sudo apt-get update
        sudo apt-get install -y pkg-config build-essential
        sudo apt-get install -y libssl-dev libacl1-dev liblz4-dev
        sudo apt-get install -y bash zsh fish  # for shell completion tests
        sudo apt-get install -y rclone openssh-server curl
        if [[ "$TOXENV" == *"llfuse"* ]]; then
          sudo apt-get install -y libfuse-dev fuse  # Required for Python llfuse module
        elif [[ "$TOXENV" == *"pyfuse3"* || "$TOXENV" == *"mfusepy"* ]]; then
          sudo apt-get install -y libfuse3-dev fuse3  # Required for Python pyfuse3 module
        fi

    - name: Install macOS packages
      if: ${{ runner.os == 'macOS' }}
      run: |
        brew unlink pkg-config@0.29.2 || true
        brew bundle install

    - name: Configure OpenSSH SFTP server (test only)
      if: ${{ runner.os == 'Linux' && !contains(matrix.toxenv, 'mypy') && !contains(matrix.toxenv, 'docs') }}
      run: |
        sudo mkdir -p /run/sshd
        sudo useradd -m -s /bin/bash sftpuser || true
        # Create SSH key for the CI user and authorize it for sftpuser
        mkdir -p ~/.ssh
        chmod 700 ~/.ssh
        test -f ~/.ssh/id_ed25519 || ssh-keygen -t ed25519 -N '' -f ~/.ssh/id_ed25519
        sudo mkdir -p /home/sftpuser/.ssh
        sudo chmod 700 /home/sftpuser/.ssh
        sudo cp ~/.ssh/id_ed25519.pub /home/sftpuser/.ssh/authorized_keys
        sudo chown -R sftpuser:sftpuser /home/sftpuser/.ssh
        sudo chmod 600 /home/sftpuser/.ssh/authorized_keys
        # Allow publickey auth and enable Subsystem sftp
        sudo sed -i 's/^#\?PasswordAuthentication .*/PasswordAuthentication no/' /etc/ssh/sshd_config
        sudo sed -i 's/^#\?PubkeyAuthentication .*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
        if ! grep -q '^Subsystem sftp' /etc/ssh/sshd_config; then echo 'Subsystem sftp /usr/lib/openssh/sftp-server' | sudo tee -a /etc/ssh/sshd_config; fi
        # Ensure host keys exist to avoid slow generation on first sshd start
        sudo ssh-keygen -A
        # Start sshd (listen on default 22 inside runner)
        sudo /usr/sbin/sshd -D &
        # Add host key to known_hosts so paramiko trusts it
        ssh-keyscan -H localhost 127.0.0.1 | tee -a ~/.ssh/known_hosts
        # Start ssh-agent and add our key so paramiko can use the agent
        eval "$(ssh-agent -s)"
        ssh-add ~/.ssh/id_ed25519
        # Export SFTP test URL for tox via GITHUB_ENV
        echo "BORG_TEST_SFTP_REPO=sftp://sftpuser@localhost:22/borg/sftp-repo" >> $GITHUB_ENV

    - name: Install and configure MinIO S3 server (test only)
      if: ${{ runner.os == 'Linux' && !contains(matrix.toxenv, 'mypy') && !contains(matrix.toxenv, 'docs') }}
      run: |
        set -e
        arch=$(uname -m)
        case "$arch" in
          x86_64|amd64) srv_url=https://dl.min.io/server/minio/release/linux-amd64/minio; cli_url=https://dl.min.io/client/mc/release/linux-amd64/mc ;;
          aarch64|arm64) srv_url=https://dl.min.io/server/minio/release/linux-arm64/minio; cli_url=https://dl.min.io/client/mc/release/linux-arm64/mc ;;
          *) echo "Unsupported arch: $arch"; exit 1 ;;
        esac
        curl -fsSL -o /usr/local/bin/minio "$srv_url"
        curl -fsSL -o /usr/local/bin/mc "$cli_url"
        sudo chmod +x /usr/local/bin/minio /usr/local/bin/mc
        export PATH=/usr/local/bin:$PATH
        # Start MinIO on :9000 with default credentials (minioadmin/minioadmin)
        MINIO_DIR="$GITHUB_WORKSPACE/.minio-data"
        MINIO_LOG="$GITHUB_WORKSPACE/.minio.log"
        mkdir -p "$MINIO_DIR"
        nohup minio server "$MINIO_DIR" --address ":9000" >"$MINIO_LOG" 2>&1 &
        # Wait for MinIO port to be ready
        for i in $(seq 1 60); do (echo > /dev/tcp/127.0.0.1/9000) >/dev/null 2>&1 && break; sleep 1; done
        # Configure client and create bucket
        mc alias set local http://127.0.0.1:9000 minioadmin minioadmin
        mc mb --ignore-existing local/borg
        # Export S3 test URL for tox via GITHUB_ENV
        echo "BORG_TEST_S3_REPO=s3:minioadmin:minioadmin@http://127.0.0.1:9000/borg/s3-repo" >> $GITHUB_ENV

    - name: Install Python requirements
      run: |
        python -m pip install --upgrade pip setuptools wheel
        pip install -r requirements.d/development.lock.txt

    - name: Install borgbackup
      run: |
        if [[ "$TOXENV" == *"llfuse"* ]]; then
          pip install -ve ".[llfuse,cockpit,s3,sftp,rest,rclone]"
        elif [[ "$TOXENV" == *"pyfuse3"* ]]; then
          pip install -ve ".[pyfuse3,cockpit,s3,sftp,rest,rclone]"
        elif [[ "$TOXENV" == *"mfusepy"* ]]; then
          pip install -ve ".[mfusepy,cockpit,s3,sftp,rest,rclone]"
        else
          pip install -ve ".[cockpit,s3,sftp,rest,rclone]"
        fi

    - name: Build Borg fat binaries (${{ matrix.binary }})
      if: ${{ matrix.binary && startsWith(github.ref, 'refs/tags/') }}
      run: |
        pip install -r requirements.d/pyinstaller.txt
        mkdir -p dist/binary
        pyinstaller --clean --distpath=dist/binary scripts/borg.exe.spec

    - name: Smoke-test the built binary (${{ matrix.binary }})
      if: ${{ matrix.binary && startsWith(github.ref, 'refs/tags/') }}
      run: |
        pushd dist/binary
        echo "single-file binary"
        chmod +x borg.exe
        ./borg.exe -V
        echo "single-directory binary"
        chmod +x borg-dir/borg.exe
        ./borg-dir/borg.exe -V
        tar czf borg.tgz borg-dir
        popd
        # Ensure locally built binary in ./dist/binary/borg-dir is found during tests
        export PATH="$GITHUB_WORKSPACE/dist/binary/borg-dir:$PATH"
        echo "borg.exe binary in PATH"
        borg.exe -V

    - name: Prepare binaries (${{ matrix.binary }})
      if: ${{ matrix.binary && startsWith(github.ref, 'refs/tags/') }}
      run: |
        mkdir -p artifacts
        if [ -f dist/binary/borg.exe ]; then
          cp dist/binary/borg.exe artifacts/${{ matrix.binary }}
        fi
        if [ -f dist/binary/borg.tgz ]; then
          cp dist/binary/borg.tgz artifacts/${{ matrix.binary }}.tgz
        fi
        echo "binary files"
        ls -l artifacts/

    - name: Attest binaries provenance (${{ matrix.binary }})
      if: ${{ matrix.binary && startsWith(github.ref, 'refs/tags/') }}
      uses: actions/attest-build-provenance@v4
      with:
        subject-path: 'artifacts/*'

    - name: Upload binaries (${{ matrix.binary }})
      if: ${{ matrix.binary && startsWith(github.ref, 'refs/tags/') }}
      uses: actions/upload-artifact@v7
      with:
        name: ${{ matrix.binary }}
        path: artifacts/*
        if-no-files-found: error

    - name: run tox env
      run: |
        # do not use fakeroot, but run as root. avoids the dreaded EISDIR sporadic failures. see #2482.
        #sudo -E bash -c "tox -e py"
        # Ensure locally built binary in ./dist/binary/borg-dir is found during tests
        export PATH="$GITHUB_WORKSPACE/dist/binary/borg-dir:$PATH"
        tox --skip-missing-interpreters

    - name: Upload test results to Codecov
      if: ${{ !cancelled() && !contains(matrix.toxenv, 'mypy') && !contains(matrix.toxenv, 'docs') }}
      uses: codecov/codecov-action@v5
      env:
        OS: ${{ runner.os }}
        python: ${{ matrix.python-version }}
      with:
        token: ${{ secrets.CODECOV_TOKEN }}
        report_type: test_results
        env_vars: OS,python
        files: test-results.xml

    - name: Upload coverage to Codecov
      if: ${{ !cancelled() && !contains(matrix.toxenv, 'mypy') && !contains(matrix.toxenv, 'docs') }}
      uses: codecov/codecov-action@v5
      env:
        OS: ${{ runner.os }}
        python: ${{ matrix.python-version }}
      with:
        token: ${{ secrets.CODECOV_TOKEN }}
        report_type: coverage
        env_vars: OS,python
        files: coverage.xml

  vm_tests:
    permissions:
      contents: read
      id-token: write
      attestations: write
    runs-on: ubuntu-24.04
    timeout-minutes: 180
    needs: [lint]
    continue-on-error: true

    strategy:
      fail-fast: false
      matrix:
        include:
          - os: freebsd
            version: '14.3'
            display_name: FreeBSD
            # Controls binary build and provenance attestation on tags
            do_binaries: true
            artifact_prefix: borg-freebsd-14-x86_64-gh

          - os: netbsd
            version: '10.1'
            display_name: NetBSD
            do_binaries: false

          - os: openbsd
            version: '7.8'
            display_name: OpenBSD
            do_binaries: false

          - os: omnios
            version: 'r151056'
            display_name: OmniOS
            do_binaries: false

          - os: haiku
            version: 'r1beta5'
            display_name: Haiku
            do_binaries: false

    steps:
      - name: Check out repository
        uses: actions/checkout@v6
        with:
          fetch-depth: 0
          fetch-tags: true

      - name: Test on ${{ matrix.display_name }}
        id: cross_os
        uses: cross-platform-actions/action@v0.32.0
        env:
          DO_BINARIES: ${{ matrix.do_binaries }}
        with:
          operating_system: ${{ matrix.os }}
          version: ${{ matrix.version }}
          shell: bash
          run: |
            set -euxo pipefail

            case "${{ matrix.os }}" in
              freebsd)
                export IGNORE_OSVERSION=yes
                sudo -E pkg update -f
                sudo -E pkg install -y liblz4 pkgconf
                sudo -E pkg install -y fusefs-libs
                sudo -E kldload fusefs
                sudo -E sysctl vfs.usermount=1
                sudo -E chmod 666 /dev/fuse
                sudo -E pkg install -y rust
                sudo -E pkg install -y gmake
                sudo -E pkg install -y git
                sudo -E pkg install -y python310 py310-sqlite3
                sudo -E pkg install -y python311 py311-sqlite3 py311-pip py311-virtualenv
                sudo ln -sf /usr/local/bin/python3.11 /usr/local/bin/python3
                sudo ln -sf /usr/local/bin/python3.11 /usr/local/bin/python
                sudo ln -sf /usr/local/bin/pip3.11 /usr/local/bin/pip3
                sudo ln -sf /usr/local/bin/pip3.11 /usr/local/bin/pip

                # required for libsodium/pynacl build
                export MAKE=gmake

                python -m venv .venv
                . .venv/bin/activate
                python -V
                pip -V
                python -m pip install --upgrade pip wheel
                pip install -r requirements.d/development.lock.txt
                pip install -e ".[mfusepy,cockpit,s3,sftp,rest,rclone]"
                tox -e py311-mfusepy

                if [[ "${{ matrix.do_binaries }}" == "true" && "${{ startsWith(github.ref, 'refs/tags/') }}" == "true" ]]; then
                  python -m pip install -r requirements.d/pyinstaller.txt
                  mkdir -p dist/binary
                  pyinstaller --clean --distpath=dist/binary scripts/borg.exe.spec
                  pushd dist/binary
                  echo "single-file binary"
                  chmod +x borg.exe
                  ./borg.exe -V
                  echo "single-directory binary"
                  chmod +x borg-dir/borg.exe
                  ./borg-dir/borg.exe -V
                  tar czf borg.tgz borg-dir
                  popd
                  mkdir -p artifacts
                  if [ -f dist/binary/borg.exe ]; then
                    cp -v dist/binary/borg.exe artifacts/${{ matrix.artifact_prefix }}
                  fi
                  if [ -f dist/binary/borg.tgz ]; then
                    cp -v dist/binary/borg.tgz artifacts/${{ matrix.artifact_prefix }}.tgz
                  fi
                fi
                ;;

              netbsd)
                arch="$(uname -m)"
                sudo -E mkdir -p /usr/pkg/etc/pkgin
                echo "https://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/${arch}/10.1/All" | sudo tee /usr/pkg/etc/pkgin/repositories.conf > /dev/null
                sudo -E pkgin update
                sudo -E pkgin -y upgrade
                sudo -E pkgin -y install lz4 git
                sudo -E pkgin -y install rust
                sudo -E pkgin -y install pkg-config
                sudo -E pkgin -y install py311-pip py311-virtualenv py311-tox
                sudo -E ln -sf /usr/pkg/bin/python3.11 /usr/pkg/bin/python3
                sudo -E ln -sf /usr/pkg/bin/pip3.11 /usr/pkg/bin/pip3
                sudo -E ln -sf /usr/pkg/bin/virtualenv-3.11 /usr/pkg/bin/virtualenv3
                sudo -E ln -sf /usr/pkg/bin/tox-3.11 /usr/pkg/bin/tox3

                # Ensure base system admin tools are on PATH for the non-root shell
                export PATH="/sbin:/usr/sbin:$PATH"

                echo "--- Preparing an extattr-enabled filesystem ---"
                # On many NetBSD setups /tmp is tmpfs without extended attributes.
                # Create a FFS image with extended attributes enabled and use it for TMPDIR.
                VNDDEV="vnd0"
                IMGFILE="/tmp/fs.img"
                sudo -E dd if=/dev/zero of=${IMGFILE} bs=1m count=1024
                sudo -E vndconfig -c "${VNDDEV}" "${IMGFILE}"
                sudo -E newfs -O 2ea /dev/r${VNDDEV}a
                MNT="/mnt/eafs"
                sudo -E mkdir -p ${MNT}
                sudo -E mount -t ffs -o extattr /dev/${VNDDEV}a $MNT
                export TMPDIR="${MNT}/tmp"
                sudo -E mkdir -p ${TMPDIR}
                sudo -E chmod 1777 ${TMPDIR}

                touch ${TMPDIR}/testfile
                lsextattr user ${TMPDIR}/testfile && echo "[xattr] *** xattrs SUPPORTED on ${TMPDIR}! ***"

                tox3 -e py311-none
                ;;

              openbsd)
                sudo -E pkg_add lz4 git
                sudo -E pkg_add rust
                sudo -E pkg_add openssl%3.5
                sudo -E pkg_add py3-pip py3-virtualenv py3-tox

                export BORG_OPENSSL_NAME=eopenssl35
                tox -e py312-none
                ;;

              omnios)
                sudo pkg install gcc14 git pkg-config python-313 gnu-make gnu-coreutils
                sudo ln -sf /usr/bin/python3.13 /usr/bin/python3
                sudo ln -sf /usr/bin/python3.13-config /usr/bin/python3-config
                sudo python3 -m ensurepip
                sudo python3 -m pip install virtualenv

                python3 -m venv .venv
                . .venv/bin/activate
                python -V
                pip -V
                python -m pip install --upgrade pip wheel
                pip install -r requirements.d/development.lock.txt
                # no fuse support on omnios in our tests usually
                pip install -e .

                tox -e py313-none
                ;;

              haiku)
                pkgman refresh
                pkgman install -y git pkgconfig lz4
                pkgman install -y openssl3
                pkgman install -y rust_bin
                pkgman install -y python3.10
                pkgman install -y cffi
                pkgman install -y lz4_devel openssl3_devel libffi_devel

                # there is no pkgman package for tox, so we install it into a venv
                python3 -m ensurepip --upgrade
                python3 -m pip install --upgrade pip wheel
                python3 -m venv .venv
                . .venv/bin/activate

                export PKG_CONFIG_PATH="/system/develop/lib/pkgconfig:/system/lib/pkgconfig:${PKG_CONFIG_PATH:-}"
                export BORG_LIBLZ4_PREFIX=/system/develop
                export BORG_OPENSSL_PREFIX=/system/develop
                pip install -r requirements.d/development.lock.txt
                pip install -e .

                # troubles with either tox or pytest xdist, so we run pytest manually:
                pytest -v -n auto -rs --cov=borg --cov-config=pyproject.toml --cov-report=xml --junitxml=test-results.xml --benchmark-skip -k "not remote and not socket"
                ;;
            esac

      - name: Upload artifacts
        if: startsWith(github.ref, 'refs/tags/') && matrix.do_binaries
        uses: actions/upload-artifact@v7
        with:
          name: ${{ matrix.artifact_prefix }}
          path: artifacts/*
          if-no-files-found: ignore

      - name: Attest provenance
        if: startsWith(github.ref, 'refs/tags/') && matrix.do_binaries
        uses: actions/attest-build-provenance@v4
        with:
          subject-path: 'artifacts/*'

      - name: Upload test results to Codecov
        if: ${{ !cancelled() }}
        uses: codecov/codecov-action@v5
        env:
          OS: ${{ matrix.os }}
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          report_type: test_results
          env_vars: OS
          files: test-results.xml

      - name: Upload coverage to Codecov
        if: ${{ !cancelled() }}
        uses: codecov/codecov-action@v5
        env:
          OS: ${{ matrix.os }}
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          report_type: coverage
          env_vars: OS
          files: coverage.xml

  windows_tests:

    if: true  # can be used to temporarily disable the build
    runs-on: windows-latest
    timeout-minutes: 90
    needs: [lint]

    env:
      PY_COLORS: 1
      MSYS2_ARG_CONV_EXCL: "*"
      MSYS2_ENV_CONV_EXCL: "*"

    defaults:
      run:
        shell: msys2 {0}

    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - uses: msys2/setup-msys2@v2
        with:
          msystem: UCRT64
          update: true

      - name: Install system packages
        run: ./scripts/msys2-install-deps development

      - name: Build python venv
        run: |
          # building cffi / argon2-cffi in the venv fails, so we try to use the system packages
          python -m venv --system-site-packages env
          . env/bin/activate
          # python -m pip install --upgrade pip
          # pip install --upgrade setuptools build wheel
          pip install -r requirements.d/pyinstaller.txt

      - name: Build
        run: |
          # build borg.exe
          . env/bin/activate
          pip install -e ".[cockpit,s3,sftp,rest,rclone]"
          mkdir -p dist/binary
          pyinstaller -y --clean --distpath=dist/binary scripts/borg.exe.spec
          # build sdist and wheel in dist/...
          python -m build

      - uses: actions/upload-artifact@v7
        with:
          name: borg-windows
          path: dist/binary/borg.exe

      - name: Run tests
        run: |
          # Ensure locally built binary in ./dist/binary/borg-dir is found during tests
          export PATH="$GITHUB_WORKSPACE/dist/binary/borg-dir:$PATH"
          borg.exe -V
          . env/bin/activate
          python -m pytest -n4 --benchmark-skip -vv -rs -k "not remote" --cov=borg --cov-config=pyproject.toml --cov-report=xml --junitxml=test-results.xml

      - name: Upload test results to Codecov
        if: ${{ !cancelled() }}
        uses: codecov/codecov-action@v5
        env:
          OS: ${{ runner.os }}
          python: '3.11'
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          report_type: test_results
          env_vars: OS,python
          files: test-results.xml

      - name: Upload coverage to Codecov
        if: ${{ !cancelled() }}
        uses: codecov/codecov-action@v5
        env:
          OS: ${{ runner.os }}
          python: '3.11'
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          report_type: coverage
          env_vars: OS,python
          files: coverage.xml


================================================
FILE: .github/workflows/codeql-analysis.yml
================================================
# CodeQL semantic code analysis engine

name: "CodeQL"

on:
  push:
    branches: [ master ]
    paths:
      - '**.py'
      - '**.pyx'
      - '**.c'
      - '**.h'
      - '.github/workflows/codeql-analysis.yml'
  pull_request:
    # The branches below must be a subset of the branches above
    branches: [ master ]
    paths:
      - '**.py'
      - '**.pyx'
      - '**.c'
      - '**.h'
      - '.github/workflows/codeql-analysis.yml'
  schedule:
    - cron: '39 2 * * 5'

concurrency:
  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
  analyze:
    name: Analyze
    runs-on: ubuntu-24.04
    timeout-minutes: 20
    permissions:
      actions: read
      contents: read
      security-events: write

    strategy:
      fail-fast: false
      matrix:
        language: [ 'cpp', 'python' ]
        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
        # Learn more about CodeQL language support at https://codeql.github.com/docs/codeql-overview/supported-languages-and-frameworks/

    steps:
    - name: Checkout repository
      uses: actions/checkout@v6
      with:
        # Just fetching one commit is not enough for setuptools-scm, so we fetch all.
        fetch-depth: 0
    - name: Set up Python
      uses: actions/setup-python@v6
      with:
        python-version: 3.11
    - name: Cache pip
      uses: actions/cache@v5
      with:
        path: ~/.cache/pip
        key: ${{ runner.os }}-pip-${{ hashFiles('requirements.d/development.txt') }}
        restore-keys: |
            ${{ runner.os }}-pip-
            ${{ runner.os }}-
    - name: Install requirements
      run: |
        sudo apt-get update
        sudo apt-get install -y pkg-config build-essential
        sudo apt-get install -y libssl-dev libacl1-dev liblz4-dev
    # Initializes the CodeQL tools for scanning.
    - name: Initialize CodeQL
      uses: github/codeql-action/init@v4
      with:
        languages: ${{ matrix.language }}
        # If you wish to specify custom queries, you can do so here or in a config file.
        # By default, queries listed here will override any specified in a config file.
        # Prefix the list here with "+" to use these queries and those in the config file.
        # queries: ./path/to/local/query, your-org/your-repo/queries@main
    - name: Build and install Borg
      run: |
        python3 -m venv ../borg-env
        source ../borg-env/bin/activate
        pip3 install -r requirements.d/development.txt
        pip3 install -ve .
    - name: Perform CodeQL Analysis
      uses: github/codeql-action/analyze@v4


================================================
FILE: .gitignore
================================================
MANIFEST
docs/_build
build
dist
.tox
src/borg/compress.c
src/borg/hashindex.c
src/borg/crypto/low_level.c
src/borg/item.c
src/borg/chunkers/buzhash.c
src/borg/chunkers/buzhash64.c
src/borg/chunkers/reader.c
src/borg/checksums.c
src/borg/platform/darwin.c
src/borg/platform/freebsd.c
src/borg/platform/netbsd.c
src/borg/platform/linux.c
src/borg/platform/syncfilerange.c
src/borg/platform/posix.c
src/borg/platform/windows.c
src/borg/_version.py
*.egg-info
*.pyc
*.pyd
*.so
.idea/
.junie/
.vscode/
borg.exe
.coverage
.coverage.*
coverage.xml
test-results.xml
.vagrant
.DS_Store


================================================
FILE: .mailmap
================================================
Abdel-Rahman <abodyxplay1@gmail.com>
Brian Johnson <brian@sherbang.com>
Carlo Teubner <carlo.teubner@gmail.com>
Mark Edgington <edgimar@gmail.com>
Leo Famulari <leo@famulari.name>
Marian Beermann <public@enkore.de>
Thomas Waldmann <tw@waldmann-edv.de>
Dan Christensen <jdc@uwo.ca> <jdc+github@uwo.ca>
Antoine Beaupré <anarcat@koumbit.org> <anarcat@debian.org> <anarcat@users.noreply.github.com>
Hartmut Goebel <h.goebel@crazy-compilers.com> <htgoebel@users.noreply.github.com>
Michael Gajda <michaelg@speciesm.net> <michael.gajda@tu-dortmund.de>
Milkey Mouse <milkeymouse@meme.institute> <milkey-mouse@users.noreply.github.com>
Ronny Pfannschmidt <opensource@ronnypfannschmidt.de> <ronny.pfannschmidt@redhat.com>
Stefan Tatschner <rumpelsepp@sevenbyte.org> <stefan@sevenbyte.org>


================================================
FILE: .pre-commit-config.yaml
================================================
repos:
-   repo: https://github.com/psf/black
    rev: 24.8.0
    hooks:
    -   id: black
- repo: https://github.com/astral-sh/ruff-pre-commit
  rev: v0.15.0
  hooks:
    - id: ruff


================================================
FILE: .readthedocs.yaml
================================================
# .readthedocs.yaml - Read the Docs configuration file.
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details.

version: 2

build:
    os: ubuntu-22.04
    tools:
        python: "3.11"
    jobs:
        post_checkout:
            - git fetch --unshallow
    apt_packages:
        - build-essential
        - pkg-config
        - libacl1-dev
        - libssl-dev
        - liblz4-dev

python:
    install:
        - requirements: requirements.d/development.lock.txt
        - requirements: requirements.d/docs.txt
        - method: pip
          path: .

sphinx:
    configuration: docs/conf.py

formats:
    - htmlzip


================================================
FILE: AUTHORS
================================================
Email addresses listed here are not intended for support.
Please see the `support section`_ instead.

.. _support section: https://borgbackup.readthedocs.io/en/stable/support.html

Borg authors ("The Borg Collective")
------------------------------------

- Thomas Waldmann <tw@waldmann-edv.de>
- Radek Podgorny <radek@podgorny.cz>
- Yuri D'Elia
- Michael Hanselmann <public@hansmi.ch>
- Teemu Toivanen <public@profnetti.fi>
- Marian Beermann <public@enkore.de>
- Martin Hostettler <textshell@uchuujin.de>
- Daniel Reichelt <hacking@nachtgeist.net>
- Lauri Niskanen <ape@ape3000.com>
- Abdel-Rahman A. (Abogical)
- Gu1nness <guinness@crans.org>
- Andrey Andreyevich Bienkowski <hexagon-recursion@posteo.net>

Retired
```````

- Antoine Beaupré <anarcat@debian.org>

Borg is a fork of Attic.

Attic authors
-------------

Attic is written and maintained by Jonas Borgström and various contributors:

Attic Development Lead
``````````````````````
- Jonas Borgström <jonas@borgstrom.se>

Attic Patches and Suggestions
`````````````````````````````
- Brian Johnson
- Cyril Roussillon
- Dan Christensen
- Jeremy Maitin-Shepard
- Johann Klähn
- Petros Moisiadis
- Thomas Waldmann


================================================
FILE: Brewfile
================================================
brew 'pkgconf'
brew 'lz4'
brew 'openssl@3'

# osxfuse (aka macFUSE) is only required for "borg mount",
# but won't work on GitHub Actions' workers.
# It requires installing a kernel extension, so some users
# may want it and some won't.

#cask 'osxfuse'


================================================
FILE: LICENSE
================================================
Copyright (C) 2015-2025 The Borg Collective (see AUTHORS file)
Copyright (C) 2010-2014 Jonas Borgström <jonas@borgstrom.se>
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

 1. Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
 2. Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in
    the documentation and/or other materials provided with the
    distribution.
 3. The name of the author may not be used to endorse or promote
    products derived from this software without specific prior
    written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


================================================
FILE: MANIFEST.in
================================================
# The files we need to include in the sdist are handled automatically by
# setuptools_scm - it includes all git-committed files.
# But we want to exclude some committed files/directories not needed in the sdist:
exclude .editorconfig .gitattributes .gitignore .mailmap Vagrantfile
prune .github
include src/borg/platform/darwin.c src/borg/platform/freebsd.c src/borg/platform/linux.c src/borg/platform/posix.c
include src/borg/platform/syncfilerange.c
include src/borg/platform/windows.c


================================================
FILE: README.rst
================================================
This is borg2!
--------------

Please note that this is the README for borg2 / master branch.

For the stable version's docs, please see here:

https://borgbackup.readthedocs.io/en/stable/

Borg2 is currently in beta testing and might get major and/or
breaking changes between beta releases (and there is no beta to
next-beta upgrade code, so you will have to delete and re-create repos).

Thus, **DO NOT USE BORG2 FOR YOUR PRODUCTION BACKUPS!** Please help with
testing it, but set it up *additionally* to your production backups.

TODO: the screencasts need a remake using borg2, see here:

https://github.com/borgbackup/borg/issues/6303


What is BorgBackup?
-------------------

BorgBackup (short: Borg) is a deduplicating backup program.
Optionally, it supports compression and authenticated encryption.

The main goal of Borg is to provide an efficient and secure way to back up data.
The data deduplication technique used makes Borg suitable for daily backups
since only changes are stored.
The authenticated encryption technique makes it suitable for backups to targets not
fully trusted.

See the `installation manual`_ or, if you have already
downloaded Borg, ``docs/installation.rst`` to get started with Borg.
There is also an `offline documentation`_ available, in multiple formats.

.. _installation manual: https://borgbackup.readthedocs.io/en/master/installation.html
.. _offline documentation: https://readthedocs.org/projects/borgbackup/downloads

Main features
~~~~~~~~~~~~~

**Space efficient storage**
  Deduplication based on content-defined chunking is used to reduce the number
  of bytes stored: each file is split into a number of variable length chunks
  and only chunks that have never been seen before are added to the repository.

  A chunk is considered duplicate if its id_hash value is identical.
  A cryptographically strong hash or MAC function is used as id_hash, e.g.
  (hmac-)sha256.

  To deduplicate, all the chunks in the same repository are considered, no
  matter whether they come from different machines, from previous backups,
  from the same backup or even from the same single file.

  Compared to other deduplication approaches, this method does NOT depend on:

  * file/directory names staying the same: So you can move your stuff around
    without killing the deduplication, even between machines sharing a repo.

  * complete files or time stamps staying the same: If a big file changes a
    little, only a few new chunks need to be stored - this is great for VMs or
    raw disks.

  * The absolute position of a data chunk inside a file: Stuff may get shifted
    and will still be found by the deduplication algorithm.

**Speed**
  * performance-critical code (chunking, compression, encryption) is
    implemented in C/Cython
  * local caching
  * quick detection of unmodified files

**Data encryption**
    All data can be protected client-side using 256-bit authenticated encryption
    (AES-OCB or chacha20-poly1305), ensuring data confidentiality, integrity and
    authenticity.

**Obfuscation**
    Optionally, Borg can actively obfuscate, e.g., the size of files/chunks to
    make fingerprinting attacks more difficult.

**Compression**
    All data can be optionally compressed:

    * lz4 (super fast, low compression)
    * zstd (wide range from high speed and low compression to high compression
      and lower speed)
    * zlib (medium speed and compression)
    * lzma (low speed, high compression)

**Off-site backups**
    Borg can store data on any remote host accessible over SSH. If Borg is
    installed on the remote host, significant performance gains can be achieved
    compared to using a network file system (sshfs, NFS, ...).

**Backups mountable as file systems**
    Backup archives are mountable as user-space file systems for easy interactive
    backup examination and restores (e.g., by using a regular file manager).

**Easy installation on multiple platforms**
    We offer single-file binaries that do not require installing anything -
    you can just run them on these platforms:

    * Linux
    * macOS
    * FreeBSD
    * OpenBSD and NetBSD (no xattrs/ACLs support or binaries yet)
    * Cygwin (experimental, no binaries yet)
    * Windows Subsystem for Linux (WSL) on Windows 10/11 (experimental)

**Free and Open Source Software**
  * security and functionality can be audited independently
  * licensed under the BSD (3-clause) license, see `License`_ for the
    complete license

Easy to use
~~~~~~~~~~~

For ease of use, set the BORG_REPO environment variable::

    $ export BORG_REPO=/path/to/repo

Create a new backup repository (see ``borg repo-create --help`` for encryption options)::

    $ borg repo-create -e repokey-aes-ocb

Create a new backup archive::

    $ borg create Monday1 ~/Documents

Now do another backup, just to show off the great deduplication::

    $ borg create -v --stats Monday2 ~/Documents
    Repository: /path/to/repo
    Archive name: Monday2
    Archive fingerprint: 7714aef97c1a24539cc3dc73f79b060f14af04e2541da33d54c7ee8e81a00089
    Time (start): Mon, 2022-10-03 19:57:35 +0200
    Time (end):   Mon, 2022-10-03 19:57:35 +0200
    Duration: 0.01 seconds
    Number of files: 24
    Original size: 29.73 MB
    Deduplicated size: 520 B


Helping, donations and bounties, becoming a Patron
--------------------------------------------------

Your help is always welcome!

Spread the word, give feedback, help with documentation, testing or development.

You can also give monetary support to the project, see here for details:

https://www.borgbackup.org/support/fund.html

Links
-----

* `Main website <https://borgbackup.readthedocs.io/>`_
* `Releases <https://github.com/borgbackup/borg/releases>`_,
  `PyPI packages <https://pypi.org/project/borgbackup/>`_ and
  `Changelog <https://github.com/borgbackup/borg/blob/master/docs/changes.rst>`_
* `Offline documentation <https://readthedocs.org/projects/borgbackup/downloads>`_
* `GitHub <https://github.com/borgbackup/borg>`_ and
  `Issue tracker <https://github.com/borgbackup/borg/issues>`_.
* `Web chat (IRC) <https://web.libera.chat/#borgbackup>`_ and
  `Mailing list <https://mail.python.org/mailman/listinfo/borgbackup>`_
* `License <https://borgbackup.readthedocs.io/en/master/authors.html#license>`_
* `Security contact <https://borgbackup.readthedocs.io/en/master/support.html#security-contact>`_

Compatibility notes
-------------------

EXPECT THAT WE WILL BREAK COMPATIBILITY REPEATEDLY WHEN MAJOR RELEASE NUMBER
CHANGES (like when going from 0.x.y to 1.0.0 or from 1.x.y to 2.0.0).

NOT RELEASED DEVELOPMENT VERSIONS HAVE UNKNOWN COMPATIBILITY PROPERTIES.

THIS IS SOFTWARE IN DEVELOPMENT, DECIDE FOR YOURSELF WHETHER IT FITS YOUR NEEDS.

Security issues should be reported to the `Security contact`_ (or
see ``docs/support.rst`` in the source distribution).

.. start-badges

|doc| |build| |coverage| |bestpractices|

.. |doc| image:: https://readthedocs.org/projects/borgbackup/badge/?version=master
        :alt: Documentation
        :target: https://borgbackup.readthedocs.io/en/master/

.. |build| image:: https://github.com/borgbackup/borg/workflows/CI/badge.svg?branch=master
        :alt: Build Status (master)
        :target: https://github.com/borgbackup/borg/actions

.. |coverage| image:: https://codecov.io/github/borgbackup/borg/coverage.svg?branch=master
        :alt: Test Coverage
        :target: https://codecov.io/github/borgbackup/borg?branch=master

.. |screencast_basic| image:: https://asciinema.org/a/133292.png
        :alt: BorgBackup Basic Usage
        :target: https://asciinema.org/a/133292?autoplay=1&speed=1
        :width: 100%

.. _installation: https://asciinema.org/a/133291?autoplay=1&speed=1

.. _advanced usage: https://asciinema.org/a/133293?autoplay=1&speed=1

.. |bestpractices| image:: https://bestpractices.coreinfrastructure.org/projects/271/badge
        :alt: Best Practices Score
        :target: https://bestpractices.coreinfrastructure.org/projects/271

.. end-badges


================================================
FILE: SECURITY.md
================================================
# Security Policy

## Supported Versions

These Borg releases are currently supported with security updates.

| Version | Supported          |
|---------|--------------------|
| 2.0.x   | :x: (beta)         |
| 1.4.x   | :white_check_mark: |
| 1.2.x   | :x: (no new releases, critical fixes may still be backported) |
| 1.1.x   | :x:                |
| < 1.1   | :x:                |

## Reporting a Vulnerability

See here:

https://borgbackup.readthedocs.io/en/latest/support.html#security-contact


================================================
FILE: Vagrantfile
================================================
# -*- mode: ruby -*-
# vi: set ft=ruby :

# Automated creation of testing environments/binaries on miscellaneous platforms

$cpus = Integer(ENV.fetch('VMCPUS', '8'))  # create VMs with that many cpus
$xdistn = Integer(ENV.fetch('XDISTN', '8'))  # dispatch tests to that many pytest workers
$wmem = $xdistn * 256  # give the VM additional memory for workers [MB]

def packages_debianoid(user)
  return <<-EOF
    export DEBIAN_FRONTEND=noninteractive
    # this is to avoid grub asking about which device it should install to:
    echo "set grub-pc/install_devices /dev/sda" | debconf-communicate
    apt-get -y -qq update
    apt-get -y -qq dist-upgrade
    # for building borgbackup and dependencies:
    apt install -y pkg-config
    apt install -y libssl-dev libacl1-dev liblz4-dev || true
    apt install -y libfuse-dev fuse || true
    apt install -y libfuse3-dev fuse3 || true
    apt install -y locales || true
    sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen
    usermod -a -G fuse #{user}
    chgrp fuse /dev/fuse
    chmod 666 /dev/fuse
    apt install -y fakeroot build-essential git curl
    apt install -y python3-dev python3-setuptools virtualenv
    # for building python:
    apt install -y zlib1g-dev libbz2-dev libncurses5-dev libreadline-dev liblzma-dev libsqlite3-dev libffi-dev
  EOF
end

def packages_freebsd
  return <<-EOF
    # in case the VM has no hostname set
    hostname freebsd
    # install all the (security and other) updates, base system
    freebsd-update --not-running-from-cron fetch install
    # for building borgbackup and dependencies:
    pkg install -y liblz4 pkgconf
    pkg install -y fusefs-libs || true
    pkg install -y fusefs-libs3 || true
    pkg install -y rust
    pkg install -y git bash  # fakeroot causes lots of troubles on freebsd
    pkg install -y python310 py310-sqlite3
    pkg install -y python311 py311-sqlite3 py311-pip py311-virtualenv
    # make sure there is a python3/pip3/virtualenv command
    ln -sf /usr/local/bin/python3.11 /usr/local/bin/python3
    ln -sf /usr/local/bin/pip-3.11 /usr/local/bin/pip3
    ln -sf /usr/local/bin/virtualenv-3.11 /usr/local/bin/virtualenv
    # make bash default / work:
    chsh -s bash vagrant
    mount -t fdescfs fdesc /dev/fd
    echo 'fdesc        /dev/fd         fdescfs         rw      0       0' >> /etc/fstab
    # make FUSE work
    echo 'fuse_load="YES"' >> /boot/loader.conf
    echo 'vfs.usermount=1' >> /etc/sysctl.conf
    kldload fusefs
    sysctl vfs.usermount=1
    pw groupmod operator -M vagrant
    # /dev/fuse has group operator
    chmod 666 /dev/fuse
    # install all the (security and other) updates, packages
    pkg update
    yes | pkg upgrade
    echo 'export BORG_OPENSSL_PREFIX=/usr' >> ~vagrant/.bash_profile
    # (re)mount / with acls
    mount -o acls /
  EOF
end

def packages_openbsd
  return <<-EOF
    hostname "openbsd77.localdomain"
    echo "$(hostname)" > /etc/myname
    echo "127.0.0.1	localhost" > /etc/hosts
    echo "::1 localhost" >> /etc/hosts
    echo "127.0.0.1	$(hostname) $(hostname -s)" >> /etc/hosts
    echo "https://ftp.eu.openbsd.org/pub/OpenBSD" > /etc/installurl
    ftp https://cdn.openbsd.org/pub/OpenBSD/$(uname -r)/$(uname -m)/comp$(uname -r | tr -d .).tgz
    tar -C / -xzphf comp$(uname -r | tr -d .).tgz
    rm comp$(uname -r | tr -d .).tgz
    pkg_add bash
    chsh -s bash vagrant
    pkg_add lz4
    pkg_add git  # no fakeroot
    pkg_add rust
    pkg_add openssl%3.4
    pkg_add py3-pip
    pkg_add py3-virtualenv
    echo 'export BORG_OPENSSL_NAME=eopenssl30' >> ~vagrant/.bash_profile
  EOF
end

def packages_netbsd
  return <<-EOF
    echo 'https://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/$arch/9.3/All' > /usr/pkg/etc/pkgin/repositories.conf
    pkgin update
    pkgin -y upgrade
    pkg_add lz4 git
    pkg_add rust
    pkg_add bash
    chsh -s bash vagrant
    echo "export PROMPT_COMMAND=" >> ~vagrant/.bash_profile  # bug in netbsd 9.3, .bash_profile broken for screen
    echo "export PROMPT_COMMAND=" >> ~root/.bash_profile  # bug in netbsd 9.3, .bash_profile broken for screen
    pkg_add pkg-config
    # pkg_add fuse  # llfuse supports netbsd, but is still buggy.
    # https://bitbucket.org/nikratio/python-llfuse/issues/70/perfuse_open-setsockopt-no-buffer-space
    pkg_add py311-sqlite3 py311-pip py311-virtualenv py311-expat
    ln -s /usr/pkg/bin/python3.11 /usr/pkg/bin/python
    ln -s /usr/pkg/bin/python3.11 /usr/pkg/bin/python3
    ln -s /usr/pkg/bin/pip3.11 /usr/pkg/bin/pip
    ln -s /usr/pkg/bin/pip3.11 /usr/pkg/bin/pip3
    ln -s /usr/pkg/bin/virtualenv-3.11 /usr/pkg/bin/virtualenv
    ln -s /usr/pkg/bin/virtualenv-3.11 /usr/pkg/bin/virtualenv3
  EOF
end

def package_update_openindiana
  return <<-EOF
    echo "nameserver 1.1.1.1" > /etc/resolv.conf
    # needs separate provisioning step + reboot to become effective:
    pkg update
  EOF
end

def packages_openindiana
  return <<-EOF
    pkg install gcc-13 git
    pkg install pkg-config
    pkg install python-313
    ln -sf /usr/bin/python3.13 /usr/bin/python3
    ln -sf /usr/bin/python3.13-config /usr/bin/python3-config
    python3 -m ensurepip
    ln -sf /usr/bin/pip3.13 /usr/bin/pip3
    pip3 install virtualenv
    # let borg's pkg-config find openssl:
    pfexec pkg set-mediator -V 3 openssl
  EOF
end

def install_pyenv(boxname)
  return <<-EOF
    echo 'export PYTHON_CONFIGURE_OPTS="${PYTHON_CONFIGURE_OPTS} --enable-shared"' >> ~/.bash_profile
    echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
    echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
    . ~/.bash_profile
    curl -s -L https://raw.githubusercontent.com/yyuu/pyenv-installer/master/bin/pyenv-installer | bash
    echo 'eval "$(pyenv init --path)"' >> ~/.bash_profile
    echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
    echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
    echo 'eval "$(pyenv init -)"' >> ~/.bashrc
    echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bashrc
  EOF
end

def install_pythons(boxname)
  return <<-EOF
    . ~/.bash_profile
    echo "PYTHON_CONFIGURE_OPTS: ${PYTHON_CONFIGURE_OPTS}"
    pyenv install 3.13.8
    pyenv rehash
  EOF
end

def build_sys_venv(boxname)
  return <<-EOF
    . ~/.bash_profile
    cd /vagrant/borg
    virtualenv --python=python3 borg-env
  EOF
end

def build_pyenv_venv(boxname)
  return <<-EOF
    . ~/.bash_profile
    cd /vagrant/borg
    # use the latest 3.13 release
    pyenv global 3.13.8
    pyenv virtualenv 3.13.8 borg-env
    ln -s ~/.pyenv/versions/borg-env .
  EOF
end

def install_borg(fuse)
  return <<-EOF
    . ~/.bash_profile
    cd /vagrant/borg
    . borg-env/bin/activate
    pip install -U wheel  # upgrade wheel, might be too old
    cd borg
    pip install -r requirements.d/development.lock.txt
    python3 scripts/make.py clean
    # install borgstore WITH all options, so it pulls in the needed
    # requirements, so they will also get into the binaries built. #8574
    pip install borgstore[sftp,s3]
    pip install -e .[#{fuse}]
  EOF
end

def install_pyinstaller()
  return <<-EOF
    . ~/.bash_profile
    cd /vagrant/borg
    . borg-env/bin/activate
    pip install -r requirements.d/pyinstaller.txt
  EOF
end

def build_binary_with_pyinstaller(boxname)
  return <<-EOF
    . ~/.bash_profile
    cd /vagrant/borg
    . borg-env/bin/activate
    cd borg
    pyinstaller --clean --distpath=/vagrant/borg scripts/borg.exe.spec
    echo 'export PATH="/vagrant/borg:$PATH"' >> ~/.bash_profile
    cd .. && tar -czvf borg.tgz borg-dir
  EOF
end

def run_tests(boxname, skip_env)
  return <<-EOF
    . ~/.bash_profile
    cd /vagrant/borg/borg
    . ../borg-env/bin/activate
    if which pyenv 2> /dev/null; then
      # for testing, use the earliest point releases of the supported python versions:
      pyenv global 3.13.8
      pyenv local 3.13.8
    fi
    # otherwise: just use the system python
    # some OSes can only run specific test envs, e.g. because they miss FUSE support:
    export TOX_SKIP_ENV='#{skip_env}'
    if which fakeroot 2> /dev/null; then
      echo "Running tox WITH fakeroot -u"
      fakeroot -u tox --skip-missing-interpreters
    else
      echo "Running tox WITHOUT fakeroot -u"
      tox --skip-missing-interpreters
    fi
  EOF
end

def fs_init(user)
  return <<-EOF
    # clean up (wrong/outdated) stuff we likely got via rsync:
    rm -rf /vagrant/borg/borg/.tox 2> /dev/null
    rm -rf /vagrant/borg/borg/borgbackup.egg-info 2> /dev/null
    rm -rf /vagrant/borg/borg/__pycache__ 2> /dev/null
    find /vagrant/borg/borg/src -name '__pycache__' -exec rm -rf {} \\; 2> /dev/null
    chown -R #{user} /vagrant/borg
    touch ~#{user}/.bash_profile ; chown #{user} ~#{user}/.bash_profile
    echo 'export LANG=en_US.UTF-8' >> ~#{user}/.bash_profile
    echo 'export LC_CTYPE=en_US.UTF-8' >> ~#{user}/.bash_profile
    echo 'export XDISTN=#{$xdistn}' >> ~#{user}/.bash_profile
  EOF
end

Vagrant.configure(2) do |config|
  # use rsync to copy content to the folder
  config.vm.synced_folder ".", "/vagrant/borg/borg", :type => "rsync", :rsync__args => ["--verbose", "--archive", "--delete", "--exclude", ".python-version"], :rsync__chown => false
  # do not let the VM access . on the host machine via the default shared folder!
  config.vm.synced_folder ".", "/vagrant", disabled: true

  config.vm.provider :virtualbox do |v|
    #v.gui = true
    v.cpus = $cpus
  end

  config.vm.define "noble" do |b|
    b.vm.box = "bento/ubuntu-24.04"
    b.vm.provider :virtualbox do |v|
      v.memory = 1024 + $wmem
    end
    b.vm.provision "fs init", :type => :shell, :inline => fs_init("vagrant")
    b.vm.provision "packages debianoid", :type => :shell, :inline => packages_debianoid("vagrant")
    b.vm.provision "build env", :type => :shell, :privileged => false, :inline => build_sys_venv("noble")
    b.vm.provision "install borg", :type => :shell, :privileged => false, :inline => install_borg("llfuse")
    b.vm.provision "run tests", :type => :shell, :privileged => false, :inline => run_tests("noble", ".*none.*")
  end

  config.vm.define "jammy" do |b|
    b.vm.box = "ubuntu/jammy64"
    b.vm.provider :virtualbox do |v|
      v.memory = 1024 + $wmem
    end
    b.vm.provision "fs init", :type => :shell, :inline => fs_init("vagrant")
    b.vm.provision "packages debianoid", :type => :shell, :inline => packages_debianoid("vagrant")
    b.vm.provision "build env", :type => :shell, :privileged => false, :inline => build_sys_venv("jammy")
    b.vm.provision "install borg", :type => :shell, :privileged => false, :inline => install_borg("llfuse")
    b.vm.provision "run tests", :type => :shell, :privileged => false, :inline => run_tests("jammy", ".*none.*")
  end

  config.vm.define "trixie" do |b|
    b.vm.box = "debian/testing64"
    b.vm.provider :virtualbox do |v|
      v.memory = 1024 + $wmem
    end
    b.vm.provision "fs init", :type => :shell, :inline => fs_init("vagrant")
    b.vm.provision "packages debianoid", :type => :shell, :inline => packages_debianoid("vagrant")
    b.vm.provision "install pyenv", :type => :shell, :privileged => false, :inline => install_pyenv("trixie")
    b.vm.provision "install pythons", :type => :shell, :privileged => false, :inline => install_pythons("trixie")
    b.vm.provision "build env", :type => :shell, :privileged => false, :inline => build_pyenv_venv("trixie")
    b.vm.provision "install borg", :type => :shell, :privileged => false, :inline => install_borg("llfuse")
    b.vm.provision "install pyinstaller", :type => :shell, :privileged => false, :inline => install_pyinstaller()
    b.vm.provision "build binary with pyinstaller", :type => :shell, :privileged => false, :inline => build_binary_with_pyinstaller("trixie")
    b.vm.provision "run tests", :type => :shell, :privileged => false, :inline => run_tests("trixie", ".*none.*")
  end

  config.vm.define "bookworm32" do |b|
    b.vm.box = "generic-x32/debian12"
    b.vm.provider :virtualbox do |v|
      v.memory = 1024 + $wmem
    end
    b.vm.provision "fs init", :type => :shell, :inline => fs_init("vagrant")
    b.vm.provision "packages debianoid", :type => :shell, :inline => packages_debianoid("vagrant")
    b.vm.provision "install pyenv", :type => :shell, :privileged => false, :inline => install_pyenv("bookworm32")
    b.vm.provision "install pythons", :type => :shell, :privileged => false, :inline => install_pythons("bookworm32")
    b.vm.provision "build env", :type => :shell, :privileged => false, :inline => build_pyenv_venv("bookworm32")
    b.vm.provision "install borg", :type => :shell, :privileged => false, :inline => install_borg("llfuse")
    b.vm.provision "install pyinstaller", :type => :shell, :privileged => false, :inline => install_pyinstaller()
    b.vm.provision "build binary with pyinstaller", :type => :shell, :privileged => false, :inline => build_binary_with_pyinstaller("bookworm32")
    b.vm.provision "run tests", :type => :shell, :privileged => false, :inline => run_tests("bookworm32", ".*none.*")
  end

  config.vm.define "bookworm" do |b|
    b.vm.box = "debian/bookworm64"
    b.vm.provider :virtualbox do |v|
      v.memory = 1024 + $wmem
    end
    b.vm.provision "fs init", :type => :shell, :inline => fs_init("vagrant")
    b.vm.provision "packages debianoid", :type => :shell, :inline => packages_debianoid("vagrant")
    b.vm.provision "install pyenv", :type => :shell, :privileged => false, :inline => install_pyenv("bookworm")
    b.vm.provision "install pythons", :type => :shell, :privileged => false, :inline => install_pythons("bookworm")
    b.vm.provision "build env", :type => :shell, :privileged => false, :inline => build_pyenv_venv("bookworm")
    b.vm.provision "install borg", :type => :shell, :privileged => false, :inline => install_borg("llfuse")
    b.vm.provision "install pyinstaller", :type => :shell, :privileged => false, :inline => install_pyinstaller()
    b.vm.provision "build binary with pyinstaller", :type => :shell, :privileged => false, :inline => build_binary_with_pyinstaller("bookworm")
    b.vm.provision "run tests", :type => :shell, :privileged => false, :inline => run_tests("bookworm", ".*none.*")
  end

  config.vm.define "bullseye" do |b|
    b.vm.box = "debian/bullseye64"
    b.vm.provider :virtualbox do |v|
      v.memory = 1024 + $wmem
    end
    b.vm.provision "fs init", :type => :shell, :inline => fs_init("vagrant")
    b.vm.provision "packages debianoid", :type => :shell, :inline => packages_debianoid("vagrant")
    b.vm.provision "install pyenv", :type => :shell, :privileged => false, :inline => install_pyenv("bullseye")
    b.vm.provision "install pythons", :type => :shell, :privileged => false, :inline => install_pythons("bullseye")
    b.vm.provision "build env", :type => :shell, :privileged => false, :inline => build_pyenv_venv("bullseye")
    b.vm.provision "install borg", :type => :shell, :privileged => false, :inline => install_borg("llfuse")
    b.vm.provision "install pyinstaller", :type => :shell, :privileged => false, :inline => install_pyinstaller()
    b.vm.provision "build binary with pyinstaller", :type => :shell, :privileged => false, :inline => build_binary_with_pyinstaller("bullseye")
    b.vm.provision "run tests", :type => :shell, :privileged => false, :inline => run_tests("bullseye", ".*none.*")
  end

  config.vm.define "freebsd13" do |b|
    b.vm.box = "generic/freebsd13"
    b.vm.provider :virtualbox do |v|
      v.memory = 1024 + $wmem
    end
    b.ssh.shell = "sh"
    b.vm.provision "fs init", :type => :shell, :inline => fs_init("vagrant")
    b.vm.provision "packages freebsd", :type => :shell, :inline => packages_freebsd
    b.vm.provision "install pyenv", :type => :shell, :privileged => false, :inline => install_pyenv("freebsd13")
    b.vm.provision "install pythons", :type => :shell, :privileged => false, :inline => install_pythons("freebsd13")
    b.vm.provision "build env", :type => :shell, :privileged => false, :inline => build_pyenv_venv("freebsd13")
    b.vm.provision "install borg", :type => :shell, :privileged => false, :inline => install_borg("llfuse")
    b.vm.provision "install pyinstaller", :type => :shell, :privileged => false, :inline => install_pyinstaller()
    b.vm.provision "build binary with pyinstaller", :type => :shell, :privileged => false, :inline => build_binary_with_pyinstaller("freebsd13")
    b.vm.provision "run tests", :type => :shell, :privileged => false, :inline => run_tests("freebsd13", ".*(pyfuse3|none).*")
  end

  config.vm.define "freebsd14" do |b|
    b.vm.box = "generic/freebsd14"
    b.vm.provider :virtualbox do |v|
      v.memory = 1024 + $wmem
    end
    b.ssh.shell = "sh"
    b.vm.provision "fs init", :type => :shell, :inline => fs_init("vagrant")
    b.vm.provision "packages freebsd", :type => :shell, :inline => packages_freebsd
    b.vm.provision "install pyenv", :type => :shell, :privileged => false, :inline => install_pyenv("freebsd14")
    b.vm.provision "install pythons", :type => :shell, :privileged => false, :inline => install_pythons("freebsd14")
    b.vm.provision "build env", :type => :shell, :privileged => false, :inline => build_pyenv_venv("freebsd14")
    b.vm.provision "install borg", :type => :shell, :privileged => false, :inline => install_borg("llfuse")
    b.vm.provision "install pyinstaller", :type => :shell, :privileged => false, :inline => install_pyinstaller()
    b.vm.provision "build binary with pyinstaller", :type => :shell, :privileged => false, :inline => build_binary_with_pyinstaller("freebsd14")
    b.vm.provision "run tests", :type => :shell, :privileged => false, :inline => run_tests("freebsd14", ".*(pyfuse3|none).*")
  end

  config.vm.define "openbsd7" do |b|
    b.vm.box = "l3system/openbsd77-amd64"
    b.vm.provider :virtualbox do |v|
      v.memory = 1024 + $wmem
    end
    b.vm.provision "fs init", :type => :shell, :inline => fs_init("vagrant")
    b.vm.provision "packages openbsd", :type => :shell, :inline => packages_openbsd
    b.vm.provision "build env", :type => :shell, :privileged => false, :inline => build_sys_venv("openbsd7")
    b.vm.provision "install borg", :type => :shell, :privileged => false, :inline => install_borg("nofuse")
    b.vm.provision "run tests", :type => :shell, :privileged => false, :inline => run_tests("openbsd7", ".*fuse.*")
  end

  config.vm.define "netbsd9" do |b|
    b.vm.box = "generic/netbsd9"
    b.vm.provider :virtualbox do |v|
      v.memory = 4096 + $wmem  # need big /tmp tmpfs in RAM!
    end
    b.vm.provision "fs init", :type => :shell, :inline => fs_init("vagrant")
    b.vm.provision "packages netbsd", :type => :shell, :inline => packages_netbsd
    b.vm.provision "build env", :type => :shell, :privileged => false, :inline => build_sys_venv("netbsd9")
    b.vm.provision "install borg", :type => :shell, :privileged => false, :inline => install_borg("nofuse")
    b.vm.provision "run tests", :type => :shell, :privileged => false, :inline => run_tests("netbsd9", ".*fuse.*")
  end

  # rsync on openindiana has troubles, does not set correct owner for /vagrant/borg and thus gives lots of
  # permission errors. can be manually fixed in the VM by: sudo chown -R vagrant /vagrant/borg ; then rsync again.
  config.vm.define "openindiana" do |b|
    b.vm.box = "openindiana/hipster"
    b.vm.provider :virtualbox do |v|
      v.memory = 2048 + $wmem
    end
    b.vm.provision "fs init", :type => :shell, :inline => fs_init("vagrant")
    b.vm.provision "package update openindiana", :type => :shell, :inline => package_update_openindiana, :reboot => true
    b.vm.provision "packages openindiana", :type => :shell, :inline => packages_openindiana
    b.vm.provision "build env", :type => :shell, :privileged => false, :inline => build_sys_venv("openindiana")
    b.vm.provision "install borg", :type => :shell, :privileged => false, :inline => install_borg("nofuse")
    b.vm.provision "run tests", :type => :shell, :privileged => false, :inline => run_tests("openindiana", ".*fuse.*")
  end
end


================================================
FILE: docs/3rd_party/README
================================================
Here we store third-party documentation, licenses, etc.

Please note that all files inside the "borg" package directory (except those
excluded in setup.py) will be installed, so do not keep docs or licenses
there.


================================================
FILE: docs/Makefile
================================================
# Makefile for Sphinx documentation
#

# You can set these variables from the command line.
SPHINXOPTS    =
SPHINXBUILD   = sphinx-build
PAPER         =
BUILDDIR      = _build

# Internal variables.
PAPEROPT_a4     = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .

.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest

help:
	@echo "Please use \`make <target>' where <target> is one of"
	@echo "  html       to make standalone HTML files"
	@echo "  dirhtml    to make HTML files named index.html in directories"
	@echo "  singlehtml to make a single large HTML file"
	@echo "  pickle     to make pickle files"
	@echo "  json       to make JSON files"
	@echo "  htmlhelp   to make HTML files and an HTML help project"
	@echo "  qthelp     to make HTML files and a qthelp project"
	@echo "  devhelp    to make HTML files and a Devhelp project"
	@echo "  epub       to make an epub"
	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
	@echo "  text       to make text files"
	@echo "  man        to make manual pages"
	@echo "  changes    to make an overview of all changed/added/deprecated items"
	@echo "  linkcheck  to check all external links for integrity"
	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"

clean:
	-rm -rf $(BUILDDIR)/*

html:
	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
	@echo
	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."

dirhtml:
	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
	@echo
	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."

singlehtml:
	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
	@echo
	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."

pickle:
	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
	@echo
	@echo "Build finished; now you can process the pickle files."

json:
	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
	@echo
	@echo "Build finished; now you can process the JSON files."

htmlhelp:
	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
	@echo
	@echo "Build finished; now you can run HTML Help Workshop with the" \
	      ".hhp project file in $(BUILDDIR)/htmlhelp."

qthelp:
	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
	@echo
	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/borg.qhcp"
	@echo "To view the help file:"
	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/borg.qhc"

devhelp:
	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
	@echo
	@echo "Build finished."
	@echo "To view the help file:"
	@echo "# mkdir -p $$HOME/.local/share/devhelp/borg"
	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/borg"
	@echo "# devhelp"

epub:
	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
	@echo
	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."

latex:
	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
	@echo
	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
	@echo "Run \`make' in that directory to run these through (pdf)latex" \
	      "(use \`make latexpdf' here to do that automatically)."

latexpdf:
	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
	@echo "Running LaTeX files through pdflatex..."
	make -C $(BUILDDIR)/latex all-pdf
	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."

text:
	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
	@echo
	@echo "Build finished. The text files are in $(BUILDDIR)/text."

man:
	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
	@echo
	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."

changes:
	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
	@echo
	@echo "The overview file is in $(BUILDDIR)/changes."

linkcheck:
	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
	@echo
	@echo "Link check complete; look for any errors in the above output " \
	      "or in $(BUILDDIR)/linkcheck/output.txt."

doctest:
	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
	@echo "Testing of doctests in the sources finished, look at the " \
	      "results in $(BUILDDIR)/doctest/output.txt."


================================================
FILE: docs/_static/Makefile
================================================

all: logo.pdf logo.png

logo.pdf: logo.svg
	inkscape logo.svg --export-pdf=logo.pdf

logo.png: logo.svg
	inkscape logo.svg --export-png=logo.png --export-dpi=72,72

clean:
	rm -f logo.pdf logo.png


================================================
FILE: docs/_static/logo_font.txt
================================================
Black Ops One
James Grieshaber
SIL Open Font License, 1.1

https://www.google.com/fonts/specimen/Black+Ops+One


================================================
FILE: docs/_templates/globaltoc.html
================================================
<div class="sidebar-block">
  <div class="sidebar-toc">
    {# Restrict the sidebar ToC depth to two levels while generating command usage pages.
       This avoids superfluous entries for each "Description" and "Examples" heading. #}
    {% if pagename.startswith("usage/") and pagename not in (
      "usage/general", "usage/help", "usage/debug", "usage/notes",
    ) %}
      {% set maxdepth = 2 %}
    {% else %}
      {% set maxdepth = 3 %}
    {% endif %}

    {% set toctree = toctree(maxdepth=maxdepth, collapse=True) %}
    {% if toctree %}
      {{ toctree }}
    {% else %}
      {{ toc }}
    {% endif %}
  </div>
</div>


================================================
FILE: docs/_templates/layout.html
================================================
{%- extends "basic/layout.html" %}

{# Do this so that Bootstrap is included before the main CSS file. #}
{%- block htmltitle %}
  {% set script_files = script_files + ["_static/myscript.js"] %}
  <!-- Licensed under the Apache 2.0 License -->
  <link rel="stylesheet" type="text/css" href="{{ pathto('_static/fonts/open-sans/stylesheet.css', 1) }}" />
  <!-- Licensed under the SIL Open Font License -->
  <link rel="stylesheet" type="text/css" href="{{ pathto('_static/fonts/source-serif-pro/source-serif-pro.css', 1) }}" />
  <link rel="stylesheet" type="text/css" href="{{ pathto('_static/css/bootstrap.min.css', 1) }}" />
  <link rel="stylesheet" type="text/css" href="{{ pathto('_static/css/bootstrap-theme.min.css', 1) }}" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  {{ super() }}
{%- endblock %}

{%- block extrahead %}
  {% if theme_touch_icon %}
  <link rel="apple-touch-icon" href="{{ pathto('_static/' ~ theme_touch_icon, 1) }}" />
  {% endif %}
  <meta name="readthedocs-addons-api-version" content="1" />
  {{ super() }}
{% endblock %}

{# Displays the URL for the homepage if it's set, or the master_doc if it is not. #}
{% macro homepage() -%}
  {%- if theme_homepage %}
    {%- if hasdoc(theme_homepage) %}
      {{ pathto(theme_homepage) }}
    {%- else %}
      {{ theme_homepage }}
    {%- endif %}
  {%- else %}
    {{ pathto(master_doc) }}
  {%- endif %}
{%- endmacro %}

{# Displays the URL for the tospage if it's set, or falls back to the homepage macro. #}
{% macro tospage() -%}
  {%- if theme_tospage %}
    {%- if hasdoc(theme_tospage) %}
      {{ pathto(theme_tospage) }}
    {%- else %}
      {{ theme_tospage }}
    {%- endif %}
  {%- else %}
    {{ homepage() }}
  {%- endif %}
{%- endmacro %}

{# Displays the URL for the projectpage if it's set, or falls back to the homepage macro. #}
{% macro projectlink() -%}
  {%- if theme_projectlink %}
    {%- if hasdoc(theme_projectlink) %}
      {{ pathto(theme_projectlink) }}
    {%- else %}
      {{ theme_projectlink }}
    {%- endif %}
  {%- else %}
    {{ homepage() }}
  {%- endif %}
{%- endmacro %}

{# Displays the next and previous links both before and after the content. #}
{% macro render_relations() -%}
  {% if prev or next %}
  <div class="footer-relations">
    {% if prev %}
      <div class="pull-left">
        <a class="btn btn-default" href="{{ prev.link|e }}" title="{{ _('previous chapter')}} (use the left arrow)">{{ prev.title }}</a>
      </div>
    {% endif %}
    {%- if next and next.title != '&lt;no title&gt;' %}
      <div class="pull-right">
        <a class="btn btn-default" href="{{ next.link|e }}" title="{{ _('next chapter')}} (use the right arrow)">{{ next.title }}</a>
      </div>
    {%- endif %}
    </div>
    <div class="clearer"></div>
  {% endif %}
{%- endmacro %}

{%- macro guzzle_sidebar() %}
  <div id="left-column">
    <div class="sphinxsidebar">
      {%- if sidebars != None %}
        {#- New-style sidebar: explicitly include/exclude templates. #}
        {%- for sidebartemplate in sidebars %}
        {%- include sidebartemplate %}
        {%- endfor %}
      {% else %}
        {% include "logo-text.html" %}
        {% include "globaltoc.html" %}
        {% include "searchbox.html" %}
      {%- endif %}
    </div>
  </div>
{%- endmacro %}

{%- block content %}

  {%- if pagename == 'index' and theme_index_template %}
    {% include theme_index_template %}
  {%- else %}
    <div class="container-wrapper">

      <div id="mobile-toggle">
        <a href="#"><span class="glyphicon glyphicon-align-justify" aria-hidden="true"></span></a>
      </div>

      {%- block sidebar1 %}{{ guzzle_sidebar() }}{% endblock %}

      {%- block document_wrapper %}
        {%- block document %}
        <div id="right-column">
          {% block breadcrumbs %}
          <div role="navigation" aria-label="breadcrumbs navigation">
            <ol class="breadcrumb">
              <li><a href="{{ pathto(master_doc) }}">Docs</a></li>
              {% for doc in parents %}
                <li><a href="{{ doc.link|e }}">{{ doc.title }}</a></li>
              {% endfor %}
              <li>{{ title }}</li>
            </ol>
          </div>
          {% endblock %}
          <div class="document clearer body" role="main">
            {% block body %} {% endblock %}
          </div>
          {%- block bottom_rel_links %}
            {{ render_relations() }}
          {%- endblock %}
        </div>
        <div class="clearfix"></div>
        {%- endblock %}
      {%- endblock %}

      {%- block comments -%}
        {% if theme_disqus_comments_shortname %}
        <div class="container comment-container">
          {% include "comments.html" %}
        </div>
        {% endif %}
      {%- endblock %}
    </div>
  {%- endif %}
  {%- endblock %}

{%- block footer %}
<script type="text/javascript">
  $("#mobile-toggle a").click(function () {
    $("#left-column").toggle();
  });
</script>
<script type="text/javascript" src="{{ pathto('_static/js/bootstrap.js', 1)}}"></script>
{%- block footer_wrapper %}
  <div class="footer">
    &copy; Copyright {{ copyright }}. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.
  </div>
{%- endblock %}
{%- block ga %}
  {%- if theme_google_analytics_account %}
    <script type="text/javascript">
      var _gaq = _gaq || [];
      _gaq.push(['_setAccount', '{{ theme_google_analytics_account }}']);
      _gaq.push(['_trackPageview']);
      (function() {
        var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
      })();
    </script>
  {%- endif %}
{%- endblock %}
{%- endblock %}


================================================
FILE: docs/_templates/logo-text.html
================================================
<a href="{{ homepage() }}" class="text-logo">
  <img src='{{ pathto('_static/logo.svg', 1) }}' width='100%'>

  {{ theme_project_nav_name or shorttitle }}
</a>


================================================
FILE: docs/_templates/versionselector.html
================================================
<div class="version-selector" id="borg-version-selector" style="display:none;">
  <label for="version-select">Select your Borg version:</label>
  <select id="version-select"></select>
</div>
<script type="text/javascript">
  // Populate the version selector using ReadTheDocs data if available.
  function borgInitVersionSelector(data) {
    var versions = data && data.versions && data.versions.active;
    if (!versions || !versions.length) return;
    var current = data.versions && data.versions.current && data.versions.current.slug;
    var select = document.getElementById("version-select");
    if (!select) return;
    versions.forEach(function(v) {
      var opt = document.createElement("option");
      opt.value = v.urls.documentation;
      opt.textContent = v.slug;
      if (v.slug === current) opt.selected = true;
      select.appendChild(opt);
    });
    select.addEventListener("change", function() {
      window.location.href = this.value;
    });
    document.getElementById("borg-version-selector").style.display = "";
  }

  document.addEventListener("readthedocs-addons-data-ready", function(event) {
    borgInitVersionSelector(event.detail.data());
  });
</script>


================================================
FILE: docs/authors.rst
================================================
.. include:: global.rst.inc

Authors
=======

.. include:: ../AUTHORS

License
=======

.. _license:

.. include:: ../LICENSE
   :literal:


================================================
FILE: docs/binaries/00_README.txt
================================================
Binary BorgBackup builds
========================

General notes
-------------

The binaries are supposed to work on the specified platform without installing anything else.

There are some limitations, though:
- for Linux, your system must have the same or newer glibc version as the one used for building
- for macOS, you need to have the same or newer macOS version as the one used for building
- for other OSes, there are likely similar limitations

If you don't find something working on your system, check the older borg releases.

*.asc are GnuPG signatures - only provided for locally built binaries.
*.exe (or no extension) is the single-file fat binary.
*.tgz is the single-directory fat binary (extract it once with tar -xzf).

Using the single-directory build is faster and does not require as much space
in the temporary directory as the self-extracting single-file build.

macOS: to avoid issues, download the file via the command line OR remove the
       "quarantine" attribute after downloading:
       $ xattr -dr com.apple.quarantine borg-macos1012.tgz


Download the correct files
--------------------------

Binaries built on GitHub servers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

borg-linux-glibc235-x86_64-gh Linux AMD/Intel (built on Ubuntu 22.04 LTS with glibc 2.35)
borg-linux-glibc235-arm64-gh  Linux ARM (built on Ubuntu 22.04 LTS with glibc 2.35)

borg-macos-15-arm64-gh        macOS Apple Silicon (built on macOS 15 w/o FUSE support)
borg-macos-15-x86_64-gh       macOS Intel (built on macOS 15 w/o FUSE support)

borg-freebsd-14-x86_64-gh     FreeBSD AMD/Intel (built on FreeBSD 14)

Binaries built locally
~~~~~~~~~~~~~~~~~~~~~~

borg-linux-glibc231-x86_64 Linux (built on Debian 11 "Bullseye" with glibc 2.31)

Note: if you don't find a specific binary here, check release 1.4.1 or 1.2.9.

Verifying your download
-----------------------

I provide GPG signatures for files which I have built locally on my machines.

To check the GPG signature, download both the file and the corresponding
signature (*.asc file) and then (on the shell) type, for example:

    gpg --recv-keys 9F88FB52FAF7B393
    gpg --verify borgbackup.tar.gz.asc borgbackup.tar.gz

The files are signed by:

Thomas Waldmann <tw@waldmann-edv.de>
GPG key fingerprint: 6D5B EF9A DD20 7580 5747 B70F 9F88 FB52 FAF7 B393

My fingerprint is also in the footer of all my BorgBackup mailing list posts.


Provenance attestations for GitHub-built binaries
-------------------------------------------------

For binaries built on GitHub (files with a "-gh" suffix in the name), we publish
an artifact provenance attestation that proves the binary was built by our
GitHub Actions workflow from a specific commit or tag. You can verify this using
the GitHub CLI (gh). Install it from https://cli.github.com/ and make sure you
use a recent version that supports "gh attestation".

Practical example (Linux, 2.0.0b20 tag):

    curl -LO https://github.com/borgbackup/borg/releases/download/2.0.0b20/borg-linux-glibc235-x86_64-gh
    gh attestation verify --repo borgbackup/borg --source-ref refs/tags/2.0.0b20 borg-linux-glibc235-x86_64-gh

If verification succeeds, gh prints a summary stating the subject (your file),
that it was attested by GitHub Actions, and the job/workflow reference.


Installing
----------

It is suggested that you rename or symlink the binary to just "borg".
If you need "borgfs", just also symlink it to the same binary; it will
detect internally under which name it was invoked.

On UNIX-like platforms, /usr/local/bin/ or ~/bin/ is a nice place for it,
but you can invoke it from anywhere by providing the full path to it.

Make sure the file is readable and executable (chmod +rx borg on UNIX-like
platforms).


Reporting issues
----------------

Please first check the FAQ and whether a GitHub issue already exists.

If you find a NEW issue, please open a ticket on our issue tracker:

https://github.com/borgbackup/borg/issues/

There, please give:
- the version number (it is displayed if you invoke borg -V)
- the sha256sum of the binary
- a good description of what the issue is
- a good description of how to reproduce your issue
- a traceback with system info (if you have one)
- your precise platform (CPU, 32/64-bit?), OS, distribution, release
- your Python and (g)libc versions



================================================
FILE: docs/book.rst
================================================
:orphan:

.. include:: global.rst.inc

Borg documentation
==================

.. When you add an element here, do not forget to add it to index.rst.
.. Note: Some things are in appendices (see latex_appendices in conf.py).

.. toctree::
    :maxdepth: 2

    introduction
    installation
    quickstart
    usage
    deployment
    faq
    support
    changes
    internals
    development
    authors


================================================
FILE: docs/borg_theme/css/borg.css
================================================
@import url("theme.css");

dt code {
    font-weight: normal;
}

#internals .toctree-wrapper > ul {
    column-count: 3;
    -webkit-column-count: 3;
}

#internals .toctree-wrapper > ul > li {
    display: inline-block;
    font-weight: bold;
}

#internals .toctree-wrapper > ul > li > ul {
    font-weight: normal;
}

/* bootstrap has a .container class which clashes with docutils' container class. */
.docutils.container {
    width: auto;
    margin: 0;
    padding: 0;
}

/* the default (38px) produces a jumpy baseline in Firefox on Linux. */
h1 {
    font-size: 36px;
}

.text-logo {
    background-color: #000200;
    color: #00dd00;
}

.text-logo:hover,
.text-logo:active,
.text-logo:focus {
    color: #5afe57;
}

/* by default the top and bottom margins are unequal which looks a bit unbalanced. */
.sidebar-block {
    padding: 0;
    margin: 14px 0 24px 0;
}

#borg-documentation h1 + p .external img {
    width: 100%;
}

.container.experimental,
#debugging-facilities {
    /* don't change text dimensions */
    margin: 0 -30px; /* padding below + border width */
    padding: 0 10px; /* 10 px visual margin between edge of text and the border */
    /* fallback for browsers that don't have repeating-linear-gradient: thick, red lines */
    border-left: 20px solid red;
    border-right: 20px solid red;
    /* fancy red stripes */
    border-image: repeating-linear-gradient(
            -45deg,rgba(255,0,0,0.1) 0,rgba(255,0,0,0.75) 10px,rgba(0,0,0,0) 10px,rgba(0,0,0,0) 20px,rgba(255,0,0,0.75) 20px) 0 20 repeat;
}

.topic {
    margin: 0 1em;
    padding: 0 1em;
    /* #4e4a4a = background of the ToC sidebar */
    border-left: 2px solid #4e4a4a;;
    border-right: 2px solid #4e4a4a;;
}

table.docutils:not(.footnote) td,
table.docutils:not(.footnote) th {
    padding: .2em;
}

table.docutils:not(.footnote) {
    border-collapse: collapse;
    border: none;
}

table.docutils:not(.footnote) td,
table.docutils:not(.footnote) th {
    border: 1px solid #ddd;
}

table.docutils:not(.footnote) tr:first-child th,
table.docutils:not(.footnote) tr:first-child td {
    border-top: 0;
}

table.docutils:not(.footnote) tr:last-child td {
    border-bottom: 0;
}

table.docutils:not(.footnote) tr td:first-child,
table.docutils:not(.footnote) tr th:first-child {
    border-left: 0;
}

table.docutils:not(.footnote) tr td:last-child,
table.docutils:not(.footnote) tr th:last-child,
table.docutils.borg-options-table tr td {
    border-right: 0;
}

table.docutils.option-list tr td,
table.docutils.borg-options-table tr td {
    border-left: 0;
    border-right: 0;
}

table.docutils.borg-options-table tr td:first-child:not([colspan="3"]) {
    border-top: 0;
    border-bottom: 0;
}

.borg-options-table td[colspan="3"] p {
    margin: 0;
}

.borg-options-table {
    width: 100%;
}

kbd, /* used in usage pages for options */
code,
.rst-content tt.literal,
.rst-content tt.literal,
.rst-content code.literal,
.rst-content tt,
.rst-content code,
p .literal,
p .literal span {
    border: none;
    padding: 0;
    color: black; /* slight contrast with #404040 of regular text */
    background: none;
}

kbd {
    box-shadow: none;
    line-height: 23px;
    word-wrap: normal;
    font-size: 15px;
    font-family: Consolas, monospace;
}

.borg-options-table tr td:nth-child(2) .pre {
    white-space: nowrap;
}

.borg-options-table tr td:first-child {
    width: 2em;
}

cite {
    white-space: nowrap;
    color: black; /* slight contrast with #404040 of regular text */
    font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter",
    "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace;
    font-style: normal;
    text-decoration: underline;
}

.borg-common-opt-ref {
    font-weight: bold;
}

.sidebar-toc ul li.toctree-l2 a,
.sidebar-toc ul li.toctree-l3 a {
    padding-right: 25px;
}

#common-options .option {
    white-space: nowrap;
}
/* Remove the right-column max-width cap so content fills the full available width. */
#right-column {
    max-width: none;
}
/* Hide the default RTD flyout since we show the version selector in the sidebar. */
readthedocs-flyout {
    display: none !important;
}
/* Version selector in the sidebar. */
.version-selector {
    padding: 0 22px;
    margin: 7px 0 7px 0;
    font-size: 14px;
}
.version-selector label {
    display: block;
    margin-bottom: 4px;
    color: #000;
}
.version-selector select {
    width: 100%;
    padding: 4px;
    background-color: #fafafa;
    color: #000;
    border: 1px solid #ccc;
    border-radius: 3px;
}
.version-selector::after {
    content: '';
    display: block;
    border-top: 1px solid #ccc;
    margin: 7px 0 0 0;
}
/* Reduce top and bottom margin of searchbox block to 7px to match separator spacing. */
.sidebar-block:has(#main-search) {
    margin-top: 7px;
    margin-bottom: 7px;
}
/* Reduce the separator margin below the search block to 7px. */
.sphinxsidebar > .sidebar-block:has(#main-search):after {
    margin: 7px 22px 0 22px;
}


================================================
FILE: docs/changes.rst
================================================
.. _important_notes:

Important notes 2.x
===================

This section provides information about security and corruption issues.

(nothing to see here yet)

.. _upgradenotes2:

Upgrade Notes
=============

borg 1.2.x/1.4.x to borg 2.0
----------------------------

Compatibility notes:

- This is a major "breaking" release that is not compatible with existing repositories.

  We tried to put all the necessary "breaking" changes into this release, so we
  hopefully do not need another breaking release in the near future. The changes
  were necessary for improved security, improved speed and parallelism,
  unblocking future improvements, getting rid of legacy crap and design
  limitations, having less and simpler code to maintain.

  You can use "borg transfer" to transfer archives from borg 1.2/1.4 repos to
  a new borg 2.0 repo, but it will need some time and space.

  Before using "borg transfer", you must have upgraded to borg >= 1.2.6 (or
  another borg version that was patched to fix CVE-2023-36811) and
  you must have followed the upgrade instructions at top of the change log
  relating to manifest and archive TAMs (borg2 just requires these TAMs now).

- Command-line syntax was changed; scripts and wrappers will need changes:

  - You will usually either export BORG_REPO=<MYREPO> into your environment or
    call borg like: "borg -r <MYREPO> <COMMAND>".
    In the docs, we usually omit "-r ..." for brevity.
  - The scp-style REPO syntax was removed; please use ssh://..., #6697
  - ssh:// URLs: Removed support for /~otheruser/, /~/ and /./, #6855.
    New format:

    - ssh://user@host:port/relative/path
    - ssh://user@host:port//absolute/path
  - -P / --prefix option was removed; please use the similar -a / --match-archives.
  - Archive names don't need to be unique anymore. To the contrary:
    It is now strongly recommended to use the identical name for borg create
    within the same series of archives to make borg work more efficiently.
    The name now identifies a series of archives; to identify a single archive,
    please use aid:<archive-hash-prefix>, e.g., borg delete aid:d34db33f
  - In case you do NOT want to adopt the "series name" way of naming archives
    (like "myarchive") as we recommend, but keep using always-changing names
    (like "myserver-myarchive-20241231"), you can do that, but then you must
    make use of BORG_FILES_CACHE_SUFFIX and either set it to a constant suffix
    (like "all") or to a unique suffix per archive series (like
    "myserver-myarchive") so that borg can find the correct files cache.
    For the "all" variant, you must also set BORG_FILES_CACHE_TTL to a value
    greater than the count of different archives series you write to that repo.
    Usually borg uses a different files cache suffix per archive (series) name
    and defaults to BORG_FILES_CACHE_TTL=2 because that is sufficient for that.
  - The archive ID is always given separately from the repository.
    Unlike in borg 1.x, you must not give repo::archive.
  - The series name or archive ID is either given as a positional parameter,
    like:

    - borg create documents ~/Documents
    - borg diff aid:deadbeef aid:d34db33f
  - or, if the command makes sense for an arbitrary amount of archives, archives
    can be selected using a glob pattern, like:

    - borg delete -a 'sh:myarchive-2024-??-??'
    - borg recreate -a 'sh:myarchive-2024-??-??'
  - some borg 1.x commands that supported working on a repo AND on an archive
    were split into 2 commands, some others were renamed:

    - borg 2 repo commands:

      - borg repo-create  # was: borg init
      - borg repo-list
      - borg repo-info
      - borg repo-delete
      - borg repo-compress
      - borg repo-space
    - borg 2 archive commands:

      - borg create NAME ...
      - borg list ID
      - borg extract ID ...
      - borg diff ID1 ID2
      - borg rename ID NEWNAME
      - borg info ID
      - borg delete ID
      - borg recreate ID ...
      - borg mount -a ID mountpoint ...

    For more details, please consult the docs or --help option output.
  - create/recreate/import-tar --timestamp: defaults to local timezone
    now (was: UTC)
- some deprecated options were removed:

  - removed --remote-ratelimit (use --upload-ratelimit)
  - removed --numeric-owner (use --numeric-ids)
  - removed --nobsdflags (use --noflags)
  - removed --noatime (default now, see also --atime)
  - removed --save-space option (does not change behaviour)
- removed --bypass-lock option
- removed borg config command (only worked locally anyway)
- compact command now requires access to the borg key if the repo is encrypted
  or authenticated
- using --list together with --progress is now disallowed (except with --log-json), #7219
- the --glob-archives option was renamed to --match-archives (the short option
  name -a is unchanged) and extended to support different pattern styles:

  - id: for identical string match (this is the new default!)
  - sh: for shell pattern / globbing match (this was used by --glob-archives)
  - re: for regular expression match

  So you might need to edit your scripts like e.g.::

      borg 1.x: --glob-archives 'myserver-2024-*'
      borg 2.0: --match-archives 'sh:myserver-2024-*'

- use platformdirs 3.x.x instead of home-grown code. Due to that:

  - XDG_*_HOME is not honoured on macOS and on Windows.
  - BORG_BASE_DIR can still be used to enforce some base dir + .config/ or .cache/.
  - on macOS, the default directories move to native locations:
    config/data: ``~/Library/Application Support/borg/``,
    cache: ``~/Library/Caches/borg/``,
    runtime: ``~/Library/Caches/TemporaryItems/borg/``.
  - on Windows, the default directories are:
    config: ``C:\Users\<user>\AppData\Roaming\borg``,
    cache: ``C:\Users\<user>\AppData\Local\borg\Cache``,
    data: ``C:\Users\<user>\AppData\Local\borg``.
  - **keyfile users on macOS (and Windows)**: borg 2 will look for key files in the
    new platform-specific config directory instead of ``~/.config/borg/keys/`` where
    borg 1.x stored them. You can set ``BORG_KEYS_DIR`` to point to the old location,
    or copy the key file to the new location. See :ref:`env_vars` and the ``borg transfer``
    documentation for details.
- create: different included/excluded status chars, #7321

  - dry-run: now uses "+" (was: "-") and "-" (was: "x") for included/excluded status
  - non-dry-run: now uses "-" (was: "x") for excluded files

  Option --filter=... might need an update, if you filter for the status chars
  that were changed.
- borg is now more strict and disallows giving some options multiple times -
  if that makes no sense. Highlander options, see #6269. That might make scripts
  fail now that somehow "worked" before (but maybe didn't work as intended due to
  the contradicting options).

.. _changelog:

Change Log 2.x
==============

Version 2.0.0b21 (2026-03-16)
-----------------------------

Please note:

Beta releases are only for testing on NEW repos - do not use for production.

For upgrade and compatibility hints, please also read the section "Upgrade Notes"
above.

New features:

- support https/http (REST) repositories via borgstore, #9480
- use jsonargparse as CLI argument/option parser, also supporting YAML configs
  for defaults and auto-generated environment variables to override defaults, #6551
- create --paths-from-shell-command, #5968
- create: add --tags/--hostname/--username, #9401, #9402
- create: implement "file changed while backup" detection on Windows, #9382
- prune -v: now displays archive counts (total, kept, pruned), #9262
- list --format: add fingerprint placeholder (fast!)
- archive: use 3 timestamps (cleanly separate nominal archive timestamp from
  borg operation start/end info), #9400
- benchmark crud: add --json-lines output option, #9165

Fixes:

- prune: fix Archive.DoesNotExist when using --list, #9416
- remove_dotdot_prefixes: remove bad assert, #9406
- create --compress: expose Padmé size obfuscation (250) via CLI, #9286
- remote: fix StoreObjectNotFound exception lost over RPC, #9380
- passphrase: fail if multiple passphrase environment variables are set, #8834
- cockpit: fix subprocess invocation in frozen binaries
- cockpit: start the Borg runner after all widgets are mounted
- debug format-obj: support all repository object types, #9391
- benchmark crud: suppress compact warnings during benchmark runs, #9365
- fix file: URL parsing for Windows

  - Linux: /abs/path -> file:///abs/path
  - Windows: c:/abs/path -> file:///c:/abs/path

Other changes:

- y2038: SUPPORT_32BIT_PLATFORMS = False, #9429.
  Not as bad as it sounds: 32bit platforms with 64bit time_t will still work.
  As of 2026, this is pretty much every platform that can run Borg reasonably well.
- remove handwritten bash and zsh shell completions, #9178.
  these are now auto-generated via ``borg completion bash/zsh`` (using shtab).
  fish completions are kept until shtab gains fish support.
- mount: warn about symlinks pointing outside of the mountpoint, #9254
- use FILE_FLAG_WRITE_THROUGH on Windows for SyncFile data durability, #9388
- extract: do not delete existing directory if possible, #4233
- extract --continue: optimize processing of already existing dirs
- mount: FUSE FS performance fix
- prune: print hint to run compact to free space
- prune: use same method to delete archives as delete subcommand, #9424
- use xxhash from PyPI, #6535
- use zstd from python lib or backports.zstd (python<'3.14'), #9261
- swidth: use cross-platform implementation, #7493
- platform: use F_FULLSYNC on macOS for SyncFile data durability, #9383
- cache: add seek()/tell() to SyncFile, use SaveFile in _write_files_cache, #9390
- cache: remove try_upgrade_to_b14() legacy migration, #9371
- remove unnecessary checks: API_VERSION, check_python
- time calculations: avoid floating point
- Version: do not access private attributes, #9263
- Windows platform (win32):

  - normalize drive letters, #9279
  - Path separator: internally always use "/", accept also "\" for CLI arguments
  - map_chars: deal with invalid chars in paths on Windows
- binary build:

  - use pyinstaller 6.18.0 for Python 3.14 compatibility
  - do not exclude ssl, needed for pyfuse3/trio, #9196
  - build with cockpit,s3,sftp extras installed, #9241
  - build Linux binaries with pyfuse3, #9196
- Documentation:

  - jsonargparse: update docs about configs, auto-generated environment variables, precedence
  - fix S3 URL description, #9249
  - add a note that you need to install boto3 if you want to use S3/B2 URLs
  - rename BORG_RLIST_FORMAT to BORG_REPO_LIST_FORMAT, #9411
  - document platformdirs change and platform-specific directory paths, #7332
  - borgbackup.org: move RTD version selector to sidebar top-left, #8204
  - update SECURITY.md version table, #9346
  - fuse: add thread/async safety warning
  - upgrade http:// URLs to https:// and remove dead librelist.com link, #9342, #9302
  - man pages: fix broken :ref: references (e.g. borg_patterns), #7239
  - update deprecated pypi.python.org URLs to pypi.org, #9337
  - consolidate key backup info in borg key export, #6204
  - fix typos found by codespell, #9295
  - GitHub: enhance pull request template, #9334
  - archive specification, FAQ, #9248, #9053
- testing / CI:

  - scripts/linux-run: run commands (e.g. tox) in a podman linux container,
    very useful when developing on macOS to test under Linux.
  - CI: add testing on omniOS ("OpenSolaris")
  - CI: use OpenBSD 7.8
  - CI: fix and re-enable Windows testing
  - CI: faster with borg-dir/borg.exe, #9236
  - add dependabot, #9308, #9349
  - add top-level permissions for least-privilege security, #9344
  - completion: focused tests for auto-generated shell completions
    (syntax validation, size sanity, borg-specific preamble behavior)
  - Speed up benchmark CPU tests with _BORG_BENCHMARK_CPU_TEST env var, #9414
  - fix mismatch in xattr test, #9238
  - xattr: document fakeroot xattr as Linux-only, add missing fakeroot skipping on FreeBSD, #9394
  - testsuite: remove deprecated manual cleanup in create_cmd_test
  - add borg.exe to PATH
  - fix tmpdir check on netbsd
  - enable Codecov Test Analytics, upgrade to codecov-action@v5
  - codecov: nothing to do for mypy and docs envs
  - add missing timeout-minutes to codeql, backport, and lint workflows, #9298
  - add path filters to lint and codeql workflows, #9328
  - cache tox environments
  - remove redundant tox runs, parallelize better, avoid unnecessary steps
  - add concurrency groups to cancel stale workflow runs, #9310
  - improve collecting coverage information, improve coverage, #9448
  - use locked requirements, add canary job, #9361
  - fix spurious sparse test fail on win32, #7616
  - fix race condition in test_with_lock, #8810
  - speed up prune/list/repo-list tests, #9324
  - add test for cockpit feature
  - add a borg create/extract timestamp test for y2261.


Version 2.0.0b20 (2025-12-24)
-----------------------------

New features:

- fat binary builds on GitHub (see assets on the GitHub releases page):

  - for Linux with glibc 2.35+ (Intel/AMD and ARM64)
  - for macOS 15+ (Apple Silicon/ARM64 and Intel)
  - using GitHub artifact attestations for release binaries, #9134
- borg --cockpit: show status display based on Textual
- Linux ACLs: use acl_to_any_text to avoid libacl name lookups, #8753.
- export-tar/import-tar: support for POSIX ACLs (PAX format)
- NetBSD: xattr support, #1332
- mount: alternatively, work with high-level fuse library "mfusepy", which
  supports fuse 2 and 3, #9194. Try it with: pip install borg[mfusepy]
- diff: --sort-by=field[,field,...], #8998
- list --format: add "inode" placeholder
- info: show cwd at the time of backup creation, #6191
- improved tty-less progress reporting (--progress), #9055
- BORG_MSGPACK_VERSION_CHECK=no to optionally disable the msgpack version
  check; default is "yes", use at your own risk, #9109.
- completion: generate completion scripts for supported shells, #9172,
  uses shtab, supports bash and zsh.

Fixes:

- extract: fs flags: use get/set to influence only specific flags, #9039, Linux, FreeBSD, macOS
- transfer: fix borg transfer corrupting the source repo index, #9022
- transfer: create a chunks list entry for missing chunks, see #9208
- transfer: fix AttributeError with --dry-run, see #9199
- old archives might not have a comment in metadata, see #9208
- HardLinkManager: allow NoneType for contentless hardlinks, see #9208
- legacyrepository: remove auto_recover, #9022
- legacyremote: accept raise_missing in get/get_many to avoid TypeError
  with callers that pass it; no behavior change on legacy protocol, #9199
- fix reading borg 1.x repo index, #9022
- enable S3/B2 support of borgstore
- mount --show-rc: display main process return code (rc), #8308
- create: add exception handler for NODUMP-excluded directories, #9032
- json: include archive keys in JSON lines when requested via --format, #9095
- ensure valid file URLs are created from Windows paths
- Windows: add missing guards around `preexec_fn=ignore_sigint`
- preprocess_args: fix option name matching

Other changes:

- support Python 3.14, msgpack 1.1.2, use Cython 3.2.3
- require setuptools>=78.1.1, #9042
- "bsdflags" set_flags: remove compression flag support (did not work anyway)
- Brewfile: use openssl@3
- buzhash/buzhash64: initialise all-zero memory more efficiently
- tests:

  - add fuzzing tests for chunkers
  - add tests for diff output of archives with hard links
  - read_only CM: skip test if cmd_immutable is unsuccessful, fixes #9021
  - save space in test_create_* tests
  - CI/tests: add SFTP/rclone/S3 repo testing
  - CI: add local servers for S3 and SFTP testing
  - CI: add misc. BSDs and Haiku OS (on GitHub Actions)
  - CI: do dynamic code analysis, #6819
  - transfer: add test for unexpected src repo index change, #9022
  - pyproject.toml: correctly define test environments for FUSE testing
  - add granularity_sleep, #9150
  - use context manager when opening files in patterns_test
  - FUSE related fixes/improvements, #9182
  - fix pynacl/libsodium build on freebsd, #9214
  - filter_xattrs now also filters some macOS xattrs
  - transfer: add --dry-run test
  - refactor id <-> name lookup for monkeypatching
  - CI: netbsd: enable xattrs on TMPDIR
  - improve fs cleanup directly after tests
- Vagrant:

  - add Debian testing/Trixie box
  - add an OpenBSD 7.7 box
  - fix OpenIndiana box
  - drop macOS 10.12 box (binaries are built on GitHub now)
  - use Python 3.13.8 for binary building and tests
  - use PyInstaller 6.14.2 for binary building
- docs:

  - update README for binaries
  - improve borg help patterns, #7144
  - patterns: clarify scope of default pattern style, #9004
  - extract: document how to use wildcards in PATHs, #8589
  - how to debug borg mount, #5461
  - document what happens when a new keyfile repo is created at the same path, #6230
  - update install docs to include `SETUPTOOLS_SCM_PRETEND_VERSION`
  - highlight archive series naming for fast incrementals, #8955
  - add Arch Linux to the 'Installing from source' docs
  - add systemd-inhibit and examples, #8989
  - code/docs: fix typos and grammar
  - some fixes/updates to the FAQ


Version 2.0.0b19 (2025-07-02)
-----------------------------

Fixes:

- reader: fix corruption issue "forgetting" all-zero bytestrings, #8963
- import-tar: normalize the tarinfo name/linkname when used as hlm key.
  also: when printing the path, use the already normalized item.path.
- import-tar: fix the dotslash issue, add test

New features:

- create --files-changed=MODE option, #8958.
  control how borg detects whether a file has changed while it was backed up,
  valid modes are ctime (default), mtime (2nd best) or disabled (not recommended).

Other changes:

- to_key_filename: raise length limit to 120, #8966.
  This works around a test failure on systems with deep build directories.


Version 2.0.0b18 (2025-06-19)
-----------------------------

New features:

- experimental new "buzhash64" chunker (later, after testing, this shall become
  the default chunker in borg2):

  - add own cryptographically secure pseudo-random number generator (CSPRNG)
    based on AES256-CTR to create deterministic random, based on a 256bit seed.
  - use that to deterministically create a perfectly balanced buzhash64 table.
  - "buzhash64" chunker computes 64bit hash values for the chunking decision.
  - performance is similar to "buzhash" (measured on Apple M3P cpu).

  That should also resolve these points of criticism about the old "buzhash"
  32bit code:

  - table_base: that the bits are not randomly distributed enough
  - that an XORed seed cancels out for specific window sizes
  - that XORing the table with a seed is equivalent to XORing the computed hash
    value with another constant

  Please test the chunkers extensively (e.g. with borg create, borg transfer),
  we can hardly change them "in production", because chunking differently also
  means not deduplicating with old chunks. So, in case there are changes
  needed, we need to find and fix them now while borg is in beta.

  See also some other chunker changes listed below "Other changes".
- serve: add --permissions option as an alternative to BORG_REPO_PERMISSIONS env var
- create: auto-exclude items based on xattrs or NODUMP, see #4972

  no options yet, just hardcoded macOS and Linux xattrs.
  removed the --exclude-nodump option, it is also done automagically now.

  also: create: read stat attrs, xattrs, ACLs early, before file contents.

Fixes:

- compact: fix cleaning archives directory (catch correct exception, use
  logger.warning, improve error msg)

Other changes:

- support Python 3.14
- msgpack: allow 1.1.1, version check: ignore "rc" or other version elements
- add derive_key to derive new keys from existing key material
- refactor the chunkers, #8882 #8883:

  - transform buzhash chunker C code to Cython
  - split concerns into FileFMAPReader, FileReader, Chunker*:

    - FileFMAPReader reads blocks from the input file, supporting sparse
      files and fmaps.
    - FileReader uses FileFMAPReader to fill its buffer and offers clients a
      `.read(size)` method so they can read pieces of the data.
    - all chunkers now use the FileReader/FileFMAPReader code
  - split code and test module into packages
- "fixed" chunker: add fixed chunker tests to selftest
- "fixed" chunker: do not assert on short header read
- "buzhash*" chunker: use safe_fadvise
- "buzhash" chunker: reject even window size, #8868
- fish: fix archive name completion
- refactor: modularize tests
- refactor: use pathlib.Path
- tests / CI:

  - CI: add bandit, a security-oriented static analysis tool
  - CI: disable windows as the file:// repo URLs are still broken on windows.
  - tests: tox: use native pyproject.toml configuration
  - more chunker-related tests
- docs:

  - add docs for serve --permissions / BORG_REPO_PERMISSIONS
  - borg-serve: simplify example of env in authorized_keys, #8318
  - fix mistyped CVE number


Version 2.0.0b17 (2025-05-23)
-----------------------------

New features:

- transfer: implement --chunker-params to re-chunk while transferring, #8706
- list --depth=N: list files up to N depth in path hierarchy, #8268
- compact: also clean up files cache, #8852
- `BORG_REPO_PERMISSIONS=all|no-delete|write-only|read-only`, #8823

  The posixfs borgstore backend implements permissions to make
  testing with differently permissive stores easier.

  The env var selects from pre-defined permission configurations
  within borg and gives the chosen permissions config to borgstore.
  borg uses borgstore's posixfs backend only for file: and ssh: repos.

Fixes:

- correct the signature of __set_name__ as cython 3.1 added support,
  fixing build on Cython 3.1, #6858
- compact/check: fix bug not writing the complete index, #8813
- compact: add --iec option, #8831
- check/compact/analyze: show archive timestamp in local tz, #8814
- repo-space: enable ssh: repo testing, fix AttributeError, #8815
- repo-info: fix output formatting

Other changes:

- require borgstore 0.3.x
- some updates and fixes for shell completions, needs more work
- dir_is_tagged/_is_cachedir: add fd-based operations
- cython: suppress compiler warning about CYTHON_FALLTHROUGH in unreachable code
- source code: `pyupgrade --py310-plus ./**/*.py`
- tests:

  - add/improve tests for repo-compress --stats, transfer, repo-space
  - split helpers tests from a single module into borg.testsuite.helpers package
  - save temp space (good for ramdisk users)
  - fix diff cmd test on macOS HFS+, #8860
  - test validity of shell completion files
  - CI: fix and enable windows CI, #8728
  - CI: upload coverage for windows tests
  - CI: install zsh and fish so we can test shell completions
- docs:

  - must have the release tags in the local repo, #8582
  - remove outdated docs/man files about borg change-passphrase
  - add S3/B2 urls to documentation for repository urls, #8833


Version 2.0.0b16 (2025-05-06)
-----------------------------

Fixes:

- chunks cache: invalidate old chunk index cache, #8795
- compact: always write updated chunkindex to repo, #8791
- ChunksMixin: don't use self._chunks until it is demand-built, #8785
- AdhocWithFilesCache: fix call to _maybe_write_chunks_cache
- format_time: output date/time in local tz, #8802
- check: ask for key passphrase early, #1931
- only obfuscate the size of file content chunks, #7559
- better support other repo by misc. passphrase env vars, #8457

  - passphrases now come from `BORG_[OTHER_]PASSPHRASE`, `BORG_[OTHER_]PASSCOMMAND`
    or `BORG_[OTHER_]PASSPHRASE_FD`.
  - `borg repo-create --repo B --other-repo A` does not silently copy the
    passphrase of key A to key B anymore, but either asks for the passphrase
    or reads it from env vars.

Other changes:

- remove support for / testing on Python 3.9
- docs: borg serve --repo is not supported, #8591
- remove remainders of append-only and quota support
- remove cygwin < 2.8.0 bug workaround
- fix remote api versioning


Version 2.0.0b15 (2025-04-22)
-----------------------------

New features:

- compact: without --stats, it will be faster by using the cached chunks index.
  with --stats it will be as slow as before, listing all repo objs.
- compact: support --dry-run (do nothing), #8300
- extract: --dry-run now displays +/- status flags (included/excluded), #8564
- allow timespan to be specified with common time units, #8624
- enhance passphrase handling, #8496.

  Setting `BORG_DEBUG_PASSPHRASE=YES` enables passphrase debug logging to
  stderr, showing passphrase, hex utf-8 byte sequence and related env vars if
  a wrong passphrase was encountered.

  Setting `BORG_DISPLAY_PASSPHRASE=YES` now always shows passphrase and its hex
  utf-8 byte sequence.
- add {unixtime} placeholder, #8522
- implement padme chunk size obfuscation (SPEC 250), #8705
- macOS: retrieve birthtime in nanosecond precision via system call, #8724

Bug fixes:

- borg exits when assertions are disabled with Python optimizations, #8649
- yes(): deal with UnicodeDecodeError in input(), #6984
- fix remote repository exception handling / modern exit codes, #8631
- freebsd: fix nfs4 acl processing, #8756.
  This issue only affected borg extract --numeric-ids when processing NFS4
  ACLs, it didn't affect POSIX ACL processing.

Other changes:

- adapt to and require borghash 0.1.0
- adapt to and require borgstore 0.2.0 (new s3/b2 backend, fixes/improvements)
- create: remove --make-parent-dirs option (borgstore now does this automatically), #8619
- iter_items: decouple item iteration and content data chunks preloading
- remote: simplify code, add debug logging
- pyproject.toml: SPDX expression for license, add license-files, #8771
- Item: remove .chunks_healthy, #8559
- OpenBSD fixes:

  - support other OpenSSL versions on OpenBSD, #8553
  - vagrant: fix OpenBSD box, #8506
  - Filter test output with LibreSSL related warnings on OpenBSD
- macOS: fix brew's broken pkg-config -> pkgconf transition
- tests: ignore 'com.apple.provenance' xattr (macOS specific)
- vagrant updates:

  - use pyinstaller 6.11.1 (also use this in msys2 build scripts)
  - use python 3.12.10
  - build binaries with borgstore[sftp], #8574
- docs:

  - automated backup: append to SYSTEMD_WANTS rather than overwrite, #8641
  - fix udev rule priority in automated-local.rst, #8639
  - FAQ: Why backups are slow on a Linux server that is a member of a windows domain? #8636
  - within a shell, cli options with special characters may require quoting, #8578
  - update prune documentation for new --keep-within intervals, #8630
  - borg serve: recommend using a simple shell, #3818
  - update install docs (requirements, pkgconfig, fuse), #8342
  - libffi-dev is required for argon2-cffi-bindings
  - add undelete command to index
  - borg commands updated with --repo option, #8550
  - FAQ: add entry about pure-python msgpack warning, #8323
  - readthedocs theme fixes

    - bring back highlighted content preview in search results.
    - fix erroneous warning about missing javascript support.


Version 2.0.0b14 (2024-11-17)
-----------------------------

New features:

- delete: now only soft-deletes archives (same for prune)
- repo-list: --deleted lists deleted archives
- undelete: undelete soft-deleted archives, #8500

Fixes:

- chunks index cache:

  - enable partial/incremental updates (F_NEW flag).
  - write chunks index every 10mins, #8503.
    this makes sure progress is not totally lost when a backup is interrupted.
  - write to repo/cache/chunks.<HASH> to enable parallel updates.
- mount: fix check_pending_archive to give correct root dir, #8528

Other changes:

- repo-compress: reduce memory consumption (F_COMPRESS flag)
- files cache: reduce memory consumption, #5756
- check: rename --undelete-archives to --find-lost-archives
- check: rebuild_archives_directory: accelerate by only reading metadata
- shell completions: adapt zsh for borg 2.0.0b13 - needs more work!
- chunk index: rename .refcount to .flags, use it for user and system flags.
- vagrant:

  - add bookworm32 box for 32bit platform testing
  - fix pythons on freebsd14
  - simplify openindiana box setup
- docs:

  - remove --bypass-lock, small changes regarding compression
  - FAQ: clean up entries regarding SSH settings


Version 2.0.0b13 (2024-10-31)
-----------------------------

New features:

- implement special tags, @PROT tag for protecting archives, #953.

  borg won't delete/prune/recreate protected archives.
- prune: add quarterly pruning strategy, #8337.
- import-tar/export-tar: add xattr support for PAX format, #2521.

Fixes:

- simple error msgs for existing / non-existing repo, no tracebacks, #8475.
- mount: create unique directory names, #8461.
- diff: suppress modified changes for files which weren't actually modified.
- diff: do not test for ctime difference on windows.
- prune: fix exception when NAME is given, #8486
- repo-create: build and cache an empty ChunkIndex.
- work around missing size/nfiles archive metadata, #8491
- lock after checking repo exists, #8485

Other changes:

- new file:, rclone:, ssh:, sftp: URLs, #8372, #8446.

  new way to deal with absolute vs. relative paths.
- require borgstore ~= 0.1.0, require borghash ~= 0.0.1.
- new hashtable code based on borghash project:

  - borghash replaces old / hard to maintain _hashindex.c code.
  - implement ChunkIndex, NSIndex1, FuseVersionsIndex using borghash.HashTableNT.
  - rewrite NSIndex1 (borg 1.x) on-disk format read/write methods in Cython.
  - remove NSIndex (early borg2) data structure / serialization code for repo index.
  - change xxh64 seed for ChunkIndex to invalidate old cache contents.
  - chunks index: show hashtable stats at debug log level, #506.
- check (repository part): build and cache a ChunkIndex.

  check (archives part): use cached ChunkIndex from check (repository part).
- export-tar: switch default to PAX format.
- docs:

  - update URL docs
  - mount: document on-demand loading, perf tips, #7173.
  - borg/borgfs detects internally under which name it was invoked, #8207.
  - better link modern return codes, #8370.
  - binary: using the directory build is faster, #8008.
  - update "Running the tests (using the pypi package)", #6386.
- github CI:

  - temporarily disabled windows CI, #8474.
  - msys2: use pyinstaller 6.10.0.
  - msys2: install rclone.
- tests:

  - rename test files so that pytest default discovery finds them.
  - call register_assert_rewrite before importing borg.testsuite.
  - move conftest.py one directory level higher.
  - remove hashindex tests from selftests (borghash project has own tests).


Version 2.0.0b12 (2024-10-03)
-----------------------------

New features:

- tag: new command to set, add, remove tags.
- repo-list: add tags/hostname/username/comment to default format, reorder, adjust.

  Idea: not putting these into the archive name, but keeping them separate.
- repo-list --short: only print archive IDs (unique IDs, used for scripting).
- implement --match-archives user:USERNAME host:HOSTNAME tags:TAG1,TAG2,...
- allow -a / --match-archives multiple times (logical AND).

  E.g.: borg delete -a home -a user:kenny -a host:kenny-pc
- analyze: list changed chunks' sizes per directory.

Fixes:

- locking: also refresh the lock in other repo methods. avoid repo lock
  getting stale when processing lots of unchanged files, #8442.
- make sure the store gets closed in case of exceptions, #8413.
- msgpack: increase max_buffer_size to ~4GiB, #8440.
- Location.canonical_path: fix protocol and host display, #8446.

Other changes:

- give borgstore.Store a complete levels configuration, #8432.
- add BORG_STORE_DATA_LEVELS=2 env var.
- check: also display archive timestamp.
- vagrant:

  - use python 3.12.6 for binary builds.
  - new testing box based on bento/ubuntu-24.04.
  - install Rust on BSD.


Version 2.0.0b11 (2024-09-26)
-----------------------------

New features:

- Support rclone:// URLs for borg repositories.

  This enables 70+ cloud storage products, including Amazon S3, Backblaze B2,
  Ceph, Dropbox, ftp(s), Google Cloud Storage, Google Drive, Microsoft Azure,
  Microsoft OneDrive, OpenStack Swift, pCloud, Seafile, sftp, SMB / CIFS and
  WebDAV!

  See https://rclone.org/ for more details.
- Parallel operations in same repo from same client (same user/machine).
- Archive series feature, #7930.

  TL;DR: a NAME now identifies a series of identically named archives,
  to identify a specific single archive, use aid:<archive hash>.

  in borg 1.x, we used to put a timestamp into the archive name, because borg1
  required unique archive names.

  borg2 does not require unique archive names, but it encourages you to even
  use a identical archive names within the same SERIES of archives, e.g. you
  could backup user files to archives named "user-files" and system files to
  archives named "system-files".
  that makes matching (e.g. for prune, for the files cache, ...) much simpler
  and borg now KNOWS which archives belong to the same series (because they all
  have the same name).
- info/delete/prune: allow positional NAME argument, e.g.:

  - borg prune --keep-daily 30 <seriesname>
  - borg delete aid:<archive hash>
- create: also archive inode number, #8362

  Borg can use this when using archive series to rebuild the local files cache
  from the previous archive (of the same series) in the repository.

Fixes:

- Remove superfluous repository.list() call. for high latency repos
  (like sftp, cloud), this improves performance of borg check and compact.
- repository.list: refresh lock more frequently
- misc. commands fixed for non-unique archive names
- remote: allow get_manifest method
- files cache: fix rare race condition with data loss potential, #3536
- storelocking: misc. fixes / cleanups

Other changes:

- Cache the chunks index in the repository, #8397.
  Improves high latency repo performance for most commands compared to b10.
- repo-compress: faster by using chunks index rather than repository.list().
- Files cache entries now have both ctime AND mtime.
- Borg updates the ctime and mtime of known and "unchanged" files, #4915.
- Rebuild files cache from previous archive in same series, #8385.
- Reduce RAM usage by splitting the files cache by archive series, #5658.
- Remove AdHocCache, remove BORG_CACHE_IMPL (we only have one implementation).
- Docs: user@ and :port are optional in sftp and ssh URLs.
- CI: re-enable windows build after fixing it.
- Upgrade pyinstaller to 6.10.0.
- Increase IDS_PER_CHUNK, #6945.


Version 2.0.0b10 (2024-09-09)
-----------------------------

New features:

- borgstore based repository, file:, ssh: and sftp: for now, more possible.
- repository stores objects separately now, not using segment files.
  this has more fs overhead, but needs much less I/O because no segment
  files compaction is required anymore. also, no repository index is
  needed anymore because we can directly find the objects by their ID.
- locking: new borgstore based repository locking with automatic stale
  lock removal (if lock does not get refreshed, if lock owner process is dead).
- simultaneous repository access for many borg commands except check/compact.
  the cache lock for adhocwithfiles is still exclusive though, so use
  BORG_CACHE_IMPL=adhoc if you want to try that out using only 1 machine
  and 1 user (that implementation doesn't use a cache lock). When using
  multiple client machines or users, it also works with the default cache.
- delete/prune: much quicker now and can be undone.
- check --repair --undelete-archives: bring archives back from the dead.
- repo-space: manage reserved space in repository (avoid dead-end situation if
  repository filesystem runs full).

Bugs/issues fixed:

- a lot! all linked from PR #8332.

Other changes:

- repository: remove transactions, solved differently and much simpler now
  (convergence and write order primarily).
- repository: replaced precise reference counting with "object exists in repo?"
  and "garbage collection of unused objects".
- cache: remove transactions, remove chunks cache.
  removed LocalCache, BORG_CACHE_IMPL=local, solving all related issues.
  as in beta 9, adhowwithfiles is the default implementation.
- compact: needs the borg key now (run it clientside), -v gives nice stats.
- transfer: archive transfers from borg 1.x need the --from-borg1 option
- check: reimplemented / bigger changes.
- code: got rid of a metric ton of not needed complexity.
  when borg does not need to read borg 1.x repos/archives anymore, after
  users have transferred their archives, even much more can be removed.
- docs: updated / removed outdated stuff
- renamed r* commands to repo-*


Version 2.0.0b9 (2024-07-20)
----------------------------

New features:

- add BORG_CACHE_IMPL, default is "adhocwithfiles" to test the new cache
  implementation, featuring an adhoc non-persistent chunks cache and a
  persistent files cache. See the docs for other values.

  Requires to run "borg check --repair --archives-only" to delete orphaned
  chunks before running "borg compact" to free space! These orphans are
  expected due to the simplified refcounting with the AdHocFilesCache.
- make BORG_EXIT_CODES="modern" the default, #8110
- add BORG_USE_CHUNKS_ARCHIVE env var, #8280
- automatically rebuild cache on exception, #5213

Bug fixes:

- fix Ctrl-C / SIGINT behaviour for pyinstaller-made binaries, #8155
- delete: fix error handling with Ctrl-C
- rcompress: fix error handling with Ctrl-C
- delete: fix error handling when no archive is specified, #8256
- setup.py: fix import error reporting for cythonize import, see #8208
- create: deal with EBUSY, #8123
- benchmark: inherit options --rsh --remote-path, #8099
- benchmark: fix return value, #8113
- key export: fix crash when no path is given, fix exception handling

Other changes:

- setup.py: detect noexec build fs issue, see #8208
- improve acl_get / acl_set error handling (forward port from 1.4-maint)
- allow msgpack 1.1.0
- vagrant: use pyinstaller 6.7.0
- use Python 3.11.9 for binary builds
- require Cython 3.0.3 at least, #8133
- docs: add non-root deployment strategy


Version 2.0.0b8 (2024-02-20)
----------------------------

New features:

- create: add the slashdot hack, update docs, #4685
- BORG_EXIT_CODES=modern: optional more specific return codes (for errors and warnings).

  The default value of this new environment variable is "legacy", which should result in
  a behaviour similar to borg 1.2 and older (only using rc 0, 1 and 2).
  "modern" exit codes are much more specific (see the internals/frontends docs).
- implement "borg version" (shows client and server version), #7829

Fixes:

- docs: CVE-2023-36811 upgrade steps: consider checkpoint archives, #7802
- check/compact: fix spurious reappearance of orphan chunks since borg 1.2, #6687 -
  this consists of 2 fixes:

  - for existing chunks: check --repair: recreate shadow index, #7897 #6687
  - for newly created chunks: update shadow index when doing a double-put, #7896 #5661

  If you have experienced issue #6687, you may want to run borg check --repair
  after upgrading to borg 1.2.7 to recreate the shadow index and get rid of the
  issue for existing chunks.
- check: fix return code for index entry value discrepancies
- LockRoster.modify: no KeyError if element was already gone, #7937
- create --X-from-command: run subcommands with a clean environment, #7916
- list --sort-by: support "archive" as alias of "name", #7873
- fix rc and msg if arg parsing throws an exception, #7885
- PATH: do not accept empty strings, #4221
- fix invalid pattern argument error msg
- zlib legacy decompress fixes, #7883

Other changes:

- replace archive/manifest TAMs by typed repo objects (ro_type), docs, #7670
- crypto: use a one-step kdf for session keys, #7953
- remove recreate --recompress option, use the more efficient repo-wide "rcompress".
- include unistd.h in _chunker.c (fix for Python 3.13)
- allow msgpack 1.0.7
- allow platformdirs 4, #7950
- use and require cython3
- move conftest.py to src/borg/testsuite, #6386
- use less setup.py, use pip and build
- linux: use pkgconfig to find libacl
- borg.logger: use same method params as python logging
- create and use Brewfile, document "brew bundle" install (macOS)
- blacken master branch
- prevent CLI argument issues in scripts/glibc_check.py
- pyproject.toml: exclude source files which have been compiled, #7828
- sdist: dynamically compute readme (long_description)
- init: better borg key export instructions
- scripts/make.py: move clean, build_man, build_usage to there,
  so we do not need to invoke setup.py directly, update docs
- vagrant:

  - use openssl 3.0 on macOS
  - add script for fetching borg binaries from VMs, #7989
  - use generic/openbsd7 box
  - netbsd: test on py311 only
  - remove debian 9 "stretch" box
  - use freebsd 14, #6871
  - use python 3.9.4 for tests, latest python 3.11.7 for binary builds
  - use pyinstaller 6.3.0
- docs:

  - add typical PR workflow to development docs, #7495
  - improve docs for borg with-lock, add example #8024
  - create disk/partition sector backup by disk serial number
  - Add "check.rebuild_refcounts" message
  - not only attack/unsafe, can also be a fs issue, #7853
  - use virtualenv on Cygwin
  - readthedocs: also build offline docs, #7835
  - do not refer to setup.py installation method
  - how to run the testsuite using the dist package
  - requirements are defined in pyproject.toml


Version 2.0.0b7 (2023-09-14)
----------------------------

New features:

- BORG_WORKAROUNDS=authenticated_no_key to extract from authenticated repos
  without having the borg key, #7700

Fixes:

- archive tam verify security fix, fixes CVE-2023-36811
- remote logging/progress: use callback to send queued records, #7662
- make_path_safe: remove test for backslashes, #7651
- benchmark cpu: use sanitized path, #7654
- create: do not try to read parent dir of recursion root, #7746

Other changes:

- always implicitly require archive TAMs (all archives have TAMs since borg 1.2.6)
- always implicitly require manifest TAMs (manifests have TAMs since borg 1.0.9)
- rlist: remove support for {tam} placeholder, archives are now always TAM-authenticated.
- support / test on Python 3.12
- allow msgpack 1.0.6 (which has py312 wheels), #7810
- manifest: move item_keys into config dict (manifest.version == 2 now), #7710
- replace "datetime.utcfromtimestamp" to avoid deprecation warnings with Python 3.12
- properly normalise paths on Windows (forward slashes, integrate drive letter into path)
- Docs:

  - move upgrade / compat. notes to own section, see #7546
  - fix borg delete examples, #7759
  - improve rcreate / related repos docs
  - automated-local.rst: use UUID for consistent udev rule
  - rewrite `borg check` docs, #7578
  - misc. other docs updates
- Tests / CI / Vagrant:

  - major testsuite refactoring: a lot more tests now use pytest, #7626
  - freebsd: add some ACL tests, #7745
  - fix test_disk_full, #7617
  - fix failing test_get_runtime_dir test on OpenBSD, #7719
  - CI: run on ubuntu 22.04
  - CI: test building the docs
  - simplify flake8 config, fix some complaints
  - use pyinstaller 5.13.1 to build the borg binaries


Version 2.0.0b6 (2023-06-11)
----------------------------

New features:

- diff: include changes in ctime and mtime, #7248
- diff: sort JSON output alphabetically
- diff --content-only: option added to ignore metadata changes
- diff: add --format option, #4634
- import-tar --ignore-zeros: new option to support importing concatenated tars, #7432
- debug id-hash / parse-obj / format-obj: new debug commands, #7406
- transfer --compression=C --recompress=M: recompress while transferring, #7529
- extract --continue: continue a previously interrupted extraction, #1356
- prune --list-kept/--list-pruned: only list the kept (or pruned) archives, #7511
- prune --short/--format: enable users to format the list output, #3238
- implement BORG_<CMD>_FORMAT env vars for prune, list, rlist, #5166
- rlist: size and nfiles format keys
- implement unix domain (ipc) socket support, #6183::

      borg serve --socket  # server side (not started automatically!)
      borg -r socket:///path/to/repo ...  # client side

- add get_runtime_dir / BORG_RUNTIME_DIR (contains e.g. .sock and .pid file)
- support shell-style alternatives, like: sh:image.{png,jpg}, #7602

Fixes:

- do not retry on permission errors (pointless)
- transfer: verify chunks we get using assert_id, #7383
- fix config/cache dir compatibility issues, #7445
- xattrs: fix namespace processing on FreeBSD, #6997
- ProgressIndicatorPercent: fix space computation for wide chars, #3027
- delete: remove --cache-only option, #7440.
  for deleting the cache only, use: borg rdelete --cache-only
- borg debug get-obj/put-obj: fixed chunk id
- create: ignore empty paths, print warning, #5637
- extract: support extraction of atime/mtime on win32
- benchmark crud: use TemporaryDirectory below given path, #4706
- Ensure that cli options specified with action=Highlander can only be set once, even
  if the set value is a default value. Add tests for action=Highlander, #7500, #6269.
- Fix argparse error messages from misc. validators (being more specific).
- put security infos into data dir, add BORG_DATA_DIR env var, #5760
- setup.cfg: remove setup_requires (we have a pyproject.toml for that), #7574
- do not crash for empty archives list in borg rlist date based matching, #7522
- sanitize paths during archive creation and extraction, #7108 #7099
- make sure we do not get backslashes into item paths

Other changes:

- allow msgpack 1.0.5 also
- development.lock.txt: upgrade cython to 0.29.35, misc. other upgrades
- clarify platformdirs requirements, #7393.
  3.0.0 is only required for macOS due to breaking changes.
  2.6.0 was the last breaking change for Linux/UNIX.
- mount: improve mountpoint error msgs, see #7496
- more Highlander options, #6269
- Windows: simplify building (just use pip)
- refactor toplevel exception handling, #6018
- remove nonce management, related repo methods (not needed for borg2)
- borg.remote: remove support for borg < 1.1.0
  ($LOG, logging setup, exceptions, rpc tuple data format, version)
- new remote and progress logging, #7604
- borg.logger: add logging debugging functionality
- add function to clear empty directories at end of compact process
- unify scanning and listing of segment dirs / segment files, #7597
- replace `LRUCache` internals with `OrderedDict`
- docs:

  - add installation instructions for Windows
  - improve --one-file-system help and docs (macOS APFS), #5618 #4876
  - BORG_KEY_FILE: clarify docs, #7444
  - installation: add link to OS dependencies, #7356
  - update FAQ about locale/unicode issues, #6999
  - improve mount options rendering, #7359
  - make timestamps in manual pages reproducible.
  - describe performing pull-backups via ssh remote forwarding
  - suggest to use forced command when using remote-forwarding via ssh
  - fix some -a / --match-archives docs issues
  - incl./excl. options header, clarify --path-from-stdin exclusive control
  - add note about MAX_DATA_SIZE
  - update security support docs
  - improve patterns help

- CI / tests / vagrant:

  - added pre-commit for linting purposes, #7476
  - resolved mode bug and added sleep clause for darwin systems, #7470
  - "auto" compressor tests: do not assume zlib is better than lz4, #7363
  - add stretch64 VM with deps built from source
  - misc. other CI / test fixes and updates
  - vagrant: add lunar64 VM, fix packages_netbsd
  - avoid long ids in pytest output
  - tox: package = editable-legacy, #7580
  - tox under fakeroot: fix finding setup_docs, #7391
  - check buzhash chunksize distribution, #7586
  - use debian/bookworm64 box


Version 2.0.0b5 (2023-02-27)
----------------------------

New features:

- create: implement retries for individual fs files
  (e.g. if a file changed while we read it, if a file had an OSError)
- info: add used storage quota, #7121
- transfer: support --progress
- create/recreate/import-tar: add --checkpoint-volume option
- support date-based matching for archive selection,
  add --newer/--older/--newest/--oldest options, #7062 #7296

Fixes:

- disallow --list with --progress, #7219
- create: fix --list --dry-run output for directories, #7209
- do no assume hardlink_master=True if not present, #7175
- fix item_ptrs orphaned chunks of checkpoint archives
- avoid orphan content chunks on BackupOSError, #6709
- transfer: fix bug in obfuscated data upgrade code
- fs.py: fix bug in f-string (thanks mypy!)
- recreate: when --target is given, do not detect "nothing to do", #7254
- locking (win32): deal with os.rmdir/listdir PermissionErrors
- locking: thread id must be parsed as hex from lock file name
- extract: fix mtime when ResourceFork xattr is set (macOS specific), #7234
- recreate: without --chunker-params borg shall not rechunk, #7336
- allow mixing --progress and --list in log-json mode
- add "files changed while reading" to Statistics class, #7354
- fixed keys determination in Statistics.__add__(), #7355

Other changes:

- use local time / local timezone to output timestamps, #7283
- update development.lock.txt, including a setuptools security fix, #7227
- remove --save-space option (does not change behaviour)
- remove part files from final archive
- remove --consider-part-files, related stats code, update docs
- transfer: drop part files
- check: show id of orphaned chunks
- ArchiveItem.cmdline list-of-str -> .command_line str, #7246
- Item: symlinks: rename .source to .target, #7245
- Item: make user/group/uid/gid optional
- create: do not store user/group for stdin data by default, #7249
- extract: chown only if we have u/g info in archived item, #7249
- export-tar: for items w/o uid/gid, default to 0/0, #7249
- fix some uid/gid lookup code / tests for win32
- cache.py: be less verbose during cache sync
- update bash completion script commands and options, #7273
- require and use platformdirs 3.x.x package, tests
- better included/excluded status chars, docs, #7321
- undef NDEBUG for chunker and hashindex (make assert() work)
- assert_id: better be paranoid (add back same crypto code as in old borg), #7362
- check --verify_data: always decompress and call assert_id(), #7362
- make hashindex_compact simpler and probably faster, minor fixes, cleanups, more tests
- hashindex minor fixes, refactor, tweaks, tests
- pyinstaller: remove icon
- validation / placeholders / JSON:

  - implement (text|binary)_to_json: key (text), key_b64 (base64(binary))
  - remove bpath, barchive, bcomment placeholders / JSON keys
  - archive metadata: make sure hostname and username have no surrogate escapes
  - text attributes (like archive name, comment): validate more strictly, #2290
  - transfer: validate archive names and comment before transfer
  - json output: use text_to_json (path, target), #6151
- docs:

  - docs and comments consistency, readability and spelling fixes
  - fix --progress display description, #7180
  - document how borg deals with non-unicode bytes in JSON output
  - document another way to get UTF-8 encoding on stdin/stdout/stderr, #2273
  - pruning interprets timestamps in the local timezone where borg prune runs
  - shellpattern: add license, use copyright/license markup
  - key change-passphrase: fix --encryption value in examples
  - remove BORG_LIBB2_PREFIX (not used any more)
  - Installation: Update Fedora in distribution list, #7357
  - add .readthedocs.yaml (use py311, use non-shallow clone)
- tests:

  - fix archiver tests on Windows, add running the tests to Windows CI
  - fix tox4 passenv issue, #7199
  - github actions updates (fix deprecation warnings)
  - add tests for borg transfer/upgrade
  - fix test hanging reading FIFO when `borg create` failed
  - mypy inspired fixes / updates
  - fix prune tests, prune in localtime
  - do not look up uid 0 / gid 0, but current process uid/gid
  - safe_unlink tests: use os.link to support win32 also
  - fix test_size_on_disk_accurate for large st_blksize, #7250
  - relaxed timestamp comparisons, use same_ts_ns
  - add test for extracted directory mtime
  - use "fail" chunker to test erroneous input file skipping


Version 2.0.0b4 (2022-11-27)
----------------------------

Fixes:

- transfer/upgrade: fix borg < 1.2 chunker_params, #7079
- transfer/upgrade: do not access Item._dict, #7077
- transfer/upgrade: fix crash in borg transfer, #7156
- archive.save(): always use metadata from stats, #7072
- benchmark: fixed TypeError in compression benchmarks, #7075
- fix repository.scan api minimum requirement
- fix args.paths related argparsing, #6994

Other changes:

- tar_filter: recognize .tar.zst as zstd, #7093
- adding performance statistics to borg create, #6991
- docs: add rcompress to usage index
- tests:

  - use github and MSYS2 for Windows CI, #7097
  - win32 and cygwin: test fixes / skip hanging test
  - vagrant / github CI: use python 3.11.0 / 3.10.8
- vagrant:

  - upgrade pyinstaller to 5.6.2 (supports python 3.11)
  - use python 3.11 to build the borg binary

Version 2.0.0b3 (2022-10-02)
----------------------------

Fixes:

- transfer: fix user/group == None crash with borg1 archives
- compressors: avoid memoryview related TypeError
- check: fix uninitialised variable if repo is completely empty, #7034
- do not use version_tuple placeholder in setuptools_scm template, #7024
- get_chunker: fix missing sparse=False argument, #7056

New features:

- rcompress: do a repo-wide (re)compression, #7037
- implement pattern support for --match-archives, #6504
- BORG_LOCK_WAIT=n env var to set default for --lock-wait option, #5279

Other:

- repository.scan: misc. fixes / improvements
- metadata: differentiate between empty/zero and unknown, #6908
- CI: test pyfuse3 with python 3.11
- use more relative imports
- make borg.testsuite.archiver a package, split archiver tests into many modules
- support reading new, improved hashindex header format, #6960.
  added version number and num_empty to the HashHeader, fixed alignment.
- vagrant: upgrade pyinstaller 4.10 -> 5.4.1, use python 3.9.14 for binary build
- item.pyx: use more Cython (faster, uses less memory), #5763


Version 2.0.0b2 (2022-09-10)
----------------------------

Bug fixes:

- xattrs / extended stat: improve exception handling, #6988
- fix and refactor replace_placeholders, #6966

New features:

- support archive timestamps with utc offsets, adapt them when using
  borg transfer to transfer from borg 1.x repos (append +00:00 for UTC).
- create/recreate/import-tar --timestamp: accept giving timezone via
  its utc offset. defaults to local timezone, if no utc offset is given.

Other changes:

- chunks: have separate encrypted metadata (ctype, clevel, csize, size)

  chunk = enc_meta_len16 + encrypted(msgpacked(meta)) + encrypted(compressed(data)).

  this breaks repo format compatibility, you need to create fresh repos!
- repository api: flags support, #6982
- OpenBSD only - statically link OpenSSL, #6474.
  Avoid conflicting with shared libcrypto from the base OS pulled in via dependencies.
- restructured source code
- update diagrams to odg format, #6928

Version 2.0.0b1 (2022-08-08)
----------------------------

New features:

- massively increase archive metadata stream size limit, #1473.
  currently rather testing the code, scalability will improve later, see #6945.
- rcreate --copy-crypt-key: copy crypt_key from key of other repo, #6710.
  default: create new, random authenticated encryption key.
- prune/delete --checkpoint-interval=1800 and ctrl-c/SIGINT support, #6284

Fixes:

- ctrl-c must not kill important subprocesses, #6912
- transfer: check whether ID hash method and chunker secret are same.
  add PlaintextKey and AuthenticatedKey support to uses_same_id_hash function.
- check: try harder to create the key, #5719
- SaveFile: use a custom mkstemp with mode support, #6933, #6400
- make setuptools happy, #6874
- fix misc. compiler warnings
- list: fix {flags:<WIDTH>} formatting, #6081

Other changes:

- new crypto does not need to call ._assert_id(), update code and docs.
  https://github.com/borgbackup/borg/pull/6463#discussion_r925436156
- check: --verify-data does not need to decompress with new crypto modes
- Key: crypt_key instead of enc_key + enc_hmac_key, #6611
- misc. docs updates and improvements
- CI: test on macOS 12 without fuse / fuse tests
- repository: add debug logging for issue #6687
- _version.py: remove trailing blank, add LF at EOF (make pep8 checker happy)


Version 2.0.0a4 (2022-07-17)
----------------------------

New features:

- recreate: consider level for recompression, #6698, #3622

Other changes:

- stop using libdeflate
- CI: add mypy (if we add type hints, it can do type checking)
- big changes to the source code:

  - split up archiver module, transform it into a package
  - use Black for automated code formatting
  - remove some legacy code
  - adapt/fix code for mypy
- use language_level = 3str for cython (this will be the default in cython 3)
- docs: document HardLinkManager and hlid, #2388


Version 2.0.0a3 (2022-07-04)
----------------------------

Fixes:

- check repo version, accept old repos only for --other-repo (e.g. rcreate/transfer).
  v2 is the default repo version for borg 2.0. v1 repos must only be used in a
  read-only way, e.g. for --other-repo=V1_REPO with borg init and borg transfer!

New features:

- transfer: --upgrader=NoOp is the default.
  This is to support general-purpose transfer of archives between related borg2
  repos.
- transfer: --upgrader=From12To20 must be used to transfer (and convert) archives
  from borg 1.2 repos to borg 2.0 repos.

Other changes:

- removed some deprecated options
- removed -P (aka --prefix) option, #6806. The option -a (aka --glob-archives)
  can be used for same purpose and is more powerful, e.g.: -a 'PREFIX*'
- rcreate: always use argon2 kdf for new repos, #6820
- rcreate: remove legacy encryption modes for new repos, #6490


Version 2.0.0a2 (2022-06-26)
----------------------------

Changes:

- split repo and archive name into separate args, #948

  - use -r or --repo or BORG_REPO env var to give the repository
  - use --other-repo or BORG_OTHER_REPO to give another repo (e.g. borg transfer)
  - use positional argument for archive name or `-a ARCH_GLOB`
- remove support for scp-style repo specification, use ssh://...
- simplify stats output: repo ops -> repo stats, archive ops -> archive stats
- repository index: add payload size (==csize) and flags to NSIndex entries
- repository index: set/query flags, iteration over flagged items (NSIndex)
- repository: sync write file in get_fd
- stats: deduplicated size now, was deduplicated compressed size in borg 1.x
- remove csize support at most places in the code (chunks index, stats, get_size,
  Item.chunks)
- replace problematic/ugly hardlink_master approach of borg 1.x by:

  - symmetric hlid (all hardlinks pointing to same inode have same hlid)
  - all archived hardlinked regular files have a chunks list
- borg rcreate --other-repo=OTHER_REPO: reuse key material from OTHER_REPO, #6554.
  This is useful if you want to use borg transfer to transfer archives from an
  existing borg 1.1/1.2 repo. If the chunker secret and the id key and algorithm
  stay the same, the deduplication will also work between past and future backups.
- borg transfer:

  - efficiently copy archives from a borg 1.1/1.2 repo to a new repo.
    uses deduplication and does not decompress/recompress file content data.
  - does some cleanups / fixes / conversions:

    - disallow None value for .user/group/chunks/chunks_healthy
    - cleanup msgpack related str/bytes mess, use new msgpack spec, #968
    - obfuscation: fix byte order for size, #6701
    - compression: use the 2 bytes for type and level, #6698
    - use version 2 for new archives
    - convert timestamps int/bigint -> msgpack.Timestamp, see #2323
    - all hardlinks have chunks, maybe chunks_healthy, hlid
    - remove the zlib type bytes hack
    - make sure items with chunks have precomputed size
    - removes the csize element from the tuples in the Item.chunks list
    - clean item of attic 0.13 'acl' bug remnants
- crypto: see 1.3.0a1 log entry
- removed "borg upgrade" command (not needed any more)
- compact: removed --cleanup-commits option
- docs: fixed quickstart and usage docs with new cli command syntax
- docs: removed the parts talking about potential AES-CTR mode issues
  (we will not use that any more).


Version 1.3.0a1 (2022-04-15)
----------------------------

Although this was released as 1.3.0a1, it can be also seen as 2.0.0a1 as it was
later decided to do breaking changes and thus the major release number had to
be increased (thus, there will not be a 1.3.0 release, but 2.0.0).

New features:

- init: new --encryption=(repokey|keyfile)-[blake2-](aes-ocb|chacha20-poly1305)

  - New, better, faster crypto (see encryption-aead diagram in the docs), #6463.
  - New AEAD cipher suites: AES-OCB and CHACHA20-POLY1305.
  - Session keys are derived via HKDF from random session id and master key.
  - Nonces/MessageIVs are counters starting from 0 for each session.
  - AAD: chunk id, key type, messageIV, sessionID are now authenticated also.
  - Solves the potential AES-CTR mode counter management issues of the legacy crypto.
- init: --key-algorithm=argon2 (new default KDF, older pbkdf2 also still available)

  borg key change-passphrase / change-location keeps the key algorithm unchanged.
- key change-algorithm: to upgrade existing keys to argon2 or downgrade to pbkdf2.

  We recommend you to upgrade unless you have to keep the key compatible with older versions of borg.
- key change-location: usable for repokey <-> keyfile location change
- benchmark cpu: display benchmarks of cpu bound stuff
- export-tar: new --tar-format=PAX (default: GNU)
- import-tar/export-tar: can use PAX format for ctime and atime support
- import-tar/export-tar: --tar-format=BORG: roundtrip ALL item metadata, #5830
- repository: create and use version 2 repos only for now
- repository: implement PUT2: header crc32, overall xxh64, #1704

Other changes:

- require python >= 3.9, #6315
- simplify libs setup, #6482
- unbundle most bundled 3rd party code, use libs, #6316
- use libdeflate.crc32 (Linux and all others) or zlib.crc32 (macOS)
- repository: code cleanups / simplifications
- internal crypto api: speedups / cleanups / refactorings / modernisation
- remove "borg upgrade" support for "attic backup" repos
- remove PassphraseKey code and borg key migrate-to-repokey command
- OpenBSD: build borg with OpenSSL (not: LibreSSL), #6474
- remove support for LibreSSL, #6474
- remove support for OpenSSL < 1.1.1


================================================
FILE: docs/changes_0.x.rst
================================================
.. _changelog_0x:

Change Log 0.x
==============

Version 0.30.0 (2016-01-23)
---------------------------

Compatibility notes:

- The new default logging level is WARNING. Previously, it was INFO, which was
  more verbose. Use -v (or --info) to show once again log level INFO messages.
  See the "general" section in the usage docs.
- For borg create, you need --list (in addition to -v) to see the long file
  list (was needed so you can have e.g. --stats alone without the long list)
- See below about BORG_DELETE_I_KNOW_WHAT_I_AM_DOING (was:
  BORG_CHECK_I_KNOW_WHAT_I_AM_DOING)

Bug fixes:

- fix crash when using borg create --dry-run --keep-tag-files, #570
- make sure teardown with cleanup happens for Cache and RepositoryCache,
  avoiding leftover locks and TEMP dir contents, #285 (partially), #548
- fix locking KeyError, partial fix for #502
- log stats consistently, #526
- add abbreviated weekday to timestamp format, fixes #496
- strip whitespace when loading exclusions from file
- unset LD_LIBRARY_PATH before invoking ssh, fixes strange OpenSSL library
  version warning when using the borg binary, #514
- add some error handling/fallback for C library loading, #494
- added BORG_DELETE_I_KNOW_WHAT_I_AM_DOING for check in "borg delete", #503
- remove unused "repair" rpc method name

New features:

- borg create: implement exclusions using regular expression patterns.
- borg create: implement inclusions using patterns.
- borg extract: support patterns, #361
- support different styles for patterns:

  - fnmatch (`fm:` prefix, default when omitted), like borg <= 0.29.
  - shell (`sh:` prefix) with `*` not matching directory separators and
    `**/` matching 0..n directories
  - path prefix (`pp:` prefix, for unifying borg create pp1 pp2 into the
    patterns system), semantics like in borg <= 0.29
  - regular expression (`re:`), new!
- --progress option for borg upgrade (#291) and borg delete <archive>
- update progress indication more often (e.g. for borg create within big
  files or for borg check repo), #500
- finer chunker granularity for items metadata stream, #547, #487
- borg create --list is now used (in addition to -v) to enable the verbose
  file list output
- display borg version below tracebacks, #532

Other changes:

- hashtable size (and thus: RAM and disk consumption) follows a growth policy:
  grows fast while small, grows slower when getting bigger, #527
- Vagrantfile: use pyinstaller 3.1 to build binaries, freebsd sqlite3 fix,
  fixes #569
- no separate binaries for centos6 any more because the generic linux binaries
  also work on centos6 (or in general: on systems with a slightly older glibc
  than debian7
- dev environment: require virtualenv<14.0 so we get a py32 compatible pip
- docs:

  - add space-saving chunks.archive.d trick to FAQ
  - important: clarify -v and log levels in usage -> general, please read!
  - sphinx configuration: create a simple man page from usage docs
  - add a repo server setup example
  - disable unneeded SSH features in authorized_keys examples for security.
  - borg prune only knows "--keep-within" and not "--within"
  - add gource video to resources docs, #507
  - add netbsd install instructions
  - authors: make it more clear what refers to borg and what to attic
  - document standalone binary requirements, #499
  - rephrase the mailing list section
  - development docs: run build_api and build_usage before tagging release
  - internals docs: hash table max. load factor is 0.75 now
  - markup, typo, grammar, phrasing, clarifications and other fixes.
  - add gcc gcc-c++ to redhat/fedora/corora install docs, fixes #583


Version 0.29.0 (2015-12-13)
---------------------------

Compatibility notes:

- When upgrading to 0.29.0, you need to upgrade client as well as server
  installations due to the locking and command-line interface changes; otherwise
  you'll get an error message about an RPC protocol mismatch or a wrong command-line
  option.
  If you run a server that needs to support both old and new clients, it is
  suggested that you have a "borg-0.28.2" and a "borg-0.29.0" command.
  clients then can choose via e.g. "borg --remote-path=borg-0.29.0 ...".
- The default waiting time for a lock changed from infinity to 1 second for a
  better interactive user experience. If the repo you want to access is
  currently locked, borg will now terminate after 1s with an error message.
  If you have scripts that should wait for the lock for a longer time, use
  --lock-wait N (with N being the maximum wait time in seconds).

Bug fixes:

- hash table tuning (better chosen hashtable load factor 0.75 and prime initial
  size of 1031 gave ~1000x speedup in some scenarios)
- avoid creation of an orphan lock for one case, #285
- --keep-tag-files: fix file mode and multiple tag files in one directory, #432
- fixes for "borg upgrade" (attic repo converter), #466
- remove --progress isatty magic (and also --no-progress option) again, #476
- borg init: display proper repo URL
- fix format of umask in help pages, #463

New features:

- implement --lock-wait, support timeout for UpgradableLock, #210
- implement borg break-lock command, #157
- include system info below traceback, #324
- sane remote logging, remote stderr, #461:

  - remote log output: intercept it and log it via local logging system,
    with "Remote: " prefixed to message. log remote tracebacks.
  - remote stderr: output it to local stderr with "Remote: " prefixed.
- add --debug and --info (same as --verbose) to set the log level of the
  builtin logging configuration (which otherwise defaults to warning), #426
  note: there are few messages emitted at DEBUG level currently.
- optionally configure logging via env var BORG_LOGGING_CONF
- add --filter option for status characters: e.g. to show only the added
  or modified files (and also errors), use "borg create -v --filter=AME ...".
- more progress indicators, #394
- use ISO-8601 date and time format, #375
- "borg check --prefix" to restrict archive checking to that name prefix, #206

Other changes:

- hashindex_add C implementation (speed up cache re-sync for new archives)
- increase FUSE read_size to 1024 (speed up metadata operations)
- check/delete/prune --save-space: free unused segments quickly, #239
- increase rpc protocol version to 2 (see also Compatibility notes), #458
- silence borg by default (via default log level WARNING)
- get rid of C compiler warnings, #391
- upgrade OS X FUSE to 3.0.9 on the OS X binary build system
- use python 3.5.1 to build binaries
- docs:

  - new mailing list borgbackup@python.org, #468
  - readthedocs: color and logo improvements
  - load coverage icons over SSL (avoids mixed content)
  - more precise binary installation steps
  - update release procedure docs about OS X FUSE
  - FAQ entry about unexpected 'A' status for unchanged file(s), #403
  - add docs about 'E' file status
  - add "borg upgrade" docs, #464
  - add developer docs about output and logging
  - clarify encryption, add note about client-side encryption
  - add resources section, with videos, talks, presentations, #149
  - Borg moved to Arch Linux [community]
  - fix wrong installation instructions for archlinux


Version 0.28.2 (2015-11-15)
---------------------------

New features:

- borg create --exclude-if-present TAGFILE - exclude directories that have the
  given file from the backup. You can additionally give --keep-tag-files to
  preserve just the directory roots and the tag-files (but not back up other
  directory contents), #395, attic #128, attic #142

Other changes:

- do not create docs sources at build time (just have them in the repo),
  completely remove have_cython() hack, do not use the "mock" library at build
  time, #384
- avoid hidden import, make it easier for PyInstaller, easier fix for #218
- docs:

  - add description of item flags / status output, fixes #402
  - explain how to regenerate usage and API files (build_api or
    build_usage) and when to commit usage files directly into git, #384
  - minor install docs improvements


Version 0.28.1 (2015-11-08)
---------------------------

Bug fixes:

- do not try to build api / usage docs for production install,
  fixes unexpected "mock" build dependency, #384

Other changes:

- avoid using msgpack.packb at import time
- fix formatting issue in changes.rst
- fix build on readthedocs


Version 0.28.0 (2015-11-08)
---------------------------

Compatibility notes:

- changed return codes (exit codes), see docs. in short:
  old: 0 = ok, 1 = error. now: 0 = ok, 1 = warning, 2 = error

New features:

- refactor return codes (exit codes), fixes #61
- add --show-rc option enable "terminating with X status, rc N" output, fixes 58, #351
- borg create backups atime and ctime additionally to mtime, fixes #317
  - extract: support atime additionally to mtime
  - FUSE: support ctime and atime additionally to mtime
- support borg --version
- emit a warning if we have a slow msgpack installed
- borg list --prefix=thishostname- REPO, fixes #205
- Debug commands (do not use except if you know what you do: debug-get-obj,
  debug-put-obj, debug-delete-obj, debug-dump-archive-items.

Bug fixes:

- setup.py: fix bug related to BORG_LZ4_PREFIX processing
- fix "check" for repos that have incomplete chunks, fixes #364
- borg mount: fix unlocking of repository at umount time, fixes #331
- fix reading files without touching their atime, #334
- non-ascii ACL fixes for Linux, FreeBSD and OS X, #277
- fix acl_use_local_uid_gid() and add a test for it, attic #359
- borg upgrade: do not upgrade repositories in place by default, #299
- fix cascading failure with the index conversion code, #269
- borg check: implement 'cmdline' archive metadata value decoding, #311
- fix RobustUnpacker, it missed some metadata keys (new atime and ctime keys
  were missing, but also bsdflags). add check for unknown metadata keys.
- create from stdin: also save atime, ctime (cosmetic)
- use default_notty=False for confirmations, fixes #345
- vagrant: fix msgpack installation on centos, fixes #342
- deal with unicode errors for symlinks in same way as for regular files and
  have a helpful warning message about how to fix wrong locale setup, fixes #382
- add ACL keys the RobustUnpacker must know about

Other changes:

- improve file size displays, more flexible size formatters
- explicitly commit to the units standard, #289
- archiver: add E status (means that an error occurred when processing this
  (single) item
- do binary releases via "github releases", closes #214
- create: use -x and --one-file-system (was: --do-not-cross-mountpoints), #296
- a lot of changes related to using "logging" module and screen output, #233
- show progress display if on a tty, output more progress information, #303
- factor out status output so it is consistent, fix surrogates removal,
  maybe fixes #309
- move away from RawConfigParser to ConfigParser
- archive checker: better error logging, give chunk_id and sequence numbers
  (can be used together with borg debug-dump-archive-items).
- do not mention the deprecated passphrase mode
- emit a deprecation warning for --compression N (giving a just a number)
- misc .coverragerc fixes (and coverage measurement improvements), fixes #319
- refactor confirmation code, reduce code duplication, add tests
- prettier error messages, fixes #307, #57
- tests:

  - add a test to find disk-full issues, #327
  - travis: also run tests on Python 3.5
  - travis: use tox -r so it rebuilds the tox environments
  - test the generated pyinstaller-based binary by archiver unit tests, #215
  - vagrant: tests: announce whether fakeroot is used or not
  - vagrant: add vagrant user to fuse group for debianoid systems also
  - vagrant: llfuse install on darwin needs pkgconfig installed
  - vagrant: use pyinstaller from develop branch, fixes #336
  - benchmarks: test create, extract, list, delete, info, check, help, fixes #146
  - benchmarks: test with both the binary and the python code
  - archiver tests: test with both the binary and the python code, fixes #215
  - make basic test more robust
- docs:

  - moved docs to borgbackup.readthedocs.org, #155
  - a lot of fixes and improvements, use mobile-friendly RTD standard theme
  - use zlib,6 compression in some examples, fixes #275
  - add missing rename usage to docs, closes #279
  - include the help offered by borg help <topic> in the usage docs, fixes #293
  - include a list of major changes compared to attic into README, fixes #224
  - add OS X install instructions, #197
  - more details about the release process, #260
  - fix linux glibc requirement (binaries built on debian7 now)
  - build: move usage and API generation to setup.py
  - update docs about return codes, #61
  - remove api docs (too much breakage on rtd)
  - borgbackup install + basics presentation (asciinema)
  - describe the current style guide in documentation
  - add section about debug commands
  - warn about not running out of space
  - add example for rename
  - improve chunker params docs, fixes #362
  - minor development docs update


Version 0.27.0 (2015-10-07)
---------------------------

New features:

- "borg upgrade" command - attic -> borg one time converter / migration, #21
- temporary hack to avoid using lots of disk space for chunks.archive.d, #235:
  To use it: rm -rf chunks.archive.d ; touch chunks.archive.d
- respect XDG_CACHE_HOME, attic #181
- add support for arbitrary SSH commands, attic #99
- borg delete --cache-only REPO (only delete cache, not REPO), attic #123


Bug fixes:

- use Debian 7 (wheezy) to build pyinstaller borgbackup binaries, fixes slow
  down observed when running the Centos6-built binary on Ubuntu, #222
- do not crash on empty lock.roster, fixes #232
- fix multiple issues with the cache config version check, #234
- fix segment entry header size check, attic #352
  plus other error handling improvements / code deduplication there.
- always give segment and offset in repo IntegrityErrors


Other changes:

- stop producing binary wheels, remove docs about it, #147
- docs:
  - add warning about prune
  - generate usage include files only as needed
  - development docs: add Vagrant section
  - update / improve / reformat FAQ
  - hint to single-file pyinstaller binaries from README


Version 0.26.1 (2015-09-28)
---------------------------

This is a minor update, just docs and new pyinstaller binaries.

- docs update about python and binary requirements
- better docs for --read-special, fix #220
- re-built the binaries, fix #218 and #213 (glibc version issue)
- update web site about single-file pyinstaller binaries

Note: if you did a python-based installation, there is no need to upgrade.


Version 0.26.0 (2015-09-19)
---------------------------

New features:

- Faster cache sync (do all in one pass, remove tar/compression stuff), #163
- BORG_REPO env var to specify the default repo, #168
- read special files as if they were regular files, #79
- implement borg create --dry-run, attic issue #267
- Normalize paths before pattern matching on OS X, #143
- support OpenBSD and NetBSD (except xattrs/ACLs)
- support / run tests on Python 3.5

Bug fixes:

- borg mount repo: use absolute path, attic #200, attic #137
- chunker: use off_t to get 64bit on 32bit platform, #178
- initialize chunker fd to -1, so it's not equal to STDIN_FILENO (0)
- fix reaction to "no" answer at delete repo prompt, #182
- setup.py: detect lz4.h header file location
- to support python < 3.2.4, add less buggy argparse lib from 3.2.6 (#194)
- fix for obtaining ``char *`` from temporary Python value (old code causes
  a compile error on Mint 17.2)
- llfuse 0.41 install troubles on some platforms, require < 0.41
  (UnicodeDecodeError exception due to non-ascii llfuse setup.py)
- cython code: add some int types to get rid of unspecific python add /
  subtract operations (avoid ``undefined symbol FPE_``... error on some platforms)
- fix verbose mode display of stdin backup
- extract: warn if a include pattern never matched, fixes #209,
  implement counters for Include/ExcludePatterns
- archive names with slashes are invalid, attic issue #180
- chunker: add a check whether the POSIX_FADV_DONTNEED constant is defined -
  fixes building on OpenBSD.

Other changes:

- detect inconsistency / corruption / hash collision, #170
- replace versioneer with setuptools_scm, #106
- docs:

  - pkg-config is needed for llfuse installation
  - be more clear about pruning, attic issue #132
- unit tests:

  - xattr: ignore security.selinux attribute showing up
  - ext3 seems to need a bit more space for a sparse file
  - do not test lzma level 9 compression (avoid MemoryError)
  - work around strange mtime granularity issue on netbsd, fixes #204
  - ignore st_rdev if file is not a block/char device, fixes #203
  - stay away from the setgid and sticky mode bits
- use Vagrant to do easy cross-platform testing (#196), currently:

  - Debian 7 "wheezy" 32bit, Debian 8 "jessie" 64bit
  - Ubuntu 12.04 32bit, Ubuntu 14.04 64bit
  - Centos 7 64bit
  - FreeBSD 10.2 64bit
  - OpenBSD 5.7 64bit
  - NetBSD 6.1.5 64bit
  - Darwin (OS X Yosemite)


Version 0.25.0 (2015-08-29)
---------------------------

Compatibility notes:

- lz4 compression library (liblz4) is a new requirement (#156)
- the new compression code is very compatible: as long as you stay with zlib
  compression, older borg releases will still be able to read data from a
  repo/archive made with the new code (note: this is not the case for the
  default "none" compression, use "zlib,0" if you want a "no compression" mode
  that can be read by older borg). Also the new code is able to read repos and
  archives made with older borg versions (for all zlib levels  0..9).

Deprecations:

- --compression N (with N being a number, as in 0.24) is deprecated.
  We keep the --compression 0..9 for now not to break scripts, but it is
  deprecated and will be removed later, so better fix your scripts now:
  --compression 0 (as in 0.24) is the same as --compression zlib,0 (now).
  BUT: if you do not want compression, use --compression none
  (which is the default).
  --compression 1 (in 0.24) is the same as --compression zlib,1 (now)
  --compression 9 (in 0.24) is the same as --compression zlib,9 (now)

New features:

- create --compression none (default, means: do not compress, just pass through
  data "as is". this is more efficient than zlib level 0 as used in borg 0.24)
- create --compression lz4 (super-fast, but not very high compression)
- create --compression zlib,N (slower, higher compression, default for N is 6)
- create --compression lzma,N (slowest, highest compression, default N is 6)
- honor the nodump flag (UF_NODUMP) and do not back up such items
- list --short just outputs a simple list of the files/directories in an archive

Bug fixes:

- fixed --chunker-params parameter order confusion / malfunction, fixes #154
- close fds of segments we delete (during compaction)
- close files which fell out the lrucache
- fadvise DONTNEED now is only called for the byte range actually read, not for
  the whole file, fixes #158.
- fix issue with negative "all archives" size, fixes #165
- restore_xattrs: ignore if setxattr fails with EACCES, fixes #162

Other changes:

- remove fakeroot requirement for tests, tests run faster without fakeroot
  (test setup does not fail any more without fakeroot, so you can run with or
  without fakeroot), fixes #151 and #91.
- more tests for archiver
- recover_segment(): don't assume we have an fd for segment
- lrucache refactoring / cleanup, add dispose function, py.test tests
- generalize hashindex code for any key length (less hardcoding)
- lock roster: catch file not found in remove() method and ignore it
- travis CI: use requirements file
- improved docs:

  - replace hack for llfuse with proper solution (install libfuse-dev)
  - update docs about compression
  - update development docs about fakeroot
  - internals: add some words about lock files / locking system
  - support: mention BountySource and for what it can be used
  - theme: use a lighter green
  - add pypi, wheel, dist package based install docs
  - split install docs into system-specific preparations and generic instructions


Version 0.24.0 (2015-08-09)
---------------------------

Incompatible changes (compared to 0.23):

- borg now always issues --umask NNN option when invoking another borg via ssh
  on the repository server. By that, it's making sure it uses the same umask
  for remote repos as for local ones. Because of this, you must upgrade both
  server and client(s) to 0.24.
- the default umask is 077 now (if you do not specify via --umask) which might
  be a different one as you used previously. The default umask avoids that
  you accidentally give access permissions for group and/or others to files
  created by borg (e.g. the repository).

Deprecations:

- "--encryption passphrase" mode is deprecated, see #85 and #97.
  See the new "--encryption repokey" mode for a replacement.

New features:

- borg create --chunker-params ... to configure the chunker, fixes #16
  (attic #302, attic #300, and somehow also #41).
  This can be used to reduce memory usage caused by chunk management overhead,
  so borg does not create a huge chunks index/repo index and eats all your RAM
  if you back up lots of data in huge files (like VM disk images).
  See docs/misc/create_chunker-params.txt for more information.
- borg info now reports chunk counts in the chunk index.
- borg create --compression 0..9 to select zlib compression level, fixes #66
  (attic #295).
- borg init --encryption repokey (to store the encryption key into the repo),
  fixes #85
- improve at-end error logging, always log exceptions and set exit_code=1
- LoggedIO: better error checks / exceptions / exception handling
- implement --remote-path to allow non-default-path borg locations, #125
- implement --umask M and use 077 as default umask for better security, #117
- borg check: give a named single archive to it, fixes #139
- cache sync: show progress indication
- cache sync: reimplement the chunk index merging in C

Bug fixes:

- fix segfault that happened for unreadable files (chunker: n needs to be a
  signed size_t), #116
- fix the repair mode, #144
- repo delete: add destroy to allowed rpc methods, fixes issue #114
- more compatible repository locking code (based on mkdir), maybe fixes #92
  (attic #317, attic #201).
- better Exception msg if no Borg is installed on the remote repo server, #56
- create a RepositoryCache implementation that can cope with >2GiB,
  fixes attic #326.
- fix Traceback when running check --repair, attic #232
- clarify help text, fixes #73.
- add help string for --no-files-cache, fixes #140

Other changes:

- improved docs:

  - added docs/misc directory for misc. writeups that won't be included
    "as is" into the html docs.
  - document environment variables and return codes (attic #324, attic #52)
  - web site: add related projects, fix web site url, IRC #borgbackup
  - Fedora/Fedora-based install instructions added to docs
  - Cygwin-based install instructions added to docs
  - updated AUTHORS
  - add FAQ entries about redundancy / integrity
  - clarify that borg extract uses the cwd as extraction target
  - update internals doc about chunker params, memory usage and compression
  - added docs about development
  - add some words about resource usage in general
  - document how to back up a raw disk
  - add note about how to run borg from virtual env
  - add solutions for (ll)fuse installation problems
  - document what borg check does, fixes #138
  - reorganize borgbackup.github.io sidebar, prev/next at top
  - deduplicate and refactor the docs / README.rst

- use borg-tmp as prefix for temporary files / directories
- short prune options without "keep-" are deprecated, do not suggest them
- improved tox configuration
- remove usage of unittest.mock, always use mock from pypi
- use entrypoints instead of scripts, for better use of the wheel format and
  modern installs
- add requirements.d/development.txt and modify tox.ini
- use travis-ci for testing based on Linux and (new) OS X
- use coverage.py, pytest-cov and codecov.io for test coverage support

I forgot to list some stuff already implemented in 0.23.0, here they are:

New features:

- efficient archive list from manifest, meaning a big speedup for slow
  repo connections and "list <repo>", "delete <repo>", "prune" (attic #242,
  attic #167)
- big speedup for chunks cache sync (esp. for slow repo connections), fixes #18
- hashindex: improve error messages

Other changes:

- explicitly specify binary mode to open binary files
- some easy micro optimizations


Version 0.23.0 (2015-06-11)
---------------------------

Incompatible changes (compared to attic, fork related):

- changed sw name and cli command to "borg", updated docs
- package name (and name in urls) uses "borgbackup" to have fewer collisions
- changed repo / cache internal magic strings from ATTIC* to BORG*,
  changed cache location to .cache/borg/ - this means that it currently won't
  accept attic repos (see issue #21 about improving that)

Bug fixes:

- avoid defect python-msgpack releases, fixes attic #171, fixes attic #185
- fix traceback when trying to do unsupported passphrase change, fixes attic #189
- datetime does not like the year 10.000, fixes attic #139
- fix "info" all archives stats, fixes attic #183
- fix parsing with missing microseconds, fixes attic #282
- fix misleading hint the fuse ImportError handler gave, fixes attic #237
- check unpacked data from RPC for tuple type and correct length, fixes attic #127
- fix Repository._active_txn state when lock upgrade fails
- give specific path to xattr.is_enabled(), disable symlink setattr call that
  always fails
- fix test setup for 32bit platforms, partial fix for attic #196
- upgraded versioneer, PEP440 compliance, fixes attic #257

New features:

- less memory usage: add global option --no-cache-files
- check --last N (only check the last N archives)
- check: sort archives in reverse time order
- rename repo::oldname newname (rename repository)
- create -v output more informative
- create --progress (backup progress indicator)
- create --timestamp (utc string or reference file/dir)
- create: if "-" is given as path, read binary from stdin
- extract: if --stdout is given, write all extracted binary data to stdout
- extract --sparse (simple sparse file support)
- extra debug information for 'fread failed'
- delete <repo> (deletes whole repo + local cache)
- FUSE: reflect deduplication in allocated blocks
- only allow whitelisted RPC calls in server mode
- normalize source/exclude paths before matching
- use posix_fadvise not to spoil the OS cache, fixes attic #252
- toplevel error handler: show tracebacks for better error analysis
- sigusr1 / sigint handler to print current file infos - attic PR #286
- RPCError: include the exception args we get from remote

Other changes:

- source: misc. cleanups, pep8, style
- docs and faq improvements, fixes, updates
- cleanup crypto.pyx, make it easier to adapt to other AES modes
- do os.fsync like recommended in the python docs
- source: Let chunker optionally work with os-level file descriptor.
- source: Linux: remove duplicate os.fsencode calls
- source: refactor _open_rb code a bit, so it is more consistent / regular
- source: refactor indicator (status) and item processing
- source: use py.test for better testing, flake8 for code style checks
- source: fix tox >=2.0 compatibility (test runner)
- pypi package: add python version classifiers, add FreeBSD to platforms


Attic Changelog
---------------

Here you can see the full list of changes between each Attic release until Borg
forked from Attic:

Version 0.17
~~~~~~~~~~~~

(bugfix release, released on X)

- Fix hashindex ARM memory alignment issue (#309)
- Improve hashindex error messages (#298)

Version 0.16
~~~~~~~~~~~~

(bugfix release, released on May 16, 2015)

- Fix typo preventing the security confirmation prompt from working (#303)
- Improve handling of systems with improperly configured file system encoding (#289)
- Fix "All archives" output for attic info. (#183)
- More user friendly error message when repository key file is not found (#236)
- Fix parsing of iso 8601 timestamps with zero microseconds (#282)

Version 0.15
~~~~~~~~~~~~

(bugfix release, released on Apr 15, 2015)

- xattr: Be less strict about unknown/unsupported platforms (#239)
- Reduce repository listing memory usage (#163).
- Fix BrokenPipeError for remote repositories (#233)
- Fix incorrect behavior with two character directory names (#265, #268)
- Require approval before accessing relocated/moved repository (#271)
- Require approval before accessing previously unknown unencrypted repositories (#271)
- Fix issue with hash index files larger than 2GB.
- Fix Python 3.2 compatibility issue with noatime open() (#164)
- Include missing pyx files in dist files (#168)

Version 0.14
~~~~~~~~~~~~

(feature release, released on Dec 17, 2014)

- Added support for stripping leading path segments (#95)
  "attic extract --strip-segments X"
- Add workaround for old Linux systems without acl_extended_file_no_follow (#96)
- Add MacPorts' path to the default openssl search path (#101)
- HashIndex improvements, eliminates unnecessary IO on low memory systems.
- Fix "Number of files" output for attic info. (#124)
- limit create file permissions so files aren't read while restoring
- Fix issue with empty xattr values (#106)

Version 0.13
~~~~~~~~~~~~

(feature release, released on Jun 29, 2014)

- Fix sporadic "Resource temporarily unavailable" when using remote repositories
- Reduce file cache memory usage (#90)
- Faster AES encryption (utilizing AES-NI when available)
- Experimental Linux, OS X and FreeBSD ACL support (#66)
- Added support for backup and restore of BSDFlags (OSX, FreeBSD) (#56)
- Fix bug where xattrs on symlinks were not correctly restored
- Added cachedir support. CACHEDIR.TAG compatible cache directories
  can now be excluded using ``--exclude-caches`` (#74)
- Fix crash on extreme mtime timestamps (year 2400+) (#81)
- Fix Python 3.2 specific lockf issue (EDEADLK)

Version 0.12
~~~~~~~~~~~~

(feature release, released on April 7, 2014)

- Python 3.4 support (#62)
- Various documentation improvements a new style
- ``attic mount`` now supports mounting an entire repository not only
  individual archives (#59)
- Added option to restrict remote repository access to specific path(s):
  ``attic serve --restrict-to-path X`` (#51)
- Include "all archives" size information in "--stats" output. (#54)
- Added ``--stats`` option to ``attic delete`` and ``attic prune``
- Fixed bug where ``attic prune`` used UTC instead of the local time zone
  when determining which archives to keep.
- Switch to SI units (Power of 1000 instead 1024) when printing file sizes

Version 0.11
~~~~~~~~~~~~

(feature release, released on March 7, 2014)

- New "check" command for repository consistency checking (#24)
- Documentation improvements
- Fix exception during "attic create" with repeated files (#39)
- New "--exclude-from" option for attic create/extract/verify.
- Improved archive metadata deduplication.
- "attic verify" has been deprecated. Use "attic extract --dry-run" instead.
- "attic prune --hourly|daily|..." has been deprecated.
  Use "attic prune --keep-hourly|daily|..." instead.
- Ignore xattr errors during "extract" if not supported by the filesystem. (#46)

Version 0.10
~~~~~~~~~~~~

(bugfix release, released on Jan 30, 2014)

- Fix deadlock when extracting 0 sized files from remote repositories
- "--exclude" wildcard patterns are now properly applied to the full path
  not just the file name part (#5).
- Make source code endianness agnostic (#1)

Version 0.9
~~~~~~~~~~~

(feature release, released on Jan 23, 2014)

- Remote repository speed and reliability improvements.
- Fix sorting of segment names to ignore NFS left over files. (#17)
- Fix incorrect display of time (#13)
- Improved error handling / reporting. (#12)
- Use fcntl() instead of flock() when locking repository/cache. (#15)
- Let ssh figure out port/user if not specified so we don't override .ssh/config (#9)
- Improved libcrypto path detection (#23).

Version 0.8.1
~~~~~~~~~~~~~

(bugfix release, released on Oct 4, 2013)

- Fix segmentation fault issue.

Version 0.8
~~~~~~~~~~~

(feature release, released on Oct 3, 2013)

- Fix xattr issue when backing up sshfs filesystems (#4)
- Fix issue with excessive index file size (#6)
- Support access of read only repositories.
- New syntax to enable repository encryption:
    attic init --encryption="none|passphrase|keyfile".
- Detect and abort if repository is older than the cache.


Version 0.7
~~~~~~~~~~~

(feature release, released on Aug 5, 2013)

- Ported to FreeBSD
- Improved documentation
- Experimental: Archives mountable as FUSE filesystems.
- The "user." prefix is no longer stripped from xattrs on Linux


Version 0.6.1
~~~~~~~~~~~~~

(bugfix release, released on July 19, 2013)

- Fixed an issue where mtime was not always correctly restored.


Version 0.6
~~~~~~~~~~~

First public release on July 9, 2013


================================================
FILE: docs/changes_1.x.rst
================================================
.. _important_notes_1x:

Important notes 1.x
===================

This section provides information about security and corruption issues.

.. _archives_tam_vuln:

Pre-1.2.5 archives spoofing vulnerability (CVE-2023-36811)
----------------------------------------------------------

A flaw in the cryptographic authentication scheme in Borg allowed an attacker to
fake archives and potentially indirectly cause backup data loss in the repository.

The attack requires an attacker to be able to

1. insert files (with no additional headers) into backups
2. gain write access to the repository

This vulnerability does not disclose plaintext to the attacker, nor does it
affect the authenticity of existing archives.

Creating plausible fake archives may be feasible for empty or small archives,
but is unlikely for large archives.

The fix enforces checking the TAM authentication tag of archives at critical
places. Borg now considers archives without TAM as garbage or an attack.

We are not aware of others having discovered, disclosed or exploited this vulnerability.

Below, if we speak of borg 1.2.6, we mean a borg version >= 1.2.6 **or** a
borg version that has the relevant security patches for this vulnerability applied
(could be also an older version in that case).

Steps you must take to upgrade a repository (this applies to all kinds of repos
no matter what encryption mode they use, including "none"):

1. Upgrade all clients using this repository to borg 1.2.6.
   Note: it is not required to upgrade a server, except if the server-side borg
   is also used as a client (and not just for "borg serve").

   Do **not** run ``borg check`` with borg 1.2.6 before completing the upgrade steps:

   - ``borg check`` would complain about archives without a valid archive TAM.
   - ``borg check --repair`` would remove such archives!
2. Run: ``BORG_WORKAROUNDS=ignore_invalid_archive_tam borg info --debug <repo> 2>&1 | grep TAM | grep -i manifest``

   a) If you get 
Download .txt
gitextract_845rfasc/

├── .editorconfig
├── .git-blame-ignore-revs
├── .gitattributes
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── dependabot.yml
│   └── workflows/
│       ├── backport.yml
│       ├── black.yaml
│       ├── canary.yml
│       ├── ci.yml
│       └── codeql-analysis.yml
├── .gitignore
├── .mailmap
├── .pre-commit-config.yaml
├── .readthedocs.yaml
├── AUTHORS
├── Brewfile
├── LICENSE
├── MANIFEST.in
├── README.rst
├── SECURITY.md
├── Vagrantfile
├── docs/
│   ├── 3rd_party/
│   │   └── README
│   ├── Makefile
│   ├── _static/
│   │   ├── Makefile
│   │   └── logo_font.txt
│   ├── _templates/
│   │   ├── globaltoc.html
│   │   ├── layout.html
│   │   ├── logo-text.html
│   │   └── versionselector.html
│   ├── authors.rst
│   ├── binaries/
│   │   └── 00_README.txt
│   ├── book.rst
│   ├── borg_theme/
│   │   └── css/
│   │       └── borg.css
│   ├── changes.rst
│   ├── changes_0.x.rst
│   ├── changes_1.x.rst
│   ├── conf.py
│   ├── deployment/
│   │   ├── automated-local.rst
│   │   ├── central-backup-server.rst
│   │   ├── hosting-repositories.rst
│   │   ├── image-backup.rst
│   │   ├── non-root-user.rst
│   │   └── pull-backup.rst
│   ├── deployment.rst
│   ├── development.rst
│   ├── faq.rst
│   ├── global.rst.inc
│   ├── index.rst
│   ├── installation.rst
│   ├── internals/
│   │   ├── data-structures.rst
│   │   ├── encryption-aead.odg
│   │   ├── frontends.rst
│   │   ├── object-graph.odg
│   │   ├── security.rst
│   │   └── structure.odg
│   ├── internals.rst
│   ├── introduction.rst
│   ├── man/
│   │   ├── borg-analyze.1
│   │   ├── borg-benchmark-cpu.1
│   │   ├── borg-benchmark-crud.1
│   │   ├── borg-benchmark.1
│   │   ├── borg-break-lock.1
│   │   ├── borg-check.1
│   │   ├── borg-common.1
│   │   ├── borg-compact.1
│   │   ├── borg-completion.1
│   │   ├── borg-compression.1
│   │   ├── borg-config.1
│   │   ├── borg-create.1
│   │   ├── borg-delete.1
│   │   ├── borg-diff.1
│   │   ├── borg-export-tar.1
│   │   ├── borg-extract.1
│   │   ├── borg-import-tar.1
│   │   ├── borg-info.1
│   │   ├── borg-key-change-algorithm.1
│   │   ├── borg-key-change-location.1
│   │   ├── borg-key-change-passphrase.1
│   │   ├── borg-key-export.1
│   │   ├── borg-key-import.1
│   │   ├── borg-key-migrate-to-repokey.1
│   │   ├── borg-key.1
│   │   ├── borg-list.1
│   │   ├── borg-match-archives.1
│   │   ├── borg-mount.1
│   │   ├── borg-patterns.1
│   │   ├── borg-placeholders.1
│   │   ├── borg-prune.1
│   │   ├── borg-recreate.1
│   │   ├── borg-rename.1
│   │   ├── borg-repo-compress.1
│   │   ├── borg-repo-create.1
│   │   ├── borg-repo-delete.1
│   │   ├── borg-repo-info.1
│   │   ├── borg-repo-list.1
│   │   ├── borg-repo-space.1
│   │   ├── borg-serve.1
│   │   ├── borg-tag.1
│   │   ├── borg-transfer.1
│   │   ├── borg-umount.1
│   │   ├── borg-undelete.1
│   │   ├── borg-upgrade.1
│   │   ├── borg-version.1
│   │   ├── borg-with-lock.1
│   │   ├── borg.1
│   │   └── borgfs.1
│   ├── man_intro.rst
│   ├── misc/
│   │   ├── asciinema/
│   │   │   ├── README
│   │   │   ├── Vagrantfile
│   │   │   ├── advanced.json
│   │   │   ├── advanced.tcl
│   │   │   ├── basic.json
│   │   │   ├── basic.tcl
│   │   │   ├── install.json
│   │   │   ├── install.tcl
│   │   │   └── sample-wallpapers.txt
│   │   ├── benchmark-crud.txt
│   │   ├── borg-data-flow.odg
│   │   ├── create_chunker-params.txt
│   │   ├── internals-picture.txt
│   │   ├── logging.conf
│   │   └── prune-example.txt
│   ├── quickstart.rst
│   ├── quickstart_example.rst.inc
│   ├── support.rst
│   ├── usage/
│   │   ├── analyze.rst
│   │   ├── analyze.rst.inc
│   │   ├── benchmark.rst
│   │   ├── benchmark_cpu.rst.inc
│   │   ├── benchmark_crud.rst.inc
│   │   ├── borgfs.rst
│   │   ├── borgfs.rst.inc
│   │   ├── break-lock.rst.inc
│   │   ├── check.rst
│   │   ├── check.rst.inc
│   │   ├── common-options.rst.inc
│   │   ├── compact.rst
│   │   ├── compact.rst.inc
│   │   ├── completion.rst
│   │   ├── completion.rst.inc
│   │   ├── create.rst
│   │   ├── create.rst.inc
│   │   ├── debug.rst
│   │   ├── delete.rst
│   │   ├── delete.rst.inc
│   │   ├── diff.rst
│   │   ├── diff.rst.inc
│   │   ├── export-tar.rst.inc
│   │   ├── extract.rst
│   │   ├── extract.rst.inc
│   │   ├── general/
│   │   │   ├── archive-specification.rst.inc
│   │   │   ├── config.rst.inc
│   │   │   ├── date-time.rst.inc
│   │   │   ├── environment.rst.inc
│   │   │   ├── file-metadata.rst.inc
│   │   │   ├── file-systems.rst.inc
│   │   │   ├── logging.rst.inc
│   │   │   ├── positional-arguments.rst.inc
│   │   │   ├── repository-locations.rst.inc
│   │   │   ├── repository-urls.rst.inc
│   │   │   ├── resources.rst.inc
│   │   │   ├── return-codes.rst.inc
│   │   │   └── units.rst.inc
│   │   ├── general.rst
│   │   ├── help.rst
│   │   ├── help.rst.inc
│   │   ├── import-tar.rst.inc
│   │   ├── info.rst
│   │   ├── info.rst.inc
│   │   ├── key.rst
│   │   ├── key_change-location.rst.inc
│   │   ├── key_change-passphrase.rst.inc
│   │   ├── key_export.rst.inc
│   │   ├── key_import.rst.inc
│   │   ├── list.rst
│   │   ├── list.rst.inc
│   │   ├── lock.rst
│   │   ├── mount.rst
│   │   ├── mount.rst.inc
│   │   ├── notes.rst
│   │   ├── prune.rst
│   │   ├── prune.rst.inc
│   │   ├── recreate.rst
│   │   ├── recreate.rst.inc
│   │   ├── rename.rst
│   │   ├── rename.rst.inc
│   │   ├── repo-compress.rst
│   │   ├── repo-compress.rst.inc
│   │   ├── repo-create.rst
│   │   ├── repo-create.rst.inc
│   │   ├── repo-delete.rst
│   │   ├── repo-delete.rst.inc
│   │   ├── repo-info.rst
│   │   ├── repo-info.rst.inc
│   │   ├── repo-list.rst
│   │   ├── repo-list.rst.inc
│   │   ├── repo-space.rst
│   │   ├── repo-space.rst.inc
│   │   ├── serve.rst
│   │   ├── serve.rst.inc
│   │   ├── tag.rst
│   │   ├── tag.rst.inc
│   │   ├── tar.rst
│   │   ├── transfer.rst
│   │   ├── transfer.rst.inc
│   │   ├── umount.rst.inc
│   │   ├── undelete.rst
│   │   ├── undelete.rst.inc
│   │   ├── usage_general.rst.inc
│   │   ├── version.rst
│   │   ├── version.rst.inc
│   │   └── with-lock.rst.inc
│   ├── usage.rst
│   └── usage_general.rst.inc
├── pyproject.toml
├── requirements.d/
│   ├── codestyle.txt
│   ├── development.lock.txt
│   ├── development.txt
│   ├── docs.txt
│   └── pyinstaller.txt
├── scripts/
│   ├── Dockerfile.linux-run
│   ├── borg.exe.spec
│   ├── errorlist.py
│   ├── fetch-binaries
│   ├── glibc_check.py
│   ├── linux-run
│   ├── make-testdata/
│   │   └── test_transfer_upgrade.sh
│   ├── make.py
│   ├── msys2-install-deps
│   ├── sdist-sign
│   ├── shell_completions/
│   │   └── fish/
│   │       └── borg.fish
│   ├── sign-binaries
│   └── upload-pypi
├── setup.py
└── src/
    └── borg/
        ├── __init__.py
        ├── __main__.py
        ├── _item.c
        ├── archive.py
        ├── archiver/
        │   ├── __init__.py
        │   ├── _common.py
        │   ├── analyze_cmd.py
        │   ├── benchmark_cmd.py
        │   ├── check_cmd.py
        │   ├── compact_cmd.py
        │   ├── completion_cmd.py
        │   ├── create_cmd.py
        │   ├── debug_cmd.py
        │   ├── delete_cmd.py
        │   ├── diff_cmd.py
        │   ├── extract_cmd.py
        │   ├── help_cmd.py
        │   ├── info_cmd.py
        │   ├── key_cmds.py
        │   ├── list_cmd.py
        │   ├── lock_cmds.py
        │   ├── mount_cmds.py
        │   ├── prune_cmd.py
        │   ├── recreate_cmd.py
        │   ├── rename_cmd.py
        │   ├── repo_compress_cmd.py
        │   ├── repo_create_cmd.py
        │   ├── repo_delete_cmd.py
        │   ├── repo_info_cmd.py
        │   ├── repo_list_cmd.py
        │   ├── repo_space_cmd.py
        │   ├── serve_cmd.py
        │   ├── tag_cmd.py
        │   ├── tar_cmds.py
        │   ├── transfer_cmd.py
        │   ├── undelete_cmd.py
        │   └── version_cmd.py
        ├── cache.py
        ├── checksums.pyi
        ├── checksums.pyx
        ├── chunkers/
        │   ├── __init__.py
        │   ├── buzhash.pyi
        │   ├── buzhash.pyx
        │   ├── buzhash64.pyi
        │   ├── buzhash64.pyx
        │   ├── failing.py
        │   ├── fixed.py
        │   ├── reader.pyi
        │   └── reader.pyx
        ├── cockpit/
        │   ├── __init__.py
        │   ├── app.py
        │   ├── cockpit.tcss
        │   ├── runner.py
        │   ├── theme.py
        │   ├── translator.py
        │   └── widgets.py
        ├── compress.pyi
        ├── compress.pyx
        ├── conftest.py
        ├── constants.py
        ├── crypto/
        │   ├── __init__.py
        │   ├── file_integrity.py
        │   ├── key.py
        │   ├── keymanager.py
        │   ├── low_level.pyi
        │   └── low_level.pyx
        ├── fslocking.py
        ├── fuse.py
        ├── fuse_impl.py
        ├── hashindex.pyi
        ├── hashindex.pyx
        ├── helpers/
        │   ├── __init__.py
        │   ├── argparsing.py
        │   ├── datastruct.py
        │   ├── errors.py
        │   ├── fs.py
        │   ├── lrucache.py
        │   ├── misc.py
        │   ├── msgpack.py
        │   ├── nanorst.py
        │   ├── parseformat.py
        │   ├── passphrase.py
        │   ├── process.py
        │   ├── progress.py
        │   ├── shellpattern.py
        │   ├── time.py
        │   └── yes_no.py
        ├── hlfuse.py
        ├── item.pyi
        ├── item.pyx
        ├── legacyremote.py
        ├── legacyrepository.py
        ├── logger.py
        ├── manifest.py
        ├── paperkey.html
        ├── patterns.py
        ├── platform/
        │   ├── __init__.py
        │   ├── base.py
        │   ├── darwin.pyx
        │   ├── freebsd.pyx
        │   ├── linux.pyx
        │   ├── netbsd.pyx
        │   ├── posix.pyx
        │   ├── posix_ug.py
        │   ├── syncfilerange.pyx
        │   ├── windows.pyx
        │   ├── windows_ug.py
        │   └── xattr.py
        ├── platformflags.py
        ├── remote.py
        ├── repoobj.py
        ├── repository.py
        ├── selftest.py
        ├── storelocking.py
        ├── testsuite/
        │   ├── __init__.py
        │   ├── archive_test.py
        │   ├── archiver/
        │   │   ├── __init__.py
        │   │   ├── analyze_cmd_test.py
        │   │   ├── argparsing_test.py
        │   │   ├── benchmark_cmd_test.py
        │   │   ├── check_cmd_test.py
        │   │   ├── checks_test.py
        │   │   ├── compact_cmd_test.py
        │   │   ├── completion_cmd_test.py
        │   │   ├── corruption_test.py
        │   │   ├── create_cmd_test.py
        │   │   ├── debug_cmds_test.py
        │   │   ├── delete_cmd_test.py
        │   │   ├── diff_cmd_test.py
        │   │   ├── disk_full_test.py
        │   │   ├── extract_cmd_test.py
        │   │   ├── help_cmd_test.py
        │   │   ├── info_cmd_test.py
        │   │   ├── key_cmds_test.py
        │   │   ├── list_cmd_test.py
        │   │   ├── lock_cmds_test.py
        │   │   ├── mount_cmds_test.py
        │   │   ├── patterns_test.py
        │   │   ├── prune_cmd_test.py
        │   │   ├── recreate_cmd_test.py
        │   │   ├── remote_repo_test.py
        │   │   ├── rename_cmd_test.py
        │   │   ├── repo_compress_cmd_test.py
        │   │   ├── repo_create_cmd_test.py
        │   │   ├── repo_delete_cmd_test.py
        │   │   ├── repo_info_cmd_test.py
        │   │   ├── repo_list_cmd_test.py
        │   │   ├── repo_space_cmd_test.py
        │   │   ├── restricted_permissions_test.py
        │   │   ├── return_codes_test.py
        │   │   ├── serve_cmd_test.py
        │   │   ├── tag_cmd_test.py
        │   │   ├── tar_cmds_test.py
        │   │   ├── transfer_cmd_test.py
        │   │   └── undelete_cmd_test.py
        │   ├── benchmark_test.py
        │   ├── cache_test.py
        │   ├── checksums_test.py
        │   ├── chunkers/
        │   │   ├── __init__.py
        │   │   ├── buzhash64_self_test.py
        │   │   ├── buzhash64_test.py
        │   │   ├── buzhash_self_test.py
        │   │   ├── buzhash_test.py
        │   │   ├── failing_test.py
        │   │   ├── fixed_self_test.py
        │   │   ├── fixed_test.py
        │   │   ├── interaction_test.py
        │   │   └── reader_test.py
        │   ├── cockpit_test.py
        │   ├── compress_test.py
        │   ├── crypto/
        │   │   ├── __init__.py
        │   │   ├── crypto_test.py
        │   │   ├── csprng_test.py
        │   │   ├── file_integrity_test.py
        │   │   └── key_test.py
        │   ├── fslocking_test.py
        │   ├── hashindex_test.py
        │   ├── helpers/
        │   │   ├── __init__.py
        │   │   ├── __init__test.py
        │   │   ├── datastruct_test.py
        │   │   ├── efficient_collection_queue_test.py
        │   │   ├── fs_test.py
        │   │   ├── lrucache_test.py
        │   │   ├── misc_test.py
        │   │   ├── msgpack_test.py
        │   │   ├── nanorst_test.py
        │   │   ├── parseformat_test.py
        │   │   ├── passphrase_test.py
        │   │   ├── process_test.py
        │   │   ├── progress_test.py
        │   │   ├── shellpattern_test.py
        │   │   ├── time_test.py
        │   │   └── yes_no_test.py
        │   ├── item_test.py
        │   ├── legacyrepository_test.py
        │   ├── logger_test.py
        │   ├── patterns_test.py
        │   ├── platform/
        │   │   ├── __init__.py
        │   │   ├── all_test.py
        │   │   ├── darwin_test.py
        │   │   ├── freebsd_test.py
        │   │   ├── linux_test.py
        │   │   ├── platform_test.py
        │   │   └── windows_test.py
        │   ├── remote_test.py
        │   ├── repoobj_test.py
        │   ├── repository_test.py
        │   ├── shell_completions_test.py
        │   ├── storelocking_test.py
        │   ├── version_test.py
        │   └── xattr_test.py
        ├── upgrade.py
        ├── version.py
        └── xattr.py
Download .txt
Showing preview only (234K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (2871 symbols across 192 files)

FILE: docs/conf.py
  function set_rst_settings (line 108) | def set_rst_settings(app):
  function setup (line 112) | def setup(app):

FILE: scripts/errorlist.py
  function subclasses (line 12) | def subclasses(cls):

FILE: scripts/glibc_check.py
  function parse_version (line 18) | def parse_version(v):
  function format_version (line 23) | def format_version(version):
  function main (line 27) | def main():

FILE: scripts/make.py
  function format_metavar (line 15) | def format_metavar(option):
  class BuildUsage (line 26) | class BuildUsage:
    method run (line 29) | def run(self):
    method generate_level (line 46) | def generate_level(self, prefix, parser, Archiver, extra_choices=None):
    method write_usage (line 103) | def write_usage(self, parser, fp):
    method write_options (line 113) | def write_options(self, parser, fp):
    method rows_to_table (line 164) | def rows_to_table(self, rows, write):
    method write_options_group (line 223) | def write_options_group(self, group, fp, with_title=True, base_indent=4):
  class BuildMan (line 260) | class BuildMan:
    method run (line 309) | def run(self):
    method generate_level (line 326) | def generate_level(self, prefix, parser, Archiver, extra_choices=None):
    method build_topic_pages (line 405) | def build_topic_pages(self, Archiver):
    method build_intro_page (line 416) | def build_intro_page(self):
    method new_doc (line 427) | def new_doc(self):
    method printer (line 433) | def printer(self, fd):
    method write_heading (line 439) | def write_heading(self, write, header, char="-", double_sided=False):
    method write_man_header (line 447) | def write_man_header(self, write, title, description):
    method write_examples (line 458) | def write_examples(self, write, command):
    method write_see_also (line 480) | def write_see_also(self, write, man_title):
    method gen_man_page (line 487) | def gen_man_page(self, name, rst):
    method write_usage (line 509) | def write_usage(self, write, parser):
    method write_options (line 518) | def write_options(self, write, parser):
    method write_options_group (line 527) | def write_options_group(self, write, group):
  function rm (line 574) | def rm(file):
  class Clean (line 583) | class Clean:
    method run (line 584) | def run(self):
  function usage (line 594) | def usage():
  function main (line 607) | def main(argv):

FILE: setup.py
  class Sdist (line 89) | class Sdist(sdist):
    method __init__ (line 90) | def __init__(self, *args, **kwargs):
  function members_appended (line 109) | def members_appended(*ds):
  function lib_ext_kwargs (line 123) | def lib_ext_kwargs(pc, prefix_env_var, lib_name, lib_pkg_name, pc_versio...
  function long_desc_from_readme (line 240) | def long_desc_from_readme():

FILE: src/borg/_item.c
  function PyObject (line 15) | static PyObject *
  function PyObject (line 28) | static PyObject *

FILE: src/borg/archive.py
  class Statistics (line 60) | class Statistics:
    method __init__ (line 61) | def __init__(self, output_json=False, iec=False):
    method update (line 72) | def update(self, size, unique):
    method __add__ (line 77) | def __add__(self, other):
    method __str__ (line 91) | def __str__(self):
    method __repr__ (line 118) | def __repr__(self):
    method as_dict (line 123) | def as_dict(self):
    method as_raw_dict (line 132) | def as_raw_dict(self):
    method from_raw_dict (line 136) | def from_raw_dict(cls, **kw):
    method osize_fmt (line 143) | def osize_fmt(self):
    method usize_fmt (line 147) | def usize_fmt(self):
    method show_progress (line 150) | def show_progress(self, item=None, final=False, stream=None, dt=None):
  function is_special (line 190) | def is_special(mode):
  class BackupIO (line 195) | class BackupIO:
    method __call__ (line 198) | def __call__(self, op=""):
    method __enter__ (line 202) | def __enter__(self):
    method __exit__ (line 205) | def __exit__(self, exc_type, exc_val, exc_tb):
  function backup_io_iter (line 222) | def backup_io_iter(iterator):
  function stat_update_check (line 233) | def stat_update_check(st_old, st_curr):
  function OsOpen (line 260) | def OsOpen(*, flags, path=None, parent_fd=None, name=None, noatime=False...
  class DownloadPipeline (line 271) | class DownloadPipeline:
    method __init__ (line 272) | def __init__(self, repository, repo_objs):
    method unpack_many (line 277) | def unpack_many(self, ids, *, filter=None):
    method preload_item_chunks (line 299) | def preload_item_chunks(self, item, optimize_hardlinks=False):
    method fetch_many (line 327) | def fetch_many(self, chunks, is_preloaded=False, ro_type=None, replace...
  class ChunkBuffer (line 356) | class ChunkBuffer:
    method __init__ (line 359) | def __init__(self, key, chunker_params=ITEMS_CHUNKER_PARAMS):
    method add (line 367) | def add(self, item):
    method write_chunk (line 372) | def write_chunk(self, chunk):
    method flush (line 375) | def flush(self, flush=False):
    method is_full (line 402) | def is_full(self):
  class CacheChunkBuffer (line 406) | class CacheChunkBuffer(ChunkBuffer):
    method __init__ (line 407) | def __init__(self, cache, key, stats, chunker_params=ITEMS_CHUNKER_PAR...
    method write_chunk (line 412) | def write_chunk(self, chunk):
  function get_item_uid_gid (line 421) | def get_item_uid_gid(item, *, numeric, uid_forced=None, gid_forced=None,...
  function archive_get_items (line 439) | def archive_get_items(metadata, *, repo_objs, repository):
  function archive_put_items (line 454) | def archive_put_items(chunk_ids, *, repo_objs, cache=None, stats=None, a...
  class Archive (line 472) | class Archive:
    class AlreadyExists (line 473) | class AlreadyExists(Error):
    class DoesNotExist (line 478) | class DoesNotExist(Error):
    class IncompatibleFilesystemEncodingError (line 483) | class IncompatibleFilesystemEncodingError(Error):
    method __init__ (line 488) | def __init__(
    method _load_meta (line 557) | def _load_meta(self, id):
    method load (line 568) | def load(self, id):
    method ts (line 576) | def ts(self):
    method ts_start (line 582) | def ts_start(self):
    method ts_end (line 589) | def ts_end(self):
    method fpr (line 596) | def fpr(self):
    method duration (line 600) | def duration(self):
    method duration_from_meta (line 604) | def duration_from_meta(self):
    method info (line 607) | def info(self):
    method __str__ (line 641) | def __str__(self):
    method __repr__ (line 658) | def __repr__(self):
    method item_filter (line 661) | def item_filter(self, item, filter=None):
    method iter_items (line 664) | def iter_items(self, filter=None):
    method preload_item_chunks (line 667) | def preload_item_chunks(self, item, optimize_hardlinks=False):
    method add_item (line 676) | def add_item(self, item, show_progress=True, stats=None):
    method save (line 683) | def save(self, name=None, comment=None, timestamp=None, stats=None, ad...
    method calc_stats (line 734) | def calc_stats(self, cache, want_unique=True):
    method extract_helper (line 742) | def extract_helper(self, item, path, hlm, *, dry_run=False):
    method extract_item (line 764) | def extract_item(
    method restore_attrs (line 948) | def restore_attrs(self, path, item, symlink=False, fd=None):
    method set_meta (line 1034) | def set_meta(self, key, value):
    method rename (line 1045) | def rename(self, name):
    method delete (line 1051) | def delete(self):
    method compare_archives_iter (line 1058) | def compare_archives_iter(
  class MetadataCollector (line 1113) | class MetadataCollector:
    method __init__ (line 1114) | def __init__(self, *, noatime, noctime, nobirthtime, numeric_ids, nofl...
    method stat_simple_attrs (line 1123) | def stat_simple_attrs(self, st, path, fd=None):
    method stat_ext_attrs (line 1151) | def stat_ext_attrs(self, st, path, fd=None):
    method stat_attrs (line 1170) | def stat_attrs(self, st, path, fd=None):
  function cached_hash (line 1183) | def cached_hash(chunk, id_hash):
  class ChunksProcessor (line 1202) | class ChunksProcessor:
    method __init__ (line 1205) | def __init__(self, *, key, cache, add_item, rechunkify):
    method process_file_chunks (line 1211) | def process_file_chunks(self, item, cache, stats, show_progress, chunk...
  function maybe_exclude_by_attr (line 1230) | def maybe_exclude_by_attr(item):
  class FilesystemObjectProcessors (line 1242) | class FilesystemObjectProcessors:
    method __init__ (line 1246) | def __init__(
    method create_helper (line 1277) | def create_helper(self, path, st, status=None, hardlinkable=True, stri...
    method process_dir_with_fd (line 1310) | def process_dir_with_fd(self, *, path, fd, st, strip_prefix):
    method process_dir (line 1321) | def process_dir(self, *, path, parent_fd, name, st, strip_prefix):
    method process_fifo (line 1338) | def process_fifo(self, *, path, parent_fd, name, st, strip_prefix):
    method process_dev (line 1353) | def process_dev(self, *, path, parent_fd, name, st, dev_type, strip_pr...
    method process_symlink (line 1369) | def process_symlink(self, *, path, parent_fd, name, st, strip_prefix):
    method process_pipe (line 1385) | def process_pipe(self, *, path, cache, fd, mode, user=None, group=None):
    method process_file (line 1417) | def process_file(self, *, path, parent_fd, name, st, cache, flags=flag...
  class TarfileObjectProcessors (line 1538) | class TarfileObjectProcessors:
    method __init__ (line 1539) | def __init__(
    method create_helper (line 1564) | def create_helper(self, tarinfo, status=None, type=None):
    method process_dir (line 1618) | def process_dir(self, *, tarinfo, status, type):
    method process_fifo (line 1622) | def process_fifo(self, *, tarinfo, status, type):
    method process_dev (line 1626) | def process_dev(self, *, tarinfo, status, type):
    method process_symlink (line 1631) | def process_symlink(self, *, tarinfo, status, type):
    method process_hardlink (line 1636) | def process_hardlink(self, *, tarinfo, status, type):
    method process_file (line 1648) | def process_file(self, *, tarinfo, status, type, tar):
  function valid_msgpacked_dict (line 1663) | def valid_msgpacked_dict(d, keys_serialized):
  class RobustUnpacker (line 1691) | class RobustUnpacker:
    method __init__ (line 1694) | def __init__(self, validator, item_keys):
    method resync (line 1702) | def resync(self):
    method feed (line 1706) | def feed(self, data):
    method __iter__ (line 1712) | def __iter__(self):
    method __next__ (line 1715) | def __next__(self):
  class ArchiveChecker (line 1741) | class ArchiveChecker:
    method __init__ (line 1742) | def __init__(self):
    method check (line 1746) | def check(
    method make_key (line 1815) | def make_key(self, repository, manifest_only=False):
    method verify_data (line 1852) | def verify_data(self):
    method rebuild_manifest (line 1916) | def rebuild_manifest(self):
    method rebuild_archives_directory (line 1927) | def rebuild_archives_directory(self):
    method rebuild_archives (line 1997) | def rebuild_archives(
    method finish (line 2194) | def finish(self):
  class ArchiveRecreater (line 2203) | class ArchiveRecreater:
    class Interrupted (line 2204) | class Interrupted(Exception):
      method __init__ (line 2205) | def __init__(self, metadata=None):
    method is_temporary_archive (line 2209) | def is_temporary_archive(archive_name):
    method __init__ (line 2212) | def __init__(
    method recreate (line 2252) | def recreate(self, archive_id, target_name, delete_original, comment=N...
    method process_items (line 2264) | def process_items(self, archive, target):
    method process_item (line 2278) | def process_item(self, archive, target, item):
    method process_chunks (line 2288) | def process_chunks(self, archive, target, item):
    method chunk_processor (line 2297) | def chunk_processor(self, target, chunk):
    method iter_chunks (line 2307) | def iter_chunks(self, archive, target, chunks):
    method save (line 2318) | def save(self, archive, target, comment=None, delete_original=True):
    method matcher_add_tagged_dirs (line 2337) | def matcher_add_tagged_dirs(self, archive):
    method create_target (line 2364) | def create_target(self, archive, target_name):
    method create_target_archive (line 2383) | def create_target_archive(self, name):
    method open_archive (line 2394) | def open_archive(self, archive_id, **kwargs):

FILE: src/borg/archiver/__init__.py
  class Archiver (line 100) | class Archiver(
    method __init__ (line 133) | def __init__(self, lock_wait=None, prog=None):
    method print_warning (line 138) | def print_warning(self, msg, *args, **kw):
    method print_warning_instance (line 151) | def print_warning_instance(self, warning):
    method print_file_status (line 158) | def print_file_status(self, status, path):
    method preprocess_args (line 168) | def preprocess_args(self, args):
    class CommonOptions (line 181) | class CommonOptions:
      method __init__ (line 200) | def __init__(self, define_common_options):
      method add_common_group (line 213) | def add_common_group(self, parser, provide_defaults=False):
    method build_parser (line 248) | def build_parser(self):
    method get_args (line 311) | def get_args(self, argv, cmd):
    method parse_args (line 344) | def parse_args(self, args=None):
    method get_func (line 386) | def get_func(self, args, parser):
    method prerun_checks (line 400) | def prerun_checks(self, logger, is_serve):
    method _setup_implied_logging (line 413) | def _setup_implied_logging(self, args):
    method _setup_topic_debugging (line 430) | def _setup_topic_debugging(self, args):
    method run (line 438) | def run(self, args):
  function sig_info_handler (line 500) | def sig_info_handler(sig_no, stack):  # pragma: no cover
  function sig_trace_handler (line 524) | def sig_trace_handler(sig_no, stack):  # pragma: no cover
  function format_tb (line 529) | def format_tb(exc):
  function main (line 552) | def main():  # pragma: no cover

FILE: src/borg/archiver/_common.py
  function get_repository (line 34) | def get_repository(location, *, create, exclusive, lock_wait, lock, args...
  function compat_check (line 52) | def compat_check(*, create, manifest, key, cache, compatibility, decorat...
  function with_repository (line 68) | def with_repository(
  function with_other_repository (line 153) | def with_other_repository(manifest=False, cache=False, compatibility=None):
  function with_archive (line 221) | def with_archive(method):
  function process_epilog (line 257) | def process_epilog(epilog):
  function define_exclude_and_patterns (line 271) | def define_exclude_and_patterns(add_option, *, tag_files=False, strip_co...
  function define_exclusion_group (line 336) | def define_exclusion_group(subparser, **kwargs):
  function define_archive_filters_group (line 342) | def define_archive_filters_group(
  function define_common_options (line 437) | def define_common_options(add_common_option):
  function build_matcher (line 579) | def build_matcher(inclexcl_patterns, include_paths, pattern_roots=()):
  function build_filter (line 587) | def build_filter(matcher, strip_components):

FILE: src/borg/archiver/analyze_cmd.py
  class ArchiveAnalyzer (line 19) | class ArchiveAnalyzer:
    method __init__ (line 20) | def __init__(self, args, repository, manifest):
    method analyze (line 27) | def analyze(self):
    method analyze_archives (line 33) | def analyze_archives(self) -> None:
    method analyze_archive (line 60) | def analyze_archive(self, id):
    method analyze_change (line 71) | def analyze_change(self, base, new):
    method report (line 90) | def report(self):
  class AnalyzeMixIn (line 99) | class AnalyzeMixIn:
    method do_analyze (line 101) | def do_analyze(self, args, repository, manifest):
    method build_parser_analyze (line 105) | def build_parser_analyze(self, subparsers, common_parser, mid_common_p...

FILE: src/borg/archiver/benchmark_cmd.py
  class BenchmarkMixIn (line 19) | class BenchmarkMixIn:
    method do_benchmark_crud (line 20) | def do_benchmark_crud(self, args):
    method do_benchmark_cpu (line 163) | def do_benchmark_cpu(self, args):
    method build_parser_benchmarks (line 350) | def build_parser_benchmarks(self, subparsers, common_parser, mid_commo...

FILE: src/borg/archiver/check_cmd.py
  class CheckMixIn (line 13) | class CheckMixIn:
    method do_check (line 15) | def do_check(self, args, repository):
    method build_parser_check (line 74) | def build_parser_check(self, subparsers, common_parser, mid_common_par...

FILE: src/borg/archiver/compact_cmd.py
  class ArchiveGarbageCollector (line 22) | class ArchiveGarbageCollector:
    method __init__ (line 23) | def __init__(self, repository, manifest, *, stats, iec):
    method repository_size (line 35) | def repository_size(self):
    method garbage_collect (line 40) | def garbage_collect(self):
    method get_repository_chunks (line 51) | def get_repository_chunks(self) -> ChunkIndex:
    method save_chunk_index (line 67) | def save_chunk_index(self):
    method cleanup_files_cache (line 77) | def cleanup_files_cache(self):
    method analyze_archives (line 114) | def analyze_archives(self) -> tuple[set, int, int, int]:
    method report_and_delete (line 156) | def report_and_delete(self):
  class CompactMixIn (line 208) | class CompactMixIn:
    method do_compact (line 210) | def do_compact(self, args, repository, manifest):
    method build_parser_compact (line 215) | def build_parser_compact(self, subparsers, common_parser, mid_common_p...

FILE: src/borg/archiver/completion_cmd.py
  function _attach_completion (line 630) | def _attach_completion(parser: ArgumentParser, type_class, completion_di...
  function _attach_help_completion (line 643) | def _attach_help_completion(parser: ArgumentParser, completion_dict: dict):
  class CompletionMixIn (line 655) | class CompletionMixIn:
    method do_completion (line 656) | def do_completion(self, args):
    method build_parser_completion (line 743) | def build_parser_completion(self, subparsers, common_parser, mid_commo...

FILE: src/borg/archiver/create_cmd.py
  class CreateMixIn (line 42) | class CreateMixIn:
    method do_create (line 44) | def do_create(self, args, repository, manifest):
    method _process_any (line 292) | def _process_any(self, *, path, parent_fd, name, st, fso, cache, read_...
    method _rec_walk (line 425) | def _rec_walk(
    method build_parser_create (line 575) | def build_parser_create(self, subparsers, common_parser, mid_common_pa...

FILE: src/borg/archiver/debug_cmd.py
  class DebugMixIn (line 23) | class DebugMixIn:
    method do_debug_info (line 24) | def do_debug_info(self, args):
    method do_debug_dump_archive_items (line 30) | def do_debug_dump_archive_items(self, args, repository, manifest):
    method do_debug_dump_archive (line 44) | def do_debug_dump_archive(self, args, repository, manifest):
    method do_debug_dump_manifest (line 99) | def do_debug_dump_manifest(self, args, repository, manifest):
    method do_debug_dump_repo_objs (line 111) | def do_debug_dump_repo_objs(self, args, repository):
    method do_debug_search_repo_objs (line 137) | def do_debug_search_repo_objs(self, args, repository):
    method do_debug_get_obj (line 201) | def do_debug_get_obj(self, args, repository):
    method do_debug_id_hash (line 217) | def do_debug_id_hash(self, args, repository, manifest):
    method do_debug_parse_obj (line 226) | def do_debug_parse_obj(self, args, repository, manifest):
    method do_debug_format_obj (line 249) | def do_debug_format_obj(self, args, repository, manifest):
    method do_debug_put_obj (line 273) | def do_debug_put_obj(self, args, repository):
    method do_debug_delete_obj (line 287) | def do_debug_delete_obj(self, args, repository):
    method do_debug_convert_profile (line 302) | def do_debug_convert_profile(self, args):
    method build_parser_debug (line 309) | def build_parser_debug(self, subparsers, common_parser, mid_common_par...

FILE: src/borg/archiver/delete_cmd.py
  class DeleteMixIn (line 14) | class DeleteMixIn:
    method do_delete (line 16) | def do_delete(self, args, repository):
    method build_parser_delete (line 62) | def build_parser_delete(self, subparsers, common_parser, mid_common_pa...

FILE: src/borg/archiver/diff_cmd.py
  class DiffMixIn (line 19) | class DiffMixIn:
    method do_diff (line 21) | def do_diff(self, args, repository, manifest):
    method build_parser_diff (line 173) | def build_parser_diff(self, subparsers, common_parser, mid_common_pars...

FILE: src/borg/archiver/extract_cmd.py
  class ExtractMixIn (line 22) | class ExtractMixIn:
    method do_extract (line 25) | def do_extract(self, args, repository, manifest, archive):
    method build_parser_extract (line 124) | def build_parser_extract(self, subparsers, common_parser, mid_common_p...

FILE: src/borg/archiver/help_cmd.py
  class HelpMixIn (line 9) | class HelpMixIn:
    method do_help (line 525) | def do_help(self, parser, args):
    method do_subcommand_help (line 549) | def do_subcommand_help(self, parser, args):
    method build_parser_help (line 555) | def build_parser_help(self, subparsers, common_parser, mid_common_pars...

FILE: src/borg/archiver/info_cmd.py
  class InfoMixIn (line 16) | class InfoMixIn:
    method do_info (line 18) | def do_info(self, args, repository, manifest, cache):
    method build_parser_info (line 64) | def build_parser_info(self, subparsers, common_parser, mid_common_pars...

FILE: src/borg/archiver/key_cmds.py
  class KeysMixIn (line 18) | class KeysMixIn:
    method do_key_change_passphrase (line 20) | def do_key_change_passphrase(self, args, repository, manifest):
    method do_key_change_location (line 32) | def do_key_change_location(self, args, repository, manifest, cache):
    method do_key_export (line 86) | def do_key_export(self, args, repository):
    method do_key_import (line 105) | def do_key_import(self, args, repository):
    method build_parser_keys (line 119) | def build_parser_keys(self, subparsers, common_parser, mid_common_pars...

FILE: src/borg/archiver/list_cmd.py
  class ListMixIn (line 18) | class ListMixIn:
    method do_list (line 20) | def do_list(self, args, repository, manifest):
    method build_parser_list (line 60) | def build_parser_list(self, subparsers, common_parser, mid_common_pars...

FILE: src/borg/archiver/lock_cmds.py
  class LocksMixIn (line 14) | class LocksMixIn:
    method do_with_lock (line 16) | def do_with_lock(self, args, repository):
    method do_break_lock (line 33) | def do_break_lock(self, args, repository):
    method build_parser_locks (line 38) | def build_parser_locks(self, subparsers, common_parser, mid_common_par...

FILE: src/borg/archiver/mount_cmds.py
  class MountMixIn (line 17) | class MountMixIn:
    method do_mount (line 18) | def do_mount(self, args):
    method _do_mount (line 36) | def _do_mount(self, args, repository, manifest):
    method do_umount (line 63) | def do_umount(self, args):
    method build_parser_mount_umount (line 67) | def build_parser_mount_umount(self, subparsers, common_parser, mid_com...
    method build_parser_borgfs (line 172) | def build_parser_borgfs(self, parser):
    method _define_borg_mount (line 180) | def _define_borg_mount(self, parser):

FILE: src/borg/archiver/prune_cmd.py
  function prune_within (line 19) | def prune_within(archives, seconds, kept_because):
  function default_period_func (line 31) | def default_period_func(pattern):
  function quarterly_13weekly_period_func (line 39) | def quarterly_13weekly_period_func(a):
  function quarterly_3monthly_period_func (line 60) | def quarterly_3monthly_period_func(a):
  function prune_split (line 91) | def prune_split(archives, rule, n, kept_because=None):
  class PruneMixIn (line 117) | class PruneMixIn:
    method do_prune (line 119) | def do_prune(self, args, repository, manifest):
    method build_parser_prune (line 209) | def build_parser_prune(self, subparsers, common_parser, mid_common_par...

FILE: src/borg/archiver/recreate_cmd.py
  class RecreateMixIn (line 15) | class RecreateMixIn:
    method do_recreate (line 17) | def do_recreate(self, args, repository, manifest, cache):
    method build_parser_recreate (line 57) | def build_parser_recreate(self, subparsers, common_parser, mid_common_...

FILE: src/borg/archiver/rename_cmd.py
  class RenameMixIn (line 12) | class RenameMixIn:
    method do_rename (line 15) | def do_rename(self, args, repository, manifest, cache, archive):
    method build_parser_rename (line 20) | def build_parser_rename(self, subparsers, common_parser, mid_common_pa...

FILE: src/borg/archiver/repo_compress_cmd.py
  function find_chunks (line 18) | def find_chunks(repository, repo_objs, cache, stats, ctype, clevel, olev...
  function process_chunks (line 37) | def process_chunks(repository, repo_objs, stats, recompress_ids, olevel):
  function format_compression_spec (line 75) | def format_compression_spec(ctype, clevel, olevel):
  class RepoCompressMixIn (line 87) | class RepoCompressMixIn:
    method do_repo_compress (line 89) | def do_repo_compress(self, args, repository, manifest, cache):
    method build_parser_repo_compress (line 156) | def build_parser_repo_compress(self, subparsers, common_parser, mid_co...

FILE: src/borg/archiver/repo_create_cmd.py
  class RepoCreateMixIn (line 15) | class RepoCreateMixIn:
    method do_repo_create (line 18) | def do_repo_create(self, args, repository, *, other_repository=None, o...
    method build_parser_repo_create (line 58) | def build_parser_repo_create(self, subparsers, common_parser, mid_comm...

FILE: src/borg/archiver/repo_delete_cmd.py
  class RepoDeleteMixIn (line 16) | class RepoDeleteMixIn:
    method do_repo_delete (line 18) | def do_repo_delete(self, args, repository):
    method build_parser_repo_delete (line 89) | def build_parser_repo_delete(self, subparsers, common_parser, mid_comm...

FILE: src/borg/archiver/repo_info_cmd.py
  class RepoInfoMixIn (line 14) | class RepoInfoMixIn:
    method do_repo_info (line 16) | def do_repo_info(self, args, repository, manifest, cache):
    method build_parser_repo_info (line 58) | def build_parser_repo_info(self, subparsers, common_parser, mid_common...

FILE: src/borg/archiver/repo_list_cmd.py
  class RepoListMixIn (line 16) | class RepoListMixIn:
    method do_repo_list (line 18) | def do_repo_list(self, args, repository, manifest):
    method build_parser_repo_list (line 42) | def build_parser_repo_list(self, subparsers, common_parser, mid_common...

FILE: src/borg/archiver/repo_space_cmd.py
  class RepoSpaceMixIn (line 16) | class RepoSpaceMixIn:
    method do_repo_space (line 18) | def do_repo_space(self, args, repository):
    method build_parser_repo_space (line 52) | def build_parser_repo_space(self, subparsers, common_parser, mid_commo...

FILE: src/borg/archiver/serve_cmd.py
  class ServeMixIn (line 10) | class ServeMixIn:
    method do_serve (line 11) | def do_serve(self, args):
    method build_parser_serve (line 20) | def build_parser_serve(self, subparsers, common_parser, mid_common_par...

FILE: src/borg/archiver/tag_cmd.py
  class TagMixIn (line 13) | class TagMixIn:
    method do_tag (line 15) | def do_tag(self, args, repository, manifest, cache):
    method build_parser_tag (line 44) | def build_parser_tag(self, subparsers, common_parser, mid_common_parser):

FILE: src/borg/archiver/tar_cmds.py
  function get_tar_filter (line 36) | def get_tar_filter(fname, decompress):
  class TarMixIn (line 54) | class TarMixIn:
    method do_export_tar (line 57) | def do_export_tar(self, args, repository, manifest, archive):
    method _export_tar (line 87) | def _export_tar(self, args, archive, tarstream):
    method do_import_tar (line 256) | def do_import_tar(self, args, repository, manifest, cache):
    method _import_tar (line 269) | def _import_tar(self, args, repository, manifest, key, cache, tarstream):
    method build_parser_tar (line 337) | def build_parser_tar(self, subparsers, common_parser, mid_common_parser):

FILE: src/borg/archiver/transfer_cmd.py
  function transfer_chunks (line 21) | def transfer_chunks(
  class TransferMixIn (line 130) | class TransferMixIn:
    method do_transfer (line 133) | def do_transfer(self, args, *, repository, manifest, cache, other_repo...
    method build_parser_transfer (line 272) | def build_parser_transfer(self, subparsers, common_parser, mid_common_...

FILE: src/borg/archiver/undelete_cmd.py
  class UnDeleteMixIn (line 14) | class UnDeleteMixIn:
    method do_undelete (line 16) | def do_undelete(self, args, repository):
    method build_parser_undelete (line 55) | def build_parser_undelete(self, subparsers, common_parser, mid_common_...

FILE: src/borg/archiver/version_cmd.py
  class VersionMixIn (line 11) | class VersionMixIn:
    method do_version (line 12) | def do_version(self, args):
    method build_parser_version (line 24) | def build_parser_version(self, subparsers, common_parser, mid_common_p...

FILE: src/borg/cache.py
  function files_cache_name (line 43) | def files_cache_name(archive_name, files_cache_name="files"):
  function discover_files_cache_names (line 60) | def discover_files_cache_names(path, files_cache_name="files"):
  class SecurityManager (line 75) | class SecurityManager:
    method __init__ (line 95) | def __init__(self, repository):
    method destroy (line 103) | def destroy(repository, path=None):
    method known (line 109) | def known(self):
    method key_matches (line 112) | def key_matches(self, key):
    method save (line 122) | def save(self, manifest, key):
    method assert_location_matches (line 135) | def assert_location_matches(self):
    method assert_no_manifest_replay (line 169) | def assert_no_manifest_replay(self, manifest, key):
    method assert_key_type (line 188) | def assert_key_type(self, key):
    method assert_secure (line 193) | def assert_secure(self, manifest, key, *, warn_if_unencrypted=True):
    method _assert_secure (line 200) | def _assert_secure(self, manifest, key):
    method assert_access_unknown (line 208) | def assert_access_unknown(self, warn_if_unencrypted, manifest, key):
  function assert_secure (line 233) | def assert_secure(repository, manifest):
  function cache_dir (line 238) | def cache_dir(repository, path=None):
  class CacheConfig (line 242) | class CacheConfig:
    method __init__ (line 243) | def __init__(self, repository, path=None):
    method __enter__ (line 249) | def __enter__(self):
    method __exit__ (line 253) | def __exit__(self, exc_type, exc_val, exc_tb):
    method exists (line 256) | def exists(self):
    method create (line 259) | def create(self):
    method open (line 271) | def open(self):
    method load (line 274) | def load(self):
    method save (line 300) | def save(self, manifest=None):
    method close (line 313) | def close(self):
    method _check_upgrade (line 316) | def _check_upgrade(self, config_path):
  class Cache (line 330) | class Cache:
    class CacheInitAbortedError (line 333) | class CacheInitAbortedError(Error):
    class EncryptionMethodMismatch (line 338) | class EncryptionMethodMismatch(Error):
    class RepositoryAccessAborted (line 343) | class RepositoryAccessAborted(Error):
    class RepositoryIDNotUnique (line 348) | class RepositoryIDNotUnique(Error):
    class RepositoryReplay (line 353) | class RepositoryReplay(Error):
    method break_lock (line 359) | def break_lock(repository, path=None):
    method destroy (line 363) | def destroy(repository, path=None):
    method __new__ (line 371) | def __new__(
  class FilesCacheMixin (line 396) | class FilesCacheMixin:
    method __init__ (line 408) | def __init__(self, cache_mode, archive_name=None, start_backup=None):
    method compress_entry (line 418) | def compress_entry(self, entry):
    method decompress_entry (line 441) | def decompress_entry(self, entry_packed):
    method files (line 458) | def files(self):
    method _build_files_cache (line 467) | def _build_files_cache(self):
    method files_cache_name (line 527) | def files_cache_name(self):
    method discover_files_cache_names (line 530) | def discover_files_cache_names(self, path):
    method _read_files_cache (line 533) | def _read_files_cache(self):
    method _write_files_cache (line 576) | def _write_files_cache(self, files):
    method file_known_and_unchanged (line 620) | def file_known_and_unchanged(self, hashed_path, path_hash, st):
    method memorize_file (line 676) | def memorize_file(self, hashed_path, path_hash, st, chunks):
  function list_chunkindex_hashes (line 701) | def list_chunkindex_hashes(repository):
  function delete_chunkindex_cache (line 713) | def delete_chunkindex_cache(repository):
  function write_chunkindex_to_repo_cache (line 727) | def write_chunkindex_to_repo_cache(
  function read_chunkindex_from_repo_cache (line 782) | def read_chunkindex_from_repo_cache(repository, hash):
  function build_chunkindex_from_repo (line 799) | def build_chunkindex_from_repo(repository, *, disable_caches=False, cach...
  class ChunksMixin (line 848) | class ChunksMixin:
    method __init__ (line 853) | def __init__(self):
    method chunks (line 861) | def chunks(self):
    method seen_chunk (line 866) | def seen_chunk(self, id, size=None):
    method reuse_chunk (line 879) | def reuse_chunk(self, id, size, stats):
    method add_chunk (line 884) | def add_chunk(
    method _maybe_write_chunks_cache (line 921) | def _maybe_write_chunks_cache(self, now, force=False, clear=False):
    method refresh_lock (line 927) | def refresh_lock(self, now):
  class AdHocWithFilesCache (line 935) | class AdHocWithFilesCache(FilesCacheMixin, ChunksMixin):
    method __init__ (line 946) | def __init__(
    method __enter__ (line 991) | def __enter__(self):
    method __exit__ (line 995) | def __exit__(self, exc_type, exc_val, exc_tb):
    method create (line 999) | def create(self):
    method open (line 1006) | def open(self):
    method close (line 1012) | def close(self):
    method check_cache_compatibility (line 1033) | def check_cache_compatibility(self):
    method wipe_cache (line 1045) | def wipe_cache(self):
    method update_compatibility (line 1054) | def update_compatibility(self):

FILE: src/borg/checksums.pyi
  function crc32 (line 1) | def crc32(data: bytes, value: int = 0) -> int: ...

FILE: src/borg/chunkers/__init__.py
  function get_chunker (line 8) | def get_chunker(algo, *params, **kw):

FILE: src/borg/chunkers/buzhash.pyi
  function buzhash (line 5) | def buzhash(data: bytes, seed: int) -> int: ...
  function buzhash_update (line 6) | def buzhash_update(sum: int, remove: int, add: int, len: int, seed: int)...
  class Chunker (line 8) | class Chunker:
    method __init__ (line 9) | def __init__(
    method chunkify (line 18) | def chunkify(self, fd: BinaryIO = None, fh: int = -1, fmap: List[fmap_...

FILE: src/borg/chunkers/buzhash64.pyi
  function buzhash64 (line 5) | def buzhash64(data: bytes, key: bytes) -> int: ...
  function buzhash64_update (line 6) | def buzhash64_update(sum: int, remove: int, add: int, len: int, key: byt...
  function buzhash64_get_table (line 7) | def buzhash64_get_table(key: bytes) -> List[int]: ...
  class ChunkerBuzHash64 (line 9) | class ChunkerBuzHash64:
    method __init__ (line 10) | def __init__(
    method chunkify (line 19) | def chunkify(self, fd: BinaryIO = None, fh: int = -1, fmap: List[fmap_...

FILE: src/borg/chunkers/failing.py
  class ChunkerFailing (line 9) | class ChunkerFailing:
    method __init__ (line 18) | def __init__(self, block_size: int, map: str) -> None:
    method chunkify (line 29) | def chunkify(self, fd: BinaryIO | None = None, fh: int = -1) -> Iterator:

FILE: src/borg/chunkers/fixed.py
  class ChunkerFixed (line 9) | class ChunkerFixed:
    method __init__ (line 30) | def __init__(self, block_size: int, header_size: int = 0, sparse: bool...
    method chunkify (line 38) | def chunkify(self, fd: BinaryIO | None = None, fh: int = -1, fmap: lis...

FILE: src/borg/chunkers/reader.pyi
  class _Chunk (line 5) | class _Chunk(NamedTuple):
  function Chunk (line 9) | def Chunk(data: bytes | None, **meta) -> Type[_Chunk]: ...
  function sparsemap (line 13) | def sparsemap(fd: BinaryIO = None, fh: int = -1) -> List[fmap_entry]: ...
  class FileFMAPReader (line 15) | class FileFMAPReader:
    method __init__ (line 16) | def __init__(
    method _build_fmap (line 25) | def _build_fmap(self) -> List[fmap_entry]: ...
    method blockify (line 26) | def blockify(self) -> Iterator: ...
  class FileReader (line 28) | class FileReader:
    method __init__ (line 29) | def __init__(
    method _fill_buffer (line 38) | def _fill_buffer(self) -> bool: ...
    method read (line 39) | def read(self, size: int) -> Type[_Chunk]: ...

FILE: src/borg/cockpit/app.py
  class BorgCockpitApp (line 15) | class BorgCockpitApp(App):
    method compose (line 24) | def compose(self) -> ComposeResult:
    method get_theme_variable_defaults (line 39) | def get_theme_variable_defaults(self):
    method on_load (line 49) | def on_load(self) -> None:
    method on_mount (line 54) | def on_mount(self) -> None:
    method start_runner (line 62) | def start_runner(self) -> None:
    method compute_speed (line 77) | def compute_speed(self) -> None:
    method on_unmount (line 88) | async def on_unmount(self) -> None:
    method action_quit (line 93) | async def action_quit(self) -> None:
    method action_toggle_translator (line 106) | def action_toggle_translator(self) -> None:
    method handle_log_event (line 116) | def handle_log_event(self, data: dict):

FILE: src/borg/cockpit/runner.py
  class BorgRunner (line 12) | class BorgRunner:
    method __init__ (line 17) | def __init__(self, command: List[str], log_callback: Callable[[dict], ...
    method start (line 23) | async def start(self):
    method stop (line 67) | async def stop(self):

FILE: src/borg/cockpit/translator.py
  class UniversalTranslator (line 19) | class UniversalTranslator:
    method __init__ (line 24) | def __init__(self, enabled: bool = True):
    method toggle (line 29) | def toggle(self):
    method translate (line 34) | def translate(self, message: str) -> str:

FILE: src/borg/cockpit/widgets.py
  class StatusPanel (line 17) | class StatusPanel(Static):
    method __init__ (line 27) | def __init__(self, *args, **kwargs):
    method compose (line 31) | def compose(self) -> ComposeResult:
    method update_speed (line 46) | def update_speed(self, kfiles_per_second: float):
    method watch_error_count (line 53) | def watch_error_count(self, count: int) -> None:
    method watch_files_count (line 63) | def watch_files_count(self, count: int) -> None:
    method watch_unchanged_count (line 66) | def watch_unchanged_count(self, count: int) -> None:
    method watch_modified_count (line 69) | def watch_modified_count(self, count: int) -> None:
    method watch_added_count (line 72) | def watch_added_count(self, count: int) -> None:
    method watch_other_count (line 75) | def watch_other_count(self, count: int) -> None:
    method watch_rc (line 78) | def watch_rc(self, rc: int):
    method watch_elapsed_time (line 98) | def watch_elapsed_time(self, elapsed: float) -> None:
    method refresh_ui_labels (line 112) | def refresh_ui_labels(self):
  class StandardLog (line 128) | class StandardLog(Vertical):
    method compose (line 129) | def compose(self) -> ComposeResult:
    method update_title (line 133) | def update_title(self):
    method add_line (line 136) | def add_line(self, line: str):
  class Starfield (line 183) | class Starfield(Static):
    method __init__ (line 184) | def __init__(self, *args, **kwargs):
    method on_mount (line 190) | def on_mount(self) -> None:
    method on_resize (line 193) | def on_resize(self, event) -> None:
    method _update_art (line 196) | def _update_art(self) -> None:
  class Pulsar (line 243) | class Pulsar(Static):
    method on_mount (line 248) | def on_mount(self) -> None:
    method pulse (line 252) | def pulse(self) -> None:
    method update_art (line 255) | def update_art(self) -> None:
  class Slogan (line 259) | class Slogan(Static):
    method on_mount (line 264) | def on_mount(self) -> None:
    method pulse (line 268) | def pulse(self) -> None:
    method update_slogan (line 271) | def update_slogan(self):
  class Logo (line 275) | class Logo(Static):
    method on_mount (line 287) | def on_mount(self) -> None:
  class LogoPanel (line 298) | class LogoPanel(Container):
    method __init__ (line 299) | def __init__(self, *args, **kwargs):
    method compose (line 303) | def compose(self) -> ComposeResult:
    method on_resize (line 309) | def on_resize(self, event) -> None:
  class SpeedSparkline (line 376) | class SpeedSparkline(Static):
    method __init__ (line 384) | def __init__(self, data: list[float] = None, **kwargs):
    method update_data (line 388) | def update_data(self, data: list[float]):
    method refresh_chart (line 392) | def refresh_chart(self):
    method on_resize (line 429) | def on_resize(self, event):

FILE: src/borg/compress.pyi
  function get_compressor (line 3) | def get_compressor(name: str, **kwargs) -> Any: ...
  class Compressor (line 5) | class Compressor:
    method __init__ (line 6) | def __init__(self, name: Any = ..., **kwargs) -> None: ...
    method compress (line 7) | def compress(self, meta: Dict, data: bytes) -> Tuple[Dict, bytes]: ...
    method decompress (line 8) | def decompress(self, meta: Dict, data: bytes) -> Tuple[Dict, bytes]: ...
    method detect (line 10) | def detect(data: bytes) -> Any: ...
  class CompressorBase (line 12) | class CompressorBase:
    method detect (line 16) | def detect(self, data: bytes) -> bool: ...
    method __init__ (line 17) | def __init__(self, level: int = ..., **kwargs) -> None: ...
    method decide (line 18) | def decide(self, data: bytes) -> Any: ...
    method compress (line 19) | def compress(self, data: bytes) -> bytes: ...
    method decompress (line 20) | def decompress(self, data: bytes) -> bytes: ...
  class Auto (line 22) | class Auto(CompressorBase):
    method __init__ (line 23) | def __init__(self, compressor: Any) -> None: ...
  class DecidingCompressor (line 25) | class DecidingCompressor(CompressorBase):
    method __init__ (line 26) | def __init__(self, level: int = ..., **kwargs) -> None: ...
    method decide_compress (line 27) | def decide_compress(self, data: bytes) -> Any: ...
  class CNONE (line 29) | class CNONE(CompressorBase):
    method __init__ (line 30) | def __init__(self, level: int = ..., **kwargs) -> None: ...
  class ObfuscateSize (line 32) | class ObfuscateSize(CompressorBase):
    method __init__ (line 33) | def __init__(self, level: int = ..., compressor: Any = ...) -> None: ...
  class ZLIB_legacy (line 35) | class ZLIB_legacy(CompressorBase):
    method __init__ (line 36) | def __init__(self, level: int = ..., **kwargs) -> None: ...
  class ZLIB (line 39) | class ZLIB(CompressorBase):
    method __init__ (line 40) | def __init__(self, level: int = ..., **kwargs) -> None: ...
  class LZ4 (line 43) | class LZ4(DecidingCompressor):
    method __init__ (line 44) | def __init__(self, level: int = ..., **kwargs) -> None: ...
  class LZMA (line 46) | class LZMA(DecidingCompressor):
    method __init__ (line 47) | def __init__(self, level: int = ..., **kwargs) -> None: ...
  class ZSTD (line 50) | class ZSTD(DecidingCompressor):
    method __init__ (line 51) | def __init__(self, level: int = ..., **kwargs) -> None: ...

FILE: src/borg/conftest.py
  function clean_env (line 22) | def clean_env(tmpdir_factory, monkeypatch):
  function pytest_report_header (line 37) | def pytest_report_header(config, start_path):
  function set_env_variables (line 62) | def set_env_variables():
  function backup_files (line 70) | def backup_files(tmp_path_factory):
  class ArchiverSetup (line 81) | class ArchiverSetup:
    method __init__ (line 86) | def __init__(self):
    method get_kind (line 98) | def get_kind(self) -> str:
  function archiver (line 108) | def archiver(tmp_path, set_env_variables):
  function remote_archiver (line 140) | def remote_archiver(archiver):
  function binary_archiver (line 146) | def binary_archiver(archiver):

FILE: src/borg/constants.py
  class KeyBlobStorage (line 167) | class KeyBlobStorage:
  class KeyType (line 173) | class KeyType:

FILE: src/borg/crypto/file_integrity.py
  class FileLikeWrapper (line 16) | class FileLikeWrapper:
    method __init__ (line 17) | def __init__(self, fd):
    method __enter__ (line 20) | def __enter__(self):
    method __exit__ (line 24) | def __exit__(self, exc_type, exc_val, exc_tb):
    method tell (line 27) | def tell(self):
    method seek (line 30) | def seek(self, offset, whence=io.SEEK_SET):
    method write (line 33) | def write(self, data):
    method read (line 36) | def read(self, n=None):
    method flush (line 39) | def flush(self):
    method fileno (line 42) | def fileno(self):
  class FileHashingWrapper (line 46) | class FileHashingWrapper(FileLikeWrapper):
    method __init__ (line 65) | def __init__(self, backing_fd, write):
    method __exit__ (line 70) | def __exit__(self, exc_type, exc_val, exc_tb):
    method write (line 75) | def write(self, data):
    method read (line 83) | def read(self, n=None):
    method hexdigest (line 91) | def hexdigest(self):
    method update (line 99) | def update(self, data: bytes):
    method hash_length (line 102) | def hash_length(self, seek_to_end=False):
  class SHA512FileHashingWrapper (line 109) | class SHA512FileHashingWrapper(FileHashingWrapper):
  class XXH64FileHashingWrapper (line 114) | class XXH64FileHashingWrapper(FileHashingWrapper):
  class FileIntegrityError (line 125) | class FileIntegrityError(IntegrityError):
  class IntegrityCheckedFile (line 131) | class IntegrityCheckedFile(FileLikeWrapper):
    method __init__ (line 132) | def __init__(self, path, write, filename=None, override_fd=None, integ...
    method load_integrity_data (line 155) | def load_integrity_data(self, path, integrity_data):
    method hash_filename (line 159) | def hash_filename(self, filename=None):
    method parse_integrity_data (line 171) | def parse_integrity_data(cls, path: str, data: str):
    method hash_part (line 187) | def hash_part(self, partname, is_final=False):
    method __exit__ (line 199) | def __exit__(self, exc_type, exc_val, exc_tb):
    method store_integrity_data (line 216) | def store_integrity_data(self, data: str):
  class DetachedIntegrityCheckedFile (line 220) | class DetachedIntegrityCheckedFile(IntegrityCheckedFile):
    method __init__ (line 221) | def __init__(self, path, write, filename=None, override_fd=None):
    method load_integrity_data (line 227) | def load_integrity_data(self, path, integrity_data):
    method integrity_file_path (line 232) | def integrity_file_path(path):
    method read_integrity_file (line 236) | def read_integrity_file(cls, path):
    method store_integrity_data (line 246) | def store_integrity_data(self, data: str):

FILE: src/borg/crypto/key.py
  class UnsupportedPayloadError (line 39) | class UnsupportedPayloadError(Error):
  class UnsupportedManifestError (line 45) | class UnsupportedManifestError(Error):
  class KeyfileNotFoundError (line 51) | class KeyfileNotFoundError(Error):
  class KeyfileInvalidError (line 57) | class KeyfileInvalidError(Error):
  class KeyfileMismatchError (line 63) | class KeyfileMismatchError(Error):
  class RepoKeyNotFoundError (line 69) | class RepoKeyNotFoundError(Error):
  class UnsupportedKeyFormatError (line 75) | class UnsupportedKeyFormatError(Error):
  function key_creator (line 81) | def key_creator(repository, args, *, other_key=None):
  function key_argument_names (line 90) | def key_argument_names():
  function identify_key (line 94) | def identify_key(manifest_data):
  function key_factory (line 106) | def key_factory(repository, manifest_chunk, *, other=False, ro_cls=RepoO...
  function uses_same_chunker_secret (line 112) | def uses_same_chunker_secret(other_key, key):
  function uses_same_id_hash (line 119) | def uses_same_id_hash(other_key, key):
  class KeyBase (line 145) | class KeyBase:
    method __init__ (line 179) | def __init__(self, repository):
    method id_hash (line 185) | def id_hash(self, data):
    method encrypt (line 189) | def encrypt(self, id, data):
    method decrypt (line 192) | def decrypt(self, id, data):
    method assert_id (line 195) | def assert_id(self, id, data):
    method assert_type (line 201) | def assert_type(self, type_byte, id=None):
    method derive_key (line 206) | def derive_key(self, *, salt, domain, size, from_id_key=False):
    method pack_metadata (line 221) | def pack_metadata(self, metadata_dict):
    method unpack_manifest (line 225) | def unpack_manifest(self, data):
    method unpack_archive (line 237) | def unpack_archive(self, data):
  class PlaintextKey (line 247) | class PlaintextKey(KeyBase):
    method create (line 260) | def create(cls, repository, args, **kw):
    method detect (line 265) | def detect(cls, repository, manifest_data, *, other=False):
    method id_hash (line 268) | def id_hash(self, data):
    method encrypt (line 271) | def encrypt(self, id, data):
    method decrypt (line 274) | def decrypt(self, id, data):
  function random_blake2b_256_key (line 279) | def random_blake2b_256_key():
  class ID_BLAKE2b_256 (line 293) | class ID_BLAKE2b_256:
    method id_hash (line 300) | def id_hash(self, data):
    method init_from_random_data (line 303) | def init_from_random_data(self):
  class ID_HMAC_SHA_256 (line 311) | class ID_HMAC_SHA_256:
    method id_hash (line 318) | def id_hash(self, data):
  class AESKeyBase (line 322) | class AESKeyBase(KeyBase):
    method encrypt (line 340) | def encrypt(self, id, data):
    method decrypt (line 345) | def decrypt(self, id, data):
    method init_from_given_data (line 352) | def init_from_given_data(self, *, crypt_key, id_key, chunk_seed):
    method init_from_random_data (line 360) | def init_from_random_data(self):
    method init_ciphers (line 368) | def init_ciphers(self, manifest_data=None):
  class FlexiKey (line 383) | class FlexiKey:
    method detect (line 388) | def detect(cls, repository, manifest_data, *, other=False):
    method _load (line 411) | def _load(self, key_data, passphrase):
    method decrypt_key_file (line 432) | def decrypt_key_file(self, data, passphrase):
    method pbkdf2 (line 449) | def pbkdf2(passphrase, salt, iterations, output_len_in_bytes):
    method argon2 (line 455) | def argon2(
    method decrypt_key_file_pbkdf2 (line 481) | def decrypt_key_file_pbkdf2(self, encrypted_key, passphrase):
    method decrypt_key_file_argon2 (line 488) | def decrypt_key_file_argon2(self, encrypted_key, passphrase):
    method encrypt_key_file (line 504) | def encrypt_key_file(self, data, passphrase, algorithm):
    method encrypt_key_file_pbkdf2 (line 512) | def encrypt_key_file_pbkdf2(self, data, passphrase):
    method encrypt_key_file_argon2 (line 521) | def encrypt_key_file_argon2(self, data, passphrase):
    method _save (line 534) | def _save(self, passphrase, algorithm):
    method change_passphrase (line 546) | def change_passphrase(self, passphrase=None):
    method create (line 552) | def create(cls, repository, args, *, other_key=None):
    method sanity_check (line 580) | def sanity_check(self, filename, id):
    method find_key (line 616) | def find_key(self):
    method get_existing_or_new_target (line 635) | def get_existing_or_new_target(self, args):
    method _find_key_in_keys_dir (line 644) | def _find_key_in_keys_dir(self):
    method get_new_target (line 654) | def get_new_target(self, args):
    method _find_key_file_from_environment (line 665) | def _find_key_file_from_environment(self):
    method _get_new_target_in_keys_dir (line 670) | def _get_new_target_in_keys_dir(self, args):
    method load (line 679) | def load(self, target, passphrase):
    method save (line 703) | def save(self, target, passphrase, algorithm, create=False):
    method remove (line 723) | def remove(self, target):
  class KeyfileKey (line 732) | class KeyfileKey(ID_HMAC_SHA_256, AESKeyBase, FlexiKey):
  class RepoKey (line 741) | class RepoKey(ID_HMAC_SHA_256, AESKeyBase, FlexiKey):
  class Blake2KeyfileKey (line 750) | class Blake2KeyfileKey(ID_BLAKE2b_256, AESKeyBase, FlexiKey):
  class Blake2RepoKey (line 759) | class Blake2RepoKey(ID_BLAKE2b_256, AESKeyBase, FlexiKey):
  class AuthenticatedKeyBase (line 768) | class AuthenticatedKeyBase(AESKeyBase, FlexiKey):
    method _load (line 774) | def _load(self, key_data, passphrase):
    method load (line 786) | def load(self, target, passphrase):
    method save (line 791) | def save(self, target, passphrase, algorithm, create=False):
    method init_ciphers (line 795) | def init_ciphers(self, manifest_data=None):
    method encrypt (line 799) | def encrypt(self, id, data):
    method decrypt (line 802) | def decrypt(self, id, data):
  class AuthenticatedKey (line 807) | class AuthenticatedKey(ID_HMAC_SHA_256, AuthenticatedKeyBase):
  class Blake2AuthenticatedKey (line 814) | class Blake2AuthenticatedKey(ID_BLAKE2b_256, AuthenticatedKeyBase):
  class AEADKeyBase (line 824) | class AEADKeyBase(KeyBase):
    method assert_id (line 849) | def assert_id(self, id, data):
    method encrypt (line 868) | def encrypt(self, id, data):
    method decrypt (line 878) | def decrypt(self, id, data):
    method init_from_given_data (line 890) | def init_from_given_data(self, *, crypt_key, id_key, chunk_seed):
    method init_from_random_data (line 898) | def init_from_random_data(self):
    method _get_session_key (line 906) | def _get_session_key(self, sessionid, domain=None):
    method _get_cipher (line 921) | def _get_cipher(self, sessionid, iv):
    method init_ciphers (line 927) | def init_ciphers(self, manifest_data=None, iv=0):
  class AESOCBKeyfileKey (line 933) | class AESOCBKeyfileKey(ID_HMAC_SHA_256, AEADKeyBase, FlexiKey):
  class AESOCBRepoKey (line 942) | class AESOCBRepoKey(ID_HMAC_SHA_256, AEADKeyBase, FlexiKey):
  class CHPOKeyfileKey (line 951) | class CHPOKeyfileKey(ID_HMAC_SHA_256, AEADKeyBase, FlexiKey):
  class CHPORepoKey (line 960) | class CHPORepoKey(ID_HMAC_SHA_256, AEADKeyBase, FlexiKey):
  class Blake2AESOCBKeyfileKey (line 969) | class Blake2AESOCBKeyfileKey(ID_BLAKE2b_256, AEADKeyBase, FlexiKey):
  class Blake2AESOCBRepoKey (line 978) | class Blake2AESOCBRepoKey(ID_BLAKE2b_256, AEADKeyBase, FlexiKey):
  class Blake2CHPOKeyfileKey (line 987) | class Blake2CHPOKeyfileKey(ID_BLAKE2b_256, AEADKeyBase, FlexiKey):
  class Blake2CHPORepoKey (line 996) | class Blake2CHPORepoKey(ID_BLAKE2b_256, AEADKeyBase, FlexiKey):

FILE: src/borg/crypto/keymanager.py
  class NotABorgKeyFile (line 13) | class NotABorgKeyFile(Error):
  class RepoIdMismatch (line 19) | class RepoIdMismatch(Error):
  class UnencryptedRepo (line 25) | class UnencryptedRepo(Error):
  class UnknownKeyType (line 31) | class UnknownKeyType(Error):
  function sha256_truncated (line 37) | def sha256_truncated(data, num):
  class KeyManager (line 43) | class KeyManager:
    method __init__ (line 44) | def __init__(self, repository):
    method load_keyblob (line 56) | def load_keyblob(self):
    method store_keyblob (line 71) | def store_keyblob(self, args):
    method get_keyfile_data (line 80) | def get_keyfile_data(self):
    method store_keyfile (line 87) | def store_keyfile(self, target):
    method export (line 91) | def export(self, path):
    method export_qr (line 97) | def export_qr(self, path):
    method export_paperkey (line 107) | def export_paperkey(self, path):
    method import_keyfile (line 145) | def import_keyfile(self, args):
    method import_paperkey (line 159) | def import_paperkey(self, args):

FILE: src/borg/crypto/low_level.pyi
  function num_cipher_blocks (line 7) | def num_cipher_blocks(length: int, blocksize: int = 16) -> int:
  function bytes_to_int (line 11) | def bytes_to_int(x: bytes, offset: int = 0) -> int: ...
  function bytes_to_long (line 12) | def bytes_to_long(x: bytes, offset: int = 0) -> int: ...
  function long_to_bytes (line 13) | def long_to_bytes(x: int) -> bytes: ...
  function hmac_sha256 (line 14) | def hmac_sha256(key: bytes, data: bytes) -> bytes: ...
  function blake2b_256 (line 15) | def blake2b_256(key: bytes, data: bytes) -> bytes: ...
  function blake2b_128 (line 16) | def blake2b_128(data: bytes) -> bytes: ...
  class CryptoError (line 19) | class CryptoError(Exception):
  class IntegrityError (line 24) | class IntegrityError(CryptoError):
  class UNENCRYPTED (line 30) | class UNENCRYPTED:
    method __init__ (line 36) | def __init__(
    method encrypt (line 44) | def encrypt(
    method decrypt (line 47) | def decrypt(self, envelope: bytes, aad: Optional[bytes] = None) -> mem...
    method block_count (line 48) | def block_count(self, length: int) -> int: ...
    method set_iv (line 49) | def set_iv(self, iv: Union[int, bytes]) -> None: ...
    method next_iv (line 50) | def next_iv(self) -> Union[int, bytes]: ...
    method extract_iv (line 51) | def extract_iv(self, envelope: bytes) -> int: ...
  class AES256_CTR_BASE (line 53) | class AES256_CTR_BASE:
    method requirements_check (line 57) | def requirements_check(cls) -> None: ...
    method __init__ (line 58) | def __init__(
    method encrypt (line 66) | def encrypt(
    method decrypt (line 69) | def decrypt(self, envelope: bytes, aad: Optional[bytes] = None) -> byt...
    method block_count (line 70) | def block_count(self, length: int) -> int: ...
    method set_iv (line 71) | def set_iv(self, iv: Union[int, bytes]) -> None: ...
    method next_iv (line 72) | def next_iv(self) -> int: ...
    method extract_iv (line 73) | def extract_iv(self, envelope: bytes) -> int: ...
  class AES256_CTR_HMAC_SHA256 (line 75) | class AES256_CTR_HMAC_SHA256(AES256_CTR_BASE):
    method __init__ (line 78) | def __init__(
  class AES256_CTR_BLAKE2b (line 87) | class AES256_CTR_BLAKE2b(AES256_CTR_BASE):
    method __init__ (line 90) | def __init__(
  class _AEAD_BASE (line 99) | class _AEAD_BASE:
    method requirements_check (line 103) | def requirements_check(cls) -> None:
    method __init__ (line 107) | def __init__(
    method encrypt (line 110) | def encrypt(
    method decrypt (line 113) | def decrypt(self, envelope: bytes, aad: bytes = b"") -> bytes: ...
    method block_count (line 114) | def block_count(self, length: int) -> int: ...
    method set_iv (line 115) | def set_iv(self, iv: Union[int, bytes]) -> None: ...
    method next_iv (line 116) | def next_iv(self) -> int: ...
  class AES256_OCB (line 118) | class AES256_OCB(_AEAD_BASE):
    method requirements_check (line 122) | def requirements_check(cls) -> None: ...
    method __init__ (line 123) | def __init__(
  class CHACHA20_POLY1305 (line 127) | class CHACHA20_POLY1305(_AEAD_BASE):
    method requirements_check (line 131) | def requirements_check(cls) -> None: ...
    method __init__ (line 132) | def __init__(
  class AES (line 136) | class AES:
    method __init__ (line 139) | def __init__(self, enc_key: bytes, iv: Optional[Union[int, bytes]] = N...
    method encrypt (line 140) | def encrypt(self, data: bytes, iv: Optional[Union[int, bytes]] = None)...
    method decrypt (line 141) | def decrypt(self, data: bytes) -> bytes: ...
    method block_count (line 142) | def block_count(self, length: int) -> int: ...
    method set_iv (line 143) | def set_iv(self, iv: Union[int, bytes]) -> None: ...
    method next_iv (line 144) | def next_iv(self) -> int: ...
  class CSPRNG (line 146) | class CSPRNG:
    method __init__ (line 154) | def __init__(self, seed_key: bytes) -> None:
    method random_bytes (line 162) | def random_bytes(self, n: int) -> bytes:
    method random_int (line 171) | def random_int(self, n: int) -> int:
    method shuffle (line 180) | def shuffle(self, items: list) -> None:

FILE: src/borg/fslocking.py
  class TimeoutTimer (line 18) | class TimeoutTimer:
    method __init__ (line 25) | def __init__(self, timeout=None, sleep=None):
    method __repr__ (line 46) | def __repr__(self):
    method start (line 51) | def start(self):
    method sleep (line 57) | def sleep(self):
    method timed_out (line 61) | def timed_out(self):
    method timed_out_or_sleep (line 64) | def timed_out_or_sleep(self):
  class LockError (line 72) | class LockError(Error):
  class LockErrorT (line 78) | class LockErrorT(ErrorWithTraceback):
  class LockFailed (line 84) | class LockFailed(LockErrorT):
  class LockTimeout (line 90) | class LockTimeout(LockError):
  class NotLocked (line 96) | class NotLocked(LockErrorT):
  class NotMyLock (line 102) | class NotMyLock(LockErrorT):
  class ExclusiveLock (line 108) | class ExclusiveLock:
    method __init__ (line 120) | def __init__(self, path, timeout=None, sleep=None, id=None):
    method __enter__ (line 129) | def __enter__(self):
    method __exit__ (line 132) | def __exit__(self, *exc):
    method __repr__ (line 135) | def __repr__(self):
    method acquire (line 138) | def acquire(self, timeout=None, sleep=None):
    method release (line 180) | def release(self):
    method is_locked (line 201) | def is_locked(self):
    method by_me (line 204) | def by_me(self):
    method kill_stale_lock (line 207) | def kill_stale_lock(self):
    method break_lock (line 260) | def break_lock(self):
    method migrate_lock (line 266) | def migrate_lock(self, old_id, new_id):
  class LockRoster (line 277) | class LockRoster:
    method __init__ (line 285) | def __init__(self, path, id=None):
    method load (line 291) | def load(self):
    method save (line 317) | def save(self, data):
    method remove (line 321) | def remove(self):
    method get (line 327) | def get(self, key):
    method empty (line 331) | def empty(self, *keys):
    method modify (line 334) | def modify(self, key, op):
    method migrate_lock (line 354) | def migrate_lock(self, key, old_id, new_id):
  class Lock (line 374) | class Lock:
    method __init__ (line 390) | def __init__(self, path, exclusive=False, sleep=None, timeout=None, id...
    method __enter__ (line 403) | def __enter__(self):
    method __exit__ (line 406) | def __exit__(self, *exc):
    method __repr__ (line 409) | def __repr__(self):
    method acquire (line 412) | def acquire(self, exclusive=None, remove=None, sleep=None):
    method _wait_for_readers_finishing (line 427) | def _wait_for_readers_finishing(self, remove, sleep):
    method release (line 448) | def release(self):
    method upgrade (line 460) | def upgrade(self):
    method downgrade (line 466) | def downgrade(self):
    method got_exclusive_lock (line 470) | def got_exclusive_lock(self):
    method break_lock (line 473) | def break_lock(self):
    method migrate_lock (line 477) | def migrate_lock(self, old_id, new_id):

FILE: src/borg/fuse.py
  function async_wrapper (line 43) | def async_wrapper(fn):
  function async_wrapper (line 53) | def async_wrapper(fn):
  function fuse_main (line 76) | def fuse_main():
  class ItemCache (line 97) | class ItemCache:
    method __init__ (line 116) | def __init__(self, decrypted_repository):
    method get (line 154) | def get(self, inode):
    method iter_archive_items (line 178) | def iter_archive_items(self, archive_item_ids, filter=None):
  class FuseBackend (line 269) | class FuseBackend:
    method __init__ (line 272) | def __init__(self, manifest, args, decrypted_repository):
    method _create_filesystem (line 304) | def _create_filesystem(self):
    method get_item (line 326) | def get_item(self, inode):
    method check_pending_archive (line 339) | def check_pending_archive(self, inode):
    method _allocate_inode (line 345) | def _allocate_inode(self):
    method _create_dir (line 349) | def _create_dir(self, parent, mtime=None):
    method find_inode (line 360) | def find_inode(self, path, prefix=[]):
    method _process_archive (line 367) | def _process_archive(self, archive_id, prefix=[]):
    method _process_leaf (line 402) | def _process_leaf(self, name, item, parent, prefix, is_dir, item_inode...
    method _process_inner (line 467) | def _process_inner(self, name, parent_inode):
  class FuseOperations (line 478) | class FuseOperations(llfuse.Operations, FuseBackend):
    method __init__ (line 481) | def __init__(self, manifest, args, decrypted_repository):
    method sig_info_handler (line 490) | def sig_info_handler(self, sig_no, stack):
    method mount (line 516) | def mount(self, mountpoint, mount_options, foreground=False, show_rc=F...
    method statfs (line 614) | def statfs(self, ctx=None):
    method _getattr (line 627) | def _getattr(self, inode, ctx=None):
    method getattr (line 656) | def getattr(self, inode, ctx=None):
    method listxattr (line 660) | def listxattr(self, inode, ctx=None):
    method getxattr (line 665) | def getxattr(self, inode, name, ctx=None):
    method lookup (line 673) | def lookup(self, parent_inode, name, ctx=None):
    method open (line 686) | def open(self, inode, flags, ctx=None):
    method opendir (line 690) | def opendir(self, inode, ctx=None):
    method read (line 695) | def read(self, fh, offset, size):
    method readdir (line 750) | async def readdir(self, fh, off, token):  # type: ignore[misc]
    method readdir (line 760) | def readdir(self, fh, off):  # type: ignore[misc]
    method readlink (line 768) | def readlink(self, inode, ctx=None):

FILE: src/borg/hashindex.pyi
  class ChunkIndexEntry (line 5) | class ChunkIndexEntry(NamedTuple):
  class ChunkIndex (line 11) | class ChunkIndex:
    method add (line 18) | def add(self, key: bytes, size: int) -> None: ...
    method iteritems (line 19) | def iteritems(self, *, only_new: bool = ...) -> Iterator: ...
    method clear_new (line 20) | def clear_new(self) -> None: ...
    method __contains__ (line 21) | def __contains__(self, key: bytes) -> bool: ...
    method __getitem__ (line 22) | def __getitem__(self, key: bytes) -> Type[ChunkIndexEntry]: ...
    method __setitem__ (line 23) | def __setitem__(self, key: bytes, value: CIE) -> None: ...
  class NSIndex1Entry (line 25) | class NSIndex1Entry(NamedTuple):
  class NSIndex1 (line 29) | class NSIndex1:  # legacy
    method iteritems (line 30) | def iteritems(self, *args, **kwargs) -> Iterator: ...
    method __contains__ (line 31) | def __contains__(self, key: bytes) -> bool: ...
    method __getitem__ (line 32) | def __getitem__(self, key: bytes) -> Any: ...
    method __setitem__ (line 33) | def __setitem__(self, key: bytes, value: Any) -> None: ...
  class FuseVersionsIndexEntry (line 35) | class FuseVersionsIndexEntry(NamedTuple):
  class FuseVersionsIndex (line 39) | class FuseVersionsIndex:
    method __contains__ (line 40) | def __contains__(self, key: bytes) -> bool: ...
    method __getitem__ (line 41) | def __getitem__(self, key: bytes) -> Any: ...
    method __setitem__ (line 42) | def __setitem__(self, key: bytes, value: Any) -> None: ...

FILE: src/borg/helpers/__init__.py
  function add_warning (line 81) | def add_warning(msg, *args, **kwargs):
  function classify_ec (line 97) | def classify_ec(ec):
  function max_ec (line 112) | def max_ec(ec1, ec2):
  function set_ec (line 133) | def set_ec(ec):
  function init_ec_warnings (line 141) | def init_ec_warnings(ec=EXIT_SUCCESS, warnings=None):
  function get_ec (line 152) | def get_ec(ec=None):
  function get_reset_ec (line 179) | def get_reset_ec(ec=None):
  function do_show_rc (line 186) | def do_show_rc(exit_code):

FILE: src/borg/helpers/argparsing.py
  class ArgumentParser (line 107) | class ArgumentParser(_ArgumentParser):
    method __init__ (line 109) | def __init__(self, *args, formatter_class=RawDescriptionHelpFormatter,...
  function flatten_namespace (line 113) | def flatten_namespace(ns: Any) -> Namespace:

FILE: src/borg/helpers/datastruct.py
  class StableDict (line 4) | class StableDict(dict):
    method items (line 7) | def items(self):
  class Buffer (line 11) | class Buffer:
    class MemoryLimitExceeded (line 16) | class MemoryLimitExceeded(Error, OSError):
    method __init__ (line 19) | def __init__(self, allocator, size=4096, limit=None):
    method __len__ (line 30) | def __len__(self):
    method resize (line 33) | def resize(self, size, init=False):
    method get (line 45) | def get(self, size=None, init=False):
  class EfficientCollectionQueue (line 55) | class EfficientCollectionQueue:
    class SizeUnderflow (line 60) | class SizeUnderflow(Error):
    method __init__ (line 63) | def __init__(self, split_size, member_type):
    method peek_front (line 74) | def peek_front(self):
    method pop_front (line 85) | def pop_front(self, size):
    method push_back (line 103) | def push_back(self, data):
    method __len__ (line 122) | def __len__(self):
    method __bool__ (line 128) | def __bool__(self):

FILE: src/borg/helpers/errors.py
  class ErrorBase (line 11) | class ErrorBase(Exception):
    method __init__ (line 24) | def __init__(self, *args):
    method get_message (line 28) | def get_message(self):
    method exit_code (line 34) | def exit_code(self):
  class Error (line 40) | class Error(ErrorBase):
  class ErrorWithTraceback (line 44) | class ErrorWithTraceback(Error):
  class IntegrityError (line 51) | class IntegrityError(ErrorWithTraceback, IntegrityErrorBase):
  class DecompressionError (line 57) | class DecompressionError(IntegrityError):
  class CancelledByUser (line 63) | class CancelledByUser(Error):
  class RTError (line 69) | class RTError(Error):
  class CommandError (line 73) | class CommandError(Error):
  class BorgWarning (line 79) | class BorgWarning:
    method __init__ (line 88) | def __init__(self, *args):
    method get_message (line 91) | def get_message(self):
    method exit_code (line 97) | def exit_code(self):
  class FileChangedWarning (line 103) | class FileChangedWarning(BorgWarning):
  class IncludePatternNeverMatchedWarning (line 109) | class IncludePatternNeverMatchedWarning(BorgWarning):
  class BackupWarning (line 115) | class BackupWarning(BorgWarning):
    method exit_code (line 121) | def exit_code(self):
  class BackupError (line 129) | class BackupError(ErrorBase):
  class BackupRaceConditionError (line 136) | class BackupRaceConditionError(BackupError):
  class BackupOSError (line 143) | class BackupOSError(BackupError):
    method __init__ (line 155) | def __init__(self, op, os_error):
    method __str__ (line 162) | def __str__(self):
  class BackupPermissionError (line 169) | class BackupPermissionError(BackupOSError):
  class BackupIOError (line 175) | class BackupIOError(BackupOSError):
  class BackupFileNotFoundError (line 181) | class BackupFileNotFoundError(BackupOSError):
  class BackupItemExcluded (line 187) | class BackupItemExcluded(Exception):

FILE: src/borg/helpers/fs.py
  function ensure_dir (line 26) | def ensure_dir(path, mode=stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO, pr...
  function get_base_dir (line 48) | def get_base_dir(*, legacy=False):
  function join_base_dir (line 71) | def join_base_dir(*paths, **kw):
  function get_keys_dir (line 77) | def get_keys_dir(*, legacy=False, create=True):
  function get_security_dir (line 88) | def get_security_dir(repository_id=None, *, legacy=False, create=True):
  function get_data_dir (line 102) | def get_data_dir(*, legacy=False, create=True):
  function get_runtime_dir (line 113) | def get_runtime_dir(*, legacy=False, create=True):
  function get_socket_filename (line 124) | def get_socket_filename():
  function get_cache_dir (line 128) | def get_cache_dir(*, legacy=False, create=True):
  function get_config_dir (line 164) | def get_config_dir(*, legacy=False, create=True):
  function dir_is_cachedir (line 184) | def dir_is_cachedir(path=None, dir_fd=None):
  function dir_is_tagged (line 206) | def dir_is_tagged(path=None, exclude_caches=None, exclude_if_present=Non...
  function make_path_safe (line 241) | def make_path_safe(path):
  function slashify (line 270) | def slashify(path):
  function map_chars (line 294) | def map_chars(path):
  function get_strip_prefix (line 307) | def get_strip_prefix(path):
  function remove_dotdot_prefixes (line 325) | def remove_dotdot_prefixes(path):
  function assert_sanitized_path (line 342) | def assert_sanitized_path(path):
  function to_sanitized_path (line 352) | def to_sanitized_path(path):
  class HardLinkManager (line 367) | class HardLinkManager:
    method __init__ (line 392) | def __init__(self, *, id_type, info_type):
    method borg1_hardlinkable (line 397) | def borg1_hardlinkable(self, mode):  # legacy
    method borg1_hardlink_master (line 400) | def borg1_hardlink_master(self, item):  # legacy
    method borg1_hardlink_slave (line 403) | def borg1_hardlink_slave(self, item):  # legacy
    method hardlink_id_from_path (line 406) | def hardlink_id_from_path(self, path):
    method hardlink_id_from_inode (line 411) | def hardlink_id_from_inode(self, *, ino, dev):
    method remember (line 417) | def remember(self, *, id, info):
    method retrieve (line 433) | def retrieve(self, id, *, default=None):
  function scandir_keyfunc (line 441) | def scandir_keyfunc(dirent):
  function scandir_inorder (line 454) | def scandir_inorder(*, path, fd=None):
  function secure_erase (line 459) | def secure_erase(path, *, avoid_collateral_damage):
  function safe_unlink (line 480) | def safe_unlink(path):
  function dash_open (line 517) | def dash_open(path, mode):
  function O_ (line 526) | def O_(*flags):
  function os_open (line 541) | def os_open(*, flags, path=None, parent_fd=None, name=None, noatime=False):
  function os_stat (line 588) | def os_stat(*, path=None, parent_fd=None, name=None, follow_symlinks=Fal...
  function umount (line 608) | def umount(mountpoint):
  function _mkstemp_inner (line 629) | def _mkstemp_inner(dir, pre, suf, flags, output_type, mode=0o600):
  function mkstemp_mode (line 657) | def mkstemp_mode(suffix=None, prefix=None, dir=None, text=False, mode=0o...

FILE: src/borg/helpers/lrucache.py
  class LRUCache (line 9) | class LRUCache(MutableMapping[K, V]):
    method __init__ (line 22) | def __init__(self, capacity: int, dispose: Callable[[V], None] = lambd...
    method __setitem__ (line 27) | def __setitem__(self, key: K, value: V) -> None:
    method __getitem__ (line 35) | def __getitem__(self, key: K) -> V:
    method __delitem__ (line 39) | def __delitem__(self, key: K) -> None:
    method __contains__ (line 42) | def __contains__(self, key: object) -> bool:
    method __len__ (line 45) | def __len__(self) -> int:
    method replace (line 48) | def replace(self, key: K, value: V) -> None:
    method clear (line 54) | def clear(self) -> None:
    method __iter__ (line 59) | def __iter__(self) -> Iterator[K]:
    method keys (line 62) | def keys(self) -> KeysView[K]:
    method values (line 65) | def values(self) -> ValuesView[V]:
    method items (line 68) | def items(self) -> ItemsView[K, V]:

FILE: src/borg/helpers/misc.py
  function sysinfo (line 18) | def sysinfo():
  function log_multi (line 61) | def log_multi(*msgs, level=logging.INFO, logger=logger):
  class ChunkIteratorFileWrapper (line 74) | class ChunkIteratorFileWrapper:
    method __init__ (line 77) | def __init__(self, chunk_iterator, read_callback=None):
    method _refill (line 92) | def _refill(self):
    method _read (line 105) | def _read(self, nbytes):
    method read (line 113) | def read(self, nbytes):
  function open_item (line 124) | def open_item(archive, item):
  function chunkit (line 130) | def chunkit(it, size):
  function consume (line 141) | def consume(iterator, n=None):
  class ErrorIgnoringTextIOWrapper (line 152) | class ErrorIgnoringTextIOWrapper(io.TextIOWrapper):
    method read (line 153) | def read(self, n):
    method write (line 164) | def write(self, s):
  function iter_separated (line 176) | def iter_separated(fd, sep=None, read_size=4096):

FILE: src/borg/helpers/msgpack.py
  class PackException (line 73) | class PackException(Exception):
  class UnpackException (line 77) | class UnpackException(Exception):
  class Packer (line 81) | class Packer(mp_Packer):
    method __init__ (line 82) | def __init__(
    method pack (line 102) | def pack(self, obj):
  function packb (line 109) | def packb(o, *, use_bin_type=USE_BIN_TYPE, unicode_errors=UNICODE_ERRORS...
  function pack (line 117) | def pack(o, stream, *, use_bin_type=USE_BIN_TYPE, unicode_errors=UNICODE...
  class Unpacker (line 125) | class Unpacker(mp_Unpacker):
    method __init__ (line 126) | def __init__(
    method unpack (line 158) | def unpack(self):
    method __next__ (line 166) | def __next__(self):
  function unpackb (line 177) | def unpackb(packed, *, raw=RAW, unicode_errors=UNICODE_ERRORS, strict_ma...
  function unpack (line 188) | def unpack(stream, *, raw=RAW, unicode_errors=UNICODE_ERRORS, strict_map...
  function is_slow_msgpack (line 202) | def is_slow_msgpack():
  function is_supported_msgpack (line 209) | def is_supported_msgpack():
  function get_limited_unpacker (line 224) | def get_limited_unpacker(kind):
  function int_to_timestamp (line 238) | def int_to_timestamp(ns):
  function timestamp_to_int (line 243) | def timestamp_to_int(ts):

FILE: src/borg/helpers/nanorst.py
  class TextPecker (line 7) | class TextPecker:
    method __init__ (line 8) | def __init__(self, s):
    method read (line 12) | def read(self, n):
    method peek (line 16) | def peek(self, n):
    method peekline (line 22) | def peekline(self):
    method readline (line 30) | def readline(self):
  function process_directive (line 36) | def process_directive(directive, arguments, out, state_hook):
  function rst_to_text (line 51) | def rst_to_text(text, state_hook=None, references=None):
  class RstToTextLazy (line 166) | class RstToTextLazy:
    method __init__ (line 167) | def __init__(self, str, state_hook=None, references=None):
    method rst (line 174) | def rst(self):
    method __getattr__ (line 179) | def __getattr__(self, item):
    method __str__ (line 182) | def __str__(self):
    method __add__ (line 185) | def __add__(self, other):
    method __iter__ (line 188) | def __iter__(self):
    method __contains__ (line 191) | def __contains__(self, item):
  function ansi_escapes (line 195) | def ansi_escapes(old_state, new_state, out):
  function rst_to_terminal (line 204) | def rst_to_terminal(rst, references=None, destination=sys.stdout):

FILE: src/borg/helpers/parseformat.py
  function octal_int (line 40) | def octal_int(s):
  function bin_to_hex (line 46) | def bin_to_hex(binary):
  function hex_to_bin (line 50) | def hex_to_bin(hex, length=None):
  function safe_decode (line 61) | def safe_decode(s, coding="utf-8", errors="surrogateescape"):
  function safe_encode (line 68) | def safe_encode(s, coding="utf-8", errors="surrogateescape"):
  function remove_surrogates (line 75) | def remove_surrogates(s, errors="replace"):
  function binary_to_json (line 80) | def binary_to_json(key, value):
  function text_to_json (line 86) | def text_to_json(key, value):
  function join_cmd (line 114) | def join_cmd(argv, rs=False):
  function eval_escapes (line 119) | def eval_escapes(s):
  function decode_dict (line 124) | def decode_dict(d, keys, encoding="utf-8", errors="surrogateescape"):
  function interval (line 131) | def interval(s):
  class CompressionSpec (line 168) | class CompressionSpec:
    method __init__ (line 169) | def __init__(self, s):
    method compressor (line 221) | def compressor(self):
    method __str__ (line 233) | def __str__(self):
  function ChunkerParams (line 246) | def ChunkerParams(s):
  function FilesCacheMode (line 300) | def FilesCacheMode(s):
  function partial_format (line 315) | def partial_format(format, mapping):
  class DatetimeWrapper (line 329) | class DatetimeWrapper:
    method __init__ (line 330) | def __init__(self, dt):
    method __format__ (line 333) | def __format__(self, format_spec):
  class PlaceholderError (line 339) | class PlaceholderError(Error):
  class InvalidPlaceholder (line 345) | class InvalidPlaceholder(PlaceholderError):
  function format_line (line 351) | def format_line(format, data):
  function _replace_placeholders (line 363) | def _replace_placeholders(text, overrides={}):
  class PlaceholderReplacer (line 387) | class PlaceholderReplacer:
    method __init__ (line 388) | def __init__(self):
    method override (line 391) | def override(self, key, value):
    method reset (line 394) | def reset(self):
    method __call__ (line 397) | def __call__(self, text, overrides=None):
  function PathSpec (line 405) | def PathSpec(text):
  function FilesystemPathSpec (line 411) | def FilesystemPathSpec(text):
  function SortBySpec (line 417) | def SortBySpec(text):
  function format_file_size (line 426) | def format_file_size(v, precision=2, sign=False, iec=False):
  class FileSize (line 432) | class FileSize(int):
    method __new__ (line 433) | def __new__(cls, value, iec=False):
    method __format__ (line 438) | def __format__(self, format_spec):
  function parse_file_size (line 442) | def parse_file_size(s):
  function sizeof_fmt (line 459) | def sizeof_fmt(num, suffix="B", units=None, power=None, sep="", precisio...
  function sizeof_fmt_iec (line 473) | def sizeof_fmt_iec(num, suffix="B", sep="", precision=2, sign=False):
  function sizeof_fmt_decimal (line 485) | def sizeof_fmt_decimal(num, suffix="B", sep="", precision=2, sign=False):
  function format_archive (line 497) | def format_archive(archive):
  function parse_stringified_list (line 501) | def parse_stringified_list(s):
  class Location (line 506) | class Location:
    method __init__ (line 594) | def __init__(self, text="", overrides={}, other=False):
    method parse (line 610) | def parse(self, text, overrides={}):
    method _parse (line 625) | def _parse(self, text):
    method __str__ (line 670) | def __str__(self):
    method to_key_filename (line 681) | def to_key_filename(self):
    method __repr__ (line 692) | def __repr__(self):
    method host (line 696) | def host(self):
    method canonical_path (line 701) | def canonical_path(self):
    method with_timestamp (line 716) | def with_timestamp(self, timestamp):
  function location_validator (line 727) | def location_validator(proto=None, other=False):
  function relative_time_marker_validator (line 755) | def relative_time_marker_validator(text: str):
  function text_validator (line 764) | def text_validator(*, name, max_length, min_length=0, invalid_ctrl_chars...
  function tag_validator (line 791) | def tag_validator(text):
  function archivename_validator (line 798) | def archivename_validator(text):
  class BaseFormatter (line 819) | class BaseFormatter(metaclass=abc.ABCMeta):
    method __init__ (line 843) | def __init__(self, format: str, static: dict[str, Any]) -> None:
    method get_item_data (line 848) | def get_item_data(self, item, jsonline=False) -> dict:
    method format_item (line 851) | def format_item(self, item, jsonline=False, sort=False):
    method keys_help (line 858) | def keys_help(cls):
  class ArchiveFormatter (line 876) | class ArchiveFormatter(BaseFormatter):
    method __init__ (line 899) | def __init__(self, format, repository, manifest, key, *, iec=False, de...
    method get_item_data (line 924) | def get_item_data(self, archive_info, jsonline=False):
    method archive (line 946) | def archive(self):
    method get_meta (line 954) | def get_meta(self, key, default=None):
    method get_ts_start (line 957) | def get_ts_start(self):
    method get_ts_end (line 960) | def get_ts_end(self):
    method format_time (line 963) | def format_time(self, ts):
    method get_tags (line 966) | def get_tags(self):
  class ItemFormatter (line 970) | class ItemFormatter(BaseFormatter):
    method format_needs_cache (line 1011) | def format_needs_cache(cls, format):
    method __init__ (line 1015) | def __init__(self, archive, format):
    method get_item_data (line 1048) | def get_item_data(self, item, jsonline=False):
    method calculate_num_chunks (line 1087) | def calculate_num_chunks(self, item):
    method calculate_size (line 1090) | def calculate_size(self, item):
    method calculate_fingerprint (line 1094) | def calculate_fingerprint(self, item):
    method hash_item (line 1104) | def hash_item(self, hash_function, item):
    method format_time (line 1115) | def format_time(self, key, item):
    method format_iso_time (line 1118) | def format_iso_time(self, key, item):
  class DiffFormatter (line 1122) | class DiffFormatter(BaseFormatter):
    method __init__ (line 1150) | def __init__(self, format, content_only=False):
    method get_item_data (line 1176) | def get_item_data(self, item: "ItemDiff", jsonline=False) -> dict:
    method format_other (line 1193) | def format_other(self, key, diff: "ItemDiff"):
    method format_mode (line 1197) | def format_mode(self, diff: "ItemDiff", filetype=False):
    method format_owner (line 1201) | def format_owner(self, diff: "ItemDiff", spec: Literal["owner", "user"...
    method format_content (line 1220) | def format_content(self, diff: "ItemDiff"):
    method format_time (line 1236) | def format_time(self, key, diff: "ItemDiff"):
    method format_iso_time (line 1240) | def format_iso_time(self, key, diff: "ItemDiff"):
  function file_status (line 1249) | def file_status(mode):
  function clean_lines (line 1265) | def clean_lines(lines, lstrip=None, rstrip=None, remove_empty=True, remo...
  function swidth_slice (line 1292) | def swidth_slice(string, max_width):
  function ellipsis_truncate (line 1319) | def ellipsis_truncate(msg, space):
  class BorgJsonEncoder (line 1336) | class BorgJsonEncoder(json.JSONEncoder):
    method default (line 1337) | def default(self, o):
  function basic_json_data (line 1358) | def basic_json_data(manifest, *, cache=None, extra=None):
  function json_dump (line 1370) | def json_dump(obj):
  function json_print (line 1375) | def json_print(obj):
  function prepare_dump_dict (line 1379) | def prepare_dump_dict(d):
  class Highlander (line 1424) | class Highlander(Action):
    method __init__ (line 1427) | def __init__(self, *args, **kwargs):
    method __call__ (line 1431) | def __call__(self, parser, namespace, values, option_string=None):
  class MakePathSafeAction (line 1438) | class MakePathSafeAction(Highlander):
    method __call__ (line 1439) | def __call__(self, parser, namespace, path, option_string=None):

FILE: src/borg/helpers/passphrase.py
  class NoPassphraseFailure (line 18) | class NoPassphraseFailure(Error):
  class PasscommandFailure (line 24) | class PasscommandFailure(Error):
  class PassphraseWrong (line 30) | class PassphraseWrong(Error):
  class PasswordRetriesExceeded (line 36) | class PasswordRetriesExceeded(Error):
  class Passphrase (line 42) | class Passphrase(str):
    method _check_ambiguity (line 44) | def _check_ambiguity(cls, vars):
    method _env_passphrase (line 50) | def _env_passphrase(cls, env_var, default=None):
    method env_passphrase (line 56) | def env_passphrase(cls, default=None, other=False):
    method env_passcommand (line 73) | def env_passcommand(cls, default=None, other=False):
    method fd_passphrase (line 86) | def fd_passphrase(cls, other=False):
    method env_new_passphrase (line 97) | def env_new_passphrase(cls, default=None):
    method getpass (line 101) | def getpass(cls, prompt):
    method verification (line 117) | def verification(cls, passphrase):
    method display_debug_info (line 138) | def display_debug_info(passphrase):
    method new (line 164) | def new(cls, allow_empty=False):
    method __repr__ (line 186) | def __repr__(self):

FILE: src/borg/helpers/process.py
  function _daemonize (line 22) | def _daemonize():
  function daemonize (line 56) | def daemonize():
  function daemonizing (line 66) | def daemonizing(*, timeout=5, show_rc=False):
  class _ExitCodeException (line 150) | class _ExitCodeException(BaseException):
    method __init__ (line 151) | def __init__(self, exit_code):
  class SignalException (line 155) | class SignalException(BaseException):
  class SigHup (line 159) | class SigHup(SignalException):
  class SigTerm (line 163) | class SigTerm(SignalException):
  function signal_handler (line 168) | def signal_handler(sig, handler):
  function raising_signal_handler (line 190) | def raising_signal_handler(exc_cls):
  class SigIntManager (line 201) | class SigIntManager:
    method __init__ (line 202) | def __init__(self):
    method __bool__ (line 210) | def __bool__(self):
    method action_triggered (line 214) | def action_triggered(self):
    method action_done (line 218) | def action_done(self):
    method action_completed (line 222) | def action_completed(self):
    method handler (line 228) | def handler(self, sig_no, stack):
    method __enter__ (line 246) | def __enter__(self):
    method __exit__ (line 249) | def __exit__(self, exception_type, exception_value, traceback):
  function ignore_sigint (line 260) | def ignore_sigint():
  function popen_with_error_handling (line 273) | def popen_with_error_handling(cmd_line: str, log_prefix="", **kwargs):
  function is_terminal (line 304) | def is_terminal(fd=sys.stdout):
  function prepare_subprocess_env (line 308) | def prepare_subprocess_env(system, env=None):
  function create_filter_process (line 347) | def create_filter_process(cmd, stream, stream_close, inbound=True):
  class ThreadRunner (line 410) | class ThreadRunner:
    method __init__ (line 411) | def __init__(self, sleep_interval, target, *args, **kwargs):
    method _run_with_termination (line 428) | def _run_with_termination(self):
    method start (line 441) | def start(self):
    method terminate (line 448) | def terminate(self):

FILE: src/borg/helpers/progress.py
  class ProgressIndicatorBase (line 10) | class ProgressIndicatorBase:
    method operation_id (line 17) | def operation_id(cls):
    method __init__ (line 22) | def __init__(self, msgid=None):
    method make_json (line 27) | def make_json(self, *, finished=False, **kwargs):
    method finish (line 31) | def finish(self):
  class ProgressIndicatorMessage (line 36) | class ProgressIndicatorMessage(ProgressIndicatorBase):
    method output (line 39) | def output(self, msg):
  class ProgressIndicatorPercent (line 44) | class ProgressIndicatorPercent(ProgressIndicatorBase):
    method __init__ (line 47) | def __init__(self, total=0, step=5, start=0, msg="%3.0f%%", msgid=None):
    method progress (line 64) | def progress(self, current=None, increase=1):
    method show (line 73) | def show(self, current=None, increase=1, info=None):
    method output (line 88) | def output(self, message, info=None):

FILE: src/borg/helpers/shellpattern.py
  function translate (line 6) | def translate(pat, match_end=r"\Z"):
  function _parse_braces (line 71) | def _parse_braces(pat):
  function _translate_alternatives (line 108) | def _translate_alternatives(pat):

FILE: src/borg/helpers/time.py
  function parse_timestamp (line 6) | def parse_timestamp(timestamp, tzinfo=timezone.utc):
  function parse_local_timestamp (line 17) | def parse_local_timestamp(timestamp, tzinfo=None):
  function utcfromtimestampns (line 32) | def utcfromtimestampns(ts_ns: int) -> datetime:
  function timestamp (line 38) | def timestamp(s):
  function safe_s (line 78) | def safe_s(ts):
  function safe_ns (line 87) | def safe_ns(ts):
  function safe_timestamp (line 96) | def safe_timestamp(item_timestamp_ns):
  function format_time (line 101) | def format_time(ts: datetime, format_spec=""):
  function format_timedelta (line 108) | def format_timedelta(td):
  function calculate_relative_offset (line 124) | def calculate_relative_offset(format_string, from_ts, earlier=False):
  function offset_n_months (line 160) | def offset_n_months(from_ts, n_months):
  class OutputTimestamp (line 179) | class OutputTimestamp:
    method __init__ (line 180) | def __init__(self, ts: datetime):
    method __format__ (line 183) | def __format__(self, format_spec):
    method __str__ (line 187) | def __str__(self):
    method isoformat (line 190) | def isoformat(self):
  function archive_ts_now (line 197) | def archive_ts_now():

FILE: src/borg/helpers/yes_no.py
  function yes (line 15) | def yes(

FILE: src/borg/hlfuse.py
  function debug_log (line 41) | def debug_log(msg):
  class DirEntry (line 49) | class DirEntry:
    method __init__ (line 52) | def __init__(self, ino, parent=None):
    method add_child (line 57) | def add_child(self, name, child):
    method get_child (line 63) | def get_child(self, name):
    method has_child (line 69) | def has_child(self, name):
    method iter_children (line 75) | def iter_children(self):
  class FuseBackend (line 82) | class FuseBackend:
    method __init__ (line 85) | def __init__(self, manifest, args, repository):
    method _create_node (line 115) | def _create_node(self, item=None, parent=None):
    method get_inode (line 121) | def get_inode(self, ino):
    method set_inode (line 127) | def set_inode(self, ino, item):
    method _create_filesystem (line 137) | def _create_filesystem(self):
    method check_pending_archive (line 172) | def check_pending_archive(self, node):
    method _iter_archive_items (line 177) | def _iter_archive_items(self, archive_item_ids, filter=None):
    method _process_archive (line 188) | def _process_archive(self, archive_id, root_node=None):
    method _process_leaf_versioned (line 257) | def _process_leaf_versioned(self, segments, item, root_node, hlm):
    method _file_version (line 343) | def _file_version(self, item, path):
    method _make_versioned_name (line 361) | def _make_versioned_name(self, name, version):
    method _find_node_from_root (line 370) | def _find_node_from_root(self, root, path):
    method _find_node (line 383) | def _find_node(self, path):
    method _get_handle (line 407) | def _get_handle(self, node):
    method _get_node_from_handle (line 412) | def _get_node_from_handle(self, fh):
    method _make_stat_dict (line 415) | def _make_stat_dict(self, node):
  class borgfs (line 446) | class borgfs(hlfuse.Operations, FuseBackend):
    method __init__ (line 451) | def __init__(self, manifest, args, repository):
    method sig_info_handler (line 459) | def sig_info_handler(self, sig_no, stack):
    method mount (line 463) | def mount(self, mountpoint, mount_options, foreground=False, show_rc=F...
    method statfs (line 535) | def statfs(self, path):
    method getattr (line 550) | def getattr(self, path, fh=None):
    method listxattr (line 565) | def listxattr(self, path):
    method getxattr (line 575) | def getxattr(self, path, name, position=0):
    method open (line 591) | def open(self, path, fi):
    method release (line 601) | def release(self, path, fi):
    method create (line 607) | def create(self, path, mode, fi=None):
    method read (line 611) | def read(self, path, size, offset, fi):
    method readdir (line 668) | def readdir(self, path, fh=None):
    method readlink (line 690) | def readlink(self, path):

FILE: src/borg/item.pyi
  function want_bytes (line 5) | def want_bytes(v: Any, *, errors: str = ...) -> bytes: ...
  function chunks_contents_equal (line 6) | def chunks_contents_equal(chunks1: Iterator, chunks2: Iterator) -> bool:...
  class PropDict (line 8) | class PropDict:
    method __init__ (line 10) | def __init__(self, data_dict: dict = None, internal_dict: dict = None,...
    method as_dict (line 11) | def as_dict(self) -> StableDict: ...
    method get (line 12) | def get(self, key: str, default: Any = None) -> Any: ...
    method update (line 13) | def update(self, d: dict) -> None: ...
    method update_internal (line 14) | def update_internal(self, d: dict) -> None: ...
    method __contains__ (line 15) | def __contains__(self, key: str) -> bool: ...
    method __eq__ (line 16) | def __eq__(self, other: object) -> bool: ...
  class ArchiveItem (line 18) | class ArchiveItem(PropDict):
    method version (line 20) | def version(self) -> int: ...
    method version (line 22) | def version(self, val: int) -> None: ...
    method name (line 24) | def name(self) -> str: ...
    method name (line 26) | def name(self, val: str) -> None: ...
    method start (line 28) | def start(self) -> str: ...
    method start (line 30) | def start(self, val: str) -> None: ...
    method end (line 32) | def end(self) -> str: ...
    method end (line 34) | def end(self, val: str) -> None: ...
    method time (line 36) | def time(self) -> str: ...
    method time (line 38) | def time(self, val: str) -> None: ...
    method time_end (line 40) | def time_end(self) -> str: ...
    method time_end (line 42) | def time_end(self, val: str) -> None: ...
    method username (line 44) | def username(self) -> str: ...
    method username (line 46) | def username(self, val: str) -> None: ...
    method hostname (line 48) | def hostname(self) -> str: ...
    method hostname (line 50) | def hostname(self, val: str) -> None: ...
    method comment (line 52) | def comment(self) -> str: ...
    method comment (line 54) | def comment(self, val: str) -> None: ...
    method tags (line 56) | def tags(self) -> List[str]: ...
    method tags (line 58) | def tags(self, val: List[str]) -> None: ...
    method chunker_params (line 60) | def chunker_params(self) -> Tuple: ...
    method chunker_params (line 62) | def chunker_params(self, val: Tuple) -> None: ...
    method cmdline (line 64) | def cmdline(self) -> List[str]: ...
    method cmdline (line 66) | def cmdline(self, val: List[str]) -> None: ...
    method recreate_cmdline (line 68) | def recreate_cmdline(self) -> List[str]: ...
    method recreate_cmdline (line 70) | def recreate_cmdline(self, val: List[str]) -> None: ...
    method recreate_args (line 72) | def recreate_args(self) -> Any: ...
    method recreate_args (line 74) | def recreate_args(self, val: Any) -> None: ...
    method recreate_partial_chunks (line 76) | def recreate_partial_chunks(self) -> Any: ...
    method recreate_partial_chunks (line 78) | def recreate_partial_chunks(self, val: Any) -> None: ...
    method recreate_source_id (line 80) | def recreate_source_id(self) -> Any: ...
    method recreate_source_id (line 82) | def recreate_source_id(self, val: Any) -> None: ...
    method nfiles (line 84) | def nfiles(self) -> int: ...
    method nfiles (line 86) | def nfiles(self, val: int) -> None: ...
    method nfiles_parts (line 88) | def nfiles_parts(self) -> int: ...
    method nfiles_parts (line 90) | def nfiles_parts(self, val: int) -> None: ...
    method size (line 92) | def size(self) -> int: ...
    method size (line 94) | def size(self, val: int) -> None: ...
    method size_parts (line 96) | def size_parts(self) -> int: ...
    method size_parts (line 98) | def size_parts(self, val: int) -> None: ...
    method csize (line 100) | def csize(self) -> int: ...
    method csize (line 102) | def csize(self, val: int) -> None: ...
    method items (line 104) | def items(self) -> List: ...
    method items (line 106) | def items(self, val: List) -> None: ...
    method item_ptrs (line 108) | def item_ptrs(self) -> List: ...
    method item_ptrs (line 110) | def item_ptrs(self, val: List) -> None: ...
  class ChunkListEntry (line 112) | class ChunkListEntry(NamedTuple):
  class Item (line 116) | class Item(PropDict):
    method path (line 118) | def path(self) -> str: ...
    method path (line 120) | def path(self, val: str) -> None: ...
    method source (line 122) | def source(self) -> str: ...
    method source (line 124) | def source(self, val: str) -> None: ...
    method is_dir (line 125) | def is_dir(self) -> bool: ...
    method is_link (line 126) | def is_link(self) -> bool: ...
    method _is_type (line 127) | def _is_type(self, typetest: Callable) -> bool: ...
    method create_deleted (line 129) | def create_deleted(self, path) -> Item: ...
    method from_optr (line 131) | def from_optr(self, optr: Any) -> Item: ...
    method to_optr (line 132) | def to_optr(self) -> Any: ...
    method atime (line 134) | def atime(self) -> int: ...
    method atime (line 136) | def atime(self, val: int) -> None: ...
    method ctime (line 138) | def ctime(self) -> int: ...
    method ctime (line 140) | def ctime(self, val: int) -> None: ...
    method mtime (line 142) | def mtime(self) -> int: ...
    method mtime (line 144) | def mtime(self, val: int) -> None: ...
    method birthtime (line 146) | def birthtime(self) -> int: ...
    method birthtime (line 148) | def birthtime(self, val: int) -> None: ...
    method xattrs (line 150) | def xattrs(self) -> StableDict: ...
    method xattrs (line 152) | def xattrs(self, val: StableDict) -> None: ...
    method acl_access (line 154) | def acl_access(self) -> bytes: ...
    method acl_access (line 156) | def acl_access(self, val: bytes) -> None: ...
    method acl_default (line 158) | def acl_default(self) -> bytes: ...
    method acl_default (line 160) | def acl_default(self, val: bytes) -> None: ...
    method acl_extended (line 162) | def acl_extended(self) -> bytes: ...
    method acl_extended (line 164) | def acl_extended(self, val: bytes) -> None: ...
    method acl_nfs4 (line 166) | def acl_nfs4(self) -> bytes: ...
    method acl_nfs4 (line 168) | def acl_nfs4(self, val: bytes) -> None: ...
    method bsdflags (line 170) | def bsdflags(self) -> int: ...
    method bsdflags (line 172) | def bsdflags(self, val: int) -> None: ...
    method chunks (line 174) | def chunks(self) -> List: ...
    method chunks (line 176) | def chunks(self, val: List) -> None: ...
    method chunks_healthy (line 178) | def chunks_healthy(self) -> List: ...
    method chunks_healthy (line 180) | def chunks_healthy(self, val: List) -> None: ...
    method deleted (line 182) | def deleted(self) -> bool: ...
    method deleted (line 184) | def deleted(self, val: bool) -> None: ...
    method hlid (line 186) | def hlid(self) -> bytes: ...
    method hlid (line 188) | def hlid(self, val: bytes) -> None: ...
    method hardlink_master (line 190) | def hardlink_master(self) -> bool: ...
    method hardlink_master (line 192) | def hardlink_master(self, val: bool) -> None: ...
    method uid (line 194) | def uid(self) -> int: ...
    method uid (line 196) | def uid(self, val: int) -> None: ...
    method gid (line 198) | def gid(self) -> int: ...
    method gid (line 200) | def gid(self, val: int) -> None: ...
    method user (line 202) | def user(self) -> str: ...
    method user (line 204) | def user(self, val: str) -> None: ...
    method group (line 206) | def group(self) -> str: ...
    method group (line 208) | def group(self, val: str) -> None: ...
    method mode (line 210) | def mode(self) -> int: ...
    method mode (line 212) | def mode(self, val: int) -> None: ...
    method rdev (line 214) | def rdev(self) -> int: ...
    method rdev (line 216) | def rdev(self, val: int) -> None: ...
    method nlink (line 218) | def nlink(self) -> int: ...
    method nlink (line 220) | def nlink(self, val: int) -> None: ...
    method inode (line 222) | def inode(self) -> int: ...
    method inode (line 224) | def inode(self, val: int) -> None: ...
    method size (line 226) | def size(self) -> int: ...
    method size (line 228) | def size(self, val: int) -> None: ...
    method get_size (line 229) | def get_size(
    method part (line 238) | def part(self) -> int: ...
    method part (line 240) | def part(self, val: int) -> None: ...
  class ManifestItem (line 242) | class ManifestItem(PropDict):
    method version (line 244) | def version(self) -> int: ...
    method version (line 246) | def version(self, val: int) -> None: ...
    method timestamp (line 248) | def timestamp(self) -> str: ...
    method timestamp (line 250) | def timestamp(self, val: str) -> None: ...
    method archives (line 252) | def archives(self) -> Mapping[bytes, dict]: ...
    method archives (line 254) | def archives(self, val: Mapping[bytes, dict]) -> None: ...
    method config (line 256) | def config(self) -> Dict: ...
    method config (line 258) | def config(self, val: Dict) -> None: ...
    method item_keys (line 260) | def item_keys(self) -> Tuple: ...
    method item_keys (line 262) | def item_keys(self, val: Tuple) -> None: ...
  class DiffChange (line 264) | class DiffChange:
    method __init__ (line 267) | def __init__(self, diff_type: str, diff_data: Dict[str, Any] | None = ...
    method to_dict (line 268) | def to_dict(self) -> Dict[str, Any]: ...
  class ItemDiff (line 270) | class ItemDiff:
    method __init__ (line 278) | def __init__(
    method changes (line 288) | def changes(self) -> Dict[str, DiffChange]: ...
    method equal (line 289) | def equal(self, content_only: bool = ...) -> bool: ...
    method content (line 290) | def content(self) -> DiffChange | None: ...
    method ctime (line 291) | def ctime(self) -> DiffChange | None: ...
    method mtime (line 292) | def mtime(self) -> DiffChange | None: ...
    method mode (line 293) | def mode(self) -> DiffChange | None: ...
    method type (line 294) | def type(self) -> DiffChange | None: ...
    method owner (line 295) | def owner(self) -> DiffChange | None: ...
    method user (line 296) | def user(self) -> DiffChange | None: ...
    method group (line 297) | def group(self) -> DiffChange | None: ...
  function chunk_content_equal (line 299) | def chunk_content_equal(chunks_a: Iterator, chunks_b: Iterator) -> bool:...
  class Key (line 301) | class Key(PropDict):
    method version (line 303) | def version(self) -> int: ...
    method version (line 305) | def version(self, val: int) -> None: ...
    method chunk_seed (line 307) | def chunk_seed(self) -> int: ...
    method chunk_seed (line 309) | def chunk_seed(self, val: int) -> None: ...
    method tam_required (line 311) | def tam_required(self) -> bool: ...
    method tam_required (line 313) | def tam_required(self, val: bool) -> None: ...
    method enc_hmac_key (line 315) | def enc_hmac_key(self) -> bytes: ...
    method enc_hmac_key (line 317) | def enc_hmac_key(self, val: bytes) -> None: ...
    method enc_key (line 319) | def enc_key(self) -> bytes: ...
    method enc_key (line 321) | def enc_key(self, val: bytes) -> None: ...
    method id_key (line 323) | def id_key(self) -> bytes: ...
    method id_key (line 325) | def id_key(self, val: bytes) -> None: ...
    method repository_id (line 327) | def repository_id(self) -> bytes: ...
    method repository_id (line 329) | def repository_id(self, val: bytes) -> None: ...
  class EncryptedKey (line 331) | class EncryptedKey(PropDict):
    method version (line 333) | def version(self) -> int: ...
    method version (line 335) | def version(self, val: int) -> None: ...
    method algorithm (line 337) | def algorithm(self) -> str: ...
    method algorithm (line 339) | def algorithm(self, val: str) -> None: ...
    method salt (line 341) | def salt(self) -> bytes: ...
    method salt (line 343) | def salt(self, val: bytes) -> None: ...
    method iterations (line 345) | def iterations(self) -> int: ...
    method iterations (line 347) | def iterations(self, val: int) -> None: ...
    method data (line 349) | def data(self) -> bytes: ...
    method data (line 351) | def data(self, val: bytes) -> None: ...
    method hash (line 353) | def hash(self) -> bytes: ...
    method hash (line 355) | def hash(self, val: bytes) -> None: ...

FILE: src/borg/legacyremote.py
  class ConnectionClosed (line 48) | class ConnectionClosed(Error):
  class ConnectionClosedWithHint (line 54) | class ConnectionClosedWithHint(ConnectionClosed):
  class PathNotAllowed (line 60) | class PathNotAllowed(Error):
  class InvalidRPCMethod (line 66) | class InvalidRPCMethod(Error):
  class UnexpectedRPCDataFormatFromClient (line 72) | class UnexpectedRPCDataFormatFromClient(Error):
  class UnexpectedRPCDataFormatFromServer (line 78) | class UnexpectedRPCDataFormatFromServer(Error):
    method __init__ (line 83) | def __init__(self, data):
  class ConnectionBrokenWithHint (line 93) | class ConnectionBrokenWithHint(Error):
  class SleepingBandwidthLimiter (line 115) | class SleepingBandwidthLimiter:
    method __init__ (line 116) | def __init__(self, limit):
    method write (line 124) | def write(self, fd, to_send):
  function api (line 148) | def api(*, since, **kwargs_decorator):
  class LegacyRemoteRepository (line 210) | class LegacyRemoteRepository:
    class RPCError (line 213) | class RPCError(Exception):
      method __init__ (line 214) | def __init__(self, unpacked):
      method get_message (line 218) | def get_message(self):
      method traceback (line 222) | def traceback(self):
      method exception_class (line 226) | def exception_class(self):
      method exception_full (line 230) | def exception_full(self):
      method sysinfo (line 234) | def sysinfo(self):
    class RPCServerOutdated (line 237) | class RPCServerOutdated(Error):
      method method (line 243) | def method(self):
      method required_version (line 247) | def required_version(self):
    method __init__ (line 250) | def __init__(self, location, create=False, exclusive=False, lock_wait=...
    method __del__ (line 349) | def __del__(self):
    method __repr__ (line 356) | def __repr__(self):
    method __enter__ (line 359) | def __enter__(self):
    method __exit__ (line 362) | def __exit__(self, exc_type, exc_val, exc_tb):
    method id_str (line 380) | def id_str(self):
    method borg_cmd (line 383) | def borg_cmd(self, args, testing):
    method ssh_cmd (line 426) | def ssh_cmd(self, location):
    method call (line 438) | def call(self, cmd, args, **kw):
    method call_many (line 442) | def call_many(self, cmd, calls, wait=True, is_preloaded=False, async_w...
    method open (line 633) | def open(self, path, create=False, lock_wait=None, lock=True, exclusiv...
    method info (line 637) | def info(self):
    method check (line 641) | def check(self, repair=False, max_duration=0):
    method commit (line 649) | def commit(self, compact=True, threshold=0.1):
    method rollback (line 653) | def rollback(self):
    method destroy (line 657) | def destroy(self):
    method __len__ (line 661) | def __len__(self):
    method list (line 665) | def list(self, limit=None, marker=None):
    method get (line 668) | def get(self, id, read_data=True, raise_missing=True):
    method get_many (line 672) | def get_many(self, ids, read_data=True, is_preloaded=False, raise_miss...
    method put (line 677) | def put(self, id, data, wait=True):
    method delete (line 681) | def delete(self, id, wait=True):
    method save_key (line 685) | def save_key(self, keydata):
    method load_key (line 689) | def load_key(self):
    method break_lock (line 693) | def break_lock(self):
    method close (line 696) | def close(self):
    method async_response (line 713) | def async_response(self, wait=True):
    method preload (line 717) | def preload(self, ids):
    method get_manifest (line 721) | def get_manifest(self):
    method put_manifest (line 725) | def put_manifest(self, data):
  class RepositoryNoCache (line 729) | class RepositoryNoCache:
    method __init__ (line 739) | def __init__(self, repository, transform=None):
    method close (line 743) | def close(self):
    method __enter__ (line 746) | def __enter__(self):
    method __exit__ (line 749) | def __exit__(self, exc_type, exc_val, exc_tb):
    method get (line 752) | def get(self, key, read_data=True, raise_missing=True):
    method get_many (line 755) | def get_many(self, keys, read_data=True, cache=True, raise_missing=True):
    method log_instrumentation (line 759) | def log_instrumentation(self):
  class RepositoryCache (line 763) | class RepositoryCache(RepositoryNoCache):
    method __init__ (line 775) | def __init__(self, repository, pack=None, unpack=None, transform=None):
    method query_size_limit (line 791) | def query_size_limit(self):
    method prefixed_key (line 795) | def prefixed_key(self, key, complete):
    method key_filename (line 801) | def key_filename(self, key):
    method backoff (line 804) | def backoff(self):
    method add_entry (line 814) | def add_entry(self, key, data, cache, complete):
    method log_instrumentation (line 841) | def log_instrumentation(self):
    method close (line 856) | def close(self):
    method get_many (line 861) | def get_many(self, keys, read_data=True, cache=True, raise_missing=True):
  function cache_if_remote (line 894) | def cache_if_remote(repository, *, decrypted_cache=False, pack=None, unp...

FILE: src/borg/legacyrepository.py
  function header_size (line 56) | def header_size(tag):
  class LegacyRepository (line 68) | class LegacyRepository:
    class AlreadyExists (line 138) | class AlreadyExists(Error):
    class CheckNeeded (line 143) | class CheckNeeded(ErrorWithTraceback):
    class DoesNotExist (line 148) | class DoesNotExist(Error):
    class InsufficientFreeSpaceError (line 153) | class InsufficientFreeSpaceError(Error):
    class InvalidRepository (line 158) | class InvalidRepository(Error):
    class InvalidRepositoryConfig (line 163) | class InvalidRepositoryConfig(Error):
    class ObjectNotFound (line 168) | class ObjectNotFound(ErrorWithTraceback):
      method __init__ (line 173) | def __init__(self, id, repo):
    class ParentPathDoesNotExist (line 178) | class ParentPathDoesNotExist(Error):
    class PathAlreadyExists (line 183) | class PathAlreadyExists(Error):
    class PathPermissionDenied (line 190) | class PathPermissionDenied(Error):
    method __init__ (line 195) | def __init__(self, path, create=False, exclusive=False, lock_wait=None...
    method __del__ (line 228) | def __del__(self):
    method __repr__ (line 233) | def __repr__(self):
    method __enter__ (line 236) | def __enter__(self):
    method __exit__ (line 244) | def __exit__(self, exc_type, exc_val, exc_tb):
    method id_str (line 258) | def id_str(self):
    method is_repository (line 262) | def is_repository(path):
    method check_can_create_repository (line 276) | def check_can_create_repository(self, path):
    method create (line 317) | def create(self, path):
    method save_config (line 334) | def save_config(self, path, config):
    method save_key (line 373) | def save_key(self, keydata):
    method load_key (line 380) | def load_key(self):
    method destroy (line 385) | def destroy(self):
    method get_index_transaction_id (line 391) | def get_index_transaction_id(self):
    method check_transaction (line 402) | def check_transaction(self):
    method get_transaction_id (line 422) | def get_transaction_id(self):
    method break_lock (line 426) | def break_lock(self):
    method migrate_lock (line 429) | def migrate_lock(self, old_id, new_id):
    method open (line 434) | def open(self, path, exclusive, lock_wait=None, lock=True):
    method _load_hints (line 471) | def _load_hints(self):
    method info (line 479) | def info(self):
    method close (line 485) | def close(self):
    method commit (line 493) | def commit(self, compact=True, threshold=0.1):
    method _read_integrity (line 508) | def _read_integrity(self, transaction_id, key):
    method open_index (line 521) | def open_index(self, transaction_id):
    method _unpack_hints (line 529) | def _unpack_hints(self, transaction_id):
    method prepare_txn (line 535) | def prepare_txn(self, transaction_id, do_cleanup=True):
    method write_index (line 602) | def write_index(self):
    method check_free_space (line 661) | def check_free_space(self):
    method compact_segments (line 720) | def compact_segments(self, threshold):
    method replay_segments (line 895) | def replay_segments(self, index_transaction_id, segments_transaction_id):
    method _update_index (line 921) | def _update_index(self, segment, objects, report=None):
    method _rebuild_sparse (line 960) | def _rebuild_sparse(self, segment):
    method check (line 985) | def check(self, repair=False, max_duration=0):
    method _rollback (line 1116) | def _rollback(self, *, cleanup):
    method rollback (line 1123) | def rollback(self):
    method __len__ (line 1127) | def __len__(self):
    method __contains__ (line 1132) | def __contains__(self, id):
    method list (line 1137) | def list(self, limit=None, marker=None):
    method get (line 1145) | def get(self, id, read_data=True, raise_missing=True):
    method get_many (line 1157) | def get_many(self, ids, read_data=True, is_preloaded=False, raise_miss...
    method put (line 1161) | def put(self, id, data, wait=True):
    method delete (line 1184) | def delete(self, id, wait=True):
    method _delete (line 1198) | def _delete(self, id, segment, offset, size):
    method async_response (line 1211) | def async_response(self, wait=True):
    method preload (line 1222) | def preload(self, ids):
    method get_manifest (line 1225) | def get_manifest(self):
    method put_manifest (line 1231) | def put_manifest(self, data):
  class LoggedIO (line 1235) | class LoggedIO:
    class SegmentFull (line 1236) | class SegmentFull(Exception):
    method __init__ (line 1252) | def __init__(self, path, limit, segments_per_dir, capacity=90):
    method close (line 1262) | def close(self):
    method _close_fd (line 1267) | def _close_fd(self, ts_fd):
    method get_segment_dirs (line 1272) | def get_segment_dirs(self, data_dir, start_index=MIN_SEGMENT_DIR_INDEX...
    method get_segment_files (line 1283) | def get_segment_files(self, segment_dir, start_index=MIN_SEGMENT_INDEX...
    method segment_iterator (line 1294) | def segment_iterator(self, start_segment=None, end_segment=None, rever...
    method get_latest_segment (line 1318) | def get_latest_segment(self):
    method get_segments_transaction_id (line 1323) | def get_segments_transaction_id(self):
    method cleanup (line 1330) | def cleanup(self, transaction_id):
    method is_committed_segment (line 1343) | def is_committed_segment(self, segment):
    method segment_filename (line 1374) | def segment_filename(self, segment):
    method get_write_fd (line 1377) | def get_write_fd(self, no_new=False, want_new=False, raise_full=False):
    method get_fd (line 1399) | def get_fd(self, segment):
    method close_segment (line 1434) | def close_segment(self):
    method delete_segment (line 1442) | def delete_segment(self, segment):
    method clear_empty_dirs (line 1450) | def clear_empty_dirs(self):
    method segment_exists (line 1465) | def segment_exists(self, segment):
    method segment_size (line 1471) | def segment_size(self, segment):
    method get_segment_magic (line 1474) | def get_segment_magic(self, segment):
    method iter_objects (line 1479) | def iter_objects(self, segment, read_data=True):
    method recover_segment (line 1512) | def recover_segment(self, segment, filename):
    method entry_hash (line 1563) | def entry_hash(self, *data):
    method read (line 1569) | def read(self, segment, offset, id, *, read_data=True, expected_size=N...
    method _read (line 1592) | def _read(self, fd, header, segment, offset, acceptable_tags, read_dat...
    method write_put (line 1711) | def write_put(self, id, data, raise_full=False):
    method write_delete (line 1727) | def write_delete(self, id, raise_full=False):
    method write_commit (line 1735) | def write_commit(self, intermediate=False):

FILE: src/borg/logger.py
  class BorgQueueHandler (line 69) | class BorgQueueHandler(logging.handlers.QueueHandler):
    method prepare (line 72) | def prepare(self, record: logging.LogRecord) -> dict:
  class StderrHandler (line 87) | class StderrHandler(logging.StreamHandler):
    method __init__ (line 94) | def __init__(self, stream=None):
    method stream (line 98) | def stream(self):
  class TextProgressFormatter (line 102) | class TextProgressFormatter(logging.Formatter):
    method format (line 103) | def format(self, record: logging.LogRecord) -> str:
  class JSONProgressFormatter (line 110) | class JSONProgressFormatter(logging.Formatter):
    method format (line 111) | def format(self, record: logging.LogRecord) -> str:
  function _log_warning (line 126) | def _log_warning(message, category, filename, lineno, file=None, line=No...
  function remove_handlers (line 135) | def remove_handlers(logger):
  function flush_logging (line 142) | def flush_logging():
  function setup_logging (line 152) | def setup_logging(
  function find_parent_module (line 238) | def find_parent_module():
  class LazyLogger (line 257) | class LazyLogger:
    method __init__ (line 258) | def __init__(self, name=None):
    method __logger (line 263) | def __logger(self):
    method getChild (line 272) | def getChild(self, suffix):
    method setLevel (line 275) | def setLevel(self, level):
    method log (line 278) | def log(self, level, msg, *args, **kwargs):
    method exception (line 283) | def exception(self, msg, *args, exc_info=True, **kwargs):
    method debug (line 288) | def debug(self, msg, *args, **kwargs):
    method info (line 293) | def info(self, msg, *args, **kwargs):
    method warning (line 298) | def warning(self, msg, *args, **kwargs):
    method error (line 303) | def error(self, msg, *args, **kwargs):
    method critical (line 308) | def critical(self, msg, *args, **kwargs):
  function create_logger (line 314) | def create_logger(name: str = None) -> LazyLogger:
  class JsonFormatter (line 334) | class JsonFormatter(logging.Formatter):
    method format (line 351) | def format(self, record):

FILE: src/borg/manifest.py
  class MandatoryFeatureUnsupported (line 24) | class MandatoryFeatureUnsupported(Error):
  class NoManifestError (line 30) | class NoManifestError(Error):
  function filter_archives_by_date (line 43) | def filter_archives_by_date(archives, older=None, newer=None, oldest=Non...
  class Archives (line 72) | class Archives:
    method __init__ (line 81) | def __init__(self, repository, manifest):
    method prepare (line 91) | def prepare(self, manifest, m):
    method finish (line 97) | def finish(self, manifest):
    method ids (line 104) | def ids(self, *, deleted=False):
    method _get_archive_meta (line 118) | def _get_archive_meta(self, id: bytes) -> dict:
    method _infos (line 159) | def _infos(self, *, deleted=False):
    method _info_tuples (line 164) | def _info_tuples(self, *, deleted=False):
    method _matching_info_tuples (line 175) | def _matching_info_tuples(self, match_patterns, match_end, *, deleted=...
    method count (line 202) | def count(self):
    method names (line 206) | def names(self):
    method exists (line 211) | def exists(self, name):
    method exists_id (line 219) | def exists_id(self, id, *, deleted=False):
    method exists_name_and_id (line 227) | def exists_name_and_id(self, name, id):
    method exists_name_and_ts (line 240) | def exists_name_and_ts(self, name, ts):
    method _lookup_name (line 253) | def _lookup_name(self, name, raw=False):
    method get (line 273) | def get(self, name, raw=False):
    method get_by_id (line 290) | def get_by_id(self, id, raw=False, *, deleted=False):
    method create (line 321) | def create(self, name, id, ts, *, overwrite=False):
    method delete_by_id (line 335) | def delete_by_id(self, id):
    method undelete_by_id (line 341) | def undelete_by_id(self, id):
    method nuke_by_id (line 347) | def nuke_by_id(self, id):
    method list (line 353) | def list(
    method list_considering (line 404) | def list_considering(self, args):
    method get_one (line 425) | def get_one(self, match, *, match_end=r"\Z", deleted=False):
    method _set_raw_dict (line 433) | def _set_raw_dict(self, d):
    method _get_raw_dict (line 440) | def _get_raw_dict(self):
  class Manifest (line 445) | class Manifest:
    class Operation (line 447) | class Operation(enum.Enum):
    method __init__ (line 476) | def __init__(self, key, repository, item_keys=None, ro_cls=RepoObj):
    method id_str (line 486) | def id_str(self):
    method last_timestamp (line 490) | def last_timestamp(self):
    method load (line 494) | def load(cls, repository, operations, key=None, *, other=False, ro_cls...
    method check_repository_compatibility (line 518) | def check_repository_compatibility(self, operations):
    method get_all_mandatory_features (line 532) | def get_all_mandatory_features(self):
    method write (line 543) | def write(self):

FILE: src/borg/patterns.py
  function parse_patternfile_line (line 14) | def parse_patternfile_line(line, roots, ie_commands, fallback):
  function load_pattern_file (line 27) | def load_pattern_file(fileobj, roots, ie_commands, fallback=None):
  function load_exclude_file (line 34) | def load_exclude_file(fileobj, patterns):
  class ArgparsePatternAction (line 39) | class ArgparsePatternAction(Action):
    method __init__ (line 40) | def __init__(self, nargs=1, **kw):
    method __call__ (line 43) | def __call__(self, parser, args, values, option_string=None):
  class ArgparsePatternFileAction (line 47) | class ArgparsePatternFileAction(Action):
    method __init__ (line 48) | def __init__(self, nargs=1, **kw):
    method __call__ (line 51) | def __call__(self, parser, args, values, option_string=None):
    method parse (line 62) | def parse(self, fobj, args):
  class ArgparseExcludeFileAction (line 66) | class ArgparseExcludeFileAction(ArgparsePatternFileAction):
    method parse (line 67) | def parse(self, fobj, args):
  class PatternMatcher (line 71) | class PatternMatcher:
    method __init__ (line 78) | def __init__(self, fallback=None):
    method empty (line 101) | def empty(self):
    method _add (line 104) | def _add(self, pattern, cmd):
    method add (line 112) | def add(self, patterns, cmd):
    method add_includepaths (line 120) | def add_includepaths(self, include_paths):
    method get_unmatched_include_patterns (line 127) | def get_unmatched_include_patterns(self):
    method add_inclexcl (line 133) | def add_inclexcl(self, patterns):
    method match (line 138) | def match(self, path):
  function normalize_path (line 166) | def normalize_path(path):
  class PatternBase (line 173) | class PatternBase:
    method __init__ (line 178) | def __init__(self, pattern, recurse_dir=False):
    method match (line 185) | def match(self, path, normalize=True):
    method __repr__ (line 198) | def __repr__(self):
    method __str__ (line 201) | def __str__(self):
    method _prepare (line 204) | def _prepare(self, pattern):
    method _match (line 208) | def _match(self, path):
  class PathFullPattern (line 212) | class PathFullPattern(PatternBase):
    method _prepare (line 217) | def _prepare(self, pattern):
    method _match (line 220) | def _match(self, path):
  class PathPrefixPattern (line 229) | class PathPrefixPattern(PatternBase):
    method _prepare (line 238) | def _prepare(self, pattern):
    method _match (line 241) | def _match(self, path):
  class FnmatchPattern (line 245) | class FnmatchPattern(PatternBase):
    method _prepare (line 252) | def _prepare(self, pattern):
    method _match (line 264) | def _match(self, path):
  class ShellPattern (line 268) | class ShellPattern(PatternBase):
    method _prepare (line 275) | def _prepare(self, pattern):
    method _match (line 284) | def _match(self, path):
  class RegexPattern (line 288) | class RegexPattern(PatternBase):
    method _prepare (line 293) | def _prepare(self, pattern):
    method _match (line 297) | def _match(self, path):
  class IECommand (line 308) | class IECommand(Enum):
  function command_recurses_dir (line 318) | def command_recurses_dir(cmd):
  function get_pattern_class (line 323) | def get_pattern_class(prefix):
  function parse_pattern (line 330) | def parse_pattern(pattern, fallback=FnmatchPattern, recurse_dir=True):
  function parse_exclude_pattern (line 340) | def parse_exclude_pattern(pattern_str, fallback=FnmatchPattern):
  function parse_inclexcl_command (line 346) | def parse_inclexcl_command(cmd_line_str, fallback=ShellPattern):
  function get_regex_from_pattern (line 387) | def get_regex_from_pattern(pattern: str) -> str:

FILE: src/borg/platform/__init__.py
  function get_birthtime_ns (line 81) | def get_birthtime_ns(st, path, fd=None):
  function uid2user (line 95) | def uid2user(uid, default=None):
  function gid2group (line 99) | def gid2group(gid, default=None):
  function user2uid (line 103) | def user2uid(user, default=None):
  function group2gid (line 107) | def group2gid(group, default=None):

FILE: src/borg/platform/base.py
  function listxattr (line 35) | def listxattr(path, *, follow_symlinks=False):
  function getxattr (line 46) | def getxattr(path, name, *, follow_symlinks=False):
  function setxattr (line 60) | def setxattr(path, name, value, *, follow_symlinks=False):
  function acl_get (line 72) | def acl_get(path, item, st, numeric_ids=False, fd=None):
  function acl_set (line 80) | def acl_set(path, item, numeric_ids=False, fd=None):
  function set_flags (line 91) | def set_flags(path, bsd_flags, fd=None):
  function set_flags (line 96) | def set_flags(path, bsd_flags, fd=None):
  function get_flags (line 100) | def get_flags(path, st, fd=None):
  function sync_dir (line 105) | def sync_dir(path):
  function safe_fadvise (line 122) | def safe_fadvise(fd, offset, len, advice):
  class SyncFile (line 139) | class SyncFile:
    method __init__ (line 158) | def __init__(self, path, *, fd=None, binary=False):
    method __enter__ (line 175) | def __enter__(self):
    method __exit__ (line 178) | def __exit__(self, exc_type, exc_val, exc_tb):
    method write (line 181) | def write(self, data):
    method read (line 184) | def read(self, *args, **kwargs):
    method seek (line 187) | def seek(self, offset, whence=io.SEEK_SET):
    method tell (line 190) | def tell(self):
    method sync (line 193) | def sync(self):
    method close (line 206) | def close(self):
  class SaveFile (line 222) | class SaveFile:
    method __init__ (line 239) | def __init__(self, path, binary=False):
    method __enter__ (line 249) | def __enter__(self):
    method __exit__ (line 257) | def __exit__(self, exc_type, exc_val, exc_tb):
  function swidth (line 275) | def swidth(s):
  function getfqdn (line 297) | def getfqdn(name=""):
  function get_process_id (line 333) | def get_process_id():

FILE: src/borg/platform/posix_ug.py
  function _uid2user (line 7) | def _uid2user(uid, default=None):
  function _user2uid (line 15) | def _user2uid(user, default=None):
  function _gid2group (line 25) | def _gid2group(gid, default=None):
  function _group2gid (line 33) | def _group2gid(group, default=None):

FILE: src/borg/platform/windows_ug.py
  function _uid2user (line 5) | def _uid2user(uid, default=None):
  function _user2uid (line 12) | def _user2uid(user, default=None):
  function _gid2group (line 21) | def _gid2group(gid, default=None):
  function _group2gid (line 28) | def _group2gid(group, default=None):

FILE: src/borg/platform/xattr.py
  function split_string0 (line 10) | def split_string0(buf):
  function split_lstring (line 17) | def split_lstring(buf):
  class BufferTooSmallError (line 28) | class BufferTooSmallError(Exception):
  function _check (line 32) | def _check(rv, path=None, detect_buffer_too_small=False):
  function _listxattr_inner (line 58) | def _listxattr_inner(func, path):
  function _getxattr_inner (line 71) | def _getxattr_inner(func, path, name):
  function _setxattr_inner (line 85) | def _setxattr_inner(func, path, name, value):

FILE: src/borg/remote.py
  class ConnectionClosed (line 55) | class ConnectionClosed(Error):
  class ConnectionClosedWithHint (line 61) | class ConnectionClosedWithHint(ConnectionClosed):
  class PathNotAllowed (line 67) | class PathNotAllowed(Error):
  class InvalidRPCMethod (line 73) | class InvalidRPCMethod(Error):
  class UnexpectedRPCDataFormatFromClient (line 79) | class UnexpectedRPCDataFormatFromClient(Error):
  class UnexpectedRPCDataFormatFromServer (line 85) | class UnexpectedRPCDataFormatFromServer(Error):
    method __init__ (line 90) | def __init__(self, data):
  class ConnectionBrokenWithHint (line 100) | class ConnectionBrokenWithHint(Error):
  class RepositoryServer (line 122) | class RepositoryServer:  # pragma: no cover
    method __init__ (line 169) | def __init__(self, restrict_to_paths, restrict_to_repositories, use_so...
    method filter_args (line 188) | def filter_args(self, f, kwargs):
    method send_queued_log (line 193) | def send_queued_log(self):
    method serve (line 204) | def serve(self):
    method negotiate (line 345) | def negotiate(self, client_data):
    method _resolve_path (line 354) | def _resolve_path(self, path):
    method open (line 360) | def open(self, path, create=False, lock_wait=None, lock=True, exclusiv...
    method close (line 391) | def close(self):
    method inject_exception (line 398) | def inject_exception(self, kind):
  class SleepingBandwidthLimiter (line 421) | class SleepingBandwidthLimiter:
    method __init__ (line 422) | def __init__(self, limit):
    method write (line 430) | def write(self, fd, to_send):
  function api (line 454) | def api(*, since, **kwargs_decorator):
  class RemoteRepository (line 516) | class RemoteRepository:
    class RPCError (line 519) | class RPCError(Exception):
      method __init__ (line 520) | def __init__(self, unpacked):
      method get_message (line 524) | def get_message(self):
      method traceback (line 528) | def traceback(self):
      method exception_class (line 532) | def exception_class(self):
      method exception_full (line 536) | def exception_full(self):
      method sysinfo (line 540) | def sysinfo(self):
    class RPCServerOutdated (line 543) | class RPCServerOutdated(Error):
      method method (line 549) | def method(self):
      method required_version (line 553) | def required_version(self):
    method __init__ (line 556) | def __init__(self, location, create=False, exclusive=False, lock_wait=...
    method __del__ (line 650) | def __del__(self):
    method __repr__ (line 657) | def __repr__(self):
    method __enter__ (line 660) | def __enter__(self):
    method __exit__ (line 663) | def __exit__(self, exc_type, exc_val, exc_tb):
    method id_str (line 678) | def id_str(self):
    method borg_cmd (line 681) | def borg_cmd(self, args, testing):
    method ssh_cmd (line 724) | def ssh_cmd(self, location):
    method call (line 736) | def call(self, cmd, args, **kw):
    method call_many (line 740) | def call_many(self, cmd, calls, wait=True, is_preloaded=False, async_w...
    method open (line 950) | def open(self, path, create=False, lock_wait=None, lock=True, exclusiv...
    method info (line 954) | def info(self):
    method check (line 958) | def check(self, repair=False, max_duration=0):
    method commit (line 966) | def commit(self, compact=True, threshold=0.1):
    method rollback (line 970) | def rollback(self):
    method destroy (line 974) | def destroy(self):
    method __len__ (line 978) | def __len__(self):
    method list (line 982) | def list(self, limit=None, marker=None):
    method get (line 985) | def get(self, id, read_data=True, raise_missing=True):
    method get_many (line 989) | def get_many(self, ids, read_data=True, is_preloaded=False, raise_miss...
    method put (line 997) | def put(self, id, data, wait=True):
    method delete (line 1001) | def delete(self, id, wait=True):
    method save_key (line 1005) | def save_key(self, keydata):
    method load_key (line 1009) | def load_key(self):
    method break_lock (line 1013) | def break_lock(self):
    method close (line 1016) | def close(self):
    method async_response (line 1033) | def async_response(self, wait=True):
    method preload (line 1037) | def preload(self, ids):
    method get_manifest (line 1041) | def get_manifest(self):
    method put_manifest (line 1045) | def put_manifest(self, data):
    method store_list (line 1049) | def store_list(self, name, *, deleted=False):
    method store_load (line 1053) | def store_load(self, name):
    method store_store (line 1057) | def store_store(self, name, value):
    method store_delete (line 1061) | def store_delete(self, name, *, deleted=False):
    method store_move (line 1065) | def store_move(self, name, new_name=None, *, delete=False, undelete=Fa...
  class RepositoryNoCache (line 1069) | class RepositoryNoCache:
    method __init__ (line 1079) | def __init__(self, repository, transform=None):
    method close (line 1083) | def close(self):
    method __enter__ (line 1086) | def __enter__(self):
    method __exit__ (line 1089) | def __exit__(self, exc_type, exc_val, exc_tb):
    method get (line 1092) | def get(self, key, read_data=True, raise_missing=True):
    method get_many (line 1095) | def get_many(self, keys, read_data=True, raise_missing=True, cache=True):
    method log_instrumentation (line 1099) | def log_instrumentation(self):
  class RepositoryCache (line 1103) | class RepositoryCache(RepositoryNoCache):
    method __init__ (line 1115) | def __init__(self, repository, pack=None, unpack=None, transform=None):
    method query_size_limit (line 1131) | def query_size_limit(self):
    method prefixed_key (line 1135) | def prefixed_key(self, key, complete):
    method key_filename (line 1141) | def key_filename(self, key):
    method backoff (line 1144) | def backoff(self):
    method add_entry (line 1154) | def add_entry(self, key, data, cache, complete):
    method log_instrumentation (line 1181) | def log_instrumentation(self):
    method close (line 1196) | def close(self):
    method get_many (line 1201) | def get_many(self, keys, read_data=True, raise_missing=True, cache=True):
  function cache_if_remote (line 1234) | def cache_if_remote(repository, *, decrypted_cache=False, pack=None, unp...

FILE: src/borg/repoobj.py
  class RepoObj (line 15) | class RepoObj:
    method extract_crypted_data (line 22) | def extract_crypted_data(cls, data: bytes) -> bytes:
    method __init__ (line 28) | def __init__(self, key):
    method id_hash (line 34) | def id_hash(self, data: bytes) -> bytes:
    method format (line 37) | def format(
    method parse_meta (line 76) | def parse_meta(self, id: bytes, cdata: bytes, ro_type: str) -> dict:
    method parse (line 93) | def parse(
  class RepoObj1 (line 142) | class RepoObj1:  # legacy
    method extract_crypted_data (line 144) | def extract_crypted_data(cls, data: bytes) -> bytes:
    method __init__ (line 148) | def __init__(self, key):
    method id_hash (line 152) | def id_hash(self, data: bytes) -> bytes:
    method format (line 155) | def format(
    method parse_meta (line 180) | def parse_meta(self, id: bytes, cdata: bytes) -> dict:
    method parse (line 183) | def parse(

FILE: src/borg/repository.py
  function repo_lister (line 26) | def repo_lister(repository, *, limit=None):
  class Repository (line 37) | class Repository:
    class AlreadyExists (line 40) | class AlreadyExists(Error):
    class CheckNeeded (line 45) | class CheckNeeded(ErrorWithTraceback):
    class DoesNotExist (line 50) | class DoesNotExist(Error):
    class InsufficientFreeSpaceError (line 55) | class InsufficientFreeSpaceError(Error):
    class InvalidRepository (line 60) | class InvalidRepository(Error):
    class InvalidRepositoryConfig (line 65) | class InvalidRepositoryConfig(Error):
    class ObjectNotFound (line 70) | class ObjectNotFound(ErrorWithTraceback):
      method __init__ (line 75) | def __init__(self, id, repo):
    class ParentPathDoesNotExist (line 80) | class ParentPathDoesNotExist(Error):
    class PathAlreadyExists (line 85) | class PathAlreadyExists(Error):
    class PathPermissionDenied (line 92) | class PathPermissionDenied(Error):
    method __init__ (line 97) | def __init__(
    method __repr__ (line 181) | def __repr__(self):
    method __enter__ (line 184) | def __enter__(self):
    method __exit__ (line 196) | def __exit__(self, exc_type, exc_val, exc_tb):
    method id_str (line 200) | def id_str(self):
    method create (line 203) | def create(self):
    method _set_id (line 226) | def _set_id(self, id):
    method _lock_refresh (line 233) | def _lock_refresh(self):
    method save_key (line 237) | def save_key(self, keydata):
    method load_key (line 241) | def load_key(self):
    method destroy (line 246) | def destroy(self):
    method open (line 251) | def open(self, *, exclusive, lock_wait=None, lock=True):
    method close (line 277) | def close(self):
    method info (line 286) | def info(self):
    method check (line 293) | def check(self, repair=False, max_duration=0):
    method list (line 425) | def list(self, limit=None, marker=None):
    method get (line 452) | def get(self, id, read_data=True, raise_missing=True):
    method get_many (line 484) | def get_many(self, ids, read_data=True, is_preloaded=False, raise_miss...
    method put (line 488) | def put(self, id, data, wait=True):
    method delete (line 502) | def delete(self, id, wait=True):
    method async_response (line 515) | def async_response(self, wait=True):
    method preload (line 526) | def preload(self, ids):
    method break_lock (line 529) | def break_lock(self):
    method migrate_lock (line 532) | def migrate_lock(self, old_id, new_id):
    method get_manifest (line 537) | def get_manifest(self):
    method put_manifest (line 544) | def put_manifest(self, data):
    method store_list (line 548) | def store_list(self, name, *, deleted=False):
    method store_load (line 555) | def store_load(self, name):
    method store_store (line 559) | def store_store(self, name, value):
    method store_delete (line 563) | def store_delete(self, name, *, deleted=False):
    method store_move (line 567) | def store_move(self, name, new_name=None, *, delete=False, undelete=Fa...

FILE: src/borg/selftest.py
  class SelfTestResult (line 32) | class SelfTestResult(TestResult):
    method __init__ (line 33) | def __init__(self):
    method addSuccess (line 37) | def addSuccess(self, test):
    method test_name (line 41) | def test_name(self, test):
    method log_results (line 44) | def log_results(self, logger):
    method successful_test_count (line 50) | def successful_test_count(self):
  function selftest (line 54) | def selftest(logger):

FILE: src/borg/storelocking.py
  class LockError (line 17) | class LockError(Error):
  class LockErrorT (line 23) | class LockErrorT(ErrorWithTraceback):
  class LockFailed (line 29) | class LockFailed(LockErrorT):
  class LockTimeout (line 35) | class LockTimeout(LockError):
  class NotLocked (line 41) | class NotLocked(LockErrorT):
  class NotMyLock (line 47) | class NotMyLock(LockErrorT):
  class Lock (line 53) | class Lock:
    method __init__ (line 70) | def __init__(self, store, exclusive=False, sleep=None, timeout=1.0, st...
    method __enter__ (line 86) | def __enter__(self):
    method __exit__ (line 89) | def __exit__(self, exc_type, exc_val, exc_tb):
    method __repr__ (line 95) | def __repr__(self):
    method _create_lock (line 98) | def _create_lock(self, *, exclusive=None, update_last_refresh=False):
    method _delete_lock (line 112) | def _delete_lock(self, key, *, ignore_not_found=False, update_last_ref...
    method _is_our_lock (line 123) | def _is_our_lock(self, lock):
    method _is_stale_lock (line 126) | def _is_stale_lock(self, lock):
    method _get_locks (line 136) | def _get_locks(self):
    method _find_locks (line 155) | def _find_locks(self, *, only_exclusive=False, only_mine=False):
    method acquire (line 166) | def acquire(self):
    method release (line 212) | def release(self, *, ignore_not_found=False):
    method got_exclusive_lock (line 226) | def got_exclusive_lock(self):
    method break_lock (line 230) | def break_lock(self):
    method migrate_lock (line 238) | def migrate_lock(self, old_id, new_id):
    method refresh (line 249) | def refresh(self):

FILE: src/borg/testsuite/__init__.py
  function same_ts_ns (line 51) | def same_ts_ns(ts_ns1, ts_ns2):
  function granularity_sleep (line 58) | def granularity_sleep(*, ctime_quirk=False):
  function unopened_tempfile (line 117) | def unopened_tempfile():
  function changedir (line 123) | def changedir(dir):
  function is_root (line 130) | def is_root():
  function are_symlinks_supported (line 139) | def are_symlinks_supported():
  function are_hardlinks_supported (line 151) | def are_hardlinks_supported():
  function are_fifos_supported (line 170) | def are_fifos_supported():
  function is_utime_fully_supported (line 185) | def is_utime_fully_supported():
  function is_birthtime_fully_supported (line 205) | def is_birthtime_fully_supported():
  function filter_xattrs (line 228) | def filter_xattrs(x):
  class BaseTestCase (line 238) | class BaseTestCase(unittest.TestCase):
  class FakeInputs (line 246) | class FakeInputs:
    method __init__ (line 249) | def __init__(self, inputs):
    method __call__ (line 252) | def __call__(self, prompt=None):

FILE: src/borg/testsuite/archive_test.py
  function stats (line 21) | def stats():
  function test_stats_basic (line 28) | def test_stats_basic(stats):
  function test_stats_progress_tty (line 36) | def test_stats_progress_tty(stats, monkeypatch, columns=80):
  function test_stats_progress_file (line 62) | def test_stats_progress_file(stats, monkeypatch):
  function test_stats_format (line 82) | def test_stats_format(stats):
  function test_stats_progress_json (line 106) | def test_stats_progress_json(stats):
  function test_timestamp_parsing (line 137) | def test_timestamp_parsing(monkeypatch, isoformat, expected):
  class MockCache (line 146) | class MockCache:
    class MockRepo (line 147) | class MockRepo:
      method async_response (line 148) | def async_response(self, wait=True):
    method __init__ (line 151) | def __init__(self):
    method add_chunk (line 155) | def add_chunk(self, id, meta, data, stats=None, wait=True, ro_type=None):
  function test_cache_chunk_buffer (line 161) | def test_cache_chunk_buffer():
  function test_partial_cache_chunk_buffer (line 177) | def test_partial_cache_chunk_buffer():
  function make_chunks (line 199) | def make_chunks(items):
  function _validator (line 203) | def _validator(value):
  function process (line 207) | def process(input):
  function test_extra_garbage_no_sync (line 220) | def test_extra_garbage_no_sync():
  function split (line 226) | def split(left, length):
  function test_correct_stream (line 234) | def test_correct_stream():
  function test_missing_chunk (line 241) | def test_missing_chunk():
  function test_corrupt_chunk (line 248) | def test_corrupt_chunk():
  function item_keys_serialized (line 256) | def item_keys_serialized():
  function test_invalid_msgpacked_item (line 271) | def test_invalid_msgpacked_item(packed, item_keys_serialized):
  function test_valid_msgpacked_items (line 291) | def test_valid_msgpacked_items(packed, item_keys_serialized):
  function test_key_length_msgpacked_items (line 295) | def test_key_length_msgpacked_items():
  function test_backup_io (line 302) | def test_backup_io():
  function test_backup_io_iter (line 308) | def test_backup_io_iter():
  function test_get_item_uid_gid (line 326) | def test_get_item_uid_gid():
  function test_reject_non_sanitized_item (line 426) | def test_reject_non_sanitized_item():

FILE: src/borg/testsuite/archiver/__init__.py
  function exec_cmd (line 47) | def exec_cmd(*args, archiver=None, fork=False, exe=None, input=b"", bina...
  function cmd_fixture (line 107) | def cmd_fixture(request):
  function generate_archiver_tests (line 121) | def generate_archiver_tests(metafunc, kinds: str):
  function checkts (line 138) | def checkts(ts):
  function cmd (line 143) | def cmd(archiver, *args, **kw):
  function create_src_archive (line 163) | def create_src_archive(archiver, name, ts=None):
  function open_archive (line 170) | def open_archive(repo_path, name):
  function open_repository (line 179) | def open_repository(archiver):
  function create_regular_file (line 186) | def create_regular_file(input_path, name, size=0, contents=None):
  function create_test_files (line 197) | def create_test_files(input_path, create_hardlinks=True):
  function _extract_repository_id (line 259) | def _extract_repository_id(repo_path):
  function _set_repository_id (line 264) | def _set_repository_id(repo_path, id):
  function _extract_hardlinks_setup (line 270) | def _extract_hardlinks_setup(archiver):
  function _create_test_caches (line 287) | def _create_test_caches(archiver):
  function _assert_test_caches (line 300) | def _assert_test_caches(archiver):
  function _create_test_tagged (line 307) | def _create_test_tagged(archiver):
  function _assert_test_tagged (line 316) | def _assert_test_tagged(archiver):
  function _create_test_keep_tagged (line 322) | def _create_test_keep_tagged(archiver):
  function _assert_test_keep_tagged (line 338) | def _assert_test_keep_tagged(archiver):
  function assert_creates_file (line 349) | def assert_creates_file(path):
  function assert_dirs_equal (line 355) | def assert_dirs_equal(dir1, dir2, **kwargs):
  function assert_line_exists (line 360) | def assert_line_exists(lines, expected_regexpr):
  function assert_line_not_exists (line 364) | def assert_line_not_exists(lines, expected_regexpr):
  function _assert_dirs_equal_cmp (line 370) | def _assert_dirs_equal_cmp(diff, ignore_flags=False, ignore_xattrs=False...
  function read_only (line 420) | def read_only(path):
  function wait_for_mountstate (line 459) | def wait_for_mountstate(mountpoint, *, mounted, timeout=5):
  function fuse_mount (line 471) | def fuse_mount(archiver, mountpoint=None, *options, fork=True, os_fork=F...

FILE: src/borg/testsuite/archiver/analyze_cmd_test.py
  function test_analyze (line 9) | def test_analyze(archivers, request):

FILE: src/borg/testsuite/archiver/argparsing_test.py
  function test_bad_filters (line 7) | def test_bad_filters(archiver):
  function test_highlander (line 13) | def test_highlander(archiver):
  function test_get_args (line 29) | def test_get_args():
  class TestCommonOptions (line 78) | class TestCommonOptions:
    method define_common_options (line 80) | def define_common_options(add_common_option):
    method basic_parser (line 95) | def basic_parser(self):
    method subcommands (line 101) | def subcommands(self, basic_parser):
    method parser (line 105) | def parser(self, basic_parser):
    method common_parser (line 110) | def common_parser(self, parser):
    method parse_vars_from_line (line 116) | def parse_vars_from_line(self, parser, subcommands, common_parser):
    method test_simple (line 129) | def test_simple(self, parse_vars_from_line):
    method test_flag_position_independence (line 160) | def test_flag_position_independence(self, parse_vars_from_line, positi...

FILE: src/borg/testsuite/archiver/benchmark_cmd_test.py
  function test_benchmark_crud (line 7) | def test_benchmark_crud(archiver, monkeypatch):
  function test_benchmark_crud_json_lines (line 17) | def test_benchmark_crud_json_lines(archiver, monkeypatch):
  function test_benchmark_cpu (line 48) | def test_benchmark_cpu(archiver, monkeypatch):
  function test_benchmark_cpu_json (line 61) | def test_benchmark_cpu_json(archiver, monkeypatch):

FILE: src/borg/testsuite/archiver/check_cmd_test.py
  function check_cmd_setup (line 20) | def check_cmd_setup(archiver):
  function test_check_usage (line 27) | def test_check_usage(archivers, request):
  function test_date_matching (line 55) | def test_date_matching(archivers, request):
  function test_missing_file_chunk (line 142) | def test_missing_file_chunk(archivers, request):
  function test_missing_archive_item_chunk (line 184) | def test_missing_archive_item_chunk(archivers, request):
  function test_missing_archive_metadata (line 195) | def test_missing_archive_metadata(archivers, request):
  function test_missing_manifest (line 206) | def test_missing_manifest(archivers, request):
  function test_corrupted_manifest (line 222) | def test_corrupted_manifest(archivers, request):
  function test_spoofed_manifest (line 237) | def test_spoofed_manifest(archivers, request):
  function test_manifest_rebuild_corrupted_chunk (line 270) | def test_manifest_rebuild_corrupted_chunk(archivers, request):
  function test_check_undelete_archives (line 287) | def test_check_undelete_archives(archivers, request):
  function test_spoofed_archive (line 307) | def test_spoofed_archive(archivers, request):
  function test_extra_chunks (line 347) | def test_extra_chunks(archivers, request):
  function test_verify_data (line 360) | def test_verify_data(archivers, request, init_args):
  function test_corrupted_file_chunk (line 412) | def test_corrupted_file_chunk(archivers, request, init_args):
  function test_empty_repository (line 445) | def test_empty_repository(archivers, request):

FILE: src/borg/testsuite/archiver/checks_test.py
  function get_security_directory (line 22) | def get_security_directory(repo_path):
  function add_unknown_feature (line 27) | def add_unknown_feature(repo_path, operation):
  function cmd_raises_unknown_feature (line 34) | def cmd_raises_unknown_feature(archiver, args):
  function test_repository_swap_detection (line 43) | def test_repository_swap_detection(archivers, request):
  function test_repository_swap_detection2 (line 61) | def test_repository_swap_detection2(archivers, request):
  function test_repository_swap_detection_no_cache (line 80) | def test_repository_swap_detection_no_cache(archivers, request):
  function test_repository_swap_detection2_no_cache (line 99) | def test_repository_swap_detection2_no_cache(archivers, request):
  function test_repository_swap_detection_repokey_blank_passphrase (line 122) | def test_repository_swap_detection_repokey_blank_passphrase(archivers, r...
  function test_repository_move (line 149) | def test_repository_move(archivers, request, monkeypatch):
  function test_unknown_unencrypted (line 178) | def test_unknown_unencrypted(archivers, request, monkeypatch):
  function test_unknown_feature_on_create (line 199) | def test_unknown_feature_on_create(archivers, request):
  function test_unknown_feature_on_change_passphrase (line 206) | def test_unknown_feature_on_change_passphrase(archivers, request):
  function test_unknown_feature_on_read (line 213) | def test_unknown_feature_on_read(archivers, request):
  function test_unknown_feature_on_rename (line 224) | def test_unknown_feature_on_rename(archivers, request):
  function test_unknown_feature_on_delete (line 232) | def test_unknown_feature_on_delete(archivers, request):
  function test_unknown_feature_on_mount (line 245) | def test_unknown_feature_on_mount(archivers, request):
  function test_unknown_mandatory_feature_in_cache (line 256) | def test_unknown_mandatory_feature_in_cache(archivers, request):
  function test_remote_repo_restrict_to_path (line 280) | def test_remote_repo_restrict_to_path(remote_archiver):
  function test_remote_repo_restrict_to_repository (line 308) | def test_remote_repo_restrict_to_repository(remote_archiver):
  function test_remote_repo_strip_components_doesnt_leak (line 319) | def test_remote_repo_strip_components_doesnt_leak(remote_archiver):

FILE: src/borg/testsuite/archiver/compact_cmd_test.py
  function test_compact_empty_repository (line 14) | def test_compact_empty_repository(archivers, request, stats):
  function test_compact_after_deleting_all_archives (line 30) | def test_compact_after_deleting_all_archives(archivers, request, stats):
  function test_compact_after_deleting_some_archives (line 49) | def test_compact_after_deleting_some_archives(archivers, request, stats):
  function test_compact_index_corruption (line 68) | def test_compact_index_corruption(archivers, request):
  function test_compact_files_cache_cleanup (line 88) | def test_compact_files_cache_cleanup(archivers, request):

FILE: src/borg/testsuite/archiver/completion_cmd_test.py
  function cmd_available (line 14) | def cmd_available(cmd):
  function _run_bash_completion_fn (line 27) | def _run_bash_completion_fn(completion_script, setup_code):
  function test_bash_completion_nontrivial (line 44) | def test_bash_completion_nontrivial(archivers, request):
  function test_zsh_completion_nontrivial (line 52) | def test_zsh_completion_nontrivial(archivers, request):
  function _check_shell_syntax (line 63) | def _check_shell_syntax(script_content, shell, suffix):
  function test_bash_completion_syntax (line 76) | def test_bash_completion_syntax(archivers, request):
  function test_zsh_completion_syntax (line 85) | def test_zsh_completion_syntax(archivers, request):
  function test_bash_sortby_dedup (line 97) | def test_bash_sortby_dedup(archivers, request):
  function test_bash_filescachemode_exclusivity (line 117) | def test_bash_filescachemode_exclusivity(archivers, request):
  function test_bash_archive_name_completion (line 149) | def test_bash_archive_name_completion(archivers, request):
  function test_bash_archive_aid_completion (line 168) | def test_bash_archive_aid_completion(archivers, request):

FILE: src/borg/testsuite/archiver/corruption_test.py
  function corrupt_archiver (line 12) | def corrupt_archiver(archiver):
  function test_old_version_interfered (line 18) | def test_old_version_interfered(archiver):

FILE: src/borg/testsuite/archiver/create_cmd_test.py
  function test_basic_functionality (line 51) | def test_basic_functionality(archivers, request):
  function test_archived_paths (line 125) | def test_archived_paths(archivers, request):
  function test_create_msys2_path_translation_warning (line 155) | def test_create_msys2_path_translation_warning(archivers, request, monke...
  function test_create_duplicate_root (line 194) | def test_create_duplicate_root(archivers, request):
  function test_create_unreadable_parent (line 214) | def test_create_unreadable_parent(archiver):
  function test_unix_socket (line 229) | def test_unix_socket(archivers, request, monkeypatch):
  function test_nobirthtime (line 251) | def test_nobirthtime(archivers, request):
  function test_create_stdin (line 269) | def test_create_stdin(archivers, request):
  function test_create_erroneous_file (line 281) | def test_create_erroneous_file(archivers, request):
  function test_create_no_permission_file (line 311) | def test_create_no_permission_file(archivers, request):
  function test_sanitized_stdin_name (line 348) | def test_sanitized_stdin_name(archivers, request):
  function test_dotdot_stdin_name (line 356) | def test_dotdot_stdin_name(archivers, request):
  function test_dot_stdin_name (line 363) | def test_dot_stdin_name(archivers, request):
  function test_create_content_from_command (line 370) | def test_create_content_from_command(archivers, request):
  function test_create_content_from_command_with_failed_command (line 383) | def test_create_content_from_command_with_failed_command(archivers, requ...
  function test_create_content_from_command_missing_command (line 399) | def test_create_content_from_command_missing_command(archivers, request):
  function test_create_paths_from_stdin (line 406) | def test_create_paths_from_stdin(archivers, request):
  function test_create_paths_from_command (line 420) | def test_create_paths_from_command(archivers, request):
  function test_create_paths_from_command_with_failed_command (line 438) | def test_create_paths_from_command_with_failed_command(archivers, request):
  function test_create_paths_from_command_missing_command (line 454) | def test_create_paths_from_command_missing_command(archivers, request):
  function test_create_paths_from_shell_command (line 462) | def test_create_paths_from_shell_command(archivers, request):
  function test_create_without_root (line 476) | def test_create_without_root(archivers, request):
  function test_create_pattern_root (line 483) | def test_create_pattern_root(archivers, request):
  function test_create_pattern (line 494) | def test_create_pattern(archivers, request):
  function test_create_pattern_file (line 509) | def test_create_pattern_file(archivers, request):
  function test_create_pattern_exclude_folder_but_recurse (line 533) | def test_create_pattern_exclude_folder_but_recurse(archivers, request):
  function test_create_pattern_exclude_folder_no_recurse (line 549) | def test_create_pattern_exclude_folder_no_recurse(archivers, request):
  function test_create_pattern_intermediate_folders_first (line 565) | def test_create_pattern_intermediate_folders_first(archivers, request):
  function test_create_archivename_with_placeholder (line 586) | def test_create_archivename_with_placeholder(archivers, request):
  function test_exclude_caches (line 598) | def test_exclude_caches(archivers, request):
  function test_exclude_tagged (line 605) | def test_exclude_tagged(archivers, request):
  function test_exclude_keep_tagged (line 612) | def test_exclude_keep_tagged(archivers, request):
  function test_path_sanitation (line 630) | def test_path_sanitation(archivers, request):
  function test_exclude_sanitation (line 641) | def test_exclude_sanitation(archivers, request):
  function test_repeated_files (line 662) | def test_repeated_files(archivers, request):
  function test_umask (line 671) | def test_umask(archivers, request):
  function test_create_dry_run (line 680) | def test_create_dry_run(archivers, request):
  function test_progress_on (line 690) | def test_progress_on(archivers, request):
  function test_progress_off (line 698) | def test_progress_off(archivers, request):
  function test_file_status (line 706) | def test_file_status(archivers, request):
  function test_create_tags (line 725) | def test_create_tags(archivers, request):
  function test_create_invalid_tags (line 735) | def test_create_invalid_tags(archivers, request):
  function test_file_status_cs_cache_mode (line 746) | def test_file_status_cs_cache_mode(archivers, request):
  function test_files_changed_modes (line 763) | def test_files_changed_modes(archivers, request):
  function test_file_status_ms_cache_mode (line 777) | def test_file_status_ms_cache_mode(archivers, request):
  function test_file_status_rc_cache_mode (line 793) | def test_file_status_rc_cache_mode(archivers, request):
  function test_file_status_excluded (line 806) | def test_file_status_excluded(archivers, request):
  function test_file_status_counters (line 829) | def test_file_status_counters(archivers, request):
  function test_create_json (line 871) | def test_create_json(archivers, request):
  function test_explicit_hostname_and_username (line 890) | def test_explicit_hostname_and_username(archivers, request):
  function test_create_topical (line 901) | def test_create_topical(archivers, request):
  function test_create_read_special_symlink (line 928) | def test_create_read_special_symlink(archivers, request):
  function test_create_read_special_broken_symlink (line 971) | def test_create_read_special_broken_symlink(archivers, request):
  function test_create_dotslash_hack (line 980) | def test_create_dotslash_hack(archivers, request):
  function test_log_json (line 1006) | def test_log_json(archivers, request):
  function test_common_options (line 1026) | def test_common_options(archivers, request):
  function test_create_big_zeros_files (line 1034) | def test_create_big_zeros_files(archivers, request):
  function test_create_big_random_files (line 1064) | def test_create_big_random_files(archivers, request):
  function test_create_with_compression_algorithms (line 1096) | def test_create_with_compression_algorithms(archivers, request):
  function test_exclude_nodump_dir_with_file (line 1158) | def test_exclude_nodump_dir_with_file(archivers, request):

FILE: src/borg/testsuite/archiver/debug_cmds_test.py
  function test_debug_profile (line 13) | def test_debug_profile(archivers, request):
  function test_debug_dump_archive_items (line 28) | def test_debug_dump_archive_items(archivers, request):
  function test_debug_dump_repo_objs (line 40) | def test_debug_dump_repo_objs(archivers, request):
  function test_debug_put_get_delete_obj (line 52) | def test_debug_put_get_delete_obj(archivers, request):
  function test_debug_id_hash_format_put_get_parse_obj (line 81) | def test_debug_id_hash_format_put_get_parse_obj(archivers, request):
  function test_debug_format_obj_respects_type (line 126) | def test_debug_format_obj_respects_type(archivers, request):
  function test_debug_dump_manifest (line 148) | def test_debug_dump_manifest(archivers, request):
  function test_debug_dump_archive (line 166) | def test_debug_dump_archive(archivers, request):
  function test_debug_info (line 183) | def test_debug_info(archivers, request):

FILE: src/borg/testsuite/archiver/delete_cmd_test.py
  function test_delete_options (line 7) | def test_delete_options(archivers, request):
  function test_delete_multiple (line 26) | def test_delete_multiple(archivers, request):
  function test_delete_ignore_protected (line 37) | def test_delete_ignore_protected(archivers, request):

FILE: src/borg/testsuite/archiver/diff_cmd_test.py
  function test_basic_functionality (line 23) | def test_basic_functionality(archivers, request):
  function test_time_diffs (line 266) | def test_time_diffs(archivers, request):
  function test_sort_by_option (line 292) | def test_sort_by_option(archivers, request):
  function test_sort_by_invalid_field_is_rejected (line 320) | def test_sort_by_invalid_field_is_rejected(archivers, request):
  function test_sort_by_size_added_then_path (line 333) | def test_sort_by_size_added_then_path(archivers, request):
  function test_sort_by_all_keys_with_directions (line 382) | def test_sort_by_all_keys_with_directions(archivers, request, sort_key):
  function test_hard_link_deletion_and_replacement (line 434) | def test_hard_link_deletion_and_replacement(archivers, request):

FILE: src/borg/testsuite/archiver/disk_full_test.py
  function make_files (line 31) | def make_files(dir, count, size, rnd=True):
  function test_disk_full (line 47) | def test_disk_full(test_pass, cmd_fixture, monkeypatch):

FILE: src/borg/testsuite/archiver/extract_cmd_test.py
  function test_symlink_extract (line 39) | def test_symlink_extract(archivers, request):
  function test_hardlinked_symlinks_extract (line 53) | def test_hardlinked_symlinks_extract(archivers, request):
  function test_directory_timestamps1 (line 77) | def test_directory_timestamps1(archivers, request):
  function test_directory_timestamps2 (line 94) | def test_directory_timestamps2(archivers, request):
  function test_directory_timestamps3 (line 112) | def test_directory_timestamps3(archivers, request):
  function test_atime (line 130) | def test_atime(archivers, request):
  function test_birthtime (line 167) | def test_birthtime(archivers, request):
  function test_sparse_file (line 185) | def test_sparse_file(archivers, request):
  function test_unusual_filenames (line 241) | def test_unusual_filenames(archivers, request):
  function test_strip_components (line 256) | def test_strip_components(archivers, request):
  function test_extract_hardlinks1 (line 273) | def test_extract_hardlinks1(archivers, request):
  function test_extract_hardlinks2 (line 286) | def test_extract_hardlinks2(archivers, request):
  function test_extract_hardlinks_twice (line 308) | def test_extract_hardlinks_twice(archivers, request):
  function test_extract_include_exclude (line 332) | def test_extract_include_exclude(archivers, request):
  function test_extract_include_exclude_regex (line 354) | def test_extract_include_exclude_regex(archivers, request):
  function test_extract_include_exclude_regex_from_file (line 395) | def test_extract_include_exclude_regex_from_file(archivers, request):
  function test_extract_with_pattern (line 435) | def test_extract_with_pattern(archivers, request):
  function test_extract_list_output (line 469) | def test_extract_list_output(archivers, request):
  function test_extract_progress (line 495) | def test_extract_progress(archivers, request):
  function test_extract_pattern_opt (line 506) | def test_extract_pattern_opt(archivers, request):
  function test_extract_capabilities (line 519) | def test_extract_capabilities(archivers, request):
  function test_extract_xattrs_errors (line 544) | def test_extract_xattrs_errors(archivers, request):
  function test_extract_xattrs_resourcefork (line 585) | def test_extract_xattrs_resourcefork(archivers, request):
  function test_extract_restores_append_flag (line 611) | def test_extract_restores_append_flag(archivers, request):
  function test_overwrite (line 637) | def test_overwrite(archivers, request):
  function test_do_not_fail_when_percent_is_in_xattr_name (line 667) | def test_do_not_fail_when_percent_is_in_xattr_name(archivers, request):
  function test_do_not_fail_when_percent_is_in_file_name (line 687) | def test_do_not_fail_when_percent_is_in_file_name(archivers, request):
  function test_extract_continue (line 706) | def test_extract_continue(archivers, request):
  function test_dry_run_extraction_flags (line 774) | def test_dry_run_extraction_flags(archivers, request):
  function test_extract_file_with_missing_chunk (line 793) | def test_extract_file_with_missing_chunk(archivers, request):
  function test_extract_existing_directory (line 812) | def test_extract_existing_directory(archivers, request):
  function test_extract_y2261 (line 830) | def test_extract_y2261(archivers, request):

FILE: src/borg/testsuite/archiver/help_cmd_test.py
  function get_all_parsers (line 8) | def get_all_parsers():
  function test_usage (line 33) | def test_usage(archiver):
  function test_help (line 38) | def test_help(archiver):
  function test_help_formatting (line 47) | def test_help_formatting(command, parser):
  function test_help_formatting_helptexts (line 53) | def test_help_formatting_helptexts(topic):

FILE: src/borg/testsuite/archiver/info_cmd_test.py
  function test_info (line 11) | def test_info(archivers, request):
  function test_info_json (line 22) | def test_info_json(archivers, request):
  function test_info_json_of_empty_archive (line 42) | def test_info_json_of_empty_archive(archivers, request):
  function test_info_working_directory (line 52) | def test_info_working_directory(archivers, request):

FILE: src/borg/testsuite/archiver/key_cmds_test.py
  function test_change_passphrase (line 19) | def test_change_passphrase(archivers, request):
  function test_change_location_to_keyfile (line 29) | def test_change_location_to_keyfile(archivers, request):
  function test_change_location_to_b2keyfile (line 39) | def test_change_location_to_b2keyfile(archivers, request):
  function test_change_location_to_repokey (line 49) | def test_change_location_to_repokey(archivers, request):
  function test_change_location_to_b2repokey (line 59) | def test_change_location_to_b2repokey(archivers, request):
  function test_key_export_keyfile (line 69) | def test_key_export_keyfile(archivers, request):
  function test_key_import_keyfile_with_borg_key_file (line 98) | def test_key_import_keyfile_with_borg_key_file(archivers, request, monke...
  function test_key_export_repokey (line 120) | def test_key_export_repokey(archivers, request):
  function test_key_export_qr (line 153) | def test_key_export_qr(archivers, request):
  function test_key_export_directory (line 168) | def test_key_export_directory(archivers, request):
  function test_key_export_qr_directory (line 181) | def test_key_export_qr_directory(archivers, request):
  function test_key_import_errors (line 194) | def test_key_import_errors(archivers, request):
  function test_key_export_paperkey (line 226) | def test_key_export_paperkey(archivers, request):
  function test_key_import_paperkey (line 255) | def test_key_import_paperkey(archivers, request):
  function test_init_defaults_to_argon2 (line 301) | def test_init_defaults_to_argon2(archivers, request):
  function test_change_passphrase_does_not_change_algorithm_argon2 (line 310) | def test_change_passphrase_does_not_change_algorithm_argon2(archivers, r...
  function test_change_location_does_not_change_algorithm_argon2 (line 321) | def test_change_location_does_not_change_algorithm_argon2(archivers, req...

FILE: src/borg/testsuite/archiver/list_cmd_test.py
  function test_list_format (line 11) | def test_list_format(archivers, request, backup_files):
  function test_list_hash (line 24) | def test_list_hash(archivers, request):
  function test_list_chunk_counts (line 35) | def test_list_chunk_counts(archivers, request):
  function test_list_size (line 51) | def test_list_size(archivers, request):
  function test_list_json (line 61) | def test_list_json(archivers, request):
  function test_list_json_lines_includes_archive_keys_in_format (line 82) | def test_list_json_lines_includes_archive_keys_in_format(archivers, requ...
  function test_list_depth (line 105) | def test_list_depth(archivers, request):
  function test_list_inode_hardlinks (line 167) | def test_list_inode_hardlinks(archivers, request):
  function test_fingerprint (line 206) | def test_fingerprint(archivers, request):

FILE: src/borg/testsuite/archiver/lock_cmds_test.py
  function test_break_lock (line 16) | def test_break_lock(archivers, request):
  function test_with_lock (line 23) | def test_with_lock(tmp_path):
  function test_with_lock_non_existent_command (line 57) | def test_with_lock_non_existent_command(archivers, request):

FILE: src/borg/testsuite/archiver/mount_cmds_test.py
  function test_fuse_mount_hardlinks (line 30) | def test_fuse_mount_hardlinks(archivers, request):
  function test_fuse (line 68) | def test_fuse(archivers, request):
  function test_fuse_versions_view (line 176) | def test_fuse_versions_view(archivers, request):
  function test_fuse_duplicate_name (line 210) | def test_fuse_duplicate_name(archivers, request):
  function test_fuse_allow_damaged_files (line 228) | def test_fuse_allow_damaged_files(archivers, request):
  function test_fuse_mount_options (line 258) | def test_fuse_mount_options(archivers, request):
  function test_migrate_lock_alive (line 281) | def test_migrate_lock_alive(archivers, request):

FILE: src/borg/testsuite/archiver/patterns_test.py
  function test_basic (line 7) | def test_basic():
  function test_empty (line 16) | def test_empty():
  function test_strip_components (line 22) | def test_strip_components():

FILE: src/borg/testsuite/archiver/prune_cmd_test.py
  function _create_archive_ts (line 14) | def _create_archive_ts(archiver, backup_files, name, y, m, d, H=0, M=0, ...
  function test_prune_repository (line 25) | def test_prune_repository(archivers, request, backup_files):
  function test_prune_repository_example (line 45) | def test_prune_repository_example(archivers, request, backup_files):
  function test_prune_quarterly (line 107) | def test_prune_quarterly(archivers, request, backup_files):
  function test_prune_retain_and_expire_oldest (line 179) | def test_prune_retain_and_expire_oldest(archivers, request, backup_files):
  function test_prune_repository_prefix (line 204) | def test_prune_repository_prefix(archivers, request, backup_files):
  function test_prune_repository_glob (line 227) | def test_prune_repository_glob(archivers, request, backup_files):
  function test_prune_ignore_protected (line 250) | def test_prune_ignore_protected(archivers, request):
  class MockArchive (line 266) | class MockArchive:
    method __init__ (line 267) | def __init__(self, ts, id):
    method __repr__ (line 271) | def __repr__(self):
  function test_prune_within (line 286) | def test_prune_within():
  function test_prune_split (line 331) | def test_prune_split(rule, num_to_keep, expected_ids):
  function test_prune_split_keep_oldest (line 363) | def test_prune_split_keep_oldest():
  function test_prune_split_no_archives (line 395) | def test_prune_split_no_archives():
  function test_prune_list_with_metadata_format (line 405) | def test_prune_list_with_metadata_format(archivers, request, backup_files):

FILE: src/borg/testsuite/archiver/recreate_cmd_test.py
  function test_recreate_exclude_caches (line 28) | def test_recreate_exclude_caches(archivers, request):
  function test_recreate_exclude_tagged (line 36) | def test_recreate_exclude_tagged(archivers, request):
  function test_recreate_exclude_keep_tagged (line 44) | def test_recreate_exclude_keep_tagged(archivers, request):
  function test_recreate_hardlinked_tags (line 64) | def test_recreate_hardlinked_tags(archivers, request):  # test for issue...
  function test_recreate_target (line 82) | def test_recreate_target(archivers, request):
  function test_recreate_basic (line 103) | def test_recreate_basic(archivers, request):
  function test_recreate_subtree_hardlinks (line 118) | def test_recreate_subtree_hardlinks(archivers, request):
  function test_recreate_rechunkify (line 136) | def test_recreate_rechunkify(archivers, request):
  function test_recreate_fixed_rechunkify (line 158) | def test_recreate_fixed_rechunkify(archivers, request):
  function test_recreate_no_rechunkify (line 173) | def test_recreate_no_rechunkify(archivers, request):
  function test_recreate_keep_original_timestamp (line 190) | def test_recreate_keep_original_timestamp(archivers, request):
  function test_recreate_with_given_timestamp (line 205) | def test_recreate_with_given_timestamp(archivers, request):
  function test_recreate_dry_run (line 223) | def test_recreate_dry_run(archivers, request):
  function test_recreate_skips_nothing_to_do (line 235) | def test_recreate_skips_nothing_to_do(archivers, request):
  function test_recreate_list_output (line 247) | def test_recreate_list_output(archivers, request):
  function test_comment (line 278) | def test_comment(archivers, request):
  function test_recreate_ignore_protected (line 300) | def test_recreate_ignore_protected(archivers, request):

FILE: src/borg/testsuite/archiver/remote_repo_test.py
  function have_rclone (line 16) | def have_rclone():
  function test_rclone_repo_basics (line 35) | def test_rclone_repo_basics(archiver, tmp_path):
  function test_sftp_repo_basics (line 61) | def test_sftp_repo_basics(archiver):
  function test_s3_repo_basics (line 85) | def test_s3_repo_basics(archiver):

FILE: src/borg/testsuite/archiver/rename_cmd_test.py
  function test_rename (line 9) | def test_rename(archivers, request):

FILE: src/borg/testsuite/archiver/repo_compress_cmd_test.py
  function test_repo_compress (line 12) | def test_repo_compress(archiver):
  function test_repo_compress_stats (line 74) | def test_repo_compress_stats(archiver):

FILE: src/borg/testsuite/archiver/repo_create_cmd_test.py
  function test_repo_create_interrupt (line 14) | def test_repo_create_interrupt(archivers, request):
  function test_repo_create_requires_encryption_option (line 32) | def test_repo_create_requires_encryption_option(archivers, request):
  function test_repo_create_refuse_to_overwrite_keyfile (line 37) | def test_repo_create_refuse_to_overwrite_keyfile(archivers, request, mon...
  function test_repo_create_keyfile_same_path_creates_new_keys (line 60) | def test_repo_create_keyfile_same_path_creates_new_keys(archivers, reque...

FILE: src/borg/testsuite/archiver/repo_delete_cmd_test.py
  function test_delete_repo (line 12) | def test_delete_repo(archivers, request):

FILE: src/borg/testsuite/archiver/repo_info_cmd_test.py
  function test_info (line 9) | def test_info(archivers, request):
  function test_info_json (line 18) | def test_info_json(archivers, request):

FILE: src/borg/testsuite/archiver/repo_list_cmd_test.py
  function test_repo_list_glob (line 11) | def test_repo_list_glob(archivers, request, backup_files):
  function test_archives_format (line 23) | def test_archives_format(archivers, request, backup_files):
  function test_size_nfiles (line 43) | def test_size_nfiles(archivers, request):
  function test_date_matching (line 58) | def test_date_matching(archivers, request, backup_files):
  function test_repo_list_json (line 139) | def test_repo_list_json(archivers, request):
  function test_repo_list_deleted (line 154) | def test_repo_list_deleted(archivers, request, backup_files):

FILE: src/borg/testsuite/archiver/repo_space_cmd_test.py
  function test_repo_space_basics (line 8) | def test_repo_space_basics(archivers, request):
  function test_repo_space_modify_reservation (line 35) | def test_repo_space_modify_reservation(archivers, request):
  function test_repo_space_edge_cases (line 60) | def test_repo_space_edge_cases(archivers, request):

FILE: src/borg/testsuite/archiver/restricted_permissions_test.py
  function test_repository_permissions_all (line 13) | def test_repository_permissions_all(archivers, request, monkeypatch):
  function test_repository_permissions_no_delete (line 37) | def test_repository_permissions_no_delete(archivers, request, monkeypatch):
  function test_repository_permissions_read_only (line 95) | def test_repository_permissions_read_only(archivers, request, monkeypatch):
  function test_repository_permissions_write_only (line 141) | def test_repository_permissions_write_only(archivers, request, monkeypat...

FILE: src/borg/testsuite/archiver/return_codes_test.py
  function test_return_codes (line 11) | def test_return_codes(archivers, request):
  function test_exit_codes (line 27) | def test_exit_codes(archivers, request, monkeypatch):

FILE: src/borg/testsuite/archiver/serve_cmd_test.py
  function have_a_short_runtime_dir (line 14) | def have_a_short_runtime_dir(mp):
  function serve_socket (line 22) | def serve_socket(monkeypatch):
  function test_with_socket (line 34) | def test_with_socket(serve_socket, tmpdir, monkeypatch):
  function test_socket_permissions (line 53) | def test_socket_permissions(serve_socket):

FILE: src/borg/testsuite/archiver/tag_cmd_test.py
  function test_tag_set (line 7) | def test_tag_set(archivers, request):
  function test_tag_add_remove (line 21) | def test_tag_add_remove(archivers, request):
  function test_tag_set_noclobber_special (line 35) | def test_tag_set_noclobber_special(archivers, request):
  function test_tag_only_known_special (line 50) | def test_tag_only_known_special(archivers, request):

FILE: src/borg/testsuite/archiver/tar_cmds_test.py
  function have_gnutar (line 19) | def have_gnutar():
  function test_export_tar (line 32) | def test_export_tar(archivers, request):
  function test_export_tar_gz (line 47) | def test_export_tar_gz(archivers, request):
  function test_export_tar_strip_components (line 63) | def test_export_tar_strip_components(archivers, request):
  function test_export_tar_strip_components_links (line 80) | def test_export_tar_strip_components_links(archivers, request):
  function test_extract_hardlinks_tar (line 94) | def test_extract_hardlinks_tar(archivers, request):
  function test_import_tar (line 106) | def test_import_tar(archivers, request, tar_format="PAX"):
  function test_import_unusual_tar (line 119) | def test_import_unusual_tar(archivers, request):
  function test_import_tar_with_dotdot (line 135) | def test_import_tar_with_dotdot(archivers, request):
  function test_import_tar_gz (line 149) | def test_import_tar_gz(archivers, request, tar_format="GNU"):
  function test_import_concatenated_tar_with_ignore_zeros (line 163) | def test_import_concatenated_tar_with_ignore_zeros(archivers, request):
  function test_import_concatenated_tar_without_ignore_zeros (line 192) | def test_import_concatenated_tar_without_ignore_zeros(archivers, request):
  function test_import_tar_with_dotslash_paths (line 217) | def test_import_tar_with_dotslash_paths(archivers, request):
  function test_roundtrip_pax_borg (line 244) | def test_roundtrip_pax_borg(archivers, request):
  function test_roundtrip_pax_xattrs (line 257) | def test_roundtrip_pax_xattrs(archivers, request):
  function test_acl_roundtrip (line 278) | def test_acl_roundtrip(archivers, request):

FILE: src/borg/testsuite/archiver/transfer_cmd_test.py
  function test_transfer_upgrade (line 23) | def test_transfer_upgrade(archivers, request, monkeypatch):
  function setup_repos (line 288) | def setup_repos(archiver, mp):
  function test_transfer (line 312) | def test_transfer(archivers, request, monkeypatch):
  function test_transfer_archive_metadata (line 338) | def test_transfer_archive_metadata(archivers, request, monkeypatch):
  function test_transfer_recompress (line 381) | def test_transfer_recompress(archivers, request, monkeypatch, recompress...
  function test_transfer_rechunk (line 416) | def test_transfer_rechunk(archivers, request, monkeypatch):
  function test_transfer_rechunk_dry_run (line 479) | def test_transfer_rechunk_dry_run(archivers, request, monkeypatch):
  function test_issue_9022 (line 506) | def test_issue_9022(archivers, request, monkeypatch):

FILE: src/borg/testsuite/archiver/undelete_cmd_test.py
  function test_undelete_single (line 7) | def test_undelete_single(archivers, request):
  function test_undelete_multiple_dryrun (line 24) | def test_undelete_multiple_dryrun(archivers, request):
  function test_undelete_multiple_run (line 47) | def test_undelete_multiple_run(archivers, request):

FILE: src/borg/testsuite/benchmark_test.py
  function repo_url (line 19) | def repo_url(request, tmpdir, monkeypatch):
  function repo (line 31) | def repo(request, cmd_fixture, repo_url):
  function testdata (line 37) | def testdata(request, tmpdir_factory):
  function repo_archive (line 62) | def repo_archive(request, cmd_fixture, repo, testdata):
  function test_create_none (line 68) | def test_create_none(benchmark, cmd_fixture, repo, testdata):
  function test_create_lz4 (line 75) | def test_create_lz4(benchmark, cmd_fixture, repo, testdata):
  function test_extract (line 82) | def test_extract(benchmark, cmd_fixture, repo_archive, tmpdir):
  function test_delete (line 89) | def test_delete(benchmark, cmd_fixture, repo_archive):
  function test_list (line 95) | def test_list(benchmark, cmd_fixture, repo_archive):
  function test_info (line 101) | def test_info(benchmark, cmd_fixture, repo_archive):
  function test_check (line 107) | def test_check(benchmark, cmd_fixture, repo_archive):
  function test_help (line 113) | def test_help(benchmark, cmd_fixture):
  function test_propdict_attributes (line 119) | def test_propdict_attributes(benchmark, type, key, value):

FILE: src/borg/testsuite/cache_test.py
  class TestAdHocWithFilesCache (line 14) | class TestAdHocWithFilesCache:
    method repository (line 16) | def repository(self, tmpdir):
    method key (line 23) | def key(self, repository, monkeypatch):
    method manifest (line 29) | def manifest(self, repository, key):
    method cache (line 34) | def cache(self, repository, key, manifest):
    method test_does_not_contain_manifest (line 37) | def test_does_not_contain_manifest(self, cache):
    method test_seen_chunk_add_chunk_size (line 40) | def test_seen_chunk_add_chunk_size(self, cache):
    method test_reuse_after_add_chunk (line 43) | def test_reuse_after_add_chunk(self, cache):
    method test_existing_reuse_after_add_chunk (line 47) | def test_existing_reuse_after_add_chunk(self, cache):
    method test_files_cache (line 51) | def test_files_cache(self, cache):
  function test_delete_chunkindex_cache_missing (line 58) | def test_delete_chunkindex_cache_missing(tmp_path):
  function test_read_chunkindex_from_repo_cache_missing (line 78) | def test_read_chunkindex_from_repo_cache_missing(tmp_path):

FILE: src/borg/testsuite/checksums_test.py
  function test_xxh64 (line 6) | def test_xxh64():

FILE: src/borg/testsuite/chunkers/__init__.py
  function cf (line 9) | def cf(chunks):
  function cf_expand (line 25) | def cf_expand(chunks):
  function make_sparsefile (line 30) | def make_sparsefile(fname, sparsemap, header_size=0):
  function make_content (line 46) | def make_content(sparsemap, header_size=0):
  function fs_supports_sparse (line 61) | def fs_supports_sparse():

FILE: src/borg/testsuite/chunkers/buzhash64_self_test.py
  class ChunkerBuzHash64TestCase (line 19) | class ChunkerBuzHash64TestCase(BaseTestCase):
    method test_chunkify64 (line 20) | def test_chunkify64(self):
    method test_buzhash64 (line 63) | def test_buzhash64(self):
    method test_small_reads64 (line 73) | def test_small_reads64(self):

FILE: src/borg/testsuite/chunkers/buzhash64_test.py
  function H (line 20) | def H(data):
  function test_chunkpoints64_unchanged (line 24) | def test_chunkpoints64_unchanged():
  function test_buzhash64_chunksize_distribution (line 55) | def test_buzhash64_chunksize_distribution():
  function test_buzhash64_table (line 82) | def test_buzhash64_table():
  function test_fuzz_bh64 (line 108) | def test_fuzz_bh64(worker):

FILE: src/borg/testsuite/chunkers/buzhash_self_test.py
  class ChunkerTestCase (line 13) | class ChunkerTestCase(BaseTestCase):
    method test_chunkify (line 14) | def test_chunkify(self):
    method test_buzhash (line 55) | def test_buzhash(self):
    method test_small_reads (line 64) | def test_small_reads(self):

FILE: src/borg/testsuite/chunkers/buzhash_test.py
  function H (line 14) | def H(data):
  function test_chunkpoints_unchanged (line 18) | def test_chunkpoints_unchanged():
  function test_buzhash_chunksize_distribution (line 48) | def test_buzhash_chunksize_distribution():
  function test_fuzz_buzhash (line 77) | def test_fuzz_buzhash(worker):

FILE: src/borg/testsuite/chunkers/failing_test.py
  function test_chunker_failing (line 9) | def test_chunker_failing():

FILE: src/borg/testsuite/chunkers/fixed_self_test.py
  class ChunkerFixedTestCase (line 12) | class ChunkerFixedTestCase(BaseTestCase):
    method test_chunkify_just_blocks (line 13) | def test_chunkify_just_blocks(self):
    method test_chunkify_header_and_blocks (line 19) | def test_chunkify_header_and_blocks(self):
    method test_chunkify_just_blocks_fmap_complete (line 27) | def test_chunkify_just_blocks_fmap_complete(self):
    method test_chunkify_header_and_blocks_fmap_complete (line 34) | def test_chunkify_header_and_blocks_fmap_complete(self):
    method test_chunkify_header_and_blocks_fmap_zeros (line 43) | def test_chunkify_header_and_blocks_fmap_zeros(self):
    method test_chunkify_header_and_blocks_fmap_partial (line 51) | def test_chunkify_header_and_blocks_fmap_partial(self):

FILE: src/borg/testsuite/chunkers/fixed_test.py
  function test_chunkify_sparse (line 35) | def test_chunkify_sparse(tmpdir, fname, sparse_map, header_size, sparse):
  function test_fuzz_fixed (line 48) | def test_fuzz_fixed(worker):

FILE: src/borg/testsuite/chunkers/interaction_test.py
  function test_reader_chunker_interaction (line 21) | def test_reader_chunker_interaction(chunker_params):

FILE: src/borg/testsuite/chunkers/reader_test.py
  function test_sparsemap (line 17) | def test_sparsemap(tmpdir, fname, sparse_map):
  function test_filereader_read_simple (line 46) | def test_filereader_read_simple(file_content, read_size, expected_data, ...
  function test_filereader_read_multiple (line 77) | def test_filereader_read_multiple(file_content, read_sizes, expected_res...
  function test_filereader_read_with_mock (line 111) | def test_filereader_read_with_mock(mock_chunks, read_size, expected_data...
  function test_filefmapreader_basic (line 171) | def test_filefmapreader_basic(file_content, read_size, expected_chunks):
  function test_filefmapreader_with_fmap (line 229) | def test_filefmapreader_with_fmap(file_content, fmap, read_size, expecte...
  function test_filefmapreader_allocation_types (line 250) | def test_filefmapreader_allocation_types(zeros_length, read_size, expect...
  function test_filefmapreader_with_real_sparse_file (line 267) | def test_filefmapreader_with_real_sparse_file(tmpdir):
  function test_filefmapreader_build_fmap (line 315) | def test_filefmapreader_build_fmap():

FILE: src/borg/testsuite/cockpit_test.py
  function test_cockpit_app_create_archive (line 18) | def test_cockpit_app_create_archive(tmp_path):

FILE: src/borg/testsuite/compress_test.py
  function test_get_compressor (line 19) | def test_get_compressor(c_type, expected_compressor):
  function test_compression_types (line 29) | def test_compression_types(c_type):
  function test_lz4_buffer_allocation (line 40) | def test_lz4_buffer_allocation(monkeypatch):
  function test_autodetect_invalid (line 53) | def test_autodetect_invalid(invalid_cdata):
  function test_zlib_legacy_compat (line 58) | def test_zlib_legacy_compat():
  function test_compressor (line 84) | def test_compressor(c_params):
  function test_auto (line 99) | def test_auto():
  function test_factor_obfuscation (line 129) | def test_factor_obfuscation(specs, c_type, result_range, obfuscation_fac...
  function test_additive_obfuscation (line 154) | def test_additive_obfuscation(specs, c_type, obfuscation_padding: int):
  function test_obfuscate_meta (line 170) | def test_obfuscate_meta():
  function test_default_compression_level (line 192) | def test_default_compression_level(c_type, c_name):
  function test_specified_compression_level (line 204) | def test_specified_compression_level(c_type, c_name, c_levels):
  function test_invalid_compression_level (line 212) | def test_invalid_compression_level(invalid_spec):
  function test_padme_obfuscation (line 235) | def test_padme_obfuscation(data_length, expected_padding):
  function test_robj_specific_obfuscation (line 254) | def test_robj_specific_obfuscation(data_length, expected_padding, robj_t...

FILE: src/borg/testsuite/crypto/crypto_test.py
  class CryptoTestCase (line 17) | class CryptoTestCase(BaseTestCase):
    method test_bytes_to_int (line 18) | def test_bytes_to_int(self):
    method test_bytes_to_long (line 21) | def test_bytes_to_long(self):
    method test_UNENCRYPTED (line 25) | def test_UNENCRYPTED(self):
    method test_AES256_CTR_HMAC_SHA256 (line 35) | def test_AES256_CTR_HMAC_SHA256(self):
    method test_AES256_CTR_HMAC_SHA256_aad (line 64) | def test_AES256_CTR_HMAC_SHA256_aad(self):
    method test_AE (line 92) | def test_AE(self):
    method test_AEAD (line 135) | def test_AEAD(self):
    method test_AEAD_with_more_AAD (line 178) | def test_AEAD_with_more_AAD(self):
  function test_decrypt_key_file_argon2_chacha20_poly1305 (line 198) | def test_decrypt_key_file_argon2_chacha20_poly1305():
  function test_decrypt_key_file_pbkdf2_sha256_aes256_ctr_hmac_sha256 (line 225) | def test_decrypt_key_file_pbkdf2_sha256_aes256_ctr_hmac_sha256():
  function test_repo_key_detect_does_not_raise_integrity_error (line 243) | def test_repo_key_detect_does_not_raise_integrity_error(getpass, monkeyp...
  class TestDeriveKey (line 282) | class TestDeriveKey(BaseTestCase):
    class CustomKey (line 284) | class CustomKey(KeyBase):
      method __init__ (line 285) | def __init__(self, crypt_key, id_key):
    method test_derive_key_with_plaintext_key (line 289) | def test_derive_key_with_plaintext_key(self):
    method test_derive_key_with_custom_key (line 299) | def test_derive_key_with_custom_key(self):
    method test_derive_key_from_different_keys (line 320) | def test_derive_key_from_different_keys(self):

FILE: src/borg/testsuite/crypto/csprng_test.py
  function test_deterministic_output (line 11) | def test_deterministic_output():
  function test_random_bytes (line 30) | def test_random_bytes():
  function test_random_int (line 45) | def test_random_int():
  function test_random_int_edge_cases (line 62) | def test_random_int_edge_cases():
  function test_shuffle (line 106) | def test_shuffle():
  function test_statistical_properties (line 137) | def test_statistical_properties():
  function test_large_shuffle (line 166) | def test_large_shuffle():

FILE: src/borg/testsuite/crypto/file_integrity_test.py
  class TestReadIntegrityFile (line 7) | class TestReadIntegrityFile:
    method test_no_integrity (line 8) | def test_no_integrity(self, tmpdir):
    method test_truncated_integrity (line 13) | def test_truncated_integrity(self, tmpdir):
    method test_unknown_algorithm (line 20) | def test_unknown_algorithm(self, tmpdir):
    method test_malformed (line 29) | def test_malformed(self, tmpdir, json):
  class TestDetachedIntegrityCheckedFile (line 37) | class TestDetachedIntegrityCheckedFile:
    method integrity_protected_file (line 39) | def integrity_protected_file(self, tmpdir):
    method test_simple (line 45) | def test_simple(self, tmpdir, integrity_protected_file):
    method test_corrupted_file (line 51) | def test_corrupted_file(self, integrity_protected_file):
    method test_corrupted_file_partial_read (line 58) | def test_corrupted_file_partial_read(self, integrity_protected_file):
    method test_renamed_file (line 67) | def test_renamed_file(self, tmpdir, integrity_protected_file, new_name):
    method test_moved_file (line 75) | def test_moved_file(self, tmpdir, integrity_protected_file):
    method test_no_integrity (line 83) | def test_no_integrity(self, tmpdir, integrity_protected_file):
  class TestDetachedIntegrityCheckedFileParts (line 89) | class TestDetachedIntegrityCheckedFileParts:
    method integrity_protected_file (line 91) | def integrity_protected_file(self, tmpdir):
    method test_simple (line 99) | def test_simple(self, integrity_protected_file):
    method test_wrong_part_name (line 106) | def test_wrong_part_name(self, integrity_protected_file):
    method test_part_independence (line 120) | def test_part_independence(self, integrity_protected_file, partial_read):
  class TestIntegrityCheckedFileWithSyncFile (line 136) | class TestIntegrityCheckedFileWithSyncFile:
    method test_write_and_verify_with_syncfile (line 137) | def test_write_and_verify_with_syncfile(self, tmp_path):

FILE: src/borg/testsuite/crypto/key_test.py
  class TestKey (line 23) | class TestKey:
    class MockArgs (line 24) | class MockArgs:
    method keys_dir (line 70) | def keys_dir(self, request, monkeypatch, tmpdir):
    method key (line 96) | def key(self, request, monkeypatch):
    class MockRepository (line 100) | class MockRepository:
      class _Location (line 101) | class _Location:
        method canonical_path (line 104) | def canonical_path(self):
      method save_key (line 112) | def save_key(self, data):
      method load_key (line 115) | def load_key(self):
    method test_plaintext (line 118) | def test_plaintext(self):
    method test_keyfile (line 125) | def test_keyfile(self, monkeypatch, keys_dir):
    method test_keyfile_kfenv (line 147) | def test_keyfile_kfenv(self, tmpdir, monkeypatch):
    method test_keyfile2 (line 163) | def test_keyfile2(self, monkeypatch, keys_dir):
    method test_keyfile2_kfenv (line 170) | def test_keyfile2_kfenv(self, tmpdir, monkeypatch):
    method test_keyfile_blake2 (line 179) | def test_keyfile_blake2(self, monkeypatch, keys_dir):
    method _corrupt_byte (line 186) | def _corrupt_byte(self, key, data, offset):
    method test_decrypt_integrity (line 194) | def test_decrypt_integrity(self, monkeypatch, keys_dir):
    method test_roundtrip (line 211) | def test_roundtrip(self, key):
    method test_assert_id (line 222) | def test_assert_id(self, key):
    method test_authenticated_encrypt (line 235) | def test_authenticated_encrypt(self, monkeypatch):
    method test_blake2_authenticated_encrypt (line 246) | def test_blake2_authenticated_encrypt(self, monkeypatch):
  class TestTAM (line 258) | class TestTAM:
    method key (line 260) | def key(self, monkeypatch):
    method test_unpack_future (line 264) | def test_unpack_future(self, key):
    method test_round_trip_manifest (line 273) | def test_round_trip_manifest(self, key):
    method test_round_trip_archive (line 280) | def test_round_trip_archive(self, key):
  function test_decrypt_key_file_unsupported_algorithm (line 288) | def test_decrypt_key_file_unsupported_algorithm():
  function test_decrypt_key_file_v2_is_unsupported (line 297) | def test_decrypt_key_file_v2_is_unsupported():
  function test_key_file_roundtrip (line 306) | def test_key_file_roundtrip(monkeypatch):

FILE: src/borg/testsuite/fslocking_test.py
  function free_pid (line
Condensed preview — 450 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,226K chars).
[
  {
    "path": ".editorconfig",
    "chars": 201,
    "preview": "# EditorConfig is awesome: https://editorconfig.org/\n\nroot = true\n\n[*]\nend_of_line = lf\ncharset = utf-8\nindent_style = s"
  },
  {
    "path": ".git-blame-ignore-revs",
    "chars": 71,
    "preview": "# Migrate code style to Black\n7957af562d5ce8266b177039783be4dc8bdd7898\n"
  },
  {
    "path": ".gitattributes",
    "chars": 102,
    "preview": "borg/_version.py export-subst\n\n*.py diff=python\ndocs/usage/*.rst.inc merge=ours\ndocs/man/* merge=ours\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 173,
    "preview": "# These are supported funding model platforms\n\ngithub: borgbackup\nliberapay: borgbackup\nopen_collective: borgbackup\ncust"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "chars": 1640,
    "preview": "<!--\nThank you for reporting an issue.\n\n*IMPORTANT* – Before creating a new issue, please look around:\n - BorgBackup doc"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 556,
    "preview": "<!--\nThank you for contributing to BorgBackup!\n\nPlease make sure your PR complies with our contribution guidelines:\nhttp"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 464,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n  "
  },
  {
    "path": ".github/workflows/backport.yml",
    "chars": 1175,
    "preview": "name: Backport pull request\n\non:\n  pull_request_target:\n    types: [closed]\n  issue_comment:\n    types: [created]\n\npermi"
  },
  {
    "path": ".github/workflows/black.yaml",
    "chars": 783,
    "preview": "# https://black.readthedocs.io/en/stable/integrations/github_actions.html#usage\n# See also what we use locally in requir"
  },
  {
    "path": ".github/workflows/canary.yml",
    "chars": 4861,
    "preview": "name: Canary (Unlocked Requirements)\n\non:\n  schedule:\n    - cron: '0 7 * * *'  # Run at 07:00 UTC\n  workflow_dispatch:  "
  },
  {
    "path": ".github/workflows/ci.yml",
    "chars": 27334,
    "preview": "# badge: https://github.com/borgbackup/borg/workflows/CI/badge.svg?branch=master\n\nname: CI\n\non:\n  push:\n    branches: [ "
  },
  {
    "path": ".github/workflows/codeql-analysis.yml",
    "chars": 2683,
    "preview": "# CodeQL semantic code analysis engine\n\nname: \"CodeQL\"\n\non:\n  push:\n    branches: [ master ]\n    paths:\n      - '**.py'\n"
  },
  {
    "path": ".gitignore",
    "chars": 577,
    "preview": "MANIFEST\ndocs/_build\nbuild\ndist\n.tox\nsrc/borg/compress.c\nsrc/borg/hashindex.c\nsrc/borg/crypto/low_level.c\nsrc/borg/item."
  },
  {
    "path": ".mailmap",
    "chars": 780,
    "preview": "Abdel-Rahman <abodyxplay1@gmail.com>\nBrian Johnson <brian@sherbang.com>\nCarlo Teubner <carlo.teubner@gmail.com>\nMark Edg"
  },
  {
    "path": ".pre-commit-config.yaml",
    "chars": 183,
    "preview": "repos:\n-   repo: https://github.com/psf/black\n    rev: 24.8.0\n    hooks:\n    -   id: black\n- repo: https://github.com/as"
  },
  {
    "path": ".readthedocs.yaml",
    "chars": 641,
    "preview": "# .readthedocs.yaml - Read the Docs configuration file.\n# See https://docs.readthedocs.io/en/stable/config-file/v2.html "
  },
  {
    "path": "AUTHORS",
    "chars": 1174,
    "preview": "Email addresses listed here are not intended for support.\nPlease see the `support section`_ instead.\n\n.. _support sectio"
  },
  {
    "path": "Brewfile",
    "chars": 254,
    "preview": "brew 'pkgconf'\nbrew 'lz4'\nbrew 'openssl@3'\n\n# osxfuse (aka macFUSE) is only required for \"borg mount\",\n# but won't work "
  },
  {
    "path": "LICENSE",
    "chars": 1550,
    "preview": "Copyright (C) 2015-2025 The Borg Collective (see AUTHORS file)\nCopyright (C) 2010-2014 Jonas Borgström <jonas@borgstrom."
  },
  {
    "path": "MANIFEST.in",
    "chars": 488,
    "preview": "# The files we need to include in the sdist are handled automatically by\n# setuptools_scm - it includes all git-committe"
  },
  {
    "path": "README.rst",
    "chars": 8030,
    "preview": "This is borg2!\n--------------\n\nPlease note that this is the README for borg2 / master branch.\n\nFor the stable version's "
  },
  {
    "path": "SECURITY.md",
    "chars": 500,
    "preview": "# Security Policy\n\n## Supported Versions\n\nThese Borg releases are currently supported with security updates.\n\n| Version "
  },
  {
    "path": "Vagrantfile",
    "chars": 19993,
    "preview": "# -*- mode: ruby -*-\n# vi: set ft=ruby :\n\n# Automated creation of testing environments/binaries on miscellaneous platfor"
  },
  {
    "path": "docs/3rd_party/README",
    "chars": 214,
    "preview": "Here we store third-party documentation, licenses, etc.\n\nPlease note that all files inside the \"borg\" package directory "
  },
  {
    "path": "docs/Makefile",
    "chars": 4583,
    "preview": "# Makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line.\nSPHINXOPTS    =\nSPHINXBUILD "
  },
  {
    "path": "docs/_static/Makefile",
    "chars": 198,
    "preview": "\nall: logo.pdf logo.png\n\nlogo.pdf: logo.svg\n\tinkscape logo.svg --export-pdf=logo.pdf\n\nlogo.png: logo.svg\n\tinkscape logo."
  },
  {
    "path": "docs/_static/logo_font.txt",
    "chars": 111,
    "preview": "Black Ops One\nJames Grieshaber\nSIL Open Font License, 1.1\n\nhttps://www.google.com/fonts/specimen/Black+Ops+One\n"
  },
  {
    "path": "docs/_templates/globaltoc.html",
    "chars": 633,
    "preview": "<div class=\"sidebar-block\">\n  <div class=\"sidebar-toc\">\n    {# Restrict the sidebar ToC depth to two levels while genera"
  },
  {
    "path": "docs/_templates/layout.html",
    "chars": 5872,
    "preview": "{%- extends \"basic/layout.html\" %}\n\n{# Do this so that Bootstrap is included before the main CSS file. #}\n{%- block html"
  },
  {
    "path": "docs/_templates/logo-text.html",
    "chars": 160,
    "preview": "<a href=\"{{ homepage() }}\" class=\"text-logo\">\n  <img src='{{ pathto('_static/logo.svg', 1) }}' width='100%'>\n\n  {{ theme"
  },
  {
    "path": "docs/_templates/versionselector.html",
    "chars": 1194,
    "preview": "<div class=\"version-selector\" id=\"borg-version-selector\" style=\"display:none;\">\n  <label for=\"version-select\">Select you"
  },
  {
    "path": "docs/authors.rst",
    "chars": 139,
    "preview": ".. include:: global.rst.inc\n\nAuthors\n=======\n\n.. include:: ../AUTHORS\n\nLicense\n=======\n\n.. _license:\n\n.. include:: ../LI"
  },
  {
    "path": "docs/binaries/00_README.txt",
    "chars": 4306,
    "preview": "Binary BorgBackup builds\n========================\n\nGeneral notes\n-------------\n\nThe binaries are supposed to work on the"
  },
  {
    "path": "docs/book.rst",
    "chars": 403,
    "preview": ":orphan:\n\n.. include:: global.rst.inc\n\nBorg documentation\n==================\n\n.. When you add an element here, do not fo"
  },
  {
    "path": "docs/borg_theme/css/borg.css",
    "chars": 5076,
    "preview": "@import url(\"theme.css\");\n\ndt code {\n    font-weight: normal;\n}\n\n#internals .toctree-wrapper > ul {\n    column-count: 3;"
  },
  {
    "path": "docs/changes.rst",
    "chars": 62883,
    "preview": ".. _important_notes:\n\nImportant notes 2.x\n===================\n\nThis section provides information about security and corr"
  },
  {
    "path": "docs/changes_0.x.rst",
    "chars": 33213,
    "preview": ".. _changelog_0x:\n\nChange Log 0.x\n==============\n\nVersion 0.30.0 (2016-01-23)\n---------------------------\n\nCompatibility"
  },
  {
    "path": "docs/changes_1.x.rst",
    "chars": 200822,
    "preview": ".. _important_notes_1x:\n\nImportant notes 1.x\n===================\n\nThis section provides information about security and c"
  },
  {
    "path": "docs/conf.py",
    "chars": 8495,
    "preview": "# Documentation build configuration file, created by\n# sphinx-quickstart on Sat Sep 10 18:18:25 2011.\n#\n# This file is e"
  },
  {
    "path": "docs/deployment/automated-local.rst",
    "chars": 7756,
    "preview": ".. include:: ../global.rst.inc\n.. highlight:: none\n\nAutomated backups to a local hard drive\n============================"
  },
  {
    "path": "docs/deployment/central-backup-server.rst",
    "chars": 7736,
    "preview": ".. include:: ../global.rst.inc\n.. highlight:: none\n.. _central-backup-server:\n\nCentral repository server with Ansible or"
  },
  {
    "path": "docs/deployment/hosting-repositories.rst",
    "chars": 2521,
    "preview": ".. include:: ../global.rst.inc\n.. highlight:: none\n.. _hosting_repositories:\n\nHosting repositories\n====================\n"
  },
  {
    "path": "docs/deployment/image-backup.rst",
    "chars": 7206,
    "preview": ".. include:: ../global.rst.inc\n.. highlight:: none\n\nBacking up entire disk images\n=============================\n\nBacking"
  },
  {
    "path": "docs/deployment/non-root-user.rst",
    "chars": 2484,
    "preview": ".. include:: ../global.rst.inc\n.. highlight:: none\n.. _non_root_user:\n\n================================\nBacking up using"
  },
  {
    "path": "docs/deployment/pull-backup.rst",
    "chars": 20603,
    "preview": ".. include:: ../global.rst.inc\n.. highlight:: none\n.. _pull_backup:\n\n=======================\nBacking up in pull mode\n==="
  },
  {
    "path": "docs/deployment.rst",
    "chars": 357,
    "preview": ".. include:: global.rst.inc\n.. highlight:: none\n\nDeployment\n==========\n\nThis chapter details deployment strategies for t"
  },
  {
    "path": "docs/development.rst",
    "chars": 18760,
    "preview": ".. include:: global.rst.inc\n.. highlight:: bash\n.. _development:\n\nDevelopment\n===========\n\nThis chapter will get you sta"
  },
  {
    "path": "docs/faq.rst",
    "chars": 49688,
    "preview": ".. include:: global.rst.inc\n.. highlight:: none\n.. _faq:\n\nFrequently asked questions\n==========================\n\nUsage &"
  },
  {
    "path": "docs/global.rst.inc",
    "chars": 1606,
    "preview": ".. highlight:: bash\n.. |package_dirname| replace:: borgbackup-|version|\n.. |package_filename| replace:: |package_dirname"
  },
  {
    "path": "docs/index.rst",
    "chars": 368,
    "preview": ".. include:: global.rst.inc\n.. highlight:: none\n\nBorg Documentation\n==================\n\n.. include:: ../README.rst\n\n.. W"
  },
  {
    "path": "docs/installation.rst",
    "chars": 19578,
    "preview": ".. include:: global.rst.inc\n.. highlight:: bash\n.. _installation:\n\nInstallation\n============\n\nThere are different ways t"
  },
  {
    "path": "docs/internals/data-structures.rst",
    "chars": 41272,
    "preview": ".. include:: ../global.rst.inc\n.. highlight:: none\n\n.. _data-structures:\n\nData structures and file formats\n============="
  },
  {
    "path": "docs/internals/frontends.rst",
    "chars": 31574,
    "preview": ".. include:: ../global.rst.inc\n.. highlight:: none\n\n.. _json_output:\n\nAll about JSON: How to develop frontends\n========="
  },
  {
    "path": "docs/internals/security.rst",
    "chars": 18876,
    "preview": ".. include:: ../global.rst.inc\n\n.. somewhat surprisingly the \"bash\" highlighter gives nice results with\n   the pseudo-co"
  },
  {
    "path": "docs/internals.rst",
    "chars": 1686,
    "preview": ".. include:: global.rst.inc\n.. _internals:\n\nInternals\n=========\n\nThe internals chapter describes and analyzes most of th"
  },
  {
    "path": "docs/introduction.rst",
    "chars": 233,
    "preview": "Introduction\n============\n\n.. This shim is here to fix the structure in the PDF\n   rendering. Without this stub, the ele"
  },
  {
    "path": "docs/man/borg-analyze.1",
    "chars": 3013,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-benchmark-cpu.1",
    "chars": 1572,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-benchmark-crud.1",
    "chars": 3564,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-benchmark.1",
    "chars": 1154,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-break-lock.1",
    "chars": 1314,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-check.1",
    "chars": 8627,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-common.1",
    "chars": 2720,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-compact.1",
    "chars": 3398,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-completion.1",
    "chars": 1959,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-compression.1",
    "chars": 5248,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-config.1",
    "chars": 2683,
    "preview": ".\\\" Man page generated from reStructuredText.\n.\n.\n.nr rst2man-indent-level 0\n.\n.de1 rstReportMargin\n\\\\$1 \\\\n[an-margin]\n"
  },
  {
    "path": "docs/man/borg-create.1",
    "chars": 21695,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-delete.1",
    "chars": 3621,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-diff.1",
    "chars": 7665,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-export-tar.1",
    "chars": 3762,
    "preview": "'\\\" t\n.\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-lev"
  },
  {
    "path": "docs/man/borg-extract.1",
    "chars": 4576,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-import-tar.1",
    "chars": 5692,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-info.1",
    "chars": 3308,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-key-change-algorithm.1",
    "chars": 2779,
    "preview": ".\\\" Man page generated from reStructuredText.\n.\n.\n.nr rst2man-indent-level 0\n.\n.de1 rstReportMargin\n\\\\$1 \\\\n[an-margin]\n"
  },
  {
    "path": "docs/man/borg-key-change-location.1",
    "chars": 1728,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-key-change-passphrase.1",
    "chars": 3357,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-key-export.1",
    "chars": 3293,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-key-import.1",
    "chars": 2219,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-key-migrate-to-repokey.1",
    "chars": 1955,
    "preview": ".\\\" Man page generated from reStructuredText.\n.\n.\n.nr rst2man-indent-level 0\n.\n.de1 rstReportMargin\n\\\\$1 \\\\n[an-margin]\n"
  },
  {
    "path": "docs/man/borg-key.1",
    "chars": 1272,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-list.1",
    "chars": 6739,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-match-archives.1",
    "chars": 2746,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-mount.1",
    "chars": 7202,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-patterns.1",
    "chars": 14759,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-placeholders.1",
    "chars": 3232,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-prune.1",
    "chars": 8669,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-recreate.1",
    "chars": 7091,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-rename.1",
    "chars": 1621,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-repo-compress.1",
    "chars": 2640,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-repo-create.1",
    "chars": 8664,
    "preview": "'\\\" t\n.\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-lev"
  },
  {
    "path": "docs/man/borg-repo-delete.1",
    "chars": 2433,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-repo-info.1",
    "chars": 1772,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-repo-list.1",
    "chars": 5030,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-repo-space.1",
    "chars": 2586,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-serve.1",
    "chars": 9073,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-tag.1",
    "chars": 2851,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-transfer.1",
    "chars": 9157,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-umount.1",
    "chars": 3110,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-undelete.1",
    "chars": 2808,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-upgrade.1",
    "chars": 3787,
    "preview": ".\\\" Man page generated from reStructuredText.\n.\n.\n.nr rst2man-indent-level 0\n.\n.de1 rstReportMargin\n\\\\$1 \\\\n[an-margin]\n"
  },
  {
    "path": "docs/man/borg-version.1",
    "chars": 1997,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg-with-lock.1",
    "chars": 2111,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man/borg.1",
    "chars": 39326,
    "preview": "'\\\" t\n.\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-lev"
  },
  {
    "path": "docs/man/borgfs.1",
    "chars": 3494,
    "preview": ".\\\" Man page generated from reStructuredText\n.\\\" by the Docutils 0.22.4 manpage writer.\n.\n.\n.nr rst2man-indent-level 0\n."
  },
  {
    "path": "docs/man_intro.rst",
    "chars": 1752,
    "preview": ":orphan:\n\nSYNOPSIS\n--------\n\nborg [common options] <command> [options] [arguments]\n\nDESCRIPTION\n-----------\n\n.. we don't"
  },
  {
    "path": "docs/misc/asciinema/README",
    "chars": 181,
    "preview": "Do NOT run the examples without isolation (e.g Vagrant) or\nthis code may make undesirable changes to your host.\n\nRunning"
  },
  {
    "path": "docs/misc/asciinema/Vagrantfile",
    "chars": 3215,
    "preview": "Vagrant.configure(\"2\") do |config|\n  config.vm.box = \"debian/bullseye64\"\n  config.vm.provision \"install dependencies\", t"
  },
  {
    "path": "docs/misc/asciinema/advanced.json",
    "chars": 179870,
    "preview": "{\"version\": 2, \"width\": 80, \"height\": 24, \"timestamp\": 1657143034, \"env\": {\"SHELL\": \"/bin/bash\", \"TERM\": \"vt100\"}}\n[0.76"
  },
  {
    "path": "docs/misc/asciinema/advanced.tcl",
    "chars": 3173,
    "preview": "# Configuration for send -h\n# Tries to emulate a human typing\n# Tweak this if typing is too fast or too slow\nset send_hu"
  },
  {
    "path": "docs/misc/asciinema/basic.json",
    "chars": 73711,
    "preview": "{\"version\": 2, \"width\": 80, \"height\": 24, \"timestamp\": 1657142858, \"env\": {\"SHELL\": \"/bin/bash\", \"TERM\": \"vt100\"}}\n[0.90"
  },
  {
    "path": "docs/misc/asciinema/basic.tcl",
    "chars": 3200,
    "preview": "# Configuration for send -h\n# Tries to emulate a human typing\n# Tweak this if typing is too fast or too slow\nset send_hu"
  },
  {
    "path": "docs/misc/asciinema/install.json",
    "chars": 24232,
    "preview": "{\"version\": 2, \"width\": 80, \"height\": 24, \"timestamp\": 1657142795, \"env\": {\"SHELL\": \"/bin/bash\", \"TERM\": \"vt100\"}}\n[0.01"
  },
  {
    "path": "docs/misc/asciinema/install.tcl",
    "chars": 1301,
    "preview": "# Configuration for send -h\n# Tries to emulate a human typing\n# Tweak this if typing is too fast or too slow\nset send_hu"
  },
  {
    "path": "docs/misc/asciinema/sample-wallpapers.txt",
    "chars": 3007,
    "preview": "https://upload.wikimedia.org/wikipedia/commons/2/22/Pseudo_kleinian_001_OpenCL_45154214_8K.jpg\nhttps://upload.wikimedia."
  },
  {
    "path": "docs/misc/benchmark-crud.txt",
    "chars": 3587,
    "preview": "borg benchmark crud\n===================\n\nHere is an example of borg benchmark crud output.\n\nI ran it on my laptop: Core "
  },
  {
    "path": "docs/misc/create_chunker-params.txt",
    "chars": 4456,
    "preview": "About borg create --chunker-params\n==================================\n\n--chunker-params CHUNK_MIN_EXP,CHUNK_MAX_EXP,HASH"
  },
  {
    "path": "docs/misc/internals-picture.txt",
    "chars": 1827,
    "preview": "BorgBackup from 10,000 m\n========================\n\n+--------+ +--------+     +--------+\n|archive0| |archive1| ... |archi"
  },
  {
    "path": "docs/misc/logging.conf",
    "chars": 305,
    "preview": "[loggers]\nkeys=root\n\n[handlers]\nkeys=logfile\n\n[formatters]\nkeys=logfile\n\n[logger_root]\nlevel=NOTSET\nhandlers=logfile\n\n[h"
  },
  {
    "path": "docs/misc/prune-example.txt",
    "chars": 5448,
    "preview": "borg prune visualized\n=====================\n\nAssume it is 2016-01-01. Today's backup has not yet been made. You have\ncre"
  },
  {
    "path": "docs/quickstart.rst",
    "chars": 20519,
    "preview": ".. include:: global.rst.inc\n.. highlight:: bash\n.. _quickstart:\n\nQuick Start\n===========\n\nThis chapter will get you star"
  },
  {
    "path": "docs/quickstart_example.rst.inc",
    "chars": 2529,
    "preview": "1. Before a backup can be made, a repository has to be initialized::\n\n    $ borg -r /path/to/repo repo-create --encrypti"
  },
  {
    "path": "docs/support.rst",
    "chars": 2055,
    "preview": ".. _support:\n\nSupport\n=======\n\nSupport and Services\n--------------------\n\nPlease see https://www.borgbackup.org/ for fre"
  },
  {
    "path": "docs/usage/analyze.rst",
    "chars": 29,
    "preview": ".. include:: analyze.rst.inc\n"
  },
  {
    "path": "docs/usage/analyze.rst.inc",
    "chars": 8422,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_analyze:\n\nborg analyze\n-----"
  },
  {
    "path": "docs/usage/benchmark.rst",
    "chars": 72,
    "preview": ".. include:: benchmark_crud.rst.inc\n\n.. include:: benchmark_cpu.rst.inc\n"
  },
  {
    "path": "docs/usage/benchmark_cpu.rst.inc",
    "chars": 1827,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_benchmark_cpu:\n\nborg benchma"
  },
  {
    "path": "docs/usage/benchmark_crud.rst.inc",
    "chars": 4466,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_benchmark_crud:\n\nborg benchm"
  },
  {
    "path": "docs/usage/borgfs.rst",
    "chars": 38,
    "preview": ":orphan:\n\n.. include:: borgfs.rst.inc\n"
  },
  {
    "path": "docs/usage/borgfs.rst.inc",
    "chars": 16095,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_borgfs:\n\nborg borgfs\n-------"
  },
  {
    "path": "docs/usage/break-lock.rst.inc",
    "chars": 996,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_break-lock:\n\nborg break-lock"
  },
  {
    "path": "docs/usage/check.rst",
    "chars": 27,
    "preview": ".. include:: check.rst.inc\n"
  },
  {
    "path": "docs/usage/check.rst.inc",
    "chars": 17409,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_check:\n\nborg check\n---------"
  },
  {
    "path": "docs/usage/common-options.rst.inc",
    "chars": 1661,
    "preview": "-h, --help               show this help message and exit\n--critical               work on log level CRITICAL\n--error    "
  },
  {
    "path": "docs/usage/compact.rst",
    "chars": 126,
    "preview": ".. include:: compact.rst.inc\n\nExamples\n~~~~~~~~\n::\n\n    # Compact segments and free repository disk space\n    $ borg com"
  },
  {
    "path": "docs/usage/compact.rst.inc",
    "chars": 3929,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_compact:\n\nborg compact\n-----"
  },
  {
    "path": "docs/usage/completion.rst",
    "chars": 353,
    "preview": ".. include:: completion.rst.inc\n\nExamples\n~~~~~~~~\n\nTo activate completion in your current shell session, evaluate the o"
  },
  {
    "path": "docs/usage/completion.rst.inc",
    "chars": 2139,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_completion:\n\nborg completion"
  },
  {
    "path": "docs/usage/create.rst",
    "chars": 4502,
    "preview": ".. include:: create.rst.inc\n\n.. note::\n\n   Archive series and performance: In Borg 2, archives that share the same NAME "
  },
  {
    "path": "docs/usage/create.rst.inc",
    "chars": 46338,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_create:\n\nborg create\n-------"
  },
  {
    "path": "docs/usage/debug.rst",
    "chars": 1751,
    "preview": "Debugging Facilities\n--------------------\n\nThere is a ``borg debug`` command that has some subcommands which are all\n**n"
  },
  {
    "path": "docs/usage/delete.rst",
    "chars": 635,
    "preview": ".. include:: delete.rst.inc\n\nExamples\n~~~~~~~~\n::\n\n    # Delete all backup archives named \"kenny-files\":\n    $ borg dele"
  },
  {
    "path": "docs/usage/delete.rst.inc",
    "chars": 10797,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_delete:\n\nborg delete\n-------"
  },
  {
    "path": "docs/usage/diff.rst",
    "chars": 1018,
    "preview": ".. include:: diff.rst.inc\n\nExamples\n~~~~~~~~\n::\n\n    $ borg diff archive1 archive2\n        +17 B      -5 B [-rw-r--r-- -"
  },
  {
    "path": "docs/usage/diff.rst.inc",
    "chars": 12037,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_diff:\n\nborg diff\n---------\n."
  },
  {
    "path": "docs/usage/export-tar.rst.inc",
    "chars": 10404,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_export-tar:\n\nborg export-tar"
  },
  {
    "path": "docs/usage/extract.rst",
    "chars": 768,
    "preview": ".. include:: extract.rst.inc\n\nExamples\n~~~~~~~~\n::\n\n    # Extract entire archive\n    $ borg extract my-files\n\n    # Extr"
  },
  {
    "path": "docs/usage/extract.rst.inc",
    "chars": 12134,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_extract:\n\nborg extract\n-----"
  },
  {
    "path": "docs/usage/general/archive-specification.rst.inc",
    "chars": 1002,
    "preview": ".. _archive_specification:\n\nSpecifying an archive\n~~~~~~~~~~~~~~~~~~~~~\n\nHow to refer to an archive depends on whether y"
  },
  {
    "path": "docs/usage/general/config.rst.inc",
    "chars": 2502,
    "preview": "Configuration Precedence\n~~~~~~~~~~~~~~~~~~~~~~~~\n\n From lowest to highest:\n\n    1. Defaults defined in the source code."
  },
  {
    "path": "docs/usage/general/date-time.rst.inc",
    "chars": 553,
    "preview": "Date and Time\n~~~~~~~~~~~~~\n\nWe format date and time in accordance with ISO 8601, that is: YYYY-MM-DD and\nHH:MM:SS (24-h"
  },
  {
    "path": "docs/usage/general/environment.rst.inc",
    "chars": 17105,
    "preview": "Environment Variables\n~~~~~~~~~~~~~~~~~~~~~\n\nBorg uses some environment variables for automation:\n\nGeneral:\n    BORG_REP"
  },
  {
    "path": "docs/usage/general/file-metadata.rst.inc",
    "chars": 3086,
    "preview": "Support for file metadata\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\nBesides regular file and directory structures, Borg can preserve\n\n*"
  },
  {
    "path": "docs/usage/general/file-systems.rst.inc",
    "chars": 1588,
    "preview": "File systems\n~~~~~~~~~~~~\n\nWe recommend using a reliable, scalable journaling filesystem for the\nrepository, e.g., zfs, "
  },
  {
    "path": "docs/usage/general/logging.rst.inc",
    "chars": 1649,
    "preview": "Logging\n~~~~~~~\n\nBorg writes all log output to stderr by default. However, output on stderr does\nnot necessarily indicat"
  },
  {
    "path": "docs/usage/general/positional-arguments.rst.inc",
    "chars": 635,
    "preview": "Positional Arguments and Options: Order matters\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nBorg only supports taki"
  },
  {
    "path": "docs/usage/general/repository-locations.rst.inc",
    "chars": 618,
    "preview": "Repository Locations / Archive Names\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nMany commands need to know the repository loc"
  },
  {
    "path": "docs/usage/general/repository-urls.rst.inc",
    "chars": 1947,
    "preview": "Repository URLs\n~~~~~~~~~~~~~~~\n\n**Local filesystem** (or locally mounted network filesystem):\n\n``/path/to/repo`` — file"
  },
  {
    "path": "docs/usage/general/resources.rst.inc",
    "chars": 4657,
    "preview": "Resource Usage\n~~~~~~~~~~~~~~\n\nBorg might use significant resources depending on the size of the data set it is dealing "
  },
  {
    "path": "docs/usage/general/return-codes.rst.inc",
    "chars": 859,
    "preview": "Return codes\n~~~~~~~~~~~~\n\nBorg can exit with the following return codes (rc):\n\n=========== =======\nReturn code Meaning\n"
  },
  {
    "path": "docs/usage/general/units.rst.inc",
    "chars": 499,
    "preview": "Units\n~~~~~\n\nTo display quantities, Borg takes care of respecting the\nusual conventions of scale. Disk sizes are display"
  },
  {
    "path": "docs/usage/general.rst",
    "chars": 1541,
    "preview": "General\n-------\n\nBorg consists of a number of commands. Each command accepts\na number of arguments and options and inter"
  },
  {
    "path": "docs/usage/help.rst",
    "chars": 65,
    "preview": "Miscellaneous Help\n------------------\n\n.. include:: help.rst.inc\n"
  },
  {
    "path": "docs/usage/help.rst.inc",
    "chars": 21084,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_patterns:\n\nborg help pattern"
  },
  {
    "path": "docs/usage/import-tar.rst.inc",
    "chars": 13856,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_import-tar:\n\nborg import-tar"
  },
  {
    "path": "docs/usage/info.rst",
    "chars": 573,
    "preview": ".. include:: info.rst.inc\n\nExamples\n~~~~~~~~\n::\n\n    $ borg info aid:f7dea078\n    Archive name: source-backup\n    Archiv"
  },
  {
    "path": "docs/usage/info.rst.inc",
    "chars": 10110,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_info:\n\nborg info\n---------\n."
  },
  {
    "path": "docs/usage/key.rst",
    "chars": 2236,
    "preview": ".. include:: key_change-location.rst.inc\n\n.. _borg-change-passphrase:\n\n.. include:: key_change-passphrase.rst.inc\n\nExamp"
  },
  {
    "path": "docs/usage/key_change-location.rst.inc",
    "chars": 2957,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_key_change-location:\n\nborg k"
  },
  {
    "path": "docs/usage/key_change-passphrase.rst.inc",
    "chars": 1299,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_key_change-passphrase:\n\nborg"
  },
  {
    "path": "docs/usage/key_export.rst.inc",
    "chars": 4417,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_key_export:\n\nborg key export"
  },
  {
    "path": "docs/usage/key_import.rst.inc",
    "chars": 3265,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_key_import:\n\nborg key import"
  },
  {
    "path": "docs/usage/list.rst",
    "chars": 1725,
    "preview": ".. include:: list.rst.inc\n\nExamples\n~~~~~~~~\n::\n\n    $ borg list root-2016-02-15\n    drwxr-xr-x root   root          0 M"
  },
  {
    "path": "docs/usage/list.rst.inc",
    "chars": 12625,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_list:\n\nborg list\n---------\n."
  },
  {
    "path": "docs/usage/lock.rst",
    "chars": 64,
    "preview": ".. include:: with-lock.rst.inc\n\n.. include:: break-lock.rst.inc\n"
  },
  {
    "path": "docs/usage/mount.rst",
    "chars": 1643,
    "preview": ".. include:: mount.rst.inc\n\n.. include:: umount.rst.inc\n\nExamples\n~~~~~~~~\n\n::\n\n    # Mounting the repository shows all "
  },
  {
    "path": "docs/usage/mount.rst.inc",
    "chars": 18961,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_mount:\n\nborg mount\n---------"
  },
  {
    "path": "docs/usage/notes.rst",
    "chars": 8734,
    "preview": "Additional Notes\n----------------\n\nHere are miscellaneous notes about topics that may not be covered in enough detail in"
  },
  {
    "path": "docs/usage/prune.rst",
    "chars": 2078,
    "preview": ".. include:: prune.rst.inc\n\nExamples\n~~~~~~~~\n\nBe careful: prune is a potentially dangerous command that removes backup\n"
  },
  {
    "path": "docs/usage/prune.rst.inc",
    "chars": 18450,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_prune:\n\nborg prune\n---------"
  },
  {
    "path": "docs/usage/recreate.rst",
    "chars": 1004,
    "preview": ".. include:: recreate.rst.inc\n\nExamples\n~~~~~~~~\n::\n\n    # Create a backup with fast, low compression\n    $ borg create "
  },
  {
    "path": "docs/usage/recreate.rst.inc",
    "chars": 26356,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_recreate:\n\nborg recreate\n---"
  },
  {
    "path": "docs/usage/rename.rst",
    "chars": 297,
    "preview": ".. include:: rename.rst.inc\n\nExamples\n~~~~~~~~\n::\n\n    $ borg create archivename ~\n    $ borg repo-list\n    archivename "
  },
  {
    "path": "docs/usage/rename.rst.inc",
    "chars": 1939,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_rename:\n\nborg rename\n-------"
  },
  {
    "path": "docs/usage/repo-compress.rst",
    "chars": 274,
    "preview": ".. include:: repo-compress.rst.inc\n\nExamples\n~~~~~~~~\n\n::\n\n    # Recompress repository contents\n    $ borg repo-compress"
  },
  {
    "path": "docs/usage/repo-compress.rst.inc",
    "chars": 4037,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_repo-compress:\n\nborg repo-co"
  },
  {
    "path": "docs/usage/repo-create.rst",
    "chars": 1061,
    "preview": ".. _borg_repo_create:\n\n.. include:: repo-create.rst.inc\n\nExamples\n~~~~~~~~\n::\n\n    # Local repository\n    $ export BORG_"
  },
  {
    "path": "docs/usage/repo-create.rst.inc",
    "chars": 10923,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_repo-create:\n\nborg repo-crea"
  },
  {
    "path": "docs/usage/repo-delete.rst",
    "chars": 497,
    "preview": ".. include:: repo-delete.rst.inc\n\nExamples\n~~~~~~~~\n::\n\n    # delete the whole repository and the related local cache:\n "
  },
  {
    "path": "docs/usage/repo-delete.rst.inc",
    "chars": 4589,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_repo-delete:\n\nborg repo-dele"
  },
  {
    "path": "docs/usage/repo-info.rst",
    "chars": 561,
    "preview": ".. include:: repo-info.rst.inc\n\nExamples\n~~~~~~~~\n::\n\n    $ borg repo-info\n    Repository ID: 0e85a7811022326c067acb2a71"
  },
  {
    "path": "docs/usage/repo-info.rst.inc",
    "chars": 1531,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_repo-info:\n\nborg repo-info\n-"
  },
  {
    "path": "docs/usage/repo-list.rst",
    "chars": 625,
    "preview": ".. include:: repo-list.rst.inc\n\nExamples\n~~~~~~~~\n::\n\n    $ borg repo-list\n    151b1a57  Mon, 2024-09-23 22:57:11 +0200 "
  },
  {
    "path": "docs/usage/repo-list.rst.inc",
    "chars": 13882,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_repo-list:\n\nborg repo-list\n-"
  },
  {
    "path": "docs/usage/repo-space.rst",
    "chars": 32,
    "preview": ".. include:: repo-space.rst.inc\n"
  },
  {
    "path": "docs/usage/repo-space.rst.inc",
    "chars": 3652,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_repo-space:\n\nborg repo-space"
  },
  {
    "path": "docs/usage/serve.rst",
    "chars": 5065,
    "preview": ".. include:: serve.rst.inc\n\nExamples\n~~~~~~~~\n\n``borg serve`` has special support for ssh forced commands (see ``authori"
  },
  {
    "path": "docs/usage/serve.rst.inc",
    "chars": 10025,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_serve:\n\nborg serve\n---------"
  },
  {
    "path": "docs/usage/tag.rst",
    "chars": 25,
    "preview": ".. include:: tag.rst.inc\n"
  },
  {
    "path": "docs/usage/tag.rst.inc",
    "chars": 11296,
    "preview": ".. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!\n\n.. _borg_tag:\n\nborg tag\n--------\n.. c"
  }
]

// ... and 250 more files (download for full content)

About this extraction

This page contains the full source code of the borgbackup/borg GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 450 files (3.8 MB), approximately 1.0M tokens, and a symbol index with 2871 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!