util: Preserve symlinks when copying

Currently the `copy_all` function resolves all symlinks and crashes on
broken symlinks. Instead it should copy symlinks as symlinks.

Fixes: https://pagure.io/pungi/issue/1084
Signed-off-by: Lubomír Sedlář <lsedlar@redhat.com>
This commit is contained in:
Lubomír Sedlář 2018-11-15 09:09:12 +01:00
parent 8e88373a82
commit 1d020dbedd
2 changed files with 32 additions and 1 deletions

View File

@ -564,7 +564,11 @@ def copy_all(src, dest):
if os.path.isdir(source):
shutil.copytree(source, destination)
else:
shutil.copy2(source, destination)
if os.path.islink(source):
# It's a symlink, we should preserve it instead of resolving.
os.symlink(os.readlink(source), destination)
else:
shutil.copy2(source, destination)
return recursive_file_list(src)

View File

@ -753,5 +753,32 @@ class TestParseKojiEvent(PungiTestCase):
util.parse_koji_event(self.topdir)
class TestCopyAll(PungiTestCase):
def setUp(self):
super(TestCopyAll, self).setUp()
self.src = os.path.join(self.topdir, "src")
self.dst = os.path.join(self.topdir, "dst")
util.makedirs(self.src)
def test_preserve_symlink(self):
touch(os.path.join(self.src, "target"))
os.symlink("target", os.path.join(self.src, "symlink"))
util.copy_all(self.src, self.dst)
self.assertTrue(os.path.isfile(os.path.join(self.dst, "target")))
self.assertTrue(os.path.islink(os.path.join(self.dst, "symlink")))
self.assertEqual(os.readlink(os.path.join(self.dst, "symlink")), "target")
def test_copy_broken_symlink(self):
os.symlink("broken", os.path.join(self.src, "symlink"))
util.copy_all(self.src, self.dst)
self.assertTrue(os.path.islink(os.path.join(self.dst, "symlink")))
self.assertEqual(os.readlink(os.path.join(self.dst, "symlink")), "broken")
if __name__ == "__main__":
unittest.main()