17
17
"""builtin bzr commands"""
23
from shutil import rmtree
24
from bzrlib import BZRDIR
25
from bzrlib._merge_core import ApplyMerge3
26
from bzrlib.commands import Command, display_command
28
27
from bzrlib.branch import Branch
29
import bzrlib.bzrdir as bzrdir
30
from bzrlib.bundle.read_bundle import BundleReader
31
from bzrlib.bundle.apply_bundle import merge_bundle
32
from bzrlib.commands import Command, display_command
28
from bzrlib.revision import common_ancestor
33
29
import bzrlib.errors as errors
34
30
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError,
35
31
NotBranchError, DivergedBranches, NotConflicted,
36
NoSuchFile, NoWorkingTree, FileInWrongBranch,
37
NotVersionedError, NotABundle)
32
NoSuchFile, NoWorkingTree, FileInWrongBranch)
38
33
from bzrlib.log import show_one_log
39
from bzrlib.merge import Merge3Merger
40
34
from bzrlib.option import Option
42
from bzrlib.progress import DummyProgress, ProgressPhase
43
from bzrlib.revision import common_ancestor
44
35
from bzrlib.revisionspec import RevisionSpec
45
36
import bzrlib.trace
46
37
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
47
38
from bzrlib.transport.local import LocalTransport
49
import bzrlib.urlutils as urlutils
50
39
from bzrlib.workingtree import WorkingTree
275
221
takes_args = ['file*']
276
222
takes_options = ['no-recurse', 'dry-run', 'verbose']
277
encoding_type = 'replace'
279
224
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
280
225
import bzrlib.add
282
action = bzrlib.add.AddAction(to_file=self.outf,
283
should_print=(not is_quiet()))
229
# This is pointless, but I'd rather not raise an error
230
action = bzrlib.add.add_action_null
232
action = bzrlib.add.add_action_print
234
action = bzrlib.add.add_action_add
236
action = bzrlib.add.add_action_add_and_print
285
238
added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
286
action=action, save=not dry_run)
287
240
if len(ignored) > 0:
289
for glob in sorted(ignored.keys()):
241
for glob in sorted(ignored.keys()):
242
match_len = len(ignored[glob])
290
244
for path in ignored[glob]:
291
self.outf.write("ignored %s matching \"%s\"\n"
295
for glob, paths in ignored.items():
296
match_len += len(paths)
297
self.outf.write("ignored %d file(s).\n" % match_len)
298
self.outf.write("If you wish to add some of these files,"
299
" please add them by name.\n")
245
print "ignored %s matching \"%s\"" % (path, glob)
247
print "ignored %d file(s) matching \"%s\"" % (match_len,
249
print "If you wish to add some of these files, please add them"\
302
253
class cmd_mkdir(Command):
390
365
if os.path.isdir(names_list[-1]):
391
366
# move into existing directory
392
367
for pair in tree.move(rel_names[:-1], rel_names[-1]):
393
self.outf.write("%s => %s\n" % pair)
368
print "%s => %s" % pair
395
370
if len(names_list) != 2:
396
371
raise BzrCommandError('to mv multiple files the destination '
397
372
'must be a versioned directory')
398
373
tree.rename_one(rel_names[0], rel_names[1])
399
self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
374
print "%s => %s" % (rel_names[0], rel_names[1])
402
377
class cmd_pull(Command):
403
"""Turn this branch into a mirror of another branch.
378
"""Pull any changes from another branch into the current one.
380
If there is no default location set, the first pull will set it. After
381
that, you can omit the location to use the default. To change the
382
default, use --remember.
405
384
This command only works on branches that have not diverged. Branches are
406
considered diverged if the destination branch's most recent commit is one
407
that has not been merged (directly or indirectly) into the parent.
409
If branches have diverged, you can use 'bzr merge' to integrate the changes
410
from one into the other. Once one branch has merged, the other should
411
be able to pull it again.
385
considered diverged if both branches have had commits without first
386
pulling from the other.
413
388
If branches have diverged, you can use 'bzr merge' to pull the text changes
414
389
from one into the other. Once one branch has merged, the other should
415
390
be able to pull it again.
417
392
If you want to forget your local changes and just update your branch to
418
match the remote one, use pull --overwrite.
420
If there is no default location set, the first pull will set it. After
421
that, you can omit the location to use the default. To change the
422
default, use --remember.
393
match the remote one, use --overwrite.
425
takes_options = ['remember', 'overwrite', 'revision', 'verbose']
395
takes_options = ['remember', 'overwrite', 'verbose']
426
396
takes_args = ['location?']
427
encoding_type = 'replace'
429
def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
430
# FIXME: too much stuff is in the command class
432
tree_to = WorkingTree.open_containing(u'.')[0]
433
branch_to = tree_to.branch
434
except NoWorkingTree:
436
branch_to = Branch.open_containing(u'.')[0]
437
stored_loc = branch_to.get_parent()
398
def run(self, location=None, remember=False, overwrite=False, verbose=False):
399
from shutil import rmtree
401
# FIXME: too much stuff is in the command class
402
tree_to = WorkingTree.open_containing(u'.')[0]
403
stored_loc = tree_to.branch.get_parent()
438
404
if location is None:
439
405
if stored_loc is None:
440
406
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)
408
print "Using saved location: %s" % stored_loc
445
409
location = stored_loc
447
branch_from = Branch.open(location)
449
if branch_to.get_parent() is None or remember:
450
branch_to.set_parent(branch_from.base)
454
elif len(revision) == 1:
455
rev_id = revision[0].in_history(branch_from).rev_id
457
raise BzrCommandError('bzr pull --revision takes one value.')
459
old_rh = branch_to.revision_history()
460
if tree_to is not None:
461
count = tree_to.pull(branch_from, overwrite, rev_id)
463
count = branch_to.pull(branch_from, overwrite, rev_id)
411
br_from = Branch.open(location)
412
br_to = tree_to.branch
414
old_rh = br_to.revision_history()
415
count = tree_to.pull(br_from, overwrite)
417
if br_to.get_parent() is None or remember:
418
br_to.set_parent(location)
464
419
note('%d revision(s) pulled.' % (count,))
467
new_rh = branch_to.revision_history()
422
new_rh = tree_to.branch.revision_history()
468
423
if old_rh != new_rh:
469
424
# Something changed
470
425
from bzrlib.log import show_changed_revisions
471
show_changed_revisions(branch_to, old_rh, new_rh,
426
show_changed_revisions(tree_to.branch, old_rh, new_rh)
475
429
class cmd_push(Command):
476
"""Update a mirror of this branch.
478
The target branch will not have its working tree populated because this
479
is both expensive, and is not supported on remote file systems.
481
Some smart servers or protocols *may* put the working tree in place in
430
"""Push this branch into another branch.
432
The remote branch will not have its working tree populated because this
433
is both expensive, and may not be supported on the remote file system.
435
Some smart servers or protocols *may* put the working tree in place.
437
If there is no default push location set, the first push will set it.
438
After that, you can omit the location to use the default. To change the
439
default, use --remember.
484
441
This command only works on branches that have not diverged. Branches are
485
considered diverged if the destination branch's most recent commit is one
486
that has not been merged (directly or indirectly) by the source branch.
442
considered diverged if the branch being pushed to is not an older version
488
445
If branches have diverged, you can use 'bzr push --overwrite' to replace
489
the other branch completely, discarding its unmerged changes.
446
the other branch completely.
491
448
If you want to ensure you have the different changes in the other branch,
492
do a merge (see bzr help merge) from the other branch, and commit that.
493
After that you will be able to do a push without '--overwrite'.
495
If there is no default push location set, the first push will set it.
496
After that, you can omit the location to use the default. To change the
497
default, use --remember.
449
do a merge (see bzr help merge) from the other branch, and commit that
450
before doing a 'push --overwrite'.
500
takes_options = ['remember', 'overwrite', 'verbose',
452
takes_options = ['remember', 'overwrite',
501
453
Option('create-prefix',
502
454
help='Create the path leading up to the branch '
503
455
'if it does not already exist')]
504
456
takes_args = ['location?']
505
encoding_type = 'replace'
507
458
def run(self, location=None, remember=False, overwrite=False,
508
459
create_prefix=False, verbose=False):
509
460
# FIXME: Way too big! Put this into a function called from the
463
from shutil import rmtree
511
464
from bzrlib.transport import get_transport
513
br_from = Branch.open_containing('.')[0]
514
stored_loc = br_from.get_push_location()
466
tree_from = WorkingTree.open_containing(u'.')[0]
467
br_from = tree_from.branch
468
stored_loc = tree_from.branch.get_push_location()
515
469
if location is None:
516
470
if stored_loc is None:
517
471
raise BzrCommandError("No push location known or specified.")
519
display_url = urlutils.unescape_for_display(stored_loc,
521
self.outf.write("Using saved location: %s" % display_url)
473
print "Using saved location: %s" % stored_loc
522
474
location = stored_loc
524
transport = get_transport(location)
525
location_url = transport.base
526
if br_from.get_push_location() is None or remember:
527
br_from.set_push_location(location_url)
531
dir_to = bzrlib.bzrdir.BzrDir.open(location_url)
532
br_to = dir_to.open_branch()
476
br_to = Branch.open(location)
533
477
except NotBranchError:
534
478
# create a branch.
535
transport = transport.clone('..')
479
transport = get_transport(location).clone('..')
536
480
if not create_prefix:
538
relurl = transport.relpath(location_url)
539
mutter('creating directory %s => %s', location_url, relurl)
540
transport.mkdir(relurl)
482
transport.mkdir(transport.relpath(location))
541
483
except NoSuchFile:
542
484
raise BzrCommandError("Parent directory of %s "
543
485
"does not exist." % location)
545
487
current = transport.base
546
needed = [(transport, transport.relpath(location_url))]
488
needed = [(transport, transport.relpath(location))]
549
491
transport, relpath = needed[-1]
554
496
needed.append((new_transport,
555
497
new_transport.relpath(transport.base)))
556
498
if new_transport.base == transport.base:
557
raise BzrCommandError("Could not create "
499
raise BzrCommandError("Could not creeate "
559
dir_to = br_from.bzrdir.clone(location_url,
560
revision_id=br_from.last_revision())
561
br_to = dir_to.open_branch()
562
count = len(br_to.revision_history())
564
old_rh = br_to.revision_history()
501
if isinstance(transport, LocalTransport):
502
br_to = WorkingTree.create_standalone(location).branch
504
br_to = Branch.create(location)
505
old_rh = br_to.revision_history()
567
tree_to = dir_to.open_workingtree()
568
except errors.NotLocalUrl:
569
warning('This transport does not update the working '
570
'tree of: %s' % (br_to.base,))
571
count = br_to.pull(br_from, overwrite)
572
except NoWorkingTree:
573
count = br_to.pull(br_from, overwrite)
575
count = tree_to.pull(br_from, overwrite)
576
except DivergedBranches:
577
raise BzrCommandError("These branches have diverged."
578
" Try a merge then push with overwrite.")
508
tree_to = br_to.working_tree()
509
except NoWorkingTree:
510
# TODO: This should be updated for branches which don't have a
511
# working tree, as opposed to ones where we just couldn't
513
warning('Unable to update the working tree of: %s' % (br_to.base,))
514
count = br_to.pull(br_from, overwrite)
516
count = tree_to.pull(br_from, overwrite)
517
except DivergedBranches:
518
raise BzrCommandError("These branches have diverged."
519
" Try a merge then push with overwrite.")
520
if br_from.get_push_location() is None or remember:
521
br_from.set_push_location(location)
579
522
note('%d revision(s) pushed.' % (count,))
623
565
br_from.lock_read()
625
567
if basis is not None:
626
basis_dir = bzrdir.BzrDir.open_containing(basis)[0]
568
basis_branch = WorkingTree.open_containing(basis)[0].branch
629
571
if len(revision) == 1 and revision[0] is not None:
630
572
revision_id = revision[0].in_history(br_from)[1]
632
# FIXME - wt.last_revision, fallback to branch, fall back to
633
# None or perhaps NULL_REVISION to mean copy nothing
635
revision_id = br_from.last_revision()
636
575
if to_location is None:
637
576
to_location = os.path.basename(from_location.rstrip("/\\"))
640
579
name = os.path.basename(to_location) + '\n'
642
to_transport = get_transport(to_location)
644
to_transport.mkdir('.')
645
except bzrlib.errors.FileExists:
646
raise BzrCommandError('Target directory "%s" already'
647
' exists.' % to_location)
648
except bzrlib.errors.NoSuchFile:
649
raise BzrCommandError('Parent of "%s" does not exist.' %
652
# preserve whatever source format we have.
653
dir = br_from.bzrdir.sprout(to_transport.base,
654
revision_id, basis_dir)
655
branch = dir.open_branch()
581
os.mkdir(to_location)
583
if e.errno == errno.EEXIST:
584
raise BzrCommandError('Target directory "%s" already'
585
' exists.' % to_location)
586
if e.errno == errno.ENOENT:
587
raise BzrCommandError('Parent of "%s" does not exist.' %
592
br_from.clone(to_location, revision_id, basis_branch)
656
593
except bzrlib.errors.NoSuchRevision:
657
to_transport.delete_tree('.')
658
595
msg = "The branch %s has no revision %s." % (from_location, revision[0])
659
596
raise BzrCommandError(msg)
660
597
except bzrlib.errors.UnlistableBranch:
661
598
rmtree(to_location)
662
msg = "The branch %s cannot be used as a --basis" % (basis,)
599
msg = "The branch %s cannot be used as a --basis"
663
600
raise BzrCommandError(msg)
601
branch = Branch.open(to_location)
665
603
branch.control_files.put_utf8('branch-name', name)
666
605
note('Branched %d revision(s).' % branch.revno())
671
class cmd_checkout(Command):
672
"""Create a new checkout of an existing branch.
674
If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree for
675
the branch found in '.'. This is useful if you have removed the working tree
676
or if it was never created - i.e. if you pushed the branch to its current
679
If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
680
be used. In other words, "checkout ../foo/bar" will attempt to create ./bar.
682
To retrieve the branch as of a particular revision, supply the --revision
683
parameter, as in "checkout foo/bar -r 5". Note that this will be immediately
684
out of date [so you cannot commit] but it may be useful (i.e. to examine old
687
--basis is to speed up checking out from remote branches. When specified, it
688
uses the inventory and file contents from the basis branch in preference to the
689
branch being checked out.
691
takes_args = ['branch_location?', 'to_location?']
692
takes_options = ['revision', # , 'basis']
693
Option('lightweight',
694
help="perform a lightweight checkout. Lightweight "
695
"checkouts depend on access to the branch for "
696
"every operation. Normal checkouts can perform "
697
"common operations like diff and status without "
698
"such access, and also support local commits."
702
def run(self, branch_location=None, to_location=None, revision=None, basis=None,
706
elif len(revision) > 1:
707
raise BzrCommandError(
708
'bzr checkout --revision takes exactly 1 revision value')
709
if branch_location is None:
710
branch_location = bzrlib.osutils.getcwd()
711
to_location = branch_location
712
source = Branch.open(branch_location)
713
if len(revision) == 1 and revision[0] is not None:
714
revision_id = revision[0].in_history(source)[1]
717
if to_location is None:
718
to_location = os.path.basename(branch_location.rstrip("/\\"))
719
# if the source and to_location are the same,
720
# and there is no working tree,
721
# then reconstitute a branch
722
if (bzrlib.osutils.abspath(to_location) ==
723
bzrlib.osutils.abspath(branch_location)):
725
source.bzrdir.open_workingtree()
726
except errors.NoWorkingTree:
727
source.bzrdir.create_workingtree()
730
os.mkdir(to_location)
732
if e.errno == errno.EEXIST:
733
raise BzrCommandError('Target directory "%s" already'
734
' exists.' % to_location)
735
if e.errno == errno.ENOENT:
736
raise BzrCommandError('Parent of "%s" does not exist.' %
740
old_format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
741
bzrlib.bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
744
checkout = bzrdir.BzrDirMetaFormat1().initialize(to_location)
745
bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
747
checkout_branch = bzrlib.bzrdir.BzrDir.create_branch_convenience(
748
to_location, force_new_tree=False)
749
checkout = checkout_branch.bzrdir
750
checkout_branch.bind(source)
751
if revision_id is not None:
752
rh = checkout_branch.revision_history()
753
checkout_branch.set_revision_history(rh[:rh.index(revision_id) + 1])
754
checkout.create_workingtree(revision_id)
756
bzrlib.bzrdir.BzrDirFormat.set_default_format(old_format)
759
610
class cmd_renames(Command):
760
611
"""Show list of renamed files.
768
619
def run(self, dir=u'.'):
769
620
tree = WorkingTree.open_containing(dir)[0]
770
old_inv = tree.basis_tree().inventory
621
old_inv = tree.branch.basis_tree().inventory
771
622
new_inv = tree.read_working_inventory()
773
624
renames = list(bzrlib.tree.find_renames(old_inv, new_inv))
775
626
for old_name, new_name in renames:
776
self.outf.write("%s => %s\n" % (old_name, new_name))
779
class cmd_update(Command):
780
"""Update a tree to have the latest code committed to its branch.
782
This will perform a merge into the working tree, and may generate
783
conflicts. If you have any local changes, you will still
784
need to commit them after the update for the update to be complete.
786
If you want to discard your local changes, you can just do a
787
'bzr revert' instead of 'bzr commit' after the update.
789
takes_args = ['dir?']
791
def run(self, dir='.'):
792
tree = WorkingTree.open_containing(dir)[0]
795
if tree.last_revision() == tree.branch.last_revision():
796
# may be up to date, check master too.
797
master = tree.branch.get_master_branch()
798
if master is None or master.last_revision == tree.last_revision():
799
note("Tree is up to date.")
801
conflicts = tree.update()
802
note('Updated to revision %d.' %
803
(tree.branch.revision_id_to_revno(tree.last_revision()),))
627
print "%s => %s" % (old_name, new_name)
812
630
class cmd_info(Command):
813
"""Show information about a working tree, branch or repository.
815
This command will show all known locations and formats associated to the
816
tree, branch or repository. Statistical information is included with
819
Branches and working trees will also report any missing revisions.
821
takes_args = ['location?']
822
takes_options = ['verbose']
631
"""Show statistical information about a branch."""
632
takes_args = ['branch?']
825
def run(self, location=None, verbose=False):
826
from bzrlib.info import show_bzrdir_info
827
show_bzrdir_info(bzrdir.BzrDir.open_containing(location)[0],
635
def run(self, branch=None):
637
b = WorkingTree.open_containing(branch)[0].branch
831
641
class cmd_remove(Command):
834
644
This makes bzr stop tracking changes to a versioned file. It does
835
645
not delete the working copy.
837
You can specify one or more files, and/or --new. If you specify --new,
838
only 'added' files will be removed. If you specify both, then new files
839
in the specified directories will be removed. If the directories are
840
also new, they will also be removed.
842
takes_args = ['file*']
843
takes_options = ['verbose', Option('new', help='remove newly-added files')]
647
takes_args = ['file+']
648
takes_options = ['verbose']
845
encoding_type = 'replace'
847
def run(self, file_list, verbose=False, new=False):
651
def run(self, file_list, verbose=False):
848
652
tree, file_list = tree_files(file_list)
850
if file_list is None:
851
raise BzrCommandError('Specify one or more files to remove, or'
854
from bzrlib.delta import compare_trees
855
added = [compare_trees(tree.basis_tree(), tree,
856
specific_files=file_list).added]
857
file_list = sorted([f[0] for f in added[0]], reverse=True)
858
if len(file_list) == 0:
859
raise BzrCommandError('No matching files.')
860
tree.remove(file_list, verbose=verbose, to_file=self.outf)
653
tree.remove(file_list, verbose=verbose)
863
656
class cmd_file_id(Command):
900
688
raise BzrError("%r is not a versioned file" % filename)
901
689
for fip in inv.get_idpath(fid):
902
self.outf.write(fip + '\n')
905
class cmd_reconcile(Command):
906
"""Reconcile bzr metadata in a branch.
908
This can correct data mismatches that may have been caused by
909
previous ghost operations or bzr upgrades. You should only
910
need to run this command if 'bzr check' or a bzr developer
911
advises you to run it.
913
If a second branch is provided, cross-branch reconciliation is
914
also attempted, which will check that data like the tree root
915
id which was not present in very early bzr versions is represented
916
correctly in both branches.
918
At the same time it is run it may recompress data resulting in
919
a potential saving in disk space or performance gain.
921
The branch *MUST* be on a listable system such as local disk or sftp.
923
takes_args = ['branch?']
925
def run(self, branch="."):
926
from bzrlib.reconcile import reconcile
927
dir = bzrlib.bzrdir.BzrDir.open(branch)
931
693
class cmd_revision_history(Command):
932
694
"""Display list of revision ids on this branch."""
937
698
branch = WorkingTree.open_containing(u'.')[0].branch
938
699
for patchid in branch.revision_history():
939
self.outf.write(patchid)
940
self.outf.write('\n')
943
703
class cmd_ancestry(Command):
944
704
"""List all revisions merged into this branch."""
949
708
tree = WorkingTree.open_containing(u'.')[0]
951
710
# FIXME. should be tree.last_revision
952
revision_ids = b.repository.get_ancestry(b.last_revision())
953
assert revision_ids[0] == None
955
for revision_id in revision_ids:
956
self.outf.write(revision_id + '\n')
711
for revision_id in b.get_ancestry(b.last_revision()):
959
715
class cmd_init(Command):
1000
738
# locations if the user supplies an extended path
1001
739
if not os.path.exists(location):
1002
740
os.mkdir(location)
1004
existing_bzrdir = bzrdir.BzrDir.open(location)
1005
except NotBranchError:
1006
# really a NotBzrDir error...
1007
bzrdir.BzrDir.create_branch_convenience(location, format=format)
1009
if existing_bzrdir.has_branch():
1010
if existing_bzrdir.has_workingtree():
1011
raise errors.AlreadyBranchError(location)
1013
raise errors.BranchExistsWithoutWorkingTree(location)
1015
existing_bzrdir.create_branch()
1016
existing_bzrdir.create_workingtree()
1019
class cmd_init_repository(Command):
1020
"""Create a shared repository to hold branches.
1022
New branches created under the repository directory will store their revisions
1023
in the repository, not in the branch directory, if the branch format supports
1029
bzr checkout --lightweight repo/trunk trunk-checkout
1033
takes_args = ["location"]
1034
takes_options = [Option('format',
1035
help='Specify a format for this repository.'
1036
' Current formats are: default, knit,'
1037
' metaweave and weave. Default is knit;'
1038
' metaweave and weave are deprecated',
1039
type=get_format_type),
1041
help='Allows branches in repository to have'
1043
aliases = ["init-repo"]
1044
def run(self, location, format=None, trees=False):
1045
from bzrlib.transport import get_transport
1047
format = get_format_type('default')
1048
transport = get_transport(location)
1049
if not transport.has('.'):
1051
newdir = format.initialize_on_transport(transport)
1052
repo = newdir.create_repository(shared=True)
1053
repo.set_make_working_trees(trees)
741
WorkingTree.create_standalone(location)
1056
744
class cmd_diff(Command):
1059
747
If files are listed, only the changes in those files are listed.
1060
748
Otherwise, all changes for the tree are listed.
1062
"bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1063
produces patches suitable for "patch -p1".
1069
bzr diff --diff-prefix old/:new/
1070
bzr diff bzr.mine bzr.dev
755
# TODO: Allow diff across branches.
1073
756
# TODO: Option to use external diff command; could be GNU diff, wdiff,
1074
757
# or a graphical diff.
1076
759
# TODO: Python difflib is not exactly the same as unidiff; should
1077
760
# either fix it up or prefer to use an external diff.
762
# TODO: If a directory is given, diff everything under that.
1079
764
# TODO: Selected-file diff is inefficient and doesn't show you
1080
765
# deleted files.
1082
767
# TODO: This probably handles non-Unix newlines poorly.
1084
769
takes_args = ['file*']
1085
takes_options = ['revision', 'diff-options', 'prefix']
770
takes_options = ['revision', 'diff-options']
1086
771
aliases = ['di', 'dif']
1087
encoding_type = 'exact'
1089
773
@display_command
1090
def run(self, revision=None, file_list=None, diff_options=None,
1092
from bzrlib.diff import diff_cmd_helper, show_diff_trees
1094
if (prefix is None) or (prefix == '0'):
1102
if not ':' in prefix:
1103
raise BzrError("--diff-prefix expects two values separated by a colon")
1104
old_label, new_label = prefix.split(":")
774
def run(self, revision=None, file_list=None, diff_options=None):
775
from bzrlib.diff import show_diff
1107
tree1, file_list = internal_tree_files(file_list)
777
tree, file_list = internal_tree_files(file_list)
1111
780
except FileInWrongBranch:
1112
781
if len(file_list) != 2:
1113
782
raise BzrCommandError("Files are in different branches")
1115
tree1, file1 = WorkingTree.open_containing(file_list[0])
1116
tree2, file2 = WorkingTree.open_containing(file_list[1])
784
b, file1 = Branch.open_containing(file_list[0])
785
b2, file2 = Branch.open_containing(file_list[1])
1117
786
if file1 != "" or file2 != "":
1118
787
# FIXME diff those two files. rbc 20051123
1119
788
raise BzrCommandError("Files are in different branches")
1120
789
file_list = None
1121
790
if revision is not None:
1122
if tree2 is not None:
1123
792
raise BzrCommandError("Can't specify -r with two branches")
1124
793
if (len(revision) == 1) or (revision[1].spec is None):
1125
return diff_cmd_helper(tree1, file_list, diff_options,
1127
old_label=old_label, new_label=new_label)
794
return show_diff(tree.branch, revision[0], specific_files=file_list,
795
external_diff_options=diff_options)
1128
796
elif len(revision) == 2:
1129
return diff_cmd_helper(tree1, file_list, diff_options,
1130
revision[0], revision[1],
1131
old_label=old_label, new_label=new_label)
797
return show_diff(tree.branch, revision[0], specific_files=file_list,
798
external_diff_options=diff_options,
799
revision2=revision[1])
1133
801
raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
1135
if tree2 is not None:
1136
return show_diff_trees(tree1, tree2, sys.stdout,
1137
specific_files=file_list,
1138
external_diff_options=diff_options,
1139
old_label=old_label, new_label=new_label)
804
return show_diff(b, None, specific_files=file_list,
805
external_diff_options=diff_options, b2=b2)
1141
return diff_cmd_helper(tree1, file_list, diff_options,
1142
old_label=old_label, new_label=new_label)
807
return show_diff(tree.branch, None, specific_files=file_list,
808
external_diff_options=diff_options)
1145
811
class cmd_deleted(Command):
1207
872
def run(self, filename=None):
1208
873
"""Print the branch root."""
1209
874
tree = WorkingTree.open_containing(filename)[0]
1210
self.outf.write(tree.basedir + '\n')
1213
878
class cmd_log(Command):
1214
"""Show log of a branch, file, or directory.
1216
By default show the log of the branch containing the working directory.
879
"""Show log of this branch.
1218
881
To request a range of logs, you can use the command -r begin..end
1219
882
-r revision requests a specific revision, -r ..end or -r begin.. are
1225
bzr log -r -10.. http://server/branch
1228
886
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
1230
takes_args = ['location?']
888
takes_args = ['filename?']
1231
889
takes_options = [Option('forward',
1232
890
help='show from oldest to newest'),
1235
help='show files changed in each revision'),
891
'timezone', 'verbose',
1236
892
'show-ids', 'revision',
1239
894
Option('message',
1240
895
help='show revisions whose message matches this regexp',
1244
encoding_type = 'replace'
1246
899
@display_command
1247
def run(self, location=None, timezone='original',
900
def run(self, filename=None, timezone='original',
1257
909
from bzrlib.log import log_formatter, show_log
1258
911
assert message is None or isinstance(message, basestring), \
1259
912
"invalid message argument %r" % message
1260
913
direction = (forward and 'forward') or 'reverse'
1265
# find the file id to log:
1267
dir, fp = bzrdir.BzrDir.open_containing(location)
1268
b = dir.open_branch()
919
tree, fp = WorkingTree.open_containing(filename)
922
inv = tree.read_working_inventory()
923
except NotBranchError:
926
b, fp = Branch.open_containing(filename)
928
inv = b.repository.get_inventory(b.last_revision())
1272
inv = dir.open_workingtree().inventory
1273
except (errors.NotBranchError, errors.NotLocalUrl):
1274
# either no tree, or is remote.
1275
inv = b.basis_tree().inventory
1276
930
file_id = inv.path2id(fp)
932
file_id = None # points to branch root
1279
# FIXME ? log the current subdir only RBC 20060203
1280
dir, relpath = bzrdir.BzrDir.open_containing('.')
1281
b = dir.open_branch()
934
tree, relpath = WorkingTree.open_containing(u'.')
1283
938
if revision is None:
2033
1593
merge refuses to run if there are any uncommitted changes, unless
2034
1594
--force is given.
2036
The following merge types are available:
2038
1596
takes_args = ['branch?']
2039
takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
1597
takes_options = ['revision', 'force', 'merge-type', 'reprocess',
2040
1598
Option('show-base', help="Show base revision text in "
2044
from merge import merge_type_help
2045
from inspect import getdoc
2046
return getdoc(self) + '\n' + merge_type_help()
2048
1601
def run(self, branch=None, revision=None, force=False, merge_type=None,
2049
show_base=False, reprocess=False, remember=False):
1602
show_base=False, reprocess=False):
1603
from bzrlib._merge_core import ApplyMerge3
2050
1604
if merge_type is None:
2051
merge_type = Merge3Merger
2053
tree = WorkingTree.open_containing(u'.')[0]
2056
if branch is not None:
2057
reader = BundleReader(file(branch, 'rb'))
2061
if e.errno not in (errno.ENOENT, errno.EISDIR):
2066
if reader is not None:
2067
conflicts = merge_bundle(reader, tree, not force, merge_type,
2068
reprocess, show_base)
2074
branch = self._get_remembered_parent(tree, branch, 'Merging from')
1605
merge_type = ApplyMerge3
1607
branch = WorkingTree.open_containing(u'.')[0].branch.get_parent()
1609
raise BzrCommandError("No merge location known or specified.")
1611
print "Using saved location: %s" % branch
2076
1612
if revision is None or len(revision) < 1:
2077
1613
base = [None, None]
2078
1614
other = [branch, -1]
2079
other_branch, path = Branch.open_containing(branch)
2081
1616
if len(revision) == 1:
2082
1617
base = [None, None]
2083
other_branch, path = Branch.open_containing(branch)
1618
other_branch = Branch.open_containing(branch)[0]
2084
1619
revno = revision[0].in_history(other_branch).revno
2085
1620
other = [branch, revno]
2123
1645
"and (if you want) report this to the bzr developers\n")
2126
# TODO: move up to common parent; this isn't merge-specific anymore.
2127
def _get_remembered_parent(self, tree, supplied_location, verb_string):
2128
"""Use tree.branch's parent if none was supplied.
2130
Report if the remembered location was used.
2132
if supplied_location is not None:
2133
return supplied_location
2134
stored_location = tree.branch.get_parent()
2135
mutter("%s", stored_location)
2136
if stored_location is None:
2137
raise BzrCommandError("No location specified or remembered")
2138
display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
2139
self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
2140
return stored_location
2143
1649
class cmd_remerge(Command):
2144
1650
"""Redo a merge.
2146
Use this if you want to try a different merge technique while resolving
2147
conflicts. Some merge techniques are better than others, and remerge
2148
lets you try different ones on different files.
2150
The options for remerge have the same meaning and defaults as the ones for
2151
merge. The difference is that remerge can (only) be run when there is a
2152
pending merge, and it lets you specify particular files.
2155
$ bzr remerge --show-base
2156
Re-do the merge of all conflicted files, and show the base text in
2157
conflict regions, in addition to the usual THIS and OTHER texts.
2159
$ bzr remerge --merge-type weave --reprocess foobar
2160
Re-do the merge of "foobar", using the weave merge algorithm, with
2161
additional processing to reduce the size of conflict regions.
2163
The following merge types are available:"""
2164
1652
takes_args = ['file*']
2165
1653
takes_options = ['merge-type', 'reprocess',
2166
1654
Option('show-base', help="Show base revision text in "
2170
from merge import merge_type_help
2171
from inspect import getdoc
2172
return getdoc(self) + '\n' + merge_type_help()
2174
1657
def run(self, file_list=None, merge_type=None, show_base=False,
2175
1658
reprocess=False):
2176
1659
from bzrlib.merge import merge_inner, transform_tree
1660
from bzrlib._merge_core import ApplyMerge3
2177
1661
if merge_type is None:
2178
merge_type = Merge3Merger
1662
merge_type = ApplyMerge3
2179
1663
tree, file_list = tree_files(file_list)
2180
1664
tree.lock_write()
2344
1819
raise BzrCommandError("No missing location known or specified.")
2345
1820
print "Using last location: " + local_branch.get_parent()
2346
1821
remote_branch = bzrlib.branch.Branch.open(other_branch)
2347
if remote_branch.base == local_branch.base:
2348
remote_branch = local_branch
2349
local_branch.lock_read()
2351
remote_branch.lock_read()
2353
local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
2354
if (log_format == None):
2355
default = bzrlib.config.BranchConfig(local_branch).log_format()
2356
log_format = get_log_format(long=long, short=short, line=line, default=default)
2357
lf = log_formatter(log_format, sys.stdout,
2359
show_timezone='original')
2360
if reverse is False:
2361
local_extra.reverse()
2362
remote_extra.reverse()
2363
if local_extra and not theirs_only:
2364
print "You have %d extra revision(s):" % len(local_extra)
2365
for data in iter_log_data(local_extra, local_branch.repository,
2368
printed_local = True
2370
printed_local = False
2371
if remote_extra and not mine_only:
2372
if printed_local is True:
2374
print "You are missing %d revision(s):" % len(remote_extra)
2375
for data in iter_log_data(remote_extra, remote_branch.repository,
2378
if not remote_extra and not local_extra:
2380
print "Branches are up to date."
2384
remote_branch.unlock()
2386
local_branch.unlock()
2387
if not status_code and parent is None and other_branch is not None:
2388
local_branch.lock_write()
2390
# handle race conditions - a parent might be set while we run.
2391
if local_branch.get_parent() is None:
2392
local_branch.set_parent(remote_branch.base)
2394
local_branch.unlock()
1822
local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
1823
log_format = get_log_format(long=long, short=short, line=line)
1824
lf = log_formatter(log_format, sys.stdout,
1826
show_timezone='original')
1827
if reverse is False:
1828
local_extra.reverse()
1829
remote_extra.reverse()
1830
if local_extra and not theirs_only:
1831
print "You have %d extra revision(s):" % len(local_extra)
1832
for data in iter_log_data(local_extra, local_branch.repository,
1835
printed_local = True
1837
printed_local = False
1838
if remote_extra and not mine_only:
1839
if printed_local is True:
1841
print "You are missing %d revision(s):" % len(remote_extra)
1842
for data in iter_log_data(remote_extra, remote_branch.repository,
1845
if not remote_extra and not local_extra:
1847
print "Branches are up to date."
1850
if parent is None and other_branch is not None:
1851
local_branch.set_parent(other_branch)
2395
1852
return status_code
2448
1905
shown only at the top, unless the --all option is given.
2450
1907
# TODO: annotate directories; showing when each file was last changed
1908
# TODO: annotate a previous version of a file
2451
1909
# TODO: if the working copy is modified, show annotations on that
2452
1910
# with new uncommitted lines marked
2453
1911
aliases = ['blame', 'praise']
2454
1912
takes_args = ['filename']
2455
1913
takes_options = [Option('all', help='show annotations on all lines'),
2456
1914
Option('long', help='show date in annotations'),
2460
1917
@display_command
2461
def run(self, filename, all=False, long=False, revision=None):
1918
def run(self, filename, all=False, long=False):
2462
1919
from bzrlib.annotate import annotate_file
2463
1920
tree, relpath = WorkingTree.open_containing(filename)
2464
1921
branch = tree.branch
2465
1922
branch.lock_read()
2467
if revision is None:
2468
revision_id = branch.last_revision()
2469
elif len(revision) != 1:
2470
raise BzrCommandError('bzr annotate --revision takes exactly 1 argument')
2472
revision_id = revision[0].in_history(branch).rev_id
2473
1924
file_id = tree.inventory.path2id(relpath)
2474
tree = branch.repository.revision_tree(revision_id)
1925
tree = branch.repository.revision_tree(branch.last_revision())
2475
1926
file_version = tree.inventory[file_id].revision
2476
1927
annotate_file(branch, file_version, file_id, long, all, sys.stdout)
2519
1969
raise BzrCommandError('Please supply either one revision, or a range.')
2522
class cmd_bind(Command):
2523
"""Bind the current branch to a master branch.
2525
After binding, commits must succeed on the master branch
2526
before they are executed on the local one.
2529
takes_args = ['location']
2532
def run(self, location=None):
2533
b, relpath = Branch.open_containing(u'.')
2534
b_other = Branch.open(location)
2537
except DivergedBranches:
2538
raise BzrCommandError('These branches have diverged.'
2539
' Try merging, and then bind again.')
2542
class cmd_unbind(Command):
2543
"""Unbind the current branch from its master branch.
2545
After unbinding, the local branch is considered independent.
2546
All subsequent commits will be local.
2553
b, relpath = Branch.open_containing(u'.')
2555
raise BzrCommandError('Local branch is not bound')
2558
1972
class cmd_uncommit(bzrlib.commands.Command):
2559
1973
"""Remove the last committed revision.
1975
By supplying the --all flag, it will not only remove the entry
1976
from revision_history, but also remove all of the entries in the
2561
1979
--verbose will print out what is being removed.
2562
1980
--dry-run will go through all the motions, but not actually
2563
1981
remove anything.
2565
In the future, uncommit will create a revision bundle, which can then
1983
In the future, uncommit will create a changeset, which can then
1986
TODO: jam 20060108 Add an option to allow uncommit to remove unreferenced
1987
information in 'branch-as-repostory' branches.
1988
TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
1989
information in shared branches as well.
2569
# TODO: jam 20060108 Add an option to allow uncommit to remove
2570
# unreferenced information in 'branch-as-repository' branches.
2571
# TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
2572
# information in shared branches as well.
2573
1991
takes_options = ['verbose', 'revision',
2574
1992
Option('dry-run', help='Don\'t actually make changes'),
2575
1993
Option('force', help='Say yes to all questions.')]
2619
2031
print 'Canceled'
2622
uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
2034
uncommit(b, dry_run=dry_run, verbose=verbose,
2626
class cmd_break_lock(Command):
2627
"""Break a dead lock on a repository, branch or working directory.
2629
CAUTION: Locks should only be broken when you are sure that the process
2630
holding the lock has been stopped.
2632
You can get information on what locks are open via the 'bzr info' command.
2637
takes_args = ['location?']
2639
def run(self, location=None, show=False):
2640
if location is None:
2642
control, relpath = bzrdir.BzrDir.open_containing(location)
2644
control.break_lock()
2645
except NotImplementedError:
2650
# command-line interpretation helper for merge-related commands
2651
2038
def merge(other_revision, base_revision,
2652
2039
check_clean=True, ignore_zero=False,
2653
this_dir=None, backup_files=False, merge_type=Merge3Merger,
2654
file_list=None, show_base=False, reprocess=False,
2655
pb=DummyProgress()):
2040
this_dir=None, backup_files=False, merge_type=ApplyMerge3,
2041
file_list=None, show_base=False, reprocess=False):
2656
2042
"""Merge changes into a tree.
2680
2066
clients might prefer to call merge.merge_inner(), which has less magic
2683
from bzrlib.merge import Merger
2069
from bzrlib.merge import Merger, _MergeConflictHandler
2684
2070
if this_dir is None:
2685
2071
this_dir = u'.'
2686
2072
this_tree = WorkingTree.open_containing(this_dir)[0]
2687
if show_base and not merge_type is Merge3Merger:
2073
if show_base and not merge_type is ApplyMerge3:
2688
2074
raise BzrCommandError("Show-base is not supported for this merge"
2689
2075
" type. %s" % merge_type)
2690
if reprocess and not merge_type.supports_reprocess:
2691
raise BzrCommandError("Conflict reduction is not supported for merge"
2692
" type %s." % merge_type)
2076
if reprocess and not merge_type is ApplyMerge3:
2077
raise BzrCommandError("Reprocess is not supported for this merge"
2078
" type. %s" % merge_type)
2693
2079
if reprocess and show_base:
2694
raise BzrCommandError("Cannot do conflict reduction and show base.")
2696
merger = Merger(this_tree.branch, this_tree=this_tree, pb=pb)
2697
merger.pp = ProgressPhase("Merge phase", 5, pb)
2698
merger.pp.next_phase()
2699
merger.check_basis(check_clean)
2700
merger.set_other(other_revision)
2701
merger.pp.next_phase()
2702
merger.set_base(base_revision)
2703
if merger.base_rev_id == merger.other_rev_id:
2704
note('Nothing to do.')
2706
merger.backup_files = backup_files
2707
merger.merge_type = merge_type
2708
merger.set_interesting_files(file_list)
2709
merger.show_base = show_base
2710
merger.reprocess = reprocess
2711
conflicts = merger.do_merge()
2712
if file_list is None:
2713
merger.set_pending()
2080
raise BzrCommandError("Cannot reprocess and show base.")
2081
merger = Merger(this_tree.branch, this_tree=this_tree)
2082
merger.check_basis(check_clean)
2083
merger.set_other(other_revision)
2084
merger.set_base(base_revision)
2085
if merger.base_rev_id == merger.other_rev_id:
2086
note('Nothing to do.')
2088
merger.backup_files = backup_files
2089
merger.merge_type = merge_type
2090
merger.set_interesting_files(file_list)
2091
merger.show_base = show_base
2092
merger.reprocess = reprocess
2093
merger.conflict_handler = _MergeConflictHandler(merger.this_tree,
2096
ignore_zero=ignore_zero)
2097
conflicts = merger.do_merge()
2098
merger.set_pending()
2716
2099
return conflicts
2719
2102
# these get imported and then picked up by the scan for cmd_*
2720
2103
# TODO: Some more consistent way to split command definitions across files;
2721
2104
# we do need to load at least some information about them to know of
2722
# aliases. ideally we would avoid loading the implementation until the
2723
# details were needed.
2724
2106
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
2725
from bzrlib.bundle.commands import cmd_bundle_revisions
2726
from bzrlib.sign_my_commits import cmd_sign_my_commits
2727
from bzrlib.weave_commands import cmd_weave_list, cmd_weave_join, \
2728
cmd_weave_plan_merge, cmd_weave_merge_text