/[gentoo]/xml/htdocs/proj/en/devrel/undertakers/scripts/retire.py.txt
Gentoo

Contents of /xml/htdocs/proj/en/devrel/undertakers/scripts/retire.py.txt

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.12 - (show annotations) (download)
Sat Oct 27 15:03:31 2012 UTC (22 months ago) by hwoarang
Branch: MAIN
CVS Tags: HEAD
Changes since 1.11: +12 -1 lines
File MIME type: text/plain
Skip pr/events and userrel/soc/archives paths thanks to marienz

1 #!/usr/bin/env python
2 # vim: set ai et sw=4 ts=4 sts=4:
3 """Script to remove retired devs from metadata.xml."""
4
5 __author__ = """marien zwart marienz@gentoo.org"""
6
7 import difflib
8 import inspect
9 import os
10 import sys
11 import StringIO
12 from xml.etree import cElementTree as etree
13
14
15 # Directories --project skips (relative to the path passed as last argument).
16 PROJECT_SKIP_DIRS = frozenset([
17 'pr/events',
18 'userrel/soc/archives',
19 ])
20
21
22 def getretired(userinfo_path):
23 """Generator yielding names of retired devs from userinfo.xml."""
24 userinfo = etree.parse(userinfo_path)
25
26 for entry in userinfo.findall('user'):
27 status = entry.find('status')
28 if status is not None:
29 if status.text in ('Retired', 'retired'):
30 devname = entry.get('username')
31 yield devname.lower()
32
33
34 def herds(userinfo_path, herds_path):
35 """ Show retired developers and which herds they are in
36 """
37 try:
38 retired = set(getretired(userinfo_path))
39 except (SyntaxError, EnvironmentError), e:
40 print >>sys.stderr, "Couldn't parse userinfo.xml (%s)" % (e,)
41 return 1
42
43 try:
44 herds = etree.parse(herds_path)
45 except (SyntaxError, EnvironmentError), e:
46 print >>sys.stderr, "Couldn't parse herds.xml (%s)" % (e,)
47 return 1
48
49 for herd in herds.findall('herd'):
50 herdname = herd.find('name').text
51 for entry in herd.findall('maintainer'):
52 email = entry.find('email')
53 username = email.text.replace('@gentoo.org','').lower()
54 if username in retired:
55 print '%s:\t%s' % (herdname, username)
56 return 0
57
58 def project(userinfo_path, path):
59 """ Remove retired developers from project pages
60 userinfo is path to proj/en/devrel/roll-call/userinfo.xml
61 files is a list of project xmls
62 """
63 try:
64 retired = set(getretired(userinfo_path))
65 except (SyntaxError, EnvironmentError), e:
66 print >>sys.stderr, "Couldn't parse userinfo.xml (%s)" % (e,)
67 return 1
68
69 for root, dirs, files in os.walk(path, topdown=True):
70 if root[len(path):].lstrip('/') in PROJECT_SKIP_DIRS:
71 del dirs[:]
72 continue
73 for file in files:
74 if file.endswith('.xml'):
75 fpath = root + '/' + file
76 try:
77 project = etree.parse(fpath)
78 except (SyntaxError, EnvironmentError):
79 #print "Skipping %s, probably not a project xml" % file
80 continue
81 for entry in project.findall('dev'):
82 if entry.text.lower() in retired:
83 print fpath + ':\t' + entry.text
84 for elem in ['extraproject', 'task']:
85 for entry in project.findall(elem):
86 if 'lead' in entry.attrib and entry.attrib['lead'].lower() in retired:
87 print fpath + ':\t' + entry.attrib['lead']
88
89 def _metadata(path, modifier):
90 """Mutate metadata.xml and produce a diff.
91 metadata.xml with the retired dev removed.
92
93 path is the path to the root of the portage tree.
94
95 modifier is a function called as modifier(metadata, herds).
96 It should return whether it mutated metadata.
97 """
98 if not os.path.isdir(path):
99 print >>sys.stderr, '%r is not a directory' % path
100 return 1
101 # Make sure path has a / at the end
102 if not path.endswith('/'):
103 path += '/'
104 for root, dirs, files in os.walk(path):
105 if 'metadata.xml' not in files:
106 continue
107 metadata_path = os.path.join(root, 'metadata.xml')
108 try:
109 metadata = etree.parse(metadata_path)
110 except (SyntaxError, EnvironmentError), e:
111 print >>sys.stderr, "Couldn't parse %s (%s) .. skipping" % (root[len(path) + 1:], e)
112 continue
113
114 shortpath = root[len(path):]
115
116 # NOTE(antarus): herd is an optional field. <herd>no-herd</herd> is
117 # not allowed.
118 herds = {}
119 for herd in metadata.findall('herd'):
120 herdname = herd.text
121 if herdname is None:
122 print >>sys.stderr, "Bogus herd entry in %s" % (shortpath,)
123 continue
124 herdname = herdname.strip()
125 if herdname in herds:
126 print >>sys.stderr, 'Duplicate herd in %s' % (shortpath,)
127 continue
128 herds[herdname] = herd
129 # NOTE(antarus): no-herd is deprecated, but we still want to complain
130 # if it is listed along with other herds because that is a bug.
131 if 'no-herd' in herds and len(herds) != 1:
132 print >>sys.stderr, 'no-herd and actual herds in %s' % (shortpath,)
133
134 if modifier(metadata, herds):
135 # we don't want the full path in the diff
136 if not root.startswith(path):
137 print 'wtf (not %r.startswith(%r/))' % (root, path)
138 return 1
139 newfile = StringIO.StringIO()
140 # etree does not write the <?xml ...> header and DOCTYPE
141 newfile.write('<?xml version="1.0" encoding="UTF-8"?>\n')
142 newfile.write(
143 '<!DOCTYPE pkgmetadata SYSTEM '
144 '"http://www.gentoo.org/dtd/metadata.dtd">\n')
145 metadata.write(newfile)
146 # etree omits the final newline, add that to make the diff nicer
147 newfile.write('\n')
148 newfile.seek(0)
149 # (skips the <?xml ...> and DOCTYPE lines, hopefully)
150 for line in difflib.unified_diff(
151 open(metadata_path).readlines(),
152 list(newfile),
153 '%s.orig' % shortpath,
154 shortpath):
155 print line,
156 print
157 return 0
158
159 def metadata_dev(devname, path):
160 email = '%s@gentoo.org' % devname
161 def modifier(metadata, herds):
162 changed = False
163 for entry in metadata.findall('maintainer'):
164 for mailentry in entry.findall('email'):
165 if mailentry.text.strip() == email:
166 if not herds:
167 # remove name
168 for name in entry.findall('name'):
169 entry.remove(name)
170 mailentry.text = 'maintainer-needed@gentoo.org'
171 else:
172 metadata.getroot().remove(entry)
173 changed = True
174 return changed
175
176 return _metadata(path, modifier)
177
178
179 def metadata_herd(herdname, path):
180 def modifier(metadata, herds):
181 if herdname not in herds:
182 return False
183 herd = herds[herdname]
184 # Just remove this herd element.
185 metadata.getroot().remove(herd)
186 return True
187
188 return _metadata(path, modifier)
189
190
191 def usage():
192 print 'Usage: %s subcommand opts' % sys.argv[0]
193 print 'Subcommands:'
194 print '--herds /path/to/userinfo.xml /path/to/herds.xml : check herds.xml for retired developers'
195 print '--metadata-dev devname /path/to/tree :'
196 print '--metadata-herd herdname /path/to/tree :'
197 print '\toutputs a diff between the current metadata.xml and'
198 print '\tmetadata.xml with the retired dev or herd removed.'
199 print '--project /path/to/userinfo.xml /path/to/proj :'
200 print '\tcheck the project pages for retired developers'
201
202
203 def main(args):
204 subcommands = dict(('--' + f.__name__.replace('_', '-'), f)
205 for f in [herds, metadata_dev, metadata_herd, project])
206 if len(args) == 1:
207 usage()
208 return 1
209 try:
210 subcommand = subcommands[args[1]]
211 except KeyError:
212 print '%s is not a valid subcommand (%s)' % (
213 args[1], ', '.join(subcommands))
214 usage()
215 return 1
216
217 argcount = len(inspect.getargspec(subcommand)[0])
218 if len(args) - 2 != argcount:
219 print 'Expected %s arguments, got %s' % (argcount, len(args) - 2)
220 usage()
221 return 1
222
223 return subcommand(*args[2:])
224
225 if __name__ == '__main__':
226 sys.exit(main(sys.argv))

  ViewVC Help
Powered by ViewVC 1.1.20