[master] 552f5c1ff Renovate the gcov_digest script.

Poul-Henning Kamp phk at FreeBSD.org
Mon Jun 16 14:00:05 UTC 2025


commit 552f5c1ff8453ac45e5aca2775ca0ff728f0fd29
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Mon Jun 16 13:58:33 2025 +0000

    Renovate the gcov_digest script.

diff --git a/tools/gcov_digest.py b/tools/gcov_digest.py
index eb6fa58c3..309958fba 100644
--- a/tools/gcov_digest.py
+++ b/tools/gcov_digest.py
@@ -55,39 +55,92 @@ import sys
 import getopt
 import subprocess
 
-counts = {}
-lengths = {}
+source_files = {}
+
+class SourceFile():
+    ''' GCOV counts for a single source file '''
+
+    def __init__(self, path):
+        self.path = path
+        self.counts = {}
+        self.length = 0
+        source_files[path] = self
+
+    def __lt__(self, other):
+        return self.path < other.path
+
+    def ingest(self, fd):
+        ''' Ingest a gcov file '''
+        for line in fd:
+            flds = line.split(':', maxsplit=2)
+            cnt = flds[0].strip()
+            if cnt == "-":
+                continue
+            if cnt == "#####":
+                cnt = 0
+            else:
+                cnt = int(cnt)
+            lno = int(flds[1])
+            if lno not in self.counts:
+                self.counts[lno] = cnt
+            else:
+                self.counts[lno] += cnt
+        self.length = lno
+
+    def summary(self):
+        """
+        Produce compact output file
+
+        Format:
+            linefm [lineto] count
+
+            "+" in linefm means "previous line + 1"
+            "." in count means "same as previous count"
+        """
+        yield "/" + self.path + " " + str(self.length)
+        lnos = list(sorted(self.counts.items()))
+        pln = -1
+        pcn = -1
+        while lnos:
+            ln, cn = lnos.pop(0)
+            lnl = ln
+            while lnos:
+                lnn, cnn = lnos[0]
+                if lnl + 1 != lnn or cnn != cn:
+                    break
+                lnos.pop(0)
+                lnl = lnn
+            if ln == pln + 1:
+                s = "+ "
+            else:
+                s = "%d " % ln
+
+            if ln != lnl:
+                s += "%d " % lnl
+                pln = lnl
+            else:
+                pln = ln
+
+            if cn == pcn:
+                s += "."
+            else:
+                s += "%d" % cn
+                pcn = cn
+            yield s
 
 exclude = [".git", ".deps",]
 
-def process_gcov(fn, sn):
+def process_gcov(fn, root):
     """ Sum .gcov file into counts, then delete it """
-    dd = counts.get(sn)
-    if dd is None:
-        dd = {}
-    for ln in open(fn, encoding="UTF-8"):
-        d = ln.split(":")
-        cnt = d[0].strip()
-        ll = d[1]
-        if cnt == "-":
-            continue
-        if cnt == "#####":
-            cnt = 0
-        else:
-            cnt = int(cnt)
-        lno = int(d[1])
-        if lno not in dd:
-            dd[lno] = 0
-        dd[lno] += cnt
-    counts[sn] = dd
-    pl = lengths.get(sn)
-    ll = ll.strip()
-    if d[2] == "/*EOF*/\n":
-        ll = pl
-    elif pl != ll and not pl is None:
-        print("CONFLICT", fn, ll, pl)
-        ll = "-1"
-    lengths[sn] = ll
+
+    with open(fn, encoding="UTF-8") as gfile:
+        sline = gfile.readline().split(':')
+        assert sline[2] == "Source"
+        sname = os.path.normpath(os.path.join(root, sline[3].strip()))
+        sfile = source_files.get(sname)
+        if not sfile:
+            sfile = SourceFile(sname)
+        sfile.ingest(gfile)
     os.remove(fn)
 
 def run_gcov(prog, subdir):
@@ -109,18 +162,31 @@ def run_gcov(prog, subdir):
                 subdir = root.split("/")[-1]
                 cmd = ["cd " + root + "/.. && " + "exec " + prog + " " + subdir + "/" + fn]
                 rpath = "/../"
+            elif "vtest2" in root:
+                cmd = ["cd " + root + "/../.. && " + "exec " + prog + " vtest2/src/" + fn]
+                rpath = "/../../"
+                #print("VT2")
             elif root[-6:] == "/.libs":
                 cmd = ["cd " + root + "/.. && " + "exec " + prog + " .libs/" + fn]
                 rpath = "/../"
             else:
+                #print("R", root, "FN", fn)
                 cmd = ["cd " + root + " && " + "exec " + prog + " " + fn]
                 rpath = "/"
 
-            x = subprocess.check_output(
+            sp = subprocess.run(
                     cmd,
-                    stderr=subprocess.STDOUT, shell=True,
-                    universal_newlines=True)
-            pf = ""
+                    shell=True,
+                    universal_newlines=True,
+                    capture_output=True,
+            )
+
+            if sp.returncode != 0 or sp.stderr:
+                print("CMD", cmd, "EXIT", sp.returncode)
+                print("SERR", len(sp.stderr), sp.stderr)
+                print("SOUT", sp.stdout)
+                sys.exit(2)
+            x = sp.stdout
 
             for ln in x.split("\n"):
                 if "such file" in ln:
@@ -129,59 +195,15 @@ def run_gcov(prog, subdir):
                 ln = ln.split()
                 if not ln:
                     continue
-                if ln[0].find("reating") != -1:
+                if "reating" in ln[0]:
                     gn = root + rpath + ln[1].strip("'")
                     gn = os.path.normpath(gn)
                     assert gn[-5:] == ".gcov"
-                    sn = gn[:-5]
-                    process_gcov(gn, sn)
-
-def produce_output(fdo):
-    """
-    Produce compact output file
-
-    Format:
-        linefm [lineto] count
-
-        "+" in linefm means "previous line + 1"
-        "." in count means "same as previous count"
-    """
-
-    for sn, cnt in counts.items():
-        fdo.write("/" + sn + " " + str(lengths[sn]) + "\n")
-        lnos = list(cnt.items())
-        lnos.sort()
-        pln = -1
-        pcn = -1
-        while lnos:
-            ln, cn = lnos.pop(0)
-            lnl = ln
-            while lnos:
-                lnn, cnn = lnos[0]
-                if lnl + 1 != lnn or cnn != cn:
-                    break
-                lnos.pop(0)
-                lnl = lnn
-            if ln == pln + 1:
-                s = "+ "
-            else:
-                s = "%d " % ln
-
-            if ln != lnl:
-                s += "%d " % lnl
-                pln = lnl
-            else:
-                pln = ln
-
-            if cn == pcn:
-                s += "."
-            else:
-                s += "%d" % cn
-                pcn = cn
-            fdo.write(s + "\n")
-
-if __name__ == "__main__":
+                    #print("GS", gn)
+                    process_gcov(gn, root)
 
+def main():
+    ''' ... '''
     optlist, args = getopt.getopt(sys.argv[1:], "g:o:x:")
 
     fo = sys.stdout
@@ -193,7 +215,7 @@ if __name__ == "__main__":
         if f == '-o' and v == '-':
             fo = sys.stdout
         elif f == '-o':
-            fo = open(v, "w")
+            fo = open(v, "w", encoding="utf8")
         elif f == '-g':
             gcovprog = v
         elif f == '-x':
@@ -205,4 +227,9 @@ if __name__ == "__main__":
     for dn in args:
         run_gcov(gcovprog, dn)
 
-    produce_output(fo)
+    for sf in sorted(source_files.values()):
+        for i in sf.summary():
+            fo.write(i + "\n")
+
+if __name__ == "__main__":
+    main()


More information about the varnish-commit mailing list