mirror of https://github.com/borgbackup/borg.git
Improved error handling.
This commit is contained in:
parent
0cc09fb761
commit
da0e3c4ec8
|
@ -100,7 +100,7 @@ class Archive(object):
|
|||
self.numeric_owner = numeric_owner
|
||||
if create:
|
||||
if name in manifest.archives:
|
||||
raise self.AlreadyExists
|
||||
raise self.AlreadyExists(name)
|
||||
self.last_checkpoint = time.time()
|
||||
i = 0
|
||||
while True:
|
||||
|
@ -112,7 +112,7 @@ class Archive(object):
|
|||
try:
|
||||
info = self.manifest.archives[name]
|
||||
except KeyError:
|
||||
raise self.DoesNotExist
|
||||
raise self.DoesNotExist(name)
|
||||
self.load(info['id'])
|
||||
|
||||
def load(self, id):
|
||||
|
|
|
@ -411,9 +411,26 @@ class Archiver(object):
|
|||
|
||||
def main():
|
||||
archiver = Archiver()
|
||||
exit_code = archiver.run()
|
||||
if exit_code:
|
||||
archiver.print_error('Exiting with failure status due to previous errors')
|
||||
try:
|
||||
exit_code = archiver.run()
|
||||
except Store.DoesNotExist:
|
||||
archiver.print_error('Error: Store not found')
|
||||
exit_code = 1
|
||||
except Store.AlreadyExists:
|
||||
archiver.print_error('Error: Store already exists')
|
||||
exit_code = 1
|
||||
except Archive.AlreadyExists, e:
|
||||
archiver.print_error('Error: Archive "%s" already exists', e)
|
||||
exit_code = 1
|
||||
except Archive.DoesNotExist, e:
|
||||
archiver.print_error('Error: Archive "%s" does not exist', e)
|
||||
exit_code = 1
|
||||
except KeyboardInterrupt:
|
||||
archiver.print_error('Error: Keyboard interrupt')
|
||||
exit_code = 1
|
||||
else:
|
||||
if exit_code:
|
||||
archiver.print_error('Exiting with failure status due to previous errors')
|
||||
sys.exit(exit_code)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -61,12 +61,6 @@ class StoreServer(object):
|
|||
|
||||
class RemoteStore(object):
|
||||
|
||||
class DoesNotExist(Exception):
|
||||
pass
|
||||
|
||||
class AlreadyExists(Exception):
|
||||
pass
|
||||
|
||||
class RPCError(Exception):
|
||||
|
||||
def __init__(self, name):
|
||||
|
@ -92,7 +86,13 @@ class RemoteStore(object):
|
|||
version = self.call('negotiate', (1,))
|
||||
if version != 1:
|
||||
raise Exception('Server insisted on using unsupported protocol version %d' % version)
|
||||
self.id = self.call('open', (location.path, create))
|
||||
try:
|
||||
self.id = self.call('open', (location.path, create))
|
||||
except self.RPCError, e:
|
||||
if e.name == 'DoesNotExist':
|
||||
raise Store.DoesNotExist
|
||||
elif e.name == 'AlreadyExists':
|
||||
raise Store.AlreadyExists
|
||||
|
||||
def __del__(self):
|
||||
self.close()
|
||||
|
@ -106,7 +106,10 @@ class RemoteStore(object):
|
|||
if x:
|
||||
raise Exception('FD exception occured')
|
||||
if r:
|
||||
self.unpacker.feed(os.read(self.stdout_fd, BUFSIZE))
|
||||
data = os.read(self.stdout_fd, BUFSIZE)
|
||||
if not data:
|
||||
raise Exception('Remote host closed connection')
|
||||
self.unpacker.feed(data)
|
||||
for type, msgid, error, res in self.unpacker:
|
||||
if msgid == self.msgid:
|
||||
assert msgid == self.msgid
|
||||
|
@ -130,7 +133,7 @@ class RemoteStore(object):
|
|||
def _read(self):
|
||||
data = os.read(self.stdout_fd, BUFSIZE)
|
||||
if not data:
|
||||
raise Exception('EOF')
|
||||
raise Exception('Remote host closed connection')
|
||||
self.unpacker.feed(data)
|
||||
to_yield = []
|
||||
for type, msgid, error, res in self.unpacker:
|
||||
|
@ -229,7 +232,7 @@ class RemoteStore(object):
|
|||
return res
|
||||
except self.RPCError, e:
|
||||
if e.name == 'DoesNotExist':
|
||||
raise self.DoesNotExist
|
||||
raise Store.DoesNotExist
|
||||
raise
|
||||
|
||||
def get_many(self, ids, peek=None):
|
||||
|
@ -241,13 +244,9 @@ class RemoteStore(object):
|
|||
self.pending.pop(self.cache.pop(key)[0], None)
|
||||
|
||||
def put(self, id, data, wait=True):
|
||||
try:
|
||||
resp = self.call('put', (id, data), wait=wait)
|
||||
self._invalidate(id)
|
||||
return resp
|
||||
except self.RPCError, e:
|
||||
if e.name == 'AlreadyExists':
|
||||
raise self.AlreadyExists
|
||||
resp = self.call('put', (id, data), wait=wait)
|
||||
self._invalidate(id)
|
||||
return resp
|
||||
|
||||
def delete(self, id, wait=True):
|
||||
resp = self.call('delete', (id, ), wait=wait)
|
||||
|
|
|
@ -36,6 +36,9 @@ class Store(object):
|
|||
class DoesNotExist(KeyError):
|
||||
"""Requested key does not exist"""
|
||||
|
||||
class AlreadyExists(KeyError):
|
||||
"""Requested key does not exist"""
|
||||
|
||||
def __init__(self, path, create=False):
|
||||
if create:
|
||||
self.create(path)
|
||||
|
@ -45,7 +48,7 @@ class Store(object):
|
|||
"""Create a new empty store at `path`
|
||||
"""
|
||||
if os.path.exists(path) and (not os.path.isdir(path) or os.listdir(path)):
|
||||
raise Exception('Path "%s" already exists' % path)
|
||||
raise self.AlreadyExists(path)
|
||||
if not os.path.exists(path):
|
||||
os.mkdir(path)
|
||||
with open(os.path.join(path, 'README'), 'wb') as fd:
|
||||
|
@ -64,7 +67,7 @@ class Store(object):
|
|||
self.head = None
|
||||
self.path = path
|
||||
if not os.path.isdir(path):
|
||||
raise Exception('%s Does not look like a darc store' % path)
|
||||
raise self.DoesNotExist(path)
|
||||
self.lock_fd = open(os.path.join(path, 'README'), 'r+')
|
||||
fcntl.flock(self.lock_fd, fcntl.LOCK_EX)
|
||||
self.config = RawConfigParser()
|
||||
|
@ -426,11 +429,11 @@ class StoreTestCase(unittest.TestCase):
|
|||
key50 = '%-32d' % 50
|
||||
self.assertEqual(self.store.get(key50), 'SOMEDATA')
|
||||
self.store.delete(key50)
|
||||
self.assertRaises(self.store.DoesNotExist, lambda: self.store.get(key50))
|
||||
self.assertRaises(Store.DoesNotExist, lambda: self.store.get(key50))
|
||||
self.store.commit()
|
||||
self.store.close()
|
||||
store2 = self.open()
|
||||
self.assertRaises(store2.DoesNotExist, lambda: store2.get(key50))
|
||||
self.assertRaises(Store.DoesNotExist, lambda: store2.get(key50))
|
||||
for x in range(100):
|
||||
if x == 50:
|
||||
continue
|
||||
|
@ -457,7 +460,7 @@ class StoreTestCase(unittest.TestCase):
|
|||
self.store.put('00000000000000000000000000000000', 'bar')
|
||||
self.assertEqual(self.store.get('00000000000000000000000000000000'), 'bar')
|
||||
self.store.delete('00000000000000000000000000000000')
|
||||
self.assertRaises(self.store.DoesNotExist, lambda: self.store.get('00000000000000000000000000000000'))
|
||||
self.assertRaises(Store.DoesNotExist, lambda: self.store.get('00000000000000000000000000000000'))
|
||||
|
||||
def test_consistency2(self):
|
||||
"""Test cache consistency2
|
||||
|
|
16
darc/test.py
16
darc/test.py
|
@ -3,6 +3,7 @@ import doctest
|
|||
import filecmp
|
||||
import os
|
||||
from StringIO import StringIO
|
||||
import stat
|
||||
import sys
|
||||
import shutil
|
||||
import tempfile
|
||||
|
@ -84,7 +85,7 @@ class Test(unittest.TestCase):
|
|||
path2 = os.path.join(dir2, filename)
|
||||
s1 = os.lstat(path1)
|
||||
s2 = os.lstat(path2)
|
||||
attrs = ['st_mode', 'st_uid', 'st_gid']
|
||||
attrs = ['st_mode', 'st_uid', 'st_gid', 'st_rdev']
|
||||
# We can't restore symlink atime/mtime right now
|
||||
if not os.path.islink(path1):
|
||||
attrs.append('st_mtime')
|
||||
|
@ -95,15 +96,28 @@ class Test(unittest.TestCase):
|
|||
self.assertEqual(d1, d2)
|
||||
|
||||
def test_basic_functionality(self):
|
||||
# File
|
||||
self.create_regual_file('file1', size=1024 * 80)
|
||||
# Directory
|
||||
self.create_regual_file('dir2/file2', size=1024 * 80)
|
||||
# File owner
|
||||
os.chown('input/file1', 100, 200)
|
||||
# File mode
|
||||
os.chmod('input/file1', 0600)
|
||||
os.chmod('input/dir2', 0700)
|
||||
# Block device
|
||||
os.mknod('input/bdev', 0600 | stat.S_IFBLK, os.makedev(10, 20))
|
||||
# Char device
|
||||
os.mknod('input/cdev', 0600 | stat.S_IFCHR, os.makedev(30, 40))
|
||||
# xattr
|
||||
x = xattr(os.path.join(self.input_path, 'file1'))
|
||||
x.set('user.foo', 'bar')
|
||||
# Hard link
|
||||
os.link(os.path.join(self.input_path, 'file1'),
|
||||
os.path.join(self.input_path, 'hardlink'))
|
||||
# Symlink
|
||||
os.symlink('somewhere', os.path.join(self.input_path, 'link1'))
|
||||
# FIFO node
|
||||
os.mkfifo(os.path.join(self.input_path, 'fifo1'))
|
||||
self.darc('init', self.store_location)
|
||||
self.darc('create', self.store_location + '::test', 'input')
|
||||
|
|
Loading…
Reference in New Issue