@@ -727,6 +727,32 @@ def _filter(src, names):
727727 shutil .rmtree (src_dir )
728728 shutil .rmtree (os .path .dirname (dst_dir ))
729729
730+ def test_copytree_retains_permissions (self ):
731+ tmp_dir = tempfile .mkdtemp ()
732+ src_dir = os .path .join (tmp_dir , 'source' )
733+ os .mkdir (src_dir )
734+ dst_dir = os .path .join (tmp_dir , 'destination' )
735+ self .addCleanup (shutil .rmtree , tmp_dir )
736+
737+ os .chmod (src_dir , 0o777 )
738+ write_file ((src_dir , 'permissive.txt' ), '123' )
739+ os .chmod (os .path .join (src_dir , 'permissive.txt' ), 0o777 )
740+ write_file ((src_dir , 'restrictive.txt' ), '456' )
741+ os .chmod (os .path .join (src_dir , 'restrictive.txt' ), 0o600 )
742+ restrictive_subdir = tempfile .mkdtemp (dir = src_dir )
743+ os .chmod (restrictive_subdir , 0o600 )
744+
745+ shutil .copytree (src_dir , dst_dir )
746+ self .assertEquals (os .stat (src_dir ).st_mode , os .stat (dst_dir ).st_mode )
747+ self .assertEquals (os .stat (os .path .join (src_dir , 'permissive.txt' )).st_mode ,
748+ os .stat (os .path .join (dst_dir , 'permissive.txt' )).st_mode )
749+ self .assertEquals (os .stat (os .path .join (src_dir , 'restrictive.txt' )).st_mode ,
750+ os .stat (os .path .join (dst_dir , 'restrictive.txt' )).st_mode )
751+ restrictive_subdir_dst = os .path .join (dst_dir ,
752+ os .path .split (restrictive_subdir )[1 ])
753+ self .assertEquals (os .stat (restrictive_subdir ).st_mode ,
754+ os .stat (restrictive_subdir_dst ).st_mode )
755+
730756 @unittest .skipUnless (hasattr (os , 'link' ), 'requires os.link' )
731757 def test_dont_copy_file_onto_link_to_itself (self ):
732758 # Temporarily disable test on Windows.
0 commit comments