Skip to content

fix: git-ignore-block.sh writes an exclude target only inside a real git dir (#431) - #448

Merged
kiki830621 merged 3 commits into
mainfrom
idd/431-git-ignore-block-sh-target-allowlist-inf
Oct 31, 2026
Merged

kiki830621 merged 3 commits into
mainfrom
idd/431-git-ignore-block-sh-target-allowlist-inf

Conversation

@kiki830621

Copy link
Copy Markdown
Member

Refs #431

Summary

scripts/git-ignore-block.sh 的 #194 allowlist 只比對 target 的 basename,任何 <dir>/exclude 都會被寫入,mkdir -p 還會建出父目錄;呼叫端的 "$(git rev-parse --git-dir)/info/exclude" 在任何 repository 之外會變成 /info/exclude。

  • exclude target 現在必須是 <D>/info/exclude:<D> 是目錄,且 git --git-dir=<D> rev-parse --git-dir 成功;含控制字元的 --target 會先被拒絕($(dirname …) 會剝掉結尾換行)。不符合的一律在任何寫入之前 exit 2
  • 合法的 target 都仍被接受:相對與絕對的 .git/info/exclude、子目錄、linked worktree 的 git dir、bare repo、submodule 的 .git/modules/<m>、--git-path info/exclude,以及 PR 修復附件失敗、skill 路徑與 runtime ignore #402 新增的 runtime-ignore.sh 呼叫
  • Test 10 共 15 項:空 git-dir、非 git 目錄、hooks/exclude、任意 <dir>/exclude、換行、gitfile,以及相對路徑仍會生效。測試的暫存 repo 統一放在同一個 mktemp root;repo 建不起來時整個測試會停下,不會寫到 /

Verification

Claude-only verification PASS(雲端 session,沒有跑 Codex 那一條,屬於降級驗證)。詳見 issue #431 的 Verify comment:#431 (comment)

  • git-ignore-block 41/41、stage45-carveout-migration 23/23、correction-archive、correct-flow 全過
  • run-all-tests.sh:idd-repo-map、idd-tree-lock 失敗,在乾淨的 main 上以 root 執行也一樣會失敗,與本 PR 無關

Checklist

  • Diagnose ✓
  • Implement(3 commits)
  • Verify ✓
  • Verify-gated: verify PASS — ready to merge → after merge, run /idd-close to finalize this issue (manual gate + closing summary; no auto-close trailer)

Related


🤖 Generated by /idd-all. Do NOT add a GitHub close trailer (Closes/Fixes/Resolves) — IDD discipline requires manual /idd-close after merge to enforce checklist gate + closing summary.


Generated by Claude Code

…git dir (#431)

The #194 allowlist checked the basename alone, so any <dir>/exclude passed
and mkdir -p created its parents — including /info/exclude, which the
callers' "$(git rev-parse --git-dir)/info/exclude" becomes outside a work
tree. An exclude target must now be <D>/info/exclude where
`git --git-dir=<D> rev-parse --git-dir` succeeds; anything else exits 2
before any write. Test 10 covers the empty git-dir, a non-git info/, a
<git-dir>/hooks/exclude, an arbitrary <dir>/exclude, and the relative
.git/info/exclude the callers pass from the top level.

Refs #431

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TdBi8k2uM27M7TAdunMnmo
…achment manifest

Refs #431

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TdBi8k2uM27M7TAdunMnmo
…test harness guards (#431)

From the /idd-verify report on #431 (all In-scope, no blocking):
- refuse a --target containing a control character before the allowlist:
  `$(dirname …)` strips trailing newlines, so `<git-dir>⏎/info/exclude`
  passed the probe while the write landed in a non-git `.git⏎/` directory
- require the git dir to be a directory: `git --git-dir` follows a .git
  FILE's gitdir: line, and nothing can be written under a file
- test: every throwaway repo lives under one mktemp root removed on EXIT,
  and a repo that cannot be created stops the run (with R="" the old tests
  wrote to /.gitignore and /.git/info/exclude)
- test: the /info/exclude case reports SKIP instead of vanishing when /info
  exists, and still runs when /info/exclude holds only this test's block
- CHANGELOG: "outside any repository", not "outside a work tree"

Refs #431

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TdBi8k2uM27M7TAdunMnmo
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.

2 participants