Fix for MatchPackageOptions
[paludis-scripts.git] / grex.rb
1 #!/usr/bin/ruby -w
2 # vim: set sw=4 sts=4 et tw=80 ft=ruby :
3 # $Id$
4
5 # Copyright (c) 2007 Mike Kelly <pioto@pioto.org>
6 #
7 # This file is part of the Paludis package manager. Paludis is free software;
8 # you can redistribute it and/or modify it under the terms of the GNU General
9 # Public License, version 2, as published by the Free Software Foundation.
10 #
11 # Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
12 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
14 # details.
15 #
16 # You should have received a copy of the GNU General Public License along with
17 # this program; if not, write to the Free Software Foundation, Inc., 59 Temple
18 # Place, Suite 330, Boston, MA  02111-1307  USA
19
20 %w(Paludis getoptlong rexml/document net/http uri fileutils).each {|x| require x}
21
22 include Paludis
23
24 Log.instance.log_level = Paludis::LogLevel::Warning
25 Log.instance.program_name = $0
26
27 version = "0.1.1"
28 herdsxml_url = URI.parse('http://sources.gentoo.org/viewcvs.py/*checkout*/gentoo/xml/htdocs/proj/en/metastructure/herds/herds.xml?content-type=text%2Fplain')
29
30 opts = GetoptLong.new(
31     [ '--help',          '-h', GetoptLong::NO_ARGUMENT ],
32     [ '--version',       '-V', GetoptLong::NO_ARGUMENT ],
33     [ '--log-level',           GetoptLong::REQUIRED_ARGUMENT ],
34     [ '--environment',   '-E', GetoptLong::REQUIRED_ARGUMENT ],
35     [ '--herd',                GetoptLong::NO_ARGUMENT ],
36     [ '--package',             GetoptLong::NO_ARGUMENT ],
37     [ '--dev',                 GetoptLong::NO_ARGUMENT ],
38     [ '--verbose',       '-v', GetoptLong::NO_ARGUMENT ])
39
40 env_spec = ''
41 verbose = false
42 mode = 'package'
43
44 opts.each do | opt, arg |
45     case opt
46     when '--help'
47         puts "Usage: " + $0 + " [options] <name> [<name> ...]"
48         puts
49         puts "Options:"
50         puts "  -h|--help                  Display a help message"
51         puts "  -V|--version               Display program version"
52         puts "  --log-level level          Set log level (debug, qa, warning, slient)"
53         puts "  -E|--environment env       Environment specification (class:suffix, both parts optional)"
54         puts
55         puts "The following options affect what sort of information is shown:"
56         puts "  --herd                     Show more information about the herds given."
57         puts "  --package                  Show the maintainer data for the given package names (default)."
58         puts "  --dev                      Show the herds that the given developer is a member of."
59         puts
60         puts "  -v|--verbose               Verbose output (e.g. lookup herd members)"
61         exit 0
62
63     when '--version'
64         puts $0.to_s.split(/\//).last + " " + version + " (Paludis Version: " +Paludis::Version + ")"
65         exit 0
66
67     when '--log-level'
68         case arg
69         when 'debug'
70             Paludis::Log.instance.log_level = Paludis::LogLevel::Debug
71         when 'qa'
72             Paludis::Log.instance.log_level = Paludis::LogLevel::Qa
73         when 'warning'
74             Paludis::Log.instance.log_level = Paludis::LogLevel::Warning
75         when 'silent'
76             Paludis::Log.instance.log_level = Paludis::LogLevel::Silent
77         else
78             puts "Bad --log-level value " + arg
79             exit 1
80         end
81     when '--environment'
82         env_spec = arg
83
84     when '--herd'
85         mode = "herd"
86     when '--package'
87         mode = "package"
88     when '--dev'
89         mode = "dev"
90
91     when '--verbose'
92         verbose = true
93
94     end
95
96 end
97
98 env = EnvironmentFactory.instance.create(env_spec)
99
100 if ARGV.empty?
101     puts "No arguments supplied"
102     exit 1
103 end
104
105 package_db = env.package_database()
106
107 # build a hash of repo.name->repo.location
108 locations = Hash.new
109
110 package_db.repositories.each do | repo |
111     next if repo.e_interface == nil
112     repo.each_metadata do | key |
113        locations[repo.name] = key.value if key.raw_name == 'location'
114     end
115 end
116
117 cache_dir = File.expand_path '~/.grex'
118 herds_cache_file = "#{cache_dir}/herds.xml"
119
120 if File.readable?(herds_cache_file) && File.mtime(herds_cache_file) > Time.now - 24 * 60 * 60
121     herdsxml = REXML::Document.new File.read(herds_cache_file)
122 else
123     begin
124         req = Net::HTTP::Get.new(herdsxml_url.path)
125         res = Net::HTTP.start(herdsxml_url.host, herdsxml_url.port) {|http|
126             http.request(req)
127         }
128         body =  res.body
129     rescue
130         puts "Couldn't fetch herds.xml."
131         verbose = false
132     end
133     FileUtils.mkdir(cache_dir) unless File.directory? cache_dir
134     File.open(herds_cache_file, 'w') {|x| x.print body}
135     herdsxml = REXML::Document.new body
136 end
137
138 ARGV.each do | name |
139     if mode == "package"
140         package_name = name
141         if package_name.include? ?/
142             fqpn = QualifiedPackageName.new(package_name)
143         else
144             fqpn = package_db.fetch_unique_qualified_package_name(package_name)
145         end
146         puts "#{fqpn}"
147
148         package_db.repositories.each do | repo |
149             next if repo.e_interface == nil
150             next unless repo.has_package_named? fqpn
151
152             location = locations[repo.name]
153
154             begin
155                 file = File.new(location + "/" + fqpn + "/metadata.xml")
156             rescue Errno::ENOENT
157                 puts "  No metadata.xml for this repo (#{repo.name}). Skipping."
158                 next
159             end
160             puts "  #{repo.name}: #{location}"
161
162             begin
163                 metadata = REXML::Document.new file
164             rescue
165                 puts "  Error parsing metadata.xml for this repo (#{repo.name}). Skipping."
166                 next
167             end
168
169             metadata.elements.each("pkgmetadata/herd") do | element |
170                 herd = element.text.to_s
171                 if herd.empty?
172                     Paludis::Log.instance.message("grex.empty_herd", Paludis::LogLevel::Qa, "Empty <herd> tag in metadata.xml for #{fqpn} in #{repo.name}.")
173                     next
174                 end
175
176                 print "    herd:  #{herd}"
177
178                 if verbose
179                     herdsxml.elements.each("herds/herd") do | element |
180                         next unless element.text("name").strip == herd
181                         print " <#{element.text("email").strip}>" unless element.text("email") == nil
182                         puts
183                         element.elements.each() do | maintainer |
184                             name = maintainer.text("name").to_s.strip
185                             email = maintainer.text("email").to_s.strip
186                             next if name.empty? and email.empty?
187
188                             print "      maintainer:  "
189
190                             if email.empty?
191                                 print name
192                             elsif name.empty?
193                                 print "<#{email}>"
194                             else
195                                 print "#{name} <#{email}>"
196                             end
197                             print "\n"
198                         end
199                     end
200                 end
201             end
202
203             metadata.elements.each("pkgmetadata/maintainer") do | element |
204                 name = element.text("name").to_s.strip
205                 email = element.text("email").to_s.strip
206                 next if name.empty? and email.empty?
207
208                 print "    maintainer:  "
209
210                 if email.empty?
211                     print name
212                 elsif name.empty?
213                     print "<#{email}>"
214                 else
215                     print "#{name} <#{email}>"
216                 end
217                 print "\n"
218             end
219         end
220     elsif mode == "herd"
221         print "#{name}"
222         herdsxml.elements.each("herds/herd") do | element |
223             element.context={:compress_whitespace => :all}
224             next unless element.text("name").strip == name
225             print " <#{element.text("email").strip}>" unless element.text("email") == nil
226             puts
227
228             desc = element.text("description").to_s.strip
229             puts " :: #{desc}" unless desc.empty?
230
231             proj_page = element.text("maintainingproject").to_s.strip
232             puts " :: http://www.gentoo.org#{proj_page}" unless proj_page.empty?
233
234             element.elements.each() do | maintainer |
235                 name = maintainer.text("name").to_s.strip
236                 email = maintainer.text("email").to_s.strip
237                 role = maintainer.text("role").to_s.strip
238                 next if name.empty? and email.empty?
239
240                 print "  maintainer:  "
241
242                 if email.empty?
243                     print name
244                 elsif name.empty?
245                     print "<#{email}>"
246                 else
247                     print "#{name} <#{email}>"
248                 end
249                 print " (#{role})" unless role.empty?
250                 print "\n"
251             end
252         end
253     end
254 end