fix(git): resolve canonical_root '..' components for worktree git_common_dir#696
fix(git): resolve canonical_root '..' components for worktree git_common_dir#696lg320531124 wants to merge 1 commit into
Conversation
e777d0f to
58ce88c
Compare
|
Huge thanks for opening this PR and for the work you put into it. The maintainer shop is currently full, so this may sit for a bit before it gets a proper review. We will come back to this as soon as possible with real feedback; I wanted to make sure it did not sit unacknowledged in the meantime. |
58ce88c to
8fbcd5d
Compare
|
Thanks, this looks focused. Before merge, please rewrite the commit metadata to remove generated/co-author/session attribution. DCO otherwise appears to be present on the non-merge commit. |
…on_dir When git_common_dir is a relative path like '../.git', join_root_relative produces '/workspace/../.git'. After stripping '/.git', the result is '/workspace/..' which resolves to the PARENT directory instead of the workspace root. This caused detect_changes to return empty impacted_symbols because the path-prefix mismatch between git diff output and graph file paths. Add realpath() call after stripping '/.git' to resolve any remaining '..' components. Falls back to the un-resolved path if realpath fails (e.g. non-existent path during testing). Fixes DeusData#690, fixes DeusData#659 Signed-off-by: lg320531124 <lg320531124@users.noreply.github.com>
8fbcd5d to
cc8344a
Compare
|
Done — rewrote the commit metadata to drop the |
|
Thanks, confirmed the metadata cleanup. Current checks and DCO are green; this is back in the maintainer review queue. |
|
Thank you @lg320531124 — you correctly spotted that unresolved The catch: this resolves the path after stripping #672 (from @anivaryam) changes the join base to the input path and normalizes before the strip, fixing both the subdirectory and linked-worktree cases. We've landed that approach as a distilled follow-up (#749) with a cross-platform test guard. Closing this one as superseded in favor of the more complete fix — genuinely appreciate the contribution and the correct diagnosis of the |
detect_changes returned an empty impacted_symbols set for projects indexed inside a git worktree or from a repo subdirectory (DeusData#659): canonical_root was computed wrong. `git rev-parse --git-common-dir` emits a path relative to the directory passed via -C (input_path), NOT to worktree_root, and the "/.git" suffix was stripped textually without resolving ".." components. So e.g. "../.git" joined against worktree_root, or "/ws/scripts/../.git" strip, left an unresolved ".." and never matched the project's stored root path. Fix (src/git/git_context.c): join the relative --git-common-dir against input_path (the -C dir) instead of worktree_root, and realpath()/_fullpath()- normalize the result BEFORE stripping "/.git" (the .git dir always exists for a valid repo, so resolution succeeds). This is consistent with the existing realpath'd root_path used for prefix matching (mcp.c). Reproduce-first: tests/test_git_context.c. The subdirectory case is the genuine guard — a repo indexed from a subdir yields a *relative* --git-common-dir, so the unfixed code leaves an un-normalized "<root>/subdir/.." (verified RED; GREEN after the realpath fix). The linked-worktree case is a supporting invariant, not the DeusData#659 reproducer: git that emits an *absolute* worktree --git-common-dir (e.g. 2.48.x) doesn't manifest the bug, so it passes either way; it still enforces the worktree->main-root invariant. All three git-based tests SKIP_PLATFORM on Windows (the CI shell there cannot init a repo via system()). Distilled from DeusData#672 (thanks @anivaryam); that PR's production fix is taken verbatim. Its repo_root/subdir tests ran git unconditionally and failed the Windows CI leg ("failed to init git repo"); here all three git-based tests are Windows-skipped so ci-ok is green cross-platform. Supersedes DeusData#696, which only realpath'd after the strip without changing the join base and so still yielded the workspace parent for the subdirectory case. Closes DeusData#659 Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com> Co-Authored-By: anivaryam <anivaryam.dev@gmail.com>
What Problem This Solves
When a project is inside a git worktree and
git_common_diris a relative path (e.g.../.git),derive_canonical_rootjoins it withworktree_rootproducing/workspace/../.git. After stripping the/.gitsuffix, the result is/workspace/..whichrealpath-resolves to the parent directory, not the workspace root.This caused
detect_changesto return emptyimpacted_symbolsbecause the canonical root path prefix mismatch meant git diff paths could not be matched to graph file paths.Example from #659:
/Users/openclaw/.openclaw/workspace/canonical_root:/Users/openclaw/(one..too many)scripts/solar_daily_report_v1.pysolar_daily_report_v1.py(relative to root_path)Why This Change Was Made
Added
realpath()call after stripping/.gitto resolve any remaining..path components. This normalizes/workspace/..→/parent_of_workspacecorrectly, matching the actual git repository root.Falls back to the un-resolved path if
realpath()fails (e.g. path doesn't exist during testing).Evidence
canonical_root=/Users/lg/project/(parent dir)canonical_root=/Users/lg/project/codebase-memory-mcp(correct git root)detect_changesnow returns correctimpacted_symbolsfor worktree projectsFixes #690, fixes #659