17
17
"""builtin bzr commands"""
19
# DO NOT change this to cStringIO - it results in control files
21
# FIXIT! (Only deal with byte streams OR unicode at any one layer.)
24
from StringIO import StringIO
22
from shutil import rmtree
29
from bzrlib import BZRDIR
30
from bzrlib.commands import Command, display_command
27
31
from bzrlib.branch import Branch
28
import bzrlib.bzrdir as bzrdir
29
from bzrlib.commands import Command, display_command
30
32
from bzrlib.revision import common_ancestor
31
33
import bzrlib.errors as errors
32
34
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError,
33
35
NotBranchError, DivergedBranches, NotConflicted,
34
36
NoSuchFile, NoWorkingTree, FileInWrongBranch)
35
from bzrlib.log import show_one_log
36
from bzrlib.merge import Merge3Merger
37
37
from bzrlib.option import Option
38
from bzrlib.progress import DummyProgress
39
38
from bzrlib.revisionspec import RevisionSpec
40
39
import bzrlib.trace
41
40
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
42
from bzrlib.transport.local import LocalTransport
44
41
from bzrlib.workingtree import WorkingTree
42
from bzrlib.log import show_one_log
47
45
def tree_files(file_list, default_branch=u'.'):
125
123
def run(self, all=False, show_ids=False, file_list=None, revision=None):
126
124
tree, file_list = tree_files(file_list)
128
from bzrlib.status import show_tree_status
129
show_tree_status(tree, show_unchanged=all, show_ids=show_ids,
130
specific_files=file_list, revision=revision)
126
from bzrlib.status import show_status
127
show_status(tree.branch, show_unchanged=all, show_ids=show_ids,
128
specific_files=file_list, revision=revision)
133
131
class cmd_cat_revision(Command):
150
148
raise BzrCommandError('You must supply either --revision or a revision_id')
151
149
b = WorkingTree.open_containing(u'.')[0].branch
152
150
if revision_id is not None:
153
sys.stdout.write(b.repository.get_revision_xml(revision_id))
151
sys.stdout.write(b.get_revision_xml(revision_id))
154
152
elif revision is not None:
155
153
for rev in revision:
157
155
raise BzrCommandError('You cannot specify a NULL revision.')
158
156
revno, rev_id = rev.in_history(b)
159
sys.stdout.write(b.repository.get_revision_xml(rev_id))
157
sys.stdout.write(b.get_revision_xml(rev_id))
162
160
class cmd_revno(Command):
397
395
If you want to forget your local changes and just update your branch to
398
396
match the remote one, use --overwrite.
400
takes_options = ['remember', 'overwrite', 'revision', 'verbose']
398
takes_options = ['remember', 'overwrite', 'verbose']
401
399
takes_args = ['location?']
403
def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
401
def run(self, location=None, remember=False, overwrite=False, verbose=False):
402
from bzrlib.merge import merge
403
from shutil import rmtree
404
405
# FIXME: too much stuff is in the command class
405
406
tree_to = WorkingTree.open_containing(u'.')[0]
406
407
stored_loc = tree_to.branch.get_parent()
414
415
br_from = Branch.open(location)
415
416
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.')
424
418
old_rh = br_to.revision_history()
425
count = tree_to.pull(br_from, overwrite, rev_id)
419
count = tree_to.pull(br_from, overwrite)
427
421
if br_to.get_parent() is None or remember:
428
422
br_to.set_parent(location)
568
567
br_from.lock_read()
570
569
if basis is not None:
571
basis_dir = bzrdir.BzrDir.open_containing(basis)[0]
570
basis_branch = WorkingTree.open_containing(basis)[0].branch
574
573
if len(revision) == 1 and revision[0] is not None:
575
574
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()
581
577
if to_location is None:
582
578
to_location = os.path.basename(from_location.rstrip("/\\"))
605
600
rmtree(to_location)
606
601
msg = "The branch %s cannot be used as a --basis"
607
602
raise BzrCommandError(msg)
603
branch = Branch.open(to_location)
609
branch.control_files.put_utf8('branch-name', name)
605
name = StringIO(name)
606
branch.put_controlfile('branch-name', name)
611
607
note('Branched %d revision(s).' % branch.revno())
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)
663
612
class cmd_renames(Command):
664
613
"""Show list of renamed files.
680
629
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()),))
710
632
class cmd_info(Command):
711
633
"""Show statistical information about a branch."""
712
634
takes_args = ['branch?']
715
637
def run(self, branch=None):
717
bzrlib.info.show_bzrdir_info(bzrdir.BzrDir.open_containing(branch)[0])
639
b = WorkingTree.open_containing(branch)[0].branch
720
643
class cmd_remove(Command):
853
776
def run(self, revision=None, file_list=None, diff_options=None):
854
from bzrlib.diff import diff_cmd_helper, show_diff_trees
777
from bzrlib.diff import show_diff
856
tree1, file_list = internal_tree_files(file_list)
779
tree, file_list = internal_tree_files(file_list)
860
782
except FileInWrongBranch:
861
783
if len(file_list) != 2:
862
784
raise BzrCommandError("Files are in different branches")
864
tree1, file1 = WorkingTree.open_containing(file_list[0])
865
tree2, file2 = WorkingTree.open_containing(file_list[1])
786
b, file1 = Branch.open_containing(file_list[0])
787
b2, file2 = Branch.open_containing(file_list[1])
866
788
if file1 != "" or file2 != "":
867
789
# FIXME diff those two files. rbc 20051123
868
790
raise BzrCommandError("Files are in different branches")
870
792
if revision is not None:
871
if tree2 is not None:
872
794
raise BzrCommandError("Can't specify -r with two branches")
873
if (len(revision) == 1) or (revision[1].spec is None):
874
return diff_cmd_helper(tree1, file_list, diff_options,
795
if len(revision) == 1:
796
return show_diff(tree.branch, revision[0], specific_files=file_list,
797
external_diff_options=diff_options)
876
798
elif len(revision) == 2:
877
return diff_cmd_helper(tree1, file_list, diff_options,
878
revision[0], revision[1])
799
return show_diff(tree.branch, revision[0], specific_files=file_list,
800
external_diff_options=diff_options,
801
revision2=revision[1])
880
803
raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
882
if tree2 is not None:
883
return show_diff_trees(tree1, tree2, sys.stdout,
884
specific_files=file_list,
885
external_diff_options=diff_options)
806
return show_diff(b, None, specific_files=file_list,
807
external_diff_options=diff_options, b2=b2)
887
return diff_cmd_helper(tree1, file_list, diff_options)
809
return show_diff(tree.branch, None, specific_files=file_list,
810
external_diff_options=diff_options)
890
813
class cmd_deleted(Command):
993
914
"invalid message argument %r" % message
994
915
direction = (forward and 'forward') or 'reverse'
999
# find the file id to log:
1001
dir, fp = bzrdir.BzrDir.open_containing(filename)
1002
b = dir.open_branch()
921
tree, fp = WorkingTree.open_containing(filename)
924
inv = tree.read_working_inventory()
925
except NotBranchError:
928
b, fp = Branch.open_containing(filename)
930
inv = b.get_inventory(b.last_revision())
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
1010
932
file_id = inv.path2id(fp)
934
file_id = None # points to branch root
1013
# FIXME ? log the current subdir only RBC 20060203
1014
dir, relpath = bzrdir.BzrDir.open_containing('.')
1015
b = dir.open_branch()
936
tree, relpath = WorkingTree.open_containing(u'.')
1017
940
if revision is None:
1020
943
elif len(revision) == 1:
1021
944
rev1 = rev2 = revision[0].in_history(b).revno
1022
945
elif len(revision) == 2:
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
946
rev1 = revision[0].in_history(b).revno
947
rev2 = revision[1].in_history(b).revno
1035
949
raise BzrCommandError('bzr log --revision takes one or two values.')
1046
960
# in e.g. the default C locale.
1047
961
outf = codecs.getwriter(bzrlib.user_encoding)(sys.stdout, errors='replace')
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)
963
log_format = get_log_format(long=long, short=short, line=line)
1053
964
lf = log_formatter(log_format,
1054
965
show_ids=show_ids,
1449
1360
if c.needs_write:
1453
def get_format_type(typestring):
1454
"""Parse and return a format specifier."""
1455
if typestring == "metadir":
1456
return bzrdir.BzrDirMetaFormat1()
1457
if typestring == "knit":
1458
format = bzrdir.BzrDirMetaFormat1()
1459
format.repository_format = bzrlib.repository.RepositoryFormatKnit1()
1461
msg = "No known bzr-dir format %s. Supported types are: metadir\n" %\
1463
raise BzrCommandError(msg)
1466
1365
class cmd_upgrade(Command):
1467
1366
"""Upgrade branch storage to current format.
1469
1368
The check command or bzr developers may sometimes advise you to run
1470
this command. When the default format has changed you may also be warned
1471
during other operations to upgrade.
1371
This version of this command upgrades from the full-text storage
1372
used by bzr 0.0.8 and earlier to the weave format (v5).
1473
takes_args = ['url?']
1476
help='Upgrade to a specific format rather than the'
1477
' current default format. Currently this '
1478
' option only accepts =metadir',
1479
type=get_format_type),
1483
def run(self, url='.', format=None):
1374
takes_args = ['dir?']
1376
def run(self, dir=u'.'):
1484
1377
from bzrlib.upgrade import upgrade
1485
upgrade(url, format)
1488
1381
class cmd_whoami(Command):
1533
1424
If arguments are given, they are regular expressions that say
1534
1425
which tests should run.
1536
If the global option '--no-plugins' is given, plugins are not loaded
1537
before running the selftests. This has two effects: features provided or
1538
modified by plugins will not be tested, and tests provided by plugins will
1543
bzr --no-plugins selftest -v
1545
1427
# TODO: --list should give a list of all available tests
1547
# NB: this is used from the class without creating an instance, which is
1548
# why it does not have a self parameter.
1549
def get_transport_type(typestring):
1550
"""Parse and return a transport specifier."""
1551
if typestring == "sftp":
1552
from bzrlib.transport.sftp import SFTPAbsoluteServer
1553
return SFTPAbsoluteServer
1554
if typestring == "memory":
1555
from bzrlib.transport.memory import MemoryServer
1557
msg = "No known transport type %s. Supported types are: sftp\n" %\
1559
raise BzrCommandError(msg)
1562
1429
takes_args = ['testspecs*']
1563
takes_options = ['verbose',
1430
takes_options = ['verbose',
1564
1431
Option('one', help='stop when one test fails'),
1565
1432
Option('keep-output',
1566
help='keep output directories when tests fail'),
1568
help='Use a different transport by default '
1569
'throughout the test suite.',
1570
type=get_transport_type),
1433
help='keep output directories when tests fail')
1573
1436
def run(self, testspecs_list=None, verbose=False, one=False,
1574
keep_output=False, transport=None):
1575
1438
import bzrlib.ui
1576
1439
from bzrlib.tests import selftest
1577
1440
# we don't want progress meters from the tests to go to the
1599
1461
bzrlib.ui.ui_factory = save_ui
1602
def _get_bzr_branch():
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
1607
from os.path import dirname
1610
branch = Branch.open(dirname(abspath(dirname(__file__))))
1612
except bzrlib.errors.BzrError:
1616
1464
def show_version():
1617
1465
print "bzr (bazaar-ng) %s" % bzrlib.__version__
1618
1466
# is bzrlib itself in a branch?
1619
branch = _get_bzr_branch()
1621
rh = branch.revision_history()
1623
print " bzr checkout, revision %d" % (revno,)
1624
print " nick: %s" % (branch.nick,)
1626
print " revid: %s" % (rh[-1],)
1467
bzrrev = bzrlib.get_bzr_revision()
1469
print " (bzr checkout, revision %d {%s})" % bzrrev
1627
1470
print bzrlib.__copyright__
1628
1471
print "http://bazaar-ng.org/"
1788
1632
raise BzrCommandError("Sorry, remerge only works after normal"
1789
1633
+ " merges. Not cherrypicking or"
1790
1634
+ "multi-merges.")
1791
repository = tree.branch.repository
1792
1635
base_revision = common_ancestor(tree.branch.last_revision(),
1793
pending_merges[0], repository)
1794
base_tree = repository.revision_tree(base_revision)
1795
other_tree = repository.revision_tree(pending_merges[0])
1636
pending_merges[0], tree.branch)
1637
base_tree = tree.branch.revision_tree(base_revision)
1638
other_tree = tree.branch.revision_tree(pending_merges[0])
1796
1639
interesting_ids = None
1797
1640
if file_list is not None:
1798
1641
interesting_ids = set()
1839
1682
aliases = ['merge-revert']
1841
1684
def run(self, revision=None, no_backup=False, file_list=None):
1685
from bzrlib.merge import merge_inner
1842
1686
from bzrlib.commands import parse_spec
1843
1687
if file_list is not None:
1844
1688
if len(file_list) == 0:
1845
1689
raise BzrCommandError("No files specified")
1849
tree, file_list = tree_files(file_list)
1850
1692
if revision is None:
1694
tree = WorkingTree.open_containing(u'.')[0]
1851
1695
# FIXME should be tree.last_revision
1852
1696
rev_id = tree.branch.last_revision()
1853
1697
elif len(revision) != 1:
1854
1698
raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
1700
tree, file_list = tree_files(file_list)
1856
1701
rev_id = revision[0].in_history(tree.branch).rev_id
1857
tree.revert(file_list, tree.branch.repository.revision_tree(rev_id),
1858
not no_backup, bzrlib.ui.ui_factory.progress_bar())
1702
tree.revert(file_list, tree.branch.revision_tree(rev_id),
1861
1706
class cmd_assert_fail(Command):
1930
1782
def run(self, other_branch=None, reverse=False, mine_only=False,
1931
theirs_only=False, log_format=None, long=False, short=False, line=False,
1783
theirs_only=False, long=True, short=False, line=False,
1932
1784
show_ids=False, verbose=False):
1933
1785
from bzrlib.missing import find_unmerged, iter_log_data
1934
1786
from bzrlib.log import log_formatter
1941
1793
print "Using last location: " + local_branch.get_parent()
1942
1794
remote_branch = bzrlib.branch.Branch.open(other_branch)
1943
1795
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)
1796
log_format = get_log_format(long=long, short=short, line=line)
1947
1797
lf = log_formatter(log_format, sys.stdout,
1948
1798
show_ids=show_ids,
1949
1799
show_timezone='original')
2057
1905
# TODO be able to replace existing ones.
2059
1907
hidden = True # is this right ?
2060
takes_args = ['revision_id*']
1908
takes_args = ['revision_id?']
2061
1909
takes_options = ['revision']
2063
def run(self, revision_id_list=None, revision=None):
1911
def run(self, revision_id=None, revision=None):
2064
1912
import bzrlib.config as config
2065
1913
import bzrlib.gpg as gpg
2066
if revision_id_list is not None and revision is not None:
1914
if revision_id is not None and revision is not None:
2067
1915
raise BzrCommandError('You can only supply one of revision_id or --revision')
2068
if revision_id_list is None and revision is None:
1916
if revision_id is None and revision is None:
2069
1917
raise BzrCommandError('You must supply either --revision or a revision_id')
2070
1918
b = WorkingTree.open_containing(u'.')[0].branch
2071
1919
gpg_strategy = gpg.GPGStrategy(config.BranchConfig(b))
2072
if revision_id_list is not None:
2073
for revision_id in revision_id_list:
2074
b.repository.sign_revision(revision_id, gpg_strategy)
1920
if revision_id is not None:
1921
b.sign_revision(revision_id, gpg_strategy)
2075
1922
elif revision is not None:
2076
1923
if len(revision) == 1:
2077
1924
revno, rev_id = revision[0].in_history(b)
2078
b.repository.sign_revision(rev_id, gpg_strategy)
1925
b.sign_revision(rev_id, gpg_strategy)
2079
1926
elif len(revision) == 2:
2080
1927
# are they both on rh- if so we can walk between them
2081
1928
# might be nice to have a range helper for arbitrary
2107
1953
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.
2115
takes_options = ['verbose', 'revision',
1956
takes_options = ['all', 'verbose', 'revision',
2116
1957
Option('dry-run', help='Don\'t actually make changes'),
2117
1958
Option('force', help='Say yes to all questions.')]
2118
1959
takes_args = ['location?']
2121
def run(self, location=None,
1962
def run(self, location=None, all=False,
2122
1963
dry_run=False, verbose=False,
2123
1964
revision=None, force=False):
2124
1965
from bzrlib.branch import Branch
2160
1996
print 'Canceled'
2163
uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
1999
uncommit(b, remove_files=all,
2000
dry_run=dry_run, verbose=verbose,
2167
def merge(other_revision, base_revision,
2168
check_clean=True, ignore_zero=False,
2169
this_dir=None, backup_files=False, merge_type=Merge3Merger,
2170
file_list=None, show_base=False, reprocess=False,
2171
pb=DummyProgress()):
2172
"""Merge changes into a tree.
2175
list(path, revno) Base for three-way merge.
2176
If [None, None] then a base will be automatically determined.
2178
list(path, revno) Other revision for three-way merge.
2180
Directory to merge changes into; '.' by default.
2182
If true, this_dir must have no uncommitted changes before the
2184
ignore_zero - If true, suppress the "zero conflicts" message when
2185
there are no conflicts; should be set when doing something we expect
2186
to complete perfectly.
2187
file_list - If supplied, merge only changes to selected files.
2189
All available ancestors of other_revision and base_revision are
2190
automatically pulled into the branch.
2192
The revno may be -1 to indicate the last revision on the branch, which is
2195
This function is intended for use from the command line; programmatic
2196
clients might prefer to call merge.merge_inner(), which has less magic
2199
from bzrlib.merge import Merger
2200
if this_dir is None:
2202
this_tree = WorkingTree.open_containing(this_dir)[0]
2203
if show_base and not merge_type is Merge3Merger:
2204
raise BzrCommandError("Show-base is not supported for this merge"
2205
" 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)
2209
if reprocess and show_base:
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()
2228
2004
# these get imported and then picked up by the scan for cmd_*
2229
2005
# TODO: Some more consistent way to split command definitions across files;
2230
2006
# we do need to load at least some information about them to know of
2232
2008
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
2233
from bzrlib.sign_my_commits import cmd_sign_my_commits