@@ -887,7 +887,7 @@ def _get_uid(name):
887
887
return None
888
888
889
889
def _make_tarball (base_name , base_dir , compress = "gzip" , verbose = 0 , dry_run = 0 ,
890
- owner = None , group = None , logger = None ):
890
+ owner = None , group = None , logger = None , root_dir = None ):
891
891
"""Create a (possibly compressed) tar file from all the files under
892
892
'base_dir'.
893
893
@@ -944,14 +944,20 @@ def _set_uid_gid(tarinfo):
944
944
945
945
if not dry_run :
946
946
tar = tarfile .open (archive_name , 'w|%s' % tar_compression )
947
+ arcname = base_dir
948
+ if root_dir is not None :
949
+ base_dir = os .path .join (root_dir , base_dir )
947
950
try :
948
- tar .add (base_dir , filter = _set_uid_gid )
951
+ tar .add (base_dir , arcname , filter = _set_uid_gid )
949
952
finally :
950
953
tar .close ()
951
954
955
+ if root_dir is not None :
956
+ archive_name = os .path .abspath (archive_name )
952
957
return archive_name
953
958
954
- def _make_zipfile (base_name , base_dir , verbose = 0 , dry_run = 0 , logger = None ):
959
+ def _make_zipfile (base_name , base_dir , verbose = 0 , dry_run = 0 ,
960
+ logger = None , owner = None , group = None , root_dir = None ):
955
961
"""Create a zip file from all the files under 'base_dir'.
956
962
957
963
The output zip file will be named 'base_name' + ".zip". Returns the
@@ -975,42 +981,60 @@ def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None):
975
981
if not dry_run :
976
982
with zipfile .ZipFile (zip_filename , "w" ,
977
983
compression = zipfile .ZIP_DEFLATED ) as zf :
978
- path = os .path .normpath (base_dir )
979
- if path != os .curdir :
980
- zf .write (path , path )
984
+ arcname = os .path .normpath (base_dir )
985
+ if root_dir is not None :
986
+ base_dir = os .path .join (root_dir , base_dir )
987
+ base_dir = os .path .normpath (base_dir )
988
+ if arcname != os .curdir :
989
+ zf .write (base_dir , arcname )
981
990
if logger is not None :
982
- logger .info ("adding '%s'" , path )
991
+ logger .info ("adding '%s'" , base_dir )
983
992
for dirpath , dirnames , filenames in os .walk (base_dir ):
993
+ arcdirpath = dirpath
994
+ if root_dir is not None :
995
+ arcdirpath = os .path .relpath (arcdirpath , root_dir )
996
+ arcdirpath = os .path .normpath (arcdirpath )
984
997
for name in sorted (dirnames ):
985
- path = os .path .normpath (os .path .join (dirpath , name ))
986
- zf .write (path , path )
998
+ path = os .path .join (dirpath , name )
999
+ arcname = os .path .join (arcdirpath , name )
1000
+ zf .write (path , arcname )
987
1001
if logger is not None :
988
1002
logger .info ("adding '%s'" , path )
989
1003
for name in filenames :
990
- path = os .path .normpath (os .path .join (dirpath , name ))
1004
+ path = os .path .join (dirpath , name )
1005
+ path = os .path .normpath (path )
991
1006
if os .path .isfile (path ):
992
- zf .write (path , path )
1007
+ arcname = os .path .join (arcdirpath , name )
1008
+ zf .write (path , arcname )
993
1009
if logger is not None :
994
1010
logger .info ("adding '%s'" , path )
995
1011
1012
+ if root_dir is not None :
1013
+ zip_filename = os .path .abspath (zip_filename )
996
1014
return zip_filename
997
1015
1016
+ # Maps the name of the archive format to a tuple containing:
1017
+ # * the archiving function
1018
+ # * extra keyword arguments
1019
+ # * description
1020
+ # * does it support the root_dir argument?
998
1021
_ARCHIVE_FORMATS = {
999
- 'tar' : (_make_tarball , [('compress' , None )], "uncompressed tar file" ),
1022
+ 'tar' : (_make_tarball , [('compress' , None )],
1023
+ "uncompressed tar file" , True ),
1000
1024
}
1001
1025
1002
1026
if _ZLIB_SUPPORTED :
1003
1027
_ARCHIVE_FORMATS ['gztar' ] = (_make_tarball , [('compress' , 'gzip' )],
1004
- "gzip'ed tar-file" )
1005
- _ARCHIVE_FORMATS ['zip' ] = (_make_zipfile , [], "ZIP file" )
1028
+ "gzip'ed tar-file" , True )
1029
+ _ARCHIVE_FORMATS ['zip' ] = (_make_zipfile , [], "ZIP file" , True )
1006
1030
1007
1031
if _BZ2_SUPPORTED :
1008
1032
_ARCHIVE_FORMATS ['bztar' ] = (_make_tarball , [('compress' , 'bzip2' )],
1009
- "bzip2'ed tar-file" )
1033
+ "bzip2'ed tar-file" , True )
1010
1034
1011
1035
if _LZMA_SUPPORTED :
1012
1036
_ARCHIVE_FORMATS ['xztar' ] = (_make_tarball , [('compress' , 'xz' )],
1013
- "xz'ed tar-file" )
1037
+ "xz'ed tar-file" , True )
1014
1038
1015
1039
def get_archive_formats ():
1016
1040
"""Returns a list of supported formats for archiving and unarchiving.
@@ -1041,7 +1065,7 @@ def register_archive_format(name, function, extra_args=None, description=''):
1041
1065
if not isinstance (element , (tuple , list )) or len (element ) != 2 :
1042
1066
raise TypeError ('extra_args elements are : (arg_name, value)' )
1043
1067
1044
- _ARCHIVE_FORMATS [name ] = (function , extra_args , description )
1068
+ _ARCHIVE_FORMATS [name ] = (function , extra_args , description , False )
1045
1069
1046
1070
def unregister_archive_format (name ):
1047
1071
del _ARCHIVE_FORMATS [name ]
@@ -1065,36 +1089,38 @@ def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
1065
1089
uses the current owner and group.
1066
1090
"""
1067
1091
sys .audit ("shutil.make_archive" , base_name , format , root_dir , base_dir )
1068
- save_cwd = os .getcwd ()
1069
- if root_dir is not None :
1070
- if logger is not None :
1071
- logger .debug ("changing into '%s'" , root_dir )
1072
- base_name = os .path .abspath (base_name )
1073
- if not dry_run :
1074
- os .chdir (root_dir )
1075
-
1076
- if base_dir is None :
1077
- base_dir = os .curdir
1078
-
1079
- kwargs = {'dry_run' : dry_run , 'logger' : logger }
1080
-
1081
1092
try :
1082
1093
format_info = _ARCHIVE_FORMATS [format ]
1083
1094
except KeyError :
1084
1095
raise ValueError ("unknown archive format '%s'" % format ) from None
1085
1096
1097
+ kwargs = {'dry_run' : dry_run , 'logger' : logger ,
1098
+ 'owner' : owner , 'group' : group }
1099
+
1086
1100
func = format_info [0 ]
1087
1101
for arg , val in format_info [1 ]:
1088
1102
kwargs [arg ] = val
1089
1103
1090
- if format != 'zip' :
1091
- kwargs ['owner' ] = owner
1092
- kwargs ['group' ] = group
1104
+ if base_dir is None :
1105
+ base_dir = os .curdir
1106
+
1107
+ support_root_dir = format_info [3 ]
1108
+ save_cwd = None
1109
+ if root_dir is not None :
1110
+ if support_root_dir :
1111
+ kwargs ['root_dir' ] = root_dir
1112
+ else :
1113
+ save_cwd = os .getcwd ()
1114
+ if logger is not None :
1115
+ logger .debug ("changing into '%s'" , root_dir )
1116
+ base_name = os .path .abspath (base_name )
1117
+ if not dry_run :
1118
+ os .chdir (root_dir )
1093
1119
1094
1120
try :
1095
1121
filename = func (base_name , base_dir , ** kwargs )
1096
1122
finally :
1097
- if root_dir is not None :
1123
+ if save_cwd is not None :
1098
1124
if logger is not None :
1099
1125
logger .debug ("changing back to '%s'" , save_cwd )
1100
1126
os .chdir (save_cwd )
@@ -1207,6 +1233,11 @@ def _unpack_tarfile(filename, extract_dir):
1207
1233
finally :
1208
1234
tarobj .close ()
1209
1235
1236
+ # Maps the name of the unpack format to a tuple containing:
1237
+ # * extensions
1238
+ # * the unpacking function
1239
+ # * extra keyword arguments
1240
+ # * description
1210
1241
_UNPACK_FORMATS = {
1211
1242
'tar' : (['.tar' ], _unpack_tarfile , [], "uncompressed tar file" ),
1212
1243
'zip' : (['.zip' ], _unpack_zipfile , [], "ZIP file" ),
0 commit comments