Fix 576 stash apply conflicts (#578)

* unittest that applying with conflicts errors out and prepare for stash apply to allow creating conflicts for later
* mark conflicting items
This commit is contained in:
Stephan Dilly 2021-03-09 14:14:16 +01:00 committed by GitHub
parent cfd5c6ad03
commit c79b3d74fa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 87 additions and 4 deletions

View file

@ -1,6 +1,9 @@
use super::{utils::repo, CommitId};
use crate::error::{Error, Result};
use git2::{Oid, Repository, StashFlags};
use git2::{
build::CheckoutBuilder, Oid, Repository, StashApplyOptions,
StashFlags,
};
use scopetime::scope_time;
///
@ -45,6 +48,7 @@ pub fn stash_drop(repo_path: &str, stash_id: CommitId) -> Result<()> {
pub fn stash_apply(
repo_path: &str,
stash_id: CommitId,
allow_conflicts: bool,
) -> Result<()> {
scope_time!("stash_apply");
@ -52,7 +56,12 @@ pub fn stash_apply(
let index = get_stash_index(&mut repo, stash_id.get_oid())?;
repo.stash_apply(index, None)?;
let mut checkout = CheckoutBuilder::new();
checkout.allow_conflicts(allow_conflicts);
let mut opt = StashApplyOptions::default();
opt.checkout_options(checkout);
repo.stash_apply(index, Some(&mut opt))?;
Ok(())
}
@ -109,7 +118,11 @@ mod tests {
use super::*;
use crate::sync::{
commit, get_commit_files, get_commits_info, stage_add_file,
tests::{debug_cmd_print, get_statuses, repo_init},
staging::repo_write_file,
tests::{
debug_cmd_print, get_statuses, repo_init,
write_commit_file,
},
};
use std::{fs::File, io::Write, path::Path};
@ -211,4 +224,66 @@ mod tests {
Ok(())
}
#[test]
fn test_stash_apply_conflict() {
let (_td, repo) = repo_init().unwrap();
let root = repo.path().parent().unwrap();
let repo_path = root.as_os_str().to_str().unwrap();
repo_write_file(&repo, "test.txt", "test").unwrap();
let id =
stash_save(repo_path, Some("foo"), true, false).unwrap();
repo_write_file(&repo, "test.txt", "foo").unwrap();
let res = stash_apply(repo_path, id, false);
assert!(res.is_err());
}
#[test]
fn test_stash_apply_conflict2() {
let (_td, repo) = repo_init().unwrap();
let root = repo.path().parent().unwrap();
let repo_path = root.as_os_str().to_str().unwrap();
write_commit_file(&repo, "test.txt", "test", "c1");
repo_write_file(&repo, "test.txt", "test2").unwrap();
let id =
stash_save(repo_path, Some("foo"), true, false).unwrap();
repo_write_file(&repo, "test.txt", "test3").unwrap();
let res = stash_apply(repo_path, id, false);
assert!(res.is_err());
}
#[test]
fn test_stash_apply_creating_conflict() {
let (_td, repo) = repo_init().unwrap();
let root = repo.path().parent().unwrap();
let repo_path = root.as_os_str().to_str().unwrap();
write_commit_file(&repo, "test.txt", "test", "c1");
repo_write_file(&repo, "test.txt", "test2").unwrap();
let id =
stash_save(repo_path, Some("foo"), true, false).unwrap();
repo_write_file(&repo, "test.txt", "test3").unwrap();
let res = stash_apply(repo_path, id, false);
assert!(res.is_err());
let res = stash_apply(repo_path, id, true);
assert!(res.is_ok());
}
}

View file

@ -18,6 +18,8 @@ pub enum StatusItemType {
Renamed,
///
Typechange,
///
Conflicted,
}
impl From<Status> for StatusItemType {
@ -30,6 +32,8 @@ impl From<Status> for StatusItemType {
Self::Renamed
} else if s.is_index_typechange() || s.is_wt_typechange() {
Self::Typechange
} else if s.is_conflicted() {
Self::Conflicted
} else {
Self::Modified
}

View file

@ -142,6 +142,7 @@ impl FileTreeComponent {
StatusItemType::Deleted => '-',
StatusItemType::Renamed => 'R',
StatusItemType::Typechange => ' ',
StatusItemType::Conflicted => '!',
}
}

View file

@ -57,7 +57,7 @@ impl StashList {
fn apply_stash(&mut self) {
if let Some(e) = self.list.selected_entry() {
match sync::stash_apply(CWD, e.id) {
match sync::stash_apply(CWD, e.id, false) {
Ok(_) => {
self.queue
.borrow_mut()

View file

@ -135,6 +135,9 @@ impl Theme {
StatusItemType::Renamed => {
Style::default().fg(self.diff_file_moved)
}
StatusItemType::Conflicted => Style::default()
.fg(self.diff_file_modified)
.add_modifier(Modifier::BOLD),
StatusItemType::Typechange => Style::default(),
};