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
|
#!/usr/bin/ruby1.8
#
# 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-2012 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;
# 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 'debian/apt_preferences'
require 'tempfile'
APTCACHE = "/usr/bin/apt-cache"
LISTBUGS = "/usr/sbin/apt-listbugs"
# read apt preferences
p = Debian::AptPreferences.new
pinnedpkgs = []
bugpkgs = []
# store apt preferences with no apt-listbugs pins in a temporary file
unpinned_pref_file = Tempfile.new('apt_preferences_')
p.filter( bugpkgs, unpinned_pref_file )
unpinned_pref_file.flush
unpinned_preferences = unpinned_pref_file.path
p.pins.each do |pin|
if pin.listbugs?
pinned_package = pin["Package"]
pinnedpkgs << 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::Preferences=#{unpinned_preferences} 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
pack_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 #{pack_with_vers}" if $DEBUG
optionB = nil
if feared_list != "" and feared_list != nil
optionB = "-B #{feared_list}"
end
open("|#{LISTBUGS} -y -q #{optionB} list #{pack_with_vers}") { |io|
array = io.readlines()
bugpkgs << pinned_package if array.size != 0
}
if $?.exitstatus != 0
$stderr.puts "Error... exiting!" if $DEBUG
exit 1
end
end
end
# get rid of the temporary file
unpinned_pref_file.close!
$stderr.puts "Pinned packages: #{pinnedpkgs.sort.join(' ')}" if $DEBUG
$stderr.puts "Buggy packages : #{bugpkgs.sort.join(' ')}" if $DEBUG
if (pinnedpkgs - bugpkgs).size > 0
$stderr.puts "Fixed packages : #{(pinnedpkgs - bugpkgs).sort.join(' ')}"
end
# write out filtered preferences file
p.filter( bugpkgs )
|