Compatibility with packing read-only source files

File permissions are no longer copied when packing. This means that
read-only source files can still be packed without errors, even when
they have to be rewritten (due to changed paths).

Reviewed by: sybren

Differential Revision: https://developer.blender.org/D13128
This commit is contained in:
Ethan Simon 2021-11-09 11:08:19 +01:00 committed by Sybren A. Stüvel
parent 2843cce6fd
commit 608a7bdac9
3 changed files with 39 additions and 5 deletions

View File

@ -206,7 +206,8 @@ class BlendFile:
self.log.debug("Copying %s to %s", self.filepath, path) self.log.debug("Copying %s to %s", self.filepath, path)
# TODO(Sybren): remove str() calls when targeting Python 3.6+ # TODO(Sybren): remove str() calls when targeting Python 3.6+
shutil.copy(str(self.filepath), str(path)) # dst needs to be a file and not a directory
shutil.copyfile(str(self.filepath), str(path))
self.fileobj = self._open_file(path, mode=mode) self.fileobj = self._open_file(path, mode=mode)
_cache(path, self) _cache(path, self)

View File

@ -152,12 +152,12 @@ class FileCopier(transfer.FileTransferer):
return True return True
def _move(self, srcpath: pathlib.Path, dstpath: pathlib.Path): def _move(self, srcpath: pathlib.Path, dstpath: pathlib.Path):
"""Low-level file move""" """Low-level file move."""
shutil.move(str(srcpath), str(dstpath)) shutil.move(str(srcpath), str(dstpath))
def _copy(self, srcpath: pathlib.Path, dstpath: pathlib.Path): def _copy(self, srcpath: pathlib.Path, dstpath: pathlib.Path):
"""Low-level file copy""" """Low-level file copy. dstpath needs to be a file and not a directory."""
shutil.copy2(str(srcpath), str(dstpath)) shutil.copyfile(str(srcpath), str(dstpath))
def move(self, srcpath: pathlib.Path, dstpath: pathlib.Path): def move(self, srcpath: pathlib.Path, dstpath: pathlib.Path):
s_stat = srcpath.stat() s_stat = srcpath.stat()

View File

@ -1,5 +1,5 @@
import logging import logging
import os import stat
import platform import platform
import shutil import shutil
import tempfile import tempfile
@ -218,6 +218,39 @@ class PackTest(AbstractPackTest):
packer.close() packer.close()
self.assertFalse(packer._rewrite_in.exists()) self.assertFalse(packer._rewrite_in.exists())
def test_execute_rewrite_readonly_files(self):
ppath = self.blendfiles / "subdir"
infile = ppath / "doubly_linked_up.blend"
# Make the input file read-only for everybody (owner, group, world).
orig_mode = infile.stat().st_mode
infile.chmod(stat.S_IREAD | stat.S_IRGRP | stat.S_IROTH)
try:
packer = pack.Packer(infile, ppath, self.tpath)
packer.strategise()
packer.execute()
finally:
# Restore the original file permissions.
infile.chmod(orig_mode)
if platform.system() == "Windows":
extpath = PurePosixPath(
"//_outside_project",
self.blendfiles.drive[0],
*self.blendfiles.parts[1:],
)
else:
extpath = PurePosixPath("//_outside_project", *self.blendfiles.parts[1:])
extbpath = bpathlib.BlendPath(extpath)
# Those libraries should be properly rewritten.
bfile = blendfile.open_cached(self.tpath / infile.name, assert_cached=False)
libs = sorted(bfile.code_index[b"LI"])
self.assertEqual(b"LILib", libs[0].id_name)
self.assertEqual(extbpath / b"linked_cube.blend", libs[0][b"name"])
self.assertEqual(b"LILib.002", libs[1].id_name)
self.assertEqual(extbpath / b"material_textures.blend", libs[1][b"name"])
@unittest.skipIf( @unittest.skipIf(
platform.system() == "Windows", platform.system() == "Windows",
"Symlinks on Windows require Administrator rights", "Symlinks on Windows require Administrator rights",