@@ -59,41 +59,50 @@ def ValidateArgs(args):
5959
6060
6161def CopyTree (src , dst , ignore = None ):
62- names = os .listdir (src )
63- if ignore is not None :
64- ignored_names = ignore (src , names )
65- else :
66- ignored_names = set ()
62+ # Recusive helper method to collect errors but keep processing.
63+ def copy_tree (src , dst , ignore , errors ):
64+ names = os .listdir (src )
65+ if ignore is not None :
66+ ignored_names = ignore (src , names )
67+ else :
68+ ignored_names = set ()
69+
70+ if not os .path .exists (dst ):
71+ os .makedirs (dst )
72+ for name in names :
73+ if name in ignored_names :
74+ continue
75+ srcname = os .path .join (src , name )
76+ dstname = os .path .join (dst , name )
77+ try :
78+ if os .path .isdir (srcname ):
79+ copy_tree (srcname , dstname , ignore , errors )
80+ else :
81+ shutil .copy (srcname , dstname )
82+ except (IOError , os .error ) as why :
83+ errors .append ((srcname , dstname , str (why )))
84+ try :
85+ shutil .copystat (src , dst )
86+ except WindowsError :
87+ # Can't copy file access times on Windows.
88+ pass
89+ except OSError as why :
90+ errors .append ((src , dst , str (why )))
91+
92+ # Format errors from file copies.
93+ def format_error (error ):
94+ if len (error ) == 1 :
95+ return "Error: {msg}" .format (msg = str (error [0 ]))
96+ return "From: {src}\n To: {dst}\n {msg}" \
97+ .format (src = error [0 ], dst = error [1 ], msg = error [2 ])
6798
68- if not os .path .exists (dst ):
69- os .makedirs (dst )
7099 errors = []
71- for name in names :
72- if name in ignored_names :
73- continue
74- srcname = os .path .join (src , name )
75- dstname = os .path .join (dst , name )
76- try :
77- if os .path .isdir (srcname ):
78- CopyTree (srcname , dstname , ignore )
79- else :
80- shutil .copy (srcname , dstname )
81- except (IOError , os .error ) as why :
82- errors .append ((srcname , dstname , str (why )))
83- # catch the Error from the recursive CopyTree so that we can
84- # continue with other files
85- except Exception as err :
86- errors .extend (err .args [0 ])
87- try :
88- shutil .copystat (src , dst )
89- except WindowsError :
90- # can't copy file access times on Windows
91- pass
92- except OSError as why :
93- errors .extend ((src , dst , str (why )))
100+ copy_tree (src ,dst ,ignore , errors )
94101 if errors :
95- raise Error (errors )
96-
102+ failures = "\n \n " .join (format_error (error ) for error in errors )
103+ parts = ("Some file copies failed:" , "=" * 78 , failures )
104+ msg = '\n ' .join (parts )
105+ raise RuntimeError (msg )
97106
98107def ListTree (src , ignore = None ):
99108 names = os .listdir (src )
0 commit comments