3 using System
.Data
.Odbc
;
4 using System
.Collections
;
8 namespace Wv
.Schedulator
10 public class MantisSource
: Source
, IDisposable
12 string user
; // get the bugs for this username
16 public MantisSource(Schedulator s
, string name
, string odbcstring
,
20 // note: the null user doesn't exist, but the "" user is used
21 // for all bugs not assigned to anyone yet.
27 log
= new WvLog(wv
.fmt("Mantis:{0}", name
));
28 log
.print("Initializing Mantis source '{0}'.\n", name
);
29 log
.print("Connecting to: '{0}'\n", odbcstring
);
30 db
= WvDbi
.create(odbcstring
);
35 if (db
!= null) db
.Dispose();
38 public static Source
create(Schedulator s
, string name
,
39 string prefix
, string suffix
)
41 string[] bits
= suffix
.Split(':');
43 return new MantisSource(s
, name
, bits
[0], bits
[1]);
44 else if (bits
.Length
>= 1)
45 return new MantisSource(s
, name
, bits
[0], null);
47 throw new ArgumentException("bad moniker for MantisSource");
50 Hashtable mantispersons
= new Hashtable();
51 Hashtable mantispersons_byname
= new Hashtable();
52 Hashtable mantisprojects
= new Hashtable();
53 Hashtable mantisfixfors
= new Hashtable();
55 public override string view_url(string taskid
)
57 return wv
.fmt("http://mantis/view.php?id={0}", taskid
);
60 public override void make_basic()
62 log
.print("Reading mantis_user_table.\n");
63 foreach (var r
in db
.select("select id, username, realname "
64 + "from mantis_user_table "
65 + "order by enabled desc, id "))
68 string name
= r
[1].IsNull
? "--" : r
[1];
69 string fullname
= r
[2];
70 if (wv
.isempty(fullname
))
72 name
= name
.ToLower();
74 Person p
= s
.persons
.Add(name
, fullname
);
75 mantispersons
.Add(ix
, p
);
76 if (!mantispersons_byname
.Contains(name
))
77 mantispersons_byname
.Add(name
, ix
);
80 // the "Undecided" user
81 mantispersons
.Add(0, s
.persons
.Add("", "-Undecided-"));
82 mantispersons_byname
.Remove("");
83 mantispersons_byname
.Add("", 0);
85 log
.print("Reading mantis_project_table.\n");
86 foreach (var r
in db
.select("select id, name from mantis_project_table"))
91 Project p
= s
.projects
.Add(name
);
92 mantisprojects
.Add(ix
, p
);
95 log
.print("Reading list of versions.\n");
96 string[] cols
= {"fixed_in_version", "version"}
;
97 foreach (string col
in cols
)
99 foreach (var r
in db
.select(wv
.fmt("select distinct project_id, {0} "
100 + "from mantis_bug_table "
101 + "order by project_id, {0} ", col
)))
105 if (wv
.isempty(name
)) name
= "-Undecided-";
106 string ix
= projix
.ToString() + "." + name
;
108 Project project
= (Project
)mantisprojects
[projix
];
110 project
= s
.projects
.Add("UNKNOWN");
112 FixFor f
= s
.fixfors
.Add(project
, name
);
113 if (!mantisfixfors
.Contains(ix
))
114 mantisfixfors
.Add(ix
, f
);
118 log
.print("Reading mantis_project_version_table.\n");
119 foreach (var r
in db
.select("select project_id, version, date_order "
120 + " from mantis_project_version_table "))
124 DateTime date
= r
[2];
125 string ix
= projix
.ToString() + "." + name
;
127 Project project
= (Project
)mantisprojects
[projix
];
129 project
= s
.projects
.Add("UNKNOWN");
131 FixFor f
= s
.fixfors
.Add(project
, name
);
132 if (!mantisfixfors
.Contains(ix
))
133 mantisfixfors
.Add(ix
, f
);
138 string bug_str(ICollection list
)
144 string[] array
= new string[list
.Count
];
145 list
.CopyTo(array
, 0);
146 return String
.Join(",", array
);
150 void add_list(ArrayList list
, ICollection src
)
152 foreach (object o
in src
)
156 Task
add_task(string ixstr
, string title
, FixFor fixfor
, int pri
,
157 bool done
, bool halfdone
, DateTime donedate
)
159 Task t
= s
.tasks
.Add(this, ixstr
, title
);
165 t
.donedate
= donedate
;
167 t
.halfdone
= halfdone
;
172 New
=10, Feedback
=20, Acknowledged
=30, Confirmed
=40,
173 Assigned
=50, Resolved
=80, Closed
=90,
177 Open
=10, Fixed
=20, Reopened
=30, NotReproducible
=40,
178 NotFixable
=50, Duplicate
=60, NotABug
=70, Suspended
=80,
183 None
=10, Low
=20, Normal
=30, High
=40, Urgent
=50, Immediate
=60,
186 int priority_map(int pri
)
188 if (pri
<= (int)Priority
.None
)
190 else if (pri
<= (int)Priority
.Low
)
192 else if (pri
<= (int)Priority
.Normal
)
194 else if (pri
<= (int)Priority
.High
)
196 else if (pri
<= (int)Priority
.Urgent
)
198 else if (pri
<= (int)Priority
.Immediate
)
204 public override Task
[] make_tasks()
206 Hashtable abugs
= new Hashtable(); // active
207 Hashtable vbugs
= new Hashtable(); // needs-verify
208 Hashtable rbugs
= new Hashtable(); // resolved-by-me
209 Hashtable sbugs
= new Hashtable(); // stolen by someone else
211 if (!mantispersons_byname
.Contains(user
))
213 log
.print("No user '{0}' exists!\n", user
);
217 int userix
= (int)mantispersons_byname
[user
];
219 log
.print("Listing active bugs.\n");
220 foreach (var r
in db
.select(wv
.fmt("select id, status "
221 + "from mantis_bug_table "
222 + "where handler_id={0} "
223 + " and status != {1} ",
224 userix
, (int)Status
.Closed
)))
228 if (status
>= (int)Status
.Resolved
)
229 vbugs
.Add(ix
, ix
.ToString());
231 abugs
.Add(ix
, ix
.ToString());
234 log
.print("Reading mantis_bug_history_table (1).\n");
235 foreach (var r
in db
.select(wv
.fmt("select distinct bug_id "
236 + " from mantis_bug_history_table "
237 + " where user_id={0} "
238 + " and field_name='resolution' ",
240 rbugs
.Add((int)r
[0], (string)r
[0]);
241 log
.print(" {0} bugs to check.\n", rbugs
.Count
);
242 string rbugs_str
= bug_str(rbugs
.Values
);
243 // log.print("rbugs: {0}\n", rbugs_str);
245 log
.print("Reading mantis_bug_history_table (2).\n");
248 bool resolved_by_me_once
= false, resolved_away
= false;
249 foreach (var r
in db
.select(wv
.fmt
250 ("select bug_id, user_id, new_value "
251 + " from mantis_bug_history_table "
252 + " where field_name='resolution' "
253 + " and new_value is not null "
254 + " and bug_id in ({1}) "
255 + " order by bug_id, id ",
265 sbugs
.Add(last_bug
, last_bug
.ToString());
266 else if (resolved_by_me_once
)
267 rbugs
.Add(last_bug
, last_bug
.ToString());
270 resolved_by_me_once
= resolved_away
= false;
273 // hacky attempt at Resolved (Again) from FogBugz
274 if (newval
== (int)Resolution
.Suspended
)
277 if (userix
== ixperson
)
279 resolved_by_me_once
= true;
280 resolved_away
= false; // I stole it back!
282 else if (resolved_by_me_once
)
283 resolved_away
= true; // Someone re-resolved my bug!
286 // finish the very last bug from that query
288 sbugs
.Add(last_bug
, last_bug
.ToString());
289 else if (resolved_by_me_once
)
290 rbugs
.Add(last_bug
, last_bug
.ToString());
292 log
.print("{0} abugs, {1} vbugs, {2} rbugs and {3} sbugs.\n",
293 abugs
.Count
, vbugs
.Count
, rbugs
.Count
, sbugs
.Count
);
295 log
.print("Reading bug details.\n");
296 ArrayList all_bugs
= new ArrayList();
297 add_list(all_bugs
, abugs
.Values
);
298 add_list(all_bugs
, vbugs
.Values
);
299 add_list(all_bugs
, rbugs
.Values
);
300 add_list(all_bugs
, sbugs
.Values
);
301 string all_str
= bug_str(all_bugs
);
302 foreach (var r
in db
.select(wv
.fmt
303 ("select id, summary, project_id, "
304 + " fixed_in_version, version, "
305 + " priority, last_updated "
306 + "from mantis_bug_table "
307 + "where id in ({0})", all_str
)))
310 string ixstr
= ix
.ToString();
311 string title
= r
[1].IsNull
? "--" : r
[1];
312 int ixproject
= r
[2];
315 ? (r
[4].IsNull
? "" : r
[4])
317 if (wv
.isempty(ffname
)) ffname
= "-Undecided-";
318 int pri
= priority_map(r
[5]);
319 string ixfixfor
= ixproject
.ToString() + "." + ffname
;
320 DateTime resolvedate
= r
[6];
322 FixFor fixfor
= (FixFor
)mantisfixfors
[ixfixfor
];
324 if (abugs
.Contains(ix
))
325 add_task(ixstr
, title
, fixfor
, pri
, false, false,
327 else if (rbugs
.Contains(ix
) && !vbugs
.Contains(ix
))
328 add_task(ixstr
, title
, fixfor
, pri
, true, true,
330 else if (sbugs
.Contains(ix
))
331 add_task(ixstr
, title
, fixfor
, pri
, true, true,
334 // FIXME: "verify" tasks will disappear once closed,
335 // since they'll no longer be assigned to the user.
336 // We should read "closed" verbs from BugEvent too.
337 if (vbugs
.Contains(ix
))
339 string x
= abugs
.Contains(ix
) ? "v"+ixstr
: ixstr
;
340 add_task(x
, "VERIFY: " + title
, fixfor
, pri
,
341 false, true, DateTime
.MinValue
);