1400
1365
class cmd_diff(Command):
1401
"""Show differences in the working tree, between revisions or branches.
1366
"""Show differences in the working tree or between revisions.
1403
If no arguments are given, all changes for the current tree are listed.
1404
If files are given, only the changes in those files are listed.
1405
Remote and multiple branches can be compared by using the --old and
1406
--new options. If not provided, the default for both is derived from
1407
the first argument, if any, or the current tree if no arguments are
1368
If files are listed, only the changes in those files are listed.
1369
Otherwise, all changes for the tree are listed.
1410
1371
"bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1411
1372
produces patches suitable for "patch -p1".
1415
2 - unrepresentable changes
1420
Shows the difference in the working tree versus the last commit::
1424
Difference between the working tree and revision 1::
1428
Difference between revision 2 and revision 1::
1432
Difference between revision 2 and revision 1 for branch xxx::
1436
Show just the differences for file NEWS::
1440
Show the differences in working tree xxx for file NEWS::
1444
Show the differences from branch xxx to this working tree:
1448
Show the differences between two branches for file NEWS::
1450
bzr diff --old xxx --new yyy NEWS
1452
Same as 'bzr diff' but prefix paths with old/ and new/::
1454
bzr diff --prefix old/:new/
1376
Shows the difference in the working tree versus the last commit
1378
Difference between the working tree and revision 1
1380
Difference between revision 2 and revision 1
1381
bzr diff --prefix old/:new/
1382
Same as 'bzr diff' but prefix paths with old/ and new/
1383
bzr diff bzr.mine bzr.dev
1384
Show the differences between the two working trees
1386
Show just the differences for 'foo.c'
1388
# TODO: Option to use external diff command; could be GNU diff, wdiff,
1389
# or a graphical diff.
1391
# TODO: Python difflib is not exactly the same as unidiff; should
1392
# either fix it up or prefer to use an external diff.
1394
# TODO: Selected-file diff is inefficient and doesn't show you
1397
# TODO: This probably handles non-Unix newlines poorly.
1456
1399
_see_also = ['status']
1457
1400
takes_args = ['file*']
1459
Option('diff-options', type=str,
1460
help='Pass these options to the external diff program.'),
1401
takes_options = ['revision', 'diff-options',
1461
1402
Option('prefix', type=str,
1462
1403
short_name='p',
1463
help='Set prefixes added to old and new filenames, as '
1464
'two values separated by a colon. (eg "old/:new/").'),
1466
help='Branch/tree to compare from.',
1470
help='Branch/tree to compare to.',
1476
help='Use this command to compare files.',
1404
help='Set prefixes to added to old and new filenames, as '
1405
'two values separated by a colon. (eg "old/:new/")'),
1480
1407
aliases = ['di', 'dif']
1481
1408
encoding_type = 'exact'
1483
1410
@display_command
1484
1411
def run(self, revision=None, file_list=None, diff_options=None,
1485
prefix=None, old=None, new=None, using=None):
1486
from bzrlib.diff import _get_trees_to_diff, show_diff_trees
1413
from bzrlib.diff import diff_cmd_helper, show_diff_trees
1488
1415
if (prefix is None) or (prefix == '0'):
1489
1416
# diff -p0 format
1503
1430
raise errors.BzrCommandError('bzr diff --revision takes exactly'
1504
1431
' one or two revision specifiers')
1506
old_tree, new_tree, specific_files, extra_trees = \
1507
_get_trees_to_diff(file_list, revision, old, new)
1508
return show_diff_trees(old_tree, new_tree, sys.stdout,
1509
specific_files=specific_files,
1510
external_diff_options=diff_options,
1511
old_label=old_label, new_label=new_label,
1512
extra_trees=extra_trees, using=using)
1434
tree1, file_list = internal_tree_files(file_list)
1438
except errors.FileInWrongBranch:
1439
if len(file_list) != 2:
1440
raise errors.BzrCommandError("Files are in different branches")
1442
tree1, file1 = WorkingTree.open_containing(file_list[0])
1443
tree2, file2 = WorkingTree.open_containing(file_list[1])
1444
if file1 != "" or file2 != "":
1445
# FIXME diff those two files. rbc 20051123
1446
raise errors.BzrCommandError("Files are in different branches")
1448
except errors.NotBranchError:
1449
if (revision is not None and len(revision) == 2
1450
and not revision[0].needs_branch()
1451
and not revision[1].needs_branch()):
1452
# If both revision specs include a branch, we can
1453
# diff them without needing a local working tree
1454
tree1, tree2 = None, None
1458
if tree2 is not None:
1459
if revision is not None:
1460
# FIXME: but there should be a clean way to diff between
1461
# non-default versions of two trees, it's not hard to do
1463
raise errors.BzrCommandError(
1464
"Sorry, diffing arbitrary revisions across branches "
1465
"is not implemented yet")
1466
return show_diff_trees(tree1, tree2, sys.stdout,
1467
specific_files=file_list,
1468
external_diff_options=diff_options,
1469
old_label=old_label, new_label=new_label)
1471
return diff_cmd_helper(tree1, file_list, diff_options,
1472
revision_specs=revision,
1473
old_label=old_label, new_label=new_label)
1515
1476
class cmd_deleted(Command):
2568
2421
takes_args = ['testspecs*']
2569
2422
takes_options = ['verbose',
2571
help='Stop when one test fails.',
2424
help='stop when one test fails',
2572
2425
short_name='1',
2427
Option('keep-output',
2428
help='keep output directories when tests fail'),
2574
2429
Option('transport',
2575
2430
help='Use a different transport by default '
2576
2431
'throughout the test suite.',
2577
2432
type=get_transport_type),
2579
help='Run the benchmarks rather than selftests.'),
2433
Option('benchmark', help='run the bzr benchmarks.'),
2580
2434
Option('lsprof-timed',
2581
help='Generate lsprof output for benchmarked'
2435
help='generate lsprof output for benchmarked'
2582
2436
' sections of code.'),
2583
2437
Option('cache-dir', type=str,
2584
help='Cache intermediate benchmark output in this '
2438
help='a directory to cache intermediate'
2439
' benchmark steps'),
2440
Option('clean-output',
2441
help='clean temporary tests directories'
2442
' without running tests'),
2586
2443
Option('first',
2587
help='Run all tests, but run specified tests first.',
2444
help='run all tests, but run specified tests first',
2588
2445
short_name='f',
2447
Option('numbered-dirs',
2448
help='use numbered dirs for TestCaseInTempDir'),
2590
2449
Option('list-only',
2591
help='List the tests instead of running them.'),
2450
help='list the tests instead of running them'),
2592
2451
Option('randomize', type=str, argname="SEED",
2593
help='Randomize the order of tests using the given'
2594
' seed or "now" for the current time.'),
2452
help='randomize the order of tests using the given'
2453
' seed or "now" for the current time'),
2595
2454
Option('exclude', type=str, argname="PATTERN",
2596
2455
short_name='x',
2597
help='Exclude tests that match this regular'
2599
Option('strict', help='Fail on missing dependencies or '
2601
Option('coverage', type=str, argname="DIRECTORY",
2602
help='Generate line coverage report in this '
2456
help='exclude tests that match this regular'
2605
2459
encoding_type = 'replace'
2607
def run(self, testspecs_list=None, verbose=False, one=False,
2608
transport=None, benchmark=None,
2609
lsprof_timed=None, cache_dir=None,
2610
first=False, list_only=False,
2611
randomize=None, exclude=None, strict=False, coverage=None):
2461
def run(self, testspecs_list=None, verbose=None, one=False,
2462
keep_output=False, transport=None, benchmark=None,
2463
lsprof_timed=None, cache_dir=None, clean_output=False,
2464
first=False, numbered_dirs=None, list_only=False,
2465
randomize=None, exclude=None):
2612
2466
import bzrlib.ui
2613
2467
from bzrlib.tests import selftest
2614
2468
import bzrlib.benchmarks as benchmarks
2615
2469
from bzrlib.benchmarks import tree_creator
2472
from bzrlib.tests import clean_selftest_output
2473
clean_selftest_output()
2476
trace.warning("notice: selftest --keep-output "
2477
"is no longer supported; "
2478
"test output is always removed")
2480
if numbered_dirs is None and sys.platform == 'win32':
2481
numbered_dirs = True
2617
2483
if cache_dir is not None:
2618
2484
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2620
print 'testing: %s' % (osutils.realpath(sys.argv[0]),)
2621
print ' %s (%s python%s)' % (
2623
bzrlib.version_string,
2624
'.'.join(map(str, sys.version_info)),
2485
print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
2486
print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
2627
2488
if testspecs_list is not None:
2628
2489
pattern = '|'.join(testspecs_list)
2741
2596
The results of the merge are placed into the destination working
2742
2597
directory, where they can be reviewed (with bzr diff), tested, and then
2743
2598
committed to record the result of the merge.
2602
To merge the latest revision from bzr.dev:
2603
bzr merge ../bzr.dev
2605
To merge changes up to and including revision 82 from bzr.dev:
2606
bzr merge -r 82 ../bzr.dev
2608
To merge the changes introduced by 82, without previous changes:
2609
bzr merge -r 81..82 ../bzr.dev
2745
2611
merge refuses to run if there are any uncommitted changes, unless
2746
2612
--force is given.
2749
To merge the latest revision from bzr.dev::
2751
bzr merge ../bzr.dev
2753
To merge changes up to and including revision 82 from bzr.dev::
2755
bzr merge -r 82 ../bzr.dev
2757
To merge the changes introduced by 82, without previous changes::
2759
bzr merge -r 81..82 ../bzr.dev
2762
_see_also = ['update', 'remerge', 'status-flags']
2615
_see_also = ['update', 'remerge']
2763
2616
takes_args = ['branch?']
2768
help='Merge even if the destination tree has uncommitted changes.'),
2617
takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
2772
2618
Option('show-base', help="Show base revision text in "
2774
2620
Option('uncommitted', help='Apply uncommitted changes'
2775
' from a working copy, instead of branch changes.'),
2621
' from a working copy, instead of branch changes'),
2776
2622
Option('pull', help='If the destination is already'
2777
2623
' completely merged into the source, pull from the'
2778
' source rather than merging. When this happens,'
2624
' source rather than merging. When this happens,'
2779
2625
' you do not need to commit the result.'),
2780
2626
Option('directory',
2781
help='Branch to merge into, '
2782
'rather than the one containing the working directory.',
2627
help='Branch to merge into, '
2628
'rather than the one containing the working directory',
2788
2634
def run(self, branch=None, revision=None, force=False, merge_type=None,
2790
2636
uncommitted=False, pull=False,
2791
2637
directory=None,
2793
# This is actually a branch (or merge-directive) *location*.
2639
from bzrlib.tag import _merge_tags_if_possible
2640
other_revision_id = None
2797
2641
if merge_type is None:
2798
2642
merge_type = _mod_merge.Merge3Merger
2800
2644
if directory is None: directory = u'.'
2801
possible_transports = []
2803
allow_pending = True
2804
verified = 'inapplicable'
2645
# XXX: jam 20070225 WorkingTree should be locked before you extract its
2646
# inventory. Because merge is a mutating operation, it really
2647
# should be a lock_write() for the whole cmd_merge operation.
2648
# However, cmd_merge open's its own tree in _merge_helper, which
2649
# means if we lock here, the later lock_write() will always block.
2650
# Either the merge helper code should be updated to take a tree,
2651
# (What about tree.merge_from_branch?)
2805
2652
tree = WorkingTree.open_containing(directory)[0]
2806
2653
change_reporter = delta._ChangeReporter(
2807
2654
unversioned_filter=tree.is_ignored)
2810
pb = ui.ui_factory.nested_progress_bar()
2811
cleanups.append(pb.finished)
2813
cleanups.append(tree.unlock)
2814
if location is not None:
2815
mergeable, other_transport = _get_mergeable_helper(location)
2818
raise errors.BzrCommandError('Cannot use --uncommitted'
2819
' with bundles or merge directives.')
2821
if revision is not None:
2822
raise errors.BzrCommandError(
2823
'Cannot use -r with merge directives or bundles')
2824
merger, verified = _mod_merge.Merger.from_mergeable(tree,
2826
possible_transports.append(other_transport)
2828
if merger is None and uncommitted:
2829
if revision is not None and len(revision) > 0:
2830
raise errors.BzrCommandError('Cannot use --uncommitted and'
2831
' --revision at the same time.')
2832
location = self._select_branch_location(tree, location)[0]
2833
other_tree, other_path = WorkingTree.open_containing(location)
2834
merger = _mod_merge.Merger.from_uncommitted(tree, other_tree,
2836
allow_pending = False
2837
if other_path != '':
2838
merger.interesting_files = [other_path]
2841
merger, allow_pending = self._get_merger_from_branch(tree,
2842
location, revision, remember, possible_transports, pb)
2844
merger.merge_type = merge_type
2845
merger.reprocess = reprocess
2846
merger.show_base = show_base
2847
merger.change_reporter = change_reporter
2848
self.sanity_check_merger(merger)
2849
if (merger.base_rev_id == merger.other_rev_id and
2850
merger.other_rev_id != None):
2851
note('Nothing to do.')
2854
if merger.interesting_files is not None:
2855
raise errors.BzrCommandError('Cannot pull individual files')
2856
if (merger.base_rev_id == tree.last_revision()):
2857
result = tree.pull(merger.other_branch, False,
2858
merger.other_rev_id)
2859
result.report(self.outf)
2861
merger.check_basis(not force)
2862
conflict_count = merger.do_merge()
2864
merger.set_pending()
2865
if verified == 'failed':
2866
warning('Preview patch does not match changes')
2867
if conflict_count != 0:
2872
for cleanup in reversed(cleanups):
2875
def sanity_check_merger(self, merger):
2876
if (merger.show_base and
2877
not merger.merge_type is _mod_merge.Merge3Merger):
2878
raise errors.BzrCommandError("Show-base is not supported for this"
2879
" merge type. %s" % merger.merge_type)
2880
if merger.reprocess and not merger.merge_type.supports_reprocess:
2881
raise errors.BzrCommandError("Conflict reduction is not supported"
2882
" for merge type %s." %
2884
if merger.reprocess and merger.show_base:
2885
raise errors.BzrCommandError("Cannot do conflict reduction and"
2888
def _get_merger_from_branch(self, tree, location, revision, remember,
2889
possible_transports, pb):
2890
"""Produce a merger from a location, assuming it refers to a branch."""
2891
from bzrlib.tag import _merge_tags_if_possible
2892
assert revision is None or len(revision) < 3
2893
# find the branch locations
2894
other_loc, location = self._select_branch_location(tree, location,
2896
if revision is not None and len(revision) == 2:
2897
base_loc, location = self._select_branch_location(tree, location,
2900
base_loc = other_loc
2902
other_branch, other_path = Branch.open_containing(other_loc,
2903
possible_transports)
2904
if base_loc == other_loc:
2905
base_branch = other_branch
2907
base_branch, base_path = Branch.open_containing(base_loc,
2908
possible_transports)
2909
# Find the revision ids
2910
if revision is None or len(revision) < 1 or revision[-1] is None:
2911
other_revision_id = _mod_revision.ensure_null(
2912
other_branch.last_revision())
2914
other_revision_id = \
2915
_mod_revision.ensure_null(
2916
revision[-1].in_history(other_branch).rev_id)
2917
if (revision is not None and len(revision) == 2
2918
and revision[0] is not None):
2919
base_revision_id = \
2920
_mod_revision.ensure_null(
2921
revision[0].in_history(base_branch).rev_id)
2923
base_revision_id = None
2924
# Remember where we merge from
2656
if branch is not None:
2658
mergeable = bundle.read_mergeable_from_url(
2660
except errors.NotABundle:
2661
pass # Continue on considering this url a Branch
2663
if revision is not None:
2664
raise errors.BzrCommandError(
2665
'Cannot use -r with merge directives or bundles')
2666
other_revision_id = mergeable.install_revisions(
2667
tree.branch.repository)
2668
revision = [RevisionSpec.from_string(
2669
'revid:' + other_revision_id)]
2671
if revision is None \
2672
or len(revision) < 1 or revision[0].needs_branch():
2673
branch = self._get_remembered_parent(tree, branch, 'Merging from')
2675
if revision is None or len(revision) < 1:
2678
other = [branch, None]
2681
other = [branch, -1]
2682
other_branch, path = Branch.open_containing(branch)
2685
raise errors.BzrCommandError('Cannot use --uncommitted and'
2686
' --revision at the same time.')
2687
branch = revision[0].get_branch() or branch
2688
if len(revision) == 1:
2690
if other_revision_id is not None:
2695
other_branch, path = Branch.open_containing(branch)
2696
revno = revision[0].in_history(other_branch).revno
2697
other = [branch, revno]
2699
assert len(revision) == 2
2700
if None in revision:
2701
raise errors.BzrCommandError(
2702
"Merge doesn't permit empty revision specifier.")
2703
base_branch, path = Branch.open_containing(branch)
2704
branch1 = revision[1].get_branch() or branch
2705
other_branch, path1 = Branch.open_containing(branch1)
2706
if revision[0].get_branch() is not None:
2707
# then path was obtained from it, and is None.
2710
base = [branch, revision[0].in_history(base_branch).revno]
2711
other = [branch1, revision[1].in_history(other_branch).revno]
2925
2713
if ((tree.branch.get_parent() is None or remember) and
2926
2714
other_branch is not None):
2927
2715
tree.branch.set_parent(other_branch.base)
2928
_merge_tags_if_possible(other_branch, tree.branch)
2929
merger = _mod_merge.Merger.from_revision_ids(pb, tree,
2930
other_revision_id, base_revision_id, other_branch, base_branch)
2931
if other_path != '':
2932
allow_pending = False
2933
merger.interesting_files = [other_path]
2717
# pull tags now... it's a bit inconsistent to do it ahead of copying
2718
# the history but that's done inside the merge code
2719
if other_branch is not None:
2720
_merge_tags_if_possible(other_branch, tree.branch)
2723
interesting_files = [path]
2935
allow_pending = True
2936
return merger, allow_pending
2938
def _select_branch_location(self, tree, location, revision=None,
2940
"""Select a branch location, according to possible inputs.
2942
If provided, branches from ``revision`` are preferred. (Both
2943
``revision`` and ``index`` must be supplied.)
2945
Otherwise, the ``location`` parameter is used. If it is None, then the
2946
``parent`` location is used, and a note is printed.
2948
:param tree: The working tree to select a branch for merging into
2949
:param location: The location entered by the user
2950
:param revision: The revision parameter to the command
2951
:param index: The index to use for the revision parameter. Negative
2952
indices are permitted.
2953
:return: (selected_location, default_location). The default location
2954
will be the user-entered location, if any, or else the remembered
2957
if (revision is not None and index is not None
2958
and revision[index] is not None):
2959
branch = revision[index].get_branch()
2960
if branch is not None:
2961
return branch, location
2962
location = self._get_remembered_parent(tree, location, 'Merging from')
2963
return location, location
2725
interesting_files = None
2726
pb = ui.ui_factory.nested_progress_bar()
2729
conflict_count = _merge_helper(
2730
other, base, other_rev_id=other_revision_id,
2731
check_clean=(not force),
2732
merge_type=merge_type,
2733
reprocess=reprocess,
2734
show_base=show_base,
2737
pb=pb, file_list=interesting_files,
2738
change_reporter=change_reporter)
2741
if conflict_count != 0:
2745
except errors.AmbiguousBase, e:
2746
m = ("sorry, bzr can't determine the right merge base yet\n"
2747
"candidates are:\n "
2748
+ "\n ".join(e.bases)
2750
"please specify an explicit base with -r,\n"
2751
"and (if you want) report this to the bzr developers\n")
2965
2754
# TODO: move up to common parent; this isn't merge-specific anymore.
2966
2755
def _get_remembered_parent(self, tree, supplied_location, verb_string):
3307
3060
return status_code
3310
class cmd_pack(Command):
3311
"""Compress the data within a repository."""
3313
_see_also = ['repositories']
3314
takes_args = ['branch_or_repo?']
3316
def run(self, branch_or_repo='.'):
3317
dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
3319
branch = dir.open_branch()
3320
repository = branch.repository
3321
except errors.NotBranchError:
3322
repository = dir.open_repository()
3326
3063
class cmd_plugins(Command):
3327
"""List the installed plugins.
3329
This command displays the list of installed plugins including the
3330
path where each one is located and a short description of each.
3332
A plugin is an external component for Bazaar that extends the
3333
revision control system, by adding or replacing code in Bazaar.
3334
Plugins can do a variety of things, including overriding commands,
3335
adding new commands, providing additional network transports and
3336
customizing log output.
3338
See the Bazaar web site, http://bazaar-vcs.org, for further
3339
information on plugins including where to find them and how to
3340
install them. Instructions are also provided there on how to
3341
write new plugins using the Python programming language.
3344
3066
@display_command
3346
3068
import bzrlib.plugin
3347
3069
from inspect import getdoc
3348
for name, plugin in bzrlib.plugin.plugins().items():
3349
print plugin.path(), "[%s]" % plugin.__version__
3350
d = getdoc(plugin.module)
3070
for name, plugin in bzrlib.plugin.all_plugins().items():
3071
if getattr(plugin, '__path__', None) is not None:
3072
print plugin.__path__[0]
3073
elif getattr(plugin, '__file__', None) is not None:
3074
print plugin.__file__
3352
3080
print '\t', d.split('\n')[0]
3355
3083
class cmd_testament(Command):
3356
3084
"""Show testament (signing-form) of a revision."""
3359
Option('long', help='Produce long-format testament.'),
3361
help='Produce a strict-format testament.')]
3085
takes_options = ['revision',
3086
Option('long', help='Produce long-format testament'),
3087
Option('strict', help='Produce a strict-format'
3362
3089
takes_args = ['branch?']
3363
3090
@display_command
3364
3091
def run(self, branch=u'.', revision=None, long=False, strict=False):
3852
3526
takes_args = ['submit_branch?', 'public_branch?']
3856
_see_also = ['send']
3858
3528
takes_options = [
3859
3529
RegistryOption.from_kwargs('patch-type',
3860
'The type of patch to include in the directive.',
3862
value_switches=True,
3864
bundle='Bazaar revision bundle (default).',
3865
diff='Normal unified diff.',
3866
plain='No patch, just directive.'),
3867
Option('sign', help='GPG-sign the directive.'), 'revision',
3530
'The type of patch to include in the directive',
3531
title='Patch type', value_switches=True, enum_switch=False,
3532
bundle='Bazaar revision bundle (default)',
3533
diff='Normal unified diff',
3534
plain='No patch, just directive'),
3535
Option('sign', help='GPG-sign the directive'), 'revision',
3868
3536
Option('mail-to', type=str,
3869
help='Instead of printing the directive, email to this address.'),
3537
help='Instead of printing the directive, email to this address'),
3870
3538
Option('message', type=str, short_name='m',
3871
help='Message to use when committing this merge.')
3539
help='Message to use when committing this merge')
3874
encoding_type = 'exact'
3876
3542
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
3877
3543
sign=False, revision=None, mail_to=None, message=None):
3878
from bzrlib.revision import ensure_null, NULL_REVISION
3879
include_patch, include_bundle = {
3880
'plain': (False, False),
3881
'diff': (True, False),
3882
'bundle': (True, True),
3544
if patch_type == 'plain':
3884
3546
branch = Branch.open('.')
3885
3547
stored_submit_branch = branch.get_submit_branch()
3886
3548
if submit_branch is None:
3928
3583
self.outf.writelines(directive.to_lines())
3930
3585
message = directive.to_email(mail_to, branch, sign)
3931
s = SMTPConnection(branch.get_config())
3932
s.send_email(message)
3935
class cmd_send(Command):
3936
"""Mail or create a merge-directive for submiting changes.
3938
A merge directive provides many things needed for requesting merges:
3940
* A machine-readable description of the merge to perform
3942
* An optional patch that is a preview of the changes requested
3944
* An optional bundle of revision data, so that the changes can be applied
3945
directly from the merge directive, without retrieving data from a
3948
If --no-bundle is specified, then public_branch is needed (and must be
3949
up-to-date), so that the receiver can perform the merge using the
3950
public_branch. The public_branch is always included if known, so that
3951
people can check it later.
3953
The submit branch defaults to the parent, but can be overridden. Both
3954
submit branch and public branch will be remembered if supplied.
3956
If a public_branch is known for the submit_branch, that public submit
3957
branch is used in the merge instructions. This means that a local mirror
3958
can be used as your actual submit branch, once you have set public_branch
3961
Mail is sent using your preferred mail program. This should be transparent
3962
on Windows (it uses MAPI). On Linux, it requires the xdg-email utility.
3963
If the preferred client can't be found (or used), your editor will be used.
3965
To use a specific mail program, set the mail_client configuration option.
3966
(For Thunderbird 1.5, this works around some bugs.) Supported values for
3967
specific clients are "evolution", "kmail", "mutt", and "thunderbird";
3968
generic options are "default", "editor", "mapi", and "xdg-email".
3970
If mail is being sent, a to address is required. This can be supplied
3971
either on the commandline, or by setting the submit_to configuration
3974
Two formats are currently supported: "4" uses revision bundle format 4 and
3975
merge directive format 2. It is significantly faster and smaller than
3976
older formats. It is compatible with Bazaar 0.19 and later. It is the
3977
default. "0.9" uses revision bundle format 0.9 and merge directive
3978
format 1. It is compatible with Bazaar 0.12 - 0.18.
3981
encoding_type = 'exact'
3983
_see_also = ['merge']
3985
takes_args = ['submit_branch?', 'public_branch?']
3989
help='Do not include a bundle in the merge directive.'),
3990
Option('no-patch', help='Do not include a preview patch in the merge'
3993
help='Remember submit and public branch.'),
3995
help='Branch to generate the submission from, '
3996
'rather than the one containing the working directory.',
3999
Option('output', short_name='o', help='Write directive to this file.',
4001
Option('mail-to', help='Mail the request to this address.',
4005
RegistryOption.from_kwargs('format',
4006
'Use the specified output format.',
4007
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4008
'0.9': 'Bundle format 0.9, Merge Directive 1',})
4011
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4012
no_patch=False, revision=None, remember=False, output=None,
4013
format='4', mail_to=None, message=None, **kwargs):
4014
return self._run(submit_branch, revision, public_branch, remember,
4015
format, no_bundle, no_patch, output,
4016
kwargs.get('from', '.'), mail_to, message)
4018
def _run(self, submit_branch, revision, public_branch, remember, format,
4019
no_bundle, no_patch, output, from_, mail_to, message):
4020
from bzrlib.revision import NULL_REVISION
4021
branch = Branch.open_containing(from_)[0]
4023
outfile = StringIO()
4027
outfile = open(output, 'wb')
4028
# we may need to write data into branch's repository to calculate
4033
config = branch.get_config()
4035
mail_to = config.get_user_option('submit_to')
4036
mail_client = config.get_mail_client()
4037
if remember and submit_branch is None:
4038
raise errors.BzrCommandError(
4039
'--remember requires a branch to be specified.')
4040
stored_submit_branch = branch.get_submit_branch()
4041
remembered_submit_branch = False
4042
if submit_branch is None:
4043
submit_branch = stored_submit_branch
4044
remembered_submit_branch = True
4046
if stored_submit_branch is None or remember:
4047
branch.set_submit_branch(submit_branch)
4048
if submit_branch is None:
4049
submit_branch = branch.get_parent()
4050
remembered_submit_branch = True
4051
if submit_branch is None:
4052
raise errors.BzrCommandError('No submit branch known or'
4054
if remembered_submit_branch:
4055
note('Using saved location: %s', submit_branch)
4057
stored_public_branch = branch.get_public_branch()
4058
if public_branch is None:
4059
public_branch = stored_public_branch
4060
elif stored_public_branch is None or remember:
4061
branch.set_public_branch(public_branch)
4062
if no_bundle and public_branch is None:
4063
raise errors.BzrCommandError('No public branch specified or'
4065
base_revision_id = None
4067
if revision is not None:
4068
if len(revision) > 2:
4069
raise errors.BzrCommandError('bzr send takes '
4070
'at most two one revision identifiers')
4071
revision_id = revision[-1].in_history(branch).rev_id
4072
if len(revision) == 2:
4073
base_revision_id = revision[0].in_history(branch).rev_id
4074
if revision_id is None:
4075
revision_id = branch.last_revision()
4076
if revision_id == NULL_REVISION:
4077
raise errors.BzrCommandError('No revisions to submit.')
4079
directive = merge_directive.MergeDirective2.from_objects(
4080
branch.repository, revision_id, time.time(),
4081
osutils.local_time_offset(), submit_branch,
4082
public_branch=public_branch, include_patch=not no_patch,
4083
include_bundle=not no_bundle, message=message,
4084
base_revision_id=base_revision_id)
4085
elif format == '0.9':
4088
patch_type = 'bundle'
4090
raise errors.BzrCommandError('Format 0.9 does not'
4091
' permit bundle with no patch')
4097
directive = merge_directive.MergeDirective.from_objects(
4098
branch.repository, revision_id, time.time(),
4099
osutils.local_time_offset(), submit_branch,
4100
public_branch=public_branch, patch_type=patch_type,
4103
outfile.writelines(directive.to_lines())
4105
subject = '[MERGE] '
4106
if message is not None:
4109
revision = branch.repository.get_revision(revision_id)
4110
subject += revision.get_summary()
4111
mail_client.compose_merge_request(mail_to, subject,
4119
class cmd_bundle_revisions(cmd_send):
4121
"""Create a merge-directive for submiting changes.
4123
A merge directive provides many things needed for requesting merges:
4125
* A machine-readable description of the merge to perform
4127
* An optional patch that is a preview of the changes requested
4129
* An optional bundle of revision data, so that the changes can be applied
4130
directly from the merge directive, without retrieving data from a
4133
If --no-bundle is specified, then public_branch is needed (and must be
4134
up-to-date), so that the receiver can perform the merge using the
4135
public_branch. The public_branch is always included if known, so that
4136
people can check it later.
4138
The submit branch defaults to the parent, but can be overridden. Both
4139
submit branch and public branch will be remembered if supplied.
4141
If a public_branch is known for the submit_branch, that public submit
4142
branch is used in the merge instructions. This means that a local mirror
4143
can be used as your actual submit branch, once you have set public_branch
4146
Two formats are currently supported: "4" uses revision bundle format 4 and
4147
merge directive format 2. It is significantly faster and smaller than
4148
older formats. It is compatible with Bazaar 0.19 and later. It is the
4149
default. "0.9" uses revision bundle format 0.9 and merge directive
4150
format 1. It is compatible with Bazaar 0.12 - 0.18.
4155
help='Do not include a bundle in the merge directive.'),
4156
Option('no-patch', help='Do not include a preview patch in the merge'
4159
help='Remember submit and public branch.'),
4161
help='Branch to generate the submission from, '
4162
'rather than the one containing the working directory.',
4165
Option('output', short_name='o', help='Write directive to this file.',
4168
RegistryOption.from_kwargs('format',
4169
'Use the specified output format.',
4170
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4171
'0.9': 'Bundle format 0.9, Merge Directive 1',})
4173
aliases = ['bundle']
4175
_see_also = ['send', 'merge']
4179
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4180
no_patch=False, revision=None, remember=False, output=None,
4181
format='4', **kwargs):
4184
return self._run(submit_branch, revision, public_branch, remember,
4185
format, no_bundle, no_patch, output,
4186
kwargs.get('from', '.'), None, None)
3587
server = branch.get_config().get_user_option('smtp_server')
3589
server = 'localhost'
3591
s.sendmail(message['From'], message['To'], message.as_string())
4189
3594
class cmd_tag(Command):
4190
"""Create, remove or modify a tag naming a revision.
3595
"""Create a tag naming a revision.
4192
3597
Tags give human-meaningful names to revisions. Commands that take a -r
4193
3598
(--revision) option can be given -rtag:X, where X is any previously
4249
3654
class cmd_tags(Command):
4252
This command shows a table of tag names and the revisions they reference.
3657
This tag shows a table of tag names and the revisions they reference.
4255
3660
_see_also = ['tag']
4256
3661
takes_options = [
4257
3662
Option('directory',
4258
help='Branch whose tags should be displayed.',
3663
help='Branch whose tags should be displayed',
4259
3664
short_name='d',
4262
RegistryOption.from_kwargs('sort',
4263
'Sort tags by different criteria.', title='Sorting',
4264
alpha='Sort tags lexicographically (default).',
4265
time='Sort tags chronologically.',
4270
3669
@display_command
4276
3673
branch, relpath = Branch.open_containing(directory)
4277
tags = branch.tags.get_tag_dict().items()
4280
elif sort == 'time':
4282
for tag, revid in tags:
4284
revobj = branch.repository.get_revision(revid)
4285
except errors.NoSuchRevision:
4286
timestamp = sys.maxint # place them at the end
3674
for tag_name, target in sorted(branch.tags.get_tag_dict().items()):
3675
self.outf.write('%-20s %s\n' % (tag_name, target))
3678
# command-line interpretation helper for merge-related commands
3679
def _merge_helper(other_revision, base_revision,
3680
check_clean=True, ignore_zero=False,
3681
this_dir=None, backup_files=False,
3683
file_list=None, show_base=False, reprocess=False,
3686
change_reporter=None,
3688
"""Merge changes into a tree.
3691
list(path, revno) Base for three-way merge.
3692
If [None, None] then a base will be automatically determined.
3694
list(path, revno) Other revision for three-way merge.
3696
Directory to merge changes into; '.' by default.
3698
If true, this_dir must have no uncommitted changes before the
3700
ignore_zero - If true, suppress the "zero conflicts" message when
3701
there are no conflicts; should be set when doing something we expect
3702
to complete perfectly.
3703
file_list - If supplied, merge only changes to selected files.
3705
All available ancestors of other_revision and base_revision are
3706
automatically pulled into the branch.
3708
The revno may be -1 to indicate the last revision on the branch, which is
3711
This function is intended for use from the command line; programmatic
3712
clients might prefer to call merge.merge_inner(), which has less magic
3715
# Loading it late, so that we don't always have to import bzrlib.merge
3716
if merge_type is None:
3717
merge_type = _mod_merge.Merge3Merger
3718
if this_dir is None:
3720
this_tree = WorkingTree.open_containing(this_dir)[0]
3721
if show_base and not merge_type is _mod_merge.Merge3Merger:
3722
raise errors.BzrCommandError("Show-base is not supported for this merge"
3723
" type. %s" % merge_type)
3724
if reprocess and not merge_type.supports_reprocess:
3725
raise errors.BzrCommandError("Conflict reduction is not supported for merge"
3726
" type %s." % merge_type)
3727
if reprocess and show_base:
3728
raise errors.BzrCommandError("Cannot do conflict reduction and show base.")
3729
# TODO: jam 20070226 We should really lock these trees earlier. However, we
3730
# only want to take out a lock_tree_write() if we don't have to pull
3731
# any ancestry. But merge might fetch ancestry in the middle, in
3732
# which case we would need a lock_write().
3733
# Because we cannot upgrade locks, for now we live with the fact that
3734
# the tree will be locked multiple times during a merge. (Maybe
3735
# read-only some of the time, but it means things will get read
3738
merger = _mod_merge.Merger(this_tree.branch, this_tree=this_tree,
3739
pb=pb, change_reporter=change_reporter)
3740
merger.pp = ProgressPhase("Merge phase", 5, pb)
3741
merger.pp.next_phase()
3742
merger.check_basis(check_clean)
3743
if other_rev_id is not None:
3744
merger.set_other_revision(other_rev_id, this_tree.branch)
3746
merger.set_other(other_revision)
3747
merger.pp.next_phase()
3748
merger.set_base(base_revision)
3749
if merger.base_rev_id == merger.other_rev_id:
3750
note('Nothing to do.')
3752
if file_list is None:
3753
if pull and merger.base_rev_id == merger.this_rev_id:
3754
# FIXME: deduplicate with pull
3755
result = merger.this_tree.pull(merger.this_branch,
3756
False, merger.other_rev_id)
3757
if result.old_revid == result.new_revid:
3758
note('No revisions to pull.')
4288
timestamp = revobj.timestamp
4289
timestamps[revid] = timestamp
4290
tags.sort(key=lambda x: timestamps[x[1]])
4292
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
4293
revno_map = branch.get_revision_id_to_revno_map()
4294
tags = [ (tag, '.'.join(map(str, revno_map.get(revid, ('?',)))))
4295
for tag, revid in tags ]
4296
for tag, revspec in tags:
4297
self.outf.write('%-20s %s\n' % (tag, revspec))
4300
class cmd_reconfigure(Command):
4301
"""Reconfigure the type of a bzr directory.
4303
A target configuration must be specified.
4305
For checkouts, the bind-to location will be auto-detected if not specified.
4306
The order of preference is
4307
1. For a lightweight checkout, the current bound location.
4308
2. For branches that used to be checkouts, the previously-bound location.
4309
3. The push location.
4310
4. The parent location.
4311
If none of these is available, --bind-to must be specified.
4314
takes_args = ['location?']
4315
takes_options = [RegistryOption.from_kwargs('target_type',
4316
title='Target type',
4317
help='The type to reconfigure the directory to.',
4318
value_switches=True, enum_switch=False,
4319
branch='Reconfigure to a branch.',
4320
tree='Reconfigure to a tree.',
4321
checkout='Reconfigure to a checkout.',
4322
lightweight_checkout='Reconfigure to a lightweight'
4324
Option('bind-to', help='Branch to bind checkout to.',
4327
help='Perform reconfiguration even if local changes'
4331
def run(self, location=None, target_type=None, bind_to=None, force=False):
4332
directory = bzrdir.BzrDir.open(location)
4333
if target_type is None:
4334
raise errors.BzrCommandError('No target configuration specified')
4335
elif target_type == 'branch':
4336
reconfiguration = reconfigure.Reconfigure.to_branch(directory)
4337
elif target_type == 'tree':
4338
reconfiguration = reconfigure.Reconfigure.to_tree(directory)
4339
elif target_type == 'checkout':
4340
reconfiguration = reconfigure.Reconfigure.to_checkout(directory,
4342
elif target_type == 'lightweight-checkout':
4343
reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
4345
reconfiguration.apply(force)
4348
class cmd_switch(Command):
4349
"""Set the branch of a checkout and update.
4351
For lightweight checkouts, this changes the branch being referenced.
4352
For heavyweight checkouts, this checks that there are no local commits
4353
versus the current bound branch, then it makes the local branch a mirror
4354
of the new location and binds to it.
4356
In both cases, the working tree is updated and uncommitted changes
4357
are merged. The user can commit or revert these as they desire.
4359
Pending merges need to be committed or reverted before using switch.
4362
takes_args = ['to_location']
4363
takes_options = [Option('force',
4364
help='Switch even if local commits will be lost.')
4367
def run(self, to_location, force=False):
4368
from bzrlib import switch
4369
to_branch = Branch.open(to_location)
4371
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
4372
switch.switch(control_dir, to_branch, force)
4373
note('Switched to branch: %s',
4374
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
3760
note('Now on revision %d.' % result.new_revno)
3762
merger.backup_files = backup_files
3763
merger.merge_type = merge_type
3764
merger.set_interesting_files(file_list)
3765
merger.show_base = show_base
3766
merger.reprocess = reprocess
3767
conflicts = merger.do_merge()
3768
if file_list is None:
3769
merger.set_pending()
4377
3775
def _create_prefix(cur_transport):