Clones fail on Windows-invalid paths (chars, reserved names, too-long) that are fine on Linux #2

Closed
opened 2026-07-03 13:58:55 +00:00 by KofTwentyTwo · 1 comment
KofTwentyTwo commented 2026-07-03 13:58:55 +00:00 (Migrated from github.com)

Owner-reported: frequent real-world failures. Repos containing paths that are legal in git but invalid on Windows (trailing spaces/dots, invalid characters, reserved device names like CON/NUL, case-only filename collisions, or paths exceeding MAX_PATH) currently fail checkout with a raw LibGit2SharpException.

Plan (spec agreed with owner)

Phase 1 — quick win (path length): switch clones to two-phase (Checkout = false, then explicit checkout), setting core.longpaths=true in the repo config before any file touches disk. Should eliminate the "filename or folder too long" class outright.

Phase 2 — validation & recovery:

  • After the no-checkout clone, walk the HEAD tree validating every path: Path.GetInvalidFileNameChars, trailing space/dot, reserved names (CON, PRN, AUX, NUL, COM1-9, LPT1-9), segment length, case-insensitive collisions, and full destination path length (target root + repo path).
  • Return a structured result (InvalidPathInfo { RepoPath, Reason, SuggestedSanitizedName }) instead of throwing; happy path proceeds to normal checkout.
  • Recovery contract for UI/CLI: Rename (editable suggested name), Skip, Abort (Clone-in-WSL verb reserved, see the deferred issue). Rename/skip apply a mapping via manual blob materialization (blob.GetContentStream(new FilteringOptions(path)) so .gitattributes filters apply).
  • Mapped repos are flagged: future updates fetch + re-materialize instead of fast-forward merge (the working tree intentionally diverges from the index), with a clear status.
  • Abort keeps the existing didn't-exist-before directory cleanup. Log invalid-path counts and chosen recovery action (no sensitive content).

Tests / acceptance

  • Fixture repos with offending tree entries built via ObjectDatabase plumbing (such files cannot be created on a Windows working tree).
  • No LibGit2SharpException bubbles to the UI for invalid paths; structured list returned; mapping produces a usable working tree; valid repos are unaffected.

Known limitation to document alongside: LibGit2Sharp 0.31's CloneOptions has no cancelable checkout callback, so cancellation covers transfer/indexing but not the final checkout phase.

**Owner-reported: frequent real-world failures.** Repos containing paths that are legal in git but invalid on Windows (trailing spaces/dots, invalid characters, reserved device names like CON/NUL, case-only filename collisions, or paths exceeding MAX_PATH) currently fail checkout with a raw `LibGit2SharpException`. ## Plan (spec agreed with owner) **Phase 1 — quick win (path length):** switch clones to two-phase (`Checkout = false`, then explicit checkout), setting `core.longpaths=true` in the repo config before any file touches disk. Should eliminate the "filename or folder too long" class outright. **Phase 2 — validation & recovery:** - After the no-checkout clone, walk the HEAD tree validating every path: `Path.GetInvalidFileNameChars`, trailing space/dot, reserved names (CON, PRN, AUX, NUL, COM1-9, LPT1-9), segment length, case-insensitive collisions, and full destination path length (target root + repo path). - Return a structured result (`InvalidPathInfo { RepoPath, Reason, SuggestedSanitizedName }`) instead of throwing; happy path proceeds to normal checkout. - Recovery contract for UI/CLI: **Rename** (editable suggested name), **Skip**, **Abort** (Clone-in-WSL verb reserved, see the deferred issue). Rename/skip apply a mapping via manual blob materialization (`blob.GetContentStream(new FilteringOptions(path))` so .gitattributes filters apply). - Mapped repos are flagged: future updates fetch + re-materialize instead of fast-forward merge (the working tree intentionally diverges from the index), with a clear status. - Abort keeps the existing didn't-exist-before directory cleanup. Log invalid-path counts and chosen recovery action (no sensitive content). ## Tests / acceptance - Fixture repos with offending tree entries built via `ObjectDatabase` plumbing (such files cannot be created on a Windows working tree). - No `LibGit2SharpException` bubbles to the UI for invalid paths; structured list returned; mapping produces a usable working tree; valid repos are unaffected. Known limitation to document alongside: LibGit2Sharp 0.31's `CloneOptions` has no cancelable checkout callback, so cancellation covers transfer/indexing but not the final checkout phase.
KofTwentyTwo commented 2026-07-03 15:43:55 +00:00 (Migrated from github.com)

Fixed end to end: core.longpaths + pre-checkout validation (phase 1, shipped in beta.2) and rename/skip recovery with GUI dialog + CLI --sanitize-paths (phase 2, PR #17). WSL verb remains tracked in #8.

Fixed end to end: core.longpaths + pre-checkout validation (phase 1, shipped in beta.2) and rename/skip recovery with GUI dialog + CLI --sanitize-paths (phase 2, PR #17). WSL verb remains tracked in #8.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: KofTwentyTwo/gclo#2