Add undo_last_commit command (#769)

closes #758
This commit is contained in:
Emil Jaszczuk 2021-06-07 16:46:45 +02:00 committed by GitHub
parent 12b90715f9
commit b2b5a0faa0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 94 additions and 2 deletions

View file

@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
## Added
- undo-last-commit command under `[U]` key [[@remique](https://github.com/remique)] ([#758](https://github.com/extrawurst/gitui/issues/758))
## Fixed
- openssl vendoring broken on macos ([#772](https://github.com/extrawurst/gitui/issues/772))

View file

@ -149,6 +149,21 @@ pub fn stage_add_all(repo_path: &str, pattern: &str) -> Result<()> {
Ok(())
}
/// Undo last commit in repo
pub fn undo_last_commit(repo_path: &str) -> Result<()> {
let repo = repo(repo_path)?;
let previous_commit = repo.revparse_single("HEAD~")?;
Repository::reset(
&repo,
&previous_commit,
git2::ResetType::Soft,
None,
)?;
Ok(())
}
/// stage a removed file
pub fn stage_addremoved(repo_path: &str, path: &Path) -> Result<()> {
scope_time!("stage_addremoved");
@ -206,9 +221,11 @@ mod tests {
use super::*;
use crate::sync::{
commit,
diff::get_diff,
status::{get_status, StatusType},
tests::{
debug_cmd_print, get_statuses, repo_init, repo_init_empty,
debug_cmd_print, get_statuses, repo_init,
repo_init_empty, write_commit_file,
},
};
use std::{
@ -282,6 +299,43 @@ mod tests {
Ok(())
}
#[test]
fn test_undo_commit_empty_repo() {
let (_td, repo) = repo_init().unwrap();
let root = repo.path().parent().unwrap();
let repo_path = root.as_os_str().to_str().unwrap();
// expect to fail
assert!(undo_last_commit(repo_path).is_err());
}
#[test]
fn test_undo_commit() {
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 test.txt
let c1 =
write_commit_file(&repo, "test.txt", "content1", "c1");
let _c2 =
write_commit_file(&repo, "test.txt", "content2", "c2");
assert!(undo_last_commit(repo_path).is_ok());
// Make sure that HEAD points to c1
assert_eq!(c1, get_head_repo(&repo).unwrap());
// Make sure that now we have 1 file staged
assert_eq!(get_statuses(repo_path), (0, 1));
// And that file is test.txt
let diff = get_diff(repo_path, "test.txt", true).unwrap();
assert_eq!(
diff.hunks[0].lines[0].content,
String::from("@@ -1 +1 @@\n")
);
}
#[test]
fn test_not_staging_untracked_folder() -> Result<()> {
let (_td, repo) = repo_init().unwrap();

View file

@ -81,6 +81,7 @@ pub struct KeyConfig {
pub force_push: KeyEvent,
pub pull: KeyEvent,
pub abort_merge: KeyEvent,
pub undo_commit: KeyEvent,
}
#[rustfmt::skip]
@ -144,6 +145,7 @@ impl Default for KeyConfig {
select_tag: KeyEvent { code: KeyCode::Enter, modifiers: KeyModifiers::empty()},
push: KeyEvent { code: KeyCode::Char('p'), modifiers: KeyModifiers::empty()},
force_push: KeyEvent { code: KeyCode::Char('P'), modifiers: KeyModifiers::SHIFT},
undo_commit: KeyEvent { code: KeyCode::Char('U'), modifiers: KeyModifiers::SHIFT},
pull: KeyEvent { code: KeyCode::Char('f'), modifiers: KeyModifiers::empty()},
abort_merge: KeyEvent { code: KeyCode::Char('M'), modifiers: KeyModifiers::SHIFT},
open_file_tree: KeyEvent { code: KeyCode::Char('F'), modifiers: KeyModifiers::SHIFT},

View file

@ -579,6 +579,16 @@ pub mod commands {
CMD_GROUP_GENERAL,
)
}
pub fn undo_commit(key_config: &SharedKeyConfig) -> CommandText {
CommandText::new(
format!(
"Undo Commit [{}]",
key_config.get_hint(key_config.undo_commit),
),
"undo last commit",
CMD_GROUP_GENERAL,
)
}
pub fn commit_open(key_config: &SharedKeyConfig) -> CommandText {
CommandText::new(
format!(

View file

@ -7,7 +7,7 @@ use crate::{
FileTreeItemKind,
},
keys::SharedKeyConfig,
queue::{Action, InternalEvent, Queue, ResetItem},
queue::{Action, InternalEvent, NeedsUpdate, Queue, ResetItem},
strings, try_or_popup,
ui::style::SharedTheme,
};
@ -468,6 +468,14 @@ impl Status {
}
}
fn undo_last_commit(&self) {
try_or_popup!(
self,
"undo commit failed:",
sync::utils::undo_last_commit(CWD)
);
}
fn branch_compare(&mut self) {
self.git_branch_state =
self.git_branch_name.last().and_then(|branch| {
@ -579,6 +587,12 @@ impl Component for Status {
!focus_on_diff,
));
out.push(CommandInfo::new(
strings::commands::undo_commit(&self.key_config),
true,
!focus_on_diff,
));
out.push(CommandInfo::new(
strings::commands::abort_merge(&self.key_config),
true,
@ -687,6 +701,14 @@ impl Component for Status {
{
self.pull();
Ok(EventState::Consumed)
} else if k == self.key_config.undo_commit
&& !self.is_focus_on_diff()
{
self.undo_last_commit();
self.queue.borrow_mut().push_back(
InternalEvent::Update(NeedsUpdate::ALL),
);
Ok(EventState::Consumed)
} else if k == self.key_config.abort_merge
&& Self::can_abort_merge()
{

View file

@ -34,6 +34,7 @@
// Also just plain text characters will not work because the commit
// msg editor will interpret them as text input
open_commit_editor: ( code: Char('e'), modifiers: ( bits: 2,),),
undo_commit: ( code: Char('U'), modifiers: ( bits: 1,),),
move_left: ( code: Char('h'), modifiers: ( bits: 0,),),
move_right: ( code: Char('l'), modifiers: ( bits: 0,),),