/[gentoo]/src/packages/gentoo.py
Gentoo

Diff of /src/packages/gentoo.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 1.4 Revision 1.13
1#!/usr/bin/python -OO 1#!/usr/bin/python -O
2"""These functions mainly take ebuild info (grabbed from the database and 2"""These functions mainly take ebuild info (grabbed from the database and
3 convert it to HTML. See the "main" function at the bottom.""" 3 convert it to HTML. See the "main" function at the bottom."""
4 4
5__revision__ = "$Revision: 1.4 $" 5__revision__ = "$Revision: 1.13 $"
6# $Source: /var/cvsroot/gentoo/src/packages/gentoo.py,v $ 6# $Source: /var/cvsroot/gentoo/src/packages/gentoo.py,v $
7 7
8import config 8import config
9import os 9import os
10import time 10import time
11import string
11import sys 12import sys
12import ebuilddb 13import ebuilddb
13import bugs 14import bugs
14import changelogs 15import changelogs
15from cgi import escape 16from cgi import escape
16from urllib import quote 17from urllib import quote
17 18
18# import portage, but temporarily redirect stderr 19endversion={"pre":-2,"p":0,"alpha":-4,"beta":-3,"rc":-1}
19if 'portage' not in dir(): 20# as there's no reliable way to set {}.keys() order
20 null = open('/dev/null', 'w') 21# netversion_keys will be used instead of endversion.keys
21 tmp = sys.stderr 22# to have fixed search order, so that "pre" is checked
22 sys.stderr = null 23# before "p"
23 sys.path = ["/usr/lib/portage/pym"]+sys.path 24endversion_keys = ["pre", "p", "alpha", "beta", "rc"]
24 import portage
25 sys.stderr = tmp
26 sys.path = sys.path[1:]
27 25
28tree = portage.portdbapi('/usr/portage')
29
30def is_masked(ebuild):
31 """Return true if ebuild is masked"""
32
33 return (not tree.visible(['%(category)s/%(name)s-%(version)s' % ebuild]))
34
35def is_new(db, ebuild): 26def is_new(db, ebuild):
36 """Check for newness. An ebuild is considered new if it is the 27 """Check for newness."""
37 only ebuild with that category/name in ebuild and it has no prevarch""" 28
38
39 c = db.cursor() 29 c = db.cursor()
40 query = ('SELECT prevarch FROM ebuild WHERE category="%s" AND name="%s"' 30 query = ('SELECT new FROM package WHERE category="%s" AND name="%s"'
41 % (ebuild['category'], ebuild['name'])) 31 % (ebuild['category'], ebuild['name']))
42 c.execute(query) 32 c.execute(query)
43 results = c.fetchall() 33 results = c.fetchall()
44 if len(results) == 1 and results[0][0] is None: 34 if len(results) == 1 and results[0][0]:
45 return 1 35 return 1
46 return 0 36 return 0
47 37
48def changelog_to_html(changelog): 38def changelog_to_html(changelog):
49 """HTML-ize a changelog entry""" 39 """HTML-ize a changelog entry"""
56 html = changelogs.bugs_to_html(html) 46 html = changelogs.bugs_to_html(html)
57 return html 47 return html
58 48
59def homepage_to_html(homepage): 49def homepage_to_html(homepage):
60 """convert HOMEPAGE entry to HTML""" 50 """convert HOMEPAGE entry to HTML"""
61 if not homepage.strip(): 51 if not homepage.strip():
62 return "?" 52 return "?"
63 homepage = homepage.replace('|',' ') 53 homepage = homepage.replace('|',' ')
64 pieces = homepage.split() 54 pieces = homepage.split()
65 count = len(pieces) 55 count = len(pieces)
66 if count == 1: 56 if count == 1:
67 return ('<a class="homepage" href="%s">' 57 return ('<a class="homepage" href="%s">'
68 'Homepage</a>' % pieces[0]) 58 'Homepage</a>' % pieces[0])
69 59
70 html = ['[<a href="%s">%s</a>]' % (page, index + 1) for index, 60 html = ['[<a href="%s">%s</a>]' % (page, index + 1) for index,
71 page in enumerate(pieces)] 61 page in enumerate(pieces)]
72 return " ".join(['<span class="homepage">Homepages'] + html + 62 return " ".join(['<span class="homepage">Homepages'] + html +
73 ['</span>']) 63 ['</span>'])
74 64
75def license_to_html(license): 65def license_to_html(license):
76 """Create link to license[s]""" 66 """Create link to license[s]"""
77 if not license.strip(): return "?" 67 if not license.strip(): return "?"
78 license = license.replace('|',' ') 68 license = license.replace('|',' ')
69 license = license.replace('(', '')
70 license = license.replace(')', '')
79 pieces = license.split() 71 pieces = license.split()
80 html = ['<a href="http://www.gentoo.org/cgi-bin/viewcvs.cgi/*checkout*/' 72 html = ['<a href="http://www.gentoo.org/cgi-bin/viewcvs.cgi/*checkout*/'
81 'licenses/%s">%s</a>' % (piece, piece) for piece in pieces] 73 'licenses/%s">%s</a>' % (piece, piece) for piece in pieces]
82 return '<br>\n'.join(html) 74 return '<br>\n'.join(html)
83 75
84def package_to_html(pkginfo, db): 76def package_to_html(pkginfo, db, full=False):
85 """This function needs a database (db) connection because it performs a 77 """This function needs a database (db) connection because it performs a
86 query_to_dict on the package""" 78 query_to_dict on the package"""
87 79
88 table_begin = '<table class="ebuild">' 80 table_begin = '<table class="ebuild">'
89 name = '<tr><td class="fields">%s</td></tr>' % pkginfo['name'] 81 name = '<tr><td class="fields">%s</td></tr>' % pkginfo['name']
82 if full:
83 image = ('<img class="pkgimg"alt="" src="%s/%s/%s.jpg" align="right">' %
84 (config.ICONS, pkginfo['category'], pkginfo['name'])
85 )
86 else:
87 image = ''
90 description = ('<tr><td class="item">' 88 description = ('<tr><td class="item">'
91 '<img align="right" alt="" src="%s/%s.png">'
92 '<b>Description: </b>%s</td></tr>' % (config.ICONS, 89 '%s<b>Description: </b>%s</td></tr>'
93 pkginfo['category'], escape(pkginfo['description']))) 90 % (image, escape(pkginfo['description']))
91 )
94 ebuilds = get_recent_releases(pkginfo, db) 92 ebuilds = get_recent_releases(pkginfo, db)
95 releases = '<tr><td>%s</td></tr>' % archs_to_html(ebuilds, 'Releases') 93 releases = '<tr><td>%s</td></tr>' % archs_to_html(ebuilds, 'Releases')
96 #bug_string = ('<br><h3>Related bugs:</h3>\n%s' 94 #bug_string = ('<br><h3>Related bugs:</h3>\n%s'
97 # % bugs_to_html(pkginfo['name'])) 95 # % bugs_to_html(pkginfo['name']))
98 general = '<tr><td>%s</td></tr>' % general_info_to_html(pkginfo) 96 general = '<tr><td>%s</td></tr>' % general_info_to_html(pkginfo)
97 #similar = '<tr><td>%s</td></tr>' % create_similar_pkgs_link(pkginfo)
99 table_end = '</table>' 98 table_end = '</table>'
100 rows = '\n\t'.join([name, description, releases, general]) 99 rows = '\n\t'.join([name, description, releases, general])
101 return '\n\t'.join([table_begin, rows, table_end]) 100 return '\n\t'.join([table_begin, rows, table_end])
102 101
103def archs_to_html(ebuilds, heading = None): 102def archs_to_html(ebuilds, heading = None):
104 """Create table for availability on each architecture""" 103 """Create table for availability on each architecture"""
105 heading = heading or '&nbsp;' 104 heading = heading or '&nbsp;'
106 table_begin = '<table class="releases">' 105 table_begin = '<table class="releases">'
107 header_row = ''.join(['<tr><td><b>%s</b></td>' % heading] + 106 header_row = ''.join(['<tr><td><b>%s</b></td>' % heading] +
108 ['<th class="arch">%s</th>' % i for i in config.ARCHLIST] + 107 ['<th class="arch">%s</th>' % i.replace('-',' ') for i in config.ARCHLIST] +
109 ['</tr>'] 108 ['</tr>']
110 ) 109 )
111 rows = [] 110 rows = []
111 ebuilds.sort(cmp_ebuilds)
112 ebuilds.reverse()
112 for ebuild in ebuilds: 113 for ebuild in ebuilds:
113 masked = is_masked(ebuild)
114 archs = ebuild['arch'].split() 114 archs = ebuild['arch'].split()
115 row_start = ('<tr>\n\t<th class="releases"><a href="%sebuilds/?%s-%s"' 115 row_start = ('<tr>\n\t<th class="releases"><a href="%sebuilds/?%s-%s"'
116 ' title="%s">%s</a></th>\n' % (config.FEHOME, 116 ' title="%s">%s</a></th>\n' % (config.FEHOME,
117 ebuild['name'], ebuild['version'], ebuild['time'], 117 ebuild['name'], ebuild['version'], ebuild['time'],
118 ebuild['version'])) 118 ebuild['version']))
119 row_data = [] 119 row_data = []
120 for arch in config.ARCHLIST: 120 for arch in config.ARCHLIST:
121 if arch in archs: 121 if arch in archs:
122 arch_string = '+' 122 arch_string = '+'
123 elif '~%s' % arch in archs: 123 elif '~%s' % arch in archs:
124 arch_string = '~' 124 arch_string = '~'
125 else: 125 else:
126 arch_string = '-' 126 arch_string = '-'
127 if arch_string != '-' and masked: 127 if arch_string != '-' and ebuild['masked']:
128 arch_string = 'M' + arch_string 128 arch_string = 'M' + arch_string
129 row_data.append('\t<td class="archcell" arch="%s">%s</td>' 129 row_data.append('\t<td class="archcell" arch="%s">%s</td>'
130 % (arch_string, arch_string)) 130 % (arch_string, arch_string))
131 row_end = '</tr>' 131 row_end = '</tr>'
132 rows.append('\n\t'.join([row_start] + row_data + [row_end])) 132 rows.append('\n\t'.join([row_start] + row_data + [row_end]))
133 table_end = '</table>' 133 table_end = '</table>'
134 return '\n\t'.join([table_begin] + [header_row] + rows + [table_end]) 134 return '\n\t'.join([table_begin] + [header_row] + rows + [table_end])
135 135
136def ebuild_to_html(ebinfo, new=0, show_bugs=0): 136def ebuild_to_html(ebinfo, new=0, show_bugs=0, full = False):
137 """Convert ebuild (dict) to html, if new, print out a "this is new" notice 137 """Convert ebuild (dict) to html, if new, print out a "this is new" notice
138 if show_bugs, show bugs for this particular ebuild (requires access to 138 if show_bugs, show bugs for this particular ebuild (requires access to
139 bugzilla""" 139 bugzilla"""
140 if new: 140 if new:
141 new_string = """ &nbsp;&nbsp;<span class="new">new!</span> """ 141 new_string = """ &nbsp;&nbsp;<span class="new">new!</span> """
142 else: 142 else:
143 new_string = "" 143 new_string = ""
144 144
145 table_begin = '<table class="ebuild">' 145 table_begin = '<table class="ebuild">'
146 name_and_date = ('<tr><td class="fields">' 146 name_and_date = ('<tr><td class="fields">'
147 '<a href="%spackages/?category=%s;name=%s">%s</a> %s%s<br>' 147 '<a href="%spackages/?category=%s;name=%s">%s</a> %s%s<br>'
148 '<span class="time">%s</span>' 148 '<span class="time">%s</span>'
149 '</td></tr>' % (config.FEHOME, quote(ebinfo['category']), 149 '</td></tr>' % (config.FEHOME, quote(ebinfo['category']),
150 quote(ebinfo['name']), 150 quote(ebinfo['name']),
151 ebinfo['name'], 151 ebinfo['name'],
152 ebinfo['version'], 152 ebinfo['version'],
153 new_string, 153 new_string,
154 ebinfo['time'].localtime().strftime("%c %Z"))) 154 ebinfo['time'].localtime().strftime("%c %Z")))
155
156 if full:
157 image = ('<img class="pkgimg" alt="" src="%s/%s/%s.jpg" align="right">' %
158 (config.ICONS, ebinfo['category'], ebinfo['name'])
155 159 )
160 else:
161 image = ''
156 desc_and_changes = ('<tr><td class="item" valign="top">' 162 desc_and_changes = ('<tr><td class="item" valign="top">'
157 '<img alt="" align="right" src="%simages/%s.png">'
158 '<p><b>Description:</b> %s</p>' 163 '<p><b>Description:</b> %s %s</p>'
159 '<p><b>Changes:</b><br>' 164 '<p><b>Changes:</b><br>'
160 '%s</p></td></tr>' % ( 165 '%s</p></td></tr>' % (
161 config.FEHOME,
162 ebinfo['category'],
163 escape(ebinfo['description']), 166 escape(ebinfo['description']),
167 image,
164 changelog_to_html(ebinfo['changelog']))) 168 changelog_to_html(ebinfo['changelog'])))
165 169
166 archs = '<tr><td>%s</td></tr>' % archs_to_html([ebinfo]) 170 archs = '<tr><td>%s</td></tr>' % archs_to_html([ebinfo])
167 general = '<tr><td>%s</td></tr>' % general_info_to_html(ebinfo) 171 general = '<tr><td>%s</td></tr>' % general_info_to_html(ebinfo)
168 table_end = '</table>' 172 table_end = '</table>'
169 173
170 if 1 == 1:
171 bug_string = '' 174 bug_string = ''
172 else: 175 if show_bugs:
176 bug_string = bugs_to_html(ebinfo['name'])
177 if bug_string:
173 bug_string = '<br><h3>Related bugs:</h3>%s' \ 178 bug_string = '<br><h3 class="bugs">Related bugs:</h3>%s' \
174 % bugs_to_html(ebinfo['name']) 179 % bug_string
175 180
176 return '\n\t'.join([table_begin, 181 return '\n\t'.join([table_begin,
177 name_and_date, 182 name_and_date,
178 desc_and_changes, 183 desc_and_changes,
179 archs, 184 archs,
180 general, 185 general,
181 table_end, 186 table_end,
182 bug_string]) 187 bug_string])
183 188
184def general_info_to_html(pkg): 189def general_info_to_html(pkg):
185 """This actually will (should) take either a package or ebuild dict 190 """This actually will (should) take either a package or ebuild dict
186 as an argument""" 191 as an argument"""
187 192
193 import forums
194
188 changelogurl = ('http://www.gentoo.org/cgi-bin/viewcvs.cgi/*checkout*/' 195 changelogurl = ('http://www.gentoo.org/cgi-bin/viewcvs.cgi/*checkout*/'
189 '%s/%s/ChangeLog' % (pkg['category'],pkg['name'])) 196 '%s/%s/ChangeLog' % (pkg['category'],pkg['name']))
190 cat_header = '<th class="category">Category</th>' 197 cat_header = '<th class="category">Category</th>'
191 license_header = '<th class="license">License</th>' 198 license_header = '<th class="license">License</th>'
192 category = ('<td class="category">' 199 category = ('<td class="category">'
193 '<a href="%spackages/?category=%s">%s</a></td>' % (config.FEHOME, 200 '<a href="%spackages/?category=%s">%s</a></td>' % (config.FEHOME,
194 pkg['category'], pkg['category'])) 201 pkg['category'], pkg['category']))
195 homepage = ('<td class="homepage" rowspan="2">%s</td>' 202 homepage = ('<td class="homepage" rowspan="2">%s</td>'
196 % homepage_to_html(pkg['homepage'])) 203 % homepage_to_html(pkg['homepage']))
197 license = ('<td class="license">%s</td>' 204 license = ('<td class="license">%s</td>'
198 % license_to_html(pkg['license'])) 205 % license_to_html(pkg['license']))
199 changelog = ('<td class="changelog" rowspan="2">' 206 changelog = ('<td class="changelog" rowspan="2">'
200 '<a href="%s">ChangeLog</a><td>' % changelogurl) 207 '<a href="%s">ChangeLog</a></td>' % changelogurl)
201 208 similar = ('<td class="similar" rowspan="2">'
209 '%s</td>' % create_similar_pkgs_link(pkg))
210 related_bugs = ('<td class="related_bugs" rowspan="2">'
211 '%s</td>' % create_related_bugs_link(pkg))
212 forums = ('<td class="forums" rowspan="2">'
213 '%s</td>' % forums.create_forums_link(pkg))
214
202 return '\n\t'.join(['<table class="general_info">', 215 return '\n\t'.join(['<table class="general_info">',
203 '<tr>', 216 '<tr>',
204 cat_header, 217 cat_header,
205 homepage, 218 homepage,
206 license_header, 219 license_header,
207 changelog, 220 changelog,
221 similar,
222 related_bugs,
223 forums,
208 '</tr>', 224 '</tr>',
209 '<tr>', 225 '<tr>',
210 category, 226 category,
211 license, 227 license,
212 '</tr>', 228 '</tr>',
213 '</table>']) 229 '</table>'])
214 230
231def create_similar_pkgs_link(pkg):
232 """Create a link to similar packages"""
233
234 def strip_chars(mystring):
235 newstring = ''
236 for char in mystring:
237 if char not in string.punctuation:
238 newstring = newstring + char
239 else:
240 newstring = newstring + ' '
241 return newstring
242
243 description = strip_chars(pkg['description'].lower())
244
245 words = [word for word in description.split()
246 if word and len(word)>2 and word not in config.EXCLUDED_FROM_SIMILAR]
247 words = words[:config.SIMILAR_MAX_WORDS] + [pkg['name']]
248 #query = ['[[:<:]]%s[[:>:]].*' % word for word in words]
249 query = ['[[:<:]]%s.*' % word for word in words]
250 query = '(%s){%s,}' % ('|'.join(query), config.SIMILAR_MIN_MATCHES)
251 url = '%ssearch/?sstring=%s' % (config.FEHOME, escape(query))
252 return '<a href="%s">Similar</a>' % url
253
254def create_related_bugs_link(pkg):
255 """Create a link to related bugs"""
256
257 url = ('http://bugs.gentoo.org/buglist.cgi?query_format='
258 '&amp;short_desc_type=allwords'
259 '&amp;short_desc=%s'
260 '&amp;bug_status=UNCONFIRMED'
261 '&amp;bug_status=NEW'
262 '&amp;bug_status=ASSIGNED'
263 '&amp;bug_status=REOPENED'
264 % escape(pkg['name']))
265
266 return '<a title="bugs.gentoo.org" href="%s">Bugs</a>' % url
267
215def bugs_to_html(package): 268def bugs_to_html(package):
216 """Given package name (no version #s), return html text of bugs as 269 """Given package name (no version #s), return html text of bugs as
217 reported by bugzilla""" 270 reported by bugzilla"""
218 # Right now we have an issue with the bugzilla site. New interface 271 # Right now we have an issue with the bugzilla site. New interface
219 # needs to be written, Bail out. 272 # needs to be written, Bail out.
220 return "" 273 #return ""
221 import urllib2 274 import urllib2
222 url = ('http://bugs.gentoo.org/buglist.cgi?query_format=' 275 url = ('http://bugs.gentoo.org/buglist.cgi?query_format='
223 '&short_desc_type=allwords&short_desc=%s' 276 '&amp;short_desc_type=allwords'
224 '&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED' 277 '&amp;short_desc=%s'
278 '&amp;bug_status=UNCONFIRMED'
279 '&amp;bug_status=NEW'
280 '&amp;bug_status=ASSIGNED'
225 '&bug_status=REOPENED' 281 '&amp;bug_status=REOPENED'
282 '&amp;ctype=csv'
226 '&ctype=csv' % package) 283 % package)
227 fp = urllib2.urlopen(url) 284 fp = urllib2.urlopen(url)
228 factory = bugs.BugFactory() 285 factory = bugs.BugFactory()
229 package_bugs = factory.fromCSV(fp) 286 package_bugs = factory.fromCSV(fp)
230 if package_bugs: 287 if package_bugs:
231 writer = bugs.HTMLWriter(package_bugs, 'bugs.gentoo.org') 288 writer = bugs.HTMLWriter(package_bugs, 'bugs.gentoo.org')
232 return str(writer) 289 return str(writer)
233 else: 290 else:
234 return "None" 291 return ""
235 292
236def get_most_recent(db, max=config.MAXPERPAGE, arch="", branch=""): 293def get_most_recent(db, max=config.MAXPERPAGE, arch="", branch="", new = False):
237 c = db.cursor() 294 c = db.cursor()
238 extra = '' 295 extra = ''
239 if arch: 296 if arch:
240 stable_extra = ('ebuild.arch REGEXP "^%s| %s" ' 297 stable_extra = ('ebuild.arch REGEXP "^%s[[:>:]]|[[:blank:]]%s[[:>:]]" '
241 ' AND ebuild.prevarch NOT REGEXP"^%s| %s"'
242 % (arch,arch,arch,arch)) 298 % (arch,arch))
243 testing_extra = ('ebuild.arch REGEXP "^~%s| ~%s" ' 299 testing_extra = ('ebuild.arch REGEXP "[~]%s[[:>:]]" ' % arch)
244 ' AND ebuild.prevarch NOT REGEXP "^~%s| ~%s"'
245 % (arch,arch,arch,arch))
246 if branch == 'stable': 300 if branch == 'stable':
247 extra = ' AND (%s) ' % stable_extra 301 extra = ' AND (%s) ' % stable_extra
248 elif branch == 'testing': 302 elif branch == 'testing':
249 extra = ' AND (%s) ' % testing_extra 303 extra = ' AND (%s) ' % testing_extra
250 else: 304 else:
251 extra = ' AND ((%s) OR (%s)) ' % (stable_extra, testing_extra) 305 extra = ' AND ((%s) OR (%s)) ' % (stable_extra, testing_extra)
306
307 if new:
308 extra = ('%s AND package.new=1 ' % extra)
309
252 query = """SELECT ebuild.category,ebuild.name,version,when_found,description, 310 query = """SELECT ebuild.category,ebuild.name,version,when_found,description,
253 changelog,arch,homepage,license FROM ebuild,package WHERE ebuild.name=\ 311 changelog,arch,homepage,license,is_masked FROM ebuild,package WHERE ebuild.name=\
254 package.name AND ebuild.category=package.category %s ORDER by when_found DESC \ 312 package.name AND ebuild.category=package.category %s ORDER by when_found DESC \
255 LIMIT %s""" % (extra,max) 313 LIMIT %s""" % (extra,max)
256 c.execute(query) 314 c.execute(query)
257 results = c.fetchall() 315 results = c.fetchall()
258 return results 316 return results
259 317
318def get_most_recent_bumps(db, max=config.MAXPERPAGE):
319 """Return most recent version bumps (pkgs with no prevarch)"""
320 c = db.cursor()
321 query = ('SELECT ebuild.category, ebuild.name, version, when_found, '
322 'description, changelog, arch, homepage, license,is_masked FROM ebuild, package '
323 'WHERE ebuild.name=package.name AND ebuild.category=package.category '
324 'AND prevarch="" AND version NOT LIKE "%%-r_" AND version NOT LIKE '
325 '"%%-r__" AND NOT new ORDER by when_found '
326 'DESC LIMIT %s' % max)
327
328 c.execute(query)
329 results = c.fetchall()
330 return results
331
260def query_to_dict(d): 332def query_to_dict(d):
261 """Convert a SQL query to a dict""" 333 """Convert a SQL query to a dict"""
262 einfo = {} 334 einfo = {}
263 keys = ('category', 'name', 'version', 'time', 'description', 'changelog', 335 keys = ('category', 'name', 'version', 'time', 'description', 'changelog',
264 'arch', 'homepage', 'license') 336 'arch', 'homepage', 'license', 'masked')
265 for i in range(len(keys)): 337 for i in range(len(keys)):
266 try: 338 try:
267 einfo[keys[i]] = d[i] 339 einfo[keys[i]] = d[i]
268 except IndexError: 340 except IndexError:
269 continue 341 continue
272def get_recent_releases(pkg, db, max=config.MAX_RECENT_RELEASES): 344def get_recent_releases(pkg, db, max=config.MAX_RECENT_RELEASES):
273 """Return MAX_RECENT_RELEASES most recent releases for pkg. Returns and 345 """Return MAX_RECENT_RELEASES most recent releases for pkg. Returns and
274 ebuild-type dict""" 346 ebuild-type dict"""
275 c = db.cursor() 347 c = db.cursor()
276 query = ('SELECT category,name,version,when_found,NULL,changelog,arch ,' 348 query = ('SELECT category,name,version,when_found,NULL,changelog,arch ,'
277 'NULL,NULL FROM ebuild WHERE name="%s" AND category="%s" ORDER BY ' 349 'NULL,NULL,is_masked FROM ebuild WHERE name="%s" AND category="%s" ORDER BY '
278 'version DESC LIMIT %s' % (pkg['name'],pkg['category'],max)) 350 'version DESC LIMIT %s' % (pkg['name'],pkg['category'],max))
279 c.execute(query) 351 c.execute(query)
280 results = c.fetchall() 352 results = c.fetchall()
281 #print results 353 #print results
282 return [ query_to_dict(i) for i in results ] 354 return [ query_to_dict(i) for i in results ]
283 355
356def cmp_ebuilds(a, b):
357 """Compare two ebuilds"""
358 fields_a = pkgsplit('%s-%s' % (a['name'], a['version']))
359 fields_b = pkgsplit('%s-%s' % (b['name'], b['version']))
360 return pkgcmp(fields_a, fields_b)
361
362pkgcache={}
363
364def pkgsplit(mypkg,silent=1):
365 try:
366 if not pkgcache[mypkg]:
367 return None
368 return pkgcache[mypkg][:]
369 except KeyError:
370 pass
371 myparts=string.split(mypkg,'-')
372 if len(myparts)<2:
373 if not silent:
374 print "!!! Name error in",mypkg+": missing a version or name part."
375 pkgcache[mypkg]=None
376 return None
377 for x in myparts:
378 if len(x)==0:
379 if not silent:
380 print "!!! Name error in",mypkg+": empty \"-\" part."
381 pkgcache[mypkg]=None
382 return None
383 #verify rev
384 revok=0
385 myrev=myparts[-1]
386 if len(myrev) and myrev[0]=="r":
387 try:
388 int(myrev[1:])
389 revok=1
390 except SystemExit, e:
391 raise
392 except:
393 pass
394 if revok:
395 if ververify(myparts[-2]):
396 if len(myparts)==2:
397 pkgcache[mypkg]=None
398 return None
399 else:
400 for x in myparts[:-2]:
401 if ververify(x):
402 pkgcache[mypkg]=None
403 return None
404 #names can't have versiony looking parts
405 myval=[string.join(myparts[:-2],"-"),myparts[-2],myparts[-1]]
406 pkgcache[mypkg]=myval
407 return myval
408 else:
409 pkgcache[mypkg]=None
410 return None
411
412 elif ververify(myparts[-1],silent=silent):
413 if len(myparts)==1:
414 if not silent:
415 print "!!! Name error in",mypkg+": missing name part."
416 pkgcache[mypkg]=None
417 return None
418 else:
419 for x in myparts[:-1]:
420 if ververify(x):
421 if not silent:
422 print "!!! Name error in",mypkg+": multiple version parts."
423 pkgcache[mypkg]=None
424 return None
425 myval=[string.join(myparts[:-1],"-"),myparts[-1],"r0"]
426 pkgcache[mypkg]=myval[:]
427 return myval
428 else:
429 pkgcache[mypkg]=None
430 return None
431
432vercache={}
433def ververify(myorigval,silent=1):
434 try:
435 return vercache[myorigval]
436 except KeyError:
437 pass
438 if len(myorigval)==0:
439 if not silent:
440 print "!!! Name error: package contains empty \"-\" part."
441 return 0
442 myval=string.split(myorigval,'.')
443 if len(myval)==0:
444 if not silent:
445 print "!!! Name error: empty version string."
446 vercache[myorigval]=0
447 return 0
448 #all but the last version must be a numeric
449 for x in myval[:-1]:
450 if not len(x):
451 if not silent:
452 print "!!! Name error in",myorigval+": two decimal points in a row"
453 vercache[myorigval]=0
454 return 0
455 try:
456 foo=int(x)
457 except SystemExit, e:
458 raise
459 except:
460 if not silent:
461 print "!!! Name error in",myorigval+": \""+x+"\" is not a valid version component."
462 vercache[myorigval]=0
463 return 0
464 if not len(myval[-1]):
465 if not silent:
466 print "!!! Name error in",myorigval+": two decimal points in a row"
467 vercache[myorigval]=0
468 return 0
469 try:
470 foo=int(myval[-1])
471 vercache[myorigval]=1
472 return 1
473 except SystemExit, e:
474 raise
475 except:
476 pass
477 #ok, our last component is not a plain number or blank, let's continue
478 if myval[-1][-1] in string.lowercase:
479 try:
480 foo=int(myval[-1][:-1])
481 vercache[myorigval]=1
482 return 1
483 # 1a, 2.0b, etc.
484 except SystemExit, e:
485 raise
486 except:
487 pass
488 #ok, maybe we have a 1_alpha or 1_beta2; let's see
489 #ep="endpart"
490 ep=string.split(myval[-1],"_")
491 if len(ep)!=2:
492 if not silent:
493 print "!!! Name error in",myorigval
494 vercache[myorigval]=0
495 return 0
496 try:
497 foo=int(ep[0][-1])
498 chk=ep[0]
499 except SystemExit, e:
500 raise
501 except:
502 # because it's ok last char is not numeric. example: foo-1.0.0a_pre1
503 chk=ep[0][:-1]
504
505 try:
506 foo=int(chk)
507 except SystemExit, e:
508 raise
509 except:
510 #this needs to be numeric or numeric+single letter,
511 #i.e. the "1" in "1_alpha" or "1a_alpha"
512 if not silent:
513 print "!!! Name error in",myorigval+": characters before _ must be numeric or numeric+single letter"
514 vercache[myorigval]=0
515 return 0
516 for mye in endversion_keys:
517 if ep[1][0:len(mye)]==mye:
518 if len(mye)==len(ep[1]):
519 #no trailing numeric; ok
520 vercache[myorigval]=1
521 return 1
522 else:
523 try:
524 foo=int(ep[1][len(mye):])
525 vercache[myorigval]=1
526 return 1
527 except SystemExit, e:
528 raise
529 except:
530 #if no endversions work, *then* we return 0
531 pass
532 if not silent:
533 print "!!! Name error in",myorigval
534 vercache[myorigval]=0
535 return 0
536
537def relparse(myver):
538 "converts last version part into three components"
539 number=0
540 suffix=0
541 endtype=0
542 endnumber=0
543
544 mynewver=string.split(myver,"_")
545 myver=mynewver[0]
546
547 #normal number or number with letter at end
548 divider=len(myver)-1
549 if myver[divider:] not in "1234567890":
550 #letter at end
551 suffix=ord(myver[divider:])
552 number=string.atof(myver[0:divider])
553 else:
554 number=string.atof(myver)
555
556 if len(mynewver)==2:
557 #an endversion
558 for x in endversion_keys:
559 elen=len(x)
560 if mynewver[1][:elen] == x:
561 endtype=endversion[x]
562 try:
563 endnumber=string.atof(mynewver[1][elen:])
564 except:
565 endnumber=0
566 break
567 return [number,suffix,endtype,endnumber]
568
569# vercmp:
570# ripped from portage.py to prevent having to import
571vcmpcache={}
572def vercmp(val1,val2):
573 if val1==val2:
574 #quick short-circuit
575 return 0
576 valkey=val1+" "+val2
577 try:
578 return vcmpcache[valkey]
579 try:
580 return -vcmpcache[val2+" "+val1]
581 except KeyError:
582 pass
583 except KeyError:
584 pass
585
586 # consider 1_p2 vc 1.1
587 # after expansion will become (1_p2,0) vc (1,1)
588 # then 1_p2 is compared with 1 before 0 is compared with 1
589 # to solve the bug we need to convert it to (1,0_p2)
590 # by splitting _prepart part and adding it back _after_expansion
591 val1_prepart = val2_prepart = ''
592 if val1.count('_'):
593 val1, val1_prepart = val1.split('_', 1)
594 if val2.count('_'):
595 val2, val2_prepart = val2.split('_', 1)
596
597 # replace '-' by '.'
598 # FIXME: Is it needed? can val1/2 contain '-'?
599 val1=string.split(val1,'-')
600 if len(val1)==2:
601 val1[0]=val1[0]+"."+val1[1]
602 val2=string.split(val2,'-')
603 if len(val2)==2:
604 val2[0]=val2[0]+"."+val2[1]
605
606 val1=string.split(val1[0],'.')
607 val2=string.split(val2[0],'.')
608
609 #add back decimal point so that .03 does not become "3" !
610 for x in range(1,len(val1)):
611 if val1[x][0] == '0' :
612 val1[x]='.' + val1[x]
613 for x in range(1,len(val2)):
614 if val2[x][0] == '0' :
615 val2[x]='.' + val2[x]
616
617 # extend version numbers
618 if len(val2)<len(val1):
619 val2.extend(["0"]*(len(val1)-len(val2)))
620 elif len(val1)<len(val2):
621 val1.extend(["0"]*(len(val2)-len(val1)))
622
623 # add back _prepart tails
624 if val1_prepart:
625 val1[-1] += '_' + val1_prepart
626 if val2_prepart:
627 val2[-1] += '_' + val2_prepart
628 #The above code will extend version numbers out so they
629 #have the same number of digits.
630 for x in range(0,len(val1)):
631 cmp1=relparse(val1[x])
632 cmp2=relparse(val2[x])
633 for y in range(0,4):
634 myret=cmp1[y]-cmp2[y]
635 if myret != 0:
636 vcmpcache[valkey]=myret
637 return myret
638 vcmpcache[valkey]=0
639 return 0
640
641# pkgcmp:
642# ripped from portage.py to prevent having to import
643def pkgcmp(pkg1,pkg2):
644 """if returnval is less than zero, then pkg2 is newer than pkg1, zero if equal and positive if older."""
645 if pkg1[0] != pkg2[0]:
646 return None
647 mycmp=vercmp(pkg1[1],pkg2[1])
648 if mycmp>0:
649 return 1
650 if mycmp<0:
651 return -1
652 r1=int(pkg1[2][1:])
653 r2=int(pkg2[2][1:])
654 if r1>r2:
655 return 1
656 if r2>r1:
657 return -1
658 return 0
659
284def ebuilds_to_rss(fp, ebuilds, simple=False, subtitle=""): 660def ebuilds_to_rss(fp, ebuilds, simple=False, subtitle=""):
285 """write out ebuild info to RSS file (fp)""" 661 """write out ebuild info to RSS file (fp)"""
662
663 # web link for RSS feed
664 if subtitle:
665 link = '%s/%s' % (config.FEHOME, subtitle.replace(' ','/',1))
666 else:
667 link = config.FEHOME
668
669 pubDate = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime())
286 fp.write("""<?xml version="1.0" encoding="iso-8859-1"?> 670 fp.write("""<?xml version="1.0" encoding="UTF-8"?>
287 <rss version="0.92"> 671 <rss version="2.0">
288 <channel> 672 <channel>
289 <title>Fresh ebuilds %s</title> 673 <title>packages.gentoo.org [ %s ]</title>
290 <link>%s</link> 674 <link>%s</link>
291 <description>Latest ebuilds from the Gentoo Linux portage tree</description> 675 <description>Latest ebuilds from the Gentoo Linux portage tree</description>
292 <![CDATA[<link rel="stylesheet" href="%s" type="text/css" title="styled" />]]>
293 <webMaster>www@gentoo.org</webMaster> 676 <webMaster>www@gentoo.org</webMaster>
677
678 <image>
679 <title>Online Package Database</title>
680 <url>%s</url>
681 <link>%s</link>
682 </image>
683
294 <managingEditor>marduk@gentoo.org</managingEditor> 684 <managingEditor>marduk@gentoo.org</managingEditor>
295 <pubDate>%s</pubDate>""" % (subtitle,config.FEHOME, config.STYLESHEET, 685 <pubDate>%s</pubDate>\n""" % (subtitle, link, config.RSS_IMAGE,
296 time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime()))) 686 config.FEHOME, pubDate))
297 687
298 for ebuild in ebuilds: 688 for ebuild in ebuilds:
299 if simple: 689 if simple:
300 description = escape(ebuild['description']) 690 description = escape(ebuild['description'])
301 else: 691 else:
302 description = '\n<![CDATA[\n%s\n]]>' % ebuild_to_html(ebuild) 692 description = ('\n'
693 '<![CDATA[\n'
694 '<link rel="stylesheet" type="text/css" href="%s"></link>\n'
695 '%s\n]]>' % (config.STYLESHEET, ebuild_to_html(ebuild, full=True))
696 )
303 697
304 fp.write("""<item> 698 fp.write("""<item>
305 <title>%s %s</title> 699 <title>%s/%s %s</title>
306 <link>%sebuilds/?%s-%s</link> 700 <link>%sebuilds/?%s-%s</link>
307 <description> 701 <description>
308 %s 702 %s
309 </description> 703 </description>
310 <pubDate>%s</pubDate> 704 <pubDate>%s</pubDate>
311 </item> 705 </item>
312 """ % (ebuild['name'], 706 """ % (ebuild['category'],
707 ebuild['name'],
313 ebuild['version'], 708 ebuild['version'],
314 config.FEHOME, 709 config.FEHOME,
315 ebuild['name'], 710 ebuild['name'],
316 ebuild['version'], 711 ebuild['version'],
317 description, 712 description,
318 ebuild['time'].gmtime().strftime("%a, %d %b %Y %H:%M:%S +0000")) 713 ebuild['time'].gmtime().strftime("%a, %d %b %Y %H:%M:%S +0000"))
319 ) 714 )
320 715
321 fp.write("</channel>\n</rss>\n") 716 fp.write("\n\
322 717 <textInput>\n\
323if __name__ == '__main__': 718 <title>Search the Online Package Database</title>\n\
719 <link>%s/search/</link>\n\
720 <description>emerge -Ss</description>\n\
721 <name>sstring</name>\n\
722 </textInput>\n\
723 </channel>\n\
724 </rss>\n" % config.FEHOME)
725
726def main(argv=None):
727 if argv is None:
728 argv = sys.argv
324 try: 729 try:
325 if sys.argv[1] == '-g': 730 if argv[1] == '-g':
326 ebuilddb.main() 731 ebuilddb.main()
327 except IndexError: 732 except IndexError:
328 pass 733 pass
329 734
330 db = ebuilddb.db_connect() 735 db = ebuilddb.db_connect()
331 branches = ('', 'stable', 'testing') 736 branches = ('', 'stable', 'testing')
332 for arch in [''] + config.ARCHLIST: 737 for arch in [''] + config.ARCHLIST:
333 for branch in branches: 738 for branch in branches:
334 fullpath = os.path.join(config.LOCALHOME, "archs", arch, branch, 739 fullpath = os.path.join(config.LOCALHOME, "archs", arch, branch,
335 config.INDEX) 740 config.INDEX)
336 index = open(fullpath,'w') 741 index = open(fullpath,'w')
337 if arch: 742
338 sarch = arch
339 else:
340 sarch = 'all'
341 if branch:
342 sbranch = branch
343 else:
344 sbranch = 'all'
345
346 index.write("""<table border="0" cellpadding="0" cellspacing="5" 743 index.write("""<table border="0" cellpadding="0" cellspacing="5"
347 width="100%">\n""") 744 width="100%">\n""")
348 index.write("""<tr><td valign="top">\n""") 745 index.write("""<tr><td valign="top">\n""")
349 index.write('<!--#include file="archnav.html" -->\n\n</td></tr>\n' 746 index.write('<!--#include file="archnav.html" -->\n\n</td></tr>\n'
350 '<tr><td>') 747 '<tr><td>')
351 results = get_most_recent(db, arch=arch, branch=branch) 748 results = get_most_recent(db, arch=arch, branch=branch)
352 ebuilds = [ query_to_dict(i) for i in results ] 749 ebuilds = [ query_to_dict(i) for i in results ]
353 for ebuild in ebuilds: 750 for ebuild in ebuilds:
354 new = is_new(db, ebuild) 751 new = is_new(db, ebuild)
355 pkgfilename = "%s/%s-%s.html" % ( 752 pkgfilename = "%s/%s-%s.html" % (
356 config.EBUILD_FILES,ebuild['name'],ebuild['version']) 753 config.EBUILD_FILES,ebuild['name'],ebuild['version'])
357 ebuild_html = ebuild_to_html(ebuild, new) 754 ebuild_html = ebuild_to_html(ebuild, new, show_bugs = False)
358 if arch == '' and branch == '': 755 if arch == '' and branch == '':
359 pkgfile = open(pkgfilename,'w') 756 pkgfile = open(pkgfilename,'w')
360 pkgfile.write(ebuild_html) 757 pkgfile.write(ebuild_html)
361 pkgfile.close() 758 pkgfile.close()
362 ebuildfilename = "%s/%s/%s/%s-%s.ebuild" \ 759 ebuildfilename = "%s/%s/%s/%s-%s.ebuild" \
363 % (ebuilddb.config.PORTAGE_DIR, 760 % (ebuilddb.config.PORTAGE_DIR,
364 ebuild['category'],ebuild['name'],ebuild['name'], 761 ebuild['category'],ebuild['name'],ebuild['name'],
365 ebuild['version']) 762 ebuild['version'])
366 os.system('touch -r %s %s || touch -d "today -1 year" %s' 763 os.system('touch -r %s %s || touch -d "today -1 year" %s'
367 % (ebuildfilename,pkgfilename,pkgfilename)) 764 % (ebuildfilename,pkgfilename,pkgfilename))
368 765
369 try: 766 try:
370 index.write('%s\n\n' % (ebuild_html)) 767 index.write('%s\n\n' % (ebuild_html))
371 except IOError: 768 except IOError:
372 continue 769 continue
373 index.write("""</table>\n""") 770 index.write("""</table>\n""")
374 index.close() 771 index.close()
375 772
376 subtitle = ' %s %s' % (arch, branch) 773 subtitle = ' %s %s' % (arch, branch)
377 rss = open(os.path.join(config.LOCALHOME, "archs", arch, branch, 774 rss = open(os.path.join(config.LOCALHOME, "archs", arch, branch,
378 config.RSS), 'w') 775 config.RSS), 'w')
379 ebuilds_to_rss(rss, ebuilds, simple=False, subtitle=subtitle) 776 ebuilds_to_rss(rss, ebuilds, simple=False, subtitle=subtitle)
380 rss.close() 777 rss.close()
381 778
382 rss2 = open(os.path.join(config.LOCALHOME, "archs", arch, branch, 779 rss2 = open(os.path.join(config.LOCALHOME, "archs", arch, branch,
383 config.RSS2), 'w') 780 config.RSS2), 'w')
384 ebuilds_to_rss(rss2, ebuilds, simple=True, subtitle=subtitle) 781 ebuilds_to_rss(rss2, ebuilds, simple=True, subtitle=subtitle)
385 rss.close() 782 rss.close()
783
784if __name__ == '__main__':
785 sys.exit(main())

Legend:
Removed from v.1.4  
changed lines
  Added in v.1.13

  ViewVC Help
Powered by ViewVC 1.1.20