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
|
#!/usr/bin/ruby
#
# aptcleanup: filters /etc/apt/preferences to unpin packages when bugs are fixed
#
# Copyright (C) 2004 Masato Taruishi <taru@debian.org>
# Copyright (C) 2007 Jean Lepropre <jlepropre@gmail.com>
# Copyright (C) 2008-2014 Francesco Poli <invernomuto@paranoici.org>
# Copyright (C) 2009 Ryan Niebur <ryan@debian.org>
#
# 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 with
# the Debian GNU/Linux distribution in file /usr/share/common-licenses/GPL-2;
# if not, write to the Free Software Foundation, Inc., 51 Franklin St,
# Fifth Floor, Boston, MA 02110-1301, USA.
#
#
if File.expand_path(__FILE__).match(/^\/usr\/share\/apt-listbugs\//)
$LOAD_PATH.unshift("/usr/share/apt-listbugs")
else
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "lib"))
end
require 'gettext'
include GetText
GetText::bindtextdomain("apt-listbugs")
require 'debian/apt_preferences'
require 'tmpdir'
APTCACHE = "/usr/bin/apt-cache"
LISTBUGS = "/usr/sbin/apt-listbugs"
# read APT preferences
pref_dir = "/etc/apt/preferences.d"
pref_name = "apt-listbugs"
pref_file = pref_dir + "/" + pref_name
begin
p = Debian::AptPreferences.new
rescue Errno::ENOENT
$stderr.puts sprintf("Cannot find %s: exiting!", pref_file) if $DEBUG
exit 0
rescue Errno::EACCES
$stderr.puts _("E: ") + sprintf(_("Cannot read from %s"), pref_file)
exit 1
rescue
$stderr.puts _("E: ") + "#{$!}"
exit 1
end
pinned_pkg_keys = []
buggy_pkg_keys = []
# store APT preferences with no apt-listbugs pins in a temporary directory
unpinned_pref_dir = Dir.mktmpdir('apt_preferences_')
begin
FileUtils.cp_r "#{pref_dir}/.", unpinned_pref_dir
unpinned_pref_file = File.open(unpinned_pref_dir + "/" + pref_name, "w")
p.filter( buggy_pkg_keys, unpinned_pref_file )
unpinned_pref_file.flush
p.pins.each do |pin|
if pin.listbugs?
pinned_package = pin["Package"]
pinned_pkg_keys << pinned_package
# which version would get installed, if the pinning were removed ?
unpinned_candidate_version = nil
policy_cand_line = `env LC_ALL=C #{APTCACHE} -o Dir::Etc::PreferencesParts=#{unpinned_pref_dir} policy #{pinned_package} 2> /dev/null`.split("\n").select{|x| x.match("Candidate:")}[0]
if policy_cand_line != nil
policy_cand_vers = policy_cand_line.split(" ")[1]
if policy_cand_vers != nil
unpinned_candidate_version = "/" + policy_cand_vers
end
end
if unpinned_candidate_version == "/(none)" or unpinned_candidate_version == nil
unpinned_candidate_version = ""
$stderr.puts "Warning: no candidate version for #{pinned_package}" if $DEBUG
end
pkg_key_with_vers = pinned_package + unpinned_candidate_version
# read which bugs caused the pinning ("bugs that the user fears")
feared_bugs = pin["Explanation"].scan(/#(\d+):/)
feared_list = feared_bugs.join(',')
# are bugs that the user fears still affecting unpinned_candidate_version ?
$stderr.puts "Checking bug(s) #{feared_list} for #{pkg_key_with_vers}" if $DEBUG
optionB = nil
if feared_list != "" and feared_list != nil
optionB = "-B #{feared_list}"
end
open("|#{LISTBUGS} -y -q #{optionB} list #{pkg_key_with_vers}") { |io|
array = io.readlines()
buggy_pkg_keys << pinned_package if array.size != 0
}
if $?.exitstatus != 0
$stderr.puts sprintf("Error while invoking %s: exiting!", LISTBUGS) if $DEBUG
exit 1
end
end
end
ensure
# get rid of the temporary directory along with its content
FileUtils.remove_entry unpinned_pref_dir
end
$stderr.puts "Pinned packages: #{pinned_pkg_keys.sort.join(' ')}" if $DEBUG
$stderr.puts "Buggy packages : #{buggy_pkg_keys.sort.join(' ')}" if $DEBUG
if (pinned_pkg_keys - buggy_pkg_keys).size > 0
$stderr.puts _("Fixed packages : ") + (pinned_pkg_keys - buggy_pkg_keys).sort.join(' ')
end
# write out filtered preferences file
p.filter( buggy_pkg_keys )
|