/[qa]/trunk/pts/www/bin/sources_to_xml.py
ViewVC logotype

Contents of /trunk/pts/www/bin/sources_to_xml.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1427 - (show annotations) (download) (as text)
Sun Sep 24 09:13:54 2006 UTC (6 years, 7 months ago) by hertzog
File MIME type: text/x-python
File size: 8262 byte(s)
Support X-Vcs and Vcs-*.
1 #!/usr/bin/python
2 # -*- coding: utf8 -*-
3
4 # vim: expandtab
5
6 # Copyright 2002 Raphaƫl Hertzog
7 # This file is distributed under the terms of the General Public License
8 # version 2 or (at your option) any later version.
9
10 import os.path, rfc822, email, email.Utils, sys, string, re, cPickle
11 from xml.dom import implementation, ext
12
13 from config import dir, odir
14 from common import vcs_table
15
16 # address_from_string takes an address in RFC822 format
17 # and turns it into a tuple of the form (real name, email).
18 # The difference with email.Utils.parseaddr and rfc822.parseaddr
19 # is that this routine allows unquoted comma's to appear in the real name
20 # (in violation of RFC822). This is a hack to allow a Maintainer field to
21 # be like 'Maintainer: John H. Robinson, IV <jaqque@debian.org>'. [PvR]
22 def address_from_string(content):
23 hacked_content = string.replace(content, ",", "WEWANTNOCOMMAS")
24 (name, mail) = email.Utils.parseaddr(hacked_content)
25 return (string.replace(name,"WEWANTNOCOMMAS",","),string.replace(mail,"WEWANTNOCOMMAS",","))
26
27 # addresses_from_string takes a string with addresses in RFC822 format
28 # and changes it into a list of tuples of the form (real name, email).
29 # Just as address_from_string, it tries to be forgiving about unquoted
30 # commas in addresses. [PvR]
31 def addresses_from_string(content):
32 pattern = re.compile("([^>]),")
33 hacked_content = pattern.sub("\\1WEWANTNOCOMMAS", content)
34 msg = email.message_from_string("Header: " + hacked_content)
35 hacked_list = email.Utils.getaddresses(msg.get_all("Header", []))
36 list = map(lambda p:
37 map(lambda s:string.replace(s,"WEWANTNOCOMMAS",","), p),
38 hacked_list)
39 return list
40
41 def add_maintainer_info(child, name, mail, doc):
42 text = doc.createTextNode(unicode(name,'UTF8','replace')) # Take care of non-ascii
43 item_elt = doc.createElement("name")
44 item_elt.appendChild(text)
45 child.appendChild(item_elt)
46 text = doc.createTextNode(mail)
47 item_elt = doc.createElement("email")
48 item_elt.appendChild(text)
49 child.appendChild(item_elt)
50
51 def update_sources_info(m, dist):
52 """Update the XML information with the given Message (Package entry)"""
53 global odir, old_done, new_done, new_dist_map
54 package = m["Package"]
55 hash = package[0]
56 if package[0:3] == "lib":
57 hash = package[0:4]
58 # Check if the work has already been done
59 key = "%s_%s_%s" % (m["Package"], m["Version"], dist)
60 new_done[key] = 1
61 new_dist_map["%s_%s" % (m["Package"], dist)] = 1
62 if old_done.has_key(key) and os.path.isfile("%s/%s/%s/%s.xml" % (odir, hash, package, dist)):
63 return
64 # Make sure the directory exists
65 if not os.path.isdir(odir + "/" + hash + "/" + package):
66 if not os.path.isdir(odir + "/" + hash):
67 os.mkdir(odir + "/" + hash)
68 os.mkdir(odir + "/" + hash + "/" + package)
69 # Create the XML DOM object
70 doc = implementation.createDocument(None, None, None)
71 root = doc.createElement("source")
72 doc.appendChild(root)
73 root.setAttribute("release", dist)
74 if re.search("-\d+\.\d+(\.\d+)?$", m["version"]):
75 root.setAttribute("nmu", "yes")
76 for tag in m.keys():
77 child = doc.createElement(tag)
78 root.appendChild(child)
79 if tag == "binary" or tag[0:5] == "build":
80 for item in re.split(", ?", m[tag]):
81 # Take care of non-ascii, prevents troubles...
82 text = doc.createTextNode(unicode(item,'ISO-8859-1','replace'))
83 item_elt = doc.createElement("item")
84 item_elt.appendChild(text)
85 child.appendChild(item_elt)
86 elif tag == "maintainer":
87 (name, mail) = address_from_string(m[tag])
88 add_maintainer_info(child, name, mail, doc)
89 elif tag == "uploaders":
90 uploaders = addresses_from_string(m[tag])
91 for item in uploaders:
92 item_elt = doc.createElement("item")
93 (name,mail) = item
94 add_maintainer_info(item_elt, name, mail, doc)
95 child.appendChild(item_elt)
96 elif tag == "files":
97 for line in string.split(m[tag], "\n"):
98 item_elt = doc.createElement("item")
99 child.appendChild(item_elt)
100 line = line.strip()
101 fields = ["md5sum", "size", "filename"]
102 values = string.split(line)
103 for i in range(len(fields)):
104 new_elt = doc.createElement(fields[i])
105 text = doc.createTextNode(values[i])
106 new_elt.appendChild(text)
107 item_elt.appendChild(new_elt)
108 else:
109 text = doc.createTextNode(m[tag])
110 child.appendChild(text)
111 # now compute derived information and store it in the xml
112 # add 'parsed' version of VCS info
113 if tag[:6] == 'x-vcs-' or tag[:4] == 'vcs':
114 if tag[0] == 'x':
115 prefix_len = 6
116 else:
117 prefix_len = 4
118 # e.g. tag[prefix_len:] would be 'svn' for 'x-vcs-svn'/'vcs-svn'
119 if vcs_table.has_key(tag[prefix_len:]):
120 repos_elt = doc.createElement('repository')
121 root.appendChild(repos_elt)
122 kind_elt = doc.createElement('kind')
123 repos_elt.appendChild(kind_elt)
124 (name, vcsurl) = vcs_table[tag[prefix_len:]]
125 kind_elt.setAttribute('href', vcsurl)
126 name_txt = doc.createTextNode(name)
127 kind_elt.appendChild(name_txt)
128 url_elt = doc.createElement('url')
129 repos_elt.appendChild(url_elt)
130 url_txt = doc.createTextNode(m[tag])
131 url_elt.appendChild(url_txt)
132 # Print the DOM object to a file
133 try:
134 f = open("%s/%s/%s/%s.xml" % (odir, hash, package, dist), "w")
135 ext.PrettyPrint(doc, f, "UTF-8")
136 f.close()
137 except:
138 sys.stderr.write("Output problem for " + m["package"] + "\n");
139
140 def treat_sources_file(f, dist):
141 """Scan the given Sources file and treat each Package entry"""
142 while 1:
143 try:
144 m = rfc822.Message(f)
145 if len(m) == 0: #eof
146 break
147 update_sources_info(m, dist)
148 except EOFError:
149 break
150
151 # Load the list of sources generated the last time
152 old_done = {}
153 new_done = {}
154 new_dist_map = {}
155 if os.path.exists(odir + "/sources_done"):
156 f = open(odir + "/sources_done", "r")
157 old_done = cPickle.load(f)
158 f.close()
159
160 for comp in ["main", "contrib", "non-free"]:
161 for dist in ["oldstable", "stable", "testing", "unstable", "experimental"]:
162 f = open(dir + "/Sources_%s_%s" % (dist, comp), "r")
163 treat_sources_file(f, dist)
164 f.close()
165 # s-p-u and t-p-u
166 f = open(dir + "/Sources-spu_%s" % comp, "r")
167 treat_sources_file(f, "s-p-u")
168 f.close()
169 f = open(dir + "/Sources-tpu_%s" % comp, "r")
170 treat_sources_file(f, "t-p-u")
171 f.close()
172 # security
173 f = open(dir + "/Sources-security-oldstable_%s" % comp, "r")
174 treat_sources_file(f, "oldstable-security")
175 f.close()
176 f = open(dir + "/Sources-security-stable_%s" % comp, "r")
177 treat_sources_file(f, "stable-security")
178 f.close()
179 #f = open(dir + "/Sources-security-testing_%s" % comp, "r")
180 #treat_sources_file(f, "testing-security")
181 #f.close()
182 f = open(dir + "/Sources-volatile_%s" % comp, "r")
183 treat_sources_file(f, "volatile")
184 f.close()
185
186 # Store the list of sources generated
187 f = open(odir + "/sources_done", "w")
188 cPickle.dump(new_done, f, 0)
189 f.close()
190
191 # Scan the old package/distribution that existed and check if they
192 # still exist ... if they don't, remove the associated xml file.
193 for key in old_done.keys():
194 (p, v, d) = key.split("_", 2)
195 if not new_dist_map.has_key("%s_%s" % (p, d)):
196 hash = p[0]
197 if p[0:3] == "lib":
198 hash = p[0:4]
199 filename = "%s/%s/%s/%s.xml" % (odir, hash, p, d)
200 filenamerebuild = "%s/%s/%s/force-rebuild" % (odir, hash, p)
201 if os.path.exists(filename):
202 os.unlink(filename)
203 f = open(filenamerebuild, "w")
204 f.close()
205
206 # We're done

Properties

Name Value
svn:eol-style native
svn:executable *
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.5