30
30
import bzrlib.errors as errors
31
31
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError,
32
32
NotBranchError, DivergedBranches, NotConflicted,
33
NoSuchFile, NoWorkingTree)
33
NoSuchFile, NoWorkingTree, FileInWrongBranch)
34
34
from bzrlib.option import Option
35
35
from bzrlib.revisionspec import RevisionSpec
36
36
import bzrlib.trace
37
from bzrlib.trace import mutter, note, log_error, warning
37
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
38
38
from bzrlib.workingtree import WorkingTree
41
def branch_files(file_list, default_branch='.'):
41
def tree_files(file_list, default_branch='.'):
43
return inner_branch_files(file_list, default_branch)
44
except NotBranchError:
43
return internal_tree_files(file_list, default_branch)
44
except FileInWrongBranch, e:
45
45
raise BzrCommandError("%s is not in the same branch as %s" %
46
(filename, file_list[0]))
46
(e.path, file_list[0]))
48
def inner_branch_files(file_list, default_branch='.'):
48
def internal_tree_files(file_list, default_branch='.'):
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:
65
new_list.append(tree.relpath(filename))
60
new_list.append(tree.relpath(filename))
61
except NotBranchError:
62
raise FileInWrongBranch(tree.branch, filename)
69
66
# TODO: Make sure no commands unconditionally use the working directory as a
122
119
def run(self, all=False, show_ids=False, file_list=None, revision=None):
123
b, file_list = branch_files(file_list)
120
tree, file_list = tree_files(file_list)
125
122
from bzrlib.status import show_status
126
show_status(b, show_unchanged=all, show_ids=show_ids,
123
show_status(tree.branch, show_unchanged=all, show_ids=show_ids,
127
124
specific_files=file_list, revision=revision)
145
142
raise BzrCommandError('You can only supply one of revision_id or --revision')
146
143
if revision_id is None and revision is None:
147
144
raise BzrCommandError('You must supply either --revision or a revision_id')
148
b = Branch.open_containing('.')[0]
145
b = WorkingTree.open_containing('.')[0].branch
149
146
if revision_id is not None:
150
sys.stdout.write(b.get_revision_xml_file(revision_id).read())
147
sys.stdout.write(b.get_revision_xml(revision_id))
151
148
elif revision is not None:
152
149
for rev in revision:
154
151
raise BzrCommandError('You cannot specify a NULL revision.')
155
152
revno, rev_id = rev.in_history(b)
156
sys.stdout.write(b.get_revision_xml_file(rev_id).read())
153
sys.stdout.write(b.get_revision_xml(rev_id))
159
156
class cmd_revno(Command):
217
214
get added when you add a file in the directory.
219
216
takes_args = ['file*']
220
takes_options = ['no-recurse', 'quiet']
217
takes_options = ['no-recurse']
222
def run(self, file_list, no_recurse=False, quiet=False):
219
def run(self, file_list, no_recurse=False):
223
220
from bzrlib.add import smart_add, add_reporter_print, add_reporter_null
225
222
reporter = add_reporter_null
227
224
reporter = add_reporter_print
254
249
def run(self, filename):
255
branch, relpath = Branch.open_containing(filename)
250
tree, relpath = WorkingTree.open_containing(filename)
259
254
class cmd_inventory(Command):
260
"""Show inventory of the current working copy or a revision."""
261
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']
264
def run(self, revision=None, show_ids=False):
265
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('.')[0]
266
267
if revision is None:
267
inv = b.working_tree().read_working_inventory()
268
inv = tree.read_working_inventory()
269
270
if len(revision) > 1:
270
271
raise BzrCommandError('bzr inventory --revision takes'
271
272
' exactly one revision identifier')
272
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)
274
276
for path, entry in inv.entries():
277
if kind and kind != entry.kind:
276
280
print '%-50s %s' % (path, entry.file_id)
289
293
takes_args = ['source$', 'dest']
290
294
def run(self, source_list, dest):
291
b, source_list = branch_files(source_list)
295
tree, source_list = tree_files(source_list)
293
296
# TODO: glob expansion on windows?
294
tree = WorkingTree(b.base, b)
295
b.move(source_list, tree.relpath(dest))
297
tree.move(source_list, tree.relpath(dest))
298
300
class cmd_rename(Command):
312
314
takes_args = ['from_name', 'to_name']
314
316
def run(self, from_name, to_name):
315
b, (from_name, to_name) = branch_files((from_name, to_name))
316
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)
319
321
class cmd_mv(Command):
333
335
def run(self, names_list):
334
336
if len(names_list) < 2:
335
337
raise BzrCommandError("missing file argument")
336
b, rel_names = branch_files(names_list)
338
tree, rel_names = tree_files(names_list)
338
340
if os.path.isdir(names_list[-1]):
339
341
# move into existing directory
340
for pair in b.move(rel_names[:-1], rel_names[-1]):
342
for pair in tree.move(rel_names[:-1], rel_names[-1]):
341
343
print "%s => %s" % pair
343
345
if len(names_list) != 2:
344
346
raise BzrCommandError('to mv multiple files the destination '
345
347
'must be a versioned directory')
346
b.rename_one(rel_names[0], rel_names[1])
348
tree.rename_one(rel_names[0], rel_names[1])
347
349
print "%s => %s" % (rel_names[0], rel_names[1])
372
374
from bzrlib.merge import merge
373
375
from shutil import rmtree
376
br_to = Branch.open_containing('.')[0]
377
bound_loc = br_to.get_bound_location()
379
br = Branch.open(bound_loc)
380
stored_loc = br.get_parent()
383
stored_loc = br_to.get_parent()
377
# FIXME: too much stuff is in the command class
378
tree_to = WorkingTree.open_containing('.')[0]
379
stored_loc = tree_to.branch.get_parent()
384
380
if location is None:
385
381
if stored_loc is None:
386
382
raise BzrCommandError("No pull location known or specified.")
388
384
print "Using saved location: %s" % stored_loc
389
385
location = stored_loc
390
386
br_from = Branch.open(location)
387
br_to = tree_to.branch
392
389
old_rh = br_to.revision_history()
393
br_to.working_tree().pull(br_from, overwrite)
390
count = tree_to.pull(br_from, overwrite)
394
391
except DivergedBranches:
392
# FIXME: Just make DivergedBranches display the right message
395
394
raise BzrCommandError("These branches have diverged."
397
396
if br_to.get_parent() is None or remember:
398
397
br_to.set_parent(location)
398
note('%d revision(s) pulled.', count)
401
new_rh = br_to.revision_history()
400
new_rh = tree_to.branch.revision_history()
402
401
if old_rh != new_rh:
403
402
# Something changed
404
403
from bzrlib.log import show_changed_revisions
405
show_changed_revisions(br_to, old_rh, new_rh)
404
show_changed_revisions(tree_to.branch, old_rh, new_rh)
408
407
class cmd_push(Command):
437
436
def run(self, location=None, remember=False, overwrite=False,
438
437
create_prefix=False, verbose=False):
438
# FIXME: Way too big! Put this into a function called from the
440
441
from shutil import rmtree
441
442
from bzrlib.transport import get_transport
443
br_from = Branch.open_containing('.')[0]
444
stored_loc = br_from.get_push_location()
444
tree_from = WorkingTree.open_containing('.')[0]
445
br_from = tree_from.branch
446
stored_loc = tree_from.branch.get_push_location()
445
447
if location is None:
446
448
if stored_loc is None:
447
449
raise BzrCommandError("No push location known or specified.")
474
476
if new_transport.base == transport.base:
475
477
raise BzrCommandError("Could not creeate "
479
479
br_to = Branch.initialize(location)
481
481
old_rh = br_to.revision_history()
482
br_to.pull(br_from, overwrite)
482
count = br_to.pull(br_from, overwrite)
483
483
except DivergedBranches:
484
484
raise BzrCommandError("These branches have diverged."
485
485
" Try a merge then push with overwrite.")
486
486
if br_from.get_push_location() is None or remember:
487
487
br_from.set_push_location(location)
488
note('%d revision(s) pushed.' % (count,))
490
490
new_rh = br_to.revision_history()
491
491
if old_rh != new_rh:
588
590
def run(self, dir='.'):
589
b = Branch.open_containing(dir)[0]
590
old_inv = b.basis_tree().inventory
591
new_inv = b.working_tree().read_working_inventory()
591
tree = WorkingTree.open_containing(dir)[0]
592
old_inv = tree.branch.basis_tree().inventory
593
new_inv = tree.read_working_inventory()
593
595
renames = list(bzrlib.tree.find_renames(old_inv, new_inv))
634
635
takes_args = ['filename']
636
637
def run(self, filename):
637
b, relpath = Branch.open_containing(filename)
638
i = b.working_tree().inventory.path2id(relpath)
638
tree, relpath = WorkingTree.open_containing(filename)
639
i = tree.inventory.path2id(relpath)
640
641
raise BzrError("%r is not a versioned file" % filename)
677
b = Branch.open_containing('.')[0]
679
tree = WorkingTree.open_containing('.')[0]
681
# FIXME. should be tree.last_revision
678
682
for revision_id in b.get_ancestry(b.last_revision()):
679
683
print revision_id
682
class cmd_directories(Command):
683
"""Display list of versioned directories in this branch."""
686
for name, ie in (Branch.open_containing('.')[0].working_tree().
687
read_working_inventory().directories()):
694
686
class cmd_init(Command):
695
687
"""Make a directory into a versioned branch.
753
745
def run(self, revision=None, file_list=None, diff_options=None):
754
746
from bzrlib.diff import show_diff
756
b, file_list = inner_branch_files(file_list)
748
tree, file_list = internal_tree_files(file_list)
758
except NotBranchError:
751
except FileInWrongBranch:
759
752
if len(file_list) != 2:
760
753
raise BzrCommandError("Files are in different branches")
762
755
b, file1 = Branch.open_containing(file_list[0])
763
756
b2, file2 = Branch.open_containing(file_list[1])
764
757
if file1 != "" or file2 != "":
758
# FIXME diff those two files. rbc 20051123
765
759
raise BzrCommandError("Files are in different branches")
767
761
if revision is not None:
768
762
if b2 is not None:
769
763
raise BzrCommandError("Can't specify -r with two branches")
770
764
if len(revision) == 1:
771
return show_diff(b, revision[0], specific_files=file_list,
765
return show_diff(tree.branch, revision[0], specific_files=file_list,
772
766
external_diff_options=diff_options)
773
767
elif len(revision) == 2:
774
return show_diff(b, revision[0], specific_files=file_list,
768
return show_diff(tree.branch, revision[0], specific_files=file_list,
775
769
external_diff_options=diff_options,
776
770
revision2=revision[1])
778
772
raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
780
return show_diff(b, None, specific_files=file_list,
781
external_diff_options=diff_options, b2=b2)
775
return show_diff(b, None, specific_files=file_list,
776
external_diff_options=diff_options, b2=b2)
778
return show_diff(tree.branch, None, specific_files=file_list,
779
external_diff_options=diff_options)
784
782
class cmd_deleted(Command):
792
790
# if the directories are very large...)
794
792
def run(self, show_ids=False):
795
b = Branch.open_containing('.')[0]
797
new = b.working_tree()
793
tree = WorkingTree.open_containing('.')[0]
794
old = tree.branch.basis_tree()
798
795
for path, ie in old.inventory.iter_entries():
799
if not new.has_id(ie.file_id):
796
if not tree.has_id(ie.file_id):
801
798
print '%-50s %s' % (path, ie.file_id)
811
808
from bzrlib.delta import compare_trees
813
b = Branch.open_containing('.')[0]
814
td = compare_trees(b.basis_tree(), b.working_tree())
810
tree = WorkingTree.open_containing('.')[0]
811
td = compare_trees(tree.branch.basis_tree(), tree)
816
813
for path, id, kind, text_modified, meta_modified in td.modified:
889
885
direction = (forward and 'forward') or 'reverse'
892
b, fp = Branch.open_containing(filename)
891
tree, fp = WorkingTree.open_containing(filename)
894
inv = tree.read_working_inventory()
895
except NotBranchError:
898
b, fp = Branch.open_containing(filename)
900
inv = b.get_inventory(b.last_revision())
895
inv = b.working_tree().read_working_inventory()
896
except NoWorkingTree:
897
inv = b.get_inventory(b.last_revision())
898
902
file_id = inv.path2id(fp)
900
904
file_id = None # points to branch root
902
b, relpath = Branch.open_containing('.')
906
tree, relpath = WorkingTree.open_containing('.')
905
910
if revision is None:
914
919
raise BzrCommandError('bzr log --revision takes one or two values.')
921
# By this point, the revision numbers are converted to the +ve
922
# form if they were supplied in the -ve form, so we can do
923
# this comparison in relative safety
925
(rev2, rev1) = (rev1, rev2)
921
927
mutter('encoding log as %r', bzrlib.user_encoding)
953
959
takes_args = ["filename"]
955
961
def run(self, filename):
956
b, relpath = Branch.open_containing(filename)[0]
957
inv = b.working_tree().read_working_inventory()
962
tree, relpath = WorkingTree.open_containing(filename)
964
inv = tree.read_working_inventory()
958
965
file_id = inv.path2id(relpath)
959
966
for revno, revision_id, what in bzrlib.log.find_touching_revisions(b, file_id):
960
967
print "%6d %s" % (revno, what)
989
996
selection = {'I':ignored, '?':unknown, 'V':versioned}
991
b, relpath = Branch.open_containing('.')
998
tree, relpath = WorkingTree.open_containing('.')
997
tree = b.working_tree()
999
tree = b.revision_tree(revision[0].in_history(b).rev_id)
1003
if revision is not None:
1004
tree = tree.branch.revision_tree(
1005
revision[0].in_history(tree.branch).rev_id)
1000
1006
for fp, fc, kind, fid, entry in tree.list_files():
1001
1007
if fp.startswith(relpath):
1002
1008
fp = fp[len(relpath):]
1147
1150
def run(self, dest, revision=None, format=None, root=None):
1149
1152
from bzrlib.export import export
1150
b = Branch.open_containing('.')[0]
1153
tree = WorkingTree.open_containing('.')[0]
1151
1155
if revision is None:
1156
# should be tree.last_revision FIXME
1152
1157
rev_id = b.last_revision()
1154
1159
if len(revision) != 1:
1173
1178
raise BzrCommandError("bzr cat requires a revision number")
1174
1179
elif len(revision) != 1:
1175
1180
raise BzrCommandError("bzr cat --revision takes exactly one number")
1176
b, relpath = Branch.open_containing(filename)
1183
tree, relpath = WorkingTree.open_containing(filename)
1185
except NotBranchError:
1188
b, relpath = Branch.open_containing(filename)
1177
1189
b.print_file(relpath, revision[0].in_history(b).revno)
1229
1241
from bzrlib.status import show_status
1230
1242
from cStringIO import StringIO
1232
b, selected_list = branch_files(selected_list)
1244
tree, selected_list = tree_files(selected_list)
1233
1245
if message is None and not file:
1234
1246
catcher = StringIO()
1235
show_status(b, specific_files=selected_list,
1247
show_status(tree.branch, specific_files=selected_list,
1236
1248
to_file=catcher)
1237
1249
message = edit_commit_message(catcher.getvalue())
1250
1262
raise BzrCommandError("empty commit message specified")
1253
b.working_tree().commit(message, specific_files=selected_list,
1254
allow_pointless=unchanged, strict=strict)
1265
tree.commit(message, specific_files=selected_list,
1266
allow_pointless=unchanged, strict=strict)
1255
1267
except PointlessCommit:
1256
1268
# FIXME: This should really happen before the file is read in;
1257
1269
# perhaps prepare the commit; get the message; then actually commit
1563
1577
from bzrlib.merge_core import ApplyMerge3
1564
1578
if merge_type is None:
1565
1579
merge_type = ApplyMerge3
1566
b, file_list = branch_files(file_list)
1580
tree, file_list = tree_files(file_list)
1569
pending_merges = b.working_tree().pending_merges()
1583
pending_merges = tree.pending_merges()
1570
1584
if len(pending_merges) != 1:
1571
1585
raise BzrCommandError("Sorry, remerge only works after normal"
1572
1586
+ " merges. Not cherrypicking or"
1573
1587
+ "multi-merges.")
1574
this_tree = b.working_tree()
1575
base_revision = common_ancestor(b.last_revision(),
1576
pending_merges[0], b)
1577
base_tree = b.revision_tree(base_revision)
1578
other_tree = b.revision_tree(pending_merges[0])
1588
base_revision = common_ancestor(tree.branch.last_revision(),
1589
pending_merges[0], tree.branch)
1590
base_tree = tree.branch.revision_tree(base_revision)
1591
other_tree = tree.branch.revision_tree(pending_merges[0])
1579
1592
interesting_ids = None
1580
1593
if file_list is not None:
1581
1594
interesting_ids = set()
1582
1595
for filename in file_list:
1583
file_id = this_tree.path2id(filename)
1596
file_id = tree.path2id(filename)
1584
1597
interesting_ids.add(file_id)
1585
if this_tree.kind(file_id) != "directory":
1598
if tree.kind(file_id) != "directory":
1588
for name, ie in this_tree.inventory.iter_entries(file_id):
1601
for name, ie in tree.inventory.iter_entries(file_id):
1589
1602
interesting_ids.add(ie.file_id)
1590
transform_tree(this_tree, b.basis_tree(), interesting_ids)
1603
transform_tree(tree, tree.branch.basis_tree(), interesting_ids)
1591
1604
if file_list is None:
1592
restore_files = list(this_tree.iter_conflicts())
1605
restore_files = list(tree.iter_conflicts())
1594
1607
restore_files = file_list
1595
1608
for filename in restore_files:
1597
restore(this_tree.abspath(filename))
1610
restore(tree.abspath(filename))
1598
1611
except NotConflicted:
1600
conflicts = merge_inner(b, other_tree, base_tree,
1613
conflicts = merge_inner(tree.branch, other_tree, base_tree,
1601
1614
interesting_ids = interesting_ids,
1602
1615
other_rev_id=pending_merges[0],
1603
1616
merge_type=merge_type,
1604
1617
show_base=show_base,
1605
1618
reprocess=reprocess)
1608
1621
if conflicts > 0:
1632
1645
if revision is None:
1634
b = Branch.open_containing('.')[0]
1635
rev_id = b.last_revision()
1647
tree = WorkingTree.open_containing('.')[0]
1648
# FIXME should be tree.last_revision
1649
rev_id = tree.branch.last_revision()
1636
1650
elif len(revision) != 1:
1637
1651
raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
1639
b, file_list = branch_files(file_list)
1640
rev_id = revision[0].in_history(b).rev_id
1641
b.working_tree().revert(file_list, b.revision_tree(rev_id),
1653
tree, file_list = tree_files(file_list)
1654
rev_id = revision[0].in_history(tree.branch).rev_id
1655
tree.revert(file_list, tree.branch.revision_tree(rev_id),
1710
1724
takes_args = ['remote?']
1711
1725
aliases = ['mis', 'miss']
1712
# We don't have to add quiet to the list, because
1713
# unknown options are parsed as booleans
1714
takes_options = ['verbose', 'quiet']
1726
takes_options = ['verbose']
1716
1728
@display_command
1717
def run(self, remote=None, verbose=False, quiet=False):
1729
def run(self, remote=None, verbose=False):
1718
1730
from bzrlib.errors import BzrCommandError
1719
1731
from bzrlib.missing import show_missing
1721
if verbose and quiet:
1733
if verbose and is_quiet():
1722
1734
raise BzrCommandError('Cannot pass both quiet and verbose')
1724
b = Branch.open_containing('.')[0]
1725
parent = b.get_parent()
1736
tree = WorkingTree.open_containing('.')[0]
1737
parent = tree.branch.get_parent()
1726
1738
if remote is None:
1727
1739
if parent is None:
1728
1740
raise BzrCommandError("No missing location known or specified.")
1731
1743
print "Using last location: %s" % parent
1732
1744
remote = parent
1733
1745
elif parent is None:
1734
1746
# We only update parent if it did not exist, missing
1735
1747
# should not change the parent
1736
b.set_parent(remote)
1748
tree.branch.set_parent(remote)
1737
1749
br_remote = Branch.open_containing(remote)[0]
1738
return show_missing(b, br_remote, verbose=verbose, quiet=quiet)
1750
return show_missing(tree.branch, br_remote, verbose=verbose,
1741
1754
class cmd_plugins(Command):
1803
1816
@display_command
1804
1817
def run(self, filename, all=False, long=False):
1805
1818
from bzrlib.annotate import annotate_file
1806
b, relpath = Branch.open_containing(filename)
1819
tree, relpath = WorkingTree.open_containing(filename)
1820
branch = tree.branch
1809
tree = WorkingTree(b.base, b)
1810
tree = b.revision_tree(b.last_revision())
1811
1823
file_id = tree.inventory.path2id(relpath)
1824
tree = branch.revision_tree(branch.last_revision())
1812
1825
file_version = tree.inventory[file_id].revision
1813
annotate_file(b, file_version, file_id, long, all, sys.stdout)
1826
annotate_file(branch, file_version, file_id, long, all, sys.stdout)
1818
1831
class cmd_re_sign(Command):
1830
1843
raise BzrCommandError('You can only supply one of revision_id or --revision')
1831
1844
if revision_id is None and revision is None:
1832
1845
raise BzrCommandError('You must supply either --revision or a revision_id')
1833
b = Branch.open_containing('.')[0]
1846
b = WorkingTree.open_containing('.')[0].branch
1834
1847
gpg_strategy = gpg.GPGStrategy(config.BranchConfig(b))
1835
1848
if revision_id is not None:
1836
1849
b.sign_revision(revision_id, gpg_strategy)
1927
class cmd_uncommit(bzrlib.commands.Command):
1928
"""Remove the last committed revision.
1930
By supplying the --all flag, it will not only remove the entry
1931
from revision_history, but also remove all of the entries in the
1934
--verbose will print out what is being removed.
1935
--dry-run will go through all the motions, but not actually
1938
In the future, uncommit will create a changeset, which can then
1941
takes_options = ['all', 'verbose', 'revision',
1942
Option('dry-run', help='Don\'t actually make changes'),
1943
Option('force', help='Say yes to all questions.')]
1944
takes_args = ['location?']
1947
def run(self, location=None, all=False,
1948
dry_run=False, verbose=False,
1949
revision=None, force=False):
1950
from bzrlib.branch import Branch
1951
from bzrlib.log import log_formatter
1953
from bzrlib.uncommit import uncommit
1955
if location is None:
1957
b, relpath = Branch.open_containing(location)
1959
if revision is None:
1961
rev_id = b.last_revision()
1963
revno, rev_id = revision[0].in_history(b)
1965
print 'No revisions to uncommit.'
1967
for r in range(revno, b.revno()+1):
1968
rev_id = b.get_rev_id(r)
1969
lf = log_formatter('short', to_file=sys.stdout,show_timezone='original')
1970
lf.show(r, b.get_revision(rev_id), None)
1973
print 'Dry-run, pretending to remove the above revisions.'
1975
val = raw_input('Press <enter> to continue')
1977
print 'The above revision(s) will be removed.'
1979
val = raw_input('Are you sure [y/N]? ')
1980
if val.lower() not in ('y', 'yes'):
1984
uncommit(b, remove_files=all,
1985
dry_run=dry_run, verbose=verbose,
1914
1989
# these get imported and then picked up by the scan for cmd_*
1915
1990
# TODO: Some more consistent way to split command definitions across files;
1916
1991
# we do need to load at least some information about them to know of