mirror of
				https://github.com/python/cpython.git
				synced 2025-10-25 10:44:55 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			170 lines
		
	
	
	
		
			6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
	
		
			6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """distutils.archive_util
 | |
| 
 | |
| Utility functions for creating archive files (tarballs, zip files,
 | |
| that sort of thing)."""
 | |
| 
 | |
| # created 2000/04/03, Greg Ward (extracted from util.py)
 | |
| 
 | |
| __revision__ = "$Id$"
 | |
| 
 | |
| import os
 | |
| from distutils.errors import DistutilsExecError
 | |
| from distutils.spawn import spawn
 | |
| 
 | |
| 
 | |
| def make_tarball (base_name, base_dir, compress="gzip",
 | |
|                   verbose=0, dry_run=0):
 | |
|     """Create a (possibly compressed) tar file from all the files under
 | |
|        'base_dir'.  'compress' must be "gzip" (the default), "compress",
 | |
|        "bzip2", or None.  Both "tar" and the compression utility named by
 | |
|        'compress' must be on the default program search path, so this is
 | |
|        probably Unix-specific.  The output tar file will be named 'base_dir'
 | |
|        + ".tar", possibly plus the appropriate compression extension (".gz",
 | |
|        ".bz2" or ".Z").  Return the output filename."""
 | |
| 
 | |
|     # XXX GNU tar 1.13 has a nifty option to add a prefix directory.
 | |
|     # It's pretty new, though, so we certainly can't require it --
 | |
|     # but it would be nice to take advantage of it to skip the
 | |
|     # "create a tree of hardlinks" step!  (Would also be nice to
 | |
|     # detect GNU tar to use its 'z' option and save a step.)
 | |
| 
 | |
|     compress_ext = { 'gzip': ".gz",
 | |
|                      'bzip2': '.bz2',
 | |
|                      'compress': ".Z" }
 | |
|     
 | |
|     # flags for compression program, each element of list will be an argument
 | |
|     compress_flags = {'gzip': ["-f9"],
 | |
|                       'compress': ["-f"],
 | |
|                       'bzip2': ['-f9']}
 | |
| 
 | |
|     if compress is not None and compress not in compress_ext.keys():
 | |
|         raise ValueError, \
 | |
|               "bad value for 'compress': must be None, 'gzip', or 'compress'"
 | |
| 
 | |
|     archive_name = base_name + ".tar"
 | |
|     cmd = ["tar", "-cf", archive_name, base_dir]
 | |
|     spawn (cmd, verbose=verbose, dry_run=dry_run)
 | |
| 
 | |
|     if compress:
 | |
|         spawn ([compress] + compress_flags[compress] + [archive_name],
 | |
|                verbose=verbose, dry_run=dry_run)
 | |
|         return archive_name + compress_ext[compress]
 | |
|     else:
 | |
|         return archive_name
 | |
| 
 | |
| # make_tarball ()
 | |
| 
 | |
| 
 | |
| def make_zipfile (base_name, base_dir, verbose=0, dry_run=0):
 | |
|     """Create a zip file from all the files under 'base_dir'.  The
 | |
|        output zip file will be named 'base_dir' + ".zip".  Uses either the
 | |
|        InfoZIP "zip" utility (if installed and found on the default search
 | |
|        path) or the "zipfile" Python module (if available).  If neither
 | |
|        tool is available, raises DistutilsExecError.  Returns the name
 | |
|        of the output zip file."""
 | |
| 
 | |
|     # This initially assumed the Unix 'zip' utility -- but
 | |
|     # apparently InfoZIP's zip.exe works the same under Windows, so
 | |
|     # no changes needed!
 | |
| 
 | |
|     zip_filename = base_name + ".zip"
 | |
|     try:
 | |
|         spawn (["zip", "-rq", zip_filename, base_dir],
 | |
|                verbose=verbose, dry_run=dry_run)
 | |
|     except DistutilsExecError:
 | |
| 
 | |
|         # XXX really should distinguish between "couldn't find
 | |
|         # external 'zip' command" and "zip failed" -- shouldn't try
 | |
|         # again in the latter case.  (I think fixing this will
 | |
|         # require some cooperation from the spawn module -- perhaps
 | |
|         # a utility function to search the path, so we can fallback
 | |
|         # on zipfile.py without the failed spawn.)
 | |
|         try:
 | |
|             import zipfile
 | |
|         except ImportError:
 | |
|             raise DistutilsExecError, \
 | |
|                   ("unable to create zip file '%s': " + 
 | |
|                    "could neither find a standalone zip utility nor " +
 | |
|                    "import the 'zipfile' module") % zip_filename
 | |
| 
 | |
|         if verbose:
 | |
|             print "creating '%s' and adding '%s' to it" % \
 | |
|                   (zip_filename, base_dir)
 | |
| 
 | |
|         def visit (z, dirname, names):
 | |
|             for name in names:
 | |
|                 path = os.path.normpath(os.path.join(dirname, name))
 | |
|                 if os.path.isfile (path):
 | |
|                     z.write (path, path)
 | |
| 
 | |
|         if not dry_run:
 | |
|             z = zipfile.ZipFile (zip_filename, "wb",
 | |
|                                  compression=zipfile.ZIP_DEFLATED)
 | |
| 
 | |
|             os.path.walk (base_dir, visit, z)
 | |
|             z.close()
 | |
| 
 | |
|     return zip_filename
 | |
| 
 | |
| # make_zipfile ()
 | |
| 
 | |
| 
 | |
| ARCHIVE_FORMATS = {
 | |
|     'gztar': (make_tarball, [('compress', 'gzip')]),
 | |
|     'bztar': (make_tarball, [('compress', 'bzip2')]),
 | |
|     'ztar':  (make_tarball, [('compress', 'compress')]),
 | |
|     'tar':   (make_tarball, [('compress', None)]),
 | |
|     'zip':   (make_zipfile, [])
 | |
|     }
 | |
| 
 | |
| def check_archive_formats (formats):
 | |
|     for format in formats:
 | |
|         if not ARCHIVE_FORMATS.has_key(format):
 | |
|             return format
 | |
|     else:
 | |
|         return None
 | |
| 
 | |
| def make_archive (base_name, format,
 | |
|                   root_dir=None, base_dir=None,
 | |
|                   verbose=0, dry_run=0):
 | |
| 
 | |
|     """Create an archive file (eg. zip or tar).  'base_name' is the name
 | |
|     of the file to create, minus any format-specific extension; 'format'
 | |
|     is the archive format: one of "zip", "tar", "ztar", or "gztar".
 | |
|     'root_dir' is a directory that will be the root directory of the
 | |
|     archive; ie. we typically chdir into 'root_dir' before creating the
 | |
|     archive.  'base_dir' is the directory where we start archiving from;
 | |
|     ie. 'base_dir' will be the common prefix of all files and
 | |
|     directories in the archive.  'root_dir' and 'base_dir' both default
 | |
|     to the current directory."""
 | |
| 
 | |
|     save_cwd = os.getcwd()
 | |
|     if root_dir is not None:
 | |
|         if verbose:
 | |
|             print "changing into '%s'" % root_dir
 | |
|         base_name = os.path.abspath (base_name)
 | |
|         if not dry_run:
 | |
|             os.chdir (root_dir)
 | |
| 
 | |
|     if base_dir is None:
 | |
|         base_dir = os.curdir
 | |
| 
 | |
|     kwargs = { 'verbose': verbose,
 | |
|                'dry_run': dry_run }
 | |
|     
 | |
|     try:
 | |
|         format_info = ARCHIVE_FORMATS[format]
 | |
|     except KeyError:
 | |
|         raise ValueError, "unknown archive format '%s'" % format
 | |
| 
 | |
|     func = format_info[0]
 | |
|     for (arg,val) in format_info[1]:
 | |
|         kwargs[arg] = val
 | |
|     apply (func, (base_name, base_dir), kwargs)
 | |
| 
 | |
|     if root_dir is not None:
 | |
|         if verbose:
 | |
|             print "changing back to '%s'" % save_cwd
 | |
|         os.chdir (save_cwd)
 | |
| 
 | |
| # make_archive ()
 | 
