git: Pass project environment to git binary invocations (#26301)
Closes #26213 Release Notes: - Git Beta: pass down environment variables from project to git operations
This commit is contained in:
parent
013a646799
commit
b91e929086
6 changed files with 194 additions and 55 deletions
|
@ -149,7 +149,12 @@ pub trait GitRepository: Send + Sync {
|
||||||
/// Also returns `None` for symlinks.
|
/// Also returns `None` for symlinks.
|
||||||
fn load_committed_text(&self, path: &RepoPath) -> Option<String>;
|
fn load_committed_text(&self, path: &RepoPath) -> Option<String>;
|
||||||
|
|
||||||
fn set_index_text(&self, path: &RepoPath, content: Option<String>) -> anyhow::Result<()>;
|
fn set_index_text(
|
||||||
|
&self,
|
||||||
|
path: &RepoPath,
|
||||||
|
content: Option<String>,
|
||||||
|
env: &HashMap<String, String>,
|
||||||
|
) -> anyhow::Result<()>;
|
||||||
|
|
||||||
/// Returns the URL of the remote with the given name.
|
/// Returns the URL of the remote with the given name.
|
||||||
fn remote_url(&self, name: &str) -> Option<String>;
|
fn remote_url(&self, name: &str) -> Option<String>;
|
||||||
|
@ -167,8 +172,13 @@ pub trait GitRepository: Send + Sync {
|
||||||
fn create_branch(&self, _: &str) -> Result<()>;
|
fn create_branch(&self, _: &str) -> Result<()>;
|
||||||
fn branch_exits(&self, _: &str) -> Result<bool>;
|
fn branch_exits(&self, _: &str) -> Result<bool>;
|
||||||
|
|
||||||
fn reset(&self, commit: &str, mode: ResetMode) -> Result<()>;
|
fn reset(&self, commit: &str, mode: ResetMode, env: &HashMap<String, String>) -> Result<()>;
|
||||||
fn checkout_files(&self, commit: &str, paths: &[RepoPath]) -> Result<()>;
|
fn checkout_files(
|
||||||
|
&self,
|
||||||
|
commit: &str,
|
||||||
|
paths: &[RepoPath],
|
||||||
|
env: &HashMap<String, String>,
|
||||||
|
) -> Result<()>;
|
||||||
|
|
||||||
fn show(&self, commit: &str) -> Result<CommitDetails>;
|
fn show(&self, commit: &str) -> Result<CommitDetails>;
|
||||||
|
|
||||||
|
@ -189,13 +199,18 @@ pub trait GitRepository: Send + Sync {
|
||||||
/// Updates the index to match the worktree at the given paths.
|
/// Updates the index to match the worktree at the given paths.
|
||||||
///
|
///
|
||||||
/// If any of the paths have been deleted from the worktree, they will be removed from the index if found there.
|
/// If any of the paths have been deleted from the worktree, they will be removed from the index if found there.
|
||||||
fn stage_paths(&self, paths: &[RepoPath]) -> Result<()>;
|
fn stage_paths(&self, paths: &[RepoPath], env: &HashMap<String, String>) -> Result<()>;
|
||||||
/// Updates the index to match HEAD at the given paths.
|
/// Updates the index to match HEAD at the given paths.
|
||||||
///
|
///
|
||||||
/// If any of the paths were previously staged but do not exist in HEAD, they will be removed from the index.
|
/// If any of the paths were previously staged but do not exist in HEAD, they will be removed from the index.
|
||||||
fn unstage_paths(&self, paths: &[RepoPath]) -> Result<()>;
|
fn unstage_paths(&self, paths: &[RepoPath], env: &HashMap<String, String>) -> Result<()>;
|
||||||
|
|
||||||
fn commit(&self, message: &str, name_and_email: Option<(&str, &str)>) -> Result<()>;
|
fn commit(
|
||||||
|
&self,
|
||||||
|
message: &str,
|
||||||
|
name_and_email: Option<(&str, &str)>,
|
||||||
|
env: &HashMap<String, String>,
|
||||||
|
) -> Result<()>;
|
||||||
|
|
||||||
fn push(
|
fn push(
|
||||||
&self,
|
&self,
|
||||||
|
@ -203,6 +218,7 @@ pub trait GitRepository: Send + Sync {
|
||||||
upstream_name: &str,
|
upstream_name: &str,
|
||||||
options: Option<PushOptions>,
|
options: Option<PushOptions>,
|
||||||
askpass: AskPassSession,
|
askpass: AskPassSession,
|
||||||
|
env: &HashMap<String, String>,
|
||||||
) -> Result<RemoteCommandOutput>;
|
) -> Result<RemoteCommandOutput>;
|
||||||
|
|
||||||
fn pull(
|
fn pull(
|
||||||
|
@ -210,8 +226,13 @@ pub trait GitRepository: Send + Sync {
|
||||||
branch_name: &str,
|
branch_name: &str,
|
||||||
upstream_name: &str,
|
upstream_name: &str,
|
||||||
askpass: AskPassSession,
|
askpass: AskPassSession,
|
||||||
|
env: &HashMap<String, String>,
|
||||||
|
) -> Result<RemoteCommandOutput>;
|
||||||
|
fn fetch(
|
||||||
|
&self,
|
||||||
|
askpass: AskPassSession,
|
||||||
|
env: &HashMap<String, String>,
|
||||||
) -> Result<RemoteCommandOutput>;
|
) -> Result<RemoteCommandOutput>;
|
||||||
fn fetch(&self, askpass: AskPassSession) -> Result<RemoteCommandOutput>;
|
|
||||||
|
|
||||||
fn get_remotes(&self, branch_name: Option<&str>) -> Result<Vec<Remote>>;
|
fn get_remotes(&self, branch_name: Option<&str>) -> Result<Vec<Remote>>;
|
||||||
|
|
||||||
|
@ -308,7 +329,7 @@ impl GitRepository for RealGitRepository {
|
||||||
Ok(details)
|
Ok(details)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset(&self, commit: &str, mode: ResetMode) -> Result<()> {
|
fn reset(&self, commit: &str, mode: ResetMode, env: &HashMap<String, String>) -> Result<()> {
|
||||||
let working_directory = self.working_directory()?;
|
let working_directory = self.working_directory()?;
|
||||||
|
|
||||||
let mode_flag = match mode {
|
let mode_flag = match mode {
|
||||||
|
@ -317,6 +338,7 @@ impl GitRepository for RealGitRepository {
|
||||||
};
|
};
|
||||||
|
|
||||||
let output = new_std_command(&self.git_binary_path)
|
let output = new_std_command(&self.git_binary_path)
|
||||||
|
.envs(env)
|
||||||
.current_dir(&working_directory)
|
.current_dir(&working_directory)
|
||||||
.args(["reset", mode_flag, commit])
|
.args(["reset", mode_flag, commit])
|
||||||
.output()?;
|
.output()?;
|
||||||
|
@ -329,7 +351,12 @@ impl GitRepository for RealGitRepository {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn checkout_files(&self, commit: &str, paths: &[RepoPath]) -> Result<()> {
|
fn checkout_files(
|
||||||
|
&self,
|
||||||
|
commit: &str,
|
||||||
|
paths: &[RepoPath],
|
||||||
|
env: &HashMap<String, String>,
|
||||||
|
) -> Result<()> {
|
||||||
if paths.is_empty() {
|
if paths.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -337,6 +364,7 @@ impl GitRepository for RealGitRepository {
|
||||||
|
|
||||||
let output = new_std_command(&self.git_binary_path)
|
let output = new_std_command(&self.git_binary_path)
|
||||||
.current_dir(&working_directory)
|
.current_dir(&working_directory)
|
||||||
|
.envs(env)
|
||||||
.args(["checkout", commit, "--"])
|
.args(["checkout", commit, "--"])
|
||||||
.args(paths.iter().map(|path| path.as_ref()))
|
.args(paths.iter().map(|path| path.as_ref()))
|
||||||
.output()?;
|
.output()?;
|
||||||
|
@ -385,11 +413,17 @@ impl GitRepository for RealGitRepository {
|
||||||
Some(content)
|
Some(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_index_text(&self, path: &RepoPath, content: Option<String>) -> anyhow::Result<()> {
|
fn set_index_text(
|
||||||
|
&self,
|
||||||
|
path: &RepoPath,
|
||||||
|
content: Option<String>,
|
||||||
|
env: &HashMap<String, String>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
let working_directory = self.working_directory()?;
|
let working_directory = self.working_directory()?;
|
||||||
if let Some(content) = content {
|
if let Some(content) = content {
|
||||||
let mut child = new_std_command(&self.git_binary_path)
|
let mut child = new_std_command(&self.git_binary_path)
|
||||||
.current_dir(&working_directory)
|
.current_dir(&working_directory)
|
||||||
|
.envs(env)
|
||||||
.args(["hash-object", "-w", "--stdin"])
|
.args(["hash-object", "-w", "--stdin"])
|
||||||
.stdin(Stdio::piped())
|
.stdin(Stdio::piped())
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
|
@ -402,6 +436,7 @@ impl GitRepository for RealGitRepository {
|
||||||
|
|
||||||
let output = new_std_command(&self.git_binary_path)
|
let output = new_std_command(&self.git_binary_path)
|
||||||
.current_dir(&working_directory)
|
.current_dir(&working_directory)
|
||||||
|
.envs(env)
|
||||||
.args(["update-index", "--add", "--cacheinfo", "100644", &sha])
|
.args(["update-index", "--add", "--cacheinfo", "100644", &sha])
|
||||||
.arg(path.as_ref())
|
.arg(path.as_ref())
|
||||||
.output()?;
|
.output()?;
|
||||||
|
@ -415,6 +450,7 @@ impl GitRepository for RealGitRepository {
|
||||||
} else {
|
} else {
|
||||||
let output = new_std_command(&self.git_binary_path)
|
let output = new_std_command(&self.git_binary_path)
|
||||||
.current_dir(&working_directory)
|
.current_dir(&working_directory)
|
||||||
|
.envs(env)
|
||||||
.args(["update-index", "--force-remove"])
|
.args(["update-index", "--force-remove"])
|
||||||
.arg(path.as_ref())
|
.arg(path.as_ref())
|
||||||
.output()?;
|
.output()?;
|
||||||
|
@ -607,12 +643,13 @@ impl GitRepository for RealGitRepository {
|
||||||
Ok(String::from_utf8_lossy(&output.stdout).to_string())
|
Ok(String::from_utf8_lossy(&output.stdout).to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stage_paths(&self, paths: &[RepoPath]) -> Result<()> {
|
fn stage_paths(&self, paths: &[RepoPath], env: &HashMap<String, String>) -> Result<()> {
|
||||||
let working_directory = self.working_directory()?;
|
let working_directory = self.working_directory()?;
|
||||||
|
|
||||||
if !paths.is_empty() {
|
if !paths.is_empty() {
|
||||||
let output = new_std_command(&self.git_binary_path)
|
let output = new_std_command(&self.git_binary_path)
|
||||||
.current_dir(&working_directory)
|
.current_dir(&working_directory)
|
||||||
|
.envs(env)
|
||||||
.args(["update-index", "--add", "--remove", "--"])
|
.args(["update-index", "--add", "--remove", "--"])
|
||||||
.args(paths.iter().map(|p| p.as_ref()))
|
.args(paths.iter().map(|p| p.as_ref()))
|
||||||
.output()?;
|
.output()?;
|
||||||
|
@ -627,12 +664,13 @@ impl GitRepository for RealGitRepository {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unstage_paths(&self, paths: &[RepoPath]) -> Result<()> {
|
fn unstage_paths(&self, paths: &[RepoPath], env: &HashMap<String, String>) -> Result<()> {
|
||||||
let working_directory = self.working_directory()?;
|
let working_directory = self.working_directory()?;
|
||||||
|
|
||||||
if !paths.is_empty() {
|
if !paths.is_empty() {
|
||||||
let output = new_std_command(&self.git_binary_path)
|
let output = new_std_command(&self.git_binary_path)
|
||||||
.current_dir(&working_directory)
|
.current_dir(&working_directory)
|
||||||
|
.envs(env)
|
||||||
.args(["reset", "--quiet", "--"])
|
.args(["reset", "--quiet", "--"])
|
||||||
.args(paths.iter().map(|p| p.as_ref()))
|
.args(paths.iter().map(|p| p.as_ref()))
|
||||||
.output()?;
|
.output()?;
|
||||||
|
@ -647,11 +685,17 @@ impl GitRepository for RealGitRepository {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn commit(&self, message: &str, name_and_email: Option<(&str, &str)>) -> Result<()> {
|
fn commit(
|
||||||
|
&self,
|
||||||
|
message: &str,
|
||||||
|
name_and_email: Option<(&str, &str)>,
|
||||||
|
env: &HashMap<String, String>,
|
||||||
|
) -> Result<()> {
|
||||||
let working_directory = self.working_directory()?;
|
let working_directory = self.working_directory()?;
|
||||||
|
|
||||||
let mut cmd = new_std_command(&self.git_binary_path);
|
let mut cmd = new_std_command(&self.git_binary_path);
|
||||||
cmd.current_dir(&working_directory)
|
cmd.current_dir(&working_directory)
|
||||||
|
.envs(env)
|
||||||
.args(["commit", "--quiet", "-m"])
|
.args(["commit", "--quiet", "-m"])
|
||||||
.arg(message)
|
.arg(message)
|
||||||
.arg("--cleanup=strip");
|
.arg("--cleanup=strip");
|
||||||
|
@ -677,11 +721,13 @@ impl GitRepository for RealGitRepository {
|
||||||
remote_name: &str,
|
remote_name: &str,
|
||||||
options: Option<PushOptions>,
|
options: Option<PushOptions>,
|
||||||
ask_pass: AskPassSession,
|
ask_pass: AskPassSession,
|
||||||
|
env: &HashMap<String, String>,
|
||||||
) -> Result<RemoteCommandOutput> {
|
) -> Result<RemoteCommandOutput> {
|
||||||
let working_directory = self.working_directory()?;
|
let working_directory = self.working_directory()?;
|
||||||
|
|
||||||
let mut command = new_smol_command("git");
|
let mut command = new_smol_command("git");
|
||||||
command
|
command
|
||||||
|
.envs(env)
|
||||||
.env("GIT_ASKPASS", ask_pass.script_path())
|
.env("GIT_ASKPASS", ask_pass.script_path())
|
||||||
.env("SSH_ASKPASS", ask_pass.script_path())
|
.env("SSH_ASKPASS", ask_pass.script_path())
|
||||||
.env("SSH_ASKPASS_REQUIRE", "force")
|
.env("SSH_ASKPASS_REQUIRE", "force")
|
||||||
|
@ -705,11 +751,13 @@ impl GitRepository for RealGitRepository {
|
||||||
branch_name: &str,
|
branch_name: &str,
|
||||||
remote_name: &str,
|
remote_name: &str,
|
||||||
ask_pass: AskPassSession,
|
ask_pass: AskPassSession,
|
||||||
|
env: &HashMap<String, String>,
|
||||||
) -> Result<RemoteCommandOutput> {
|
) -> Result<RemoteCommandOutput> {
|
||||||
let working_directory = self.working_directory()?;
|
let working_directory = self.working_directory()?;
|
||||||
|
|
||||||
let mut command = new_smol_command("git");
|
let mut command = new_smol_command("git");
|
||||||
command
|
command
|
||||||
|
.envs(env)
|
||||||
.env("GIT_ASKPASS", ask_pass.script_path())
|
.env("GIT_ASKPASS", ask_pass.script_path())
|
||||||
.env("SSH_ASKPASS", ask_pass.script_path())
|
.env("SSH_ASKPASS", ask_pass.script_path())
|
||||||
.env("SSH_ASKPASS_REQUIRE", "force")
|
.env("SSH_ASKPASS_REQUIRE", "force")
|
||||||
|
@ -724,11 +772,16 @@ impl GitRepository for RealGitRepository {
|
||||||
run_remote_command(ask_pass, git_process)
|
run_remote_command(ask_pass, git_process)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch(&self, ask_pass: AskPassSession) -> Result<RemoteCommandOutput> {
|
fn fetch(
|
||||||
|
&self,
|
||||||
|
ask_pass: AskPassSession,
|
||||||
|
env: &HashMap<String, String>,
|
||||||
|
) -> Result<RemoteCommandOutput> {
|
||||||
let working_directory = self.working_directory()?;
|
let working_directory = self.working_directory()?;
|
||||||
|
|
||||||
let mut command = new_smol_command("git");
|
let mut command = new_smol_command("git");
|
||||||
command
|
command
|
||||||
|
.envs(env)
|
||||||
.env("GIT_ASKPASS", ask_pass.script_path())
|
.env("GIT_ASKPASS", ask_pass.script_path())
|
||||||
.env("SSH_ASKPASS", ask_pass.script_path())
|
.env("SSH_ASKPASS", ask_pass.script_path())
|
||||||
.env("SSH_ASKPASS_REQUIRE", "force")
|
.env("SSH_ASKPASS_REQUIRE", "force")
|
||||||
|
@ -919,7 +972,12 @@ impl GitRepository for FakeGitRepository {
|
||||||
state.head_contents.get(path.as_ref()).cloned()
|
state.head_contents.get(path.as_ref()).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_index_text(&self, path: &RepoPath, content: Option<String>) -> anyhow::Result<()> {
|
fn set_index_text(
|
||||||
|
&self,
|
||||||
|
path: &RepoPath,
|
||||||
|
content: Option<String>,
|
||||||
|
_env: &HashMap<String, String>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
let mut state = self.state.lock();
|
let mut state = self.state.lock();
|
||||||
if let Some(message) = state.simulated_index_write_error_message.clone() {
|
if let Some(message) = state.simulated_index_write_error_message.clone() {
|
||||||
return Err(anyhow::anyhow!(message));
|
return Err(anyhow::anyhow!(message));
|
||||||
|
@ -952,11 +1010,11 @@ impl GitRepository for FakeGitRepository {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset(&self, _: &str, _: ResetMode) -> Result<()> {
|
fn reset(&self, _: &str, _: ResetMode, _: &HashMap<String, String>) -> Result<()> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn checkout_files(&self, _: &str, _: &[RepoPath]) -> Result<()> {
|
fn checkout_files(&self, _: &str, _: &[RepoPath], _: &HashMap<String, String>) -> Result<()> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1042,15 +1100,20 @@ impl GitRepository for FakeGitRepository {
|
||||||
.cloned()
|
.cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stage_paths(&self, _paths: &[RepoPath]) -> Result<()> {
|
fn stage_paths(&self, _paths: &[RepoPath], _env: &HashMap<String, String>) -> Result<()> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unstage_paths(&self, _paths: &[RepoPath]) -> Result<()> {
|
fn unstage_paths(&self, _paths: &[RepoPath], _env: &HashMap<String, String>) -> Result<()> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn commit(&self, _message: &str, _name_and_email: Option<(&str, &str)>) -> Result<()> {
|
fn commit(
|
||||||
|
&self,
|
||||||
|
_message: &str,
|
||||||
|
_name_and_email: Option<(&str, &str)>,
|
||||||
|
_env: &HashMap<String, String>,
|
||||||
|
) -> Result<()> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1060,6 +1123,7 @@ impl GitRepository for FakeGitRepository {
|
||||||
_remote: &str,
|
_remote: &str,
|
||||||
_options: Option<PushOptions>,
|
_options: Option<PushOptions>,
|
||||||
_ask_pass: AskPassSession,
|
_ask_pass: AskPassSession,
|
||||||
|
_env: &HashMap<String, String>,
|
||||||
) -> Result<RemoteCommandOutput> {
|
) -> Result<RemoteCommandOutput> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
@ -1069,11 +1133,16 @@ impl GitRepository for FakeGitRepository {
|
||||||
_branch: &str,
|
_branch: &str,
|
||||||
_remote: &str,
|
_remote: &str,
|
||||||
_ask_pass: AskPassSession,
|
_ask_pass: AskPassSession,
|
||||||
|
_env: &HashMap<String, String>,
|
||||||
) -> Result<RemoteCommandOutput> {
|
) -> Result<RemoteCommandOutput> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch(&self, _ask_pass: AskPassSession) -> Result<RemoteCommandOutput> {
|
fn fetch(
|
||||||
|
&self,
|
||||||
|
_ask_pass: AskPassSession,
|
||||||
|
_env: &HashMap<String, String>,
|
||||||
|
) -> Result<RemoteCommandOutput> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -901,13 +901,14 @@ impl GitPanel {
|
||||||
let buffers = futures::future::join_all(tasks).await;
|
let buffers = futures::future::join_all(tasks).await;
|
||||||
|
|
||||||
active_repository
|
active_repository
|
||||||
.update(&mut cx, |repo, _| {
|
.update(&mut cx, |repo, cx| {
|
||||||
repo.checkout_files(
|
repo.checkout_files(
|
||||||
"HEAD",
|
"HEAD",
|
||||||
entries
|
entries
|
||||||
.iter()
|
.iter()
|
||||||
.map(|entries| entries.repo_path.clone())
|
.map(|entries| entries.repo_path.clone())
|
||||||
.collect(),
|
.collect(),
|
||||||
|
cx,
|
||||||
)
|
)
|
||||||
})?
|
})?
|
||||||
.await??;
|
.await??;
|
||||||
|
@ -1289,7 +1290,8 @@ impl GitPanel {
|
||||||
|
|
||||||
let task = if self.has_staged_changes() {
|
let task = if self.has_staged_changes() {
|
||||||
// Repository serializes all git operations, so we can just send a commit immediately
|
// Repository serializes all git operations, so we can just send a commit immediately
|
||||||
let commit_task = active_repository.read(cx).commit(message.into(), None);
|
let commit_task =
|
||||||
|
active_repository.update(cx, |repo, cx| repo.commit(message.into(), None, cx));
|
||||||
cx.background_spawn(async move { commit_task.await? })
|
cx.background_spawn(async move { commit_task.await? })
|
||||||
} else {
|
} else {
|
||||||
let changed_files = self
|
let changed_files = self
|
||||||
|
@ -1310,7 +1312,7 @@ impl GitPanel {
|
||||||
cx.spawn(|_, mut cx| async move {
|
cx.spawn(|_, mut cx| async move {
|
||||||
stage_task.await?;
|
stage_task.await?;
|
||||||
let commit_task = active_repository
|
let commit_task = active_repository
|
||||||
.update(&mut cx, |repo, _| repo.commit(message.into(), None))?;
|
.update(&mut cx, |repo, cx| repo.commit(message.into(), None, cx))?;
|
||||||
commit_task.await?
|
commit_task.await?
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
@ -1346,7 +1348,7 @@ impl GitPanel {
|
||||||
if let Ok(true) = confirmation.await {
|
if let Ok(true) = confirmation.await {
|
||||||
let prior_head = prior_head.await?;
|
let prior_head = prior_head.await?;
|
||||||
|
|
||||||
repo.update(&mut cx, |repo, _| repo.reset("HEAD^", ResetMode::Soft))?
|
repo.update(&mut cx, |repo, cx| repo.reset("HEAD^", ResetMode::Soft, cx))?
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
Ok(Some(prior_head))
|
Ok(Some(prior_head))
|
||||||
|
|
|
@ -178,6 +178,7 @@ impl EntityMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
fn double_lease_panic<T>(operation: &str) -> ! {
|
fn double_lease_panic<T>(operation: &str) -> ! {
|
||||||
panic!(
|
panic!(
|
||||||
"cannot {operation} {} while it is already being updated",
|
"cannot {operation} {} while it is already being updated",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
buffer_store::{BufferStore, BufferStoreEvent},
|
buffer_store::{BufferStore, BufferStoreEvent},
|
||||||
worktree_store::{WorktreeStore, WorktreeStoreEvent},
|
worktree_store::{WorktreeStore, WorktreeStoreEvent},
|
||||||
Project, ProjectItem, ProjectPath,
|
Project, ProjectEnvironment, ProjectItem, ProjectPath,
|
||||||
};
|
};
|
||||||
use anyhow::{Context as _, Result};
|
use anyhow::{Context as _, Result};
|
||||||
use askpass::{AskPassDelegate, AskPassSession};
|
use askpass::{AskPassDelegate, AskPassSession};
|
||||||
|
@ -10,6 +10,7 @@ use client::ProjectId;
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use futures::{
|
use futures::{
|
||||||
channel::{mpsc, oneshot},
|
channel::{mpsc, oneshot},
|
||||||
|
future::OptionFuture,
|
||||||
StreamExt as _,
|
StreamExt as _,
|
||||||
};
|
};
|
||||||
use git::repository::DiffType;
|
use git::repository::DiffType;
|
||||||
|
@ -43,6 +44,7 @@ use worktree::{ProjectEntryId, RepositoryEntry, StatusEntry, WorkDirectory};
|
||||||
|
|
||||||
pub struct GitStore {
|
pub struct GitStore {
|
||||||
buffer_store: Entity<BufferStore>,
|
buffer_store: Entity<BufferStore>,
|
||||||
|
environment: Option<Entity<ProjectEnvironment>>,
|
||||||
pub(super) project_id: Option<ProjectId>,
|
pub(super) project_id: Option<ProjectId>,
|
||||||
pub(super) client: AnyProtoClient,
|
pub(super) client: AnyProtoClient,
|
||||||
repositories: Vec<Entity<Repository>>,
|
repositories: Vec<Entity<Repository>>,
|
||||||
|
@ -54,6 +56,7 @@ pub struct GitStore {
|
||||||
pub struct Repository {
|
pub struct Repository {
|
||||||
commit_message_buffer: Option<Entity<Buffer>>,
|
commit_message_buffer: Option<Entity<Buffer>>,
|
||||||
git_store: WeakEntity<GitStore>,
|
git_store: WeakEntity<GitStore>,
|
||||||
|
project_environment: Option<WeakEntity<ProjectEnvironment>>,
|
||||||
pub worktree_id: WorktreeId,
|
pub worktree_id: WorktreeId,
|
||||||
pub repository_entry: RepositoryEntry,
|
pub repository_entry: RepositoryEntry,
|
||||||
pub dot_git_abs_path: PathBuf,
|
pub dot_git_abs_path: PathBuf,
|
||||||
|
@ -101,6 +104,7 @@ impl GitStore {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
worktree_store: &Entity<WorktreeStore>,
|
worktree_store: &Entity<WorktreeStore>,
|
||||||
buffer_store: Entity<BufferStore>,
|
buffer_store: Entity<BufferStore>,
|
||||||
|
environment: Option<Entity<ProjectEnvironment>>,
|
||||||
client: AnyProtoClient,
|
client: AnyProtoClient,
|
||||||
project_id: Option<ProjectId>,
|
project_id: Option<ProjectId>,
|
||||||
cx: &mut Context<'_, Self>,
|
cx: &mut Context<'_, Self>,
|
||||||
|
@ -115,6 +119,7 @@ impl GitStore {
|
||||||
project_id,
|
project_id,
|
||||||
client,
|
client,
|
||||||
buffer_store,
|
buffer_store,
|
||||||
|
environment,
|
||||||
repositories: Vec::new(),
|
repositories: Vec::new(),
|
||||||
active_index: None,
|
active_index: None,
|
||||||
update_sender,
|
update_sender,
|
||||||
|
@ -225,6 +230,10 @@ impl GitStore {
|
||||||
existing_handle
|
existing_handle
|
||||||
} else {
|
} else {
|
||||||
cx.new(|_| Repository {
|
cx.new(|_| Repository {
|
||||||
|
project_environment: self
|
||||||
|
.environment
|
||||||
|
.as_ref()
|
||||||
|
.map(|env| env.downgrade()),
|
||||||
git_store: this.clone(),
|
git_store: this.clone(),
|
||||||
worktree_id,
|
worktree_id,
|
||||||
askpass_delegates: Default::default(),
|
askpass_delegates: Default::default(),
|
||||||
|
@ -282,9 +291,13 @@ impl GitStore {
|
||||||
if let BufferDiffEvent::HunksStagedOrUnstaged(new_index_text) = event {
|
if let BufferDiffEvent::HunksStagedOrUnstaged(new_index_text) = event {
|
||||||
let buffer_id = diff.read(cx).buffer_id;
|
let buffer_id = diff.read(cx).buffer_id;
|
||||||
if let Some((repo, path)) = this.repository_and_path_for_buffer_id(buffer_id, cx) {
|
if let Some((repo, path)) = this.repository_and_path_for_buffer_id(buffer_id, cx) {
|
||||||
let recv = repo
|
let recv = repo.update(cx, |repo, cx| {
|
||||||
.read(cx)
|
repo.set_index_text(
|
||||||
.set_index_text(&path, new_index_text.as_ref().map(|rope| rope.to_string()));
|
&path,
|
||||||
|
new_index_text.as_ref().map(|rope| rope.to_string()),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
});
|
||||||
let diff = diff.downgrade();
|
let diff = diff.downgrade();
|
||||||
cx.spawn(|this, mut cx| async move {
|
cx.spawn(|this, mut cx| async move {
|
||||||
if let Some(result) = cx.background_spawn(async move { recv.await.ok() }).await
|
if let Some(result) = cx.background_spawn(async move { recv.await.ok() }).await
|
||||||
|
@ -542,10 +555,11 @@ impl GitStore {
|
||||||
Self::repository_for_request(&this, worktree_id, work_directory_id, &mut cx)?;
|
Self::repository_for_request(&this, worktree_id, work_directory_id, &mut cx)?;
|
||||||
|
|
||||||
repository_handle
|
repository_handle
|
||||||
.update(&mut cx, |repository_handle, _| {
|
.update(&mut cx, |repository_handle, cx| {
|
||||||
repository_handle.set_index_text(
|
repository_handle.set_index_text(
|
||||||
&RepoPath::from_str(&envelope.payload.path),
|
&RepoPath::from_str(&envelope.payload.path),
|
||||||
envelope.payload.text,
|
envelope.payload.text,
|
||||||
|
cx,
|
||||||
)
|
)
|
||||||
})?
|
})?
|
||||||
.await??;
|
.await??;
|
||||||
|
@ -567,8 +581,8 @@ impl GitStore {
|
||||||
let email = envelope.payload.email.map(SharedString::from);
|
let email = envelope.payload.email.map(SharedString::from);
|
||||||
|
|
||||||
repository_handle
|
repository_handle
|
||||||
.update(&mut cx, |repository_handle, _| {
|
.update(&mut cx, |repository_handle, cx| {
|
||||||
repository_handle.commit(message, name.zip(email))
|
repository_handle.commit(message, name.zip(email), cx)
|
||||||
})?
|
})?
|
||||||
.await??;
|
.await??;
|
||||||
Ok(proto::Ack {})
|
Ok(proto::Ack {})
|
||||||
|
@ -703,8 +717,8 @@ impl GitStore {
|
||||||
};
|
};
|
||||||
|
|
||||||
repository_handle
|
repository_handle
|
||||||
.update(&mut cx, |repository_handle, _| {
|
.update(&mut cx, |repository_handle, cx| {
|
||||||
repository_handle.reset(&envelope.payload.commit, mode)
|
repository_handle.reset(&envelope.payload.commit, mode, cx)
|
||||||
})?
|
})?
|
||||||
.await??;
|
.await??;
|
||||||
Ok(proto::Ack {})
|
Ok(proto::Ack {})
|
||||||
|
@ -727,8 +741,8 @@ impl GitStore {
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
repository_handle
|
repository_handle
|
||||||
.update(&mut cx, |repository_handle, _| {
|
.update(&mut cx, |repository_handle, cx| {
|
||||||
repository_handle.checkout_files(&envelope.payload.commit, paths)
|
repository_handle.checkout_files(&envelope.payload.commit, paths, cx)
|
||||||
})?
|
})?
|
||||||
.await??;
|
.await??;
|
||||||
Ok(proto::Ack {})
|
Ok(proto::Ack {})
|
||||||
|
@ -1115,11 +1129,14 @@ impl Repository {
|
||||||
&self,
|
&self,
|
||||||
commit: &str,
|
commit: &str,
|
||||||
paths: Vec<RepoPath>,
|
paths: Vec<RepoPath>,
|
||||||
|
cx: &mut App,
|
||||||
) -> oneshot::Receiver<Result<()>> {
|
) -> oneshot::Receiver<Result<()>> {
|
||||||
let commit = commit.to_string();
|
let commit = commit.to_string();
|
||||||
|
let env = self.worktree_environment(cx);
|
||||||
|
|
||||||
self.send_job(|git_repo| async move {
|
self.send_job(|git_repo| async move {
|
||||||
match git_repo {
|
match git_repo {
|
||||||
GitRepo::Local(repo) => repo.checkout_files(&commit, &paths),
|
GitRepo::Local(repo) => repo.checkout_files(&commit, &paths, &env.await),
|
||||||
GitRepo::Remote {
|
GitRepo::Remote {
|
||||||
project_id,
|
project_id,
|
||||||
client,
|
client,
|
||||||
|
@ -1145,11 +1162,20 @@ impl Repository {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(&self, commit: &str, reset_mode: ResetMode) -> oneshot::Receiver<Result<()>> {
|
pub fn reset(
|
||||||
|
&self,
|
||||||
|
commit: &str,
|
||||||
|
reset_mode: ResetMode,
|
||||||
|
cx: &mut App,
|
||||||
|
) -> oneshot::Receiver<Result<()>> {
|
||||||
let commit = commit.to_string();
|
let commit = commit.to_string();
|
||||||
|
let env = self.worktree_environment(cx);
|
||||||
self.send_job(|git_repo| async move {
|
self.send_job(|git_repo| async move {
|
||||||
match git_repo {
|
match git_repo {
|
||||||
GitRepo::Local(git_repo) => git_repo.reset(&commit, reset_mode),
|
GitRepo::Local(git_repo) => {
|
||||||
|
let env = env.await;
|
||||||
|
git_repo.reset(&commit, reset_mode, &env)
|
||||||
|
}
|
||||||
GitRepo::Remote {
|
GitRepo::Remote {
|
||||||
project_id,
|
project_id,
|
||||||
client,
|
client,
|
||||||
|
@ -1219,6 +1245,7 @@ impl Repository {
|
||||||
if entries.is_empty() {
|
if entries.is_empty() {
|
||||||
return Task::ready(Ok(()));
|
return Task::ready(Ok(()));
|
||||||
}
|
}
|
||||||
|
let env = self.worktree_environment(cx);
|
||||||
|
|
||||||
let mut save_futures = Vec::new();
|
let mut save_futures = Vec::new();
|
||||||
if let Some(buffer_store) = self.buffer_store(cx) {
|
if let Some(buffer_store) = self.buffer_store(cx) {
|
||||||
|
@ -1245,11 +1272,12 @@ impl Repository {
|
||||||
for save_future in save_futures {
|
for save_future in save_futures {
|
||||||
save_future.await?;
|
save_future.await?;
|
||||||
}
|
}
|
||||||
|
let env = env.await;
|
||||||
|
|
||||||
this.update(&mut cx, |this, _| {
|
this.update(&mut cx, |this, _| {
|
||||||
this.send_job(|git_repo| async move {
|
this.send_job(|git_repo| async move {
|
||||||
match git_repo {
|
match git_repo {
|
||||||
GitRepo::Local(repo) => repo.stage_paths(&entries),
|
GitRepo::Local(repo) => repo.stage_paths(&entries, &env),
|
||||||
GitRepo::Remote {
|
GitRepo::Remote {
|
||||||
project_id,
|
project_id,
|
||||||
client,
|
client,
|
||||||
|
@ -1288,6 +1316,7 @@ impl Repository {
|
||||||
if entries.is_empty() {
|
if entries.is_empty() {
|
||||||
return Task::ready(Ok(()));
|
return Task::ready(Ok(()));
|
||||||
}
|
}
|
||||||
|
let env = self.worktree_environment(cx);
|
||||||
|
|
||||||
let mut save_futures = Vec::new();
|
let mut save_futures = Vec::new();
|
||||||
if let Some(buffer_store) = self.buffer_store(cx) {
|
if let Some(buffer_store) = self.buffer_store(cx) {
|
||||||
|
@ -1314,11 +1343,12 @@ impl Repository {
|
||||||
for save_future in save_futures {
|
for save_future in save_futures {
|
||||||
save_future.await?;
|
save_future.await?;
|
||||||
}
|
}
|
||||||
|
let env = env.await;
|
||||||
|
|
||||||
this.update(&mut cx, |this, _| {
|
this.update(&mut cx, |this, _| {
|
||||||
this.send_job(|git_repo| async move {
|
this.send_job(|git_repo| async move {
|
||||||
match git_repo {
|
match git_repo {
|
||||||
GitRepo::Local(repo) => repo.unstage_paths(&entries),
|
GitRepo::Local(repo) => repo.unstage_paths(&entries, &env),
|
||||||
GitRepo::Remote {
|
GitRepo::Remote {
|
||||||
project_id,
|
project_id,
|
||||||
client,
|
client,
|
||||||
|
@ -1375,19 +1405,42 @@ impl Repository {
|
||||||
self.repository_entry.status_len()
|
self.repository_entry.status_len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn worktree_environment(
|
||||||
|
&self,
|
||||||
|
cx: &mut App,
|
||||||
|
) -> impl Future<Output = HashMap<String, String>> + 'static {
|
||||||
|
let task = self.project_environment.as_ref().and_then(|env| {
|
||||||
|
env.update(cx, |env, cx| {
|
||||||
|
env.get_environment(
|
||||||
|
Some(self.worktree_id),
|
||||||
|
Some(self.worktree_abs_path.clone()),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
});
|
||||||
|
async move { OptionFuture::from(task).await.flatten().unwrap_or_default() }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn commit(
|
pub fn commit(
|
||||||
&self,
|
&self,
|
||||||
message: SharedString,
|
message: SharedString,
|
||||||
name_and_email: Option<(SharedString, SharedString)>,
|
name_and_email: Option<(SharedString, SharedString)>,
|
||||||
|
cx: &mut App,
|
||||||
) -> oneshot::Receiver<Result<()>> {
|
) -> oneshot::Receiver<Result<()>> {
|
||||||
|
let env = self.worktree_environment(cx);
|
||||||
self.send_job(|git_repo| async move {
|
self.send_job(|git_repo| async move {
|
||||||
match git_repo {
|
match git_repo {
|
||||||
GitRepo::Local(repo) => repo.commit(
|
GitRepo::Local(repo) => {
|
||||||
message.as_ref(),
|
let env = env.await;
|
||||||
name_and_email
|
repo.commit(
|
||||||
.as_ref()
|
message.as_ref(),
|
||||||
.map(|(name, email)| (name.as_ref(), email.as_ref())),
|
name_and_email
|
||||||
),
|
.as_ref()
|
||||||
|
.map(|(name, email)| (name.as_ref(), email.as_ref())),
|
||||||
|
&env,
|
||||||
|
)
|
||||||
|
}
|
||||||
GitRepo::Remote {
|
GitRepo::Remote {
|
||||||
project_id,
|
project_id,
|
||||||
client,
|
client,
|
||||||
|
@ -1416,17 +1469,19 @@ impl Repository {
|
||||||
pub fn fetch(
|
pub fn fetch(
|
||||||
&mut self,
|
&mut self,
|
||||||
askpass: AskPassDelegate,
|
askpass: AskPassDelegate,
|
||||||
cx: &App,
|
cx: &mut App,
|
||||||
) -> oneshot::Receiver<Result<RemoteCommandOutput>> {
|
) -> oneshot::Receiver<Result<RemoteCommandOutput>> {
|
||||||
let executor = cx.background_executor().clone();
|
let executor = cx.background_executor().clone();
|
||||||
let askpass_delegates = self.askpass_delegates.clone();
|
let askpass_delegates = self.askpass_delegates.clone();
|
||||||
let askpass_id = util::post_inc(&mut self.latest_askpass_id);
|
let askpass_id = util::post_inc(&mut self.latest_askpass_id);
|
||||||
|
let env = self.worktree_environment(cx);
|
||||||
|
|
||||||
self.send_job(move |git_repo| async move {
|
self.send_job(move |git_repo| async move {
|
||||||
match git_repo {
|
match git_repo {
|
||||||
GitRepo::Local(git_repository) => {
|
GitRepo::Local(git_repository) => {
|
||||||
let askpass = AskPassSession::new(&executor, askpass).await?;
|
let askpass = AskPassSession::new(&executor, askpass).await?;
|
||||||
git_repository.fetch(askpass)
|
let env = env.await;
|
||||||
|
git_repository.fetch(askpass, &env)
|
||||||
}
|
}
|
||||||
GitRepo::Remote {
|
GitRepo::Remote {
|
||||||
project_id,
|
project_id,
|
||||||
|
@ -1465,17 +1520,19 @@ impl Repository {
|
||||||
remote: SharedString,
|
remote: SharedString,
|
||||||
options: Option<PushOptions>,
|
options: Option<PushOptions>,
|
||||||
askpass: AskPassDelegate,
|
askpass: AskPassDelegate,
|
||||||
cx: &App,
|
cx: &mut App,
|
||||||
) -> oneshot::Receiver<Result<RemoteCommandOutput>> {
|
) -> oneshot::Receiver<Result<RemoteCommandOutput>> {
|
||||||
let executor = cx.background_executor().clone();
|
let executor = cx.background_executor().clone();
|
||||||
let askpass_delegates = self.askpass_delegates.clone();
|
let askpass_delegates = self.askpass_delegates.clone();
|
||||||
let askpass_id = util::post_inc(&mut self.latest_askpass_id);
|
let askpass_id = util::post_inc(&mut self.latest_askpass_id);
|
||||||
|
let env = self.worktree_environment(cx);
|
||||||
|
|
||||||
self.send_job(move |git_repo| async move {
|
self.send_job(move |git_repo| async move {
|
||||||
match git_repo {
|
match git_repo {
|
||||||
GitRepo::Local(git_repository) => {
|
GitRepo::Local(git_repository) => {
|
||||||
|
let env = env.await;
|
||||||
let askpass = AskPassSession::new(&executor, askpass).await?;
|
let askpass = AskPassSession::new(&executor, askpass).await?;
|
||||||
git_repository.push(&branch, &remote, options, askpass)
|
git_repository.push(&branch, &remote, options, askpass, &env)
|
||||||
}
|
}
|
||||||
GitRepo::Remote {
|
GitRepo::Remote {
|
||||||
project_id,
|
project_id,
|
||||||
|
@ -1518,16 +1575,19 @@ impl Repository {
|
||||||
branch: SharedString,
|
branch: SharedString,
|
||||||
remote: SharedString,
|
remote: SharedString,
|
||||||
askpass: AskPassDelegate,
|
askpass: AskPassDelegate,
|
||||||
cx: &App,
|
cx: &mut App,
|
||||||
) -> oneshot::Receiver<Result<RemoteCommandOutput>> {
|
) -> oneshot::Receiver<Result<RemoteCommandOutput>> {
|
||||||
let executor = cx.background_executor().clone();
|
let executor = cx.background_executor().clone();
|
||||||
let askpass_delegates = self.askpass_delegates.clone();
|
let askpass_delegates = self.askpass_delegates.clone();
|
||||||
let askpass_id = util::post_inc(&mut self.latest_askpass_id);
|
let askpass_id = util::post_inc(&mut self.latest_askpass_id);
|
||||||
|
let env = self.worktree_environment(cx);
|
||||||
|
|
||||||
self.send_job(move |git_repo| async move {
|
self.send_job(move |git_repo| async move {
|
||||||
match git_repo {
|
match git_repo {
|
||||||
GitRepo::Local(git_repository) => {
|
GitRepo::Local(git_repository) => {
|
||||||
let askpass = AskPassSession::new(&executor, askpass).await?;
|
let askpass = AskPassSession::new(&executor, askpass).await?;
|
||||||
git_repository.pull(&branch, &remote, askpass)
|
let env = env.await;
|
||||||
|
git_repository.pull(&branch, &remote, askpass, &env)
|
||||||
}
|
}
|
||||||
GitRepo::Remote {
|
GitRepo::Remote {
|
||||||
project_id,
|
project_id,
|
||||||
|
@ -1565,13 +1625,16 @@ impl Repository {
|
||||||
&self,
|
&self,
|
||||||
path: &RepoPath,
|
path: &RepoPath,
|
||||||
content: Option<String>,
|
content: Option<String>,
|
||||||
|
cx: &mut App,
|
||||||
) -> oneshot::Receiver<anyhow::Result<()>> {
|
) -> oneshot::Receiver<anyhow::Result<()>> {
|
||||||
let path = path.clone();
|
let path = path.clone();
|
||||||
|
let env = self.worktree_environment(cx);
|
||||||
|
|
||||||
self.send_keyed_job(
|
self.send_keyed_job(
|
||||||
Some(GitJobKey::WriteIndex(path.clone())),
|
Some(GitJobKey::WriteIndex(path.clone())),
|
||||||
|git_repo| async move {
|
|git_repo| async move {
|
||||||
match git_repo {
|
match git_repo {
|
||||||
GitRepo::Local(repo) => repo.set_index_text(&path, content),
|
GitRepo::Local(repo) => repo.set_index_text(&path, content, &env.await),
|
||||||
GitRepo::Remote {
|
GitRepo::Remote {
|
||||||
project_id,
|
project_id,
|
||||||
client,
|
client,
|
||||||
|
|
|
@ -844,6 +844,7 @@ impl Project {
|
||||||
GitStore::new(
|
GitStore::new(
|
||||||
&worktree_store,
|
&worktree_store,
|
||||||
buffer_store.clone(),
|
buffer_store.clone(),
|
||||||
|
Some(environment.clone()),
|
||||||
client.clone().into(),
|
client.clone().into(),
|
||||||
None,
|
None,
|
||||||
cx,
|
cx,
|
||||||
|
@ -972,6 +973,7 @@ impl Project {
|
||||||
GitStore::new(
|
GitStore::new(
|
||||||
&worktree_store,
|
&worktree_store,
|
||||||
buffer_store.clone(),
|
buffer_store.clone(),
|
||||||
|
Some(environment.clone()),
|
||||||
ssh_proto.clone(),
|
ssh_proto.clone(),
|
||||||
Some(ProjectId(SSH_PROJECT_ID)),
|
Some(ProjectId(SSH_PROJECT_ID)),
|
||||||
cx,
|
cx,
|
||||||
|
@ -1179,6 +1181,7 @@ impl Project {
|
||||||
GitStore::new(
|
GitStore::new(
|
||||||
&worktree_store,
|
&worktree_store,
|
||||||
buffer_store.clone(),
|
buffer_store.clone(),
|
||||||
|
None,
|
||||||
client.clone().into(),
|
client.clone().into(),
|
||||||
Some(ProjectId(remote_id)),
|
Some(ProjectId(remote_id)),
|
||||||
cx,
|
cx,
|
||||||
|
|
|
@ -87,10 +87,12 @@ impl HeadlessProject {
|
||||||
buffer_store
|
buffer_store
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let environment = project::ProjectEnvironment::new(&worktree_store, None, cx);
|
||||||
let git_store = cx.new(|cx| {
|
let git_store = cx.new(|cx| {
|
||||||
GitStore::new(
|
GitStore::new(
|
||||||
&worktree_store,
|
&worktree_store,
|
||||||
buffer_store.clone(),
|
buffer_store.clone(),
|
||||||
|
Some(environment.clone()),
|
||||||
session.clone().into(),
|
session.clone().into(),
|
||||||
None,
|
None,
|
||||||
cx,
|
cx,
|
||||||
|
@ -105,7 +107,6 @@ impl HeadlessProject {
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let environment = project::ProjectEnvironment::new(&worktree_store, None, cx);
|
|
||||||
let toolchain_store = cx.new(|cx| {
|
let toolchain_store = cx.new(|cx| {
|
||||||
ToolchainStore::local(
|
ToolchainStore::local(
|
||||||
languages.clone(),
|
languages.clone(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue