22
22
import bzrlib.trace
23
23
from bzrlib.trace import mutter, note, log_error, warning
24
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError
25
from bzrlib.branch import find_branch
26
from bzrlib.revisionspec import RevisionSpec
24
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError, NotBranchError
25
from bzrlib.branch import Branch
27
26
from bzrlib import BZRDIR
28
27
from bzrlib.commands import Command
64
63
files or directories is reported. If a directory is given, status
65
64
is reported for everything inside that directory.
67
If a revision is specified, the changes since that revision are shown.
66
If a revision argument is given, the status is calculated against
67
that revision, or between two revisions if two are provided.
69
# XXX: FIXME: bzr status should accept a -r option to show changes
70
# relative to a revision, or between revisions
69
72
takes_args = ['file*']
70
takes_options = ['all', 'show-ids', 'revision']
73
takes_options = ['all', 'show-ids']
71
74
aliases = ['st', 'stat']
73
def run(self, all=False, show_ids=False, file_list=None):
76
def run(self, all=False, show_ids=False, file_list=None, revision=None):
75
b = find_branch(file_list[0])
78
b = Branch.open_containing(file_list[0])
76
79
file_list = [b.relpath(x) for x in file_list]
77
80
# special case: only one path was given and it's the root
79
82
if file_list == ['']:
85
b = Branch.open_containing('.')
84
87
from bzrlib.status import show_status
85
88
show_status(b, show_unchanged=all, show_ids=show_ids,
86
specific_files=file_list)
89
specific_files=file_list, revision=revision)
89
92
class cmd_cat_revision(Command):
90
"""Write out metadata for a revision."""
93
"""Write out metadata for a revision.
95
The revision to print can either be specified by a specific
96
revision identifier, or you can use --revision.
93
takes_args = ['revision_id']
100
takes_args = ['revision_id?']
101
takes_options = ['revision']
95
def run(self, revision_id):
97
sys.stdout.write(b.get_revision_xml_file(revision_id).read())
103
def run(self, revision_id=None, revision=None):
104
from bzrlib.revisionspec import RevisionSpec
106
if revision_id is not None and revision is not None:
107
raise BzrCommandError('You can only supply one of revision_id or --revision')
108
if revision_id is None and revision is None:
109
raise BzrCommandError('You must supply either --revision or a revision_id')
110
b = Branch.open_containing('.')
111
if revision_id is not None:
112
sys.stdout.write(b.get_revision_xml_file(revision_id).read())
113
elif revision is not None:
116
raise BzrCommandError('You cannot specify a NULL revision.')
117
revno, rev_id = rev.in_history(b)
118
sys.stdout.write(b.get_revision_xml_file(rev_id).read())
100
121
class cmd_revno(Command):
101
122
"""Show current revision number.
103
124
This is equal to the number of revisions on this branch."""
105
print find_branch('.').revno()
126
print Branch.open_containing('.').revno()
108
129
class cmd_revision_info(Command):
112
133
takes_args = ['revision_info*']
113
134
takes_options = ['revision']
114
def run(self, revision=None, revision_info_list=None):
115
from bzrlib.branch import find_branch
135
def run(self, revision=None, revision_info_list=[]):
136
from bzrlib.revisionspec import RevisionSpec
118
139
if revision is not None:
119
140
revs.extend(revision)
120
141
if revision_info_list is not None:
121
revs.extend(revision_info_list)
142
for rev in revision_info_list:
143
revs.append(RevisionSpec(rev))
122
144
if len(revs) == 0:
123
145
raise BzrCommandError('You must supply a revision identifier')
147
b = Branch.open_containing('.')
128
print '%4d %s' % RevisionSpec(b, rev)
150
revinfo = rev.in_history(b)
151
if revinfo.revno is None:
152
print ' %s' % revinfo.rev_id
154
print '%4d %s' % (revinfo.revno, revinfo.rev_id)
131
157
class cmd_add(Command):
146
172
Therefore simply saying 'bzr add' will version all files that
147
173
are currently unknown.
149
TODO: Perhaps adding a file whose directly is not versioned should
150
recursively add that parent, rather than giving an error?
175
Adding a file whose parent directory is not versioned will
176
implicitly add the parent, and so on up to the root. This means
177
you should never need to explictly add a directory, they'll just
178
get added when you add a file in the directory.
152
180
takes_args = ['file*']
153
181
takes_options = ['verbose', 'no-recurse']
192
220
takes_options = ['revision', 'show-ids']
194
222
def run(self, revision=None, show_ids=False):
223
b = Branch.open_containing('.')
197
225
inv = b.read_working_inventory()
199
227
if len(revision) > 1:
200
228
raise BzrCommandError('bzr inventory --revision takes'
201
229
' exactly one revision identifier')
202
inv = b.get_revision_inventory(b.lookup_revision(revision[0]))
230
inv = b.get_revision_inventory(revision[0].in_history(b).rev_id)
204
232
for path, entry in inv.entries():
317
340
print "Using last location: %s" % stored_loc
318
341
location = stored_loc
319
342
cache_root = tempfile.mkdtemp()
320
from bzrlib.branch import DivergedBranches
321
br_from = find_branch(location)
343
from bzrlib.errors import DivergedBranches
344
br_from = Branch.open_containing(location)
322
345
location = br_from.base
323
346
old_revno = br_to.revno()
325
from branch import find_cached_branch, DivergedBranches
326
br_from = find_cached_branch(location, cache_root)
348
from bzrlib.errors import DivergedBranches
349
br_from = Branch.open(location)
350
br_from.setup_caching(cache_root)
327
351
location = br_from.base
328
352
old_revno = br_to.revno()
349
373
To retrieve the branch as of a particular revision, supply the --revision
350
374
parameter, as in "branch foo/bar -r 5".
376
--basis is to speed up branching from remote branches. When specified, it
377
copies all the file-contents, inventory and revision data from the basis
378
branch before copying anything from the remote branch.
352
380
takes_args = ['from_location', 'to_location?']
353
takes_options = ['revision']
381
takes_options = ['revision', 'basis']
354
382
aliases = ['get', 'clone']
356
def run(self, from_location, to_location=None, revision=None):
357
from bzrlib.branch import copy_branch, find_cached_branch
384
def run(self, from_location, to_location=None, revision=None, basis=None):
385
from bzrlib.clone import copy_branch
360
388
from shutil import rmtree
366
394
raise BzrCommandError(
367
395
'bzr branch --revision takes exactly 1 revision value')
369
br_from = find_cached_branch(from_location, cache_root)
397
br_from = Branch.open(from_location)
370
398
except OSError, e:
371
399
if e.errno == errno.ENOENT:
372
400
raise BzrCommandError('Source location "%s" does not'
373
401
' exist.' % to_location)
404
br_from.setup_caching(cache_root)
405
if basis is not None:
406
basis_branch = Branch.open_containing(basis)
409
if len(revision) == 1 and revision[0] is not None:
410
revision_id = revision[0].in_history(br_from)[1]
376
413
if to_location is None:
377
414
to_location = os.path.basename(from_location.rstrip("/\\"))
390
copy_branch(br_from, to_location, revision[0])
427
copy_branch(br_from, to_location, revision_id, basis_branch)
391
428
except bzrlib.errors.NoSuchRevision:
392
429
rmtree(to_location)
393
430
msg = "The branch %s has no revision %d." % (from_location, revision[0])
394
431
raise BzrCommandError(msg)
432
except bzrlib.errors.UnlistableBranch:
433
msg = "The branch %s cannot be used as a --basis"
396
435
rmtree(cache_root)
480
519
"""Display list of revision ids on this branch."""
483
for patchid in find_branch('.').revision_history():
522
for patchid in Branch.open_containing('.').revision_history():
526
class cmd_ancestry(Command):
527
"""List all revisions merged into this branch."""
531
for revision_id in b.get_ancestry(b.last_revision()):
487
535
class cmd_directories(Command):
488
536
"""Display list of versioned directories in this branch."""
490
for name, ie in find_branch('.').read_working_inventory().directories():
538
for name, ie in Branch.open_containing('.').read_working_inventory().directories():
649
696
--message allows you to give a regular expression, which will be evaluated
650
697
so that only matching entries will be displayed.
652
TODO: Make --revision support uuid: and hash: [future tag:] notation.
700
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
656
702
takes_args = ['filename?']
657
703
takes_options = ['forward', 'timezone', 'verbose', 'show-ids', 'revision',
658
704
'long', 'message', 'short',]
671
717
direction = (forward and 'forward') or 'reverse'
674
b = find_branch(filename)
720
b = Branch.open_containing(filename)
675
721
fp = b.relpath(filename)
677
723
file_id = b.read_working_inventory().path2id(fp)
679
725
file_id = None # points to branch root
727
b = Branch.open_containing('.')
684
730
if revision is None:
687
733
elif len(revision) == 1:
688
rev1 = rev2 = RevisionSpec(b, revision[0]).revno
734
rev1 = rev2 = revision[0].in_history(b).revno
689
735
elif len(revision) == 2:
690
rev1 = RevisionSpec(b, revision[0]).revno
691
rev2 = RevisionSpec(b, revision[1]).revno
736
rev1 = revision[0].in_history(b).revno
737
rev2 = revision[1].in_history(b).revno
693
739
raise BzrCommandError('bzr log --revision takes one or two values.')
746
792
def run(self, revision=None, verbose=False):
793
b = Branch.open_containing('.')
748
794
if revision == None:
749
795
tree = b.working_tree()
751
tree = b.revision_tree(b.lookup_revision(revision))
753
for fp, fc, kind, fid in tree.list_files():
797
tree = b.revision_tree(revision.in_history(b).rev_id)
798
for fp, fc, kind, fid, entry in tree.list_files():
755
if kind == 'directory':
800
kindch = entry.kind_character()
762
801
print '%-8s %s%s' % (fc, fp, kindch)
880
919
takes_options = ['revision', 'format', 'root']
881
920
def run(self, dest, revision=None, format=None, root=None):
922
b = Branch.open_containing('.')
884
923
if revision is None:
885
rev_id = b.last_patch()
924
rev_id = b.last_revision()
887
926
if len(revision) != 1:
888
927
raise BzrError('bzr export --revision takes exactly 1 argument')
889
rev_id = RevisionSpec(b, revision[0]).rev_id
928
rev_id = revision[0].in_history(b).rev_id
890
929
t = b.revision_tree(rev_id)
891
root, ext = os.path.splitext(dest)
930
arg_root, ext = os.path.splitext(os.path.basename(dest))
931
if ext in ('.gz', '.bz2'):
932
new_root, new_ext = os.path.splitext(arg_root)
933
if new_ext == '.tar':
893
939
if ext in (".tar",):
895
elif ext in (".gz", ".tgz"):
941
elif ext in (".tar.gz", ".tgz"):
897
elif ext in (".bz2", ".tbz2"):
943
elif ext in (".tar.bz2", ".tbz2"):
908
954
takes_args = ['filename']
910
956
def run(self, filename, revision=None):
912
958
raise BzrCommandError("bzr cat requires a revision number")
913
959
elif len(revision) != 1:
914
960
raise BzrCommandError("bzr cat --revision takes exactly one number")
916
b.print_file(b.relpath(filename), revision[0])
961
b = Branch.open_containing('.')
962
b.print_file(b.relpath(filename), revision[0].in_history(b).revno)
919
965
class cmd_local_time_offset(Command):
954
1002
from bzrlib.status import show_status
955
1003
from cStringIO import StringIO
1005
b = Branch.open_containing('.')
958
1006
if selected_list:
959
1007
selected_list = [b.relpath(s) for s in selected_list]
961
if not message and not file:
1009
if message is None and not file:
962
1010
catcher = StringIO()
963
1011
show_status(b, specific_files=selected_list,
964
1012
to_file=catcher)
965
1013
message = edit_commit_message(catcher.getvalue())
967
1015
if message is None:
968
1016
raise BzrCommandError("please specify a commit message"
969
1017
" with either --message or --file")
1055
1105
class cmd_selftest(Command):
1056
"""Run internal test suite"""
1106
"""Run internal test suite.
1108
This creates temporary test directories in the working directory,
1109
but not existing data is affected. These directories are deleted
1110
if the tests pass, or left behind to help in debugging if they
1113
If arguments are given, they are regular expressions that say
1114
which tests should run."""
1115
# TODO: --list should give a list of all available tests
1117
takes_args = ['testnames*']
1058
1118
takes_options = ['verbose', 'pattern']
1059
def run(self, verbose=False, pattern=".*"):
1119
def run(self, testnames_list=None, verbose=False, pattern=".*"):
1060
1120
import bzrlib.ui
1061
1121
from bzrlib.selftest import selftest
1062
1122
# we don't want progress meters from the tests to go to the
1114
1176
def run(self, branch, other):
1115
1177
from bzrlib.revision import common_ancestor, MultipleRevisionSources
1117
branch1 = find_branch(branch)
1118
branch2 = find_branch(other)
1179
branch1 = Branch.open_containing(branch)
1180
branch2 = Branch.open_containing(other)
1120
1182
history_1 = branch1.revision_history()
1121
1183
history_2 = branch2.revision_history()
1123
last1 = branch1.last_patch()
1124
last2 = branch2.last_patch()
1185
last1 = branch1.last_revision()
1186
last2 = branch2.last_revision()
1126
1188
source = MultipleRevisionSources(branch1, branch2)
1184
1246
other = [branch, -1]
1186
1248
if len(revision) == 1:
1187
other = [branch, revision[0]]
1188
1249
base = [None, None]
1250
other = [branch, revision[0].in_history(branch).revno]
1190
1252
assert len(revision) == 2
1191
1253
if None in revision:
1192
1254
raise BzrCommandError(
1193
1255
"Merge doesn't permit that revision specifier.")
1194
base = [branch, revision[0]]
1195
other = [branch, revision[1]]
1256
b = Branch.open(branch)
1258
base = [branch, revision[0].in_history(b).revno]
1259
other = [branch, revision[1].in_history(b).revno]
1198
1262
merge(other, base, check_clean=(not force), merge_type=merge_type)
1220
1284
def run(self, revision=None, no_backup=False, file_list=None):
1221
1285
from bzrlib.merge import merge
1222
from bzrlib.branch import Branch
1223
1286
from bzrlib.commands import parse_spec
1225
1288
if file_list is not None:
1226
1289
if len(file_list) == 0:
1227
1290
raise BzrCommandError("No files specified")
1228
1291
if revision is None:
1230
1293
elif len(revision) != 1:
1231
1294
raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
1232
merge(('.', revision[0]), parse_spec('.'),
1296
b = Branch.open_containing('.')
1297
revno = revision[0].in_history(b).revno
1298
merge(('.', revno), parse_spec('.'),
1233
1299
check_clean=False,
1234
1300
ignore_zero=True,
1235
1301
backup_files=not no_backup,
1236
1302
file_list=file_list)
1237
1303
if not file_list:
1238
Branch('.').set_pending_merges([])
1304
Branch.open_containing('.').set_pending_merges([])
1241
1307
class cmd_assert_fail(Command):
1273
1339
shellcomplete.shellcomplete(context)
1342
class cmd_fetch(Command):
1343
"""Copy in history from another branch but don't merge it.
1345
This is an internal method used for pull and merge."""
1347
takes_args = ['from_branch', 'to_branch']
1348
def run(self, from_branch, to_branch):
1349
from bzrlib.fetch import Fetcher
1350
from bzrlib.branch import Branch
1351
from_b = Branch(from_branch)
1352
to_b = Branch(to_branch)
1353
Fetcher(to_b, from_b)
1276
1357
class cmd_missing(Command):
1277
1358
"""What is missing in this branch relative to other branch.
1360
# TODO: rewrite this in terms of ancestry so that it shows only
1279
1363
takes_args = ['remote?']
1280
1364
aliases = ['mis', 'miss']
1281
1365
# We don't have to add quiet to the list, because
1299
1383
print "Using last location: %s" % parent
1300
1384
remote = parent
1301
1385
elif parent is None:
1302
# We only update x-pull if it did not exist, missing should not change the parent
1303
b.controlfile('x-pull', 'wb').write(remote + '\n')
1304
br_remote = find_branch(remote)
1386
# We only update parent if it did not exist, missing
1387
# should not change the parent
1388
b.set_parent(remote)
1389
br_remote = Branch.open_containing(remote)
1306
1390
return show_missing(b, br_remote, verbose=verbose, quiet=quiet)
1310
1393
class cmd_plugins(Command):
1311
1394
"""List plugins"""