mirror of
https://github.com/borgbackup/borg.git
synced 2026-11-02 03:01:25 +01:00
* known-repos: new command to list locally known repositories
Lists repositories this local Borg installation has state for (security
info and/or a local cache) without accessing any repository, local or
remote. Scans both the current borg2 security/cache directories and,
separately, the legacy borg 1.x security/cache directories (which can be
different default locations, e.g. on macOS).
Does not follow symlinks anywhere in the scanned trees (repo-id
directories, or the location/key-type files inside them), since borg
only ever writes plain directories and regular files there.
Key-type labels are derived from the key classes themselves
(LEGACY_KEY_TYPES + AVAILABLE_KEY_TYPES), matching how "borg repo-info"
names crypto suites, rather than a separately hand-maintained table.
dir_size() pushes each directory handle (root, and any subdirectory
opened while walking the cache tree) onto its explicit stack before
calling list_names() on it, not after, so cleanup can always close it
even if list_names() raises something other than OSError (it only
catches OSError itself) - e.g. KeyboardInterrupt. Covered by two unit
tests that monkeypatch list_names() to raise and then check the fd via
os.fstat().
has_cache and has_security_info are tri-state (True/False/None, not a
plain bool): an inspection failure (e.g. EACCES on a repo-id directory,
or on the security/cache root itself, including a root that opens but
fails during its own listing) is reported as unknown rather than being
collapsed into a false "no". A repo-id directory that could be listed
but not opened/classified is still included in the results with its
fields set to unknown, instead of silently disappearing from the
output. The JSON/text field for which state-directory layout a
repository was discovered under is named "layout" (values "borg2" /
"legacy" / null), not "version", so it cannot be confused with Borg's
actual repository format version (see "borg repo-info").
Adds docs/usage/known-repos.rst{,.inc} and the usage.rst toctree entry, and
the generated man page.
* known-repos: simplify after maintainer review, drop leftover defenses
Rewrite the scanner around ordinary OS file access instead of extra
symlink/size defenses, collapse duplicated scan/table/test logic, and
surface real inspection failures (ENOTDIR, unparseable cache config)
instead of treating them as absence.
Also forward create=False through legacy get_keys_dir(), refresh the
usage example, keep tests to the remaining behavioral surface, and
shorten a few overly verbose test docstrings.
* known-repos: fix black formatting, restore generated usage/man docs
black wants the process_epilog("""...""") call's opening triple-quote on
its own line and the closing paren on a separate line.
docs/usage/known-repos.rst still includes known-repos.rst.inc, which a
previous commit deleted along with the generated man page - this broke
the docs build (InputError: no such file). Regenerate both with
scripts/make.py build_usage/build_man, following the convention other
recently added commands (copy, find) already use.
* known-repos: address second-review minor points
- location_mismatch now compares the security location and cache
previous_location through normalize_local_path(), the same way
assert_location_matches() does, so an NFC vs. NFD unicode-form
difference alone isn't flagged as a mismatch on macOS (#2913).
Added a regression test for it.
- The table no longer truncates the repository id to 15 chars - users
acting on an entry (e.g. removing a stale cache dir) need the full id.
Strengthened the existing test assertion to match. Updated the
epilog and the usage example accordingly (full id was previously
JSON-only), and regenerated docs/usage/known-repos.rst.inc and
docs/man/borg-known-repos.1 to match.
- legacy/fs.py: dropped the "(and now also the known-repos command)"
historical phrasing from the module docstring; the following
paragraph already lists both callers.
- Epilog: mentioned that a security-only repo gets layout "unknown"
when BORG_SECURITY_DIR makes the borg2 and legacy security roots
coincide. Thomas noted the behavior itself is fine either way, just
worth a brief mention.
* known-repos: address PyPy msgpack warning and Windows encoding failures
Fixes two CI failures reported in maintainer follow-up review:
- PyPy: test_known_repos_without_repo_argument and
test_known_repos_multiple_sorted_by_id failed with JSONDecodeError
because pure-python msgpack emits PURE_PYTHON_MSGPACK_WARNING on PyPy,
which contaminated exec_cmd() output. Introduce cmd_without_repo()
helper that filters the warning line identically to cmd() while avoiding
--repo injection, as suggested.
- Windows: test_known_repos_location_mismatch_ignores_nfc_nfd_difference
crashed with UnicodeEncodeError writing NFD path in cp1252. Skip the NFD
test on Windows, as suggested.
- Windows/scanner: read state files using default locale encoding matching
borg's SaveFile/SyncFile implementation, dropping explicit encoding="utf-8",
as suggested.
* known-repos: use security location mtime + cache newest-file mtime for last_written
PR #10497 (sealed files cache) removed CacheConfig.save(), so on
current master the borg2 cache config file's mtime stays at cache
creation time and no longer tracks last use.
last_written is now the newer of:
- the security location file's mtime (rewritten by Cache.close() via
security_manager.save() on every run; also gives security-only
repos a value)
- the newest mtime of the regular files below the cache dir, tracked
during the existing cache_stats() walk that already computes size
The JSON field is renamed from cache_config_mtime to last_written.
Epilog/docs/man page say where the timestamp comes from and say
"regular file" to match what the code tracks. The long run-on epilog
sentence is split into shorter sentences.
Tests assert which source wins (location-newer, cache-newer including
a nested file) and the cache-only case now checks the exact mtime
instead of only non-null.
|
||
|---|---|---|
| .. | ||
| general | ||
| analyze.rst | ||
| analyze.rst.inc | ||
| benchmark.rst | ||
| benchmark_cpu.rst.inc | ||
| benchmark_crud.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 | ||
| copy.rst | ||
| copy.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 | ||
| find.rst | ||
| find.rst.inc | ||
| general.rst | ||
| help.rst | ||
| help.rst.inc | ||
| import-tar.rst.inc | ||
| info.rst | ||
| info.rst.inc | ||
| key.rst | ||
| key_add.rst.inc | ||
| key_change-location.rst.inc | ||
| key_change-passphrase.rst.inc | ||
| key_export.rst.inc | ||
| key_import.rst.inc | ||
| key_list.rst.inc | ||
| key_remove.rst.inc | ||
| known-repos.rst | ||
| known-repos.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 | ||
| webdav.rst | ||
| webdav.rst.inc | ||
| with-lock.rst.inc | ||