symbian-qemu-0.9.1-12/python-2.6.1/Lib/distutils/dir_util.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 """distutils.dir_util
       
     2 
       
     3 Utility functions for manipulating directories and directory trees."""
       
     4 
       
     5 # This module should be kept compatible with Python 2.1.
       
     6 
       
     7 __revision__ = "$Id: dir_util.py 60923 2008-02-21 18:18:37Z guido.van.rossum $"
       
     8 
       
     9 import os, sys
       
    10 from types import *
       
    11 from distutils.errors import DistutilsFileError, DistutilsInternalError
       
    12 from distutils import log
       
    13 
       
    14 # cache for by mkpath() -- in addition to cheapening redundant calls,
       
    15 # eliminates redundant "creating /foo/bar/baz" messages in dry-run mode
       
    16 _path_created = {}
       
    17 
       
    18 # I don't use os.makedirs because a) it's new to Python 1.5.2, and
       
    19 # b) it blows up if the directory already exists (I want to silently
       
    20 # succeed in that case).
       
    21 def mkpath (name, mode=0777, verbose=0, dry_run=0):
       
    22     """Create a directory and any missing ancestor directories.  If the
       
    23        directory already exists (or if 'name' is the empty string, which
       
    24        means the current directory, which of course exists), then do
       
    25        nothing.  Raise DistutilsFileError if unable to create some
       
    26        directory along the way (eg. some sub-path exists, but is a file
       
    27        rather than a directory).  If 'verbose' is true, print a one-line
       
    28        summary of each mkdir to stdout.  Return the list of directories
       
    29        actually created."""
       
    30 
       
    31     global _path_created
       
    32 
       
    33     # Detect a common bug -- name is None
       
    34     if not isinstance(name, StringTypes):
       
    35         raise DistutilsInternalError, \
       
    36               "mkpath: 'name' must be a string (got %r)" % (name,)
       
    37 
       
    38     # XXX what's the better way to handle verbosity? print as we create
       
    39     # each directory in the path (the current behaviour), or only announce
       
    40     # the creation of the whole path? (quite easy to do the latter since
       
    41     # we're not using a recursive algorithm)
       
    42 
       
    43     name = os.path.normpath(name)
       
    44     created_dirs = []
       
    45     if os.path.isdir(name) or name == '':
       
    46         return created_dirs
       
    47     if _path_created.get(os.path.abspath(name)):
       
    48         return created_dirs
       
    49 
       
    50     (head, tail) = os.path.split(name)
       
    51     tails = [tail]                      # stack of lone dirs to create
       
    52 
       
    53     while head and tail and not os.path.isdir(head):
       
    54         #print "splitting '%s': " % head,
       
    55         (head, tail) = os.path.split(head)
       
    56         #print "to ('%s','%s')" % (head, tail)
       
    57         tails.insert(0, tail)          # push next higher dir onto stack
       
    58 
       
    59     #print "stack of tails:", tails
       
    60 
       
    61     # now 'head' contains the deepest directory that already exists
       
    62     # (that is, the child of 'head' in 'name' is the highest directory
       
    63     # that does *not* exist)
       
    64     for d in tails:
       
    65         #print "head = %s, d = %s: " % (head, d),
       
    66         head = os.path.join(head, d)
       
    67         abs_head = os.path.abspath(head)
       
    68 
       
    69         if _path_created.get(abs_head):
       
    70             continue
       
    71 
       
    72         log.info("creating %s", head)
       
    73 
       
    74         if not dry_run:
       
    75             try:
       
    76                 os.mkdir(head)
       
    77                 created_dirs.append(head)
       
    78             except OSError, exc:
       
    79                 raise DistutilsFileError, \
       
    80                       "could not create '%s': %s" % (head, exc[-1])
       
    81 
       
    82         _path_created[abs_head] = 1
       
    83     return created_dirs
       
    84 
       
    85 # mkpath ()
       
    86 
       
    87 
       
    88 def create_tree (base_dir, files, mode=0777, verbose=0, dry_run=0):
       
    89 
       
    90     """Create all the empty directories under 'base_dir' needed to
       
    91        put 'files' there.  'base_dir' is just the a name of a directory
       
    92        which doesn't necessarily exist yet; 'files' is a list of filenames
       
    93        to be interpreted relative to 'base_dir'.  'base_dir' + the
       
    94        directory portion of every file in 'files' will be created if it
       
    95        doesn't already exist.  'mode', 'verbose' and 'dry_run' flags are as
       
    96        for 'mkpath()'."""
       
    97 
       
    98     # First get the list of directories to create
       
    99     need_dir = {}
       
   100     for file in files:
       
   101         need_dir[os.path.join(base_dir, os.path.dirname(file))] = 1
       
   102     need_dirs = need_dir.keys()
       
   103     need_dirs.sort()
       
   104 
       
   105     # Now create them
       
   106     for dir in need_dirs:
       
   107         mkpath(dir, mode, dry_run=dry_run)
       
   108 
       
   109 # create_tree ()
       
   110 
       
   111 
       
   112 def copy_tree (src, dst,
       
   113                preserve_mode=1,
       
   114                preserve_times=1,
       
   115                preserve_symlinks=0,
       
   116                update=0,
       
   117                verbose=0,
       
   118                dry_run=0):
       
   119 
       
   120     """Copy an entire directory tree 'src' to a new location 'dst'.  Both
       
   121        'src' and 'dst' must be directory names.  If 'src' is not a
       
   122        directory, raise DistutilsFileError.  If 'dst' does not exist, it is
       
   123        created with 'mkpath()'.  The end result of the copy is that every
       
   124        file in 'src' is copied to 'dst', and directories under 'src' are
       
   125        recursively copied to 'dst'.  Return the list of files that were
       
   126        copied or might have been copied, using their output name.  The
       
   127        return value is unaffected by 'update' or 'dry_run': it is simply
       
   128        the list of all files under 'src', with the names changed to be
       
   129        under 'dst'.
       
   130 
       
   131        'preserve_mode' and 'preserve_times' are the same as for
       
   132        'copy_file'; note that they only apply to regular files, not to
       
   133        directories.  If 'preserve_symlinks' is true, symlinks will be
       
   134        copied as symlinks (on platforms that support them!); otherwise
       
   135        (the default), the destination of the symlink will be copied.
       
   136        'update' and 'verbose' are the same as for 'copy_file'."""
       
   137 
       
   138     from distutils.file_util import copy_file
       
   139 
       
   140     if not dry_run and not os.path.isdir(src):
       
   141         raise DistutilsFileError, \
       
   142               "cannot copy tree '%s': not a directory" % src
       
   143     try:
       
   144         names = os.listdir(src)
       
   145     except os.error, (errno, errstr):
       
   146         if dry_run:
       
   147             names = []
       
   148         else:
       
   149             raise DistutilsFileError, \
       
   150                   "error listing files in '%s': %s" % (src, errstr)
       
   151 
       
   152     if not dry_run:
       
   153         mkpath(dst)
       
   154 
       
   155     outputs = []
       
   156 
       
   157     for n in names:
       
   158         src_name = os.path.join(src, n)
       
   159         dst_name = os.path.join(dst, n)
       
   160 
       
   161         if preserve_symlinks and os.path.islink(src_name):
       
   162             link_dest = os.readlink(src_name)
       
   163             log.info("linking %s -> %s", dst_name, link_dest)
       
   164             if not dry_run:
       
   165                 os.symlink(link_dest, dst_name)
       
   166             outputs.append(dst_name)
       
   167 
       
   168         elif os.path.isdir(src_name):
       
   169             outputs.extend(
       
   170                 copy_tree(src_name, dst_name, preserve_mode,
       
   171                           preserve_times, preserve_symlinks, update,
       
   172                           dry_run=dry_run))
       
   173         else:
       
   174             copy_file(src_name, dst_name, preserve_mode,
       
   175                       preserve_times, update, dry_run=dry_run)
       
   176             outputs.append(dst_name)
       
   177 
       
   178     return outputs
       
   179 
       
   180 # copy_tree ()
       
   181 
       
   182 # Helper for remove_tree()
       
   183 def _build_cmdtuple(path, cmdtuples):
       
   184     for f in os.listdir(path):
       
   185         real_f = os.path.join(path,f)
       
   186         if os.path.isdir(real_f) and not os.path.islink(real_f):
       
   187             _build_cmdtuple(real_f, cmdtuples)
       
   188         else:
       
   189             cmdtuples.append((os.remove, real_f))
       
   190     cmdtuples.append((os.rmdir, path))
       
   191 
       
   192 
       
   193 def remove_tree (directory, verbose=0, dry_run=0):
       
   194     """Recursively remove an entire directory tree.  Any errors are ignored
       
   195     (apart from being reported to stdout if 'verbose' is true).
       
   196     """
       
   197     from distutils.util import grok_environment_error
       
   198     global _path_created
       
   199 
       
   200     log.info("removing '%s' (and everything under it)", directory)
       
   201     if dry_run:
       
   202         return
       
   203     cmdtuples = []
       
   204     _build_cmdtuple(directory, cmdtuples)
       
   205     for cmd in cmdtuples:
       
   206         try:
       
   207             apply(cmd[0], (cmd[1],))
       
   208             # remove dir from cache if it's already there
       
   209             abspath = os.path.abspath(cmd[1])
       
   210             if abspath in _path_created:
       
   211                 del _path_created[abspath]
       
   212         except (IOError, OSError), exc:
       
   213             log.warn(grok_environment_error(
       
   214                     exc, "error removing %s: " % directory))
       
   215 
       
   216 
       
   217 def ensure_relative (path):
       
   218     """Take the full path 'path', and make it a relative path so
       
   219     it can be the second argument to os.path.join().
       
   220     """
       
   221     drive, path = os.path.splitdrive(path)
       
   222     if sys.platform == 'mac':
       
   223         return os.sep + path
       
   224     else:
       
   225         if path[0:1] == os.sep:
       
   226             path = drive + path[1:]
       
   227         return path