22
22
import bzrlib.trace
23
23
from bzrlib.trace import mutter, note, log_error, warning
24
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError, NotBranchError
25
from bzrlib.errors import DivergedBranches
26
from bzrlib.branch import Branch
24
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError
25
from bzrlib.branch import find_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 argument is given, the status is calculated against
68
that revision, or between two revisions if two are provided.
66
If a revision is specified, the changes since that revision are shown.
70
# XXX: FIXME: bzr status should accept a -r option to show changes
71
# relative to a revision, or between revisions
73
68
takes_args = ['file*']
74
takes_options = ['all', 'show-ids']
69
takes_options = ['all', 'show-ids', 'revision']
75
70
aliases = ['st', 'stat']
77
def run(self, all=False, show_ids=False, file_list=None, revision=None):
72
def run(self, all=False, show_ids=False, file_list=None):
79
b = Branch.open_containing(file_list[0])
74
b = find_branch(file_list[0])
80
75
file_list = [b.relpath(x) for x in file_list]
81
76
# special case: only one path was given and it's the root
83
78
if file_list == ['']:
86
b = Branch.open_containing('.')
88
83
from bzrlib.status import show_status
89
84
show_status(b, show_unchanged=all, show_ids=show_ids,
90
specific_files=file_list, revision=revision)
85
specific_files=file_list)
93
88
class cmd_cat_revision(Command):
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.
89
"""Write out metadata for a revision."""
101
takes_args = ['revision_id?']
102
takes_options = ['revision']
92
takes_args = ['revision_id']
104
def run(self, revision_id=None, revision=None):
105
from bzrlib.revisionspec import RevisionSpec
94
def run(self, revision_id):
95
from bzrlib.xml import pack_xml
96
pack_xml(find_branch('.').get_revision(revision_id), sys.stdout)
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())
122
99
class cmd_revno(Command):
123
100
"""Show current revision number.
125
102
This is equal to the number of revisions on this branch."""
127
print Branch.open_containing('.').revno()
104
print find_branch('.').revno()
130
106
class cmd_revision_info(Command):
131
107
"""Show revision number and revision id for a given revision identifier.
134
110
takes_args = ['revision_info*']
135
111
takes_options = ['revision']
136
def run(self, revision=None, revision_info_list=[]):
137
from bzrlib.revisionspec import RevisionSpec
112
def run(self, revision=None, revision_info_list=None):
113
from bzrlib.branch import find_branch
140
116
if revision is not None:
141
117
revs.extend(revision)
142
118
if revision_info_list is not None:
143
for rev in revision_info_list:
144
revs.append(RevisionSpec(rev))
119
revs.extend(revision_info_list)
145
120
if len(revs) == 0:
146
121
raise BzrCommandError('You must supply a revision identifier')
148
b = Branch.open_containing('.')
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)
126
print '%4d %s' % b.get_revision_info(rev)
158
129
class cmd_add(Command):
173
144
Therefore simply saying 'bzr add' will version all files that
174
145
are currently unknown.
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.
147
TODO: Perhaps adding a file whose directly is not versioned should
148
recursively add that parent, rather than giving an error?
181
150
takes_args = ['file*']
182
takes_options = ['no-recurse', 'quiet']
151
takes_options = ['verbose', 'no-recurse']
184
def run(self, file_list, no_recurse=False, quiet=False):
185
from bzrlib.add import smart_add, add_reporter_print, add_reporter_null
187
reporter = add_reporter_null
189
reporter = add_reporter_print
190
smart_add(file_list, not no_recurse, reporter)
153
def run(self, file_list, verbose=False, no_recurse=False):
154
# verbose currently has no effect
155
from bzrlib.add import smart_add, add_reporter_print
156
smart_add(file_list, not no_recurse, add_reporter_print)
193
160
class cmd_mkdir(Command):
223
190
takes_options = ['revision', 'show-ids']
225
192
def run(self, revision=None, show_ids=False):
226
b = Branch.open_containing('.')
228
195
inv = b.read_working_inventory()
230
197
if len(revision) > 1:
231
198
raise BzrCommandError('bzr inventory --revision takes'
232
199
' exactly one revision identifier')
233
inv = b.get_revision_inventory(revision[0].in_history(b).rev_id)
200
inv = b.get_revision_inventory(b.lookup_revision(revision[0]))
235
202
for path, entry in inv.entries():
267
234
See also the 'move' command, which moves files into a different
268
235
directory without changing their name.
270
# TODO: Some way to rename multiple files without invoking
271
# bzr for each one?"""
237
TODO: Some way to rename multiple files without invoking bzr for each
272
239
takes_args = ['from_name', 'to_name']
274
241
def run(self, from_name, to_name):
275
b = Branch.open_containing('.')
276
243
b.rename_one(b.relpath(from_name), b.relpath(to_name))
326
293
If branches have diverged, you can use 'bzr merge' to pull the text changes
327
294
from one into the other.
329
takes_options = ['remember']
330
296
takes_args = ['location?']
332
def run(self, location=None, remember=False):
298
def run(self, location=None):
333
299
from bzrlib.merge import merge
335
301
from shutil import rmtree
303
from bzrlib.branch import pull_loc
338
br_to = Branch.open_containing('.')
339
stored_loc = br_to.get_parent()
305
br_to = find_branch('.')
308
stored_loc = br_to.controlfile("x-pull", "rb").read().rstrip('\n')
310
if e.errno != errno.ENOENT:
340
312
if location is None:
341
313
if stored_loc is None:
342
314
raise BzrCommandError("No pull location known or specified.")
344
print "Using saved location: %s" % stored_loc
316
print "Using last location: %s" % stored_loc
345
317
location = stored_loc
346
318
cache_root = tempfile.mkdtemp()
347
br_from = Branch.open(location)
319
from bzrlib.branch import DivergedBranches
320
br_from = find_branch(location)
321
location = pull_loc(br_from)
322
old_revno = br_to.revno()
350
br_from.setup_caching(cache_root)
351
location = br_from.base
324
from branch import find_cached_branch, DivergedBranches
325
br_from = find_cached_branch(location, cache_root)
326
location = pull_loc(br_from)
352
327
old_revno = br_to.revno()
353
old_revision_history = br_to.revision_history()
355
329
br_to.update_revisions(br_from)
356
330
except DivergedBranches:
357
331
raise BzrCommandError("These branches have diverged."
359
new_revision_history = br_to.revision_history()
360
if new_revision_history != old_revision_history:
361
merge(('.', -1), ('.', old_revno), check_clean=False)
362
if stored_loc is None or remember:
363
br_to.set_parent(location)
334
merge(('.', -1), ('.', old_revno), check_clean=False)
335
if location != stored_loc:
336
br_to.controlfile("x-pull", "wb").write(location + "\n")
366
338
rmtree(cache_root)
376
348
To retrieve the branch as of a particular revision, supply the --revision
377
349
parameter, as in "branch foo/bar -r 5".
379
--basis is to speed up branching from remote branches. When specified, it
380
copies all the file-contents, inventory and revision data from the basis
381
branch before copying anything from the remote branch.
383
351
takes_args = ['from_location', 'to_location?']
384
takes_options = ['revision', 'basis']
352
takes_options = ['revision']
385
353
aliases = ['get', 'clone']
387
def run(self, from_location, to_location=None, revision=None, basis=None):
388
from bzrlib.clone import copy_branch
355
def run(self, from_location, to_location=None, revision=None):
356
from bzrlib.branch import copy_branch, find_cached_branch
391
359
from shutil import rmtree
392
360
cache_root = tempfile.mkdtemp()
395
elif len(revision) > 1:
396
raise BzrCommandError(
397
'bzr branch --revision takes exactly 1 revision value')
399
br_from = Branch.open(from_location)
401
if e.errno == errno.ENOENT:
402
raise BzrCommandError('Source location "%s" does not'
403
' exist.' % to_location)
408
br_from.setup_caching(cache_root)
409
if basis is not None:
410
basis_branch = Branch.open_containing(basis)
413
if len(revision) == 1 and revision[0] is not None:
414
revision_id = revision[0].in_history(br_from)[1]
364
elif len(revision) > 1:
365
raise BzrCommandError(
366
'bzr branch --revision takes exactly 1 revision value')
368
br_from = find_cached_branch(from_location, cache_root)
370
if e.errno == errno.ENOENT:
371
raise BzrCommandError('Source location "%s" does not'
372
' exist.' % to_location)
417
375
if to_location is None:
418
376
to_location = os.path.basename(from_location.rstrip("/\\"))
431
copy_branch(br_from, to_location, revision_id, basis_branch)
389
copy_branch(br_from, to_location, revision[0])
432
390
except bzrlib.errors.NoSuchRevision:
433
391
rmtree(to_location)
434
392
msg = "The branch %s has no revision %d." % (from_location, revision[0])
435
393
raise BzrCommandError(msg)
436
except bzrlib.errors.UnlistableBranch:
437
msg = "The branch %s cannot be used as a --basis"
440
395
rmtree(cache_root)
443
398
class cmd_renames(Command):
444
399
"""Show list of renamed files.
401
TODO: Option to show renames between two historical versions.
403
TODO: Only show renames under dir, rather than in the whole branch.
446
# TODO: Option to show renames between two historical versions.
448
# TODO: Only show renames under dir, rather than in the whole branch.
449
405
takes_args = ['dir?']
451
407
def run(self, dir='.'):
452
b = Branch.open_containing(dir)
453
409
old_inv = b.basis_tree().inventory
454
410
new_inv = b.read_working_inventory()
523
479
"""Display list of revision ids on this branch."""
526
for patchid in Branch.open_containing('.').revision_history():
482
for patchid in find_branch('.').revision_history():
530
class cmd_ancestry(Command):
531
"""List all revisions merged into this branch."""
535
for revision_id in b.get_ancestry(b.last_revision()):
539
486
class cmd_directories(Command):
540
487
"""Display list of versioned directories in this branch."""
542
for name, ie in Branch.open_containing('.').read_working_inventory().directories():
489
for name, ie in find_branch('.').read_working_inventory().directories():
569
517
If files are listed, only the changes in those files are listed.
570
518
Otherwise, all changes for the tree are listed.
520
TODO: Allow diff across branches.
522
TODO: Option to use external diff command; could be GNU diff, wdiff,
525
TODO: Python difflib is not exactly the same as unidiff; should
526
either fix it up or prefer to use an external diff.
528
TODO: If a directory is given, diff everything under that.
530
TODO: Selected-file diff is inefficient and doesn't show you
533
TODO: This probably handles non-Unix newlines poorly.
577
# TODO: Allow diff across branches.
578
# TODO: Option to use external diff command; could be GNU diff, wdiff,
579
# or a graphical diff.
581
# TODO: Python difflib is not exactly the same as unidiff; should
582
# either fix it up or prefer to use an external diff.
584
# TODO: If a directory is given, diff everything under that.
586
# TODO: Selected-file diff is inefficient and doesn't show you
589
# TODO: This probably handles non-Unix newlines poorly.
591
541
takes_args = ['file*']
592
542
takes_options = ['revision', 'diff-options']
624
574
class cmd_deleted(Command):
625
575
"""List files deleted in the working tree.
577
TODO: Show files deleted since a previous revision, or between two revisions.
627
# TODO: Show files deleted since a previous revision, or
628
# between two revisions.
629
# TODO: Much more efficient way to do this: read in new
630
# directories with readdir, rather than stating each one. Same
631
# level of effort but possibly much less IO. (Or possibly not,
632
# if the directories are very large...)
633
579
def run(self, show_ids=False):
634
b = Branch.open_containing('.')
635
581
old = b.basis_tree()
636
582
new = b.working_tree()
584
## TODO: Much more efficient way to do this: read in new
585
## directories with readdir, rather than stating each one. Same
586
## level of effort but possibly much less IO. (Or possibly not,
587
## if the directories are very large...)
637
589
for path, ie in old.inventory.iter_entries():
638
590
if not new.has_id(ie.file_id):
696
648
--message allows you to give a regular expression, which will be evaluated
697
649
so that only matching entries will be displayed.
651
TODO: Make --revision support uuid: and hash: [future tag:] notation.
700
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
702
655
takes_args = ['filename?']
703
656
takes_options = ['forward', 'timezone', 'verbose', 'show-ids', 'revision',
704
657
'long', 'message', 'short',]
717
670
direction = (forward and 'forward') or 'reverse'
720
b = Branch.open_containing(filename)
673
b = find_branch(filename)
721
674
fp = b.relpath(filename)
723
676
file_id = b.read_working_inventory().path2id(fp)
725
678
file_id = None # points to branch root
727
b = Branch.open_containing('.')
730
683
if revision is None:
733
686
elif len(revision) == 1:
734
rev1 = rev2 = revision[0].in_history(b).revno
687
rev1 = rev2 = b.get_revision_info(revision[0])[0]
735
688
elif len(revision) == 2:
736
rev1 = revision[0].in_history(b).revno
737
rev2 = revision[1].in_history(b).revno
689
rev1 = b.get_revision_info(revision[0])[0]
690
rev2 = b.get_revision_info(revision[1])[0]
739
692
raise BzrCommandError('bzr log --revision takes one or two values.')
786
739
class cmd_ls(Command):
787
740
"""List files in a tree.
742
TODO: Take a revision or remote path and list that tree instead.
789
# TODO: Take a revision or remote path and list that tree instead.
791
745
def run(self, revision=None, verbose=False):
792
b = Branch.open_containing('.')
793
747
if revision == None:
794
748
tree = b.working_tree()
796
tree = b.revision_tree(revision.in_history(b).rev_id)
797
for fp, fc, kind, fid, entry in tree.list_files():
750
tree = b.revision_tree(b.lookup_revision(revision))
752
for fp, fc, kind, fid in tree.list_files():
799
kindch = entry.kind_character()
754
if kind == 'directory':
800
761
print '%-8s %s%s' % (fc, fp, kindch)
920
879
takes_options = ['revision', 'format', 'root']
921
880
def run(self, dest, revision=None, format=None, root=None):
923
b = Branch.open_containing('.')
924
883
if revision is None:
925
rev_id = b.last_revision()
884
rev_id = b.last_patch()
927
886
if len(revision) != 1:
928
887
raise BzrError('bzr export --revision takes exactly 1 argument')
929
rev_id = revision[0].in_history(b).rev_id
888
revno, rev_id = b.get_revision_info(revision[0])
930
889
t = b.revision_tree(rev_id)
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':
890
root, ext = os.path.splitext(dest)
940
892
if ext in (".tar",):
942
elif ext in (".tar.gz", ".tgz"):
894
elif ext in (".gz", ".tgz"):
944
elif ext in (".tar.bz2", ".tbz2"):
896
elif ext in (".bz2", ".tbz2"):
955
907
takes_args = ['filename']
957
909
def run(self, filename, revision=None):
959
911
raise BzrCommandError("bzr cat requires a revision number")
960
912
elif len(revision) != 1:
961
913
raise BzrCommandError("bzr cat --revision takes exactly one number")
962
b = Branch.open_containing('.')
963
b.print_file(b.relpath(filename), revision[0].in_history(b).revno)
915
b.print_file(b.relpath(filename), revision[0])
966
918
class cmd_local_time_offset(Command):
983
935
A selected-file commit may fail in some cases where the committed
984
936
tree would be invalid, such as trying to commit a file in a
985
937
newly-added directory that is not itself committed.
939
TODO: Run hooks on tree to-be-committed, and after commit.
941
TODO: Strict commit that fails if there are unknown or deleted files.
987
# TODO: Run hooks on tree to-be-committed, and after commit.
989
# TODO: Strict commit that fails if there are unknown or deleted files.
990
# TODO: Give better message for -s, --summary, used by tla people
992
# XXX: verbose currently does nothing
994
943
takes_args = ['selected*']
995
944
takes_options = ['message', 'file', 'verbose', 'unchanged']
996
945
aliases = ['ci', 'checkin']
947
# TODO: Give better message for -s, --summary, used by tla people
998
949
def run(self, message=None, file=None, verbose=True, selected_list=None,
999
950
unchanged=False):
1000
from bzrlib.errors import PointlessCommit, ConflictsInTree
951
from bzrlib.errors import PointlessCommit
1001
952
from bzrlib.msgeditor import edit_commit_message
1002
953
from bzrlib.status import show_status
1003
954
from cStringIO import StringIO
1005
b = Branch.open_containing('.')
1006
957
if selected_list:
1007
958
selected_list = [b.relpath(s) for s in selected_list]
1010
if message is None and not file:
960
if not message and not file:
1011
961
catcher = StringIO()
1012
962
show_status(b, specific_files=selected_list,
1013
963
to_file=catcher)
1014
964
message = edit_commit_message(catcher.getvalue())
1016
966
if message is None:
1017
967
raise BzrCommandError("please specify a commit message"
1018
968
" with either --message or --file")
1097
1042
def run(self, email=False):
1099
b = bzrlib.branch.Branch.open_containing('.')
1100
except NotBranchError:
1044
b = bzrlib.branch.find_branch('.')
1104
print bzrlib.config.user_email(b)
1049
print bzrlib.osutils.user_email(b)
1106
print bzrlib.config.username(b)
1051
print bzrlib.osutils.username(b)
1109
1054
class cmd_selftest(Command):
1110
"""Run internal test suite.
1112
This creates temporary test directories in the working directory,
1113
but not existing data is affected. These directories are deleted
1114
if the tests pass, or left behind to help in debugging if they
1117
If arguments are given, they are regular expressions that say
1118
which tests should run."""
1119
# TODO: --list should give a list of all available tests
1055
"""Run internal test suite"""
1121
takes_args = ['testspecs*']
1122
takes_options = ['verbose']
1123
def run(self, testspecs_list=None, verbose=False):
1057
takes_options = ['verbose', 'pattern']
1058
def run(self, verbose=False, pattern=".*"):
1124
1059
import bzrlib.ui
1125
1060
from bzrlib.selftest import selftest
1126
1061
# we don't want progress meters from the tests to go to the
1174
1104
class cmd_find_merge_base(Command):
1175
1105
"""Find and print a base revision for merging two branches.
1107
TODO: Options to specify revisions on either side, as if
1108
merging only part of the history.
1177
# TODO: Options to specify revisions on either side, as if
1178
# merging only part of the history.
1179
1110
takes_args = ['branch', 'other']
1182
1113
def run(self, branch, other):
1183
1114
from bzrlib.revision import common_ancestor, MultipleRevisionSources
1185
branch1 = Branch.open_containing(branch)
1186
branch2 = Branch.open_containing(other)
1116
branch1 = find_branch(branch)
1117
branch2 = find_branch(other)
1188
1119
history_1 = branch1.revision_history()
1189
1120
history_2 = branch2.revision_history()
1191
last1 = branch1.last_revision()
1192
last2 = branch2.last_revision()
1122
last1 = branch1.last_patch()
1123
last2 = branch2.last_patch()
1194
1125
source = MultipleRevisionSources(branch1, branch2)
1213
1144
class cmd_merge(Command):
1214
1145
"""Perform a three-way merge.
1216
The branch is the branch you will merge from. By default, it will
1217
merge the latest revision. If you specify a revision, that
1218
revision will be merged. If you specify two revisions, the first
1219
will be used as a BASE, and the second one as OTHER. Revision
1220
numbers are always relative to the specified branch.
1222
By default bzr will try to merge in all new work from the other
1223
branch, automatically determining an appropriate base. If this
1224
fails, you may need to give an explicit base.
1147
The branch is the branch you will merge from. By default, it will merge
1148
the latest revision. If you specify a revision, that revision will be
1149
merged. If you specify two revisions, the first will be used as a BASE,
1150
and the second one as OTHER. Revision numbers are always relative to the
1240
1167
takes_args = ['branch?']
1241
1168
takes_options = ['revision', 'force', 'merge-type']
1243
def run(self, branch=None, revision=None, force=False,
1170
def run(self, branch='.', revision=None, force=False,
1244
1171
merge_type=None):
1245
1172
from bzrlib.merge import merge
1246
1173
from bzrlib.merge_core import ApplyMerge3
1247
1174
if merge_type is None:
1248
1175
merge_type = ApplyMerge3
1250
branch = Branch.open_containing('.').get_parent()
1252
raise BzrCommandError("No merge location known or specified.")
1254
print "Using saved location: %s" % branch
1255
1177
if revision is None or len(revision) < 1:
1256
1178
base = [None, None]
1257
other = [branch, -1]
1179
other = (branch, -1)
1259
1181
if len(revision) == 1:
1261
other = [branch, revision[0].in_history(branch).revno]
1182
other = (branch, revision[0])
1263
1185
assert len(revision) == 2
1264
1186
if None in revision:
1265
1187
raise BzrCommandError(
1266
1188
"Merge doesn't permit that revision specifier.")
1267
b = Branch.open(branch)
1269
base = [branch, revision[0].in_history(b).revno]
1270
other = [branch, revision[1].in_history(b).revno]
1273
merge(other, base, check_clean=(not force), merge_type=merge_type)
1274
except bzrlib.errors.AmbiguousBase, e:
1275
m = ("sorry, bzr can't determine the right merge base yet\n"
1276
"candidates are:\n "
1277
+ "\n ".join(e.bases)
1279
"please specify an explicit base with -r,\n"
1280
"and (if you want) report this to the bzr developers\n")
1189
base = (branch, revision[0])
1190
other = (branch, revision[1])
1192
merge(other, base, check_clean=(not force), merge_type=merge_type)
1284
1195
class cmd_revert(Command):
1295
1206
def run(self, revision=None, no_backup=False, file_list=None):
1296
1207
from bzrlib.merge import merge
1208
from bzrlib.branch import Branch
1297
1209
from bzrlib.commands import parse_spec
1299
1211
if file_list is not None:
1300
1212
if len(file_list) == 0:
1301
1213
raise BzrCommandError("No files specified")
1302
1214
if revision is None:
1304
1216
elif len(revision) != 1:
1305
1217
raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
1307
b = Branch.open_containing('.')
1308
revno = revision[0].in_history(b).revno
1309
merge(('.', revno), parse_spec('.'),
1218
merge(('.', revision[0]), parse_spec('.'),
1310
1219
check_clean=False,
1311
1220
ignore_zero=True,
1312
1221
backup_files=not no_backup,
1313
1222
file_list=file_list)
1314
1223
if not file_list:
1315
Branch.open_containing('.').set_pending_merges([])
1224
Branch('.').set_pending_merges([])
1318
1227
class cmd_assert_fail(Command):
1350
1259
shellcomplete.shellcomplete(context)
1353
class cmd_fetch(Command):
1354
"""Copy in history from another branch but don't merge it.
1356
This is an internal method used for pull and merge."""
1358
takes_args = ['from_branch', 'to_branch']
1359
def run(self, from_branch, to_branch):
1360
from bzrlib.fetch import Fetcher
1361
from bzrlib.branch import Branch
1362
from_b = Branch(from_branch)
1363
to_b = Branch(to_branch)
1364
Fetcher(to_b, from_b)
1368
1262
class cmd_missing(Command):
1369
1263
"""What is missing in this branch relative to other branch.
1371
# TODO: rewrite this in terms of ancestry so that it shows only
1374
1265
takes_args = ['remote?']
1375
1266
aliases = ['mis', 'miss']
1376
1267
# We don't have to add quiet to the list, because
1394
1285
print "Using last location: %s" % parent
1395
1286
remote = parent
1396
1287
elif parent is None:
1397
# We only update parent if it did not exist, missing
1398
# should not change the parent
1399
b.set_parent(remote)
1400
br_remote = Branch.open_containing(remote)
1288
# We only update x-pull if it did not exist, missing should not change the parent
1289
b.controlfile('x-pull', 'wb').write(remote + '\n')
1290
br_remote = find_branch(remote)
1401
1292
return show_missing(b, br_remote, verbose=verbose, quiet=quiet)
1404
1296
class cmd_plugins(Command):
1405
1297
"""List plugins"""
1420
1312
print '\t', d.split('\n')[0]
1423
class cmd_testament(Command):
1424
"""Show testament (signing-form) of a revision."""
1425
takes_options = ['revision', 'long']
1426
takes_args = ['branch?']
1427
def run(self, branch='.', revision=None, long=False):
1428
from bzrlib.testament import Testament
1429
b = Branch.open_containing(branch)
1432
if revision is None:
1433
rev_id = b.last_revision()
1435
rev_id = revision[0].in_history(b).rev_id
1436
t = Testament.from_revision(b, rev_id)
1438
sys.stdout.writelines(t.as_text_lines())
1440
sys.stdout.write(t.as_short_text())
1445
class cmd_annotate(Command):
1446
"""Show the origin of each line in a file.
1448
This prints out the given file with an annotation on the
1449
left side indicating which revision, author and date introduced the
1452
# TODO: annotate directories; showing when each file was last changed
1453
# TODO: annotate a previous version of a file
1454
aliases = ['blame', 'praise']
1455
takes_args = ['filename']
1457
def run(self, filename):
1458
from bzrlib.annotate import annotate_file
1459
b = Branch.open_containing(filename)
1462
rp = b.relpath(filename)
1463
tree = b.revision_tree(b.last_revision())
1464
file_id = tree.inventory.path2id(rp)
1465
file_version = tree.inventory[file_id].revision
1466
annotate_file(b, file_version, file_id, sys.stdout)
1470
# these get imported and then picked up by the scan for cmd_*
1471
# TODO: Some more consistent way to split command definitions across files;
1472
# we do need to load at least some information about them to know of
1474
from bzrlib.conflicts import cmd_resolve, cmd_conflicts