Skip to content

fix: allow non-git directories to be added as projects#2173

Open
bendavid wants to merge 1 commit into
getpaseo:mainfrom
bendavid:fix/non-git-project-add
Open

fix: allow non-git directories to be added as projects#2173
bendavid wants to merge 1 commit into
getpaseo:mainfrom
bendavid:fix/non-git-project-add

Conversation

@bendavid

Copy link
Copy Markdown

Problem

Adding a non-git folder via "Add project" fails with a generic "Unable to add project" error. Non-git directories are supposed to be supported as projects — the server creates non_git projects, the app handles isGit: false throughout, and there's an e2e test (project-becomes-git.e2e.test.ts) that verifies non-git projects work and can be upgraded to git later.

Root cause

getWorktreeRoot in checkout-git.ts detected non-git directories by regex-matching git's stderr error message via isNotGitRepositoryError. The regex expected:

not a git repository (or any of the parent directories): .git

But git 2.55+ changed the message to:

not a git repository (or any parent up to mount point /)
Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).

The regex no longer matched, so the error was re-thrown instead of returning null. This propagated through getCheckoutfindOrCreateProjectForDirectoryhandleProjectAddRequest, causing every non-git project add to fail.

Fix

Replace the regex-based isNotGitRepositoryError with a programmatic exit-code check. git rev-parse --show-toplevel exits with code 128 when the cwd is not inside a git repository — this is a stable contract, not human-readable text that changes between versions.

const result = await runGitCommand(["rev-parse", "--show-toplevel"], {
  cwd,
  envOverlay: READ_ONLY_GIT_ENV,
  logger: context?.logger,
  acceptExitCodes: [0, 128],
});
if (result.exitCode !== 0) {
  return null;
}
return parseGitRevParsePath(result.stdout);

The acceptExitCodes pattern is already used throughout the codebase (e.g. acceptExitCodes: [0, 1] for ref verification). Removed the now-unused isNotGitRepositoryError function.

Verification

  • All 121 checkout-git.test.ts tests pass.
  • All 22 checkout-git-rev-parse.test.ts + workspace-git-service.test.ts tests pass.
  • Typecheck, lint, and format clean.
  • Confirmed git rev-parse --show-toplevel exits 128 for non-git dirs and 0 for git dirs on git 2.55.0.
  • Reproduced the original error via client.addProject("/tmp/paseo-non-git-test") before the fix; the fix resolves it.

getWorktreeRoot used isNotGitRepositoryError to detect non-git
directories by regex-matching git's stderr text. Git 2.55+ changed the
'not a git repository' error message, breaking the regex and causing
all non-git directory project adds to fail with a generic error.

Replace the regex approach with a programmatic exit-code check:
git rev-parse --show-toplevel exits 128 when not in a git repository.
Use acceptExitCodes: [0, 128] and check the exit code directly, which
is stable across git versions and doesn't depend on human-readable
error text.

Remove the now-unused isNotGitRepositoryError function.
@greptile-apps

greptile-apps Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a regression where adding non-git directories as projects silently failed because git rev-parse --show-toplevel's "not a git repository" error message changed in git 2.55+, breaking the regex in isNotGitRepositoryError. The fix replaces text-matching with a programmatic exit-code check (exitCode === 128), which is a stable contract that does not vary between git versions.

  • Removes isNotGitRepositoryError and its fragile regex; replaces it with acceptExitCodes: [0, 128] in getWorktreeRoot, consistent with the pattern already used throughout this file for show-ref, rev-parse --verify, and check-ref-format.
  • The return type of runGitCommand is now used directly (result.exitCode, result.stdout) instead of the destructured { stdout } from the try block, making the happy and error paths explicit.

Confidence Score: 5/5

Safe to merge — minimal, targeted fix to a broken code path regressing since git 2.55.

One function changed, one dead helper removed. The acceptExitCodes pattern is already used in at least six other call sites in the same file. The removed regex never matched on git 2.55+ so the new code only widens correctly-handled cases. No new branches, no new interfaces, no structural changes.

No files require special attention.

Important Files Changed

Filename Overview
packages/server/src/utils/checkout-git.ts Replaces fragile regex-based git error detection in getWorktreeRoot with a programmatic exit-code check using the established acceptExitCodes: [0, 128] pattern; removes the now-dead isNotGitRepositoryError helper.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[handleProjectAddRequest] --> B[findOrCreateProjectForDirectory]
    B --> C[getCheckout]
    C --> D[getWorktreeRoot\ncwd, context]

    D --> E["runGitCommand\n['rev-parse', '--show-toplevel']\nacceptExitCodes: [0, 128]"]

    E -- "exitCode = 0" --> F["return parseGitRevParsePath(result.stdout)\n→ git root path"]
    E -- "exitCode = 128\n(not a git repo)" --> G["return null\n→ non_git project"]
    E -- "other exit code or signal" --> H["throws Error\n→ propagates up"]

    F --> I[git project created]
    G --> J[non_git project created]
    H --> K[error surfaced to user]

    style G fill:#90EE90
    style F fill:#90EE90
    style H fill:#FFB6C1
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[handleProjectAddRequest] --> B[findOrCreateProjectForDirectory]
    B --> C[getCheckout]
    C --> D[getWorktreeRoot\ncwd, context]

    D --> E["runGitCommand\n['rev-parse', '--show-toplevel']\nacceptExitCodes: [0, 128]"]

    E -- "exitCode = 0" --> F["return parseGitRevParsePath(result.stdout)\n→ git root path"]
    E -- "exitCode = 128\n(not a git repo)" --> G["return null\n→ non_git project"]
    E -- "other exit code or signal" --> H["throws Error\n→ propagates up"]

    F --> I[git project created]
    G --> J[non_git project created]
    H --> K[error surfaced to user]

    style G fill:#90EE90
    style F fill:#90EE90
    style H fill:#FFB6C1
Loading

Reviews (1): Last reviewed commit: "fix: allow non-git directories to be add..." | Re-trigger Greptile

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