summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Ward <gward@python.net>1999-09-13 03:09:38 (GMT)
committerGreg Ward <gward@python.net>1999-09-13 03:09:38 (GMT)
commit138ce653cc8ae53e500c480a9763ee92b9813439 (patch)
treed9c9d4c290aa03995232d82a0b94461c87d23279
parent9b17cb58198365c9eac65a1823b7e72279caa332 (diff)
downloadcpython-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()'.
-rw-r--r--Lib/distutils/util.py149
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 ()