blob: ed54ccefd4e11e237f7f9ddd2e99241e34df51af [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 distutils.errors import DistutilsFileError, DistutilsInternalError
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +00009from distutils import log
Greg Wardaebf7062000-04-04 02:05:59 +000010
11# cache for by mkpath() -- in addition to cheapening redundant calls,
12# eliminates redundant "creating /foo/bar/baz" messages in dry-run mode
Greg Wardb248b7f2000-06-17 02:19:30 +000013_path_created = {}
Greg Wardaebf7062000-04-04 02:05:59 +000014
15# I don't use os.makedirs because a) it's new to Python 1.5.2, and
16# b) it blows up if the directory already exists (I want to silently
17# succeed in that case).
Tarek Ziadé70a74eb2009-02-06 00:38:35 +000018def mkpath (name, mode=0o777, verbose=1, dry_run=0):
Greg Wardaebf7062000-04-04 02:05:59 +000019 """Create a directory and any missing ancestor directories. If the
20 directory already exists (or if 'name' is the empty string, which
21 means the current directory, which of course exists), then do
22 nothing. Raise DistutilsFileError if unable to create some
23 directory along the way (eg. some sub-path exists, but is a file
24 rather than a directory). If 'verbose' is true, print a one-line
25 summary of each mkdir to stdout. Return the list of directories
26 actually created."""
27
Greg Wardb248b7f2000-06-17 02:19:30 +000028 global _path_created
Greg Wardaebf7062000-04-04 02:05:59 +000029
Greg Ward2d238c52000-05-27 01:35:27 +000030 # Detect a common bug -- name is None
Guido van Rossum3172c5d2007-10-16 18:12:55 +000031 if not isinstance(name, str):
Collin Winter5b7e9d72007-08-30 03:52:21 +000032 raise DistutilsInternalError(
33 "mkpath: 'name' must be a string (got %r)" % (name,))
Greg Ward2d238c52000-05-27 01:35:27 +000034
Greg Wardaebf7062000-04-04 02:05:59 +000035 # XXX what's the better way to handle verbosity? print as we create
36 # each directory in the path (the current behaviour), or only announce
37 # the creation of the whole path? (quite easy to do the latter since
38 # we're not using a recursive algorithm)
39
Greg Ward071ed762000-09-26 02:12:31 +000040 name = os.path.normpath(name)
Greg Wardaebf7062000-04-04 02:05:59 +000041 created_dirs = []
Greg Ward071ed762000-09-26 02:12:31 +000042 if os.path.isdir(name) or name == '':
Greg Wardaebf7062000-04-04 02:05:59 +000043 return created_dirs
Greg Ward963cd2d2000-09-30 17:47:17 +000044 if _path_created.get(os.path.abspath(name)):
Greg Wardaebf7062000-04-04 02:05:59 +000045 return created_dirs
46
Greg Ward071ed762000-09-26 02:12:31 +000047 (head, tail) = os.path.split(name)
Greg Wardaebf7062000-04-04 02:05:59 +000048 tails = [tail] # stack of lone dirs to create
Fred Drakeb94b8492001-12-06 20:51:35 +000049
Greg Ward071ed762000-09-26 02:12:31 +000050 while head and tail and not os.path.isdir(head):
Greg Ward071ed762000-09-26 02:12:31 +000051 (head, tail) = os.path.split(head)
Greg Ward071ed762000-09-26 02:12:31 +000052 tails.insert(0, tail) # push next higher dir onto stack
Greg Wardaebf7062000-04-04 02:05:59 +000053
Greg Wardaebf7062000-04-04 02:05:59 +000054 # now 'head' contains the deepest directory that already exists
55 # (that is, the child of 'head' in 'name' is the highest directory
56 # that does *not* exist)
57 for d in tails:
58 #print "head = %s, d = %s: " % (head, d),
Greg Ward071ed762000-09-26 02:12:31 +000059 head = os.path.join(head, d)
Greg Ward963cd2d2000-09-30 17:47:17 +000060 abs_head = os.path.abspath(head)
61
62 if _path_created.get(abs_head):
Greg Wardaebf7062000-04-04 02:05:59 +000063 continue
64
Tarek Ziadé35e6fd52009-02-06 00:53:43 +000065 if verbose >= 1:
Tarek Ziadé70a74eb2009-02-06 00:38:35 +000066 log.info("creating %s", head)
Greg Wardaebf7062000-04-04 02:05:59 +000067
68 if not dry_run:
69 try:
Greg Ward071ed762000-09-26 02:12:31 +000070 os.mkdir(head)
Greg Wardaebf7062000-04-04 02:05:59 +000071 created_dirs.append(head)
Guido van Rossumb940e112007-01-10 16:19:56 +000072 except OSError as exc:
Guido van Rossum8c746142007-08-29 13:18:47 +000073 raise DistutilsFileError(
74 "could not create '%s': %s" % (head, exc.args[-1]))
Greg Wardaebf7062000-04-04 02:05:59 +000075
Greg Ward963cd2d2000-09-30 17:47:17 +000076 _path_created[abs_head] = 1
Greg Wardaebf7062000-04-04 02:05:59 +000077 return created_dirs
78
79# mkpath ()
80
81
Tarek Ziadé70a74eb2009-02-06 00:38:35 +000082def create_tree (base_dir, files, mode=0o777, verbose=1, dry_run=0):
Greg Wardaebf7062000-04-04 02:05:59 +000083
84 """Create all the empty directories under 'base_dir' needed to
85 put 'files' there. 'base_dir' is just the a name of a directory
86 which doesn't necessarily exist yet; 'files' is a list of filenames
87 to be interpreted relative to 'base_dir'. 'base_dir' + the
88 directory portion of every file in 'files' will be created if it
89 doesn't already exist. 'mode', 'verbose' and 'dry_run' flags are as
90 for 'mkpath()'."""
91
92 # First get the list of directories to create
Guido van Rossum486364b2007-06-30 05:01:58 +000093 need_dir = set()
Greg Wardaebf7062000-04-04 02:05:59 +000094 for file in files:
Guido van Rossum486364b2007-06-30 05:01:58 +000095 need_dir.add(os.path.join(base_dir, os.path.dirname(file)))
Greg Wardaebf7062000-04-04 02:05:59 +000096
97 # Now create them
Guido van Rossum486364b2007-06-30 05:01:58 +000098 for dir in sorted(need_dir):
Tarek Ziadé70a74eb2009-02-06 00:38:35 +000099 mkpath(dir, mode, verbose=verbose, dry_run=dry_run)
Greg Wardaebf7062000-04-04 02:05:59 +0000100
101# create_tree ()
102
103
104def copy_tree (src, dst,
105 preserve_mode=1,
106 preserve_times=1,
107 preserve_symlinks=0,
108 update=0,
Tarek Ziadé70a74eb2009-02-06 00:38:35 +0000109 verbose=1,
Greg Wardaebf7062000-04-04 02:05:59 +0000110 dry_run=0):
111
112 """Copy an entire directory tree 'src' to a new location 'dst'. Both
113 'src' and 'dst' must be directory names. If 'src' is not a
114 directory, raise DistutilsFileError. If 'dst' does not exist, it is
115 created with 'mkpath()'. The end result of the copy is that every
116 file in 'src' is copied to 'dst', and directories under 'src' are
117 recursively copied to 'dst'. Return the list of files that were
118 copied or might have been copied, using their output name. The
119 return value is unaffected by 'update' or 'dry_run': it is simply
120 the list of all files under 'src', with the names changed to be
121 under 'dst'.
122
123 'preserve_mode' and 'preserve_times' are the same as for
124 'copy_file'; note that they only apply to regular files, not to
125 directories. If 'preserve_symlinks' is true, symlinks will be
126 copied as symlinks (on platforms that support them!); otherwise
127 (the default), the destination of the symlink will be copied.
128 'update' and 'verbose' are the same as for 'copy_file'."""
129
130 from distutils.file_util import copy_file
131
Greg Ward071ed762000-09-26 02:12:31 +0000132 if not dry_run and not os.path.isdir(src):
Collin Winter5b7e9d72007-08-30 03:52:21 +0000133 raise DistutilsFileError(
134 "cannot copy tree '%s': not a directory" % src)
Greg Wardaebf7062000-04-04 02:05:59 +0000135 try:
Greg Ward071ed762000-09-26 02:12:31 +0000136 names = os.listdir(src)
Guido van Rossumb940e112007-01-10 16:19:56 +0000137 except os.error as e:
138 (errno, errstr) = e
Greg Wardaebf7062000-04-04 02:05:59 +0000139 if dry_run:
140 names = []
141 else:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000142 raise DistutilsFileError(
143 "error listing files in '%s': %s" % (src, errstr))
Greg Wardaebf7062000-04-04 02:05:59 +0000144
145 if not dry_run:
Tarek Ziadé70a74eb2009-02-06 00:38:35 +0000146 mkpath(dst, verbose=verbose)
Greg Wardaebf7062000-04-04 02:05:59 +0000147
148 outputs = []
149
150 for n in names:
Greg Ward071ed762000-09-26 02:12:31 +0000151 src_name = os.path.join(src, n)
152 dst_name = os.path.join(dst, n)
Greg Wardaebf7062000-04-04 02:05:59 +0000153
Greg Ward071ed762000-09-26 02:12:31 +0000154 if preserve_symlinks and os.path.islink(src_name):
155 link_dest = os.readlink(src_name)
Tarek Ziadé35e6fd52009-02-06 00:53:43 +0000156 if verbose >= 1:
Tarek Ziadé70a74eb2009-02-06 00:38:35 +0000157 log.info("linking %s -> %s", dst_name, link_dest)
Greg Wardaebf7062000-04-04 02:05:59 +0000158 if not dry_run:
Greg Ward071ed762000-09-26 02:12:31 +0000159 os.symlink(link_dest, dst_name)
160 outputs.append(dst_name)
Fred Drakeb94b8492001-12-06 20:51:35 +0000161
Greg Ward071ed762000-09-26 02:12:31 +0000162 elif os.path.isdir(src_name):
163 outputs.extend(
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000164 copy_tree(src_name, dst_name, preserve_mode,
165 preserve_times, preserve_symlinks, update,
Tarek Ziadé70a74eb2009-02-06 00:38:35 +0000166 verbose=verbose, dry_run=dry_run))
Greg Wardaebf7062000-04-04 02:05:59 +0000167 else:
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000168 copy_file(src_name, dst_name, preserve_mode,
Tarek Ziadé70a74eb2009-02-06 00:38:35 +0000169 preserve_times, update, verbose=verbose,
170 dry_run=dry_run)
Greg Ward071ed762000-09-26 02:12:31 +0000171 outputs.append(dst_name)
Greg Wardaebf7062000-04-04 02:05:59 +0000172
173 return outputs
174
Greg Ward039accf2000-06-17 01:58:14 +0000175# Helper for remove_tree()
176def _build_cmdtuple(path, cmdtuples):
177 for f in os.listdir(path):
178 real_f = os.path.join(path,f)
179 if os.path.isdir(real_f) and not os.path.islink(real_f):
180 _build_cmdtuple(real_f, cmdtuples)
181 else:
182 cmdtuples.append((os.remove, real_f))
183 cmdtuples.append((os.rmdir, path))
184
Greg Wardaebf7062000-04-04 02:05:59 +0000185
Tarek Ziadé70a74eb2009-02-06 00:38:35 +0000186def remove_tree (directory, verbose=1, dry_run=0):
Greg Wardaebf7062000-04-04 02:05:59 +0000187 """Recursively remove an entire directory tree. Any errors are ignored
Greg Wardfcd4f872000-06-17 02:18:19 +0000188 (apart from being reported to stdout if 'verbose' is true).
189 """
190 from distutils.util import grok_environment_error
Greg Wardb248b7f2000-06-17 02:19:30 +0000191 global _path_created
Greg Wardfcd4f872000-06-17 02:18:19 +0000192
Tarek Ziadé35e6fd52009-02-06 00:53:43 +0000193 if verbose >= 1:
Tarek Ziadé70a74eb2009-02-06 00:38:35 +0000194 log.info("removing '%s' (and everything under it)", directory)
Greg Wardaebf7062000-04-04 02:05:59 +0000195 if dry_run:
196 return
Greg Ward039accf2000-06-17 01:58:14 +0000197 cmdtuples = []
198 _build_cmdtuple(directory, cmdtuples)
199 for cmd in cmdtuples:
200 try:
Neal Norwitzd9108552006-03-17 08:00:19 +0000201 cmd[0](cmd[1])
Greg Ward039accf2000-06-17 01:58:14 +0000202 # remove dir from cache if it's already there
Greg Ward963cd2d2000-09-30 17:47:17 +0000203 abspath = os.path.abspath(cmd[1])
Neal Norwitzf1a69c12006-08-20 16:25:10 +0000204 if abspath in _path_created:
Greg Ward963cd2d2000-09-30 17:47:17 +0000205 del _path_created[abspath]
Guido van Rossumb940e112007-01-10 16:19:56 +0000206 except (IOError, OSError) as exc:
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000207 log.warn(grok_environment_error(
208 exc, "error removing %s: " % directory))
Andrew M. Kuchling40f23e02002-11-26 17:42:48 +0000209
210
211def ensure_relative (path):
212 """Take the full path 'path', and make it a relative path so
213 it can be the second argument to os.path.join().
214 """
215 drive, path = os.path.splitdrive(path)
216 if sys.platform == 'mac':
217 return os.sep + path
218 else:
219 if path[0:1] == os.sep:
220 path = drive + path[1:]
221 return path