aboutsummaryrefslogtreecommitdiff
path: root/modules/coverage-core.el
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-22 09:23:16 -0400
committerCraig Jennings <c@cjennings.net>2026-06-22 09:23:16 -0400
commit82c81de7d1b0a75572b1c2cd7779d6f105501d6b (patch)
tree45b73c2a7f2b16f5f64c60a2f348a1db8e69efc6 /modules/coverage-core.el
parented32f94f3ff2480403eac4a3271523372e1eaefa (diff)
downloaddotemacs-82c81de7d1b0a75572b1c2cd7779d6f105501d6b.tar.gz
dotemacs-82c81de7d1b0a75572b1c2cd7779d6f105501d6b.zip
fix(coverage): normalize report and diff paths before intersecting
simplecov reports absolute source paths while git diff emits repo-relative ones, so cj/--coverage-intersect joined them by exact key and matched nothing — every changed file read ":tracked nil" under the working-tree, staged, and branch scopes (whole-project worked only because both sides came from the same simplecov source). A new cj/--coverage-relativize-keys normalizes both tables to repo-relative in cj/--coverage-read-and-display before the intersect; the intersect stays pure. Covered by 5 unit tests plus an integration test that drives the real parsers with an absolute-key report and a relative-key diff.
Diffstat (limited to 'modules/coverage-core.el')
-rw-r--r--modules/coverage-core.el33
1 files changed, 29 insertions, 4 deletions
diff --git a/modules/coverage-core.el b/modules/coverage-core.el
index 687a042fe..9b102bb7b 100644
--- a/modules/coverage-core.el
+++ b/modules/coverage-core.el
@@ -249,6 +249,27 @@ Signals `user-error' for any other SCOPE."
(maphash (lambda (k _v) (push k keys)) table)
(sort keys #'<)))
+(defun cj/--coverage-relativize-keys (table root)
+ "Return a copy of TABLE with each file-path key made relative to ROOT.
+An absolute key is relativized against ROOT via `file-relative-name'; an
+already-relative key is kept as-is. Line-set values are shared, not copied.
+
+`cj/--coverage-parse-simplecov' emits absolute path keys (simplecov reports
+absolute source paths) while `cj/--coverage-parse-diff-output' emits
+repo-relative keys (git's \"+++ b/<path>\"). Both must be normalized to
+repo-relative before `cj/--coverage-intersect' joins them by key, or every
+diff-aware match misses and each changed file reads `:tracked nil'."
+ (let ((result (make-hash-table :test 'equal)))
+ (when table
+ (maphash
+ (lambda (path lines)
+ (let ((key (if (file-name-absolute-p path)
+ (file-relative-name path root)
+ path)))
+ (puthash key lines result)))
+ table))
+ result))
+
(defun cj/--coverage-intersect (covered changed)
"Combine COVERED (LCOV) with CHANGED (git diff) into per-file records.
COVERED and CHANGED are each hash tables from file path to a hash table
@@ -479,10 +500,14 @@ line in the simplecov data — the intersect then classifies each line
as covered or uncovered. For diff-aware scopes, the changed set
comes from `git diff' via `cj/--coverage-changed-lines'."
(let* ((report-path (funcall (plist-get backend :report-path)))
- (covered (cj/--coverage-parse-simplecov report-path))
- (changed (if (eq scope 'whole-project)
- (cj/--coverage-simplecov-executable-lines report-path)
- (cj/--coverage-changed-lines scope)))
+ (root (cj/--coverage-project-root))
+ (covered (cj/--coverage-relativize-keys
+ (cj/--coverage-parse-simplecov report-path) root))
+ (changed (cj/--coverage-relativize-keys
+ (if (eq scope 'whole-project)
+ (cj/--coverage-simplecov-executable-lines report-path)
+ (cj/--coverage-changed-lines scope))
+ root))
(records (cj/--coverage-intersect covered changed)))
(cj/--coverage-render-to-buffer records scope)))