block / block/buzz

desktop: Windows Projects repo browser fails for any repo with paths over MAX_PATH — git config is neutralized without core.longpaths

Open
#5,989 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
32.7k
Forks
4.3k
Avg merge
1d 13h
Merged PRs (30d)
253

Description

## Summary

On Windows, the Projects repo browser cannot load any repository containing a path longer than `MAX_PATH` (260). `configure_git_auth` deliberately neutralizes system and global git config, but the injected replacement config does not include `core.longpaths`, so the user's `core.longpaths=true` is unreachable from Desktop by design. The snapshot clone then dies during checkout, and the resulting error text matches nothing in `projectRepoUnavailableReason`, so the panel renders the generic **"Repository unavailable"** with no indication that the cause is a fixable local git setting.

Net effect: a Windows user with a deep-path repo sees the repo listed in Projects, an empty panel, and no actionable reason. `grep -in longpath` over `main` (`78cbffe`) returns nothing — there is no long-path handling anywhere in the tree.

## Root cause

`desktop/src-tauri/src/commands/project_git_exec.rs`, `configure_git_auth`:

```rust
command.env("GIT_CONFIG_NOSYSTEM", "1"); // :133
command.env("GIT_CONFIG_GLOBAL", "/dev/null"); // :147

let mut entries: Vec<(&str, String)> = vec![ // :153
("credential.helper", String::new()),
("core.hooksPath", "/dev/null".to_string()),
("core.fsmonitor", "false".to_string()),
("protocol.allow", "never".to_string()),
("protocol.http.allow", "always".to_string()),
("protocol.https.allow", "always".to_string()),
("protocol.ext.allow", "never".to_string()),
// ... protocol.file.allow
];
```

Those entries are applied via `GIT_CONFIG_COUNT` / `GIT_CONFIG_KEY_n` (`apply_git_config`, :193). `core.longpaths` is not among them, and with `GIT_CONFIG_NOSYSTEM=1` + `GIT_CONFIG_GLOBAL=/dev/null` there is no other channel for it to arrive on. The comment at :145 shows the `/dev/null` value is intentional and cross-platform, so this is not an accident of path handling — the global file is simply gone.

The failing call site is the remote-snapshot clone in `desktop/src-tauri/src/commands/project_git.rs` (:770–780), which checks out a full working tree:

```rust
let mut clone_args = vec!["clone", "--filter=blob:none"];
if let Some(ref branch) = branch { clone_args.push("--branch"); clone_args.push(branch.as_str()); }
clone_args.push(clone_url.as_str());
clone_args.push(repo_path);
```

Git exits 128 with `fatal: unable to checkout working tree`. `projectRepoUnavailableReason` (`desktop/src/features/projects/lib/projectRepoAvailability.ts`) tests for 401/403/auth, 404/not-found, missing-ref, and network strings; this message matches none, so it returns `unknown` → the generic "Repository unavailable" panel. `refineRepoUnavailableReason` only reclassifies `missing`, so it does not help here either.

## Minimal reproduction

Self-contained, no relay required. Windows 11, git 2.54.0.windows.1, `HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled = 0x0`, and `core.longpaths=true` **set** in the user's global config.

```bash
# fixture: one file whose tracked path is 255 chars
mkdir -p src && cd src && git init -q .
D=a_very_long_directory_segment_name_padding_0001/a_very_long_directory_segment_name_padding_0002/a_very_long_directory_segment_name_padding_0003/a_very_long_directory_segment_name_padding_0004
mkdir -p "$D" && echo x > "$D/a_file_with_a_deliberately_long_leaf_name_to_exceed_max_path.md"
git add -A && git commit -qm "deep path fixture"
```

**A — Desktop's environment** (global config neutralized, as `configure_git_auth` leaves it):

```
$ env -u GIT_CONFIG_PARAMETERS GIT_CONFIG_NOSYSTEM=1 GIT_CONFIG_GLOBAL=/dev/null \
git clone ./src ./dest-fail
error: unable to create file <...>/a_file_with_a_deliberately_long_leaf_name_to_exceed_max_path.md: Filename too long
fatal: unable to checkout working tree
exit=128
```

**B — identical, plus the missing setting delivered on a channel Desktop does not clear:**

```
$ GIT_CONFIG_PARAMETERS="'core.longpaths=true'" GIT_CONFIG_NOSYSTEM=1 GIT_CONFIG_GLOBAL=/dev/null \
git clone ./src ./dest-pass
Cloning into '.../dest-pass'... done.
exit=0
```

Same machine, same git, seconds apart. The only difference is whether `core.longpaths` reaches git.

This was found on a real 8,005-file repo where the deep paths are dated evidence records; the same two-direction result held there against a relay-hosted clone.

## Workaround (for other Windows users hitting this)

Setting `core.longpaths` in the global config does **nothing** — Desktop discards it. What does work is the one config channel `configure_git_auth` does not clear, set as a user environment variable and then relaunching Desktop:

```powershell
[Environment]::SetEnvironmentVariable('GIT_CONFIG_PARAMETERS', "'core.longpaths=true'", 'User')
```

(The single quotes are part of git's `GIT_CONFIG_PARAMETERS` format, not shell quoting.) This is fragile — it applies to every git process the user starts — so it is a stopgap, not a fix.

## Suggested fixes

1. **Inject the setting.** Add `("core.longpaths", "true".to_string())` to the `entries` vec in `configure_git_auth`. One line, and it makes Desktop's git behave the way a Windows user who already enabled long paths expects. It is inert on non-Windows.
2. **Don't check out a tree you only read.** The snapshot path builds the Files listing from `git ls-tree -r --long HEAD` (`project_git.rs:401`) and `git log`; it does not need a working tree. The sibling branch fifteen lines above (`:738`) already clones with `--no-checkout`. Using `--no-checkout` on the plain-clone branch too would sidestep long paths entirely on this code path — though `read_preview_content` reads files off disk, so preview content would need to come from `git cat-file` instead.
3. **Classify the error.** Add `filename too long` / `unable to checkout working tree` to `projectRepoUnavailableReason` so the panel can say something actionable instead of "Repository unavailable".

Fix 1 alone resolves the user-visible failure. Fix 3 matters independently: this is the second reported instance of a specific, fixable local-git problem being flattened into the `unknown` bucket.

## Related, but distinct

- #3707 — Windows clone failure from a `\\?\` extended-length **destination** argument. Different code path (`project_git_workflow.rs`, the REPOS clone) and different failure: git rejects the destination before checkout. That report notes `core.longpaths` does not help *there*, which is correct and does not apply here — this failure is in the checkout of deep paths *inside* the tree, into an ordinary `tempfile::tempdir()` destination with no `\\?\` prefix.
- #5348 — same "Repository unavailable" fallthrough in `projectRepoUnavailableReason`, different trigger (git <2.46 on macOS). Suggested fix 3 above is the Windows counterpart of that report's suggested fix 3.

## Environment

- Buzz Desktop 0.5.14 (behavior confirmed present at `main` `78cbffe`)
- Windows 11 Home, build 26200
- git 2.54.0.windows.1
- `LongPathsEnabled = 0x0` (machine scope), `core.longpaths=true` in the user's global config
- Relay-hosted NIP-34 repo, self-hosted relay

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.