29
26
from bzrlib import BZRDIR
30
27
from bzrlib.commands import Command, display_command
31
28
from bzrlib.branch import Branch
32
from bzrlib.revision import common_ancestor
33
import bzrlib.errors as errors
34
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError,
35
NotBranchError, DivergedBranches, NotConflicted,
36
NoSuchFile, NoWorkingTree, FileInWrongBranch)
29
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError, NotBranchError
30
from bzrlib.errors import DivergedBranches
37
31
from bzrlib.option import Option
38
32
from bzrlib.revisionspec import RevisionSpec
39
33
import bzrlib.trace
40
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
34
from bzrlib.trace import mutter, note, log_error, warning
41
35
from bzrlib.workingtree import WorkingTree
42
from bzrlib.log import show_one_log
45
def tree_files(file_list, default_branch=u'.'):
47
return internal_tree_files(file_list, default_branch)
48
except FileInWrongBranch, e:
49
raise BzrCommandError("%s is not in the same branch as %s" %
50
(e.path, file_list[0]))
52
def internal_tree_files(file_list, default_branch=u'.'):
38
def branch_files(file_list, default_branch='.'):
54
40
Return a branch and list of branch-relative paths.
55
41
If supplied file_list is empty or None, the branch default will be used,
56
42
and returned file_list will match the original.
58
44
if file_list is None or len(file_list) == 0:
59
return WorkingTree.open_containing(default_branch)[0], file_list
60
tree = WorkingTree.open_containing(file_list[0])[0]
45
return Branch.open_containing(default_branch)[0], file_list
46
b = Branch.open_containing(file_list[0])[0]
48
# note that if this is a remote branch, we would want
49
# relpath against the transport. RBC 20051018
50
# Most branch ops can't meaningfully operate on files in remote branches;
51
# the above comment was in cmd_status. ADHB 20051026
52
tree = WorkingTree(b.base, b)
62
54
for filename in file_list:
64
56
new_list.append(tree.relpath(filename))
65
except errors.PathNotChild:
66
raise FileInWrongBranch(tree.branch, filename)
57
except NotBranchError:
58
raise BzrCommandError("%s is not in the same branch as %s" %
59
(filename, file_list[0]))
70
63
# TODO: Make sure no commands unconditionally use the working directory as a
113
106
that revision, or between two revisions if two are provided.
109
# XXX: FIXME: bzr status should accept a -r option to show changes
110
# relative to a revision, or between revisions
116
112
# TODO: --no-recurse, --recurse options
118
114
takes_args = ['file*']
119
takes_options = ['all', 'show-ids', 'revision']
115
takes_options = ['all', 'show-ids']
120
116
aliases = ['st', 'stat']
123
119
def run(self, all=False, show_ids=False, file_list=None, revision=None):
124
tree, file_list = tree_files(file_list)
120
b, file_list = branch_files(file_list)
126
122
from bzrlib.status import show_status
127
show_status(tree.branch, show_unchanged=all, show_ids=show_ids,
123
show_status(b, show_unchanged=all, show_ids=show_ids,
128
124
specific_files=file_list, revision=revision)
146
142
raise BzrCommandError('You can only supply one of revision_id or --revision')
147
143
if revision_id is None and revision is None:
148
144
raise BzrCommandError('You must supply either --revision or a revision_id')
149
b = WorkingTree.open_containing(u'.')[0].branch
145
b = Branch.open_containing('.')[0]
150
146
if revision_id is not None:
151
sys.stdout.write(b.get_revision_xml(revision_id))
147
sys.stdout.write(b.get_revision_xml_file(revision_id).read())
152
148
elif revision is not None:
153
149
for rev in revision:
155
151
raise BzrCommandError('You cannot specify a NULL revision.')
156
152
revno, rev_id = rev.in_history(b)
157
sys.stdout.write(b.get_revision_xml(rev_id))
153
sys.stdout.write(b.get_revision_xml_file(rev_id).read())
160
156
class cmd_revno(Command):
161
157
"""Show current revision number.
163
159
This is equal to the number of revisions on this branch."""
164
takes_args = ['location?']
166
def run(self, location=u'.'):
167
print Branch.open_containing(location)[0].revno()
162
print Branch.open_containing('.')[0].revno()
170
165
class cmd_revision_info(Command):
217
212
implicitly add the parent, and so on up to the root. This means
218
213
you should never need to explictly add a directory, they'll just
219
214
get added when you add a file in the directory.
221
--dry-run will show which files would be added, but not actually
224
216
takes_args = ['file*']
225
takes_options = ['no-recurse', 'dry-run', 'verbose']
227
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
232
# This is pointless, but I'd rather not raise an error
233
action = bzrlib.add.add_action_null
235
action = bzrlib.add.add_action_print
237
action = bzrlib.add.add_action_add
217
takes_options = ['no-recurse', 'quiet']
219
def run(self, file_list, no_recurse=False, quiet=False):
220
from bzrlib.add import smart_add, add_reporter_print, add_reporter_null
222
reporter = add_reporter_null
239
action = bzrlib.add.add_action_add_and_print
241
added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
244
for glob in sorted(ignored.keys()):
245
match_len = len(ignored[glob])
247
for path in ignored[glob]:
248
print "ignored %s matching \"%s\"" % (path, glob)
250
print "ignored %d file(s) matching \"%s\"" % (match_len,
252
print "If you wish to add some of these files, please add them"\
224
reporter = add_reporter_print
225
smart_add(file_list, not no_recurse, reporter)
256
228
class cmd_mkdir(Command):
277
252
def run(self, filename):
278
tree, relpath = WorkingTree.open_containing(filename)
253
branch, relpath = Branch.open_containing(filename)
282
257
class cmd_inventory(Command):
283
"""Show inventory of the current working copy or a revision.
285
It is possible to limit the output to a particular entry
286
type using the --kind option. For example; --kind file.
288
takes_options = ['revision', 'show-ids', 'kind']
258
"""Show inventory of the current working copy or a revision."""
259
takes_options = ['revision', 'show-ids']
291
def run(self, revision=None, show_ids=False, kind=None):
292
if kind and kind not in ['file', 'directory', 'symlink']:
293
raise BzrCommandError('invalid kind specified')
294
tree = WorkingTree.open_containing(u'.')[0]
262
def run(self, revision=None, show_ids=False):
263
b = Branch.open_containing('.')[0]
295
264
if revision is None:
296
inv = tree.read_working_inventory()
265
inv = b.read_working_inventory()
298
267
if len(revision) > 1:
299
268
raise BzrCommandError('bzr inventory --revision takes'
300
269
' exactly one revision identifier')
301
inv = tree.branch.get_revision_inventory(
302
revision[0].in_history(tree.branch).rev_id)
270
inv = b.get_revision_inventory(revision[0].in_history(b).rev_id)
304
272
for path, entry in inv.entries():
305
if kind and kind != entry.kind:
308
274
print '%-50s %s' % (path, entry.file_id)
321
287
takes_args = ['source$', 'dest']
322
288
def run(self, source_list, dest):
323
tree, source_list = tree_files(source_list)
289
b, source_list = branch_files(source_list)
324
291
# TODO: glob expansion on windows?
325
tree.move(source_list, tree.relpath(dest))
292
tree = WorkingTree(b.base, b)
293
b.move(source_list, tree.relpath(dest))
328
296
class cmd_rename(Command):
342
310
takes_args = ['from_name', 'to_name']
344
312
def run(self, from_name, to_name):
345
tree, (from_name, to_name) = tree_files((from_name, to_name))
346
tree.rename_one(from_name, to_name)
313
b, (from_name, to_name) = branch_files((from_name, to_name))
314
b.rename_one(from_name, to_name)
349
317
class cmd_mv(Command):
363
331
def run(self, names_list):
364
332
if len(names_list) < 2:
365
333
raise BzrCommandError("missing file argument")
366
tree, rel_names = tree_files(names_list)
334
b, rel_names = branch_files(names_list)
368
336
if os.path.isdir(names_list[-1]):
369
337
# move into existing directory
370
for pair in tree.move(rel_names[:-1], rel_names[-1]):
338
for pair in b.move(rel_names[:-1], rel_names[-1]):
371
339
print "%s => %s" % pair
373
341
if len(names_list) != 2:
374
342
raise BzrCommandError('to mv multiple files the destination '
375
343
'must be a versioned directory')
376
tree.rename_one(rel_names[0], rel_names[1])
344
b.rename_one(rel_names[0], rel_names[1])
377
345
print "%s => %s" % (rel_names[0], rel_names[1])
395
363
If you want to forget your local changes and just update your branch to
396
364
match the remote one, use --overwrite.
398
takes_options = ['remember', 'overwrite', 'verbose']
366
takes_options = ['remember', 'overwrite']
399
367
takes_args = ['location?']
401
def run(self, location=None, remember=False, overwrite=False, verbose=False):
369
def run(self, location=None, remember=False, overwrite=False):
402
370
from bzrlib.merge import merge
403
371
from shutil import rmtree
405
# FIXME: too much stuff is in the command class
406
tree_to = WorkingTree.open_containing(u'.')[0]
407
stored_loc = tree_to.branch.get_parent()
374
br_to = Branch.open_containing('.')[0]
375
stored_loc = br_to.get_parent()
408
376
if location is None:
409
377
if stored_loc is None:
410
378
raise BzrCommandError("No pull location known or specified.")
412
380
print "Using saved location: %s" % stored_loc
413
381
location = stored_loc
415
br_from = Branch.open(location)
416
br_to = tree_to.branch
418
old_rh = br_to.revision_history()
419
count = tree_to.pull(br_from, overwrite)
421
382
if br_to.get_parent() is None or remember:
422
383
br_to.set_parent(location)
423
note('%d revision(s) pulled.' % (count,))
426
new_rh = tree_to.branch.revision_history()
429
from bzrlib.log import show_changed_revisions
430
show_changed_revisions(tree_to.branch, old_rh, new_rh)
384
br_from = Branch.open(location)
386
br_to.working_tree().pull(br_from, overwrite)
387
except DivergedBranches:
388
raise BzrCommandError("These branches have diverged."
433
392
class cmd_push(Command):
453
412
do a merge (see bzr help merge) from the other branch, and commit that
454
413
before doing a 'push --overwrite'.
456
takes_options = ['remember', 'overwrite',
457
Option('create-prefix',
458
help='Create the path leading up to the branch '
459
'if it does not already exist')]
415
takes_options = ['remember', 'overwrite']
460
416
takes_args = ['location?']
462
def run(self, location=None, remember=False, overwrite=False,
463
create_prefix=False, verbose=False):
464
# FIXME: Way too big! Put this into a function called from the
418
def run(self, location=None, remember=False, overwrite=False):
467
420
from shutil import rmtree
468
421
from bzrlib.transport import get_transport
470
tree_from = WorkingTree.open_containing(u'.')[0]
471
br_from = tree_from.branch
472
stored_loc = tree_from.branch.get_push_location()
423
br_from = Branch.open_containing('.')[0]
424
stored_loc = br_from.get_push_location()
473
425
if location is None:
474
426
if stored_loc is None:
475
427
raise BzrCommandError("No push location known or specified.")
477
429
print "Using saved location: %s" % stored_loc
478
430
location = stored_loc
431
if br_from.get_push_location() is None or remember:
432
br_from.set_push_location(location)
480
434
br_to = Branch.open(location)
481
435
except NotBranchError:
482
436
# create a branch.
483
437
transport = get_transport(location).clone('..')
484
if not create_prefix:
486
transport.mkdir(transport.relpath(location))
488
raise BzrCommandError("Parent directory of %s "
489
"does not exist." % location)
491
current = transport.base
492
needed = [(transport, transport.relpath(location))]
495
transport, relpath = needed[-1]
496
transport.mkdir(relpath)
499
new_transport = transport.clone('..')
500
needed.append((new_transport,
501
new_transport.relpath(transport.base)))
502
if new_transport.base == transport.base:
503
raise BzrCommandError("Could not creeate "
438
transport.mkdir(transport.relpath(location))
505
439
br_to = Branch.initialize(location)
506
old_rh = br_to.revision_history()
509
tree_to = br_to.working_tree()
510
except NoWorkingTree:
511
# TODO: This should be updated for branches which don't have a
512
# working tree, as opposed to ones where we just couldn't
514
warning('Unable to update the working tree of: %s' % (br_to.base,))
515
count = br_to.pull(br_from, overwrite)
517
count = tree_to.pull(br_from, overwrite)
441
br_to.pull(br_from, overwrite)
518
442
except DivergedBranches:
519
443
raise BzrCommandError("These branches have diverged."
520
444
" Try a merge then push with overwrite.")
521
if br_from.get_push_location() is None or remember:
522
br_from.set_push_location(location)
523
note('%d revision(s) pushed.' % (count,))
526
new_rh = br_to.revision_history()
529
from bzrlib.log import show_changed_revisions
530
show_changed_revisions(br_to, old_rh, new_rh)
533
447
class cmd_branch(Command):
728
650
bzr commit -m 'imported project'
730
takes_args = ['location?']
731
def run(self, location=None):
732
from bzrlib.branch import Branch
736
# The path has to exist to initialize a
737
# branch inside of it.
738
# Just using os.mkdir, since I don't
739
# believe that we want to create a bunch of
740
# locations if the user supplies an extended path
741
if not os.path.exists(location):
743
Branch.initialize(location)
653
Branch.initialize('.')
746
656
class cmd_diff(Command):
776
686
def run(self, revision=None, file_list=None, diff_options=None):
777
687
from bzrlib.diff import show_diff
779
tree, file_list = internal_tree_files(file_list)
782
except FileInWrongBranch:
783
if len(file_list) != 2:
784
raise BzrCommandError("Files are in different branches")
786
b, file1 = Branch.open_containing(file_list[0])
787
b2, file2 = Branch.open_containing(file_list[1])
788
if file1 != "" or file2 != "":
789
# FIXME diff those two files. rbc 20051123
790
raise BzrCommandError("Files are in different branches")
689
b, file_list = branch_files(file_list)
792
690
if revision is not None:
794
raise BzrCommandError("Can't specify -r with two branches")
795
691
if len(revision) == 1:
796
return show_diff(tree.branch, revision[0], specific_files=file_list,
692
return show_diff(b, revision[0], specific_files=file_list,
797
693
external_diff_options=diff_options)
798
694
elif len(revision) == 2:
799
return show_diff(tree.branch, revision[0], specific_files=file_list,
695
return show_diff(b, revision[0], specific_files=file_list,
800
696
external_diff_options=diff_options,
801
697
revision2=revision[1])
803
699
raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
806
return show_diff(b, None, specific_files=file_list,
807
external_diff_options=diff_options, b2=b2)
809
return show_diff(tree.branch, None, specific_files=file_list,
810
external_diff_options=diff_options)
701
return show_diff(b, None, specific_files=file_list,
702
external_diff_options=diff_options)
813
705
class cmd_deleted(Command):
821
713
# if the directories are very large...)
823
715
def run(self, show_ids=False):
824
tree = WorkingTree.open_containing(u'.')[0]
825
old = tree.branch.basis_tree()
716
b = Branch.open_containing('.')[0]
718
new = b.working_tree()
826
719
for path, ie in old.inventory.iter_entries():
827
if not tree.has_id(ie.file_id):
720
if not new.has_id(ie.file_id):
829
722
print '%-50s %s' % (path, ie.file_id)
874
768
def run(self, filename=None):
875
769
"""Print the branch root."""
876
tree = WorkingTree.open_containing(filename)[0]
770
b = Branch.open_containing(filename)[0]
880
774
class cmd_log(Command):
881
775
"""Show log of this branch.
883
To request a range of logs, you can use the command -r begin..end
884
-r revision requests a specific revision, -r ..end or -r begin.. are
777
To request a range of logs, you can use the command -r begin:end
778
-r revision requests a specific revision, -r :end or -r begin: are
915
810
direction = (forward and 'forward') or 'reverse'
921
tree, fp = WorkingTree.open_containing(filename)
924
inv = tree.read_working_inventory()
925
except NotBranchError:
928
b, fp = Branch.open_containing(filename)
930
inv = b.get_inventory(b.last_revision())
813
b, fp = Branch.open_containing(filename)
932
file_id = inv.path2id(fp)
815
file_id = b.read_working_inventory().path2id(fp)
934
817
file_id = None # points to branch root
936
tree, relpath = WorkingTree.open_containing(u'.')
819
b, relpath = Branch.open_containing('.')
940
822
if revision is None:
949
831
raise BzrCommandError('bzr log --revision takes one or two values.')
951
# By this point, the revision numbers are converted to the +ve
952
# form if they were supplied in the -ve form, so we can do
953
# this comparison in relative safety
955
(rev2, rev1) = (rev1, rev2)
957
mutter('encoding log as %r', bzrlib.user_encoding)
838
mutter('encoding log as %r' % bzrlib.user_encoding)
959
840
# use 'replace' so that we don't abort if trying to write out
960
841
# in e.g. the default C locale.
961
842
outf = codecs.getwriter(bzrlib.user_encoding)(sys.stdout, errors='replace')
963
log_format = get_log_format(long=long, short=short, line=line)
964
849
lf = log_formatter(log_format,
965
850
show_ids=show_ids,
994
870
takes_args = ["filename"]
996
872
def run(self, filename):
997
tree, relpath = WorkingTree.open_containing(filename)
999
inv = tree.read_working_inventory()
873
b, relpath = Branch.open_containing(filename)[0]
874
inv = b.read_working_inventory()
1000
875
file_id = inv.path2id(relpath)
1001
876
for revno, revision_id, what in bzrlib.log.find_touching_revisions(b, file_id):
1002
877
print "%6d %s" % (revno, what)
1031
906
selection = {'I':ignored, '?':unknown, 'V':versioned}
1033
tree, relpath = WorkingTree.open_containing(u'.')
908
b, relpath = Branch.open_containing('.')
1038
if revision is not None:
1039
tree = tree.branch.revision_tree(
1040
revision[0].in_history(tree.branch).rev_id)
914
tree = b.working_tree()
916
tree = b.revision_tree(revision[0].in_history(b).rev_id)
1041
917
for fp, fc, kind, fid, entry in tree.list_files():
1042
918
if fp.startswith(relpath):
1043
919
fp = fp[len(relpath):]
1168
1047
is found exports to a directory (equivalent to --format=dir).
1170
1049
Root may be the top directory for tar, tgz and tbz2 formats. If none
1171
is given, the top directory will be the root name of the file.
1173
Note: export of tree with non-ascii filenames to zip is not supported.
1175
Supported formats Autodetected by extension
1176
----------------- -------------------------
1179
tbz2 .tar.bz2, .tbz2
1050
is given, the top directory will be the root name of the file."""
1051
# TODO: list known exporters
1183
1052
takes_args = ['dest']
1184
1053
takes_options = ['revision', 'format', 'root']
1185
1054
def run(self, dest, revision=None, format=None, root=None):
1187
from bzrlib.export import export
1188
tree = WorkingTree.open_containing(u'.')[0]
1056
b = Branch.open_containing('.')[0]
1190
1057
if revision is None:
1191
# should be tree.last_revision FIXME
1192
1058
rev_id = b.last_revision()
1194
1060
if len(revision) != 1:
1195
1061
raise BzrError('bzr export --revision takes exactly 1 argument')
1196
1062
rev_id = revision[0].in_history(b).rev_id
1197
1063
t = b.revision_tree(rev_id)
1199
export(t, dest, format, root)
1200
except errors.NoSuchExportFormat, e:
1201
raise BzrCommandError('Unsupported export format: %s' % e.format)
1064
arg_root, ext = os.path.splitext(os.path.basename(dest))
1065
if ext in ('.gz', '.bz2'):
1066
new_root, new_ext = os.path.splitext(arg_root)
1067
if new_ext == '.tar':
1073
if ext in (".tar",):
1075
elif ext in (".tar.gz", ".tgz"):
1077
elif ext in (".tar.bz2", ".tbz2"):
1081
t.export(dest, format, root)
1204
1084
class cmd_cat(Command):
1210
1090
@display_command
1211
1091
def run(self, filename, revision=None):
1212
if revision is not None and len(revision) != 1:
1092
if revision is None:
1093
raise BzrCommandError("bzr cat requires a revision number")
1094
elif len(revision) != 1:
1213
1095
raise BzrCommandError("bzr cat --revision takes exactly one number")
1216
tree, relpath = WorkingTree.open_containing(filename)
1218
except NotBranchError:
1222
b, relpath = Branch.open_containing(filename)
1223
if revision is None:
1224
revision_id = b.last_revision()
1226
revision_id = revision[0].in_history(b).rev_id
1227
b.print_file(relpath, revision_id)
1096
b, relpath = Branch.open_containing(filename)
1097
b.print_file(relpath, revision[0].in_history(b).revno)
1230
1100
class cmd_local_time_offset(Command):
1275
1145
unchanged=False, strict=False):
1276
1146
from bzrlib.errors import (PointlessCommit, ConflictsInTree,
1277
1147
StrictCommitFailed)
1278
from bzrlib.msgeditor import edit_commit_message, \
1279
make_commit_message_template
1148
from bzrlib.msgeditor import edit_commit_message
1280
1149
from bzrlib.status import show_status
1281
from tempfile import TemporaryFile
1284
# TODO: Need a blackbox test for invoking the external editor; may be
1285
# slightly problematic to run this cross-platform.
1287
# TODO: do more checks that the commit will succeed before
1288
# spending the user's valuable time typing a commit message.
1290
# TODO: if the commit *does* happen to fail, then save the commit
1291
# message to a temporary file where it can be recovered
1292
tree, selected_list = tree_files(selected_list)
1150
from cStringIO import StringIO
1152
b, selected_list = branch_files(selected_list)
1293
1153
if message is None and not file:
1294
template = make_commit_message_template(tree, selected_list)
1295
message = edit_commit_message(template)
1154
catcher = StringIO()
1155
show_status(b, specific_files=selected_list,
1157
message = edit_commit_message(catcher.getvalue())
1296
1159
if message is None:
1297
1160
raise BzrCommandError("please specify a commit message"
1298
1161
" with either --message or --file")
1307
1170
raise BzrCommandError("empty commit message specified")
1310
tree.commit(message, specific_files=selected_list,
1311
allow_pointless=unchanged, strict=strict)
1173
b.commit(message, specific_files=selected_list,
1174
allow_pointless=unchanged, strict=strict)
1312
1175
except PointlessCommit:
1313
1176
# FIXME: This should really happen before the file is read in;
1314
1177
# perhaps prepare the commit; get the message; then actually commit
1329
1191
This command checks various invariants about the branch storage to
1330
1192
detect data corruption or bzr bugs.
1332
takes_args = ['branch?']
1194
takes_args = ['dir?']
1333
1195
takes_options = ['verbose']
1335
def run(self, branch=None, verbose=False):
1197
def run(self, dir='.', verbose=False):
1336
1198
from bzrlib.check import check
1338
tree = WorkingTree.open_containing()[0]
1339
branch = tree.branch
1341
branch = Branch.open(branch)
1342
check(branch, verbose)
1199
check(Branch.open_containing(dir)[0], verbose)
1345
1202
class cmd_scan_cache(Command):
1396
1253
print config.username()
1398
class cmd_nick(Command):
1400
Print or set the branch nickname.
1401
If unset, the tree root directory name is used as the nickname
1402
To print the current nickname, execute with no argument.
1404
takes_args = ['nickname?']
1405
def run(self, nickname=None):
1406
branch = Branch.open_containing(u'.')[0]
1407
if nickname is None:
1408
self.printme(branch)
1410
branch.nick = nickname
1413
def printme(self, branch):
1416
1256
class cmd_selftest(Command):
1417
1257
"""Run internal test suite.
1429
1269
takes_args = ['testspecs*']
1430
1270
takes_options = ['verbose',
1431
1271
Option('one', help='stop when one test fails'),
1432
Option('keep-output',
1433
help='keep output directories when tests fail')
1436
def run(self, testspecs_list=None, verbose=False, one=False,
1274
def run(self, testspecs_list=None, verbose=False, one=False):
1438
1275
import bzrlib.ui
1439
from bzrlib.tests import selftest
1276
from bzrlib.selftest import selftest
1440
1277
# we don't want progress meters from the tests to go to the
1441
1278
# real output; and we don't want log messages cluttering up
1442
1279
# the real logs.
1461
1297
bzrlib.ui.ui_factory = save_ui
1464
def _get_bzr_branch():
1465
"""If bzr is run from a branch, return Branch or None"""
1466
import bzrlib.errors
1467
from bzrlib.branch import Branch
1468
from bzrlib.osutils import abspath
1469
from os.path import dirname
1472
branch = Branch.open(dirname(abspath(dirname(__file__))))
1474
except bzrlib.errors.BzrError:
1478
1300
def show_version():
1479
1301
print "bzr (bazaar-ng) %s" % bzrlib.__version__
1480
1302
# is bzrlib itself in a branch?
1481
branch = _get_bzr_branch()
1483
rh = branch.revision_history()
1485
print " bzr checkout, revision %d" % (revno,)
1486
print " nick: %s" % (branch.nick,)
1488
print " revid: %s" % (rh[-1],)
1303
bzrrev = bzrlib.get_bzr_revision()
1305
print " (bzr checkout, revision %d {%s})" % bzrrev
1489
1306
print bzrlib.__copyright__
1490
1307
print "http://bazaar-ng.org/"
1632
class cmd_remerge(Command):
1635
takes_args = ['file*']
1636
takes_options = ['merge-type', 'reprocess',
1637
Option('show-base', help="Show base revision text in "
1640
def run(self, file_list=None, merge_type=None, show_base=False,
1642
from bzrlib.merge import merge_inner, transform_tree
1643
from bzrlib.merge_core import ApplyMerge3
1644
if merge_type is None:
1645
merge_type = ApplyMerge3
1646
tree, file_list = tree_files(file_list)
1649
pending_merges = tree.pending_merges()
1650
if len(pending_merges) != 1:
1651
raise BzrCommandError("Sorry, remerge only works after normal"
1652
+ " merges. Not cherrypicking or"
1654
base_revision = common_ancestor(tree.branch.last_revision(),
1655
pending_merges[0], tree.branch)
1656
base_tree = tree.branch.revision_tree(base_revision)
1657
other_tree = tree.branch.revision_tree(pending_merges[0])
1658
interesting_ids = None
1659
if file_list is not None:
1660
interesting_ids = set()
1661
for filename in file_list:
1662
file_id = tree.path2id(filename)
1663
interesting_ids.add(file_id)
1664
if tree.kind(file_id) != "directory":
1667
for name, ie in tree.inventory.iter_entries(file_id):
1668
interesting_ids.add(ie.file_id)
1669
transform_tree(tree, tree.branch.basis_tree(), interesting_ids)
1670
if file_list is None:
1671
restore_files = list(tree.iter_conflicts())
1673
restore_files = file_list
1674
for filename in restore_files:
1676
restore(tree.abspath(filename))
1677
except NotConflicted:
1679
conflicts = merge_inner(tree.branch, other_tree, base_tree,
1680
interesting_ids = interesting_ids,
1681
other_rev_id=pending_merges[0],
1682
merge_type=merge_type,
1683
show_base=show_base,
1684
reprocess=reprocess)
1692
1449
class cmd_revert(Command):
1693
1450
"""Reverse all changes since the last commit.
1701
1458
aliases = ['merge-revert']
1703
1460
def run(self, revision=None, no_backup=False, file_list=None):
1704
from bzrlib.merge import merge_inner
1461
from bzrlib.merge import merge
1705
1462
from bzrlib.commands import parse_spec
1706
1464
if file_list is not None:
1707
1465
if len(file_list) == 0:
1708
1466
raise BzrCommandError("No files specified")
1711
1467
if revision is None:
1713
tree = WorkingTree.open_containing(u'.')[0]
1714
# FIXME should be tree.last_revision
1715
rev_id = tree.branch.last_revision()
1716
1469
elif len(revision) != 1:
1717
1470
raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
1719
tree, file_list = tree_files(file_list)
1720
rev_id = revision[0].in_history(tree.branch).rev_id
1721
tree.revert(file_list, tree.branch.revision_tree(rev_id),
1472
b, file_list = branch_files(file_list)
1473
revno = revision[0].in_history(b).revno
1474
merge(('.', revno), parse_spec('.'),
1477
backup_files=not no_backup,
1478
file_list=file_list)
1480
Branch.open_containing('.')[0].set_pending_merges([])
1725
1483
class cmd_assert_fail(Command):
1784
1542
class cmd_missing(Command):
1785
"""Show unmerged/unpulled revisions between two branches.
1787
OTHER_BRANCH may be local or remote."""
1788
takes_args = ['other_branch?']
1789
takes_options = [Option('reverse', 'Reverse the order of revisions'),
1791
'Display changes in the local branch only'),
1792
Option('theirs-only',
1793
'Display changes in the remote branch only'),
1801
def run(self, other_branch=None, reverse=False, mine_only=False,
1802
theirs_only=False, long=True, short=False, line=False,
1803
show_ids=False, verbose=False):
1804
from bzrlib.missing import find_unmerged, iter_log_data
1805
from bzrlib.log import log_formatter
1806
local_branch = bzrlib.branch.Branch.open_containing(u".")[0]
1807
parent = local_branch.get_parent()
1808
if other_branch is None:
1809
other_branch = parent
1810
if other_branch is None:
1543
"""What is missing in this branch relative to other branch.
1545
# TODO: rewrite this in terms of ancestry so that it shows only
1548
takes_args = ['remote?']
1549
aliases = ['mis', 'miss']
1550
# We don't have to add quiet to the list, because
1551
# unknown options are parsed as booleans
1552
takes_options = ['verbose', 'quiet']
1555
def run(self, remote=None, verbose=False, quiet=False):
1556
from bzrlib.errors import BzrCommandError
1557
from bzrlib.missing import show_missing
1559
if verbose and quiet:
1560
raise BzrCommandError('Cannot pass both quiet and verbose')
1562
b = Branch.open_containing('.')[0]
1563
parent = b.get_parent()
1811
1566
raise BzrCommandError("No missing location known or specified.")
1812
print "Using last location: " + local_branch.get_parent()
1813
remote_branch = bzrlib.branch.Branch.open(other_branch)
1814
local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
1815
log_format = get_log_format(long=long, short=short, line=line)
1816
lf = log_formatter(log_format, sys.stdout,
1818
show_timezone='original')
1819
if reverse is False:
1820
local_extra.reverse()
1821
remote_extra.reverse()
1822
if local_extra and not theirs_only:
1823
print "You have %d extra revision(s):" % len(local_extra)
1824
for data in iter_log_data(local_extra, local_branch, verbose):
1826
printed_local = True
1828
printed_local = False
1829
if remote_extra and not mine_only:
1830
if printed_local is True:
1832
print "You are missing %d revision(s):" % len(remote_extra)
1833
for data in iter_log_data(remote_extra, remote_branch, verbose):
1835
if not remote_extra and not local_extra:
1837
print "Branches are up to date."
1840
if parent is None and other_branch is not None:
1841
local_branch.set_parent(other_branch)
1569
print "Using last location: %s" % parent
1571
elif parent is None:
1572
# We only update parent if it did not exist, missing
1573
# should not change the parent
1574
b.set_parent(remote)
1575
br_remote = Branch.open_containing(remote)[0]
1576
return show_missing(b, br_remote, verbose=verbose, quiet=quiet)
1845
1579
class cmd_plugins(Command):
1907
1641
@display_command
1908
1642
def run(self, filename, all=False, long=False):
1909
1643
from bzrlib.annotate import annotate_file
1910
tree, relpath = WorkingTree.open_containing(filename)
1911
branch = tree.branch
1644
b, relpath = Branch.open_containing(filename)
1647
tree = WorkingTree(b.base, b)
1648
tree = b.revision_tree(b.last_revision())
1914
1649
file_id = tree.inventory.path2id(relpath)
1915
tree = branch.revision_tree(branch.last_revision())
1916
1650
file_version = tree.inventory[file_id].revision
1917
annotate_file(branch, file_version, file_id, long, all, sys.stdout)
1651
annotate_file(b, file_version, file_id, long, all, sys.stdout)
1922
1656
class cmd_re_sign(Command):
1958
1692
raise BzrCommandError('Please supply either one revision, or a range.')
1961
class cmd_uncommit(bzrlib.commands.Command):
1962
"""Remove the last committed revision.
1964
By supplying the --all flag, it will not only remove the entry
1965
from revision_history, but also remove all of the entries in the
1968
--verbose will print out what is being removed.
1969
--dry-run will go through all the motions, but not actually
1972
In the future, uncommit will create a changeset, which can then
1975
takes_options = ['all', 'verbose', 'revision',
1976
Option('dry-run', help='Don\'t actually make changes'),
1977
Option('force', help='Say yes to all questions.')]
1978
takes_args = ['location?']
1981
def run(self, location=None, all=False,
1982
dry_run=False, verbose=False,
1983
revision=None, force=False):
1984
from bzrlib.branch import Branch
1985
from bzrlib.log import log_formatter
1987
from bzrlib.uncommit import uncommit
1989
if location is None:
1991
b, relpath = Branch.open_containing(location)
1993
if revision is None:
1995
rev_id = b.last_revision()
1997
revno, rev_id = revision[0].in_history(b)
1999
print 'No revisions to uncommit.'
2001
for r in range(revno, b.revno()+1):
2002
rev_id = b.get_rev_id(r)
2003
lf = log_formatter('short', to_file=sys.stdout,show_timezone='original')
2004
lf.show(r, b.get_revision(rev_id), None)
2007
print 'Dry-run, pretending to remove the above revisions.'
2009
val = raw_input('Press <enter> to continue')
2011
print 'The above revision(s) will be removed.'
2013
val = raw_input('Are you sure [y/N]? ')
2014
if val.lower() not in ('y', 'yes'):
2018
uncommit(b, remove_files=all,
2019
dry_run=dry_run, verbose=verbose,
2023
1695
# these get imported and then picked up by the scan for cmd_*
2024
1696
# TODO: Some more consistent way to split command definitions across files;
2025
1697
# we do need to load at least some information about them to know of
2027
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
1699
from bzrlib.conflicts import cmd_resolve, cmd_conflicts