diff --git a/src/borg/archive.py b/src/borg/archive.py index 1611ea157..729cff6df 100644 --- a/src/borg/archive.py +++ b/src/borg/archive.py @@ -1659,6 +1659,7 @@ class RobustUnpacker: class ArchiveChecker: def __init__(self): self.error_found = False + self.key = None def check( self, @@ -1696,7 +1697,8 @@ class ArchiveChecker: # Repository.check already did a full repository-level check and has built and cached a fresh chunkindex - # we can use that here, so we don't disable the caches (also no need to cache immediately, again): self.chunks = build_chunkindex_from_repo(self.repository, disable_caches=False, cache_immediately=False) - self.key = self.make_key(repository) + if self.key is None: + self.key = self.make_key(repository) self.repo_objs = RepoObj(self.key) if verify_data: self.verify_data() @@ -1728,11 +1730,10 @@ class ArchiveChecker: logger.info("Archive consistency check complete, no problems found.") return self.repair or not self.error_found - def make_key(self, repository): + def make_key(self, repository, manifest_only=False): attempt = 0 # try the manifest first! - attempt += 1 try: cdata = repository.get_manifest() except NoManifestError: @@ -1744,19 +1745,24 @@ class ArchiveChecker: # we get here, if the cdata we got has a corrupted key type byte pass # ignore it, just continue trying - for chunkid, _ in self.chunks.iteritems(): - attempt += 1 - if attempt > 999: - # we did a lot of attempts, but could not create the key via key_factory, give up. - break - cdata = repository.get(chunkid) - try: - return key_factory(repository, cdata) - except UnsupportedPayloadError: - # we get here, if the cdata we got has a corrupted key type byte - pass # ignore it, just try the next chunk + if not manifest_only: + for chunkid, _ in self.chunks.iteritems(): + attempt += 1 + if attempt > 999: + # we did a lot of attempts, but could not create the key via key_factory, give up. + break + cdata = repository.get(chunkid) + try: + return key_factory(repository, cdata) + except UnsupportedPayloadError: + # we get here, if the cdata we got has a corrupted key type byte + pass # ignore it, just try the next chunk + if attempt == 0: - msg = "make_key: repository has no chunks at all!" + if manifest_only: + msg = "make_key: failed to create the key (tried only the manifest)" + else: + msg = "make_key: repository has no chunks at all!" else: msg = "make_key: failed to create the key (tried %d chunks)" % attempt raise IntegrityError(msg) diff --git a/src/borg/archiver/check_cmd.py b/src/borg/archiver/check_cmd.py index a9bd9f05b..233065ab7 100644 --- a/src/borg/archiver/check_cmd.py +++ b/src/borg/archiver/check_cmd.py @@ -2,7 +2,7 @@ import argparse from ._common import with_repository, Highlander from ..archive import ArchiveChecker from ..constants import * # NOQA -from ..helpers import set_ec, EXIT_WARNING, CancelledByUser, CommandError +from ..helpers import set_ec, EXIT_WARNING, CancelledByUser, CommandError, IntegrityError from ..helpers import yes from ..logger import create_logger @@ -44,10 +44,17 @@ class CheckMixIn: # archives check requires that a full repo check was done before and has built/cached a ChunkIndex. # also, there is no max_duration support in the archives check code anyway. raise CommandError("--repository-only is required for --max-duration support.") + if not args.repo_only: + # if we need the key later for the archives check, ask NOW for the passphrase! #1931 + archive_checker = ArchiveChecker() + try: + archive_checker.key = archive_checker.make_key(repository, manifest_only=True) + except IntegrityError: + pass # will try to make key later again if not args.archives_only: if not repository.check(repair=args.repair, max_duration=args.max_duration): set_ec(EXIT_WARNING) - if not args.repo_only and not ArchiveChecker().check( + if not args.repo_only and not archive_checker.check( repository, verify_data=args.verify_data, repair=args.repair,