@@ -887,7 +887,7 @@ def _get_uid(name):
887887 return None
888888
889889def _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 ):
891891 """Create a (possibly compressed) tar file from all the files under
892892 'base_dir'.
893893
@@ -944,14 +944,20 @@ def _set_uid_gid(tarinfo):
944944
945945 if not dry_run :
946946 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 )
947950 try :
948- tar .add (base_dir , filter = _set_uid_gid )
951+ tar .add (base_dir , arcname , filter = _set_uid_gid )
949952 finally :
950953 tar .close ()
951954
955+ if root_dir is not None :
956+ archive_name = os .path .abspath (archive_name )
952957 return archive_name
953958
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 ):
955961 """Create a zip file from all the files under 'base_dir'.
956962
957963 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):
975981 if not dry_run :
976982 with zipfile .ZipFile (zip_filename , "w" ,
977983 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 )
981990 if logger is not None :
982- logger .info ("adding '%s'" , path )
991+ logger .info ("adding '%s'" , base_dir )
983992 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 )
984997 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 )
9871001 if logger is not None :
9881002 logger .info ("adding '%s'" , path )
9891003 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 )
9911006 if os .path .isfile (path ):
992- zf .write (path , path )
1007+ arcname = os .path .join (arcdirpath , name )
1008+ zf .write (path , arcname )
9931009 if logger is not None :
9941010 logger .info ("adding '%s'" , path )
9951011
1012+ if root_dir is not None :
1013+ zip_filename = os .path .abspath (zip_filename )
9961014 return zip_filename
9971015
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?
9981021_ARCHIVE_FORMATS = {
999- 'tar' : (_make_tarball , [('compress' , None )], "uncompressed tar file" ),
1022+ 'tar' : (_make_tarball , [('compress' , None )],
1023+ "uncompressed tar file" , True ),
10001024}
10011025
10021026if _ZLIB_SUPPORTED :
10031027 _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 )
10061030
10071031if _BZ2_SUPPORTED :
10081032 _ARCHIVE_FORMATS ['bztar' ] = (_make_tarball , [('compress' , 'bzip2' )],
1009- "bzip2'ed tar-file" )
1033+ "bzip2'ed tar-file" , True )
10101034
10111035if _LZMA_SUPPORTED :
10121036 _ARCHIVE_FORMATS ['xztar' ] = (_make_tarball , [('compress' , 'xz' )],
1013- "xz'ed tar-file" )
1037+ "xz'ed tar-file" , True )
10141038
10151039def get_archive_formats ():
10161040 """Returns a list of supported formats for archiving and unarchiving.
@@ -1041,7 +1065,7 @@ def register_archive_format(name, function, extra_args=None, description=''):
10411065 if not isinstance (element , (tuple , list )) or len (element ) != 2 :
10421066 raise TypeError ('extra_args elements are : (arg_name, value)' )
10431067
1044- _ARCHIVE_FORMATS [name ] = (function , extra_args , description )
1068+ _ARCHIVE_FORMATS [name ] = (function , extra_args , description , False )
10451069
10461070def unregister_archive_format (name ):
10471071 del _ARCHIVE_FORMATS [name ]
@@ -1065,36 +1089,38 @@ def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
10651089 uses the current owner and group.
10661090 """
10671091 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-
10811092 try :
10821093 format_info = _ARCHIVE_FORMATS [format ]
10831094 except KeyError :
10841095 raise ValueError ("unknown archive format '%s'" % format ) from None
10851096
1097+ kwargs = {'dry_run' : dry_run , 'logger' : logger ,
1098+ 'owner' : owner , 'group' : group }
1099+
10861100 func = format_info [0 ]
10871101 for arg , val in format_info [1 ]:
10881102 kwargs [arg ] = val
10891103
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 )
10931119
10941120 try :
10951121 filename = func (base_name , base_dir , ** kwargs )
10961122 finally :
1097- if root_dir is not None :
1123+ if save_cwd is not None :
10981124 if logger is not None :
10991125 logger .debug ("changing back to '%s'" , save_cwd )
11001126 os .chdir (save_cwd )
@@ -1207,6 +1233,11 @@ def _unpack_tarfile(filename, extract_dir):
12071233 finally :
12081234 tarobj .close ()
12091235
1236+ # Maps the name of the unpack format to a tuple containing:
1237+ # * extensions
1238+ # * the unpacking function
1239+ # * extra keyword arguments
1240+ # * description
12101241_UNPACK_FORMATS = {
12111242 'tar' : (['.tar' ], _unpack_tarfile , [], "uncompressed tar file" ),
12121243 'zip' : (['.zip' ], _unpack_zipfile , [], "ZIP file" ),
0 commit comments