Repository: borgbackup/borg

Issue:
'borg config' command
Similar to [`git config`](https://git-scm.com/docs/git-config), it would be nice to have a convenience `borg config` command that just opens the repo config and changes an option accordingly.


Discussion:
It looks like it would be super simple to implement (for local repositories): just `Repository.save_key` followed by `save_config`. I'm not sure whether this should go under `borg debug` or not...
I am somehow a bit undecided what to think about this.

OTOH, it's nice to have a frontend here, so one does not need an editor. Using an editor isn't that complicated, though (locating the configs for the first time is non-trivial, though).

OTOH, you still need an editor due to security for remote repos (or run borg config on the server?).

I was thinking to run e.g. `ssh user@host borg config /path/to/repo key value` to reconfigure on the server because [some clients may only be allowed to use borg serve](https://borgbackup.readthedocs.io/en/stable/usage/notes.html?highlight=ssh#append-only-mode). If the user is allowed to run other commands, they could just run ssh directly like above. The repo config is not encrypted even with an encrypted repo, so it would still work.
Hmm, when using `ssh user@host borg config /path/to/repo key value` there is some risk that this causes permission issues, if user is not the usual borgbackup user.
btw, i am working on adding validation for the keys/values used with borg config.

when looking at the keys one might want to set with new values, I failed to find anything that a user could want to set for the cache configuration. @milkey-mouse do you see any use case?

See #3581.

If we fail to find any use case for modifying the cache config, there are 2 ways to deal with this:
- raise for any key now (if we think there could be use cases in future)
- remove the `borg config --cache` option / related code and only keep the repo related stuff

Hmm, maybe we need to look at "get" also, not just at set/delete.
I remember at the time I had a good reason for it - I think a need to edit the cache was what spurred me to make the command. I will see later what I was doing and try to add examples to the docs (unless `--cache` really is just a symptom of featuritis...)
Ah, I found it: the main thing I used `--cache` for was changing the `previous_location` variable after intentionally moving a repository so I didn't have to run a dummy `BORG_RELOCATED_REPO_ACCESS_IS_OK=yes borg list` just to stop prompts from aborting my automatic backups. I think this one is useful enough to add to the examples in the docs.

I have also used it to change the manifest ID/integrity value during ill-advised repository surgery, but that's not something that should be encouraged/mentioned in the docs...
Reopening to update the validation PR accordingly.
See PR #3674.

BTW, I noticed `borg config --cache repo previous_location <new_value>` is not working at all, it does not set a new value, the old one is still present. This is unrelated to my validation changes.

@milkey-mouse can you have a look?
Ok, wow, this is a really stupid issue. :man_facepalming:

`borg config --cache previous_location <new-location>` would never have worked in the first place! If you look at `cache.py` one can see it resets `previous_location` to the "new" canonical location again right before saving the file:

https://github.com/borgbackup/borg/blob/1473ea708cf9bdaaae54f42a06dc699e6ee926e1/src/borg/cache.py#L294-L309

So if you were resetting `previous_location` to the "correct" value after moving a repo, it would appear to work because `BORG_RELOCATED_REPO_ACCESS_IS_OK` would just so happen to change it to the same thing. But if you were trying to set it to a nonsense/inaccurate value to test it, it would never have worked!

I think the easiest course of action might just be to move line 307 to the end of the load() function.

Resolving patch:
diff --git a/src/borg/cache.py b/src/borg/cache.py
--- a/src/borg/cache.py
+++ b/src/borg/cache.py
@@ -290,6 +290,7 @@ def load(self):
             self.previous_location = recanonicalize_relative_location(previous_location, self.repository)
         else:
             self.previous_location = None
+        self._config.set('cache', 'previous_location', self.repository._location.canonical_path())
 
     def save(self, manifest=None, key=None):
         if manifest:
@@ -304,7 +305,6 @@ def save(self, manifest=None, key=None):
             self._config.set('integrity', 'manifest', manifest.id_str)
         if key:
             self._config.set('cache', 'key_type', str(key.TYPE))
-        self._config.set('cache', 'previous_location', self.repository._location.canonical_path())
         with SaveFile(self.config_path) as fd:
             self._config.write(fd)
 


Test patch: