#!/usr/bin/python from __future__ import with_statement import ConfigParser import nntplib import os import re import socket import time import urllib2 from datetime import datetime from StringIO import StringIO try: from ncpp_local import processPatch except ImportError: # I've seen this error happen multiple times at 6AM on Sundays, # coinciding with the AFS restart. Wait five minutes for the # servers to come back. time.sleep(300) from ncpp_local import processPatch STATEFILE = '/mit/ncurses/auto/state.ini' STATE = ConfigParser.ConfigParser() STATE.read(STATEFILE) state = dict(STATE.items('ncurses')) ## Patch processing subjectPattern = re.compile('(?:ANN: )?([^ ]*ncurses-\d+.\d+(?:-\d{8})?(?:.patch.gz)?)') patchPattern = re.compile(' (\S*ncurses-\d+.\d+(?:-\d{8})?.patch.gz)') vPatchPattern = re.compile('(?:ANN: )?ncurses-%s-\d{8}(?:.patch.gz)?' % state['version']) def isPatch(subject): if subjectPattern.match(subject): if vPatchPattern.match(subject): return True print "Unexpected version number in subject:\n%s\n" % subject return False def findPatchURI(body): return [line.group(0) for line in map(patchPattern.match, body) if line] ## NNTP def respOK(resp): # As per http://www.faqs.org/rfcs/rfc977.html # 2xx - Command ok return resp[0] == '2' def getSubjects(s, group, last_seen, version, **kw): last_seen = 6857 resp, count, first, last, name = s.group(group) if not respOK(resp): print "Unexpected response [%s]" % resp elif int(first) < int(last_seen) < int(last): resp, subjects = s.xhdr('subject','%i-%s' % (int(last_seen)+1,last)) if not respOK(resp): print "Unexpected response [%s]" % resp return subjects return None def processPatchArticles(s, articles): articles = filter(lambda x: isPatch(x[1]), articles) for id, subject in articles: print id, subject resp, id, msgid, body = s.body(id) if respOK(resp): with open('/mit/ncurses/cron-working/msgs/%s.msg' % id, 'w') as f: f.write('\n'.join(body)) # uris = findPatchURI(body) # if len(uris) != 1: # # Unexpected URI count, send mail. # print "Unexpected number of URIs: %s" % uris # return -1 # try: # ret = processPatch(uris[0].strip()) # if ret != 0: # return ret # except urllib2.URLError as e: # print "URLError: %s" % e.reason # print "URL was: %s" % uris[0].strip() return 0 return 0 ## High-level def doconnect(): tryCount = 0 while True: try: svr = nntplib.NNTP(state['server']) return svr except (socket.error, socket.gaierror, nntplib.NNTPError, nntplib.NNTPTemporaryError): if tryCount < 9: tryCount += 1 time.sleep(30) else: raise # Giving up def main(): svr = doconnect() subjects = getSubjects(svr, **state) if subjects: new_last = subjects[-1][0] #STATE.set('ncurses', 'last_seen', new_last) ret = processPatchArticles(svr, subjects) #STATE.set('ncurses', 'stop', ret) #with open(STATEFILE,'wb') as f: # STATE.write(f) #if state['stop'] == '0': main()