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
takes_options = ['all', 'show-ids', 'revision']
73
takes_options = ['all', 'show-ids']
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):
96
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())
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()
107
129
class cmd_revision_info(Command):
111
133
takes_args = ['revision_info*']
112
134
takes_options = ['revision']
113
def run(self, revision=None, revision_info_list=None):
114
from bzrlib.branch import find_branch
135
def run(self, revision=None, revision_info_list=[]):
136
from bzrlib.revisionspec import RevisionSpec
117
139
if revision is not None:
118
140
revs.extend(revision)
119
141
if revision_info_list is not None:
120
revs.extend(revision_info_list)
142
for rev in revision_info_list:
143
revs.append(RevisionSpec(rev))
121
144
if len(revs) == 0:
122
145
raise BzrCommandError('You must supply a revision identifier')
147
b = Branch.open_containing('.')
127
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)
130
157
class cmd_add(Command):
145
172
Therefore simply saying 'bzr add' will version all files that
146
173
are currently unknown.
148
TODO: Perhaps adding a file whose directly is not versioned should
149
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.
151
180
takes_args = ['file*']
152
181
takes_options = ['verbose', 'no-recurse']
191
220
takes_options = ['revision', 'show-ids']
193
222
def run(self, revision=None, show_ids=False):
223
b = Branch.open_containing('.')
196
225
inv = b.read_working_inventory()
198
227
if len(revision) > 1:
199
228
raise BzrCommandError('bzr inventory --revision takes'
200
229
' exactly one revision identifier')
201
inv = b.get_revision_inventory(b.lookup_revision(revision[0]))
230
inv = b.get_revision_inventory(revision[0].in_history(b).rev_id)
203
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)
322
location = pull_loc(br_from)
343
from bzrlib.errors import DivergedBranches
344
br_from = Branch.open_containing(location)
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)
327
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
328
352
old_revno = br_to.revno()
330
354
br_to.update_revisions(br_from)
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)
680
718
direction = (forward and 'forward') or 'reverse'
683
b = find_branch(filename)
721
b = Branch.open_containing(filename)
684
722
fp = b.relpath(filename)
686
724
file_id = b.read_working_inventory().path2id(fp)
688
726
file_id = None # points to branch root
728
b = Branch.open_containing('.')
693
731
if revision is None:
696
734
elif len(revision) == 1:
697
rev1 = rev2 = b.get_revision_info(revision[0])[0]
735
rev1 = rev2 = revision[0].in_history(b).revno
698
736
elif len(revision) == 2:
699
rev1 = b.get_revision_info(revision[0])[0]
700
rev2 = b.get_revision_info(revision[1])[0]
737
rev1 = revision[0].in_history(b).revno
738
rev2 = revision[1].in_history(b).revno
702
740
raise BzrCommandError('bzr log --revision takes one or two values.')
755
793
def run(self, revision=None, verbose=False):
794
b = Branch.open_containing('.')
757
795
if revision == None:
758
796
tree = b.working_tree()
760
tree = b.revision_tree(b.lookup_revision(revision))
762
for fp, fc, kind, fid in tree.list_files():
798
tree = b.revision_tree(revision.in_history(b).rev_id)
799
for fp, fc, kind, fid, entry in tree.list_files():
764
if kind == 'directory':
801
kindch = entry.kind_character()
771
802
print '%-8s %s%s' % (fc, fp, kindch)
889
920
takes_options = ['revision', 'format', 'root']
890
921
def run(self, dest, revision=None, format=None, root=None):
923
b = Branch.open_containing('.')
893
924
if revision is None:
894
rev_id = b.last_patch()
925
rev_id = b.last_revision()
896
927
if len(revision) != 1:
897
928
raise BzrError('bzr export --revision takes exactly 1 argument')
898
revno, rev_id = b.get_revision_info(revision[0])
929
rev_id = revision[0].in_history(b).rev_id
899
930
t = b.revision_tree(rev_id)
900
root, ext = os.path.splitext(dest)
931
arg_root, ext = os.path.splitext(os.path.basename(dest))
932
if ext in ('.gz', '.bz2'):
933
new_root, new_ext = os.path.splitext(arg_root)
934
if new_ext == '.tar':
902
940
if ext in (".tar",):
904
elif ext in (".gz", ".tgz"):
942
elif ext in (".tar.gz", ".tgz"):
906
elif ext in (".bz2", ".tbz2"):
944
elif ext in (".tar.bz2", ".tbz2"):
917
955
takes_args = ['filename']
919
957
def run(self, filename, revision=None):
921
959
raise BzrCommandError("bzr cat requires a revision number")
922
960
elif len(revision) != 1:
923
961
raise BzrCommandError("bzr cat --revision takes exactly one number")
925
b.print_file(b.relpath(filename), revision[0])
962
b = Branch.open_containing('.')
963
b.print_file(b.relpath(filename), revision[0].in_history(b).revno)
928
966
class cmd_local_time_offset(Command):
1125
1162
def run(self, branch, other):
1126
1163
from bzrlib.revision import common_ancestor, MultipleRevisionSources
1128
branch1 = find_branch(branch)
1129
branch2 = find_branch(other)
1165
branch1 = Branch.open_containing(branch)
1166
branch2 = Branch.open_containing(other)
1131
1168
history_1 = branch1.revision_history()
1132
1169
history_2 = branch2.revision_history()
1134
last1 = branch1.last_patch()
1135
last2 = branch2.last_patch()
1171
last1 = branch1.last_revision()
1172
last2 = branch2.last_revision()
1137
1174
source = MultipleRevisionSources(branch1, branch2)
1195
1232
other = [branch, -1]
1197
1234
if len(revision) == 1:
1198
other = [branch, revision[0]]
1199
1235
base = [None, None]
1236
other = [branch, revision[0].in_history(branch).revno]
1201
1238
assert len(revision) == 2
1202
1239
if None in revision:
1203
1240
raise BzrCommandError(
1204
1241
"Merge doesn't permit that revision specifier.")
1205
base = [branch, revision[0]]
1206
other = [branch, revision[1]]
1242
b = Branch.open(branch)
1244
base = [branch, revision[0].in_history(b).revno]
1245
other = [branch, revision[1].in_history(b).revno]
1209
1248
merge(other, base, check_clean=(not force), merge_type=merge_type)
1231
1270
def run(self, revision=None, no_backup=False, file_list=None):
1232
1271
from bzrlib.merge import merge
1233
from bzrlib.branch import Branch
1234
1272
from bzrlib.commands import parse_spec
1236
1274
if file_list is not None:
1237
1275
if len(file_list) == 0:
1238
1276
raise BzrCommandError("No files specified")
1239
1277
if revision is None:
1241
1279
elif len(revision) != 1:
1242
1280
raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
1243
merge(('.', revision[0]), parse_spec('.'),
1282
b = Branch.open_containing('.')
1283
revno = revision[0].in_history(b).revno
1284
merge(('.', revno), parse_spec('.'),
1244
1285
check_clean=False,
1245
1286
ignore_zero=True,
1246
1287
backup_files=not no_backup,
1247
1288
file_list=file_list)
1248
1289
if not file_list:
1249
Branch('.').set_pending_merges([])
1290
Branch.open_containing('.').set_pending_merges([])
1252
1293
class cmd_assert_fail(Command):
1284
1325
shellcomplete.shellcomplete(context)
1328
class cmd_fetch(Command):
1329
"""Copy in history from another branch but don't merge it.
1331
This is an internal method used for pull and merge."""
1333
takes_args = ['from_branch', 'to_branch']
1334
def run(self, from_branch, to_branch):
1335
from bzrlib.fetch import Fetcher
1336
from bzrlib.branch import Branch
1337
from_b = Branch(from_branch)
1338
to_b = Branch(to_branch)
1339
Fetcher(to_b, from_b)
1287
1343
class cmd_missing(Command):
1288
1344
"""What is missing in this branch relative to other branch.
1346
# TODO: rewrite this in terms of ancestry so that it shows only
1290
1349
takes_args = ['remote?']
1291
1350
aliases = ['mis', 'miss']
1292
1351
# We don't have to add quiet to the list, because
1310
1369
print "Using last location: %s" % parent
1311
1370
remote = parent
1312
1371
elif parent is None:
1313
# We only update x-pull if it did not exist, missing should not change the parent
1314
b.controlfile('x-pull', 'wb').write(remote + '\n')
1315
br_remote = find_branch(remote)
1372
# We only update parent if it did not exist, missing
1373
# should not change the parent
1374
b.set_parent(remote)
1375
br_remote = Branch.open_containing(remote)
1317
1376
return show_missing(b, br_remote, verbose=verbose, quiet=quiet)
1321
1379
class cmd_plugins(Command):
1322
1380
"""List plugins"""