Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion crates/fs/src/fake_git_repo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,15 @@ impl GitRepository for FakeGitRepository {
unimplemented!()
}

fn get_remotes(&self, _branch: Option<String>) -> BoxFuture<'_, Result<Vec<Remote>>> {
fn get_push_remote(&self, _branch: String) -> BoxFuture<'_, Result<Option<Remote>>> {
unimplemented!()
}

fn get_branch_remote(&self, _branch: String) -> BoxFuture<'_, Result<Option<Remote>>> {
unimplemented!()
}

fn get_all_remotes(&self) -> BoxFuture<'_, Result<Vec<Remote>>> {
unimplemented!()
}

Expand Down
70 changes: 54 additions & 16 deletions crates/git/src/repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,11 @@ pub trait GitRepository: Send + Sync {
cx: AsyncApp,
) -> BoxFuture<'_, Result<RemoteCommandOutput>>;

fn get_remotes(&self, branch_name: Option<String>) -> BoxFuture<'_, Result<Vec<Remote>>>;
fn get_push_remote(&self, branch: String) -> BoxFuture<'_, Result<Option<Remote>>>;

fn get_branch_remote(&self, branch: String) -> BoxFuture<'_, Result<Option<Remote>>>;

fn get_all_remotes(&self) -> BoxFuture<'_, Result<Vec<Remote>>>;

/// returns a list of remote branches that contain HEAD
fn check_for_pushed_commit(&self) -> BoxFuture<'_, Result<Vec<SharedString>>>;
Expand Down Expand Up @@ -1761,29 +1765,63 @@ impl GitRepository for RealGitRepository {
.boxed()
}

fn get_remotes(&self, branch_name: Option<String>) -> BoxFuture<'_, Result<Vec<Remote>>> {
fn get_push_remote(&self, branch: String) -> BoxFuture<'_, Result<Option<Remote>>> {
let working_directory = self.working_directory();
let git_binary_path = self.any_git_binary_path.clone();
self.executor
.spawn(async move {
let working_directory = working_directory?;
if let Some(branch_name) = branch_name {
let output = new_smol_command(&git_binary_path)
.current_dir(&working_directory)
.args(["config", "--get"])
.arg(format!("branch.{}.remote", branch_name))
.output()
.await?;
let output = new_smol_command(&git_binary_path)
.current_dir(&working_directory)
.args(["rev-parse", "--abbrev-ref"])
.arg(format!("{}@{{push}}", branch))
.output()
.await?;
if !output.status.success() {
return Ok(None);
}
let remote_name = String::from_utf8_lossy(&output.stdout)
.split('/')
.next()
.map(|name| Remote {
name: name.trim().to_string().into(),
});

if output.status.success() {
let remote_name = String::from_utf8_lossy(&output.stdout);
Ok(remote_name)
})
.boxed()
}

return Ok(vec![Remote {
name: remote_name.trim().to_string().into(),
}]);
}
fn get_branch_remote(&self, branch: String) -> BoxFuture<'_, Result<Option<Remote>>> {
let working_directory = self.working_directory();
let git_binary_path = self.any_git_binary_path.clone();
self.executor
.spawn(async move {
let working_directory = working_directory?;
let output = new_smol_command(&git_binary_path)
.current_dir(&working_directory)
.args(["config", "--get"])
.arg(format!("branch.{}.remote", branch))
.output()
.await?;
if !output.status.success() {
return Ok(None);
}

let remote_name = String::from_utf8_lossy(&output.stdout);
return Ok(Some(Remote {
name: remote_name.trim().to_string().into(),
}));
})
.boxed()
}

fn get_all_remotes(&self) -> BoxFuture<'_, Result<Vec<Remote>>> {
let working_directory = self.working_directory();
let git_binary_path = self.any_git_binary_path.clone();
self.executor
.spawn(async move {
let working_directory = working_directory?;
let output = new_smol_command(&git_binary_path)
.current_dir(&working_directory)
.args(["remote"])
Expand All @@ -1792,7 +1830,7 @@ impl GitRepository for RealGitRepository {

anyhow::ensure!(
output.status.success(),
"Failed to get remotes:\n{}",
"Failed to get all remotes:\n{}",
String::from_utf8_lossy(&output.stderr)
);
let remote_names = String::from_utf8_lossy(&output.stdout)
Expand Down
9 changes: 5 additions & 4 deletions crates/git_ui/src/git_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2110,7 +2110,7 @@ impl GitPanel {
cx.spawn_in(window, async move |_, cx| {
let repo = repo?;
let remotes = repo
.update(cx, |repo, _| repo.get_remotes(None))
.update(cx, |repo, _| repo.get_remotes(None, false))
.ok()?
.await
.ok()?
Expand Down Expand Up @@ -2374,7 +2374,7 @@ impl GitPanel {
};
telemetry::event!("Git Pulled");
let branch = branch.clone();
let remote = self.get_remote(false, window, cx);
let remote = self.get_remote(false, false, window, cx);
cx.spawn_in(window, async move |this, cx| {
let remote = match remote.await {
Ok(Some(remote)) => remote,
Expand Down Expand Up @@ -2450,7 +2450,7 @@ impl GitPanel {
_ => None,
}
};
let remote = self.get_remote(select_remote, window, cx);
let remote = self.get_remote(select_remote, true, window, cx);

cx.spawn_in(window, async move |this, cx| {
let remote = match remote.await {
Expand Down Expand Up @@ -2527,6 +2527,7 @@ impl GitPanel {
fn get_remote(
&mut self,
always_select: bool,
is_push: bool,
window: &mut Window,
cx: &mut Context<Self>,
) -> impl Future<Output = anyhow::Result<Option<Remote>>> + use<> {
Expand All @@ -2544,7 +2545,7 @@ impl GitPanel {
let current_branch = repo.branch.as_ref().context("No active branch")?;
Some(current_branch.name().to_string())
};
anyhow::Ok(repo.get_remotes(current_branch))
anyhow::Ok(repo.get_remotes(current_branch, is_push))
})??
.await??;

Expand Down
21 changes: 19 additions & 2 deletions crates/project/src/git_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2033,7 +2033,7 @@ impl GitStore {

let remotes = repository_handle
.update(&mut cx, |repository_handle, _| {
repository_handle.get_remotes(branch_name)
repository_handle.get_remotes(branch_name, false)
})?
.await??;

Expand Down Expand Up @@ -4595,11 +4595,28 @@ impl Repository {
pub fn get_remotes(
&mut self,
branch_name: Option<String>,
is_push: bool,
) -> oneshot::Receiver<Result<Vec<Remote>>> {
let id = self.id;
self.send_job(None, move |repo, _cx| async move {
match repo {
RepositoryState::Local { backend, .. } => backend.get_remotes(branch_name).await,
RepositoryState::Local { backend, .. } => {
let remote = match branch_name {
Some(name) => {
if is_push {
backend.get_push_remote(name.clone()).await?
} else {
backend.get_branch_remote(name).await?
}
}
None => None,
};

match remote {
Some(remote) => Ok(vec![remote]),
None => backend.get_all_remotes().await,
}
}
RepositoryState::Remote { project_id, client } => {
let response = client
.request(proto::GetRemotes {
Expand Down
Loading