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:
@@ -230,13 +230,13 @@ class Packer:
|
||||
|
||||
# The blendfile that we pack is generally not its own dependency, so
|
||||
# we have to explicitly add it to the _packed_paths.
|
||||
bfile_path = self.blendfile.absolute()
|
||||
bfile_path = bpathlib.make_absolute(self.blendfile)
|
||||
|
||||
# Both paths have to be resolved first, because this also translates
|
||||
# network shares mapped to Windows drive letters back to their UNC
|
||||
# notation. Only resolving one but not the other (which can happen
|
||||
# with the abosolute() call above) can cause errors.
|
||||
bfile_pp = self._target_path / bfile_path.resolve().relative_to(self.project.resolve())
|
||||
bfile_pp = self._target_path / bfile_path.relative_to(bpathlib.make_absolute(self.project))
|
||||
self._output_path = bfile_pp
|
||||
|
||||
self._progress_cb.pack_start()
|
||||
@@ -330,15 +330,8 @@ class Packer:
|
||||
act = self._actions[path]
|
||||
assert isinstance(act, AssetAction)
|
||||
|
||||
# Remove the base of the path, effectively removing the 'absoluteness'.
|
||||
# On POSIX this turns '/path/file.txt' into 'path/file.txt'.
|
||||
# On Windows this turns 'X:/path/file.txt' into 'X/path/file.txt'.
|
||||
if path.drive:
|
||||
path_parts = (path.drive[0], *path.parts[1:])
|
||||
else:
|
||||
path_parts = path.parts[1:]
|
||||
|
||||
act.new_path = pathlib.Path(self._target_path, '_outside_project', *path_parts)
|
||||
relpath = bpathlib.strip_root(path)
|
||||
act.new_path = pathlib.Path(self._target_path, '_outside_project', relpath)
|
||||
|
||||
def _group_rewrites(self) -> None:
|
||||
"""For each blend file, collect which fields need rewriting.
|
||||
@@ -358,7 +351,7 @@ class Packer:
|
||||
continue
|
||||
|
||||
for usage in action.usages:
|
||||
bfile_path = usage.block.bfile.filepath.absolute().resolve()
|
||||
bfile_path = bpathlib.make_absolute(usage.block.bfile.filepath)
|
||||
insert_new_action = bfile_path not in self._actions
|
||||
|
||||
self._actions[bfile_path].rewrites.append(usage)
|
||||
@@ -367,10 +360,10 @@ class Packer:
|
||||
actions.add(self._actions[bfile_path])
|
||||
|
||||
def _path_in_project(self, path: pathlib.Path) -> bool:
|
||||
abs_path = bpathlib.make_absolute(path)
|
||||
abs_project = bpathlib.make_absolute(self.project)
|
||||
try:
|
||||
# MUST use resolve(), otherwise /path/to/proj/../../asset.png
|
||||
# will return True (relative_to will return ../../asset.png).
|
||||
path.resolve().relative_to(self.project)
|
||||
abs_path.relative_to(abs_project)
|
||||
except ValueError:
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -26,6 +26,7 @@ import typing
|
||||
import requests
|
||||
|
||||
import blender_asset_tracer.pack.transfer as bat_transfer
|
||||
from blender_asset_tracer import bpathlib
|
||||
|
||||
MAX_DEFERRED_PATHS = 8
|
||||
MAX_FAILED_PATHS = 8
|
||||
@@ -83,6 +84,9 @@ class ShamanTransferrer(bat_transfer.FileTransferer):
|
||||
self.log.info('Created checkout definition file of %d KiB',
|
||||
len(definition_file) // 1024)
|
||||
self.log.info('Feeding %d files to the Shaman', len(self._file_info))
|
||||
if self.log.isEnabledFor(logging.INFO):
|
||||
for path in self._file_info:
|
||||
self.log.info(' - %s', path)
|
||||
|
||||
# Try to upload all the files.
|
||||
failed_paths = set() # type: typing.Set[str]
|
||||
@@ -151,7 +155,7 @@ class ShamanTransferrer(bat_transfer.FileTransferer):
|
||||
checksum = cache.compute_cached_checksum(src)
|
||||
filesize = src.stat().st_size
|
||||
# relpath = dst.relative_to(self.project_root)
|
||||
relpath = str(dst)[1:]
|
||||
relpath = bpathlib.strip_root(dst).as_posix()
|
||||
|
||||
self._file_info[relpath] = FileInfo(
|
||||
checksum=checksum,
|
||||
|
||||
Reference in New Issue
Block a user