56
51
assert cmd.startswith("cmd_")
57
52
return cmd[4:].replace('_','-')
60
54
def _parse_revision_str(revstr):
61
"""This handles a revision string -> revno.
63
This always returns a list. The list will have one element for
65
It supports integers directly, but everything else it
66
defers for passing to Branch.get_revision_info()
68
>>> _parse_revision_str('234')
70
>>> _parse_revision_str('234..567')
72
>>> _parse_revision_str('..')
74
>>> _parse_revision_str('..234')
76
>>> _parse_revision_str('234..')
78
>>> _parse_revision_str('234..456..789') # Maybe this should be an error
80
>>> _parse_revision_str('234....789') # Error?
82
>>> _parse_revision_str('revid:test@other.com-234234')
83
['revid:test@other.com-234234']
84
>>> _parse_revision_str('revid:test@other.com-234234..revid:test@other.com-234235')
85
['revid:test@other.com-234234', 'revid:test@other.com-234235']
86
>>> _parse_revision_str('revid:test@other.com-234234..23')
87
['revid:test@other.com-234234', 23]
88
>>> _parse_revision_str('date:2005-04-12')
90
>>> _parse_revision_str('date:2005-04-12 12:24:33')
91
['date:2005-04-12 12:24:33']
92
>>> _parse_revision_str('date:2005-04-12T12:24:33')
93
['date:2005-04-12T12:24:33']
94
>>> _parse_revision_str('date:2005-04-12,12:24:33')
95
['date:2005-04-12,12:24:33']
96
>>> _parse_revision_str('-5..23')
98
>>> _parse_revision_str('-5')
100
>>> _parse_revision_str('123a')
102
>>> _parse_revision_str('abc')
55
"""This handles a revision string -> revno.
57
There are several possibilities:
60
'234:345' -> [234, 345]
64
In the future we will also support:
65
'uuid:blah-blah-blah' -> ?
66
'hash:blahblahblah' -> ?
106
old_format_re = re.compile('\d*:\d*')
107
m = old_format_re.match(revstr)
109
warning('Colon separator for revision numbers is deprecated.'
112
for rev in revstr.split(':'):
114
revs.append(int(rev))
119
for x in revstr.split('..'):
70
if revstr.find(':') != -1:
71
revs = revstr.split(':')
73
raise ValueError('More than 2 pieces not supported for --revision: %r' % revstr)
78
revs[0] = int(revs[0])
83
revs[1] = int(revs[1])
130
def get_merge_type(typestring):
131
"""Attempt to find the merge class/factory associated with a string."""
132
from merge import merge_types
134
return merge_types[typestring][0]
136
templ = '%s%%7s: %%s' % (' '*12)
137
lines = [templ % (f[0], f[1][1]) for f in merge_types.iteritems()]
138
type_list = '\n'.join(lines)
139
msg = "No known merge type %s. Supported types are:\n%s" %\
140
(typestring, type_list)
141
raise BzrCommandError(msg)
145
90
def _get_cmd_dict(plugins_override=True):
242
184
class ExternalCommand(Command):
243
185
"""Class to wrap external commands.
245
We cheat a little here, when get_cmd_class() calls us we actually
246
give it back an object we construct that has the appropriate path,
247
help, options etc for the specified command.
249
When run_bzr() tries to instantiate that 'class' it gets caught by
250
the __call__ method, which we override to call the Command.__init__
251
method. That then calls our run method which is pretty straight
254
The only wrinkle is that we have to map bzr's dictionary of options
255
and arguments back into command line options and arguments for the
187
We cheat a little here, when get_cmd_class() calls us we actually give it back
188
an object we construct that has the appropriate path, help, options etc for the
191
When run_bzr() tries to instantiate that 'class' it gets caught by the __call__
192
method, which we override to call the Command.__init__ method. That then calls
193
our run method which is pretty straight forward.
195
The only wrinkle is that we have to map bzr's dictionary of options and arguments
196
back into command line options and arguments for the script.
259
199
def find_command(cls, cmd):
539
class cmd_mv(Command):
540
"""Move or rename a file.
543
bzr mv OLDNAME NEWNAME
544
bzr mv SOURCE... DESTINATION
546
If the last argument is a versioned directory, all the other names
547
are moved into it. Otherwise, there must be exactly two arguments
548
and the file is changed to a new name, which must not already exist.
550
Files cannot be moved between branches.
552
takes_args = ['names*']
553
def run(self, names_list):
554
if len(names_list) < 2:
555
raise BzrCommandError("missing file argument")
556
b = find_branch(names_list[0])
558
rel_names = [b.relpath(x) for x in names_list]
560
if os.path.isdir(names_list[-1]):
561
# move into existing directory
562
b.move(rel_names[:-1], rel_names[-1])
564
if len(names_list) != 2:
565
raise BzrCommandError('to mv multiple files the destination '
566
'must be a versioned directory')
567
b.move(rel_names[0], rel_names[1])
572
452
class cmd_pull(Command):
640
520
takes_args = ['from_location', 'to_location?']
641
521
takes_options = ['revision']
642
aliases = ['get', 'clone']
644
523
def run(self, from_location, to_location=None, revision=None):
646
525
from bzrlib.merge import merge
647
from bzrlib.branch import DivergedBranches, \
526
from bzrlib.branch import DivergedBranches, NoSuchRevision, \
648
527
find_cached_branch, Branch
649
528
from shutil import rmtree
650
529
from meta_store import CachedStore
652
531
cache_root = tempfile.mkdtemp()
656
elif len(revision) > 1:
657
raise BzrCommandError('bzr branch --revision takes exactly 1 revision value')
661
534
br_from = find_cached_branch(from_location, cache_root)
683
556
br_to = Branch(to_location, init=True)
685
br_to.set_root_id(br_from.get_root_id())
688
if revision[0] is None:
689
revno = br_from.revno()
691
revno, rev_id = br_from.get_revision_info(revision[0])
693
br_to.update_revisions(br_from, stop_revision=revno)
694
except bzrlib.errors.NoSuchRevision:
696
msg = "The branch %s has no revision %d." % (from_location,
698
raise BzrCommandError(msg)
559
br_to.update_revisions(br_from, stop_revision=revision)
560
except NoSuchRevision:
562
msg = "The branch %s has no revision %d." % (from_location,
564
raise BzrCommandError(msg)
700
565
merge((to_location, -1), (to_location, 0), this_dir=to_location,
701
566
check_clean=False, ignore_zero=True)
702
567
from_location = pull_loc(br_from)
959
817
-r revision requests a specific revision, -r :end or -r begin: are
962
--message allows you to give a regular expression, which will be evaluated
963
so that only matching entries will be displayed.
965
820
TODO: Make --revision support uuid: and hash: [future tag:] notation.
969
824
takes_args = ['filename?']
970
takes_options = ['forward', 'timezone', 'verbose', 'show-ids', 'revision','long', 'message']
825
takes_options = ['forward', 'timezone', 'verbose', 'show-ids', 'revision','long']
972
827
def run(self, filename=None, timezone='original',
979
833
from bzrlib.branch import find_branch
980
834
from bzrlib.log import log_formatter, show_log
1455
1262
--force is given.
1457
1264
takes_args = ['other_spec', 'base_spec?']
1458
takes_options = ['force', 'merge-type']
1265
takes_options = ['force']
1460
def run(self, other_spec, base_spec=None, force=False, merge_type=None):
1267
def run(self, other_spec, base_spec=None, force=False):
1461
1268
from bzrlib.merge import merge
1462
from bzrlib.merge_core import ApplyMerge3
1463
if merge_type is None:
1464
merge_type = ApplyMerge3
1465
1269
merge(parse_spec(other_spec), parse_spec(base_spec),
1466
check_clean=(not force), merge_type=merge_type)
1270
check_clean=(not force))
1469
1274
class cmd_revert(Command):
1275
"""Restore selected files from a previous revision.
1277
takes_args = ['file+']
1278
def run(self, file_list):
1279
from bzrlib.branch import find_branch
1284
b = find_branch(file_list[0])
1286
b.revert([b.relpath(f) for f in file_list])
1289
class cmd_merge_revert(Command):
1470
1290
"""Reverse all changes since the last commit.
1472
Only versioned files are affected. Specify filenames to revert only
1473
those files. By default, any files that are changed will be backed up
1474
first. Backup files have a '~' appended to their name.
1292
Only versioned files are affected.
1294
TODO: Store backups of any files that will be reverted, so
1295
that the revert can be undone.
1476
takes_options = ['revision', 'no-backup']
1477
takes_args = ['file*']
1478
aliases = ['merge-revert']
1297
takes_options = ['revision']
1480
def run(self, revision=None, no_backup=False, file_list=None):
1299
def run(self, revision=-1):
1481
1300
from bzrlib.merge import merge
1482
if file_list is not None:
1483
if len(file_list) == 0:
1484
raise BzrCommandError("No files specified")
1485
if revision is None:
1487
elif len(revision) != 1:
1488
raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
1489
merge(('.', revision[0]), parse_spec('.'),
1301
merge(('.', revision), parse_spec('.'),
1490
1302
check_clean=False,
1492
backup_files=not no_backup,
1493
file_list=file_list)
1496
1306
class cmd_assert_fail(Command):
1586
1387
>>> parse_args('commit --message=biter'.split())
1587
1388
(['commit'], {'message': u'biter'})
1588
1389
>>> parse_args('log -r 500'.split())
1589
(['log'], {'revision': [500]})
1590
>>> parse_args('log -r500..600'.split())
1390
(['log'], {'revision': 500})
1391
>>> parse_args('log -r500:600'.split())
1591
1392
(['log'], {'revision': [500, 600]})
1592
>>> parse_args('log -vr500..600'.split())
1393
>>> parse_args('log -vr500:600'.split())
1593
1394
(['log'], {'verbose': True, 'revision': [500, 600]})
1594
>>> parse_args('log -rv500..600'.split()) #the r takes an argument
1595
(['log'], {'revision': ['v500', 600]})
1395
>>> parse_args('log -rv500:600'.split()) #the r takes an argument
1396
Traceback (most recent call last):
1398
ValueError: invalid literal for int(): v500
1518
def _parse_master_args(argv):
1519
"""Parse the arguments that always go with the original command.
1520
These are things like bzr --no-plugins, etc.
1522
There are now 2 types of option flags. Ones that come *before* the command,
1523
and ones that come *after* the command.
1524
Ones coming *before* the command are applied against all possible commands.
1525
And are generally applied before plugins are loaded.
1527
The current list are:
1528
--builtin Allow plugins to load, but don't let them override builtin commands,
1529
they will still be allowed if they do not override a builtin.
1530
--no-plugins Don't load any plugins. This lets you get back to official source
1532
--profile Enable the hotspot profile before running the command.
1533
For backwards compatibility, this is also a non-master option.
1534
--version Spit out the version of bzr that is running and exit.
1535
This is also a non-master option.
1536
--help Run help and exit, also a non-master option (I think that should stay, though)
1538
>>> argv, opts = _parse_master_args(['bzr', '--test'])
1539
Traceback (most recent call last):
1541
BzrCommandError: Invalid master option: 'test'
1542
>>> argv, opts = _parse_master_args(['bzr', '--version', 'command'])
1545
>>> print opts['version']
1547
>>> argv, opts = _parse_master_args(['bzr', '--profile', 'command', '--more-options'])
1549
['command', '--more-options']
1550
>>> print opts['profile']
1552
>>> argv, opts = _parse_master_args(['bzr', '--no-plugins', 'command'])
1555
>>> print opts['no-plugins']
1557
>>> print opts['profile']
1559
>>> argv, opts = _parse_master_args(['bzr', 'command', '--profile'])
1561
['command', '--profile']
1562
>>> print opts['profile']
1565
master_opts = {'builtin':False,
1572
# This is the point where we could hook into argv[0] to determine
1573
# what front-end is supposed to be run
1574
# For now, we are just ignoring it.
1575
cmd_name = argv.pop(0)
1577
if arg[:2] != '--': # at the first non-option, we return the rest
1579
arg = arg[2:] # Remove '--'
1580
if arg not in master_opts:
1581
# We could say that this is not an error, that we should
1582
# just let it be handled by the main section instead
1583
raise BzrCommandError('Invalid master option: %r' % arg)
1584
argv.pop(0) # We are consuming this entry
1585
master_opts[arg] = True
1586
return argv, master_opts
1716
1590
def run_bzr(argv):
1717
1591
"""Execute a command.
1719
1593
This is similar to main(), but without all the trappings for
1720
1594
logging and error handling.
1723
The command-line arguments, without the program name from argv[0]
1725
Returns a command status or raises an exception.
1727
Special master options: these must come before the command because
1728
they control how the command is interpreted.
1731
Do not load plugin modules at all
1734
Only use builtin commands. (Plugins are still allowed to change
1738
Run under the Python profiler.
1741
1596
argv = [a.decode(bzrlib.user_encoding) for a in argv]
1743
opt_profile = opt_no_plugins = opt_builtin = False
1745
# --no-plugins is handled specially at a very early stage. We need
1746
# to load plugins before doing other command parsing so that they
1747
# can override commands, but this needs to happen first.
1750
if a == '--profile':
1752
elif a == '--no-plugins':
1753
opt_no_plugins = True
1754
elif a == '--builtin':
1760
if not opt_no_plugins:
1761
from bzrlib.plugin import load_plugins
1764
args, opts = parse_args(argv)
1767
from bzrlib.help import help
1774
if 'version' in opts:
1779
print >>sys.stderr, "please try 'bzr help' for help"
1599
# some options like --builtin and --no-plugins have special effects
1600
argv, master_opts = _parse_master_args(argv)
1601
if not master_opts['no-plugins']:
1602
from bzrlib.plugin import load_plugins
1605
args, opts = parse_args(argv)
1607
if master_opts['help']:
1608
from bzrlib.help import help
1616
from bzrlib.help import help
1622
elif 'version' in opts:
1625
elif args and args[0] == 'builtin':
1626
include_plugins=False
1628
cmd = str(args.pop(0))
1782
cmd = str(args.pop(0))
1784
canonical_cmd, cmd_class = \
1785
get_cmd_class(cmd, plugins_override=not opt_builtin)
1635
plugins_override = not (master_opts['builtin'])
1636
canonical_cmd, cmd_class = get_cmd_class(cmd, plugins_override=plugins_override)
1638
profile = master_opts['profile']
1639
# For backwards compatibility, I would rather stick with --profile being a
1640
# master/global option
1641
if 'profile' in opts:
1787
1645
# check options are reasonable
1788
1646
allowed = cmd_class.takes_options