From caa6f9edb93938abb3841dd2239c1ada6c2915a4 Mon Sep 17 00:00:00 2001 From: safishamsi Date: Sat, 18 Jul 2026 12:09:08 +0100 Subject: [PATCH] fix(extract): persist --no-gitignore instead of clobbering it (follow-up to #1979) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PR always wrote gitignore=not no_gitignore into .graphify_build.json, so a flag-less `graphify extract` after `--no-gitignore` reset it to True and the git-ignored code silently disappeared again — the exact #1971 complaint. Write False only when the flag is set (None = leave as-is, mirroring #1886 excludes), and honor the persisted value for the run when the flag is absent. Co-Authored-By: Claude Opus 4.8 (1M context) --- graphify/cli.py | 19 +++++++++++++++---- tests/test_extract_code_only_cli.py | 27 +++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/graphify/cli.py b/graphify/cli.py index 1748108..7740342 100644 --- a/graphify/cli.py +++ b/graphify/cli.py @@ -2501,11 +2501,22 @@ def dispatch_command(cmd: str) -> None: graphify_out.mkdir(parents=True, exist_ok=True) # Persist corpus-shaping options so later update/watch/hook rebuilds # use the same file set as the initial extraction (#1886). - from graphify.watch import _write_build_config as _write_build_cfg + from graphify.watch import ( + _write_build_config as _write_build_cfg, + _read_build_gitignore as _read_build_gi, + ) + # #1971 persistence: an explicit --no-gitignore persists False; a later + # flag-less `graphify extract` must NOT clobber it back to True, which + # would make the git-ignored code silently disappear again (the exact + # complaint #1971 is about). Honor the persisted value for THIS run when + # the flag is absent (read before the write below), and write False only + # when the flag is set — None leaves the setting as-is, mirroring how + # #1886 persists --exclude. + _effective_gitignore = False if no_gitignore else _read_build_gi(graphify_out) _write_build_cfg( graphify_out, excludes=cli_excludes or None, - gitignore=not no_gitignore, + gitignore=False if no_gitignore else None, ) stages = _StageTimer(cli_timing) @@ -2555,7 +2566,7 @@ def dispatch_command(cmd: str) -> None: manifest_path=str(manifest_path), google_workspace=google_workspace or None, extra_excludes=cli_excludes or None, - gitignore=not no_gitignore, + gitignore=_effective_gitignore, ) files_by_type = detection.get("files", {}) new_by_type = detection.get("new_files", {}) @@ -2583,7 +2594,7 @@ def dispatch_command(cmd: str) -> None: google_workspace=google_workspace or None, extra_excludes=cli_excludes or None, cache_root=out_root, - gitignore=not no_gitignore, + gitignore=_effective_gitignore, ) files_by_type = detection.get("files", {}) code_files = [Path(p) for p in files_by_type.get("code", [])] diff --git a/tests/test_extract_code_only_cli.py b/tests/test_extract_code_only_cli.py index 1c27d9b..af92471 100644 --- a/tests/test_extract_code_only_cli.py +++ b/tests/test_extract_code_only_cli.py @@ -80,3 +80,30 @@ def test_no_gitignore_indexes_vcs_ignored_code_but_keeps_graphifyignore(tmp_path assert any(source.endswith("proj/deep/generated/Gen.cs") for source in sources) assert any(source.endswith("local/Local.cs") for source in sources) assert not any(source.endswith("proj/hidden/Hidden.cs") for source in sources) + + +def test_no_gitignore_setting_persists_across_flagless_extract(tmp_path): + """#1971 persistence: once --no-gitignore is set, a later flag-less + `graphify extract` must NOT clobber it back to honoring .gitignore (which + would make the git-ignored code silently disappear again).""" + repo = tmp_path / "repo" + gen = repo / "generated" + gen.mkdir(parents=True) + (repo / ".gitignore").write_text("generated/\n") + (repo / "app.py").write_text("def hello():\n return 1\n") + (gen / "Gen.py").write_text("def gen():\n return 2\n") + + def _sources(): + g = json.loads((repo / "graphify-out" / "graph.json").read_text()) + return {Path(str(n.get("source_file", ""))).as_posix() for n in g["nodes"]} + + r1 = _run(repo, "--no-gitignore", "--code-only", "--no-cluster") + assert r1.returncode == 0, r1.stderr + assert any(s.endswith("generated/Gen.py") for s in _sources()) + + # A plain flag-less re-extract must keep the git-ignored file (setting persisted). + r2 = _run(repo, "--code-only", "--no-cluster") + assert r2.returncode == 0, r2.stderr + assert any(s.endswith("generated/Gen.py") for s in _sources()), ( + "flag-less re-extract clobbered the persisted --no-gitignore setting (#1971)" + )