Git uncommit warning (#25977)
Adds a prompt when clicking the uncommit button when the current commit is already present on a remote branch:  Release Notes: - N/A --------- Co-authored-by: Conrad <conrad@zed.dev>
This commit is contained in:
parent
0200dda83d
commit
e505d6bf5b
6 changed files with 171 additions and 19 deletions
|
@ -202,8 +202,12 @@ pub trait GitRepository: Send + Sync {
|
|||
options: Option<PushOptions>,
|
||||
) -> Result<RemoteCommandOutput>;
|
||||
fn pull(&self, branch_name: &str, upstream_name: &str) -> Result<RemoteCommandOutput>;
|
||||
fn get_remotes(&self, branch_name: Option<&str>) -> Result<Vec<Remote>>;
|
||||
fn fetch(&self) -> Result<RemoteCommandOutput>;
|
||||
|
||||
fn get_remotes(&self, branch_name: Option<&str>) -> Result<Vec<Remote>>;
|
||||
|
||||
/// returns a list of remote branches that contain HEAD
|
||||
fn check_for_pushed_commit(&self) -> Result<Vec<SharedString>>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, JsonSchema)]
|
||||
|
@ -781,6 +785,54 @@ impl GitRepository for RealGitRepository {
|
|||
));
|
||||
}
|
||||
}
|
||||
|
||||
fn check_for_pushed_commit(&self) -> Result<Vec<SharedString>> {
|
||||
let working_directory = self.working_directory()?;
|
||||
let git_cmd = |args: &[&str]| -> Result<String> {
|
||||
let output = new_std_command(&self.git_binary_path)
|
||||
.current_dir(&working_directory)
|
||||
.args(args)
|
||||
.output()?;
|
||||
if output.status.success() {
|
||||
Ok(String::from_utf8(output.stdout)?)
|
||||
} else {
|
||||
Err(anyhow!(String::from_utf8_lossy(&output.stderr).to_string()))
|
||||
}
|
||||
};
|
||||
|
||||
let head = git_cmd(&["rev-parse", "HEAD"])
|
||||
.context("Failed to get HEAD")?
|
||||
.trim()
|
||||
.to_owned();
|
||||
|
||||
let mut remote_branches = vec![];
|
||||
let mut add_if_matching = |remote_head: &str| {
|
||||
if let Ok(merge_base) = git_cmd(&["merge-base", &head, remote_head]) {
|
||||
if merge_base.trim() == head {
|
||||
if let Some(s) = remote_head.strip_prefix("refs/remotes/") {
|
||||
remote_branches.push(s.to_owned().into());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// check the main branch of each remote
|
||||
let remotes = git_cmd(&["remote"]).context("Failed to get remotes")?;
|
||||
for remote in remotes.lines() {
|
||||
if let Ok(remote_head) =
|
||||
git_cmd(&["symbolic-ref", &format!("refs/remotes/{remote}/HEAD")])
|
||||
{
|
||||
add_if_matching(remote_head.trim());
|
||||
}
|
||||
}
|
||||
|
||||
// ... and the remote branch that the checked-out one is tracking
|
||||
if let Ok(remote_head) = git_cmd(&["rev-parse", "--symbolic-full-name", "@{u}"]) {
|
||||
add_if_matching(remote_head.trim());
|
||||
}
|
||||
|
||||
Ok(remote_branches)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
|
@ -998,6 +1050,10 @@ impl GitRepository for FakeGitRepository {
|
|||
fn get_remotes(&self, _branch: Option<&str>) -> Result<Vec<Remote>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn check_for_pushed_commit(&self) -> Result<Vec<SharedString>> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
fn check_path_to_repo_path_errors(relative_file_path: &Path) -> Result<()> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue