mirror of
https://github.com/safishamsi/graphify.git
synced 2026-07-12 10:27:11 +00:00
f9174943a2
#1649: detect_incremental tracks the converted markdown sidecar, and convert_office_file early-returned whenever the sidecar existed — so a .docx/ .xlsx edited after its first conversion never updated its sidecar and was reported "unchanged" forever, freezing the graph. It now re-converts when the source is newer than the sidecar (bumping the sidecar so the hash check catches it); an unchanged source still skips the rewrite (#1226). #1655: _md5_file/save_manifest/count_words used plain open()/stat(), which the Windows file APIs reject for absolute paths over 260 chars unless prefixed with `\\?\`. Deeply-nested files never hashed, their manifest entry never stabilized, and detect_incremental re-flagged them as changed every run. A new _os_path adds the extended-length prefix on win32 for change-detection I/O (mirror of cache._normalize_path, which strips it for keys). No-op elsewhere. #1656: detect() re-parsed every PDF/docx/text file to size the corpus on each run. Word counts are now memoized in the existing content-hash stat index (keyed by size + mtime_ns), so an unchanged file is parsed once. file_hash's fastpath is guarded so a word-count-only entry (no hash) can't KeyError, and both writers augment a co-located entry in place instead of clobbering the other's field. Full suite: 2906 passed, 3 skipped. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
51 lines
1.7 KiB
Python
51 lines
1.7 KiB
Python
r"""#1655 — files whose absolute path exceeds Windows MAX_PATH (260) must still
|
|
be hashed, or their manifest entry never stabilizes and detect_incremental
|
|
re-flags them as changed on every run.
|
|
|
|
The plain file APIs reject long paths on win32 unless prefixed with the
|
|
extended-length marker `\\?\`. _os_path adds it (for I/O), the mirror of
|
|
cache._normalize_path which strips it (for stable keys).
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
from graphify import detect
|
|
|
|
|
|
def test_os_path_noop_on_posix(monkeypatch):
|
|
monkeypatch.setattr("sys.platform", "linux")
|
|
p = Path("/home/user/deep/file.py")
|
|
assert detect._os_path(p) == str(p)
|
|
|
|
|
|
def test_os_path_adds_prefix_on_win32(monkeypatch):
|
|
monkeypatch.setattr("sys.platform", "win32")
|
|
# os.path.abspath is posix here, so exercise the already-qualified branch:
|
|
# a value that abspath leaves intact still gets the prefix.
|
|
out = detect._os_path(Path("/already/abs/file.py"))
|
|
assert out.startswith("\\\\?\\")
|
|
|
|
|
|
def test_os_path_idempotent_on_win32(monkeypatch):
|
|
monkeypatch.setattr("sys.platform", "win32")
|
|
already = "\\\\?\\C:\\a\\file.py"
|
|
assert detect._os_path(Path(already)) == already
|
|
|
|
|
|
def test_hashing_still_works_and_stabilizes(tmp_path):
|
|
# End-to-end (posix): a hashed file must produce a stable, non-empty hash so
|
|
# its manifest entry doesn't churn. Guards against the _os_path indirection
|
|
# breaking normal hashing.
|
|
f = tmp_path / "deep" / "nested" / "module.py"
|
|
f.parent.mkdir(parents=True)
|
|
f.write_text("def x():\n return 1\n")
|
|
h1 = detect._md5_file(f)
|
|
h2 = detect._md5_file(f)
|
|
assert h1 and h1 == h2
|
|
|
|
got = detect._stat_and_hash(str(f))
|
|
assert got is not None
|
|
assert got[0] == str(f)
|
|
assert got[2] == h1
|