15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
# TODO: Split the command framework away from the actual commands.
20
# TODO: probably should say which arguments are candidates for glob
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.
22
34
from bzrlib.trace import mutter, note, log_error, warning
136
148
raise BzrCommandError(msg)
151
def get_merge_type(typestring):
152
"""Attempt to find the merge class/factory associated with a string."""
153
from merge import merge_types
155
return merge_types[typestring][0]
157
templ = '%s%%7s: %%s' % (' '*12)
158
lines = [templ % (f[0], f[1][1]) for f in merge_types.iteritems()]
159
type_list = '\n'.join(lines)
160
msg = "No known merge type %s. Supported types are:\n%s" %\
161
(typestring, type_list)
162
raise BzrCommandError(msg)
140
166
def _get_cmd_dict(plugins_override=True):
237
263
class ExternalCommand(Command):
238
264
"""Class to wrap external commands.
240
We cheat a little here, when get_cmd_class() calls us we actually give it back
241
an object we construct that has the appropriate path, help, options etc for the
244
When run_bzr() tries to instantiate that 'class' it gets caught by the __call__
245
method, which we override to call the Command.__init__ method. That then calls
246
our run method which is pretty straight forward.
248
The only wrinkle is that we have to map bzr's dictionary of options and arguments
249
back into command line options and arguments for the script.
266
We cheat a little here, when get_cmd_class() calls us we actually
267
give it back an object we construct that has the appropriate path,
268
help, options etc for the specified command.
270
When run_bzr() tries to instantiate that 'class' it gets caught by
271
the __call__ method, which we override to call the Command.__init__
272
method. That then calls our run method which is pretty straight
275
The only wrinkle is that we have to map bzr's dictionary of options
276
and arguments back into command line options and arguments for the
252
280
def find_command(cls, cmd):
560
class cmd_mv(Command):
561
"""Move or rename a file.
564
bzr mv OLDNAME NEWNAME
565
bzr mv SOURCE... DESTINATION
567
If the last argument is a versioned directory, all the other names
568
are moved into it. Otherwise, there must be exactly two arguments
569
and the file is changed to a new name, which must not already exist.
571
Files cannot be moved between branches.
573
takes_args = ['names*']
574
def run(self, names_list):
575
if len(names_list) < 2:
576
raise BzrCommandError("missing file argument")
577
b = find_branch(names_list[0])
579
rel_names = [b.relpath(x) for x in names_list]
581
if os.path.isdir(names_list[-1]):
582
# move into existing directory
583
b.move(rel_names[:-1], rel_names[-1])
585
if len(names_list) != 2:
586
raise BzrCommandError('to mv multiple files the destination '
587
'must be a versioned directory')
588
b.move(rel_names[0], rel_names[1])
533
593
class cmd_pull(Command):
601
661
takes_args = ['from_location', 'to_location?']
602
662
takes_options = ['revision']
663
aliases = ['get', 'clone']
604
665
def run(self, from_location, to_location=None, revision=None):
606
667
from bzrlib.merge import merge
607
from bzrlib.branch import DivergedBranches, NoSuchRevision, \
668
from bzrlib.branch import DivergedBranches, \
608
669
find_cached_branch, Branch
609
670
from shutil import rmtree
610
671
from meta_store import CachedStore
651
712
revno, rev_id = br_from.get_revision_info(revision[0])
653
714
br_to.update_revisions(br_from, stop_revision=revno)
654
except NoSuchRevision:
715
except bzrlib.errors.NoSuchRevision:
655
716
rmtree(to_location)
656
717
msg = "The branch %s has no revision %d." % (from_location,
658
719
raise BzrCommandError(msg)
660
721
merge((to_location, -1), (to_location, 0), this_dir=to_location,
661
722
check_clean=False, ignore_zero=True)
662
723
from_location = pull_loc(br_from)
832
896
b = find_branch('.')
834
# TODO: Make show_diff support taking 2 arguments
836
898
if revision is not None:
837
if len(revision) != 1:
838
raise BzrCommandError('bzr diff --revision takes exactly one revision identifier')
839
base_rev = revision[0]
841
show_diff(b, base_rev, specific_files=file_list,
842
external_diff_options=diff_options)
899
if len(revision) == 1:
900
show_diff(b, revision[0], specific_files=file_list,
901
external_diff_options=diff_options)
902
elif len(revision) == 2:
903
show_diff(b, revision[0], specific_files=file_list,
904
external_diff_options=diff_options,
905
revision2=revision[1])
907
raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
909
show_diff(b, None, specific_files=file_list,
910
external_diff_options=diff_options)
929
996
takes_args = ['filename?']
930
takes_options = ['forward', 'timezone', 'verbose', 'show-ids', 'revision','long', 'message']
997
takes_options = ['forward', 'timezone', 'verbose', 'show-ids', 'revision',
998
'long', 'message', 'short',]
932
1000
def run(self, filename=None, timezone='original',
1479
class cmd_find_merge_base(Command):
1480
"""Find and print a base revision for merging two branches.
1482
TODO: Options to specify revisions on either side, as if
1483
merging only part of the history.
1485
takes_args = ['branch', 'other']
1488
def run(self, branch, other):
1489
branch1 = find_branch(branch)
1490
branch2 = find_branch(other)
1492
base_revno, base_revid = branch1.common_ancestor(branch2)
1494
if base_revno is None:
1495
raise bzrlib.errors.UnrelatedBranches()
1497
print 'merge base is revision %s' % base_revid
1498
print ' r%-6d in %s' % (base_revno, branch)
1500
other_revno = branch2.revision_id_to_revno(base_revid)
1502
print ' r%-6d in %s' % (other_revno, other)
1387
1506
class cmd_merge(Command):
1388
"""Perform a three-way merge of trees.
1390
The SPEC parameters are working tree or revision specifiers. Working trees
1391
are specified using standard paths or urls. No component of a directory
1392
path may begin with '@'.
1394
Working tree examples: '.', '..', 'foo@', but NOT 'foo/@bar'
1396
Revisions are specified using a dirname/@revno pair, where dirname is the
1397
branch directory and revno is the revision within that branch. If no revno
1398
is specified, the latest revision is used.
1400
Revision examples: './@127', 'foo/@', '../@1'
1402
The OTHER_SPEC parameter is required. If the BASE_SPEC parameter is
1403
not supplied, the common ancestor of OTHER_SPEC the current branch is used
1507
"""Perform a three-way merge.
1509
The branch is the branch you will merge from. By default, it will merge
1510
the latest revision. If you specify a revision, that revision will be
1511
merged. If you specify two revisions, the first will be used as a BASE,
1512
and the second one as OTHER. Revision numbers are always relative to the
1517
To merge the latest revision from bzr.dev
1518
bzr merge ../bzr.dev
1520
To merge changes up to and including revision 82 from bzr.dev
1521
bzr merge -r 82 ../bzr.dev
1523
To merge the changes introduced by 82, without previous changes:
1524
bzr merge -r 81..82 ../bzr.dev
1406
1526
merge refuses to run if there are any uncommitted changes, unless
1407
1527
--force is given.
1409
takes_args = ['other_spec', 'base_spec?']
1410
takes_options = ['force', 'merge-type']
1529
takes_args = ['branch?']
1530
takes_options = ['revision', 'force', 'merge-type']
1412
def run(self, other_spec, base_spec=None, force=False, merge_type=None):
1532
def run(self, branch='.', revision=None, force=False,
1413
1534
from bzrlib.merge import merge
1414
1535
from bzrlib.merge_core import ApplyMerge3
1415
1536
if merge_type is None:
1416
1537
merge_type = ApplyMerge3
1417
merge(parse_spec(other_spec), parse_spec(base_spec),
1418
check_clean=(not force), merge_type=merge_type)
1539
if revision is None or len(revision) < 1:
1541
other = (branch, -1)
1543
if len(revision) == 1:
1544
other = (branch, revision[0])
1547
assert len(revision) == 2
1548
if None in revision:
1549
raise BzrCommandError(
1550
"Merge doesn't permit that revision specifier.")
1551
base = (branch, revision[0])
1552
other = (branch, revision[1])
1554
merge(other, base, check_clean=(not force), merge_type=merge_type)
1421
1557
class cmd_revert(Command):
1456
1592
"""Show help on a command or other topic.
1458
1594
For a list of all available commands, say 'bzr help commands'."""
1595
takes_options = ['long']
1459
1596
takes_args = ['topic?']
1460
1597
aliases = ['?']
1462
def run(self, topic=None):
1599
def run(self, topic=None, long=False):
1601
if topic is None and long:
1464
1603
help.help(topic)
1606
class cmd_shell_complete(Command):
1607
"""Show appropriate completions for context.
1609
For a list of all available commands, say 'bzr shell-complete'."""
1610
takes_args = ['context?']
1614
def run(self, context=None):
1615
import shellcomplete
1616
shellcomplete.shellcomplete(context)
1619
class cmd_missing(Command):
1620
"""What is missing in this branch relative to other branch.
1622
takes_args = ['remote?']
1623
aliases = ['mis', 'miss']
1624
# We don't have to add quiet to the list, because
1625
# unknown options are parsed as booleans
1626
takes_options = ['verbose', 'quiet']
1628
def run(self, remote=None, verbose=False, quiet=False):
1629
from bzrlib.branch import find_branch, DivergedBranches
1630
from bzrlib.errors import BzrCommandError
1631
from bzrlib.missing import get_parent, show_missing
1633
if verbose and quiet:
1634
raise BzrCommandError('Cannot pass both quiet and verbose')
1636
b = find_branch('.')
1637
parent = get_parent(b)
1640
raise BzrCommandError("No missing location known or specified.")
1643
print "Using last location: %s" % parent
1645
elif parent is None:
1646
# We only update x-pull if it did not exist, missing should not change the parent
1647
b.controlfile('x-pull', 'wb').write(remote + '\n')
1648
br_remote = find_branch(remote)
1650
return show_missing(b, br_remote, verbose=verbose, quiet=quiet)
1469
1654
class cmd_plugins(Command):
1667
def _parse_master_args(argv):
1668
"""Parse the arguments that always go with the original command.
1669
These are things like bzr --no-plugins, etc.
1671
There are now 2 types of option flags. Ones that come *before* the command,
1672
and ones that come *after* the command.
1673
Ones coming *before* the command are applied against all possible commands.
1674
And are generally applied before plugins are loaded.
1676
The current list are:
1677
--builtin Allow plugins to load, but don't let them override builtin commands,
1678
they will still be allowed if they do not override a builtin.
1679
--no-plugins Don't load any plugins. This lets you get back to official source
1681
--profile Enable the hotspot profile before running the command.
1682
For backwards compatibility, this is also a non-master option.
1683
--version Spit out the version of bzr that is running and exit.
1684
This is also a non-master option.
1685
--help Run help and exit, also a non-master option (I think that should stay, though)
1687
>>> argv, opts = _parse_master_args(['--test'])
1688
Traceback (most recent call last):
1690
BzrCommandError: Invalid master option: 'test'
1691
>>> argv, opts = _parse_master_args(['--version', 'command'])
1694
>>> print opts['version']
1696
>>> argv, opts = _parse_master_args(['--profile', 'command', '--more-options'])
1698
['command', '--more-options']
1699
>>> print opts['profile']
1701
>>> argv, opts = _parse_master_args(['--no-plugins', 'command'])
1704
>>> print opts['no-plugins']
1706
>>> print opts['profile']
1708
>>> argv, opts = _parse_master_args(['command', '--profile'])
1710
['command', '--profile']
1711
>>> print opts['profile']
1714
master_opts = {'builtin':False,
1722
if arg[:2] != '--': # at the first non-option, we return the rest
1724
arg = arg[2:] # Remove '--'
1725
if arg not in master_opts:
1726
# We could say that this is not an error, that we should
1727
# just let it be handled by the main section instead
1728
raise BzrCommandError('Invalid master option: %r' % arg)
1729
argv.pop(0) # We are consuming this entry
1730
master_opts[arg] = True
1731
return argv, master_opts
1735
1854
def run_bzr(argv):
1736
1855
"""Execute a command.
1739
1858
logging and error handling.
1742
The command-line arguments, without the program name.
1861
The command-line arguments, without the program name from argv[0]
1744
1863
Returns a command status or raises an exception.
1865
Special master options: these must come before the command because
1866
they control how the command is interpreted.
1869
Do not load plugin modules at all
1872
Only use builtin commands. (Plugins are still allowed to change
1876
Run under the Python profiler.
1746
1879
argv = [a.decode(bzrlib.user_encoding) for a in argv]
1748
# some options like --builtin and --no-plugins have special effects
1749
argv, master_opts = _parse_master_args(argv)
1750
if not master_opts['no-plugins']:
1881
opt_profile = opt_no_plugins = opt_builtin = False
1883
# --no-plugins is handled specially at a very early stage. We need
1884
# to load plugins before doing other command parsing so that they
1885
# can override commands, but this needs to happen first.
1888
if a == '--profile':
1890
elif a == '--no-plugins':
1891
opt_no_plugins = True
1892
elif a == '--builtin':
1898
if not opt_no_plugins:
1751
1899
from bzrlib.plugin import load_plugins
1754
1902
args, opts = parse_args(argv)
1756
if master_opts.get('help') or 'help' in opts:
1757
1905
from bzrlib.help import help
1768
if args and args[0] == 'builtin':
1769
include_plugins=False
1917
from bzrlib.help import help
1773
cmd = str(args.pop(0))
1775
print >>sys.stderr, "please try 'bzr help' for help"
1778
plugins_override = not (master_opts['builtin'])
1779
canonical_cmd, cmd_class = get_cmd_class(cmd, plugins_override=plugins_override)
1781
profile = master_opts['profile']
1782
# For backwards compatibility, I would rather stick with --profile being a
1783
# master/global option
1784
if 'profile' in opts:
1921
cmd = str(args.pop(0))
1923
canonical_cmd, cmd_class = \
1924
get_cmd_class(cmd, plugins_override=not opt_builtin)
1788
1926
# check options are reasonable
1789
1927
allowed = cmd_class.takes_options
1823
1961
return cmd_class(cmdopts, cmdargs).status
1826
def _report_exception(summary, quiet=False):
1828
log_error('bzr: ' + summary)
1829
bzrlib.trace.log_exception()
1832
tb = sys.exc_info()[2]
1833
exinfo = traceback.extract_tb(tb)
1835
sys.stderr.write(' at %s:%d in %s()\n' % exinfo[-1][:3])
1836
sys.stderr.write(' see ~/.bzr.log for debug information\n')
1840
1964
def main(argv):
1842
bzrlib.trace.open_tracefile(argv)
1967
bzrlib.trace.log_startup(argv)
1969
bzrlib.ui.ui_factory = bzrlib.ui.TextUIFactory()
1847
return run_bzr(argv[1:])
1849
# do this here inside the exception wrappers to catch EPIPE
1852
quiet = isinstance(e, (BzrCommandError))
1853
_report_exception('error: ' + e.args[0], quiet=quiet)
1856
# some explanation or hints
1859
except AssertionError, e:
1860
msg = 'assertion failed'
1862
msg += ': ' + str(e)
1863
_report_exception(msg)
1865
except KeyboardInterrupt, e:
1866
_report_exception('interrupted', quiet=True)
1868
except Exception, e:
1871
if (isinstance(e, IOError)
1872
and hasattr(e, 'errno')
1873
and e.errno == errno.EPIPE):
1877
msg = str(e).rstrip('\n')
1878
_report_exception(msg, quiet)
1881
bzrlib.trace.close_trace()
1973
return run_bzr(argv[1:])
1975
# do this here inside the exception wrappers to catch EPIPE
1977
except BzrCommandError, e:
1978
# command line syntax error, etc
1982
bzrlib.trace.log_exception()
1984
except AssertionError, e:
1985
bzrlib.trace.log_exception('assertion failed: ' + str(e))
1987
except KeyboardInterrupt, e:
1988
bzrlib.trace.note('interrupted')
1990
except Exception, e:
1992
if (isinstance(e, IOError)
1993
and hasattr(e, 'errno')
1994
and e.errno == errno.EPIPE):
1995
bzrlib.trace.note('broken pipe')
1998
bzrlib.trace.log_exception()
1884
2002
if __name__ == '__main__':