205 |
205 |
206 |
206 |
207 destDir = destination.Dir() |
207 destDir = destination.Dir() |
208 if not destDir.isDir(): |
208 if not destDir.isDir(): |
209 os.makedirs(str(destDir)) |
209 os.makedirs(str(destDir)) |
210 shutil.copyfile(source_str, dest_str) |
210 # preserve permissions |
|
211 shutil.copy(source_str, dest_str) |
211 return |
212 return |
212 # Destination file exists so we have to think about updating it |
213 # Destination file exists so we have to think about updating it |
213 sourceMTime = 0 |
214 sourceMTime = 0 |
214 destMTime = 0 |
215 destMTime = 0 |
215 sourceStat = 0 |
216 sourceStat = 0 |
223 destMTime = os.stat(dest_str)[stat.ST_MTIME] |
224 destMTime = os.stat(dest_str)[stat.ST_MTIME] |
224 except OSError, e: |
225 except OSError, e: |
225 pass # destination doesn't have to exist |
226 pass # destination doesn't have to exist |
226 |
227 |
227 if destMTime == 0 or destMTime < sourceMTime: |
228 if destMTime == 0 or destMTime < sourceMTime: |
|
229 # remove old version |
|
230 # - not having ownership prevents chmod |
|
231 # - avoid clobbering the original if it is a hard link |
228 if os.path.exists(dest_str): |
232 if os.path.exists(dest_str): |
229 os.chmod(dest_str,stat.S_IREAD | stat.S_IWRITE) |
233 os.unlink(dest_str) |
230 shutil.copyfile(source_str, dest_str) |
234 # preserve permissions |
231 |
235 shutil.copy(source_str, dest_str) |
232 # Ensure that the destination file remains executable if the source was also: |
|
233 os.chmod(dest_str,sourceStat[stat.ST_MODE] | stat.S_IREAD | stat.S_IWRITE | stat.S_IWGRP ) |
|
234 |
|
235 |
236 |
236 except Exception,e: |
237 except Exception,e: |
237 message = "Could not update " + dest_str + " from " + source_str + " : " + str(e) |
238 message = "Could not update " + dest_str + " from " + source_str + " : " + str(e) |
238 raise IOError(message) |
239 raise IOError(message) |
239 |
240 |
240 return |
241 return |
|
242 |
|
243 |
|
244 |
|
245 ## Commandline processing utilities ## |
|
246 |
|
247 fullCommandOption = "--command" |
|
248 miniCommandOption = "--co" # update this if another "co" option is added |
|
249 |
|
250 def read_command_file(filename, used): |
|
251 """Read commandline options in from a file""" |
|
252 if filename in used: |
|
253 raise IOError("command file '%s' refers to itself" % filename) |
|
254 |
|
255 args = [] |
|
256 try: |
|
257 file = open(filename, "r") |
|
258 for line in file.readlines(): |
|
259 args.extend(line.split()) |
|
260 file.close() |
|
261 except: |
|
262 raise IOError("couldn't read command file '%s'" % filename) |
|
263 |
|
264 # expand any command files in the options we just read. |
|
265 # making sure we don't get stuck in a loop. |
|
266 usedPlusThis = used[:] |
|
267 usedPlusThis.append(filename) |
|
268 return expand_command_options(args, usedPlusThis) |
|
269 |
|
270 def expand_command_options(args, files = []): |
|
271 """process commandline options to recursively expand command files (--command options) into a full list of options.""" |
|
272 expanded = [] |
|
273 previousWasOpt = False |
|
274 |
|
275 for a in args: |
|
276 if previousWasOpt: # then this one is the filename |
|
277 expanded.extend(read_command_file(a, files)) |
|
278 previousWasOpt = False |
|
279 continue |
|
280 |
|
281 if a.startswith(miniCommandOption): |
|
282 if "=" in a: # then this is opt=filename |
|
283 opt = a.split("=") |
|
284 if fullCommandOption.startswith(opt[0]): |
|
285 expanded.extend(read_command_file(opt[1], files)) |
|
286 continue |
|
287 else: # the next one is the filename |
|
288 if fullCommandOption.startswith(a): |
|
289 previousWasOpt = True |
|
290 continue |
|
291 |
|
292 expanded.append(a) # an ordinary arg, nothing to do with command files |
|
293 |
|
294 return expanded |