Conversation
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/82628923-30ee-4061-af73-61b141aba2e4 Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
…rsal
Fixes `gh aw init` failing with "not in a git repository" on macOS ARM64
(Apple Silicon) when the x86_64 binary runs under Rosetta 2.
Previously, `isGitRepo()` and `FindGitRoot()` used `exec.Command("git", ...)`
to detect git repositories. Under Rosetta 2 (x86_64 emulation on ARM64), this
subprocess call can silently fail due to PATH differences or OS-level subprocess
restrictions.
Replace with pure Go filesystem traversal: walk up from the current directory
(or a given starting directory) looking for a `.git` entry (directory or file,
handling both normal repos and worktrees). This eliminates the dependency on
the `git` executable for repository detection, making it work regardless of
architecture, Rosetta translation, or git installation state.
Changes:
- `pkg/gitutil/gitutil.go`: `FindGitRoot()` now uses `os.Stat`/`filepath.Dir`
traversal; new exported `FindGitRootFrom(startDir)` helper for callers that
start from a specific directory
- `pkg/cli/git.go`: `isGitRepo()` delegates to `gitutil.FindGitRoot()`;
`findGitRootForPath()` uses `gitutil.FindGitRootFrom(dir)` instead of exec
- `pkg/gitutil/gitutil_test.go`: add `TestFindGitRootFrom` tests
- `pkg/gitutil/spec_test.go`: update doc comment to reflect new implementation
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/82628923-30ee-4061-af73-61b141aba2e4
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
…t robustness Agent-Logs-Url: https://github.com/github/gh-aw/sessions/82628923-30ee-4061-af73-61b141aba2e4 Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Updates git repository detection to avoid invoking the git executable (addressing macOS ARM64 Rosetta 2 failures) by switching to filesystem-based traversal and centralizing the logic in pkg/gitutil.
Changes:
- Replaced
FindGitRoot()implementation to locate repo roots by walking up the directory tree looking for a.gitentry. - Added
FindGitRootFrom(startDir)and updated CLI git-repo detection helpers to usegitutilinstead of subprocess calls. - Added tests for
FindGitRootFromand updated the public API spec text accordingly; lockfile workflows were also modified.
Show a summary per file
| File | Description |
|---|---|
| pkg/gitutil/gitutil.go | Implements filesystem-based git root discovery and adds FindGitRootFrom. |
| pkg/cli/git.go | Switches repo detection/root lookup to gitutil.FindGitRoot* helpers. |
| pkg/gitutil/gitutil_test.go | Adds test coverage for FindGitRootFrom. |
| pkg/gitutil/spec_test.go | Updates the spec wording for FindGitRoot to match new behavior. |
| .github/workflows/spec-librarian.lock.yml | Updates pinned action version annotations/manifest metadata (now inconsistent in-file). |
| .github/workflows/copilot-pr-nlp-analysis.lock.yml | Updates pinned action version annotations/manifest metadata (now inconsistent/duplicated in-file). |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (3)
.github/workflows/spec-librarian.lock.yml:470
- This step is annotated as
# v9while otheractions/github-scriptsteps in the same lockfile are annotated# v9.0.0(e.g., line 452). Please keep the version annotations consistent (ideally by regenerating the lockfile) to avoid confusion and drift.
- name: Determine automatic lockdown mode for GitHub MCP Server
id: determine-automatic-lockdown
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
.github/workflows/copilot-pr-nlp-analysis.lock.yml:53
- The "Custom actions used" section now lists the same
actions/github-scriptSHA twice with different versions (v9andv9.0.0). This looks like an inconsistent regeneration and should be deduplicated/standardized so the lockfile accurately describes what is pinned.
# - actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
.github/workflows/copilot-pr-nlp-analysis.lock.yml:522
- This step is annotated as
# v9while otheractions/github-scriptsteps in the same lockfile are annotated# v9.0.0. Please keep version annotations consistent (ideally via lockfile regeneration) to avoid drift.
- name: Determine automatic lockdown mode for GitHub MCP Server
id: determine-automatic-lockdown
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
- Files reviewed: 6/6 changed files
- Comments generated: 4
| func TestFindGitRootFrom(t *testing.T) { | ||
| t.Run("returns git root from the repository root itself", func(t *testing.T) { | ||
| gitRoot, err := FindGitRoot() | ||
| require.NoError(t, err, "must be inside a git repository") | ||
|
|
| @@ -1,5 +1,5 @@ | |||
| # gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"b21c866096e7bf37ad8390647a4e60737201a07a362b4a013fe73ebdfe63b049","strict":true,"agent_id":"copilot"} | |||
| # gh-aw-manifest: {"version":1,"secrets":["GH_AW_AGENT_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41","digest":"sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41@sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"ghcr.io/github/serena-mcp-server:latest","digest":"sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5","pinned_image":"ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} | |||
| # gh-aw-manifest: {"version":1,"secrets":["GH_AW_AGENT_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41","digest":"sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.41@sha256:62171f2fa508667b8b0a9e096f826983f312e3da0ce894f80c0f83a875af60fe"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"ghcr.io/github/serena-mcp-server:latest","digest":"sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5","pinned_image":"ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} | |||
| @@ -1,5 +1,5 @@ | |||
| # gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"e680d07d85ca99dc6dc3ee4be59cdb3c9d1c49e7bf28efa85f1641c408445d8c","strict":true,"agent_id":"copilot"} | |||
| # gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} | |||
| # gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_ENDPOINT","GH_AW_OTEL_HEADERS","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41","digest":"sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.41@sha256:cb2b565d070116d4b67e355775340528b5a2c3cb18b2c9049638bcc2df681770"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41","digest":"sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.41@sha256:fadd0de387209f69a9a7a1b8722bb5e7fdfb80ba9749a5c60f0e4cd7582a74d0"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41","digest":"sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.41@sha256:1260445d25968dbf3ae70143964177a0e5914cf2ce07a6117f7d3caec6c3e3c4"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} | |||
| func FindGitRootFrom(startDir string) (string, error) { | ||
| dir := startDir | ||
| for { | ||
| if _, err := os.Stat(filepath.Join(dir, ".git")); err == nil { | ||
| return dir, nil | ||
| } | ||
| parent := filepath.Dir(dir) |
🧪 Test Quality Sentinel ReportTest Quality Score: 90/100✅ Excellent test quality
Test Classification DetailsThe PR modifies View per-test classification table
Flagged Tests — Requires Reviewi️
|
| Component | Points | Notes |
|---|---|---|
| Behavioral Coverage (40 pts) | 40 | 3/3 tests are design tests (100%) |
| Error/Edge Case Coverage (30 pts) | 20 | 2/3 top-level functions explicitly test error paths |
| Low Duplication (20 pts) | 20 | No copy-paste clusters detected |
| Proportional Growth (10 pts) | 10 | Test:prod ratio = 1.06 (well below 2:1 threshold) |
Language Support
Tests analyzed:
- 🐹 Go (
*_test.go): 7 subtests across 3 functions — unit (//go:build !integration) ✅ - 🟨 JavaScript (
*.test.cjs,*.test.js): 0 tests changed in this PR
Verdict
✅ Check passed. 0% of new tests are implementation tests (threshold: 30%). Build tags are present on all new/modified test files. No mock libraries detected. All tests exercise observable behavioral contracts of the new pure-Go git root detection.
📖 Understanding Test Classifications
Design Tests (High Value) verify what the system does:
- Assert on observable outputs, return values, or state changes
- Cover error paths and boundary conditions
- Would catch a behavioral regression if deleted
- Remain valid even after internal refactoring
Implementation Tests (Low Value) verify how the system does it:
- Assert on internal function calls (mocking internals)
- Only test the happy path with typical inputs
- Break during legitimate refactoring even when behavior is correct
- Give false assurance: they pass even when the system is wrong
Goal: Shift toward tests that describe the system's behavioral contract — the promises it makes to its users and collaborators.
References: §25568904322
🧪 Test quality analysis by Test Quality Sentinel · ● 7.3M · ◷
There was a problem hiding this comment.
✅ Test Quality Sentinel: 90/100. Test quality is excellent — 0% of new tests are implementation tests (threshold: 30%). All 7 new subtests exercise behavioral contracts of the new pure-Go git root detection. Build tags present, no mock libraries used.
|
@copilot merge main and recompile |
…t-error Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Done — merged latest |
|
@copilot add integration tests for git repos and worktrees |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Done in the latest commit. Added four new test cases to
Also fixed |
gh aw init(and any command callingisGitRepo()/FindGitRoot()) fails with "not in a git repository" on macOS ARM64 when the x86_64 binary runs under Rosetta 2 — theexec.Command("git", "rev-parse", ...)subprocess call silently fails in that environment even when the user is inside a valid git repo.Changes
pkg/gitutil/gitutil.go— ReplaceFindGitRoot()implementation: swapexec.Command("git", "rev-parse", "--show-toplevel")foros.Stat+filepath.Dirupward traversal.FindGitRootFrom(startDir string)now normalizesstartDirto an absolute path viafilepath.Abs, surfaces non-ErrNotExiststat errors (e.g. permission denied), and validates.gitas either a directory (normal repo) or a regular file beginning withgitdir:(worktree / submodule pointer) — surfacing read errors instead of silently skipping an unreadable.gitfile.pkg/cli/git.go—isGitRepo()now delegates togitutil.FindGitRoot()instead of its ownexec.Command("git", "rev-parse", "--git-dir")call.findGitRootForPath()usesgitutil.FindGitRootFrom(dir).pkg/gitutil/gitutil_test.go—TestFindGitRootFromextended to cover: start from repo root, start from nested subdir, start outside any repo,.gitis a valid worktree marker file (detected from root and subdirectory),.gitfile withoutgitdir:prefix is not accepted, and relative path input (".") resolves correctly.All actual git operations (commit, push, status, add, log) still invoke the
gitbinary — only repository detection is changed.