fix(extract): initialize detection for pathless Postgres
This commit is contained in:
committed by
safishamsi
parent
220a675265
commit
b35898aafc
+19
-3
@@ -2557,6 +2557,7 @@ def dispatch_command(cmd: str) -> None:
|
||||
)
|
||||
|
||||
if not has_path:
|
||||
detection = {}
|
||||
code_files = []
|
||||
doc_files = []
|
||||
paper_files = []
|
||||
@@ -2976,7 +2977,9 @@ def dispatch_command(cmd: str) -> None:
|
||||
_live_hashes.add(_file_hash(_abs, target, cache_root=out_root))
|
||||
except OSError:
|
||||
pass
|
||||
_prune_semantic_cache(out_root, _live_hashes)
|
||||
# A pathless database extraction has no filesystem corpus to sweep.
|
||||
if has_path:
|
||||
_prune_semantic_cache(out_root, _live_hashes)
|
||||
except Exception as exc:
|
||||
print(f"[graphify extract] warning: could not prune semantic cache: {exc}", file=sys.stderr)
|
||||
stages.mark("semantic extract")
|
||||
@@ -3056,6 +3059,15 @@ def dispatch_command(cmd: str) -> None:
|
||||
if has_path else None
|
||||
)
|
||||
|
||||
def _invalidate_file_manifest_for_db_graph() -> None:
|
||||
if has_path:
|
||||
return
|
||||
try:
|
||||
manifest_path.unlink(missing_ok=True)
|
||||
except OSError as exc:
|
||||
print(f"error: could not invalidate file manifest: {exc}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
if no_cluster:
|
||||
# --no-cluster: dump the raw merged extraction as graph.json.
|
||||
# No NetworkX, no community detection, no analysis sidecar.
|
||||
@@ -3140,6 +3152,7 @@ def dispatch_command(cmd: str) -> None:
|
||||
)
|
||||
sys.exit(1)
|
||||
_backup(graphify_out)
|
||||
_invalidate_file_manifest_for_db_graph()
|
||||
from graphify.paths import write_json_atomic as _write_json_atomic
|
||||
_write_json_atomic(graph_json_path, merged, indent=2)
|
||||
stages.mark("write")
|
||||
@@ -3159,7 +3172,8 @@ def dispatch_command(cmd: str) -> None:
|
||||
f"est. cost: ${cost:.4f}"
|
||||
)
|
||||
try:
|
||||
_save_manifest(_manifest_files, manifest_path=str(manifest_path), kind="both", root=target, scan_corpus=_scan_corpus, clear_semantic=_cleared_semantic)
|
||||
if has_path:
|
||||
_save_manifest(_manifest_files, manifest_path=str(manifest_path), kind="both", root=target, scan_corpus=_scan_corpus, clear_semantic=_cleared_semantic)
|
||||
except Exception as exc:
|
||||
print(f"[graphify extract] warning: could not write manifest: {exc}", file=sys.stderr)
|
||||
if global_merge:
|
||||
@@ -3231,6 +3245,7 @@ def dispatch_command(cmd: str) -> None:
|
||||
|
||||
from graphify.export import backup_if_protected as _backup
|
||||
_backup(graphify_out)
|
||||
_invalidate_file_manifest_for_db_graph()
|
||||
# force=True bypasses the #479 shrink guard entirely. A full build
|
||||
# legitimately shrinks (fuzzy dedup collapse, deleted code) so it keeps
|
||||
# force=True — EXCEPT when this run's extraction was incomplete (an
|
||||
@@ -3296,7 +3311,8 @@ def dispatch_command(cmd: str) -> None:
|
||||
from graphify.paths import write_json_atomic as _wja
|
||||
_wja(analysis_path, analysis, indent=2)
|
||||
try:
|
||||
_save_manifest(_manifest_files, manifest_path=str(manifest_path), kind="both", root=target, scan_corpus=_scan_corpus, clear_semantic=_cleared_semantic)
|
||||
if has_path:
|
||||
_save_manifest(_manifest_files, manifest_path=str(manifest_path), kind="both", root=target, scan_corpus=_scan_corpus, clear_semantic=_cleared_semantic)
|
||||
except Exception as exc:
|
||||
print(f"[graphify extract] warning: could not write manifest: {exc}", file=sys.stderr)
|
||||
|
||||
|
||||
@@ -789,6 +789,116 @@ def test_extract_timing_flag_emits_stage_timings(monkeypatch, tmp_path, capsys):
|
||||
assert "graphify timing" not in capsys.readouterr().err
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"postgres_args",
|
||||
[["--postgres", "test-dsn"], ["--postgres=test-dsn"]],
|
||||
)
|
||||
@pytest.mark.parametrize("cluster_args", [[], ["--no-cluster"]])
|
||||
def test_pathless_postgres_extract_initializes_empty_detection(
|
||||
monkeypatch, tmp_path, postgres_args, cluster_args
|
||||
):
|
||||
calls = []
|
||||
|
||||
def _introspect(dsn):
|
||||
calls.append(dsn)
|
||||
return {
|
||||
"nodes": [
|
||||
{
|
||||
"id": "postgresql_users",
|
||||
"label": "users",
|
||||
"type": "table",
|
||||
"file_type": "code",
|
||||
"source_file": "postgresql:/localhost/test",
|
||||
}
|
||||
],
|
||||
"edges": [],
|
||||
}
|
||||
|
||||
corpus = tmp_path / "corpus"
|
||||
corpus.mkdir()
|
||||
(corpus / "app.py").write_text("def app():\n return 1\n")
|
||||
launcher = tmp_path / "launcher"
|
||||
launcher.mkdir()
|
||||
monkeypatch.chdir(launcher)
|
||||
out_root = tmp_path / "output"
|
||||
graph_path = out_root / "graphify-out" / "graph.json"
|
||||
manifest = out_root / "graphify-out" / "manifest.json"
|
||||
monkeypatch.setattr(mainmod, "_check_skill_version", lambda _: None)
|
||||
monkeypatch.setattr("graphify.pg_introspect.introspect_postgres", _introspect)
|
||||
|
||||
def _run(argv):
|
||||
monkeypatch.setattr(mainmod.sys, "argv", argv)
|
||||
try:
|
||||
mainmod.main()
|
||||
except SystemExit as exc:
|
||||
assert exc.code in (None, 0)
|
||||
|
||||
_run(
|
||||
[
|
||||
"graphify",
|
||||
"extract",
|
||||
str(corpus),
|
||||
"--code-only",
|
||||
"--no-cluster",
|
||||
"--out",
|
||||
str(out_root),
|
||||
]
|
||||
)
|
||||
assert manifest.exists()
|
||||
assert "app.py" in _node_sources(graph_path)
|
||||
manifest_content = manifest.read_text()
|
||||
(out_root / "graphify-out" / ".graphify_semantic_marker").write_text(
|
||||
'{"output_tokens": 1}'
|
||||
)
|
||||
|
||||
cache_entry = (
|
||||
out_root
|
||||
/ "graphify-out"
|
||||
/ "cache"
|
||||
/ "semantic"
|
||||
/ "deadbeef.json"
|
||||
)
|
||||
cache_entry.parent.mkdir(parents=True)
|
||||
cache_entry.write_text('{"nodes": [], "edges": []}')
|
||||
_run(
|
||||
[
|
||||
"graphify",
|
||||
"extract",
|
||||
*postgres_args,
|
||||
*cluster_args,
|
||||
"--out",
|
||||
str(out_root),
|
||||
]
|
||||
)
|
||||
assert calls == ["test-dsn"]
|
||||
assert cache_entry.exists()
|
||||
assert not manifest.exists()
|
||||
assert "postgresql:/localhost/test" in _node_sources(graph_path)
|
||||
backups = [
|
||||
path
|
||||
for path in (out_root / "graphify-out").iterdir()
|
||||
if path.is_dir() and (path / "manifest.json").exists()
|
||||
]
|
||||
assert backups
|
||||
assert backups[0].joinpath("manifest.json").read_text() == manifest_content
|
||||
|
||||
_run(
|
||||
[
|
||||
"graphify",
|
||||
"extract",
|
||||
str(corpus),
|
||||
"--code-only",
|
||||
"--no-cluster",
|
||||
"--out",
|
||||
str(out_root),
|
||||
]
|
||||
)
|
||||
final_sources = _node_sources(graph_path)
|
||||
assert "app.py" in final_sources
|
||||
assert "postgresql:/localhost/test" not in final_sources
|
||||
assert manifest.exists()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# #1909: a newly-excluded file's nodes must be pruned from graph.json on the
|
||||
# next incremental extract even when the manifest never listed the file (the
|
||||
|
||||
Reference in New Issue
Block a user