1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 """
16 Random functions that don't fit elsewhere
17 """
18
19 import os
20 import rpm
21 import sys
22 import time
23 import urllib
24 import logging
25 import traceback
26 import simplejson
27 import urllib2
28
29 from kid import Element
30
31 from os.path import isdir, exists, join, dirname, basename, isfile
32 from datetime import datetime
33 from turbogears import config, url, flash
34 from bodhi.exceptions import RPMNotFound
35
36
37 sys.path.append('/usr/share/createrepo')
38 import genpkgmetadata
39
40 log = logging.getLogger(__name__)
41
42
43 header = lambda x: "%s\n %s\n%s\n" % ('=' * 80, x, '=' * 80)
44
46 log.debug("Grabbing the rpm header of %s" % pkgpath)
47 is_oldrpm = hasattr(rpm, 'opendb')
48 try:
49 fd = os.open(pkgpath,0)
50 if is_oldrpm:
51 h = rpm.headerFromPackage(fd)[0]
52 else:
53 ts = rpm.TransactionSet()
54 h = ts.hdrFromFdno(fd)
55 del ts
56 except (OSError, TypeError):
57 raise RPMNotFound
58 os.close(fd)
59 return h
60
62 """
63 Determine if an RPM should be excluded from a given architecture, either
64 if it is explicitly marked as ExcludeArch, or if it is Exclusive to another
65 """
66 excluded = rpmheader[rpm.RPMTAG_EXCLUDEARCH]
67 exclusive = rpmheader[rpm.RPMTAG_EXCLUSIVEARCH]
68 return (excluded and arch in excluded) or \
69 (exclusive and arch not in exclusive)
70
72 import sha
73 fd = open(file)
74 hash = sha.new(fd.read())
75 fd.close()
76 return hash.hexdigest()
77
79 """ Return the [ name, version, release ] a given name-ver-rel. """
80 x = nvr.split('-')
81 return ['-'.join(x[:-2]), x[-2], x[-1]]
82
93
95 """ Synchronization decorator """
96 def wrap(f):
97 def new(*args, **kw):
98 lock.acquire()
99 try:
100 return f(*args, **kw)
101 finally:
102 lock.release()
103 return new
104 return wrap
105
107 """
108 Convert value to a 'str' object encoded as UTF-8.
109 If value is not valid UTF-8 to begin with, assume it is
110 encoded in the 'fallback' charset.
111 """
112 if not value:
113 return value
114
115 if isinstance(value, unicode):
116
117
118 return value.encode('utf8')
119 else:
120
121
122
123 try:
124 return value.decode('utf8').encode('utf8')
125 except UnicodeDecodeError, err:
126 return value.decode(fallback).encode('utf8')
127
129 """
130 Return the Full Name <email@address> of the current identity
131 """
132 return fixEncoding('%s %s' % (identity.current.user.display_name,
133 hasattr(identity.current.user, 'user') and
134 '<%s>' % identity.current.user.user['email']
135 or ''))
136
141
147
151
160
162 age = datetime.utcnow() - date
163 if age.days == 0:
164 if age.seconds < 60:
165 return "%d seconds" % age.seconds
166 return "%d minutes" % int(age.seconds / 60)
167 return "%s days" % age.days
168
170 if date:
171 age = datetime.utcnow() - date
172 return age.days
173 else:
174 return 0
175
177 """ Flash and log a given message """
178 flash(msg)
179 log.debug(msg)
180
184
192
194 """ Pull the koji tag from the given mash repo """
195 mashconfig = join(dirname(config.get('mash_conf')), basename(repo)+'.mash')
196 if isfile(mashconfig):
197 mashconfig = file(mashconfig, 'r')
198 lines = mashconfig.readlines()
199 mashconfig.close()
200 return filter(lambda x: x.startswith('tag ='), lines)[0].split()[-1]
201 else:
202 log.error("Cannot find mash configuration for %s: %s" % (repo,
203 mashconfig))
204
206 """ Pull users who can commit and are watching a package
207
208 Return two lists:
209 * The first consists of usernames allowed to commit to the package.
210 * The second are usernames watching the package for updates.
211
212 Note: The interface to the pkgdb could undergo the following changes:
213 FAS2 related:
214 * pkg['packageListings'][0]['owneruser'] =>
215 pkg['packageListings'][0]['owner']
216 * pkg['packageListings'][0]['people'][0..n]['user'] =>
217 pkg['packageListings'][0]['people'][0..n]['userid']
218
219 * We may want to create a 'push' acl specifically for bodhi instead of
220 reusing 'commit'.
221 * ['status']['translations'] may one day contain more than the 'C'
222 translation. The pkgdb will have to figure out how to deal with that
223 if so.
224 """
225 pkgPage=urllib2.urlopen(config.get('pkgdb_url') + '/packages/name/%s/%s/%s?tg_format=json' %
226 (pkgName, collectionName, collectionVersion))
227 pkg = simplejson.load(pkgPage)
228 if pkg.has_key('status') and not pkg['status']:
229 raise Exception, 'Package %s not found in PackageDB. Error: %s' % (
230 pkgName, pkg['message'])
231
232
233
234
235 notify = [pkg['packageListings'][0]['owneruser']]
236 allowed = [notify[0]]
237
238
239 for person in pkg['packageListings'][0]['people']:
240 if person['aclOrder']['watchcommits'] and \
241 person['aclOrder']['watchcommits']['status']['translations'][0]['statusname'] == 'Approved':
242 notify.append(person['user'])
243 if person['aclOrder']['commit'] and \
244 person['aclOrder']['commit']['status']['translations'][0]['statusname'] == 'Approved':
245 allowed.append(person['user'])
246
247 return (allowed, notify)
248