1
# Copyright (C) 2005 Canonical Ltd
1
# Copyright (C) 2009, 2010 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
from __future__ import absolute_import
21
from bzrlib import bzrdir, errors
22
from bzrlib.osutils import isdir
23
from bzrlib.trace import note
24
from bzrlib.workingtree import WorkingTree
28
from .osutils import isdir
29
from .trace import note
30
from .workingtree import WorkingTree
31
from .i18n import gettext
27
33
def is_detritus(subp):
28
34
"""Return True if the supplied path is detritus, False otherwise"""
53
59
deletables = list(iter_deletables(tree, unknown=unknown,
54
60
ignored=ignored, detritus=detritus))
55
deletables = _filter_out_nested_bzrdirs(deletables)
61
deletables = _filter_out_nested_controldirs(deletables)
56
62
if len(deletables) == 0:
57
note('Nothing to delete.')
63
note(gettext('Nothing to delete.'))
60
66
for path, subp in deletables:
61
# FIXME using print is very bad idea
62
# clean_tree should accept to_file argument to write the output
64
val = raw_input('Are you sure you wish to delete these [y/N]?')
65
if val.lower() not in ('y', 'yes'):
67
ui.ui_factory.note(subp)
68
prompt = gettext('Are you sure you wish to delete these')
69
if not ui.ui_factory.get_boolean(prompt):
70
ui.ui_factory.note(gettext('Canceled'))
68
72
delete_items(deletables, dry_run=dry_run)
73
def _filter_out_nested_bzrdirs(deletables):
77
def _filter_out_nested_controldirs(deletables):
75
79
for path, subp in deletables:
76
80
# bzr won't recurse into unknowns/ignored directories by default
77
81
# so we don't pay a penalty for checking subdirs of path for nested
79
83
# That said we won't detect the branch in the subdir of non-branch
80
84
# directory and therefore delete it. (worth to FIXME?)
83
bzrdir.BzrDir.open(path)
87
controldir.ControlDir.open(path)
84
88
except errors.NotBranchError:
85
89
result.append((path,subp))
94
98
def delete_items(deletables, dry_run=False):
95
99
"""Delete files in the deletables iterable"""
100
def onerror(function, path, excinfo):
101
"""Show warning for errors seen by rmtree.
103
# Handle only permission error while removing files.
104
# Other errors are re-raised.
105
if function is not os.remove or excinfo[1].errno != errno.EACCES:
107
ui.ui_factory.show_warning(gettext('unable to remove %s') % path)
96
108
has_deleted = False
97
109
for path, subp in deletables:
98
110
if not has_deleted:
99
note("deleting paths:")
111
note(gettext("deleting paths:"))
100
112
has_deleted = True
115
shutil.rmtree(path, onerror=onerror)
121
# We handle only permission error here
122
if e.errno != errno.EACCES:
124
ui.ui_factory.show_warning(gettext(
125
'unable to remove "{0}": {1}.').format(
107
129
if not has_deleted:
108
note("No files deleted.")
130
note(gettext("No files deleted."))