mirror of
https://github.com/borgbackup/borg.git
synced 2025-01-04 06:21:46 +00:00
fuse: fix hardlinks in versions view, fixes #1599
This commit is contained in:
parent
c021cf466a
commit
39170479aa
1 changed files with 21 additions and 4 deletions
|
@ -15,7 +15,7 @@
|
|||
logger = create_logger()
|
||||
|
||||
from .archive import Archive
|
||||
from .helpers import daemonize, safe_encode
|
||||
from .helpers import daemonize
|
||||
from .item import Item
|
||||
from .lrucache import LRUCache
|
||||
|
||||
|
@ -136,6 +136,7 @@ def _create_dir(self, parent):
|
|||
def process_archive(self, archive, prefix=[]):
|
||||
"""Build fuse inode hierarchy from archive metadata
|
||||
"""
|
||||
self.file_versions = {} # for versions mode: original path -> version
|
||||
unpacker = msgpack.Unpacker()
|
||||
for key, chunk in zip(archive.metadata.items, self.repository.get_many(archive.metadata.items)):
|
||||
_, data = self.key.decrypt(key, chunk)
|
||||
|
@ -155,7 +156,6 @@ def process_archive(self, archive, prefix=[]):
|
|||
self.items[inode] = item
|
||||
continue
|
||||
segments = prefix + os.fsencode(os.path.normpath(item.path)).split(b'/')
|
||||
del item.path
|
||||
parent = 1
|
||||
for segment in segments[:-1]:
|
||||
parent = self.process_inner(segment, parent)
|
||||
|
@ -169,14 +169,31 @@ def file_version(item):
|
|||
ident = adler32(chunkid, ident)
|
||||
return ident
|
||||
|
||||
def make_versioned_name(name, version, add_dir=False):
|
||||
if add_dir:
|
||||
# add intermediate directory with same name as filename
|
||||
path_fname = name.rsplit(b'/', 1)
|
||||
name += b'/' + path_fname[-1]
|
||||
return name + os.fsencode('.%08x' % version)
|
||||
|
||||
if self.versions and not is_dir:
|
||||
parent = self.process_inner(name, parent)
|
||||
version = file_version(item)
|
||||
if version is not None:
|
||||
name += safe_encode('.%08x' % version)
|
||||
# regular file, with contents - maybe a hardlink master
|
||||
name = make_versioned_name(name, version)
|
||||
self.file_versions[item.path] = version
|
||||
|
||||
del item.path # safe some space
|
||||
if 'source' in item and stat.S_ISREG(item.mode):
|
||||
inode = self._find_inode(item.source, prefix)
|
||||
# a hardlink, no contents, <source> is the hardlink master
|
||||
source = item.source
|
||||
if self.versions:
|
||||
# adjust source name with version
|
||||
version = self.file_versions[source]
|
||||
source = os.fsdecode(make_versioned_name(os.fsencode(source), version, add_dir=True))
|
||||
name = make_versioned_name(name, version)
|
||||
inode = self._find_inode(source, prefix)
|
||||
item = self.cache.get(inode)
|
||||
item.nlink = item.get('nlink', 1) + 1
|
||||
self.items[inode] = item
|
||||
|
|
Loading…
Reference in a new issue