diff --git a/src/borg/archiver.py b/src/borg/archiver.py index bc1497d2..59ee4f92 100644 --- a/src/borg/archiver.py +++ b/src/borg/archiver.py @@ -75,6 +75,7 @@ try: from .helpers import sig_int, ignore_sigint from .helpers import iter_separated from .helpers import get_tar_filter + from .helpers import ignore_invalid_archive_tam from .helpers.parseformat import BorgJsonEncoder, safe_decode from .nanorst import rst_to_terminal from .patterns import ArgparsePatternAction, ArgparseExcludeFileAction, ArgparsePatternFileAction, parse_exclude_pattern @@ -1639,47 +1640,48 @@ class Archiver: def do_upgrade(self, args, repository, manifest=None, key=None): """upgrade a repository from a previous version""" if args.archives_tam or args.check_archives_tam: - archive_tam_issues = 0 - read_only = args.check_archives_tam - manifest, key = Manifest.load(repository, (Manifest.Operation.CHECK,), force_tam_not_required=args.force) - with Cache(repository, key, manifest) as cache: - stats = Statistics() - for info in manifest.archives.list(sort_by=['ts']): - archive_id = info.id - archive_formatted = format_archive(info) - cdata = repository.get(archive_id) - data = key.decrypt(archive_id, cdata) - archive, verified, _ = key.unpack_and_verify_archive(data, force_tam_not_required=True) - if not verified: - if not read_only: - # we do not have an archive TAM yet -> add TAM now! - archive = ArchiveItem(internal_dict=archive) - archive.cmdline = [safe_decode(arg) for arg in archive.cmdline] - data = key.pack_and_authenticate_metadata(archive.as_dict(), context=b'archive') - new_archive_id = key.id_hash(data) - cache.add_chunk(new_archive_id, data, stats) - cache.chunk_decref(archive_id, stats) - manifest.archives[info.name] = (new_archive_id, info.ts) - print(f"Added archive TAM: {archive_formatted} -> [{bin_to_hex(new_archive_id)}]") + with ignore_invalid_archive_tam(): + archive_tam_issues = 0 + read_only = args.check_archives_tam + manifest, key = Manifest.load(repository, (Manifest.Operation.CHECK,), force_tam_not_required=args.force) + with Cache(repository, key, manifest) as cache: + stats = Statistics() + for info in manifest.archives.list(sort_by=['ts']): + archive_id = info.id + archive_formatted = format_archive(info) + cdata = repository.get(archive_id) + data = key.decrypt(archive_id, cdata) + archive, verified, _ = key.unpack_and_verify_archive(data, force_tam_not_required=True) + if not verified: + if not read_only: + # we do not have an archive TAM yet -> add TAM now! + archive = ArchiveItem(internal_dict=archive) + archive.cmdline = [safe_decode(arg) for arg in archive.cmdline] + data = key.pack_and_authenticate_metadata(archive.as_dict(), context=b'archive') + new_archive_id = key.id_hash(data) + cache.add_chunk(new_archive_id, data, stats) + cache.chunk_decref(archive_id, stats) + manifest.archives[info.name] = (new_archive_id, info.ts) + print(f"Added archive TAM: {archive_formatted} -> [{bin_to_hex(new_archive_id)}]") + else: + print(f"Archive TAM missing: {archive_formatted}") + archive_tam_issues += 1 else: - print(f"Archive TAM missing: {archive_formatted}") - archive_tam_issues += 1 + print(f"Archive TAM present: {archive_formatted}") + if not read_only: + manifest.write() + repository.commit(compact=False) + cache.commit() + if archive_tam_issues > 0: + print(f"Fixed {archive_tam_issues} archives with TAM issues!") + print("All archives are TAM authenticated now.") + else: + print("All archives are TAM authenticated.") else: - print(f"Archive TAM present: {archive_formatted}") - if not read_only: - manifest.write() - repository.commit(compact=False) - cache.commit() - if archive_tam_issues > 0: - print(f"Fixed {archive_tam_issues} archives with TAM issues!") - print("All archives are TAM authenticated now.") - else: - print("All archives are TAM authenticated.") - else: - if archive_tam_issues > 0: - self.print_warning(f"Found {archive_tam_issues} archives with TAM issues!") - else: - print("All archives are TAM authenticated.") + if archive_tam_issues > 0: + self.print_warning(f"Found {archive_tam_issues} archives with TAM issues!") + else: + print("All archives are TAM authenticated.") elif args.tam: manifest, key = Manifest.load(repository, (Manifest.Operation.CHECK,), force_tam_not_required=args.force) if not manifest.tam_verified or not manifest.config.get(b'tam_required', False): diff --git a/src/borg/helpers/__init__.py b/src/borg/helpers/__init__.py index 34a59b90..b24d61a6 100644 --- a/src/borg/helpers/__init__.py +++ b/src/borg/helpers/__init__.py @@ -5,6 +5,7 @@ that did not fit better elsewhere. Code used to be in borg/helpers.py but was split into the modules in this package, which are imported into here for compatibility. """ +from contextlib import contextmanager from .checks import * # NOQA from .datastruct import * # NOQA @@ -26,6 +27,18 @@ from . import msgpack # see the docs for a list of known workaround strings. workarounds = tuple(os.environ.get('BORG_WORKAROUNDS', '').split(',')) + +@contextmanager +def ignore_invalid_archive_tam(): + global workarounds + saved = workarounds + if 'ignore_invalid_archive_tam' not in workarounds: + # we really need this workaround here or borg will likely raise an exception. + workarounds += ('ignore_invalid_archive_tam',) + yield + workarounds = saved + + """ The global exit_code variable is used so that modules other than archiver can increase the program exit code if a warning or error occurred during their operation. This is different from archiver.exit_code, which is only accessible