Copying is cheap and fast: no file content is read or written, only a new
archive metadata object is created. Like any deduplicated archives, the two
archives share their data, so a copy needs almost no additional repository
space.
The copy is an independent archive: deleting either of the two archives
keeps the other one intact, because "borg compact" only frees chunks that no
remaining archive references.
Archive.copy() is Archive.rename() without removing the original archive
entry. Copying an archive to its own name is refused: the new metadata would
be identical, thus have the same archive ID, and no second archive would be
created. NEWNAME may well be the name of some other existing archive, the
copy then just joins that archive series.
OLDNAME must match precisely one archive, so it accepts an archive name (if
it is unique) or an archive ID like "aid:d34db33f".
Co-Authored-By: Claude Fable 5 <[email protected]>
borg find iterates over the archives selected by the usual archive
filter options (all archives by default) from newest to oldest, over
all items of each archive, and outputs one line per item matching the
given PATHs (paths or patterns, matching like in borg list /
borg extract).
Output lines are formatted like borg list default output, but are
prefixed with a short archive ID and the archive name. As the
archives of a series all share the same name, only the archive ID
uniquely identifies the archive.
Output is customizable via --format / BORG_FIND_FORMAT (ItemFormatter
keys) and --json-lines.
There is no extra index for file paths (keeping one up to date would
cost considerable runtime and space), so this reads the metadata of
all selected archives.
reimplemented for the pack-based repository format: the repository is
processed pack after pack - each pack is read as a whole and, if it has
objects not stored with the desired compression, those get recompressed
and the pack is rewritten (objects already fine are copied into the new
pack unchanged), the chunk index is updated and the old pack is deleted.
a pack whose objects all already match is not touched at all.
- new Repository.transform_pack: rewrite one pack, passing each indexed
object's bytes through a transform callback. gap bytes are handled
like in compact_pack: superseded duplicates are dropped, other
unindexed bytes are carried forward for "borg check --repair".
- factored the check_pack_objects / superseded_gap_ranges helpers out
of compact_pack, now shared with merge_packs and transform_pack.
- crash safety like compact (#9748): stored chunk indexes are
invalidated before the first store change, a full updated index is
written back at the end. SIGINT stops cleanly at a pack boundary,
saving a valid index; a later run recompresses the remaining packs.
- --stats reports rewritten packs, per-object outcomes (recompressed /
already had the desired compression / kept as-is because
recompression brings no gain) and the repository size change.
- re-adding the fish completions also restores the compression_methods
definition that the create/transfer/recreate/import-tar completions
kept referencing after it was removed together with the old
repo-compress.
Co-Authored-By: Claude Fable 5 <[email protected]>
New "borg webdav" command: it starts a read-only HTTP server on localhost,
so archive contents can be browsed and files downloaded with a web browser.
This first step implements plain HTTP only (GET/HEAD, HTML directory
listings, file downloads). The WebDAV methods (OPTIONS/PROPFIND), which
enable native mounting by Windows Explorer, macOS Finder and the Linux
desktop file managers, are planned to be added on top of this later.
Implementation notes:
- only uses the python standard library, no new dependencies.
- the directory tree of an archive is built in memory when it is first
accessed, so a big archive only costs time/memory if it is browsed.
- all repository access is serialized with a lock, because borgstore
connections are not thread-safe.
- a LockRefresher keeps the repository lock of an idle server alive,
so it is not killed as stale, see #9872.
- missing chunks abort the download connection, so damaged files are
never served as silently corrupted content.
- symlinks and special files are listed, but not downloadable.
Note: downloads via HTTP do not preserve POSIX metadata (owner, group,
mode, timestamps, xattrs, ACLs) - use borg extract or borg export-tar
for full-fidelity restores.
Co-Authored-By: Claude Fable 5 <[email protected]>
for packs, this needs to get implemented differently to perform well.
processing needs to be pack-after-pack and the index needs to be
updated correctly and carefully, e.g. considering interruptions
of repo-compress.
This command works similarly to "git config" - it parses repo and
cache configs to get, set, and delete values. It only works on local
repos so a malicious client can't e.g. override their storage quota
or reset the append_only flag.
Add tests for borg config
Add documentation for borg config
Change manual config edits -> borg config
There were a couple places in the documentation where it was advised
to edit the repository or cache config file, a process that is stream-
lined by borg config.
The former section is a bit older (Nov 2016) and has been the piece
responsible for finding CVE-2016-10099, since while writing it I
wondered how the manifest was authenticated to actually
*be* the manifest. Well. There it is ;)
It has been edited to final form only recently and should now be ready
for review.
The latter section is new.