mirror of
https://github.com/borgbackup/borg.git
synced 2026-05-28 04:03:21 -04:00
fix remote repository exception handling / exit codes, fixes #8631
also: reduce code duplication.
This commit is contained in:
parent
1659be23f8
commit
dddb6b1556
2 changed files with 36 additions and 12 deletions
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
Loading…
Reference in a new issue