fixed issue with utracked files.

This commit is contained in:
Mehran Kordi 2020-07-02 10:04:26 +02:00 committed by Stephan Dilly
parent dd459ecb8a
commit ea244b8cfa
2 changed files with 51 additions and 16 deletions

View file

@ -1,5 +1,5 @@
use super::{utils::repo, CommitId};
use crate::{error::Result, StatusItem, StatusItemType};
use super::{stash::is_stash_commit, utils::repo, CommitId};
use crate::{error::Result, StatusItem, StatusItemType, CWD};
use git2::{Diff, DiffDelta, DiffOptions, Repository};
use scopetime::scope_time;
@ -33,6 +33,22 @@ 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)
}
@ -52,7 +68,7 @@ pub(crate) fn get_commit_diff(
None
};
let mut opt = pathspec.map(|p| {
let mut opt = pathspec.clone().map(|p| {
let mut opts = DiffOptions::new();
opts.pathspec(p);
opts.show_binary(true);
@ -65,6 +81,16 @@ pub(crate) fn get_commit_diff(
opt.as_mut(),
)?;
if diff.deltas().len() == 0 && is_stash_commit(CWD, &id)? {
let untracked_commit = commit.parent_id(2)?;
return get_commit_diff(
repo,
CommitId::new(untracked_commit),
(&pathspec).clone(),
);
}
Ok(diff)
}
@ -81,31 +107,31 @@ mod tests {
use std::{fs::File, io::Write, path::Path};
#[test]
fn test_smoke() {
fn test_smoke() -> Result<()> {
let file_path = Path::new("file1.txt");
let (_td, repo) = repo_init().unwrap();
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_path))
.unwrap()
.write_all(b"test file1 content")
.unwrap();
File::create(&root.join(file_path))?
.write_all(b"test file1 content")?;
stage_add_file(repo_path, file_path).unwrap();
stage_add_file(repo_path, file_path)?;
let id = commit(repo_path, "commit msg").unwrap();
let id = commit(repo_path, "commit msg")?;
let diff = get_commit_files(repo_path, id).unwrap();
let diff = get_commit_files(repo_path, id)?;
assert_eq!(diff.len(), 1);
assert_eq!(diff[0].status, StatusItemType::New);
Ok(())
}
#[test]
fn test_stashed_untracked() -> Result<()> {
let file_path = Path::new("file1.txt");
let (_td, repo) = repo_init().unwrap();
let (_td, repo) = repo_init()?;
let root = repo.path().parent().unwrap();
let repo_path = root.as_os_str().to_str().unwrap();
@ -117,10 +143,10 @@ mod tests {
//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)?;
let diff = get_commit_files(repo_path, id)?;
// assert_eq!(diff.len(), 1);
// assert_eq!(diff[0].status, StatusItemType::New);
assert_eq!(diff.len(), 1);
assert_eq!(diff[0].status, StatusItemType::New);
Ok(())
}

View file

@ -19,6 +19,15 @@ pub fn get_stashes(repo_path: &str) -> Result<Vec<CommitId>> {
Ok(list)
}
/// checks whether a given commit is a stash commit.
pub fn is_stash_commit(
repo_path: &str,
id: &CommitId,
) -> Result<bool> {
let stashes = get_stashes(repo_path)?;
Ok(stashes.contains(&id))
}
///
pub fn stash_drop(repo_path: &str, stash_id: CommitId) -> Result<()> {
scope_time!("stash_drop");