/usr/share/pyshared/bzrlib/clean_tree.py is in python-bzrlib 2.6.0~bzr6526-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | # Copyright (C) 2009, 2010 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
from __future__ import absolute_import
import errno
import os
import shutil
from bzrlib import (
controldir,
errors,
ui,
)
from bzrlib.osutils import isdir
from bzrlib.trace import note
from bzrlib.workingtree import WorkingTree
from bzrlib.i18n import gettext
def is_detritus(subp):
"""Return True if the supplied path is detritus, False otherwise"""
return subp.endswith('.THIS') or subp.endswith('.BASE') or\
subp.endswith('.OTHER') or subp.endswith('~') or subp.endswith('.tmp')
def iter_deletables(tree, unknown=False, ignored=False, detritus=False):
"""Iterate through files that may be deleted"""
for subp in tree.extras():
if detritus and is_detritus(subp):
yield tree.abspath(subp), subp
continue
if tree.is_ignored(subp):
if ignored:
yield tree.abspath(subp), subp
else:
if unknown:
yield tree.abspath(subp), subp
def clean_tree(directory, unknown=False, ignored=False, detritus=False,
dry_run=False, no_prompt=False):
"""Remove files in the specified classes from the tree"""
tree = WorkingTree.open_containing(directory)[0]
tree.lock_read()
try:
deletables = list(iter_deletables(tree, unknown=unknown,
ignored=ignored, detritus=detritus))
deletables = _filter_out_nested_bzrdirs(deletables)
if len(deletables) == 0:
note(gettext('Nothing to delete.'))
return 0
if not no_prompt:
for path, subp in deletables:
ui.ui_factory.note(subp)
prompt = gettext('Are you sure you wish to delete these')
if not ui.ui_factory.get_boolean(prompt):
ui.ui_factory.note(gettext('Canceled'))
return 0
delete_items(deletables, dry_run=dry_run)
finally:
tree.unlock()
def _filter_out_nested_bzrdirs(deletables):
result = []
for path, subp in deletables:
# bzr won't recurse into unknowns/ignored directories by default
# so we don't pay a penalty for checking subdirs of path for nested
# bzrdir.
# That said we won't detect the branch in the subdir of non-branch
# directory and therefore delete it. (worth to FIXME?)
if isdir(path):
try:
controldir.ControlDir.open(path)
except errors.NotBranchError:
result.append((path,subp))
else:
# TODO may be we need to notify user about skipped directories?
pass
else:
result.append((path,subp))
return result
def delete_items(deletables, dry_run=False):
"""Delete files in the deletables iterable"""
def onerror(function, path, excinfo):
"""Show warning for errors seen by rmtree.
"""
# Handle only permission error while removing files.
# Other errors are re-raised.
if function is not os.remove or excinfo[1].errno != errno.EACCES:
raise
ui.ui_factory.show_warning(gettext('unable to remove %s') % path)
has_deleted = False
for path, subp in deletables:
if not has_deleted:
note(gettext("deleting paths:"))
has_deleted = True
if not dry_run:
if isdir(path):
shutil.rmtree(path, onerror=onerror)
else:
try:
os.unlink(path)
note(' ' + subp)
except OSError, e:
# We handle only permission error here
if e.errno != errno.EACCES:
raise e
ui.ui_factory.show_warning(gettext(
'unable to remove "{0}": {1}.').format(
path, e.strerror))
else:
note(' ' + subp)
if not has_deleted:
note(gettext("No files deleted."))
|