mirror of https://github.com/borgbackup/borg.git
extract: implement extract_helper context manager
Most code of the CM is just moved 1:1 from the regular file block. Use the CM for regular files, FIFOs and devices, but not for: - directories (can not have hardlinks) - symlinks (we can not support hardlinked symlinks)
This commit is contained in:
parent
cda7465038
commit
cb86bda413
|
@ -502,6 +502,26 @@ Utilization of max. archive size: {csize_max:.0%}
|
||||||
cache.rollback()
|
cache.rollback()
|
||||||
return stats
|
return stats
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def extract_helper(self, dest, item, path, stripped_components, original_path, hardlink_masters):
|
||||||
|
hardlink_set = False
|
||||||
|
# Hard link?
|
||||||
|
if 'source' in item:
|
||||||
|
source = os.path.join(dest, *item.source.split(os.sep)[stripped_components:])
|
||||||
|
chunks, link_target = hardlink_masters.get(item.source, (None, source))
|
||||||
|
if link_target:
|
||||||
|
# Hard link was extracted previously, just link
|
||||||
|
with backup_io('link'):
|
||||||
|
os.link(link_target, path)
|
||||||
|
hardlink_set = True
|
||||||
|
elif chunks is not None:
|
||||||
|
# assign chunks to this item, since the item which had the chunks was not extracted
|
||||||
|
item.chunks = chunks
|
||||||
|
yield hardlink_set
|
||||||
|
if not hardlink_set and hardlink_masters: # 2nd term, is it correct/needed?
|
||||||
|
# Update master entry with extracted item path, so that following hardlinks don't extract twice.
|
||||||
|
hardlink_masters[item.get('source') or original_path] = (None, path)
|
||||||
|
|
||||||
def extract_item(self, item, restore_attrs=True, dry_run=False, stdout=False, sparse=False,
|
def extract_item(self, item, restore_attrs=True, dry_run=False, stdout=False, sparse=False,
|
||||||
hardlink_masters=None, stripped_components=0, original_path=None, pi=None):
|
hardlink_masters=None, stripped_components=0, original_path=None, pi=None):
|
||||||
"""
|
"""
|
||||||
|
@ -566,20 +586,8 @@ Utilization of max. archive size: {csize_max:.0%}
|
||||||
if stat.S_ISREG(mode):
|
if stat.S_ISREG(mode):
|
||||||
with backup_io('makedirs'):
|
with backup_io('makedirs'):
|
||||||
make_parent(path)
|
make_parent(path)
|
||||||
hardlink_set = False
|
with self.extract_helper(dest, item, path, stripped_components, original_path,
|
||||||
# Hard link?
|
hardlink_masters) as hardlink_set:
|
||||||
if 'source' in item:
|
|
||||||
source = os.path.join(dest, *item.source.split(os.sep)[stripped_components:])
|
|
||||||
chunks, link_target = hardlink_masters.get(item.source, (None, source))
|
|
||||||
if link_target:
|
|
||||||
# Hard link was extracted previously, just link
|
|
||||||
with backup_io('link'):
|
|
||||||
os.link(link_target, path)
|
|
||||||
hardlink_set = True
|
|
||||||
elif chunks is not None:
|
|
||||||
# assign chunks to this item, since the item which had the chunks was not extracted
|
|
||||||
item.chunks = chunks
|
|
||||||
if True:
|
|
||||||
if hardlink_set:
|
if hardlink_set:
|
||||||
return
|
return
|
||||||
if sparse and self.zeros is None:
|
if sparse and self.zeros is None:
|
||||||
|
@ -610,9 +618,6 @@ Utilization of max. archive size: {csize_max:.0%}
|
||||||
if has_damaged_chunks:
|
if has_damaged_chunks:
|
||||||
logger.warning('File %s has damaged (all-zero) chunks. Try running borg check --repair.' %
|
logger.warning('File %s has damaged (all-zero) chunks. Try running borg check --repair.' %
|
||||||
remove_surrogates(item.path))
|
remove_surrogates(item.path))
|
||||||
if not hardlink_set and hardlink_masters: # 2nd term, is it correct/needed?
|
|
||||||
# Update master entry with extracted file path, so that following hardlinks don't extract twice.
|
|
||||||
hardlink_masters[item.get('source') or original_path] = (None, path)
|
|
||||||
return
|
return
|
||||||
with backup_io:
|
with backup_io:
|
||||||
# No repository access beyond this point.
|
# No repository access beyond this point.
|
||||||
|
@ -632,10 +637,18 @@ Utilization of max. archive size: {csize_max:.0%}
|
||||||
self.restore_attrs(path, item, symlink=True)
|
self.restore_attrs(path, item, symlink=True)
|
||||||
elif stat.S_ISFIFO(mode):
|
elif stat.S_ISFIFO(mode):
|
||||||
make_parent(path)
|
make_parent(path)
|
||||||
|
with self.extract_helper(dest, item, path, stripped_components, original_path,
|
||||||
|
hardlink_masters) as hardlink_set:
|
||||||
|
if hardlink_set:
|
||||||
|
return
|
||||||
os.mkfifo(path)
|
os.mkfifo(path)
|
||||||
self.restore_attrs(path, item)
|
self.restore_attrs(path, item)
|
||||||
elif stat.S_ISCHR(mode) or stat.S_ISBLK(mode):
|
elif stat.S_ISCHR(mode) or stat.S_ISBLK(mode):
|
||||||
make_parent(path)
|
make_parent(path)
|
||||||
|
with self.extract_helper(dest, item, path, stripped_components, original_path,
|
||||||
|
hardlink_masters) as hardlink_set:
|
||||||
|
if hardlink_set:
|
||||||
|
return
|
||||||
os.mknod(path, item.mode, item.rdev)
|
os.mknod(path, item.mode, item.rdev)
|
||||||
self.restore_attrs(path, item)
|
self.restore_attrs(path, item)
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Reference in New Issue