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.
30
# TODO: Help messages for options.
32
# TODO: Define arguments by objects, rather than just using names.
33
# Those objects can specify the expected type of the argument, which
34
# would help with validation and shell completion.
22
42
from bzrlib.trace import mutter, note, log_error, warning
23
43
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError
24
44
from bzrlib.branch import find_branch
136
156
raise BzrCommandError(msg)
159
def get_merge_type(typestring):
160
"""Attempt to find the merge class/factory associated with a string."""
161
from merge import merge_types
163
return merge_types[typestring][0]
165
templ = '%s%%7s: %%s' % (' '*12)
166
lines = [templ % (f[0], f[1][1]) for f in merge_types.iteritems()]
167
type_list = '\n'.join(lines)
168
msg = "No known merge type %s. Supported types are:\n%s" %\
169
(typestring, type_list)
170
raise BzrCommandError(msg)
140
174
def _get_cmd_dict(plugins_override=True):
237
271
class ExternalCommand(Command):
238
272
"""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.
274
We cheat a little here, when get_cmd_class() calls us we actually
275
give it back an object we construct that has the appropriate path,
276
help, options etc for the specified command.
278
When run_bzr() tries to instantiate that 'class' it gets caught by
279
the __call__ method, which we override to call the Command.__init__
280
method. That then calls our run method which is pretty straight
283
The only wrinkle is that we have to map bzr's dictionary of options
284
and arguments back into command line options and arguments for the
252
288
def find_command(cls, cmd):
438
474
takes_options = ['verbose', 'no-recurse']
440
476
def run(self, file_list, verbose=False, no_recurse=False):
441
from bzrlib.add import smart_add
442
smart_add(file_list, verbose, not no_recurse)
477
from bzrlib.add import smart_add, _PrintAddCallback
478
smart_add(file_list, verbose, not no_recurse,
479
callback=_PrintAddCallback)
569
class cmd_mv(Command):
570
"""Move or rename a file.
573
bzr mv OLDNAME NEWNAME
574
bzr mv SOURCE... DESTINATION
576
If the last argument is a versioned directory, all the other names
577
are moved into it. Otherwise, there must be exactly two arguments
578
and the file is changed to a new name, which must not already exist.
580
Files cannot be moved between branches.
582
takes_args = ['names*']
583
def run(self, names_list):
584
if len(names_list) < 2:
585
raise BzrCommandError("missing file argument")
586
b = find_branch(names_list[0])
588
rel_names = [b.relpath(x) for x in names_list]
590
if os.path.isdir(names_list[-1]):
591
# move into existing directory
592
b.move(rel_names[:-1], rel_names[-1])
594
if len(names_list) != 2:
595
raise BzrCommandError('to mv multiple files the destination '
596
'must be a versioned directory')
597
b.move(rel_names[0], rel_names[1])
533
602
class cmd_pull(Command):
601
671
takes_args = ['from_location', 'to_location?']
602
672
takes_options = ['revision']
673
aliases = ['get', 'clone']
604
675
def run(self, from_location, to_location=None, revision=None):
676
from bzrlib.branch import copy_branch, find_cached_branch
606
from bzrlib.merge import merge
607
from bzrlib.branch import DivergedBranches, NoSuchRevision, \
608
find_cached_branch, Branch
609
679
from shutil import rmtree
610
from meta_store import CachedStore
612
680
cache_root = tempfile.mkdtemp()
616
elif len(revision) > 1:
617
raise BzrCommandError('bzr branch --revision takes exactly 1 revision value')
684
elif len(revision) > 1:
685
raise BzrCommandError(
686
'bzr branch --revision takes exactly 1 revision value')
621
688
br_from = find_cached_branch(from_location, cache_root)
622
689
except OSError, e:
643
br_to = Branch(to_location, init=True)
645
br_to.set_root_id(br_from.get_root_id())
648
if revision[0] is None:
649
revno = br_from.revno()
651
revno, rev_id = br_from.get_revision_info(revision[0])
653
br_to.update_revisions(br_from, stop_revision=revno)
654
except NoSuchRevision:
656
msg = "The branch %s has no revision %d." % (from_location,
658
raise BzrCommandError(msg)
660
merge((to_location, -1), (to_location, 0), this_dir=to_location,
661
check_clean=False, ignore_zero=True)
662
from_location = pull_loc(br_from)
663
br_to.controlfile("x-pull", "wb").write(from_location + "\n")
709
copy_branch(br_from, to_location, revision[0])
710
except bzrlib.errors.NoSuchRevision:
712
msg = "The branch %s has no revision %d." % (from_location, revision[0])
713
raise BzrCommandError(msg)
665
715
rmtree(cache_root)
668
def pull_loc(branch):
669
# TODO: Should perhaps just make attribute be 'base' in
670
# RemoteBranch and Branch?
671
if hasattr(branch, "baseurl"):
672
return branch.baseurl
678
718
class cmd_renames(Command):
679
719
"""Show list of renamed files.
832
875
b = find_branch('.')
834
# TODO: Make show_diff support taking 2 arguments
836
877
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)
878
if len(revision) == 1:
879
show_diff(b, revision[0], specific_files=file_list,
880
external_diff_options=diff_options)
881
elif len(revision) == 2:
882
show_diff(b, revision[0], specific_files=file_list,
883
external_diff_options=diff_options,
884
revision2=revision[1])
886
raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
888
show_diff(b, None, specific_files=file_list,
889
external_diff_options=diff_options)
929
975
takes_args = ['filename?']
930
takes_options = ['forward', 'timezone', 'verbose', 'show-ids', 'revision','long', 'message']
976
takes_options = ['forward', 'timezone', 'verbose', 'show-ids', 'revision',
977
'long', 'message', 'short',]
932
979
def run(self, filename=None, timezone='original',
1311
1367
takes_options = ['email']
1313
1369
def run(self, email=False):
1371
b = bzrlib.branch.find_branch('.')
1315
print bzrlib.osutils.user_email()
1376
print bzrlib.osutils.user_email(b)
1317
print bzrlib.osutils.username()
1378
print bzrlib.osutils.username(b)
1320
1381
class cmd_selftest(Command):
1321
1382
"""Run internal test suite"""
1323
takes_options = ['verbose']
1324
def run(self, verbose=False):
1384
takes_options = ['verbose', 'pattern']
1385
def run(self, verbose=False, pattern=".*"):
1325
1387
from bzrlib.selftest import selftest
1326
return int(not selftest(verbose=verbose))
1388
# we don't want progress meters from the tests to go to the
1389
# real output; and we don't want log messages cluttering up
1391
save_ui = bzrlib.ui.ui_factory
1392
bzrlib.trace.info('running tests...')
1393
bzrlib.trace.disable_default_logging()
1395
bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
1396
result = selftest(verbose=verbose, pattern=pattern)
1398
bzrlib.trace.info('tests passed')
1400
bzrlib.trace.info('tests failed')
1401
return int(not result)
1403
bzrlib.trace.enable_default_logging()
1404
bzrlib.ui.ui_factory = save_ui
1329
1407
class cmd_version(Command):
1465
class cmd_find_merge_base(Command):
1466
"""Find and print a base revision for merging two branches.
1468
TODO: Options to specify revisions on either side, as if
1469
merging only part of the history.
1471
takes_args = ['branch', 'other']
1474
def run(self, branch, other):
1475
branch1 = find_branch(branch)
1476
branch2 = find_branch(other)
1478
base_revno, base_revid = branch1.common_ancestor(branch2)
1480
if base_revno is None:
1481
raise bzrlib.errors.UnrelatedBranches()
1483
print 'merge base is revision %s' % base_revid
1484
print ' r%-6d in %s' % (base_revno, branch)
1486
other_revno = branch2.revision_id_to_revno(base_revid)
1488
print ' r%-6d in %s' % (other_revno, other)
1387
1492
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
1493
"""Perform a three-way merge.
1495
The branch is the branch you will merge from. By default, it will merge
1496
the latest revision. If you specify a revision, that revision will be
1497
merged. If you specify two revisions, the first will be used as a BASE,
1498
and the second one as OTHER. Revision numbers are always relative to the
1503
To merge the latest revision from bzr.dev
1504
bzr merge ../bzr.dev
1506
To merge changes up to and including revision 82 from bzr.dev
1507
bzr merge -r 82 ../bzr.dev
1509
To merge the changes introduced by 82, without previous changes:
1510
bzr merge -r 81..82 ../bzr.dev
1406
1512
merge refuses to run if there are any uncommitted changes, unless
1407
1513
--force is given.
1409
takes_args = ['other_spec', 'base_spec?']
1410
takes_options = ['force', 'merge-type']
1515
takes_args = ['branch?']
1516
takes_options = ['revision', 'force', 'merge-type']
1412
def run(self, other_spec, base_spec=None, force=False, merge_type=None):
1518
def run(self, branch='.', revision=None, force=False,
1413
1520
from bzrlib.merge import merge
1414
1521
from bzrlib.merge_core import ApplyMerge3
1415
1522
if merge_type is None:
1416
1523
merge_type = ApplyMerge3
1417
merge(parse_spec(other_spec), parse_spec(base_spec),
1418
check_clean=(not force), merge_type=merge_type)
1525
if revision is None or len(revision) < 1:
1527
other = (branch, -1)
1529
if len(revision) == 1:
1530
other = (branch, revision[0])
1533
assert len(revision) == 2
1534
if None in revision:
1535
raise BzrCommandError(
1536
"Merge doesn't permit that revision specifier.")
1537
base = (branch, revision[0])
1538
other = (branch, revision[1])
1540
merge(other, base, check_clean=(not force), merge_type=merge_type)
1421
1543
class cmd_revert(Command):
1456
1581
"""Show help on a command or other topic.
1458
1583
For a list of all available commands, say 'bzr help commands'."""
1584
takes_options = ['long']
1459
1585
takes_args = ['topic?']
1460
1586
aliases = ['?']
1462
def run(self, topic=None):
1588
def run(self, topic=None, long=False):
1590
if topic is None and long:
1464
1592
help.help(topic)
1595
class cmd_shell_complete(Command):
1596
"""Show appropriate completions for context.
1598
For a list of all available commands, say 'bzr shell-complete'."""
1599
takes_args = ['context?']
1603
def run(self, context=None):
1604
import shellcomplete
1605
shellcomplete.shellcomplete(context)
1608
class cmd_missing(Command):
1609
"""What is missing in this branch relative to other branch.
1611
takes_args = ['remote?']
1612
aliases = ['mis', 'miss']
1613
# We don't have to add quiet to the list, because
1614
# unknown options are parsed as booleans
1615
takes_options = ['verbose', 'quiet']
1617
def run(self, remote=None, verbose=False, quiet=False):
1618
from bzrlib.branch import find_branch, DivergedBranches
1619
from bzrlib.errors import BzrCommandError
1620
from bzrlib.missing import get_parent, show_missing
1622
if verbose and quiet:
1623
raise BzrCommandError('Cannot pass both quiet and verbose')
1625
b = find_branch('.')
1626
parent = get_parent(b)
1629
raise BzrCommandError("No missing location known or specified.")
1632
print "Using last location: %s" % parent
1634
elif parent is None:
1635
# We only update x-pull if it did not exist, missing should not change the parent
1636
b.controlfile('x-pull', 'wb').write(remote + '\n')
1637
br_remote = find_branch(remote)
1639
return show_missing(b, br_remote, verbose=verbose, quiet=quiet)
1469
1643
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
1844
def run_bzr(argv):
1736
1845
"""Execute a command.
1739
1848
logging and error handling.
1742
The command-line arguments, without the program name.
1851
The command-line arguments, without the program name from argv[0]
1744
1853
Returns a command status or raises an exception.
1855
Special master options: these must come before the command because
1856
they control how the command is interpreted.
1859
Do not load plugin modules at all
1862
Only use builtin commands. (Plugins are still allowed to change
1866
Run under the Python profiler.
1746
1869
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']:
1871
opt_profile = opt_no_plugins = opt_builtin = False
1873
# --no-plugins is handled specially at a very early stage. We need
1874
# to load plugins before doing other command parsing so that they
1875
# can override commands, but this needs to happen first.
1878
if a == '--profile':
1880
elif a == '--no-plugins':
1881
opt_no_plugins = True
1882
elif a == '--builtin':
1888
if not opt_no_plugins:
1751
1889
from bzrlib.plugin import load_plugins
1754
1892
args, opts = parse_args(argv)
1756
if master_opts.get('help') or 'help' in opts:
1757
1895
from bzrlib.help import help
1768
if args and args[0] == 'builtin':
1769
include_plugins=False
1907
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:
1911
cmd = str(args.pop(0))
1913
canonical_cmd, cmd_class = \
1914
get_cmd_class(cmd, plugins_override=not opt_builtin)
1788
1916
# check options are reasonable
1789
1917
allowed = cmd_class.takes_options
1823
1951
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
1954
def main(argv):
1842
bzrlib.trace.open_tracefile(argv)
1956
bzrlib.trace.log_startup(argv)
1957
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()
1961
return run_bzr(argv[1:])
1963
# do this here inside the exception wrappers to catch EPIPE
1965
except BzrCommandError, e:
1966
# command line syntax error, etc
1970
bzrlib.trace.log_exception()
1972
except AssertionError, e:
1973
bzrlib.trace.log_exception('assertion failed: ' + str(e))
1975
except KeyboardInterrupt, e:
1976
bzrlib.trace.note('interrupted')
1978
except Exception, e:
1980
if (isinstance(e, IOError)
1981
and hasattr(e, 'errno')
1982
and e.errno == errno.EPIPE):
1983
bzrlib.trace.note('broken pipe')
1986
bzrlib.trace.log_exception()
1884
1990
if __name__ == '__main__':