From 7501c3b530a2069e9bc450487753644330e47a3a Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sun, 5 Jun 2016 01:05:32 +0200 Subject: [PATCH 1/3] better error handling for missing repo manifest, fixes #1043 can happen for not correctly initialized repos or corrupted repos. here: borg list failing more pretty --- borg/helpers.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/borg/helpers.py b/borg/helpers.py index 27697cade..aefcdffc5 100644 --- a/borg/helpers.py +++ b/borg/helpers.py @@ -65,6 +65,10 @@ class ExtensionModuleError(Error): """The Borg binary extension modules do not seem to be properly installed""" +class NoManifestError(Error): + """Repository has no manifest.""" + + def check_extension_modules(): from . import platform if hashindex.API_VERSION != 2: @@ -90,7 +94,11 @@ class Manifest: @classmethod def load(cls, repository, key=None): from .key import key_factory - cdata = repository.get(cls.MANIFEST_ID) + from .repository import Repository + try: + cdata = repository.get(cls.MANIFEST_ID) + except Repository.ObjectNotFound: + raise NoManifestError if not key: key = key_factory(repository, cdata) manifest = cls(key, repository) From 6a70d9968c3dfd904e678814f55a9da2206d4af0 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sun, 5 Jun 2016 01:22:43 +0200 Subject: [PATCH 2/3] make borg check work for empty repo --- borg/archive.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/borg/archive.py b/borg/archive.py index b10bac07a..e21c1aab5 100644 --- a/borg/archive.py +++ b/borg/archive.py @@ -695,7 +695,12 @@ class ArchiveChecker: self.chunks[id_] = (0, 0, 0) def identify_key(self, repository): - cdata = repository.get(next(self.chunks.iteritems())[0]) + try: + some_chunkid, _ = next(self.chunks.iteritems()) + except StopIteration: + # repo is completely empty, no chunks + return None + cdata = repository.get(some_chunkid) return key_factory(repository, cdata) def rebuild_manifest(self): From e10d543ef4a52ea1d3dfd23799f0e73f952f9888 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sun, 5 Jun 2016 02:14:14 +0200 Subject: [PATCH 3/3] delete a repo without manifest --- borg/archiver.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/borg/archiver.py b/borg/archiver.py index fb1fa523e..bbd6a2e43 100644 --- a/borg/archiver.py +++ b/borg/archiver.py @@ -19,7 +19,7 @@ from . import __version__ from .helpers import Error, location_validator, archivename_validator, format_line, format_time, format_file_size, \ parse_pattern, PathPrefixPattern, to_localtime, timestamp, safe_timestamp, \ get_cache_dir, prune_within, prune_split, \ - Manifest, remove_surrogates, update_excludes, format_archive, check_extension_modules, Statistics, \ + Manifest, NoManifestError, remove_surrogates, update_excludes, format_archive, check_extension_modules, Statistics, \ dir_is_tagged, bigint_to_int, ChunkerParams, CompressionSpec, is_slow_msgpack, yes, sysinfo, \ EXIT_SUCCESS, EXIT_WARNING, EXIT_ERROR, log_multi, PatternMatcher from .logger import create_logger, setup_logging @@ -397,10 +397,11 @@ class Archiver: cache.commit() return self.exit_code - @with_repository(exclusive=True) - def do_delete(self, args, repository, manifest, key): + @with_repository(exclusive=True, manifest=False) + def do_delete(self, args, repository): """Delete an existing repository or archive""" if args.location.archive: + manifest, key = Manifest.load(repository) with Cache(repository, key, manifest, lock_wait=self.lock_wait) as cache: archive = Archive(repository, key, manifest, args.location.archive, cache=cache) stats = Statistics() @@ -417,9 +418,15 @@ class Archiver: else: if not args.cache_only: msg = [] - msg.append("You requested to completely DELETE the repository *including* all archives it contains:") - for archive_info in manifest.list_archive_infos(sort_by='ts'): - msg.append(format_archive(archive_info)) + try: + manifest, key = Manifest.load(repository) + except NoManifestError: + msg.append("You requested to completely DELETE the repository *including* all archives it may contain.") + msg.append("This repository seems to have no manifest, so we can't tell anything about its contents.") + else: + msg.append("You requested to completely DELETE the repository *including* all archives it contains:") + for archive_info in manifest.list_archive_infos(sort_by='ts'): + msg.append(format_archive(archive_info)) msg.append("Type 'YES' if you understand this and want to continue: ") msg = '\n'.join(msg) if not yes(msg, false_msg="Aborting.", truish=('YES', ),