diff --git a/README.md b/README.md index 7e9bb6b5..4fcd6084 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ GITUI_LOGGING=true gitui # todo for 0.1 (first release) +* [ ] fix crashes on empty git repos (unstaging,committing?) * [ ] (un)staging selected hunks * [ ] publish as homebrew-tap diff --git a/asyncgit/src/sync/diff.rs b/asyncgit/src/sync/diff.rs index 19096f31..c8664c92 100644 --- a/asyncgit/src/sync/diff.rs +++ b/asyncgit/src/sync/diff.rs @@ -74,16 +74,24 @@ pub fn get_diff(repo_path: &str, p: String, stage: bool) -> Diff { let diff = if stage { // diff against head - let ref_head = repo.head().unwrap(); - let parent = - repo.find_commit(ref_head.target().unwrap()).unwrap(); - let tree = parent.tree().unwrap(); - repo.diff_tree_to_index( - Some(&tree), - Some(&repo.index().unwrap()), - Some(&mut opt), - ) - .unwrap() + if let Ok(ref_head) = repo.head() { + let parent = + repo.find_commit(ref_head.target().unwrap()).unwrap(); + let tree = parent.tree().unwrap(); + repo.diff_tree_to_index( + Some(&tree), + Some(&repo.index().unwrap()), + Some(&mut opt), + ) + .unwrap() + } else { + repo.diff_tree_to_index( + None, + Some(&repo.index().unwrap()), + Some(&mut opt), + ) + .unwrap() + } } else { opt.include_untracked(true); opt.recurse_untracked_dirs(true); @@ -206,7 +214,7 @@ mod tests { use crate::sync::{ stage_add, status::{get_status, StatusType}, - tests::repo_init, + tests::{repo_init, repo_init_empty}, }; use std::{ fs::{self, File}, @@ -239,6 +247,32 @@ mod tests { assert_eq!(diff.0[0].0[1].content, "test\n"); } + #[test] + fn test_empty_repo() { + let file_path = Path::new("foo.txt"); + let (_td, repo) = repo_init_empty(); + let root = repo.path().parent().unwrap(); + let repo_path = root.as_os_str().to_str().unwrap(); + + let res = get_status(repo_path, StatusType::WorkingDir); + assert_eq!(res.len(), 0); + + File::create(&root.join(file_path)) + .unwrap() + .write_all(b"test\nfoo") + .unwrap(); + + assert_eq!(stage_add(repo_path, file_path), true); + + let diff = get_diff( + repo_path, + String::from(file_path.to_str().unwrap()), + true, + ); + + assert_eq!(diff.0.len(), 1); + } + static HUNK_A: &str = r" 1 start 2 diff --git a/asyncgit/src/sync/mod.rs b/asyncgit/src/sync/mod.rs index e1783183..c1779406 100644 --- a/asyncgit/src/sync/mod.rs +++ b/asyncgit/src/sync/mod.rs @@ -14,6 +14,18 @@ mod tests { use std::process::Command; use tempfile::TempDir; + /// + pub fn repo_init_empty() -> (TempDir, Repository) { + let td = TempDir::new().unwrap(); + let repo = Repository::init(td.path()).unwrap(); + { + let mut config = repo.config().unwrap(); + config.set_str("user.name", "name").unwrap(); + config.set_str("user.email", "email").unwrap(); + } + (td, repo) + } + pub fn repo_init() -> (TempDir, Repository) { let td = TempDir::new().unwrap(); let repo = Repository::init(td.path()).unwrap();