blob: 5a134408fdfb174f1e694b33f082a12ea56929a3 [file] [log] [blame]
Greg Wardaebf7062000-04-04 02:05:59 +00001"""distutils.dir_util
2
3Utility functions for manipulating directories and directory trees."""
4
Greg Wardaebf7062000-04-04 02:05:59 +00005__revision__ = "$Id$"
6
Andrew M. Kuchling40f23e02002-11-26 17:42:48 +00007import os, sys
Greg Ward2d238c52000-05-27 01:35:27 +00008from types import *
9from distutils.errors import DistutilsFileError, DistutilsInternalError
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +000010from distutils import log
Greg Wardaebf7062000-04-04 02:05:59 +000011
12# cache for by mkpath() -- in addition to cheapening redundant calls,
13# eliminates redundant "creating /foo/bar/baz" messages in dry-run mode
Greg Wardb248b7f2000-06-17 02:19:30 +000014_path_created = {}
Greg Wardaebf7062000-04-04 02:05:59 +000015
16# I don't use os.makedirs because a) it's new to Python 1.5.2, and
17# b) it blows up if the directory already exists (I want to silently
18# succeed in that case).
Tarek Ziadéd5eb9852009-02-06 00:31:59 +000019def mkpath (name, mode=0777, verbose=1, dry_run=0):
Greg Wardaebf7062000-04-04 02:05:59 +000020 """Create a directory and any missing ancestor directories. If the
21 directory already exists (or if 'name' is the empty string, which
22 means the current directory, which of course exists), then do
23 nothing. Raise DistutilsFileError if unable to create some
24 directory along the way (eg. some sub-path exists, but is a file
25 rather than a directory). If 'verbose' is true, print a one-line
26 summary of each mkdir to stdout. Return the list of directories
27 actually created."""
28
Greg Wardb248b7f2000-06-17 02:19:30 +000029 global _path_created
Greg Wardaebf7062000-04-04 02:05:59 +000030
Greg Ward2d238c52000-05-27 01:35:27 +000031 # Detect a common bug -- name is None
Tim Peters9e34c042005-08-26 15:20:46 +000032 if not isinstance(name, StringTypes):
Greg Ward2d238c52000-05-27 01:35:27 +000033 raise DistutilsInternalError, \
Walter Dörwald70a6b492004-02-12 17:35:32 +000034 "mkpath: 'name' must be a string (got %r)" % (name,)
Greg Ward2d238c52000-05-27 01:35:27 +000035
Greg Wardaebf7062000-04-04 02:05:59 +000036 # XXX what's the better way to handle verbosity? print as we create
37 # each directory in the path (the current behaviour), or only announce
38 # the creation of the whole path? (quite easy to do the latter since
39 # we're not using a recursive algorithm)
40
Greg Ward071ed762000-09-26 02:12:31 +000041 name = os.path.normpath(name)
Greg Wardaebf7062000-04-04 02:05:59 +000042 created_dirs = []
Greg Ward071ed762000-09-26 02:12:31 +000043 if os.path.isdir(name) or name == '':
Greg Wardaebf7062000-04-04 02:05:59 +000044 return created_dirs
Greg Ward963cd2d2000-09-30 17:47:17 +000045 if _path_created.get(os.path.abspath(name)):
Greg Wardaebf7062000-04-04 02:05:59 +000046 return created_dirs
47
Greg Ward071ed762000-09-26 02:12:31 +000048 (head, tail) = os.path.split(name)
Greg Wardaebf7062000-04-04 02:05:59 +000049 tails = [tail] # stack of lone dirs to create
Fred Drakeb94b8492001-12-06 20:51:35 +000050
Greg Ward071ed762000-09-26 02:12:31 +000051 while head and tail and not os.path.isdir(head):
Greg Ward071ed762000-09-26 02:12:31 +000052 (head, tail) = os.path.split(head)
Greg Ward071ed762000-09-26 02:12:31 +000053 tails.insert(0, tail) # push next higher dir onto stack
Greg Wardaebf7062000-04-04 02:05:59 +000054
Greg Wardaebf7062000-04-04 02:05:59 +000055 # now 'head' contains the deepest directory that already exists
56 # (that is, the child of 'head' in 'name' is the highest directory
57 # that does *not* exist)
58 for d in tails:
59 #print "head = %s, d = %s: " % (head, d),
Greg Ward071ed762000-09-26 02:12:31 +000060 head = os.path.join(head, d)
Greg Ward963cd2d2000-09-30 17:47:17 +000061 abs_head = os.path.abspath(head)
62
63 if _path_created.get(abs_head):
Greg Wardaebf7062000-04-04 02:05:59 +000064 continue
65
Tarek Ziadéaaf2e182009-02-06 00:49:45 +000066 if verbose >= 1:
Tarek Ziadéd5eb9852009-02-06 00:31:59 +000067 log.info("creating %s", head)
Greg Wardaebf7062000-04-04 02:05:59 +000068
69 if not dry_run:
70 try:
Greg Ward071ed762000-09-26 02:12:31 +000071 os.mkdir(head)
Greg Wardaebf7062000-04-04 02:05:59 +000072 created_dirs.append(head)
73 except OSError, exc:
74 raise DistutilsFileError, \
75 "could not create '%s': %s" % (head, exc[-1])
76
Greg Ward963cd2d2000-09-30 17:47:17 +000077 _path_created[abs_head] = 1
Greg Wardaebf7062000-04-04 02:05:59 +000078 return created_dirs
79
80# mkpath ()
81
82
Tarek Ziadéd5eb9852009-02-06 00:31:59 +000083def create_tree (base_dir, files, mode=0777, verbose=1, dry_run=0):
Greg Wardaebf7062000-04-04 02:05:59 +000084
85 """Create all the empty directories under 'base_dir' needed to
86 put 'files' there. 'base_dir' is just the a name of a directory
87 which doesn't necessarily exist yet; 'files' is a list of filenames
88 to be interpreted relative to 'base_dir'. 'base_dir' + the
89 directory portion of every file in 'files' will be created if it
90 doesn't already exist. 'mode', 'verbose' and 'dry_run' flags are as
91 for 'mkpath()'."""
92
93 # First get the list of directories to create
94 need_dir = {}
95 for file in files:
Greg Ward071ed762000-09-26 02:12:31 +000096 need_dir[os.path.join(base_dir, os.path.dirname(file))] = 1
Greg Wardaebf7062000-04-04 02:05:59 +000097 need_dirs = need_dir.keys()
98 need_dirs.sort()
99
100 # Now create them
101 for dir in need_dirs:
Tarek Ziadéd5eb9852009-02-06 00:31:59 +0000102 mkpath(dir, mode, verbose=verbose, dry_run=dry_run)
Greg Wardaebf7062000-04-04 02:05:59 +0000103
104# create_tree ()
105
106
107def copy_tree (src, dst,
108 preserve_mode=1,
109 preserve_times=1,
110 preserve_symlinks=0,
111 update=0,
Tarek Ziadéd5eb9852009-02-06 00:31:59 +0000112 verbose=1,
Greg Wardaebf7062000-04-04 02:05:59 +0000113 dry_run=0):
114
115 """Copy an entire directory tree 'src' to a new location 'dst'. Both
116 'src' and 'dst' must be directory names. If 'src' is not a
117 directory, raise DistutilsFileError. If 'dst' does not exist, it is
118 created with 'mkpath()'. The end result of the copy is that every
119 file in 'src' is copied to 'dst', and directories under 'src' are
120 recursively copied to 'dst'. Return the list of files that were
121 copied or might have been copied, using their output name. The
122 return value is unaffected by 'update' or 'dry_run': it is simply
123 the list of all files under 'src', with the names changed to be
124 under 'dst'.
125
126 'preserve_mode' and 'preserve_times' are the same as for
127 'copy_file'; note that they only apply to regular files, not to
128 directories. If 'preserve_symlinks' is true, symlinks will be
129 copied as symlinks (on platforms that support them!); otherwise
130 (the default), the destination of the symlink will be copied.
131 'update' and 'verbose' are the same as for 'copy_file'."""
132
133 from distutils.file_util import copy_file
134
Greg Ward071ed762000-09-26 02:12:31 +0000135 if not dry_run and not os.path.isdir(src):
Greg Wardaebf7062000-04-04 02:05:59 +0000136 raise DistutilsFileError, \
Fred Drakeb94b8492001-12-06 20:51:35 +0000137 "cannot copy tree '%s': not a directory" % src
Greg Wardaebf7062000-04-04 02:05:59 +0000138 try:
Greg Ward071ed762000-09-26 02:12:31 +0000139 names = os.listdir(src)
Greg Wardaebf7062000-04-04 02:05:59 +0000140 except os.error, (errno, errstr):
141 if dry_run:
142 names = []
143 else:
144 raise DistutilsFileError, \
145 "error listing files in '%s': %s" % (src, errstr)
146
147 if not dry_run:
Tarek Ziadéd5eb9852009-02-06 00:31:59 +0000148 mkpath(dst, verbose=verbose)
Greg Wardaebf7062000-04-04 02:05:59 +0000149
150 outputs = []
151
152 for n in names:
Greg Ward071ed762000-09-26 02:12:31 +0000153 src_name = os.path.join(src, n)
154 dst_name = os.path.join(dst, n)
Greg Wardaebf7062000-04-04 02:05:59 +0000155
Greg Ward071ed762000-09-26 02:12:31 +0000156 if preserve_symlinks and os.path.islink(src_name):
157 link_dest = os.readlink(src_name)
Tarek Ziadéaaf2e182009-02-06 00:49:45 +0000158 if verbose >= 1:
Tarek Ziadéd5eb9852009-02-06 00:31:59 +0000159 log.info("linking %s -> %s", dst_name, link_dest)
Greg Wardaebf7062000-04-04 02:05:59 +0000160 if not dry_run:
Greg Ward071ed762000-09-26 02:12:31 +0000161 os.symlink(link_dest, dst_name)
162 outputs.append(dst_name)
Fred Drakeb94b8492001-12-06 20:51:35 +0000163
Greg Ward071ed762000-09-26 02:12:31 +0000164 elif os.path.isdir(src_name):
165 outputs.extend(
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000166 copy_tree(src_name, dst_name, preserve_mode,
167 preserve_times, preserve_symlinks, update,
Tarek Ziadéd5eb9852009-02-06 00:31:59 +0000168 verbose=verbose, dry_run=dry_run))
Greg Wardaebf7062000-04-04 02:05:59 +0000169 else:
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000170 copy_file(src_name, dst_name, preserve_mode,
Tarek Ziadéd5eb9852009-02-06 00:31:59 +0000171 preserve_times, update, verbose=verbose,
172 dry_run=dry_run)
Greg Ward071ed762000-09-26 02:12:31 +0000173 outputs.append(dst_name)
Greg Wardaebf7062000-04-04 02:05:59 +0000174
175 return outputs
176
177# copy_tree ()
178
Greg Ward039accf2000-06-17 01:58:14 +0000179# Helper for remove_tree()
180def _build_cmdtuple(path, cmdtuples):
181 for f in os.listdir(path):
182 real_f = os.path.join(path,f)
183 if os.path.isdir(real_f) and not os.path.islink(real_f):
184 _build_cmdtuple(real_f, cmdtuples)
185 else:
186 cmdtuples.append((os.remove, real_f))
187 cmdtuples.append((os.rmdir, path))
188
Greg Wardaebf7062000-04-04 02:05:59 +0000189
Tarek Ziadéd5eb9852009-02-06 00:31:59 +0000190def remove_tree (directory, verbose=1, dry_run=0):
Greg Wardaebf7062000-04-04 02:05:59 +0000191 """Recursively remove an entire directory tree. Any errors are ignored
Greg Wardfcd4f872000-06-17 02:18:19 +0000192 (apart from being reported to stdout if 'verbose' is true).
193 """
194 from distutils.util import grok_environment_error
Greg Wardb248b7f2000-06-17 02:19:30 +0000195 global _path_created
Greg Wardfcd4f872000-06-17 02:18:19 +0000196
Tarek Ziadéaaf2e182009-02-06 00:49:45 +0000197 if verbose >= 1:
Tarek Ziadéd5eb9852009-02-06 00:31:59 +0000198 log.info("removing '%s' (and everything under it)", directory)
Greg Wardaebf7062000-04-04 02:05:59 +0000199 if dry_run:
200 return
Greg Ward039accf2000-06-17 01:58:14 +0000201 cmdtuples = []
202 _build_cmdtuple(directory, cmdtuples)
203 for cmd in cmdtuples:
204 try:
205 apply(cmd[0], (cmd[1],))
206 # remove dir from cache if it's already there
Greg Ward963cd2d2000-09-30 17:47:17 +0000207 abspath = os.path.abspath(cmd[1])
Guido van Rossum8bc09652008-02-21 18:18:37 +0000208 if abspath in _path_created:
Greg Ward963cd2d2000-09-30 17:47:17 +0000209 del _path_created[abspath]
Greg Ward039accf2000-06-17 01:58:14 +0000210 except (IOError, OSError), exc:
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000211 log.warn(grok_environment_error(
212 exc, "error removing %s: " % directory))
Andrew M. Kuchling40f23e02002-11-26 17:42:48 +0000213
214
215def ensure_relative (path):
216 """Take the full path 'path', and make it a relative path so
217 it can be the second argument to os.path.join().
218 """
219 drive, path = os.path.splitdrive(path)
220 if sys.platform == 'mac':
221 return os.sep + path
222 else:
223 if path[0:1] == os.sep:
224 path = drive + path[1:]
225 return path