Error in execution of <bleachbit.Command.Function instance at 0x7f4f5a104cf8>
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
BleachBit |
Won't Fix
|
Undecided
|
Weiller |
Bug Description
Traceback (most recent call last):
File "/usr/share/
for ret in cmd.execute(
File "/usr/share/
func_ret = self.func()
File "/usr/share/
raise RuntimeError(line)
RuntimeError: E: Não foi possível abrir arquivo de trava /var/lib/dpkg/lock - open (13: Permission Denied)
BleachBit 1.10 - Ubuntu 16.04 Xenial
When I run BleachBit, Normal User, it's this error after I click for it to do the cleaning of my Firefox browser. I read the line of the error and believe to be at the very code of the program in Python which I do not have extensive knowledge to fix. Below is a donate application error files.
Worker.py
# vim: ts=4:sw=4:expandtab
# BleachBit
# Copyright (C) 2008-2015 Andrew Ziem
# http://
#
# 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 3 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, see <http://
"""
Perform the preview or delete operations
"""
import logging
import math
import os
import sys
import traceback
import DeepScan
import FileUtilities
from Cleaner import backends
from Common import _, ungettext
class Worker:
"""Perform the preview or delete operations"""
def __init__(self, ui, really_delete, operations):
"""Create a Worker
ui: an instance with methods
operations: dictionary where operation-id is the key and
"""
self.ui = ui
self.size = 0
if 0 == len(self.
raise RuntimeError("No work to do")
def print_exception
"""Display exception"""
# TRANSLATORS: This indicates an error. The special keyword
# %(operation)s will be replaced by 'firefox' or 'opera' or
# some other cleaner ID. The special keyword %(msg)s will be
# replaced by a message such as 'Permission denied.'
err = _("Exception while running operation '%(operation)s': '%(msg)s'") \
% {'operation': operation, 'msg': str(sys.
logger = logging.
def execute(self, cmd):
"""Execute or preview the command"""
ret = None
try:
for ret in cmd.execute(
if True == ret or isinstance(ret, tuple):
except SystemExit:
pass
except Exception, e:
# 2 = does not exist
# 13 = permission denied
from errno import ENOENT, EACCES
logger = logging.
if (isinstance(e, OSError) and e.errno in (ENOENT, EACCES)):
# For access denied, do not show traceback
else:
# For other errors, show the traceback.
else:
if None == ret:
if isinstance(
else:
if ret['path']:
else:
path = path.decode('utf8', 'replace') # for invalid encoding
line = u"%s %s %s\n" % (ret['label'], size, path)
if ret['label']:
# the label may be a hidden operation
# (e.g., win.shell.
def clean_operation
"""Perform a single cleaning operation"""
logger = logging.
if not operation_options:
raise StopIteration
if self.really_delete and backends[
# TRANSLATORS: %s expands to a name such as 'Firefox' or 'System'.
err = _("%s cannot be cleaned because it is currently running. Close it, and try again.") \
% backends[
return
import time
total_size = 0
for option_id in operation_options:
# normal scan
for cmd in backends[
for ret in self.execute(cmd):
if time.time() - self.yield_time > 0.25:
# deep scan
for ds in backends[
if '' == ds['path']:
if 'delete' != ds['command']:
if not self.deepscans.
def run_delayed_
"""Run one delayed operation"""
if 'free_disk_space' == option_id:
# TRANSLATORS: 'free' means 'unallocated'
msg = _("Please wait. Wiping free disk space.")
elif 'memory' == option_id:
msg = _("Please wait. Cleaning %s.") % _("Memory")
else:
raise RuntimeError(
for cmd in backends[
for ret in self.execute(cmd):
if isinstance(ret, tuple):
if True == ret or isinstance(ret, tuple):
def run(self):
"""Perform the main cleaning process which has these phases
1. General cleaning
2. Deep scan
3. Memory
4. Free disk space"""
# prioritize
for operation in self.operations:
for delayable in delayables:
if operation not in ('system', '_gui'):
if delayable in self.operations
# standard operations
for dummy in self.run_
# yield to GTK+ idle loop
yield True
# run deep scan
if self.deepscans:
for dummy in self.run_
# delayed operations
for op in sorted(
for option_id in op[1].values()[0]:
for ret in self.run_
# print final stats
if self.really_delete:
# TRANSLATORS: This refers to disk space that was
# really recovered (in other words, not a preview)
line = _("Disk space recovered: %s") % bytes_delete
else:
# TRANSLATORS: This refers to a preview (no real
# changes were made yet)
line = _("Disk space to be recovered: %s") % bytes_delete
if self.really_delete:
# TRANSLATORS: This refers to the number of files really
# deleted (in other words, not a preview).
line = _("Files deleted: %d") % self.total_deleted
else:
# TRANSLATORS: This refers to the number of files that
# would be deleted (in other words, simply a preview).
line = _("Files to be deleted: %d") % self.total_deleted
if self.total_special > 0:
line = _("Special operations: %d") % self.total_special
if self.total_errors > 0:
line = _("Errors: %d") % self.total_errors
if self.really_delete:
yield False
def run_deep_
"""Run deep scans"""
logger = logging.
# TRANSLATORS: The "deep scan" feature searches over broad
# areas of the file system such as the user's whole home directory
# or all the system executables.
yield True # allow GTK to update the screen
ds = DeepScan.DeepScan()
for (path, dsdict) in self.deepscans.
for dsdict2 in dsdict:
for path in ds.scan():
if True == path:
# fixme: support non-delete commands
import Command
cmd = Command.
for ret in self.execute(cmd):
def run_operations(
"""Run a set of operations (general, memory, free disk space)"""
count = 0
for operation in my_operations:
name = backends[
if self.really_delete:
# TRANSLATORS: %s is replaced with Firefox, System, etc.
msg = _("Please wait. Cleaning %s.") % name
else:
# TRANSLATORS: %s is replaced with Firefox, System, etc.
msg = _("Please wait. Previewing %s.") % name
yield True # show the progress bar message now
try:
for dummy in self.clean_
except:
count += 1
Command.py
# vim: ts=4:sw=4:expandtab
# BleachBit
# Copyright (C) 2008-2015 Andrew Ziem
# http://
#
# 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 3 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, see <http://
"""
Command design pattern implementation for cleaning
"""
import os
import types
import FileUtilities
from sqlite3 import DatabaseError
from Common import _
if 'nt' == os.name:
import Windows
else:
from General import WindowsError
def whitelist(path):
"""Return information that this file was whitelisted"""
ret = {
# TRANSLATORS: This is the label in the log indicating was
# skipped because it matches the whitelist
'label': _('Skip'),
'path': path,
'size': 0}
return ret
class Delete:
"""Delete a single file or directory. Obey the user
preference regarding shredding."""
def __init__(self, path):
"""Create a Delete instance to delete 'path'"""
self.path = path
self.shred = False
def __str__(self):
return 'Command to %s %s' % \
def execute(self, really_delete):
"""Make changes and return results"""
if FileUtilities.
yield whitelist(
return
ret = {
# TRANSLATORS: This is the label in the log indicating will be
# deleted (for previews) or was actually deleted
'path': self.path,
'size': FileUtilities.
if really_delete:
try:
except WindowsError, e:
# WindowsError: [Error 32] The process cannot access the file because it is being
# used by another process: u'C:\\Documents and
# Settings\
if 32 != e.winerror and 5 != e.winerror:
yield ret
class Function:
"""Execute a simple Python function"""
def __init__(self, path, func, label):
"""Path is a pathname that exists or None. If
it exists, func takes the pathname. Otherwise,
function returns the size."""
self.path = path
self.func = func
self.label = label
try:
assert isinstance(func, types.FunctionType)
except AssertionError:
raise AssertionError(
def execute(self, really_delete):
if None != self.path and FileUtilities.
yield whitelist(
return
ret = {
'path': self.path,
'size': None}
if really_delete:
if None == self.path:
# Function takes no path. It returns the size.
if isinstance(
# either way, func_ret should be an integer
else:
# Function takes a path. We check the size.
yield ret
class Ini:
"""Remove sections or parameters from a .ini file"""
def __init__(self, path, section, parameter):
"""Create the instance"""
self.path = path
def __str__(self):
return 'Command to clean .ini path=%s, section=-%s, parameter=%s ' % \
def execute(self, really_delete):
"""Make changes and return results"""
if FileUtilities.
yield whitelist(
return
ret = {
# TRANSLATORS: Parts of this file will be deleted
'path': self.path,
'size': None}
if really_delete:
oldsize = FileUtilities.
newsize = FileUtilities.
yield ret
class Json:
"""Remove a key from a JSON configuration file"""
def __init__(self, path, address):
"""Create the instance"""
self.path = path
def __str(self):
return 'Command to clean JSON file, path=%s, address=%s ' % \
def execute(self, really_delete):
"""Make changes and return results"""
if FileUtilities.
yield whitelist(
return
ret = {
'path': self.path,
'size': None}
if really_delete:
oldsize = FileUtilities.
newsize = FileUtilities.
yield ret
class Shred(Delete):
"""Shred a single file"""
def __init__(self, path):
"""Create an instance to shred 'path'"""
self.shred = True
def __str__(self):
return 'Command to shred %s' % self.path
class Truncate(Delete):
"""Truncate a single file"""
def __str__(self):
return 'Command to truncate %s' % self.path
def execute(self, really_delete):
"""Make changes and return results"""
if FileUtilities.
yield whitelist(
return
ret = {
# TRANSLATORS: The file will be truncated to 0 bytes in length
'path': self.path,
'size': FileUtilities.
if really_delete:
f = open(self.path, 'wb')
yield ret
class Winreg:
"""Clean Windows registry"""
def __init__(self, keyname, valuename):
"""Create the Windows registry cleaner"""
def __str__(self):
return 'Command to clean registry, key=%, value=%s ' % \
def execute(self, really_delete):
"""Execute the Windows registry cleaner"""
if 'nt' != os.name:
raise StopIteration
_str = None # string representation
ret = None # return value meaning 'deleted' or 'delete-able'
if self.valuename:
_str = '%s<%s>' % (self.keyname, self.valuename)
ret = Windows.
else:
ret = Windows.
_str = self.keyname
if not ret:
# Nothing to delete or nothing was deleted. This return
# makes the auto-hide feature work nicely.
raise StopIteration
ret = {
'path': _str,
'size': 0}
yield ret
Unix.py
# vim: ts=4:sw=4:expandtab
# -*- coding: UTF-8 -*-
# BleachBit
# Copyright (C) 2008-2015 Andrew Ziem
# http://
#
# 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 3 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, see <http://
"""
Integration specific to Unix-like operating systems
"""
import glob
import os
import re
import shlex
import subprocess
import ConfigParser
from Common import _, autostart_path
import Common
import FileUtilities
import General
HAVE_GIO = True
try:
import gio
except:
HAVE_GIO = False
class Locales:
"""Find languages and localization files"""
localepattern = r"(?P<locale>
native_
{'aa': 'Afaraf',
'ab': 'аҧсуа бызшәа',
'ach': 'Acoli',
'ae': 'avesta',
'af': 'Afrikaans',
'ak': 'Akan',
'am': 'አማርኛ',
'an': 'aragonés',
'ang': 'Old English',
'ar': 'العربية',
'as': 'অসমীয়া',
'ast': 'Asturianu',
'av': 'авар мацӀ',
'ay': 'aymar aru',
'az': 'azərbaycan dili',
'ba': 'башҡорт теле',
'bal': 'Baluchi',
'be': 'Беларуская мова',
'bg': 'български език',
'bh': 'भोजपुरी',
'bi': 'Bislama',
'bm': 'bamanankan',
'bn': 'বাংলা',
'bo': 'བོད་ཡིག',
'br': 'brezhoneg',
'bs': 'босански',
'byn': 'Bilin',
'ca': 'català',
'ce': 'нохчийн мотт',
'cgg': 'Chiga',
'ch': 'Chamoru',
'ckb': 'Central Kurdish',
'co': 'corsu',
'cr': 'ᓀᐦᐃᔭᐍᐏᐣ',
'crh': 'Crimean Tatar',
'cs': 'česky',
'csb': 'Cashubian',
'cu': 'ѩзыкъ словѣньскъ',
'cv': 'чӑваш чӗлхи',
'cy': 'Cymraeg',
'da': 'dansk',
'de': 'Deutsch',
'dv': 'ދިވެހި',
'dz': 'རྫོང་ཁ',
'ee': 'Eʋegbe',
'el': 'Ελληνικά',
'en': 'English',
'en_AU': 'Australian English',
'en_CA': 'Canadian English',
'en_GB': 'British English',
'eo': 'Esperanto',
'es': 'Español',
'et': 'eesti',
'eu': 'euskara',
'fa': 'فارسی',
'ff': 'Fulfulde',
'fi': 'suomen kieli',
'fj': 'vosa Vakaviti',
'fo': 'føroyskt',
'fr': 'Français',
'fur': 'Frilian',
'fy': 'Frysk',
'ga': 'Gaeilge',
'gd': 'Gàidhlig',
'gez': 'Geez',
'gl': 'galego',
'gn': 'Avañeẽ',
'gu': 'Gujarati',
'gv': 'Gaelg',
'ha': 'هَوُسَ',
'haw': 'Hawaiian',
'he': 'עברית',
'hi': 'हिन्दी',
'hne': 'Chhattisgarhi',
'ho': 'Hiri Motu',
'hr': 'Hrvatski',
'hsb': 'Upper Sorbian',
'ht': 'Kreyòl ayisyen',
'hu': 'Magyar',
'hy': 'Հայերեն',
'hz': 'Otjiherero',
'ia': 'Interlingua',
'id': 'Indonesian',
'ig': 'Asụsụ Igbo',
'ii': 'ꆈꌠ꒿',
'ik': 'Iñupiaq',
'io': 'Ido',
'is': 'Íslenska',
'it': 'Italiano',
'iu': 'ᐃᓄᒃᑎᑐᑦ',
'iw': 'עברית',
'ja': '日本語',
'jv': 'basa Jawa',
'ka': 'ქართული',
'kg': 'Kikongo',
'ki': 'Gĩkũyũ',
'kj': 'Kuanyama',
'kk': 'қазақ тілі',
'kl': 'kalaallisut',
'km': 'ខ្មែរ',
'kn': 'ಕನ್ನಡ',
'ko': '한국어',
'kok': 'Konkani',
'kr': 'Kanuri',
'ks': 'कश्मीरी',
'ku': 'Kurdî',
'kv': 'коми кыв',
'kw': 'Kernewek',
'ky': 'Кыргызча',
'la': 'latine',
'lb': 'Lëtzebuergesch',
'lg': 'Luganda',
'li': 'Limburgs',
'ln': 'Lingála',
'lo': 'ພາສາລາວ',
'lt': 'lietuvių kalba',
'lu': 'Tshiluba',
'lv': 'latviešu valoda',
'mai': 'Maithili',
'mg': 'fiteny malagasy',
'mh': 'Kajin M̧ajeļ',
'mhr': 'Eastern Mari',
'mi': 'te reo Māori',
'mk': 'македонски јазик',
'ml': 'മലയാളം',
'mn': 'монгол',
'mr': 'मराठी',
'ms': 'بهاس ملايو',
'mt': 'Malti',
'my': 'ဗမာစာ',
'na': 'Ekakairũ Naoero',
'nb': 'Bokmål',
'nd': 'isiNdebele',
'nds': 'Plattdüütsch',
'ne': 'नेपाली',
'ng': 'Owambo',
'nl': 'Nederlands',
'nn': 'Norsk nynorsk',
'no': 'Norsk',
'nr': 'isiNdebele',
'nso': 'Pedi',
'nv': 'Diné bizaad',
'ny': 'chiCheŵa',
'oc': 'occitan',
'oj': 'ᐊᓂᔑᓈᐯᒧᐎᓐ',
'om': 'Afaan Oromoo',
'or': 'ଓଡ଼ିଆ',
'os': 'ирон æвзаг',
'pa': 'ਪੰਜਾਬੀ',
'pi': 'पाऴि',
'pl': 'polski',
'ps': 'پښتو',
'pt': 'Português',
'qu': 'Runa Simi',
'rm': 'rumantsch grischun',
'rn': 'Ikirundi',
'ro': 'română',
'ru': 'Pусский',
'rw': 'Ikinyarwanda',
'sa': 'संस्कृतम्',
'sc': 'sardu',
'sd': 'सिन्धी',
'se': 'Davvisámegiella',
'sg': 'yângâ tî sängö',
'shn': 'Shan',
'si': 'සිංහල',
'sk': 'slovenčina',
'sl': 'slovenščina',
'sm': 'gagana faa Samoa',
'sn': 'chiShona',
'so': 'Soomaaliga',
'sq': 'Shqip',
'sr': 'Српски',
'ss': 'SiSwati',
'st': 'Sesotho',
'su': 'Basa Sunda',
'sv': 'svenska',
'sw': 'Kiswahili',
'ta': 'தமிழ்',
'te': 'తెలుగు',
'tet': 'Tetum',
'tg': 'тоҷикӣ',
'th': 'ไทย',
'ti': 'ትግርኛ',
'tig': 'Tigre',
'tk': 'Türkmen',
'tl': 'ᜏᜒᜃᜅ᜔ ᜆᜄᜎᜓᜄ᜔',
'tn': 'Setswana',
'to': 'faka Tonga',
'tr': 'Türkçe',
'ts': 'Xitsonga',
'tt': 'татар теле',
'tw': 'Twi',
'ty': 'Reo Tahiti',
'ug': 'Uyghur',
'uk': 'Українська',
'ur': 'اردو',
'uz': 'Ўзбек',
've': 'Tshivenḓa',
'vi': 'Tiếng Việt',
'vo': 'Volapük',
'wa': 'walon',
'wae': 'Walser',
'wal': 'Wolaytta',
'wo': 'Wollof',
'xh': 'isiXhosa',
'yi': 'ייִדיש',
'yo': 'Yorùbá',
'za': 'Saɯ cueŋƅ',
'zh': '中文',
'zu': 'isiZulu'}
_paths = []
def __init__(self):
pass
def add_xml(self, xml_node):
def localization_
if not locales_to_keep:
raise RuntimeError('Found no locales to keep')
for xml_node in self._paths:
for (locale, path) in Locales.
if locale in purgeable_locales:
@staticmethod
def handle_path(path, xmldata):
"""Extracts paths and filters from the supplied xml tree and yields matching files"""
if xmldata.
return
if not xmldata.nodeName in ['path', 'regexfilter']:
raise RuntimeError(
location = xmldata.
if '.' != location:
path = path + location
if not path.endswith('/'):
path += '/'
if not os.path.
return
pre = None
post = None
if 'regexfilter' == xmldata.nodeName:
pre = xmldata.
post = xmldata.
if 'path' == xmldata.nodeName:
if not userfilter and not xmldata.
if userfilter:
if 1 != userfilter.
# we can't use re.escape, because it escapes too much
# handle child nodes
for child in xmldata.childNodes:
for (locale, subpath) in Locales.
if pre is not None and post is not None:
try:
except Exception as errormsg:
regex = re.compile('^' + pre + Locales.
for subpath in os.listdir(path):
if match is not None:
def apt_autoclean():
"""Run 'apt-get autoclean' and return the size (un-rounded, in bytes)
of freed space"""
if not FileUtilities.
raise RuntimeError(
args = ['apt-get', 'autoclean']
process = subprocess.
total_bytes = 0
while True:
line = process.
if line.startswith('E: '):
raise RuntimeError(line)
# Del cups-common 1.3.9-17ubuntu3 [1165kB]
match = re.search("^Del .*\[([0-
if match:
if "" == line and process.poll() != None:
break
return total_bytes
def apt_autoremove():
"""Run 'apt-get autoremove' and return the size (un-rounded, in bytes)
of freed space"""
if not FileUtilities.
raise RuntimeError(
args = ['apt-get', '--yes', 'autoremove']
process = subprocess.
total_bytes = 0
while True:
line = process.
if line.startswith('E: '):
raise RuntimeError(line)
# After this operation, 74.7MB disk space will be freed.
match = re.search(
r", ([0-9.]
if match:
if "" == line and process.poll() != None:
break
return total_bytes
def __is_broken_
"""Returns boolean whether application deskop entry file is broken"""
if not config.
print "info: is_broken_xdg_menu: missing required option 'Exec': '%s'" \
% (desktop_pathname)
return True
exe = config.get('Desktop Entry', 'Exec').split(" ")[0]
if not FileUtilities.
print "info: is_broken_xdg_menu: executable '%s' does not exist '%s'" \
% (exe, desktop_pathname)
return True
if 'env' == exe:
# Wine v1.0 creates .desktop files like this
# Exec=env WINEPREFIX=
# Files\\
execs = shlex.split(
wineprefix = None
del execs[0]
while True:
if 0 <= execs[0].find("="):
if 'WINEPREFIX' == name:
del execs[0]
else:
if not FileUtilities.
print "info: is_broken_xdg_menu: executable '%s'" \
return True
# check the Windows executable exists
if wineprefix:
if not os.path.
return False
def is_broken_
"""Returns boolean whether the given XDG desktop entry file is broken.
Reference: http://
config = ConfigParser.
config.
if not config.
print "info: is_broken_xdg_menu: missing required section " \
return True
if not config.
print "info: is_broken_xdg_menu: missing required option 'Type': '%s'" % (pathname)
return True
file_type = config.get('Desktop Entry', 'Type')
if 'link' == file_type:
if not config.
not config.
print "info: is_broken_xdg_menu: missing required option 'URL': '%s'" % (pathname)
return True
return False
if 'mimetype' == file_type:
if not config.
print "info: is_broken_xdg_menu: missing required option 'MimeType': '%s'" % (pathname)
return True
mimetype = config.get('Desktop Entry', 'MimeType'
if HAVE_GIO and 0 == len(gio.
print "info: is_broken_xdg_menu: MimeType '%s' not " \
return True
return False
if 'application' != file_type:
print "Warning: unhandled type '%s': file '%s'" % (file_type, pathname)
return False
if __is_broken_
return True
return False
def is_running(
"""Check whether exename is running"""
for filename in glob.iglob(
try:
target = os.path.
except TypeError:
# happens, for example, when link points to
# '/etc/password\x00 (deleted)'
except OSError:
# 13 = permission denied
if exename == os.path.
return True
return False
def rotated_logs():
"""Yield a list of rotated (i.e., old) logs in /var/log/"""
# Ubuntu 9.04
# /var/log/dmesg.0
# /var/log/dmesg.1.gz
# Fedora 10
# /var/log/
globpaths = ('/var/
for globpath in globpaths:
for path in glob.iglob(
yield path
regex = '-[0-9]{8}$'
globpaths = ('/var/log/*-*', '/var/log/*/*-*')
for path in FileUtilities.
if None == re.match(
yield path
def start_with_
"""If enabled, create shortcut to start application with computer.
If disabled, then delete the shortcut."""
if not enabled:
# User requests to not automatically start BleachBit
if os.path.
# Delete the shortcut
return
# User requests to automatically start BleachBit
if os.path.
# Already automatic, so exit
return
if not os.path.
print 'ERROR: does not exist: ', Common.
return
import shutil
General.
shutil.
os.
if General.
def start_with_
"""Return boolean whether BleachBit will start with the computer"""
return os.path.
def wine_to_
"""Return a Linux pathname from an absolute Windows pathname and Wine prefix"""
drive_letter = windows_pathname[0]
windows_
windows_
return os.path.
def yum_clean():
"""Run 'yum clean all' and return size in bytes recovered"""
if os.path.
msg = _(
"%s cannot be cleaned because it is currently running. Close it, and try again.") % "Yum"
raise RuntimeError(msg)
if not FileUtilities.
raise RuntimeError(
old_size = FileUtilities.
args = ['yum', "--enablerepo=*", 'clean', 'all']
p = subprocess.
non_blank_line = ""
while True:
line = p.stdout.
if len(line) > 2:
if -1 != line.find('You need to be root'):
# Seen before Fedora 13
raise RuntimeError(line)
if -1 != line.find('Cannot remove rpmdb file'):
# Since first in Fedora 13
raise RuntimeError(line)
if -1 != line.find('Another app is currently holding'):
print "debug: yum: '%s'" % line
if "" == line and p.poll() != None:
break
print 'debug: yum process return code = %d' % p.returncode
if p.returncode > 0:
raise RuntimeError(
new_size = FileUtilities.
return old_size - new_size
locales = Locales()
Changed in bleachbit: | |
assignee: | nobody → Weiller (weillerronfini) |
Closing. This is a duplicate bug report to the other one you made: https:/ /bugs.launchpad .net/bleachbit/ +bug/1573182
Please, for future reference, do not open up multiple bug tickets for 1 issue.