git: Add ability to clone remote repositories from Zed (#35606)

This PR adds preliminary git clone support through using the new
`GitClone` action. This works with SSH connections too.

- [x] Get backend working
- [x] Add a UI to interact with this

Future follow-ups:
- Polish the UI
- Have the path select prompt say "Select Repository clone target"
instead of “Open”
- Use Zed path prompt if the user has that as a setting
- Add support for cloning from a user's GitHub repositories directly

Release Notes:

- Add the ability to clone remote git repositories through the `git:
Clone` action

---------

Co-authored-by: hpmcdona <hayden_mcdonald@brown.edu>
This commit is contained in:
Anthony Eid 2025-08-11 11:09:38 -04:00 committed by GitHub
parent 12084b6677
commit 62270b33c2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 310 additions and 8 deletions

View file

@ -12,7 +12,7 @@ use gpui::BackgroundExecutor;
use gpui::Global;
use gpui::ReadGlobal as _;
use std::borrow::Cow;
use util::command::new_std_command;
use util::command::{new_smol_command, new_std_command};
#[cfg(unix)]
use std::os::fd::{AsFd, AsRawFd};
@ -134,6 +134,7 @@ pub trait Fs: Send + Sync {
fn home_dir(&self) -> Option<PathBuf>;
fn open_repo(&self, abs_dot_git: &Path) -> Option<Arc<dyn GitRepository>>;
fn git_init(&self, abs_work_directory: &Path, fallback_branch_name: String) -> Result<()>;
async fn git_clone(&self, repo_url: &str, abs_work_directory: &Path) -> Result<()>;
fn is_fake(&self) -> bool;
async fn is_case_sensitive(&self) -> Result<bool>;
@ -839,6 +840,23 @@ impl Fs for RealFs {
Ok(())
}
async fn git_clone(&self, repo_url: &str, abs_work_directory: &Path) -> Result<()> {
let output = new_smol_command("git")
.current_dir(abs_work_directory)
.args(&["clone", repo_url])
.output()
.await?;
if !output.status.success() {
anyhow::bail!(
"git clone failed: {}",
String::from_utf8_lossy(&output.stderr)
);
}
Ok(())
}
fn is_fake(&self) -> bool {
false
}
@ -2352,6 +2370,10 @@ impl Fs for FakeFs {
smol::block_on(self.create_dir(&abs_work_directory_path.join(".git")))
}
async fn git_clone(&self, _repo_url: &str, _abs_work_directory: &Path) -> Result<()> {
anyhow::bail!("Git clone is not supported in fake Fs")
}
fn is_fake(&self) -> bool {
true
}