Merge lp:~jelmer/bzr-builddeb/lazy-1 into lp:~bzr-builddeb-hackers/bzr-builddeb/trunk-old

Proposed by Jelmer Vernooij
Status: Merged
Merge reported by: James Westby
Merged at revision: not available
Proposed branch: lp:~jelmer/bzr-builddeb/lazy-1
Merge into: lp:~bzr-builddeb-hackers/bzr-builddeb/trunk-old
Diff against target: None lines
To merge this branch: bzr merge lp:~jelmer/bzr-builddeb/lazy-1
To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

The attached patch improves the import overhead of bzr-builddeb by:

 * lazily registering all commands (moved to cmds.py)
 * using absolute imports everywhere, and no longer updating sys.path to
   include "bzrlib.plugins.builddeb"

It seems intrusive, but mainly just moves code from __init__.py to cmds.py.

In practice, this means having bzr-builddeb enabled will only load the
__init__.py file if you're not using it.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file '__init__.py'
--- __init__.py 2008-12-02 16:42:32 +0000
+++ __init__.py 2009-02-12 14:45:56 +0000
@@ -24,84 +24,24 @@
24"""bzr-builddeb - manage packages in a Bazaar branch."""24"""bzr-builddeb - manage packages in a Bazaar branch."""
2525
26import os26import os
27import shutil27
28import subprocess28from bzrlib.commands import plugin_cmds
29import tempfile
30import urlparse
31
32from debian_bundle.changelog import Version
33
34from bzrlib import bzrdir
35from bzrlib.branch import Branch
36from bzrlib.commands import Command, register_command
37from bzrlib.config import ConfigObj
38from bzrlib.directory_service import directories29from bzrlib.directory_service import directories
39from bzrlib.errors import (BzrCommandError,
40 NoSuchFile,
41 NoWorkingTree,
42 NotBranchError,
43 FileExists,
44 AlreadyBranchError,
45 )
46from bzrlib.option import Option
47from bzrlib.trace import info, warning
48from bzrlib.transport import get_transport
49from bzrlib import urlutils
50from bzrlib.workingtree import WorkingTree
5130
52from bzrlib.plugins.builddeb.builder import (DebBuild,
53 DebMergeBuild,
54 DebNativeBuild,
55 DebSplitBuild,
56 DebMergeExportUpstreamBuild,
57 DebExportUpstreamBuild,
58 )
59from bzrlib.plugins.builddeb.config import DebBuildConfig
60from bzrlib.plugins.builddeb.errors import (StopBuild,
61 )
62from bzrlib.plugins.builddeb.hooks import run_hook
63from bzrlib.plugins.builddeb.import_dsc import (
64 DistributionBranch,
65 DistributionBranchSet,
66 DscCache,
67 DscComp,
68 )
69from bzrlib.plugins.builddeb.properties import BuildProperties
70from bzrlib.plugins.builddeb import revspec
71from bzrlib.plugins.builddeb.util import (find_changelog,
72 lookup_distribution,
73 suite_to_distribution,
74 tarball_name,
75 )
76from bzrlib.plugins.builddeb.version import version_info31from bzrlib.plugins.builddeb.version import version_info
7732
33commands = {
34 "test_builddeb": [],
35 "builddeb": ["bd"],
36 "merge_upstream": ["mu"],
37 "import_dsc": [],
38 "bd_do": [],
39 "mark_uploaded": []
40 }
7841
79dont_purge_opt = Option('dont-purge',42for command, aliases in commands.iteritems():
80 help="Don't purge the build directory after building")43 plugin_cmds.register_lazy('cmd_' + command, aliases,
81result_opt = Option('result-dir',44 "bzrlib.plugins.builddeb.cmds")
82 help="Directory in which to place the resulting package files", type=str)
83builder_opt = Option('builder',
84 help="Command to build the package", type=str)
85merge_opt = Option('merge',
86 help='Merge the debian part of the source in to the upstream tarball')
87build_dir_opt = Option('build-dir',
88 help="The dir to use for building", type=str)
89orig_dir_opt = Option('orig-dir',
90 help="Directory containing the .orig.tar.gz files. For use when only"
91 +"debian/ is versioned", type=str)
92native_opt = Option('native',
93 help="Build a native package")
94split_opt = Option('split',
95 help="Automatically create an .orig.tar.gz from a full source branch")
96export_upstream_opt = Option('export-upstream',
97 help="Create the .orig.tar.gz from a bzr branch before building",
98 type=unicode)
99export_upstream_revision_opt = Option('export-upstream-revision',
100 help="Select the upstream revision that will be exported",
101 type=str)
102no_user_conf_opt = Option('no-user-config',
103 help="Stop builddeb from reading the user's config file. Used mainly "
104 "for tests")
10545
106builddeb_dir = '.bzr-builddeb'46builddeb_dir = '.bzr-builddeb'
107default_conf = os.path.join(builddeb_dir, 'default.conf')47default_conf = os.path.join(builddeb_dir, 'default.conf')
@@ -113,680 +53,17 @@
113default_result_dir = '..'53default_result_dir = '..'
11454
11555
116def debuild_config(tree, working_tree, no_user_config):56directories.register_lazy("deb:", 'bzrlib.plugins.builddeb.directory',
117 """Obtain the Debuild configuration object.57 'VcsDirectory',
11858 "Directory that uses Debian Vcs-* control fields to look up branches")
119 :param tree: A Tree object, can be a WorkingTree or RevisionTree.59
120 :param working_tree: Whether the tree is a working tree.60try:
121 :param no_user_config: Whether to skip the user configuration61 from bzrlib.revisionspec import revspec_registry
122 """62 revspec_registry.register_lazy("package:", "bzrlib.plugins.builddeb.revspec", "RevisionSpec_package")
123 config_files = []63except ImportError:
124 user_config = None64 from bzrlib.revisionspec import SPEC_TYPES
125 if (working_tree and 65 from bzrlib.plugins.builddeb.revspec import RevisionSpec_package
126 tree.has_filename(local_conf) and tree.path2id(local_conf) is None):66 SPEC_TYPES.append(RevisionSpec_package)
127 config_files.append((tree.get_file_byname(local_conf), True))
128 if not no_user_config:
129 config_files.append((global_conf, True))
130 user_config = global_conf
131 if tree.path2id(default_conf):
132 config_files.append((tree.get_file(tree.path2id(default_conf)), False))
133 config = DebBuildConfig(config_files)
134 config.set_user_config(user_config)
135 return config
136
137
138class cmd_builddeb(Command):
139 """Builds a Debian package from a branch.
140
141 If BRANCH is specified it is assumed that the branch you wish to build is
142 located there. If it is not specified then the current directory is used.
143
144 By default the if a working tree is found it is used to build and otherwise
145 the last committed revision was used. To force building the last committed
146 revision use --revision -1. You can specify any other revision using the
147 --revision option.
148
149 If you only wish to export the package, and not build it (especially useful
150 for merge mode), use --export-only.
151
152 To leave the build directory when the build is completed use --dont-purge.
153
154 Specify the command to use when building using the --builder option,
155
156 You can also specify directories to use for different things. --build-dir
157 is the directory to build the packages beneath, which defaults to
158 '../build-area'. '--orig-dir' specifies the directory that contains the
159 .orig.tar.gz files , which defaults to '..'. '--result-dir' specifies where
160 the resulting package files should be placed, which defaults to '..'.
161 --result-dir will have problems if you use a build command that places
162 the results in a different directory.
163
164 The --reuse option will be useful if you are in merge mode, and the upstream
165 tarball is very large. It attempts to reuse a build directory from an earlier
166 build. It will fail if one doesn't exist, but you can create one by using
167 --export-only.
168
169 --quick allows you to define a quick-builder in your configuration files,
170 which will be used when this option is passed. It defaults to 'fakeroot
171 debian/rules binary'. It is overriden if --builder is passed. Using this
172 and --reuse allows for fast rebuilds.
173
174 --source allows you to build a source package without having to
175 specify a builder to do so with --builder. It uses the source-builder
176 option from your configuration files, and defaults to 'dpkg-buildpackage
177 -rfakeroot -uc -us -S'. It is overriden if either --builder or --quick are
178 used.
179
180 """
181 working_tree_opt = Option('working-tree', help="This option has no effect",
182 short_name='w')
183 export_only_opt = Option('export-only', help="Export only, don't build",
184 short_name='e')
185 use_existing_opt = Option('use-existing',
186 help="Use an existing build directory")
187 ignore_changes_opt = Option('ignore-changes',
188 help="This option has no effect")
189 ignore_unknowns_opt = Option('ignore-unknowns',
190 help="Ignore any unknown files, but still fail if there are any changes"
191 +", the default is to fail if there are unknowns as well.")
192 quick_opt = Option('quick', help="Quickly build the package, uses "
193 +"quick-builder, which defaults to \"fakeroot "
194 +"debian/rules binary\"")
195 reuse_opt = Option('reuse', help="Try to avoid expoting too much on each "
196 +"build. Only works in merge mode; it saves unpacking "
197 +"the upstream tarball each time. Implies --dont-purge "
198 +"and --use-existing")
199 source_opt = Option('source', help="Build a source package, uses "
200 +"source-builder, which defaults to \"dpkg-buildpackage "
201 +"-rfakeroot -uc -us -S\"", short_name='S')
202 result_compat_opt = Option('result', help="Present only for compatibility "
203 "with bzr-builddeb <= 2.0. Use --result-dir instead.")
204 takes_args = ['branch?']
205 aliases = ['bd']
206 takes_options = [working_tree_opt, export_only_opt,
207 dont_purge_opt, use_existing_opt, result_opt, builder_opt, merge_opt,
208 build_dir_opt, orig_dir_opt, ignore_changes_opt, ignore_unknowns_opt,
209 quick_opt, reuse_opt, native_opt, split_opt, export_upstream_opt,
210 export_upstream_revision_opt, source_opt, 'revision',
211 no_user_conf_opt, result_compat_opt]
212
213 def run(self, branch=None, verbose=False, working_tree=False,
214 export_only=False, dont_purge=False, use_existing=False,
215 result_dir=None, builder=None, merge=False, build_dir=None,
216 orig_dir=None, ignore_changes=False, ignore_unknowns=False,
217 quick=False, reuse=False, native=False, split=False,
218 export_upstream=None, export_upstream_revision=None,
219 source=False, revision=None, no_user_config=False, result=None):
220
221 if branch is None:
222 branch = "."
223
224 # Find out if we were passed a local or remote branch
225 is_local = urlparse.urlsplit(branch)[0] in ('', 'file')
226 if is_local:
227 os.chdir(branch)
228
229 try:
230 tree, _ = WorkingTree.open_containing(branch)
231 branch = tree.branch
232 except NoWorkingTree:
233 tree = None
234 branch, _ = Branch.open_containing(branch)
235
236 if revision is None and tree is not None:
237 info("Building using working tree")
238 working_tree = True
239 else:
240 if revision is None:
241 revid = branch.last_revision()
242 elif len(revision) == 1:
243 revid = revision[0].in_history(branch).rev_id
244 else:
245 raise BzrCommandError('bzr builddeb --revision takes exactly one '
246 'revision specifier.')
247 info("Building branch from revision %s", revid)
248 tree = branch.repository.revision_tree(revid)
249 working_tree = False
250
251 tree.lock_read()
252 try:
253 config = debuild_config(tree, working_tree, no_user_config)
254
255 if reuse:
256 info("Reusing existing build dir")
257 dont_purge = True
258 use_existing = True
259
260 if not merge:
261 merge = config.merge
262
263 if merge:
264 info("Running in merge mode")
265 else:
266 if not native:
267 native = config.native
268 if native:
269 info("Running in native mode")
270 else:
271 if not split:
272 split = config.split
273 if split:
274 info("Running in split mode")
275
276 if builder is None:
277 if quick:
278 builder = config.quick_builder
279 if builder is None:
280 builder = "fakeroot debian/rules binary"
281 else:
282 if source:
283 builder = config.source_builder
284 if builder is None:
285 builder = "dpkg-buildpackage -rfakeroot -uc -us -S"
286 else:
287 builder = config.builder
288 if builder is None:
289 builder = "dpkg-buildpackage -uc -us -rfakeroot"
290
291 (changelog, larstiq) = find_changelog(tree, merge)
292
293 config.set_version(changelog.version)
294
295 if export_upstream is None:
296 export_upstream = config.export_upstream
297
298 if export_upstream_revision is None:
299 export_upstream_revision = config.export_upstream_revision
300
301 if result_dir is None:
302 result_dir = result
303
304 if result_dir is None:
305 if is_local:
306 result_dir = config.result_dir
307 else:
308 result_dir = config.user_result_dir
309 if result_dir is not None:
310 result_dir = os.path.realpath(result_dir)
311
312 if build_dir is None:
313 if is_local:
314 build_dir = config.build_dir or default_build_dir
315 else:
316 build_dir = config.user_build_dir or 'build-area'
317
318 if orig_dir is None:
319 if is_local:
320 orig_dir = config.orig_dir or default_orig_dir
321 else:
322 orig_dir = config.user_orig_dir or 'build-area'
323
324 properties = BuildProperties(changelog, build_dir, orig_dir, larstiq)
325
326 if merge:
327 if export_upstream is None:
328 build = DebMergeBuild(properties, tree, _is_working_tree=working_tree)
329 else:
330 prepull_upstream = config.prepull_upstream
331 stop_on_no_change = config.prepull_upstream_stop
332 build = DebMergeExportUpstreamBuild(properties, tree, export_upstream,
333 export_upstream_revision,
334 prepull_upstream,
335 stop_on_no_change,
336 _is_working_tree=working_tree)
337 elif native:
338 build = DebNativeBuild(properties, tree, _is_working_tree=working_tree)
339 elif split:
340 build = DebSplitBuild(properties, tree, _is_working_tree=working_tree)
341 else:
342 if export_upstream is None:
343 build = DebBuild(properties, tree, _is_working_tree=working_tree)
344 else:
345 prepull_upstream = config.prepull_upstream
346 stop_on_no_change = config.prepull_upstream_stop
347 build = DebExportUpstreamBuild(properties, tree, export_upstream,
348 export_upstream_revision,
349 prepull_upstream,
350 stop_on_no_change,
351 _is_working_tree=working_tree)
352
353 build.prepare(use_existing)
354
355 run_hook(tree, 'pre-export', config)
356
357 try:
358 build.export(use_existing)
359 except StopBuild, e:
360 warning('Stopping the build: %s.', e.reason)
361 return
362
363 if not export_only:
364 run_hook(tree, 'pre-build', config, wd=properties.source_dir())
365 build.build(builder)
366 run_hook(tree, 'post-build', config, wd=properties.source_dir())
367 if not dont_purge:
368 build.clean()
369 arch = None
370 if source:
371 arch = "source"
372 if result_dir is not None:
373 build.move_result(result_dir, arch=arch)
374 else:
375 build.move_result(default_result_dir, allow_missing=True, arch=arch)
376 finally:
377 tree.unlock()
378
379
380register_command(cmd_builddeb)
381
382
383class cmd_merge_upstream(Command):
384 """Merges a new upstream version into the current branch.
385
386 Takes a new upstream version and merges it in to your branch, so that your
387 packaging changes are applied to the new version.
388
389 You must supply the source to import from, and the version number of the
390 new release. The source can be a .tar.gz, .tar, .tar.bz2, .tgz or .zip
391 archive, or a directory. The source may also be a remote file.
392
393 You must supply the version number of the new upstream release
394 using --version, and the target distribution using --distribution.
395 The target distribtution is the distribution that you aim to upload to,
396 one of "debian" or "ubuntu". You can also specify the target used in
397 the changelog, e.g. "unstable", and it will be resolved automatically.
398
399 If there is no debian changelog in the branch to retrieve the package
400 name from then you must pass the --package option. If this version
401 will change the name of the source package then you can use this option
402 to set the new name.
403 """
404 takes_args = ['location?']
405 aliases = ['mu']
406
407 package_opt = Option('package', help="The name of the source package.",
408 type=str)
409 version_opt = Option('version', help="The version number of this release.",
410 type=str)
411 distribution_opt = Option('distribution', help="The distribution that "
412 "this release is targetted at", type=str)
413 directory_opt = Option('directory', help='Working tree into which to merge.',
414 short_name='d', type=unicode)
415
416 takes_options = [package_opt, no_user_conf_opt, version_opt,
417 distribution_opt, directory_opt, 'revision']
418
419 def run(self, location=None, version=None, distribution=None, package=None,
420 no_user_config=None, directory=".", revision=None):
421 from bzrlib.plugins.builddeb.errors import MissingChangelogError
422 from bzrlib.plugins.builddeb.repack_tarball import repack_tarball
423 from bzrlib.plugins.builddeb.merge_upstream import merge_upstream_branch
424 tree, _ = WorkingTree.open_containing(directory)
425 tree.lock_write()
426 try:
427 # Check for uncommitted changes.
428 if tree.changes_from(tree.basis_tree()).has_changed():
429 raise BzrCommandError("There are uncommitted changes in the "
430 "working tree. You must commit before using this "
431 "command.")
432 config = debuild_config(tree, tree, no_user_config)
433 if config.merge:
434 raise BzrCommandError("Merge upstream in merge mode is not "
435 "yet supported.")
436 if config.native:
437 raise BzrCommandError("Merge upstream in native mode is not "
438 "yet supported.")
439 if config.export_upstream and location is None:
440 location = config.export_upstream
441 if config.split:
442 raise BzrCommandError("Split mode is not yet supported.")
443
444 if location is None:
445 raise BzrCommandError("No location specified to merge")
446 try:
447 changelog = find_changelog(tree, False)[0]
448 current_version = changelog.version
449 if package is None:
450 package = changelog.package
451 except MissingChangelogError:
452 current_version = None
453
454 if package is None:
455 raise BzrCommandError("You did not specify --package, and "
456 "there is no changelog from which to determine the "
457 "package name, which is needed to know the name to "
458 "give the .orig.tar.gz. Please specify --package.")
459
460 try:
461 upstream_branch = Branch.open(location)
462 except NotBranchError:
463 upstream_branch = None
464
465 if upstream_branch is None:
466 if version is None:
467 raise BzrCommandError("You must specify the version number using "
468 "--version.")
469 version = Version(version)
470 if distribution is None:
471 raise BzrCommandError("You must specify the target distribution "
472 "using --distribution.")
473 if revision is not None:
474 raise BzrCommandError("--revision is not allowed when merging a tarball")
475
476 orig_dir = config.orig_dir or default_orig_dir
477 orig_dir = os.path.join(tree.basedir, orig_dir)
478 dest_name = tarball_name(package, version.upstream_version)
479 try:
480 repack_tarball(location, dest_name, target_dir=orig_dir)
481 except FileExists:
482 raise BzrCommandError("The target file %s already exists, and is either "
483 "different to the new upstream tarball, or they "
484 "are of different formats. Either delete the target "
485 "file, or use it as the argument to import.")
486 tarball_filename = os.path.join(orig_dir, dest_name)
487 distribution = distribution.lower()
488 distribution_name = lookup_distribution(distribution)
489 if distribution_name is None:
490 raise BzrCommandError("Unknown target distribution: %s" \
491 % distribution)
492 db = DistributionBranch(distribution_name, tree.branch, None,
493 tree=tree)
494 dbs = DistributionBranchSet()
495 dbs.add_branch(db)
496 conflicts = db.merge_upstream(tarball_filename, version,
497 current_version)
498 else:
499 if revision is not None:
500 if len(revision) > 1:
501 raise BzrCommandError("merge-upstream takes only a single --revision")
502 upstream_revspec = revision[0]
503 else:
504 upstream_revspec = None
505 version = merge_upstream_branch(tree, upstream_branch, package,
506 upstream_revspec, version)
507 info("Using version string %s for upstream branch." % (version))
508 finally:
509 tree.unlock()
510
511 if "~bzr" in str(version) or "+bzr" in str(version):
512 entry_description = "New upstream snapshot."
513 else:
514 entry_description = "New upstream release."
515
516 info("The new upstream version has been imported. You should "
517 "now update the changelog (try dch -v %s-1 \"%s\"), resolve any "
518 "conflicts, and then commit." % (str(version), entry_description))
519
520
521register_command(cmd_merge_upstream)
522
523
524class cmd_import_dsc(Command):
525 """Import a series of source packages.
526
527 Provide a number of source packages (.dsc files), and they will
528 be imported to create a branch with history that reflects those
529 packages.
530
531 The first argument is the distribution that these source packages
532 were uploaded to, one of "debian" or "ubuntu". It can also
533 be the target distribution from the changelog, e.g. "unstable",
534 which will be resolved to the correct distribution.
535
536 You can also specify a file (possibly remote) that contains a
537 list of source packages (.dsc files) to import using the --file
538 option. Each line is taken to be a URI or path to import. The
539 sources specified in the file are used in addition to those
540 specified on the command line.
541
542 If you have an existing branch containing packaging and you want to
543 import a .dsc from an upload done from outside the version control
544 system you can use this command.
545 """
546
547 takes_args = ['files*']
548
549 filename_opt = Option('file', help="File containing URIs of source "
550 "packages to import.", type=str, argname="filename",
551 short_name='F')
552 distribution_opt = Option('distribution', help="The distribution that "
553 "these packages were uploaded to.", type=str)
554
555 takes_options = [filename_opt, distribution_opt]
556
557 def import_many(self, db, files_list, orig_target):
558 cache = DscCache()
559 files_list.sort(cmp=DscComp(cache).cmp)
560 if not os.path.exists(orig_target):
561 os.makedirs(orig_target)
562 for dscname in files_list:
563 dsc = cache.get_dsc(dscname)
564 def get_dsc_part(from_transport, filename):
565 from_f = from_transport.get(filename)
566 contents = from_f.read()
567 to_f = open(os.path.join(orig_target, filename), 'wb')
568 try:
569 to_f.write(contents)
570 finally:
571 to_f.close()
572 base, filename = urlutils.split(dscname)
573 from_transport = cache.get_transport(dscname)
574 get_dsc_part(from_transport, filename)
575 for file_details in dsc['files']:
576 name = file_details['name']
577 get_dsc_part(from_transport, name)
578 db.import_package(os.path.join(orig_target, filename))
579
580 def run(self, files_list, distribution=None, filename=None):
581 from bzrlib.plugins.builddeb.errors import MissingChangelogError
582 if distribution is None:
583 raise BzrCommandError("You must specify the distribution "
584 "these packages were uploaded to using --distribution.")
585 distribution = distribution.lower()
586 distribution_name = lookup_distribution(distribution)
587 if distribution_name is None:
588 raise BzrCommandError("Unknown target distribution: %s" \
589 % distribution)
590 try:
591 tree = WorkingTree.open_containing('.')[0]
592 except NotBranchError:
593 raise BzrCommandError("There is no tree to import the packages in to")
594 tree.lock_write()
595 try:
596 if tree.changes_from(tree.basis_tree()).has_changed():
597 raise BzrCommandError("There are uncommitted changes in the "
598 "working tree. You must commit before using this "
599 "command")
600 if files_list is None:
601 files_list = []
602 if filename is not None:
603 if isinstance(filename, unicode):
604 filename = filename.encode('utf-8')
605 base_dir, path = urlutils.split(filename)
606 sources_file = get_transport(base_dir).get(path)
607 for line in sources_file:
608 line.strip()
609 files_list.append(line)
610 if len(files_list) < 1:
611 raise BzrCommandError("You must give the location of at least one "
612 "source package to install, or use the "
613 "--file option.")
614 config = debuild_config(tree, tree, False)
615 orig_dir = config.orig_dir or default_orig_dir
616 orig_target = os.path.join(tree.basedir, default_orig_dir)
617 db = DistributionBranch(distribution_name, tree.branch,
618 None, tree=tree)
619 dbs = DistributionBranchSet()
620 dbs.add_branch(db)
621 try:
622 (changelog, larstiq) = find_changelog(tree, False)
623 last_version = changelog.version
624 except MissingChangelogError:
625 last_version = None
626 tempdir = tempfile.mkdtemp(dir=os.path.join(tree.basedir,
627 '..'))
628 try:
629 if last_version is not None:
630 upstream_tip = db._revid_of_upstream_version_from_branch(
631 last_version)
632 db._extract_upstream_tree(upstream_tip, tempdir)
633 else:
634 db._create_empty_upstream_tree(tempdir)
635 self.import_many(db, files_list, orig_target)
636 finally:
637 shutil.rmtree(tempdir)
638 finally:
639 tree.unlock()
640
641register_command(cmd_import_dsc)
642
643
644class cmd_bd_do(Command):
645 """Run a command in an exported package, copying the result back.
646
647 For a merge mode package the full source is not available, making some
648 operations difficult. This command allows you to run any command in an
649 exported source directory, copying the resulting debian/ directory back
650 to your branch if the command is successful.
651
652 For instance:
653
654 bzr bd-do
655
656 will run a shell in the unpacked source. Any changes you make in the
657 ``debian/`` directory (and only those made in that directory) will be copied
658 back to the branch. If you exit with a non-zero exit code (e.g. "exit 1"),
659 then the changes will not be copied back.
660
661 You can also specify single commands to be run, e.g.
662
663 bzr bd-do "dpatch-edit-patch 01-fix-build"
664
665 Note that only the first argument is used as the command, and so the above
666 example had to be quoted.
667 """
668
669 takes_args = ['command?']
670
671 def run(self, command=None):
672 t = WorkingTree.open_containing('.')[0]
673 config = debuild_config(t, t, False)
674
675 if not config.merge:
676 raise BzrCommandError("This command only works for merge mode "
677 "packages. See /usr/share/doc/bzr-builddeb"
678 "/user_manual/merge.html for more information.")
679
680 give_instruction = False
681 if command is None:
682 try:
683 command = os.environ['SHELL']
684 except KeyError:
685 command = "/bin/sh"
686 give_instruction = True
687 (changelog, larstiq) = find_changelog(t, True)
688 build_dir = config.build_dir
689 if build_dir is None:
690 build_dir = default_build_dir
691 orig_dir = config.orig_dir
692 if orig_dir is None:
693 orig_dir = default_orig_dir
694 properties = BuildProperties(changelog, build_dir, orig_dir, larstiq)
695 export_upstream = config.export_upstream
696 export_upstream_revision = config.export_upstream_revision
697
698 if export_upstream is None:
699 build = DebMergeBuild(properties, t, _is_working_tree=True)
700 else:
701 prepull_upstream = config.prepull_upstream
702 stop_on_no_change = config.prepull_upstream_stop
703 build = DebMergeExportUpstreamBuild(properties, t, export_upstream,
704 export_upstream_revision,
705 prepull_upstream,
706 stop_on_no_change,
707 _is_working_tree=True)
708
709 build.prepare()
710 try:
711 build.export()
712 except StopBuild, e:
713 warning('Stopping the build: %s.', e.reason)
714 info('Running "%s" in the exported directory.' % (command))
715 if give_instruction:
716 info('If you want to cancel your changes then exit with a non-zero '
717 'exit code, e.g. run "exit 1".')
718 proc = subprocess.Popen(command, shell=True,
719 cwd=properties.source_dir())
720 proc.wait()
721 if proc.returncode != 0:
722 raise BzrCommandError('Not updating the working tree as the command '
723 'failed.')
724 info("Copying debian/ back")
725 if larstiq:
726 destination = '.'
727 else:
728 destination = 'debian/'
729 source_debian = os.path.join(properties.source_dir(), 'debian')
730 for filename in os.listdir(source_debian):
731 proc = subprocess.Popen('cp -apf "%s" "%s"' % (
732 os.path.join(source_debian, filename), destination),
733 shell=True)
734 proc.wait()
735 if proc.returncode != 0:
736 raise BzrCommandError('Copying back debian/ failed')
737 build.clean()
738 info('If any files were added or removed you should run "bzr add" or '
739 '"bzr rm" as appropriate.')
740
741
742register_command(cmd_bd_do)
743
744
745class cmd_mark_uploaded(Command):
746 """Mark that this branch has been uploaded, prior to pushing it.
747
748 When a package has been uploaded we want to mark the revision
749 that it was uploaded in. This command automates doing that
750 by marking the current tip revision with the version indicated
751 in debian/changelog.
752 """
753 force = Option('force', help="Mark the upload even if it is already "
754 "marked.")
755
756 takes_options = [merge_opt, no_user_conf_opt, force]
757
758 def run(self, merge=False, no_user_config=False, force=None):
759 t = WorkingTree.open_containing('.')[0]
760 t.lock_write()
761 try:
762 if t.changes_from(t.basis_tree()).has_changed():
763 raise BzrCommandError("There are uncommitted changes in the "
764 "working tree. You must commit before using this "
765 "command")
766 config = debuild_config(t, t, no_user_config)
767 if not merge:
768 merge = config.merge
769 (changelog, larstiq) = find_changelog(t, merge)
770 distributions = changelog.distributions.strip()
771 target_dist = distributions.split()[0]
772 distribution_name = suite_to_distribution(target_dist)
773 if distribution_name is None:
774 raise BzrCommandError("Unknown target distribution: %s" \
775 % target_dist)
776 db = DistributionBranch(distribution_name, t.branch, None)
777 dbs = DistributionBranchSet()
778 dbs.add_branch(db)
779 if db.has_version(changelog.version):
780 if not force:
781 raise BzrCommandError("This version has already been "
782 "marked uploaded. Use --force to force marking "
783 "this new version.")
784 db.tag_version(changelog.version)
785 finally:
786 t.unlock()
787
788
789register_command(cmd_mark_uploaded)
79067
79168
792def test_suite():69def test_suite():
@@ -797,30 +74,9 @@
797 return result74 return result
79875
79976
800class cmd_test_builddeb(Command):
801 """Run the builddeb test suite"""
802
803 hidden = True
804
805 def run(self):
806 from bzrlib.tests import selftest
807 passed = selftest(test_suite_factory=test_suite)
808 # invert for shell exit code rules
809 return not passed
810
811
812register_command(cmd_test_builddeb)
813
814directories.register_lazy("deb:", 'bzrlib.plugins.builddeb.directory',
815 'VcsDirectory',
816 "Directory that uses Debian Vcs-* control fields to look up branches")
817
818if __name__ == '__main__':77if __name__ == '__main__':
819 print ("This is a Bazaar plugin. Copy this directory to ~/.bazaar/plugins "78 print ("This is a Bazaar plugin. Copy this directory to ~/.bazaar/plugins "
820 "to use it.\n")79 "to use it.\n")
821 import unittest80 import unittest
822 runner = unittest.TextTestRunner()81 runner = unittest.TextTestRunner()
823 runner.run(test_suite())82 runner.run(test_suite())
824else:
825 import sys
826 sys.path.append(os.path.dirname(os.path.abspath(__file__)))
82783
=== added file 'cmds.py'
--- cmds.py 1970-01-01 00:00:00 +0000
+++ cmds.py 2009-02-12 14:45:56 +0000
@@ -0,0 +1,788 @@
1# __init__.py -- The plugin for bzr
2# Copyright (C) 2005 Jamie Wilkinson <jaq@debian.org>
3# 2006, 2007 James Westby <jw+debian@jameswestby.net>
4# 2007 Reinhard Tartler <siretart@tauware.de>
5# 2008 Canonical Ltd.
6#
7# This file is part of bzr-builddeb.
8#
9# bzr-builddeb is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14# bzr-builddeb is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with bzr-builddeb; if not, write to the Free Software
21# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22#
23import os
24import shutil
25import subprocess
26import tempfile
27import urlparse
28
29from debian_bundle.changelog import Version
30
31from bzrlib import (
32 bzrdir,
33 urlutils,
34 )
35from bzrlib.branch import Branch
36from bzrlib.commands import Command
37from bzrlib.errors import (BzrCommandError,
38 NoWorkingTree,
39 NotBranchError,
40 FileExists,
41 )
42from bzrlib.option import Option
43from bzrlib.trace import info, warning
44from bzrlib.transport import get_transport
45from bzrlib.workingtree import WorkingTree
46
47from bzrlib.plugins.builddeb import (
48 default_build_dir,
49 default_orig_dir,
50 default_result_dir,
51 default_conf,
52 local_conf,
53 global_conf,
54 test_suite,
55 )
56from bzrlib.plugins.builddeb.builder import (
57 DebBuild,
58 DebMergeBuild,
59 DebNativeBuild,
60 DebSplitBuild,
61 DebMergeExportUpstreamBuild,
62 DebExportUpstreamBuild,
63 )
64from bzrlib.plugins.builddeb.config import DebBuildConfig
65from bzrlib.plugins.builddeb.errors import (StopBuild,
66 )
67from bzrlib.plugins.builddeb.hooks import run_hook
68from bzrlib.plugins.builddeb.import_dsc import (
69 DistributionBranch,
70 DistributionBranchSet,
71 DscCache,
72 DscComp,
73 )
74from bzrlib.plugins.builddeb.properties import BuildProperties
75from bzrlib.plugins.builddeb.util import (find_changelog,
76 lookup_distribution,
77 suite_to_distribution,
78 tarball_name,
79 )
80
81dont_purge_opt = Option('dont-purge',
82 help="Don't purge the build directory after building")
83result_opt = Option('result-dir',
84 help="Directory in which to place the resulting package files", type=str)
85builder_opt = Option('builder',
86 help="Command to build the package", type=str)
87merge_opt = Option('merge',
88 help='Merge the debian part of the source in to the upstream tarball')
89build_dir_opt = Option('build-dir',
90 help="The dir to use for building", type=str)
91orig_dir_opt = Option('orig-dir',
92 help="Directory containing the .orig.tar.gz files. For use when only"
93 +"debian/ is versioned", type=str)
94native_opt = Option('native',
95 help="Build a native package")
96split_opt = Option('split',
97 help="Automatically create an .orig.tar.gz from a full source branch")
98export_upstream_opt = Option('export-upstream',
99 help="Create the .orig.tar.gz from a bzr branch before building",
100 type=unicode)
101export_upstream_revision_opt = Option('export-upstream-revision',
102 help="Select the upstream revision that will be exported",
103 type=str)
104no_user_conf_opt = Option('no-user-config',
105 help="Stop builddeb from reading the user's config file. Used mainly "
106 "for tests")
107
108
109def debuild_config(tree, working_tree, no_user_config):
110 """Obtain the Debuild configuration object.
111
112 :param tree: A Tree object, can be a WorkingTree or RevisionTree.
113 :param working_tree: Whether the tree is a working tree.
114 :param no_user_config: Whether to skip the user configuration
115 """
116 config_files = []
117 user_config = None
118 if (working_tree and
119 tree.has_filename(local_conf) and tree.path2id(local_conf) is None):
120 config_files.append((tree.get_file_byname(local_conf), True))
121 if not no_user_config:
122 config_files.append((global_conf, True))
123 user_config = global_conf
124 if tree.path2id(default_conf):
125 config_files.append((tree.get_file(tree.path2id(default_conf)), False))
126 config = DebBuildConfig(config_files)
127 config.set_user_config(user_config)
128 return config
129
130
131class cmd_builddeb(Command):
132 """Builds a Debian package from a branch.
133
134 If BRANCH is specified it is assumed that the branch you wish to build is
135 located there. If it is not specified then the current directory is used.
136
137 By default the if a working tree is found it is used to build and otherwise
138 the last committed revision was used. To force building the last committed
139 revision use --revision -1. You can specify any other revision using the
140 --revision option.
141
142 If you only wish to export the package, and not build it (especially useful
143 for merge mode), use --export-only.
144
145 To leave the build directory when the build is completed use --dont-purge.
146
147 Specify the command to use when building using the --builder option,
148
149 You can also specify directories to use for different things. --build-dir
150 is the directory to build the packages beneath, which defaults to
151 '../build-area'. '--orig-dir' specifies the directory that contains the
152 .orig.tar.gz files , which defaults to '..'. '--result-dir' specifies where
153 the resulting package files should be placed, which defaults to '..'.
154 --result-dir will have problems if you use a build command that places
155 the results in a different directory.
156
157 The --reuse option will be useful if you are in merge mode, and the upstream
158 tarball is very large. It attempts to reuse a build directory from an earlier
159 build. It will fail if one doesn't exist, but you can create one by using
160 --export-only.
161
162 --quick allows you to define a quick-builder in your configuration files,
163 which will be used when this option is passed. It defaults to 'fakeroot
164 debian/rules binary'. It is overriden if --builder is passed. Using this
165 and --reuse allows for fast rebuilds.
166
167 --source allows you to build a source package without having to
168 specify a builder to do so with --builder. It uses the source-builder
169 option from your configuration files, and defaults to 'dpkg-buildpackage
170 -rfakeroot -uc -us -S'. It is overriden if either --builder or --quick are
171 used.
172
173 """
174 working_tree_opt = Option('working-tree', help="This option has no effect",
175 short_name='w')
176 export_only_opt = Option('export-only', help="Export only, don't build",
177 short_name='e')
178 use_existing_opt = Option('use-existing',
179 help="Use an existing build directory")
180 ignore_changes_opt = Option('ignore-changes',
181 help="This option has no effect")
182 ignore_unknowns_opt = Option('ignore-unknowns',
183 help="Ignore any unknown files, but still fail if there are any changes"
184 +", the default is to fail if there are unknowns as well.")
185 quick_opt = Option('quick', help="Quickly build the package, uses "
186 +"quick-builder, which defaults to \"fakeroot "
187 +"debian/rules binary\"")
188 reuse_opt = Option('reuse', help="Try to avoid expoting too much on each "
189 +"build. Only works in merge mode; it saves unpacking "
190 +"the upstream tarball each time. Implies --dont-purge "
191 +"and --use-existing")
192 source_opt = Option('source', help="Build a source package, uses "
193 +"source-builder, which defaults to \"dpkg-buildpackage "
194 +"-rfakeroot -uc -us -S\"", short_name='S')
195 result_compat_opt = Option('result', help="Present only for compatibility "
196 "with bzr-builddeb <= 2.0. Use --result-dir instead.")
197 takes_args = ['branch?']
198 aliases = ['bd']
199 takes_options = [working_tree_opt, export_only_opt,
200 dont_purge_opt, use_existing_opt, result_opt, builder_opt, merge_opt,
201 build_dir_opt, orig_dir_opt, ignore_changes_opt, ignore_unknowns_opt,
202 quick_opt, reuse_opt, native_opt, split_opt, export_upstream_opt,
203 export_upstream_revision_opt, source_opt, 'revision',
204 no_user_conf_opt, result_compat_opt]
205
206 def run(self, branch=None, verbose=False, working_tree=False,
207 export_only=False, dont_purge=False, use_existing=False,
208 result_dir=None, builder=None, merge=False, build_dir=None,
209 orig_dir=None, ignore_changes=False, ignore_unknowns=False,
210 quick=False, reuse=False, native=False, split=False,
211 export_upstream=None, export_upstream_revision=None,
212 source=False, revision=None, no_user_config=False, result=None):
213
214 if branch is None:
215 branch = "."
216
217 # Find out if we were passed a local or remote branch
218 is_local = urlparse.urlsplit(branch)[0] in ('', 'file')
219 if is_local:
220 os.chdir(branch)
221
222 try:
223 tree, _ = WorkingTree.open_containing(branch)
224 branch = tree.branch
225 except NoWorkingTree:
226 tree = None
227 branch, _ = Branch.open_containing(branch)
228
229 if revision is None and tree is not None:
230 info("Building using working tree")
231 working_tree = True
232 else:
233 if revision is None:
234 revid = branch.last_revision()
235 elif len(revision) == 1:
236 revid = revision[0].in_history(branch).rev_id
237 else:
238 raise BzrCommandError('bzr builddeb --revision takes exactly one '
239 'revision specifier.')
240 info("Building branch from revision %s", revid)
241 tree = branch.repository.revision_tree(revid)
242 working_tree = False
243
244 tree.lock_read()
245 try:
246 config = debuild_config(tree, working_tree, no_user_config)
247
248 if reuse:
249 info("Reusing existing build dir")
250 dont_purge = True
251 use_existing = True
252
253 if not merge:
254 merge = config.merge
255
256 if merge:
257 info("Running in merge mode")
258 else:
259 if not native:
260 native = config.native
261 if native:
262 info("Running in native mode")
263 else:
264 if not split:
265 split = config.split
266 if split:
267 info("Running in split mode")
268
269 if builder is None:
270 if quick:
271 builder = config.quick_builder
272 if builder is None:
273 builder = "fakeroot debian/rules binary"
274 else:
275 if source:
276 builder = config.source_builder
277 if builder is None:
278 builder = "dpkg-buildpackage -rfakeroot -uc -us -S"
279 else:
280 builder = config.builder
281 if builder is None:
282 builder = "dpkg-buildpackage -uc -us -rfakeroot"
283
284 (changelog, larstiq) = find_changelog(tree, merge)
285
286 config.set_version(changelog.version)
287
288 if export_upstream is None:
289 export_upstream = config.export_upstream
290
291 if export_upstream_revision is None:
292 export_upstream_revision = config.export_upstream_revision
293
294 if result_dir is None:
295 result_dir = result
296
297 if result_dir is None:
298 if is_local:
299 result_dir = config.result_dir
300 else:
301 result_dir = config.user_result_dir
302 if result_dir is not None:
303 result_dir = os.path.realpath(result_dir)
304
305 if build_dir is None:
306 if is_local:
307 build_dir = config.build_dir or default_build_dir
308 else:
309 build_dir = config.user_build_dir or 'build-area'
310
311 if orig_dir is None:
312 if is_local:
313 orig_dir = config.orig_dir or default_orig_dir
314 else:
315 orig_dir = config.user_orig_dir or 'build-area'
316
317 properties = BuildProperties(changelog, build_dir, orig_dir, larstiq)
318
319 if merge:
320 if export_upstream is None:
321 build = DebMergeBuild(properties, tree, _is_working_tree=working_tree)
322 else:
323 prepull_upstream = config.prepull_upstream
324 stop_on_no_change = config.prepull_upstream_stop
325 build = DebMergeExportUpstreamBuild(properties, tree, export_upstream,
326 export_upstream_revision,
327 prepull_upstream,
328 stop_on_no_change,
329 _is_working_tree=working_tree)
330 elif native:
331 build = DebNativeBuild(properties, tree, _is_working_tree=working_tree)
332 elif split:
333 build = DebSplitBuild(properties, tree, _is_working_tree=working_tree)
334 else:
335 if export_upstream is None:
336 build = DebBuild(properties, tree, _is_working_tree=working_tree)
337 else:
338 prepull_upstream = config.prepull_upstream
339 stop_on_no_change = config.prepull_upstream_stop
340 build = DebExportUpstreamBuild(properties, tree, export_upstream,
341 export_upstream_revision,
342 prepull_upstream,
343 stop_on_no_change,
344 _is_working_tree=working_tree)
345
346 build.prepare(use_existing)
347
348 run_hook(tree, 'pre-export', config)
349
350 try:
351 build.export(use_existing)
352 except StopBuild, e:
353 warning('Stopping the build: %s.', e.reason)
354 return
355
356 if not export_only:
357 run_hook(tree, 'pre-build', config, wd=properties.source_dir())
358 build.build(builder)
359 run_hook(tree, 'post-build', config, wd=properties.source_dir())
360 if not dont_purge:
361 build.clean()
362 arch = None
363 if source:
364 arch = "source"
365 if result_dir is not None:
366 build.move_result(result_dir, arch=arch)
367 else:
368 build.move_result(default_result_dir, allow_missing=True, arch=arch)
369 finally:
370 tree.unlock()
371
372
373
374
375class cmd_merge_upstream(Command):
376 """Merges a new upstream version into the current branch.
377
378 Takes a new upstream version and merges it in to your branch, so that your
379 packaging changes are applied to the new version.
380
381 You must supply the source to import from, and the version number of the
382 new release. The source can be a .tar.gz, .tar, .tar.bz2, .tgz or .zip
383 archive, or a directory. The source may also be a remote file.
384
385 You must supply the version number of the new upstream release
386 using --version, and the target distribution using --distribution.
387 The target distribtution is the distribution that you aim to upload to,
388 one of "debian" or "ubuntu". You can also specify the target used in
389 the changelog, e.g. "unstable", and it will be resolved automatically.
390
391 If there is no debian changelog in the branch to retrieve the package
392 name from then you must pass the --package option. If this version
393 will change the name of the source package then you can use this option
394 to set the new name.
395 """
396 takes_args = ['location?']
397 aliases = ['mu']
398
399 package_opt = Option('package', help="The name of the source package.",
400 type=str)
401 version_opt = Option('version', help="The version number of this release.",
402 type=str)
403 distribution_opt = Option('distribution', help="The distribution that "
404 "this release is targetted at", type=str)
405 directory_opt = Option('directory', help='Working tree into which to merge.',
406 short_name='d', type=unicode)
407
408 takes_options = [package_opt, no_user_conf_opt, version_opt,
409 distribution_opt, directory_opt, 'revision']
410
411 def run(self, location=None, version=None, distribution=None, package=None,
412 no_user_config=None, directory=".", revision=None):
413 from bzrlib.plugins.builddeb.errors import MissingChangelogError
414 from bzrlib.plugins.builddeb.repack_tarball import repack_tarball
415 from bzrlib.plugins.builddeb.merge_upstream import merge_upstream_branch
416 tree, _ = WorkingTree.open_containing(directory)
417 tree.lock_write()
418 try:
419 # Check for uncommitted changes.
420 if tree.changes_from(tree.basis_tree()).has_changed():
421 raise BzrCommandError("There are uncommitted changes in the "
422 "working tree. You must commit before using this "
423 "command.")
424 config = debuild_config(tree, tree, no_user_config)
425 if config.merge:
426 raise BzrCommandError("Merge upstream in merge mode is not "
427 "yet supported.")
428 if config.native:
429 raise BzrCommandError("Merge upstream in native mode is not "
430 "yet supported.")
431 if config.export_upstream and location is None:
432 location = config.export_upstream
433 if config.split:
434 raise BzrCommandError("Split mode is not yet supported.")
435
436 if location is None:
437 raise BzrCommandError("No location specified to merge")
438 try:
439 changelog = find_changelog(tree, False)[0]
440 current_version = changelog.version
441 if package is None:
442 package = changelog.package
443 except MissingChangelogError:
444 current_version = None
445
446 if package is None:
447 raise BzrCommandError("You did not specify --package, and "
448 "there is no changelog from which to determine the "
449 "package name, which is needed to know the name to "
450 "give the .orig.tar.gz. Please specify --package.")
451
452 try:
453 upstream_branch = Branch.open(location)
454 except NotBranchError:
455 upstream_branch = None
456
457 if upstream_branch is None:
458 if version is None:
459 raise BzrCommandError("You must specify the version number using "
460 "--version.")
461 version = Version(version)
462 if distribution is None:
463 raise BzrCommandError("You must specify the target distribution "
464 "using --distribution.")
465 if revision is not None:
466 raise BzrCommandError("--revision is not allowed when merging a tarball")
467
468 orig_dir = config.orig_dir or default_orig_dir
469 orig_dir = os.path.join(tree.basedir, orig_dir)
470 dest_name = tarball_name(package, version.upstream_version)
471 try:
472 repack_tarball(location, dest_name, target_dir=orig_dir)
473 except FileExists:
474 raise BzrCommandError("The target file %s already exists, and is either "
475 "different to the new upstream tarball, or they "
476 "are of different formats. Either delete the target "
477 "file, or use it as the argument to import.")
478 tarball_filename = os.path.join(orig_dir, dest_name)
479 distribution = distribution.lower()
480 distribution_name = lookup_distribution(distribution)
481 if distribution_name is None:
482 raise BzrCommandError("Unknown target distribution: %s" \
483 % distribution)
484 db = DistributionBranch(distribution_name, tree.branch, None,
485 tree=tree)
486 dbs = DistributionBranchSet()
487 dbs.add_branch(db)
488 conflicts = db.merge_upstream(tarball_filename, version,
489 current_version)
490 else:
491 if revision is not None:
492 if len(revision) > 1:
493 raise BzrCommandError("merge-upstream takes only a single --revision")
494 upstream_revspec = revision[0]
495 else:
496 upstream_revspec = None
497 version = merge_upstream_branch(tree, upstream_branch, package,
498 upstream_revspec, version)
499 info("Using version string %s for upstream branch." % (version))
500 finally:
501 tree.unlock()
502
503 if "~bzr" in str(version) or "+bzr" in str(version):
504 entry_description = "New upstream snapshot."
505 else:
506 entry_description = "New upstream release."
507
508 info("The new upstream version has been imported. You should "
509 "now update the changelog (try dch -v %s-1 \"%s\"), resolve any "
510 "conflicts, and then commit." % (str(version), entry_description))
511
512
513
514
515class cmd_import_dsc(Command):
516 """Import a series of source packages.
517
518 Provide a number of source packages (.dsc files), and they will
519 be imported to create a branch with history that reflects those
520 packages.
521
522 The first argument is the distribution that these source packages
523 were uploaded to, one of "debian" or "ubuntu". It can also
524 be the target distribution from the changelog, e.g. "unstable",
525 which will be resolved to the correct distribution.
526
527 You can also specify a file (possibly remote) that contains a
528 list of source packages (.dsc files) to import using the --file
529 option. Each line is taken to be a URI or path to import. The
530 sources specified in the file are used in addition to those
531 specified on the command line.
532
533 If you have an existing branch containing packaging and you want to
534 import a .dsc from an upload done from outside the version control
535 system you can use this command.
536 """
537
538 takes_args = ['files*']
539
540 filename_opt = Option('file', help="File containing URIs of source "
541 "packages to import.", type=str, argname="filename",
542 short_name='F')
543 distribution_opt = Option('distribution', help="The distribution that "
544 "these packages were uploaded to.", type=str)
545
546 takes_options = [filename_opt, distribution_opt]
547
548 def import_many(self, db, files_list, orig_target):
549 cache = DscCache()
550 files_list.sort(cmp=DscComp(cache).cmp)
551 if not os.path.exists(orig_target):
552 os.makedirs(orig_target)
553 for dscname in files_list:
554 dsc = cache.get_dsc(dscname)
555 def get_dsc_part(from_transport, filename):
556 from_f = from_transport.get(filename)
557 contents = from_f.read()
558 to_f = open(os.path.join(orig_target, filename), 'wb')
559 try:
560 to_f.write(contents)
561 finally:
562 to_f.close()
563 base, filename = urlutils.split(dscname)
564 from_transport = cache.get_transport(dscname)
565 get_dsc_part(from_transport, filename)
566 for file_details in dsc['files']:
567 name = file_details['name']
568 get_dsc_part(from_transport, name)
569 db.import_package(os.path.join(orig_target, filename))
570
571 def run(self, files_list, distribution=None, filename=None):
572 from bzrlib.plugins.builddeb.errors import MissingChangelogError
573 if distribution is None:
574 raise BzrCommandError("You must specify the distribution "
575 "these packages were uploaded to using --distribution.")
576 distribution = distribution.lower()
577 distribution_name = lookup_distribution(distribution)
578 if distribution_name is None:
579 raise BzrCommandError("Unknown target distribution: %s" \
580 % distribution)
581 try:
582 tree = WorkingTree.open_containing('.')[0]
583 except NotBranchError:
584 raise BzrCommandError("There is no tree to import the packages in to")
585 tree.lock_write()
586 try:
587 if tree.changes_from(tree.basis_tree()).has_changed():
588 raise BzrCommandError("There are uncommitted changes in the "
589 "working tree. You must commit before using this "
590 "command")
591 if files_list is None:
592 files_list = []
593 if filename is not None:
594 if isinstance(filename, unicode):
595 filename = filename.encode('utf-8')
596 base_dir, path = urlutils.split(filename)
597 sources_file = get_transport(base_dir).get(path)
598 for line in sources_file:
599 line.strip()
600 files_list.append(line)
601 if len(files_list) < 1:
602 raise BzrCommandError("You must give the location of at least one "
603 "source package to install, or use the "
604 "--file option.")
605 config = debuild_config(tree, tree, False)
606 orig_dir = config.orig_dir or default_orig_dir
607 orig_target = os.path.join(tree.basedir, default_orig_dir)
608 db = DistributionBranch(distribution_name, tree.branch,
609 None, tree=tree)
610 dbs = DistributionBranchSet()
611 dbs.add_branch(db)
612 try:
613 (changelog, larstiq) = find_changelog(tree, False)
614 last_version = changelog.version
615 except MissingChangelogError:
616 last_version = None
617 tempdir = tempfile.mkdtemp(dir=os.path.join(tree.basedir,
618 '..'))
619 try:
620 if last_version is not None:
621 upstream_tip = db._revid_of_upstream_version_from_branch(
622 last_version)
623 db._extract_upstream_tree(upstream_tip, tempdir)
624 else:
625 db._create_empty_upstream_tree(tempdir)
626 self.import_many(db, files_list, orig_target)
627 finally:
628 shutil.rmtree(tempdir)
629 finally:
630 tree.unlock()
631
632
633
634class cmd_bd_do(Command):
635 """Run a command in an exported package, copying the result back.
636
637 For a merge mode package the full source is not available, making some
638 operations difficult. This command allows you to run any command in an
639 exported source directory, copying the resulting debian/ directory back
640 to your branch if the command is successful.
641
642 For instance:
643
644 bzr bd-do
645
646 will run a shell in the unpacked source. Any changes you make in the
647 ``debian/`` directory (and only those made in that directory) will be copied
648 back to the branch. If you exit with a non-zero exit code (e.g. "exit 1"),
649 then the changes will not be copied back.
650
651 You can also specify single commands to be run, e.g.
652
653 bzr bd-do "dpatch-edit-patch 01-fix-build"
654
655 Note that only the first argument is used as the command, and so the above
656 example had to be quoted.
657 """
658
659 takes_args = ['command?']
660
661 def run(self, command=None):
662 t = WorkingTree.open_containing('.')[0]
663 config = debuild_config(t, t, False)
664
665 if not config.merge:
666 raise BzrCommandError("This command only works for merge mode "
667 "packages. See /usr/share/doc/bzr-builddeb"
668 "/user_manual/merge.html for more information.")
669
670 give_instruction = False
671 if command is None:
672 try:
673 command = os.environ['SHELL']
674 except KeyError:
675 command = "/bin/sh"
676 give_instruction = True
677 (changelog, larstiq) = find_changelog(t, True)
678 build_dir = config.build_dir
679 if build_dir is None:
680 build_dir = default_build_dir
681 orig_dir = config.orig_dir
682 if orig_dir is None:
683 orig_dir = default_orig_dir
684 properties = BuildProperties(changelog, build_dir, orig_dir, larstiq)
685 export_upstream = config.export_upstream
686 export_upstream_revision = config.export_upstream_revision
687
688 if export_upstream is None:
689 build = DebMergeBuild(properties, t, _is_working_tree=True)
690 else:
691 prepull_upstream = config.prepull_upstream
692 stop_on_no_change = config.prepull_upstream_stop
693 build = DebMergeExportUpstreamBuild(properties, t, export_upstream,
694 export_upstream_revision,
695 prepull_upstream,
696 stop_on_no_change,
697 _is_working_tree=True)
698
699 build.prepare()
700 try:
701 build.export()
702 except StopBuild, e:
703 warning('Stopping the build: %s.', e.reason)
704 info('Running "%s" in the exported directory.' % (command))
705 if give_instruction:
706 info('If you want to cancel your changes then exit with a non-zero '
707 'exit code, e.g. run "exit 1".')
708 proc = subprocess.Popen(command, shell=True,
709 cwd=properties.source_dir())
710 proc.wait()
711 if proc.returncode != 0:
712 raise BzrCommandError('Not updating the working tree as the command '
713 'failed.')
714 info("Copying debian/ back")
715 if larstiq:
716 destination = '.'
717 else:
718 destination = 'debian/'
719 source_debian = os.path.join(properties.source_dir(), 'debian')
720 for filename in os.listdir(source_debian):
721 proc = subprocess.Popen('cp -apf "%s" "%s"' % (
722 os.path.join(source_debian, filename), destination),
723 shell=True)
724 proc.wait()
725 if proc.returncode != 0:
726 raise BzrCommandError('Copying back debian/ failed')
727 build.clean()
728 info('If any files were added or removed you should run "bzr add" or '
729 '"bzr rm" as appropriate.')
730
731
732
733
734class cmd_mark_uploaded(Command):
735 """Mark that this branch has been uploaded, prior to pushing it.
736
737 When a package has been uploaded we want to mark the revision
738 that it was uploaded in. This command automates doing that
739 by marking the current tip revision with the version indicated
740 in debian/changelog.
741 """
742 force = Option('force', help="Mark the upload even if it is already "
743 "marked.")
744
745 takes_options = [merge_opt, no_user_conf_opt, force]
746
747 def run(self, merge=False, no_user_config=False, force=None):
748 t = WorkingTree.open_containing('.')[0]
749 t.lock_write()
750 try:
751 if t.changes_from(t.basis_tree()).has_changed():
752 raise BzrCommandError("There are uncommitted changes in the "
753 "working tree. You must commit before using this "
754 "command")
755 config = debuild_config(t, t, no_user_config)
756 if not merge:
757 merge = config.merge
758 (changelog, larstiq) = find_changelog(t, merge)
759 distributions = changelog.distributions.strip()
760 target_dist = distributions.split()[0]
761 distribution_name = suite_to_distribution(target_dist)
762 if distribution_name is None:
763 raise BzrCommandError("Unknown target distribution: %s" \
764 % target_dist)
765 db = DistributionBranch(distribution_name, t.branch, None)
766 dbs = DistributionBranchSet()
767 dbs.add_branch(db)
768 if db.has_version(changelog.version):
769 if not force:
770 raise BzrCommandError("This version has already been "
771 "marked uploaded. Use --force to force marking "
772 "this new version.")
773 db.tag_version(changelog.version)
774 finally:
775 t.unlock()
776
777
778class cmd_test_builddeb(Command):
779 """Run the builddeb test suite"""
780
781 hidden = True
782
783 def run(self):
784 from bzrlib.tests import selftest
785 passed = selftest(test_suite_factory=test_suite)
786 # invert for shell exit code rules
787 return not passed
788
0789
=== modified file 'revspec.py'
--- revspec.py 2008-11-27 15:30:30 +0000
+++ revspec.py 2009-01-29 23:47:05 +0000
@@ -19,7 +19,7 @@
19#19#
2020
21from bzrlib.errors import NoSuchTag21from bzrlib.errors import NoSuchTag
22from bzrlib.revisionspec import RevisionSpec, RevisionInfo, SPEC_TYPES22from bzrlib.revisionspec import RevisionSpec, RevisionInfo
2323
24from bzrlib.plugins.builddeb.errors import (24from bzrlib.plugins.builddeb.errors import (
25 AmbiguousPackageSpecification,25 AmbiguousPackageSpecification,
@@ -84,5 +84,4 @@
84 return RevisionInfo.from_revision_id(branch,84 return RevisionInfo.from_revision_id(branch,
85 revision_id, revs)85 revision_id, revs)
8686
87SPEC_TYPES.append(RevisionSpec_package)
8887
8988
=== modified file 'tests/__init__.py'
--- tests/__init__.py 2008-09-03 12:07:07 +0000
+++ tests/__init__.py 2009-02-12 14:45:56 +0000
@@ -134,7 +134,7 @@
134 'config'134 'config'
135 ]135 ]
136 for mod in doctest_mod_names:136 for mod in doctest_mod_names:
137 suite.addTest(doctest.DocTestSuite(mod))137 suite.addTest(doctest.DocTestSuite("bzrlib.plugins.builddeb." + mod))
138138
139 adapt_modules(['%s.test_repack_tarball' % __name__],139 adapt_modules(['%s.test_repack_tarball' % __name__],
140 RepackTarballAdaptor(), loader, suite)140 RepackTarballAdaptor(), loader, suite)
141141
=== modified file 'tests/test_repack_tarball_extra.py'
--- tests/test_repack_tarball_extra.py 2008-12-02 16:25:25 +0000
+++ tests/test_repack_tarball_extra.py 2009-02-12 14:45:56 +0000
@@ -22,7 +22,7 @@
22import shutil22import shutil
23import tarfile23import tarfile
2424
25from repack_tarball import repack_tarball25from bzrlib.plugins.builddeb.repack_tarball import repack_tarball
2626
27from bzrlib.errors import BzrCommandError, FileExists27from bzrlib.errors import BzrCommandError, FileExists
28from bzrlib.tests import TestCaseInTempDir28from bzrlib.tests import TestCaseInTempDir

Subscribers

People subscribed via source and target branches