1414from distutils .dir_util import mkpath
1515from distutils import log
1616
17- def make_tarball (base_name , base_dir , compress = "gzip" , verbose = 0 , dry_run = 0 ):
17+ try :
18+ from pwd import getpwnam
19+ except AttributeError :
20+ getpwnam = None
21+
22+ try :
23+ from grp import getgrnam
24+ except AttributeError :
25+ getgrnam = None
26+
27+ def _get_gid (name ):
28+ """Returns a gid, given a group name."""
29+ if getgrnam is None or name is None :
30+ return None
31+ try :
32+ result = getgrnam (name )
33+ except KeyError :
34+ result = None
35+ if result is not None :
36+ return result [2 ]
37+ return None
38+
39+ def _get_uid (name ):
40+ """Returns an uid, given a user name."""
41+ if getpwnam is None or name is None :
42+ return None
43+ try :
44+ result = getpwnam (name )
45+ except KeyError :
46+ result = None
47+ if result is not None :
48+ return result [2 ]
49+ return None
50+
51+ def make_tarball (base_name , base_dir , compress = "gzip" , verbose = 0 , dry_run = 0 ,
52+ owner = None , group = None ):
1853 """Create a (possibly compressed) tar file from all the files under
1954 'base_dir'.
2055
2156 'compress' must be "gzip" (the default), "compress", "bzip2", or None.
22- Both "tar" and the compression utility named by 'compress' must be on
23- the default program search path, so this is probably Unix-specific.
57+ (compress will be deprecated in Python 3.2)
58+
59+ 'owner' and 'group' can be used to define an owner and a group for the
60+ archive that is being built. If not provided, the current owner and group
61+ will be used.
62+
2463 The output tar file will be named 'base_dir' + ".tar", possibly plus
2564 the appropriate compression extension (".gz", ".bz2" or ".Z").
65+
2666 Returns the output filename.
2767 """
2868 tar_compression = {'gzip' : 'gz' , 'bzip2' : 'bz2' , None : '' , 'compress' : '' }
@@ -44,10 +84,23 @@ def make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0):
4484 import tarfile # late import so Python build itself doesn't break
4585
4686 log .info ('Creating tar archive' )
87+
88+ uid = _get_uid (owner )
89+ gid = _get_gid (group )
90+
91+ def _set_uid_gid (tarinfo ):
92+ if gid is not None :
93+ tarinfo .gid = gid
94+ tarinfo .gname = group
95+ if uid is not None :
96+ tarinfo .uid = uid
97+ tarinfo .uname = owner
98+ return tarinfo
99+
47100 if not dry_run :
48101 tar = tarfile .open (archive_name , 'w|%s' % tar_compression [compress ])
49102 try :
50- tar .add (base_dir )
103+ tar .add (base_dir , filter = _set_uid_gid )
51104 finally :
52105 tar .close ()
53106
@@ -137,7 +190,7 @@ def check_archive_formats(formats):
137190 return None
138191
139192def make_archive (base_name , format , root_dir = None , base_dir = None , verbose = 0 ,
140- dry_run = 0 ):
193+ dry_run = 0 , owner = None , group = None ):
141194 """Create an archive file (eg. zip or tar).
142195
143196 'base_name' is the name of the file to create, minus any format-specific
@@ -150,6 +203,9 @@ def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
150203 ie. 'base_dir' will be the common prefix of all files and
151204 directories in the archive. 'root_dir' and 'base_dir' both default
152205 to the current directory. Returns the name of the archive file.
206+
207+ 'owner' and 'group' are used when creating a tar archive. By default,
208+ uses the current owner and group.
153209 """
154210 save_cwd = os .getcwd ()
155211 if root_dir is not None :
@@ -171,6 +227,11 @@ def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
171227 func = format_info [0 ]
172228 for arg , val in format_info [1 ]:
173229 kwargs [arg ] = val
230+
231+ if format != 'zip' :
232+ kwargs ['owner' ] = owner
233+ kwargs ['group' ] = group
234+
174235 filename = func (base_name , base_dir , ** kwargs )
175236
176237 if root_dir is not None :
0 commit comments