Better error message when git is not found (#9206)

## Summary

Closes https://github.com/astral-sh/uv/issues/9200


## Test Plan

Using the following Dockerfile:
```Dockerfile
FROM debian:latest

RUN apt-get update && apt-get install -y python3

WORKDIR /app
COPY target/debug/uv .
RUN chmod +x uv

RUN /app/uv venv && /app/uv pip install git@github.com:pallets/flask.git
```

```
❯ cargo build -q -p uv && docker build .
...
 => ERROR [6/6] RUN /app/uv venv && /app/uv pip install git@github.com:pallets/flask.git                    0.4s
------
 > [6/6] RUN /app/uv venv && /app/uv pip install git@github.com:pallets/flask.git:
0.275 Using CPython 3.11.2 interpreter at: /usr/bin/python3
0.275 Creating virtual environment at: .venv
0.318   × Failed to download and build `git @
0.318   │ file:///app/github.com:pallets/flask.git`
0.318   ├─▶ Git operation failed
0.318   ╰─▶ Git executable not found. Ensure that Git is installed and available.
------
Dockerfile:9
--------------------
   7 |     RUN chmod +x uv
   8 |
   9 | >>> RUN /app/uv venv && /app/uv pip install git@github.com:pallets/flask.git
  10 |
--------------------
ERROR: failed to solve: process "/bin/sh -c /
```
This commit is contained in:
Ahmed Ilyas 2024-11-18 18:41:22 +01:00 committed by GitHub
parent f1554c5ecd
commit ad342009af
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -22,8 +22,20 @@ use uv_static::EnvVars;
/// checkout is ready to go. See [`GitCheckout::reset`] for why we need this.
const CHECKOUT_READY_LOCK: &str = ".ok";
#[derive(Debug, thiserror::Error)]
pub enum GitError {
#[error("Git executable not found. Ensure that Git is installed and available.")]
GitNotFound,
#[error(transparent)]
Other(#[from] which::Error),
}
/// A global cache of the result of `which git`.
pub static GIT: LazyLock<Result<PathBuf, which::Error>> = LazyLock::new(|| which::which("git"));
pub static GIT: LazyLock<Result<PathBuf, GitError>> = LazyLock::new(|| {
which::which("git").map_err(|e| match e {
which::Error::CannotFindBinaryPath => GitError::GitNotFound,
e => GitError::Other(e),
})
});
/// A reference to commit or commit-ish.
#[derive(