Make GitRepository::status
async and remove cx parameter (#27514)
This lays the groundwork for using `status` as part of the new agent panel. Release Notes: - N/A
This commit is contained in:
parent
926d10cc45
commit
7354ef91e1
19 changed files with 662 additions and 716 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -4749,6 +4749,7 @@ dependencies = [
|
|||
"env_logger 0.11.7",
|
||||
"extension",
|
||||
"fs",
|
||||
"gpui",
|
||||
"language",
|
||||
"log",
|
||||
"reqwest_client",
|
||||
|
|
|
@ -1429,7 +1429,7 @@ impl Thread {
|
|||
|
||||
// Get diff asynchronously
|
||||
let diff = repo
|
||||
.diff(git::repository::DiffType::HeadToWorktree, cx.clone())
|
||||
.diff(git::repository::DiffType::HeadToWorktree)
|
||||
.await
|
||||
.ok();
|
||||
|
||||
|
|
|
@ -149,7 +149,10 @@ pub fn init(cx: &mut App) -> Arc<HeadlessAppState> {
|
|||
cx.set_http_client(client.http_client().clone());
|
||||
|
||||
let git_binary_path = None;
|
||||
let fs = Arc::new(RealFs::new(git_binary_path));
|
||||
let fs = Arc::new(RealFs::new(
|
||||
git_binary_path,
|
||||
cx.background_executor().clone(),
|
||||
));
|
||||
|
||||
let languages = Arc::new(LanguageRegistry::new(cx.background_executor().clone()));
|
||||
|
||||
|
|
|
@ -273,7 +273,7 @@ async fn run_evaluation(
|
|||
let repos_dir = Path::new(EVAL_REPOS_DIR);
|
||||
let db_path = Path::new(EVAL_DB_PATH);
|
||||
let api_key = std::env::var("OPENAI_API_KEY").unwrap();
|
||||
let fs = Arc::new(RealFs::new(None)) as Arc<dyn Fs>;
|
||||
let fs = Arc::new(RealFs::new(None, cx.background_executor().clone())) as Arc<dyn Fs>;
|
||||
let clock = Arc::new(RealSystemClock);
|
||||
let client = cx
|
||||
.update(|cx| {
|
||||
|
|
|
@ -18,6 +18,7 @@ clap = { workspace = true, features = ["derive"] }
|
|||
env_logger.workspace = true
|
||||
extension.workspace = true
|
||||
fs.workspace = true
|
||||
gpui.workspace = true
|
||||
language.workspace = true
|
||||
log.workspace = true
|
||||
reqwest_client.workspace = true
|
||||
|
|
|
@ -34,7 +34,7 @@ async fn main() -> Result<()> {
|
|||
env_logger::init();
|
||||
|
||||
let args = Args::parse();
|
||||
let fs = Arc::new(RealFs::default());
|
||||
let fs = Arc::new(RealFs::new(None, gpui::background_executor()));
|
||||
let engine = wasmtime::Engine::default();
|
||||
let mut wasm_store = WasmStore::new(&engine)?;
|
||||
|
||||
|
|
|
@ -477,7 +477,7 @@ async fn test_extension_store_with_test_extension(cx: &mut TestAppContext) {
|
|||
let test_extension_id = "test-extension";
|
||||
let test_extension_dir = root_dir.join("extensions").join(test_extension_id);
|
||||
|
||||
let fs = Arc::new(RealFs::default());
|
||||
let fs = Arc::new(RealFs::new(None, cx.executor()));
|
||||
let extensions_dir = TempTree::new(json!({
|
||||
"installed": {},
|
||||
"work": {}
|
||||
|
|
|
@ -62,7 +62,7 @@ impl FakeGitRepository {
|
|||
.unwrap()
|
||||
}
|
||||
|
||||
fn with_state_async<F, T>(&self, write: bool, f: F) -> BoxFuture<Result<T>>
|
||||
fn with_state_async<F, T>(&self, write: bool, f: F) -> BoxFuture<'static, Result<T>>
|
||||
where
|
||||
F: 'static + Send + FnOnce(&mut FakeGitRepositoryState) -> Result<T>,
|
||||
T: Send,
|
||||
|
@ -81,7 +81,7 @@ impl FakeGitRepository {
|
|||
impl GitRepository for FakeGitRepository {
|
||||
fn reload_index(&self) {}
|
||||
|
||||
fn load_index_text(&self, path: RepoPath, _cx: AsyncApp) -> BoxFuture<Option<String>> {
|
||||
fn load_index_text(&self, path: RepoPath) -> BoxFuture<Option<String>> {
|
||||
async {
|
||||
self.with_state_async(false, move |state| {
|
||||
state
|
||||
|
@ -96,7 +96,7 @@ impl GitRepository for FakeGitRepository {
|
|||
.boxed()
|
||||
}
|
||||
|
||||
fn load_committed_text(&self, path: RepoPath, _cx: AsyncApp) -> BoxFuture<Option<String>> {
|
||||
fn load_committed_text(&self, path: RepoPath) -> BoxFuture<Option<String>> {
|
||||
async {
|
||||
self.with_state_async(false, move |state| {
|
||||
state
|
||||
|
@ -116,7 +116,6 @@ impl GitRepository for FakeGitRepository {
|
|||
path: RepoPath,
|
||||
content: Option<String>,
|
||||
_env: HashMap<String, String>,
|
||||
_cx: AsyncApp,
|
||||
) -> BoxFuture<anyhow::Result<()>> {
|
||||
self.with_state_async(true, move |state| {
|
||||
if let Some(message) = state.simulated_index_write_error_message.clone() {
|
||||
|
@ -142,7 +141,7 @@ impl GitRepository for FakeGitRepository {
|
|||
vec![]
|
||||
}
|
||||
|
||||
fn show(&self, _commit: String, _cx: AsyncApp) -> BoxFuture<Result<CommitDetails>> {
|
||||
fn show(&self, _commit: String) -> BoxFuture<Result<CommitDetails>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
|
@ -172,7 +171,12 @@ impl GitRepository for FakeGitRepository {
|
|||
self.path()
|
||||
}
|
||||
|
||||
fn status(&self, path_prefixes: &[RepoPath]) -> Result<GitStatus> {
|
||||
fn status(&self, path_prefixes: &[RepoPath]) -> BoxFuture<'static, Result<GitStatus>> {
|
||||
let status = self.status_blocking(path_prefixes);
|
||||
async move { status }.boxed()
|
||||
}
|
||||
|
||||
fn status_blocking(&self, path_prefixes: &[RepoPath]) -> Result<GitStatus> {
|
||||
let workdir_path = self.dot_git_path.parent().unwrap();
|
||||
|
||||
// Load gitignores
|
||||
|
@ -317,26 +321,21 @@ impl GitRepository for FakeGitRepository {
|
|||
})
|
||||
}
|
||||
|
||||
fn change_branch(&self, name: String, _cx: AsyncApp) -> BoxFuture<Result<()>> {
|
||||
fn change_branch(&self, name: String) -> BoxFuture<Result<()>> {
|
||||
self.with_state_async(true, |state| {
|
||||
state.current_branch_name = Some(name);
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn create_branch(&self, name: String, _: AsyncApp) -> BoxFuture<Result<()>> {
|
||||
fn create_branch(&self, name: String) -> BoxFuture<Result<()>> {
|
||||
self.with_state_async(true, move |state| {
|
||||
state.branches.insert(name.to_owned());
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn blame(
|
||||
&self,
|
||||
path: RepoPath,
|
||||
_content: Rope,
|
||||
_cx: &mut AsyncApp,
|
||||
) -> BoxFuture<Result<git::blame::Blame>> {
|
||||
fn blame(&self, path: RepoPath, _content: Rope) -> BoxFuture<Result<git::blame::Blame>> {
|
||||
self.with_state_async(false, move |state| {
|
||||
state
|
||||
.blames
|
||||
|
@ -350,7 +349,6 @@ impl GitRepository for FakeGitRepository {
|
|||
&self,
|
||||
_paths: Vec<RepoPath>,
|
||||
_env: HashMap<String, String>,
|
||||
_cx: AsyncApp,
|
||||
) -> BoxFuture<Result<()>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
@ -359,7 +357,6 @@ impl GitRepository for FakeGitRepository {
|
|||
&self,
|
||||
_paths: Vec<RepoPath>,
|
||||
_env: HashMap<String, String>,
|
||||
_cx: AsyncApp,
|
||||
) -> BoxFuture<Result<()>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
@ -369,7 +366,6 @@ impl GitRepository for FakeGitRepository {
|
|||
_message: gpui::SharedString,
|
||||
_name_and_email: Option<(gpui::SharedString, gpui::SharedString)>,
|
||||
_env: HashMap<String, String>,
|
||||
_cx: AsyncApp,
|
||||
) -> BoxFuture<Result<()>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
@ -406,38 +402,23 @@ impl GitRepository for FakeGitRepository {
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_remotes(
|
||||
&self,
|
||||
_branch: Option<String>,
|
||||
_cx: AsyncApp,
|
||||
) -> BoxFuture<Result<Vec<Remote>>> {
|
||||
fn get_remotes(&self, _branch: Option<String>) -> BoxFuture<Result<Vec<Remote>>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn check_for_pushed_commit(
|
||||
&self,
|
||||
_cx: gpui::AsyncApp,
|
||||
) -> BoxFuture<Result<Vec<gpui::SharedString>>> {
|
||||
fn check_for_pushed_commit(&self) -> BoxFuture<Result<Vec<gpui::SharedString>>> {
|
||||
future::ready(Ok(Vec::new())).boxed()
|
||||
}
|
||||
|
||||
fn diff(
|
||||
&self,
|
||||
_diff: git::repository::DiffType,
|
||||
_cx: gpui::AsyncApp,
|
||||
) -> BoxFuture<Result<String>> {
|
||||
fn diff(&self, _diff: git::repository::DiffType) -> BoxFuture<Result<String>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn checkpoint(&self, _cx: AsyncApp) -> BoxFuture<Result<GitRepositoryCheckpoint>> {
|
||||
fn checkpoint(&self) -> BoxFuture<Result<GitRepositoryCheckpoint>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn restore_checkpoint(
|
||||
&self,
|
||||
_checkpoint: GitRepositoryCheckpoint,
|
||||
_cx: AsyncApp,
|
||||
) -> BoxFuture<Result<()>> {
|
||||
fn restore_checkpoint(&self, _checkpoint: GitRepositoryCheckpoint) -> BoxFuture<Result<()>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
|
@ -445,16 +426,11 @@ impl GitRepository for FakeGitRepository {
|
|||
&self,
|
||||
_left: GitRepositoryCheckpoint,
|
||||
_right: GitRepositoryCheckpoint,
|
||||
_cx: AsyncApp,
|
||||
) -> BoxFuture<Result<bool>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn delete_checkpoint(
|
||||
&self,
|
||||
_checkpoint: GitRepositoryCheckpoint,
|
||||
_cx: AsyncApp,
|
||||
) -> BoxFuture<Result<()>> {
|
||||
fn delete_checkpoint(&self, _checkpoint: GitRepositoryCheckpoint) -> BoxFuture<Result<()>> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use anyhow::{anyhow, Context as _, Result};
|
|||
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
||||
use ashpd::desktop::trash;
|
||||
use gpui::App;
|
||||
use gpui::BackgroundExecutor;
|
||||
use gpui::Global;
|
||||
use gpui::ReadGlobal as _;
|
||||
use std::borrow::Cow;
|
||||
|
@ -240,9 +241,9 @@ impl From<MTime> for proto::Timestamp {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct RealFs {
|
||||
git_binary_path: Option<PathBuf>,
|
||||
executor: BackgroundExecutor,
|
||||
}
|
||||
|
||||
pub trait FileHandle: Send + Sync + std::fmt::Debug {
|
||||
|
@ -294,8 +295,11 @@ impl FileHandle for std::fs::File {
|
|||
pub struct RealWatcher {}
|
||||
|
||||
impl RealFs {
|
||||
pub fn new(git_binary_path: Option<PathBuf>) -> Self {
|
||||
Self { git_binary_path }
|
||||
pub fn new(git_binary_path: Option<PathBuf>, executor: BackgroundExecutor) -> Self {
|
||||
Self {
|
||||
git_binary_path,
|
||||
executor,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -754,6 +758,7 @@ impl Fs for RealFs {
|
|||
Some(Arc::new(RealGitRepository::new(
|
||||
dotgit_path,
|
||||
self.git_binary_path.clone(),
|
||||
self.executor.clone(),
|
||||
)?))
|
||||
}
|
||||
|
||||
|
|
|
@ -5,13 +5,13 @@ use collections::HashMap;
|
|||
use futures::future::BoxFuture;
|
||||
use futures::{select_biased, AsyncWriteExt, FutureExt as _};
|
||||
use git2::BranchType;
|
||||
use gpui::{AppContext, AsyncApp, BackgroundExecutor, SharedString};
|
||||
use gpui::{AsyncApp, BackgroundExecutor, SharedString};
|
||||
use parking_lot::Mutex;
|
||||
use rope::Rope;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use std::borrow::{Borrow, Cow};
|
||||
use std::ffi::OsStr;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::future;
|
||||
use std::path::Component;
|
||||
use std::process::{ExitStatus, Stdio};
|
||||
|
@ -23,7 +23,7 @@ use std::{
|
|||
};
|
||||
use sum_tree::MapSeekTarget;
|
||||
use thiserror::Error;
|
||||
use util::command::new_smol_command;
|
||||
use util::command::{new_smol_command, new_std_command};
|
||||
use util::ResultExt;
|
||||
use uuid::Uuid;
|
||||
|
||||
|
@ -161,19 +161,18 @@ pub trait GitRepository: Send + Sync {
|
|||
/// Returns the contents of an entry in the repository's index, or None if there is no entry for the given path.
|
||||
///
|
||||
/// Also returns `None` for symlinks.
|
||||
fn load_index_text(&self, path: RepoPath, cx: AsyncApp) -> BoxFuture<Option<String>>;
|
||||
fn load_index_text(&self, path: RepoPath) -> BoxFuture<Option<String>>;
|
||||
|
||||
/// Returns the contents of an entry in the repository's HEAD, or None if HEAD does not exist or has no entry for the given path.
|
||||
///
|
||||
/// Also returns `None` for symlinks.
|
||||
fn load_committed_text(&self, path: RepoPath, cx: AsyncApp) -> BoxFuture<Option<String>>;
|
||||
fn load_committed_text(&self, path: RepoPath) -> BoxFuture<Option<String>>;
|
||||
|
||||
fn set_index_text(
|
||||
&self,
|
||||
path: RepoPath,
|
||||
content: Option<String>,
|
||||
env: HashMap<String, String>,
|
||||
cx: AsyncApp,
|
||||
) -> BoxFuture<anyhow::Result<()>>;
|
||||
|
||||
/// Returns the URL of the remote with the given name.
|
||||
|
@ -184,13 +183,13 @@ pub trait GitRepository: Send + Sync {
|
|||
|
||||
fn merge_head_shas(&self) -> Vec<String>;
|
||||
|
||||
// Note: this method blocks the current thread!
|
||||
fn status(&self, path_prefixes: &[RepoPath]) -> Result<GitStatus>;
|
||||
fn status(&self, path_prefixes: &[RepoPath]) -> BoxFuture<'static, Result<GitStatus>>;
|
||||
fn status_blocking(&self, path_prefixes: &[RepoPath]) -> Result<GitStatus>;
|
||||
|
||||
fn branches(&self) -> BoxFuture<Result<Vec<Branch>>>;
|
||||
|
||||
fn change_branch(&self, _: String, _: AsyncApp) -> BoxFuture<Result<()>>;
|
||||
fn create_branch(&self, _: String, _: AsyncApp) -> BoxFuture<Result<()>>;
|
||||
fn change_branch(&self, name: String) -> BoxFuture<Result<()>>;
|
||||
fn create_branch(&self, name: String) -> BoxFuture<Result<()>>;
|
||||
|
||||
fn reset(
|
||||
&self,
|
||||
|
@ -206,14 +205,9 @@ pub trait GitRepository: Send + Sync {
|
|||
env: HashMap<String, String>,
|
||||
) -> BoxFuture<Result<()>>;
|
||||
|
||||
fn show(&self, commit: String, cx: AsyncApp) -> BoxFuture<Result<CommitDetails>>;
|
||||
fn show(&self, commit: String) -> BoxFuture<Result<CommitDetails>>;
|
||||
|
||||
fn blame(
|
||||
&self,
|
||||
path: RepoPath,
|
||||
content: Rope,
|
||||
cx: &mut AsyncApp,
|
||||
) -> BoxFuture<Result<crate::blame::Blame>>;
|
||||
fn blame(&self, path: RepoPath, content: Rope) -> BoxFuture<Result<crate::blame::Blame>>;
|
||||
|
||||
/// Returns the absolute path to the repository. For worktrees, this will be the path to the
|
||||
/// worktree's gitdir within the main repository (typically `.git/worktrees/<name>`).
|
||||
|
@ -234,7 +228,6 @@ pub trait GitRepository: Send + Sync {
|
|||
&self,
|
||||
paths: Vec<RepoPath>,
|
||||
env: HashMap<String, String>,
|
||||
cx: AsyncApp,
|
||||
) -> BoxFuture<Result<()>>;
|
||||
/// Updates the index to match HEAD at the given paths.
|
||||
///
|
||||
|
@ -243,7 +236,6 @@ pub trait GitRepository: Send + Sync {
|
|||
&self,
|
||||
paths: Vec<RepoPath>,
|
||||
env: HashMap<String, String>,
|
||||
cx: AsyncApp,
|
||||
) -> BoxFuture<Result<()>>;
|
||||
|
||||
fn commit(
|
||||
|
@ -251,7 +243,6 @@ pub trait GitRepository: Send + Sync {
|
|||
message: SharedString,
|
||||
name_and_email: Option<(SharedString, SharedString)>,
|
||||
env: HashMap<String, String>,
|
||||
cx: AsyncApp,
|
||||
) -> BoxFuture<Result<()>>;
|
||||
|
||||
fn push(
|
||||
|
@ -261,6 +252,8 @@ pub trait GitRepository: Send + Sync {
|
|||
options: Option<PushOptions>,
|
||||
askpass: AskPassSession,
|
||||
env: HashMap<String, String>,
|
||||
// This method takes an AsyncApp to ensure it's invoked on the main thread,
|
||||
// otherwise git-credentials-manager won't work.
|
||||
cx: AsyncApp,
|
||||
) -> BoxFuture<Result<RemoteCommandOutput>>;
|
||||
|
||||
|
@ -270,6 +263,8 @@ pub trait GitRepository: Send + Sync {
|
|||
upstream_name: String,
|
||||
askpass: AskPassSession,
|
||||
env: HashMap<String, String>,
|
||||
// This method takes an AsyncApp to ensure it's invoked on the main thread,
|
||||
// otherwise git-credentials-manager won't work.
|
||||
cx: AsyncApp,
|
||||
) -> BoxFuture<Result<RemoteCommandOutput>>;
|
||||
|
||||
|
@ -277,45 +272,34 @@ pub trait GitRepository: Send + Sync {
|
|||
&self,
|
||||
askpass: AskPassSession,
|
||||
env: HashMap<String, String>,
|
||||
// This method takes an AsyncApp to ensure it's invoked on the main thread,
|
||||
// otherwise git-credentials-manager won't work.
|
||||
cx: AsyncApp,
|
||||
) -> BoxFuture<Result<RemoteCommandOutput>>;
|
||||
|
||||
fn get_remotes(
|
||||
&self,
|
||||
branch_name: Option<String>,
|
||||
cx: AsyncApp,
|
||||
) -> BoxFuture<Result<Vec<Remote>>>;
|
||||
fn get_remotes(&self, branch_name: Option<String>) -> BoxFuture<Result<Vec<Remote>>>;
|
||||
|
||||
/// returns a list of remote branches that contain HEAD
|
||||
fn check_for_pushed_commit(&self, cx: AsyncApp) -> BoxFuture<Result<Vec<SharedString>>>;
|
||||
fn check_for_pushed_commit(&self) -> BoxFuture<Result<Vec<SharedString>>>;
|
||||
|
||||
/// Run git diff
|
||||
fn diff(&self, diff: DiffType, cx: AsyncApp) -> BoxFuture<Result<String>>;
|
||||
fn diff(&self, diff: DiffType) -> BoxFuture<Result<String>>;
|
||||
|
||||
/// Creates a checkpoint for the repository.
|
||||
fn checkpoint(&self, cx: AsyncApp) -> BoxFuture<Result<GitRepositoryCheckpoint>>;
|
||||
fn checkpoint(&self) -> BoxFuture<Result<GitRepositoryCheckpoint>>;
|
||||
|
||||
/// Resets to a previously-created checkpoint.
|
||||
fn restore_checkpoint(
|
||||
&self,
|
||||
checkpoint: GitRepositoryCheckpoint,
|
||||
cx: AsyncApp,
|
||||
) -> BoxFuture<Result<()>>;
|
||||
fn restore_checkpoint(&self, checkpoint: GitRepositoryCheckpoint) -> BoxFuture<Result<()>>;
|
||||
|
||||
/// Compares two checkpoints, returning true if they are equal
|
||||
fn compare_checkpoints(
|
||||
&self,
|
||||
left: GitRepositoryCheckpoint,
|
||||
right: GitRepositoryCheckpoint,
|
||||
cx: AsyncApp,
|
||||
) -> BoxFuture<Result<bool>>;
|
||||
|
||||
/// Deletes a previously-created checkpoint.
|
||||
fn delete_checkpoint(
|
||||
&self,
|
||||
checkpoint: GitRepositoryCheckpoint,
|
||||
cx: AsyncApp,
|
||||
) -> BoxFuture<Result<()>>;
|
||||
fn delete_checkpoint(&self, checkpoint: GitRepositoryCheckpoint) -> BoxFuture<Result<()>>;
|
||||
}
|
||||
|
||||
pub enum DiffType {
|
||||
|
@ -338,15 +322,21 @@ impl std::fmt::Debug for dyn GitRepository {
|
|||
pub struct RealGitRepository {
|
||||
pub repository: Arc<Mutex<git2::Repository>>,
|
||||
pub git_binary_path: PathBuf,
|
||||
executor: BackgroundExecutor,
|
||||
}
|
||||
|
||||
impl RealGitRepository {
|
||||
pub fn new(dotgit_path: &Path, git_binary_path: Option<PathBuf>) -> Option<Self> {
|
||||
pub fn new(
|
||||
dotgit_path: &Path,
|
||||
git_binary_path: Option<PathBuf>,
|
||||
executor: BackgroundExecutor,
|
||||
) -> Option<Self> {
|
||||
let workdir_root = dotgit_path.parent()?;
|
||||
let repository = git2::Repository::open(workdir_root).log_err()?;
|
||||
Some(Self {
|
||||
repository: Arc::new(Mutex::new(repository)),
|
||||
git_binary_path: git_binary_path.unwrap_or_else(|| PathBuf::from("git")),
|
||||
executor,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -386,9 +376,10 @@ impl GitRepository for RealGitRepository {
|
|||
repo.commondir().into()
|
||||
}
|
||||
|
||||
fn show(&self, commit: String, cx: AsyncApp) -> BoxFuture<Result<CommitDetails>> {
|
||||
fn show(&self, commit: String) -> BoxFuture<Result<CommitDetails>> {
|
||||
let repo = self.repository.clone();
|
||||
cx.background_spawn(async move {
|
||||
self.executor
|
||||
.spawn(async move {
|
||||
let repo = repo.lock();
|
||||
let Ok(commit) = repo.revparse_single(&commit)?.into_commit() else {
|
||||
anyhow::bail!("{} is not a commit", commit);
|
||||
|
@ -473,9 +464,10 @@ impl GitRepository for RealGitRepository {
|
|||
.boxed()
|
||||
}
|
||||
|
||||
fn load_index_text(&self, path: RepoPath, cx: AsyncApp) -> BoxFuture<Option<String>> {
|
||||
fn load_index_text(&self, path: RepoPath) -> BoxFuture<Option<String>> {
|
||||
let repo = self.repository.clone();
|
||||
cx.background_spawn(async move {
|
||||
self.executor
|
||||
.spawn(async move {
|
||||
fn logic(repo: &git2::Repository, path: &RepoPath) -> Result<Option<String>> {
|
||||
// This check is required because index.get_path() unwraps internally :(
|
||||
check_path_to_repo_path_errors(path)?;
|
||||
|
@ -501,9 +493,10 @@ impl GitRepository for RealGitRepository {
|
|||
.boxed()
|
||||
}
|
||||
|
||||
fn load_committed_text(&self, path: RepoPath, cx: AsyncApp) -> BoxFuture<Option<String>> {
|
||||
fn load_committed_text(&self, path: RepoPath) -> BoxFuture<Option<String>> {
|
||||
let repo = self.repository.clone();
|
||||
cx.background_spawn(async move {
|
||||
self.executor
|
||||
.spawn(async move {
|
||||
let repo = repo.lock();
|
||||
let head = repo.head().ok()?.peel_to_tree().log_err()?;
|
||||
let entry = head.get_path(&path).ok()?;
|
||||
|
@ -522,11 +515,11 @@ impl GitRepository for RealGitRepository {
|
|||
path: RepoPath,
|
||||
content: Option<String>,
|
||||
env: HashMap<String, String>,
|
||||
cx: AsyncApp,
|
||||
) -> BoxFuture<anyhow::Result<()>> {
|
||||
let working_directory = self.working_directory();
|
||||
let git_binary_path = self.git_binary_path.clone();
|
||||
cx.background_spawn(async move {
|
||||
self.executor
|
||||
.spawn(async move {
|
||||
let working_directory = working_directory?;
|
||||
if let Some(content) = content {
|
||||
let mut child = new_smol_command(&git_binary_path)
|
||||
|
@ -614,14 +607,32 @@ impl GitRepository for RealGitRepository {
|
|||
shas
|
||||
}
|
||||
|
||||
fn status(&self, path_prefixes: &[RepoPath]) -> Result<GitStatus> {
|
||||
let working_directory = self
|
||||
.repository
|
||||
.lock()
|
||||
.workdir()
|
||||
.context("failed to read git work directory")?
|
||||
.to_path_buf();
|
||||
GitStatus::new(&self.git_binary_path, &working_directory, path_prefixes)
|
||||
fn status(&self, path_prefixes: &[RepoPath]) -> BoxFuture<'static, Result<GitStatus>> {
|
||||
let working_directory = self.working_directory();
|
||||
let git_binary_path = self.git_binary_path.clone();
|
||||
let executor = self.executor.clone();
|
||||
let args = git_status_args(path_prefixes);
|
||||
self.executor
|
||||
.spawn(async move {
|
||||
let working_directory = working_directory?;
|
||||
let git = GitBinary::new(git_binary_path, working_directory, executor);
|
||||
git.run(&args).await?.parse()
|
||||
})
|
||||
.boxed()
|
||||
}
|
||||
|
||||
fn status_blocking(&self, path_prefixes: &[RepoPath]) -> Result<GitStatus> {
|
||||
let output = new_std_command(&self.git_binary_path)
|
||||
.current_dir(self.working_directory()?)
|
||||
.args(git_status_args(path_prefixes))
|
||||
.output()?;
|
||||
if output.status.success() {
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
stdout.parse()
|
||||
} else {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
Err(anyhow!("git status failed: {}", stderr))
|
||||
}
|
||||
}
|
||||
|
||||
fn branches(&self) -> BoxFuture<Result<Vec<Branch>>> {
|
||||
|
@ -685,9 +696,10 @@ impl GitRepository for RealGitRepository {
|
|||
.boxed()
|
||||
}
|
||||
|
||||
fn change_branch(&self, name: String, cx: AsyncApp) -> BoxFuture<Result<()>> {
|
||||
fn change_branch(&self, name: String) -> BoxFuture<Result<()>> {
|
||||
let repo = self.repository.clone();
|
||||
cx.background_spawn(async move {
|
||||
self.executor
|
||||
.spawn(async move {
|
||||
let repo = repo.lock();
|
||||
let revision = repo.find_branch(&name, BranchType::Local)?;
|
||||
let revision = revision.get();
|
||||
|
@ -703,9 +715,10 @@ impl GitRepository for RealGitRepository {
|
|||
.boxed()
|
||||
}
|
||||
|
||||
fn create_branch(&self, name: String, cx: AsyncApp) -> BoxFuture<Result<()>> {
|
||||
fn create_branch(&self, name: String) -> BoxFuture<Result<()>> {
|
||||
let repo = self.repository.clone();
|
||||
cx.background_spawn(async move {
|
||||
self.executor
|
||||
.spawn(async move {
|
||||
let repo = repo.lock();
|
||||
let current_commit = repo.head()?.peel_to_commit()?;
|
||||
repo.branch(&name, ¤t_commit, false)?;
|
||||
|
@ -714,19 +727,15 @@ impl GitRepository for RealGitRepository {
|
|||
.boxed()
|
||||
}
|
||||
|
||||
fn blame(
|
||||
&self,
|
||||
path: RepoPath,
|
||||
content: Rope,
|
||||
cx: &mut AsyncApp,
|
||||
) -> BoxFuture<Result<crate::blame::Blame>> {
|
||||
fn blame(&self, path: RepoPath, content: Rope) -> BoxFuture<Result<crate::blame::Blame>> {
|
||||
let working_directory = self.working_directory();
|
||||
let git_binary_path = self.git_binary_path.clone();
|
||||
|
||||
const REMOTE_NAME: &str = "origin";
|
||||
let remote_url = self.remote_url(REMOTE_NAME);
|
||||
|
||||
cx.background_spawn(async move {
|
||||
self.executor
|
||||
.spawn(async move {
|
||||
crate::blame::Blame::for_path(
|
||||
&git_binary_path,
|
||||
&working_directory?,
|
||||
|
@ -739,10 +748,11 @@ impl GitRepository for RealGitRepository {
|
|||
.boxed()
|
||||
}
|
||||
|
||||
fn diff(&self, diff: DiffType, cx: AsyncApp) -> BoxFuture<Result<String>> {
|
||||
fn diff(&self, diff: DiffType) -> BoxFuture<Result<String>> {
|
||||
let working_directory = self.working_directory();
|
||||
let git_binary_path = self.git_binary_path.clone();
|
||||
cx.background_spawn(async move {
|
||||
self.executor
|
||||
.spawn(async move {
|
||||
let args = match diff {
|
||||
DiffType::HeadToIndex => Some("--staged"),
|
||||
DiffType::HeadToWorktree => None,
|
||||
|
@ -770,11 +780,11 @@ impl GitRepository for RealGitRepository {
|
|||
&self,
|
||||
paths: Vec<RepoPath>,
|
||||
env: HashMap<String, String>,
|
||||
cx: AsyncApp,
|
||||
) -> BoxFuture<Result<()>> {
|
||||
let working_directory = self.working_directory();
|
||||
let git_binary_path = self.git_binary_path.clone();
|
||||
cx.background_spawn(async move {
|
||||
self.executor
|
||||
.spawn(async move {
|
||||
if !paths.is_empty() {
|
||||
let output = new_smol_command(&git_binary_path)
|
||||
.current_dir(&working_directory?)
|
||||
|
@ -800,12 +810,12 @@ impl GitRepository for RealGitRepository {
|
|||
&self,
|
||||
paths: Vec<RepoPath>,
|
||||
env: HashMap<String, String>,
|
||||
cx: AsyncApp,
|
||||
) -> BoxFuture<Result<()>> {
|
||||
let working_directory = self.working_directory();
|
||||
let git_binary_path = self.git_binary_path.clone();
|
||||
|
||||
cx.background_spawn(async move {
|
||||
self.executor
|
||||
.spawn(async move {
|
||||
if !paths.is_empty() {
|
||||
let output = new_smol_command(&git_binary_path)
|
||||
.current_dir(&working_directory?)
|
||||
|
@ -832,10 +842,10 @@ impl GitRepository for RealGitRepository {
|
|||
message: SharedString,
|
||||
name_and_email: Option<(SharedString, SharedString)>,
|
||||
env: HashMap<String, String>,
|
||||
cx: AsyncApp,
|
||||
) -> BoxFuture<Result<()>> {
|
||||
let working_directory = self.working_directory();
|
||||
cx.background_spawn(async move {
|
||||
self.executor
|
||||
.spawn(async move {
|
||||
let mut cmd = new_smol_command("git");
|
||||
cmd.current_dir(&working_directory?)
|
||||
.envs(env)
|
||||
|
@ -867,8 +877,6 @@ impl GitRepository for RealGitRepository {
|
|||
options: Option<PushOptions>,
|
||||
ask_pass: AskPassSession,
|
||||
env: HashMap<String, String>,
|
||||
// note: git push *must* be started on the main thread for
|
||||
// git-credentials manager to work (hence taking an AsyncApp)
|
||||
_cx: AsyncApp,
|
||||
) -> BoxFuture<Result<RemoteCommandOutput>> {
|
||||
let working_directory = self.working_directory();
|
||||
|
@ -954,14 +962,11 @@ impl GitRepository for RealGitRepository {
|
|||
.boxed()
|
||||
}
|
||||
|
||||
fn get_remotes(
|
||||
&self,
|
||||
branch_name: Option<String>,
|
||||
cx: AsyncApp,
|
||||
) -> BoxFuture<Result<Vec<Remote>>> {
|
||||
fn get_remotes(&self, branch_name: Option<String>) -> BoxFuture<Result<Vec<Remote>>> {
|
||||
let working_directory = self.working_directory();
|
||||
let git_binary_path = self.git_binary_path.clone();
|
||||
cx.background_spawn(async move {
|
||||
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)
|
||||
|
@ -1006,10 +1011,11 @@ impl GitRepository for RealGitRepository {
|
|||
.boxed()
|
||||
}
|
||||
|
||||
fn check_for_pushed_commit(&self, cx: AsyncApp) -> BoxFuture<Result<Vec<SharedString>>> {
|
||||
fn check_for_pushed_commit(&self) -> BoxFuture<Result<Vec<SharedString>>> {
|
||||
let working_directory = self.working_directory();
|
||||
let git_binary_path = self.git_binary_path.clone();
|
||||
cx.background_spawn(async move {
|
||||
self.executor
|
||||
.spawn(async move {
|
||||
let working_directory = working_directory?;
|
||||
let git_cmd = async |args: &[&str]| -> Result<String> {
|
||||
let output = new_smol_command(&git_binary_path)
|
||||
|
@ -1054,7 +1060,9 @@ impl GitRepository for RealGitRepository {
|
|||
}
|
||||
|
||||
// ... and the remote branch that the checked-out one is tracking
|
||||
if let Ok(remote_head) = git_cmd(&["rev-parse", "--symbolic-full-name", "@{u}"]).await {
|
||||
if let Ok(remote_head) =
|
||||
git_cmd(&["rev-parse", "--symbolic-full-name", "@{u}"]).await
|
||||
{
|
||||
add_if_matching(remote_head.trim()).await;
|
||||
}
|
||||
|
||||
|
@ -1063,11 +1071,12 @@ impl GitRepository for RealGitRepository {
|
|||
.boxed()
|
||||
}
|
||||
|
||||
fn checkpoint(&self, cx: AsyncApp) -> BoxFuture<Result<GitRepositoryCheckpoint>> {
|
||||
fn checkpoint(&self) -> BoxFuture<Result<GitRepositoryCheckpoint>> {
|
||||
let working_directory = self.working_directory();
|
||||
let git_binary_path = self.git_binary_path.clone();
|
||||
let executor = cx.background_executor().clone();
|
||||
cx.background_spawn(async move {
|
||||
let executor = self.executor.clone();
|
||||
self.executor
|
||||
.spawn(async move {
|
||||
let working_directory = working_directory?;
|
||||
let mut git = GitBinary::new(git_binary_path, working_directory, executor)
|
||||
.envs(checkpoint_author_envs());
|
||||
|
@ -1099,16 +1108,13 @@ impl GitRepository for RealGitRepository {
|
|||
.boxed()
|
||||
}
|
||||
|
||||
fn restore_checkpoint(
|
||||
&self,
|
||||
checkpoint: GitRepositoryCheckpoint,
|
||||
cx: AsyncApp,
|
||||
) -> BoxFuture<Result<()>> {
|
||||
fn restore_checkpoint(&self, checkpoint: GitRepositoryCheckpoint) -> BoxFuture<Result<()>> {
|
||||
let working_directory = self.working_directory();
|
||||
let git_binary_path = self.git_binary_path.clone();
|
||||
|
||||
let executor = cx.background_executor().clone();
|
||||
cx.background_spawn(async move {
|
||||
let executor = self.executor.clone();
|
||||
self.executor
|
||||
.spawn(async move {
|
||||
let working_directory = working_directory?;
|
||||
|
||||
let mut git = GitBinary::new(git_binary_path, working_directory, executor);
|
||||
|
@ -1144,7 +1150,6 @@ impl GitRepository for RealGitRepository {
|
|||
&self,
|
||||
left: GitRepositoryCheckpoint,
|
||||
right: GitRepositoryCheckpoint,
|
||||
cx: AsyncApp,
|
||||
) -> BoxFuture<Result<bool>> {
|
||||
if left.head_sha != right.head_sha {
|
||||
return future::ready(Ok(false)).boxed();
|
||||
|
@ -1153,8 +1158,9 @@ impl GitRepository for RealGitRepository {
|
|||
let working_directory = self.working_directory();
|
||||
let git_binary_path = self.git_binary_path.clone();
|
||||
|
||||
let executor = cx.background_executor().clone();
|
||||
cx.background_spawn(async move {
|
||||
let executor = self.executor.clone();
|
||||
self.executor
|
||||
.spawn(async move {
|
||||
let working_directory = working_directory?;
|
||||
let git = GitBinary::new(git_binary_path, working_directory, executor);
|
||||
let result = git
|
||||
|
@ -1183,16 +1189,13 @@ impl GitRepository for RealGitRepository {
|
|||
.boxed()
|
||||
}
|
||||
|
||||
fn delete_checkpoint(
|
||||
&self,
|
||||
checkpoint: GitRepositoryCheckpoint,
|
||||
cx: AsyncApp,
|
||||
) -> BoxFuture<Result<()>> {
|
||||
fn delete_checkpoint(&self, checkpoint: GitRepositoryCheckpoint) -> BoxFuture<Result<()>> {
|
||||
let working_directory = self.working_directory();
|
||||
let git_binary_path = self.git_binary_path.clone();
|
||||
|
||||
let executor = cx.background_executor().clone();
|
||||
cx.background_spawn(async move {
|
||||
let executor = self.executor.clone();
|
||||
self.executor
|
||||
.spawn(async move {
|
||||
let working_directory = working_directory?;
|
||||
let git = GitBinary::new(git_binary_path, working_directory, executor);
|
||||
git.run(&["update-ref", "-d", &checkpoint.ref_name]).await?;
|
||||
|
@ -1202,6 +1205,25 @@ impl GitRepository for RealGitRepository {
|
|||
}
|
||||
}
|
||||
|
||||
fn git_status_args(path_prefixes: &[RepoPath]) -> Vec<OsString> {
|
||||
let mut args = vec![
|
||||
OsString::from("--no-optional-locks"),
|
||||
OsString::from("status"),
|
||||
OsString::from("--porcelain=v1"),
|
||||
OsString::from("--untracked-files=all"),
|
||||
OsString::from("--no-renames"),
|
||||
OsString::from("-z"),
|
||||
];
|
||||
args.extend(path_prefixes.iter().map(|path_prefix| {
|
||||
if path_prefix.0.as_ref() == Path::new("") {
|
||||
Path::new(".").into()
|
||||
} else {
|
||||
path_prefix.as_os_str().into()
|
||||
}
|
||||
}));
|
||||
args
|
||||
}
|
||||
|
||||
struct GitBinary {
|
||||
git_binary_path: PathBuf,
|
||||
working_directory: PathBuf,
|
||||
|
@ -1259,7 +1281,10 @@ impl GitBinary {
|
|||
Ok(result)
|
||||
}
|
||||
|
||||
pub async fn run(&self, args: &[&str]) -> Result<String> {
|
||||
pub async fn run<S>(&self, args: impl IntoIterator<Item = S>) -> Result<String>
|
||||
where
|
||||
S: AsRef<OsStr>,
|
||||
{
|
||||
let mut command = new_smol_command(&self.git_binary_path);
|
||||
command.current_dir(&self.working_directory);
|
||||
command.args(args);
|
||||
|
@ -1558,20 +1583,12 @@ mod tests {
|
|||
let file_path = repo_dir.path().join("file");
|
||||
smol::fs::write(&file_path, "initial").await.unwrap();
|
||||
|
||||
let repo = RealGitRepository::new(&repo_dir.path().join(".git"), None).unwrap();
|
||||
repo.stage_paths(
|
||||
vec![RepoPath::from_str("file")],
|
||||
HashMap::default(),
|
||||
cx.to_async(),
|
||||
)
|
||||
let repo =
|
||||
RealGitRepository::new(&repo_dir.path().join(".git"), None, cx.executor()).unwrap();
|
||||
repo.stage_paths(vec![RepoPath::from_str("file")], HashMap::default())
|
||||
.await
|
||||
.unwrap();
|
||||
repo.commit(
|
||||
"Initial commit".into(),
|
||||
None,
|
||||
checkpoint_author_envs(),
|
||||
cx.to_async(),
|
||||
)
|
||||
repo.commit("Initial commit".into(), None, checkpoint_author_envs())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
@ -1582,7 +1599,7 @@ mod tests {
|
|||
.await
|
||||
.unwrap();
|
||||
let sha_before_checkpoint = repo.head_sha().unwrap();
|
||||
let checkpoint = repo.checkpoint(cx.to_async()).await.unwrap();
|
||||
let checkpoint = repo.checkpoint().await.unwrap();
|
||||
|
||||
// Ensure the user can't see any branches after creating a checkpoint.
|
||||
assert_eq!(repo.branches().await.unwrap().len(), 1);
|
||||
|
@ -1590,18 +1607,13 @@ mod tests {
|
|||
smol::fs::write(&file_path, "modified after checkpoint")
|
||||
.await
|
||||
.unwrap();
|
||||
repo.stage_paths(
|
||||
vec![RepoPath::from_str("file")],
|
||||
HashMap::default(),
|
||||
cx.to_async(),
|
||||
)
|
||||
repo.stage_paths(vec![RepoPath::from_str("file")], HashMap::default())
|
||||
.await
|
||||
.unwrap();
|
||||
repo.commit(
|
||||
"Commit after checkpoint".into(),
|
||||
None,
|
||||
checkpoint_author_envs(),
|
||||
cx.to_async(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
@ -1614,10 +1626,8 @@ mod tests {
|
|||
.unwrap();
|
||||
|
||||
// Ensure checkpoint stays alive even after a Git GC.
|
||||
repo.gc(cx.to_async()).await.unwrap();
|
||||
repo.restore_checkpoint(checkpoint.clone(), cx.to_async())
|
||||
.await
|
||||
.unwrap();
|
||||
repo.gc().await.unwrap();
|
||||
repo.restore_checkpoint(checkpoint.clone()).await.unwrap();
|
||||
|
||||
assert_eq!(repo.head_sha().unwrap(), sha_before_checkpoint);
|
||||
assert_eq!(
|
||||
|
@ -1638,11 +1648,9 @@ mod tests {
|
|||
);
|
||||
|
||||
// Garbage collecting after deleting a checkpoint makes it unreachable.
|
||||
repo.delete_checkpoint(checkpoint.clone(), cx.to_async())
|
||||
.await
|
||||
.unwrap();
|
||||
repo.gc(cx.to_async()).await.unwrap();
|
||||
repo.restore_checkpoint(checkpoint.clone(), cx.to_async())
|
||||
repo.delete_checkpoint(checkpoint.clone()).await.unwrap();
|
||||
repo.gc().await.unwrap();
|
||||
repo.restore_checkpoint(checkpoint.clone())
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
@ -1653,12 +1661,13 @@ mod tests {
|
|||
|
||||
let repo_dir = tempfile::tempdir().unwrap();
|
||||
git2::Repository::init(repo_dir.path()).unwrap();
|
||||
let repo = RealGitRepository::new(&repo_dir.path().join(".git"), None).unwrap();
|
||||
let repo =
|
||||
RealGitRepository::new(&repo_dir.path().join(".git"), None, cx.executor()).unwrap();
|
||||
|
||||
smol::fs::write(repo_dir.path().join("foo"), "foo")
|
||||
.await
|
||||
.unwrap();
|
||||
let checkpoint_sha = repo.checkpoint(cx.to_async()).await.unwrap();
|
||||
let checkpoint_sha = repo.checkpoint().await.unwrap();
|
||||
|
||||
// Ensure the user can't see any branches after creating a checkpoint.
|
||||
assert_eq!(repo.branches().await.unwrap().len(), 1);
|
||||
|
@ -1669,9 +1678,7 @@ mod tests {
|
|||
smol::fs::write(repo_dir.path().join("baz"), "qux")
|
||||
.await
|
||||
.unwrap();
|
||||
repo.restore_checkpoint(checkpoint_sha, cx.to_async())
|
||||
.await
|
||||
.unwrap();
|
||||
repo.restore_checkpoint(checkpoint_sha).await.unwrap();
|
||||
assert_eq!(
|
||||
smol::fs::read_to_string(repo_dir.path().join("foo"))
|
||||
.await
|
||||
|
@ -1696,20 +1703,12 @@ mod tests {
|
|||
let file_path = repo_dir.path().join("file");
|
||||
smol::fs::write(&file_path, "initial").await.unwrap();
|
||||
|
||||
let repo = RealGitRepository::new(&repo_dir.path().join(".git"), None).unwrap();
|
||||
repo.stage_paths(
|
||||
vec![RepoPath::from_str("file")],
|
||||
HashMap::default(),
|
||||
cx.to_async(),
|
||||
)
|
||||
let repo =
|
||||
RealGitRepository::new(&repo_dir.path().join(".git"), None, cx.executor()).unwrap();
|
||||
repo.stage_paths(vec![RepoPath::from_str("file")], HashMap::default())
|
||||
.await
|
||||
.unwrap();
|
||||
repo.commit(
|
||||
"Initial commit".into(),
|
||||
None,
|
||||
checkpoint_author_envs(),
|
||||
cx.to_async(),
|
||||
)
|
||||
repo.commit("Initial commit".into(), None, checkpoint_author_envs())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
@ -1722,7 +1721,7 @@ mod tests {
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let checkpoint = repo.checkpoint(cx.to_async()).await.unwrap();
|
||||
let checkpoint = repo.checkpoint().await.unwrap();
|
||||
|
||||
repo.stage_paths(
|
||||
vec![
|
||||
|
@ -1730,22 +1729,14 @@ mod tests {
|
|||
RepoPath::from_str("new_file2"),
|
||||
],
|
||||
HashMap::default(),
|
||||
cx.to_async(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
repo.commit(
|
||||
"Commit new files".into(),
|
||||
None,
|
||||
checkpoint_author_envs(),
|
||||
cx.to_async(),
|
||||
)
|
||||
repo.commit("Commit new files".into(), None, checkpoint_author_envs())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
repo.restore_checkpoint(checkpoint, cx.to_async())
|
||||
.await
|
||||
.unwrap();
|
||||
repo.restore_checkpoint(checkpoint).await.unwrap();
|
||||
assert_eq!(repo.head_sha().unwrap(), initial_commit_sha);
|
||||
assert_eq!(
|
||||
smol::fs::read_to_string(repo_dir.path().join("new_file1"))
|
||||
|
@ -1760,7 +1751,7 @@ mod tests {
|
|||
"content2"
|
||||
);
|
||||
assert_eq!(
|
||||
repo.status(&[]).unwrap().entries.as_ref(),
|
||||
repo.status(&[]).await.unwrap().entries.as_ref(),
|
||||
&[
|
||||
(RepoPath::from_str("new_file1"), FileStatus::Untracked),
|
||||
(RepoPath::from_str("new_file2"), FileStatus::Untracked)
|
||||
|
@ -1774,26 +1765,27 @@ mod tests {
|
|||
|
||||
let repo_dir = tempfile::tempdir().unwrap();
|
||||
git2::Repository::init(repo_dir.path()).unwrap();
|
||||
let repo = RealGitRepository::new(&repo_dir.path().join(".git"), None).unwrap();
|
||||
let repo =
|
||||
RealGitRepository::new(&repo_dir.path().join(".git"), None, cx.executor()).unwrap();
|
||||
|
||||
smol::fs::write(repo_dir.path().join("file1"), "content1")
|
||||
.await
|
||||
.unwrap();
|
||||
let checkpoint1 = repo.checkpoint(cx.to_async()).await.unwrap();
|
||||
let checkpoint1 = repo.checkpoint().await.unwrap();
|
||||
|
||||
smol::fs::write(repo_dir.path().join("file2"), "content2")
|
||||
.await
|
||||
.unwrap();
|
||||
let checkpoint2 = repo.checkpoint(cx.to_async()).await.unwrap();
|
||||
let checkpoint2 = repo.checkpoint().await.unwrap();
|
||||
|
||||
assert!(!repo
|
||||
.compare_checkpoints(checkpoint1, checkpoint2.clone(), cx.to_async())
|
||||
.compare_checkpoints(checkpoint1, checkpoint2.clone())
|
||||
.await
|
||||
.unwrap());
|
||||
|
||||
let checkpoint3 = repo.checkpoint(cx.to_async()).await.unwrap();
|
||||
let checkpoint3 = repo.checkpoint().await.unwrap();
|
||||
assert!(repo
|
||||
.compare_checkpoints(checkpoint2, checkpoint3, cx.to_async())
|
||||
.compare_checkpoints(checkpoint2, checkpoint3)
|
||||
.await
|
||||
.unwrap());
|
||||
}
|
||||
|
@ -1827,11 +1819,12 @@ mod tests {
|
|||
|
||||
impl RealGitRepository {
|
||||
/// Force a Git garbage collection on the repository.
|
||||
fn gc(&self, cx: AsyncApp) -> BoxFuture<Result<()>> {
|
||||
fn gc(&self) -> BoxFuture<Result<()>> {
|
||||
let working_directory = self.working_directory();
|
||||
let git_binary_path = self.git_binary_path.clone();
|
||||
let executor = cx.background_executor().clone();
|
||||
cx.background_spawn(async move {
|
||||
let executor = self.executor.clone();
|
||||
self.executor
|
||||
.spawn(async move {
|
||||
let git_binary_path = git_binary_path.clone();
|
||||
let working_directory = working_directory?;
|
||||
let git = GitBinary::new(git_binary_path, working_directory, executor);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::repository::RepoPath;
|
||||
use anyhow::{anyhow, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{path::Path, process::Stdio, sync::Arc};
|
||||
use std::{path::Path, str::FromStr, sync::Arc};
|
||||
use util::ResultExt;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
|
@ -443,45 +443,11 @@ pub struct GitStatus {
|
|||
pub entries: Arc<[(RepoPath, FileStatus)]>,
|
||||
}
|
||||
|
||||
impl GitStatus {
|
||||
pub(crate) fn new(
|
||||
git_binary: &Path,
|
||||
working_directory: &Path,
|
||||
path_prefixes: &[RepoPath],
|
||||
) -> Result<Self> {
|
||||
let child = util::command::new_std_command(git_binary)
|
||||
.current_dir(working_directory)
|
||||
.args([
|
||||
"--no-optional-locks",
|
||||
"status",
|
||||
"--porcelain=v1",
|
||||
"--untracked-files=all",
|
||||
"--no-renames",
|
||||
"-z",
|
||||
])
|
||||
.args(path_prefixes.iter().map(|path_prefix| {
|
||||
if path_prefix.0.as_ref() == Path::new("") {
|
||||
Path::new(".")
|
||||
} else {
|
||||
path_prefix
|
||||
}
|
||||
}))
|
||||
.stdin(Stdio::null())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.map_err(|e| anyhow!("Failed to start git status process: {e}"))?;
|
||||
impl FromStr for GitStatus {
|
||||
type Err = anyhow::Error;
|
||||
|
||||
let output = child
|
||||
.wait_with_output()
|
||||
.map_err(|e| anyhow!("Failed to read git status output: {e}"))?;
|
||||
|
||||
if !output.status.success() {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
return Err(anyhow!("git status process failed: {stderr}"));
|
||||
}
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
let mut entries = stdout
|
||||
fn from_str(s: &str) -> Result<Self> {
|
||||
let mut entries = s
|
||||
.split('\0')
|
||||
.filter_map(|entry| {
|
||||
let sep = entry.get(2..3)?;
|
||||
|
|
|
@ -74,6 +74,11 @@ pub(crate) use windows::*;
|
|||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub use test::TestScreenCaptureSource;
|
||||
|
||||
/// Returns a background executor for the current platform.
|
||||
pub fn background_executor() -> BackgroundExecutor {
|
||||
current_platform(true).background_executor()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub(crate) fn current_platform(headless: bool) -> Rc<dyn Platform> {
|
||||
Rc::new(MacPlatform::new(headless))
|
||||
|
|
|
@ -773,11 +773,11 @@ impl GitStore {
|
|||
anyhow::Ok(Some((repo, relative_path, content)))
|
||||
});
|
||||
|
||||
cx.spawn(async move |cx| {
|
||||
cx.spawn(async move |_cx| {
|
||||
let Some((repo, relative_path, content)) = blame_params? else {
|
||||
return Ok(None);
|
||||
};
|
||||
repo.blame(relative_path.clone(), content, cx)
|
||||
repo.blame(relative_path.clone(), content)
|
||||
.await
|
||||
.with_context(|| format!("Failed to blame {:?}", relative_path.0))
|
||||
.map(Some)
|
||||
|
@ -1282,16 +1282,13 @@ impl GitStore {
|
|||
let index_text = if current_index_text.is_some() {
|
||||
local_repo
|
||||
.repo()
|
||||
.load_index_text(relative_path.clone(), cx.clone())
|
||||
.load_index_text(relative_path.clone())
|
||||
.await
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let head_text = if current_head_text.is_some() {
|
||||
local_repo
|
||||
.repo()
|
||||
.load_committed_text(relative_path, cx.clone())
|
||||
.await
|
||||
local_repo.repo().load_committed_text(relative_path).await
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -2832,9 +2829,9 @@ impl Repository {
|
|||
}
|
||||
|
||||
pub fn show(&self, commit: String) -> oneshot::Receiver<Result<CommitDetails>> {
|
||||
self.send_job(|git_repo, cx| async move {
|
||||
self.send_job(|git_repo, _cx| async move {
|
||||
match git_repo {
|
||||
RepositoryState::Local(git_repository) => git_repository.show(commit, cx).await,
|
||||
RepositoryState::Local(git_repository) => git_repository.show(commit).await,
|
||||
RepositoryState::Remote {
|
||||
project_id,
|
||||
client,
|
||||
|
@ -2901,9 +2898,9 @@ impl Repository {
|
|||
let env = env.await;
|
||||
|
||||
this.update(cx, |this, _| {
|
||||
this.send_job(|git_repo, cx| async move {
|
||||
this.send_job(|git_repo, _cx| async move {
|
||||
match git_repo {
|
||||
RepositoryState::Local(repo) => repo.stage_paths(entries, env, cx).await,
|
||||
RepositoryState::Local(repo) => repo.stage_paths(entries, env).await,
|
||||
RepositoryState::Remote {
|
||||
project_id,
|
||||
client,
|
||||
|
@ -2969,9 +2966,9 @@ impl Repository {
|
|||
let env = env.await;
|
||||
|
||||
this.update(cx, |this, _| {
|
||||
this.send_job(|git_repo, cx| async move {
|
||||
this.send_job(|git_repo, _cx| async move {
|
||||
match git_repo {
|
||||
RepositoryState::Local(repo) => repo.unstage_paths(entries, env, cx).await,
|
||||
RepositoryState::Local(repo) => repo.unstage_paths(entries, env).await,
|
||||
RepositoryState::Remote {
|
||||
project_id,
|
||||
client,
|
||||
|
@ -3055,11 +3052,11 @@ impl Repository {
|
|||
cx: &mut App,
|
||||
) -> oneshot::Receiver<Result<()>> {
|
||||
let env = self.worktree_environment(cx);
|
||||
self.send_job(|git_repo, cx| async move {
|
||||
self.send_job(|git_repo, _cx| async move {
|
||||
match git_repo {
|
||||
RepositoryState::Local(repo) => {
|
||||
let env = env.await;
|
||||
repo.commit(message, name_and_email, env, cx).await
|
||||
repo.commit(message, name_and_email, env).await
|
||||
}
|
||||
RepositoryState::Remote {
|
||||
project_id,
|
||||
|
@ -3254,10 +3251,10 @@ impl Repository {
|
|||
|
||||
self.send_keyed_job(
|
||||
Some(GitJobKey::WriteIndex(path.clone())),
|
||||
|git_repo, cx| async {
|
||||
|git_repo, _cx| async {
|
||||
match git_repo {
|
||||
RepositoryState::Local(repo) => {
|
||||
repo.set_index_text(path, content, env.await, cx).await
|
||||
repo.set_index_text(path, content, env.await).await
|
||||
}
|
||||
RepositoryState::Remote {
|
||||
project_id,
|
||||
|
@ -3283,10 +3280,10 @@ impl Repository {
|
|||
&self,
|
||||
branch_name: Option<String>,
|
||||
) -> oneshot::Receiver<Result<Vec<Remote>>> {
|
||||
self.send_job(|repo, cx| async move {
|
||||
self.send_job(|repo, _cx| async move {
|
||||
match repo {
|
||||
RepositoryState::Local(git_repository) => {
|
||||
git_repository.get_remotes(branch_name, cx).await
|
||||
git_repository.get_remotes(branch_name).await
|
||||
}
|
||||
RepositoryState::Remote {
|
||||
project_id,
|
||||
|
@ -3352,9 +3349,9 @@ impl Repository {
|
|||
}
|
||||
|
||||
pub fn diff(&self, diff_type: DiffType, _cx: &App) -> oneshot::Receiver<Result<String>> {
|
||||
self.send_job(|repo, cx| async move {
|
||||
self.send_job(|repo, _cx| async move {
|
||||
match repo {
|
||||
RepositoryState::Local(git_repository) => git_repository.diff(diff_type, cx).await,
|
||||
RepositoryState::Local(git_repository) => git_repository.diff(diff_type).await,
|
||||
RepositoryState::Remote {
|
||||
project_id,
|
||||
client,
|
||||
|
@ -3383,10 +3380,10 @@ impl Repository {
|
|||
}
|
||||
|
||||
pub fn create_branch(&self, branch_name: String) -> oneshot::Receiver<Result<()>> {
|
||||
self.send_job(|repo, cx| async move {
|
||||
self.send_job(|repo, _cx| async move {
|
||||
match repo {
|
||||
RepositoryState::Local(git_repository) => {
|
||||
git_repository.create_branch(branch_name, cx).await
|
||||
git_repository.create_branch(branch_name).await
|
||||
}
|
||||
RepositoryState::Remote {
|
||||
project_id,
|
||||
|
@ -3408,10 +3405,10 @@ impl Repository {
|
|||
}
|
||||
|
||||
pub fn change_branch(&self, branch_name: String) -> oneshot::Receiver<Result<()>> {
|
||||
self.send_job(|repo, cx| async move {
|
||||
self.send_job(|repo, _cx| async move {
|
||||
match repo {
|
||||
RepositoryState::Local(git_repository) => {
|
||||
git_repository.change_branch(branch_name, cx).await
|
||||
git_repository.change_branch(branch_name).await
|
||||
}
|
||||
RepositoryState::Remote {
|
||||
project_id,
|
||||
|
@ -3433,10 +3430,10 @@ impl Repository {
|
|||
}
|
||||
|
||||
pub fn check_for_pushed_commits(&self) -> oneshot::Receiver<Result<Vec<SharedString>>> {
|
||||
self.send_job(|repo, cx| async move {
|
||||
self.send_job(|repo, _cx| async move {
|
||||
match repo {
|
||||
RepositoryState::Local(git_repository) => {
|
||||
git_repository.check_for_pushed_commit(cx).await
|
||||
git_repository.check_for_pushed_commit().await
|
||||
}
|
||||
RepositoryState::Remote {
|
||||
project_id,
|
||||
|
@ -3459,9 +3456,9 @@ impl Repository {
|
|||
}
|
||||
|
||||
pub fn checkpoint(&self) -> oneshot::Receiver<Result<GitRepositoryCheckpoint>> {
|
||||
self.send_job(|repo, cx| async move {
|
||||
self.send_job(|repo, _cx| async move {
|
||||
match repo {
|
||||
RepositoryState::Local(git_repository) => git_repository.checkpoint(cx).await,
|
||||
RepositoryState::Local(git_repository) => git_repository.checkpoint().await,
|
||||
RepositoryState::Remote { .. } => Err(anyhow!("not implemented yet")),
|
||||
}
|
||||
})
|
||||
|
@ -3471,10 +3468,10 @@ impl Repository {
|
|||
&self,
|
||||
checkpoint: GitRepositoryCheckpoint,
|
||||
) -> oneshot::Receiver<Result<()>> {
|
||||
self.send_job(move |repo, cx| async move {
|
||||
self.send_job(move |repo, _cx| async move {
|
||||
match repo {
|
||||
RepositoryState::Local(git_repository) => {
|
||||
git_repository.restore_checkpoint(checkpoint, cx).await
|
||||
git_repository.restore_checkpoint(checkpoint).await
|
||||
}
|
||||
RepositoryState::Remote { .. } => Err(anyhow!("not implemented yet")),
|
||||
}
|
||||
|
@ -3513,10 +3510,10 @@ impl Repository {
|
|||
left: GitRepositoryCheckpoint,
|
||||
right: GitRepositoryCheckpoint,
|
||||
) -> oneshot::Receiver<Result<bool>> {
|
||||
self.send_job(move |repo, cx| async move {
|
||||
self.send_job(move |repo, _cx| async move {
|
||||
match repo {
|
||||
RepositoryState::Local(git_repository) => {
|
||||
git_repository.compare_checkpoints(left, right, cx).await
|
||||
git_repository.compare_checkpoints(left, right).await
|
||||
}
|
||||
RepositoryState::Remote { .. } => Err(anyhow!("not implemented yet")),
|
||||
}
|
||||
|
@ -3527,10 +3524,10 @@ impl Repository {
|
|||
&self,
|
||||
checkpoint: GitRepositoryCheckpoint,
|
||||
) -> oneshot::Receiver<Result<()>> {
|
||||
self.send_job(move |repo, cx| async move {
|
||||
self.send_job(move |repo, _cx| async move {
|
||||
match repo {
|
||||
RepositoryState::Local(git_repository) => {
|
||||
git_repository.delete_checkpoint(checkpoint, cx).await
|
||||
git_repository.delete_checkpoint(checkpoint).await
|
||||
}
|
||||
RepositoryState::Remote { .. } => Err(anyhow!("not implemented yet")),
|
||||
}
|
||||
|
|
|
@ -1476,7 +1476,7 @@ impl Project {
|
|||
) -> Entity<Project> {
|
||||
use clock::FakeSystemClock;
|
||||
|
||||
let fs = Arc::new(RealFs::default());
|
||||
let fs = Arc::new(RealFs::new(None, cx.background_executor().clone()));
|
||||
let languages = LanguageRegistry::test(cx.background_executor().clone());
|
||||
let clock = Arc::new(FakeSystemClock::new());
|
||||
let http_client = http_client::FakeHttpClient::with_404_response();
|
||||
|
|
|
@ -99,7 +99,12 @@ async fn test_symlinks(cx: &mut gpui::TestAppContext) {
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
let project = Project::test(Arc::new(RealFs::default()), [root_link_path.as_ref()], cx).await;
|
||||
let project = Project::test(
|
||||
Arc::new(RealFs::new(None, cx.executor())),
|
||||
[root_link_path.as_ref()],
|
||||
cx,
|
||||
)
|
||||
.await;
|
||||
|
||||
project.update(cx, |project, cx| {
|
||||
let tree = project.worktrees(cx).next().unwrap().read(cx);
|
||||
|
@ -3332,7 +3337,7 @@ async fn test_rescan_and_remote_updates(cx: &mut gpui::TestAppContext) {
|
|||
}
|
||||
}));
|
||||
|
||||
let project = Project::test(Arc::new(RealFs::default()), [dir.path()], cx).await;
|
||||
let project = Project::test(Arc::new(RealFs::new(None, cx.executor())), [dir.path()], cx).await;
|
||||
|
||||
let buffer_for_path = |path: &'static str, cx: &mut gpui::TestAppContext| {
|
||||
let buffer = project.update(cx, |p, cx| p.open_local_buffer(dir.path().join(path), cx));
|
||||
|
|
|
@ -445,7 +445,7 @@ pub fn execute_run(
|
|||
let extension_host_proxy = ExtensionHostProxy::global(cx);
|
||||
|
||||
let project = cx.new(|cx| {
|
||||
let fs = Arc::new(RealFs::new(None));
|
||||
let fs = Arc::new(RealFs::new(None, cx.background_executor().clone()));
|
||||
let node_settings_rx = initialize_settings(session.clone(), fs.clone(), cx);
|
||||
|
||||
let proxy_url = read_proxy_settings(cx);
|
||||
|
|
|
@ -1035,16 +1035,13 @@ impl Worktree {
|
|||
Worktree::Local(this) => {
|
||||
let path = Arc::from(path);
|
||||
let snapshot = this.snapshot();
|
||||
cx.spawn(async move |cx| {
|
||||
cx.spawn(async move |_cx| {
|
||||
if let Some(repo) = snapshot.local_repo_containing_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, cx.clone())
|
||||
.await);
|
||||
return Ok(git_repo.repo_ptr.load_index_text(repo_path).await);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1062,16 +1059,13 @@ impl Worktree {
|
|||
Worktree::Local(this) => {
|
||||
let path = Arc::from(path);
|
||||
let snapshot = this.snapshot();
|
||||
cx.spawn(async move |cx| {
|
||||
cx.spawn(async move |_cx| {
|
||||
if let Some(repo) = snapshot.local_repo_containing_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, cx.clone())
|
||||
.await);
|
||||
return Ok(git_repo.repo_ptr.load_committed_text(repo_path).await);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5027,7 +5021,7 @@ impl BackgroundScanner {
|
|||
}
|
||||
|
||||
for (_work_directory, mut paths) in paths_by_git_repo {
|
||||
if let Ok(status) = paths.repo.status(&paths.repo_paths) {
|
||||
if let Ok(status) = paths.repo.status_blocking(&paths.repo_paths) {
|
||||
let mut changed_path_statuses = Vec::new();
|
||||
let statuses = paths.entry.statuses_by_path.clone();
|
||||
let mut cursor = statuses.cursor::<PathProgress>(&());
|
||||
|
@ -5531,7 +5525,7 @@ async fn do_git_status_update(
|
|||
log::trace!("updating git statuses for repo {repository_name}");
|
||||
let Some(statuses) = local_repository
|
||||
.repo()
|
||||
.status(&[git::WORK_DIRECTORY_REPO_PATH.clone()])
|
||||
.status_blocking(&[git::WORK_DIRECTORY_REPO_PATH.clone()])
|
||||
.log_err()
|
||||
else {
|
||||
return;
|
||||
|
|
|
@ -351,7 +351,7 @@ async fn test_renaming_case_only(cx: &mut TestAppContext) {
|
|||
const OLD_NAME: &str = "aaa.rs";
|
||||
const NEW_NAME: &str = "AAA.rs";
|
||||
|
||||
let fs = Arc::new(RealFs::default());
|
||||
let fs = Arc::new(RealFs::new(None, cx.executor()));
|
||||
let temp_root = TempTree::new(json!({
|
||||
OLD_NAME: "",
|
||||
}));
|
||||
|
@ -876,7 +876,7 @@ async fn test_write_file(cx: &mut TestAppContext) {
|
|||
let worktree = Worktree::local(
|
||||
dir.path(),
|
||||
true,
|
||||
Arc::new(RealFs::default()),
|
||||
Arc::new(RealFs::new(None, cx.executor())),
|
||||
Default::default(),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
|
@ -965,7 +965,7 @@ async fn test_file_scan_inclusions(cx: &mut TestAppContext) {
|
|||
let tree = Worktree::local(
|
||||
dir.path(),
|
||||
true,
|
||||
Arc::new(RealFs::default()),
|
||||
Arc::new(RealFs::new(None, cx.executor())),
|
||||
Default::default(),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
|
@ -1028,7 +1028,7 @@ async fn test_file_scan_exclusions_overrules_inclusions(cx: &mut TestAppContext)
|
|||
let tree = Worktree::local(
|
||||
dir.path(),
|
||||
true,
|
||||
Arc::new(RealFs::default()),
|
||||
Arc::new(RealFs::new(None, cx.executor())),
|
||||
Default::default(),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
|
@ -1085,7 +1085,7 @@ async fn test_file_scan_inclusions_reindexes_on_setting_change(cx: &mut TestAppC
|
|||
let tree = Worktree::local(
|
||||
dir.path(),
|
||||
true,
|
||||
Arc::new(RealFs::default()),
|
||||
Arc::new(RealFs::new(None, cx.executor())),
|
||||
Default::default(),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
|
@ -1166,7 +1166,7 @@ async fn test_file_scan_exclusions(cx: &mut TestAppContext) {
|
|||
let tree = Worktree::local(
|
||||
dir.path(),
|
||||
true,
|
||||
Arc::new(RealFs::default()),
|
||||
Arc::new(RealFs::new(None, cx.executor())),
|
||||
Default::default(),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
|
@ -1271,7 +1271,7 @@ async fn test_fs_events_in_exclusions(cx: &mut TestAppContext) {
|
|||
let tree = Worktree::local(
|
||||
dir.path(),
|
||||
true,
|
||||
Arc::new(RealFs::default()),
|
||||
Arc::new(RealFs::new(None, cx.executor())),
|
||||
Default::default(),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
|
@ -1382,7 +1382,7 @@ async fn test_fs_events_in_dot_git_worktree(cx: &mut TestAppContext) {
|
|||
let tree = Worktree::local(
|
||||
dot_git_worktree_dir.clone(),
|
||||
true,
|
||||
Arc::new(RealFs::default()),
|
||||
Arc::new(RealFs::new(None, cx.executor())),
|
||||
Default::default(),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
|
@ -1512,7 +1512,7 @@ async fn test_create_dir_all_on_create_entry(cx: &mut TestAppContext) {
|
|||
assert!(tree.entry_for_path("a/b/").unwrap().is_dir());
|
||||
});
|
||||
|
||||
let fs_real = Arc::new(RealFs::default());
|
||||
let fs_real = Arc::new(RealFs::new(None, cx.executor()));
|
||||
let temp_root = TempTree::new(json!({
|
||||
"a": {}
|
||||
}));
|
||||
|
@ -2126,7 +2126,7 @@ async fn test_rename_work_directory(cx: &mut TestAppContext) {
|
|||
let tree = Worktree::local(
|
||||
root_path,
|
||||
true,
|
||||
Arc::new(RealFs::default()),
|
||||
Arc::new(RealFs::new(None, cx.executor())),
|
||||
Default::default(),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
|
@ -2233,7 +2233,7 @@ async fn test_file_status(cx: &mut TestAppContext) {
|
|||
let tree = Worktree::local(
|
||||
root.path(),
|
||||
true,
|
||||
Arc::new(RealFs::default()),
|
||||
Arc::new(RealFs::new(None, cx.executor())),
|
||||
Default::default(),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
|
@ -2422,7 +2422,7 @@ async fn test_git_repository_status(cx: &mut TestAppContext) {
|
|||
let tree = Worktree::local(
|
||||
root.path(),
|
||||
true,
|
||||
Arc::new(RealFs::default()),
|
||||
Arc::new(RealFs::new(None, cx.executor())),
|
||||
Default::default(),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
|
@ -2551,7 +2551,7 @@ async fn test_git_status_postprocessing(cx: &mut TestAppContext) {
|
|||
let tree = Worktree::local(
|
||||
root.path(),
|
||||
true,
|
||||
Arc::new(RealFs::default()),
|
||||
Arc::new(RealFs::new(None, cx.executor())),
|
||||
Default::default(),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
|
@ -2619,7 +2619,7 @@ async fn test_repository_subfolder_git_status(cx: &mut TestAppContext) {
|
|||
let tree = Worktree::local(
|
||||
root.path().join(project_root),
|
||||
true,
|
||||
Arc::new(RealFs::default()),
|
||||
Arc::new(RealFs::new(None, cx.executor())),
|
||||
Default::default(),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
|
@ -2685,7 +2685,7 @@ async fn test_conflicted_cherry_pick(cx: &mut TestAppContext) {
|
|||
let tree = Worktree::local(
|
||||
root_path,
|
||||
true,
|
||||
Arc::new(RealFs::default()),
|
||||
Arc::new(RealFs::new(None, cx.executor())),
|
||||
Default::default(),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
|
|
|
@ -264,7 +264,7 @@ fn main() {
|
|||
};
|
||||
log::info!("Using git binary path: {:?}", git_binary_path);
|
||||
|
||||
let fs = Arc::new(RealFs::new(git_binary_path));
|
||||
let fs = Arc::new(RealFs::new(git_binary_path, app.background_executor()));
|
||||
let user_settings_file_rx = watch_config_file(
|
||||
&app.background_executor(),
|
||||
fs.clone(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue