3 # This script reports which binary/source packages that can be safely
4 # deleted from one of the main APTs suite in our custom repo. It requires a
5 # .build-manifest as the source for which packages that are used
6 # during build and thus cannot be deleted.
11 raise 'please install the ruby-debian package'
17 class NoSource
< StandardError
20 def source_package(package
)
22 APT_SOURCES
.each_package
do |dsc
|
23 # The -dbg(sym) packages are not listed, so we look for the
24 # original package's source instead, which will be the same.
25 matches
<< dsc
if dsc
.binary
.include?(package
.sub(/-dbg(sym)?$/, ''))
27 raise NoSource
, "found no source package for #{package}" if matches
.size
.zero
?
29 raise "found multiple source packages for #{package}" if matches
.size
> 1
34 def binary_packages(package
)
35 APT_SOURCES
[package
].binary
38 Options
= Struct
.new(:suite, :build_manifest, keyword_init
: true)
41 def self.parse(options
)
42 args
= Options
.new(suite
: nil, build_manifest
: nil)
44 opt_parser
= OptionParser
.new
do |opts
|
47 'Look for cruft in APT suite SUITE'
52 '--build-manifest MANIFEST',
53 'Use specified build manifest instead of downloading the latest one'
55 args
.build_manifest
= build_manifest
57 opts
.on('-h', '--help', 'Prints this help') do
62 opt_parser
.parse
!(options
)
64 !args
.suite
.nil? or raise 'Please use --suite SUITE'
69 options
= Parser
.parse(ARGV)
71 allowed_suites
= ['stable', 'devel']
72 unless allowed_suites
.include?(options
.suite
)
73 raise "we only support checking the following' " \
74 "custom APT suites: #{allowed_suites.join(', ')}"
77 apt_repo_hostnames
= [
79 'umjqavufhoix3smyq6az2sx4istmuvsgmz4bq5u5x56rnayejoo6l2qd.onion',
81 apt_repo_filenames
= apt_repo_hostnames
.map
do |hostname
|
82 "/var/lib/apt/lists/#{hostname}_dists_#{options.suite}_main_source_Sources"
84 apt_repo_filename
= apt_repo_filenames
.find
do |filename
|
87 APT_SOURCES
= Debian
::Sources.new(apt_repo_filename
).freeze
89 raise "could not find Tails custom APT repo's sources, " \
90 "please add this to your APT sources:\n" \
91 "deb-src [arch=amd64] http://deb.tails.boum.org/ #{options.suite} main"
94 if options
.build_manifest
.nil?
95 url
= "https://nightly.tails.boum.org/build_Tails_ISO_#{options.suite}/lastSuccessful/archive/latest.build-manifest"
97 manifest
= YAML
.safe_load(
100 rescue OpenURI
::HTTPError
101 raise "got HTTP 404 when attempting to fetch: #{url}\n" \
102 'Please try again in a while -- Jenkins sometimes needs some time ' \
103 'to create the latest.build-manifest symlink after a build completes'
106 manifest
= YAML
.load_file(options
.build_manifest
)
109 all_source_packages
= []
110 used_source_packages
= []
111 binary_cruft_candidates
= []
113 custom_packages
= `ssh reprepro@incoming.deb.tails.boum.org reprepro list #{options.suite}`
114 custom_packages
.each_line(chomp
: true) do |line
|
115 type
, name
, version = line
.split
117 all_source_packages
<< name
119 installed
= manifest
['packages']['binary'].find
{ |x
| x
['package'] == name
}
120 if installed
.nil? || version != installed
['version']
121 binary_cruft_candidates
<< name
123 used_source_packages
<< source_package(name
)
128 source_cruft
= all_source_packages
.uniq
- used_source_packages
130 binary_cruft_candidates
.each
do |p
|
132 next if used_source_packages
.include?(source_package(p
))
134 # If we don't have a source for a package, it should be a package
135 # we forgot to clean up when we removed its sources.
140 unless binary_cruft
.empty
?
141 puts
'Binary packages that are not used:'
142 binary_cruft
.each
{ |p
| puts
" - #{p}" }
144 puts
" Clean up command:\n" \
145 ' ssh reprepro@incoming.deb.tails.boum.org ' \
146 "reprepro remove #{options.suite} #{binary_cruft.join(' ')}"
150 unless source_cruft
.empty
?
151 puts
'Source packages that are not used:'
152 source_cruft
.each
{ |p
| puts
" - #{p}" }
154 puts
" Clean up command:\n" \
155 ' ssh reprepro@incoming.deb.tails.boum.org ' \
156 "reprepro removesrcs #{options.suite} #{source_cruft.join(' ')}"