22
from bzrlib.trace import mutter, note, log_error
23
from bzrlib.errors import bailout, BzrError, BzrCheckError, BzrCommandError
24
from bzrlib.osutils import quotefn
25
from bzrlib import Branch, Inventory, InventoryEntry, BZRDIR, \
22
from bzrlib.trace import mutter, note, log_error, warning
23
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError
24
from bzrlib.branch import find_branch
25
from bzrlib import BZRDIR
31
def register_command(cmd):
32
"Utility function to help register a command"
35
if k.startswith("cmd_"):
36
k_unsquished = _unsquish_command_name(k)
39
if not plugin_cmds.has_key(k_unsquished):
40
plugin_cmds[k_unsquished] = cmd
42
log_error('Two plugins defined the same command: %r' % k)
43
log_error('Not loading the one in %r' % sys.modules[cmd.__module__])
29
46
def _squish_command_name(cmd):
34
51
assert cmd.startswith("cmd_")
35
52
return cmd[4:].replace('_','-')
37
55
def _parse_revision_str(revstr):
38
"""This handles a revision string -> revno.
40
There are several possibilities:
43
'234:345' -> [234, 345]
47
In the future we will also support:
48
'uuid:blah-blah-blah' -> ?
49
'hash:blahblahblah' -> ?
56
"""This handles a revision string -> revno.
58
This always returns a list. The list will have one element for
60
It supports integers directly, but everything else it
61
defers for passing to Branch.get_revision_info()
63
>>> _parse_revision_str('234')
65
>>> _parse_revision_str('234..567')
67
>>> _parse_revision_str('..')
69
>>> _parse_revision_str('..234')
71
>>> _parse_revision_str('234..')
73
>>> _parse_revision_str('234..456..789') # Maybe this should be an error
75
>>> _parse_revision_str('234....789') # Error?
77
>>> _parse_revision_str('revid:test@other.com-234234')
78
['revid:test@other.com-234234']
79
>>> _parse_revision_str('revid:test@other.com-234234..revid:test@other.com-234235')
80
['revid:test@other.com-234234', 'revid:test@other.com-234235']
81
>>> _parse_revision_str('revid:test@other.com-234234..23')
82
['revid:test@other.com-234234', 23]
83
>>> _parse_revision_str('date:2005-04-12')
85
>>> _parse_revision_str('date:2005-04-12 12:24:33')
86
['date:2005-04-12 12:24:33']
87
>>> _parse_revision_str('date:2005-04-12T12:24:33')
88
['date:2005-04-12T12:24:33']
89
>>> _parse_revision_str('date:2005-04-12,12:24:33')
90
['date:2005-04-12,12:24:33']
91
>>> _parse_revision_str('-5..23')
93
>>> _parse_revision_str('-5')
95
>>> _parse_revision_str('123a')
97
>>> _parse_revision_str('abc')
53
if revstr.find(':') != -1:
54
revs = revstr.split(':')
56
raise ValueError('More than 2 pieces not supported for --revision: %r' % revstr)
61
revs[0] = int(revs[0])
66
revs[1] = int(revs[1])
101
old_format_re = re.compile('\d*:\d*')
102
m = old_format_re.match(revstr)
104
warning('Colon separator for revision numbers is deprecated.'
107
for rev in revstr.split(':'):
109
revs.append(int(rev))
114
for x in revstr.split('..'):
72
"""Return canonical name and class for all registered commands."""
125
def get_merge_type(typestring):
126
"""Attempt to find the merge class/factory associated with a string."""
127
from merge import merge_types
129
return merge_types[typestring][0]
131
templ = '%s%%7s: %%s' % (' '*12)
132
lines = [templ % (f[0], f[1][1]) for f in merge_types.iteritems()]
133
type_list = '\n'.join(lines)
134
msg = "No known merge type %s. Supported types are:\n%s" %\
135
(typestring, type_list)
136
raise BzrCommandError(msg)
140
def _get_cmd_dict(plugins_override=True):
73
142
for k, v in globals().iteritems():
74
143
if k.startswith("cmd_"):
75
yield _unsquish_command_name(k), v
77
def get_cmd_class(cmd):
144
d[_unsquish_command_name(k)] = v
145
# If we didn't load plugins, the plugin_cmds dict will be empty
147
d.update(plugin_cmds)
149
d2 = plugin_cmds.copy()
155
def get_all_cmds(plugins_override=True):
156
"""Return canonical name and class for all registered commands."""
157
for k, v in _get_cmd_dict(plugins_override=plugins_override).iteritems():
161
def get_cmd_class(cmd, plugins_override=True):
78
162
"""Return the canonical name and command class for a command.
80
164
cmd = str(cmd) # not unicode
82
166
# first look up this command under the specified name
167
cmds = _get_cmd_dict(plugins_override=plugins_override)
84
return cmd, globals()[_squish_command_name(cmd)]
169
return cmd, cmds[cmd]
88
173
# look for any command which claims this as an alias
89
for cmdname, cmdclass in get_all_cmds():
174
for cmdname, cmdclass in cmds.iteritems():
90
175
if cmd in cmdclass.aliases:
91
176
return cmdname, cmdclass
177
265
def __init__(self, path):
180
# TODO: If either of these fail, we should detect that and
181
# assume that path is not really a bzr plugin after all.
183
268
pipe = os.popen('%s --bzr-usage' % path, 'r')
184
269
self.takes_options = pipe.readline().split()
271
for opt in self.takes_options:
272
if not opt in OPTIONS:
273
raise BzrError("Unknown option '%s' returned by external command %s"
276
# TODO: Is there any way to check takes_args is valid here?
185
277
self.takes_args = pipe.readline().split()
279
if pipe.close() is not None:
280
raise BzrError("Failed funning '%s --bzr-usage'" % path)
188
282
pipe = os.popen('%s --bzr-help' % path, 'r')
189
283
self.__doc__ = pipe.read()
284
if pipe.close() is not None:
285
raise BzrError("Failed funning '%s --bzr-help'" % path)
192
287
def __call__(self, options, arguments):
193
288
Command.__init__(self, options, arguments)
253
349
directory is shown. Otherwise, only the status of the specified
254
350
files or directories is reported. If a directory is given, status
255
351
is reported for everything inside that directory.
353
If a revision is specified, the changes since that revision are shown.
257
355
takes_args = ['file*']
258
takes_options = ['all', 'show-ids']
356
takes_options = ['all', 'show-ids', 'revision']
259
357
aliases = ['st', 'stat']
261
359
def run(self, all=False, show_ids=False, file_list=None):
263
b = Branch(file_list[0])
361
b = find_branch(file_list[0])
264
362
file_list = [b.relpath(x) for x in file_list]
265
363
# special case: only one path was given and it's the root
267
365
if file_list == ['']:
272
status.show_status(b, show_unchanged=all, show_ids=show_ids,
273
specific_files=file_list)
370
from bzrlib.status import show_status
371
show_status(b, show_unchanged=all, show_ids=show_ids,
372
specific_files=file_list)
276
375
class cmd_cat_revision(Command):
304
426
whether already versioned or not, are searched for files or
305
427
subdirectories that are neither versioned or ignored, and these
306
428
are added. This search proceeds recursively into versioned
429
directories. If no names are given '.' is assumed.
309
Therefore simply saying 'bzr add .' will version all files that
431
Therefore simply saying 'bzr add' will version all files that
310
432
are currently unknown.
312
434
TODO: Perhaps adding a file whose directly is not versioned should
313
435
recursively add that parent, rather than giving an error?
315
takes_args = ['file+']
437
takes_args = ['file*']
316
438
takes_options = ['verbose', 'no-recurse']
318
440
def run(self, file_list, verbose=False, no_recurse=False):
319
bzrlib.add.smart_add(file_list, verbose, not no_recurse)
441
from bzrlib.add import smart_add
442
smart_add(file_list, verbose, not no_recurse)
446
class cmd_mkdir(Command):
447
"""Create a new versioned directory.
449
This is equivalent to creating the directory and then adding it.
451
takes_args = ['dir+']
453
def run(self, dir_list):
460
b.add([d], verbose=True)
322
463
class cmd_relpath(Command):
405
549
def run(self, location=None):
406
550
from bzrlib.merge import merge
552
from shutil import rmtree
555
br_to = find_branch('.')
410
556
stored_loc = None
412
558
stored_loc = br_to.controlfile("x-pull", "rb").read().rstrip('\n')
413
559
except IOError, e:
414
if errno == errno.ENOENT:
560
if e.errno != errno.ENOENT:
416
562
if location is None:
417
location = stored_loc
419
raise BzrCommandError("No pull location known or specified.")
420
from branch import find_branch, DivergedBranches
563
if stored_loc is None:
564
raise BzrCommandError("No pull location known or specified.")
566
print "Using last location: %s" % stored_loc
567
location = stored_loc
568
cache_root = tempfile.mkdtemp()
569
from bzrlib.branch import DivergedBranches
421
570
br_from = find_branch(location)
422
571
location = pull_loc(br_from)
423
572
old_revno = br_to.revno()
425
br_to.update_revisions(br_from)
426
except DivergedBranches:
427
raise BzrCommandError("These branches have diverged. Try merge.")
429
merge(('.', -1), ('.', old_revno))
430
if location != stored_loc:
431
br_to.controlfile("x-pull", "wb").write(location + "\n")
574
from branch import find_cached_branch, DivergedBranches
575
br_from = find_cached_branch(location, cache_root)
576
location = pull_loc(br_from)
577
old_revno = br_to.revno()
579
br_to.update_revisions(br_from)
580
except DivergedBranches:
581
raise BzrCommandError("These branches have diverged."
584
merge(('.', -1), ('.', old_revno), check_clean=False)
585
if location != stored_loc:
586
br_to.controlfile("x-pull", "wb").write(location + "\n")
435
592
class cmd_branch(Command):
436
593
"""Create a new copy of a branch.
438
If the TO_LOCATION is omitted, the last component of the
439
FROM_LOCATION will be used. In other words,
440
"branch ../foo/bar" will attempt to create ./bar.
595
If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
596
be used. In other words, "branch ../foo/bar" will attempt to create ./bar.
598
To retrieve the branch as of a particular revision, supply the --revision
599
parameter, as in "branch foo/bar -r 5".
442
601
takes_args = ['from_location', 'to_location?']
602
takes_options = ['revision']
444
def run(self, from_location, to_location=None):
604
def run(self, from_location, to_location=None, revision=None):
446
606
from bzrlib.merge import merge
448
if to_location is None:
449
to_location = os.path.basename(from_location)
450
# FIXME: If there's a trailing slash, keep removing them
451
# until we find the right bit
454
os.mkdir(to_location)
456
if e.errno == errno.EEXIST:
457
raise BzrCommandError('Target directory "%s" already exists.' %
459
if e.errno == errno.ENOENT:
460
raise BzrCommandError('Parent of "%s" does not exist.' %
464
br_to = Branch(to_location, init=True)
465
from branch import find_branch, DivergedBranches
467
br_from = find_branch(from_location)
469
if e.errno == errno.ENOENT:
470
raise BzrCommandError('Source location "%s" does not exist.' %
475
from_location = pull_loc(br_from)
476
br_to.update_revisions(br_from)
477
merge((to_location, -1), (to_location, 0), this_dir=to_location,
479
br_to.controlfile("x-pull", "wb").write(from_location + "\n")
607
from bzrlib.branch import DivergedBranches, NoSuchRevision, \
608
find_cached_branch, Branch
609
from shutil import rmtree
610
from meta_store import CachedStore
612
cache_root = tempfile.mkdtemp()
616
elif len(revision) > 1:
617
raise BzrCommandError('bzr branch --revision takes exactly 1 revision value')
621
br_from = find_cached_branch(from_location, cache_root)
623
if e.errno == errno.ENOENT:
624
raise BzrCommandError('Source location "%s" does not'
625
' exist.' % to_location)
629
if to_location is None:
630
to_location = os.path.basename(from_location.rstrip("/\\"))
633
os.mkdir(to_location)
635
if e.errno == errno.EEXIST:
636
raise BzrCommandError('Target directory "%s" already'
637
' exists.' % to_location)
638
if e.errno == errno.ENOENT:
639
raise BzrCommandError('Parent of "%s" does not exist.' %
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")
482
668
def pull_loc(branch):
680
872
"""List files modified in working tree."""
685
inv = b.read_working_inventory()
686
sc = statcache.update_cache(b, inv)
687
basis = b.basis_tree()
688
basis_inv = basis.inventory
690
# We used to do this through iter_entries(), but that's slow
691
# when most of the files are unmodified, as is usually the
692
# case. So instead we iterate by inventory entry, and only
693
# calculate paths as necessary.
695
for file_id in basis_inv:
696
cacheentry = sc.get(file_id)
697
if not cacheentry: # deleted
699
ie = basis_inv[file_id]
700
if cacheentry[statcache.SC_SHA1] != ie.text_sha1:
701
path = inv.id2path(file_id)
875
from bzrlib.diff import compare_trees
878
td = compare_trees(b.basis_tree(), b.working_tree())
880
for path, id, kind in td.modified:
741
919
-r revision requests a specific revision, -r :end or -r begin: are
922
--message allows you to give a regular expression, which will be evaluated
923
so that only matching entries will be displayed.
744
925
TODO: Make --revision support uuid: and hash: [future tag:] notation.
748
929
takes_args = ['filename?']
749
takes_options = ['forward', 'timezone', 'verbose', 'show-ids', 'revision']
930
takes_options = ['forward', 'timezone', 'verbose', 'show-ids', 'revision','long', 'message']
751
932
def run(self, filename=None, timezone='original',
756
from bzrlib import show_log, find_branch
939
from bzrlib.branch import find_branch
940
from bzrlib.log import log_formatter, show_log
759
943
direction = (forward and 'forward') or 'reverse'
933
1133
except ValueError:
934
1134
raise BzrCommandError("not a valid revision-number: %r" % revno)
936
print Branch('.').lookup_revision(revno)
1136
print find_branch('.').lookup_revision(revno)
939
1139
class cmd_export(Command):
940
1140
"""Export past revision to destination directory.
942
If no revision is specified this exports the last committed revision."""
1142
If no revision is specified this exports the last committed revision.
1144
Format may be an "exporter" name, such as tar, tgz, tbz2. If none is
1145
given, try to find the format with the extension. If no extension
1146
is found exports to a directory (equivalent to --format=dir).
1148
Root may be the top directory for tar, tgz and tbz2 formats. If none
1149
is given, the top directory will be the root name of the file."""
1150
# TODO: list known exporters
943
1151
takes_args = ['dest']
944
takes_options = ['revision']
945
def run(self, dest, revision=None):
948
rh = b.revision_history()[-1]
1152
takes_options = ['revision', 'format', 'root']
1153
def run(self, dest, revision=None, format=None, root=None):
1155
b = find_branch('.')
1156
if revision is None:
1157
rev_id = b.last_patch()
950
rh = b.lookup_revision(int(revision))
951
t = b.revision_tree(rh)
1159
if len(revision) != 1:
1160
raise BzrError('bzr export --revision takes exactly 1 argument')
1161
revno, rev_id = b.get_revision_info(revision[0])
1162
t = b.revision_tree(rev_id)
1163
root, ext = os.path.splitext(dest)
1165
if ext in (".tar",):
1167
elif ext in (".gz", ".tgz"):
1169
elif ext in (".bz2", ".tbz2"):
1173
t.export(dest, format, root)
955
1176
class cmd_cat(Command):
989
1212
TODO: Strict commit that fails if there are unknown or deleted files.
991
1214
takes_args = ['selected*']
992
takes_options = ['message', 'file', 'verbose']
1215
takes_options = ['message', 'file', 'verbose', 'unchanged']
993
1216
aliases = ['ci', 'checkin']
995
def run(self, message=None, file=None, verbose=True, selected_list=None):
996
from bzrlib.commit import commit
1218
def run(self, message=None, file=None, verbose=True, selected_list=None,
1220
from bzrlib.errors import PointlessCommit
1221
from bzrlib.osutils import get_text_message
998
1223
## Warning: shadows builtin file()
999
1224
if not message and not file:
1000
raise BzrCommandError("please specify a commit message",
1001
["use either --message or --file"])
1227
catcher = cStringIO.StringIO()
1228
sys.stdout = catcher
1229
cmd_status({"file_list":selected_list}, {})
1230
info = catcher.getvalue()
1232
message = get_text_message(info)
1235
raise BzrCommandError("please specify a commit message",
1236
["use either --message or --file"])
1002
1237
elif message and file:
1003
1238
raise BzrCommandError("please specify either --message or --file")
1016
1260
This command checks various invariants about the branch storage to
1017
1261
detect data corruption or bzr bugs.
1019
takes_args = ['dir?']
1020
def run(self, dir='.'):
1022
bzrlib.check.check(Branch(dir))
1263
If given the --update flag, it will update some optional fields
1264
to help ensure data consistency.
1266
takes_args = ['dir?']
1268
def run(self, dir='.'):
1269
from bzrlib.check import check
1270
check(find_branch(dir))
1274
class cmd_scan_cache(Command):
1277
from bzrlib.hashcache import HashCache
1284
print '%6d stats' % c.stat_count
1285
print '%6d in hashcache' % len(c._cache)
1286
print '%6d files removed from cache' % c.removed_count
1287
print '%6d hashes updated' % c.update_count
1288
print '%6d files changed too recently to cache' % c.danger_count
1295
class cmd_upgrade(Command):
1296
"""Upgrade branch storage to current format.
1298
This should normally be used only after the check command tells
1301
takes_args = ['dir?']
1303
def run(self, dir='.'):
1304
from bzrlib.upgrade import upgrade
1305
upgrade(find_branch(dir))
1121
1407
--force is given.
1123
1409
takes_args = ['other_spec', 'base_spec?']
1124
takes_options = ['force']
1410
takes_options = ['force', 'merge-type']
1126
def run(self, other_spec, base_spec=None, force=False):
1412
def run(self, other_spec, base_spec=None, force=False, merge_type=None):
1127
1413
from bzrlib.merge import merge
1414
from bzrlib.merge_core import ApplyMerge3
1415
if merge_type is None:
1416
merge_type = ApplyMerge3
1128
1417
merge(parse_spec(other_spec), parse_spec(base_spec),
1129
check_clean=(not force))
1418
check_clean=(not force), merge_type=merge_type)
1132
1422
class cmd_revert(Command):
1423
"""Restore selected files from a previous revision.
1425
takes_args = ['file+']
1426
def run(self, file_list):
1427
from bzrlib.branch import find_branch
1432
b = find_branch(file_list[0])
1434
b.revert([b.relpath(f) for f in file_list])
1437
class cmd_merge_revert(Command):
1133
1438
"""Reverse all changes since the last commit.
1135
Only versioned files are affected.
1137
TODO: Store backups of any files that will be reverted, so
1138
that the revert can be undone.
1440
Only versioned files are affected. By default, any files that are changed
1441
will be backed up first. Backup files have a '~' appended to their name.
1140
takes_options = ['revision']
1443
takes_options = ['revision', 'no-backup']
1142
def run(self, revision=-1):
1143
merge(('.', revision), parse_spec('.'),
1445
def run(self, revision=None, no_backup=False):
1446
from bzrlib.merge import merge
1447
if revision is None:
1449
elif len(revision) != 1:
1450
raise BzrCommandError('bzr merge-revert --revision takes exactly 1 argument')
1451
merge(('.', revision[0]), parse_spec('.'),
1144
1452
check_clean=False,
1454
backup_files=not no_backup)
1148
1457
class cmd_assert_fail(Command):
1242
1574
optname = a[2:]
1243
1575
if optname not in OPTIONS:
1244
bailout('unknown long option %r' % a)
1576
raise BzrError('unknown long option %r' % a)
1246
1578
shortopt = a[1:]
1247
if shortopt not in SHORT_OPTIONS:
1248
bailout('unknown short option %r' % a)
1249
optname = SHORT_OPTIONS[shortopt]
1579
if shortopt in SHORT_OPTIONS:
1580
# Multi-character options must have a space to delimit
1582
optname = SHORT_OPTIONS[shortopt]
1584
# Single character short options, can be chained,
1585
# and have their value appended to their name
1587
if shortopt not in SHORT_OPTIONS:
1588
# We didn't find the multi-character name, and we
1589
# didn't find the single char name
1590
raise BzrError('unknown short option %r' % a)
1591
optname = SHORT_OPTIONS[shortopt]
1594
# There are extra things on this option
1595
# see if it is the value, or if it is another
1597
optargfn = OPTIONS[optname]
1598
if optargfn is None:
1599
# This option does not take an argument, so the
1600
# next entry is another short option, pack it back
1602
argv.insert(0, '-' + a[2:])
1604
# This option takes an argument, so pack it
1251
1608
if optname in opts:
1252
1609
# XXX: Do we ever want to support this, e.g. for -r?
1253
bailout('repeated option %r' % a)
1610
raise BzrError('repeated option %r' % a)
1255
1612
optargfn = OPTIONS[optname]
1257
1614
if optarg == None:
1259
bailout('option %r needs an argument' % a)
1616
raise BzrError('option %r needs an argument' % a)
1261
1618
optarg = argv.pop(0)
1262
1619
opts[optname] = optargfn(optarg)
1264
1621
if optarg != None:
1265
bailout('option %r takes no argument' % optname)
1622
raise BzrError('option %r takes no argument' % optname)
1266
1623
opts[optname] = True
1676
def _parse_master_args(argv):
1677
"""Parse the arguments that always go with the original command.
1678
These are things like bzr --no-plugins, etc.
1680
There are now 2 types of option flags. Ones that come *before* the command,
1681
and ones that come *after* the command.
1682
Ones coming *before* the command are applied against all possible commands.
1683
And are generally applied before plugins are loaded.
1685
The current list are:
1686
--builtin Allow plugins to load, but don't let them override builtin commands,
1687
they will still be allowed if they do not override a builtin.
1688
--no-plugins Don't load any plugins. This lets you get back to official source
1690
--profile Enable the hotspot profile before running the command.
1691
For backwards compatibility, this is also a non-master option.
1692
--version Spit out the version of bzr that is running and exit.
1693
This is also a non-master option.
1694
--help Run help and exit, also a non-master option (I think that should stay, though)
1696
>>> argv, opts = _parse_master_args(['--test'])
1697
Traceback (most recent call last):
1699
BzrCommandError: Invalid master option: 'test'
1700
>>> argv, opts = _parse_master_args(['--version', 'command'])
1703
>>> print opts['version']
1705
>>> argv, opts = _parse_master_args(['--profile', 'command', '--more-options'])
1707
['command', '--more-options']
1708
>>> print opts['profile']
1710
>>> argv, opts = _parse_master_args(['--no-plugins', 'command'])
1713
>>> print opts['no-plugins']
1715
>>> print opts['profile']
1717
>>> argv, opts = _parse_master_args(['command', '--profile'])
1719
['command', '--profile']
1720
>>> print opts['profile']
1723
master_opts = {'builtin':False,
1731
if arg[:2] != '--': # at the first non-option, we return the rest
1733
arg = arg[2:] # Remove '--'
1734
if arg not in master_opts:
1735
# We could say that this is not an error, that we should
1736
# just let it be handled by the main section instead
1737
raise BzrCommandError('Invalid master option: %r' % arg)
1738
argv.pop(0) # We are consuming this entry
1739
master_opts[arg] = True
1740
return argv, master_opts
1320
1744
def run_bzr(argv):
1321
1745
"""Execute a command.
1323
1747
This is similar to main(), but without all the trappings for
1324
1748
logging and error handling.
1751
The command-line arguments, without the program name.
1753
Returns a command status or raises an exception.
1326
1755
argv = [a.decode(bzrlib.user_encoding) for a in argv]
1757
# some options like --builtin and --no-plugins have special effects
1758
argv, master_opts = _parse_master_args(argv)
1759
if not master_opts['no-plugins']:
1760
from bzrlib.plugin import load_plugins
1763
args, opts = parse_args(argv)
1765
if master_opts.get('help') or 'help' in opts:
1766
from bzrlib.help import help
1773
if 'version' in opts:
1777
if args and args[0] == 'builtin':
1778
include_plugins=False
1329
args, opts = parse_args(argv[1:])
1337
elif 'version' in opts:
1340
1782
cmd = str(args.pop(0))
1341
1783
except IndexError:
1784
print >>sys.stderr, "please try 'bzr help' for help"
1347
canonical_cmd, cmd_class = get_cmd_class(cmd)
1787
plugins_override = not (master_opts['builtin'])
1788
canonical_cmd, cmd_class = get_cmd_class(cmd, plugins_override=plugins_override)
1790
profile = master_opts['profile']
1791
# For backwards compatibility, I would rather stick with --profile being a
1792
# master/global option
1350
1793
if 'profile' in opts:
1352
1795
del opts['profile']
1356
1797
# check options are reasonable
1357
1798
allowed = cmd_class.takes_options