From 86043ed931be0787dd1ad9a7f50e185087e5a56e Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Sat, 17 Oct 2026 10:31:48 +0200 Subject: [PATCH] fix: count drift since the pin in profile triage --- scripts/profile_sync.py | 3 ++- scripts/upstream.py | 49 ++++++++++++++++++++++++++++++++++++----- tests/test_upstream.py | 25 ++++++++++++++++++--- 3 files changed, 67 insertions(+), 10 deletions(-) diff --git a/scripts/profile_sync.py b/scripts/profile_sync.py index f3ae63cb..363c79ef 100644 --- a/scripts/profile_sync.py +++ b/scripts/profile_sync.py @@ -3367,7 +3367,8 @@ def _print_triage(args, selected: dict, reports: list[ProfileReport]) -> None: paths = _cited_paths(report) for path in paths[:TRIAGE_PATH_SAMPLE]: commits += upstream.commits_touching( - repo, path, report.pin, args.cache_dir, args.offline + repo, path, report.pin, args.cache_dir, args.offline, + head=report.head, ) if len(paths) > TRIAGE_PATH_SAMPLE: print( diff --git a/scripts/upstream.py b/scripts/upstream.py index 87a2eb5a..ed855fb4 100644 --- a/scripts/upstream.py +++ b/scripts/upstream.py @@ -667,22 +667,59 @@ def list_tree( return paths, bool(payload.get("truncated")) +def commit_date(repo: Repo, sha: str, cache_dir: str, offline: bool = False) -> str | None: + """When a revision was committed, as the forge reports it (ISO 8601).""" + if repo.family == "gitlab": + payload = _api( + f"{repo.api_base}/projects/{_project(repo)}/repository/commits/{sha}", + cache_dir, offline, + ) + value = payload.get("committed_date") if isinstance(payload, dict) else None + return value if isinstance(value, str) else None + if repo.family == "github": + url = f"{repo.api_base}/repos/{repo.slug}/commits/{sha}" + else: + url = f"{repo.api_base}/repos/{repo.slug}/git/commits/{sha}" + stamp = _gitea_commit_date(_api(url, cache_dir, offline)) + return stamp.isoformat() if stamp is not None else None + + def commits_touching( - repo: Repo, path: str, base: str, cache_dir: str, offline: bool = False + repo: Repo, path: str, base: str, cache_dir: str, offline: bool = False, + head: str | None = None, ) -> int: - """Commits touching one path since a revision.""" + """Commits touching one path since a revision, on the default branch. + + Listing from the pin counted the history before it: a profile pinned on + HEAD scored the age of its files as drift. The count is of the commits + after the pin's date that touch the path, the pin itself excluded. + """ + if head is not None and head == base: + return 0 + since = commit_date(repo, base, cache_dir, offline) + if since is None: + return 0 quoted = urllib.parse.quote(path) + stamp = urllib.parse.quote(since) if repo.family == "gitlab": url = ( f"{repo.api_base}/projects/{_project(repo)}" - f"/repository/commits?path={quoted}&per_page=100" + f"/repository/commits?path={quoted}&since={stamp}&per_page=100" ) elif repo.family == "github": url = ( f"{repo.api_base}/repos/{repo.slug}/commits" - f"?path={quoted}&sha={base}&per_page=100" + f"?path={quoted}&since={stamp}&per_page=100" ) else: - url = f"{repo.api_base}/repos/{repo.slug}/commits?path={quoted}&limit=100" + url = ( + f"{repo.api_base}/repos/{repo.slug}/commits" + f"?path={quoted}&since={stamp}&limit=100" + ) payload = _api(url, cache_dir, offline) - return len(payload) if isinstance(payload, list) else 0 + if not isinstance(payload, list): + return 0 + return sum( + 1 for entry in payload + if isinstance(entry, dict) and (entry.get("sha") or entry.get("id")) != base + ) diff --git a/tests/test_upstream.py b/tests/test_upstream.py index 0fec7a16..ded955f3 100644 --- a/tests/test_upstream.py +++ b/tests/test_upstream.py @@ -602,10 +602,29 @@ class TestCompare(unittest.TestCase): result = upstream.compare(repo, "a", "b", self.dir) self.assertEqual(upstream.find_renamed(result, "old.c"), "new.c") - def test_commits_touching_counts_entries(self): - self.payload = [{"sha": "1"}, {"sha": "2"}, {"sha": "3"}] + def test_commits_touching_counts_the_commits_after_the_pin(self): + """Listing from the pin counted its history: freeintv's pin on HEAD + scored 26 commits of drift.""" + served = { + "commits/base": {"commit": {"committer": {"date": "2026-01-01T00:00:00Z"}}}, + } + listing = [{"sha": "1"}, {"sha": "2"}, {"sha": "base"}] + seen: list[str] = [] + + def answer(url): + seen.append(url) + for key, value in served.items(): + if url.endswith(key): + return value + return listing + + upstream._http_json = answer self.assertEqual( - upstream.commits_touching(self.repo, "a.c", "base", self.dir), 3 + upstream.commits_touching(self.repo, "a.c", "base", self.dir, head="tip"), 2 + ) + self.assertTrue(any("since=2026-01-01" in url for url in seen)) + self.assertEqual( + upstream.commits_touching(self.repo, "a.c", "tip", self.dir, head="tip"), 0 )