Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions graphify/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -1776,6 +1776,8 @@ def _on_walk_error(err: OSError) -> None:
for dirpath, dirnames, filenames in os.walk(
scan_root, followlinks=follow_symlinks, onerror=_on_walk_error
):
dirnames.sort()
filenames.sort()
dp = Path(dirpath)
if follow_symlinks and os.path.islink(dirpath):
real = os.path.realpath(dirpath)
Expand Down
25 changes: 25 additions & 0 deletions tests/test_detect_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from pathlib import Path
from graphify.detect import detect


def test_detect_directory_walk_is_sorted(tmp_path):
# Create dirs in reverse-alpha order to ensure os.walk would visit them
# non-deterministically without our sorting fix.
(tmp_path / "b").mkdir()
(tmp_path / "a").mkdir()

# Files named in reverse order within each dir, for the same reason.
(tmp_path / "b" / "z.py").write_text("print('z')")
(tmp_path / "b" / "y.py").write_text("print('y')")
(tmp_path / "a" / "x.py").write_text("print('x')")
(tmp_path / "a" / "w.py").write_text("print('w')")

result = detect(tmp_path)
code_files = result["files"]["code"]

# Full repo-relative paths should arrive in sorted order:
# a/w.py, a/x.py, b/y.py, b/z.py — not filesystem-dependent.
relative = [str(Path(f).relative_to(tmp_path)) for f in code_files]
assert relative == ["a/w.py", "a/x.py", "b/y.py", "b/z.py"], (
f"Files were not detected in sorted order: {relative}"
)