block / block/buzz

Desktop Projects: pull request "Files changed" is empty on a local checkout — local_ref_exists accepts any 40-hex SHA, and the PR head is never fetched

Open
#7,174 2 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

**Describe the bug**

In Desktop → Projects, opening a pull request against a **local checkout** shows no
file diff. The "Files changed" view stays empty.

Two defects combine to cause it.

**1. `local_ref_exists` never reports a missing commit.**

`desktop/src-tauri/src/commands/project_git_diff.rs` (`main` @ `59328d5ae`):

```rust
fn local_ref_exists(repo_dir: &std::path::Path, auth: &GitAuthConfig, ref_name: &str) -> bool {
run_git(
&["rev-parse", "--verify", "--quiet", ref_name],
Some(repo_dir),
auth,
)
.is_ok()
}
```

`git rev-parse --verify` accepts any well-formed 40-hex string without checking that
the object is present. `pullRequest.commit` is always a full 40-hex SHA, so this
helper returns `true` for a commit the repository does not have:

```
$ git --version
git version 2.55.0
$ git rev-parse --verify --quiet 0123456789abcdef0123456789abcdef01234567
0123456789abcdef0123456789abcdef01234567 # rc=0, object is absent
$ git rev-parse --verify --quiet 0123456789abcdef0123456789abcdef01234567^{commit}
# rc=1, correct answer
```

`local_target_ref` therefore returns the absent SHA, and `local_diff_range` builds a
range git cannot resolve:

```
$ git diff --name-status "HEAD...0123456789abcdef0123456789abcdef01234567"
fatal: Invalid symmetric difference expression HEAD...0123456789abcdef...
```

The same helper backs `local_base_ref` and the `base_commit` check inside
`local_diff_range`, so all five call sites share the defect.

**2. The pull request head is never fetched into a local checkout.**

`get_project_local_repo_diff` takes `target_commit` but no target branch, and it never
fetches. A personal checkout that has only ever fetched its default branch simply does
not contain the review head. Even with defect 1 fixed, the diff stays empty until the
user fetches the branch by hand.

**Steps to reproduce**

1. Clone a repository yourself, outside Buzz (`git clone ~/code/`), and
fetch only the default branch.
2. Point a Buzz project at that checkout.
3. Open a pull request whose head branch was never fetched locally.
4. Open "Files changed".
5. The diff is empty. No error explains why.

**Expected behavior**

Buzz either shows the diff — fetching the pull request head branch from the checkout's
already-configured `origin` — or reports that the commit is not present locally.
Silently rendering an empty diff is the worst of the three.

**Version and platform**

- Buzz version: reproduced on a local build of `822c5ab23` (0.5.18). The code path is
byte-identical on `main` @ `59328d5ae` (0.5.20), so this is not fixed there.
- OS: Arch Linux, Hyprland (Wayland), git 2.55.0. The `rev-parse` defect is
platform-independent.

**Logs / additional context**

Suggested fix for defect 1 — peel to `^{commit}` so git performs a real object lookup.
One change in the shared helper covers all five call sites:

```rust
fn local_ref_exists(repo_dir: &Path, auth: &GitAuthConfig, ref_name: &str) -> bool {
// `git rev-parse --verify` accepts any well-formed 40-hex string without
// checking that the object is present, so a bare pull request head SHA
// always looks resolvable. Peeling to `^{commit}` forces the object lookup.
let peeled = format!("{ref_name}^{{commit}}");
run_git(&["rev-parse", "--verify", "--quiet", &peeled], Some(repo_dir), auth).is_ok()
}
```

Peeling stays correct for the branch and `origin/` call sites.

For defect 2, passing the pull request head branch down and fetching
`refs/heads/` from the existing local `origin` is enough. Two notes on that:

- The fetch must not pass `--depth`. Every other `--depth=100` in this file runs against
clones Buzz created in `reposDir`. A shallow fetch into a user's own full clone turns
it shallow, and only `git fetch --unshallow` undoes that.
- The clone URL from the relay must not be used here — the checkout's own `origin`
already carries the user's remote and credentials.

I have a working patch for both defects and am happy to open a PR if the direction
looks right. Related but distinct: the "Open in Terminal" defects filed separately.

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.