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
|
#!/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-2019 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
#
if ! File.expand_path(__FILE__).match(/^\/usr\/libexec\/apt-listbugs\//)
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "../lib"))
end
require 'gettext'
include GetText
GetText::bindtextdomain("apt-listbugs")
require 'aptlistbugs/debian/apt_preferences'
require 'tmpdir'
APTCACHE = "/usr/bin/apt-cache"
LISTBUGS = "/usr/bin/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} -a -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 )
|