27
27
from bzrlib.commands import Command, display_command
28
28
from bzrlib.branch import Branch
29
29
from bzrlib.revision import common_ancestor
30
import bzrlib.errors as errors
30
31
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError,
31
32
NotBranchError, DivergedBranches, NotConflicted,
32
NoSuchFile, NoWorkingTree, FileInWrongBranch)
33
NoSuchFile, NoWorkingTree, FileInWrongBranch)
33
34
from bzrlib.option import Option
34
35
from bzrlib.revisionspec import RevisionSpec
35
36
import bzrlib.trace
36
from bzrlib.trace import mutter, note, log_error, warning
37
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
37
38
from bzrlib.workingtree import WorkingTree
40
def branch_files(file_list, default_branch='.'):
41
def tree_files(file_list, default_branch=u'.'):
42
return inner_branch_files(file_list, default_branch)
43
return internal_tree_files(file_list, default_branch)
43
44
except FileInWrongBranch, e:
45
45
raise BzrCommandError("%s is not in the same branch as %s" %
46
46
(e.path, file_list[0]))
48
def inner_branch_files(file_list, default_branch='.'):
48
def internal_tree_files(file_list, default_branch=u'.'):
50
50
Return a branch and list of branch-relative paths.
51
51
If supplied file_list is empty or None, the branch default will be used,
52
52
and returned file_list will match the original.
54
54
if file_list is None or len(file_list) == 0:
55
return Branch.open_containing(default_branch)[0], file_list
56
b = Branch.open_containing(file_list[0])[0]
58
# note that if this is a remote branch, we would want
59
# relpath against the transport. RBC 20051018
60
# Most branch ops can't meaningfully operate on files in remote branches;
61
# the above comment was in cmd_status. ADHB 20051026
62
tree = WorkingTree(b.base, b)
55
return WorkingTree.open_containing(default_branch)[0], file_list
56
tree = WorkingTree.open_containing(file_list[0])[0]
64
58
for filename in file_list:
66
60
new_list.append(tree.relpath(filename))
67
61
except NotBranchError:
68
raise FileInWrongBranch(b, filename)
62
raise FileInWrongBranch(tree.branch, filename)
72
66
# TODO: Make sure no commands unconditionally use the working directory as a
125
119
def run(self, all=False, show_ids=False, file_list=None, revision=None):
126
b, file_list = branch_files(file_list)
120
tree, file_list = tree_files(file_list)
128
122
from bzrlib.status import show_status
129
show_status(b, show_unchanged=all, show_ids=show_ids,
123
show_status(tree.branch, show_unchanged=all, show_ids=show_ids,
130
124
specific_files=file_list, revision=revision)
148
142
raise BzrCommandError('You can only supply one of revision_id or --revision')
149
143
if revision_id is None and revision is None:
150
144
raise BzrCommandError('You must supply either --revision or a revision_id')
151
b = Branch.open_containing('.')[0]
145
b = WorkingTree.open_containing(u'.')[0].branch
152
146
if revision_id is not None:
153
sys.stdout.write(b.get_revision_xml_file(revision_id).read())
147
sys.stdout.write(b.get_revision_xml(revision_id))
154
148
elif revision is not None:
155
149
for rev in revision:
157
151
raise BzrCommandError('You cannot specify a NULL revision.')
158
152
revno, rev_id = rev.in_history(b)
159
sys.stdout.write(b.get_revision_xml_file(rev_id).read())
153
sys.stdout.write(b.get_revision_xml(rev_id))
162
156
class cmd_revno(Command):
220
214
get added when you add a file in the directory.
222
216
takes_args = ['file*']
223
takes_options = ['no-recurse', 'quiet']
217
takes_options = ['no-recurse']
225
def run(self, file_list, no_recurse=False, quiet=False):
219
def run(self, file_list, no_recurse=False):
226
220
from bzrlib.add import smart_add, add_reporter_print, add_reporter_null
228
222
reporter = add_reporter_null
230
224
reporter = add_reporter_print
257
249
def run(self, filename):
258
branch, relpath = Branch.open_containing(filename)
250
tree, relpath = WorkingTree.open_containing(filename)
262
254
class cmd_inventory(Command):
263
"""Show inventory of the current working copy or a revision."""
264
takes_options = ['revision', 'show-ids']
255
"""Show inventory of the current working copy or a revision.
257
It is possible to limit the output to a particular entry
258
type using the --kind option. For example; --kind file.
260
takes_options = ['revision', 'show-ids', 'kind']
267
def run(self, revision=None, show_ids=False):
268
b = Branch.open_containing('.')[0]
263
def run(self, revision=None, show_ids=False, kind=None):
264
if kind and kind not in ['file', 'directory', 'symlink']:
265
raise BzrCommandError('invalid kind specified')
266
tree = WorkingTree.open_containing(u'.')[0]
269
267
if revision is None:
270
inv = b.working_tree().read_working_inventory()
268
inv = tree.read_working_inventory()
272
270
if len(revision) > 1:
273
271
raise BzrCommandError('bzr inventory --revision takes'
274
272
' exactly one revision identifier')
275
inv = b.get_revision_inventory(revision[0].in_history(b).rev_id)
273
inv = tree.branch.get_revision_inventory(
274
revision[0].in_history(tree.branch).rev_id)
277
276
for path, entry in inv.entries():
277
if kind and kind != entry.kind:
279
280
print '%-50s %s' % (path, entry.file_id)
292
293
takes_args = ['source$', 'dest']
293
294
def run(self, source_list, dest):
294
b, source_list = branch_files(source_list)
295
tree, source_list = tree_files(source_list)
296
296
# TODO: glob expansion on windows?
297
tree = WorkingTree(b.base, b)
298
b.move(source_list, tree.relpath(dest))
297
tree.move(source_list, tree.relpath(dest))
301
300
class cmd_rename(Command):
315
314
takes_args = ['from_name', 'to_name']
317
316
def run(self, from_name, to_name):
318
b, (from_name, to_name) = branch_files((from_name, to_name))
319
b.rename_one(from_name, to_name)
317
tree, (from_name, to_name) = tree_files((from_name, to_name))
318
tree.rename_one(from_name, to_name)
322
321
class cmd_mv(Command):
336
335
def run(self, names_list):
337
336
if len(names_list) < 2:
338
337
raise BzrCommandError("missing file argument")
339
b, rel_names = branch_files(names_list)
338
tree, rel_names = tree_files(names_list)
341
340
if os.path.isdir(names_list[-1]):
342
341
# move into existing directory
343
for pair in b.move(rel_names[:-1], rel_names[-1]):
342
for pair in tree.move(rel_names[:-1], rel_names[-1]):
344
343
print "%s => %s" % pair
346
345
if len(names_list) != 2:
347
346
raise BzrCommandError('to mv multiple files the destination '
348
347
'must be a versioned directory')
349
b.rename_one(rel_names[0], rel_names[1])
348
tree.rename_one(rel_names[0], rel_names[1])
350
349
print "%s => %s" % (rel_names[0], rel_names[1])
375
374
from bzrlib.merge import merge
376
375
from shutil import rmtree
379
br_to = Branch.open_containing('.')[0]
380
stored_loc = br_to.get_parent()
377
# FIXME: too much stuff is in the command class
378
tree_to = WorkingTree.open_containing(u'.')[0]
379
stored_loc = tree_to.branch.get_parent()
381
380
if location is None:
382
381
if stored_loc is None:
383
382
raise BzrCommandError("No pull location known or specified.")
385
384
print "Using saved location: %s" % stored_loc
386
385
location = stored_loc
387
386
br_from = Branch.open(location)
387
br_to = tree_to.branch
389
389
old_rh = br_to.revision_history()
390
count = br_to.working_tree().pull(br_from, overwrite)
390
count = tree_to.pull(br_from, overwrite)
391
391
except DivergedBranches:
392
# FIXME: Just make DivergedBranches display the right message
392
394
raise BzrCommandError("These branches have diverged."
394
396
if br_to.get_parent() is None or remember:
395
397
br_to.set_parent(location)
397
note('%d revision(s) pushed.' % (count,))
399
note('No revisions pushed.')
398
note('%d revision(s) pulled.', count)
402
new_rh = br_to.revision_history()
401
new_rh = tree_to.branch.revision_history()
403
402
if old_rh != new_rh:
404
403
# Something changed
405
404
from bzrlib.log import show_changed_revisions
406
show_changed_revisions(br_to, old_rh, new_rh)
405
show_changed_revisions(tree_to.branch, old_rh, new_rh)
409
408
class cmd_push(Command):
438
437
def run(self, location=None, remember=False, overwrite=False,
439
438
create_prefix=False, verbose=False):
439
# FIXME: Way too big! Put this into a function called from the
441
442
from shutil import rmtree
442
443
from bzrlib.transport import get_transport
444
br_from = Branch.open_containing('.')[0]
445
stored_loc = br_from.get_push_location()
445
tree_from = WorkingTree.open_containing(u'.')[0]
446
br_from = tree_from.branch
447
stored_loc = tree_from.branch.get_push_location()
446
448
if location is None:
447
449
if stored_loc is None:
448
450
raise BzrCommandError("No push location known or specified.")
486
486
" Try a merge then push with overwrite.")
487
487
if br_from.get_push_location() is None or remember:
488
488
br_from.set_push_location(location)
490
note('%d revision(s) pushed.' % (count,))
492
note('No revisions pushed.')
489
note('%d revision(s) pushed.' % (count,))
495
492
new_rh = br_to.revision_history()
586
584
takes_args = ['dir?']
589
def run(self, dir='.'):
590
b = Branch.open_containing(dir)[0]
591
old_inv = b.basis_tree().inventory
592
new_inv = b.working_tree().read_working_inventory()
587
def run(self, dir=u'.'):
588
tree = WorkingTree.open_containing(dir)[0]
589
old_inv = tree.branch.basis_tree().inventory
590
new_inv = tree.read_working_inventory()
594
592
renames = list(bzrlib.tree.find_renames(old_inv, new_inv))
678
b = Branch.open_containing('.')[0]
676
tree = WorkingTree.open_containing(u'.')[0]
678
# FIXME. should be tree.last_revision
679
679
for revision_id in b.get_ancestry(b.last_revision()):
680
680
print revision_id
683
class cmd_directories(Command):
684
"""Display list of versioned directories in this branch."""
687
for name, ie in (Branch.open_containing('.')[0].working_tree().
688
read_working_inventory().directories()):
695
683
class cmd_init(Command):
696
684
"""Make a directory into a versioned branch.
763
752
b, file1 = Branch.open_containing(file_list[0])
764
753
b2, file2 = Branch.open_containing(file_list[1])
765
754
if file1 != "" or file2 != "":
755
# FIXME diff those two files. rbc 20051123
766
756
raise BzrCommandError("Files are in different branches")
768
758
if revision is not None:
769
759
if b2 is not None:
770
760
raise BzrCommandError("Can't specify -r with two branches")
771
761
if len(revision) == 1:
772
return show_diff(b, revision[0], specific_files=file_list,
762
return show_diff(tree.branch, revision[0], specific_files=file_list,
773
763
external_diff_options=diff_options)
774
764
elif len(revision) == 2:
775
return show_diff(b, revision[0], specific_files=file_list,
765
return show_diff(tree.branch, revision[0], specific_files=file_list,
776
766
external_diff_options=diff_options,
777
767
revision2=revision[1])
779
769
raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
781
return show_diff(b, None, specific_files=file_list,
782
external_diff_options=diff_options, b2=b2)
772
return show_diff(b, None, specific_files=file_list,
773
external_diff_options=diff_options, b2=b2)
775
return show_diff(tree.branch, None, specific_files=file_list,
776
external_diff_options=diff_options)
785
779
class cmd_deleted(Command):
793
787
# if the directories are very large...)
795
789
def run(self, show_ids=False):
796
b = Branch.open_containing('.')[0]
798
new = b.working_tree()
790
tree = WorkingTree.open_containing(u'.')[0]
791
old = tree.branch.basis_tree()
799
792
for path, ie in old.inventory.iter_entries():
800
if not new.has_id(ie.file_id):
793
if not tree.has_id(ie.file_id):
802
795
print '%-50s %s' % (path, ie.file_id)
812
805
from bzrlib.delta import compare_trees
814
b = Branch.open_containing('.')[0]
815
td = compare_trees(b.basis_tree(), b.working_tree())
807
tree = WorkingTree.open_containing(u'.')[0]
808
td = compare_trees(tree.branch.basis_tree(), tree)
817
810
for path, id, kind, text_modified, meta_modified in td.modified:
890
882
direction = (forward and 'forward') or 'reverse'
893
b, fp = Branch.open_containing(filename)
888
tree, fp = WorkingTree.open_containing(filename)
891
inv = tree.read_working_inventory()
892
except NotBranchError:
895
b, fp = Branch.open_containing(filename)
897
inv = b.get_inventory(b.last_revision())
896
inv = b.working_tree().read_working_inventory()
897
except NoWorkingTree:
898
inv = b.get_inventory(b.last_revision())
899
899
file_id = inv.path2id(fp)
901
901
file_id = None # points to branch root
903
b, relpath = Branch.open_containing('.')
903
tree, relpath = WorkingTree.open_containing(u'.')
906
907
if revision is None:
955
956
takes_args = ["filename"]
957
958
def run(self, filename):
958
b, relpath = Branch.open_containing(filename)[0]
959
inv = b.working_tree().read_working_inventory()
959
tree, relpath = WorkingTree.open_containing(filename)
961
inv = tree.read_working_inventory()
960
962
file_id = inv.path2id(relpath)
961
963
for revno, revision_id, what in bzrlib.log.find_touching_revisions(b, file_id):
962
964
print "%6d %s" % (revno, what)
991
993
selection = {'I':ignored, '?':unknown, 'V':versioned}
993
b, relpath = Branch.open_containing('.')
995
tree, relpath = WorkingTree.open_containing(u'.')
999
tree = b.working_tree()
1001
tree = b.revision_tree(revision[0].in_history(b).rev_id)
1000
if revision is not None:
1001
tree = tree.branch.revision_tree(
1002
revision[0].in_history(tree.branch).rev_id)
1002
1003
for fp, fc, kind, fid, entry in tree.list_files():
1003
1004
if fp.startswith(relpath):
1004
1005
fp = fp[len(relpath):]
1132
1130
is found exports to a directory (equivalent to --format=dir).
1134
1132
Root may be the top directory for tar, tgz and tbz2 formats. If none
1135
is given, the top directory will be the root name of the file."""
1136
# TODO: list known exporters
1133
is given, the top directory will be the root name of the file.
1135
Note: export of tree with non-ascii filenames to zip is not supported.
1137
Supported formats Autodetected by extension
1138
----------------- -------------------------
1141
tbz2 .tar.bz2, .tbz2
1137
1145
takes_args = ['dest']
1138
1146
takes_options = ['revision', 'format', 'root']
1139
1147
def run(self, dest, revision=None, format=None, root=None):
1141
b = Branch.open_containing('.')[0]
1149
from bzrlib.export import export
1150
tree = WorkingTree.open_containing(u'.')[0]
1142
1152
if revision is None:
1153
# should be tree.last_revision FIXME
1143
1154
rev_id = b.last_revision()
1145
1156
if len(revision) != 1:
1146
1157
raise BzrError('bzr export --revision takes exactly 1 argument')
1147
1158
rev_id = revision[0].in_history(b).rev_id
1148
1159
t = b.revision_tree(rev_id)
1149
arg_root, ext = os.path.splitext(os.path.basename(dest))
1150
if ext in ('.gz', '.bz2'):
1151
new_root, new_ext = os.path.splitext(arg_root)
1152
if new_ext == '.tar':
1158
if ext in (".tar",):
1160
elif ext in (".tar.gz", ".tgz"):
1162
elif ext in (".tar.bz2", ".tbz2"):
1166
t.export(dest, format, root)
1161
export(t, dest, format, root)
1162
except errors.NoSuchExportFormat, e:
1163
raise BzrCommandError('Unsupported export format: %s' % e.format)
1169
1166
class cmd_cat(Command):
1178
1175
raise BzrCommandError("bzr cat requires a revision number")
1179
1176
elif len(revision) != 1:
1180
1177
raise BzrCommandError("bzr cat --revision takes exactly one number")
1181
b, relpath = Branch.open_containing(filename)
1180
tree, relpath = WorkingTree.open_containing(filename)
1182
except NotBranchError:
1185
b, relpath = Branch.open_containing(filename)
1182
1186
b.print_file(relpath, revision[0].in_history(b).revno)
1234
1238
from bzrlib.status import show_status
1235
1239
from cStringIO import StringIO
1237
b, selected_list = branch_files(selected_list)
1241
tree, selected_list = tree_files(selected_list)
1238
1242
if message is None and not file:
1239
1243
catcher = StringIO()
1240
show_status(b, specific_files=selected_list,
1244
show_status(tree.branch, specific_files=selected_list,
1241
1245
to_file=catcher)
1242
1246
message = edit_commit_message(catcher.getvalue())
1255
1259
raise BzrCommandError("empty commit message specified")
1258
b.working_tree().commit(message, specific_files=selected_list,
1259
allow_pointless=unchanged, strict=strict)
1262
tree.commit(message, specific_files=selected_list,
1263
allow_pointless=unchanged, strict=strict)
1260
1264
except PointlessCommit:
1261
1265
# FIXME: This should really happen before the file is read in;
1262
1266
# perhaps prepare the commit; get the message; then actually commit
1277
1281
This command checks various invariants about the branch storage to
1278
1282
detect data corruption or bzr bugs.
1280
takes_args = ['dir?']
1284
takes_args = ['branch?']
1281
1285
takes_options = ['verbose']
1283
def run(self, dir='.', verbose=False):
1287
def run(self, branch=None, verbose=False):
1284
1288
from bzrlib.check import check
1285
check(Branch.open_containing(dir)[0], verbose)
1290
tree = WorkingTree.open_containing()[0]
1291
branch = tree.branch
1293
branch = Branch.open(branch)
1294
check(branch, verbose)
1288
1297
class cmd_scan_cache(Command):
1567
1576
from bzrlib.merge_core import ApplyMerge3
1568
1577
if merge_type is None:
1569
1578
merge_type = ApplyMerge3
1570
b, file_list = branch_files(file_list)
1579
tree, file_list = tree_files(file_list)
1573
pending_merges = b.working_tree().pending_merges()
1582
pending_merges = tree.pending_merges()
1574
1583
if len(pending_merges) != 1:
1575
1584
raise BzrCommandError("Sorry, remerge only works after normal"
1576
1585
+ " merges. Not cherrypicking or"
1577
1586
+ "multi-merges.")
1578
this_tree = b.working_tree()
1579
base_revision = common_ancestor(b.last_revision(),
1580
pending_merges[0], b)
1581
base_tree = b.revision_tree(base_revision)
1582
other_tree = b.revision_tree(pending_merges[0])
1587
base_revision = common_ancestor(tree.branch.last_revision(),
1588
pending_merges[0], tree.branch)
1589
base_tree = tree.branch.revision_tree(base_revision)
1590
other_tree = tree.branch.revision_tree(pending_merges[0])
1583
1591
interesting_ids = None
1584
1592
if file_list is not None:
1585
1593
interesting_ids = set()
1586
1594
for filename in file_list:
1587
file_id = this_tree.path2id(filename)
1595
file_id = tree.path2id(filename)
1588
1596
interesting_ids.add(file_id)
1589
if this_tree.kind(file_id) != "directory":
1597
if tree.kind(file_id) != "directory":
1592
for name, ie in this_tree.inventory.iter_entries(file_id):
1600
for name, ie in tree.inventory.iter_entries(file_id):
1593
1601
interesting_ids.add(ie.file_id)
1594
transform_tree(this_tree, b.basis_tree(), interesting_ids)
1602
transform_tree(tree, tree.branch.basis_tree(), interesting_ids)
1595
1603
if file_list is None:
1596
restore_files = list(this_tree.iter_conflicts())
1604
restore_files = list(tree.iter_conflicts())
1598
1606
restore_files = file_list
1599
1607
for filename in restore_files:
1601
restore(this_tree.abspath(filename))
1609
restore(tree.abspath(filename))
1602
1610
except NotConflicted:
1604
conflicts = merge_inner(b, other_tree, base_tree,
1612
conflicts = merge_inner(tree.branch, other_tree, base_tree,
1605
1613
interesting_ids = interesting_ids,
1606
1614
other_rev_id=pending_merges[0],
1607
1615
merge_type=merge_type,
1608
1616
show_base=show_base,
1609
1617
reprocess=reprocess)
1612
1620
if conflicts > 0:
1636
1644
if revision is None:
1638
b = Branch.open_containing('.')[0]
1639
rev_id = b.last_revision()
1646
tree = WorkingTree.open_containing(u'.')[0]
1647
# FIXME should be tree.last_revision
1648
rev_id = tree.branch.last_revision()
1640
1649
elif len(revision) != 1:
1641
1650
raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
1643
b, file_list = branch_files(file_list)
1644
rev_id = revision[0].in_history(b).rev_id
1645
b.working_tree().revert(file_list, b.revision_tree(rev_id),
1652
tree, file_list = tree_files(file_list)
1653
rev_id = revision[0].in_history(tree.branch).rev_id
1654
tree.revert(file_list, tree.branch.revision_tree(rev_id),
1714
1723
takes_args = ['remote?']
1715
1724
aliases = ['mis', 'miss']
1716
# We don't have to add quiet to the list, because
1717
# unknown options are parsed as booleans
1718
takes_options = ['verbose', 'quiet']
1725
takes_options = ['verbose']
1720
1727
@display_command
1721
def run(self, remote=None, verbose=False, quiet=False):
1728
def run(self, remote=None, verbose=False):
1722
1729
from bzrlib.errors import BzrCommandError
1723
1730
from bzrlib.missing import show_missing
1725
if verbose and quiet:
1732
if verbose and is_quiet():
1726
1733
raise BzrCommandError('Cannot pass both quiet and verbose')
1728
b = Branch.open_containing('.')[0]
1729
parent = b.get_parent()
1735
tree = WorkingTree.open_containing(u'.')[0]
1736
parent = tree.branch.get_parent()
1730
1737
if remote is None:
1731
1738
if parent is None:
1732
1739
raise BzrCommandError("No missing location known or specified.")
1735
1742
print "Using last location: %s" % parent
1736
1743
remote = parent
1737
1744
elif parent is None:
1738
1745
# We only update parent if it did not exist, missing
1739
1746
# should not change the parent
1740
b.set_parent(remote)
1747
tree.branch.set_parent(remote)
1741
1748
br_remote = Branch.open_containing(remote)[0]
1742
return show_missing(b, br_remote, verbose=verbose, quiet=quiet)
1749
return show_missing(tree.branch, br_remote, verbose=verbose,
1745
1753
class cmd_plugins(Command):
1767
1775
takes_options = ['revision', 'long']
1768
1776
takes_args = ['branch?']
1769
1777
@display_command
1770
def run(self, branch='.', revision=None, long=False):
1778
def run(self, branch=u'.', revision=None, long=False):
1771
1779
from bzrlib.testament import Testament
1772
b = Branch.open_containing(branch)[0]
1780
b = WorkingTree.open_containing(branch)[0].branch
1775
1783
if revision is None:
1807
1815
@display_command
1808
1816
def run(self, filename, all=False, long=False):
1809
1817
from bzrlib.annotate import annotate_file
1810
b, relpath = Branch.open_containing(filename)
1818
tree, relpath = WorkingTree.open_containing(filename)
1819
branch = tree.branch
1813
tree = WorkingTree(b.base, b)
1814
tree = b.revision_tree(b.last_revision())
1815
1822
file_id = tree.inventory.path2id(relpath)
1823
tree = branch.revision_tree(branch.last_revision())
1816
1824
file_version = tree.inventory[file_id].revision
1817
annotate_file(b, file_version, file_id, long, all, sys.stdout)
1825
annotate_file(branch, file_version, file_id, long, all, sys.stdout)
1822
1830
class cmd_re_sign(Command):
1834
1842
raise BzrCommandError('You can only supply one of revision_id or --revision')
1835
1843
if revision_id is None and revision is None:
1836
1844
raise BzrCommandError('You must supply either --revision or a revision_id')
1837
b = Branch.open_containing('.')[0]
1845
b = WorkingTree.open_containing(u'.')[0].branch
1838
1846
gpg_strategy = gpg.GPGStrategy(config.BranchConfig(b))
1839
1847
if revision_id is not None:
1840
1848
b.sign_revision(revision_id, gpg_strategy)
1858
1866
raise BzrCommandError('Please supply either one revision, or a range.')
1869
class cmd_uncommit(bzrlib.commands.Command):
1870
"""Remove the last committed revision.
1872
By supplying the --all flag, it will not only remove the entry
1873
from revision_history, but also remove all of the entries in the
1876
--verbose will print out what is being removed.
1877
--dry-run will go through all the motions, but not actually
1880
In the future, uncommit will create a changeset, which can then
1883
takes_options = ['all', 'verbose', 'revision',
1884
Option('dry-run', help='Don\'t actually make changes'),
1885
Option('force', help='Say yes to all questions.')]
1886
takes_args = ['location?']
1889
def run(self, location=None, all=False,
1890
dry_run=False, verbose=False,
1891
revision=None, force=False):
1892
from bzrlib.branch import Branch
1893
from bzrlib.log import log_formatter
1895
from bzrlib.uncommit import uncommit
1897
if location is None:
1899
b, relpath = Branch.open_containing(location)
1901
if revision is None:
1903
rev_id = b.last_revision()
1905
revno, rev_id = revision[0].in_history(b)
1907
print 'No revisions to uncommit.'
1909
for r in range(revno, b.revno()+1):
1910
rev_id = b.get_rev_id(r)
1911
lf = log_formatter('short', to_file=sys.stdout,show_timezone='original')
1912
lf.show(r, b.get_revision(rev_id), None)
1915
print 'Dry-run, pretending to remove the above revisions.'
1917
val = raw_input('Press <enter> to continue')
1919
print 'The above revision(s) will be removed.'
1921
val = raw_input('Are you sure [y/N]? ')
1922
if val.lower() not in ('y', 'yes'):
1926
uncommit(b, remove_files=all,
1927
dry_run=dry_run, verbose=verbose,
1861
1931
# these get imported and then picked up by the scan for cmd_*
1862
1932
# TODO: Some more consistent way to split command definitions across files;
1863
1933
# we do need to load at least some information about them to know of