1818from distutils .dir_util import mkpath
1919from distutils import log
2020
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 ):
2257 """Create a (possibly compressed) tar file from all the files under
2358 'base_dir'.
2459
2560 'compress' must be "gzip" (the default), "compress", "bzip2", or None.
26- Both "tar" and the compression utility named by 'compress' must be on
27- the default program search path, so this is probably Unix-specific.
61+ (compress will be deprecated in Python 3.2)
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+
2867 The output tar file will be named 'base_dir' + ".tar", possibly plus
2968 the appropriate compression extension (".gz", ".bz2" or ".Z").
69+
3070 Returns the output filename.
3171 """
3272 tar_compression = {'gzip' : 'gz' , 'bzip2' : 'bz2' , None : '' , 'compress' : '' }
@@ -48,10 +88,23 @@ def make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0):
4888 import tarfile # late import so Python build itself doesn't break
4989
5090 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+
51104 if not dry_run :
52105 tar = tarfile .open (archive_name , 'w|%s' % tar_compression [compress ])
53106 try :
54- tar .add (base_dir )
107+ tar .add (base_dir , filter = _set_uid_gid )
55108 finally :
56109 tar .close ()
57110
@@ -140,7 +193,7 @@ def check_archive_formats(formats):
140193 return None
141194
142195def 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 ):
144197 """Create an archive file (eg. zip or tar).
145198
146199 'base_name' is the name of the file to create, minus any format-specific
@@ -153,6 +206,9 @@ def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
153206 ie. 'base_dir' will be the common prefix of all files and
154207 directories in the archive. 'root_dir' and 'base_dir' both default
155208 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.
156212 """
157213 save_cwd = os .getcwd ()
158214 if root_dir is not None :
@@ -174,6 +230,11 @@ def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
174230 func = format_info [0 ]
175231 for arg , val in format_info [1 ]:
176232 kwargs [arg ] = val
233+
234+ if format != 'zip' :
235+ kwargs ['owner' ] = owner
236+ kwargs ['group' ] = group
237+
177238 try :
178239 filename = func (base_name , base_dir , ** kwargs )
179240 finally :
0 commit comments