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.
35
from bzrlib.trace import mutter, note, log_error, warning
36
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError
37
from bzrlib.branch import find_branch
38
from bzrlib import BZRDIR
44
def register_command(cmd):
45
"Utility function to help register a command"
48
if k.startswith("cmd_"):
49
k_unsquished = _unsquish_command_name(k)
52
if not plugin_cmds.has_key(k_unsquished):
53
plugin_cmds[k_unsquished] = cmd
55
log_error('Two plugins defined the same command: %r' % k)
56
log_error('Not loading the one in %r' % sys.modules[cmd.__module__])
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, \
59
29
def _squish_command_name(cmd):
64
34
assert cmd.startswith("cmd_")
65
35
return cmd[4:].replace('_','-')
68
37
def _parse_revision_str(revstr):
69
"""This handles a revision string -> revno.
71
This always returns a list. The list will have one element for
73
It supports integers directly, but everything else it
74
defers for passing to Branch.get_revision_info()
76
>>> _parse_revision_str('234')
78
>>> _parse_revision_str('234..567')
80
>>> _parse_revision_str('..')
82
>>> _parse_revision_str('..234')
84
>>> _parse_revision_str('234..')
86
>>> _parse_revision_str('234..456..789') # Maybe this should be an error
88
>>> _parse_revision_str('234....789') # Error?
90
>>> _parse_revision_str('revid:test@other.com-234234')
91
['revid:test@other.com-234234']
92
>>> _parse_revision_str('revid:test@other.com-234234..revid:test@other.com-234235')
93
['revid:test@other.com-234234', 'revid:test@other.com-234235']
94
>>> _parse_revision_str('revid:test@other.com-234234..23')
95
['revid:test@other.com-234234', 23]
96
>>> _parse_revision_str('date:2005-04-12')
98
>>> _parse_revision_str('date:2005-04-12 12:24:33')
99
['date:2005-04-12 12:24:33']
100
>>> _parse_revision_str('date:2005-04-12T12:24:33')
101
['date:2005-04-12T12:24:33']
102
>>> _parse_revision_str('date:2005-04-12,12:24:33')
103
['date:2005-04-12,12:24:33']
104
>>> _parse_revision_str('-5..23')
106
>>> _parse_revision_str('-5')
108
>>> _parse_revision_str('123a')
110
>>> _parse_revision_str('abc')
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' -> ?
114
old_format_re = re.compile('\d*:\d*')
115
m = old_format_re.match(revstr)
117
warning('Colon separator for revision numbers is deprecated.'
120
for rev in revstr.split(':'):
122
revs.append(int(rev))
127
for x in revstr.split('..'):
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])
138
def get_merge_type(typestring):
139
"""Attempt to find the merge class/factory associated with a string."""
140
from merge import merge_types
142
return merge_types[typestring][0]
144
templ = '%s%%7s: %%s' % (' '*12)
145
lines = [templ % (f[0], f[1][1]) for f in merge_types.iteritems()]
146
type_list = '\n'.join(lines)
147
msg = "No known merge type %s. Supported types are:\n%s" %\
148
(typestring, type_list)
149
raise BzrCommandError(msg)
152
def get_merge_type(typestring):
153
"""Attempt to find the merge class/factory associated with a string."""
154
from merge import merge_types
156
return merge_types[typestring][0]
158
templ = '%s%%7s: %%s' % (' '*12)
159
lines = [templ % (f[0], f[1][1]) for f in merge_types.iteritems()]
160
type_list = '\n'.join(lines)
161
msg = "No known merge type %s. Supported types are:\n%s" %\
162
(typestring, type_list)
163
raise BzrCommandError(msg)
167
def _get_cmd_dict(plugins_override=True):
72
"""Return canonical name and class for all registered commands."""
169
73
for k, v in globals().iteritems():
170
74
if k.startswith("cmd_"):
171
d[_unsquish_command_name(k)] = v
172
# If we didn't load plugins, the plugin_cmds dict will be empty
174
d.update(plugin_cmds)
176
d2 = plugin_cmds.copy()
182
def get_all_cmds(plugins_override=True):
183
"""Return canonical name and class for all registered commands."""
184
for k, v in _get_cmd_dict(plugins_override=plugins_override).iteritems():
188
def get_cmd_class(cmd, plugins_override=True):
75
yield _unsquish_command_name(k), v
77
def get_cmd_class(cmd):
189
78
"""Return the canonical name and command class for a command.
191
80
cmd = str(cmd) # not unicode
193
82
# first look up this command under the specified name
194
cmds = _get_cmd_dict(plugins_override=plugins_override)
196
return cmd, cmds[cmd]
84
return cmd, globals()[_squish_command_name(cmd)]
200
88
# look for any command which claims this as an alias
201
for cmdname, cmdclass in cmds.iteritems():
89
for cmdname, cmdclass in get_all_cmds():
202
90
if cmd in cmdclass.aliases:
203
91
return cmdname, cmdclass
264
149
class ExternalCommand(Command):
265
150
"""Class to wrap external commands.
267
We cheat a little here, when get_cmd_class() calls us we actually
268
give it back an object we construct that has the appropriate path,
269
help, options etc for the specified command.
271
When run_bzr() tries to instantiate that 'class' it gets caught by
272
the __call__ method, which we override to call the Command.__init__
273
method. That then calls our run method which is pretty straight
276
The only wrinkle is that we have to map bzr's dictionary of options
277
and arguments back into command line options and arguments for the
152
We cheat a little here, when get_cmd_class() calls us we actually give it back
153
an object we construct that has the appropriate path, help, options etc for the
156
When run_bzr() tries to instantiate that 'class' it gets caught by the __call__
157
method, which we override to call the Command.__init__ method. That then calls
158
our run method which is pretty straight forward.
160
The only wrinkle is that we have to map bzr's dictionary of options and arguments
161
back into command line options and arguments for the script.
281
164
def find_command(cls, cmd):
283
166
bzrpath = os.environ.get('BZRPATH', '')
285
for dir in bzrpath.split(os.pathsep):
168
for dir in bzrpath.split(':'):
286
169
path = os.path.join(dir, cmd)
287
170
if os.path.isfile(path):
288
171
return ExternalCommand(path)
294
177
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.
297
183
pipe = os.popen('%s --bzr-usage' % path, 'r')
298
184
self.takes_options = pipe.readline().split()
300
for opt in self.takes_options:
301
if not opt in OPTIONS:
302
raise BzrError("Unknown option '%s' returned by external command %s"
305
# TODO: Is there any way to check takes_args is valid here?
306
185
self.takes_args = pipe.readline().split()
308
if pipe.close() is not None:
309
raise BzrError("Failed funning '%s --bzr-usage'" % path)
311
188
pipe = os.popen('%s --bzr-help' % path, 'r')
312
189
self.__doc__ = pipe.read()
313
if pipe.close() is not None:
314
raise BzrError("Failed funning '%s --bzr-help'" % path)
316
192
def __call__(self, options, arguments):
317
193
Command.__init__(self, options, arguments)
378
253
directory is shown. Otherwise, only the status of the specified
379
254
files or directories is reported. If a directory is given, status
380
255
is reported for everything inside that directory.
382
If a revision is specified, the changes since that revision are shown.
384
257
takes_args = ['file*']
385
takes_options = ['all', 'show-ids', 'revision']
258
takes_options = ['all', 'show-ids']
386
259
aliases = ['st', 'stat']
388
261
def run(self, all=False, show_ids=False, file_list=None):
390
b = find_branch(file_list[0])
263
b = Branch(file_list[0])
391
264
file_list = [b.relpath(x) for x in file_list]
392
265
# special case: only one path was given and it's the root
394
267
if file_list == ['']:
399
from bzrlib.status import show_status
400
show_status(b, show_unchanged=all, show_ids=show_ids,
401
specific_files=file_list)
272
status.show_status(b, show_unchanged=all, show_ids=show_ids,
273
specific_files=file_list)
404
276
class cmd_cat_revision(Command):
455
304
whether already versioned or not, are searched for files or
456
305
subdirectories that are neither versioned or ignored, and these
457
306
are added. This search proceeds recursively into versioned
458
directories. If no names are given '.' is assumed.
460
Therefore simply saying 'bzr add' will version all files that
309
Therefore simply saying 'bzr add .' will version all files that
461
310
are currently unknown.
463
312
TODO: Perhaps adding a file whose directly is not versioned should
464
313
recursively add that parent, rather than giving an error?
466
takes_args = ['file*']
315
takes_args = ['file+']
467
316
takes_options = ['verbose', 'no-recurse']
469
318
def run(self, file_list, verbose=False, no_recurse=False):
470
from bzrlib.add import smart_add
472
recurse = not no_recurse
473
for path, kind, file_id in smart_add(file_list, verbose, recurse):
478
class cmd_mkdir(Command):
479
"""Create a new versioned directory.
481
This is equivalent to creating the directory and then adding it.
483
takes_args = ['dir+']
485
def run(self, dir_list):
319
bzrlib.add.smart_add(file_list, verbose, not no_recurse)
496
322
class cmd_relpath(Command):
557
379
takes_args = ['from_name', 'to_name']
559
381
def run(self, from_name, to_name):
561
383
b.rename_one(b.relpath(from_name), b.relpath(to_name))
565
class cmd_mv(Command):
566
"""Move or rename a file.
569
bzr mv OLDNAME NEWNAME
570
bzr mv SOURCE... DESTINATION
572
If the last argument is a versioned directory, all the other names
573
are moved into it. Otherwise, there must be exactly two arguments
574
and the file is changed to a new name, which must not already exist.
576
Files cannot be moved between branches.
578
takes_args = ['names*']
579
def run(self, names_list):
580
if len(names_list) < 2:
581
raise BzrCommandError("missing file argument")
582
b = find_branch(names_list[0])
584
rel_names = [b.relpath(x) for x in names_list]
586
if os.path.isdir(names_list[-1]):
587
# move into existing directory
588
for pair in b.move(rel_names[:-1], rel_names[-1]):
589
print "%s => %s" % pair
591
if len(names_list) != 2:
592
raise BzrCommandError('to mv multiple files the destination '
593
'must be a versioned directory')
594
for pair in b.move(rel_names[0], rel_names[1]):
595
print "%s => %s" % pair
600
class cmd_pull(Command):
601
"""Pull any changes from another branch into the current one.
603
If the location is omitted, the last-used location will be used.
604
Both the revision history and the working directory will be
607
This command only works on branches that have not diverged. Branches are
608
considered diverged if both branches have had commits without first
609
pulling from the other.
611
If branches have diverged, you can use 'bzr merge' to pull the text changes
612
from one into the other.
614
takes_args = ['location?']
616
def run(self, location=None):
617
from bzrlib.merge import merge
619
from shutil import rmtree
622
br_to = find_branch('.')
625
stored_loc = br_to.controlfile("x-pull", "rb").read().rstrip('\n')
627
if e.errno != errno.ENOENT:
630
if stored_loc is None:
631
raise BzrCommandError("No pull location known or specified.")
633
print "Using last location: %s" % stored_loc
634
location = stored_loc
635
cache_root = tempfile.mkdtemp()
636
from bzrlib.branch import DivergedBranches
637
br_from = find_branch(location)
638
location = pull_loc(br_from)
639
old_revno = br_to.revno()
641
from branch import find_cached_branch, DivergedBranches
642
br_from = find_cached_branch(location, cache_root)
643
location = pull_loc(br_from)
644
old_revno = br_to.revno()
646
br_to.update_revisions(br_from)
647
except DivergedBranches:
648
raise BzrCommandError("These branches have diverged."
651
merge(('.', -1), ('.', old_revno), check_clean=False)
652
if location != stored_loc:
653
br_to.controlfile("x-pull", "wb").write(location + "\n")
659
class cmd_branch(Command):
660
"""Create a new copy of a branch.
662
If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
663
be used. In other words, "branch ../foo/bar" will attempt to create ./bar.
665
To retrieve the branch as of a particular revision, supply the --revision
666
parameter, as in "branch foo/bar -r 5".
668
takes_args = ['from_location', 'to_location?']
669
takes_options = ['revision']
670
aliases = ['get', 'clone']
672
def run(self, from_location, to_location=None, revision=None):
674
from bzrlib.merge import merge
675
from bzrlib.branch import DivergedBranches, \
676
find_cached_branch, Branch
677
from shutil import rmtree
678
from meta_store import CachedStore
680
cache_root = tempfile.mkdtemp()
684
elif len(revision) > 1:
685
raise BzrCommandError('bzr branch --revision takes exactly 1 revision value')
689
br_from = find_cached_branch(from_location, cache_root)
691
if e.errno == errno.ENOENT:
692
raise BzrCommandError('Source location "%s" does not'
693
' exist.' % to_location)
697
if to_location is None:
698
to_location = os.path.basename(from_location.rstrip("/\\"))
701
os.mkdir(to_location)
703
if e.errno == errno.EEXIST:
704
raise BzrCommandError('Target directory "%s" already'
705
' exists.' % to_location)
706
if e.errno == errno.ENOENT:
707
raise BzrCommandError('Parent of "%s" does not exist.' %
711
br_to = Branch(to_location, init=True)
713
br_to.set_root_id(br_from.get_root_id())
716
if revision[0] is None:
717
revno = br_from.revno()
719
revno, rev_id = br_from.get_revision_info(revision[0])
721
br_to.update_revisions(br_from, stop_revision=revno)
722
except bzrlib.errors.NoSuchRevision:
724
msg = "The branch %s has no revision %d." % (from_location,
726
raise BzrCommandError(msg)
728
merge((to_location, -1), (to_location, 0), this_dir=to_location,
729
check_clean=False, ignore_zero=True)
730
from_location = pull_loc(br_from)
731
br_to.controlfile("x-pull", "wb").write(from_location + "\n")
736
def pull_loc(branch):
737
# TODO: Should perhaps just make attribute be 'base' in
738
# RemoteBranch and Branch?
739
if hasattr(branch, "baseurl"):
740
return branch.baseurl
746
387
class cmd_renames(Command):
747
388
"""Show list of renamed files.
946
575
"""List files modified in working tree."""
949
from bzrlib.delta import compare_trees
952
td = compare_trees(b.basis_tree(), b.working_tree())
954
for path, id, kind in td.modified:
580
inv = b.read_working_inventory()
581
sc = statcache.update_cache(b, inv)
582
basis = b.basis_tree()
583
basis_inv = basis.inventory
585
# We used to do this through iter_entries(), but that's slow
586
# when most of the files are unmodified, as is usually the
587
# case. So instead we iterate by inventory entry, and only
588
# calculate paths as necessary.
590
for file_id in basis_inv:
591
cacheentry = sc.get(file_id)
592
if not cacheentry: # deleted
594
ie = basis_inv[file_id]
595
if cacheentry[statcache.SC_SHA1] != ie.text_sha1:
596
path = inv.id2path(file_id)
993
636
-r revision requests a specific revision, -r :end or -r begin: are
996
--message allows you to give a regular expression, which will be evaluated
997
so that only matching entries will be displayed.
999
639
TODO: Make --revision support uuid: and hash: [future tag:] notation.
1003
643
takes_args = ['filename?']
1004
takes_options = ['forward', 'timezone', 'verbose', 'show-ids', 'revision',
1005
'long', 'message', 'short',]
644
takes_options = ['forward', 'timezone', 'verbose', 'show-ids', 'revision']
1007
646
def run(self, filename=None, timezone='original',
1015
from bzrlib.branch import find_branch
1016
from bzrlib.log import log_formatter, show_log
651
from bzrlib import show_log, find_branch
1019
654
direction = (forward and 'forward') or 'reverse'
1209
828
except ValueError:
1210
829
raise BzrCommandError("not a valid revision-number: %r" % revno)
1212
print find_branch('.').lookup_revision(revno)
831
print Branch('.').lookup_revision(revno)
1215
834
class cmd_export(Command):
1216
835
"""Export past revision to destination directory.
1218
If no revision is specified this exports the last committed revision.
1220
Format may be an "exporter" name, such as tar, tgz, tbz2. If none is
1221
given, try to find the format with the extension. If no extension
1222
is found exports to a directory (equivalent to --format=dir).
1224
Root may be the top directory for tar, tgz and tbz2 formats. If none
1225
is given, the top directory will be the root name of the file."""
1226
# TODO: list known exporters
837
If no revision is specified this exports the last committed revision."""
1227
838
takes_args = ['dest']
1228
takes_options = ['revision', 'format', 'root']
1229
def run(self, dest, revision=None, format=None, root=None):
1231
b = find_branch('.')
1232
if revision is None:
1233
rev_id = b.last_patch()
839
takes_options = ['revision']
840
def run(self, dest, revision=None):
843
rh = b.revision_history()[-1]
1235
if len(revision) != 1:
1236
raise BzrError('bzr export --revision takes exactly 1 argument')
1237
revno, rev_id = b.get_revision_info(revision[0])
1238
t = b.revision_tree(rev_id)
1239
root, ext = os.path.splitext(dest)
1241
if ext in (".tar",):
1243
elif ext in (".gz", ".tgz"):
1245
elif ext in (".bz2", ".tbz2"):
1249
t.export(dest, format, root)
845
rh = b.lookup_revision(int(revision))
846
t = b.revision_tree(rh)
1252
850
class cmd_cat(Command):
1290
884
TODO: Strict commit that fails if there are unknown or deleted files.
1292
886
takes_args = ['selected*']
1293
takes_options = ['message', 'file', 'verbose', 'unchanged']
887
takes_options = ['message', 'file', 'verbose']
1294
888
aliases = ['ci', 'checkin']
1296
# TODO: Give better message for -s, --summary, used by tla people
1298
def run(self, message=None, file=None, verbose=True, selected_list=None,
1300
from bzrlib.errors import PointlessCommit
1301
from bzrlib.osutils import get_text_message
890
def run(self, message=None, file=None, verbose=True, selected_list=None):
891
from bzrlib.commit import commit
1303
893
## Warning: shadows builtin file()
1304
894
if not message and not file:
1305
# FIXME: Ugly; change status code to send to a provided function?
1309
catcher = cStringIO.StringIO()
1310
sys.stdout = catcher
1311
cmd_status({"file_list":selected_list}, {})
1312
info = catcher.getvalue()
1314
message = get_text_message(info)
1317
raise BzrCommandError("please specify a commit message",
1318
["use either --message or --file"])
895
raise BzrCommandError("please specify a commit message",
896
["use either --message or --file"])
1319
897
elif message and file:
1320
898
raise BzrCommandError("please specify either --message or --file")
1344
911
This command checks various invariants about the branch storage to
1345
912
detect data corruption or bzr bugs.
1347
If given the --update flag, it will update some optional fields
1348
to help ensure data consistency.
1350
takes_args = ['dir?']
1352
def run(self, dir='.'):
1353
from bzrlib.check import check
1355
check(find_branch(dir))
1358
class cmd_scan_cache(Command):
1361
from bzrlib.hashcache import HashCache
1368
print '%6d stats' % c.stat_count
1369
print '%6d in hashcache' % len(c._cache)
1370
print '%6d files removed from cache' % c.removed_count
1371
print '%6d hashes updated' % c.update_count
1372
print '%6d files changed too recently to cache' % c.danger_count
1379
class cmd_upgrade(Command):
1380
"""Upgrade branch storage to current format.
1382
The check command or bzr developers may sometimes advise you to run
1385
takes_args = ['dir?']
1387
def run(self, dir='.'):
1388
from bzrlib.upgrade import upgrade
1389
upgrade(find_branch(dir))
914
takes_args = ['dir?']
915
def run(self, dir='.'):
917
bzrlib.check.check(Branch(dir))
1395
923
takes_options = ['email']
1397
925
def run(self, email=False):
1399
b = bzrlib.branch.find_branch('.')
1404
print bzrlib.osutils.user_email(b)
927
print bzrlib.osutils.user_email()
1406
print bzrlib.osutils.username(b)
929
print bzrlib.osutils.username()
1409
932
class cmd_selftest(Command):
1410
933
"""Run internal test suite"""
1412
takes_options = ['verbose']
1413
def run(self, verbose=False):
1415
936
from bzrlib.selftest import selftest
1417
# we don't want progress meters from the tests to go to the
1418
# real output; and we don't want log messages cluttering up
1421
save_ui = bzrlib.ui.ui_factory
1422
bzrlib.trace.info('running tests...')
1424
bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
1425
result = selftest(verbose=verbose)
1427
bzrlib.trace.info('tests passed')
1429
bzrlib.trace.info('tests failed')
1430
return int(not result)
1432
bzrlib.ui.ui_factory = save_ui
1435
944
class cmd_version(Command):
1436
"""Show version of bzr."""
945
"""Show version of bzr"""
1458
967
print "it sure does!"
1460
969
def parse_spec(spec):
1462
>>> parse_spec(None)
1464
>>> parse_spec("./")
1466
>>> parse_spec("../@")
1468
>>> parse_spec("../f/@35")
1470
>>> parse_spec('./@revid:john@arbash-meinel.com-20050711044610-3ca0327c6a222f67')
1471
['.', 'revid:john@arbash-meinel.com-20050711044610-3ca0327c6a222f67']
1475
970
if '/@' in spec:
1476
971
parsed = spec.split('/@')
1477
972
assert len(parsed) == 2
1478
973
if parsed[1] == "":
1482
parsed[1] = int(parsed[1])
1484
pass # We can allow stuff like ./@revid:blahblahblah
1486
assert parsed[1] >=0
976
parsed[1] = int(parsed[1])
1488
979
parsed = [spec, None]
1493
class cmd_find_merge_base(Command):
1494
"""Find and print a base revision for merging two branches.
1496
TODO: Options to specify revisions on either side, as if
1497
merging only part of the history.
1499
takes_args = ['branch', 'other']
1502
def run(self, branch, other):
1503
branch1 = find_branch(branch)
1504
branch2 = find_branch(other)
1506
base_revno, base_revid = branch1.common_ancestor(branch2)
1508
if base_revno is None:
1509
raise bzrlib.errors.UnrelatedBranches()
1511
print 'merge base is revision %s' % base_revid
1512
print ' r%-6d in %s' % (base_revno, branch)
1514
other_revno = branch2.revision_id_to_revno(base_revid)
1516
print ' r%-6d in %s' % (other_revno, other)
1520
982
class cmd_merge(Command):
1521
"""Perform a three-way merge.
1523
The branch is the branch you will merge from. By default, it will merge
1524
the latest revision. If you specify a revision, that revision will be
1525
merged. If you specify two revisions, the first will be used as a BASE,
1526
and the second one as OTHER. Revision numbers are always relative to the
1531
To merge the latest revision from bzr.dev
1532
bzr merge ../bzr.dev
1534
To merge changes up to and including revision 82 from bzr.dev
1535
bzr merge -r 82 ../bzr.dev
1537
To merge the changes introduced by 82, without previous changes:
1538
bzr merge -r 81..82 ../bzr.dev
1540
merge refuses to run if there are any uncommitted changes, unless
1543
takes_args = ['branch?']
1544
takes_options = ['revision', 'force', 'merge-type']
1546
def run(self, branch='.', revision=None, force=False,
1548
from bzrlib.merge import merge
1549
from bzrlib.merge_core import ApplyMerge3
1550
if merge_type is None:
1551
merge_type = ApplyMerge3
1553
if revision is None or len(revision) < 1:
1555
other = (branch, -1)
1557
if len(revision) == 1:
1558
other = (branch, revision[0])
1561
assert len(revision) == 2
1562
if None in revision:
1563
raise BzrCommandError(
1564
"Merge doesn't permit that revision specifier.")
1565
base = (branch, revision[0])
1566
other = (branch, revision[1])
1568
merge(other, base, check_clean=(not force), merge_type=merge_type)
1571
class cmd_revert(Command):
1572
"""Reverse all changes since the last commit.
1574
Only versioned files are affected. Specify filenames to revert only
1575
those files. By default, any files that are changed will be backed up
1576
first. Backup files have a '~' appended to their name.
1578
takes_options = ['revision', 'no-backup']
1579
takes_args = ['file*']
1580
aliases = ['merge-revert']
1582
def run(self, revision=None, no_backup=False, file_list=None):
1583
from bzrlib.merge import merge
1584
if file_list is not None:
1585
if len(file_list) == 0:
1586
raise BzrCommandError("No files specified")
1587
if revision is None:
1589
elif len(revision) != 1:
1590
raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
1591
merge(('.', revision[0]), parse_spec('.'),
1594
backup_files=not no_backup,
1595
file_list=file_list)
983
"""Perform a three-way merge of trees."""
984
takes_args = ['other_spec', 'base_spec']
986
def run(self, other_spec, base_spec):
987
from bzrlib.merge import merge
988
merge(parse_spec(other_spec), parse_spec(base_spec))
1598
990
class cmd_assert_fail(Command):
1599
991
"""Test reporting of assertion failures"""
1606
998
"""Show help on a command or other topic.
1608
1000
For a list of all available commands, say 'bzr help commands'."""
1609
takes_options = ['long']
1610
1001
takes_args = ['topic?']
1611
1002
aliases = ['?']
1613
def run(self, topic=None, long=False):
1004
def run(self, topic=None):
1615
if topic is None and long:
1617
1006
help.help(topic)
1620
class cmd_shell_complete(Command):
1621
"""Show appropriate completions for context.
1623
For a list of all available commands, say 'bzr shell-complete'."""
1624
takes_args = ['context?']
1628
def run(self, context=None):
1629
import shellcomplete
1630
shellcomplete.shellcomplete(context)
1633
class cmd_missing(Command):
1634
"""What is missing in this branch relative to other branch.
1636
takes_args = ['remote?']
1637
aliases = ['mis', 'miss']
1638
# We don't have to add quiet to the list, because
1639
# unknown options are parsed as booleans
1640
takes_options = ['verbose', 'quiet']
1642
def run(self, remote=None, verbose=False, quiet=False):
1643
from bzrlib.branch import find_branch, DivergedBranches
1644
from bzrlib.errors import BzrCommandError
1645
from bzrlib.missing import get_parent, show_missing
1647
if verbose and quiet:
1648
raise BzrCommandError('Cannot pass both quiet and verbose')
1650
b = find_branch('.')
1651
parent = get_parent(b)
1654
raise BzrCommandError("No missing location known or specified.")
1657
print "Using last location: %s" % parent
1659
elif parent is None:
1660
# We only update x-pull if it did not exist, missing should not change the parent
1661
b.controlfile('x-pull', 'wb').write(remote + '\n')
1662
br_remote = find_branch(remote)
1664
return show_missing(b, br_remote, verbose=verbose, quiet=quiet)
1668
class cmd_plugins(Command):
1009
class cmd_update_stat_cache(Command):
1010
"""Update stat-cache mapping inodes to SHA-1 hashes.
1012
For testing only."""
1672
import bzrlib.plugin
1673
from inspect import getdoc
1674
from pprint import pprint
1675
for plugin in bzrlib.plugin.all_plugins:
1676
print plugin.__path__[0]
1679
print '\t', d.split('\n')[0]
1681
#pprint(bzrlib.plugin.all_plugins)
1017
statcache.update_cache(b.base, b.read_working_inventory())
1765
1083
optname = a[2:]
1766
1084
if optname not in OPTIONS:
1767
raise BzrError('unknown long option %r' % a)
1085
bailout('unknown long option %r' % a)
1769
1087
shortopt = a[1:]
1770
if shortopt in SHORT_OPTIONS:
1771
# Multi-character options must have a space to delimit
1773
optname = SHORT_OPTIONS[shortopt]
1775
# Single character short options, can be chained,
1776
# and have their value appended to their name
1778
if shortopt not in SHORT_OPTIONS:
1779
# We didn't find the multi-character name, and we
1780
# didn't find the single char name
1781
raise BzrError('unknown short option %r' % a)
1782
optname = SHORT_OPTIONS[shortopt]
1785
# There are extra things on this option
1786
# see if it is the value, or if it is another
1788
optargfn = OPTIONS[optname]
1789
if optargfn is None:
1790
# This option does not take an argument, so the
1791
# next entry is another short option, pack it back
1793
argv.insert(0, '-' + a[2:])
1795
# This option takes an argument, so pack it
1088
if shortopt not in SHORT_OPTIONS:
1089
bailout('unknown short option %r' % a)
1090
optname = SHORT_OPTIONS[shortopt]
1799
1092
if optname in opts:
1800
1093
# XXX: Do we ever want to support this, e.g. for -r?
1801
raise BzrError('repeated option %r' % a)
1094
bailout('repeated option %r' % a)
1803
1096
optargfn = OPTIONS[optname]
1805
1098
if optarg == None:
1807
raise BzrError('option %r needs an argument' % a)
1100
bailout('option %r needs an argument' % a)
1809
1102
optarg = argv.pop(0)
1810
1103
opts[optname] = optargfn(optarg)
1812
1105
if optarg != None:
1813
raise BzrError('option %r takes no argument' % optname)
1106
bailout('option %r takes no argument' % optname)
1814
1107
opts[optname] = True
1871
1164
This is similar to main(), but without all the trappings for
1872
1165
logging and error handling.
1875
The command-line arguments, without the program name from argv[0]
1877
Returns a command status or raises an exception.
1879
Special master options: these must come before the command because
1880
they control how the command is interpreted.
1883
Do not load plugin modules at all
1886
Only use builtin commands. (Plugins are still allowed to change
1890
Run under the Python profiler.
1893
1167
argv = [a.decode(bzrlib.user_encoding) for a in argv]
1895
opt_profile = opt_no_plugins = opt_builtin = False
1897
# --no-plugins is handled specially at a very early stage. We need
1898
# to load plugins before doing other command parsing so that they
1899
# can override commands, but this needs to happen first.
1902
if a == '--profile':
1904
elif a == '--no-plugins':
1905
opt_no_plugins = True
1906
elif a == '--builtin':
1912
if not opt_no_plugins:
1913
from bzrlib.plugin import load_plugins
1916
args, opts = parse_args(argv)
1919
from bzrlib.help import help
1926
if 'version' in opts:
1931
from bzrlib.help import help
1935
cmd = str(args.pop(0))
1937
canonical_cmd, cmd_class = \
1938
get_cmd_class(cmd, plugins_override=not opt_builtin)
1170
args, opts = parse_args(argv[1:])
1178
elif 'version' in opts:
1181
cmd = str(args.pop(0))
1188
canonical_cmd, cmd_class = get_cmd_class(cmd)
1191
if 'profile' in opts:
1940
1197
# check options are reasonable
1941
1198
allowed = cmd_class.takes_options
1975
1232
return cmd_class(cmdopts, cmdargs).status
1235
def _report_exception(summary, quiet=False):
1237
log_error('bzr: ' + summary)
1238
bzrlib.trace.log_exception()
1241
tb = sys.exc_info()[2]
1242
exinfo = traceback.extract_tb(tb)
1244
sys.stderr.write(' at %s:%d in %s()\n' % exinfo[-1][:3])
1245
sys.stderr.write(' see ~/.bzr.log for debug information\n')
1978
1249
def main(argv):
1981
bzrlib.trace.log_startup(argv)
1983
bzrlib.ui.ui_factory = bzrlib.ui.TextUIFactory()
1252
bzrlib.open_tracefile(argv)
1987
return run_bzr(argv[1:])
1989
# do this here inside the exception wrappers to catch EPIPE
1991
except BzrCommandError, e:
1992
# command line syntax error, etc
1996
bzrlib.trace.log_exception()
1998
except AssertionError, e:
1999
bzrlib.trace.log_exception('assertion failed: ' + str(e))
2001
except KeyboardInterrupt, e:
2002
bzrlib.trace.note('interrupted')
2004
except Exception, e:
2006
if (isinstance(e, IOError)
2007
and hasattr(e, 'errno')
2008
and e.errno == errno.EPIPE):
2009
bzrlib.trace.note('broken pipe')
2012
bzrlib.trace.log_exception()
1257
return run_bzr(argv)
1259
# do this here inside the exception wrappers to catch EPIPE
1262
quiet = isinstance(e, (BzrCommandError))
1263
_report_exception('error: ' + e.args[0], quiet=quiet)
1266
# some explanation or hints
1269
except AssertionError, e:
1270
msg = 'assertion failed'
1272
msg += ': ' + str(e)
1273
_report_exception(msg)
1275
except KeyboardInterrupt, e:
1276
_report_exception('interrupted', quiet=True)
1278
except Exception, e:
1280
if (isinstance(e, IOError)
1281
and hasattr(e, 'errno')
1282
and e.errno == errno.EPIPE):
1286
msg = str(e).rstrip('\n')
1287
_report_exception(msg, quiet)
1290
bzrlib.trace.close_trace()
2016
1293
if __name__ == '__main__':