public
Description:
Homepage:
Clone URL: git://github.com/rbrown/scripts.git
scripts / compare_gems.rb
100644 276 lines (253 sloc) 10.803 kb
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
#!/usr/bin/env ruby
# vim: set sw=4 sts=4 et :
require 'Paludis'
require 'rubygems/source_info_cache'
require 'markaby'
require 'getoptlong'
 
include Paludis
 
master_repository_dir = '/var/empty'
write_cache_dir = '/var/empty'
repository_dir = '/var/paludis/repositories/gentoo'
Log.instance.log_level = LogLevel::Warning
Log.instance.program_name = $0
 
opts = GetoptLong.new(
    [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
    [ '--log-level', GetoptLong::REQUIRED_ARGUMENT ],
    [ '--master-repository-dir', GetoptLong::REQUIRED_ARGUMENT ],
    [ '--repository-dir', GetoptLong::REQUIRED_ARGUMENT ],
    [ '--write-cache-dir', GetoptLong::REQUIRED_ARGUMENT ]
)
 
opts.each do | opt, arg |
    case opt
    when '--help'
        puts "Usage: " + $0 + " [options]"
        puts
        puts "Options:"
        puts " --help Display a help message"
        puts " --version Display program version"
        puts
        puts " --log-level level Set log level (debug, qa, warning, silent)"
        puts " --repository-dir Use the specified location for the repository (default /var/paludis/repositories/gentoo"
        puts " --master-repository-dir Use the specified location for the master repository"
        puts " --write-cache-dir Use a subdirectory named for the repository name under the specified directory for repository write cache"
        exit 0
    when '--log-level'
        case arg
        when 'debug'
            Paludis::Log.instance.log_level = Paludis::LogLevel::Debug
        when 'qa'
            Paludis::Log.instance.log_level = Paludis::LogLevel::Qa
        when 'warning'
            Paludis::Log.instance.log_level = Paludis::LogLevel::Warning
        when 'silent'
            Paludis::Log.instance.log_level = Paludis::LogLevel::Silent
        else
            puts "Bad --log-level value " + arg
            exit 1
        end
 
    when '--write-cache-dir'
        write_cache_dir = arg
 
    when '--master-repository-dir'
        master_repository_dir = arg
 
    when '--repository-dir'
        repository_dir = arg
    end
end
 
$env = NoConfigEnvironment.new(repository_dir, write_cache_dir, master_repository_dir)
 
$db = $env.package_database
$repo_name = $env.main_repository.name
 
pids = $db.query(Query::Repository.new($repo_name), QueryOrder::BestVersionOnly)
 
$not_found = []
$equal = []
$higher = []
$lower = []
 
# Pretty Print a DepSpec
def pp_pspec(spec)
    output = ''
    if spec.kind_of? AllDepSpec
        output+= ' ( '
        spec.each do |child|
            output+= pp_pspec(child)
        end
        output+= ' ) '
    elsif spec.kind_of? AnyDepSpec
        output+= ' || ( '
        spec.each do |child|
            output+= pp_pspec(child)
        end
        output+= ' ) '
    elsif spec.kind_of? ConditionalDepSpec
        output+= spec.condition
        output+= ' ( '
        spec.each do |child|
            output+= pp_pspec(child)
        end
        output+= ' ) '
    elsif spec.kind_of? PackageDepSpec
        output += "#{spec.to_s} "
    elsif spec.kind_of? BlockDepSpec
        output+= ' !' + pp_pspec(spec.blocked_spec)
    else
        $stderr.puts "#{spec.class} is missing, fail."
    end
    return output
end
 
module Gem
    class Requirement
        # Helps to be able to read this in Dependency
        attr_reader :requirements
    end
 
    class Dependency
        # Create an array of PackageDepSpecs base on the name of gem
        def paludis_array(db)
            begin
                qpn = db.fetch_unique_qualified_package_name(name.downcase)
            rescue NoSuchPackageError
                qpn = "gems/#{name}"
            rescue Paludis::AmbiguousPackageNameError
                qpn = "ambiguous/#{name}"
            rescue Paludis::PackageNameLookupError
            end
            version_requirements.requirements.collect do |op, ver|
                parse_user_package_dep_spec("#{op}#{qpn}-#{ver}", [])
            end
        end
    end
end
 
# Given an array of Gems::Dependency, get an array of PacakgeDepSpec from them.
def gem_dep_list(deps, db)
    deps.collect do |dep|
        dep.paludis_array(db)
    end.flatten
end
 
pids.each do |pid|
    # We only care about packages that inherite gems.eclass
    inherit = pid['INHERITED']
    if !inherit.nil? && inherit.value.include?('gems')
        specs = Gem::SourceInfoCache.search(/^#{pid.name.package}$/i)
        if specs.empty?
            $not_found << pid
        else
            # Gem::SourceInfoCache returns an array of Gem:Specification,
            # we only care about the highest version
            gemspec = specs.last
 
            # Rely on paludis to do version comparisons
            version = VersionSpec.new(gemspec.version.to_s)
 
            # Gems don't have a revision, so remove it from the PackageID
            pid_version = pid.version.remove_revision
            entry = { :pid => pid, :gemspec => gemspec }
            if version > pid_version
                $higher << entry
            elsif version == pid_version
                $equal << entry
            else
                $lower << entry
            end
        end
    end
end
 
module HideMarkaby
    Markaby::Builder.set(:indent, 2)
    mab = Markaby::Builder.new.xhtml_strict do
        head do
            title " #{$repo_name} rubygems comparison "
            tag! :link, :href => 'compare_gems.css', :rel => 'stylesheet', :type => 'text/css'
        end
        body do
            h1 " #{$repo_name} rubygems comparison "
 
            unless $higher.empty?
                h2 "Newer versions are available for the following packages"
                dl do
                    $higher.each do |entry|
                        pid = entry[:pid]
                        gemspec = entry[:gemspec]
                        output = pid.to_s
 
                        # ebuilds can have more than 1 homepage, collect them
                        # this method is fragile.
                        homepages = []
                        i = 1
                        pid['HOMEPAGE'].value.each do |spec|
                            homepages << a.homepage("#{i}", :href=> spec)
                            i+=1
                        end
                        output += ' (' + homepages.join(', ') + ')'
                        dt { output }
                        dd do
                            p pid['DESCRIPTION'].value
                            table do
                                tr do
                                    th ''
                                    th 'Version'
                                    th 'Dependencies'
                                end
                                tr do
                                    td 'gentoo-x86'
                                    td pid.version
                                    td do
                                        %w{build run post}.each do |key|
                                            spec_text = pp_pspec(pid.send("#{key}_dependencies_key".to_sym).value)
                                            unless ' ( ) ' == spec_text
                                                text "#{key.capitalize}: #{spec_text}"
                                                br
                                            end
                                        end
                                    end
                                end
                                tr do
                                    td 'rubygems'
                                    td gemspec.version
                                    td do
                                        specs = gem_dep_list(gemspec.dependencies, $db)
                                        specs.each do |spec|
                                            case spec.package.category
                                            when 'gems'
                                                # If the category is gems, there is not an ebuild for this gem, so link
                                                # to the gem's homepage
                                                new_specs = Gem::SourceInfoCache.search(/^#{spec.package.package}$/i)
                                                if new_specs.nil?
                                                    span.gems spec.to_s
                                                else
                                                    a.gems spec.to_s, :href => new_specs.last.homepage
                                                end
                                            when 'ambiguous'
                                                # Do nothing fancy if we had an ambiguous match
                                                span.ambiguous spec.to_s
                                            else
                                                # Query for the spec we generated in the database
                                                unless $db.query(Query::Matches.new(spec), QueryOrder::BestVersionOnly).empty?
                                                    # Our spec matches, we already have a high enough version
                                                    span.ok spec.to_s
                                                else
                                                    # Link to the gem homepage, because we need to bump
                                                    new_pid = $db.query(Query::Package.new(spec.package), QueryOrder::BestVersionOnly)[0]
                                                    output=""
                                                    new_pid["HOMEPAGE"].value.each do |homepage_spec|
                                                        output << homepage_spec.to_s
                                                        break
                                                    end
                                                    a.bad_version spec.to_s, :href => output
                                                end
                                            end
                                        end
                                    end
                                end
                            end
                        end
                    end
                end
            end
            unless $not_found.empty?
                h2 "Packages not found in gems.rubyforge.org"
                dl do
                    $not_found.each do |pid|
                        dt pid.to_s
                        dd pid['DESCRIPTION'].value
                    end
                end
            end
        end
    end
    File.open($0.gsub(/\.rb$/, '.html'), 'w') do |out|
        out.print mab.to_s
    end
end