| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  | """distutils.archive_util
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Utility functions for creating archive files (tarballs, zip files, | 
					
						
							|  |  |  | that sort of thing)."""
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-19 13:12:28 +00:00
										 |  |  | # This module should be kept compatible with Python 1.5.2. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  | __revision__ = "$Id$" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | from distutils.errors import DistutilsExecError | 
					
						
							|  |  |  | from distutils.spawn import spawn | 
					
						
							| 
									
										
										
										
											2000-08-22 01:48:54 +00:00
										 |  |  | from distutils.dir_util import mkpath | 
					
						
							| 
									
										
										
										
											2002-06-04 20:14:43 +00:00
										 |  |  | from distutils import log | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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
 | 
					
						
							| 
									
										
										
										
											2000-09-26 02:13:49 +00:00
										 |  |  |     '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. | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  |     # 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", | 
					
						
							| 
									
										
										
										
											2000-04-25 01:38:20 +00:00
										 |  |  |                      'bzip2': '.bz2', | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  |                      'compress': ".Z" } | 
					
						
							| 
									
										
										
										
											2001-12-06 20:51:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-25 01:38:20 +00:00
										 |  |  |     # flags for compression program, each element of list will be an argument | 
					
						
							|  |  |  |     compress_flags = {'gzip': ["-f9"], | 
					
						
							|  |  |  |                       'compress': ["-f"], | 
					
						
							|  |  |  |                       'bzip2': ['-f9']} | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-25 01:38:20 +00:00
										 |  |  |     if compress is not None and compress not in compress_ext.keys(): | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  |         raise ValueError, \ | 
					
						
							|  |  |  |               "bad value for 'compress': must be None, 'gzip', or 'compress'" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     archive_name = base_name + ".tar" | 
					
						
							| 
									
										
										
										
											2002-06-04 20:14:43 +00:00
										 |  |  |     mkpath(os.path.dirname(archive_name), dry_run=dry_run) | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  |     cmd = ["tar", "-cf", archive_name, base_dir] | 
					
						
							| 
									
										
										
										
											2002-06-04 20:14:43 +00:00
										 |  |  |     spawn(cmd, dry_run=dry_run) | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if compress: | 
					
						
							| 
									
										
										
										
											2000-09-26 02:13:49 +00:00
										 |  |  |         spawn([compress] + compress_flags[compress] + [archive_name], | 
					
						
							| 
									
										
										
										
											2002-06-04 20:14:43 +00:00
										 |  |  |               dry_run=dry_run) | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  |         return archive_name + compress_ext[compress] | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         return archive_name | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # make_tarball () | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def make_zipfile (base_name, base_dir, verbose=0, dry_run=0): | 
					
						
							| 
									
										
										
										
											2000-09-26 02:13:49 +00:00
										 |  |  |     """Create a zip file from all the files under 'base_dir'.  The output
 | 
					
						
							| 
									
										
										
										
											2002-11-21 18:33:28 +00:00
										 |  |  |     zip file will be named 'base_dir' + ".zip".  Uses either the "zipfile" | 
					
						
							|  |  |  |     Python module (if available) or the InfoZIP "zip" utility (if installed | 
					
						
							|  |  |  |     and found on the default search path).  If neither tool is available, | 
					
						
							|  |  |  |     raises DistutilsExecError.  Returns the name of the output zip file. | 
					
						
							| 
									
										
										
										
											2000-09-26 02:13:49 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2002-11-21 18:33:28 +00:00
										 |  |  |     try: | 
					
						
							|  |  |  |         import zipfile | 
					
						
							|  |  |  |     except ImportError: | 
					
						
							|  |  |  |         zipfile = None | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  |     zip_filename = base_name + ".zip" | 
					
						
							| 
									
										
										
										
											2002-06-04 20:14:43 +00:00
										 |  |  |     mkpath(os.path.dirname(zip_filename), dry_run=dry_run) | 
					
						
							| 
									
										
										
										
											2002-11-21 18:33:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # If zipfile module is not available, try spawning an external | 
					
						
							|  |  |  |     # 'zip' command. | 
					
						
							|  |  |  |     if zipfile is None: | 
					
						
							|  |  |  |         if verbose: | 
					
						
							|  |  |  |             zipoptions = "-r" | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             zipoptions = "-rq" | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2002-11-21 18:33:28 +00:00
										 |  |  |             spawn(["zip", zipoptions, zip_filename, base_dir], | 
					
						
							|  |  |  |                   dry_run=dry_run) | 
					
						
							|  |  |  |         except DistutilsExecError: | 
					
						
							|  |  |  |             # XXX really should distinguish between "couldn't find | 
					
						
							|  |  |  |             # external 'zip' command" and "zip failed". | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  |             raise DistutilsExecError, \ | 
					
						
							| 
									
										
										
										
											2002-11-21 18:33:28 +00:00
										 |  |  |                   ("unable to create zip file '%s': " | 
					
						
							|  |  |  |                    "could neither import the 'zipfile' module nor " | 
					
						
							|  |  |  |                    "find a standalone zip utility") % zip_filename | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-21 18:33:28 +00:00
										 |  |  |     else: | 
					
						
							|  |  |  |         log.info("creating '%s' and adding '%s' to it", | 
					
						
							| 
									
										
										
										
											2002-06-04 20:14:43 +00:00
										 |  |  |                  zip_filename, base_dir) | 
					
						
							| 
									
										
										
										
											2002-11-21 18:33:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  |         def visit (z, dirname, names): | 
					
						
							|  |  |  |             for name in names: | 
					
						
							| 
									
										
										
										
											2000-05-31 02:17:19 +00:00
										 |  |  |                 path = os.path.normpath(os.path.join(dirname, name)) | 
					
						
							| 
									
										
										
										
											2000-09-26 02:13:49 +00:00
										 |  |  |                 if os.path.isfile(path): | 
					
						
							|  |  |  |                     z.write(path, path) | 
					
						
							| 
									
										
										
										
											2002-11-21 18:33:28 +00:00
										 |  |  |                     log.info("adding '%s'" % path) | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if not dry_run: | 
					
						
							| 
									
										
										
										
											2001-04-14 16:17:00 +00:00
										 |  |  |             z = zipfile.ZipFile(zip_filename, "w", | 
					
						
							| 
									
										
										
										
											2000-09-26 02:13:49 +00:00
										 |  |  |                                 compression=zipfile.ZIP_DEFLATED) | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-09-26 02:13:49 +00:00
										 |  |  |             os.path.walk(base_dir, visit, z) | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  |             z.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return zip_filename | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # make_zipfile () | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-22 03:09:56 +00:00
										 |  |  | ARCHIVE_FORMATS = { | 
					
						
							| 
									
										
										
										
											2000-06-24 00:23:20 +00:00
										 |  |  |     'gztar': (make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"), | 
					
						
							|  |  |  |     'bztar': (make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file"), | 
					
						
							|  |  |  |     'ztar':  (make_tarball, [('compress', 'compress')], "compressed tar file"), | 
					
						
							|  |  |  |     'tar':   (make_tarball, [('compress', None)], "uncompressed tar file"), | 
					
						
							| 
									
										
										
										
											2000-08-22 01:48:54 +00:00
										 |  |  |     'zip':   (make_zipfile, [],"ZIP file") | 
					
						
							| 
									
										
										
										
											2000-04-22 03:09:56 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def check_archive_formats (formats): | 
					
						
							|  |  |  |     for format in formats: | 
					
						
							|  |  |  |         if not ARCHIVE_FORMATS.has_key(format): | 
					
						
							|  |  |  |             return format | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  | 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 | 
					
						
							| 
									
										
										
										
											2000-06-01 01:07:55 +00:00
										 |  |  |     to the current directory.  Returns the name of the archive file. | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  |     save_cwd = os.getcwd() | 
					
						
							|  |  |  |     if root_dir is not None: | 
					
						
							| 
									
										
										
										
											2002-06-04 20:14:43 +00:00
										 |  |  |         log.debug("changing into '%s'", root_dir) | 
					
						
							| 
									
										
										
										
											2000-09-26 02:13:49 +00:00
										 |  |  |         base_name = os.path.abspath(base_name) | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  |         if not dry_run: | 
					
						
							| 
									
										
										
										
											2000-09-26 02:13:49 +00:00
										 |  |  |             os.chdir(root_dir) | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if base_dir is None: | 
					
						
							|  |  |  |         base_dir = os.curdir | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-04 20:14:43 +00:00
										 |  |  |     kwargs = { 'dry_run': dry_run } | 
					
						
							| 
									
										
										
										
											2001-12-06 20:51:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-22 03:09:56 +00:00
										 |  |  |     try: | 
					
						
							|  |  |  |         format_info = ARCHIVE_FORMATS[format] | 
					
						
							|  |  |  |     except KeyError: | 
					
						
							|  |  |  |         raise ValueError, "unknown archive format '%s'" % format | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-22 03:09:56 +00:00
										 |  |  |     func = format_info[0] | 
					
						
							|  |  |  |     for (arg,val) in format_info[1]: | 
					
						
							|  |  |  |         kwargs[arg] = val | 
					
						
							| 
									
										
										
										
											2000-09-26 02:13:49 +00:00
										 |  |  |     filename = apply(func, (base_name, base_dir), kwargs) | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if root_dir is not None: | 
					
						
							| 
									
										
										
										
											2002-06-04 20:14:43 +00:00
										 |  |  |         log.debug("changing back to '%s'", save_cwd) | 
					
						
							| 
									
										
										
										
											2000-09-26 02:13:49 +00:00
										 |  |  |         os.chdir(save_cwd) | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-06-01 01:07:55 +00:00
										 |  |  |     return filename | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-04 02:05:59 +00:00
										 |  |  | # make_archive () |