diff --git a/src/borg/remote.py b/src/borg/remote.py index c69b2fe04..3064176da 100644 --- a/src/borg/remote.py +++ b/src/borg/remote.py @@ -251,6 +251,19 @@ class RepositoryServer: # pragma: no cover args = self.filter_args(f, args) res = f(**args) except BaseException as e: + # These exceptions are reconstructed on the client end in RemoteRepository.call_many(), + # and will be handled just like locally raised exceptions. Suppress the remote traceback + # for these, except ErrorWithTraceback, which should always display a traceback. + reconstructed_exceptions = ( + Repository.InvalidRepository, + Repository.InvalidRepositoryConfig, + Repository.DoesNotExist, + Repository.AlreadyExists, + Repository.PathAlreadyExists, + PathNotAllowed, + Repository.InsufficientFreeSpaceError, + Repository.StorageQuotaExceeded, + ) if dictFormat: ex_short = traceback.format_exception_only(e.__class__, e) ex_full = traceback.format_exception(*sys.exc_info()) @@ -258,12 +271,7 @@ class RepositoryServer: # pragma: no cover if isinstance(e, Error): ex_short = [e.get_message()] ex_trace = e.traceback - if isinstance(e, (Repository.DoesNotExist, Repository.AlreadyExists, PathNotAllowed)): - # These exceptions are reconstructed on the client end in RemoteRepository.call_many(), - # and will be handled just like locally raised exceptions. Suppress the remote traceback - # for these, except ErrorWithTraceback, which should always display a traceback. - pass - else: + if not isinstance(e, reconstructed_exceptions): logging.debug('\n'.join(ex_full)) try: @@ -286,12 +294,7 @@ class RepositoryServer: # pragma: no cover os_write(stdout_fd, msg) else: - if isinstance(e, (Repository.DoesNotExist, Repository.AlreadyExists, PathNotAllowed)): - # These exceptions are reconstructed on the client end in RemoteRepository.call_many(), - # and will be handled just like locally raised exceptions. Suppress the remote traceback - # for these, except ErrorWithTraceback, which should always display a traceback. - pass - else: + if not isinstance(e, reconstructed_exceptions): if isinstance(e, Error): tb_log_level = logging.ERROR if e.traceback else logging.DEBUG msg = e.get_message() @@ -759,6 +762,8 @@ This problem will go away as soon as the server has been upgraded to 1.0.7+. raise Error(args[0].decode()) elif error == 'ErrorWithTraceback': raise ErrorWithTraceback(args[0].decode()) + elif error == 'InvalidRepository': + raise Repository.InvalidRepository(self.location.processed) elif error == 'DoesNotExist': raise Repository.DoesNotExist(self.location.processed) elif error == 'AlreadyExists': @@ -782,6 +787,8 @@ This problem will go away as soon as the server has been upgraded to 1.0.7+. raise PathNotAllowed(args[0].decode()) elif error == 'PathPermissionDenied': raise Repository.PathPermissionDenied(args[0].decode()) + elif error == 'PathAlreadyExists': + raise Repository.PathAlreadyExists(args[0].decode()) elif error == 'ParentPathDoesNotExist': raise Repository.ParentPathDoesNotExist(args[0].decode()) elif error == 'ObjectNotFound': @@ -814,6 +821,12 @@ This problem will go away as soon as the server has been upgraded to 1.0.7+. raise NotMyLock('(not available)') else: raise NotMyLock(args[0].decode()) + elif error == 'InsufficientFreeSpaceError': + raise Repository.InsufficientFreeSpaceError(args[0].decode(), args[1].decode()) + elif error == 'InvalidRepositoryConfig': + raise Repository.InvalidRepositoryConfig(self.location.processed, args[1].decode()) + elif error == 'StorageQuotaExceeded': + raise Repository.StorageQuotaExceeded(args[0].decode(), args[1].decode()) else: raise self.RPCError(unpacked) diff --git a/src/borg/testsuite/archiver.py b/src/borg/testsuite/archiver.py index bc9aee798..5dc14faee 100644 --- a/src/borg/testsuite/archiver.py +++ b/src/borg/testsuite/archiver.py @@ -3935,6 +3935,17 @@ id: 2 / e29442 3506da 4e1ea7 / 25f62a 5a3d41 - 02 self.cmd('create', self.repository_location + '::test2', 'input') assert os.path.exists(nonce) + def test_exit_codes(self): + # we create the repo path, but do NOT initialize the borg repo, + # so the borg create commands are expected to fail with InvalidRepository. + os.makedirs(self.repository_path, exist_ok=True) + with environment_variable(BORG_EXIT_CODES='classic'): + self.cmd('create', self.repository_location + '::archive', 'input', fork=True, + exit_code=EXIT_ERROR) + with environment_variable(BORG_EXIT_CODES='modern'): + self.cmd('create', self.repository_location + '::archive', 'input', fork=True, + exit_code=Repository.InvalidRepository.exit_mcode) + @unittest.skipUnless('binary' in BORG_EXES, 'no borg.exe available') class ArchiverTestCaseBinary(ArchiverTestCase):