diff --git a/pungi/util.py b/pungi/util.py index 3a31ca87..b798d323 100644 --- a/pungi/util.py +++ b/pungi/util.py @@ -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) diff --git a/tests/test_util.py b/tests/test_util.py index 9e247cde..da240fef 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -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()