]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-38523: ignore_dangling_symlinks does not apply recursively (GH-22937)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Mon, 7 Nov 2022 12:11:11 +0000 (04:11 -0800)
committerGitHub <noreply@github.com>
Mon, 7 Nov 2022 12:11:11 +0000 (04:11 -0800)
(cherry picked from commit 5ff81da6d3a8eb01fc5500fd1c9eaa6543286301)

Co-authored-by: Zackery Spytz <zspytz@gmail.com>
Lib/shutil.py
Lib/test/test_shutil.py
Misc/NEWS.d/next/Library/2020-10-23-22-20-52.bpo-38523.CrkxLh.rst [new file with mode: 0644]

index 6093e11374294ad2e9c3875823772cc2c0799d5c..bfed796d51b1d0975a6e7b8510f9736c6ee2a12d 100644 (file)
@@ -489,12 +489,13 @@ def _copytree(entries, src, dst, symlinks, ignore, copy_function,
                     # otherwise let the copy occur. copy2 will raise an error
                     if srcentry.is_dir():
                         copytree(srcobj, dstname, symlinks, ignore,
-                                 copy_function, dirs_exist_ok=dirs_exist_ok)
+                                 copy_function, ignore_dangling_symlinks,
+                                 dirs_exist_ok)
                     else:
                         copy_function(srcobj, dstname)
             elif srcentry.is_dir():
                 copytree(srcobj, dstname, symlinks, ignore, copy_function,
-                         dirs_exist_ok=dirs_exist_ok)
+                         ignore_dangling_symlinks, dirs_exist_ok)
             else:
                 # Will raise a SpecialFileError for unsupported file types
                 copy_function(srcobj, dstname)
index a2c4ab508195b34f3ab38098d38aadfe4e9cc3ae..055c9af2cc50921ce7d58b66a66a20ef206d050c 100644 (file)
@@ -752,18 +752,25 @@ class TestCopyTree(BaseTest, unittest.TestCase):
 
     @os_helper.skip_unless_symlink
     def test_copytree_dangling_symlinks(self):
-        # a dangling symlink raises an error at the end
         src_dir = self.mkdtemp()
+        valid_file = os.path.join(src_dir, 'test.txt')
+        write_file(valid_file, 'abc')
+        dir_a = os.path.join(src_dir, 'dir_a')
+        os.mkdir(dir_a)
+        for d in src_dir, dir_a:
+            os.symlink('IDONTEXIST', os.path.join(d, 'broken'))
+            os.symlink(valid_file, os.path.join(d, 'valid'))
+
+        # A dangling symlink should raise an error.
         dst_dir = os.path.join(self.mkdtemp(), 'destination')
-        os.symlink('IDONTEXIST', os.path.join(src_dir, 'test.txt'))
-        os.mkdir(os.path.join(src_dir, 'test_dir'))
-        write_file((src_dir, 'test_dir', 'test.txt'), '456')
         self.assertRaises(Error, shutil.copytree, src_dir, dst_dir)
 
-        # a dangling symlink is ignored with the proper flag
+        # Dangling symlinks should be ignored with the proper flag.
         dst_dir = os.path.join(self.mkdtemp(), 'destination2')
         shutil.copytree(src_dir, dst_dir, ignore_dangling_symlinks=True)
-        self.assertNotIn('test.txt', os.listdir(dst_dir))
+        for root, dirs, files in os.walk(dst_dir):
+            self.assertNotIn('broken', files)
+            self.assertIn('valid', files)
 
         # a dangling symlink is copied if symlinks=True
         dst_dir = os.path.join(self.mkdtemp(), 'destination3')
diff --git a/Misc/NEWS.d/next/Library/2020-10-23-22-20-52.bpo-38523.CrkxLh.rst b/Misc/NEWS.d/next/Library/2020-10-23-22-20-52.bpo-38523.CrkxLh.rst
new file mode 100644 (file)
index 0000000..3810e29
--- /dev/null
@@ -0,0 +1,2 @@
+:func:`shutil.copytree` now applies the *ignore_dangling_symlinks* argument
+recursively.