Mercurial > treepkg
comparison contrib/sawmill/bin/generate-rss.py @ 492:93d66243bce7
sawmill: Added RSS feed generator.
author | Sascha Teichmann <teichmann@intevation.de> |
---|---|
date | Thu, 30 Sep 2010 22:51:45 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
491:f1be9657c1d2 | 492:93d66243bce7 |
---|---|
1 #!/usr/bin/env python | |
2 # -*- coding: UTF-8 -*- | |
3 # | |
4 # Copyright (C) 2010 by Intevation GmbH | |
5 # Authors: | |
6 # Sascha L. Teichmann <sascha.teichmann@intevation.de> | |
7 # | |
8 # This program is free software under the GPL (>=v2) | |
9 # Read the file COPYING coming with the software for details. | |
10 | |
11 import sys | |
12 import os | |
13 import re | |
14 import traceback | |
15 | |
16 from datetime import datetime | |
17 | |
18 from lxml import etree | |
19 | |
20 import PyRSS2Gen as RSS2 | |
21 | |
22 BASE_URL = "http://saegewerk2.wald.intevation.org/buildlogs" | |
23 LINK_URL = "%s/details.py?treepkg=%%s" % BASE_URL | |
24 ITEM_URL = "%s/details.py?treepkg=%%s#%%s" % BASE_URL | |
25 | |
26 TITLE = "Saegewerk - %s" | |
27 DESCRIPTION = "Build errors of '%s'" | |
28 MESSAGE = "%s: error building %s rev. %s" | |
29 TTL = 7 | |
30 | |
31 START = re.compile( | |
32 r"start:\s+(\d{4})-(\d{2})-(\d{2})\s+(\d{2}):(\d{2}):(\d{2})") | |
33 STATUS = re.compile(r"status:\s+(.+)") | |
34 | |
35 INVALID_LABEL = re.compile(r"[^a-zA-Z0-9_]") | |
36 | |
37 def make_valid_label(l): | |
38 return INVALID_LABEL.sub("_", l) | |
39 | |
40 def to_datetime(m): | |
41 m = map(int, m.groups()) | |
42 return datetime( | |
43 year=m[0], month=m[1], day=m[2], | |
44 hour=m[3], minute=m[4], second=m[5]) | |
45 | |
46 def usage(msg, code=1): | |
47 print >> sys.stderr, "%s <treepkgs directory>" % sys.argv[0] | |
48 print >> sys.stderr, "%s" % msg | |
49 sys.exit(code) | |
50 | |
51 def main(): | |
52 if len(sys.argv) < 2: | |
53 usage("missing treepkgs directory") | |
54 | |
55 treepkgs_dir = sys.argv[1] | |
56 if not os.path.isdir(treepkgs_dir): | |
57 usage("'%s' is not a directory" % treepkgs_dir) | |
58 | |
59 for treepkg in os.listdir(treepkgs_dir): | |
60 treepkg_dir = os.path.join(treepkgs_dir, treepkg) | |
61 if not os.path.isdir(treepkg_dir): continue | |
62 treepkg_xml = os.path.join(treepkg_dir, "treepkg.xml") | |
63 if not os.path.isfile(treepkg_xml): continue | |
64 try: | |
65 f = open(treepkg_xml, "rb") | |
66 try: treepkg_dom = etree.parse(f) | |
67 finally: f.close() | |
68 except: | |
69 traceback.print_exc(file=sys.stderr) | |
70 continue | |
71 description = ''.join( | |
72 treepkg_dom.xpath('/treepkg/description/text()')) | |
73 | |
74 tracks_dir = os.path.join(treepkg_dir, "tracks") | |
75 if not os.path.isdir(tracks_dir): continue | |
76 | |
77 items = [] | |
78 | |
79 for track in os.listdir(tracks_dir): | |
80 track_dir = os.path.join(tracks_dir, track, "pkg") | |
81 if not os.path.isdir(track_dir): continue | |
82 | |
83 track_label = make_valid_label(track) | |
84 | |
85 for revision in os.listdir(track_dir): | |
86 revision_dir = os.path.join(track_dir, revision) | |
87 if not os.path.isdir(revision_dir): continue | |
88 status_file = os.path.join(revision_dir, "status") | |
89 if not os.path.isfile(status_file): continue | |
90 start, status = None, None | |
91 try: | |
92 f = open(status_file, "r") | |
93 try: | |
94 while True: | |
95 line = f.readline() | |
96 if not line: break | |
97 m = STATUS.match(line) | |
98 if m: status = m.group(1); continue | |
99 m = START.match(line) | |
100 if m: start = to_datetime(m) | |
101 finally: | |
102 f.close() | |
103 except: | |
104 traceback.print_exc(file=sys.stderr) | |
105 continue | |
106 if status != "error" or not start: continue | |
107 | |
108 label = ''.join([ | |
109 track_label, | |
110 make_valid_label(revision), | |
111 start.strftime("%Y%m%d%H%M%S")]) | |
112 | |
113 link = ITEM_URL % (treepkg, label) | |
114 msg = MESSAGE % (description, track, revision) | |
115 item = RSS2.RSSItem( | |
116 title = msg, | |
117 link = link, | |
118 description = msg, | |
119 guid = RSS2.Guid(link, isPermaLink=0), | |
120 pubDate = start | |
121 ) | |
122 items.append(item) | |
123 | |
124 items.sort(key=lambda x: x.pubDate) | |
125 | |
126 rss = RSS2.RSS2( | |
127 title = TITLE % description, | |
128 link = LINK_URL % treepkg, | |
129 description = DESCRIPTION % description, | |
130 pubDate = datetime.utcnow(), | |
131 ttl = TTL, | |
132 items = items) | |
133 | |
134 pid, idx = os.getpid(), 0 | |
135 while True: | |
136 tmp_f = os.path.join( | |
137 treepkg_dir, "rss.xml.tmp%d-%d" % (pid, idx)) | |
138 if not os.path.exists(tmp_f): break | |
139 idx += 1 | |
140 | |
141 try: | |
142 f = open(tmp_f, "wb") | |
143 try: rss.write_xml(f, encoding="UTF-8") | |
144 finally: f.close() | |
145 | |
146 rss_xml = os.path.join(treepkg_dir, "rss.xml") | |
147 | |
148 os.rename(tmp_f, rss_xml) | |
149 except: | |
150 traceback.print_exc(file=sys.stderr) | |
151 if os.path.exists(tmp_f): | |
152 try: os.remove(tmp_f) | |
153 except: pass | |
154 | |
155 if __name__ == '__main__': | |
156 main() |