17
17
"""builtin bzr commands"""
22
from shutil import rmtree
24
from bzrlib import BZRDIR
25
from bzrlib._merge_core import ApplyMerge3
27
from bzrlib.branch import Branch
28
import bzrlib.bzrdir as bzrdir
26
29
from bzrlib.commands import Command, display_command
27
from bzrlib.branch import Branch
28
30
from bzrlib.revision import common_ancestor
29
31
import bzrlib.errors as errors
30
32
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError,
31
33
NotBranchError, DivergedBranches, NotConflicted,
32
34
NoSuchFile, NoWorkingTree, FileInWrongBranch)
33
35
from bzrlib.log import show_one_log
36
from bzrlib.merge import Merge3Merger
34
37
from bzrlib.option import Option
38
from bzrlib.progress import DummyProgress
35
39
from bzrlib.revisionspec import RevisionSpec
36
40
import bzrlib.trace
37
41
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
38
42
from bzrlib.transport.local import LocalTransport
39
44
from bzrlib.workingtree import WorkingTree
392
397
If you want to forget your local changes and just update your branch to
393
398
match the remote one, use --overwrite.
395
takes_options = ['remember', 'overwrite', 'verbose']
400
takes_options = ['remember', 'overwrite', 'revision', 'verbose']
396
401
takes_args = ['location?']
398
def run(self, location=None, remember=False, overwrite=False, verbose=False):
399
from shutil import rmtree
403
def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
401
404
# FIXME: too much stuff is in the command class
402
405
tree_to = WorkingTree.open_containing(u'.')[0]
403
406
stored_loc = tree_to.branch.get_parent()
411
414
br_from = Branch.open(location)
412
415
br_to = tree_to.branch
419
elif len(revision) == 1:
420
rev_id = revision[0].in_history(br_from).rev_id
422
raise BzrCommandError('bzr pull --revision takes one value.')
414
424
old_rh = br_to.revision_history()
415
count = tree_to.pull(br_from, overwrite)
425
count = tree_to.pull(br_from, overwrite, rev_id)
417
427
if br_to.get_parent() is None or remember:
418
428
br_to.set_parent(location)
459
469
create_prefix=False, verbose=False):
460
470
# FIXME: Way too big! Put this into a function called from the
463
from shutil import rmtree
464
472
from bzrlib.transport import get_transport
466
474
tree_from = WorkingTree.open_containing(u'.')[0]
498
506
if new_transport.base == transport.base:
499
507
raise BzrCommandError("Could not creeate "
501
if isinstance(transport, LocalTransport):
502
br_to = WorkingTree.create_standalone(location).branch
504
br_to = Branch.create(location)
509
br_to = bzrlib.bzrdir.BzrDir.create_branch_convenience(location)
505
510
old_rh = br_to.revision_history()
547
552
aliases = ['get', 'clone']
549
554
def run(self, from_location, to_location=None, revision=None, basis=None):
551
from shutil import rmtree
552
555
if revision is None:
553
556
revision = [None]
554
557
elif len(revision) > 1:
565
568
br_from.lock_read()
567
570
if basis is not None:
568
basis_branch = WorkingTree.open_containing(basis)[0].branch
571
basis_dir = bzrdir.BzrDir.open_containing(basis)[0]
571
574
if len(revision) == 1 and revision[0] is not None:
572
575
revision_id = revision[0].in_history(br_from)[1]
577
# FIXME - wt.last_revision, fallback to branch, fall back to
578
# None or perhaps NULL_REVISION to mean copy nothing
580
revision_id = br_from.last_revision()
575
581
if to_location is None:
576
582
to_location = os.path.basename(from_location.rstrip("/\\"))
592
br_from.clone(to_location, revision_id, basis_branch)
598
dir = br_from.bzrdir.sprout(to_location, revision_id, basis_dir)
599
branch = dir.open_branch()
593
600
except bzrlib.errors.NoSuchRevision:
594
601
rmtree(to_location)
595
602
msg = "The branch %s has no revision %s." % (from_location, revision[0])
598
605
rmtree(to_location)
599
606
msg = "The branch %s cannot be used as a --basis"
600
607
raise BzrCommandError(msg)
601
branch = Branch.open(to_location)
603
609
branch.control_files.put_utf8('branch-name', name)
616
class cmd_checkout(Command):
617
"""Create a new checkout of an existing branch.
619
If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
620
be used. In other words, "checkout ../foo/bar" will attempt to create ./bar.
622
To retrieve the branch as of a particular revision, supply the --revision
623
parameter, as in "checkout foo/bar -r 5". Note that this will be immediately
624
out of date [so you cannot commit] but it may be useful (i.e. to examine old
627
--basis is to speed up checking out from remote branches. When specified, it
628
uses the inventory and file contents from the basis branch in preference to the
629
branch being checked out. [Not implemented yet.]
631
takes_args = ['branch_location', 'to_location?']
632
takes_options = ['revision'] # , 'basis']
634
def run(self, branch_location, to_location=None, revision=None, basis=None):
637
elif len(revision) > 1:
638
raise BzrCommandError(
639
'bzr checkout --revision takes exactly 1 revision value')
640
source = Branch.open(branch_location)
641
if len(revision) == 1 and revision[0] is not None:
642
revision_id = revision[0].in_history(source)[1]
645
if to_location is None:
646
to_location = os.path.basename(branch_location.rstrip("/\\"))
648
os.mkdir(to_location)
650
if e.errno == errno.EEXIST:
651
raise BzrCommandError('Target directory "%s" already'
652
' exists.' % to_location)
653
if e.errno == errno.ENOENT:
654
raise BzrCommandError('Parent of "%s" does not exist.' %
658
checkout = bzrdir.BzrDirMetaFormat1().initialize(to_location)
659
bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
660
checkout.create_workingtree(revision_id)
610
663
class cmd_renames(Command):
611
664
"""Show list of renamed files.
619
672
def run(self, dir=u'.'):
620
673
tree = WorkingTree.open_containing(dir)[0]
621
old_inv = tree.branch.basis_tree().inventory
674
old_inv = tree.basis_tree().inventory
622
675
new_inv = tree.read_working_inventory()
624
677
renames = list(bzrlib.tree.find_renames(old_inv, new_inv))
627
680
print "%s => %s" % (old_name, new_name)
683
class cmd_update(Command):
684
"""Update a tree to have the latest code committed to its branch.
686
This will perform a merge into the working tree, and may generate
687
conflicts. If you have any uncommitted changes, you will still
688
need to commit them after the update.
690
takes_args = ['dir?']
692
def run(self, dir='.'):
693
tree = WorkingTree.open_containing(dir)[0]
696
if tree.last_revision() == tree.branch.last_revision():
697
note("Tree is up to date.")
699
conflicts = tree.update()
700
note('Updated to revision %d.' %
701
(tree.branch.revision_id_to_revno(tree.last_revision()),))
630
710
class cmd_info(Command):
631
711
"""Show statistical information about a branch."""
632
712
takes_args = ['branch?']
635
715
def run(self, branch=None):
637
b = WorkingTree.open_containing(branch)[0].branch
717
bzrlib.info.show_bzrdir_info(bzrdir.BzrDir.open_containing(branch)[0])
641
720
class cmd_remove(Command):
821
900
def run(self, show_ids=False):
822
901
tree = WorkingTree.open_containing(u'.')[0]
823
old = tree.branch.basis_tree()
902
old = tree.basis_tree()
824
903
for path, ie in old.inventory.iter_entries():
825
904
if not tree.has_id(ie.file_id):
837
916
from bzrlib.delta import compare_trees
839
918
tree = WorkingTree.open_containing(u'.')[0]
840
td = compare_trees(tree.branch.basis_tree(), tree)
919
td = compare_trees(tree.basis_tree(), tree)
842
921
for path, id, kind, text_modified, meta_modified in td.modified:
912
993
"invalid message argument %r" % message
913
994
direction = (forward and 'forward') or 'reverse'
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())
999
# find the file id to log:
1001
dir, fp = bzrdir.BzrDir.open_containing(filename)
1002
b = dir.open_branch()
1006
inv = dir.open_workingtree().inventory
1007
except (errors.NotBranchError, errors.NotLocalUrl):
1008
# either no tree, or is remote.
1009
inv = b.basis_tree().inventory
930
1010
file_id = inv.path2id(fp)
932
file_id = None # points to branch root
934
tree, relpath = WorkingTree.open_containing(u'.')
1013
# FIXME ? log the current subdir only RBC 20060203
1014
dir, relpath = bzrdir.BzrDir.open_containing('.')
1015
b = dir.open_branch()
938
1017
if revision is None:
941
1020
elif len(revision) == 1:
942
1021
rev1 = rev2 = revision[0].in_history(b).revno
943
1022
elif len(revision) == 2:
944
rev1 = revision[0].in_history(b).revno
945
rev2 = revision[1].in_history(b).revno
1023
if revision[0].spec is None:
1024
# missing begin-range means first revision
1027
rev1 = revision[0].in_history(b).revno
1029
if revision[1].spec is None:
1030
# missing end-range means last known revision
1033
rev2 = revision[1].in_history(b).revno
947
1035
raise BzrCommandError('bzr log --revision takes one or two values.')
958
1046
# in e.g. the default C locale.
959
1047
outf = codecs.getwriter(bzrlib.user_encoding)(sys.stdout, errors='replace')
961
log_format = get_log_format(long=long, short=short, line=line)
1049
if (log_format == None):
1050
default = bzrlib.config.BranchConfig(b).log_format()
1051
log_format = get_log_format(long=long, short=short, line=line, default=default)
962
1053
lf = log_formatter(log_format,
963
1054
show_ids=show_ids,
1358
1450
if c.needs_write:
1454
def get_format_type(typestring):
1455
"""Parse and return a format specifier."""
1456
if typestring == "metadir":
1457
return bzrdir.BzrDirMetaFormat1
1458
msg = "No known bzr-dir format %s. Supported types are: metadir\n" %\
1460
raise BzrCommandError(msg)
1363
1463
class cmd_upgrade(Command):
1368
1468
during other operations to upgrade.
1370
1470
takes_args = ['url?']
1372
def run(self, url='.'):
1473
help='Upgrade to a specific format rather than the'
1474
' current default format. Currently this '
1475
' option only accepts =metadir',
1476
type=get_format_type),
1480
def run(self, url='.', format=None):
1373
1481
from bzrlib.upgrade import upgrade
1482
upgrade(url, format)
1377
1485
class cmd_whoami(Command):
1611
1719
def run(self, branch=None, revision=None, force=False, merge_type=None,
1612
1720
show_base=False, reprocess=False):
1613
from bzrlib._merge_core import ApplyMerge3
1614
1721
if merge_type is None:
1615
merge_type = ApplyMerge3
1722
merge_type = Merge3Merger
1616
1723
if branch is None:
1617
1724
branch = WorkingTree.open_containing(u'.')[0].branch.get_parent()
1618
1725
if branch is None:
1642
1749
conflict_count = merge(other, base, check_clean=(not force),
1643
1750
merge_type=merge_type, reprocess=reprocess,
1644
show_base=show_base)
1751
show_base=show_base,
1752
pb=bzrlib.ui.ui_factory.progress_bar())
1645
1753
if conflict_count != 0:
1667
1775
def run(self, file_list=None, merge_type=None, show_base=False,
1668
1776
reprocess=False):
1669
1777
from bzrlib.merge import merge_inner, transform_tree
1670
from bzrlib._merge_core import ApplyMerge3
1671
1778
if merge_type is None:
1672
merge_type = ApplyMerge3
1779
merge_type = Merge3Merger
1673
1780
tree, file_list = tree_files(file_list)
1674
1781
tree.lock_write()
1695
1802
for name, ie in tree.inventory.iter_entries(file_id):
1696
1803
interesting_ids.add(ie.file_id)
1697
transform_tree(tree, tree.branch.basis_tree(), interesting_ids)
1804
transform_tree(tree, tree.basis_tree(), interesting_ids)
1698
1805
if file_list is None:
1699
1806
restore_files = list(tree.iter_conflicts())
1746
1853
rev_id = revision[0].in_history(tree.branch).rev_id
1747
1854
tree.revert(file_list, tree.branch.repository.revision_tree(rev_id),
1855
not no_backup, bzrlib.ui.ui_factory.progress_bar())
1751
1858
class cmd_assert_fail(Command):
1819
1927
def run(self, other_branch=None, reverse=False, mine_only=False,
1820
theirs_only=False, long=True, short=False, line=False,
1928
theirs_only=False, log_format=None, long=False, short=False, line=False,
1821
1929
show_ids=False, verbose=False):
1822
1930
from bzrlib.missing import find_unmerged, iter_log_data
1823
1931
from bzrlib.log import log_formatter
1830
1938
print "Using last location: " + local_branch.get_parent()
1831
1939
remote_branch = bzrlib.branch.Branch.open(other_branch)
1832
1940
local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
1833
log_format = get_log_format(long=long, short=short, line=line)
1941
if (log_format == None):
1942
default = bzrlib.config.BranchConfig(local_branch).log_format()
1943
log_format = get_log_format(long=long, short=short, line=line, default=default)
1834
1944
lf = log_formatter(log_format, sys.stdout,
1835
1945
show_ids=show_ids,
1836
1946
show_timezone='original')
1944
2054
# TODO be able to replace existing ones.
1946
2056
hidden = True # is this right ?
1947
takes_args = ['revision_id?']
2057
takes_args = ['revision_id*']
1948
2058
takes_options = ['revision']
1950
def run(self, revision_id=None, revision=None):
2060
def run(self, revision_id_list=None, revision=None):
1951
2061
import bzrlib.config as config
1952
2062
import bzrlib.gpg as gpg
1953
if revision_id is not None and revision is not None:
2063
if revision_id_list is not None and revision is not None:
1954
2064
raise BzrCommandError('You can only supply one of revision_id or --revision')
1955
if revision_id is None and revision is None:
2065
if revision_id_list is None and revision is None:
1956
2066
raise BzrCommandError('You must supply either --revision or a revision_id')
1957
2067
b = WorkingTree.open_containing(u'.')[0].branch
1958
2068
gpg_strategy = gpg.GPGStrategy(config.BranchConfig(b))
1959
if revision_id is not None:
1960
b.repository.sign_revision(revision_id, gpg_strategy)
2069
if revision_id_list is not None:
2070
for revision_id in revision_id_list:
2071
b.repository.sign_revision(revision_id, gpg_strategy)
1961
2072
elif revision is not None:
1962
2073
if len(revision) == 1:
1963
2074
revno, rev_id = revision[0].in_history(b)
2048
2159
def merge(other_revision, base_revision,
2049
2160
check_clean=True, ignore_zero=False,
2050
this_dir=None, backup_files=False, merge_type=ApplyMerge3,
2051
file_list=None, show_base=False, reprocess=False):
2161
this_dir=None, backup_files=False, merge_type=Merge3Merger,
2162
file_list=None, show_base=False, reprocess=False,
2163
pb=DummyProgress()):
2052
2164
"""Merge changes into a tree.
2076
2188
clients might prefer to call merge.merge_inner(), which has less magic
2079
from bzrlib.merge import Merger, _MergeConflictHandler
2191
from bzrlib.merge import Merger
2080
2192
if this_dir is None:
2081
2193
this_dir = u'.'
2082
2194
this_tree = WorkingTree.open_containing(this_dir)[0]
2083
if show_base and not merge_type is ApplyMerge3:
2195
if show_base and not merge_type is Merge3Merger:
2084
2196
raise BzrCommandError("Show-base is not supported for this merge"
2085
2197
" type. %s" % merge_type)
2086
if reprocess and not merge_type is ApplyMerge3:
2198
if reprocess and not merge_type is Merge3Merger:
2087
2199
raise BzrCommandError("Reprocess is not supported for this merge"
2088
2200
" type. %s" % merge_type)
2089
2201
if reprocess and show_base:
2090
2202
raise BzrCommandError("Cannot reprocess and show base.")
2091
merger = Merger(this_tree.branch, this_tree=this_tree)
2203
merger = Merger(this_tree.branch, this_tree=this_tree, pb=pb)
2092
2204
merger.check_basis(check_clean)
2093
2205
merger.set_other(other_revision)
2094
2206
merger.set_base(base_revision)
2100
2212
merger.set_interesting_files(file_list)
2101
2213
merger.show_base = show_base
2102
2214
merger.reprocess = reprocess
2103
merger.conflict_handler = _MergeConflictHandler(merger.this_tree,
2106
ignore_zero=ignore_zero)
2107
2215
conflicts = merger.do_merge()
2108
2216
merger.set_pending()
2109
2217
return conflicts