Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(124128)

Side by Side Diff: Lib/distutils/archive_util.py

Issue 6516: reset owner/group to root for distutils tarballs
Patch Set: Created 5 years, 4 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Doc/distutils/sourcedist.rst ('k') | Lib/distutils/cmd.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 """distutils.archive_util 1 """distutils.archive_util
2 2
3 Utility functions for creating archive files (tarballs, zip files, 3 Utility functions for creating archive files (tarballs, zip files,
4 that sort of thing).""" 4 that sort of thing)."""
5 5
6 import os 6 import os
7 from warnings import warn 7 from warnings import warn
8 import sys 8 import sys
9 9
10 try: 10 try:
11 import zipfile 11 import zipfile
12 except ImportError: 12 except ImportError:
13 zipfile = None 13 zipfile = None
14 14
15 15
16 from distutils.errors import DistutilsExecError 16 from distutils.errors import DistutilsExecError
17 from distutils.spawn import spawn 17 from distutils.spawn import spawn
18 from distutils.dir_util import mkpath 18 from distutils.dir_util import mkpath
19 from distutils import log 19 from distutils import log
20 20
21 def make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0): 21 try:
22 from pwd import getpwnam
23 except AttributeError:
24 getpwnam = None
25
26 try:
27 from grp import getgrnam
28 except AttributeError:
29 getgrnam = None
30
31 def _get_gid(name):
32 """Returns a gid, given a group name."""
33 if getgrnam is None or name is None:
34 return None
35 try:
36 result = getgrnam(name)
37 except KeyError:
38 result = None
39 if result is not None:
40 return result[2]
41 return None
42
43 def _get_uid(name):
44 """Returns an uid, given a user name."""
45 if getpwnam is None or name is None:
46 return None
47 try:
48 result = getpwnam(name)
49 except KeyError:
50 result = None
51 if result is not None:
52 return result[2]
53 return None
54
55 def make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
56 owner=None, group=None):
22 """Create a (possibly compressed) tar file from all the files under 57 """Create a (possibly compressed) tar file from all the files under
23 'base_dir'. 58 'base_dir'.
24 59
25 'compress' must be "gzip" (the default), "compress", "bzip2", or None. 60 'compress' must be "gzip" (the default), "compress", "bzip2", or None.
26 Both "tar" and the compression utility named by 'compress' must be on 61 (compress will be deprecated in Python 3.2)
27 the default program search path, so this is probably Unix-specific. 62
63 'owner' and 'group' can be used to define an owner and a group for the
64 archive that is being built. If not provided, the current owner and group
65 will be used.
66
28 The output tar file will be named 'base_dir' + ".tar", possibly plus 67 The output tar file will be named 'base_dir' + ".tar", possibly plus
29 the appropriate compression extension (".gz", ".bz2" or ".Z"). 68 the appropriate compression extension (".gz", ".bz2" or ".Z").
69
30 Returns the output filename. 70 Returns the output filename.
31 """ 71 """
32 tar_compression = {'gzip': 'gz', 'bzip2': 'bz2', None: '', 'compress': ''} 72 tar_compression = {'gzip': 'gz', 'bzip2': 'bz2', None: '', 'compress': ''}
33 compress_ext = {'gzip': '.gz', 'bzip2': '.bz2', 'compress': '.Z'} 73 compress_ext = {'gzip': '.gz', 'bzip2': '.bz2', 'compress': '.Z'}
34 74
35 # flags for compression program, each element of list will be an argument 75 # flags for compression program, each element of list will be an argument
36 if compress is not None and compress not in compress_ext.keys(): 76 if compress is not None and compress not in compress_ext.keys():
37 raise ValueError( 77 raise ValueError(
38 "bad value for 'compress': must be None, 'gzip', 'bzip2' " 78 "bad value for 'compress': must be None, 'gzip', 'bzip2' "
39 "or 'compress'") 79 "or 'compress'")
40 80
41 archive_name = base_name + '.tar' 81 archive_name = base_name + '.tar'
42 if compress != 'compress': 82 if compress != 'compress':
43 archive_name += compress_ext.get(compress, '') 83 archive_name += compress_ext.get(compress, '')
44 84
45 mkpath(os.path.dirname(archive_name), dry_run=dry_run) 85 mkpath(os.path.dirname(archive_name), dry_run=dry_run)
46 86
47 # creating the tarball 87 # creating the tarball
48 import tarfile # late import so Python build itself doesn't break 88 import tarfile # late import so Python build itself doesn't break
49 89
50 log.info('Creating tar archive') 90 log.info('Creating tar archive')
91
92 uid = _get_uid(owner)
93 gid = _get_gid(group)
94
95 def _set_uid_gid(tarinfo):
96 if gid is not None:
97 tarinfo.gid = gid
98 tarinfo.gname = group
99 if uid is not None:
100 tarinfo.uid = uid
101 tarinfo.uname = owner
102 return tarinfo
103
51 if not dry_run: 104 if not dry_run:
52 tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress]) 105 tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress])
53 try: 106 try:
54 tar.add(base_dir) 107 tar.add(base_dir, filter=_set_uid_gid)
55 finally: 108 finally:
56 tar.close() 109 tar.close()
57 110
58 # compression using `compress` 111 # compression using `compress`
59 if compress == 'compress': 112 if compress == 'compress':
60 warn("'compress' will be deprecated.", PendingDeprecationWarning) 113 warn("'compress' will be deprecated.", PendingDeprecationWarning)
61 # the option varies depending on the platform 114 # the option varies depending on the platform
62 compressed_name = archive_name + compress_ext[compress] 115 compressed_name = archive_name + compress_ext[compress]
63 if sys.platform == 'win32': 116 if sys.platform == 'win32':
64 cmd = [compress, archive_name, compressed_name] 117 cmd = [compress, archive_name, compressed_name]
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 """Returns the first format from the 'format' list that is unknown. 186 """Returns the first format from the 'format' list that is unknown.
134 187
135 If all formats are known, returns None 188 If all formats are known, returns None
136 """ 189 """
137 for format in formats: 190 for format in formats:
138 if format not in ARCHIVE_FORMATS: 191 if format not in ARCHIVE_FORMATS:
139 return format 192 return format
140 return None 193 return None
141 194
142 def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, 195 def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
143 dry_run=0): 196 dry_run=0, owner=None, group=None):
144 """Create an archive file (eg. zip or tar). 197 """Create an archive file (eg. zip or tar).
145 198
146 'base_name' is the name of the file to create, minus any format-specific 199 'base_name' is the name of the file to create, minus any format-specific
147 extension; 'format' is the archive format: one of "zip", "tar", "ztar", 200 extension; 'format' is the archive format: one of "zip", "tar", "ztar",
148 or "gztar". 201 or "gztar".
149 202
150 'root_dir' is a directory that will be the root directory of the 203 'root_dir' is a directory that will be the root directory of the
151 archive; ie. we typically chdir into 'root_dir' before creating the 204 archive; ie. we typically chdir into 'root_dir' before creating the
152 archive. 'base_dir' is the directory where we start archiving from; 205 archive. 'base_dir' is the directory where we start archiving from;
153 ie. 'base_dir' will be the common prefix of all files and 206 ie. 'base_dir' will be the common prefix of all files and
154 directories in the archive. 'root_dir' and 'base_dir' both default 207 directories in the archive. 'root_dir' and 'base_dir' both default
155 to the current directory. Returns the name of the archive file. 208 to the current directory. Returns the name of the archive file.
209
210 'owner' and 'group' are used when creating a tar archive. By default,
211 uses the current owner and group.
156 """ 212 """
157 save_cwd = os.getcwd() 213 save_cwd = os.getcwd()
158 if root_dir is not None: 214 if root_dir is not None:
159 log.debug("changing into '%s'", root_dir) 215 log.debug("changing into '%s'", root_dir)
160 base_name = os.path.abspath(base_name) 216 base_name = os.path.abspath(base_name)
161 if not dry_run: 217 if not dry_run:
162 os.chdir(root_dir) 218 os.chdir(root_dir)
163 219
164 if base_dir is None: 220 if base_dir is None:
165 base_dir = os.curdir 221 base_dir = os.curdir
166 222
167 kwargs = {'dry_run': dry_run} 223 kwargs = {'dry_run': dry_run}
168 224
169 try: 225 try:
170 format_info = ARCHIVE_FORMATS[format] 226 format_info = ARCHIVE_FORMATS[format]
171 except KeyError: 227 except KeyError:
172 raise ValueError("unknown archive format '%s'" % format) 228 raise ValueError("unknown archive format '%s'" % format)
173 229
174 func = format_info[0] 230 func = format_info[0]
175 for arg, val in format_info[1]: 231 for arg, val in format_info[1]:
176 kwargs[arg] = val 232 kwargs[arg] = val
233
234 if format != 'zip':
235 kwargs['owner'] = owner
236 kwargs['group'] = group
237
177 try: 238 try:
178 filename = func(base_name, base_dir, **kwargs) 239 filename = func(base_name, base_dir, **kwargs)
179 finally: 240 finally:
180 if root_dir is not None: 241 if root_dir is not None:
181 log.debug("changing back to '%s'", save_cwd) 242 log.debug("changing back to '%s'", save_cwd)
182 os.chdir(save_cwd) 243 os.chdir(save_cwd)
183 244
184 return filename 245 return filename
OLDNEW
« no previous file with comments | « Doc/distutils/sourcedist.rst ('k') | Lib/distutils/cmd.py » ('j') | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+