Skip to content

Remove ssh:// and socket:// remote repository for current repos (use rest://)#9732

Merged
ThomasWaldmann merged 4 commits into
borgbackup:masterfrom
ThomasWaldmann:remove-ssh-remote-repo
Jun 8, 2026
Merged

Remove ssh:// and socket:// remote repository for current repos (use rest://)#9732
ThomasWaldmann merged 4 commits into
borgbackup:masterfrom
ThomasWaldmann:remove-ssh-remote-repo

Conversation

@ThomasWaldmann

Copy link
Copy Markdown
Member

What

Removes the modern RemoteRepository (the ssh:// and socket:// client/server transport served by borg serve over an msgpack RPC protocol). For current (borg 2) repositories its functionality is replaced by rest://, which can itself tunnel over ssh to a remote borgstore REST server.

Legacy v1 (borg 1.x) access over ssh is preserved. It uses the separate LegacyRemoteRepository client, and borg serve / RepositoryServer is kept (trimmed to the legacy-only path) so a remote borg2 can still serve a v1 repo for borg transfer --from-borg1.

Changes

  • remote.py: delete RemoteRepository, SleepingBandwidthLimiter and the api decorator; trim RepositoryServer to legacy-only (drop modern _rpc_methods, socket serving, non-legacy open() branch). Keep the general-purpose cache_if_remote / RepositoryCache / RepositoryNoCache (used by all repos).
  • get_repository(): non-legacy ssh:// now raises a clear "use rest://" error; the socket:// route and the global --socket option are removed.
  • parseformat: drop the socket:// scheme (now an invalid location). ssh:// (legacy) and rest:// unchanged.
  • borg serve: kept as a command (serves legacy v1 ssh only); epilog updated.
  • borg version: drop the modern remote query; keep the legacy ssh path.
  • isinstance/import cleanups: cache.py, archive.py, fuse.py/hlfuse.py, analyze_cmd.py, compact_cmd.py, and archiver/__init__.py (RPCError handling retargeted to LegacyRemoteRepository).
  • tests/docs updated; the obsolete socket-server serve_cmd_test.py removed; changelog entry added.

Net: 23 files changed, +101 / −1194.

Behavior

  • borg -r rest://… works (replacement path).
  • borg -r ssh://host/repo create … (no --from-borg1) fails with a clear "use rest://" error; socket://… is rejected as an invalid location.
  • borg transfer --from-borg1 --other-repo ssh://… still works: the local LegacyRemoteRepository spawns a remote borg serve, which serves the v1 repo via the trimmed RepositoryServer legacy path.

Testing

Run with a venv that has borgstore[rest] (so borgstore-server-rest is on PATH). All changed/related suites pass — 322 passed, 21 skipped — including the rest:// remote_archiver tests and the legacy ssh serve tests (legacyrepository_test.py).

🤖 Generated with Claude Code

The modern client/server transport (RemoteRepository served by `borg serve`
over an msgpack RPC protocol) is now redundant for current (borg 2) repos:
its functionality is replaced by rest:// (which can tunnel over ssh to a
remote borgstore REST server).

Remove the modern RemoteRepository (both ssh:// and socket://) entirely.
Legacy v1 (borg 1.x) repos remain reachable over ssh:// via the separate
LegacyRemoteRepository client, and `borg serve` / RepositoryServer is kept,
trimmed to the legacy-only path, so a remote borg2 can still serve a v1 repo
for `borg transfer --from-borg1`.

Details:
- remote.py: delete RemoteRepository, SleepingBandwidthLimiter and the `api`
  decorator; trim RepositoryServer to legacy-only (drop modern _rpc_methods,
  socket serving, non-legacy open() branch); keep cache_if_remote /
  RepositoryCache / RepositoryNoCache (used by all repos).
- get_repository(): non-legacy ssh:// now raises a clear "use rest://" error;
  socket:// route and the global --socket option removed.
- parseformat: drop the socket:// scheme (now an invalid location).
- borg serve: keep the command (serves legacy v1 ssh only); update epilog.
- borg version: drop modern remote query; keep legacy ssh path.
- update isinstance/import sites (cache, archive, fuse/hlfuse, analyze/compact,
  archiver __init__ -> LegacyRemoteRepository.RPCError).
- tests/docs updated; obsolete socket serve test removed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@codecov

codecov Bot commented Jun 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.52459% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.69%. Comparing base (582c358) to head (6565b44).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
src/borg/archiver/version_cmd.py 0.00% 3 Missing ⚠️
src/borg/archive.py 50.00% 0 Missing and 1 partial ⚠️
src/borg/archiver/_common.py 66.66% 1 Missing ⚠️
src/borg/cache.py 0.00% 0 Missing and 1 partial ⚠️
src/borg/repository.py 96.29% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #9732      +/-   ##
==========================================
+ Coverage   83.59%   84.69%   +1.09%     
==========================================
  Files          93       92       -1     
  Lines       15717    14959     -758     
  Branches     2360     2231     -129     
==========================================
- Hits        13139    12669     -470     
+ Misses       1834     1593     -241     
+ Partials      744      697      -47     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

ThomasWaldmann and others added 3 commits June 8, 2026 08:44
After removing the modern RemoteRepository, cache_if_remote always returned
RepositoryNoCache in production (the only RepositoryCache path was the removed
isinstance(RemoteRepository) check; force_cache=True was used only by a test).

Delete the vestigial RepositoryCache class and simplify cache_if_remote: drop
the pack/unpack/force_cache parameters and the LZ4/xxh64 cache-file machinery,
keep building the decrypted_cache -> transform closure, and always return
RepositoryNoCache. Remove the imports that only RepositoryCache used.

Replace the RepositoryCache tests with a focused test of the surviving
cache_if_remote path (plain passthrough and decrypted (csize, plaintext) tuples).

The legacy copy in borg/legacy/remote.py is intentionally left untouched (its
RepositoryCache is still used for LegacyRemoteRepository).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
borg.legacy.remote.cache_if_remote (and the RepositoryCache / RepositoryNoCache
classes it returns) are dead code: nothing imports or calls them. Every
cache_if_remote consumer (archive check, mount, tests) uses the non-legacy
borg.remote version, and legacy repos never reach it (Archive.check rejects
legacy repos). The trio was copied wholesale during the borg.legacy split (borgbackup#9556).

Delete RepositoryNoCache, RepositoryCache and cache_if_remote, plus the imports
that only they used (shutil, struct, tempfile, xxhash.xxh64, compress.Compressor,
helpers.safe_unlink). LegacyRemoteRepository and the rest of the module are
unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…itory

borg.remote no longer fit its name: it held the legacy-only borg serve server
plus generic repository cache wrappers used by current repos. Split by purpose
and remove the module:

- Move RepositoryServer into borg.legacy.remote (it only serves legacy v1 ssh
  repositories). It reuses the exception classes (PathNotAllowed,
  InvalidRPCMethod, UnexpectedRPCDataFormatFromClient) and BORG_VERSION / MSGID
  constants already defined there; open() uses the module-level LegacyRepository.
  serve_cmd.py now imports RepositoryServer from ..legacy.remote.
- Move RepositoryNoCache and cache_if_remote into borg.repository (they wrap a
  Repository and are used by Archive.check and mount of current repos).
  archive.py and mount_cmds.py import them from ..repository now.
- Move the cache_if_remote tests into repository_test.py; delete remote_test.py.
- Delete src/borg/remote.py; fix the stale BUFSIZE comment in constants.py.

Pure relocation, no behavior change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant