@@ -896,7 +896,7 @@ def _get_uid(name):
896
896
return None
897
897
898
898
def _make_tarball (base_name , base_dir , compress = "gzip" , verbose = 0 , dry_run = 0 ,
899
- owner = None , group = None , logger = None ):
899
+ owner = None , group = None , logger = None , root_dir = None ):
900
900
"""Create a (possibly compressed) tar file from all the files under
901
901
'base_dir'.
902
902
@@ -953,14 +953,20 @@ def _set_uid_gid(tarinfo):
953
953
954
954
if not dry_run :
955
955
tar = tarfile .open (archive_name , 'w|%s' % tar_compression )
956
+ arcname = base_dir
957
+ if root_dir is not None :
958
+ base_dir = os .path .join (root_dir , base_dir )
956
959
try :
957
- tar .add (base_dir , filter = _set_uid_gid )
960
+ tar .add (base_dir , arcname , filter = _set_uid_gid )
958
961
finally :
959
962
tar .close ()
960
963
964
+ if root_dir is not None :
965
+ archive_name = os .path .abspath (archive_name )
961
966
return archive_name
962
967
963
- def _make_zipfile (base_name , base_dir , verbose = 0 , dry_run = 0 , logger = None ):
968
+ def _make_zipfile (base_name , base_dir , verbose = 0 , dry_run = 0 ,
969
+ logger = None , owner = None , group = None , root_dir = None ):
964
970
"""Create a zip file from all the files under 'base_dir'.
965
971
966
972
The output zip file will be named 'base_name' + ".zip". Returns the
@@ -984,42 +990,60 @@ def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None):
984
990
if not dry_run :
985
991
with zipfile .ZipFile (zip_filename , "w" ,
986
992
compression = zipfile .ZIP_DEFLATED ) as zf :
987
- path = os .path .normpath (base_dir )
988
- if path != os .curdir :
989
- zf .write (path , path )
993
+ arcname = os .path .normpath (base_dir )
994
+ if root_dir is not None :
995
+ base_dir = os .path .join (root_dir , base_dir )
996
+ base_dir = os .path .normpath (base_dir )
997
+ if arcname != os .curdir :
998
+ zf .write (base_dir , arcname )
990
999
if logger is not None :
991
- logger .info ("adding '%s'" , path )
1000
+ logger .info ("adding '%s'" , base_dir )
992
1001
for dirpath , dirnames , filenames in os .walk (base_dir ):
1002
+ arcdirpath = dirpath
1003
+ if root_dir is not None :
1004
+ arcdirpath = os .path .relpath (arcdirpath , root_dir )
1005
+ arcdirpath = os .path .normpath (arcdirpath )
993
1006
for name in sorted (dirnames ):
994
- path = os .path .normpath (os .path .join (dirpath , name ))
995
- zf .write (path , path )
1007
+ path = os .path .join (dirpath , name )
1008
+ arcname = os .path .join (arcdirpath , name )
1009
+ zf .write (path , arcname )
996
1010
if logger is not None :
997
1011
logger .info ("adding '%s'" , path )
998
1012
for name in filenames :
999
- path = os .path .normpath (os .path .join (dirpath , name ))
1013
+ path = os .path .join (dirpath , name )
1014
+ path = os .path .normpath (path )
1000
1015
if os .path .isfile (path ):
1001
- zf .write (path , path )
1016
+ arcname = os .path .join (arcdirpath , name )
1017
+ zf .write (path , arcname )
1002
1018
if logger is not None :
1003
1019
logger .info ("adding '%s'" , path )
1004
1020
1021
+ if root_dir is not None :
1022
+ zip_filename = os .path .abspath (zip_filename )
1005
1023
return zip_filename
1006
1024
1025
+ # Maps the name of the archive format to a tuple containing:
1026
+ # * the archiving function
1027
+ # * extra keyword arguments
1028
+ # * description
1029
+ # * does it support the root_dir argument?
1007
1030
_ARCHIVE_FORMATS = {
1008
- 'tar' : (_make_tarball , [('compress' , None )], "uncompressed tar file" ),
1031
+ 'tar' : (_make_tarball , [('compress' , None )],
1032
+ "uncompressed tar file" , True ),
1009
1033
}
1010
1034
1011
1035
if _ZLIB_SUPPORTED :
1012
1036
_ARCHIVE_FORMATS ['gztar' ] = (_make_tarball , [('compress' , 'gzip' )],
1013
- "gzip'ed tar-file" )
1014
- _ARCHIVE_FORMATS ['zip' ] = (_make_zipfile , [], "ZIP file" )
1037
+ "gzip'ed tar-file" , True )
1038
+ _ARCHIVE_FORMATS ['zip' ] = (_make_zipfile , [], "ZIP file" , True )
1015
1039
1016
1040
if _BZ2_SUPPORTED :
1017
1041
_ARCHIVE_FORMATS ['bztar' ] = (_make_tarball , [('compress' , 'bzip2' )],
1018
- "bzip2'ed tar-file" )
1042
+ "bzip2'ed tar-file" , True )
1019
1043
1020
1044
if _LZMA_SUPPORTED :
1021
1045
_ARCHIVE_FORMATS ['xztar' ] = (_make_tarball , [('compress' , 'xz' )],
1022
- "xz'ed tar-file" )
1046
+ "xz'ed tar-file" , True )
1023
1047
1024
1048
def get_archive_formats ():
1025
1049
"""Returns a list of supported formats for archiving and unarchiving.
@@ -1050,7 +1074,7 @@ def register_archive_format(name, function, extra_args=None, description=''):
1050
1074
if not isinstance (element , (tuple , list )) or len (element ) != 2 :
1051
1075
raise TypeError ('extra_args elements are : (arg_name, value)' )
1052
1076
1053
- _ARCHIVE_FORMATS [name ] = (function , extra_args , description )
1077
+ _ARCHIVE_FORMATS [name ] = (function , extra_args , description , False )
1054
1078
1055
1079
def unregister_archive_format (name ):
1056
1080
del _ARCHIVE_FORMATS [name ]
@@ -1074,36 +1098,38 @@ def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
1074
1098
uses the current owner and group.
1075
1099
"""
1076
1100
sys .audit ("shutil.make_archive" , base_name , format , root_dir , base_dir )
1077
- save_cwd = os .getcwd ()
1078
- if root_dir is not None :
1079
- if logger is not None :
1080
- logger .debug ("changing into '%s'" , root_dir )
1081
- base_name = os .path .abspath (base_name )
1082
- if not dry_run :
1083
- os .chdir (root_dir )
1084
-
1085
- if base_dir is None :
1086
- base_dir = os .curdir
1087
-
1088
- kwargs = {'dry_run' : dry_run , 'logger' : logger }
1089
-
1090
1101
try :
1091
1102
format_info = _ARCHIVE_FORMATS [format ]
1092
1103
except KeyError :
1093
1104
raise ValueError ("unknown archive format '%s'" % format ) from None
1094
1105
1106
+ kwargs = {'dry_run' : dry_run , 'logger' : logger ,
1107
+ 'owner' : owner , 'group' : group }
1108
+
1095
1109
func = format_info [0 ]
1096
1110
for arg , val in format_info [1 ]:
1097
1111
kwargs [arg ] = val
1098
1112
1099
- if format != 'zip' :
1100
- kwargs ['owner' ] = owner
1101
- kwargs ['group' ] = group
1113
+ if base_dir is None :
1114
+ base_dir = os .curdir
1115
+
1116
+ support_root_dir = format_info [3 ]
1117
+ save_cwd = None
1118
+ if root_dir is not None :
1119
+ if support_root_dir :
1120
+ kwargs ['root_dir' ] = root_dir
1121
+ else :
1122
+ save_cwd = os .getcwd ()
1123
+ if logger is not None :
1124
+ logger .debug ("changing into '%s'" , root_dir )
1125
+ base_name = os .path .abspath (base_name )
1126
+ if not dry_run :
1127
+ os .chdir (root_dir )
1102
1128
1103
1129
try :
1104
1130
filename = func (base_name , base_dir , ** kwargs )
1105
1131
finally :
1106
- if root_dir is not None :
1132
+ if save_cwd is not None :
1107
1133
if logger is not None :
1108
1134
logger .debug ("changing back to '%s'" , save_cwd )
1109
1135
os .chdir (save_cwd )
@@ -1216,6 +1242,11 @@ def _unpack_tarfile(filename, extract_dir):
1216
1242
finally :
1217
1243
tarobj .close ()
1218
1244
1245
+ # Maps the name of the unpack format to a tuple containing:
1246
+ # * extensions
1247
+ # * the unpacking function
1248
+ # * extra keyword arguments
1249
+ # * description
1219
1250
_UNPACK_FORMATS = {
1220
1251
'tar' : (['.tar' ], _unpack_tarfile , [], "uncompressed tar file" ),
1221
1252
'zip' : (['.zip' ], _unpack_zipfile , [], "ZIP file" ),
0 commit comments