Git on main thread (#26573)
This moves spawning of the git subprocess to the main thread. We're not yet sure why, but when we spawn a process using GCD's background queues, sub-processes like git-credential-manager fail to open windows. This seems to be fixable either by using the main thread, or by using a standard background thread, but for now we use the main thread. Release Notes: - Git: Fix git-credential-manager --------- Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com> Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
This commit is contained in:
parent
5268e74315
commit
7bca15704b
11 changed files with 926 additions and 713 deletions
|
@ -6770,7 +6770,7 @@ async fn test_remote_git_branches(
|
|||
|
||||
assert_eq!(branches_b, branches_set);
|
||||
|
||||
cx_b.update(|cx| repo_b.read(cx).change_branch(new_branch))
|
||||
cx_b.update(|cx| repo_b.read(cx).change_branch(new_branch.to_string()))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
@ -6790,15 +6790,23 @@ async fn test_remote_git_branches(
|
|||
assert_eq!(host_branch.name, branches[2]);
|
||||
|
||||
// Also try creating a new branch
|
||||
cx_b.update(|cx| repo_b.read(cx).create_branch("totally-new-branch"))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
cx_b.update(|cx| {
|
||||
repo_b
|
||||
.read(cx)
|
||||
.create_branch("totally-new-branch".to_string())
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
cx_b.update(|cx| repo_b.read(cx).change_branch("totally-new-branch"))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
cx_b.update(|cx| {
|
||||
repo_b
|
||||
.read(cx)
|
||||
.change_branch("totally-new-branch".to_string())
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
executor.run_until_parked();
|
||||
|
||||
|
|
|
@ -294,7 +294,7 @@ async fn test_ssh_collaboration_git_branches(
|
|||
|
||||
assert_eq!(&branches_b, &branches_set);
|
||||
|
||||
cx_b.update(|cx| repo_b.read(cx).change_branch(new_branch))
|
||||
cx_b.update(|cx| repo_b.read(cx).change_branch(new_branch.to_string()))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
@ -316,15 +316,23 @@ async fn test_ssh_collaboration_git_branches(
|
|||
assert_eq!(server_branch.name, branches[2]);
|
||||
|
||||
// Also try creating a new branch
|
||||
cx_b.update(|cx| repo_b.read(cx).create_branch("totally-new-branch"))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
cx_b.update(|cx| {
|
||||
repo_b
|
||||
.read(cx)
|
||||
.create_branch("totally-new-branch".to_string())
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
cx_b.update(|cx| repo_b.read(cx).change_branch("totally-new-branch"))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
cx_b.update(|cx| {
|
||||
repo_b
|
||||
.read(cx)
|
||||
.change_branch("totally-new-branch".to_string())
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
executor.run_until_parked();
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@ use crate::commit::get_messages;
|
|||
use crate::Oid;
|
||||
use anyhow::{anyhow, Context as _, Result};
|
||||
use collections::{HashMap, HashSet};
|
||||
use futures::AsyncWriteExt;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io::Write;
|
||||
use std::process::Stdio;
|
||||
use std::{ops::Range, path::Path};
|
||||
use text::Rope;
|
||||
|
@ -21,14 +21,14 @@ pub struct Blame {
|
|||
}
|
||||
|
||||
impl Blame {
|
||||
pub fn for_path(
|
||||
pub async fn for_path(
|
||||
git_binary: &Path,
|
||||
working_directory: &Path,
|
||||
path: &Path,
|
||||
content: &Rope,
|
||||
remote_url: Option<String>,
|
||||
) -> Result<Self> {
|
||||
let output = run_git_blame(git_binary, working_directory, path, content)?;
|
||||
let output = run_git_blame(git_binary, working_directory, path, content).await?;
|
||||
let mut entries = parse_git_blame(&output)?;
|
||||
entries.sort_unstable_by(|a, b| a.range.start.cmp(&b.range.start));
|
||||
|
||||
|
@ -39,8 +39,9 @@ impl Blame {
|
|||
}
|
||||
|
||||
let shas = unique_shas.into_iter().collect::<Vec<_>>();
|
||||
let messages =
|
||||
get_messages(working_directory, &shas).context("failed to get commit messages")?;
|
||||
let messages = get_messages(working_directory, &shas)
|
||||
.await
|
||||
.context("failed to get commit messages")?;
|
||||
|
||||
Ok(Self {
|
||||
entries,
|
||||
|
@ -53,13 +54,13 @@ impl Blame {
|
|||
const GIT_BLAME_NO_COMMIT_ERROR: &str = "fatal: no such ref: HEAD";
|
||||
const GIT_BLAME_NO_PATH: &str = "fatal: no such path";
|
||||
|
||||
fn run_git_blame(
|
||||
async fn run_git_blame(
|
||||
git_binary: &Path,
|
||||
working_directory: &Path,
|
||||
path: &Path,
|
||||
contents: &Rope,
|
||||
) -> Result<String> {
|
||||
let child = util::command::new_std_command(git_binary)
|
||||
let mut child = util::command::new_smol_command(git_binary)
|
||||
.current_dir(working_directory)
|
||||
.arg("blame")
|
||||
.arg("--incremental")
|
||||
|
@ -72,18 +73,19 @@ fn run_git_blame(
|
|||
.spawn()
|
||||
.map_err(|e| anyhow!("Failed to start git blame process: {}", e))?;
|
||||
|
||||
let mut stdin = child
|
||||
let stdin = child
|
||||
.stdin
|
||||
.as_ref()
|
||||
.as_mut()
|
||||
.context("failed to get pipe to stdin of git blame command")?;
|
||||
|
||||
for chunk in contents.chunks() {
|
||||
stdin.write_all(chunk.as_bytes())?;
|
||||
stdin.write_all(chunk.as_bytes()).await?;
|
||||
}
|
||||
stdin.flush()?;
|
||||
stdin.flush().await?;
|
||||
|
||||
let output = child
|
||||
.wait_with_output()
|
||||
.output()
|
||||
.await
|
||||
.map_err(|e| anyhow!("Failed to read git blame output: {}", e))?;
|
||||
|
||||
if !output.status.success() {
|
||||
|
|
|
@ -3,20 +3,21 @@ use anyhow::{anyhow, Result};
|
|||
use collections::HashMap;
|
||||
use std::path::Path;
|
||||
|
||||
pub fn get_messages(working_directory: &Path, shas: &[Oid]) -> Result<HashMap<Oid, String>> {
|
||||
pub async fn get_messages(working_directory: &Path, shas: &[Oid]) -> Result<HashMap<Oid, String>> {
|
||||
if shas.is_empty() {
|
||||
return Ok(HashMap::default());
|
||||
}
|
||||
|
||||
const MARKER: &str = "<MARKER>";
|
||||
|
||||
let output = util::command::new_std_command("git")
|
||||
let output = util::command::new_smol_command("git")
|
||||
.current_dir(working_directory)
|
||||
.arg("show")
|
||||
.arg("-s")
|
||||
.arg(format!("--format=%B{}", MARKER))
|
||||
.args(shas.iter().map(ToString::to_string))
|
||||
.output()
|
||||
.await
|
||||
.map_err(|e| anyhow!("Failed to start git blame process: {}", e))?;
|
||||
|
||||
anyhow::ensure!(
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -205,9 +205,9 @@ impl BranchListDelegate {
|
|||
return;
|
||||
};
|
||||
cx.spawn(|_, cx| async move {
|
||||
cx.update(|cx| repo.read(cx).create_branch(&new_branch_name))?
|
||||
cx.update(|cx| repo.read(cx).create_branch(new_branch_name.to_string()))?
|
||||
.await??;
|
||||
cx.update(|cx| repo.read(cx).change_branch(&new_branch_name))?
|
||||
cx.update(|cx| repo.read(cx).change_branch(new_branch_name.to_string()))?
|
||||
.await??;
|
||||
Ok(())
|
||||
})
|
||||
|
@ -358,7 +358,7 @@ impl PickerDelegate for BranchListDelegate {
|
|||
let cx = cx.to_async();
|
||||
|
||||
anyhow::Ok(async move {
|
||||
cx.update(|cx| repo.read(cx).change_branch(&branch.name))?
|
||||
cx.update(|cx| repo.read(cx).change_branch(branch.name.to_string()))?
|
||||
.await?
|
||||
})
|
||||
})??;
|
||||
|
|
|
@ -1501,15 +1501,17 @@ impl GitPanel {
|
|||
telemetry::event!("Git Uncommitted");
|
||||
|
||||
let confirmation = self.check_for_pushed_commits(window, cx);
|
||||
let prior_head = self.load_commit_details("HEAD", cx);
|
||||
let prior_head = self.load_commit_details("HEAD".to_string(), cx);
|
||||
|
||||
let task = cx.spawn_in(window, |this, mut cx| async move {
|
||||
let result = maybe!(async {
|
||||
if let Ok(true) = confirmation.await {
|
||||
let prior_head = prior_head.await?;
|
||||
|
||||
repo.update(&mut cx, |repo, cx| repo.reset("HEAD^", ResetMode::Soft, cx))?
|
||||
.await??;
|
||||
repo.update(&mut cx, |repo, cx| {
|
||||
repo.reset("HEAD^".to_string(), ResetMode::Soft, cx)
|
||||
})?
|
||||
.await??;
|
||||
|
||||
Ok(Some(prior_head))
|
||||
} else {
|
||||
|
@ -3401,7 +3403,7 @@ impl GitPanel {
|
|||
|
||||
fn load_commit_details(
|
||||
&self,
|
||||
sha: &str,
|
||||
sha: String,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Task<anyhow::Result<CommitDetails>> {
|
||||
let Some(repo) = self.active_repository.clone() else {
|
||||
|
@ -3911,7 +3913,7 @@ impl GitPanelMessageTooltip {
|
|||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
let details = git_panel
|
||||
.update(&mut cx, |git_panel, cx| {
|
||||
git_panel.load_commit_details(&sha, cx)
|
||||
git_panel.load_commit_details(sha.to_string(), cx)
|
||||
})?
|
||||
.await?;
|
||||
|
||||
|
|
|
@ -837,52 +837,63 @@ impl LocalBufferStore {
|
|||
let snapshot =
|
||||
worktree_handle.update(&mut cx, |tree, _| tree.as_local().unwrap().snapshot())?;
|
||||
let diff_bases_changes_by_buffer = cx
|
||||
.background_spawn(async move {
|
||||
diff_state_updates
|
||||
.into_iter()
|
||||
.filter_map(|(buffer, path, current_index_text, current_head_text)| {
|
||||
let local_repo = snapshot.local_repo_for_path(&path)?;
|
||||
let relative_path = local_repo.relativize(&path).ok()?;
|
||||
let index_text = if current_index_text.is_some() {
|
||||
local_repo.repo().load_index_text(&relative_path)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let head_text = if current_head_text.is_some() {
|
||||
local_repo.repo().load_committed_text(&relative_path)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
.spawn(async move |cx| {
|
||||
let mut results = Vec::new();
|
||||
for (buffer, path, current_index_text, current_head_text) in diff_state_updates
|
||||
{
|
||||
let Some(local_repo) = snapshot.local_repo_for_path(&path) else {
|
||||
continue;
|
||||
};
|
||||
let Some(relative_path) = local_repo.relativize(&path).ok() else {
|
||||
continue;
|
||||
};
|
||||
let index_text = if current_index_text.is_some() {
|
||||
local_repo
|
||||
.repo()
|
||||
.load_index_text(relative_path.clone(), cx.clone())
|
||||
.await
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let head_text = if current_head_text.is_some() {
|
||||
local_repo
|
||||
.repo()
|
||||
.load_committed_text(relative_path, cx.clone())
|
||||
.await
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Avoid triggering a diff update if the base text has not changed.
|
||||
if let Some((current_index, current_head)) =
|
||||
current_index_text.as_ref().zip(current_head_text.as_ref())
|
||||
// Avoid triggering a diff update if the base text has not changed.
|
||||
if let Some((current_index, current_head)) =
|
||||
current_index_text.as_ref().zip(current_head_text.as_ref())
|
||||
{
|
||||
if current_index.as_deref() == index_text.as_ref()
|
||||
&& current_head.as_deref() == head_text.as_ref()
|
||||
{
|
||||
if current_index.as_deref() == index_text.as_ref()
|
||||
&& current_head.as_deref() == head_text.as_ref()
|
||||
{
|
||||
return None;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let diff_bases_change =
|
||||
match (current_index_text.is_some(), current_head_text.is_some()) {
|
||||
(true, true) => Some(if index_text == head_text {
|
||||
DiffBasesChange::SetBoth(head_text)
|
||||
} else {
|
||||
DiffBasesChange::SetEach {
|
||||
index: index_text,
|
||||
head: head_text,
|
||||
}
|
||||
}),
|
||||
(true, false) => Some(DiffBasesChange::SetIndex(index_text)),
|
||||
(false, true) => Some(DiffBasesChange::SetHead(head_text)),
|
||||
(false, false) => None,
|
||||
};
|
||||
let diff_bases_change =
|
||||
match (current_index_text.is_some(), current_head_text.is_some()) {
|
||||
(true, true) => Some(if index_text == head_text {
|
||||
DiffBasesChange::SetBoth(head_text)
|
||||
} else {
|
||||
DiffBasesChange::SetEach {
|
||||
index: index_text,
|
||||
head: head_text,
|
||||
}
|
||||
}),
|
||||
(true, false) => Some(DiffBasesChange::SetIndex(index_text)),
|
||||
(false, true) => Some(DiffBasesChange::SetHead(head_text)),
|
||||
(false, false) => None,
|
||||
};
|
||||
|
||||
Some((buffer, diff_bases_change))
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
results.push((buffer, diff_bases_change))
|
||||
}
|
||||
|
||||
results
|
||||
})
|
||||
.await;
|
||||
|
||||
|
@ -1620,11 +1631,12 @@ impl BufferStore {
|
|||
anyhow::Ok(Some((repo, relative_path, content)))
|
||||
});
|
||||
|
||||
cx.background_spawn(async move {
|
||||
cx.spawn(|cx| async move {
|
||||
let Some((repo, relative_path, content)) = blame_params? else {
|
||||
return Ok(None);
|
||||
};
|
||||
repo.blame(&relative_path, content)
|
||||
repo.blame(relative_path.clone(), content, cx)
|
||||
.await
|
||||
.with_context(|| format!("Failed to blame {:?}", relative_path.0))
|
||||
.map(Some)
|
||||
})
|
||||
|
|
|
@ -401,7 +401,7 @@ impl GitStore {
|
|||
if let Some((repo, path)) = this.repository_and_path_for_buffer_id(buffer_id, cx) {
|
||||
let recv = repo.update(cx, |repo, cx| {
|
||||
repo.set_index_text(
|
||||
&path,
|
||||
path,
|
||||
new_index_text.as_ref().map(|rope| rope.to_string()),
|
||||
cx,
|
||||
)
|
||||
|
@ -715,7 +715,7 @@ impl GitStore {
|
|||
repository_handle
|
||||
.update(&mut cx, |repository_handle, cx| {
|
||||
repository_handle.set_index_text(
|
||||
&RepoPath::from_str(&envelope.payload.path),
|
||||
RepoPath::from_str(&envelope.payload.path),
|
||||
envelope.payload.text,
|
||||
cx,
|
||||
)
|
||||
|
@ -808,7 +808,7 @@ impl GitStore {
|
|||
|
||||
repository_handle
|
||||
.update(&mut cx, |repository_handle, _| {
|
||||
repository_handle.create_branch(&branch_name)
|
||||
repository_handle.create_branch(branch_name)
|
||||
})?
|
||||
.await??;
|
||||
|
||||
|
@ -828,7 +828,7 @@ impl GitStore {
|
|||
|
||||
repository_handle
|
||||
.update(&mut cx, |repository_handle, _| {
|
||||
repository_handle.change_branch(&branch_name)
|
||||
repository_handle.change_branch(branch_name)
|
||||
})?
|
||||
.await??;
|
||||
|
||||
|
@ -847,7 +847,7 @@ impl GitStore {
|
|||
|
||||
let commit = repository_handle
|
||||
.update(&mut cx, |repository_handle, _| {
|
||||
repository_handle.show(&envelope.payload.commit)
|
||||
repository_handle.show(envelope.payload.commit)
|
||||
})?
|
||||
.await??;
|
||||
Ok(proto::GitCommitDetails {
|
||||
|
@ -876,7 +876,7 @@ impl GitStore {
|
|||
|
||||
repository_handle
|
||||
.update(&mut cx, |repository_handle, cx| {
|
||||
repository_handle.reset(&envelope.payload.commit, mode, cx)
|
||||
repository_handle.reset(envelope.payload.commit, mode, cx)
|
||||
})?
|
||||
.await??;
|
||||
Ok(proto::Ack {})
|
||||
|
@ -1081,8 +1081,8 @@ impl Repository {
|
|||
|
||||
fn send_job<F, Fut, R>(&self, job: F) -> oneshot::Receiver<R>
|
||||
where
|
||||
F: FnOnce(GitRepo) -> Fut + 'static,
|
||||
Fut: Future<Output = R> + Send + 'static,
|
||||
F: FnOnce(GitRepo, AsyncApp) -> Fut + 'static,
|
||||
Fut: Future<Output = R> + 'static,
|
||||
R: Send + 'static,
|
||||
{
|
||||
self.send_keyed_job(None, job)
|
||||
|
@ -1090,8 +1090,8 @@ impl Repository {
|
|||
|
||||
fn send_keyed_job<F, Fut, R>(&self, key: Option<GitJobKey>, job: F) -> oneshot::Receiver<R>
|
||||
where
|
||||
F: FnOnce(GitRepo) -> Fut + 'static,
|
||||
Fut: Future<Output = R> + Send + 'static,
|
||||
F: FnOnce(GitRepo, AsyncApp) -> Fut + 'static,
|
||||
Fut: Future<Output = R> + 'static,
|
||||
R: Send + 'static,
|
||||
{
|
||||
let (result_tx, result_rx) = futures::channel::oneshot::channel();
|
||||
|
@ -1100,8 +1100,8 @@ impl Repository {
|
|||
.unbounded_send(GitJob {
|
||||
key,
|
||||
job: Box::new(|cx: &mut AsyncApp| {
|
||||
let job = job(git_repo);
|
||||
cx.background_spawn(async move {
|
||||
let job = job(git_repo, cx.clone());
|
||||
cx.spawn(|_| async move {
|
||||
let result = job.await;
|
||||
result_tx.send(result).ok();
|
||||
})
|
||||
|
@ -1292,9 +1292,9 @@ impl Repository {
|
|||
let commit = commit.to_string();
|
||||
let env = self.worktree_environment(cx);
|
||||
|
||||
self.send_job(|git_repo| async move {
|
||||
self.send_job(|git_repo, _| async move {
|
||||
match git_repo {
|
||||
GitRepo::Local(repo) => repo.checkout_files(&commit, &paths, &env.await),
|
||||
GitRepo::Local(repo) => repo.checkout_files(commit, paths, env.await).await,
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
|
@ -1322,17 +1322,17 @@ impl Repository {
|
|||
|
||||
pub fn reset(
|
||||
&self,
|
||||
commit: &str,
|
||||
commit: String,
|
||||
reset_mode: ResetMode,
|
||||
cx: &mut App,
|
||||
) -> oneshot::Receiver<Result<()>> {
|
||||
let commit = commit.to_string();
|
||||
let env = self.worktree_environment(cx);
|
||||
self.send_job(|git_repo| async move {
|
||||
self.send_job(|git_repo, _| async move {
|
||||
match git_repo {
|
||||
GitRepo::Local(git_repo) => {
|
||||
let env = env.await;
|
||||
git_repo.reset(&commit, reset_mode, &env)
|
||||
git_repo.reset(commit, reset_mode, env).await
|
||||
}
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
|
@ -1359,11 +1359,10 @@ impl Repository {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn show(&self, commit: &str) -> oneshot::Receiver<Result<CommitDetails>> {
|
||||
let commit = commit.to_string();
|
||||
self.send_job(|git_repo| async move {
|
||||
pub fn show(&self, commit: String) -> oneshot::Receiver<Result<CommitDetails>> {
|
||||
self.send_job(|git_repo, cx| async move {
|
||||
match git_repo {
|
||||
GitRepo::Local(git_repository) => git_repository.show(&commit),
|
||||
GitRepo::Local(git_repository) => git_repository.show(commit, cx).await,
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
|
@ -1433,9 +1432,9 @@ impl Repository {
|
|||
let env = env.await;
|
||||
|
||||
this.update(&mut cx, |this, _| {
|
||||
this.send_job(|git_repo| async move {
|
||||
this.send_job(|git_repo, cx| async move {
|
||||
match git_repo {
|
||||
GitRepo::Local(repo) => repo.stage_paths(&entries, &env),
|
||||
GitRepo::Local(repo) => repo.stage_paths(entries, env, cx).await,
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
|
@ -1504,9 +1503,9 @@ impl Repository {
|
|||
let env = env.await;
|
||||
|
||||
this.update(&mut cx, |this, _| {
|
||||
this.send_job(|git_repo| async move {
|
||||
this.send_job(|git_repo, cx| async move {
|
||||
match git_repo {
|
||||
GitRepo::Local(repo) => repo.unstage_paths(&entries, &env),
|
||||
GitRepo::Local(repo) => repo.unstage_paths(entries, env, cx).await,
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
|
@ -1587,17 +1586,11 @@ impl Repository {
|
|||
cx: &mut App,
|
||||
) -> oneshot::Receiver<Result<()>> {
|
||||
let env = self.worktree_environment(cx);
|
||||
self.send_job(|git_repo| async move {
|
||||
self.send_job(|git_repo, cx| async move {
|
||||
match git_repo {
|
||||
GitRepo::Local(repo) => {
|
||||
let env = env.await;
|
||||
repo.commit(
|
||||
message.as_ref(),
|
||||
name_and_email
|
||||
.as_ref()
|
||||
.map(|(name, email)| (name.as_ref(), email.as_ref())),
|
||||
&env,
|
||||
)
|
||||
repo.commit(message, name_and_email, env, cx).await
|
||||
}
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
|
@ -1634,12 +1627,12 @@ impl Repository {
|
|||
let askpass_id = util::post_inc(&mut self.latest_askpass_id);
|
||||
let env = self.worktree_environment(cx);
|
||||
|
||||
self.send_job(move |git_repo| async move {
|
||||
self.send_job(move |git_repo, cx| async move {
|
||||
match git_repo {
|
||||
GitRepo::Local(git_repository) => {
|
||||
let askpass = AskPassSession::new(&executor, askpass).await?;
|
||||
let env = env.await;
|
||||
git_repository.fetch(askpass, &env)
|
||||
git_repository.fetch(askpass, env, cx).await
|
||||
}
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
|
@ -1685,12 +1678,21 @@ impl Repository {
|
|||
let askpass_id = util::post_inc(&mut self.latest_askpass_id);
|
||||
let env = self.worktree_environment(cx);
|
||||
|
||||
self.send_job(move |git_repo| async move {
|
||||
self.send_job(move |git_repo, cx| async move {
|
||||
match git_repo {
|
||||
GitRepo::Local(git_repository) => {
|
||||
let env = env.await;
|
||||
let askpass = AskPassSession::new(&executor, askpass).await?;
|
||||
git_repository.push(&branch, &remote, options, askpass, &env)
|
||||
git_repository
|
||||
.push(
|
||||
branch.to_string(),
|
||||
remote.to_string(),
|
||||
options,
|
||||
askpass,
|
||||
env,
|
||||
cx,
|
||||
)
|
||||
.await
|
||||
}
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
|
@ -1740,12 +1742,14 @@ impl Repository {
|
|||
let askpass_id = util::post_inc(&mut self.latest_askpass_id);
|
||||
let env = self.worktree_environment(cx);
|
||||
|
||||
self.send_job(move |git_repo| async move {
|
||||
self.send_job(move |git_repo, cx| async move {
|
||||
match git_repo {
|
||||
GitRepo::Local(git_repository) => {
|
||||
let askpass = AskPassSession::new(&executor, askpass).await?;
|
||||
let env = env.await;
|
||||
git_repository.pull(&branch, &remote, askpass, &env)
|
||||
git_repository
|
||||
.pull(branch.to_string(), remote.to_string(), askpass, env, cx)
|
||||
.await
|
||||
}
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
|
@ -1781,18 +1785,17 @@ impl Repository {
|
|||
|
||||
fn set_index_text(
|
||||
&self,
|
||||
path: &RepoPath,
|
||||
path: RepoPath,
|
||||
content: Option<String>,
|
||||
cx: &mut App,
|
||||
) -> oneshot::Receiver<anyhow::Result<()>> {
|
||||
let path = path.clone();
|
||||
let env = self.worktree_environment(cx);
|
||||
|
||||
self.send_keyed_job(
|
||||
Some(GitJobKey::WriteIndex(path.clone())),
|
||||
|git_repo| async move {
|
||||
|git_repo, cx| async move {
|
||||
match git_repo {
|
||||
GitRepo::Local(repo) => repo.set_index_text(&path, content, &env.await),
|
||||
GitRepo::Local(repo) => repo.set_index_text(path, content, env.await, cx).await,
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
|
@ -1819,11 +1822,9 @@ impl Repository {
|
|||
&self,
|
||||
branch_name: Option<String>,
|
||||
) -> oneshot::Receiver<Result<Vec<Remote>>> {
|
||||
self.send_job(|repo| async move {
|
||||
self.send_job(|repo, cx| async move {
|
||||
match repo {
|
||||
GitRepo::Local(git_repository) => {
|
||||
git_repository.get_remotes(branch_name.as_deref())
|
||||
}
|
||||
GitRepo::Local(git_repository) => git_repository.get_remotes(branch_name, cx).await,
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
|
@ -1854,9 +1855,13 @@ impl Repository {
|
|||
}
|
||||
|
||||
pub fn branches(&self) -> oneshot::Receiver<Result<Vec<Branch>>> {
|
||||
self.send_job(|repo| async move {
|
||||
self.send_job(|repo, cx| async move {
|
||||
match repo {
|
||||
GitRepo::Local(git_repository) => git_repository.branches(),
|
||||
GitRepo::Local(git_repository) => {
|
||||
let git_repository = git_repository.clone();
|
||||
cx.background_spawn(async move { git_repository.branches().await })
|
||||
.await
|
||||
}
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
|
@ -1884,9 +1889,9 @@ impl Repository {
|
|||
}
|
||||
|
||||
pub fn diff(&self, diff_type: DiffType, _cx: &App) -> oneshot::Receiver<Result<String>> {
|
||||
self.send_job(|repo| async move {
|
||||
self.send_job(|repo, cx| async move {
|
||||
match repo {
|
||||
GitRepo::Local(git_repository) => git_repository.diff(diff_type),
|
||||
GitRepo::Local(git_repository) => git_repository.diff(diff_type, cx).await,
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
|
@ -1916,11 +1921,12 @@ impl Repository {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn create_branch(&self, branch_name: &str) -> oneshot::Receiver<Result<()>> {
|
||||
let branch_name = branch_name.to_owned();
|
||||
self.send_job(|repo| async move {
|
||||
pub fn create_branch(&self, branch_name: String) -> oneshot::Receiver<Result<()>> {
|
||||
self.send_job(|repo, cx| async move {
|
||||
match repo {
|
||||
GitRepo::Local(git_repository) => git_repository.create_branch(&branch_name),
|
||||
GitRepo::Local(git_repository) => {
|
||||
git_repository.create_branch(branch_name, cx).await
|
||||
}
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
|
@ -1942,11 +1948,12 @@ impl Repository {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn change_branch(&self, branch_name: &str) -> oneshot::Receiver<Result<()>> {
|
||||
let branch_name = branch_name.to_owned();
|
||||
self.send_job(|repo| async move {
|
||||
pub fn change_branch(&self, branch_name: String) -> oneshot::Receiver<Result<()>> {
|
||||
self.send_job(|repo, cx| async move {
|
||||
match repo {
|
||||
GitRepo::Local(git_repository) => git_repository.change_branch(&branch_name),
|
||||
GitRepo::Local(git_repository) => {
|
||||
git_repository.change_branch(branch_name, cx).await
|
||||
}
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
|
@ -1969,9 +1976,9 @@ impl Repository {
|
|||
}
|
||||
|
||||
pub fn check_for_pushed_commits(&self) -> oneshot::Receiver<Result<Vec<SharedString>>> {
|
||||
self.send_job(|repo| async move {
|
||||
self.send_job(|repo, cx| async move {
|
||||
match repo {
|
||||
GitRepo::Local(git_repository) => git_repository.check_for_pushed_commit(),
|
||||
GitRepo::Local(git_repository) => git_repository.check_for_pushed_commit(cx).await,
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
|
|
|
@ -1361,7 +1361,7 @@ async fn test_remote_git_branches(cx: &mut TestAppContext, server_cx: &mut TestA
|
|||
|
||||
assert_eq!(&remote_branches, &branches_set);
|
||||
|
||||
cx.update(|cx| repository.read(cx).change_branch(new_branch))
|
||||
cx.update(|cx| repository.read(cx).change_branch(new_branch.to_string()))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
@ -1383,15 +1383,23 @@ async fn test_remote_git_branches(cx: &mut TestAppContext, server_cx: &mut TestA
|
|||
assert_eq!(server_branch.name, branches[2]);
|
||||
|
||||
// Also try creating a new branch
|
||||
cx.update(|cx| repository.read(cx).create_branch("totally-new-branch"))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
cx.update(|cx| {
|
||||
repository
|
||||
.read(cx)
|
||||
.create_branch("totally-new-branch".to_string())
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
cx.update(|cx| repository.read(cx).change_branch("totally-new-branch"))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
cx.update(|cx| {
|
||||
repository
|
||||
.read(cx)
|
||||
.change_branch("totally-new-branch".to_string())
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
cx.run_until_parked();
|
||||
|
||||
|
|
|
@ -1055,13 +1055,13 @@ impl Worktree {
|
|||
Worktree::Local(this) => {
|
||||
let path = Arc::from(path);
|
||||
let snapshot = this.snapshot();
|
||||
cx.background_spawn(async move {
|
||||
cx.spawn(|cx| async move {
|
||||
if let Some(repo) = snapshot.repository_for_path(&path) {
|
||||
if let Some(repo_path) = repo.relativize(&path).log_err() {
|
||||
if let Some(git_repo) =
|
||||
snapshot.git_repositories.get(&repo.work_directory_id)
|
||||
{
|
||||
return Ok(git_repo.repo_ptr.load_index_text(&repo_path));
|
||||
return Ok(git_repo.repo_ptr.load_index_text(repo_path, cx).await);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1079,13 +1079,16 @@ impl Worktree {
|
|||
Worktree::Local(this) => {
|
||||
let path = Arc::from(path);
|
||||
let snapshot = this.snapshot();
|
||||
cx.background_spawn(async move {
|
||||
cx.spawn(|cx| async move {
|
||||
if let Some(repo) = snapshot.repository_for_path(&path) {
|
||||
if let Some(repo_path) = repo.relativize(&path).log_err() {
|
||||
if let Some(git_repo) =
|
||||
snapshot.git_repositories.get(&repo.work_directory_id)
|
||||
{
|
||||
return Ok(git_repo.repo_ptr.load_committed_text(&repo_path));
|
||||
return Ok(git_repo
|
||||
.repo_ptr
|
||||
.load_committed_text(repo_path, cx)
|
||||
.await);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5520,7 +5523,9 @@ impl BackgroundScanner {
|
|||
state.repository_scans.insert(
|
||||
path_key.clone(),
|
||||
self.executor.spawn(async move {
|
||||
update_branches(&job_state, &mut local_repository).log_err();
|
||||
update_branches(&job_state, &mut local_repository)
|
||||
.await
|
||||
.log_err();
|
||||
log::trace!("updating git statuses for repo {repository_name}",);
|
||||
let t0 = Instant::now();
|
||||
|
||||
|
@ -5665,11 +5670,11 @@ fn send_status_update_inner(
|
|||
.is_ok()
|
||||
}
|
||||
|
||||
fn update_branches(
|
||||
async fn update_branches(
|
||||
state: &Mutex<BackgroundScannerState>,
|
||||
repository: &mut LocalRepositoryEntry,
|
||||
) -> Result<()> {
|
||||
let branches = repository.repo().branches()?;
|
||||
let branches = repository.repo().branches().await?;
|
||||
let snapshot = state.lock().snapshot.snapshot.clone();
|
||||
let mut repository = snapshot
|
||||
.repository(repository.work_directory.path_key())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue