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.
27
22
from bzrlib.trace import mutter, note, log_error, warning
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
126
def _get_cmd_dict(plugins_override=True):
242
223
class ExternalCommand(Command):
243
224
"""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
226
We cheat a little here, when get_cmd_class() calls us we actually give it back
227
an object we construct that has the appropriate path, help, options etc for the
230
When run_bzr() tries to instantiate that 'class' it gets caught by the __call__
231
method, which we override to call the Command.__init__ method. That then calls
232
our run method which is pretty straight forward.
234
The only wrinkle is that we have to map bzr's dictionary of options and arguments
235
back into command line options and arguments for the script.
259
238
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
519
class cmd_pull(Command):
640
587
takes_args = ['from_location', 'to_location?']
641
588
takes_options = ['revision']
642
aliases = ['get', 'clone']
644
590
def run(self, from_location, to_location=None, revision=None):
646
592
from bzrlib.merge import merge
647
from bzrlib.branch import DivergedBranches, \
593
from bzrlib.branch import DivergedBranches, NoSuchRevision, \
648
594
find_cached_branch, Branch
649
595
from shutil import rmtree
650
596
from meta_store import CachedStore
1239
1185
class cmd_commit(Command):
1240
1186
"""Commit changes into a new revision.
1242
If no arguments are given, the entire tree is committed.
1244
1188
If selected files are specified, only changes to those files are
1245
committed. If a directory is specified then the directory and everything
1246
within it is committed.
1189
committed. If a directory is specified then its contents are also
1248
1192
A selected-file commit may fail in some cases where the committed
1249
1193
tree would be invalid, such as trying to commit a file in a
1257
1201
takes_options = ['message', 'file', 'verbose', 'unchanged']
1258
1202
aliases = ['ci', 'checkin']
1260
# TODO: Give better message for -s, --summary, used by tla people
1262
1204
def run(self, message=None, file=None, verbose=True, selected_list=None,
1263
1205
unchanged=False):
1264
1206
from bzrlib.errors import PointlessCommit
1288
1228
message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1290
1230
b = find_branch('.')
1292
selected_list = [b.relpath(s) for s in selected_list]
1295
1233
b.commit(message, verbose=verbose,
1296
1234
specific_files=selected_list,
1455
1393
--force is given.
1457
1395
takes_args = ['other_spec', 'base_spec?']
1458
takes_options = ['force', 'merge-type']
1396
takes_options = ['force']
1460
def run(self, other_spec, base_spec=None, force=False, merge_type=None):
1398
def run(self, other_spec, base_spec=None, force=False):
1461
1399
from bzrlib.merge import merge
1462
from bzrlib.merge_core import ApplyMerge3
1463
if merge_type is None:
1464
merge_type = ApplyMerge3
1465
1400
merge(parse_spec(other_spec), parse_spec(base_spec),
1466
check_clean=(not force), merge_type=merge_type)
1401
check_clean=(not force))
1469
1405
class cmd_revert(Command):
1406
"""Restore selected files from a previous revision.
1408
takes_args = ['file+']
1409
def run(self, file_list):
1410
from bzrlib.branch import find_branch
1415
b = find_branch(file_list[0])
1417
b.revert([b.relpath(f) for f in file_list])
1420
class cmd_merge_revert(Command):
1470
1421
"""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.
1423
Only versioned files are affected.
1425
TODO: Store backups of any files that will be reverted, so
1426
that the revert can be undone.
1476
takes_options = ['revision', 'no-backup']
1477
takes_args = ['file*']
1478
aliases = ['merge-revert']
1428
takes_options = ['revision']
1480
def run(self, revision=None, no_backup=False, file_list=None):
1430
def run(self, revision=None):
1481
1431
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
1432
if revision is None:
1486
1433
revision = [-1]
1487
1434
elif len(revision) != 1:
1488
raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
1435
raise BzrCommandError('bzr merge-revert --revision takes exactly 1 argument')
1489
1436
merge(('.', revision[0]), parse_spec('.'),
1490
1437
check_clean=False,
1492
backup_files=not no_backup,
1493
file_list=file_list)
1496
1441
class cmd_assert_fail(Command):
1658
def _parse_master_args(argv):
1659
"""Parse the arguments that always go with the original command.
1660
These are things like bzr --no-plugins, etc.
1662
There are now 2 types of option flags. Ones that come *before* the command,
1663
and ones that come *after* the command.
1664
Ones coming *before* the command are applied against all possible commands.
1665
And are generally applied before plugins are loaded.
1667
The current list are:
1668
--builtin Allow plugins to load, but don't let them override builtin commands,
1669
they will still be allowed if they do not override a builtin.
1670
--no-plugins Don't load any plugins. This lets you get back to official source
1672
--profile Enable the hotspot profile before running the command.
1673
For backwards compatibility, this is also a non-master option.
1674
--version Spit out the version of bzr that is running and exit.
1675
This is also a non-master option.
1676
--help Run help and exit, also a non-master option (I think that should stay, though)
1678
>>> argv, opts = _parse_master_args(['--test'])
1679
Traceback (most recent call last):
1681
BzrCommandError: Invalid master option: 'test'
1682
>>> argv, opts = _parse_master_args(['--version', 'command'])
1685
>>> print opts['version']
1687
>>> argv, opts = _parse_master_args(['--profile', 'command', '--more-options'])
1689
['command', '--more-options']
1690
>>> print opts['profile']
1692
>>> argv, opts = _parse_master_args(['--no-plugins', 'command'])
1695
>>> print opts['no-plugins']
1697
>>> print opts['profile']
1699
>>> argv, opts = _parse_master_args(['command', '--profile'])
1701
['command', '--profile']
1702
>>> print opts['profile']
1705
master_opts = {'builtin':False,
1713
if arg[:2] != '--': # at the first non-option, we return the rest
1715
arg = arg[2:] # Remove '--'
1716
if arg not in master_opts:
1717
# We could say that this is not an error, that we should
1718
# just let it be handled by the main section instead
1719
raise BzrCommandError('Invalid master option: %r' % arg)
1720
argv.pop(0) # We are consuming this entry
1721
master_opts[arg] = True
1722
return argv, master_opts
1716
1726
def run_bzr(argv):
1717
1727
"""Execute a command.
1720
1730
logging and error handling.
1723
The command-line arguments, without the program name from argv[0]
1733
The command-line arguments, without the program name.
1725
1735
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
1737
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:
1739
# some options like --builtin and --no-plugins have special effects
1740
argv, master_opts = _parse_master_args(argv)
1741
if not master_opts['no-plugins']:
1761
1742
from bzrlib.plugin import load_plugins
1764
1745
args, opts = parse_args(argv)
1747
if master_opts.get('help') or 'help' in opts:
1767
1748
from bzrlib.help import help
1759
if args and args[0] == 'builtin':
1760
include_plugins=False
1764
cmd = str(args.pop(0))
1779
1766
print >>sys.stderr, "please try 'bzr help' for help"
1782
cmd = str(args.pop(0))
1784
canonical_cmd, cmd_class = \
1785
get_cmd_class(cmd, plugins_override=not opt_builtin)
1769
plugins_override = not (master_opts['builtin'])
1770
canonical_cmd, cmd_class = get_cmd_class(cmd, plugins_override=plugins_override)
1772
profile = master_opts['profile']
1773
# For backwards compatibility, I would rather stick with --profile being a
1774
# master/global option
1775
if 'profile' in opts:
1787
1779
# check options are reasonable
1788
1780
allowed = cmd_class.takes_options