Improved path handling
This commit fixes a bunch of issues at the same time, as they are all related to path handling: - `pathlib.Path.resolve()` or `.absolute()` are replaced by `bpathlib.make_absolute()`. The latter does NOT follow symlinks and does NOT network mounts from a drive letter to UNC notation. This also has advantages on non-Windows sytems, as it allows BAT-packing a directory structure with symlinked files (such as a Shaman checkout). - Better handling of drive letters, and of paths that cross drive boundaries. - Better testing of Windows-specific cases when running the tests on Windows, and of POSIX-specific cases on other platforms. Thanks to @wisaac for starting this patch in D6676. Thanks to @jbakker for pointing out the drive letter issue. This fixes T70655.
This commit is contained in:
@@ -82,7 +82,7 @@ class BlockIterator:
|
||||
yield from self._visit_linked_blocks(blocks_per_lib)
|
||||
|
||||
def _visit_blocks(self, bfile, limit_to):
|
||||
bpath = bfile.filepath.absolute().resolve()
|
||||
bpath = bpathlib.make_absolute(bfile.filepath)
|
||||
root_dir = bpathlib.BlendPath(bpath.parent)
|
||||
|
||||
# Mapping from library path to data blocks to expand.
|
||||
@@ -123,10 +123,10 @@ class BlockIterator:
|
||||
# We've gone through all the blocks in this file, now open the libraries
|
||||
# and iterate over the blocks referred there.
|
||||
for lib_bpath, idblocks in blocks_per_lib.items():
|
||||
lib_path = pathlib.Path(lib_bpath.to_path())
|
||||
try:
|
||||
lib_path = lib_path.resolve()
|
||||
except FileNotFoundError:
|
||||
lib_path = bpathlib.make_absolute(lib_bpath.to_path())
|
||||
|
||||
assert lib_path.exists()
|
||||
if not lib_path.exists():
|
||||
log.warning('Library %s does not exist', lib_path)
|
||||
continue
|
||||
|
||||
|
||||
@@ -107,8 +107,8 @@ class BlockUsage:
|
||||
def __repr__(self):
|
||||
if self.path_full_field is None:
|
||||
field_name = self.path_dir_field.name.name_full.decode() + \
|
||||
'/' + \
|
||||
self.path_base_field.name.name_full.decode()
|
||||
'/' + \
|
||||
self.path_base_field.name.name_full.decode()
|
||||
else:
|
||||
field_name = self.path_full_field.name.name_full.decode()
|
||||
return '<BlockUsage name=%r type=%r field=%r asset=%r%s>' % (
|
||||
@@ -141,20 +141,19 @@ class BlockUsage:
|
||||
log.warning('Path %s does not exist for %s', path, self)
|
||||
|
||||
def __fspath__(self) -> pathlib.Path:
|
||||
"""Determine the absolute path of the asset on the filesystem.
|
||||
|
||||
The path is resolved (see pathlib.Path.resolve()) if it exists on the
|
||||
filesystem.
|
||||
"""
|
||||
"""Determine the absolute path of the asset on the filesystem."""
|
||||
if self._abspath is None:
|
||||
bpath = self.block.bfile.abspath(self.asset_path)
|
||||
log.info('Resolved %s rel to %s -> %s',
|
||||
self.asset_path, self.block.bfile.filepath, bpath)
|
||||
|
||||
as_path = pathlib.Path(bpath.to_path())
|
||||
|
||||
# Windows cannot resolve() a path that has a glob pattern in it.
|
||||
# Windows cannot make a path that has a glob pattern in it absolute.
|
||||
# Since globs are generally only on the filename part, we take that off,
|
||||
# resolve() the parent directory, then put the filename back.
|
||||
# make the parent directory absolute, then put the filename back.
|
||||
try:
|
||||
abs_parent = as_path.parent.resolve()
|
||||
abs_parent = bpathlib.make_absolute(as_path.parent)
|
||||
except FileNotFoundError:
|
||||
self._abspath = as_path
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user