diff --git a/asyncgit/src/sync/stash.rs b/asyncgit/src/sync/stash.rs index fbd268f0cc..f4c6dd3aa0 100644 --- a/asyncgit/src/sync/stash.rs +++ b/asyncgit/src/sync/stash.rs @@ -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()); + } } diff --git a/asyncgit/src/sync/status.rs b/asyncgit/src/sync/status.rs index 0e7343e403..891079d6e0 100644 --- a/asyncgit/src/sync/status.rs +++ b/asyncgit/src/sync/status.rs @@ -18,6 +18,8 @@ pub enum StatusItemType { Renamed, /// Typechange, + /// + Conflicted, } impl From for StatusItemType { @@ -30,6 +32,8 @@ impl From 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 } diff --git a/src/components/filetree.rs b/src/components/filetree.rs index fb2f423d89..e1bd3f23be 100644 --- a/src/components/filetree.rs +++ b/src/components/filetree.rs @@ -142,6 +142,7 @@ impl FileTreeComponent { StatusItemType::Deleted => '-', StatusItemType::Renamed => 'R', StatusItemType::Typechange => ' ', + StatusItemType::Conflicted => '!', } } diff --git a/src/tabs/stashlist.rs b/src/tabs/stashlist.rs index 98f6c0139a..5d7e12967e 100644 --- a/src/tabs/stashlist.rs +++ b/src/tabs/stashlist.rs @@ -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() diff --git a/src/ui/style.rs b/src/ui/style.rs index 52ec05d6bf..2a2aa34556 100644 --- a/src/ui/style.rs +++ b/src/ui/style.rs @@ -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(), };