14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
# DO NOT change this to cStringIO - it results in control files
19
# FIXIT! (Only deal with byte streams OR unicode at any one layer.)
21
from StringIO import StringIO
17
"""builtin bzr commands"""
22
from shutil import rmtree
26
from bzrlib import BZRDIR
27
from bzrlib.branch import Branch
28
import bzrlib.bzrdir as bzrdir
29
from bzrlib._merge_core import ApplyMerge3
27
30
from bzrlib.commands import Command, display_command
28
from bzrlib.branch import Branch
29
31
from bzrlib.revision import common_ancestor
32
import bzrlib.errors as errors
30
33
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError,
31
34
NotBranchError, DivergedBranches, NotConflicted,
32
NoSuchFile, NoWorkingTree, FileInWrongBranch)
35
NoSuchFile, NoWorkingTree, FileInWrongBranch)
36
from bzrlib.log import show_one_log
33
37
from bzrlib.option import Option
34
38
from bzrlib.revisionspec import RevisionSpec
35
39
import bzrlib.trace
36
from bzrlib.trace import mutter, note, log_error, warning
40
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
41
from bzrlib.transport.local import LocalTransport
37
42
from bzrlib.workingtree import WorkingTree
40
def branch_files(file_list, default_branch='.'):
45
def tree_files(file_list, default_branch=u'.'):
42
return inner_branch_files(file_list, default_branch)
47
return internal_tree_files(file_list, default_branch)
43
48
except FileInWrongBranch, e:
44
49
raise BzrCommandError("%s is not in the same branch as %s" %
45
50
(e.path, file_list[0]))
47
def inner_branch_files(file_list, default_branch='.'):
52
def internal_tree_files(file_list, default_branch=u'.'):
49
54
Return a branch and list of branch-relative paths.
50
55
If supplied file_list is empty or None, the branch default will be used,
51
56
and returned file_list will match the original.
53
58
if file_list is None or len(file_list) == 0:
54
return Branch.open_containing(default_branch)[0], file_list
55
b = Branch.open_containing(file_list[0])[0]
57
# note that if this is a remote branch, we would want
58
# relpath against the transport. RBC 20051018
59
# Most branch ops can't meaningfully operate on files in remote branches;
60
# the above comment was in cmd_status. ADHB 20051026
61
tree = WorkingTree(b.base, b)
59
return WorkingTree.open_containing(default_branch)[0], file_list
60
tree = WorkingTree.open_containing(file_list[0])[0]
63
62
for filename in file_list:
65
64
new_list.append(tree.relpath(filename))
66
except NotBranchError:
67
raise FileInWrongBranch(b, filename)
65
except errors.PathNotChild:
66
raise FileInWrongBranch(tree.branch, filename)
71
70
# TODO: Make sure no commands unconditionally use the working directory as a
147
146
raise BzrCommandError('You can only supply one of revision_id or --revision')
148
147
if revision_id is None and revision is None:
149
148
raise BzrCommandError('You must supply either --revision or a revision_id')
150
b = Branch.open_containing('.')[0]
149
b = WorkingTree.open_containing(u'.')[0].branch
151
150
if revision_id is not None:
152
sys.stdout.write(b.get_revision_xml_file(revision_id).read())
151
sys.stdout.write(b.repository.get_revision_xml(revision_id))
153
152
elif revision is not None:
154
153
for rev in revision:
156
155
raise BzrCommandError('You cannot specify a NULL revision.')
157
156
revno, rev_id = rev.in_history(b)
158
sys.stdout.write(b.get_revision_xml_file(rev_id).read())
157
sys.stdout.write(b.repository.get_revision_xml(rev_id))
161
160
class cmd_revno(Command):
162
161
"""Show current revision number.
164
163
This is equal to the number of revisions on this branch."""
164
takes_args = ['location?']
167
print Branch.open_containing('.')[0].revno()
166
def run(self, location=u'.'):
167
print Branch.open_containing(location)[0].revno()
170
170
class cmd_revision_info(Command):
217
217
implicitly add the parent, and so on up to the root. This means
218
218
you should never need to explictly add a directory, they'll just
219
219
get added when you add a file in the directory.
221
--dry-run will show which files would be added, but not actually
221
224
takes_args = ['file*']
222
takes_options = ['no-recurse', 'quiet']
224
def run(self, file_list, no_recurse=False, quiet=False):
225
from bzrlib.add import smart_add, add_reporter_print, add_reporter_null
227
reporter = add_reporter_null
225
takes_options = ['no-recurse', 'dry-run', 'verbose']
227
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
232
# This is pointless, but I'd rather not raise an error
233
action = bzrlib.add.add_action_null
235
action = bzrlib.add.add_action_print
237
action = bzrlib.add.add_action_add
229
reporter = add_reporter_print
230
smart_add(file_list, not no_recurse, reporter)
239
action = bzrlib.add.add_action_add_and_print
241
added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
244
for glob in sorted(ignored.keys()):
245
match_len = len(ignored[glob])
247
for path in ignored[glob]:
248
print "ignored %s matching \"%s\"" % (path, glob)
250
print "ignored %d file(s) matching \"%s\"" % (match_len,
252
print "If you wish to add some of these files, please add them"\
233
256
class cmd_mkdir(Command):
375
395
If you want to forget your local changes and just update your branch to
376
396
match the remote one, use --overwrite.
378
takes_options = ['remember', 'overwrite', 'verbose']
398
takes_options = ['remember', 'overwrite', 'revision', 'verbose']
379
399
takes_args = ['location?']
381
def run(self, location=None, remember=False, overwrite=False, verbose=False):
382
from bzrlib.merge import merge
383
from shutil import rmtree
386
br_to = Branch.open_containing('.')[0]
387
stored_loc = br_to.get_parent()
401
def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
402
# FIXME: too much stuff is in the command class
403
tree_to = WorkingTree.open_containing(u'.')[0]
404
stored_loc = tree_to.branch.get_parent()
388
405
if location is None:
389
406
if stored_loc is None:
390
407
raise BzrCommandError("No pull location known or specified.")
392
409
print "Using saved location: %s" % stored_loc
393
410
location = stored_loc
394
412
br_from = Branch.open(location)
396
old_rh = br_to.revision_history()
397
br_to.working_tree().pull(br_from, overwrite)
398
except DivergedBranches:
399
raise BzrCommandError("These branches have diverged."
413
br_to = tree_to.branch
417
elif len(revision) == 1:
418
rev_id = revision[0].in_history(br_from).rev_id
420
raise BzrCommandError('bzr pull --revision takes one value.')
422
old_rh = br_to.revision_history()
423
count = tree_to.pull(br_from, overwrite, rev_id)
401
425
if br_to.get_parent() is None or remember:
402
426
br_to.set_parent(location)
427
note('%d revision(s) pulled.' % (count,))
405
new_rh = br_to.revision_history()
430
new_rh = tree_to.branch.revision_history()
406
431
if old_rh != new_rh:
407
432
# Something changed
408
433
from bzrlib.log import show_changed_revisions
409
show_changed_revisions(br_to, old_rh, new_rh)
434
show_changed_revisions(tree_to.branch, old_rh, new_rh)
412
437
class cmd_push(Command):
478
504
if new_transport.base == transport.base:
479
505
raise BzrCommandError("Could not creeate "
483
br_to = Branch.initialize(location)
507
if isinstance(transport, LocalTransport):
508
br_to = WorkingTree.create_standalone(location).branch
510
br_to = Branch.create(location)
511
old_rh = br_to.revision_history()
485
old_rh = br_to.revision_history()
486
br_to.pull(br_from, overwrite)
514
tree_to = br_to.working_tree()
515
except NoWorkingTree:
516
# TODO: This should be updated for branches which don't have a
517
# working tree, as opposed to ones where we just couldn't
519
warning('Unable to update the working tree of: %s' % (br_to.base,))
520
count = br_to.pull(br_from, overwrite)
522
count = tree_to.pull(br_from, overwrite)
487
523
except DivergedBranches:
488
524
raise BzrCommandError("These branches have diverged."
489
525
" Try a merge then push with overwrite.")
490
526
if br_from.get_push_location() is None or remember:
491
527
br_from.set_push_location(location)
528
note('%d revision(s) pushed.' % (count,))
494
531
new_rh = br_to.revision_history()
568
607
msg = "The branch %s cannot be used as a --basis"
569
608
raise BzrCommandError(msg)
571
branch = Branch.open(to_location)
572
name = StringIO(name)
573
branch.put_controlfile('branch-name', name)
610
branch.control_files.put_utf8('branch-name', name)
612
note('Branched %d revision(s).' % branch.revno())
617
class cmd_checkout(Command):
618
"""Create a new checkout of an existing branch.
620
If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
621
be used. In other words, "checkout ../foo/bar" will attempt to create ./bar.
623
To retrieve the branch as of a particular revision, supply the --revision
624
parameter, as in "checkout foo/bar -r 5". Note that this will be immediately
625
out of date [so you cannot commit] but it may be useful (i.e. to examine old
628
--basis is to speed up checking out from remote branches. When specified, it
629
uses the inventory and file contents from the basis branch in preference to the
630
branch being checked out. [Not implemented yet.]
632
takes_args = ['branch_location', 'to_location?']
633
takes_options = ['revision'] # , 'basis']
635
def run(self, branch_location, to_location=None, revision=None, basis=None):
638
elif len(revision) > 1:
639
raise BzrCommandError(
640
'bzr checkout --revision takes exactly 1 revision value')
641
source = Branch.open(branch_location)
642
if len(revision) == 1 and revision[0] is not None:
643
revision_id = revision[0].in_history(source)[1]
646
if to_location is None:
647
to_location = os.path.basename(branch_location.rstrip("/\\"))
649
os.mkdir(to_location)
651
if e.errno == errno.EEXIST:
652
raise BzrCommandError('Target directory "%s" already'
653
' exists.' % to_location)
654
if e.errno == errno.ENOENT:
655
raise BzrCommandError('Parent of "%s" does not exist.' %
659
checkout = bzrdir.BzrDirMetaFormat1().initialize(to_location)
660
bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
661
checkout.create_workingtree(revision_id)
578
664
class cmd_renames(Command):
579
665
"""Show list of renamed files.
749
864
b, file1 = Branch.open_containing(file_list[0])
750
865
b2, file2 = Branch.open_containing(file_list[1])
751
866
if file1 != "" or file2 != "":
867
# FIXME diff those two files. rbc 20051123
752
868
raise BzrCommandError("Files are in different branches")
754
870
if revision is not None:
755
871
if b2 is not None:
756
872
raise BzrCommandError("Can't specify -r with two branches")
757
if len(revision) == 1:
758
return show_diff(b, revision[0], specific_files=file_list,
873
if (len(revision) == 1) or (revision[1].spec is None):
874
return show_diff(tree.branch, revision[0], specific_files=file_list,
759
875
external_diff_options=diff_options)
760
876
elif len(revision) == 2:
761
return show_diff(b, revision[0], specific_files=file_list,
877
return show_diff(tree.branch, revision[0], specific_files=file_list,
762
878
external_diff_options=diff_options,
763
879
revision2=revision[1])
765
881
raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
767
return show_diff(b, None, specific_files=file_list,
768
external_diff_options=diff_options, b2=b2)
884
return show_diff(b, None, specific_files=file_list,
885
external_diff_options=diff_options, b2=b2)
887
return show_diff(tree.branch, None, specific_files=file_list,
888
external_diff_options=diff_options)
771
891
class cmd_deleted(Command):
875
992
"invalid message argument %r" % message
876
993
direction = (forward and 'forward') or 'reverse'
879
b, fp = Branch.open_containing(filename)
998
# find the file id to log:
1000
dir, fp = bzrdir.BzrDir.open_containing(filename)
1001
b = dir.open_branch()
882
inv = b.working_tree().read_working_inventory()
883
except NoWorkingTree:
884
inv = b.get_inventory(b.last_revision())
1005
inv = dir.open_workingtree().inventory
1006
except (errors.NotBranchError, errors.NotLocalUrl):
1007
# either no tree, or is remote.
1008
inv = b.basis_tree().inventory
885
1009
file_id = inv.path2id(fp)
887
file_id = None # points to branch root
889
b, relpath = Branch.open_containing('.')
1012
# FIXME ? log the current subdir only RBC 20060203
1013
dir, relpath = bzrdir.BzrDir.open_containing('.')
1014
b = dir.open_branch()
892
1016
if revision is None:
1118
1249
is found exports to a directory (equivalent to --format=dir).
1120
1251
Root may be the top directory for tar, tgz and tbz2 formats. If none
1121
is given, the top directory will be the root name of the file."""
1122
# TODO: list known exporters
1252
is given, the top directory will be the root name of the file.
1254
Note: export of tree with non-ascii filenames to zip is not supported.
1256
Supported formats Autodetected by extension
1257
----------------- -------------------------
1260
tbz2 .tar.bz2, .tbz2
1123
1264
takes_args = ['dest']
1124
1265
takes_options = ['revision', 'format', 'root']
1125
1266
def run(self, dest, revision=None, format=None, root=None):
1127
b = Branch.open_containing('.')[0]
1268
from bzrlib.export import export
1269
tree = WorkingTree.open_containing(u'.')[0]
1128
1271
if revision is None:
1272
# should be tree.last_revision FIXME
1129
1273
rev_id = b.last_revision()
1131
1275
if len(revision) != 1:
1132
1276
raise BzrError('bzr export --revision takes exactly 1 argument')
1133
1277
rev_id = revision[0].in_history(b).rev_id
1134
t = b.revision_tree(rev_id)
1135
arg_root, ext = os.path.splitext(os.path.basename(dest))
1136
if ext in ('.gz', '.bz2'):
1137
new_root, new_ext = os.path.splitext(arg_root)
1138
if new_ext == '.tar':
1144
if ext in (".tar",):
1146
elif ext in (".tar.gz", ".tgz"):
1148
elif ext in (".tar.bz2", ".tbz2"):
1152
t.export(dest, format, root)
1278
t = b.repository.revision_tree(rev_id)
1280
export(t, dest, format, root)
1281
except errors.NoSuchExportFormat, e:
1282
raise BzrCommandError('Unsupported export format: %s' % e.format)
1155
1285
class cmd_cat(Command):
1216
1356
unchanged=False, strict=False):
1217
1357
from bzrlib.errors import (PointlessCommit, ConflictsInTree,
1218
1358
StrictCommitFailed)
1219
from bzrlib.msgeditor import edit_commit_message
1359
from bzrlib.msgeditor import edit_commit_message, \
1360
make_commit_message_template
1220
1361
from bzrlib.status import show_status
1221
from cStringIO import StringIO
1223
b, selected_list = branch_files(selected_list)
1362
from tempfile import TemporaryFile
1365
# TODO: Need a blackbox test for invoking the external editor; may be
1366
# slightly problematic to run this cross-platform.
1368
# TODO: do more checks that the commit will succeed before
1369
# spending the user's valuable time typing a commit message.
1371
# TODO: if the commit *does* happen to fail, then save the commit
1372
# message to a temporary file where it can be recovered
1373
tree, selected_list = tree_files(selected_list)
1224
1374
if message is None and not file:
1225
catcher = StringIO()
1226
show_status(b, specific_files=selected_list,
1228
message = edit_commit_message(catcher.getvalue())
1375
template = make_commit_message_template(tree, selected_list)
1376
message = edit_commit_message(template)
1230
1377
if message is None:
1231
1378
raise BzrCommandError("please specify a commit message"
1232
1379
" with either --message or --file")
1352
1505
If arguments are given, they are regular expressions that say
1353
1506
which tests should run.
1508
If the global option '--no-plugins' is given, plugins are not loaded
1509
before running the selftests. This has two effects: features provided or
1510
modified by plugins will not be tested, and tests provided by plugins will
1515
bzr --no-plugins selftest -v
1355
1517
# TODO: --list should give a list of all available tests
1519
# NB: this is used from the class without creating an instance, which is
1520
# why it does not have a self parameter.
1521
def get_transport_type(typestring):
1522
"""Parse and return a transport specifier."""
1523
if typestring == "sftp":
1524
from bzrlib.transport.sftp import SFTPAbsoluteServer
1525
return SFTPAbsoluteServer
1526
if typestring == "memory":
1527
from bzrlib.transport.memory import MemoryServer
1529
msg = "No known transport type %s. Supported types are: sftp\n" %\
1531
raise BzrCommandError(msg)
1357
1534
takes_args = ['testspecs*']
1358
takes_options = ['verbose',
1535
takes_options = ['verbose',
1359
1536
Option('one', help='stop when one test fails'),
1360
1537
Option('keep-output',
1361
help='keep output directories when tests fail')
1538
help='keep output directories when tests fail'),
1540
help='Use a different transport by default '
1541
'throughout the test suite.',
1542
type=get_transport_type),
1364
1545
def run(self, testspecs_list=None, verbose=False, one=False,
1546
keep_output=False, transport=None):
1366
1547
import bzrlib.ui
1367
from bzrlib.selftest import selftest
1548
from bzrlib.tests import selftest
1368
1549
# we don't want progress meters from the tests to go to the
1369
1550
# real output; and we don't want log messages cluttering up
1370
1551
# the real logs.
1389
1571
bzrlib.ui.ui_factory = save_ui
1574
def _get_bzr_branch():
1575
"""If bzr is run from a branch, return Branch or None"""
1576
import bzrlib.errors
1577
from bzrlib.branch import Branch
1578
from bzrlib.osutils import abspath
1579
from os.path import dirname
1582
branch = Branch.open(dirname(abspath(dirname(__file__))))
1584
except bzrlib.errors.BzrError:
1392
1588
def show_version():
1393
1589
print "bzr (bazaar-ng) %s" % bzrlib.__version__
1394
1590
# is bzrlib itself in a branch?
1395
bzrrev = bzrlib.get_bzr_revision()
1397
print " (bzr checkout, revision %d {%s})" % bzrrev
1591
branch = _get_bzr_branch()
1593
rh = branch.revision_history()
1595
print " bzr checkout, revision %d" % (revno,)
1596
print " nick: %s" % (branch.nick,)
1598
print " revid: %s" % (rh[-1],)
1398
1599
print bzrlib.__copyright__
1399
1600
print "http://bazaar-ng.org/"
1549
1750
def run(self, file_list=None, merge_type=None, show_base=False,
1550
1751
reprocess=False):
1551
1752
from bzrlib.merge import merge_inner, transform_tree
1552
from bzrlib.merge_core import ApplyMerge3
1753
from bzrlib._merge_core import ApplyMerge3
1553
1754
if merge_type is None:
1554
1755
merge_type = ApplyMerge3
1555
b, file_list = branch_files(file_list)
1756
tree, file_list = tree_files(file_list)
1558
pending_merges = b.working_tree().pending_merges()
1759
pending_merges = tree.pending_merges()
1559
1760
if len(pending_merges) != 1:
1560
1761
raise BzrCommandError("Sorry, remerge only works after normal"
1561
1762
+ " merges. Not cherrypicking or"
1562
1763
+ "multi-merges.")
1563
this_tree = b.working_tree()
1564
base_revision = common_ancestor(b.last_revision(),
1565
pending_merges[0], b)
1566
base_tree = b.revision_tree(base_revision)
1567
other_tree = b.revision_tree(pending_merges[0])
1764
repository = tree.branch.repository
1765
base_revision = common_ancestor(tree.branch.last_revision(),
1766
pending_merges[0], repository)
1767
base_tree = repository.revision_tree(base_revision)
1768
other_tree = repository.revision_tree(pending_merges[0])
1568
1769
interesting_ids = None
1569
1770
if file_list is not None:
1570
1771
interesting_ids = set()
1571
1772
for filename in file_list:
1572
file_id = this_tree.path2id(filename)
1773
file_id = tree.path2id(filename)
1573
1774
interesting_ids.add(file_id)
1574
if this_tree.kind(file_id) != "directory":
1775
if tree.kind(file_id) != "directory":
1577
for name, ie in this_tree.inventory.iter_entries(file_id):
1778
for name, ie in tree.inventory.iter_entries(file_id):
1578
1779
interesting_ids.add(ie.file_id)
1579
transform_tree(this_tree, b.basis_tree(), interesting_ids)
1780
transform_tree(tree, tree.basis_tree(), interesting_ids)
1580
1781
if file_list is None:
1581
restore_files = list(this_tree.iter_conflicts())
1782
restore_files = list(tree.iter_conflicts())
1583
1784
restore_files = file_list
1584
1785
for filename in restore_files:
1586
restore(this_tree.abspath(filename))
1787
restore(tree.abspath(filename))
1587
1788
except NotConflicted:
1589
conflicts = merge_inner(b, other_tree, base_tree,
1790
conflicts = merge_inner(tree.branch, other_tree, base_tree,
1590
1791
interesting_ids = interesting_ids,
1591
1792
other_rev_id=pending_merges[0],
1592
1793
merge_type=merge_type,
1593
1794
show_base=show_base,
1594
1795
reprocess=reprocess)
1597
1798
if conflicts > 0:
1611
1812
aliases = ['merge-revert']
1613
1814
def run(self, revision=None, no_backup=False, file_list=None):
1614
from bzrlib.merge import merge_inner
1615
1815
from bzrlib.commands import parse_spec
1616
1816
if file_list is not None:
1617
1817
if len(file_list) == 0:
1618
1818
raise BzrCommandError("No files specified")
1822
tree, file_list = tree_files(file_list)
1621
1823
if revision is None:
1623
b = Branch.open_containing('.')[0]
1624
rev_id = b.last_revision()
1824
# FIXME should be tree.last_revision
1825
rev_id = tree.branch.last_revision()
1625
1826
elif len(revision) != 1:
1626
1827
raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
1628
b, file_list = branch_files(file_list)
1629
rev_id = revision[0].in_history(b).rev_id
1630
b.working_tree().revert(file_list, b.revision_tree(rev_id),
1829
rev_id = revision[0].in_history(tree.branch).rev_id
1830
tree.revert(file_list, tree.branch.repository.revision_tree(rev_id),
1634
1834
class cmd_assert_fail(Command):
1679
1879
from bzrlib.branch import Branch
1680
1880
from_b = Branch.open(from_branch)
1681
1881
to_b = Branch.open(to_branch)
1686
Fetcher(to_b, from_b)
1882
Fetcher(to_b, from_b)
1693
1885
class cmd_missing(Command):
1694
"""What is missing in this branch relative to other branch.
1696
# TODO: rewrite this in terms of ancestry so that it shows only
1699
takes_args = ['remote?']
1700
aliases = ['mis', 'miss']
1701
# We don't have to add quiet to the list, because
1702
# unknown options are parsed as booleans
1703
takes_options = ['verbose', 'quiet']
1706
def run(self, remote=None, verbose=False, quiet=False):
1707
from bzrlib.errors import BzrCommandError
1708
from bzrlib.missing import show_missing
1710
if verbose and quiet:
1711
raise BzrCommandError('Cannot pass both quiet and verbose')
1713
b = Branch.open_containing('.')[0]
1714
parent = b.get_parent()
1886
"""Show unmerged/unpulled revisions between two branches.
1888
OTHER_BRANCH may be local or remote."""
1889
takes_args = ['other_branch?']
1890
takes_options = [Option('reverse', 'Reverse the order of revisions'),
1892
'Display changes in the local branch only'),
1893
Option('theirs-only',
1894
'Display changes in the remote branch only'),
1902
def run(self, other_branch=None, reverse=False, mine_only=False,
1903
theirs_only=False, long=True, short=False, line=False,
1904
show_ids=False, verbose=False):
1905
from bzrlib.missing import find_unmerged, iter_log_data
1906
from bzrlib.log import log_formatter
1907
local_branch = bzrlib.branch.Branch.open_containing(u".")[0]
1908
parent = local_branch.get_parent()
1909
if other_branch is None:
1910
other_branch = parent
1911
if other_branch is None:
1717
1912
raise BzrCommandError("No missing location known or specified.")
1720
print "Using last location: %s" % parent
1722
elif parent is None:
1723
# We only update parent if it did not exist, missing
1724
# should not change the parent
1725
b.set_parent(remote)
1726
br_remote = Branch.open_containing(remote)[0]
1727
return show_missing(b, br_remote, verbose=verbose, quiet=quiet)
1913
print "Using last location: " + local_branch.get_parent()
1914
remote_branch = bzrlib.branch.Branch.open(other_branch)
1915
local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
1916
log_format = get_log_format(long=long, short=short, line=line)
1917
lf = log_formatter(log_format, sys.stdout,
1919
show_timezone='original')
1920
if reverse is False:
1921
local_extra.reverse()
1922
remote_extra.reverse()
1923
if local_extra and not theirs_only:
1924
print "You have %d extra revision(s):" % len(local_extra)
1925
for data in iter_log_data(local_extra, local_branch.repository,
1928
printed_local = True
1930
printed_local = False
1931
if remote_extra and not mine_only:
1932
if printed_local is True:
1934
print "You are missing %d revision(s):" % len(remote_extra)
1935
for data in iter_log_data(remote_extra, remote_branch.repository,
1938
if not remote_extra and not local_extra:
1940
print "Branches are up to date."
1943
if parent is None and other_branch is not None:
1944
local_branch.set_parent(other_branch)
1730
1948
class cmd_plugins(Command):
1792
2010
@display_command
1793
2011
def run(self, filename, all=False, long=False):
1794
2012
from bzrlib.annotate import annotate_file
1795
b, relpath = Branch.open_containing(filename)
2013
tree, relpath = WorkingTree.open_containing(filename)
2014
branch = tree.branch
1798
tree = WorkingTree(b.base, b)
1799
tree = b.revision_tree(b.last_revision())
1800
2017
file_id = tree.inventory.path2id(relpath)
2018
tree = branch.repository.revision_tree(branch.last_revision())
1801
2019
file_version = tree.inventory[file_id].revision
1802
annotate_file(b, file_version, file_id, long, all, sys.stdout)
2020
annotate_file(branch, file_version, file_id, long, all, sys.stdout)
1807
2025
class cmd_re_sign(Command):
1838
2056
if from_revno is None or to_revno is None:
1839
2057
raise BzrCommandError('Cannot sign a range of non-revision-history revisions')
1840
2058
for revno in range(from_revno, to_revno + 1):
1841
b.sign_revision(b.get_rev_id(revno), gpg_strategy)
2059
b.repository.sign_revision(b.get_rev_id(revno),
1843
2062
raise BzrCommandError('Please supply either one revision, or a range.')
2065
class cmd_uncommit(bzrlib.commands.Command):
2066
"""Remove the last committed revision.
2068
By supplying the --all flag, it will not only remove the entry
2069
from revision_history, but also remove all of the entries in the
2072
--verbose will print out what is being removed.
2073
--dry-run will go through all the motions, but not actually
2076
In the future, uncommit will create a changeset, which can then
2079
TODO: jam 20060108 Add an option to allow uncommit to remove unreferenced
2080
information in 'branch-as-repostory' branches.
2081
TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
2082
information in shared branches as well.
2084
takes_options = ['verbose', 'revision',
2085
Option('dry-run', help='Don\'t actually make changes'),
2086
Option('force', help='Say yes to all questions.')]
2087
takes_args = ['location?']
2090
def run(self, location=None,
2091
dry_run=False, verbose=False,
2092
revision=None, force=False):
2093
from bzrlib.branch import Branch
2094
from bzrlib.log import log_formatter
2096
from bzrlib.uncommit import uncommit
2098
if location is None:
2100
b, relpath = Branch.open_containing(location)
2102
if revision is None:
2104
rev_id = b.last_revision()
2106
revno, rev_id = revision[0].in_history(b)
2108
print 'No revisions to uncommit.'
2110
for r in range(revno, b.revno()+1):
2111
rev_id = b.get_rev_id(r)
2112
lf = log_formatter('short', to_file=sys.stdout,show_timezone='original')
2113
lf.show(r, b.repository.get_revision(rev_id), None)
2116
print 'Dry-run, pretending to remove the above revisions.'
2118
val = raw_input('Press <enter> to continue')
2120
print 'The above revision(s) will be removed.'
2122
val = raw_input('Are you sure [y/N]? ')
2123
if val.lower() not in ('y', 'yes'):
2127
uncommit(b, dry_run=dry_run, verbose=verbose,
2131
def merge(other_revision, base_revision,
2132
check_clean=True, ignore_zero=False,
2133
this_dir=None, backup_files=False, merge_type=ApplyMerge3,
2134
file_list=None, show_base=False, reprocess=False):
2135
"""Merge changes into a tree.
2138
list(path, revno) Base for three-way merge.
2139
If [None, None] then a base will be automatically determined.
2141
list(path, revno) Other revision for three-way merge.
2143
Directory to merge changes into; '.' by default.
2145
If true, this_dir must have no uncommitted changes before the
2147
ignore_zero - If true, suppress the "zero conflicts" message when
2148
there are no conflicts; should be set when doing something we expect
2149
to complete perfectly.
2150
file_list - If supplied, merge only changes to selected files.
2152
All available ancestors of other_revision and base_revision are
2153
automatically pulled into the branch.
2155
The revno may be -1 to indicate the last revision on the branch, which is
2158
This function is intended for use from the command line; programmatic
2159
clients might prefer to call merge.merge_inner(), which has less magic
2162
from bzrlib.merge import Merger, _MergeConflictHandler
2163
if this_dir is None:
2165
this_tree = WorkingTree.open_containing(this_dir)[0]
2166
if show_base and not merge_type is ApplyMerge3:
2167
raise BzrCommandError("Show-base is not supported for this merge"
2168
" type. %s" % merge_type)
2169
if reprocess and not merge_type is ApplyMerge3:
2170
raise BzrCommandError("Reprocess is not supported for this merge"
2171
" type. %s" % merge_type)
2172
if reprocess and show_base:
2173
raise BzrCommandError("Cannot reprocess and show base.")
2174
merger = Merger(this_tree.branch, this_tree=this_tree)
2175
merger.check_basis(check_clean)
2176
merger.set_other(other_revision)
2177
merger.set_base(base_revision)
2178
if merger.base_rev_id == merger.other_rev_id:
2179
note('Nothing to do.')
2181
merger.backup_files = backup_files
2182
merger.merge_type = merge_type
2183
merger.set_interesting_files(file_list)
2184
merger.show_base = show_base
2185
merger.reprocess = reprocess
2186
merger.conflict_handler = _MergeConflictHandler(merger.this_tree,
2189
ignore_zero=ignore_zero)
2190
conflicts = merger.do_merge()
2191
merger.set_pending()
1846
2195
# these get imported and then picked up by the scan for cmd_*
1847
2196
# TODO: Some more consistent way to split command definitions across files;
1848
2197
# we do need to load at least some information about them to know of