17
17
"""builtin bzr commands"""
22
from shutil import rmtree
27
from bzrlib.branch import Branch, BranchReferenceFormat
28
from bzrlib import (bundle, branch, bzrdir, errors, osutils, ui, config,
30
from bzrlib.bundle import read_bundle_from_url
31
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
32
from bzrlib.conflicts import ConflictList
27
from bzrlib.branch import Branch
28
import bzrlib.bzrdir as bzrdir
33
29
from bzrlib.commands import Command, display_command
30
from bzrlib.revision import common_ancestor
31
import bzrlib.errors as errors
34
32
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError,
35
33
NotBranchError, DivergedBranches, NotConflicted,
36
NoSuchFile, NoWorkingTree, FileInWrongBranch,
37
NotVersionedError, NotABundle)
34
NoSuchFile, NoWorkingTree, FileInWrongBranch)
35
from bzrlib.log import show_one_log
38
36
from bzrlib.merge import Merge3Merger
39
37
from bzrlib.option import Option
40
from bzrlib.progress import DummyProgress, ProgressPhase
41
from bzrlib.revision import common_ancestor
38
from bzrlib.progress import DummyProgress
42
39
from bzrlib.revisionspec import RevisionSpec
43
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
41
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
44
42
from bzrlib.transport.local import LocalTransport
45
import bzrlib.urlutils as urlutils
46
44
from bzrlib.workingtree import WorkingTree
146
118
# TODO: --no-recurse, --recurse options
148
120
takes_args = ['file*']
149
takes_options = ['show-ids', 'revision']
121
takes_options = ['all', 'show-ids', 'revision']
150
122
aliases = ['st', 'stat']
152
encoding_type = 'replace'
155
def run(self, show_ids=False, file_list=None, revision=None):
125
def run(self, all=False, show_ids=False, file_list=None, revision=None):
126
tree, file_list = tree_files(file_list)
156
128
from bzrlib.status import show_tree_status
158
tree, file_list = tree_files(file_list)
160
show_tree_status(tree, show_ids=show_ids,
161
specific_files=file_list, revision=revision,
129
show_tree_status(tree, show_unchanged=all, show_ids=show_ids,
130
specific_files=file_list, revision=revision)
165
133
class cmd_cat_revision(Command):
267
226
takes_args = ['file*']
268
227
takes_options = ['no-recurse', 'dry-run', 'verbose']
269
encoding_type = 'replace'
271
229
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
272
230
import bzrlib.add
274
action = bzrlib.add.AddAction(to_file=self.outf,
275
should_print=(not is_quiet()))
234
# This is pointless, but I'd rather not raise an error
235
action = bzrlib.add.add_action_null
237
action = bzrlib.add.add_action_print
239
action = bzrlib.add.add_action_add
241
action = bzrlib.add.add_action_add_and_print
277
243
added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
278
action=action, save=not dry_run)
279
245
if len(ignored) > 0:
281
for glob in sorted(ignored.keys()):
246
for glob in sorted(ignored.keys()):
247
match_len = len(ignored[glob])
282
249
for path in ignored[glob]:
283
self.outf.write("ignored %s matching \"%s\"\n"
287
for glob, paths in ignored.items():
288
match_len += len(paths)
289
self.outf.write("ignored %d file(s).\n" % match_len)
290
self.outf.write("If you wish to add some of these files,"
291
" please add them by name.\n")
250
print "ignored %s matching \"%s\"" % (path, glob)
252
print "ignored %d file(s) matching \"%s\"" % (match_len,
254
print "If you wish to add some of these files, please add them"\
294
258
class cmd_mkdir(Command):
350
307
if kind and kind != entry.kind:
353
self.outf.write('%-50s %s\n' % (path, entry.file_id))
310
print '%-50s %s' % (path, entry.file_id)
355
self.outf.write(path)
356
self.outf.write('\n')
315
class cmd_move(Command):
316
"""Move files to a different directory.
321
The destination must be a versioned directory in the same branch.
323
takes_args = ['source$', 'dest']
324
def run(self, source_list, dest):
325
tree, source_list = tree_files(source_list)
326
# TODO: glob expansion on windows?
327
tree.move(source_list, tree.relpath(dest))
330
class cmd_rename(Command):
331
"""Change the name of an entry.
334
bzr rename frob.c frobber.c
335
bzr rename src/frob.c lib/frob.c
337
It is an error if the destination name exists.
339
See also the 'move' command, which moves files into a different
340
directory without changing their name.
342
# TODO: Some way to rename multiple files without invoking
343
# bzr for each one?"""
344
takes_args = ['from_name', 'to_name']
346
def run(self, from_name, to_name):
347
tree, (from_name, to_name) = tree_files((from_name, to_name))
348
tree.rename_one(from_name, to_name)
359
351
class cmd_mv(Command):
385
370
if os.path.isdir(names_list[-1]):
386
371
# move into existing directory
387
372
for pair in tree.move(rel_names[:-1], rel_names[-1]):
388
self.outf.write("%s => %s\n" % pair)
373
print "%s => %s" % pair
390
375
if len(names_list) != 2:
391
376
raise BzrCommandError('to mv multiple files the destination '
392
377
'must be a versioned directory')
393
378
tree.rename_one(rel_names[0], rel_names[1])
394
self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
379
print "%s => %s" % (rel_names[0], rel_names[1])
397
382
class cmd_pull(Command):
398
"""Turn this branch into a mirror of another branch.
383
"""Pull any changes from another branch into the current one.
385
If there is no default location set, the first pull will set it. After
386
that, you can omit the location to use the default. To change the
387
default, use --remember.
400
389
This command only works on branches that have not diverged. Branches are
401
considered diverged if the destination branch's most recent commit is one
402
that has not been merged (directly or indirectly) into the parent.
390
considered diverged if both branches have had commits without first
391
pulling from the other.
404
If branches have diverged, you can use 'bzr merge' to integrate the changes
393
If branches have diverged, you can use 'bzr merge' to pull the text changes
405
394
from one into the other. Once one branch has merged, the other should
406
395
be able to pull it again.
408
397
If you want to forget your local changes and just update your branch to
409
match the remote one, use pull --overwrite.
411
If there is no default location set, the first pull will set it. After
412
that, you can omit the location to use the default. To change the
413
default, use --remember. The value will only be saved if the remote
414
location can be accessed.
398
match the remote one, use --overwrite.
417
400
takes_options = ['remember', 'overwrite', 'revision', 'verbose']
418
401
takes_args = ['location?']
419
encoding_type = 'replace'
421
403
def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
422
# FIXME: too much stuff is in the command class
424
tree_to = WorkingTree.open_containing(u'.')[0]
425
branch_to = tree_to.branch
426
except NoWorkingTree:
428
branch_to = Branch.open_containing(u'.')[0]
431
if location is not None:
433
reader = bundle.read_bundle_from_url(location)
435
pass # Continue on considering this url a Branch
437
stored_loc = branch_to.get_parent()
404
# FIXME: too much stuff is in the command class
405
tree_to = WorkingTree.open_containing(u'.')[0]
406
stored_loc = tree_to.branch.get_parent()
438
407
if location is None:
439
408
if stored_loc is None:
440
409
raise BzrCommandError("No pull location known or specified.")
442
display_url = urlutils.unescape_for_display(stored_loc,
444
self.outf.write("Using saved location: %s\n" % display_url)
411
print "Using saved location: %s" % stored_loc
445
412
location = stored_loc
448
if reader is not None:
449
install_bundle(branch_to.repository, reader)
450
branch_from = branch_to
452
branch_from = Branch.open(location)
454
if branch_to.get_parent() is None or remember:
455
branch_to.set_parent(branch_from.base)
414
br_from = Branch.open(location)
415
br_to = tree_to.branch
458
417
if revision is None:
459
if reader is not None:
460
rev_id = reader.target
461
419
elif len(revision) == 1:
462
rev_id = revision[0].in_history(branch_from).rev_id
420
rev_id = revision[0].in_history(br_from).rev_id
464
422
raise BzrCommandError('bzr pull --revision takes one value.')
466
old_rh = branch_to.revision_history()
467
if tree_to is not None:
468
count = tree_to.pull(branch_from, overwrite, rev_id)
470
count = branch_to.pull(branch_from, overwrite, rev_id)
424
old_rh = br_to.revision_history()
425
count = tree_to.pull(br_from, overwrite, rev_id)
427
if br_to.get_parent() is None or remember:
428
br_to.set_parent(location)
471
429
note('%d revision(s) pulled.' % (count,))
474
new_rh = branch_to.revision_history()
432
new_rh = tree_to.branch.revision_history()
475
433
if old_rh != new_rh:
476
434
# Something changed
477
435
from bzrlib.log import show_changed_revisions
478
show_changed_revisions(branch_to, old_rh, new_rh,
436
show_changed_revisions(tree_to.branch, old_rh, new_rh)
482
439
class cmd_push(Command):
483
"""Update a mirror of this branch.
485
The target branch will not have its working tree populated because this
486
is both expensive, and is not supported on remote file systems.
488
Some smart servers or protocols *may* put the working tree in place in
440
"""Push this branch into another branch.
442
The remote branch will not have its working tree populated because this
443
is both expensive, and may not be supported on the remote file system.
445
Some smart servers or protocols *may* put the working tree in place.
447
If there is no default push location set, the first push will set it.
448
After that, you can omit the location to use the default. To change the
449
default, use --remember.
491
451
This command only works on branches that have not diverged. Branches are
492
considered diverged if the destination branch's most recent commit is one
493
that has not been merged (directly or indirectly) by the source branch.
452
considered diverged if the branch being pushed to is not an older version
495
455
If branches have diverged, you can use 'bzr push --overwrite' to replace
496
the other branch completely, discarding its unmerged changes.
456
the other branch completely.
498
458
If you want to ensure you have the different changes in the other branch,
499
do a merge (see bzr help merge) from the other branch, and commit that.
500
After that you will be able to do a push without '--overwrite'.
502
If there is no default push location set, the first push will set it.
503
After that, you can omit the location to use the default. To change the
504
default, use --remember. The value will only be saved if the remote
505
location can be accessed.
459
do a merge (see bzr help merge) from the other branch, and commit that
460
before doing a 'push --overwrite'.
508
takes_options = ['remember', 'overwrite', 'verbose',
462
takes_options = ['remember', 'overwrite',
509
463
Option('create-prefix',
510
464
help='Create the path leading up to the branch '
511
465
'if it does not already exist')]
512
466
takes_args = ['location?']
513
encoding_type = 'replace'
515
468
def run(self, location=None, remember=False, overwrite=False,
516
469
create_prefix=False, verbose=False):
519
472
from bzrlib.transport import get_transport
521
br_from = Branch.open_containing('.')[0]
522
stored_loc = br_from.get_push_location()
474
tree_from = WorkingTree.open_containing(u'.')[0]
475
br_from = tree_from.branch
476
stored_loc = tree_from.branch.get_push_location()
523
477
if location is None:
524
478
if stored_loc is None:
525
479
raise BzrCommandError("No push location known or specified.")
527
display_url = urlutils.unescape_for_display(stored_loc,
529
self.outf.write("Using saved location: %s\n" % display_url)
481
print "Using saved location: %s" % stored_loc
530
482
location = stored_loc
532
transport = get_transport(location)
533
location_url = transport.base
537
dir_to = bzrdir.BzrDir.open(location_url)
538
br_to = dir_to.open_branch()
484
br_to = Branch.open(location)
539
485
except NotBranchError:
540
486
# create a branch.
541
transport = transport.clone('..')
487
transport = get_transport(location).clone('..')
542
488
if not create_prefix:
544
relurl = transport.relpath(location_url)
545
mutter('creating directory %s => %s', location_url, relurl)
546
transport.mkdir(relurl)
490
transport.mkdir(transport.relpath(location))
547
491
except NoSuchFile:
548
492
raise BzrCommandError("Parent directory of %s "
549
493
"does not exist." % location)
551
495
current = transport.base
552
needed = [(transport, transport.relpath(location_url))]
496
needed = [(transport, transport.relpath(location))]
555
499
transport, relpath = needed[-1]
560
504
needed.append((new_transport,
561
505
new_transport.relpath(transport.base)))
562
506
if new_transport.base == transport.base:
563
raise BzrCommandError("Could not create "
507
raise BzrCommandError("Could not creeate "
565
dir_to = br_from.bzrdir.clone(location_url,
566
revision_id=br_from.last_revision())
567
br_to = dir_to.open_branch()
568
count = len(br_to.revision_history())
569
# We successfully created the target, remember it
570
if br_from.get_push_location() is None or remember:
571
br_from.set_push_location(br_to.base)
573
# We were able to connect to the remote location, so remember it
574
# we don't need to successfully push because of possible divergence.
575
if br_from.get_push_location() is None or remember:
576
br_from.set_push_location(br_to.base)
577
old_rh = br_to.revision_history()
509
br_to = bzrlib.bzrdir.BzrDir.create_branch_convenience(location)
510
old_rh = br_to.revision_history()
580
tree_to = dir_to.open_workingtree()
581
except errors.NotLocalUrl:
582
warning('This transport does not update the working '
583
'tree of: %s' % (br_to.base,))
584
count = br_to.pull(br_from, overwrite)
585
except NoWorkingTree:
586
count = br_to.pull(br_from, overwrite)
588
count = tree_to.pull(br_from, overwrite)
589
except DivergedBranches:
590
raise BzrCommandError("These branches have diverged."
591
" Try a merge then push with overwrite.")
513
tree_to = br_to.working_tree()
514
except NoWorkingTree:
515
# TODO: This should be updated for branches which don't have a
516
# working tree, as opposed to ones where we just couldn't
518
warning('Unable to update the working tree of: %s' % (br_to.base,))
519
count = br_to.pull(br_from, overwrite)
521
count = tree_to.pull(br_from, overwrite)
522
except DivergedBranches:
523
raise BzrCommandError("These branches have diverged."
524
" Try a merge then push with overwrite.")
525
if br_from.get_push_location() is None or remember:
526
br_from.set_push_location(location)
592
527
note('%d revision(s) pushed.' % (count,))
652
585
name = os.path.basename(to_location) + '\n'
654
to_transport = get_transport(to_location)
656
to_transport.mkdir('.')
657
except errors.FileExists:
658
raise BzrCommandError('Target directory "%s" already'
659
' exists.' % to_location)
660
except errors.NoSuchFile:
661
raise BzrCommandError('Parent of "%s" does not exist.' %
664
# preserve whatever source format we have.
665
dir = br_from.bzrdir.sprout(to_transport.base,
666
revision_id, basis_dir)
587
os.mkdir(to_location)
589
if e.errno == errno.EEXIST:
590
raise BzrCommandError('Target directory "%s" already'
591
' exists.' % to_location)
592
if e.errno == errno.ENOENT:
593
raise BzrCommandError('Parent of "%s" does not exist.' %
598
dir = br_from.bzrdir.sprout(to_location, revision_id, basis_dir)
667
599
branch = dir.open_branch()
668
except errors.NoSuchRevision:
669
to_transport.delete_tree('.')
600
except bzrlib.errors.NoSuchRevision:
670
602
msg = "The branch %s has no revision %s." % (from_location, revision[0])
671
603
raise BzrCommandError(msg)
672
except errors.UnlistableBranch:
673
osutils.rmtree(to_location)
674
msg = "The branch %s cannot be used as a --basis" % (basis,)
604
except bzrlib.errors.UnlistableBranch:
606
msg = "The branch %s cannot be used as a --basis"
675
607
raise BzrCommandError(msg)
677
609
branch.control_files.put_utf8('branch-name', name)
678
611
note('Branched %d revision(s).' % branch.revno())
699
627
--basis is to speed up checking out from remote branches. When specified, it
700
628
uses the inventory and file contents from the basis branch in preference to the
701
branch being checked out.
629
branch being checked out. [Not implemented yet.]
703
takes_args = ['branch_location?', 'to_location?']
704
takes_options = ['revision', # , 'basis']
705
Option('lightweight',
706
help="perform a lightweight checkout. Lightweight "
707
"checkouts depend on access to the branch for "
708
"every operation. Normal checkouts can perform "
709
"common operations like diff and status without "
710
"such access, and also support local commits."
631
takes_args = ['branch_location', 'to_location?']
632
takes_options = ['revision'] # , 'basis']
715
def run(self, branch_location=None, to_location=None, revision=None, basis=None,
634
def run(self, branch_location, to_location=None, revision=None, basis=None):
717
635
if revision is None:
718
636
revision = [None]
719
637
elif len(revision) > 1:
720
638
raise BzrCommandError(
721
639
'bzr checkout --revision takes exactly 1 revision value')
722
if branch_location is None:
723
branch_location = osutils.getcwd()
724
to_location = branch_location
725
640
source = Branch.open(branch_location)
726
641
if len(revision) == 1 and revision[0] is not None:
727
642
revision_id = revision[0].in_history(source)[1]
849
723
This makes bzr stop tracking changes to a versioned file. It does
850
724
not delete the working copy.
852
You can specify one or more files, and/or --new. If you specify --new,
853
only 'added' files will be removed. If you specify both, then new files
854
in the specified directories will be removed. If the directories are
855
also new, they will also be removed.
857
takes_args = ['file*']
858
takes_options = ['verbose', Option('new', help='remove newly-added files')]
726
takes_args = ['file+']
727
takes_options = ['verbose']
860
encoding_type = 'replace'
862
def run(self, file_list, verbose=False, new=False):
730
def run(self, file_list, verbose=False):
863
731
tree, file_list = tree_files(file_list)
865
if file_list is None:
866
raise BzrCommandError('Specify one or more files to remove, or'
869
from bzrlib.delta import compare_trees
870
added = [compare_trees(tree.basis_tree(), tree,
871
specific_files=file_list).added]
872
file_list = sorted([f[0] for f in added[0]], reverse=True)
873
if len(file_list) == 0:
874
raise BzrCommandError('No matching files.')
875
tree.remove(file_list, verbose=verbose, to_file=self.outf)
732
tree.remove(file_list, verbose=verbose)
878
735
class cmd_file_id(Command):
915
767
raise BzrError("%r is not a versioned file" % filename)
916
768
for fip in inv.get_idpath(fid):
917
self.outf.write(fip + '\n')
920
class cmd_reconcile(Command):
921
"""Reconcile bzr metadata in a branch.
923
This can correct data mismatches that may have been caused by
924
previous ghost operations or bzr upgrades. You should only
925
need to run this command if 'bzr check' or a bzr developer
926
advises you to run it.
928
If a second branch is provided, cross-branch reconciliation is
929
also attempted, which will check that data like the tree root
930
id which was not present in very early bzr versions is represented
931
correctly in both branches.
933
At the same time it is run it may recompress data resulting in
934
a potential saving in disk space or performance gain.
936
The branch *MUST* be on a listable system such as local disk or sftp.
938
takes_args = ['branch?']
940
def run(self, branch="."):
941
from bzrlib.reconcile import reconcile
942
dir = bzrdir.BzrDir.open(branch)
946
772
class cmd_revision_history(Command):
947
"""Display the list of revision ids on a branch."""
948
takes_args = ['location?']
773
"""Display list of revision ids on this branch."""
953
def run(self, location="."):
954
branch = Branch.open_containing(location)[0]
955
for revid in branch.revision_history():
956
self.outf.write(revid)
957
self.outf.write('\n')
777
branch = WorkingTree.open_containing(u'.')[0].branch
778
for patchid in branch.revision_history():
960
782
class cmd_ancestry(Command):
961
783
"""List all revisions merged into this branch."""
962
takes_args = ['location?']
967
def run(self, location="."):
969
wt = WorkingTree.open_containing(location)[0]
970
except errors.NoWorkingTree:
971
b = Branch.open(location)
972
last_revision = b.last_revision()
975
last_revision = wt.last_revision()
977
revision_ids = b.repository.get_ancestry(last_revision)
978
assert revision_ids[0] == None
980
for revision_id in revision_ids:
981
self.outf.write(revision_id + '\n')
787
tree = WorkingTree.open_containing(u'.')[0]
789
# FIXME. should be tree.last_revision
790
for revision_id in b.repository.get_ancestry(b.last_revision()):
984
794
class cmd_init(Command):
1024
817
# locations if the user supplies an extended path
1025
818
if not os.path.exists(location):
1026
819
os.mkdir(location)
1028
existing_bzrdir = bzrdir.BzrDir.open(location)
1029
except NotBranchError:
1030
# really a NotBzrDir error...
1031
bzrdir.BzrDir.create_branch_convenience(location, format=format)
1033
if existing_bzrdir.has_branch():
1034
if existing_bzrdir.has_workingtree():
1035
raise errors.AlreadyBranchError(location)
1037
raise errors.BranchExistsWithoutWorkingTree(location)
1039
existing_bzrdir.create_branch()
1040
existing_bzrdir.create_workingtree()
1043
class cmd_init_repository(Command):
1044
"""Create a shared repository to hold branches.
1046
New branches created under the repository directory will store their revisions
1047
in the repository, not in the branch directory, if the branch format supports
1053
bzr checkout --lightweight repo/trunk trunk-checkout
1057
takes_args = ["location"]
1058
takes_options = [Option('format',
1059
help='Specify a format for this repository.'
1060
' Current formats are: default, knit,'
1061
' metaweave and weave. Default is knit;'
1062
' metaweave and weave are deprecated',
1063
type=get_format_type),
1065
help='Allows branches in repository to have'
1067
aliases = ["init-repo"]
1068
def run(self, location, format=None, trees=False):
1069
from bzrlib.transport import get_transport
1071
format = get_format_type('default')
1072
transport = get_transport(location)
1073
if not transport.has('.'):
1075
newdir = format.initialize_on_transport(transport)
1076
repo = newdir.create_repository(shared=True)
1077
repo.set_make_working_trees(trees)
820
bzrdir.BzrDir.create_standalone_workingtree(location)
1080
823
class cmd_diff(Command):
1081
"""Show differences in the working tree or between revisions.
824
"""Show differences in working tree.
1083
826
If files are listed, only the changes in those files are listed.
1084
827
Otherwise, all changes for the tree are listed.
1086
"bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1087
produces patches suitable for "patch -p1".
1091
Shows the difference in the working tree versus the last commit
1093
Difference between the working tree and revision 1
1095
Difference between revision 2 and revision 1
1096
bzr diff --diff-prefix old/:new/
1097
Same as 'bzr diff' but prefix paths with old/ and new/
1098
bzr diff bzr.mine bzr.dev
1099
Show the differences between the two working trees
1101
Show just the differences for 'foo.c'
834
# TODO: Allow diff across branches.
1103
835
# TODO: Option to use external diff command; could be GNU diff, wdiff,
1104
836
# or a graphical diff.
1106
838
# TODO: Python difflib is not exactly the same as unidiff; should
1107
839
# either fix it up or prefer to use an external diff.
841
# TODO: If a directory is given, diff everything under that.
1109
843
# TODO: Selected-file diff is inefficient and doesn't show you
1110
844
# deleted files.
1112
846
# TODO: This probably handles non-Unix newlines poorly.
1114
848
takes_args = ['file*']
1115
takes_options = ['revision', 'diff-options', 'prefix']
849
takes_options = ['revision', 'diff-options']
1116
850
aliases = ['di', 'dif']
1117
encoding_type = 'exact'
1119
852
@display_command
1120
def run(self, revision=None, file_list=None, diff_options=None,
853
def run(self, revision=None, file_list=None, diff_options=None):
1122
854
from bzrlib.diff import diff_cmd_helper, show_diff_trees
1124
if (prefix is None) or (prefix == '0'):
1132
if not ':' in prefix:
1133
raise BzrError("--diff-prefix expects two values separated by a colon")
1134
old_label, new_label = prefix.split(":")
1137
856
tree1, file_list = internal_tree_files(file_list)
1148
867
# FIXME diff those two files. rbc 20051123
1149
868
raise BzrCommandError("Files are in different branches")
1150
869
file_list = None
1151
except NotBranchError:
1152
# Don't raise an error when bzr diff is called from
1153
# outside a working tree.
1154
tree1, tree2 = None, None
1155
870
if revision is not None:
1156
871
if tree2 is not None:
1157
872
raise BzrCommandError("Can't specify -r with two branches")
1158
873
if (len(revision) == 1) or (revision[1].spec is None):
1159
874
return diff_cmd_helper(tree1, file_list, diff_options,
1161
old_label=old_label, new_label=new_label)
1162
876
elif len(revision) == 2:
1163
877
return diff_cmd_helper(tree1, file_list, diff_options,
1164
revision[0], revision[1],
1165
old_label=old_label, new_label=new_label)
878
revision[0], revision[1])
1167
880
raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
1169
882
if tree2 is not None:
1170
883
return show_diff_trees(tree1, tree2, sys.stdout,
1171
884
specific_files=file_list,
1172
external_diff_options=diff_options,
1173
old_label=old_label, new_label=new_label)
885
external_diff_options=diff_options)
1175
return diff_cmd_helper(tree1, file_list, diff_options,
1176
old_label=old_label, new_label=new_label)
887
return diff_cmd_helper(tree1, file_list, diff_options)
1179
890
class cmd_deleted(Command):
1706
1389
raise BzrCommandError("please specify either --message or --file")
1709
1393
message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1711
1395
if message == "":
1712
raise BzrCommandError("empty commit message specified")
1715
reporter = ReportCommitToLog()
1717
reporter = NullCommitReporter()
1396
raise BzrCommandError("empty commit message specified")
1720
1399
tree.commit(message, specific_files=selected_list,
1721
allow_pointless=unchanged, strict=strict, local=local,
1400
allow_pointless=unchanged, strict=strict)
1723
1401
except PointlessCommit:
1724
1402
# FIXME: This should really happen before the file is read in;
1725
1403
# perhaps prepare the commit; get the message; then actually commit
1726
raise BzrCommandError("no changes to commit."
1727
" use --unchanged to commit anyhow")
1404
raise BzrCommandError("no changes to commit",
1405
["use --unchanged to commit anyhow"])
1728
1406
except ConflictsInTree:
1729
1407
raise BzrCommandError("Conflicts detected in working tree. "
1730
1408
'Use "bzr conflicts" to list, "bzr resolve FILE" to resolve.')
1731
1409
except StrictCommitFailed:
1732
1410
raise BzrCommandError("Commit refused because there are unknown "
1733
1411
"files in the working tree.")
1734
except errors.BoundBranchOutOfDate, e:
1735
raise BzrCommandError(str(e)
1736
+ ' Either unbind, update, or'
1737
' pass --local to commit.')
1412
note('Committed revision %d.' % (tree.branch.revno(),))
1740
1415
class cmd_check(Command):
1785
1473
takes_args = ['url?']
1786
1474
takes_options = [
1787
1475
Option('format',
1788
help='Upgrade to a specific format. Current formats'
1789
' are: default, knit, metaweave and weave.'
1790
' Default is knit; metaweave and weave are'
1476
help='Upgrade to a specific format rather than the'
1477
' current default format. Currently this '
1478
' option only accepts =metadir',
1792
1479
type=get_format_type),
1796
1483
def run(self, url='.', format=None):
1797
1484
from bzrlib.upgrade import upgrade
1799
format = get_format_type('default')
1800
1485
upgrade(url, format)
1803
1488
class cmd_whoami(Command):
1804
"""Show or set bzr user id.
1808
bzr whoami 'Frank Chu <fchu@example.com>'
1810
takes_options = [ Option('email',
1811
help='display email address only'),
1813
help='set identity for the current branch instead of '
1816
takes_args = ['name?']
1817
encoding_type = 'replace'
1489
"""Show bzr user id."""
1490
takes_options = ['email']
1819
1492
@display_command
1820
def run(self, email=False, branch=False, name=None):
1822
# use branch if we're inside one; otherwise global config
1824
c = Branch.open_containing('.')[0].get_config()
1825
except NotBranchError:
1826
c = config.GlobalConfig()
1828
self.outf.write(c.user_email() + '\n')
1830
self.outf.write(c.username() + '\n')
1833
# display a warning if an email address isn't included in the given name.
1493
def run(self, email=False):
1835
config.extract_email_address(name)
1837
warning('"%s" does not seem to contain an email address. '
1838
'This is allowed, but not recommended.', name)
1495
b = WorkingTree.open_containing(u'.')[0].branch
1496
config = bzrlib.config.BranchConfig(b)
1497
except NotBranchError:
1498
config = bzrlib.config.GlobalConfig()
1840
# use global config unless --branch given
1842
c = Branch.open_containing('.')[0].get_config()
1501
print config.user_email()
1844
c = config.GlobalConfig()
1845
c.set_user_option('email', name)
1503
print config.username()
1848
1506
class cmd_nick(Command):
1913
1568
help='Use a different transport by default '
1914
1569
'throughout the test suite.',
1915
1570
type=get_transport_type),
1916
Option('benchmark', help='run the bzr bencharks.'),
1917
Option('lsprof-timed',
1918
help='generate lsprof output for benchmarked'
1919
' sections of code.'),
1922
def run(self, testspecs_list=None, verbose=None, one=False,
1923
keep_output=False, transport=None, benchmark=None,
1573
def run(self, testspecs_list=None, verbose=False, one=False,
1574
keep_output=False, transport=None):
1925
1575
import bzrlib.ui
1926
1576
from bzrlib.tests import selftest
1927
import bzrlib.benchmarks as benchmarks
1928
1577
# we don't want progress meters from the tests to go to the
1929
1578
# real output; and we don't want log messages cluttering up
1930
1579
# the real logs.
1931
save_ui = ui.ui_factory
1932
print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
1933
print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
1935
info('running tests...')
1580
save_ui = bzrlib.ui.ui_factory
1581
bzrlib.trace.info('running tests...')
1937
ui.ui_factory = ui.SilentUIFactory()
1583
bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
1938
1584
if testspecs_list is not None:
1939
1585
pattern = '|'.join(testspecs_list)
1943
test_suite_factory = benchmarks.test_suite
1947
test_suite_factory = None
1950
1588
result = selftest(verbose=verbose,
1951
1589
pattern=pattern,
1952
1590
stop_on_failure=one,
1953
1591
keep_output=keep_output,
1954
transport=transport,
1955
test_suite_factory=test_suite_factory,
1956
lsprof_timed=lsprof_timed)
1592
transport=transport)
1958
info('tests passed')
1594
bzrlib.trace.info('tests passed')
1960
info('tests failed')
1596
bzrlib.trace.info('tests failed')
1961
1597
return int(not result)
1963
ui.ui_factory = save_ui
1599
bzrlib.ui.ui_factory = save_ui
1966
1602
def _get_bzr_branch():
1967
1603
"""If bzr is run from a branch, return Branch or None"""
1604
import bzrlib.errors
1605
from bzrlib.branch import Branch
1606
from bzrlib.osutils import abspath
1968
1607
from os.path import dirname
1971
branch = Branch.open(dirname(osutils.abspath(dirname(__file__))))
1610
branch = Branch.open(dirname(abspath(dirname(__file__))))
1973
except errors.BzrError:
1612
except bzrlib.errors.BzrError:
1977
1616
def show_version():
1979
1617
print "bzr (bazaar-ng) %s" % bzrlib.__version__
1980
1618
# is bzrlib itself in a branch?
1981
1619
branch = _get_bzr_branch()
2047
1673
base_rev_id = common_ancestor(last1, last2, source)
2049
1675
print 'merge base is revision %s' % base_rev_id
1679
if base_revno is None:
1680
raise bzrlib.errors.UnrelatedBranches()
1682
print ' r%-6d in %s' % (base_revno, branch)
1684
other_revno = branch2.revision_id_to_revno(base_revid)
1686
print ' r%-6d in %s' % (other_revno, other)
2052
1690
class cmd_merge(Command):
2053
1691
"""Perform a three-way merge.
2055
The branch is the branch you will merge from. By default, it will merge
2056
the latest revision. If you specify a revision, that revision will be
2057
merged. If you specify two revisions, the first will be used as a BASE,
2058
and the second one as OTHER. Revision numbers are always relative to the
1693
The branch is the branch you will merge from. By default, it will
1694
merge the latest revision. If you specify a revision, that
1695
revision will be merged. If you specify two revisions, the first
1696
will be used as a BASE, and the second one as OTHER. Revision
1697
numbers are always relative to the specified branch.
2061
By default, bzr will try to merge in all new work from the other
1699
By default bzr will try to merge in all new work from the other
2062
1700
branch, automatically determining an appropriate base. If this
2063
1701
fails, you may need to give an explicit base.
2065
Merge will do its best to combine the changes in two branches, but there
2066
are some kinds of problems only a human can fix. When it encounters those,
2067
it will mark a conflict. A conflict means that you need to fix something,
2068
before you should commit.
2070
Use bzr resolve when you have fixed a problem. See also bzr conflicts.
2072
If there is no default branch set, the first merge will set it. After
2073
that, you can omit the branch to use the default. To change the
2074
default, use --remember. The value will only be saved if the remote
2075
location can be accessed.
2079
1705
To merge the latest revision from bzr.dev
2088
1714
merge refuses to run if there are any uncommitted changes, unless
2089
1715
--force is given.
2091
The following merge types are available:
2093
1717
takes_args = ['branch?']
2094
takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
1718
takes_options = ['revision', 'force', 'merge-type', 'reprocess',
2095
1719
Option('show-base', help="Show base revision text in "
2099
from merge import merge_type_help
2100
from inspect import getdoc
2101
return getdoc(self) + '\n' + merge_type_help()
2103
1722
def run(self, branch=None, revision=None, force=False, merge_type=None,
2104
show_base=False, reprocess=False, remember=False):
1723
show_base=False, reprocess=False):
2105
1724
if merge_type is None:
2106
1725
merge_type = Merge3Merger
2108
tree = WorkingTree.open_containing(u'.')[0]
2110
if branch is not None:
2112
reader = bundle.read_bundle_from_url(branch)
2114
pass # Continue on considering this url a Branch
1727
branch = WorkingTree.open_containing(u'.')[0].branch.get_parent()
1729
raise BzrCommandError("No merge location known or specified.")
2116
conflicts = merge_bundle(reader, tree, not force, merge_type,
2117
reprocess, show_base)
2123
branch = self._get_remembered_parent(tree, branch, 'Merging from')
1731
print "Using saved location: %s" % branch
2125
1732
if revision is None or len(revision) < 1:
2126
1733
base = [None, None]
2127
1734
other = [branch, -1]
2128
other_branch, path = Branch.open_containing(branch)
2130
1736
if len(revision) == 1:
2131
1737
base = [None, None]
2132
other_branch, path = Branch.open_containing(branch)
1738
other_branch = Branch.open_containing(branch)[0]
2133
1739
revno = revision[0].in_history(other_branch).revno
2134
1740
other = [branch, revno]
2137
1743
if None in revision:
2138
1744
raise BzrCommandError(
2139
1745
"Merge doesn't permit that revision specifier.")
2140
other_branch, path = Branch.open_containing(branch)
2142
base = [branch, revision[0].in_history(other_branch).revno]
2143
other = [branch, revision[1].in_history(other_branch).revno]
2145
if tree.branch.get_parent() is None or remember:
2146
tree.branch.set_parent(other_branch.base)
2149
interesting_files = [path]
2151
interesting_files = None
2152
pb = ui.ui_factory.nested_progress_bar()
1746
b = Branch.open_containing(branch)[0]
1748
base = [branch, revision[0].in_history(b).revno]
1749
other = [branch, revision[1].in_history(b).revno]
2155
conflict_count = merge(other, base, check_clean=(not force),
2156
merge_type=merge_type,
2157
reprocess=reprocess,
2158
show_base=show_base,
2159
pb=pb, file_list=interesting_files)
1752
conflict_count = merge(other, base, check_clean=(not force),
1753
merge_type=merge_type, reprocess=reprocess,
1754
show_base=show_base,
1755
pb=bzrlib.ui.ui_factory.progress_bar())
2162
1756
if conflict_count != 0:
2166
except errors.AmbiguousBase, e:
1760
except bzrlib.errors.AmbiguousBase, e:
2167
1761
m = ("sorry, bzr can't determine the right merge base yet\n"
2168
1762
"candidates are:\n "
2169
1763
+ "\n ".join(e.bases)
2172
1766
"and (if you want) report this to the bzr developers\n")
2175
# TODO: move up to common parent; this isn't merge-specific anymore.
2176
def _get_remembered_parent(self, tree, supplied_location, verb_string):
2177
"""Use tree.branch's parent if none was supplied.
2179
Report if the remembered location was used.
2181
if supplied_location is not None:
2182
return supplied_location
2183
stored_location = tree.branch.get_parent()
2184
mutter("%s", stored_location)
2185
if stored_location is None:
2186
raise BzrCommandError("No location specified or remembered")
2187
display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
2188
self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
2189
return stored_location
2192
1770
class cmd_remerge(Command):
2193
1771
"""Redo a merge.
2195
Use this if you want to try a different merge technique while resolving
2196
conflicts. Some merge techniques are better than others, and remerge
2197
lets you try different ones on different files.
2199
The options for remerge have the same meaning and defaults as the ones for
2200
merge. The difference is that remerge can (only) be run when there is a
2201
pending merge, and it lets you specify particular files.
2204
$ bzr remerge --show-base
2205
Re-do the merge of all conflicted files, and show the base text in
2206
conflict regions, in addition to the usual THIS and OTHER texts.
2208
$ bzr remerge --merge-type weave --reprocess foobar
2209
Re-do the merge of "foobar", using the weave merge algorithm, with
2210
additional processing to reduce the size of conflict regions.
2212
The following merge types are available:"""
2213
1773
takes_args = ['file*']
2214
1774
takes_options = ['merge-type', 'reprocess',
2215
1775
Option('show-base', help="Show base revision text in "
2219
from merge import merge_type_help
2220
from inspect import getdoc
2221
return getdoc(self) + '\n' + merge_type_help()
2223
1778
def run(self, file_list=None, merge_type=None, show_base=False,
2224
1779
reprocess=False):
2225
1780
from bzrlib.merge import merge_inner, transform_tree
2231
1786
pending_merges = tree.pending_merges()
2232
1787
if len(pending_merges) != 1:
2233
1788
raise BzrCommandError("Sorry, remerge only works after normal"
2234
" merges. Not cherrypicking or"
1789
+ " merges. Not cherrypicking or"
2236
1791
repository = tree.branch.repository
2237
1792
base_revision = common_ancestor(tree.branch.last_revision(),
2238
1793
pending_merges[0], repository)
2239
1794
base_tree = repository.revision_tree(base_revision)
2240
1795
other_tree = repository.revision_tree(pending_merges[0])
2241
1796
interesting_ids = None
2243
conflicts = tree.conflicts()
2244
1797
if file_list is not None:
2245
1798
interesting_ids = set()
2246
1799
for filename in file_list:
2247
1800
file_id = tree.path2id(filename)
2249
raise NotVersionedError(filename)
2250
1801
interesting_ids.add(file_id)
2251
1802
if tree.kind(file_id) != "directory":
2254
1805
for name, ie in tree.inventory.iter_entries(file_id):
2255
1806
interesting_ids.add(ie.file_id)
2256
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
2257
1807
transform_tree(tree, tree.basis_tree(), interesting_ids)
2258
tree.set_conflicts(ConflictList(new_conflicts))
2259
1808
if file_list is None:
2260
1809
restore_files = list(tree.iter_conflicts())
2385
encoding_type = 'replace'
2388
1930
def run(self, other_branch=None, reverse=False, mine_only=False,
2389
1931
theirs_only=False, log_format=None, long=False, short=False, line=False,
2390
1932
show_ids=False, verbose=False):
2391
1933
from bzrlib.missing import find_unmerged, iter_log_data
2392
1934
from bzrlib.log import log_formatter
2393
local_branch = Branch.open_containing(u".")[0]
1935
local_branch = bzrlib.branch.Branch.open_containing(u".")[0]
2394
1936
parent = local_branch.get_parent()
2395
1937
if other_branch is None:
2396
1938
other_branch = parent
2397
1939
if other_branch is None:
2398
1940
raise BzrCommandError("No missing location known or specified.")
2399
1941
print "Using last location: " + local_branch.get_parent()
2400
remote_branch = Branch.open(other_branch)
2401
if remote_branch.base == local_branch.base:
2402
remote_branch = local_branch
2403
local_branch.lock_read()
2405
remote_branch.lock_read()
2407
local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
2408
if (log_format == None):
2409
default = local_branch.get_config().log_format()
2410
log_format = get_log_format(long=long, short=short,
2411
line=line, default=default)
2412
lf = log_formatter(log_format,
2415
show_timezone='original')
2416
if reverse is False:
2417
local_extra.reverse()
2418
remote_extra.reverse()
2419
if local_extra and not theirs_only:
2420
print "You have %d extra revision(s):" % len(local_extra)
2421
for data in iter_log_data(local_extra, local_branch.repository,
2424
printed_local = True
2426
printed_local = False
2427
if remote_extra and not mine_only:
2428
if printed_local is True:
2430
print "You are missing %d revision(s):" % len(remote_extra)
2431
for data in iter_log_data(remote_extra, remote_branch.repository,
2434
if not remote_extra and not local_extra:
2436
print "Branches are up to date."
2440
remote_branch.unlock()
2442
local_branch.unlock()
2443
if not status_code and parent is None and other_branch is not None:
2444
local_branch.lock_write()
2446
# handle race conditions - a parent might be set while we run.
2447
if local_branch.get_parent() is None:
2448
local_branch.set_parent(remote_branch.base)
2450
local_branch.unlock()
1942
remote_branch = bzrlib.branch.Branch.open(other_branch)
1943
local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
1944
if (log_format == None):
1945
default = bzrlib.config.BranchConfig(local_branch).log_format()
1946
log_format = get_log_format(long=long, short=short, line=line, default=default)
1947
lf = log_formatter(log_format, sys.stdout,
1949
show_timezone='original')
1950
if reverse is False:
1951
local_extra.reverse()
1952
remote_extra.reverse()
1953
if local_extra and not theirs_only:
1954
print "You have %d extra revision(s):" % len(local_extra)
1955
for data in iter_log_data(local_extra, local_branch.repository,
1958
printed_local = True
1960
printed_local = False
1961
if remote_extra and not mine_only:
1962
if printed_local is True:
1964
print "You are missing %d revision(s):" % len(remote_extra)
1965
for data in iter_log_data(remote_extra, remote_branch.repository,
1968
if not remote_extra and not local_extra:
1970
print "Branches are up to date."
1973
if parent is None and other_branch is not None:
1974
local_branch.set_parent(other_branch)
2451
1975
return status_code
2510
2028
shown only at the top, unless the --all option is given.
2512
2030
# TODO: annotate directories; showing when each file was last changed
2031
# TODO: annotate a previous version of a file
2513
2032
# TODO: if the working copy is modified, show annotations on that
2514
2033
# with new uncommitted lines marked
2515
aliases = ['ann', 'blame', 'praise']
2034
aliases = ['blame', 'praise']
2516
2035
takes_args = ['filename']
2517
2036
takes_options = [Option('all', help='show annotations on all lines'),
2518
2037
Option('long', help='show date in annotations'),
2522
2040
@display_command
2523
def run(self, filename, all=False, long=False, revision=None):
2041
def run(self, filename, all=False, long=False):
2524
2042
from bzrlib.annotate import annotate_file
2525
2043
tree, relpath = WorkingTree.open_containing(filename)
2526
2044
branch = tree.branch
2527
2045
branch.lock_read()
2529
if revision is None:
2530
revision_id = branch.last_revision()
2531
elif len(revision) != 1:
2532
raise BzrCommandError('bzr annotate --revision takes exactly 1 argument')
2534
revision_id = revision[0].in_history(branch).rev_id
2535
2047
file_id = tree.inventory.path2id(relpath)
2536
tree = branch.repository.revision_tree(revision_id)
2048
tree = branch.repository.revision_tree(branch.last_revision())
2537
2049
file_version = tree.inventory[file_id].revision
2538
2050
annotate_file(branch, file_version, file_id, long, all, sys.stdout)
2580
2093
raise BzrCommandError('Please supply either one revision, or a range.')
2583
class cmd_bind(Command):
2584
"""Bind the current branch to a master branch.
2586
After binding, commits must succeed on the master branch
2587
before they are executed on the local one.
2590
takes_args = ['location']
2593
def run(self, location=None):
2594
b, relpath = Branch.open_containing(u'.')
2595
b_other = Branch.open(location)
2598
except DivergedBranches:
2599
raise BzrCommandError('These branches have diverged.'
2600
' Try merging, and then bind again.')
2603
class cmd_unbind(Command):
2604
"""Unbind the current branch from its master branch.
2606
After unbinding, the local branch is considered independent.
2607
All subsequent commits will be local.
2614
b, relpath = Branch.open_containing(u'.')
2616
raise BzrCommandError('Local branch is not bound')
2619
class cmd_uncommit(Command):
2096
class cmd_uncommit(bzrlib.commands.Command):
2620
2097
"""Remove the last committed revision.
2099
By supplying the --all flag, it will not only remove the entry
2100
from revision_history, but also remove all of the entries in the
2622
2103
--verbose will print out what is being removed.
2623
2104
--dry-run will go through all the motions, but not actually
2624
2105
remove anything.
2626
In the future, uncommit will create a revision bundle, which can then
2107
In the future, uncommit will create a changeset, which can then
2110
TODO: jam 20060108 Add an option to allow uncommit to remove unreferenced
2111
information in 'branch-as-repostory' branches.
2112
TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
2113
information in shared branches as well.
2630
# TODO: jam 20060108 Add an option to allow uncommit to remove
2631
# unreferenced information in 'branch-as-repository' branches.
2632
# TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
2633
# information in shared branches as well.
2634
2115
takes_options = ['verbose', 'revision',
2635
2116
Option('dry-run', help='Don\'t actually make changes'),
2636
2117
Option('force', help='Say yes to all questions.')]
2637
2118
takes_args = ['location?']
2640
def run(self, location=None,
2121
def run(self, location=None,
2641
2122
dry_run=False, verbose=False,
2642
2123
revision=None, force=False):
2643
from bzrlib.log import log_formatter, show_log
2124
from bzrlib.branch import Branch
2125
from bzrlib.log import log_formatter
2645
2127
from bzrlib.uncommit import uncommit
2647
2129
if location is None:
2648
2130
location = u'.'
2649
2131
control, relpath = bzrdir.BzrDir.open_containing(location)
2132
b = control.open_branch()
2651
2134
tree = control.open_workingtree()
2653
2135
except (errors.NoWorkingTree, errors.NotLocalUrl):
2655
b = control.open_branch()
2658
2138
if revision is None:
2659
2139
revno = b.revno()
2140
rev_id = b.last_revision()
2661
# 'bzr uncommit -r 10' actually means uncommit
2662
# so that the final tree is at revno 10.
2663
# but bzrlib.uncommit.uncommit() actually uncommits
2664
# the revisions that are supplied.
2665
# So we need to offset it by one
2666
revno = revision[0].in_history(b).revno+1
2668
if revno <= b.revno():
2669
rev_id = b.get_rev_id(revno)
2142
revno, rev_id = revision[0].in_history(b)
2670
2143
if rev_id is None:
2671
self.outf.write('No revisions to uncommit.\n')
2674
lf = log_formatter('short',
2676
show_timezone='original')
2681
direction='forward',
2682
start_revision=revno,
2683
end_revision=b.revno())
2144
print 'No revisions to uncommit.'
2146
for r in range(revno, b.revno()+1):
2147
rev_id = b.get_rev_id(r)
2148
lf = log_formatter('short', to_file=sys.stdout,show_timezone='original')
2149
lf.show(r, b.repository.get_revision(rev_id), None)
2686
2152
print 'Dry-run, pretending to remove the above revisions.'
2701
class cmd_break_lock(Command):
2702
"""Break a dead lock on a repository, branch or working directory.
2704
CAUTION: Locks should only be broken when you are sure that the process
2705
holding the lock has been stopped.
2707
You can get information on what locks are open via the 'bzr info' command.
2712
takes_args = ['location?']
2714
def run(self, location=None, show=False):
2715
if location is None:
2717
control, relpath = bzrdir.BzrDir.open_containing(location)
2719
control.break_lock()
2720
except NotImplementedError:
2725
# command-line interpretation helper for merge-related commands
2726
2167
def merge(other_revision, base_revision,
2727
2168
check_clean=True, ignore_zero=False,
2728
2169
this_dir=None, backup_files=False, merge_type=Merge3Merger,
2729
file_list=None, show_base=False, reprocess=False,
2170
file_list=None, show_base=False, reprocess=False,
2730
2171
pb=DummyProgress()):
2731
2172
"""Merge changes into a tree.
2762
2203
if show_base and not merge_type is Merge3Merger:
2763
2204
raise BzrCommandError("Show-base is not supported for this merge"
2764
2205
" type. %s" % merge_type)
2765
if reprocess and not merge_type.supports_reprocess:
2766
raise BzrCommandError("Conflict reduction is not supported for merge"
2767
" type %s." % merge_type)
2206
if reprocess and not merge_type is Merge3Merger:
2207
raise BzrCommandError("Reprocess is not supported for this merge"
2208
" type. %s" % merge_type)
2768
2209
if reprocess and show_base:
2769
raise BzrCommandError("Cannot do conflict reduction and show base.")
2771
merger = Merger(this_tree.branch, this_tree=this_tree, pb=pb)
2772
merger.pp = ProgressPhase("Merge phase", 5, pb)
2773
merger.pp.next_phase()
2774
merger.check_basis(check_clean)
2775
merger.set_other(other_revision)
2776
merger.pp.next_phase()
2777
merger.set_base(base_revision)
2778
if merger.base_rev_id == merger.other_rev_id:
2779
note('Nothing to do.')
2781
merger.backup_files = backup_files
2782
merger.merge_type = merge_type
2783
merger.set_interesting_files(file_list)
2784
merger.show_base = show_base
2785
merger.reprocess = reprocess
2786
conflicts = merger.do_merge()
2787
if file_list is None:
2788
merger.set_pending()
2210
raise BzrCommandError("Cannot reprocess and show base.")
2211
merger = Merger(this_tree.branch, this_tree=this_tree, pb=pb)
2212
merger.check_basis(check_clean)
2213
merger.set_other(other_revision)
2214
merger.set_base(base_revision)
2215
if merger.base_rev_id == merger.other_rev_id:
2216
note('Nothing to do.')
2218
merger.backup_files = backup_files
2219
merger.merge_type = merge_type
2220
merger.set_interesting_files(file_list)
2221
merger.show_base = show_base
2222
merger.reprocess = reprocess
2223
conflicts = merger.do_merge()
2224
merger.set_pending()
2791
2225
return conflicts
2794
2228
# these get imported and then picked up by the scan for cmd_*
2795
2229
# TODO: Some more consistent way to split command definitions across files;
2796
2230
# we do need to load at least some information about them to know of
2797
# aliases. ideally we would avoid loading the implementation until the
2798
# details were needed.
2799
2232
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
2800
from bzrlib.bundle.commands import cmd_bundle_revisions
2801
2233
from bzrlib.sign_my_commits import cmd_sign_my_commits
2802
from bzrlib.weave_commands import cmd_weave_list, cmd_weave_join, \
2803
cmd_weave_plan_merge, cmd_weave_merge_text