Skip to content

Hook to check stale file references - #174

Open
cbachhuber wants to merge 18 commits into
masterfrom
162-check-stale-references
Open

Hook to check stale file references#174
cbachhuber wants to merge 18 commits into
masterfrom
162-check-stale-references

Conversation

@cbachhuber

Copy link
Copy Markdown
Collaborator

Closes #162

Comment thread dev_tools/check_stale_references.py Outdated
Comment thread dev_tools/check_stale_references.py Outdated
Comment thread dev_tools/check_stale_references.py Outdated
Comment thread dev_tools/check_stale_references.py Outdated
@cbachhuber
cbachhuber requested a lite review from Copilot August 11, 2026 04:10
Comment thread dev_tools/check_stale_references.py Outdated
Comment thread dev_tools/check_stale_references.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new check-stale-references pre-commit hook intended to detect references to deleted/renamed files (by full repo-relative path and by basename) in the remaining tracked files, helping prevent broken cross-references after refactors.

Changes:

  • Introduces dev_tools.check_stale_references implementation and a console entrypoint (check-stale-references).
  • Adds test coverage for pattern-building, detection, and output formatting.
  • Wires the hook into .pre-commit-hooks.yaml and documents it in README.md.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
dev_tools/check_stale_references.py Implements stale-reference detection and printing for use as a pre-commit hook.
tests/test_check_stale_references.py Adds unit tests for matching behavior and reporting.
pyproject.toml Registers the new console script and adjusts Ruff test ignores.
.pre-commit-hooks.yaml Adds the new check-stale-references hook definition.
README.md Documents the new hook in the Tools section and TOC.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread dev_tools/check_stale_references.py Outdated
Comment thread dev_tools/check_stale_references.py Outdated
Comment thread dev_tools/check_stale_references.py Outdated
Comment thread dev_tools/check_stale_references.py Outdated
cbachhuber and others added 5 commits August 11, 2026 01:47
…oundaries

- Replace Python file I/O with git grep for performance
- Extract _run_git() helper using subprocess.run(check=True)
- Simplify D/R branch in get_deleted_paths (both use parts[1])
- Add __str__ to StaleReference, remove print_stale_references
- Tighten regex boundaries to [\w.-] to reject foo.hpp.bak etc.
- Remove unused get_repo_root and get_tracked_files
Comment thread dev_tools/check_stale_references.py Outdated
Comment on lines +73 to +78
matches: list[tuple[str, int, str]] = []
for line in result.stdout.splitlines():
# git grep output: file:line_number:matched_line
file, line_no, text = line.split(":", 2)
matches.append((file, int(line_no), text))
return matches

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can extract this to a list comprehension by extracting another method out of this. That'd be overkill imo.



def build_path_pattern(deleted_path: str) -> str:
"""Build a PCRE pattern for a deleted path that matches references to it.

@cbachhuber cbachhuber Aug 13, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PCRE support in git is optionally compiled in, but it seems all widely used distros ship with a binary that includes this. Even the tiny alpine image has it:

$ docker run --rm -it alpine:latest sh
$ apk add git
$ apk info -R git # already shows the libpcre2-8.so.0 dependency
$ git clone https://github.com/hofbi/dev-tools.git
$ cd dev-tools
$ git grep -P 'test'
<some output showing that it works>

If we don't want to rely on the presence of PRCE in git, we'd have to revert this commit, i.e., do the boundary check from line 59 ourselves in python because only PCRE supports that in git grep.

For path "a/b/c.txt", matches (with non-word/dot/dash boundaries):
- /?a/b/c.txt (full path, optional leading /)
- (../)*b/c.txt (intermediate suffix with optional ../ prefix)
- (../)*c.txt (basename with optional ../ prefix)

@cbachhuber cbachhuber Aug 13, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has some chance of raising false positives for common filenames such as utils.py. Similarly, there might be conflict with some language includes such as cpp's #include <mylib/foo.hpp>. Should we guard against these? We could

  1. Require more than 2 path segments
  2. Skip known import/include syntax
  3. Ditch the partial path extraction logic altogether and only check full paths
  4. Require the basename to be 'unusual enough' (my least preferred option)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should either look at full paths or relative paths starting with ./ or ../.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you're saying don't make prefixes ./ or ../ optional, but require presence of at least one of the two for partial paths?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. Only consider absolute paths as you described them or relative paths starting with ./ or ../. This should help us to skip most C++ headers and other paths you listed as false positives.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will cause a huge number of false negatives, i.e., paths that are ignored despite being references. Aren't you worried about that? Or is your idea for this hook to have it kind of opt-in via the required relative or absolute prefix?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would you suggest? Go with the current setup for now, see what issues we find, and improve based on that?

@cbachhuber
cbachhuber marked this pull request as ready for review August 13, 2026 03:56
@cbachhuber
cbachhuber requested a review from hofbi August 13, 2026 03:56
"""
segments = deleted_path.split("/")
alternatives: list[str] = []
for i in range(len(segments)):

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this what enumerate is made for?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Local link verification in source code

3 participants