diff options
author | Greg Ward <gward@python.net> | 1999-09-13 03:09:38 (GMT) |
---|---|---|
committer | Greg Ward <gward@python.net> | 1999-09-13 03:09:38 (GMT) |
commit | 138ce653cc8ae53e500c480a9763ee92b9813439 (patch) | |
tree | d9c9d4c290aa03995232d82a0b94461c87d23279 /Lib | |
parent | 9b17cb58198365c9eac65a1823b7e72279caa332 (diff) | |
download | cpython-138ce653cc8ae53e500c480a9763ee92b9813439.zip cpython-138ce653cc8ae53e500c480a9763ee92b9813439.tar.gz cpython-138ce653cc8ae53e500c480a9763ee92b9813439.tar.bz2 |
Added 'newer_pairwise()' and 'newer_group()'.
Terminology change in 'newer()'.
Made 'copy_tree' respect dry_run flag a little better.
Added 'move_file()'.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/distutils/util.py | 149 |
1 files changed, 133 insertions, 16 deletions
diff --git a/Lib/distutils/util.py b/Lib/distutils/util.py index 9a299df..bb790af 100644 --- a/Lib/distutils/util.py +++ b/Lib/distutils/util.py @@ -62,26 +62,75 @@ def mkpath (name, mode=0777, verbose=0, dry_run=0): # mkpath () -def newer (file1, file2): - """Return true if file1 exists and is more recently modified than - file2, or if file1 exists and file2 doesn't. Return false if both - exist and file2 is the same age or younger than file1. Raises - DistutilsFileError if file1 does not exist.""" - - if not os.path.exists (file1): - raise DistutilsFileError, "file '%s' does not exist" % file1 - if not os.path.exists (file2): +def newer (source, target): + """Return true if 'source' exists and is more recently modified than + 'target', or if 'source' exists and 'target' doesn't. Return + false if both exist and 'target' is the same age or younger than + 'source'. Raise DistutilsFileError if 'source' does not + exist.""" + + if not os.path.exists (source): + raise DistutilsFileError, "file '%s' does not exist" % source + if not os.path.exists (target): return 1 - from stat import * - mtime1 = os.stat(file1)[ST_MTIME] - mtime2 = os.stat(file2)[ST_MTIME] + from stat import ST_MTIME + mtime1 = os.stat(source)[ST_MTIME] + mtime2 = os.stat(target)[ST_MTIME] return mtime1 > mtime2 # newer () +def newer_pairwise (sources, targets): + + """Walk two filename lists in parallel, testing if each 'target' is + up-to-date relative to its corresponding 'source'. If so, both + are deleted from their respective lists. Return a list of tuples + containing the deleted (source,target) pairs.""" + + if len (sources) != len (targets): + raise ValueError, "'sources' and 'targets' must be same length" + + goners = [] + for i in range (len (sources)-1, -1, -1): + if not newer (sources[i], targets[i]): + goners.append ((sources[i], targets[i])) + del sources[i] + del targets[i] + goners.reverse() + return goners + +# newer_pairwise () + + +def newer_group (sources, target): + """Return true if 'target' is out-of-date with respect to any + file listed in 'sources'. In other words, if 'target' exists and + is newer than every file in 'sources', return false; otherwise + return true.""" + + # If the target doesn't even exist, then it's definitely out-of-date. + if not os.path.exists (target): + return 1 + + # Otherwise we have to find out the hard way: if *any* source file + # is more recent than 'target', then 'target' is out-of-date and + # we can immediately return true. If we fall through to the end + # of the loop, then 'target' is up-to-date and we return false. + from stat import ST_MTIME + target_mtime = os.stat (target)[ST_MTIME] + for source in sources: + source_mtime = os.stat(source)[ST_MTIME] + if source_mtime > target_mtime: + return 1 + else: + return 0 + +# newer_group () + + def make_file (src, dst, func, args, verbose=0, update_message=None, noupdate_message=None): """Makes 'dst' from 'src' (both filenames) by calling 'func' with @@ -176,7 +225,7 @@ def copy_file (src, dst, if not os.path.isfile (src): raise DistutilsFileError, \ - "can't copy %s:not a regular file" % src + "can't copy %s: not a regular file" % src if os.path.isdir (dst): dir = dst @@ -237,14 +286,17 @@ def copy_tree (src, dst, (the default), the destination of the symlink will be copied. 'update' and 'verbose' are the same as for 'copy_file'.""" - if not os.path.isdir (src): + if not dry_run and not os.path.isdir (src): raise DistutilsFileError, \ "cannot copy tree %s: not a directory" % src try: names = os.listdir (src) except os.error, (errno, errstr): - raise DistutilsFileError, \ - "error listing files in %s: %s" % (src, errstr) + if dry_run: + names = [] + else: + raise DistutilsFileError, \ + "error listing files in %s: %s" % (src, errstr) if not dry_run: mkpath (dst, verbose=verbose) @@ -277,3 +329,68 @@ def copy_tree (src, dst, return outputs # copy_tree () + + +# XXX I suspect this is Unix-specific -- need porting help! +def move_file (src, dst, + verbose=0, + dry_run=0): + + """Move a file 'src' to 'dst'. If 'dst' is a directory, the file + will be moved into it with the same name; otherwise, 'src' is + just renamed to 'dst'. Return the new full name of the file. + + Handles cross-device moves on Unix using + 'copy_file()'. What about other systems???""" + + from os.path import exists, isfile, isdir, basename, dirname + + if verbose: + print "moving %s -> %s" % (src, dst) + + if dry_run: + return dst + + if not isfile (src): + raise DistutilsFileError, \ + "can't move '%s': not a regular file" % src + + if isdir (dst): + dst = os.path.join (dst, basename (src)) + elif exists (dst): + raise DistutilsFileError, \ + "can't move '%s': destination '%s' already exists" % \ + (src, dst) + + if not isdir (dirname (dst)): + raise DistutilsFileError, \ + "can't move '%s': destination '%s' not a valid path" % \ + (src, dst) + + copy_it = 0 + try: + os.rename (src, dst) + except os.error, (num, msg): + if num == errno.EXDEV: + copy_it = 1 + else: + raise DistutilsFileError, \ + "couldn't move '%s' to '%s': %s" % (src, dst, msg) + + if copy_it: + copy_file (src, dst) + try: + os.unlink (src) + except os.error, (num, msg): + try: + os.unlink (dst) + except os.error: + pass + raise DistutilsFileError, \ + ("couldn't move '%s' to '%s' by copy/delete: " + + "delete '%s' failed: %s") % \ + (src, dst, src, msg) + + return dst + +# move_file () |