From a34bab22fa3b84c78a8784fa5c85dbc2d3c6ebed Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Thu, 2 Jul 2020 12:55:17 +0200 Subject: [PATCH] show untracked files in stash commit details (closes #130) --- CHANGELOG.md | 1 + asyncgit/src/sync/commit_files.rs | 66 +++++++++++++++++++------------ 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a639efe802..3d922bf375 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - diisplay non-utf8 commit messages at least partially ([#150](https://github.com/extrawurst/gitui/issues/150)) - hooks ignored when running `gitui` in subfolder of workdir ([#151](https://github.com/extrawurst/gitui/issues/151)) - better scrolling in file-trees [[@tisorlawan](https://github.com/tisorlawan)] ([#144](https://github.com/extrawurst/gitui/issues/144)) +- show untracked files in stash commit details [[@MCord](https://github.com/MCord)] ([#130](https://github.com/extrawurst/gitui/issues/130)) - some optimizations in reflog ## [0.7.0] - 2020-06-15 diff --git a/asyncgit/src/sync/commit_files.rs b/asyncgit/src/sync/commit_files.rs index 2f46d8e852..e643ebd1a1 100644 --- a/asyncgit/src/sync/commit_files.rs +++ b/asyncgit/src/sync/commit_files.rs @@ -1,5 +1,5 @@ use super::{stash::is_stash_commit, utils::repo, CommitId}; -use crate::{error::Result, StatusItem, StatusItemType, CWD}; +use crate::{error::Result, StatusItem, StatusItemType}; use git2::{Diff, DiffDelta, DiffOptions, Repository}; use scopetime::scope_time; @@ -33,22 +33,6 @@ pub fn get_commit_files( None, )?; - // stash commits have parent commits containing untracked files and if we want to show - // these files as if they were actually in the stash commit we have to have some specific - // handling regarding these special stash commits. - // more info can be found at https://stackoverflow.com/questions/51275777/why-does-git-stash-pop-say-that-it-could-not-restore-untracked-files-from-stash/51276389#51276389 - if is_stash_commit(repo_path, &id)? { - let commit = repo.find_commit(id.into())?; - let untracked_commit = commit.parent_id(2)?; - - let mut untracked_files = get_commit_files( - repo_path, - CommitId::new(untracked_commit), - )?; - - res.append(&mut untracked_files); - } - Ok(res) } @@ -75,20 +59,25 @@ pub(crate) fn get_commit_diff( opts }); - let diff = repo.diff_tree_to_tree( + let mut diff = repo.diff_tree_to_tree( parent.as_ref(), Some(&commit_tree), opt.as_mut(), )?; - if diff.deltas().len() == 0 && is_stash_commit(CWD, &id)? { + if is_stash_commit( + repo.path().to_str().expect("repo path utf8 err"), + &id, + )? { let untracked_commit = commit.parent_id(2)?; - return get_commit_diff( + let untracked_diff = get_commit_diff( repo, CommitId::new(untracked_commit), pathspec, - ); + )?; + + diff.merge(&untracked_diff)?; } Ok(diff) @@ -100,7 +89,8 @@ mod tests { use crate::{ error::Result, sync::{ - commit, stage_add_file, stash_save, tests::repo_init, + commit, stage_add_file, stash_save, + tests::{get_statuses, repo_init}, }, StatusItemType, }; @@ -140,9 +130,6 @@ mod tests { let id = stash_save(repo_path, None, true, false)?; - //TODO: https://github.com/extrawurst/gitui/issues/130 - // `get_commit_diff` actually needs to merge the regular diff - // and a third parent diff containing the untracked files let diff = get_commit_files(repo_path, id)?; assert_eq!(diff.len(), 1); @@ -150,4 +137,33 @@ mod tests { Ok(()) } + + #[test] + fn test_stashed_untracked_and_modified() -> Result<()> { + let file_path1 = Path::new("file1.txt"); + let file_path2 = Path::new("file2.txt"); + let (_td, repo) = repo_init()?; + let root = repo.path().parent().unwrap(); + let repo_path = root.as_os_str().to_str().unwrap(); + + File::create(&root.join(file_path1))?.write_all(b"test")?; + stage_add_file(repo_path, file_path1)?; + commit(repo_path, "c1")?; + + File::create(&root.join(file_path1))? + .write_all(b"modified")?; + File::create(&root.join(file_path2))?.write_all(b"new")?; + + assert_eq!(get_statuses(repo_path), (2, 0)); + + let id = stash_save(repo_path, None, true, false)?; + + let diff = get_commit_files(repo_path, id)?; + + assert_eq!(diff.len(), 2); + assert_eq!(diff[0].status, StatusItemType::Modified); + assert_eq!(diff[1].status, StatusItemType::New); + + Ok(()) + } }