Repository: borgbackup/borg

Issue:
Can I repair a repository with missing segments without using `borg check`?
Due to connection issues, some files might not get transferred to the remote server and subsequently are missing from the repository's `data` folder. (This has nothing to do with borg. I'm trying to improve the situation, but for now I have to assume that missing files in `data` might happen. I can explain this further if necessary, but I don't think it's relevant.)

The issue can be reproduced locally with the following steps:

- Create a append-only repository (`append_only = 1`)
- Set `max_segment_size = 1000` to make it easier to produce a lot of segments without taking up a lot of storage
- `borg create repo::one source` which creates `data/0/0` up to `5` for example
- Add some files to the local backup source folder
- `borg create repo::two source` which creates `data/0/6` up to `11` for example
- Finally, manually delete a data segment from `two` like `data/0/7` for example

Now, I can still access all files from `repo::one` without issues. However, naturally, I get errors accessing files from `repo::two` due to the deleted segment `7`.

I don't even need to repair archive `two` - I just want to repair the repo so I can create new archives without referring to the corrupted one. In other words, I *know*  when an archive got corrupted and I want to ignore all changes from that archive as they might refer to segments which don't exist.

What I tried to do:

- If I run `borg delete --force --force repo::two`, the corrupted archive `two` gets deleted.
- However, a subsequent call to `borg create repo::three` as a second try to create a new archive still tries to access missing segment `7` from the now deleted archive `two` and I get `FileNotFoundError`.

Can I make the repo "forget" that archive `two` was ever created?


Discussion:
You shouldn't use tools that silently corrupt the borg repo while transferring it. In case of the usual syncing tools, one approach might be to repeatedly run the tool until it terminates without an error.

About the double-force delete:
doesn't it tell you that you shall run `borg check --repair` afterwards to "cleanup the mess"?

An alternative way would be to roll back the transaction that was corrupted by your transfer tool via borg's transaction log, but there is no automation for that, see the docs about how to do it manually. Of course this is only advisable if the corruption is within one of the last repo transactions as you'ld lose all stuff from the rolled back transactions.

> You shouldn't use tools that silently corrupt the borg repo while transferring it. In case of the usual syncing tools, one approach might be to repeatedly run the tool until it terminates without an error.

Yes, I agree.

> About the double-force delete: doesn't it tell you that you shall run borg check --repair afterwards to "cleanup the mess"?

No, it did not. Prompted for passphrase then returned to the shell. No further infos or warnings. (This is with version 1.1.8 - I'll update and report back.)

> An alternative way would be to roll back the transaction that was corrupted by your transfer tool via borg's transaction log, but there is no automation for that, see the docs about how to do it manually.

You're referring to https://borgbackup.readthedocs.io/en/stable/usage/notes.html#append-only-mode right? I will still have to rebuild the cache completely from scratch, did I get that right?

> Of course this is only advisable if the corruption is within one of the last repo transactions as you'ld lose all stuff from the rolled back transactions.

Yes, that makes sense. But it's not an issue in this case because I can check immediately after finishing `borg create` if all files have been transferred successfully.
Yes, that is what I was referring to. Cache is also described there.
> > About the double-force delete: doesn't it tell you that you shall run borg check --repair afterwards to "cleanup the mess"?
>
> No, it did not. Prompted for passphrase then returned to the shell. No further infos or warnings. (This is with version 1.1.8 - I'll update and report back.)

Just letting you know - same behavior for 1.1.10:

```
$ ./borg-linux64 --version
borg-linux64 1.1.10
$ ./borg-linux64 init --encryption=repokey repo2

By default repositories initialized with this version will produce security
errors if written to with an older version (up to and including Borg 1.0.8).

If you want to use these older versions, you can disable the check by running:
borg upgrade --disable-tam repo2

See https://borgbackup.readthedocs.io/en/stable/changes.html#pre-1-0-9-manifest-spoofing-vulnerability for details about the security implications.

IMPORTANT: you will need both KEY AND PASSPHRASE to access this repo!
Use "borg key export" to export the key, optionally in printable format.
Write down the passphrase. Store both at safe place(s).

$ ./borg-linux64 config repo2 append_only 1
$ ./borg-linux64 config repo2 max_segment_size 1000
$ ./borg-linux64 create repo2::one local
$ ./borg-linux64 create repo2::two local
$ ./borg-linux64 list repo2
one                                  Fri, 2019-08-02 15:41:07 [################################################################]
two                                  Fri, 2019-08-02 15:41:23 [################################################################]
$ rm repo2/data/0/7
$ ./borg-linux64 delete --force --force repo2::two
$ ./borg-linux64 list repo2
one                                  Fri, 2019-08-02 15:41:07 [################################################################]
$ 
```
> Yes, that is what I was referring to. Cache is also described there.

Thanks for confirming. I had read this but wanted to make sure.

Also, it works, by the way. :+1: It makes sense that it's possible to interpret the corrupted files as an malicious attack and therefore just use that recovery procedure. Unfortunately, it's just not feasible to rebuild the cache each time. :( Is it a necessity to have to rebuild the cache or is there just (currently) no way to rollback the cache, too?

Additionally, are there intentions to implement something like `borg rollback` to automatize the mentioned steps in https://borgbackup.readthedocs.io/en/stable/usage/notes.html#append-only-mode?

Resolving patch:
diff --git a/src/borg/archiver.py b/src/borg/archiver.py
--- a/src/borg/archiver.py
+++ b/src/borg/archiver.py
@@ -1124,7 +1124,7 @@ def _delete_archives(self, args, repository):
                 manifest.write()
                 # note: might crash in compact() after committing the repo
                 repository.commit(compact=False)
-                logger.info('Done. Run "borg check --repair" to clean up the mess.')
+                logger.warning('Done. Run "borg check --repair" to clean up the mess.')
             else:
                 logger.warning('Aborted.')
             return self.exit_code


Test patch: