blob: a6c4416a6fe3f4df7d2ef693679121cc80a9722a [file] [log] [blame]
Greg Wardaebf7062000-04-04 02:05:59 +00001"""distutils.dir_util
2
3Utility functions for manipulating directories and directory trees."""
4
Martin v. Löwis5a6601c2004-11-10 22:23:15 +00005# This module should be kept compatible with Python 2.1.
Andrew M. Kuchlingd448f662002-11-19 13:12:28 +00006
Greg Wardaebf7062000-04-04 02:05:59 +00007__revision__ = "$Id$"
8
Andrew M. Kuchling40f23e02002-11-26 17:42:48 +00009import os, sys
Greg Ward2d238c52000-05-27 01:35:27 +000010from types import *
11from distutils.errors import DistutilsFileError, DistutilsInternalError
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +000012from distutils import log
Greg Wardaebf7062000-04-04 02:05:59 +000013
14# cache for by mkpath() -- in addition to cheapening redundant calls,
15# eliminates redundant "creating /foo/bar/baz" messages in dry-run mode
Greg Wardb248b7f2000-06-17 02:19:30 +000016_path_created = {}
Greg Wardaebf7062000-04-04 02:05:59 +000017
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).
Guido van Rossumcd16bf62007-06-13 18:07:49 +000021def mkpath (name, mode=0o777, verbose=0, dry_run=0):
Greg Wardaebf7062000-04-04 02:05:59 +000022 """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
Greg Wardb248b7f2000-06-17 02:19:30 +000031 global _path_created
Greg Wardaebf7062000-04-04 02:05:59 +000032
Greg Ward2d238c52000-05-27 01:35:27 +000033 # Detect a common bug -- name is None
Guido van Rossum572dbf82007-04-27 23:53:51 +000034 if not isinstance(name, basestring):
Greg Ward2d238c52000-05-27 01:35:27 +000035 raise DistutilsInternalError, \
Walter Dörwald70a6b492004-02-12 17:35:32 +000036 "mkpath: 'name' must be a string (got %r)" % (name,)
Greg Ward2d238c52000-05-27 01:35:27 +000037
Greg Wardaebf7062000-04-04 02:05:59 +000038 # 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
Greg Ward071ed762000-09-26 02:12:31 +000043 name = os.path.normpath(name)
Greg Wardaebf7062000-04-04 02:05:59 +000044 created_dirs = []
Greg Ward071ed762000-09-26 02:12:31 +000045 if os.path.isdir(name) or name == '':
Greg Wardaebf7062000-04-04 02:05:59 +000046 return created_dirs
Greg Ward963cd2d2000-09-30 17:47:17 +000047 if _path_created.get(os.path.abspath(name)):
Greg Wardaebf7062000-04-04 02:05:59 +000048 return created_dirs
49
Greg Ward071ed762000-09-26 02:12:31 +000050 (head, tail) = os.path.split(name)
Greg Wardaebf7062000-04-04 02:05:59 +000051 tails = [tail] # stack of lone dirs to create
Fred Drakeb94b8492001-12-06 20:51:35 +000052
Greg Ward071ed762000-09-26 02:12:31 +000053 while head and tail and not os.path.isdir(head):
Greg Wardaebf7062000-04-04 02:05:59 +000054 #print "splitting '%s': " % head,
Greg Ward071ed762000-09-26 02:12:31 +000055 (head, tail) = os.path.split(head)
Greg Wardaebf7062000-04-04 02:05:59 +000056 #print "to ('%s','%s')" % (head, tail)
Greg Ward071ed762000-09-26 02:12:31 +000057 tails.insert(0, tail) # push next higher dir onto stack
Greg Wardaebf7062000-04-04 02:05:59 +000058
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),
Greg Ward071ed762000-09-26 02:12:31 +000066 head = os.path.join(head, d)
Greg Ward963cd2d2000-09-30 17:47:17 +000067 abs_head = os.path.abspath(head)
68
69 if _path_created.get(abs_head):
Greg Wardaebf7062000-04-04 02:05:59 +000070 continue
71
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +000072 log.info("creating %s", head)
Greg Wardaebf7062000-04-04 02:05:59 +000073
74 if not dry_run:
75 try:
Greg Ward071ed762000-09-26 02:12:31 +000076 os.mkdir(head)
Greg Wardaebf7062000-04-04 02:05:59 +000077 created_dirs.append(head)
Guido van Rossumb940e112007-01-10 16:19:56 +000078 except OSError as exc:
Greg Wardaebf7062000-04-04 02:05:59 +000079 raise DistutilsFileError, \
80 "could not create '%s': %s" % (head, exc[-1])
81
Greg Ward963cd2d2000-09-30 17:47:17 +000082 _path_created[abs_head] = 1
Greg Wardaebf7062000-04-04 02:05:59 +000083 return created_dirs
84
85# mkpath ()
86
87
Guido van Rossumcd16bf62007-06-13 18:07:49 +000088def create_tree (base_dir, files, mode=0o777, verbose=0, dry_run=0):
Greg Wardaebf7062000-04-04 02:05:59 +000089
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
Guido van Rossum486364b2007-06-30 05:01:58 +000099 need_dir = set()
Greg Wardaebf7062000-04-04 02:05:59 +0000100 for file in files:
Guido van Rossum486364b2007-06-30 05:01:58 +0000101 need_dir.add(os.path.join(base_dir, os.path.dirname(file)))
Greg Wardaebf7062000-04-04 02:05:59 +0000102
103 # Now create them
Guido van Rossum486364b2007-06-30 05:01:58 +0000104 for dir in sorted(need_dir):
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000105 mkpath(dir, mode, dry_run=dry_run)
Greg Wardaebf7062000-04-04 02:05:59 +0000106
107# create_tree ()
108
109
110def copy_tree (src, dst,
111 preserve_mode=1,
112 preserve_times=1,
113 preserve_symlinks=0,
114 update=0,
115 verbose=0,
116 dry_run=0):
117
118 """Copy an entire directory tree 'src' to a new location 'dst'. Both
119 'src' and 'dst' must be directory names. If 'src' is not a
120 directory, raise DistutilsFileError. If 'dst' does not exist, it is
121 created with 'mkpath()'. The end result of the copy is that every
122 file in 'src' is copied to 'dst', and directories under 'src' are
123 recursively copied to 'dst'. Return the list of files that were
124 copied or might have been copied, using their output name. The
125 return value is unaffected by 'update' or 'dry_run': it is simply
126 the list of all files under 'src', with the names changed to be
127 under 'dst'.
128
129 'preserve_mode' and 'preserve_times' are the same as for
130 'copy_file'; note that they only apply to regular files, not to
131 directories. If 'preserve_symlinks' is true, symlinks will be
132 copied as symlinks (on platforms that support them!); otherwise
133 (the default), the destination of the symlink will be copied.
134 'update' and 'verbose' are the same as for 'copy_file'."""
135
136 from distutils.file_util import copy_file
137
Greg Ward071ed762000-09-26 02:12:31 +0000138 if not dry_run and not os.path.isdir(src):
Greg Wardaebf7062000-04-04 02:05:59 +0000139 raise DistutilsFileError, \
Fred Drakeb94b8492001-12-06 20:51:35 +0000140 "cannot copy tree '%s': not a directory" % src
Greg Wardaebf7062000-04-04 02:05:59 +0000141 try:
Greg Ward071ed762000-09-26 02:12:31 +0000142 names = os.listdir(src)
Guido van Rossumb940e112007-01-10 16:19:56 +0000143 except os.error as e:
144 (errno, errstr) = e
Greg Wardaebf7062000-04-04 02:05:59 +0000145 if dry_run:
146 names = []
147 else:
148 raise DistutilsFileError, \
149 "error listing files in '%s': %s" % (src, errstr)
150
151 if not dry_run:
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000152 mkpath(dst)
Greg Wardaebf7062000-04-04 02:05:59 +0000153
154 outputs = []
155
156 for n in names:
Greg Ward071ed762000-09-26 02:12:31 +0000157 src_name = os.path.join(src, n)
158 dst_name = os.path.join(dst, n)
Greg Wardaebf7062000-04-04 02:05:59 +0000159
Greg Ward071ed762000-09-26 02:12:31 +0000160 if preserve_symlinks and os.path.islink(src_name):
161 link_dest = os.readlink(src_name)
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000162 log.info("linking %s -> %s", dst_name, link_dest)
Greg Wardaebf7062000-04-04 02:05:59 +0000163 if not dry_run:
Greg Ward071ed762000-09-26 02:12:31 +0000164 os.symlink(link_dest, dst_name)
165 outputs.append(dst_name)
Fred Drakeb94b8492001-12-06 20:51:35 +0000166
Greg Ward071ed762000-09-26 02:12:31 +0000167 elif os.path.isdir(src_name):
168 outputs.extend(
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000169 copy_tree(src_name, dst_name, preserve_mode,
170 preserve_times, preserve_symlinks, update,
171 dry_run=dry_run))
Greg Wardaebf7062000-04-04 02:05:59 +0000172 else:
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000173 copy_file(src_name, dst_name, preserve_mode,
174 preserve_times, update, dry_run=dry_run)
Greg Ward071ed762000-09-26 02:12:31 +0000175 outputs.append(dst_name)
Greg Wardaebf7062000-04-04 02:05:59 +0000176
177 return outputs
178
179# copy_tree ()
180
Greg Ward039accf2000-06-17 01:58:14 +0000181# Helper for remove_tree()
182def _build_cmdtuple(path, cmdtuples):
183 for f in os.listdir(path):
184 real_f = os.path.join(path,f)
185 if os.path.isdir(real_f) and not os.path.islink(real_f):
186 _build_cmdtuple(real_f, cmdtuples)
187 else:
188 cmdtuples.append((os.remove, real_f))
189 cmdtuples.append((os.rmdir, path))
190
Greg Wardaebf7062000-04-04 02:05:59 +0000191
192def remove_tree (directory, verbose=0, dry_run=0):
193 """Recursively remove an entire directory tree. Any errors are ignored
Greg Wardfcd4f872000-06-17 02:18:19 +0000194 (apart from being reported to stdout if 'verbose' is true).
195 """
196 from distutils.util import grok_environment_error
Greg Wardb248b7f2000-06-17 02:19:30 +0000197 global _path_created
Greg Wardfcd4f872000-06-17 02:18:19 +0000198
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000199 log.info("removing '%s' (and everything under it)", directory)
Greg Wardaebf7062000-04-04 02:05:59 +0000200 if dry_run:
201 return
Greg Ward039accf2000-06-17 01:58:14 +0000202 cmdtuples = []
203 _build_cmdtuple(directory, cmdtuples)
204 for cmd in cmdtuples:
205 try:
Neal Norwitzd9108552006-03-17 08:00:19 +0000206 cmd[0](cmd[1])
Greg Ward039accf2000-06-17 01:58:14 +0000207 # remove dir from cache if it's already there
Greg Ward963cd2d2000-09-30 17:47:17 +0000208 abspath = os.path.abspath(cmd[1])
Neal Norwitzf1a69c12006-08-20 16:25:10 +0000209 if abspath in _path_created:
Greg Ward963cd2d2000-09-30 17:47:17 +0000210 del _path_created[abspath]
Guido van Rossumb940e112007-01-10 16:19:56 +0000211 except (IOError, OSError) as exc:
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000212 log.warn(grok_environment_error(
213 exc, "error removing %s: " % directory))
Andrew M. Kuchling40f23e02002-11-26 17:42:48 +0000214
215
216def ensure_relative (path):
217 """Take the full path 'path', and make it a relative path so
218 it can be the second argument to os.path.join().
219 """
220 drive, path = os.path.splitdrive(path)
221 if sys.platform == 'mac':
222 return os.sep + path
223 else:
224 if path[0:1] == os.sep:
225 path = drive + path[1:]
226 return path