blob: a1578bed6a87d13bfce9e514abc85879c3624ced [file] [log] [blame]
Greg Wardaebf7062000-04-04 02:05:59 +00001"""distutils.dir_util
2
3Utility functions for manipulating directories and directory trees."""
4
5# created 2000/04/03, Greg Ward (extracted from util.py)
6
7__revision__ = "$Id$"
8
9import os
Greg Ward2d238c52000-05-27 01:35:27 +000010from types import *
11from distutils.errors import DistutilsFileError, DistutilsInternalError
Greg Wardaebf7062000-04-04 02:05:59 +000012
13
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).
21def 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
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
34 if type(name) is not StringType:
35 raise DistutilsInternalError, \
36 "mkpath: 'name' must be a string (got %s)" % `name`
37
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
52
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
72 if verbose:
73 print "creating", head
74
75 if not dry_run:
76 try:
Greg Ward071ed762000-09-26 02:12:31 +000077 os.mkdir(head)
Greg Wardaebf7062000-04-04 02:05:59 +000078 created_dirs.append(head)
79 except OSError, exc:
80 raise DistutilsFileError, \
81 "could not create '%s': %s" % (head, exc[-1])
82
Greg Ward963cd2d2000-09-30 17:47:17 +000083 _path_created[abs_head] = 1
Greg Wardaebf7062000-04-04 02:05:59 +000084 return created_dirs
85
86# mkpath ()
87
88
89def create_tree (base_dir, files, mode=0777, verbose=0, dry_run=0):
90
91 """Create all the empty directories under 'base_dir' needed to
92 put 'files' there. 'base_dir' is just the a name of a directory
93 which doesn't necessarily exist yet; 'files' is a list of filenames
94 to be interpreted relative to 'base_dir'. 'base_dir' + the
95 directory portion of every file in 'files' will be created if it
96 doesn't already exist. 'mode', 'verbose' and 'dry_run' flags are as
97 for 'mkpath()'."""
98
99 # First get the list of directories to create
100 need_dir = {}
101 for file in files:
Greg Ward071ed762000-09-26 02:12:31 +0000102 need_dir[os.path.join(base_dir, os.path.dirname(file))] = 1
Greg Wardaebf7062000-04-04 02:05:59 +0000103 need_dirs = need_dir.keys()
104 need_dirs.sort()
105
106 # Now create them
107 for dir in need_dirs:
Greg Ward071ed762000-09-26 02:12:31 +0000108 mkpath(dir, mode, verbose, dry_run)
Greg Wardaebf7062000-04-04 02:05:59 +0000109
110# create_tree ()
111
112
113def copy_tree (src, dst,
114 preserve_mode=1,
115 preserve_times=1,
116 preserve_symlinks=0,
117 update=0,
118 verbose=0,
119 dry_run=0):
120
121 """Copy an entire directory tree 'src' to a new location 'dst'. Both
122 'src' and 'dst' must be directory names. If 'src' is not a
123 directory, raise DistutilsFileError. If 'dst' does not exist, it is
124 created with 'mkpath()'. The end result of the copy is that every
125 file in 'src' is copied to 'dst', and directories under 'src' are
126 recursively copied to 'dst'. Return the list of files that were
127 copied or might have been copied, using their output name. The
128 return value is unaffected by 'update' or 'dry_run': it is simply
129 the list of all files under 'src', with the names changed to be
130 under 'dst'.
131
132 'preserve_mode' and 'preserve_times' are the same as for
133 'copy_file'; note that they only apply to regular files, not to
134 directories. If 'preserve_symlinks' is true, symlinks will be
135 copied as symlinks (on platforms that support them!); otherwise
136 (the default), the destination of the symlink will be copied.
137 'update' and 'verbose' are the same as for 'copy_file'."""
138
139 from distutils.file_util import copy_file
140
Greg Ward071ed762000-09-26 02:12:31 +0000141 if not dry_run and not os.path.isdir(src):
Greg Wardaebf7062000-04-04 02:05:59 +0000142 raise DistutilsFileError, \
143 "cannot copy tree '%s': not a directory" % src
144 try:
Greg Ward071ed762000-09-26 02:12:31 +0000145 names = os.listdir(src)
Greg Wardaebf7062000-04-04 02:05:59 +0000146 except os.error, (errno, errstr):
147 if dry_run:
148 names = []
149 else:
150 raise DistutilsFileError, \
151 "error listing files in '%s': %s" % (src, errstr)
152
153 if not dry_run:
Greg Ward071ed762000-09-26 02:12:31 +0000154 mkpath(dst, verbose=verbose)
Greg Wardaebf7062000-04-04 02:05:59 +0000155
156 outputs = []
157
158 for n in names:
Greg Ward071ed762000-09-26 02:12:31 +0000159 src_name = os.path.join(src, n)
160 dst_name = os.path.join(dst, n)
Greg Wardaebf7062000-04-04 02:05:59 +0000161
Greg Ward071ed762000-09-26 02:12:31 +0000162 if preserve_symlinks and os.path.islink(src_name):
163 link_dest = os.readlink(src_name)
Greg Wardaebf7062000-04-04 02:05:59 +0000164 if verbose:
165 print "linking %s -> %s" % (dst_name, link_dest)
166 if not dry_run:
Greg Ward071ed762000-09-26 02:12:31 +0000167 os.symlink(link_dest, dst_name)
168 outputs.append(dst_name)
Greg Wardaebf7062000-04-04 02:05:59 +0000169
Greg Ward071ed762000-09-26 02:12:31 +0000170 elif os.path.isdir(src_name):
171 outputs.extend(
172 copy_tree(src_name, dst_name,
173 preserve_mode, preserve_times, preserve_symlinks,
174 update, verbose, dry_run))
Greg Wardaebf7062000-04-04 02:05:59 +0000175 else:
Greg Ward071ed762000-09-26 02:12:31 +0000176 copy_file(src_name, dst_name,
177 preserve_mode, preserve_times,
178 update, None, verbose, dry_run)
179 outputs.append(dst_name)
Greg Wardaebf7062000-04-04 02:05:59 +0000180
181 return outputs
182
183# copy_tree ()
184
Greg Ward039accf2000-06-17 01:58:14 +0000185# Helper for remove_tree()
186def _build_cmdtuple(path, cmdtuples):
187 for f in os.listdir(path):
188 real_f = os.path.join(path,f)
189 if os.path.isdir(real_f) and not os.path.islink(real_f):
190 _build_cmdtuple(real_f, cmdtuples)
191 else:
192 cmdtuples.append((os.remove, real_f))
193 cmdtuples.append((os.rmdir, path))
194
Greg Wardaebf7062000-04-04 02:05:59 +0000195
196def remove_tree (directory, verbose=0, dry_run=0):
197 """Recursively remove an entire directory tree. Any errors are ignored
Greg Wardfcd4f872000-06-17 02:18:19 +0000198 (apart from being reported to stdout if 'verbose' is true).
199 """
200 from distutils.util import grok_environment_error
Greg Wardb248b7f2000-06-17 02:19:30 +0000201 global _path_created
Greg Wardfcd4f872000-06-17 02:18:19 +0000202
Greg Wardaebf7062000-04-04 02:05:59 +0000203 if verbose:
204 print "removing '%s' (and everything under it)" % directory
205 if dry_run:
206 return
Greg Ward039accf2000-06-17 01:58:14 +0000207 cmdtuples = []
208 _build_cmdtuple(directory, cmdtuples)
209 for cmd in cmdtuples:
210 try:
211 apply(cmd[0], (cmd[1],))
212 # remove dir from cache if it's already there
Greg Ward963cd2d2000-09-30 17:47:17 +0000213 abspath = os.path.abspath(cmd[1])
214 if _path_created.has_key(abspath):
215 del _path_created[abspath]
Greg Ward039accf2000-06-17 01:58:14 +0000216 except (IOError, OSError), exc:
217 if verbose:
Greg Wardfcd4f872000-06-17 02:18:19 +0000218 print grok_environment_error(
219 exc, "error removing %s: " % directory)