blob: 045054b86a3b9e9869f6079b60ff0257ae750947 [file] [log] [blame]
Greg Warda82122b2000-02-17 23:56:15 +00001"""distutils.command.sdist
2
3Implements the Distutils 'sdist' command (create a source distribution)."""
4
5# created 1999/09/22, Greg Ward
6
Greg Ward3ce77fd2000-03-02 01:49:45 +00007__revision__ = "$Id$"
Greg Warda82122b2000-02-17 23:56:15 +00008
Greg Ward4571ac12000-07-30 01:05:02 +00009import sys, os, string
Greg Warda82122b2000-02-17 23:56:15 +000010from types import *
11from glob import glob
Greg Warda82122b2000-02-17 23:56:15 +000012from distutils.core import Command
Greg Wardf1fe1032000-06-08 00:14:18 +000013from distutils.util import \
Greg Ward4571ac12000-07-30 01:05:02 +000014 create_tree, remove_tree, newer, write_file, \
Greg Ward34593812000-06-24 01:23:37 +000015 check_archive_formats
Greg Warda82122b2000-02-17 23:56:15 +000016from distutils.text_file import TextFile
Greg Ward6a9a5452000-04-22 03:11:55 +000017from distutils.errors import DistutilsExecError, DistutilsOptionError
Greg Ward4571ac12000-07-30 01:05:02 +000018from distutils.filelist import FileList
Greg Warda82122b2000-02-17 23:56:15 +000019
20
Greg Ward34593812000-06-24 01:23:37 +000021def show_formats ():
22 """Print all possible values for the 'formats' option (used by
23 the "--help-formats" command-line option).
24 """
25 from distutils.fancy_getopt import FancyGetopt
26 from distutils.archive_util import ARCHIVE_FORMATS
27 formats=[]
28 for format in ARCHIVE_FORMATS.keys():
29 formats.append(("formats=" + format, None,
30 ARCHIVE_FORMATS[format][2]))
31 formats.sort()
32 pretty_printer = FancyGetopt(formats)
33 pretty_printer.print_help(
34 "List of available source distribution formats:")
35
36
Greg Ward1993f9a2000-02-18 00:13:53 +000037class sdist (Command):
Greg Warda82122b2000-02-17 23:56:15 +000038
39 description = "create a source distribution (tarball, zip file, etc.)"
40
Greg Wardbbeceea2000-02-18 00:25:39 +000041 user_options = [
42 ('template=', 't',
43 "name of manifest template file [default: MANIFEST.in]"),
44 ('manifest=', 'm',
45 "name of manifest file [default: MANIFEST]"),
46 ('use-defaults', None,
47 "include the default file set in the manifest "
48 "[default; disable with --no-defaults]"),
Greg Ward499822d2000-06-29 02:06:29 +000049 ('no-defaults', None,
50 "don't include the default file set"),
51 ('prune', None,
52 "specifically exclude files/directories that should not be "
53 "distributed (build tree, RCS/CVS dirs, etc.) "
54 "[default; disable with --no-prune]"),
55 ('no-prune', None,
56 "don't automatically exclude anything"),
Greg Ward839d5322000-04-26 01:14:33 +000057 ('manifest-only', 'o',
Greg Wardc3c8c6e2000-06-08 00:46:45 +000058 "just regenerate the manifest and then stop "
59 "(implies --force-manifest)"),
Greg Ward839d5322000-04-26 01:14:33 +000060 ('force-manifest', 'f',
Greg Wardbbeceea2000-02-18 00:25:39 +000061 "forcibly regenerate the manifest and carry on as usual"),
Greg Wardbbeceea2000-02-18 00:25:39 +000062 ('formats=', None,
Greg Ward2ff78872000-06-24 00:23:20 +000063 "formats for source distribution (comma-separated list)"),
Greg Wardbbeceea2000-02-18 00:25:39 +000064 ('keep-tree', 'k',
65 "keep the distribution tree around after creating " +
66 "archive file(s)"),
Greg Wardc0614102000-07-05 03:06:46 +000067 ('dist-dir=', 'd',
68 "directory to put the source distribution archive(s) in "
69 "[default: dist]"),
Greg Wardbbeceea2000-02-18 00:25:39 +000070 ]
Greg Wardf1fe1032000-06-08 00:14:18 +000071
72
Greg Ward9d17a7a2000-06-07 03:00:06 +000073 help_options = [
74 ('help-formats', None,
Greg Ward2ff78872000-06-24 00:23:20 +000075 "list available distribution formats", show_formats),
Greg Ward9d17a7a2000-06-07 03:00:06 +000076 ]
77
Greg Ward499822d2000-06-29 02:06:29 +000078 negative_opt = {'no-defaults': 'use-defaults',
79 'no-prune': 'prune' }
Greg Warda82122b2000-02-17 23:56:15 +000080
81 default_format = { 'posix': 'gztar',
82 'nt': 'zip' }
83
Greg Warde01149c2000-02-18 00:35:22 +000084 def initialize_options (self):
Greg Warda82122b2000-02-17 23:56:15 +000085 # 'template' and 'manifest' are, respectively, the names of
86 # the manifest template and manifest file.
87 self.template = None
88 self.manifest = None
89
90 # 'use_defaults': if true, we will include the default file set
91 # in the manifest
92 self.use_defaults = 1
Greg Ward499822d2000-06-29 02:06:29 +000093 self.prune = 1
Greg Warda82122b2000-02-17 23:56:15 +000094
95 self.manifest_only = 0
96 self.force_manifest = 0
97
98 self.formats = None
Greg Warda82122b2000-02-17 23:56:15 +000099 self.keep_tree = 0
Greg Wardc0614102000-07-05 03:06:46 +0000100 self.dist_dir = None
Greg Warda82122b2000-02-17 23:56:15 +0000101
Greg Wardd87eb732000-06-01 01:10:56 +0000102 self.archive_files = None
103
Greg Warda82122b2000-02-17 23:56:15 +0000104
Greg Warde01149c2000-02-18 00:35:22 +0000105 def finalize_options (self):
Greg Warda82122b2000-02-17 23:56:15 +0000106 if self.manifest is None:
107 self.manifest = "MANIFEST"
108 if self.template is None:
109 self.template = "MANIFEST.in"
110
Greg Ward62d5a572000-06-04 15:12:51 +0000111 self.ensure_string_list('formats')
Greg Warda82122b2000-02-17 23:56:15 +0000112 if self.formats is None:
113 try:
114 self.formats = [self.default_format[os.name]]
115 except KeyError:
116 raise DistutilsPlatformError, \
Greg Ward578c10d2000-03-31 02:50:04 +0000117 "don't know how to create source distributions " + \
118 "on platform %s" % os.name
Greg Warda82122b2000-02-17 23:56:15 +0000119
Greg Ward6a9a5452000-04-22 03:11:55 +0000120 bad_format = check_archive_formats (self.formats)
121 if bad_format:
122 raise DistutilsOptionError, \
123 "unknown archive format '%s'" % bad_format
124
Greg Wardc0614102000-07-05 03:06:46 +0000125 if self.dist_dir is None:
126 self.dist_dir = "dist"
127
Greg Warda82122b2000-02-17 23:56:15 +0000128
129 def run (self):
130
131 # 'files' is the list of files that will make up the manifest
132 self.files = []
133
134 # Ensure that all required meta-data is given; warn if not (but
135 # don't die, it's not *that* serious!)
136 self.check_metadata ()
137
138 # Do whatever it takes to get the list of files to process
139 # (process the manifest template, read an existing manifest,
140 # whatever). File list is put into 'self.files'.
141 self.get_file_list ()
142
143 # If user just wanted us to regenerate the manifest, stop now.
144 if self.manifest_only:
145 return
146
147 # Otherwise, go ahead and create the source distribution tarball,
148 # or zipfile, or whatever.
149 self.make_distribution ()
150
151
152 def check_metadata (self):
Greg Wardc3c8c6e2000-06-08 00:46:45 +0000153 """Ensure that all required elements of meta-data (name, version,
154 URL, (author and author_email) or (maintainer and
155 maintainer_email)) are supplied by the Distribution object; warn if
156 any are missing.
157 """
Greg Ward535f2d92000-04-21 04:37:12 +0000158 metadata = self.distribution.metadata
Greg Warda82122b2000-02-17 23:56:15 +0000159
160 missing = []
161 for attr in ('name', 'version', 'url'):
Greg Ward535f2d92000-04-21 04:37:12 +0000162 if not (hasattr (metadata, attr) and getattr (metadata, attr)):
Greg Warda82122b2000-02-17 23:56:15 +0000163 missing.append (attr)
164
165 if missing:
166 self.warn ("missing required meta-data: " +
167 string.join (missing, ", "))
168
Greg Ward535f2d92000-04-21 04:37:12 +0000169 if metadata.author:
170 if not metadata.author_email:
Greg Warda82122b2000-02-17 23:56:15 +0000171 self.warn ("missing meta-data: if 'author' supplied, " +
172 "'author_email' must be supplied too")
Greg Ward535f2d92000-04-21 04:37:12 +0000173 elif metadata.maintainer:
174 if not metadata.maintainer_email:
Greg Warda82122b2000-02-17 23:56:15 +0000175 self.warn ("missing meta-data: if 'maintainer' supplied, " +
176 "'maintainer_email' must be supplied too")
177 else:
178 self.warn ("missing meta-data: either (author and author_email) " +
179 "or (maintainer and maintainer_email) " +
180 "must be supplied")
181
182 # check_metadata ()
183
184
185 def get_file_list (self):
186 """Figure out the list of files to include in the source
Greg Warde0c8c2f2000-06-08 00:24:01 +0000187 distribution, and put it in 'self.files'. This might involve
188 reading the manifest template (and writing the manifest), or just
189 reading the manifest, or just using the default file set -- it all
190 depends on the user's options and the state of the filesystem.
191 """
Greg Wardb2db0eb2000-06-21 03:29:57 +0000192
193 # If we have a manifest template, see if it's newer than the
194 # manifest; if so, we'll regenerate the manifest.
Greg Warda82122b2000-02-17 23:56:15 +0000195 template_exists = os.path.isfile (self.template)
196 if template_exists:
197 template_newer = newer (self.template, self.manifest)
198
Greg Wardb2db0eb2000-06-21 03:29:57 +0000199 # The contents of the manifest file almost certainly depend on the
200 # setup script as well as the manifest template -- so if the setup
201 # script is newer than the manifest, we'll regenerate the manifest
202 # from the template. (Well, not quite: if we already have a
203 # manifest, but there's no template -- which will happen if the
204 # developer elects to generate a manifest some other way -- then we
205 # can't regenerate the manifest, so we don't.)
206 setup_newer = newer(sys.argv[0], self.manifest)
207
208 # cases:
209 # 1) no manifest, template exists: generate manifest
210 # (covered by 2a: no manifest == template newer)
211 # 2) manifest & template exist:
212 # 2a) template or setup script newer than manifest:
213 # regenerate manifest
214 # 2b) manifest newer than both:
215 # do nothing (unless --force or --manifest-only)
216 # 3) manifest exists, no template:
217 # do nothing (unless --force or --manifest-only)
218 # 4) no manifest, no template: generate w/ warning ("defaults only")
219
Greg Warda82122b2000-02-17 23:56:15 +0000220 # Regenerate the manifest if necessary (or if explicitly told to)
Greg Wardb2db0eb2000-06-21 03:29:57 +0000221 if ((template_exists and (template_newer or setup_newer)) or
222 self.force_manifest or self.manifest_only):
Greg Warda82122b2000-02-17 23:56:15 +0000223
224 if not template_exists:
225 self.warn (("manifest template '%s' does not exist " +
226 "(using default file list)") %
227 self.template)
228
229 # Add default file set to 'files'
230 if self.use_defaults:
Greg Ward4a7319c2000-06-08 00:52:52 +0000231 self.add_defaults ()
Greg Warda82122b2000-02-17 23:56:15 +0000232
233 # Read manifest template if it exists
234 if template_exists:
235 self.read_template ()
236
Greg Ward499822d2000-06-29 02:06:29 +0000237 # Prune away any directories that don't belong in the source
238 # distribution
239 if self.prune:
240 self.prune_file_list()
Greg Wardce15c6c2000-06-08 01:06:02 +0000241
Greg Warda82122b2000-02-17 23:56:15 +0000242 # File list now complete -- sort it so that higher-level files
243 # come first
244 sortable_files = map (os.path.split, self.files)
245 sortable_files.sort ()
246 self.files = []
247 for sort_tuple in sortable_files:
248 self.files.append (apply (os.path.join, sort_tuple))
249
250 # Remove duplicates from the file list
251 for i in range (len(self.files)-1, 0, -1):
252 if self.files[i] == self.files[i-1]:
253 del self.files[i]
254
255 # And write complete file list (including default file set) to
256 # the manifest.
257 self.write_manifest ()
258
259 # Don't regenerate the manifest, just read it in.
260 else:
261 self.read_manifest ()
262
263 # get_file_list ()
264
265
Greg Ward4a7319c2000-06-08 00:52:52 +0000266 def add_defaults (self):
Greg Wardc3c8c6e2000-06-08 00:46:45 +0000267 """Add all the default files to self.files:
268 - README or README.txt
269 - setup.py
270 - test/test*.py
271 - all pure Python modules mentioned in setup script
272 - all C sources listed as part of extensions or C libraries
273 in the setup script (doesn't catch C headers!)
274 Warns if (README or README.txt) or setup.py are missing; everything
275 else is optional.
276 """
Greg Ward14c8d052000-06-08 01:22:48 +0000277
278 # XXX name of setup script and config file should be taken
279 # programmatically from the Distribution object (except
280 # it doesn't have that capability... yet!)
Greg Warda82122b2000-02-17 23:56:15 +0000281 standards = [('README', 'README.txt'), 'setup.py']
282 for fn in standards:
283 if type (fn) is TupleType:
284 alts = fn
Greg Ward48401122000-02-24 03:17:43 +0000285 got_it = 0
Greg Warda82122b2000-02-17 23:56:15 +0000286 for fn in alts:
287 if os.path.exists (fn):
288 got_it = 1
289 self.files.append (fn)
290 break
291
292 if not got_it:
293 self.warn ("standard file not found: should have one of " +
294 string.join (alts, ', '))
295 else:
296 if os.path.exists (fn):
297 self.files.append (fn)
298 else:
299 self.warn ("standard file '%s' not found" % fn)
300
Greg Ward14c8d052000-06-08 01:22:48 +0000301 optional = ['test/test*.py', 'setup.cfg']
Greg Warda82122b2000-02-17 23:56:15 +0000302 for pattern in optional:
303 files = filter (os.path.isfile, glob (pattern))
304 if files:
305 self.files.extend (files)
306
Greg Ward578c10d2000-03-31 02:50:04 +0000307 if self.distribution.has_pure_modules():
Greg Ward4fb29e52000-05-27 17:27:23 +0000308 build_py = self.get_finalized_command ('build_py')
Greg Warda82122b2000-02-17 23:56:15 +0000309 self.files.extend (build_py.get_source_files ())
310
Greg Ward578c10d2000-03-31 02:50:04 +0000311 if self.distribution.has_ext_modules():
Greg Ward4fb29e52000-05-27 17:27:23 +0000312 build_ext = self.get_finalized_command ('build_ext')
Greg Warda82122b2000-02-17 23:56:15 +0000313 self.files.extend (build_ext.get_source_files ())
314
Greg Ward60908f12000-04-09 03:51:40 +0000315 if self.distribution.has_c_libraries():
Greg Ward4fb29e52000-05-27 17:27:23 +0000316 build_clib = self.get_finalized_command ('build_clib')
Greg Ward60908f12000-04-09 03:51:40 +0000317 self.files.extend (build_clib.get_source_files ())
318
Greg Ward4a7319c2000-06-08 00:52:52 +0000319 # add_defaults ()
320
Greg Warda82122b2000-02-17 23:56:15 +0000321
Greg Warda82122b2000-02-17 23:56:15 +0000322 def read_template (self):
323 """Read and parse the manifest template file named by
Greg Warde0c8c2f2000-06-08 00:24:01 +0000324 'self.template' (usually "MANIFEST.in"). Process all file
325 specifications (include and exclude) in the manifest template and
Greg Wardc3c8c6e2000-06-08 00:46:45 +0000326 update 'self.files' accordingly (filenames may be added to
327 or removed from 'self.files' based on the manifest template).
Greg Warde0c8c2f2000-06-08 00:24:01 +0000328 """
Greg Warda82122b2000-02-17 23:56:15 +0000329 assert self.files is not None and type (self.files) is ListType
Greg Wardf8b9e202000-06-08 00:08:14 +0000330 self.announce("reading manifest template '%s'" % self.template)
Greg Warda82122b2000-02-17 23:56:15 +0000331
332 template = TextFile (self.template,
333 strip_comments=1,
334 skip_blanks=1,
335 join_lines=1,
336 lstrip_ws=1,
337 rstrip_ws=1,
338 collapse_ws=1)
339
Greg Ward4571ac12000-07-30 01:05:02 +0000340 # if we give Template() a list, it modifies this list
341 filelist = FileList(files=self.files,
342 warn=self.warn,
343 debug_print=self.debug_print)
Greg Warda82122b2000-02-17 23:56:15 +0000344
345 while 1:
Greg Warda82122b2000-02-17 23:56:15 +0000346 line = template.readline()
347 if line is None: # end of file
348 break
349
Greg Ward4571ac12000-07-30 01:05:02 +0000350 filelist.process_template_line(line)
Greg Warda82122b2000-02-17 23:56:15 +0000351
352 # read_template ()
353
354
Greg Wardce15c6c2000-06-08 01:06:02 +0000355 def prune_file_list (self):
356 """Prune off branches that might slip into the file list as created
Greg Ward499822d2000-06-29 02:06:29 +0000357 by 'read_template()', but really don't belong there:
358 * the build tree (typically "build")
359 * the release tree itself (only an issue if we ran "sdist"
360 previously with --keep-tree, or it aborted)
361 * any RCS or CVS directories
Greg Wardce15c6c2000-06-08 01:06:02 +0000362 """
363 build = self.get_finalized_command('build')
364 base_dir = self.distribution.get_fullname()
Greg Wardce15c6c2000-06-08 01:06:02 +0000365
Greg Ward4571ac12000-07-30 01:05:02 +0000366 # if we give FileList a list, it modifies this list
367 filelist = FileList(files=self.files,
368 warn=self.warn,
369 debug_print=self.debug_print)
370 filelist.exclude_pattern(None, prefix=build.build_base)
371 filelist.exclude_pattern(None, prefix=base_dir)
372 filelist.exclude_pattern(r'/(RCS|CVS)/.*', is_regex=1)
Greg Wardf8b9e202000-06-08 00:08:14 +0000373
374
Greg Warda82122b2000-02-17 23:56:15 +0000375 def write_manifest (self):
Greg Warde0c8c2f2000-06-08 00:24:01 +0000376 """Write the file list in 'self.files' (presumably as filled in by
Greg Ward4a7319c2000-06-08 00:52:52 +0000377 'add_defaults()' and 'read_template()') to the manifest file named
Greg Warde0c8c2f2000-06-08 00:24:01 +0000378 by 'self.manifest'.
379 """
Greg Ward1b8e1d42000-04-26 01:12:40 +0000380 self.execute(write_file,
381 (self.manifest, self.files),
Greg Wardf8b9e202000-06-08 00:08:14 +0000382 "writing manifest file '%s'" % self.manifest)
Greg Warda82122b2000-02-17 23:56:15 +0000383
384 # write_manifest ()
385
386
387 def read_manifest (self):
Greg Warde0c8c2f2000-06-08 00:24:01 +0000388 """Read the manifest file (named by 'self.manifest') and use it to
389 fill in 'self.files', the list of files to include in the source
390 distribution.
391 """
Greg Wardf8b9e202000-06-08 00:08:14 +0000392 self.announce("reading manifest file '%s'" % self.manifest)
Greg Warda82122b2000-02-17 23:56:15 +0000393 manifest = open (self.manifest)
394 while 1:
395 line = manifest.readline ()
396 if line == '': # end of file
397 break
398 if line[-1] == '\n':
399 line = line[0:-1]
400 self.files.append (line)
401
402 # read_manifest ()
403
404
Greg Warda82122b2000-02-17 23:56:15 +0000405 def make_release_tree (self, base_dir, files):
Greg Wardc3c8c6e2000-06-08 00:46:45 +0000406 """Create the directory tree that will become the source
407 distribution archive. All directories implied by the filenames in
408 'files' are created under 'base_dir', and then we hard link or copy
409 (if hard linking is unavailable) those files into place.
410 Essentially, this duplicates the developer's source tree, but in a
411 directory named after the distribution, containing only the files
412 to be distributed.
413 """
Greg Ward578c10d2000-03-31 02:50:04 +0000414 # Create all the directories under 'base_dir' necessary to
415 # put 'files' there.
416 create_tree (base_dir, files,
417 verbose=self.verbose, dry_run=self.dry_run)
Greg Warda82122b2000-02-17 23:56:15 +0000418
419 # And walk over the list of files, either making a hard link (if
420 # os.link exists) to each one that doesn't already exist in its
421 # corresponding location under 'base_dir', or copying each file
422 # that's out-of-date in 'base_dir'. (Usually, all files will be
423 # out-of-date, because by default we blow away 'base_dir' when
424 # we're done making the distribution archives.)
425
Greg Ward578c10d2000-03-31 02:50:04 +0000426 if hasattr (os, 'link'): # can make hard links on this system
427 link = 'hard'
Greg Warda82122b2000-02-17 23:56:15 +0000428 msg = "making hard links in %s..." % base_dir
Greg Ward578c10d2000-03-31 02:50:04 +0000429 else: # nope, have to copy
430 link = None
Greg Warda82122b2000-02-17 23:56:15 +0000431 msg = "copying files to %s..." % base_dir
432
433 self.announce (msg)
434 for file in files:
435 dest = os.path.join (base_dir, file)
Greg Ward578c10d2000-03-31 02:50:04 +0000436 self.copy_file (file, dest, link=link)
Greg Warda82122b2000-02-17 23:56:15 +0000437
438 # make_release_tree ()
439
440
Greg Warda82122b2000-02-17 23:56:15 +0000441 def make_distribution (self):
Greg Wardc3c8c6e2000-06-08 00:46:45 +0000442 """Create the source distribution(s). First, we create the release
443 tree with 'make_release_tree()'; then, we create all required
444 archive files (according to 'self.formats') from the release tree.
445 Finally, we clean up by blowing away the release tree (unless
446 'self.keep_tree' is true). The list of archive files created is
447 stored so it can be retrieved later by 'get_archive_files()'.
448 """
Greg Ward578c10d2000-03-31 02:50:04 +0000449 # Don't warn about missing meta-data here -- should be (and is!)
450 # done elsewhere.
Greg Ward0ae7f762000-04-22 02:51:25 +0000451 base_dir = self.distribution.get_fullname()
Greg Wardc0614102000-07-05 03:06:46 +0000452 base_name = os.path.join(self.dist_dir, base_dir)
Greg Warda82122b2000-02-17 23:56:15 +0000453
Greg Warda82122b2000-02-17 23:56:15 +0000454 self.make_release_tree (base_dir, self.files)
Greg Wardd87eb732000-06-01 01:10:56 +0000455 archive_files = [] # remember names of files we create
Greg Wardc0614102000-07-05 03:06:46 +0000456 if self.dist_dir:
457 self.mkpath(self.dist_dir)
Greg Warda82122b2000-02-17 23:56:15 +0000458 for fmt in self.formats:
Greg Wardc0614102000-07-05 03:06:46 +0000459 file = self.make_archive (base_name, fmt, base_dir=base_dir)
Greg Wardd87eb732000-06-01 01:10:56 +0000460 archive_files.append(file)
461
462 self.archive_files = archive_files
Greg Warda82122b2000-02-17 23:56:15 +0000463
464 if not self.keep_tree:
Greg Ward2dc139c2000-03-18 15:43:42 +0000465 remove_tree (base_dir, self.verbose, self.dry_run)
Greg Warda82122b2000-02-17 23:56:15 +0000466
Greg Wardd87eb732000-06-01 01:10:56 +0000467 def get_archive_files (self):
468 """Return the list of archive files created when the command
469 was run, or None if the command hasn't run yet.
470 """
471 return self.archive_files
472
Greg Wardfcd974e2000-05-25 01:10:04 +0000473# class sdist