From 9301574624db9bdcf048c286d32f77531f7aa3db Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Fri, 12 Jun 2020 11:46:45 +0200 Subject: [PATCH] fix reset file when running gitui in subfolder (closes #118) --- CHANGELOG.md | 3 +++ asyncgit/src/sync/reset.rs | 35 +++++++++++++++++++++++++++++++++-- src/app.rs | 2 +- src/tabs/status.rs | 22 +++++++++++++++++----- 4 files changed, 54 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff23319f..37d1ae1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - file trees: `arrow-right` on expanded folder moves down into folder +### Fixed +- reset file inside folder failed when running `gitui` in a subfolder too ([#118](https://github.com/extrawurst/gitui/issues/118)) + ## [0.6.0] - 2020-06-09 ![](assets/commit-details.gif) diff --git a/asyncgit/src/sync/reset.rs b/asyncgit/src/sync/reset.rs index 7f04082d..20ce9734 100644 --- a/asyncgit/src/sync/reset.rs +++ b/asyncgit/src/sync/reset.rs @@ -1,4 +1,4 @@ -use super::utils::repo; +use super::utils::{repo, work_dir}; use crate::error::{Error, Result}; use git2::{build::CheckoutBuilder, ObjectType, Status}; use scopetime::scope_time; @@ -37,6 +37,8 @@ pub fn reset_workdir_file(repo_path: &str, path: &str) -> Result<()> { let repo = repo(repo_path)?; + let workdir = work_dir(&repo); + // Note: early out for removing untracked files, due to bug in checkout_head code: // see https://github.com/libgit2/libgit2/issues/5089 let status = repo.status_file(Path::new(path))?; @@ -44,7 +46,7 @@ pub fn reset_workdir_file(repo_path: &str, path: &str) -> Result<()> { if status == Status::WT_NEW || (status == Status::WT_MODIFIED | Status::INDEX_NEW) { - fs::remove_file(Path::new(repo_path).join(path))?; + fs::remove_file(Path::new(workdir).join(path))?; }; if status == Status::WT_NEW { @@ -303,4 +305,33 @@ mod tests { assert_eq!(get_statuses(repo_path), (1, 0)); } + + #[test] + fn test_reset_untracked_in_subdir_with_cwd_in_subdir() { + let (_td, repo) = repo_init().unwrap(); + let root = repo.path().parent().unwrap(); + let repo_path = root.as_os_str().to_str().unwrap(); + + { + fs::create_dir(&root.join("foo")).unwrap(); + File::create(&root.join("foo/bar.txt")) + .unwrap() + .write_all(b"test\nfoo") + .unwrap(); + } + + debug_cmd_print(repo_path, "git status"); + + assert_eq!(get_statuses(repo_path), (1, 0)); + + reset_workdir_file( + &root.join("foo").as_os_str().to_str().unwrap(), + "foo/bar.txt", + ) + .unwrap(); + + debug_cmd_print(repo_path, "git status"); + + assert_eq!(get_statuses(repo_path), (0, 0)); + } } diff --git a/src/app.rs b/src/app.rs index 0e42cdab..61463520 100644 --- a/src/app.rs +++ b/src/app.rs @@ -325,7 +325,7 @@ impl App { match ev { InternalEvent::ConfirmedAction(action) => match action { Action::Reset(r) => { - if Status::reset(&r) { + if self.status_tab.reset(&r) { flags.insert(NeedsUpdate::ALL); } } diff --git a/src/tabs/status.rs b/src/tabs/status.rs index f24bf4f7..a8c3c890 100644 --- a/src/tabs/status.rs +++ b/src/tabs/status.rs @@ -6,7 +6,7 @@ use crate::{ FileTreeItemKind, }, keys, - queue::{Queue, ResetItem}, + queue::{InternalEvent, Queue, ResetItem}, strings, ui::style::Theme, }; @@ -47,6 +47,7 @@ pub struct Status { git_diff: AsyncDiff, git_status_workdir: AsyncStatus, git_status_stage: AsyncStatus, + queue: Queue, } impl DrawableComponent for Status { @@ -109,6 +110,7 @@ impl Status { theme: &Theme, ) -> Self { Self { + queue: queue.clone(), visible: true, focus: Focus::WorkDir, diff_target: DiffTarget::WorkingDir, @@ -280,13 +282,23 @@ impl Status { } /// called after confirmation - pub fn reset(item: &ResetItem) -> bool { - if item.is_folder { + pub fn reset(&mut self, item: &ResetItem) -> bool { + let res = if item.is_folder { sync::reset_workdir_folder(CWD, item.path.as_str()) - .is_ok() } else { - sync::reset_workdir_file(CWD, item.path.as_str()).is_ok() + sync::reset_workdir_file(CWD, item.path.as_str()) + }; + + if let Err(e) = &res { + self.queue.borrow_mut().push_back( + InternalEvent::ShowErrorMsg(format!( + "reset failed:\n{}", + e + )), + ); } + + res.is_ok() } }