|
@@ -30,6 +30,8 @@ logger = create_logger(__name__)
|
|
|
|
|
|
MAGIC = b'BORG_SEG'
|
|
|
MAGIC_LEN = len(MAGIC)
|
|
|
+ATTIC_MAGIC = b'ATTICSEG'
|
|
|
+assert len(ATTIC_MAGIC) == MAGIC_LEN
|
|
|
TAG_PUT = 0
|
|
|
TAG_DELETE = 1
|
|
|
TAG_COMMIT = 2
|
|
@@ -116,6 +118,9 @@ class Repository:
|
|
|
class InvalidRepository(Error):
|
|
|
"""{} is not a valid repository. Check repo config."""
|
|
|
|
|
|
+ class AtticRepository(Error):
|
|
|
+ """Attic repository detected. Please run "borg upgrade {}"."""
|
|
|
+
|
|
|
class CheckNeeded(ErrorWithTraceback):
|
|
|
"""Inconsistency detected. Please run "borg check {}"."""
|
|
|
|
|
@@ -134,7 +139,7 @@ class Repository:
|
|
|
"""The storage quota ({}) has been exceeded ({}). Try deleting some archives."""
|
|
|
|
|
|
def __init__(self, path, create=False, exclusive=False, lock_wait=None, lock=True,
|
|
|
- append_only=False, storage_quota=None):
|
|
|
+ append_only=False, storage_quota=None, check_segment_magic=True):
|
|
|
self.path = os.path.abspath(path)
|
|
|
self._location = Location('file://%s' % self.path)
|
|
|
self.io = None # type: LoggedIO
|
|
@@ -154,6 +159,7 @@ class Repository:
|
|
|
self.storage_quota = storage_quota
|
|
|
self.storage_quota_use = 0
|
|
|
self.transaction_doomed = None
|
|
|
+ self.check_segment_magic = check_segment_magic
|
|
|
|
|
|
def __del__(self):
|
|
|
if self.lock:
|
|
@@ -370,6 +376,12 @@ class Repository:
|
|
|
self.storage_quota = self.config.getint('repository', 'storage_quota', fallback=0)
|
|
|
self.id = unhexlify(self.config.get('repository', 'id').strip())
|
|
|
self.io = LoggedIO(self.path, self.max_segment_size, self.segments_per_dir)
|
|
|
+ if self.check_segment_magic:
|
|
|
+ # read a segment and check whether we are dealing with a non-upgraded Attic repository
|
|
|
+ segment = self.io.get_latest_segment()
|
|
|
+ if segment is not None and self.io.get_segment_magic(segment) == ATTIC_MAGIC:
|
|
|
+ self.close()
|
|
|
+ raise self.AtticRepository(path)
|
|
|
|
|
|
def close(self):
|
|
|
if self.lock:
|
|
@@ -1245,6 +1257,11 @@ class LoggedIO:
|
|
|
def segment_size(self, segment):
|
|
|
return os.path.getsize(self.segment_filename(segment))
|
|
|
|
|
|
+ def get_segment_magic(self, segment):
|
|
|
+ fd = self.get_fd(segment)
|
|
|
+ fd.seek(0)
|
|
|
+ return fd.read(MAGIC_LEN)
|
|
|
+
|
|
|
def iter_objects(self, segment, offset=0, include_data=False, read_data=True):
|
|
|
"""
|
|
|
Return object iterator for *segment*.
|