📄 gnatsparse.py
字号:
rfp.close()def split_csl(list): """ Split a comma seperated list """ newlist = re.split(r"""\s*,\s*""", list) return newlistdef fix_email_addrs(addrs): """ Perform various fixups and cleaning on an e-mail address """ addrs = split_csl(addrs) trimmed_addrs = [] for addr in addrs: addr = re.sub(r"""\(.*\)""","",addr) addr = re.sub(r""".*<(.*)>.*""","\\1",addr) addr = addr.rstrip() addr = addr.lstrip() trimmed_addrs.append(addr) addrs = ", ".join(trimmed_addrs) return addrsclass Bugzillabug(object): """ Class representing a bugzilla bug """ def __init__(self, gbug): """ Initialize a bugzilla bug from a GNATS bug. """ self.bug_id = gbug.bug_id self.long_descs = [] self.bug_ccs = [get_userid("gcc-bugs@gcc.gnu.org")] self.bug_activity = [] self.attachments = gbug.attachments self.gnatsfields = gbug.fields self.need_unformatted = gbug.has_unformatted_attach == 0 self.need_unformatted &= gbug.fields.has_key("Unformatted") self.translate_pr() self.update_versions() if self.fields.has_key("Audit-Trail"): self.parse_audit_trail() self.write_bug() def parse_fromto(type, string): """ Parses the from and to parts of a changed-from-to line """ fromstr = "" tostr = "" # Some slightly messed up changed lines have unassigned-new, # instead of unassigned->new. So we make the > optional. result = re.search(r"""(.*)-(?:>?)(.*)""", string) # Only know how to handle parsing of State and Responsible # changed-from-to right now if type == "State": fromstr = state_lookup[result.group(1)] tostr = state_lookup[result.group(2)] elif type == "Responsible": if result.group(1) != "": fromstr = result.group(1) if result.group(2) != "": tostr = result.group(2) if responsible_map.has_key(fromstr): fromstr = responsible_map[fromstr] if responsible_map.has_key(tostr): tostr = responsible_map[tostr] return (fromstr, tostr) parse_fromto = staticmethod(parse_fromto) def parse_audit_trail(self): """ Parse a GNATS audit trail """ trail = self.fields["Audit-Trail"] # Begin to split the audit trail into pieces result = fromtore.finditer(trail) starts = [] ends = [] pieces = [] # Make a list of the pieces for x in result: pieces.append (x) # Find the start and end of each piece if len(pieces) > 0: for x in xrange(len(pieces)-1): starts.append(pieces[x].start()) ends.append(pieces[x+1].start()) starts.append(pieces[-1].start()) ends.append(len(trail)) pieces = [] # Now make the list of actual text of the pieces for x in xrange(len(starts)): pieces.append(trail[starts[x]:ends[x]]) # And parse the actual pieces for piece in pieces: result = changedfromtore.search(piece) # See what things we actually have inside this entry, and # handle them approriately if result is not None: type = result.group(1) changedfromto = result.group(2) # If the bug was reopened, mark it as such if changedfromto.find("closed->analyzed") != -1: if self.fields["bug_status"] == "'NEW'": self.fields["bug_status"] = "'REOPENED'" if type == "State" or type == "Responsible": oldstate, newstate = self.parse_fromto (type, changedfromto) result = changedbyre.search(piece) if result is not None: changedby = result.group(1) result = changedwhenre.search(piece) if result is not None: changedwhen = result.group(1) changedwhen = unixdate2datetime(changedwhen) changedwhen = SqlQuote(changedwhen) result = changedwhyre.search(piece) changedwhy = piece[result.start(1):] #changedwhy = changedwhy.lstrip() changedwhy = changedwhy.rstrip() changedby = get_userid(changedby) # Put us on the cc list if we aren't there already if changedby != self.fields["userid"] \ and changedby not in self.bug_ccs: self.bug_ccs.append(changedby) # If it's a duplicate, mark it as such result = duplicatere.search(changedwhy) if result is not None: newtext = "*** This bug has been marked as a duplicate of %s ***" % result.group(1) newtext = SqlQuote(newtext) self.long_descs.append((self.bug_id, changedby, changedwhen, newtext)) self.fields["bug_status"] = "'RESOLVED'" self.fields["resolution"] = "'DUPLICATE'" self.fields["userid"] = changedby else: newtext = "%s-Changed-From-To: %s\n%s-Changed-Why: %s\n" % (type, changedfromto, type, changedwhy) newtext = SqlQuote(newtext) self.long_descs.append((self.bug_id, changedby, changedwhen, newtext)) if type == "State" or type == "Responsible": newstate = SqlQuote("%s" % newstate) oldstate = SqlQuote("%s" % oldstate) fieldid = fieldids[type] self.bug_activity.append((newstate, oldstate, fieldid, changedby, changedwhen)) else: # It's an email result = fromre.search(piece) if result is None: continue fromstr = result.group(1) fromstr = fix_email_addrs(fromstr) fromstr = get_userid(fromstr) result = datere.search(piece) if result is None: continue datestr = result.group(1) datestr = SqlQuote(unixdate2timestamp(datestr)) if fromstr != self.fields["userid"] \ and fromstr not in self.bug_ccs: self.bug_ccs.append(fromstr) self.long_descs.append((self.bug_id, fromstr, datestr, SqlQuote(piece))) def write_bug(self): """ Output a bug to the data file """ fields = self.fields print >>outfile, "\ninsert into bugs(" print >>outfile, " bug_id, assigned_to, bug_severity, priority, bug_status, creation_ts, delta_ts," print >>outfile, " short_desc," print >>outfile, " reporter, version," print >>outfile, " product, component, resolution, target_milestone, qa_contact," print >>outfile, " gccbuild, gcctarget, gcchost, keywords" print >>outfile, " ) values (" print >>outfile, "%s, %s, %s, %s, %s, %s, %s," % (self.bug_id, fields["userid"], fields["bug_severity"], fields["priority"], fields["bug_status"], fields["creation_ts"], fields["delta_ts"]) print >>outfile, "%s," % (fields["short_desc"]) print >>outfile, "%s, %s," % (fields["reporter"], fields["version"]) print >>outfile, "%s, %s, %s, %s, 0," %(fields["product"], fields["component"], fields["resolution"], fields["target_milestone"]) print >>outfile, "%s, %s, %s, %s" % (fields["gccbuild"], fields["gcctarget"], fields["gcchost"], fields["keywords"]) print >>outfile, ");" if self.fields["keywords"] != 0: print >>outfile, "\ninsert into keywords (bug_id, keywordid) values (" print >>outfile, " %s, %s);" % (self.bug_id, fields["keywordid"]) for id, who, when, text in self.long_descs: print >>outfile, "\ninsert into longdescs (" print >>outfile, " bug_id, who, bug_when, thetext) values(" print >>outfile, " %s, %s, %s, %s);" % (id, who, when, text) for name, data, who in self.attachments: print >>outfile, "\ninsert into attachments (" print >>outfile, " bug_id, filename, description, mimetype, ispatch, submitter_id, thedata) values (" ftype = None # It's *magic*! if name.endswith(".ii") == 1: ftype = "text/x-c++" elif name.endswith(".i") == 1: ftype = "text/x-c" else: ftype = magicf.detect(cStringIO.StringIO(data)) if ftype is None: ftype = "application/octet-stream" print >>outfile, "%s,%s,%s, %s,0, %s,%s);" %(self.bug_id, SqlQuote(name), SqlQuote(name), SqlQuote (ftype), who, SqlQuote(zlib.compress(data))) for newstate, oldstate, fieldid, changedby, changedwhen in self.bug_activity: print >>outfile, "\ninsert into bugs_activity (" print >>outfile, " bug_id, who, bug_when, fieldid, added, removed) values (" print >>outfile, " %s, %s, %s, %s, %s, %s);" % (self.bug_id, changedby, changedwhen, fieldid, newstate, oldstate) for cc in self.bug_ccs: print >>outfile, "\ninsert into cc(bug_id, who) values (%s, %s);" %(self.bug_id, cc) def update_versions(self): """ Update the versions table to account for the version on this bug """ global versions_table if self.fields.has_key("Release") == 0 \ or self.fields.has_key("Category") == 0: return curr_product = "gcc" curr_version = self.fields["Release"] if curr_version == "": return curr_version = convert_gccver_to_ver (curr_version) if versions_table.has_key(curr_product) == 0: versions_table[curr_product] = [] for version in versions_table[curr_product]: if version == curr_version: return versions_table[curr_product].append(curr_version) def translate_pr(self): """ Transform a GNATS PR into a Bugzilla bug """ self.fields = self.gnatsfields if (self.fields.has_key("Organization") == 0) \ or self.fields["Organization"].find("GCC"): self.fields["Originator"] = "" self.fields["Organization"] = "" self.fields["Organization"].lstrip() if (self.fields.has_key("Release") == 0) \ or self.fields["Release"] == "" \ or self.fields["Release"].find("unknown-1.0") != -1: self.fields["Release"]="unknown" if self.fields.has_key("Responsible"): result = re.search(r"""\w+""", self.fields["Responsible"]) self.fields["Responsible"] = "%s%s" % (result.group(0), "@gcc.gnu.org") self.fields["gcchost"] = "" self.fields["gcctarget"] = "" self.fields["gccbuild"] = "" if self.fields.has_key("Environment"): result = re.search("^host: (.+?)$", self.fields["Environment"], re.MULTILINE) if result is not None: self.fields["gcchost"] = result.group(1) result = re.search("^target: (.+?)$", self.fields["Environment"], re.MULTILINE) if result is not None: self.fields["gcctarget"] = result.group(1) result = re.search("^build: (.+?)$", self.fields["Environment"], re.MULTILINE) if result is not None: self.fields["gccbuild"] = result.group(1) self.fields["userid"] = get_userid(self.fields["Responsible"]) self.fields["bug_severity"] = "normal" if self.fields["Class"] == "change-request": self.fields["bug_severity"] = "enhancement" elif self.fields.has_key("Severity"): if self.fields["Severity"] == "critical": self.fields["bug_severity"] = "critical" elif self.fields["Severity"] == "serious": self.fields["bug_severity"] = "major" elif self.fields.has_key("Synopsis"): if re.search("crash|assert", self.fields["Synopsis"]): self.fields["bug_severity"] = "critical" elif re.search("wrong|error", self.fields["Synopsis"]):
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -