summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael G. Martins <rafael@rafaelmartins.eng.br>2010-11-26 21:34:05 -0200
committerRafael G. Martins <rafael@rafaelmartins.eng.br>2010-11-26 21:34:05 -0200
commit0a389bb9374c136deb816c6f8163325f84e843af (patch)
treeb5f91325dfe838595630ad9c6e0ae34bbf28a664
parentinitial commit (diff)
downloadcheckbump-0a389bb9374c136deb816c6f8163325f84e843af.tar.gz
checkbump-0a389bb9374c136deb816c6f8163325f84e843af.tar.bz2
checkbump-0a389bb9374c136deb816c6f8163325f84e843af.zip
major rewritten. works fairly.
-rw-r--r--checkbump.py187
1 files changed, 102 insertions, 85 deletions
diff --git a/checkbump.py b/checkbump.py
index 89008bc..dce2c18 100644
--- a/checkbump.py
+++ b/checkbump.py
@@ -4,21 +4,77 @@
from ConfigParser import ConfigParser
from contextlib import closing
from datetime import datetime
+from jinja2 import Template
+from logging import getLogger, Formatter, StreamHandler, INFO
from subprocess import Popen, PIPE
-from urllib2 import urlopen
+from time import strftime
+from urllib import urlencode
+from urllib2 import urlopen, URLError
from portage import portagetree
from portage.versions import pkgsplit, vercmp
import os, sys
+# logging formatters
+LOG_FORMATTER = "[%(asctime)s] %(name)s.%(levelname)s: %(message)s"
+LOG_DATEFORMAT = "%Y-%m-%d %H:%M:%S %Z"
-class PackageException(Exception):
- pass
+HTML_TEMPLATE = Template('''\
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <title>Version bump checker - {{ config_file }}</title>
+ <meta http-equiv="content-type" content="text/html;charset=utf-8" />
+ </head>
+ <body>
+ <h1>Version bump checker</h1>
+ <h2>{{ config_file }}</h2>
+ <table border="1">
+ <tr>
+ <th>Package</th>
+ <th>Bugs</th>
+ <th>Our version</th>
+ <th>Upstream version</th>
+ <th>Up-to-date?</th>
+ </tr>
+ {%- for package in packages %}
+ <tr>
+ <td><a href="{{ package.url }}">{{ package.atom }}</a></td>
+ <td><a href="http://bugs.gentoo.org/buglist.cgi?quicksearch={{ package.atom }}">Bugs</a></td>
+ {%- if package.error %}
+ <td colspan="3">Failed!</td>
+ {%- else %}
+ <td>{{ package.gentoo_version }}</td>
+ <td>{{ package.upstream_version }}</td>
+ <td bgcolor="{{ package.up2date and 'green">yes' or 'red">no' }}</td>
+ {%- endif %}
+ </tr>
+ {%- else %}
+ <tr>
+ <td colspan="4">No packages available!</td>
+ </tr>
+ {%- endfor %}
+ </table>
+ <hr />
+ <p>Last update: {{ last_update }}</p>
+ </body>
+</html>
+''')
+
+# setup logging
+logger = getLogger('checkbump')
+logger.setLevel(INFO)
+_log_handler = StreamHandler(sys.stderr)
+_log_handler.setFormatter(Formatter(LOG_FORMATTER, LOG_DATEFORMAT))
+logger.addHandler(_log_handler)
class Package(object):
+ error = False
+
def __init__(self, atom, url):
self.atom = atom
self.url = url
@@ -26,29 +82,33 @@ class Package(object):
try:
with closing(urlopen(url)) as fp:
self._content = fp.read()
- except:
- raise PackageException('Fetch failed: %r' % url)
+ except URLError, err:
+ self.error = True
+ logger.error('fetch failed %r - %r' % (atom, err.reason))
@property
def gentoo_version(self):
- portage = portagetree()
- versions = portage.dep_match(self.atom)
- if len(versions) == 0:
- raise PackageException('Package not found: %r' % self.atom)
- last_atom = versions[-1]
- cp, pv, rev = pkgsplit(last_atom)
- return pv
+ if not self.error:
+ portage = portagetree()
+ versions = portage.dep_match(self.atom)
+ if len(versions) == 0:
+ raise Exception('package not found %r' % self.atom)
+ last_atom = versions[-1]
+ cp, pv, rev = pkgsplit(last_atom)
+ return pv
@property
def up2date(self):
- return vercmp(self.gentoo_version, self.upstream_version) == 0
+ if not self.error:
+ return vercmp(self.gentoo_version, self.upstream_version) == 0
def run_command(self, command):
- p = Popen(command, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
- stdout, stderr = p.communicate(self._content)
- if p.returncode != os.EX_OK:
- raise PackageException('Command failed: %r' % command)
- self.upstream_version += stdout.strip()
+ if not self.error:
+ p = Popen(command, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
+ stdout, stderr = p.communicate(self._content)
+ if p.returncode != os.EX_OK:
+ raise Exception('command failed: %r' % command)
+ self.upstream_version += stdout.strip()
class PackageList(list):
@@ -57,12 +117,12 @@ class PackageList(list):
self._parser = ConfigParser()
parsed_file = self._parser.read(ini_file)
if not len(parsed_file) == 1:
- raise PackageException('Failed to load config: %r' % ini_file)
+ raise Exception('failed to load config %r' % ini_file)
list.__init__(self)
atoms = self._parser.sections()
atoms.sort()
for atom in atoms:
- print >> sys.stderr, 'Fetching: %s' % atom
+ logger.info('fetching %r' % atom)
url = None
commands = None
for name, value in self._parser.items(atom):
@@ -71,79 +131,36 @@ class PackageList(list):
elif name == 'command':
commands = value
if url is None or commands is None:
- raise PackageException('Invalid url/command: %r' % atom)
+ raise Exception('invalid url/command %r' % atom)
package = Package(atom, url)
for command in commands.split('\n'):
package.run_command(command.strip())
self.append(package)
-class HTMLReport(object):
-
- def __init__(self, ini_file):
- self._ini_file = ini_file
- self._pkg_list = PackageList(self._ini_file)
-
- def _header(self):
- return """\
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
- <head>
- <title>Version bump checker</title>
- <meta http-equiv="content-type" content="text/html;charset=utf-8" />
- </head>
- <body>
- <h1>Version bump checker</h1>
- <table border="1">
- <tr>
- <th>Package</th>
- <th>Our version</th>
- <th>Upstream version</th>
- <th>Up-to-date?</th>
- </tr>
+def generate_html(config_file, pkg_list):
+ logger.info('generating html')
+ return HTML_TEMPLATE.render(
+ config_file = config_file,
+ packages = pkg_list,
+ last_update = strftime(LOG_DATEFORMAT)
+ )
-<!-- init packages -->
-"""
+def main(argv):
+ logger.info('starting ...')
+ if len(argv) != 1:
+ logger.error('invalid number of arguments.')
+ return 1
+ pkg_list = PackageList(argv[0])
+ config_file = os.path.splitext(os.path.basename(argv[0]))[0]
+ sys.stdout.write(generate_html(config_file, pkg_list))
- def _footer(self):
- return """\
-
-<!-- end packages -->
- </table>
- <hr />
- <p>
- Last update: %s UTC
- </p>
- </body>
-</html>
-""" % datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')
-
- def _package(self, pkg):
- return """\
-<tr>
- <td>%(atom)s</td>
- <td>%(gentoo_version)s</td>
- <td>%(upstream_version)s</td>
- <td bgcolor="%(color)s">%(up2date)s</td>
-</tr>
-""" % {
- 'atom': pkg.atom,
- 'gentoo_version': pkg.gentoo_version,
- 'upstream_version': pkg.upstream_version,
- 'color': pkg.up2date and 'green' or 'red',
- 'up2date': pkg.up2date and 'Yes' or 'No',
- }
-
- def __str__(self):
- tmp = self._header()
- for pkg in self._pkg_list:
- tmp += self._package(pkg)
- tmp += self._footer()
- return tmp
-
-
if __name__ == '__main__':
- print HTMLReport('sci-electronics.ini')
+ try:
+ sys.exit(main(sys.argv[1:]))
+ except KeyboardInterrupt:
+ logger.info('interrupted.')
+ except Exception, err:
+ logger.error(str(err))