Package bodhi :: Module util
[hide private]
[frames] | no frames]

Source Code for Module bodhi.util

  1  # $Id: util.py,v 1.2 2006/12/31 09:10:14 lmacken Exp $ 
  2  # This program is free software; you can redistribute it and/or modify 
  3  # it under the terms of the GNU General Public License as published by 
  4  # the Free Software Foundation; version 2 of the License. 
  5  # 
  6  # This program is distributed in the hope that it will be useful, 
  7  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
  8  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  9  # GNU Library General Public License for more details. 
 10  # 
 11  # You should have received a copy of the GNU General Public License 
 12  # along with this program; if not, write to the Free Software 
 13  # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
 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  #from koji import fixEncoding 
 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  ## TODO: give createrepo a competent API 
 37  sys.path.append('/usr/share/createrepo') 
 38  import genpkgmetadata 
 39   
 40  log = logging.getLogger(__name__) 
 41   
 42  ## Display a given message as a heading 
 43  header = lambda x: "%s\n     %s\n%s\n" % ('=' * 80, x, '=' * 80) 
 44   
45 -def rpm_fileheader(pkgpath):
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
61 -def excluded_arch(rpmheader, arch):
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
71 -def sha1sum(file):
72 import sha 73 fd = open(file) 74 hash = sha.new(fd.read()) 75 fd.close() 76 return hash.hexdigest()
77
78 -def get_nvr(nvr):
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
83 -def mkmetadatadir(dir):
84 """ 85 Generate package metadata for a given directory; if it doesn't exist, then 86 create it. 87 """ 88 log.debug("mkmetadatadir(%s)" % dir) 89 if not isdir(dir): 90 os.makedirs(dir) 91 cache = config.get('createrepo_cache_dir') 92 genpkgmetadata.main(['--cachedir', str(cache), '-q', str(dir)])
93
94 -def synchronized(lock):
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
106 -def fixEncoding(value, fallback='iso8859-15'):
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 # value is already unicode, so just convert it 117 # to a utf8-encoded str 118 return value.encode('utf8') 119 else: 120 # value is a str, but may be encoded in utf8 or some 121 # other non-ascii charset. Try to verify it's utf8, and if not, 122 # decode it using the fallback encoding. 123 try: 124 return value.decode('utf8').encode('utf8') 125 except UnicodeDecodeError, err: 126 return value.decode(fallback).encode('utf8')
127
128 -def displayname(identity):
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
137 -def authorized_user(update, identity):
138 return update.submitter == identity.current.user_name or \ 139 'releng' in identity.current.groups or \ 140 displayname(identity) == update.submitter
141 147
148 -def make_type_icon(update):
149 return Element('img', src=url('/static/images/%s.png' % update.type), 150 title=update.type)
151
152 -def make_karma_icon(update):
153 if update.karma < 0: 154 karma = -1 155 elif update.karma > 0: 156 karma = 1 157 else: 158 karma = 0 159 return Element('img', src=url('/static/images/%d.png' % karma))
160
161 -def get_age(date):
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
169 -def get_age_in_days(date):
170 if date: 171 age = datetime.utcnow() - date 172 return age.days 173 else: 174 return 0
175
176 -def flash_log(msg):
177 """ Flash and log a given message """ 178 flash(msg) 179 log.debug(msg)
180
181 -def get_release_names():
182 from bodhi.tools.init import releases 183 return map(lambda release: release['long_name'], releases)
184
185 -def get_release_tuples():
186 from bodhi.tools.init import releases 187 names = [] 188 for release in releases: 189 names.append(release['name']) 190 names.append(release['long_name']) 191 return names
192
193 -def get_repo_tag(repo):
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
205 -def get_pkg_people(pkgName, collectionName, collectionVersion):
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 # Owner is allowed to commit and gets notified of pushes 233 # This will always be 0 as we'll retrieve at most one value for 234 # Package-Collection-Version 235 notify = [pkg['packageListings'][0]['owneruser']] 236 allowed = [notify[0]] 237 238 # Find other people in the acl 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