util.py revision 2689e3ddce70e8acc5bc231a80221980d5bdfec3
12689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward"""distutils.util
22689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
32689e3ddce70e8acc5bc231a80221980d5bdfec3Greg WardGeneral-purpose utility functions used throughout the Distutils
42689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward(especially in command classes).  Mostly filesystem manipulation, but
52689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Wardnot limited to that.  The functions in this module generally raise
62689e3ddce70e8acc5bc231a80221980d5bdfec3Greg WardDistutilsFileError when they have problems with the filesystem, because
72689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Wardos.error in pre-1.5.2 Python only gives the error message and not the
82689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Wardfile causing it."""
92689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
102689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward# created 1999/03/08, Greg Ward
112689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
122689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward__rcsid__ = "$Id$"
132689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
142689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Wardimport os
152689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Wardfrom distutils.errors import *
162689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
172689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
182689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward# I don't use os.makedirs because a) it's new to Python 1.5.2, and
192689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward# b) it blows up if the directory already exists (I want to silently
202689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward# succeed in that case).
212689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Warddef mkpath (name, mode=0777, verbose=0):
222689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    """Create a directory and any missing ancestor directories.  If the
232689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       directory already exists, return silently.  Raise
242689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       DistutilsFileError if unable to create some directory along the
252689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       way (eg. some sub-path exists, but is a file rather than a
262689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       directory).  If 'verbose' is true, print a one-line summary of
272689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       each mkdir to stdout."""
282689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
292689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    # XXX what's the better way to handle verbosity? print as we create
302689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    # each directory in the path (the current behaviour), or only announce
312689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    # the creation of the whole path, and force verbose=0 on all sub-calls?
322689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
332689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    if os.path.isdir (name):
342689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        return
352689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
362689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    (head, tail) = os.path.split (name)
372689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    tails = [tail]                      # stack of lone dirs to create
382689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
392689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    while head and tail and not os.path.isdir (head):
402689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        #print "splitting '%s': " % head,
412689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        (head, tail) = os.path.split (head)
422689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        #print "to ('%s','%s')" % (head, tail)
432689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        tails.insert (0, tail)          # push next higher dir onto stack
442689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
452689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    #print "stack of tails:", tails
462689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
472689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    # now 'head' contains the highest directory that already exists
482689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    for d in tails:
492689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        #print "head = %s, d = %s: " % (head, d),
502689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        head = os.path.join (head, d)
512689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        if verbose:
522689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward            print "creating", head
532689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        try:
542689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward            os.mkdir (head)
552689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        except os.error, (errno, errstr):
562689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward            raise DistutilsFileError, "%s: %s" % (head, errstr)
572689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
582689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward# mkpath ()
592689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
602689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
612689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Warddef newer (file1, file2):
622689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    """Return true if file1 exists and is more recently modified than
632689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       file2, or if file1 exists and file2 doesn't.  Return false if both
642689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       exist and file2 is the same age or younger than file1.  Raises
652689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       DistutilsFileError if file1 does not exist."""
662689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
672689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    if not os.path.exists (file1):
682689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        raise DistutilsFileError, "file '%s' does not exist" % file1
692689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    if not os.path.exists (file2):
702689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        return 1
712689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
722689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    from stat import *
732689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    mtime1 = os.stat(file1)[ST_MTIME]
742689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    mtime2 = os.stat(file2)[ST_MTIME]
752689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
762689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    return mtime1 > mtime2
772689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
782689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward# newer ()
792689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
802689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
812689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Warddef make_file (src, dst, func, args,
822689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward               verbose=0, update_message=None, noupdate_message=None):
832689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    """Makes 'dst' from 'src' (both filenames) by calling 'func' with
842689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       'args', but only if it needs to: i.e. if 'dst' does not exist or
852689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       'src' is newer than 'dst'."""
862689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
872689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    if newer (src, dst):
882689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        if verbose and update_message:
892689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward            print update_message
902689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        apply (func, args)
912689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    else:
922689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        if verbose and noupdate_message:
932689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward            print noupdate_message
942689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
952689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward# make_file ()
962689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
972689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
982689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Warddef _copy_file_contents (src, dst, buffer_size=16*1024):
992689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    """Copy the file 'src' to 'dst'; both must be filenames.  Any error
1002689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       opening either file, reading from 'src', or writing to 'dst',
1012689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       raises DistutilsFileError.  Data is read/written in chunks of
1022689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       'buffer_size' bytes (default 16k).  No attempt is made to handle
1032689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       anything apart from regular files."""
1042689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
1052689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    # Stolen from shutil module in the standard library, but with
1062689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    # custom error-handling added.
1072689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
1082689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    fsrc = None
1092689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    fdst = None
1102689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    try:
1112689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        try:
1122689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward            fsrc = open(src, 'rb')
1132689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        except os.error, (errno, errstr):
1142689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward            raise DistutilsFileError, "could not open %s: %s" % (src, errstr)
1152689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
1162689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        try:
1172689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward            fdst = open(dst, 'wb')
1182689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        except os.error, (errno, errstr):
1192689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward            raise DistutilsFileError, "could not create %s: %s" % (dst, errstr)
1202689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
1212689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        while 1:
1222689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward            try:
1232689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward                buf = fsrc.read (buffer_size)
1242689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward            except os.error, (errno, errstr):
1252689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward                raise DistutilsFileError, \
1262689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward                      "could not read from %s: %s" % (src, errstr)
1272689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
1282689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward            if not buf:
1292689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward                break
1302689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
1312689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward            try:
1322689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward                fdst.write(buf)
1332689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward            except os.error, (errno, errstr):
1342689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward                raise DistutilsFileError, \
1352689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward                      "could not write to %s: %s" % (dst, errstr)
1362689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
1372689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    finally:
1382689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        if fdst:
1392689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward            fdst.close()
1402689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        if fsrc:
1412689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward            fsrc.close()
1422689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
1432689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward# _copy_file_contents()
1442689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
1452689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
1462689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Warddef copy_file (src, dst,
1472689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward               preserve_mode=1,
1482689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward               preserve_times=1,
1492689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward               update=0,
1502689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward               verbose=0):
1512689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
1522689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    """Copy a file 'src' to 'dst'.  If 'dst' is a directory, then 'src'
1532689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       is copied there with the same name; otherwise, it must be a
1542689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       filename.  (If the file exists, it will be ruthlessly clobbered.)
1552689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       If 'preserve_mode' is true (the default), the file's mode (type
1562689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       and permission bits, or whatever is analogous on the current
1572689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       platform) is copied.  If 'preserve_times' is true (the default),
1582689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       the last-modified and last-access times are copied as well.  If
1592689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       'update' is true, 'src' will only be copied if 'dst' does not
1602689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       exist, or if 'dst' does exist but is older than 'src'.  If
1612689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       'verbose' is true, then a one-line summary of the copy will be
1622689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       printed to stdout."""
1632689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
1642689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    # XXX doesn't copy Mac-specific metadata
1652689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
1662689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    from shutil import copyfile
1672689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    from stat import *
1682689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
1692689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    if not os.path.isfile (src):
1702689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        raise DistutilsFileError, \
1712689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward              "can't copy %s:not a regular file" % src
1722689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
1732689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    if os.path.isdir (dst):
1742689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        dir = dst
1752689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        dst = os.path.join (dst, os.path.basename (src))
1762689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    else:
1772689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        dir = os.path.dirname (dst)
1782689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
1792689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    if update and not newer (src, dst):
1802689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        return
1812689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
1822689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    if verbose:
1832689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        print "copying %s -> %s" % (src, dir)
1842689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
1852689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    copyfile (src, dst)
1862689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    if preserve_mode or preserve_times:
1872689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        st = os.stat (src)
1882689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        if preserve_mode:
1892689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward            os.chmod (dst, S_IMODE (st[ST_MODE]))
1902689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        if preserve_times:
1912689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward            os.utime (dst, (st[ST_ATIME], st[ST_MTIME]))
1922689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
1932689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward# copy_file ()
1942689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
1952689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
1962689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Warddef copy_tree (src, dst,
1972689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward               preserve_mode=1,
1982689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward               preserve_times=1,
1992689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward               preserve_symlinks=0,
2002689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward               update=0,
2012689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward               verbose=0):
2022689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
2032689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    """Copy an entire directory tree 'src' to a new location 'dst'.  Both
2042689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       'src' and 'dst' must be directory names.  If 'src' is not a
2052689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       directory, raise DistutilsFileError.  If 'dst' does not exist, it
2062689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       is created with 'mkpath'.  The endresult of the copy is that
2072689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       every file in 'src' is copied to 'dst', and directories under
2082689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       'src' are recursively copied to 'dst'.
2092689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
2102689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       'preserve_mode' and 'preserve_times' are the same as for
2112689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       'copy_file'; note that they only apply to regular files, not to
2122689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       directories.  If 'preserve_symlinks' is true, symlinks will be
2132689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       copied as symlinks (on platforms that support them!); otherwise
2142689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       (the default), the destination of the symlink will be copied.
2152689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward       'update' and 'verbose' are the same as for 'copy_file'."""
2162689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
2172689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    if not os.path.isdir (src):
2182689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        raise DistutilsFileError, \
2192689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward              "cannot copy tree %s: not a directory" % src
2202689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    try:
2212689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        names = os.listdir (src)
2222689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    except os.error, (errno, errstr):
2232689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        raise DistutilsFileError, \
2242689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward              "error listing files in %s: %s" % (src, errstr)
2252689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
2262689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
2272689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    mkpath (dst, verbose=verbose)
2282689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
2292689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward    for n in names:
2302689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        src_name = os.path.join (src, n)
2312689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        dst_name = os.path.join (dst, n)
2322689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
2332689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        if preserve_symlinks and os.path.islink (src_name):
2342689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward            link_dest = os.readlink (src_name)
2352689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward            os.symlink (link_dest, dst_name)
2362689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        elif os.path.isdir (src_name):
2372689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward            copy_tree (src_name, dst_name,
2382689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward                       preserve_mode, preserve_times, preserve_symlinks,
2392689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward                       update, verbose)
2402689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward        else:
2412689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward            copy_file (src_name, dst_name,
2422689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward                       preserve_mode, preserve_times,
2432689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward                       update, verbose)
2442689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
2452689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward# copy_tree ()
246