5c34672ef73c4852ec381944b30f99c8b9b157fb
[packages.grml.org.git] / update.rb
1 #!/usr/bin/env ruby
2 require 'git'
3 require 'erb'
4 require 'yaml'
5 require 'net/http'
6 require 'uri'
7 require 'zlib'
8 require 'yaml'
9
10 def build_used_package_list(source_files)
11   source_files.map do |source_file|
12     File.read(source_file).split("\n").reject do |l|
13       l.strip.start_with?('#') or l.strip == ""
14     end
15   end.flatten
16 end
17
18 def parse_debian_sources(data)
19   data.split("\n").push('').inject({}) do |pkgs, l|
20     l.rstrip!
21     pkg = pkgs[:_tmp] || {}
22     if pkg[:_tmp]
23       if l[0..0] == ' '
24         pkg[:_tmp][:data] << l.strip
25       else
26         pkg[pkg[:_tmp][:hdr]] = pkg[:_tmp][:data].compact
27         pkg.delete :_tmp
28       end
29     end
30     unless pkg[:_tmp]
31       if l == '':
32         pkgs[pkg['Package'][0]] = pkg
33         pkg = nil
34       else
35         hdr, data = l.strip.split(':', 2)
36         data.strip! unless data.nil?
37         pkg[:_tmp] = {:hdr => hdr, :data => [data]}
38       end
39     end
40     if pkg.nil?
41       pkgs.delete :_tmp
42     else
43       pkgs[:_tmp] = pkg
44     end
45     pkgs
46   end
47 end
48
49 def build_package_list(packages, used, sources)
50   data = {}
51   packages.each do |pkg|
52     next if not File.exists?(File.join(pkg, 'debian'))
53     begin
54       g = Git.open(working_dir = pkg)
55       #g.pull(Git::Repo, Git::Branch) # fetch and a merge
56     rescue ArgumentError
57       g = Git.bare(working_dir = pkg)
58     end
59
60     current_head = g.gcommit('HEAD')
61     next if not current_head.parent
62
63     p = {
64       :head_is_tagged => false,
65       :used => {},
66       :name => pkg,
67       :version => nil,
68       :has_tags => false,
69       :version_in_repo => nil
70     }
71     used.each do |dist,l|
72       p[:used][dist] = l.include?(pkg)
73     end
74     if sources[pkg]
75       p[:version_in_repo] = sources[pkg]['Version'][0]
76     end
77
78     for tag in g.tags.reverse
79       p[:has_tags] = true
80       t = g.gcommit(tag.name)
81       next if not t.parent
82       #$stderr.puts "#{pkg}: Checking tag #{tag.name}: tag parent: #{t.parent.sha} HEAD: #{current_head.parent.sha}"
83       if t.parent.sha === current_head.parent.sha
84         p[:head_is_tagged] = true
85         p[:version] = tag.name
86         break
87       end
88     end
89
90     data[pkg] = p
91   end
92   data
93 end
94
95 def fetch_file(uri)
96   response = Net::HTTP.get_response(URI.parse(uri))
97   body = response.body
98   if uri.match(/\.gz$/)
99     body = Zlib::GzipReader.new(StringIO.new(body.to_s)).read
100   end
101   body
102 end
103
104 template = ERB.new <<-EOF
105 <!doctype html>
106 <head>
107   <meta charset="utf-8">
108   <title>Grml.org Package Index</title>
109   <link rel="stylesheet" href="style.css">
110 </head>
111 <body>
112   <header>
113   <h1>All Grml packages</h1>
114   <p>Last update: <%= Time.now.to_s %></p>
115   </header>
116   <div id="main">
117   <table>
118   <tr>
119   <th>Package</th><th>Git</th><th>Download</th><th>Fresh?</th><th>grml-testing</th><th>In FULL?</th>
120   </tr>
121   <% packages.keys.sort.each do |pn|
122   p = packages[pn]
123   %>
124   <tr>
125   <td><%= p[:name] %></td>
126   <td class="git"><a href="http://git.grml.org/?p=<%= p[:name] %>.git;a=summary">Git</a></td>
127   <td class="download">
128     <% if p[:has_tags] %>
129     <a href="http://deb.grml.org/pool/main/<%= p[:name][0..0] %>/<%= p[:name] %>/">Download</a>
130     <% end %>
131   </td>
132   <% if p[:head_is_tagged] %>
133   <td class="ok">Version <%= p[:version] %></td>
134   <% else %>
135   <td class="error <% if p[:used][:full] %>important<% end %>">Untagged changes</td>
136   <% end %>
137   <td><%= p[:version_in_repo] || "" %></td>
138   <td class="installed"><%= p[:used][:full] ? "Yes" : "No" %></td>
139   </tr>
140   <% end %>
141   </table>
142   </div>
143   <footer>
144   </footer>
145 </body>
146 </html>
147 EOF
148
149 used_packages = {
150   :full => build_used_package_list(['grml-live/etc/grml/fai/config/package_config/GRMLBASE', 'grml-live/etc/grml/fai/config/package_config/GRML_FULL']),
151 }
152 sources = parse_debian_sources(fetch_file('http://deb.grml.org/dists/grml-testing/main/source/Sources.gz'))
153
154 packages = build_package_list(ARGV, used_packages, sources)
155
156 File.open('index.html.new','w') do |f|
157   f.write template.result(binding)
158 end
159 File.open('packages.yaml.new','w') do |f|
160   f.write packages.to_yaml
161 end
162
163 FileUtils.mv 'index.html.new', 'index.html'
164 FileUtils.mv 'packages.yaml.new', 'packages.yaml'
165