fix: ensure absolute paths are relative when combined #1752 · nedbat/coveragepy@1b19799 (original) (raw)

4 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -23,6 +23,13 @@ upgrading your version of coverage.py.
23 23 Unreleased
24 24 ----------
25 25
26 +- Fix: in some cases, even with ``[run] relative_files=True``, a data file
27 + could be created with absolute path names. When combined with other relative
28 + data files, it was random whether the absolute file names would be made
29 + relative or not. If they weren't, then a file would be listed twice in
30 + reports, as detailed in `issue 1752`_. This is now fixed: absolute file
31 + names are always made relative when combining.
32 +
26 33 - Fix: the last case of a match/case statement had an incorrect message if the
27 34 branch was missed. It said the pattern never matched, when actually the
28 35 branch is missed if the last case always matched.
@@ -33,6 +40,7 @@ Unreleased
33 40 string. Thanks, `Tanaydin Sirin <pull 1754_>`_. It is also now documented
34 41 on the :ref:`configuration page <config_report_format>`.
35 42
43 +.. _issue 1752: https://github.com/nedbat/coveragepy/issues/1752
36 44 .. _pull 1754: https://github.com/nedbat/coveragepy/pull/1754
37 45
38 46
Original file line number Diff line number Diff line change
@@ -88,7 +88,10 @@ def combinable_files(data_file: str, data_paths: Iterable[str] | None = None) ->
88 88 # We never want to combine those.
89 89 files_to_combine = [fnm for fnm in files_to_combine if not fnm.endswith("-journal")]
90 90
91 -return files_to_combine
91 +# Sorting isn't usually needed, since it shouldn't matter what order files
92 +# are combined, but sorting makes tests more predictable, and makes
93 +# debugging more understandable when things go wrong.
94 +return sorted(files_to_combine)
92 95
93 96
94 97 def combine_parallel_data(
Original file line number Diff line number Diff line change
@@ -489,6 +489,9 @@ def map(self, path: str, exists:Callable[[str], bool] = source_exists) -> str:
489 489
490 490 # If we get here, no pattern matched.
491 491
492 +if self.relative:
493 +path = relative_filename(path)
494 +
492 495 if self.relative and not isabs_anywhere(path):
493 496 # Auto-generate a pattern to implicitly match relative files
494 497 parts = re.split(r"[/\\]", path)
Original file line number Diff line number Diff line change
@@ -1465,3 +1465,23 @@ def test_combine_parallel_data_keep(self) -> None:
1465 1465 # After combining, the .coverage file & the original combined file should still be there.
1466 1466 self.assert_exists(".coverage")
1467 1467 self.assert_file_count(".coverage.*", 2)
1468 +
1469 +@pytest.mark.parametrize("abs_order, rel_order", [(1, 2), (2, 1)])
1470 +def test_combine_absolute_then_relative_1752(self, abs_order: int, rel_order: int) -> None:
1471 +# https://github.com/nedbat/coveragepy/issues/1752
1472 +# If we're combining a relative data file and an absolute data file,
1473 +# the absolutes were made relative only if the relative file name was
1474 +# encountered first. Test combining in both orders and check that the
1475 +# absolute file name is properly relative in either order.
1476 +FILE = "sub/myprog.py"
1477 +self.make_file(FILE, "a = 1")
1478 +
1479 +self.make_data_file(suffix=f"{abs_order}.abs", lines={abs_file(FILE): [1]})
1480 +self.make_data_file(suffix=f"{rel_order}.rel", lines={FILE: [1]})
1481 +
1482 +self.make_file(".coveragerc", "[run]\nrelative_files = True\n")
1483 +cov = coverage.Coverage()
1484 +cov.combine()
1485 +data = coverage.CoverageData()
1486 +data.read()
1487 +assert {os_sep("sub/myprog.py")} == data.measured_files()