diff --git a/crates/fs/src/fake_git_repo.rs b/crates/fs/src/fake_git_repo.rs index 690c2e7feab9c74fb0dce23c265efba71ce8265b..6513d5a33b6eb96f7a69c5f96530f1d44a71c3ec 100644 --- a/crates/fs/src/fake_git_repo.rs +++ b/crates/fs/src/fake_git_repo.rs @@ -20,7 +20,7 @@ use ignore::gitignore::GitignoreBuilder; use parking_lot::Mutex; use rope::Rope; use smol::{channel::Sender, future::FutureExt as _}; -use std::{path::PathBuf, sync::Arc, sync::atomic::AtomicBool}; +use std::{path::PathBuf, sync::Arc}; use text::LineEnding; use util::{paths::PathStyle, rel_path::RelPath}; @@ -32,7 +32,6 @@ pub struct FakeGitRepository { pub(crate) dot_git_path: PathBuf, pub(crate) repository_dir_path: PathBuf, pub(crate) common_dir_path: PathBuf, - pub(crate) is_trusted: Arc, } #[derive(Debug, Clone)] @@ -882,15 +881,6 @@ impl GitRepository for FakeGitRepository { fn commit_data_reader(&self) -> Result { anyhow::bail!("commit_data_reader not supported for FakeGitRepository") } - - fn set_trusted(&self, trusted: bool) { - self.is_trusted - .store(trusted, std::sync::atomic::Ordering::Release); - } - - fn is_trusted(&self) -> bool { - self.is_trusted.load(std::sync::atomic::Ordering::Acquire) - } } #[cfg(test)] diff --git a/crates/fs/src/fs.rs b/crates/fs/src/fs.rs index 0fde444171042eda859edcac7915c456ab91e265..2db9e48a2e77bdb3e49fce0b16ea9b67ffaacbc0 100644 --- a/crates/fs/src/fs.rs +++ b/crates/fs/src/fs.rs @@ -2776,7 +2776,6 @@ impl Fs for FakeFs { repository_dir_path: repository_dir_path.to_owned(), common_dir_path: common_dir_path.to_owned(), checkpoints: Arc::default(), - is_trusted: Arc::default(), }) as _ }, ) diff --git a/crates/git/clippy.toml b/crates/git/clippy.toml deleted file mode 100644 index fb3926840493fd5981c1861e7cea96bd54b9647f..0000000000000000000000000000000000000000 --- a/crates/git/clippy.toml +++ /dev/null @@ -1,28 +0,0 @@ -allow-private-module-inception = true -avoid-breaking-exported-api = false -ignore-interior-mutability = [ - # Suppresses clippy::mutable_key_type, which is a false positive as the Eq - # and Hash impls do not use fields with interior mutability. - "agent_ui::context::AgentContextKey" -] -disallowed-methods = [ - { path = "std::process::Command::spawn", reason = "Spawning `std::process::Command` can block the current thread for an unknown duration", replacement = "smol::process::Command::spawn" }, - { path = "std::process::Command::output", reason = "Spawning `std::process::Command` can block the current thread for an unknown duration", replacement = "smol::process::Command::output" }, - { path = "std::process::Command::status", reason = "Spawning `std::process::Command` can block the current thread for an unknown duration", replacement = "smol::process::Command::status" }, - { path = "std::process::Command::stdin", reason = "`smol::process::Command::from()` does not preserve stdio configuration", replacement = "smol::process::Command::stdin" }, - { path = "std::process::Command::stdout", reason = "`smol::process::Command::from()` does not preserve stdio configuration", replacement = "smol::process::Command::stdout" }, - { path = "std::process::Command::stderr", reason = "`smol::process::Command::from()` does not preserve stdio configuration", replacement = "smol::process::Command::stderr" }, - { path = "smol::Timer::after", reason = "smol::Timer introduces non-determinism in tests", replacement = "gpui::BackgroundExecutor::timer" }, - { path = "serde_json::from_reader", reason = "Parsing from a buffer is much slower than first reading the buffer into a Vec/String, see https://github.com/serde-rs/json/issues/160#issuecomment-253446892. Use `serde_json::from_slice` instead." }, - { path = "serde_json_lenient::from_reader", reason = "Parsing from a buffer is much slower than first reading the buffer into a Vec/String, see https://github.com/serde-rs/json/issues/160#issuecomment-253446892, Use `serde_json_lenient::from_slice` instead." }, - { path = "cocoa::foundation::NSString::alloc", reason = "NSString must be autoreleased to avoid memory leaks. Use `ns_string()` helper instead." }, - { path = "smol::process::Command::new", reason = "Git commands must go through `GitBinary::build_command` to ensure security flags like `-c core.fsmonitor=false` are always applied.", replacement = "GitBinary::build_command" }, - { path = "util::command::new_command", reason = "Git commands must go through `GitBinary::build_command` to ensure security flags like `-c core.fsmonitor=false` are always applied.", replacement = "GitBinary::build_command" }, - { path = "util::command::Command::new", reason = "Git commands must go through `GitBinary::build_command` to ensure security flags like `-c core.fsmonitor=false` are always applied.", replacement = "GitBinary::build_command" }, -] -disallowed-types = [ - # { path = "std::collections::HashMap", replacement = "collections::HashMap" }, - # { path = "std::collections::HashSet", replacement = "collections::HashSet" }, - # { path = "indexmap::IndexSet", replacement = "collections::IndexSet" }, - # { path = "indexmap::IndexMap", replacement = "collections::IndexMap" }, -] \ No newline at end of file diff --git a/crates/git/src/blame.rs b/crates/git/src/blame.rs index c44aea74051bb7c190a091703d6c60807fc4e27e..9dc184bf2ac253c8bc24f6203f13d6654ac2b64b 100644 --- a/crates/git/src/blame.rs +++ b/crates/git/src/blame.rs @@ -1,11 +1,11 @@ use crate::Oid; use crate::commit::get_messages; -use crate::repository::{GitBinary, RepoPath}; +use crate::repository::RepoPath; use anyhow::{Context as _, Result}; use collections::{HashMap, HashSet}; use futures::AsyncWriteExt; use serde::{Deserialize, Serialize}; -use std::ops::Range; +use std::{ops::Range, path::Path}; use text::{LineEnding, Rope}; use time::OffsetDateTime; use time::UtcOffset; @@ -21,13 +21,15 @@ pub struct Blame { } impl Blame { - pub(crate) async fn for_path( - git: &GitBinary, + pub async fn for_path( + git_binary: &Path, + working_directory: &Path, path: &RepoPath, content: &Rope, line_ending: LineEnding, ) -> Result { - let output = run_git_blame(git, path, content, line_ending).await?; + let output = + run_git_blame(git_binary, working_directory, path, content, line_ending).await?; let mut entries = parse_git_blame(&output)?; entries.sort_unstable_by(|a, b| a.range.start.cmp(&b.range.start)); @@ -38,7 +40,7 @@ impl Blame { } let shas = unique_shas.into_iter().collect::>(); - let messages = get_messages(git, &shas) + let messages = get_messages(working_directory, &shas) .await .context("failed to get commit messages")?; @@ -50,7 +52,8 @@ const GIT_BLAME_NO_COMMIT_ERROR: &str = "fatal: no such ref: HEAD"; const GIT_BLAME_NO_PATH: &str = "fatal: no such path"; async fn run_git_blame( - git: &GitBinary, + git_binary: &Path, + working_directory: &Path, path: &RepoPath, contents: &Rope, line_ending: LineEnding, @@ -58,7 +61,12 @@ async fn run_git_blame( let mut child = { let span = ztracing::debug_span!("spawning git-blame command", path = path.as_unix_str()); let _enter = span.enter(); - git.build_command(["blame", "--incremental", "--contents", "-"]) + util::command::new_command(git_binary) + .current_dir(working_directory) + .arg("blame") + .arg("--incremental") + .arg("--contents") + .arg("-") .arg(path.as_unix_str()) .stdin(Stdio::piped()) .stdout(Stdio::piped()) diff --git a/crates/git/src/commit.rs b/crates/git/src/commit.rs index 46e050ce155fc049a670fdfa26101eb729b34352..3f3526afc4ba8fa146592684a6d3acfc44ce7e73 100644 --- a/crates/git/src/commit.rs +++ b/crates/git/src/commit.rs @@ -1,11 +1,11 @@ use crate::{ BuildCommitPermalinkParams, GitHostingProviderRegistry, GitRemote, Oid, parse_git_remote_url, - repository::GitBinary, status::StatusCode, + status::StatusCode, }; use anyhow::{Context as _, Result}; use collections::HashMap; use gpui::SharedString; -use std::sync::Arc; +use std::{path::Path, sync::Arc}; #[derive(Clone, Debug, Default)] pub struct ParsedCommitMessage { @@ -48,7 +48,7 @@ impl ParsedCommitMessage { } } -pub(crate) async fn get_messages(git: &GitBinary, shas: &[Oid]) -> Result> { +pub async fn get_messages(working_directory: &Path, shas: &[Oid]) -> Result> { if shas.is_empty() { return Ok(HashMap::default()); } @@ -63,12 +63,12 @@ pub(crate) async fn get_messages(git: &GitBinary, shas: &[Oid]) -> Result Result>()) } -async fn get_messages_impl(git: &GitBinary, shas: &[Oid]) -> Result> { +async fn get_messages_impl(working_directory: &Path, shas: &[Oid]) -> Result> { const MARKER: &str = ""; - let output = git - .build_command(["show"]) + let output = util::command::new_command("git") + .current_dir(working_directory) + .arg("show") .arg("-s") .arg(format!("--format=%B{}", MARKER)) .args(shas.iter().map(ToString::to_string)) diff --git a/crates/git/src/repository.rs b/crates/git/src/repository.rs index 7586e5c80a0b8b5c0909488fef02d23d49b51bdb..ab445a1cd830a726491fab1fc6209686e80960b1 100644 --- a/crates/git/src/repository.rs +++ b/crates/git/src/repository.rs @@ -21,7 +21,6 @@ use text::LineEnding; use std::collections::HashSet; use std::ffi::{OsStr, OsString}; -use std::sync::atomic::AtomicBool; use std::process::ExitStatus; use std::str::FromStr; @@ -934,9 +933,6 @@ pub trait GitRepository: Send + Sync { ) -> BoxFuture<'_, Result<()>>; fn commit_data_reader(&self) -> Result; - - fn set_trusted(&self, trusted: bool); - fn is_trusted(&self) -> bool; } pub enum DiffType { @@ -963,7 +959,6 @@ pub struct RealGitRepository { pub any_git_binary_path: PathBuf, any_git_binary_help_output: Arc>>, executor: BackgroundExecutor, - is_trusted: Arc, } impl RealGitRepository { @@ -982,7 +977,6 @@ impl RealGitRepository { any_git_binary_path, executor, any_git_binary_help_output: Arc::new(Mutex::new(None)), - is_trusted: Arc::new(AtomicBool::new(false)), }) } @@ -994,24 +988,20 @@ impl RealGitRepository { .map(Path::to_path_buf) } - fn git_binary(&self) -> Result { - Ok(GitBinary::new( - self.any_git_binary_path.clone(), - self.working_directory() - .with_context(|| "Can't run git commands without a working directory")?, - self.executor.clone(), - self.is_trusted(), - )) - } - async fn any_git_binary_help_output(&self) -> SharedString { if let Some(output) = self.any_git_binary_help_output.lock().clone() { return output; } - let git_binary = self.git_binary(); + let git_binary_path = self.any_git_binary_path.clone(); + let executor = self.executor.clone(); + let working_directory = self.working_directory(); let output: SharedString = self .executor - .spawn(async move { git_binary?.run(["help", "-a"]).await }) + .spawn(async move { + GitBinary::new(git_binary_path, working_directory?, executor) + .run(["help", "-a"]) + .await + }) .await .unwrap_or_default() .into(); @@ -1054,7 +1044,6 @@ pub async fn get_git_committer(cx: &AsyncApp) -> GitCommitter { git_binary_path.unwrap_or(PathBuf::from("git")), paths::home_dir().clone(), cx.background_executor().clone(), - true, ); cx.background_spawn(async move { @@ -1086,12 +1075,14 @@ impl GitRepository for RealGitRepository { } fn show(&self, commit: String) -> BoxFuture<'_, Result> { - let git_binary = self.git_binary(); + let git_binary_path = self.any_git_binary_path.clone(); + let working_directory = self.working_directory(); self.executor .spawn(async move { - let git = git_binary?; - let output = git - .build_command([ + let working_directory = working_directory?; + let output = new_command(git_binary_path) + .current_dir(&working_directory) + .args([ "--no-optional-locks", "show", "--no-patch", @@ -1122,14 +1113,15 @@ impl GitRepository for RealGitRepository { } fn load_commit(&self, commit: String, cx: AsyncApp) -> BoxFuture<'_, Result> { - if self.repository.lock().workdir().is_none() { + let Some(working_directory) = self.repository.lock().workdir().map(ToOwned::to_owned) + else { return future::ready(Err(anyhow!("no working directory"))).boxed(); - } - let git_binary = self.git_binary(); + }; + let git_binary_path = self.any_git_binary_path.clone(); cx.background_spawn(async move { - let git = git_binary?; - let show_output = git - .build_command([ + let show_output = util::command::new_command(&git_binary_path) + .current_dir(&working_directory) + .args([ "--no-optional-locks", "show", "--format=", @@ -1150,8 +1142,9 @@ impl GitRepository for RealGitRepository { let changes = parse_git_diff_name_status(&show_stdout); let parent_sha = format!("{}^", commit); - let mut cat_file_process = git - .build_command(["--no-optional-locks", "cat-file", "--batch=%(objectsize)"]) + let mut cat_file_process = util::command::new_command(&git_binary_path) + .current_dir(&working_directory) + .args(["--no-optional-locks", "cat-file", "--batch=%(objectsize)"]) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) @@ -1258,17 +1251,18 @@ impl GitRepository for RealGitRepository { mode: ResetMode, env: Arc>, ) -> BoxFuture<'_, Result<()>> { - let git_binary = self.git_binary(); async move { + let working_directory = self.working_directory(); + let mode_flag = match mode { ResetMode::Mixed => "--mixed", ResetMode::Soft => "--soft", }; - let git = git_binary?; - let output = git - .build_command(["reset", mode_flag, &commit]) + let output = new_command(&self.any_git_binary_path) .envs(env.iter()) + .current_dir(&working_directory?) + .args(["reset", mode_flag, &commit]) .output() .await?; anyhow::ensure!( @@ -1287,16 +1281,17 @@ impl GitRepository for RealGitRepository { paths: Vec, env: Arc>, ) -> BoxFuture<'_, Result<()>> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); async move { if paths.is_empty() { return Ok(()); } - let git = git_binary?; - let output = git - .build_command(["checkout", &commit, "--"]) + let output = new_command(&git_binary_path) + .current_dir(&working_directory?) .envs(env.iter()) + .args(["checkout", &commit, "--"]) .args(paths.iter().map(|path| path.as_unix_str())) .output() .await?; @@ -1383,16 +1378,18 @@ impl GitRepository for RealGitRepository { env: Arc>, is_executable: bool, ) -> BoxFuture<'_, anyhow::Result<()>> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); self.executor .spawn(async move { - let git = git_binary?; + let working_directory = working_directory?; let mode = if is_executable { "100755" } else { "100644" }; if let Some(content) = content { - let mut child = git - .build_command(["hash-object", "-w", "--stdin"]) + let mut child = new_command(&git_binary_path) + .current_dir(&working_directory) .envs(env.iter()) + .args(["hash-object", "-w", "--stdin"]) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .spawn()?; @@ -1405,9 +1402,10 @@ impl GitRepository for RealGitRepository { log::debug!("indexing SHA: {sha}, path {path:?}"); - let output = git - .build_command(["update-index", "--add", "--cacheinfo", mode, sha]) + let output = new_command(&git_binary_path) + .current_dir(&working_directory) .envs(env.iter()) + .args(["update-index", "--add", "--cacheinfo", mode, sha]) .arg(path.as_unix_str()) .output() .await?; @@ -1419,9 +1417,10 @@ impl GitRepository for RealGitRepository { ); } else { log::debug!("removing path {path:?} from the index"); - let output = git - .build_command(["update-index", "--force-remove"]) + let output = new_command(&git_binary_path) + .current_dir(&working_directory) .envs(env.iter()) + .args(["update-index", "--force-remove"]) .arg(path.as_unix_str()) .output() .await?; @@ -1450,12 +1449,14 @@ impl GitRepository for RealGitRepository { } fn revparse_batch(&self, revs: Vec) -> BoxFuture<'_, Result>>> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); self.executor .spawn(async move { - let git = git_binary?; - let mut process = git - .build_command([ + let working_directory = working_directory?; + let mut process = new_command(&git_binary_path) + .current_dir(&working_directory) + .args([ "--no-optional-locks", "cat-file", "--batch-check=%(objectname)", @@ -1508,14 +1509,19 @@ impl GitRepository for RealGitRepository { } fn status(&self, path_prefixes: &[RepoPath]) -> Task> { - let git = match self.git_binary() { - Ok(git) => git, + let git_binary_path = self.any_git_binary_path.clone(); + let working_directory = match self.working_directory() { + Ok(working_directory) => working_directory, Err(e) => return Task::ready(Err(e)), }; let args = git_status_args(path_prefixes); log::debug!("Checking for git status in {path_prefixes:?}"); self.executor.spawn(async move { - let output = git.build_command(args).output().await?; + let output = new_command(&git_binary_path) + .current_dir(working_directory) + .args(args) + .output() + .await?; if output.status.success() { let stdout = String::from_utf8_lossy(&output.stdout); stdout.parse() @@ -1527,8 +1533,9 @@ impl GitRepository for RealGitRepository { } fn diff_tree(&self, request: DiffTreeType) -> BoxFuture<'_, Result> { - let git = match self.git_binary() { - Ok(git) => git, + let git_binary_path = self.any_git_binary_path.clone(); + let working_directory = match self.working_directory() { + Ok(working_directory) => working_directory, Err(e) => return Task::ready(Err(e)).boxed(), }; @@ -1553,7 +1560,11 @@ impl GitRepository for RealGitRepository { self.executor .spawn(async move { - let output = git.build_command(args).output().await?; + let output = new_command(&git_binary_path) + .current_dir(working_directory) + .args(args) + .output() + .await?; if output.status.success() { let stdout = String::from_utf8_lossy(&output.stdout); stdout.parse() @@ -1566,12 +1577,13 @@ impl GitRepository for RealGitRepository { } fn stash_entries(&self) -> BoxFuture<'_, Result> { - let git_binary = self.git_binary(); + let git_binary_path = self.any_git_binary_path.clone(); + let working_directory = self.working_directory(); self.executor .spawn(async move { - let git = git_binary?; - let output = git - .build_command(&["stash", "list", "--pretty=format:%gd%x00%H%x00%ct%x00%s"]) + let output = new_command(&git_binary_path) + .current_dir(working_directory?) + .args(&["stash", "list", "--pretty=format:%gd%x00%H%x00%ct%x00%s"]) .output() .await?; if output.status.success() { @@ -1586,7 +1598,8 @@ impl GitRepository for RealGitRepository { } fn branches(&self) -> BoxFuture<'_, Result>> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); self.executor .spawn(async move { let fields = [ @@ -1608,8 +1621,12 @@ impl GitRepository for RealGitRepository { "--format", &fields, ]; - let git = git_binary?; - let output = git.build_command(args).output().await?; + let working_directory = working_directory?; + let output = new_command(&git_binary_path) + .current_dir(&working_directory) + .args(args) + .output() + .await?; anyhow::ensure!( output.status.success(), @@ -1623,7 +1640,11 @@ impl GitRepository for RealGitRepository { if branches.is_empty() { let args = vec!["symbolic-ref", "--quiet", "HEAD"]; - let output = git.build_command(args).output().await?; + let output = new_command(&git_binary_path) + .current_dir(&working_directory) + .args(args) + .output() + .await?; // git symbolic-ref returns a non-0 exit code if HEAD points // to something other than a branch @@ -1645,12 +1666,13 @@ impl GitRepository for RealGitRepository { } fn worktrees(&self) -> BoxFuture<'_, Result>> { - let git_binary = self.git_binary(); + let git_binary_path = self.any_git_binary_path.clone(); + let working_directory = self.working_directory(); self.executor .spawn(async move { - let git = git_binary?; - let output = git - .build_command(&["--no-optional-locks", "worktree", "list", "--porcelain"]) + let output = new_command(&git_binary_path) + .current_dir(working_directory?) + .args(&["--no-optional-locks", "worktree", "list", "--porcelain"]) .output() .await?; if output.status.success() { @@ -1670,7 +1692,8 @@ impl GitRepository for RealGitRepository { directory: PathBuf, from_commit: Option, ) -> BoxFuture<'_, Result<()>> { - let git_binary = self.git_binary(); + let git_binary_path = self.any_git_binary_path.clone(); + let working_directory = self.working_directory(); let final_path = directory.join(&name); let mut args = vec![ OsString::from("--no-optional-locks"), @@ -1690,8 +1713,11 @@ impl GitRepository for RealGitRepository { self.executor .spawn(async move { std::fs::create_dir_all(final_path.parent().unwrap_or(&final_path))?; - let git = git_binary?; - let output = git.build_command(args).output().await?; + let output = new_command(&git_binary_path) + .current_dir(working_directory?) + .args(args) + .output() + .await?; if output.status.success() { Ok(()) } else { @@ -1703,7 +1729,9 @@ impl GitRepository for RealGitRepository { } fn remove_worktree(&self, path: PathBuf, force: bool) -> BoxFuture<'_, Result<()>> { - let git_binary = self.git_binary(); + let git_binary_path = self.any_git_binary_path.clone(); + let working_directory = self.working_directory(); + let executor = self.executor.clone(); self.executor .spawn(async move { @@ -1717,14 +1745,18 @@ impl GitRepository for RealGitRepository { } args.push("--".into()); args.push(path.as_os_str().into()); - git_binary?.run(args).await?; + GitBinary::new(git_binary_path, working_directory?, executor) + .run(args) + .await?; anyhow::Ok(()) }) .boxed() } fn rename_worktree(&self, old_path: PathBuf, new_path: PathBuf) -> BoxFuture<'_, Result<()>> { - let git_binary = self.git_binary(); + let git_binary_path = self.any_git_binary_path.clone(); + let working_directory = self.working_directory(); + let executor = self.executor.clone(); self.executor .spawn(async move { @@ -1736,7 +1768,9 @@ impl GitRepository for RealGitRepository { old_path.as_os_str().into(), new_path.as_os_str().into(), ]; - git_binary?.run(args).await?; + GitBinary::new(git_binary_path, working_directory?, executor) + .run(args) + .await?; anyhow::Ok(()) }) .boxed() @@ -1744,7 +1778,9 @@ impl GitRepository for RealGitRepository { fn change_branch(&self, name: String) -> BoxFuture<'_, Result<()>> { let repo = self.repository.clone(); - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); + let executor = self.executor.clone(); let branch = self.executor.spawn(async move { let repo = repo.lock(); let branch = if let Ok(branch) = repo.find_branch(&name, BranchType::Local) { @@ -1779,7 +1815,9 @@ impl GitRepository for RealGitRepository { self.executor .spawn(async move { let branch = branch.await?; - git_binary?.run(&["checkout", &branch]).await?; + GitBinary::new(git_binary_path, working_directory?, executor) + .run(&["checkout", &branch]) + .await?; anyhow::Ok(()) }) .boxed() @@ -1790,7 +1828,9 @@ impl GitRepository for RealGitRepository { name: String, base_branch: Option, ) -> BoxFuture<'_, Result<()>> { - let git_binary = self.git_binary(); + let git_binary_path = self.any_git_binary_path.clone(); + let working_directory = self.working_directory(); + let executor = self.executor.clone(); self.executor .spawn(async move { @@ -1801,18 +1841,22 @@ impl GitRepository for RealGitRepository { args.push(&base_branch_str); } - git_binary?.run(&args).await?; + GitBinary::new(git_binary_path, working_directory?, executor) + .run(&args) + .await?; anyhow::Ok(()) }) .boxed() } fn rename_branch(&self, branch: String, new_name: String) -> BoxFuture<'_, Result<()>> { - let git_binary = self.git_binary(); + let git_binary_path = self.any_git_binary_path.clone(); + let working_directory = self.working_directory(); + let executor = self.executor.clone(); self.executor .spawn(async move { - git_binary? + GitBinary::new(git_binary_path, working_directory?, executor) .run(&["branch", "-m", &branch, &new_name]) .await?; anyhow::Ok(()) @@ -1821,11 +1865,15 @@ impl GitRepository for RealGitRepository { } fn delete_branch(&self, name: String) -> BoxFuture<'_, Result<()>> { - let git_binary = self.git_binary(); + let git_binary_path = self.any_git_binary_path.clone(); + let working_directory = self.working_directory(); + let executor = self.executor.clone(); self.executor .spawn(async move { - git_binary?.run(&["branch", "-d", &name]).await?; + GitBinary::new(git_binary_path, working_directory?, executor) + .run(&["branch", "-d", &name]) + .await?; anyhow::Ok(()) }) .boxed() @@ -1837,11 +1885,20 @@ impl GitRepository for RealGitRepository { content: Rope, line_ending: LineEnding, ) -> BoxFuture<'_, Result> { - let git = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); + let executor = self.executor.clone(); - self.executor + executor .spawn(async move { - crate::blame::Blame::for_path(&git?, &path, &content, line_ending).await + crate::blame::Blame::for_path( + &git_binary_path, + &working_directory?, + &path, + &content, + line_ending, + ) + .await }) .boxed() } @@ -1856,10 +1913,11 @@ impl GitRepository for RealGitRepository { skip: usize, limit: Option, ) -> BoxFuture<'_, Result> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); self.executor .spawn(async move { - let git = git_binary?; + let working_directory = working_directory?; // Use a unique delimiter with a hardcoded UUID to separate commits // This essentially eliminates any chance of encountering the delimiter in actual commit data let commit_delimiter = @@ -1887,8 +1945,9 @@ impl GitRepository for RealGitRepository { args.push("--"); - let output = git - .build_command(&args) + let output = new_command(&git_binary_path) + .current_dir(&working_directory) + .args(&args) .arg(path.as_unix_str()) .output() .await?; @@ -1933,17 +1992,30 @@ impl GitRepository for RealGitRepository { } fn diff(&self, diff: DiffType) -> BoxFuture<'_, Result> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); self.executor .spawn(async move { - let git = git_binary?; + let working_directory = working_directory?; let output = match diff { DiffType::HeadToIndex => { - git.build_command(["diff", "--staged"]).output().await? + new_command(&git_binary_path) + .current_dir(&working_directory) + .args(["diff", "--staged"]) + .output() + .await? + } + DiffType::HeadToWorktree => { + new_command(&git_binary_path) + .current_dir(&working_directory) + .args(["diff"]) + .output() + .await? } - DiffType::HeadToWorktree => git.build_command(["diff"]).output().await?, DiffType::MergeBase { base_ref } => { - git.build_command(["diff", "--merge-base", base_ref.as_ref()]) + new_command(&git_binary_path) + .current_dir(&working_directory) + .args(["diff", "--merge-base", base_ref.as_ref()]) .output() .await? } @@ -1964,14 +2036,15 @@ impl GitRepository for RealGitRepository { paths: Vec, env: Arc>, ) -> BoxFuture<'_, Result<()>> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); self.executor .spawn(async move { if !paths.is_empty() { - let git = git_binary?; - let output = git - .build_command(["update-index", "--add", "--remove", "--"]) + let output = new_command(&git_binary_path) + .current_dir(&working_directory?) .envs(env.iter()) + .args(["update-index", "--add", "--remove", "--"]) .args(paths.iter().map(|p| p.as_unix_str())) .output() .await?; @@ -1991,15 +2064,16 @@ impl GitRepository for RealGitRepository { paths: Vec, env: Arc>, ) -> BoxFuture<'_, Result<()>> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); self.executor .spawn(async move { if !paths.is_empty() { - let git = git_binary?; - let output = git - .build_command(["reset", "--quiet", "--"]) + let output = new_command(&git_binary_path) + .current_dir(&working_directory?) .envs(env.iter()) + .args(["reset", "--quiet", "--"]) .args(paths.iter().map(|p| p.as_std_path())) .output() .await?; @@ -2020,16 +2094,19 @@ impl GitRepository for RealGitRepository { paths: Vec, env: Arc>, ) -> BoxFuture<'_, Result<()>> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); self.executor .spawn(async move { - let git = git_binary?; - let output = git - .build_command(["stash", "push", "--quiet", "--include-untracked"]) + let mut cmd = new_command(&git_binary_path); + cmd.current_dir(&working_directory?) .envs(env.iter()) - .args(paths.iter().map(|p| p.as_unix_str())) - .output() - .await?; + .args(["stash", "push", "--quiet"]) + .arg("--include-untracked"); + + cmd.args(paths.iter().map(|p| p.as_unix_str())); + + let output = cmd.output().await?; anyhow::ensure!( output.status.success(), @@ -2046,15 +2123,20 @@ impl GitRepository for RealGitRepository { index: Option, env: Arc>, ) -> BoxFuture<'_, Result<()>> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); self.executor .spawn(async move { - let git = git_binary?; + let mut cmd = new_command(git_binary_path); let mut args = vec!["stash".to_string(), "pop".to_string()]; if let Some(index) = index { args.push(format!("stash@{{{}}}", index)); } - let output = git.build_command(&args).envs(env.iter()).output().await?; + cmd.current_dir(&working_directory?) + .envs(env.iter()) + .args(args); + + let output = cmd.output().await?; anyhow::ensure!( output.status.success(), @@ -2071,15 +2153,20 @@ impl GitRepository for RealGitRepository { index: Option, env: Arc>, ) -> BoxFuture<'_, Result<()>> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); self.executor .spawn(async move { - let git = git_binary?; + let mut cmd = new_command(git_binary_path); let mut args = vec!["stash".to_string(), "apply".to_string()]; if let Some(index) = index { args.push(format!("stash@{{{}}}", index)); } - let output = git.build_command(&args).envs(env.iter()).output().await?; + cmd.current_dir(&working_directory?) + .envs(env.iter()) + .args(args); + + let output = cmd.output().await?; anyhow::ensure!( output.status.success(), @@ -2096,15 +2183,20 @@ impl GitRepository for RealGitRepository { index: Option, env: Arc>, ) -> BoxFuture<'_, Result<()>> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); self.executor .spawn(async move { - let git = git_binary?; + let mut cmd = new_command(git_binary_path); let mut args = vec!["stash".to_string(), "drop".to_string()]; if let Some(index) = index { args.push(format!("stash@{{{}}}", index)); } - let output = git.build_command(&args).envs(env.iter()).output().await?; + cmd.current_dir(&working_directory?) + .envs(env.iter()) + .args(args); + + let output = cmd.output().await?; anyhow::ensure!( output.status.success(), @@ -2124,14 +2216,16 @@ impl GitRepository for RealGitRepository { ask_pass: AskPassDelegate, env: Arc>, ) -> BoxFuture<'_, Result<()>> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); let executor = self.executor.clone(); // Note: Do not spawn this command on the background thread, it might pop open the credential helper // which we want to block on. async move { - let git = git_binary?; - let mut cmd = git.build_command(["commit", "--quiet", "-m"]); - cmd.envs(env.iter()) + let mut cmd = new_command(git_binary_path); + cmd.current_dir(&working_directory?) + .envs(env.iter()) + .args(["commit", "--quiet", "-m"]) .arg(&message.to_string()) .arg("--cleanup=strip") .arg("--no-verify") @@ -2170,21 +2264,16 @@ impl GitRepository for RealGitRepository { let working_directory = self.working_directory(); let executor = cx.background_executor().clone(); let git_binary_path = self.system_git_binary_path.clone(); - let is_trusted = self.is_trusted(); // Note: Do not spawn this command on the background thread, it might pop open the credential helper // which we want to block on. async move { let git_binary_path = git_binary_path.context("git not found on $PATH, can't push")?; let working_directory = working_directory?; - let git = GitBinary::new( - git_binary_path, - working_directory, - executor.clone(), - is_trusted, - ); - let mut command = git.build_command(["push"]); + let mut command = new_command(git_binary_path); command .envs(env.iter()) + .current_dir(&working_directory) + .args(["push"]) .args(options.map(|option| match option { PushOptions::SetUpstream => "--set-upstream", PushOptions::Force => "--force-with-lease", @@ -2212,20 +2301,15 @@ impl GitRepository for RealGitRepository { let working_directory = self.working_directory(); let executor = cx.background_executor().clone(); let git_binary_path = self.system_git_binary_path.clone(); - let is_trusted = self.is_trusted(); // Note: Do not spawn this command on the background thread, it might pop open the credential helper // which we want to block on. async move { let git_binary_path = git_binary_path.context("git not found on $PATH, can't pull")?; - let working_directory = working_directory?; - let git = GitBinary::new( - git_binary_path, - working_directory, - executor.clone(), - is_trusted, - ); - let mut command = git.build_command(["pull"]); - command.envs(env.iter()); + let mut command = new_command(git_binary_path); + command + .envs(env.iter()) + .current_dir(&working_directory?) + .arg("pull"); if rebase { command.arg("--rebase"); @@ -2253,21 +2337,15 @@ impl GitRepository for RealGitRepository { let remote_name = format!("{}", fetch_options); let git_binary_path = self.system_git_binary_path.clone(); let executor = cx.background_executor().clone(); - let is_trusted = self.is_trusted(); // Note: Do not spawn this command on the background thread, it might pop open the credential helper // which we want to block on. async move { let git_binary_path = git_binary_path.context("git not found on $PATH, can't fetch")?; - let working_directory = working_directory?; - let git = GitBinary::new( - git_binary_path, - working_directory, - executor.clone(), - is_trusted, - ); - let mut command = git.build_command(["fetch", &remote_name]); + let mut command = new_command(git_binary_path); command .envs(env.iter()) + .current_dir(&working_directory?) + .args(["fetch", &remote_name]) .stdout(Stdio::piped()) .stderr(Stdio::piped()); @@ -2277,12 +2355,14 @@ impl GitRepository for RealGitRepository { } fn get_push_remote(&self, branch: String) -> BoxFuture<'_, Result>> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); self.executor .spawn(async move { - let git = git_binary?; - let output = git - .build_command(["rev-parse", "--abbrev-ref"]) + let working_directory = working_directory?; + let output = new_command(&git_binary_path) + .current_dir(&working_directory) + .args(["rev-parse", "--abbrev-ref"]) .arg(format!("{branch}@{{push}}")) .output() .await?; @@ -2302,12 +2382,14 @@ impl GitRepository for RealGitRepository { } fn get_branch_remote(&self, branch: String) -> BoxFuture<'_, Result>> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); self.executor .spawn(async move { - let git = git_binary?; - let output = git - .build_command(["config", "--get"]) + let working_directory = working_directory?; + let output = new_command(&git_binary_path) + .current_dir(&working_directory) + .args(["config", "--get"]) .arg(format!("branch.{branch}.remote")) .output() .await?; @@ -2324,11 +2406,16 @@ impl GitRepository for RealGitRepository { } fn get_all_remotes(&self) -> BoxFuture<'_, Result>> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); self.executor .spawn(async move { - let git = git_binary?; - let output = git.build_command(["remote", "-v"]).output().await?; + let working_directory = working_directory?; + let output = new_command(&git_binary_path) + .current_dir(&working_directory) + .args(["remote", "-v"]) + .output() + .await?; anyhow::ensure!( output.status.success(), @@ -2377,12 +2464,17 @@ impl GitRepository for RealGitRepository { } fn check_for_pushed_commit(&self) -> BoxFuture<'_, Result>> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); self.executor .spawn(async move { - let git = git_binary?; + let working_directory = working_directory?; let git_cmd = async |args: &[&str]| -> Result { - let output = git.build_command(args).output().await?; + let output = new_command(&git_binary_path) + .current_dir(&working_directory) + .args(args) + .output() + .await?; anyhow::ensure!( output.status.success(), String::from_utf8_lossy(&output.stderr).to_string() @@ -2431,10 +2523,14 @@ impl GitRepository for RealGitRepository { } fn checkpoint(&self) -> BoxFuture<'static, Result> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); + let executor = self.executor.clone(); self.executor .spawn(async move { - let mut git = git_binary?.envs(checkpoint_author_envs()); + let working_directory = working_directory?; + let mut git = GitBinary::new(git_binary_path, working_directory.clone(), executor) + .envs(checkpoint_author_envs()); git.with_temp_index(async |git| { let head_sha = git.run(&["rev-parse", "HEAD"]).await.ok(); let mut excludes = exclude_files(git).await?; @@ -2460,10 +2556,15 @@ impl GitRepository for RealGitRepository { } fn restore_checkpoint(&self, checkpoint: GitRepositoryCheckpoint) -> BoxFuture<'_, Result<()>> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); + + let executor = self.executor.clone(); self.executor .spawn(async move { - let git = git_binary?; + let working_directory = working_directory?; + + let git = GitBinary::new(git_binary_path, working_directory, executor); git.run(&[ "restore", "--source", @@ -2494,10 +2595,14 @@ impl GitRepository for RealGitRepository { left: GitRepositoryCheckpoint, right: GitRepositoryCheckpoint, ) -> BoxFuture<'_, Result> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); + + let executor = self.executor.clone(); self.executor .spawn(async move { - let git = git_binary?; + let working_directory = working_directory?; + let git = GitBinary::new(git_binary_path, working_directory, executor); let result = git .run(&[ "diff-tree", @@ -2528,10 +2633,14 @@ impl GitRepository for RealGitRepository { base_checkpoint: GitRepositoryCheckpoint, target_checkpoint: GitRepositoryCheckpoint, ) -> BoxFuture<'_, Result> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); + + let executor = self.executor.clone(); self.executor .spawn(async move { - let git = git_binary?; + let working_directory = working_directory?; + let git = GitBinary::new(git_binary_path, working_directory, executor); git.run(&[ "diff", "--find-renames", @@ -2548,10 +2657,14 @@ impl GitRepository for RealGitRepository { &self, include_remote_name: bool, ) -> BoxFuture<'_, Result>> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); + let git_binary_path = self.any_git_binary_path.clone(); + + let executor = self.executor.clone(); self.executor .spawn(async move { - let git = git_binary?; + let working_directory = working_directory?; + let git = GitBinary::new(git_binary_path, working_directory, executor); let strip_prefix = if include_remote_name { "refs/remotes/" @@ -2601,19 +2714,15 @@ impl GitRepository for RealGitRepository { hook: RunHook, env: Arc>, ) -> BoxFuture<'_, Result<()>> { - let git_binary = self.git_binary(); + let working_directory = self.working_directory(); let repository = self.repository.clone(); + let git_binary_path = self.any_git_binary_path.clone(); + let executor = self.executor.clone(); let help_output = self.any_git_binary_help_output(); // Note: Do not spawn these commands on the background thread, as this causes some git hooks to hang. async move { - let git = git_binary?; - - if !git.is_trusted { - bail!("Can't run git commit hooks in restrictive workspace"); - } - - let working_directory = git.working_directory.clone(); + let working_directory = working_directory?; if !help_output .await .lines() @@ -2621,7 +2730,6 @@ impl GitRepository for RealGitRepository { { let hook_abs_path = repository.lock().path().join("hooks").join(hook.as_str()); if hook_abs_path.is_file() { - #[allow(clippy::disallowed_methods)] let output = new_command(&hook_abs_path) .envs(env.iter()) .current_dir(&working_directory) @@ -2641,7 +2749,8 @@ impl GitRepository for RealGitRepository { return Ok(()); } - let git = git.envs(HashMap::clone(&env)); + let git = GitBinary::new(git_binary_path, working_directory, executor) + .envs(HashMap::clone(&env)); git.run(&["hook", "run", "--ignore-missing", hook.as_str()]) .await?; Ok(()) @@ -2655,10 +2764,13 @@ impl GitRepository for RealGitRepository { log_order: LogOrder, request_tx: Sender>>, ) -> BoxFuture<'_, Result<()>> { - let git_binary = self.git_binary(); + let git_binary_path = self.any_git_binary_path.clone(); + let working_directory = self.working_directory(); + let executor = self.executor.clone(); async move { - let git = git_binary?; + let working_directory = working_directory?; + let git = GitBinary::new(git_binary_path, working_directory, executor); let mut command = git.build_command([ "log", @@ -2712,12 +2824,19 @@ impl GitRepository for RealGitRepository { } fn commit_data_reader(&self) -> Result { - let git_binary = self.git_binary()?; + let git_binary_path = self.any_git_binary_path.clone(); + let working_directory = self + .working_directory() + .map_err(|_| anyhow!("no working directory"))?; + let executor = self.executor.clone(); let (request_tx, request_rx) = smol::channel::bounded::(64); let task = self.executor.spawn(async move { - if let Err(error) = run_commit_data_reader(git_binary, request_rx).await { + if let Err(error) = + run_commit_data_reader(git_binary_path, working_directory, executor, request_rx) + .await + { log::error!("commit data reader failed: {error:?}"); } }); @@ -2727,21 +2846,15 @@ impl GitRepository for RealGitRepository { _task: task, }) } - - fn set_trusted(&self, trusted: bool) { - self.is_trusted - .store(trusted, std::sync::atomic::Ordering::Release); - } - - fn is_trusted(&self) -> bool { - self.is_trusted.load(std::sync::atomic::Ordering::Acquire) - } } async fn run_commit_data_reader( - git: GitBinary, + git_binary_path: PathBuf, + working_directory: PathBuf, + executor: BackgroundExecutor, request_rx: smol::channel::Receiver, ) -> Result<()> { + let git = GitBinary::new(git_binary_path, working_directory, executor); let mut process = git .build_command(["--no-optional-locks", "cat-file", "--batch"]) .stdin(Stdio::piped()) @@ -2917,21 +3030,19 @@ async fn exclude_files(git: &GitBinary) -> Result { Ok(excludes) } -pub(crate) struct GitBinary { +struct GitBinary { git_binary_path: PathBuf, working_directory: PathBuf, executor: BackgroundExecutor, index_file_path: Option, envs: HashMap, - is_trusted: bool, } impl GitBinary { - pub(crate) fn new( + fn new( git_binary_path: PathBuf, working_directory: PathBuf, executor: BackgroundExecutor, - is_trusted: bool, ) -> Self { Self { git_binary_path, @@ -2939,7 +3050,6 @@ impl GitBinary { executor, index_file_path: None, envs: HashMap::default(), - is_trusted, } } @@ -3044,20 +3154,12 @@ impl GitBinary { Ok(String::from_utf8(output.stdout)?) } - #[allow(clippy::disallowed_methods)] - pub(crate) fn build_command( - &self, - args: impl IntoIterator, - ) -> util::command::Command + fn build_command(&self, args: impl IntoIterator) -> util::command::Command where S: AsRef, { let mut command = new_command(&self.git_binary_path); command.current_dir(&self.working_directory); - command.args(["-c", "core.fsmonitor=false"]); - if !self.is_trusted { - command.args(["-c", "core.hooksPath=/dev/null"]); - } command.args(args); if let Some(index_file_path) = self.index_file_path.as_ref() { command.env("GIT_INDEX_FILE", index_file_path); @@ -3317,102 +3419,6 @@ mod tests { } } - #[gpui::test] - async fn test_build_command_untrusted_includes_both_safety_args(cx: &mut TestAppContext) { - cx.executor().allow_parking(); - let dir = tempfile::tempdir().unwrap(); - let git = GitBinary::new( - PathBuf::from("git"), - dir.path().to_path_buf(), - cx.executor(), - false, - ); - let output = git - .build_command(["version"]) - .output() - .await - .expect("git version should succeed"); - assert!(output.status.success()); - - let git = GitBinary::new( - PathBuf::from("git"), - dir.path().to_path_buf(), - cx.executor(), - false, - ); - let output = git - .build_command(["config", "--get", "core.fsmonitor"]) - .output() - .await - .expect("git config should run"); - let stdout = String::from_utf8_lossy(&output.stdout); - assert_eq!( - stdout.trim(), - "false", - "fsmonitor should be disabled for untrusted repos" - ); - - git2::Repository::init(dir.path()).unwrap(); - let git = GitBinary::new( - PathBuf::from("git"), - dir.path().to_path_buf(), - cx.executor(), - false, - ); - let output = git - .build_command(["config", "--get", "core.hooksPath"]) - .output() - .await - .expect("git config should run"); - let stdout = String::from_utf8_lossy(&output.stdout); - assert_eq!( - stdout.trim(), - "/dev/null", - "hooksPath should be /dev/null for untrusted repos" - ); - } - - #[gpui::test] - async fn test_build_command_trusted_only_disables_fsmonitor(cx: &mut TestAppContext) { - cx.executor().allow_parking(); - let dir = tempfile::tempdir().unwrap(); - git2::Repository::init(dir.path()).unwrap(); - - let git = GitBinary::new( - PathBuf::from("git"), - dir.path().to_path_buf(), - cx.executor(), - true, - ); - let output = git - .build_command(["config", "--get", "core.fsmonitor"]) - .output() - .await - .expect("git config should run"); - let stdout = String::from_utf8_lossy(&output.stdout); - assert_eq!( - stdout.trim(), - "false", - "fsmonitor should be disabled even for trusted repos" - ); - - let git = GitBinary::new( - PathBuf::from("git"), - dir.path().to_path_buf(), - cx.executor(), - true, - ); - let output = git - .build_command(["config", "--get", "core.hooksPath"]) - .output() - .await - .expect("git config should run"); - assert!( - !output.status.success(), - "hooksPath should NOT be overridden for trusted repos" - ); - } - #[gpui::test] async fn test_checkpoint_basic(cx: &mut TestAppContext) { disable_git_global_config(); @@ -4277,7 +4283,7 @@ mod tests { .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, true); + let git = GitBinary::new(git_binary_path, working_directory, executor); git.run(&["gc", "--prune"]).await?; Ok(()) }) diff --git a/crates/project/src/git_store.rs b/crates/project/src/git_store.rs index 6d6eab4216f90a2c4e5077caa7af0f155a191abe..1272a689b908413fff5eef71cf5e0e98fd72429b 100644 --- a/crates/project/src/git_store.rs +++ b/crates/project/src/git_store.rs @@ -6,9 +6,6 @@ pub mod pending_op; use crate::{ ProjectEnvironment, ProjectItem, ProjectPath, buffer_store::{BufferStore, BufferStoreEvent}, - trusted_worktrees::{ - PathTrust, TrustedWorktrees, TrustedWorktreesEvent, TrustedWorktreesStore, - }, worktree_store::{WorktreeStore, WorktreeStoreEvent}, }; use anyhow::{Context as _, Result, anyhow, bail}; @@ -346,7 +343,6 @@ impl LocalRepositoryState { dot_git_abs_path: Arc, project_environment: WeakEntity, fs: Arc, - is_trusted: bool, cx: &mut AsyncApp, ) -> anyhow::Result { let environment = project_environment @@ -374,7 +370,6 @@ impl LocalRepositoryState { } }) .await?; - backend.set_trusted(is_trusted); Ok(LocalRepositoryState { backend, environment: Arc::new(environment), @@ -483,15 +478,11 @@ impl GitStore { state: GitStoreState, cx: &mut Context, ) -> Self { - let mut _subscriptions = vec![ + let _subscriptions = vec![ cx.subscribe(&worktree_store, Self::on_worktree_store_event), cx.subscribe(&buffer_store, Self::on_buffer_store_event), ]; - if let Some(trusted_worktrees) = TrustedWorktrees::try_get_global(cx) { - _subscriptions.push(cx.subscribe(&trusted_worktrees, Self::on_trusted_worktrees_event)); - } - GitStore { state, buffer_store, @@ -1506,13 +1497,6 @@ impl GitStore { } = update { let id = RepositoryId(next_repository_id.fetch_add(1, atomic::Ordering::Release)); - let is_trusted = TrustedWorktrees::try_get_global(cx) - .map(|trusted_worktrees| { - trusted_worktrees.update(cx, |trusted_worktrees, cx| { - trusted_worktrees.can_trust(&self.worktree_store, worktree_id, cx) - }) - }) - .unwrap_or(false); let git_store = cx.weak_entity(); let repo = cx.new(|cx| { let mut repo = Repository::local( @@ -1521,7 +1505,6 @@ impl GitStore { dot_git_abs_path.clone(), project_environment.downgrade(), fs.clone(), - is_trusted, git_store, cx, ); @@ -1562,39 +1545,6 @@ impl GitStore { } } - fn on_trusted_worktrees_event( - &mut self, - _: Entity, - event: &TrustedWorktreesEvent, - cx: &mut Context, - ) { - if !matches!(self.state, GitStoreState::Local { .. }) { - return; - } - - let (is_trusted, event_paths) = match event { - TrustedWorktreesEvent::Trusted(_, trusted_paths) => (true, trusted_paths), - TrustedWorktreesEvent::Restricted(_, restricted_paths) => (false, restricted_paths), - }; - - for (repo_id, worktree_ids) in &self.worktree_ids { - if worktree_ids - .iter() - .any(|worktree_id| event_paths.contains(&PathTrust::Worktree(*worktree_id))) - { - if let Some(repo) = self.repositories.get(repo_id) { - let repository_state = repo.read(cx).repository_state.clone(); - cx.background_spawn(async move { - if let Ok(RepositoryState::Local(state)) = repository_state.await { - state.backend.set_trusted(is_trusted); - } - }) - .detach(); - } - } - } - } - fn on_buffer_store_event( &mut self, _: Entity, @@ -3743,13 +3693,6 @@ impl MergeDetails { } impl Repository { - pub fn is_trusted(&self) -> bool { - match self.repository_state.peek() { - Some(Ok(RepositoryState::Local(state))) => state.backend.is_trusted(), - _ => false, - } - } - pub fn snapshot(&self) -> RepositorySnapshot { self.snapshot.clone() } @@ -3774,7 +3717,6 @@ impl Repository { dot_git_abs_path: Arc, project_environment: WeakEntity, fs: Arc, - is_trusted: bool, git_store: WeakEntity, cx: &mut Context, ) -> Self { @@ -3787,7 +3729,6 @@ impl Repository { dot_git_abs_path, project_environment, fs, - is_trusted, cx, ) .await