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