Skip to content

Commit

Permalink
Merge branch 'gcode-poller' of git://github.com/durin42/buildbot
Browse files Browse the repository at this point in the history
* 'gcode-poller' of git://github.com/durin42/buildbot:
  googlecode_atom: convenience method for easier configuration
  googlecode_atom: various high-level style fixes
  • Loading branch information
Dustin J. Mitchell committed Sep 6, 2010
2 parents 838f9dd + 9e07a0b commit c7b3530
Showing 1 changed file with 34 additions and 28 deletions.
62 changes: 34 additions & 28 deletions master/contrib/googlecode_atom.py
Expand Up @@ -7,9 +7,9 @@
# Use this ChangeSource for projects hosted on http://code.google.com/
#
# This ChangeSource uses the project's commit Atom feed. Depending upon the
# frequency of commits, you can tune the polling interval for the feed
# frequency of commits, you can tune the polling interval for the feed
# (default is 1 hour)
#
#
# Parameters:
# feedurl (MANDATORY): The Atom feed URL of the GoogleCode repo
# pollinterval (OPTIONAL): Polling frequency for the feed (in seconds)
Expand All @@ -19,12 +19,12 @@
# from googlecode_atom import GoogleCodeAtomPoller
# poller = GoogleCodeAtomPoller(
# feedurl="http://code.google.com/feeds/p/ostinato/hgchanges/basic",
# pollinterval=10800)
# pollinterval=10800)
# c['change_source'] = [ poller ]
#

from time import strptime
from calendar import timegm
from calendar import timegm
from xml.dom import minidom, Node

from twisted.python import log, failure
Expand All @@ -34,8 +34,14 @@

from buildbot.changes import base, changes

def googleCodePollerForProject(project, vcs, pollinterval=3600):
return GoogleCodeAtomPoller(
'http://code.google.com/feeds/p/%s/%schanges/basic' % (project, vcs),
pollinterval=pollinterval)


class GoogleCodeAtomPoller(base.ChangeSource):
"""This source will poll a GoogleCode Atom feed for changes and
"""This source will poll a GoogleCode Atom feed for changes and
submit them to the change master. Works for both Svn and Hg repos.
TODO: branch processing
"""
Expand All @@ -45,7 +51,7 @@ class GoogleCodeAtomPoller(base.ChangeSource):
loop = None
volatile = ['loop']
working = False

def __init__(self, feedurl, pollinterval=3600):
"""
@type feedurl: string
Expand All @@ -56,13 +62,13 @@ def __init__(self, feedurl, pollinterval=3600):
@param pollinterval: The time (in seconds) between queries for
changes (default is 1 hour)
"""

self.feedurl = feedurl
self.branch = None
self.pollinterval = pollinterval
self.lastChange = None
self.loop = LoopingCall(self.poll)

def startService(self):
log.msg("GoogleCodeAtomPoller starting")
base.ChangeSource.startService(self)
Expand All @@ -72,11 +78,11 @@ def stopService(self):
log.msg("GoogleCodeAtomPoller stoppping")
self.loop.stop()
return base.ChangeSource.stopService(self)

def describe(self):
return "Getting changes from the GoogleCode repo changes feed %s" % \
self._make_url()
return ("Getting changes from the GoogleCode repo changes feed %s" %
self._make_url())

def poll(self):
if self.working:
log.msg("Not polling because last poll is still working")
Expand All @@ -101,11 +107,11 @@ def _finished_failure(self, res):

def _make_url(self):
return "%s" % (self.feedurl)

def _get_changes(self):
url = self._make_url()
log.msg("GoogleCodeAtomPoller polling %s" % url)

return getPage(url, timeout=self.pollinterval)

def _parse_changes(self, query):
Expand All @@ -117,37 +123,37 @@ def _parse_changes(self, query):
d = {}

# revision is the last part of the 'id' url
d["revision"] = i.getElementsByTagName("id")[0] \
.firstChild.data.split('/')[-1]
d["revision"] = i.getElementsByTagName(
"id")[0].firstChild.data.split('/')[-1]
if d["revision"] == self.lastChange:
break # no more new changes

d["when"] = timegm(strptime(
i.getElementsByTagName("updated")[0].firstChild.data,
"%Y-%m-%dT%H:%M:%SZ"))
d["author"] = i.getElementsByTagName("author")[0] \
.getElementsByTagName("name")[0].firstChild.data
i.getElementsByTagName("updated")[0].firstChild.data,
"%Y-%m-%dT%H:%M:%SZ"))
d["author"] = i.getElementsByTagName(
"author")[0].getElementsByTagName("name")[0].firstChild.data
# files and commit msg are separated by 2 consecutive <br/>
content = i.getElementsByTagName("content")[0].firstChild.data \
.split("<br/>\n <br/>")
content = i.getElementsByTagName(
"content")[0].firstChild.data.split("<br/>\n <br/>")
# Remove the action keywords from the file list
fl = content[0].replace( \
u' \xa0\xa0\xa0\xa0Add\xa0\xa0\xa0\xa0', '').replace( \
u' \xa0\xa0\xa0\xa0Delete\xa0\xa0\xa0\xa0', '').replace( \
fl = content[0].replace(
u' \xa0\xa0\xa0\xa0Add\xa0\xa0\xa0\xa0', '').replace(
u' \xa0\xa0\xa0\xa0Delete\xa0\xa0\xa0\xa0', '').replace(
u' \xa0\xa0\xa0\xa0Modify\xa0\xa0\xa0\xa0', '')
# Get individual files and remove the 'header'
d["files"] = fl.encode("ascii", "replace").split("<br/>")[1:]
d["files"] = [f.strip() for f in d["files"]]
try:
d["comments"] = content[1].encode("ascii", "replace")
except:
d["comments"] = "No commit message provided"
d["comments"] = "No commit message provided"

changes.append(d)

changes.reverse() # want them in chronological order
return changes

def _process_changes(self, query):
change_list = self._parse_changes(query)

Expand All @@ -156,7 +162,7 @@ def _process_changes(self, query):
for change in change_list:
c = changes.Change(revision = change["revision"],
who = change["author"],
files = change["files"],
files = change["files"],
comments = change["comments"],
when = change["when"],
branch = self.branch)
Expand Down

0 comments on commit c7b3530

Please sign in to comment.