Fix pint for the newer paludis install task.
[paludis-scripts.git] / gimme.rb
1 #!/usr/bin/ruby
2 # vim: set sw=4 sts=4 et tw=80 :
3 # $Id$
4
5 %w{Paludis getoptlong}.each {|x| require x}
6
7 include Paludis
8
9 $0 = File.basename $0
10 Log.instance.log_level = LogLevel::Warning
11 Log.instance.program_name = $0
12
13 EQUAL = 0
14 PACKAGE = 1
15 TILDE = 2
16
17 class PackageID
18     def my_string(style, show_repo)
19         repo = show_repo ? "::#{repository_name}" : ''
20         slot = slot_key ? ":#{slot_key.value}" : ''
21         case style
22         when EQUAL
23             "=#{name}-#{version}#{slot}#{repo}"
24         when TILDE
25             "~#{name}-#{version.remove_revision}#{slot}#{repo}"
26         when PACKAGE
27             "#{name}#{repo}"
28         end
29     end
30 end
31
32 def write_file(arr, file, base)
33     output = base
34     arr.each {|x| output += "\n#{x}"}
35     if @subdir
36         dir = "#{file}.d"
37         file = "#{dir}/#{@spec.to_s.gsub('/','_')}.conf"
38     end
39
40     if @pretend
41         puts "\n# #{file}"
42         puts output
43     else
44         if (@subdir && !File.directory?("#{@config_dir}/#{dir}"))
45             puts "#{dir} is not a directory. Either specify \"--use-subdir no\" or create #{dir}"
46             exit 1
47         else
48             File.open("#{@config_dir}/#{file}",'a') {|file| file.puts output}
49         end
50     end
51 end
52
53 def collect_highest_versions(dl)
54     seen = {}
55     dl.each do |entry|
56         next unless entry.kind == DepListEntryKind::Masked
57         pid = entry.package_id
58         seen[pid.name] ||= {}
59         seen[pid.name][:version] ||= VersionSpec.new('0')
60         if pid.version > seen[pid.name][:version]
61             seen[pid.name][:version] = pid.version
62             seen[pid.name][:dle] = entry
63         end
64     end
65
66     out = []
67     seen.each_value {|v| out << v[:dle]}
68     return out
69 end
70
71 opts = GetoptLong.new(
72     [ '--help',                   '-h',  GetoptLong::NO_ARGUMENT ],
73     [ '--version',                '-V',  GetoptLong::NO_ARGUMENT ],
74     [ '--log-level',                     GetoptLong::REQUIRED_ARGUMENT ],
75     [ '--environment',            '-E',  GetoptLong::REQUIRED_ARGUMENT ],
76     [ '--match-type',             '-m',  GetoptLong::REQUIRED_ARGUMENT ],
77     [ '--pretend',                '-p',  GetoptLong::NO_ARGUMENT ],
78     [ '--override-masks',         '-o',  GetoptLong::REQUIRED_ARGUMENT ],
79     [ '--use-subdir',             '-s',  GetoptLong::REQUIRED_ARGUMENT ],
80     [ '--include-repository-name',       GetoptLong::REQUIRED_ARGUMENT ])
81
82 envspec = ''
83 @match_type = TILDE
84 @pretend = false
85 @repository = false
86 @subdir = false
87 @masks = nil;
88
89 dlomf = DepListOverrideMasksFunctions.new
90
91 opts.each do | opt, arg |
92     case opt
93     when '--help'
94         puts "Usage: " + $0 + " [options] target"
95         puts
96         puts "Options:"
97         puts "  --help                     Display a help message"
98         puts "  --version                  Display libpaludis version"
99         puts
100         puts "  --pretend                  Display changes instead of changing files"
101         puts "  --log-level level          Set log level (debug, qa, warning, silent)"
102         puts "  --environment env          Environment specification (class:suffix, both parts optional, class must be 'paludis' if specified)" if @gt020
103         puts "  --match-type type          Set match type (equal, tilde (default), package)"
104         puts "  --include-repository-name  Include repository name in DepSpec (yes (default), no)"
105         puts "  --override-masks list      List of masks to override, seperated by \",\", default is all"
106         puts "                                license"
107         puts "                                tilde_keywords"
108         puts "                                unkeyworded"
109         puts "                                repository_masks"
110         puts "  --use-subdir               Write files to conf.d dirs (yes, no (default))"
111         exit 0
112
113     when '--version'
114         puts "#{$0} (libpaludis version: #{Paludis::Version})"
115         exit 0
116
117     when '--log-level'
118         case arg
119         when 'debug'
120             Log.instance.log_level = LogLevel::Debug
121         when 'qa'
122             Log.instance.log_level = LogLevel::Qa
123         when 'warning'
124             Log.instance.log_level = LogLevel::Warning
125         when 'silent'
126             Log.instance.log_level = LogLevel::Silent
127         else
128             $stderr.puts "Bad --log-level value " + arg
129             exit 1
130         end
131
132     when '--environment'
133             envspec = arg
134
135     when '--match-type'
136         case arg
137         when 'package'
138             @match_type = PACKAGE
139         when 'equal'
140             @match_type = EQUAL
141         when 'tilde'
142             @match_type = TILDE
143         else
144             $stderr.puts "Bad --match-type value #{arg}"
145             exit 1
146         end
147
148     when '--include-repository-name'
149         case arg
150         when 'yes'
151             @repository = true
152         when 'no'
153             @repository = false
154         else
155             $stderr.puts "Bad --include-repository-name value #{arg}"
156             exit 1
157         end
158
159     when '--override-masks'
160         @masks = arg
161
162     when '--use-subdir'
163         case arg
164         when 'yes'
165             @subdir = true
166         when 'no'
167             @subdir = false
168         else
169             $stderr.puts "Bad --use-subdir value #{arg}"
170             exit 1
171         end
172
173     when '--pretend'
174         @pretend = true
175
176     end
177 end
178
179 if ARGV.length != 1
180     puts "Please specify exactly 1 target"
181     exit 1
182 end
183
184 target = ARGV.first
185
186 env = Paludis::EnvironmentFactory.instance.create(envspec)
187 if env.format_key.value != "paludis" then
188     $stderr.puts "#$0: --environment must specify class 'paludis'"
189     exit 1
190 end
191 @config_dir = env.config_location_key.value
192
193 if @masks.nil?
194     dlomf.bind(:tilde_keywords, env)
195     dlomf.bind(:unkeyworded, env)
196     dlomf.bind(:repository_masks)
197     dlomf.bind(:license)
198 else
199     @masks.scan(/\w+/) do |mask|
200         mask_sym = mask.to_sym
201         case mask_sym
202         when :tilde_keywords, :unkeyworded
203             dlomf.bind(mask_sym, env)
204         when :repository_masks, :license
205             dlomf.bind(mask_sym)
206         else
207             $stderr.puts "Unrecognised --override-masks option: #{mask}"
208             exit 1
209         end
210     end
211 end
212
213
214 db = env.package_database
215
216 @spec = nil
217
218 begin
219     @spec = parse_user_package_dep_spec(target, env, [:throw_if_set],
220                 Filter::SupportsAction.new(InstallAction))
221 rescue GotASetNotAPackageDepSpec
222     @spec = env.set(target)
223 end
224
225 dl = DepList.new(env, DepListOptions.new)
226 dl.options.override_masks = dlomf
227
228 begin
229     dl.add(@spec, env.default_destinations)
230 rescue AllMaskedError
231     bad_spec = $!.query
232     pids = env[Selection::AllVersionsSorted.new(
233                    Generator::Matches.new(parse_user_package_dep_spec(bad_spec, env, []),[]) |
234                        Filter::SupportsAction.new(InstallAction))]
235     if pids.empty?
236         puts "No versions of #{bad_spec} are available."
237     else
238         puts "I'm not allowed to unmask #{bad_spec}: Masks are:"
239         pids.each do |pid|
240             print "#{pid}: Masked by: "
241             reasons = []
242             pid.masks.each do |reason|
243                 if reason.instance_of? UnacceptedMask
244                     if reason.unaccepted_key.instance_of? MetadataKeywordNameSetKey
245                         reasons << 'keyword'
246                     end
247                 elsif reason.instance_of? RepositoryMask
248                     reasons << 'repository'
249                 end
250             end
251             puts reasons.join(', ')
252         end
253     end
254     exit 1
255 end
256
257 keywords = []
258 unmask = []
259 #license = []
260 collect_highest_versions(dl).each do |entry|
261     reasons = entry.package_id.masks
262     repo = db.fetch_repository(entry.package_id.repository_name)
263     e_spec = entry.package_id.my_string(@match_type, @repository)
264     reasons.each do |reason|
265         if reason.instance_of? UnacceptedMask
266             key = reason.unaccepted_key
267             if key.instance_of? MetadataKeywordNameSetKey
268                 my_arch = repo.profile_variable("ARCH")
269                 kw = reason.unaccepted_key.value
270                 if kw.empty?
271                     my_arch = '*'
272                 elsif kw.include?("~#{my_arch}")
273                     my_arch = "~#{my_arch}"
274                 else
275                     my_arch = kw.first
276                     my_arch += (my_arch[0] == ?~ ? " #{my_arch[1..-1]}" : '')
277                 end
278                 keywords <<(e_spec + " #{my_arch}")
279             end
280         elsif reason.instance_of? RepositoryMask
281             unmask << e_spec
282         end
283     end
284 end
285
286 output_base = "\n# Added by #{$0} for #{target}"
287 output_base += "\n" + ('#' * (output_base.length-1))
288
289 write_file(keywords, 'keywords.conf', output_base) unless keywords.empty?
290 write_file(unmask, 'package_unmask.conf', output_base) unless unmask.empty?
291 #write_file(license, 'license.conf', output_base) unless license.empty?
292