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
24
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError, NotBranchError
25
from bzrlib.branch import Branch
26
26
from bzrlib import BZRDIR
27
27
from bzrlib.commands import Command
63
63
files or directories is reported. If a directory is given, status
64
64
is reported for everything inside that directory.
66
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
68
72
takes_args = ['file*']
69
73
takes_options = ['all', 'show-ids', 'revision']
70
74
aliases = ['st', 'stat']
72
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):
74
b = find_branch(file_list[0])
78
b = Branch.open_containing(file_list[0])
75
79
file_list = [b.relpath(x) for x in file_list]
76
80
# special case: only one path was given and it's the root
78
82
if file_list == ['']:
85
b = Branch.open_containing('.')
83
87
from bzrlib.status import show_status
84
88
show_status(b, show_unchanged=all, show_ids=show_ids,
85
specific_files=file_list)
89
specific_files=file_list, revision=revision)
88
92
class cmd_cat_revision(Command):
89
"""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.
92
takes_args = ['revision_id']
100
takes_args = ['revision_id?']
101
takes_options = ['revision']
94
def run(self, revision_id):
95
from bzrlib.xml import pack_xml
96
pack_xml(find_branch('.').get_revision(revision_id), sys.stdout)
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())
99
121
class cmd_revno(Command):
100
122
"""Show current revision number.
102
124
This is equal to the number of revisions on this branch."""
104
print find_branch('.').revno()
126
print Branch.open_containing('.').revno()
106
129
class cmd_revision_info(Command):
107
130
"""Show revision number and revision id for a given revision identifier.
110
133
takes_args = ['revision_info*']
111
134
takes_options = ['revision']
112
def run(self, revision=None, revision_info_list=None):
113
from bzrlib.branch import find_branch
135
def run(self, revision=None, revision_info_list=[]):
136
from bzrlib.revisionspec import RevisionSpec
116
139
if revision is not None:
117
140
revs.extend(revision)
118
141
if revision_info_list is not None:
119
revs.extend(revision_info_list)
142
for rev in revision_info_list:
143
revs.append(RevisionSpec(rev))
120
144
if len(revs) == 0:
121
145
raise BzrCommandError('You must supply a revision identifier')
147
b = Branch.open_containing('.')
126
print '%4d %s' % b.get_revision_info(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)
129
157
class cmd_add(Command):
144
172
Therefore simply saying 'bzr add' will version all files that
145
173
are currently unknown.
147
TODO: Perhaps adding a file whose directly is not versioned should
148
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.
150
180
takes_args = ['file*']
151
181
takes_options = ['verbose', 'no-recurse']
190
220
takes_options = ['revision', 'show-ids']
192
222
def run(self, revision=None, show_ids=False):
223
b = Branch.open_containing('.')
195
225
inv = b.read_working_inventory()
197
227
if len(revision) > 1:
198
228
raise BzrCommandError('bzr inventory --revision takes'
199
229
' exactly one revision identifier')
200
inv = b.get_revision_inventory(b.lookup_revision(revision[0]))
230
inv = b.get_revision_inventory(revision[0].in_history(b).rev_id)
202
232
for path, entry in inv.entries():
316
340
print "Using last location: %s" % stored_loc
317
341
location = stored_loc
318
342
cache_root = tempfile.mkdtemp()
319
from bzrlib.branch import DivergedBranches
320
br_from = find_branch(location)
321
location = pull_loc(br_from)
343
from bzrlib.errors import DivergedBranches
344
br_from = Branch.open_containing(location)
345
location = br_from.base
322
346
old_revno = br_to.revno()
324
from branch import find_cached_branch, DivergedBranches
325
br_from = find_cached_branch(location, cache_root)
326
location = pull_loc(br_from)
348
from bzrlib.errors import DivergedBranches
349
br_from = Branch.open(location)
350
br_from.setup_caching(cache_root)
351
location = br_from.base
327
352
old_revno = br_to.revno()
329
354
br_to.update_revisions(br_from)
348
373
To retrieve the branch as of a particular revision, supply the --revision
349
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.
351
380
takes_args = ['from_location', 'to_location?']
352
takes_options = ['revision']
381
takes_options = ['revision', 'basis']
353
382
aliases = ['get', 'clone']
355
def run(self, from_location, to_location=None, revision=None):
356
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
359
388
from shutil import rmtree
365
394
raise BzrCommandError(
366
395
'bzr branch --revision takes exactly 1 revision value')
368
br_from = find_cached_branch(from_location, cache_root)
397
br_from = Branch.open(from_location)
369
398
except OSError, e:
370
399
if e.errno == errno.ENOENT:
371
400
raise BzrCommandError('Source location "%s" does not'
372
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]
375
413
if to_location is None:
376
414
to_location = os.path.basename(from_location.rstrip("/\\"))
389
copy_branch(br_from, to_location, revision[0])
427
copy_branch(br_from, to_location, revision_id, basis_branch)
390
428
except bzrlib.errors.NoSuchRevision:
391
429
rmtree(to_location)
392
430
msg = "The branch %s has no revision %d." % (from_location, revision[0])
393
431
raise BzrCommandError(msg)
432
except bzrlib.errors.UnlistableBranch:
433
msg = "The branch %s cannot be used as a --basis"
395
435
rmtree(cache_root)
479
519
"""Display list of revision ids on this branch."""
482
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()):
486
535
class cmd_directories(Command):
487
536
"""Display list of versioned directories in this branch."""
489
for name, ie in find_branch('.').read_working_inventory().directories():
538
for name, ie in Branch.open_containing('.').read_working_inventory().directories():
670
719
direction = (forward and 'forward') or 'reverse'
673
b = find_branch(filename)
722
b = Branch.open_containing(filename)
674
723
fp = b.relpath(filename)
676
725
file_id = b.read_working_inventory().path2id(fp)
678
727
file_id = None # points to branch root
729
b = Branch.open_containing('.')
683
732
if revision is None:
686
735
elif len(revision) == 1:
687
rev1 = rev2 = b.get_revision_info(revision[0])[0]
736
rev1 = rev2 = revision[0].in_history(b).revno
688
737
elif len(revision) == 2:
689
rev1 = b.get_revision_info(revision[0])[0]
690
rev2 = b.get_revision_info(revision[1])[0]
738
rev1 = revision[0].in_history(b).revno
739
rev2 = revision[1].in_history(b).revno
692
741
raise BzrCommandError('bzr log --revision takes one or two values.')
879
928
takes_options = ['revision', 'format', 'root']
880
929
def run(self, dest, revision=None, format=None, root=None):
931
b = Branch.open_containing('.')
883
932
if revision is None:
884
rev_id = b.last_patch()
933
rev_id = b.last_revision()
886
935
if len(revision) != 1:
887
936
raise BzrError('bzr export --revision takes exactly 1 argument')
888
revno, rev_id = b.get_revision_info(revision[0])
937
rev_id = revision[0].in_history(b).rev_id
889
938
t = b.revision_tree(rev_id)
890
939
root, ext = os.path.splitext(dest)
907
956
takes_args = ['filename']
909
958
def run(self, filename, revision=None):
911
960
raise BzrCommandError("bzr cat requires a revision number")
912
961
elif len(revision) != 1:
913
962
raise BzrCommandError("bzr cat --revision takes exactly one number")
915
b.print_file(b.relpath(filename), revision[0])
963
b = Branch.open_containing('.')
964
b.print_file(b.relpath(filename), revision[0].in_history(b).revno)
918
967
class cmd_local_time_offset(Command):
1113
1163
def run(self, branch, other):
1114
1164
from bzrlib.revision import common_ancestor, MultipleRevisionSources
1116
branch1 = find_branch(branch)
1117
branch2 = find_branch(other)
1166
branch1 = Branch.open_containing(branch)
1167
branch2 = Branch.open_containing(other)
1119
1169
history_1 = branch1.revision_history()
1120
1170
history_2 = branch2.revision_history()
1122
last1 = branch1.last_patch()
1123
last2 = branch2.last_patch()
1172
last1 = branch1.last_revision()
1173
last2 = branch2.last_revision()
1125
1175
source = MultipleRevisionSources(branch1, branch2)
1183
1233
other = [branch, -1]
1185
1235
if len(revision) == 1:
1186
other = [branch, revision[0]]
1187
1236
base = [None, None]
1237
other = [branch, revision[0].in_history(branch).revno]
1189
1239
assert len(revision) == 2
1190
1240
if None in revision:
1191
1241
raise BzrCommandError(
1192
1242
"Merge doesn't permit that revision specifier.")
1193
base = [branch, revision[0]]
1194
other = [branch, revision[1]]
1243
from bzrlib.branch import Branch
1244
b = Branch.open(branch)
1246
base = [branch, revision[0].in_history(b).revno]
1247
other = [branch, revision[1].in_history(b).revno]
1197
1250
merge(other, base, check_clean=(not force), merge_type=merge_type)
1225
1278
if len(file_list) == 0:
1226
1279
raise BzrCommandError("No files specified")
1227
1280
if revision is None:
1229
1282
elif len(revision) != 1:
1230
1283
raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
1231
merge(('.', revision[0]), parse_spec('.'),
1285
b = Branch.open_containing('.')
1286
revno = revision[0].in_history(b).revno
1287
merge(('.', revno), parse_spec('.'),
1232
1288
check_clean=False,
1233
1289
ignore_zero=True,
1234
1290
backup_files=not no_backup,
1235
1291
file_list=file_list)
1236
1292
if not file_list:
1237
Branch('.').set_pending_merges([])
1293
Branch.open_containing('.').set_pending_merges([])
1240
1296
class cmd_assert_fail(Command):
1272
1328
shellcomplete.shellcomplete(context)
1331
class cmd_fetch(Command):
1332
"""Copy in history from another branch but don't merge it.
1334
This is an internal method used for pull and merge."""
1336
takes_args = ['from_branch', 'to_branch']
1337
def run(self, from_branch, to_branch):
1338
from bzrlib.fetch import Fetcher
1339
from bzrlib.branch import Branch
1340
from_b = Branch(from_branch)
1341
to_b = Branch(to_branch)
1342
Fetcher(to_b, from_b)
1275
1346
class cmd_missing(Command):
1276
1347
"""What is missing in this branch relative to other branch.
1349
# TODO: rewrite this in terms of ancestry so that it shows only
1278
1352
takes_args = ['remote?']
1279
1353
aliases = ['mis', 'miss']
1280
1354
# We don't have to add quiet to the list, because
1298
1372
print "Using last location: %s" % parent
1299
1373
remote = parent
1300
1374
elif parent is None:
1301
# We only update x-pull if it did not exist, missing should not change the parent
1302
b.controlfile('x-pull', 'wb').write(remote + '\n')
1303
br_remote = find_branch(remote)
1375
# We only update parent if it did not exist, missing
1376
# should not change the parent
1377
b.set_parent(remote)
1378
br_remote = Branch.open_containing(remote)
1305
1380
return show_missing(b, br_remote, verbose=verbose, quiet=quiet)