| 1 |
# -*- coding: utf8 -*-
|
| 2 |
# vim: expandtab
|
| 3 |
|
| 4 |
# Copyright 2002 Raphaƫl Hertzog
|
| 5 |
# Copyright 2006 Jeroen van Wolffelaar
|
| 6 |
# This file is distributed under the terms of the General Public License
|
| 7 |
# version 2 or (at your option) any later version.
|
| 8 |
|
| 9 |
import os, os.path, re, rfc822, time, email
|
| 10 |
from email import Utils, Header
|
| 11 |
|
| 12 |
from config import root
|
| 13 |
|
| 14 |
def save_msg_in_dir(msg, dir):
|
| 15 |
"""Add the message in the directory."""
|
| 16 |
if not os.path.isdir(dir):
|
| 17 |
os.makedirs(dir)
|
| 18 |
info = extract_info(msg)
|
| 19 |
|
| 20 |
nonce = 0
|
| 21 |
targetfile = "%s/%s.%d.txt" % (dir, info['timestamp'], nonce)
|
| 22 |
while os.path.isfile(targetfile):
|
| 23 |
nonce += 1
|
| 24 |
if nonce > 128: # eventually give up
|
| 25 |
raise("can't find a free slot to save message, last tried was %s"\
|
| 26 |
% targetfile)
|
| 27 |
targetfile = "%s/%s.%d.txt" % (dir, info['timestamp'], nonce)
|
| 28 |
f = open(targetfile, "w")
|
| 29 |
f.write(msg.as_string())
|
| 30 |
f.close()
|
| 31 |
os.chmod(targetfile, 0664)
|
| 32 |
|
| 33 |
re_katie_install = re.compile(r"^\S+ \S+ (\S+)")
|
| 34 |
re_distribution = re.compile(r"^Distribution:\s*(\S+)", re.M)
|
| 35 |
re_urgency = re.compile(r"^Urgency:\s*(\S+)", re.M)
|
| 36 |
|
| 37 |
def extract_info(msg):
|
| 38 |
"""Extract pseudo-header informations in a dictionnary"""
|
| 39 |
info = {}
|
| 40 |
if msg.is_multipart():
|
| 41 |
for part in msg.walk():
|
| 42 |
if part.get_content_type() == "text/plain":
|
| 43 |
body = part.get_payload(None, 1)
|
| 44 |
break
|
| 45 |
else:
|
| 46 |
body = msg.get_payload(None, 1)
|
| 47 |
lines = body.split("\n", 3)
|
| 48 |
for i in range(3):
|
| 49 |
res = re.match(r"^(\w+): (\S+)(.*)", lines[i])
|
| 50 |
if res:
|
| 51 |
field = res.group(1).lower()
|
| 52 |
info[field] = res.group(2)
|
| 53 |
if field == "subject":
|
| 54 |
info[field] = info[field] + res.group(3)
|
| 55 |
else:
|
| 56 |
break
|
| 57 |
|
| 58 |
if not info.has_key("subject"):
|
| 59 |
subject = unicode(Header.make_header(Header.decode_header(msg.get("subject"))))
|
| 60 |
if subject.split()[0] in ['Accepted', 'Installed']:
|
| 61 |
# katie install mail
|
| 62 |
version = re_katie_install.search(subject).group(1)
|
| 63 |
distribution = re_distribution.search(body)
|
| 64 |
if distribution:
|
| 65 |
distribution = " in %s" % distribution.group(1)
|
| 66 |
else:
|
| 67 |
distribution = ""
|
| 68 |
urgency = re_urgency.search(body)
|
| 69 |
if urgency:
|
| 70 |
urgency = " (%s)" % urgency.group(1)
|
| 71 |
else:
|
| 72 |
urgency = ""
|
| 73 |
subject = "Accepted %s%s%s" % (version, distribution, urgency)
|
| 74 |
info["subject"] = subject
|
| 75 |
if msg.has_key("X-PTS-Subject"):
|
| 76 |
info["subject"] = msg.get("X-PTS-Subject")
|
| 77 |
if msg.has_key("X-PTS-Url"):
|
| 78 |
info["url"] = msg.get("X-PTS-Url")
|
| 79 |
if msg.has_key("X-PTS-Package"):
|
| 80 |
info["package"] = msg.get("X-PTS-Package")
|
| 81 |
if msg.has_key("date"):
|
| 82 |
date = email.Utils.mktime_tz(email.Utils.parsedate_tz(msg.get("date")))
|
| 83 |
info["timestamp"] = time.strftime("%Y%m%dT%H%M%SZ", time.gmtime(date))
|
| 84 |
info["date"] = time.strftime("%Y-%m-%d", time.gmtime(date))
|
| 85 |
if msg.has_key("From"):
|
| 86 |
frm = msg.get("From")
|
| 87 |
if msg.has_key("X-PTS-From"): frm = msg.get("X-PTS-From")
|
| 88 |
(realname, address) = rfc822.parseaddr(frm)
|
| 89 |
if realname:
|
| 90 |
frm = realname
|
| 91 |
else:
|
| 92 |
frm = address
|
| 93 |
frm = ensure_utf8(frm)
|
| 94 |
try:
|
| 95 |
frm = unicode(Header.make_header(Header.decode_header(frm)))
|
| 96 |
except UnicodeError:
|
| 97 |
pass
|
| 98 |
info["from_name"] = frm
|
| 99 |
return info
|
| 100 |
|
| 101 |
def store_news(pkg, msg):
|
| 102 |
hash = pkg[0]
|
| 103 |
if pkg[:3] == "lib":
|
| 104 |
hash = pkg[:4]
|
| 105 |
basedir = "%s/base/%s/%s" % (root, hash, pkg)
|
| 106 |
save_msg_in_dir(msg, basedir+"/news")
|
| 107 |
# Synchronize the XML document
|
| 108 |
f = os.popen("%s/bin/update_news.py" % root, "w")
|
| 109 |
f.write(pkg+"\n")
|
| 110 |
f.close()
|
| 111 |
# Regenerate the HTML page
|
| 112 |
f = os.popen("%s/bin/generate_html.sh" % root, "w")
|
| 113 |
f.write(pkg+"\n")
|
| 114 |
f.close()
|
| 115 |
|
| 116 |
|
| 117 |
def ensure_utf8(str):
|
| 118 |
try:
|
| 119 |
str.decode("utf8")
|
| 120 |
except UnicodeError:
|
| 121 |
str = str.decode("latin1")
|
| 122 |
return str
|
| 123 |
|
| 124 |
# Version Control Systems table
|
| 125 |
# Fields:
|
| 126 |
# 'tag' is as it would appear in a vcs-XXX field, e.g. 'svn' for Vcs-Svn
|
| 127 |
# tag common name upstream URL
|
| 128 |
vcs_table = {
|
| 129 |
'arch': ('Arch', 'http://www.gnuarch.org/arch/'),
|
| 130 |
'bzr': ('Bazaar', 'http://bazaar-vcs.org/'),
|
| 131 |
'cvs': ('CVS', 'http://www.nongnu.org/cvs/'),
|
| 132 |
'darcs': ('Darcs', 'http://abridgegame.org/darcs/'),
|
| 133 |
'git': ('Git', 'http://git.or.cz/'),
|
| 134 |
'hg': ('Mercurial', 'http://www.selenic.com/mercurial/'),
|
| 135 |
'mtn': ('Monotone', 'http://venge.net/monotone/'),
|
| 136 |
'svn': ('Subversion', 'http://subversion.tigris.org/'),
|
| 137 |
}
|
| 138 |
|