Skip to content

fix: make git integration robust to renames, non-ASCII paths, and cwd - #26

Open
KEY60228 wants to merge 1 commit into
mainfrom
fix/git-diff-robustness
Open

fix: make git integration robust to renames, non-ASCII paths, and cwd#26
KEY60228 wants to merge 1 commit into
mainfrom
fix/git-diff-robustness

Conversation

@KEY60228

Copy link
Copy Markdown
Owner

Summary

Reworks the git module around vim.system() argv calls executed with git -C <root>, fixing five failure modes found in a full-project review:

  • Renamed/copied files: --name-status rename lines (R100\told\tnew) were parsed as a single bogus path with status "R100", breaking diff retrieval, the file tree, and Markdown output. Now parsed via NUL-separated -z output; rename diffs pass both paths as pathspec so git pairs them, and Markdown shows Renamed from <old>.
  • Non-ASCII filenames (e.g. Japanese): with default core.quotepath, paths were stored as octal-escaped quoted strings that matched nothing. -z output is unquoted raw bytes, so they now work regardless of the setting.
  • cwd independence: all commands run with git -C <root>, so per-file pathspecs resolve correctly when Neovim is started in a subdirectory. Previously the empty diff silently triggered the --no-index fallback and displayed tracked files as full additions.
  • Staged changes: no-argument :ReviewThemStart now diffs HEAD against the working tree (falling back to the index diff in unborn repos), so staged edits are reviewable as the docs describe.
  • --no-index fallback: only applied to files explicitly flagged as untracked by ls-files, instead of firing whenever a diff came back empty.

get_file_diff now takes the DiffFile entry (bare paths still accepted for compatibility). Docs updated to describe the merge-base semantics of the base-only form and the staged/untracked coverage of the no-argument form.

Test plan

Verified with a headless-nvim script against a fixture repo (rename commit, Japanese filenames, staged + untracked files, run from a subdirectory): all 13 checks pass, including rename parse (status=R, old_path set), unquoted Japanese paths, staged file inclusion, per-file hunks from a subdirectory, no --no-index misfire for tracked files, and end-to-end session.create.

🤖 Generated with Claude Code

Rework the git module around vim.system() argv calls executed with
`git -C <root>`, fixing several failure modes:

- Renamed/copied files: parse `--name-status -z` NUL-separated output,
  which emits two paths for R/C entries. Previously the tab-separated
  pair was captured as a single bogus path and the status kept its
  score suffix ("R100"), breaking diff retrieval, the file tree, and
  Markdown output. Rename diffs now pass both paths as pathspec so git
  can pair them, and Markdown labels show "Renamed from <old>".
- Non-ASCII filenames: -z output is unquoted raw bytes, so paths like
  日本語.txt survive regardless of core.quotepath (previously stored
  as octal-escaped quoted strings that matched nothing).
- cwd independence: all commands run with `git -C <root>`, so per-file
  pathspecs resolve correctly when Neovim is started in a subdirectory
  (previously the empty diff triggered the --no-index fallback and
  displayed tracked files as full additions).
- Staged changes: the no-argument diff now compares HEAD to the
  working tree (falling back to the index diff in unborn repos), so
  staged edits are reviewable as documented.
- --no-index fallback: only applied to files explicitly flagged as
  untracked by ls-files, instead of firing whenever a diff came back
  empty.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant