22
from bzrlib.trace import mutter, note, log_error, warning
22
from bzrlib.trace import mutter, note, log_error
23
23
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError
24
24
from bzrlib.branch import find_branch
25
25
from bzrlib import BZRDIR
51
51
assert cmd.startswith("cmd_")
52
52
return cmd[4:].replace('_','-')
55
54
def _parse_revision_str(revstr):
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')
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' -> ?
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('..'):
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])
332
296
directory is shown. Otherwise, only the status of the specified
333
297
files or directories is reported. If a directory is given, status
334
298
is reported for everything inside that directory.
336
If a revision is specified, the changes since that revision are shown.
338
300
takes_args = ['file*']
339
takes_options = ['all', 'show-ids', 'revision']
301
takes_options = ['all', 'show-ids']
340
302
aliases = ['st', 'stat']
342
304
def run(self, all=False, show_ids=False, file_list=None):
351
313
b = find_branch('.')
353
from bzrlib.status import show_status
354
show_status(b, show_unchanged=all, show_ids=show_ids,
355
specific_files=file_list)
315
status.show_status(b, show_unchanged=all, show_ids=show_ids,
316
specific_files=file_list)
358
319
class cmd_cat_revision(Command):
374
335
print find_branch('.').revno()
376
class cmd_revision_info(Command):
377
"""Show revision number and revision id for a given revision identifier.
380
takes_args = ['revision_info*']
381
takes_options = ['revision']
382
def run(self, revision=None, revision_info_list=None):
383
from bzrlib.branch import find_branch
386
if revision is not None:
387
revs.extend(revision)
388
if revision_info_list is not None:
389
revs.extend(revision_info_list)
391
raise BzrCommandError('You must supply a revision identifier')
396
print '%4d %s' % b.get_revision_info(rev)
399
338
class cmd_add(Command):
400
339
"""Add specified files or directories.
462
401
if revision == None:
463
402
inv = b.read_working_inventory()
465
if len(revision) > 1:
466
raise BzrCommandError('bzr inventory --revision takes'
467
' exactly one revision identifier')
468
inv = b.get_revision_inventory(b.lookup_revision(revision[0]))
404
inv = b.get_revision_inventory(b.lookup_revision(revision))
470
406
for path, entry in inv.entries():
626
556
br_to = Branch(to_location, init=True)
628
br_to.set_root_id(br_from.get_root_id())
631
if revision[0] is None:
632
revno = br_from.revno()
634
revno, rev_id = br_from.get_revision_info(revision[0])
636
br_to.update_revisions(br_from, stop_revision=revno)
637
except NoSuchRevision:
639
msg = "The branch %s has no revision %d." % (from_location,
641
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)
643
565
merge((to_location, -1), (to_location, 0), this_dir=to_location,
644
566
check_clean=False, ignore_zero=True)
645
567
from_location = pull_loc(br_from)
815
737
b = find_branch('.')
817
# TODO: Make show_diff support taking 2 arguments
819
if revision is not None:
820
if len(revision) != 1:
821
raise BzrCommandError('bzr diff --revision takes exactly one revision identifier')
822
base_rev = revision[0]
824
show_diff(b, base_rev, specific_files=file_list,
739
show_diff(b, revision, specific_files=file_list,
825
740
external_diff_options=diff_options)
855
770
"""List files modified in working tree."""
858
from bzrlib.diff import compare_trees
773
from bzrlib.statcache import update_cache, SC_SHA1
860
774
b = find_branch('.')
861
td = compare_trees(b.basis_tree(), b.working_tree())
775
inv = b.read_working_inventory()
776
sc = update_cache(b, inv)
777
basis = b.basis_tree()
778
basis_inv = basis.inventory
780
# We used to do this through iter_entries(), but that's slow
781
# when most of the files are unmodified, as is usually the
782
# case. So instead we iterate by inventory entry, and only
783
# calculate paths as necessary.
863
for path, id, kind in td.modified:
785
for file_id in basis_inv:
786
cacheentry = sc.get(file_id)
787
if not cacheentry: # deleted
789
ie = basis_inv[file_id]
790
if cacheentry[SC_SHA1] != ie.text_sha1:
791
path = inv.id2path(file_id)
902
830
-r revision requests a specific revision, -r :end or -r begin: are
905
--message allows you to give a regular expression, which will be evaluated
906
so that only matching entries will be displayed.
908
833
TODO: Make --revision support uuid: and hash: [future tag:] notation.
912
837
takes_args = ['filename?']
913
takes_options = ['forward', 'timezone', 'verbose', 'show-ids', 'revision','long', 'message']
838
takes_options = ['forward', 'timezone', 'verbose', 'show-ids', 'revision','long']
915
840
def run(self, filename=None, timezone='original',
922
846
from bzrlib.branch import find_branch
923
847
from bzrlib.log import log_formatter, show_log
936
860
b = find_branch('.')
942
elif len(revision) == 1:
943
rev1 = rev2 = b.get_revision_info(revision[0])[0]
944
elif len(revision) == 2:
945
rev1 = b.get_revision_info(revision[0])[0]
946
rev2 = b.get_revision_info(revision[1])[0]
864
revision = [None, None]
865
elif isinstance(revision, int):
866
revision = [revision, revision]
948
raise BzrCommandError('bzr log --revision takes one or two values.')
871
assert len(revision) == 2
955
873
mutter('encoding log as %r' % bzrlib.user_encoding)
1125
1042
If no revision is specified this exports the last committed revision.
1127
1044
Format may be an "exporter" name, such as tar, tgz, tbz2. If none is
1128
given, try to find the format with the extension. If no extension
1129
is found exports to a directory (equivalent to --format=dir).
1045
given, exports to a directory (equivalent to --format=dir).
1131
Root may be the top directory for tar, tgz and tbz2 formats. If none
1132
is given, the top directory will be the root name of the file."""
1047
Root may be the top directory for tar, tgz and tbz2 formats."""
1133
1048
# TODO: list known exporters
1134
1049
takes_args = ['dest']
1135
1050
takes_options = ['revision', 'format', 'root']
1136
def run(self, dest, revision=None, format=None, root=None):
1051
def run(self, dest, revision=None, format='dir', root=None):
1138
1052
b = find_branch('.')
1139
if revision is None:
1140
rev_id = b.last_patch()
1053
if revision == None:
1054
rh = b.revision_history()[-1]
1142
if len(revision) != 1:
1143
raise BzrError('bzr export --revision takes exactly 1 argument')
1144
revno, rev_id = b.get_revision_info(revision[0])
1145
t = b.revision_tree(rev_id)
1146
root, ext = os.path.splitext(dest)
1148
if ext in (".tar",):
1150
elif ext in (".gz", ".tgz"):
1152
elif ext in (".bz2", ".tbz2"):
1056
rh = b.lookup_revision(int(revision))
1057
t = b.revision_tree(rh)
1156
1058
t.export(dest, format, root)
1165
1067
def run(self, filename, revision=None):
1166
1068
if revision == None:
1167
1069
raise BzrCommandError("bzr cat requires a revision number")
1168
elif len(revision) != 1:
1169
raise BzrCommandError("bzr cat --revision takes exactly one number")
1170
1070
b = find_branch('.')
1171
b.print_file(b.relpath(filename), revision[0])
1071
b.print_file(b.relpath(filename), int(revision))
1174
1074
class cmd_local_time_offset(Command):
1195
1095
TODO: Strict commit that fails if there are unknown or deleted files.
1197
1097
takes_args = ['selected*']
1198
takes_options = ['message', 'file', 'verbose', 'unchanged']
1098
takes_options = ['message', 'file', 'verbose']
1199
1099
aliases = ['ci', 'checkin']
1201
def run(self, message=None, file=None, verbose=True, selected_list=None,
1203
from bzrlib.errors import PointlessCommit
1101
def run(self, message=None, file=None, verbose=True, selected_list=None):
1102
from bzrlib.commit import commit
1204
1103
from bzrlib.osutils import get_text_message
1206
1105
## Warning: shadows builtin file()
1225
1124
message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1227
1126
b = find_branch('.')
1230
b.commit(message, verbose=verbose,
1231
specific_files=selected_list,
1232
allow_pointless=unchanged)
1233
except PointlessCommit:
1234
# FIXME: This should really happen before the file is read in;
1235
# perhaps prepare the commit; get the message; then actually commit
1236
raise BzrCommandError("no changes to commit",
1237
["use --unchanged to commit anyhow"])
1127
commit(b, message, verbose=verbose, specific_files=selected_list)
1240
1130
class cmd_check(Command):
1257
class cmd_scan_cache(Command):
1260
from bzrlib.hashcache import HashCache
1267
print '%6d stats' % c.stat_count
1268
print '%6d in hashcache' % len(c._cache)
1269
print '%6d files removed from cache' % c.removed_count
1270
print '%6d hashes updated' % c.update_count
1271
print '%6d files changed too recently to cache' % c.danger_count
1278
1147
class cmd_upgrade(Command):
1279
1148
"""Upgrade branch storage to current format.
1303
1172
class cmd_selftest(Command):
1304
1173
"""Run internal test suite"""
1306
takes_options = ['verbose']
1307
def run(self, verbose=False):
1308
1176
from bzrlib.selftest import selftest
1309
return int(not selftest(verbose=verbose))
1177
return int(not selftest())
1312
1180
class cmd_version(Command):
1425
1287
takes_options = ['revision']
1427
def run(self, revision=None):
1289
def run(self, revision=-1):
1428
1290
from bzrlib.merge import merge
1429
if revision is None:
1431
elif len(revision) != 1:
1432
raise BzrCommandError('bzr merge-revert --revision takes exactly 1 argument')
1433
merge(('.', revision[0]), parse_spec('.'),
1291
merge(('.', revision), parse_spec('.'),
1434
1292
check_clean=False,
1435
1293
ignore_zero=True)
1463
1331
import bzrlib.plugin
1464
from inspect import getdoc
1465
1332
from pprint import pprint
1466
for plugin in bzrlib.plugin.all_plugins:
1467
print plugin.__path__[0]
1470
print '\t', d.split('\n')[0]
1472
#pprint(bzrlib.plugin.all_plugins)
1333
pprint(bzrlib.plugin.all_plugins)
1526
1386
>>> parse_args('commit --message=biter'.split())
1527
1387
(['commit'], {'message': u'biter'})
1528
1388
>>> parse_args('log -r 500'.split())
1529
(['log'], {'revision': [500]})
1530
>>> parse_args('log -r500..600'.split())
1389
(['log'], {'revision': 500})
1390
>>> parse_args('log -r500:600'.split())
1531
1391
(['log'], {'revision': [500, 600]})
1532
>>> parse_args('log -vr500..600'.split())
1392
>>> parse_args('log -vr500:600'.split())
1533
1393
(['log'], {'verbose': True, 'revision': [500, 600]})
1534
>>> parse_args('log -rv500..600'.split()) #the r takes an argument
1535
(['log'], {'revision': ['v500', 600]})
1394
>>> parse_args('log -rv500:600'.split()) #the r takes an argument
1395
Traceback (most recent call last):
1397
ValueError: invalid literal for int(): v500