#! /usr/bin/env python """ find_broken.py -- Build tool. Find broken packages.""" import os import re import string import sys # # Important constants. # def _scan_for_errors (filename, regexlist): """Find the error summary lines in a file.""" linecnt = 0 errcnt = 0 errlines = [] errs_by_phase = {} phaselist = [] phase = "unknown" f = open (filename, "r") for line in f.xreadlines (): if line[-1] == "\n": line = line[:-1] linecnt = linecnt + 1 if linecnt > 5000: print "ERROR: 5000 lines seen, skipping rest: %s" % (filename,) break errlines = errlines + [line] if line[0:8] == "#----- (": #print "line:", line try: (junk, phase, pkgname, pkgver) = line.split (None, 3) except Exception: try: (junk, phase, pkgname) = line.split (None, 2) except Exception: phase = "unknown" print "ERROR: malformed error log header!" print "ERROR: filename: %s" % (filename,) print "ERROR: %s" % (line,) if phase[0] == "(": phase = phase[1:] phase = phase[:-1] #print "phase: '%s'" % (phase,) elif line[0:7] == "#----- ": #print "line:", line phase = "unknown" try: (junk, pkgname, pkgver) = line.split (None, 2) except Exception: try: (junk, pkgname) = line.split (None, 1) except Exception: print "ERROR: malformed error log header!" print "ERROR: filename: %s" % (filename,) print "ERROR:", line #print "phase: '%s'" % (phase,) #if phase in ["test"]: continue #if phase == "test": # print filename if line and (line[0] != "#"): matched = 0 for regex in regexlist: if regex.search (line): matched = 1 break if not matched: errcnt = errcnt + 1 if errs_by_phase.has_key (phase): errs_by_phase[phase] = errs_by_phase[phase] + [line] else: errs_by_phase[phase] = [line] phaselist = phaselist + [phase] f.close () return (errcnt, errlines, errs_by_phase, phaselist) def _main (): # # Process command line parameters. # recipient = "" if len (sys.argv) > 1: recipient = sys.argv[1] buildnum = "" if len (sys.argv) > 2: buildnum = sys.argv[2] if buildnum: buildnum = "%02d" % (int (buildnum),) # # Process parameters. # # # Check environment variables. # pub = os.environ.get ("SRT_PUBLIC_CONTEXT") if not pub: print "ERROR: SRT_PUBLIC_CONTEXT is not set!" return 127 pri = os.environ.get ("SRT_PRIVATE_CONTEXT") if not pri: print "ERROR: SRT_PRIVATE_CONTEXT is not set!" return 127 srt_base_release = os.environ.get ("SRT_BASE_RELEASE") if not srt_base_release: print "ERROR: SRT_BASE_RELEASE is not set!" return 127 srt_subdir = os.environ.get ("SRT_SUBDIR") if not srt_subdir: print "ERROR: SRT_SUBDIR is not set!" return 127 # # Construct important directory names. # resdir = os.path.join (os.path.join (pri, "results"), srt_subdir) cmpdir = os.path.join (resdir, "compile") tstdir = os.path.join (resdir, "test") prireldbdir = os.path.join (pri, "D0reldb") pubreldbdir = os.path.join (pub, "D0reldb") # # Locate important files. # regexfil = os.path.join (prireldbdir, "errs.regex") if not os.path.isfile (regexfil): regexfil = os.path.join (pubreldbdir, "errs.regex") if not os.path.isfile (regexfil): print "ERROR: Could not find errs.regex!" return 127 # # Get regular expressions for error log filtering. # regexlist = [] f = open (regexfil, "r") for line in f.xreadlines (): if line[-1] == "\n": line = line[:-1] regexlist = regexlist + [re.compile (line)] f.close () # # Get list of packages already known to be broken # which should not get any further mail. # known_bad = [] known_bad_fil = os.path.join (pri, "known_bad.lis") if os.path.isfile (known_bad_fil): f = open (known_bad_fil, "r") for line in f.xreadlines (): if line[-1] == "\n": line = line[:-1] line = line.strip () if line: known_bad = known_bad + [line] f.close () # # Get the most recent build number. # if not buildnum: buildnumfil = os.path.join (resdir, ".buildnum") if not os.path.isfile (buildnumfil): print "ERROR: could not find .buildnum file!" return 127 f = open (buildnumfil, "r") buildnum = f.read() f.close () if not buildnum: print "ERROR: could not get buildnum!" return 127 if buildnum[-1] == "\n": buildnum = buildnum[:-1] if not buildnum: print "ERROR: could not get buildnum!" return 127 buildnum = int (buildnum) buildnum = buildnum - 1 buildnum = "%02d" % (buildnum,) sumfile = os.path.join ( pri, os.path.join ("results", os.path.join ( srt_subdir , "summary-" + buildnum + ".txt" ))) # print sumfile if os.path.islink (sumfile) or os.path.exists (sumfile): os.unlink (sumfile) fsum = open (sumfile, "w") # # Get a list of packages in the private area. # pkglist = [] pkginfo = {} for pkg in os.listdir (pri): pkgdir = os.path.join (pri, pkg) if os.path.isfile (os.path.join (pkgdir, "GNUmakefile")): pkglist = pkglist + [pkg] pkgver = "unknown" if os.path.islink (pkgdir): pkgver = os.path.basename (os.readlink (pkgdir)) pkginfo[pkg] = pkgver pkglist.sort () # # Loop over error log files and send mail. # max_warning_given = 0 pkgerrors = 0 for pkg in pkglist: pkgver = pkginfo[pkg] cmperrlogfil = os.path.join (os.path.join (cmpdir, pkg), "build-" + srt_subdir + "-" + buildnum + ".log") tsterrlogfil = os.path.join (os.path.join (tstdir, pkg), "build-" + srt_subdir + "-" + buildnum + ".log") tot_errlines = [] tot_errs_by_phase = {} tot_phaselist = [] numerrs = 0 if os.path.isfile (cmperrlogfil): (errcnt, errlines, errs_by_phase, phaselist) = _scan_for_errors (cmperrlogfil, regexlist) numerrs = numerrs + errcnt tot_errlines = errlines tot_errs_by_phase = errs_by_phase tot_phaselist = phaselist if os.path.isfile (tsterrlogfil): (errcnt, errlines, errs_by_phase, phaselist) = _scan_for_errors (tsterrlogfil, regexlist) numerrs = numerrs + errcnt tot_errlines = tot_errlines + errlines for phase in phaselist: if phase not in tot_phaselist: tot_phaselist = tot_phaselist + [phase] tot_errs_by_phase[phase] = errs_by_phase[phase] else: tot_errs_by_phase[phase] = tot_errs_by_phase[phase] + errs_by_phase[phase] if not numerrs: continue pkgerrors = pkgerrors + 1 # print pkg, tot_phaselist if pkg in known_bad: known = "known" else: known = "" print >> fsum, "%-25s %-11s" % (pkg,pkgver) print "%-25s %-20s %5s" % (pkg,pkgver,known), tot_phaselist errsumlines = [] for phase in tot_phaselist: errsumlines = errsumlines + tot_errs_by_phase[phase] err_phases = string.join (tot_phaselist) # # close summary file and write out summary. # fsum.close () if not pkgerrors: print "No package errors found." else: print print "A total of %d package errors found." % (pkgerrors,) return 0 if __name__ == "__main__": # We are being run as a script. err = _main () sys.exit (err) else: # We are being loaded as a module. pass