20
20
# TODO: probably should say which arguments are candidates for glob
21
21
# expansion on windows and do that at the command level.
23
# TODO: Help messages for options.
25
# TODO: Define arguments by objects, rather than just using names.
26
# Those objects can specify the expected type of the argument, which
27
# would help with validation and shell completion.
27
35
from bzrlib.trace import mutter, note, log_error, warning
28
36
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError
29
37
from bzrlib.branch import find_branch
141
149
raise BzrCommandError(msg)
152
def get_merge_type(typestring):
153
"""Attempt to find the merge class/factory associated with a string."""
154
from merge import merge_types
156
return merge_types[typestring][0]
158
templ = '%s%%7s: %%s' % (' '*12)
159
lines = [templ % (f[0], f[1][1]) for f in merge_types.iteritems()]
160
type_list = '\n'.join(lines)
161
msg = "No known merge type %s. Supported types are:\n%s" %\
162
(typestring, type_list)
163
raise BzrCommandError(msg)
145
167
def _get_cmd_dict(plugins_override=True):
872
901
b = find_branch('.')
874
# TODO: Make show_diff support taking 2 arguments
876
903
if revision is not None:
877
if len(revision) != 1:
878
raise BzrCommandError('bzr diff --revision takes exactly one revision identifier')
879
base_rev = revision[0]
881
show_diff(b, base_rev, specific_files=file_list,
882
external_diff_options=diff_options)
904
if len(revision) == 1:
905
show_diff(b, revision[0], specific_files=file_list,
906
external_diff_options=diff_options)
907
elif len(revision) == 2:
908
show_diff(b, revision[0], specific_files=file_list,
909
external_diff_options=diff_options,
910
revision2=revision[1])
912
raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
914
show_diff(b, None, specific_files=file_list,
915
external_diff_options=diff_options)
969
1001
takes_args = ['filename?']
970
takes_options = ['forward', 'timezone', 'verbose', 'show-ids', 'revision','long', 'message']
1002
takes_options = ['forward', 'timezone', 'verbose', 'show-ids', 'revision',
1003
'long', 'message', 'short',]
972
1005
def run(self, filename=None, timezone='original',
1371
1410
takes_options = ['verbose']
1372
1411
def run(self, verbose=False):
1373
1413
from bzrlib.selftest import selftest
1374
return int(not selftest(verbose=verbose))
1415
# we don't want progress meters from the tests to go to the
1416
# real output; and we don't want log messages cluttering up
1419
save_ui = bzrlib.ui.ui_factory
1420
bzrlib.trace.info('running tests...')
1422
bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
1423
result = selftest(verbose=verbose)
1425
bzrlib.trace.info('tests passed')
1427
bzrlib.trace.info('tests failed')
1428
return int(not result)
1430
bzrlib.ui.ui_factory = save_ui
1377
1433
class cmd_version(Command):
1491
class cmd_find_merge_base(Command):
1492
"""Find and print a base revision for merging two branches.
1494
TODO: Options to specify revisions on either side, as if
1495
merging only part of the history.
1497
takes_args = ['branch', 'other']
1500
def run(self, branch, other):
1501
branch1 = find_branch(branch)
1502
branch2 = find_branch(other)
1504
base_revno, base_revid = branch1.common_ancestor(branch2)
1506
if base_revno is None:
1507
raise bzrlib.errors.UnrelatedBranches()
1509
print 'merge base is revision %s' % base_revid
1510
print ' r%-6d in %s' % (base_revno, branch)
1512
other_revno = branch2.revision_id_to_revno(base_revid)
1514
print ' r%-6d in %s' % (other_revno, other)
1435
1518
class cmd_merge(Command):
1436
"""Perform a three-way merge of trees.
1438
The SPEC parameters are working tree or revision specifiers. Working trees
1439
are specified using standard paths or urls. No component of a directory
1440
path may begin with '@'.
1442
Working tree examples: '.', '..', 'foo@', but NOT 'foo/@bar'
1444
Revisions are specified using a dirname/@revno pair, where dirname is the
1445
branch directory and revno is the revision within that branch. If no revno
1446
is specified, the latest revision is used.
1448
Revision examples: './@127', 'foo/@', '../@1'
1450
The OTHER_SPEC parameter is required. If the BASE_SPEC parameter is
1451
not supplied, the common ancestor of OTHER_SPEC the current branch is used
1519
"""Perform a three-way merge.
1521
The branch is the branch you will merge from. By default, it will merge
1522
the latest revision. If you specify a revision, that revision will be
1523
merged. If you specify two revisions, the first will be used as a BASE,
1524
and the second one as OTHER. Revision numbers are always relative to the
1529
To merge the latest revision from bzr.dev
1530
bzr merge ../bzr.dev
1532
To merge changes up to and including revision 82 from bzr.dev
1533
bzr merge -r 82 ../bzr.dev
1535
To merge the changes introduced by 82, without previous changes:
1536
bzr merge -r 81..82 ../bzr.dev
1454
1538
merge refuses to run if there are any uncommitted changes, unless
1455
1539
--force is given.
1457
takes_args = ['other_spec', 'base_spec?']
1458
takes_options = ['force', 'merge-type']
1541
takes_args = ['branch?']
1542
takes_options = ['revision', 'force', 'merge-type']
1460
def run(self, other_spec, base_spec=None, force=False, merge_type=None):
1544
def run(self, branch='.', revision=None, force=False,
1461
1546
from bzrlib.merge import merge
1462
1547
from bzrlib.merge_core import ApplyMerge3
1463
1548
if merge_type is None:
1464
1549
merge_type = ApplyMerge3
1465
merge(parse_spec(other_spec), parse_spec(base_spec),
1466
check_clean=(not force), merge_type=merge_type)
1551
if revision is None or len(revision) < 1:
1553
other = (branch, -1)
1555
if len(revision) == 1:
1556
other = (branch, revision[0])
1559
assert len(revision) == 2
1560
if None in revision:
1561
raise BzrCommandError(
1562
"Merge doesn't permit that revision specifier.")
1563
base = (branch, revision[0])
1564
other = (branch, revision[1])
1566
merge(other, base, check_clean=(not force), merge_type=merge_type)
1469
1569
class cmd_revert(Command):
1504
1604
"""Show help on a command or other topic.
1506
1606
For a list of all available commands, say 'bzr help commands'."""
1607
takes_options = ['long']
1507
1608
takes_args = ['topic?']
1508
1609
aliases = ['?']
1510
def run(self, topic=None):
1611
def run(self, topic=None, long=False):
1613
if topic is None and long:
1512
1615
help.help(topic)
1618
class cmd_shell_complete(Command):
1619
"""Show appropriate completions for context.
1621
For a list of all available commands, say 'bzr shell-complete'."""
1622
takes_args = ['context?']
1626
def run(self, context=None):
1627
import shellcomplete
1628
shellcomplete.shellcomplete(context)
1631
class cmd_missing(Command):
1632
"""What is missing in this branch relative to other branch.
1634
takes_args = ['remote?']
1635
aliases = ['mis', 'miss']
1636
# We don't have to add quiet to the list, because
1637
# unknown options are parsed as booleans
1638
takes_options = ['verbose', 'quiet']
1640
def run(self, remote=None, verbose=False, quiet=False):
1641
from bzrlib.branch import find_branch, DivergedBranches
1642
from bzrlib.errors import BzrCommandError
1643
from bzrlib.missing import get_parent, show_missing
1645
if verbose and quiet:
1646
raise BzrCommandError('Cannot pass both quiet and verbose')
1648
b = find_branch('.')
1649
parent = get_parent(b)
1652
raise BzrCommandError("No missing location known or specified.")
1655
print "Using last location: %s" % parent
1657
elif parent is None:
1658
# We only update x-pull if it did not exist, missing should not change the parent
1659
b.controlfile('x-pull', 'wb').write(remote + '\n')
1660
br_remote = find_branch(remote)
1662
return show_missing(b, br_remote, verbose=verbose, quiet=quiet)
1517
1666
class cmd_plugins(Command):
1822
1973
return cmd_class(cmdopts, cmdargs).status
1825
def _report_exception(summary, quiet=False):
1828
log_error('bzr: ' + summary)
1829
bzrlib.trace.log_exception()
1831
if os.environ.get('BZR_DEBUG'):
1832
traceback.print_exc()
1835
sys.stderr.write('\n')
1836
tb = sys.exc_info()[2]
1837
exinfo = traceback.extract_tb(tb)
1839
sys.stderr.write(' at %s:%d in %s()\n' % exinfo[-1][:3])
1840
sys.stderr.write(' see ~/.bzr.log for debug information\n')
1844
1976
def main(argv):
1846
bzrlib.trace.open_tracefile(argv)
1979
bzrlib.trace.log_startup(argv)
1981
bzrlib.ui.ui_factory = bzrlib.ui.TextUIFactory()
1851
return run_bzr(argv[1:])
1853
# do this here inside the exception wrappers to catch EPIPE
1856
quiet = isinstance(e, (BzrCommandError))
1857
_report_exception('error: ' + str(e), quiet=quiet)
1860
# some explanation or hints
1863
except AssertionError, e:
1864
msg = 'assertion failed'
1866
msg += ': ' + str(e)
1867
_report_exception(msg)
1869
except KeyboardInterrupt, e:
1870
_report_exception('interrupted', quiet=True)
1872
except Exception, e:
1875
if (isinstance(e, IOError)
1876
and hasattr(e, 'errno')
1877
and e.errno == errno.EPIPE):
1881
msg = str(e).rstrip('\n')
1882
_report_exception(msg, quiet)
1885
bzrlib.trace.close_trace()
1985
return run_bzr(argv[1:])
1987
# do this here inside the exception wrappers to catch EPIPE
1989
except BzrCommandError, e:
1990
# command line syntax error, etc
1994
bzrlib.trace.log_exception()
1996
except AssertionError, e:
1997
bzrlib.trace.log_exception('assertion failed: ' + str(e))
1999
except KeyboardInterrupt, e:
2000
bzrlib.trace.note('interrupted')
2002
except Exception, e:
2004
if (isinstance(e, IOError)
2005
and hasattr(e, 'errno')
2006
and e.errno == errno.EPIPE):
2007
bzrlib.trace.note('broken pipe')
2010
bzrlib.trace.log_exception()
1888
2014
if __name__ == '__main__':