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

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

  ViewVC Help
Powered by ViewVC 1.1.20