1362
1423
class cmd_diff(Command):
1363
"""Show differences in the working tree or between revisions.
1424
"""Show differences in the working tree, between revisions or branches.
1365
If files are listed, only the changes in those files are listed.
1366
Otherwise, all changes for the tree are listed.
1426
If no arguments are given, all changes for the current tree are listed.
1427
If files are given, only the changes in those files are listed.
1428
Remote and multiple branches can be compared by using the --old and
1429
--new options. If not provided, the default for both is derived from
1430
the first argument, if any, or the current tree if no arguments are
1368
1433
"bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1369
1434
produces patches suitable for "patch -p1".
1373
Shows the difference in the working tree versus the last commit
1375
Difference between the working tree and revision 1
1377
Difference between revision 2 and revision 1
1378
bzr diff --prefix old/:new/
1379
Same as 'bzr diff' but prefix paths with old/ and new/
1380
bzr diff bzr.mine bzr.dev
1381
Show the differences between the two working trees
1383
Show just the differences for 'foo.c'
1438
2 - unrepresentable changes
1443
Shows the difference in the working tree versus the last commit::
1447
Difference between the working tree and revision 1::
1451
Difference between revision 2 and revision 1::
1455
Difference between revision 2 and revision 1 for branch xxx::
1459
Show just the differences for file NEWS::
1463
Show the differences in working tree xxx for file NEWS::
1467
Show the differences from branch xxx to this working tree:
1471
Show the differences between two branches for file NEWS::
1473
bzr diff --old xxx --new yyy NEWS
1475
Same as 'bzr diff' but prefix paths with old/ and new/::
1477
bzr diff --prefix old/:new/
1385
# TODO: Option to use external diff command; could be GNU diff, wdiff,
1386
# or a graphical diff.
1388
# TODO: Python difflib is not exactly the same as unidiff; should
1389
# either fix it up or prefer to use an external diff.
1391
# TODO: Selected-file diff is inefficient and doesn't show you
1394
# TODO: This probably handles non-Unix newlines poorly.
1396
1479
_see_also = ['status']
1397
1480
takes_args = ['file*']
1398
takes_options = ['revision', 'diff-options',
1482
Option('diff-options', type=str,
1483
help='Pass these options to the external diff program.'),
1399
1484
Option('prefix', type=str,
1400
1485
short_name='p',
1401
help='Set prefixes to added to old and new filenames, as '
1402
'two values separated by a colon. (eg "old/:new/")'),
1486
help='Set prefixes added to old and new filenames, as '
1487
'two values separated by a colon. (eg "old/:new/").'),
1489
help='Branch/tree to compare from.',
1493
help='Branch/tree to compare to.',
1499
help='Use this command to compare files.',
1404
1503
aliases = ['di', 'dif']
1405
1504
encoding_type = 'exact'
1407
1506
@display_command
1408
1507
def run(self, revision=None, file_list=None, diff_options=None,
1410
from bzrlib.diff import diff_cmd_helper, show_diff_trees
1508
prefix=None, old=None, new=None, using=None):
1509
from bzrlib.diff import _get_trees_to_diff, show_diff_trees
1412
1511
if (prefix is None) or (prefix == '0'):
1413
1512
# diff -p0 format
2410
2595
takes_args = ['testspecs*']
2411
2596
takes_options = ['verbose',
2413
help='stop when one test fails',
2598
help='Stop when one test fails.',
2414
2599
short_name='1',
2416
Option('keep-output',
2417
help='keep output directories when tests fail'),
2418
2601
Option('transport',
2419
2602
help='Use a different transport by default '
2420
2603
'throughout the test suite.',
2421
2604
type=get_transport_type),
2422
Option('benchmark', help='run the bzr benchmarks.'),
2606
help='Run the benchmarks rather than selftests.'),
2423
2607
Option('lsprof-timed',
2424
help='generate lsprof output for benchmarked'
2608
help='Generate lsprof output for benchmarked'
2425
2609
' sections of code.'),
2426
2610
Option('cache-dir', type=str,
2427
help='a directory to cache intermediate'
2428
' benchmark steps'),
2429
Option('clean-output',
2430
help='clean temporary tests directories'
2431
' without running tests'),
2611
help='Cache intermediate benchmark output in this '
2432
2613
Option('first',
2433
help='run all tests, but run specified tests first',
2614
help='Run all tests, but run specified tests first.',
2434
2615
short_name='f',
2436
Option('numbered-dirs',
2437
help='use numbered dirs for TestCaseInTempDir'),
2438
2617
Option('list-only',
2439
help='list the tests instead of running them'),
2618
help='List the tests instead of running them.'),
2440
2619
Option('randomize', type=str, argname="SEED",
2441
help='randomize the order of tests using the given'
2442
' seed or "now" for the current time'),
2620
help='Randomize the order of tests using the given'
2621
' seed or "now" for the current time.'),
2443
2622
Option('exclude', type=str, argname="PATTERN",
2444
2623
short_name='x',
2445
help='exclude tests that match this regular'
2624
help='Exclude tests that match this regular'
2626
Option('strict', help='Fail on missing dependencies or '
2628
Option('load-list', type=str, argname='TESTLISTFILE',
2629
help='Load a test id list from a text file.'),
2448
2631
encoding_type = 'replace'
2450
def run(self, testspecs_list=None, verbose=None, one=False,
2451
keep_output=False, transport=None, benchmark=None,
2452
lsprof_timed=None, cache_dir=None, clean_output=False,
2453
first=False, numbered_dirs=None, list_only=False,
2454
randomize=None, exclude=None):
2633
def run(self, testspecs_list=None, verbose=False, one=False,
2634
transport=None, benchmark=None,
2635
lsprof_timed=None, cache_dir=None,
2636
first=False, list_only=False,
2637
randomize=None, exclude=None, strict=False,
2455
2639
import bzrlib.ui
2456
2640
from bzrlib.tests import selftest
2457
2641
import bzrlib.benchmarks as benchmarks
2458
2642
from bzrlib.benchmarks import tree_creator
2461
from bzrlib.tests import clean_selftest_output
2462
clean_selftest_output()
2465
if numbered_dirs is None and sys.platform == 'win32':
2466
numbered_dirs = True
2468
2644
if cache_dir is not None:
2469
2645
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2470
print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
2471
print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
2647
print 'testing: %s' % (osutils.realpath(sys.argv[0]),)
2648
print ' %s (%s python%s)' % (
2650
bzrlib.version_string,
2651
'.'.join(map(str, sys.version_info)),
2473
2654
if testspecs_list is not None:
2474
2655
pattern = '|'.join(testspecs_list)
2582
2768
The results of the merge are placed into the destination working
2583
2769
directory, where they can be reviewed (with bzr diff), tested, and then
2584
2770
committed to record the result of the merge.
2588
To merge the latest revision from bzr.dev:
2589
bzr merge ../bzr.dev
2591
To merge changes up to and including revision 82 from bzr.dev:
2592
bzr merge -r 82 ../bzr.dev
2594
To merge the changes introduced by 82, without previous changes:
2595
bzr merge -r 81..82 ../bzr.dev
2597
2772
merge refuses to run if there are any uncommitted changes, unless
2598
2773
--force is given.
2776
To merge the latest revision from bzr.dev::
2778
bzr merge ../bzr.dev
2780
To merge changes up to and including revision 82 from bzr.dev::
2782
bzr merge -r 82 ../bzr.dev
2784
To merge the changes introduced by 82, without previous changes::
2786
bzr merge -r 81..82 ../bzr.dev
2601
_see_also = ['update', 'remerge']
2789
encoding_type = 'exact'
2790
_see_also = ['update', 'remerge', 'status-flags']
2602
2791
takes_args = ['branch?']
2603
takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
2796
help='Merge even if the destination tree has uncommitted changes.'),
2604
2800
Option('show-base', help="Show base revision text in "
2606
2802
Option('uncommitted', help='Apply uncommitted changes'
2607
' from a working copy, instead of branch changes'),
2803
' from a working copy, instead of branch changes.'),
2608
2804
Option('pull', help='If the destination is already'
2609
2805
' completely merged into the source, pull from the'
2610
' source rather than merging. When this happens,'
2806
' source rather than merging. When this happens,'
2611
2807
' you do not need to commit the result.'),
2612
2808
Option('directory',
2613
help='Branch to merge into, '
2614
'rather than the one containing the working directory',
2809
help='Branch to merge into, '
2810
'rather than the one containing the working directory.',
2814
Option('preview', help='Instead of merging, show a diff of the merge.')
2620
2817
def run(self, branch=None, revision=None, force=False, merge_type=None,
2621
2818
show_base=False, reprocess=False, remember=False,
2622
2819
uncommitted=False, pull=False,
2623
2820
directory=None,
2625
from bzrlib.tag import _merge_tags_if_possible
2626
other_revision_id = None
2823
# This is actually a branch (or merge-directive) *location*.
2627
2827
if merge_type is None:
2628
2828
merge_type = _mod_merge.Merge3Merger
2630
2830
if directory is None: directory = u'.'
2631
# XXX: jam 20070225 WorkingTree should be locked before you extract its
2632
# inventory. Because merge is a mutating operation, it really
2633
# should be a lock_write() for the whole cmd_merge operation.
2634
# However, cmd_merge open's its own tree in _merge_helper, which
2635
# means if we lock here, the later lock_write() will always block.
2636
# Either the merge helper code should be updated to take a tree,
2637
# (What about tree.merge_from_branch?)
2831
possible_transports = []
2833
allow_pending = True
2834
verified = 'inapplicable'
2638
2835
tree = WorkingTree.open_containing(directory)[0]
2639
2836
change_reporter = delta._ChangeReporter(
2640
2837
unversioned_filter=tree.is_ignored)
2642
if branch is not None:
2644
mergeable = bundle.read_mergeable_from_url(
2646
except errors.NotABundle:
2647
pass # Continue on considering this url a Branch
2649
if revision is not None:
2650
raise errors.BzrCommandError(
2651
'Cannot use -r with merge directives or bundles')
2652
other_revision_id = mergeable.install_revisions(
2653
tree.branch.repository)
2654
revision = [RevisionSpec.from_string(
2655
'revid:' + other_revision_id)]
2657
if revision is None \
2658
or len(revision) < 1 or revision[0].needs_branch():
2659
branch = self._get_remembered_parent(tree, branch, 'Merging from')
2661
if revision is None or len(revision) < 1:
2664
other = [branch, None]
2667
other = [branch, -1]
2668
other_branch, path = Branch.open_containing(branch)
2671
raise errors.BzrCommandError('Cannot use --uncommitted and'
2672
' --revision at the same time.')
2673
branch = revision[0].get_branch() or branch
2674
if len(revision) == 1:
2676
if other_revision_id is not None:
2681
other_branch, path = Branch.open_containing(branch)
2682
revno = revision[0].in_history(other_branch).revno
2683
other = [branch, revno]
2685
assert len(revision) == 2
2686
if None in revision:
2687
raise errors.BzrCommandError(
2688
"Merge doesn't permit empty revision specifier.")
2689
base_branch, path = Branch.open_containing(branch)
2690
branch1 = revision[1].get_branch() or branch
2691
other_branch, path1 = Branch.open_containing(branch1)
2692
if revision[0].get_branch() is not None:
2693
# then path was obtained from it, and is None.
2696
base = [branch, revision[0].in_history(base_branch).revno]
2697
other = [branch1, revision[1].in_history(other_branch).revno]
2699
if ((tree.branch.get_parent() is None or remember) and
2700
other_branch is not None):
2701
tree.branch.set_parent(other_branch.base)
2703
# pull tags now... it's a bit inconsistent to do it ahead of copying
2704
# the history but that's done inside the merge code
2705
if other_branch is not None:
2706
_merge_tags_if_possible(other_branch, tree.branch)
2709
interesting_files = [path]
2711
interesting_files = None
2712
pb = ui.ui_factory.nested_progress_bar()
2715
conflict_count = _merge_helper(
2716
other, base, other_rev_id=other_revision_id,
2717
check_clean=(not force),
2718
merge_type=merge_type,
2719
reprocess=reprocess,
2720
show_base=show_base,
2723
pb=pb, file_list=interesting_files,
2724
change_reporter=change_reporter)
2727
if conflict_count != 0:
2840
pb = ui.ui_factory.nested_progress_bar()
2841
cleanups.append(pb.finished)
2843
cleanups.append(tree.unlock)
2844
if location is not None:
2845
mergeable, other_transport = _get_mergeable_helper(location)
2848
raise errors.BzrCommandError('Cannot use --uncommitted'
2849
' with bundles or merge directives.')
2851
if revision is not None:
2852
raise errors.BzrCommandError(
2853
'Cannot use -r with merge directives or bundles')
2854
merger, verified = _mod_merge.Merger.from_mergeable(tree,
2856
possible_transports.append(other_transport)
2858
if merger is None and uncommitted:
2859
if revision is not None and len(revision) > 0:
2860
raise errors.BzrCommandError('Cannot use --uncommitted and'
2861
' --revision at the same time.')
2862
location = self._select_branch_location(tree, location)[0]
2863
other_tree, other_path = WorkingTree.open_containing(location)
2864
merger = _mod_merge.Merger.from_uncommitted(tree, other_tree,
2866
allow_pending = False
2867
if other_path != '':
2868
merger.interesting_files = [other_path]
2871
merger, allow_pending = self._get_merger_from_branch(tree,
2872
location, revision, remember, possible_transports, pb)
2874
merger.merge_type = merge_type
2875
merger.reprocess = reprocess
2876
merger.show_base = show_base
2877
self.sanity_check_merger(merger)
2878
if (merger.base_rev_id == merger.other_rev_id and
2879
merger.other_rev_id != None):
2880
note('Nothing to do.')
2731
except errors.AmbiguousBase, e:
2732
m = ("sorry, bzr can't determine the right merge base yet\n"
2733
"candidates are:\n "
2734
+ "\n ".join(e.bases)
2736
"please specify an explicit base with -r,\n"
2737
"and (if you want) report this to the bzr developers\n")
2740
# TODO: move up to common parent; this isn't merge-specific anymore.
2741
def _get_remembered_parent(self, tree, supplied_location, verb_string):
2883
if merger.interesting_files is not None:
2884
raise errors.BzrCommandError('Cannot pull individual files')
2885
if (merger.base_rev_id == tree.last_revision()):
2886
result = tree.pull(merger.other_branch, False,
2887
merger.other_rev_id)
2888
result.report(self.outf)
2890
merger.check_basis(not force)
2892
return self._do_preview(merger)
2894
return self._do_merge(merger, change_reporter, allow_pending,
2897
for cleanup in reversed(cleanups):
2900
def _do_preview(self, merger):
2901
from bzrlib.diff import show_diff_trees
2902
tree_merger = merger.make_merger()
2903
tt = tree_merger.make_preview_transform()
2905
result_tree = tt.get_preview_tree()
2906
show_diff_trees(merger.this_tree, result_tree, self.outf,
2907
old_label='', new_label='')
2911
def _do_merge(self, merger, change_reporter, allow_pending, verified):
2912
merger.change_reporter = change_reporter
2913
conflict_count = merger.do_merge()
2915
merger.set_pending()
2916
if verified == 'failed':
2917
warning('Preview patch does not match changes')
2918
if conflict_count != 0:
2923
def sanity_check_merger(self, merger):
2924
if (merger.show_base and
2925
not merger.merge_type is _mod_merge.Merge3Merger):
2926
raise errors.BzrCommandError("Show-base is not supported for this"
2927
" merge type. %s" % merger.merge_type)
2928
if merger.reprocess and not merger.merge_type.supports_reprocess:
2929
raise errors.BzrCommandError("Conflict reduction is not supported"
2930
" for merge type %s." %
2932
if merger.reprocess and merger.show_base:
2933
raise errors.BzrCommandError("Cannot do conflict reduction and"
2936
def _get_merger_from_branch(self, tree, location, revision, remember,
2937
possible_transports, pb):
2938
"""Produce a merger from a location, assuming it refers to a branch."""
2939
from bzrlib.tag import _merge_tags_if_possible
2940
assert revision is None or len(revision) < 3
2941
# find the branch locations
2942
other_loc, user_location = self._select_branch_location(tree, location,
2944
if revision is not None and len(revision) == 2:
2945
base_loc, _unused = self._select_branch_location(tree,
2946
location, revision, 0)
2948
base_loc = other_loc
2950
other_branch, other_path = Branch.open_containing(other_loc,
2951
possible_transports)
2952
if base_loc == other_loc:
2953
base_branch = other_branch
2955
base_branch, base_path = Branch.open_containing(base_loc,
2956
possible_transports)
2957
# Find the revision ids
2958
if revision is None or len(revision) < 1 or revision[-1] is None:
2959
other_revision_id = _mod_revision.ensure_null(
2960
other_branch.last_revision())
2962
other_revision_id = \
2963
_mod_revision.ensure_null(
2964
revision[-1].in_history(other_branch).rev_id)
2965
if (revision is not None and len(revision) == 2
2966
and revision[0] is not None):
2967
base_revision_id = \
2968
_mod_revision.ensure_null(
2969
revision[0].in_history(base_branch).rev_id)
2971
base_revision_id = None
2972
# Remember where we merge from
2973
if ((remember or tree.branch.get_submit_branch() is None) and
2974
user_location is not None):
2975
tree.branch.set_submit_branch(other_branch.base)
2976
_merge_tags_if_possible(other_branch, tree.branch)
2977
merger = _mod_merge.Merger.from_revision_ids(pb, tree,
2978
other_revision_id, base_revision_id, other_branch, base_branch)
2979
if other_path != '':
2980
allow_pending = False
2981
merger.interesting_files = [other_path]
2983
allow_pending = True
2984
return merger, allow_pending
2986
def _select_branch_location(self, tree, user_location, revision=None,
2988
"""Select a branch location, according to possible inputs.
2990
If provided, branches from ``revision`` are preferred. (Both
2991
``revision`` and ``index`` must be supplied.)
2993
Otherwise, the ``location`` parameter is used. If it is None, then the
2994
``submit`` or ``parent`` location is used, and a note is printed.
2996
:param tree: The working tree to select a branch for merging into
2997
:param location: The location entered by the user
2998
:param revision: The revision parameter to the command
2999
:param index: The index to use for the revision parameter. Negative
3000
indices are permitted.
3001
:return: (selected_location, user_location). The default location
3002
will be the user-entered location.
3004
if (revision is not None and index is not None
3005
and revision[index] is not None):
3006
branch = revision[index].get_branch()
3007
if branch is not None:
3008
return branch, branch
3009
if user_location is None:
3010
location = self._get_remembered(tree, 'Merging from')
3012
location = user_location
3013
return location, user_location
3015
def _get_remembered(self, tree, verb_string):
2742
3016
"""Use tree.branch's parent if none was supplied.
2744
3018
Report if the remembered location was used.
2746
if supplied_location is not None:
2747
return supplied_location
2748
stored_location = tree.branch.get_parent()
3020
stored_location = tree.branch.get_submit_branch()
3021
if stored_location is None:
3022
stored_location = tree.branch.get_parent()
2749
3023
mutter("%s", stored_location)
2750
3024
if stored_location is None:
2751
3025
raise errors.BzrCommandError("No location specified or remembered")
2752
display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
2753
self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
3026
display_url = urlutils.unescape_for_display(stored_location, 'utf-8')
3027
note(u"%s remembered location %s", verb_string, display_url)
2754
3028
return stored_location
3036
3354
return status_code
3357
class cmd_pack(Command):
3358
"""Compress the data within a repository."""
3360
_see_also = ['repositories']
3361
takes_args = ['branch_or_repo?']
3363
def run(self, branch_or_repo='.'):
3364
dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
3366
branch = dir.open_branch()
3367
repository = branch.repository
3368
except errors.NotBranchError:
3369
repository = dir.open_repository()
3039
3373
class cmd_plugins(Command):
3374
"""List the installed plugins.
3376
This command displays the list of installed plugins including
3377
version of plugin and a short description of each.
3379
--verbose shows the path where each plugin is located.
3381
A plugin is an external component for Bazaar that extends the
3382
revision control system, by adding or replacing code in Bazaar.
3383
Plugins can do a variety of things, including overriding commands,
3384
adding new commands, providing additional network transports and
3385
customizing log output.
3387
See the Bazaar web site, http://bazaar-vcs.org, for further
3388
information on plugins including where to find them and how to
3389
install them. Instructions are also provided there on how to
3390
write new plugins using the Python programming language.
3392
takes_options = ['verbose']
3042
3394
@display_command
3395
def run(self, verbose=False):
3044
3396
import bzrlib.plugin
3045
3397
from inspect import getdoc
3046
for name, plugin in bzrlib.plugin.all_plugins().items():
3047
if getattr(plugin, '__path__', None) is not None:
3048
print plugin.__path__[0]
3049
elif getattr(plugin, '__file__', None) is not None:
3050
print plugin.__file__
3399
for name, plugin in bzrlib.plugin.plugins().items():
3400
version = plugin.__version__
3401
if version == 'unknown':
3403
name_ver = '%s %s' % (name, version)
3404
d = getdoc(plugin.module)
3056
print '\t', d.split('\n')[0]
3406
doc = d.split('\n')[0]
3408
doc = '(no description)'
3409
result.append((name_ver, doc, plugin.path()))
3410
for name_ver, doc, path in sorted(result):
3059
3418
class cmd_testament(Command):
3060
3419
"""Show testament (signing-form) of a revision."""
3061
takes_options = ['revision',
3062
Option('long', help='Produce long-format testament'),
3063
Option('strict', help='Produce a strict-format'
3422
Option('long', help='Produce long-format testament.'),
3424
help='Produce a strict-format testament.')]
3065
3425
takes_args = ['branch?']
3066
3426
@display_command
3067
3427
def run(self, branch=u'.', revision=None, long=False, strict=False):
3559
4000
self.outf.writelines(directive.to_lines())
3561
4002
message = directive.to_email(mail_to, branch, sign)
3563
server = branch.get_config().get_user_option('smtp_server')
3565
server = 'localhost'
3567
s.sendmail(message['From'], message['To'], message.as_string())
4003
s = SMTPConnection(branch.get_config())
4004
s.send_email(message)
4007
class cmd_send(Command):
4008
"""Mail or create a merge-directive for submiting changes.
4010
A merge directive provides many things needed for requesting merges:
4012
* A machine-readable description of the merge to perform
4014
* An optional patch that is a preview of the changes requested
4016
* An optional bundle of revision data, so that the changes can be applied
4017
directly from the merge directive, without retrieving data from a
4020
If --no-bundle is specified, then public_branch is needed (and must be
4021
up-to-date), so that the receiver can perform the merge using the
4022
public_branch. The public_branch is always included if known, so that
4023
people can check it later.
4025
The submit branch defaults to the parent, but can be overridden. Both
4026
submit branch and public branch will be remembered if supplied.
4028
If a public_branch is known for the submit_branch, that public submit
4029
branch is used in the merge instructions. This means that a local mirror
4030
can be used as your actual submit branch, once you have set public_branch
4033
Mail is sent using your preferred mail program. This should be transparent
4034
on Windows (it uses MAPI). On Linux, it requires the xdg-email utility.
4035
If the preferred client can't be found (or used), your editor will be used.
4037
To use a specific mail program, set the mail_client configuration option.
4038
(For Thunderbird 1.5, this works around some bugs.) Supported values for
4039
specific clients are "evolution", "kmail", "mutt", and "thunderbird";
4040
generic options are "default", "editor", "mapi", and "xdg-email".
4042
If mail is being sent, a to address is required. This can be supplied
4043
either on the commandline, by setting the submit_to configuration
4044
option in the branch itself or the child_submit_to configuration option
4045
in the submit branch.
4047
Two formats are currently supported: "4" uses revision bundle format 4 and
4048
merge directive format 2. It is significantly faster and smaller than
4049
older formats. It is compatible with Bazaar 0.19 and later. It is the
4050
default. "0.9" uses revision bundle format 0.9 and merge directive
4051
format 1. It is compatible with Bazaar 0.12 - 0.18.
4054
encoding_type = 'exact'
4056
_see_also = ['merge']
4058
takes_args = ['submit_branch?', 'public_branch?']
4062
help='Do not include a bundle in the merge directive.'),
4063
Option('no-patch', help='Do not include a preview patch in the merge'
4066
help='Remember submit and public branch.'),
4068
help='Branch to generate the submission from, '
4069
'rather than the one containing the working directory.',
4072
Option('output', short_name='o', help='Write directive to this file.',
4074
Option('mail-to', help='Mail the request to this address.',
4078
RegistryOption.from_kwargs('format',
4079
'Use the specified output format.',
4080
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4081
'0.9': 'Bundle format 0.9, Merge Directive 1',})
4084
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4085
no_patch=False, revision=None, remember=False, output=None,
4086
format='4', mail_to=None, message=None, **kwargs):
4087
return self._run(submit_branch, revision, public_branch, remember,
4088
format, no_bundle, no_patch, output,
4089
kwargs.get('from', '.'), mail_to, message)
4091
def _run(self, submit_branch, revision, public_branch, remember, format,
4092
no_bundle, no_patch, output, from_, mail_to, message):
4093
from bzrlib.revision import NULL_REVISION
4094
branch = Branch.open_containing(from_)[0]
4096
outfile = StringIO()
4100
outfile = open(output, 'wb')
4101
# we may need to write data into branch's repository to calculate
4106
config = branch.get_config()
4108
mail_to = config.get_user_option('submit_to')
4109
mail_client = config.get_mail_client()
4110
if remember and submit_branch is None:
4111
raise errors.BzrCommandError(
4112
'--remember requires a branch to be specified.')
4113
stored_submit_branch = branch.get_submit_branch()
4114
remembered_submit_branch = False
4115
if submit_branch is None:
4116
submit_branch = stored_submit_branch
4117
remembered_submit_branch = True
4119
if stored_submit_branch is None or remember:
4120
branch.set_submit_branch(submit_branch)
4121
if submit_branch is None:
4122
submit_branch = branch.get_parent()
4123
remembered_submit_branch = True
4124
if submit_branch is None:
4125
raise errors.BzrCommandError('No submit branch known or'
4127
if remembered_submit_branch:
4128
note('Using saved location: %s', submit_branch)
4131
submit_config = Branch.open(submit_branch).get_config()
4132
mail_to = submit_config.get_user_option("child_submit_to")
4134
stored_public_branch = branch.get_public_branch()
4135
if public_branch is None:
4136
public_branch = stored_public_branch
4137
elif stored_public_branch is None or remember:
4138
branch.set_public_branch(public_branch)
4139
if no_bundle and public_branch is None:
4140
raise errors.BzrCommandError('No public branch specified or'
4142
base_revision_id = None
4144
if revision is not None:
4145
if len(revision) > 2:
4146
raise errors.BzrCommandError('bzr send takes '
4147
'at most two one revision identifiers')
4148
revision_id = revision[-1].in_history(branch).rev_id
4149
if len(revision) == 2:
4150
base_revision_id = revision[0].in_history(branch).rev_id
4151
if revision_id is None:
4152
revision_id = branch.last_revision()
4153
if revision_id == NULL_REVISION:
4154
raise errors.BzrCommandError('No revisions to submit.')
4156
directive = merge_directive.MergeDirective2.from_objects(
4157
branch.repository, revision_id, time.time(),
4158
osutils.local_time_offset(), submit_branch,
4159
public_branch=public_branch, include_patch=not no_patch,
4160
include_bundle=not no_bundle, message=message,
4161
base_revision_id=base_revision_id)
4162
elif format == '0.9':
4165
patch_type = 'bundle'
4167
raise errors.BzrCommandError('Format 0.9 does not'
4168
' permit bundle with no patch')
4174
directive = merge_directive.MergeDirective.from_objects(
4175
branch.repository, revision_id, time.time(),
4176
osutils.local_time_offset(), submit_branch,
4177
public_branch=public_branch, patch_type=patch_type,
4180
outfile.writelines(directive.to_lines())
4182
subject = '[MERGE] '
4183
if message is not None:
4186
revision = branch.repository.get_revision(revision_id)
4187
subject += revision.get_summary()
4188
basename = directive.get_disk_name(branch)
4189
mail_client.compose_merge_request(mail_to, subject,
4190
outfile.getvalue(), basename)
4197
class cmd_bundle_revisions(cmd_send):
4199
"""Create a merge-directive for submiting changes.
4201
A merge directive provides many things needed for requesting merges:
4203
* A machine-readable description of the merge to perform
4205
* An optional patch that is a preview of the changes requested
4207
* An optional bundle of revision data, so that the changes can be applied
4208
directly from the merge directive, without retrieving data from a
4211
If --no-bundle is specified, then public_branch is needed (and must be
4212
up-to-date), so that the receiver can perform the merge using the
4213
public_branch. The public_branch is always included if known, so that
4214
people can check it later.
4216
The submit branch defaults to the parent, but can be overridden. Both
4217
submit branch and public branch will be remembered if supplied.
4219
If a public_branch is known for the submit_branch, that public submit
4220
branch is used in the merge instructions. This means that a local mirror
4221
can be used as your actual submit branch, once you have set public_branch
4224
Two formats are currently supported: "4" uses revision bundle format 4 and
4225
merge directive format 2. It is significantly faster and smaller than
4226
older formats. It is compatible with Bazaar 0.19 and later. It is the
4227
default. "0.9" uses revision bundle format 0.9 and merge directive
4228
format 1. It is compatible with Bazaar 0.12 - 0.18.
4233
help='Do not include a bundle in the merge directive.'),
4234
Option('no-patch', help='Do not include a preview patch in the merge'
4237
help='Remember submit and public branch.'),
4239
help='Branch to generate the submission from, '
4240
'rather than the one containing the working directory.',
4243
Option('output', short_name='o', help='Write directive to this file.',
4246
RegistryOption.from_kwargs('format',
4247
'Use the specified output format.',
4248
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4249
'0.9': 'Bundle format 0.9, Merge Directive 1',})
4251
aliases = ['bundle']
4253
_see_also = ['send', 'merge']
4257
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4258
no_patch=False, revision=None, remember=False, output=None,
4259
format='4', **kwargs):
4262
return self._run(submit_branch, revision, public_branch, remember,
4263
format, no_bundle, no_patch, output,
4264
kwargs.get('from', '.'), None, None)
3570
4267
class cmd_tag(Command):
3571
"""Create a tag naming a revision.
4268
"""Create, remove or modify a tag naming a revision.
3573
4270
Tags give human-meaningful names to revisions. Commands that take a -r
3574
4271
(--revision) option can be given -rtag:X, where X is any previously
3630
4327
class cmd_tags(Command):
3633
This tag shows a table of tag names and the revisions they reference.
4330
This command shows a table of tag names and the revisions they reference.
3636
4333
_see_also = ['tag']
3637
4334
takes_options = [
3638
4335
Option('directory',
3639
help='Branch whose tags should be displayed',
4336
help='Branch whose tags should be displayed.',
3640
4337
short_name='d',
4340
RegistryOption.from_kwargs('sort',
4341
'Sort tags by different criteria.', title='Sorting',
4342
alpha='Sort tags lexicographically (default).',
4343
time='Sort tags chronologically.',
3645
4348
@display_command
3649
4354
branch, relpath = Branch.open_containing(directory)
3650
for tag_name, target in sorted(branch.tags.get_tag_dict().items()):
3651
self.outf.write('%-20s %s\n' % (tag_name, target))
3654
# command-line interpretation helper for merge-related commands
3655
def _merge_helper(other_revision, base_revision,
3656
check_clean=True, ignore_zero=False,
3657
this_dir=None, backup_files=False,
3659
file_list=None, show_base=False, reprocess=False,
3662
change_reporter=None,
3664
"""Merge changes into a tree.
3667
list(path, revno) Base for three-way merge.
3668
If [None, None] then a base will be automatically determined.
3670
list(path, revno) Other revision for three-way merge.
3672
Directory to merge changes into; '.' by default.
3674
If true, this_dir must have no uncommitted changes before the
3676
ignore_zero - If true, suppress the "zero conflicts" message when
3677
there are no conflicts; should be set when doing something we expect
3678
to complete perfectly.
3679
file_list - If supplied, merge only changes to selected files.
3681
All available ancestors of other_revision and base_revision are
3682
automatically pulled into the branch.
3684
The revno may be -1 to indicate the last revision on the branch, which is
3687
This function is intended for use from the command line; programmatic
3688
clients might prefer to call merge.merge_inner(), which has less magic
3691
# Loading it late, so that we don't always have to import bzrlib.merge
3692
if merge_type is None:
3693
merge_type = _mod_merge.Merge3Merger
3694
if this_dir is None:
3696
this_tree = WorkingTree.open_containing(this_dir)[0]
3697
if show_base and not merge_type is _mod_merge.Merge3Merger:
3698
raise errors.BzrCommandError("Show-base is not supported for this merge"
3699
" type. %s" % merge_type)
3700
if reprocess and not merge_type.supports_reprocess:
3701
raise errors.BzrCommandError("Conflict reduction is not supported for merge"
3702
" type %s." % merge_type)
3703
if reprocess and show_base:
3704
raise errors.BzrCommandError("Cannot do conflict reduction and show base.")
3705
# TODO: jam 20070226 We should really lock these trees earlier. However, we
3706
# only want to take out a lock_tree_write() if we don't have to pull
3707
# any ancestry. But merge might fetch ancestry in the middle, in
3708
# which case we would need a lock_write().
3709
# Because we cannot upgrade locks, for now we live with the fact that
3710
# the tree will be locked multiple times during a merge. (Maybe
3711
# read-only some of the time, but it means things will get read
3714
merger = _mod_merge.Merger(this_tree.branch, this_tree=this_tree,
3715
pb=pb, change_reporter=change_reporter)
3716
merger.pp = ProgressPhase("Merge phase", 5, pb)
3717
merger.pp.next_phase()
3718
merger.check_basis(check_clean)
3719
if other_rev_id is not None:
3720
merger.set_other_revision(other_rev_id, this_tree.branch)
4355
tags = branch.tags.get_tag_dict().items()
4358
elif sort == 'time':
4360
for tag, revid in tags:
4362
revobj = branch.repository.get_revision(revid)
4363
except errors.NoSuchRevision:
4364
timestamp = sys.maxint # place them at the end
4366
timestamp = revobj.timestamp
4367
timestamps[revid] = timestamp
4368
tags.sort(key=lambda x: timestamps[x[1]])
4370
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
4371
revno_map = branch.get_revision_id_to_revno_map()
4372
tags = [ (tag, '.'.join(map(str, revno_map.get(revid, ('?',)))))
4373
for tag, revid in tags ]
4374
for tag, revspec in tags:
4375
self.outf.write('%-20s %s\n' % (tag, revspec))
4378
class cmd_reconfigure(Command):
4379
"""Reconfigure the type of a bzr directory.
4381
A target configuration must be specified.
4383
For checkouts, the bind-to location will be auto-detected if not specified.
4384
The order of preference is
4385
1. For a lightweight checkout, the current bound location.
4386
2. For branches that used to be checkouts, the previously-bound location.
4387
3. The push location.
4388
4. The parent location.
4389
If none of these is available, --bind-to must be specified.
4392
takes_args = ['location?']
4393
takes_options = [RegistryOption.from_kwargs('target_type',
4394
title='Target type',
4395
help='The type to reconfigure the directory to.',
4396
value_switches=True, enum_switch=False,
4397
branch='Reconfigure to a branch.',
4398
tree='Reconfigure to a tree.',
4399
checkout='Reconfigure to a checkout.',
4400
lightweight_checkout='Reconfigure to a lightweight'
4402
Option('bind-to', help='Branch to bind checkout to.',
4405
help='Perform reconfiguration even if local changes'
4409
def run(self, location=None, target_type=None, bind_to=None, force=False):
4410
directory = bzrdir.BzrDir.open(location)
4411
if target_type is None:
4412
raise errors.BzrCommandError('No target configuration specified')
4413
elif target_type == 'branch':
4414
reconfiguration = reconfigure.Reconfigure.to_branch(directory)
4415
elif target_type == 'tree':
4416
reconfiguration = reconfigure.Reconfigure.to_tree(directory)
4417
elif target_type == 'checkout':
4418
reconfiguration = reconfigure.Reconfigure.to_checkout(directory,
4420
elif target_type == 'lightweight-checkout':
4421
reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
4423
reconfiguration.apply(force)
4426
class cmd_switch(Command):
4427
"""Set the branch of a checkout and update.
4429
For lightweight checkouts, this changes the branch being referenced.
4430
For heavyweight checkouts, this checks that there are no local commits
4431
versus the current bound branch, then it makes the local branch a mirror
4432
of the new location and binds to it.
4434
In both cases, the working tree is updated and uncommitted changes
4435
are merged. The user can commit or revert these as they desire.
4437
Pending merges need to be committed or reverted before using switch.
4440
takes_args = ['to_location']
4441
takes_options = [Option('force',
4442
help='Switch even if local commits will be lost.')
4445
def run(self, to_location, force=False):
4446
from bzrlib import switch
4447
to_branch = Branch.open(to_location)
4449
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
4450
switch.switch(control_dir, to_branch, force)
4451
note('Switched to branch: %s',
4452
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
4455
class cmd_hooks(Command):
4456
"""Show a branch's currently registered hooks.
4460
takes_args = ['path?']
4462
def run(self, path=None):
4465
branch_hooks = Branch.open(path).hooks
4466
for hook_type in branch_hooks:
4467
hooks = branch_hooks[hook_type]
4468
self.outf.write("%s:\n" % (hook_type,))
4471
self.outf.write(" %s\n" %
4472
(branch_hooks.get_hook_name(hook),))
4474
self.outf.write(" <no hooks installed>\n")
4477
def _create_prefix(cur_transport):
4478
needed = [cur_transport]
4479
# Recurse upwards until we can create a directory successfully
4481
new_transport = cur_transport.clone('..')
4482
if new_transport.base == cur_transport.base:
4483
raise errors.BzrCommandError(
4484
"Failed to create path prefix for %s."
4485
% cur_transport.base)
4487
new_transport.mkdir('.')
4488
except errors.NoSuchFile:
4489
needed.append(new_transport)
4490
cur_transport = new_transport
3722
merger.set_other(other_revision)
3723
merger.pp.next_phase()
3724
merger.set_base(base_revision)
3725
if merger.base_rev_id == merger.other_rev_id:
3726
note('Nothing to do.')
3728
if file_list is None:
3729
if pull and merger.base_rev_id == merger.this_rev_id:
3730
# FIXME: deduplicate with pull
3731
result = merger.this_tree.pull(merger.this_branch,
3732
False, merger.other_rev_id)
3733
if result.old_revid == result.new_revid:
3734
note('No revisions to pull.')
3736
note('Now on revision %d.' % result.new_revno)
3738
merger.backup_files = backup_files
3739
merger.merge_type = merge_type
3740
merger.set_interesting_files(file_list)
3741
merger.show_base = show_base
3742
merger.reprocess = reprocess
3743
conflicts = merger.do_merge()
3744
if file_list is None:
3745
merger.set_pending()
3752
merge = _merge_helper
4493
# Now we only need to create child directories
4495
cur_transport = needed.pop()
4496
cur_transport.ensure_base()
4499
def _get_mergeable_helper(location):
4500
"""Get a merge directive or bundle if 'location' points to one.
4502
Try try to identify a bundle and returns its mergeable form. If it's not,
4503
we return the tried transport anyway so that it can reused to access the
4506
:param location: can point to a bundle or a branch.
4508
:return: mergeable, transport
4511
url = urlutils.normalize_url(location)
4512
url, filename = urlutils.split(url, exclude_trailing_slash=False)
4513
location_transport = transport.get_transport(url)
4516
# There may be redirections but we ignore the intermediate
4517
# and final transports used
4518
read = bundle.read_mergeable_from_transport
4519
mergeable, t = read(location_transport, filename)
4520
except errors.NotABundle:
4521
# Continue on considering this url a Branch but adjust the
4522
# location_transport
4523
location_transport = location_transport.clone(filename)
4524
return mergeable, location_transport
3755
4527
# these get imported and then picked up by the scan for cmd_*