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.errors import DivergedBranches
26
from bzrlib.branch import Branch
26
27
from bzrlib import BZRDIR
27
28
from bzrlib.commands import Command
63
64
files or directories is reported. If a directory is given, status
64
65
is reported for everything inside that directory.
66
If a revision is specified, the changes since that revision are shown.
67
If a revision argument is given, the status is calculated against
68
that revision, or between two revisions if two are provided.
70
# XXX: FIXME: bzr status should accept a -r option to show changes
71
# relative to a revision, or between revisions
68
73
takes_args = ['file*']
69
takes_options = ['all', 'show-ids', 'revision']
74
takes_options = ['all', 'show-ids']
70
75
aliases = ['st', 'stat']
72
def run(self, all=False, show_ids=False, file_list=None):
77
def run(self, all=False, show_ids=False, file_list=None, revision=None):
74
b = find_branch(file_list[0])
79
b = Branch.open_containing(file_list[0])
75
80
file_list = [b.relpath(x) for x in file_list]
76
81
# special case: only one path was given and it's the root
78
83
if file_list == ['']:
86
b = Branch.open_containing('.')
83
88
from bzrlib.status import show_status
84
89
show_status(b, show_unchanged=all, show_ids=show_ids,
85
specific_files=file_list)
90
specific_files=file_list, revision=revision)
88
93
class cmd_cat_revision(Command):
89
"""Write out metadata for a revision."""
94
"""Write out metadata for a revision.
96
The revision to print can either be specified by a specific
97
revision identifier, or you can use --revision.
92
takes_args = ['revision_id']
101
takes_args = ['revision_id?']
102
takes_options = ['revision']
94
def run(self, revision_id):
96
sys.stdout.write(b.get_revision_xml_file(revision_id).read())
104
def run(self, revision_id=None, revision=None):
105
from bzrlib.revisionspec import RevisionSpec
107
if revision_id is not None and revision is not None:
108
raise BzrCommandError('You can only supply one of revision_id or --revision')
109
if revision_id is None and revision is None:
110
raise BzrCommandError('You must supply either --revision or a revision_id')
111
b = Branch.open_containing('.')
112
if revision_id is not None:
113
sys.stdout.write(b.get_revision_xml_file(revision_id).read())
114
elif revision is not None:
117
raise BzrCommandError('You cannot specify a NULL revision.')
118
revno, rev_id = rev.in_history(b)
119
sys.stdout.write(b.get_revision_xml_file(rev_id).read())
99
122
class cmd_revno(Command):
100
123
"""Show current revision number.
102
125
This is equal to the number of revisions on this branch."""
104
print find_branch('.').revno()
127
print Branch.open_containing('.').revno()
107
130
class cmd_revision_info(Command):
111
134
takes_args = ['revision_info*']
112
135
takes_options = ['revision']
113
def run(self, revision=None, revision_info_list=None):
114
from bzrlib.branch import find_branch
136
def run(self, revision=None, revision_info_list=[]):
137
from bzrlib.revisionspec import RevisionSpec
117
140
if revision is not None:
118
141
revs.extend(revision)
119
142
if revision_info_list is not None:
120
revs.extend(revision_info_list)
143
for rev in revision_info_list:
144
revs.append(RevisionSpec(rev))
121
145
if len(revs) == 0:
122
146
raise BzrCommandError('You must supply a revision identifier')
148
b = Branch.open_containing('.')
127
print '%4d %s' % b.get_revision_info(rev)
151
revinfo = rev.in_history(b)
152
if revinfo.revno is None:
153
print ' %s' % revinfo.rev_id
155
print '%4d %s' % (revinfo.revno, revinfo.rev_id)
130
158
class cmd_add(Command):
145
173
Therefore simply saying 'bzr add' will version all files that
146
174
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?
176
Adding a file whose parent directory is not versioned will
177
implicitly add the parent, and so on up to the root. This means
178
you should never need to explictly add a directory, they'll just
179
get added when you add a file in the directory.
151
181
takes_args = ['file*']
152
182
takes_options = ['verbose', 'no-recurse']
191
221
takes_options = ['revision', 'show-ids']
193
223
def run(self, revision=None, show_ids=False):
224
b = Branch.open_containing('.')
196
226
inv = b.read_working_inventory()
198
228
if len(revision) > 1:
199
229
raise BzrCommandError('bzr inventory --revision takes'
200
230
' exactly one revision identifier')
201
inv = b.get_revision_inventory(b.lookup_revision(revision[0]))
231
inv = b.get_revision_inventory(revision[0].in_history(b).rev_id)
203
233
for path, entry in inv.entries():
294
324
If branches have diverged, you can use 'bzr merge' to pull the text changes
295
325
from one into the other.
327
takes_options = ['remember']
297
328
takes_args = ['location?']
299
def run(self, location=None):
330
def run(self, location=None, remember=False):
300
331
from bzrlib.merge import merge
302
333
from shutil import rmtree
304
from bzrlib.branch import pull_loc
306
br_to = find_branch('.')
309
stored_loc = br_to.controlfile("x-pull", "rb").read().rstrip('\n')
311
if e.errno != errno.ENOENT:
336
br_to = Branch.open_containing('.')
337
stored_loc = br_to.get_parent()
313
338
if location is None:
314
339
if stored_loc is None:
315
340
raise BzrCommandError("No pull location known or specified.")
317
print "Using last location: %s" % stored_loc
342
print "Using saved location: %s" % stored_loc
318
343
location = stored_loc
319
344
cache_root = tempfile.mkdtemp()
320
from bzrlib.branch import DivergedBranches
321
br_from = find_branch(location)
322
location = pull_loc(br_from)
323
old_revno = br_to.revno()
345
br_from = Branch.open(location)
325
from branch import find_cached_branch, DivergedBranches
326
br_from = find_cached_branch(location, cache_root)
327
location = pull_loc(br_from)
348
br_from.setup_caching(cache_root)
349
location = br_from.base
328
350
old_revno = br_to.revno()
351
old_revision_history = br_to.revision_history()
330
353
br_to.update_revisions(br_from)
331
354
except DivergedBranches:
332
355
raise BzrCommandError("These branches have diverged."
335
merge(('.', -1), ('.', old_revno), check_clean=False)
336
if location != stored_loc:
337
br_to.controlfile("x-pull", "wb").write(location + "\n")
357
new_revision_history = br_to.revision_history()
358
if new_revision_history != old_revision_history:
359
merge(('.', -1), ('.', old_revno), check_clean=False)
360
if stored_loc is None or remember:
361
br_to.set_parent(location)
339
364
rmtree(cache_root)
349
374
To retrieve the branch as of a particular revision, supply the --revision
350
375
parameter, as in "branch foo/bar -r 5".
377
--basis is to speed up branching from remote branches. When specified, it
378
copies all the file-contents, inventory and revision data from the basis
379
branch before copying anything from the remote branch.
352
381
takes_args = ['from_location', 'to_location?']
353
takes_options = ['revision']
382
takes_options = ['revision', 'basis']
354
383
aliases = ['get', 'clone']
356
def run(self, from_location, to_location=None, revision=None):
357
from bzrlib.branch import copy_branch, find_cached_branch
385
def run(self, from_location, to_location=None, revision=None, basis=None):
386
from bzrlib.clone import copy_branch
360
389
from shutil import rmtree
366
395
raise BzrCommandError(
367
396
'bzr branch --revision takes exactly 1 revision value')
369
br_from = find_cached_branch(from_location, cache_root)
398
br_from = Branch.open(from_location)
370
399
except OSError, e:
371
400
if e.errno == errno.ENOENT:
372
401
raise BzrCommandError('Source location "%s" does not'
373
402
' exist.' % to_location)
405
br_from.setup_caching(cache_root)
406
if basis is not None:
407
basis_branch = Branch.open_containing(basis)
410
if len(revision) == 1 and revision[0] is not None:
411
revision_id = revision[0].in_history(br_from)[1]
376
414
if to_location is None:
377
415
to_location = os.path.basename(from_location.rstrip("/\\"))
390
copy_branch(br_from, to_location, revision[0])
428
copy_branch(br_from, to_location, revision_id, basis_branch)
391
429
except bzrlib.errors.NoSuchRevision:
392
430
rmtree(to_location)
393
431
msg = "The branch %s has no revision %d." % (from_location, revision[0])
394
432
raise BzrCommandError(msg)
433
except bzrlib.errors.UnlistableBranch:
434
msg = "The branch %s cannot be used as a --basis"
396
436
rmtree(cache_root)
480
520
"""Display list of revision ids on this branch."""
483
for patchid in find_branch('.').revision_history():
523
for patchid in Branch.open_containing('.').revision_history():
527
class cmd_ancestry(Command):
528
"""List all revisions merged into this branch."""
532
for revision_id in b.get_ancestry(b.last_revision()):
487
536
class cmd_directories(Command):
488
537
"""Display list of versioned directories in this branch."""
490
for name, ie in find_branch('.').read_working_inventory().directories():
539
for name, ie in Branch.open_containing('.').read_working_inventory().directories():
649
697
--message allows you to give a regular expression, which will be evaluated
650
698
so that only matching entries will be displayed.
652
TODO: Make --revision support uuid: and hash: [future tag:] notation.
701
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
656
703
takes_args = ['filename?']
657
704
takes_options = ['forward', 'timezone', 'verbose', 'show-ids', 'revision',
658
705
'long', 'message', 'short',]
671
718
direction = (forward and 'forward') or 'reverse'
674
b = find_branch(filename)
721
b = Branch.open_containing(filename)
675
722
fp = b.relpath(filename)
677
724
file_id = b.read_working_inventory().path2id(fp)
679
726
file_id = None # points to branch root
728
b = Branch.open_containing('.')
684
731
if revision is None:
687
734
elif len(revision) == 1:
688
rev1 = rev2 = b.get_revision_info(revision[0])[0]
735
rev1 = rev2 = revision[0].in_history(b).revno
689
736
elif len(revision) == 2:
690
rev1 = b.get_revision_info(revision[0])[0]
691
rev2 = b.get_revision_info(revision[1])[0]
737
rev1 = revision[0].in_history(b).revno
738
rev2 = revision[1].in_history(b).revno
693
740
raise BzrCommandError('bzr log --revision takes one or two values.')
746
793
def run(self, revision=None, verbose=False):
794
b = Branch.open_containing('.')
748
795
if revision == None:
749
796
tree = b.working_tree()
751
tree = b.revision_tree(b.lookup_revision(revision))
753
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():
755
if kind == 'directory':
801
kindch = entry.kind_character()
762
802
print '%-8s %s%s' % (fc, fp, kindch)
880
920
takes_options = ['revision', 'format', 'root']
881
921
def run(self, dest, revision=None, format=None, root=None):
923
b = Branch.open_containing('.')
884
924
if revision is None:
885
rev_id = b.last_patch()
925
rev_id = b.last_revision()
887
927
if len(revision) != 1:
888
928
raise BzrError('bzr export --revision takes exactly 1 argument')
889
revno, rev_id = b.get_revision_info(revision[0])
929
rev_id = revision[0].in_history(b).rev_id
890
930
t = b.revision_tree(rev_id)
891
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':
893
940
if ext in (".tar",):
895
elif ext in (".gz", ".tgz"):
942
elif ext in (".tar.gz", ".tgz"):
897
elif ext in (".bz2", ".tbz2"):
944
elif ext in (".tar.bz2", ".tbz2"):
908
955
takes_args = ['filename']
910
957
def run(self, filename, revision=None):
912
959
raise BzrCommandError("bzr cat requires a revision number")
913
960
elif len(revision) != 1:
914
961
raise BzrCommandError("bzr cat --revision takes exactly one number")
916
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)
919
966
class cmd_local_time_offset(Command):
952
999
def run(self, message=None, file=None, verbose=True, selected_list=None,
953
1000
unchanged=False):
954
from bzrlib.errors import PointlessCommit
1001
from bzrlib.errors import PointlessCommit, ConflictsInTree
955
1002
from bzrlib.msgeditor import edit_commit_message
956
1003
from bzrlib.status import show_status
957
1004
from cStringIO import StringIO
1006
b = Branch.open_containing('.')
960
1007
if selected_list:
961
1008
selected_list = [b.relpath(s) for s in selected_list]
963
if not message and not file:
1011
if message is None and not file:
964
1012
catcher = StringIO()
965
1013
show_status(b, specific_files=selected_list,
966
1014
to_file=catcher)
967
1015
message = edit_commit_message(catcher.getvalue())
969
1017
if message is None:
970
1018
raise BzrCommandError("please specify a commit message"
971
1019
" with either --message or --file")
1045
1098
def run(self, email=False):
1047
b = bzrlib.branch.find_branch('.')
1100
b = bzrlib.branch.Branch.open_containing('.')
1101
except NotBranchError:
1052
print bzrlib.osutils.user_email(b)
1105
print bzrlib.config.user_email(b)
1054
print bzrlib.osutils.username(b)
1107
print bzrlib.config.username(b)
1057
1110
class cmd_selftest(Command):
1058
"""Run internal test suite"""
1111
"""Run internal test suite.
1113
This creates temporary test directories in the working directory,
1114
but not existing data is affected. These directories are deleted
1115
if the tests pass, or left behind to help in debugging if they
1118
If arguments are given, they are regular expressions that say
1119
which tests should run."""
1120
# TODO: --list should give a list of all available tests
1060
takes_options = ['verbose', 'pattern']
1061
def run(self, verbose=False, pattern=".*"):
1122
takes_args = ['testspecs*']
1123
takes_options = ['verbose']
1124
def run(self, testspecs_list=None, verbose=False):
1062
1125
import bzrlib.ui
1063
1126
from bzrlib.selftest import selftest
1064
1127
# we don't want progress meters from the tests to go to the
1116
1184
def run(self, branch, other):
1117
1185
from bzrlib.revision import common_ancestor, MultipleRevisionSources
1119
branch1 = find_branch(branch)
1120
branch2 = find_branch(other)
1187
branch1 = Branch.open_containing(branch)
1188
branch2 = Branch.open_containing(other)
1122
1190
history_1 = branch1.revision_history()
1123
1191
history_2 = branch2.revision_history()
1125
last1 = branch1.last_patch()
1126
last2 = branch2.last_patch()
1193
last1 = branch1.last_revision()
1194
last2 = branch2.last_revision()
1128
1196
source = MultipleRevisionSources(branch1, branch2)
1174
1242
takes_args = ['branch?']
1175
1243
takes_options = ['revision', 'force', 'merge-type']
1177
def run(self, branch='.', revision=None, force=False,
1245
def run(self, branch=None, revision=None, force=False,
1178
1246
merge_type=None):
1179
1247
from bzrlib.merge import merge
1180
1248
from bzrlib.merge_core import ApplyMerge3
1181
1249
if merge_type is None:
1182
1250
merge_type = ApplyMerge3
1252
branch = Branch.open_containing('.').get_parent()
1254
raise BzrCommandError("No merge location known or specified.")
1256
print "Using saved location: %s" % branch
1184
1257
if revision is None or len(revision) < 1:
1185
1258
base = [None, None]
1186
1259
other = [branch, -1]
1188
1261
if len(revision) == 1:
1189
other = [branch, revision[0]]
1190
1262
base = [None, None]
1263
other = [branch, revision[0].in_history(branch).revno]
1192
1265
assert len(revision) == 2
1193
1266
if None in revision:
1194
1267
raise BzrCommandError(
1195
1268
"Merge doesn't permit that revision specifier.")
1196
base = [branch, revision[0]]
1197
other = [branch, revision[1]]
1269
b = Branch.open(branch)
1271
base = [branch, revision[0].in_history(b).revno]
1272
other = [branch, revision[1].in_history(b).revno]
1200
1275
merge(other, base, check_clean=(not force), merge_type=merge_type)
1222
1297
def run(self, revision=None, no_backup=False, file_list=None):
1223
1298
from bzrlib.merge import merge
1224
from bzrlib.branch import Branch
1225
1299
from bzrlib.commands import parse_spec
1227
1301
if file_list is not None:
1228
1302
if len(file_list) == 0:
1229
1303
raise BzrCommandError("No files specified")
1230
1304
if revision is None:
1232
1306
elif len(revision) != 1:
1233
1307
raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
1234
merge(('.', revision[0]), parse_spec('.'),
1309
b = Branch.open_containing('.')
1310
revno = revision[0].in_history(b).revno
1311
merge(('.', revno), parse_spec('.'),
1235
1312
check_clean=False,
1236
1313
ignore_zero=True,
1237
1314
backup_files=not no_backup,
1238
1315
file_list=file_list)
1239
1316
if not file_list:
1240
Branch('.').set_pending_merges([])
1317
Branch.open_containing('.').set_pending_merges([])
1243
1320
class cmd_assert_fail(Command):
1275
1352
shellcomplete.shellcomplete(context)
1355
class cmd_fetch(Command):
1356
"""Copy in history from another branch but don't merge it.
1358
This is an internal method used for pull and merge."""
1360
takes_args = ['from_branch', 'to_branch']
1361
def run(self, from_branch, to_branch):
1362
from bzrlib.fetch import Fetcher
1363
from bzrlib.branch import Branch
1364
from_b = Branch(from_branch)
1365
to_b = Branch(to_branch)
1366
Fetcher(to_b, from_b)
1278
1370
class cmd_missing(Command):
1279
1371
"""What is missing in this branch relative to other branch.
1373
# TODO: rewrite this in terms of ancestry so that it shows only
1281
1376
takes_args = ['remote?']
1282
1377
aliases = ['mis', 'miss']
1283
1378
# We don't have to add quiet to the list, because
1301
1396
print "Using last location: %s" % parent
1302
1397
remote = parent
1303
1398
elif parent is None:
1304
# We only update x-pull if it did not exist, missing should not change the parent
1305
b.controlfile('x-pull', 'wb').write(remote + '\n')
1306
br_remote = find_branch(remote)
1399
# We only update parent if it did not exist, missing
1400
# should not change the parent
1401
b.set_parent(remote)
1402
br_remote = Branch.open_containing(remote)
1308
1403
return show_missing(b, br_remote, verbose=verbose, quiet=quiet)
1312
1406
class cmd_plugins(Command):
1313
1407
"""List plugins"""