1
2
3 """
4 bts -- manage bugs filed against ftp.debian.org
5
6 @contact: Debian FTP Master <ftpmaster@debian.org>
7 @copyright: 2009 Mike O'Connor <stew@vireo.org>
8 @copyright: 2010 Alexander Reichle-Schmehl <tolimar@debian.org>
9 @license: GNU General Public License version 2 or later
10 """
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 import logging
31 import re
32 import sys
33
34 log = logging.getLogger()
35
36 import apt_pkg
37 import debianbts as bts
38
39 from daklib import utils
40
41
43 print(
44 """
45 SYNOPSIS
46 dak bts-categorize [options]
47
48 OPTIONS
49 -s
50 --simulate
51 Don't send email, instead output the lines that would be sent to
52 control@b.d.o.
53
54 -v
55 --verbose
56 Print more informational log messages
57
58 -q
59 --quiet
60 Suppress informational messages
61
62 -h
63 --help
64 Print this documentation.
65 """
66 )
67
68
69 arguments = [
70 ("s", "simulate", "BtsCategorize::Options::Simulate"),
71 ("v", "verbose", "BtsCategorize::Options::Verbose"),
72 ("q", "quiet", "BtsCategorize::Options::Quiet"),
73 ("h", "help", "BtsCategorize::Options::Help"),
74 ("o", "option", "", "ArbItem"),
75 ]
76
77
79 """
80 classify bugs using usertags based on the bug subject lines
81
82 >>> BugClassifier.rm_re.match( "RM: asdf" ) != None
83 True
84 >>> BugClassifier.rm_re.match( "[dak] Packages.diff/Index broken" ) != None
85 False
86 >>> BugClassifier.dak_re.match( "[dak] Packages.diff/Index broken" ) != None
87 True
88 """
89
90 rm_re = re.compile("^RM")
91 dak_re = re.compile(r"^\[dak\]")
92 arch_re = re.compile(r"^\[Architectures\]")
93 override_re = re.compile("^override")
94
95 classifiers = {
96 rm_re: "remove",
97 dak_re: "dak",
98 arch_re: "archs",
99 override_re: "override",
100 }
101
103 """
104 Returns a list of open bugs which have not yet been classified
105 by one of our usertags.
106 """
107
108 tagged_bugs = bts.get_usertag("ftp.debian.org@packages.debian.org")
109 tagged_bugs_ftp = []
110 for tags in tagged_bugs.keys():
111 tagged_bugs_ftp += tagged_bugs[tags]
112
113 return [
114 bug
115 for bug in bts.get_status(bts.get_bugs(package="ftp.debian.org"))
116 if bug.pending == "pending" and bug.bug_num not in tagged_bugs_ftp
117 ]
118
120 """
121 if any of our classifiers match, return a newline terminated
122 command to set an appropriate usertag, otherwise return an
123 empty string
124 """
125 retval = ""
126
127 for classifier in self.classifiers.keys():
128 if classifier.match(bug.subject):
129 retval = "usertag %s %s\n" % (bug.bug_num, self.classifiers[classifier])
130 break
131
132 if retval:
133 log.info(retval)
134 else:
135 log.debug("Unmatched: [%s] %s" % (bug.bug_num, bug.subject))
136
137 return retval
138
139 - def email_text(self):
140 controls = ""
141
142 bc = BugClassifier()
143 try:
144 for bug in bc.unclassified_bugs():
145 controls += bc.classify_bug(bug)
146
147 return controls
148 except:
149 log.error(
150 "couldn't retrieve bugs from soap interface: %s" % sys.exc_info()[0]
151 )
152 return None
153
154
156 global Cnf
157
158 Subst = {
159 "__COMMANDS__": commands,
160 "__DAK_ADDRESS__": Cnf["Dinstall::MyAdminAddress"],
161 }
162
163 bts_mail_message = utils.TemplateSubst(
164 Subst, Cnf["Dir::Templates"] + "/bts-categorize"
165 )
166
167 if simulate:
168 print(bts_mail_message)
169 else:
170 utils.send_mail(bts_mail_message)
171
172
174 """
175 for now, we just dump a list of commands that could be sent for
176 control@b.d.o
177 """
178 global Cnf
179 Cnf = utils.get_conf()
180
181 for arg in arguments:
182 opt = "BtsCategorize::Options::%s" % arg[1]
183 if opt not in Cnf:
184 Cnf[opt] = ""
185
186 apt_pkg.parse_commandline(Cnf, arguments, sys.argv)
187 Options = Cnf.subtree("BtsCategorize::Options")
188
189 if Options["Help"]:
190 usage()
191 sys.exit(0)
192
193 if Options["Quiet"]:
194 level = logging.ERROR
195
196 elif Options["Verbose"]:
197 level = logging.DEBUG
198
199 else:
200 level = logging.INFO
201
202 logging.basicConfig(
203 level=level, format="%(asctime)s %(levelname)s %(message)s", stream=sys.stderr
204 )
205
206 body = BugClassifier().email_text()
207
208 if body:
209 send_email(body, Options["Simulate"])
210
211 else:
212 log.info("nothing to do")
213
214
215 if __name__ == "__main__":
216
217
218 main()
219