mirror of
https://github.com/gitui-org/gitui
synced 2026-05-23 00:48:35 +00:00
Add pop stash command on Staches tab
This commit is contained in:
parent
1d90219df9
commit
79a38a70b9
10 changed files with 181 additions and 7 deletions
|
|
@ -59,6 +59,7 @@
|
|||
stashing_toggle_untracked: ( code: Char('u'), modifiers: ( bits: 0,),),
|
||||
stashing_toggle_index: ( code: Char('m'), modifiers: ( bits: 0,),),
|
||||
|
||||
stash_apply: ( code: Char('a'), modifiers: ( bits: 0,),),
|
||||
stash_open: ( code: Char('l'), modifiers: ( bits: 0,),),
|
||||
stash_drop: ( code: Char('D'), modifiers: ( bits: 1,),),
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,9 @@ pub use remotes::{
|
|||
};
|
||||
pub use reset::{reset_stage, reset_workdir};
|
||||
pub use staging::{discard_lines, stage_lines};
|
||||
pub use stash::{get_stashes, stash_apply, stash_drop, stash_save};
|
||||
pub use stash::{
|
||||
get_stashes, stash_apply, stash_drop, stash_pop, stash_save,
|
||||
};
|
||||
pub use state::{repo_state, RepoState};
|
||||
pub use tags::{get_tags, CommitTags, Tags};
|
||||
pub use utils::{
|
||||
|
|
|
|||
|
|
@ -44,6 +44,19 @@ pub fn stash_drop(repo_path: &str, stash_id: CommitId) -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
///
|
||||
pub fn stash_pop(repo_path: &str, stash_id: CommitId) -> Result<()> {
|
||||
scope_time!("stash_pop");
|
||||
|
||||
let mut repo = repo(repo_path)?;
|
||||
|
||||
let index = get_stash_index(&mut repo, stash_id.into())?;
|
||||
|
||||
repo.stash_pop(index, None)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
///
|
||||
pub fn stash_apply(
|
||||
repo_path: &str,
|
||||
|
|
@ -122,7 +135,7 @@ mod tests {
|
|||
debug_cmd_print, get_statuses, repo_init,
|
||||
write_commit_file,
|
||||
},
|
||||
utils::repo_write_file,
|
||||
utils::{repo_read_file, repo_write_file},
|
||||
};
|
||||
use std::{fs::File, io::Write, path::Path};
|
||||
|
||||
|
|
@ -286,4 +299,72 @@ mod tests {
|
|||
|
||||
assert!(res.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stash_pop_no_conflict() {
|
||||
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(&repo, "test.txt", "test", "c1");
|
||||
|
||||
repo_write_file(&repo, "test.txt", "test2").unwrap();
|
||||
|
||||
let id =
|
||||
stash_save(repo_path, Some("foo"), true, false).unwrap();
|
||||
|
||||
let res = stash_pop(repo_path, id);
|
||||
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(
|
||||
repo_read_file(&repo, "test.txt").unwrap(),
|
||||
"test2"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stash_pop_conflict() {
|
||||
let (_td, repo) = repo_init().unwrap();
|
||||
let root = repo.path().parent().unwrap();
|
||||
let repo_path = root.as_os_str().to_str().unwrap();
|
||||
|
||||
repo_write_file(&repo, "test.txt", "test").unwrap();
|
||||
|
||||
let id =
|
||||
stash_save(repo_path, Some("foo"), true, false).unwrap();
|
||||
|
||||
repo_write_file(&repo, "test.txt", "test2").unwrap();
|
||||
|
||||
let res = stash_pop(repo_path, id);
|
||||
|
||||
assert!(res.is_err());
|
||||
assert_eq!(
|
||||
repo_read_file(&repo, "test.txt").unwrap(),
|
||||
"test2"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stash_pop_conflict_after_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(&repo, "test.txt", "test", "c1");
|
||||
|
||||
repo_write_file(&repo, "test.txt", "test2").unwrap();
|
||||
|
||||
let id =
|
||||
stash_save(repo_path, Some("foo"), true, false).unwrap();
|
||||
|
||||
repo_write_file(&repo, "test.txt", "test3").unwrap();
|
||||
|
||||
let res = stash_pop(repo_path, id);
|
||||
|
||||
assert!(res.is_err());
|
||||
assert_eq!(
|
||||
repo_read_file(&repo, "test.txt").unwrap(),
|
||||
"test3"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,6 +187,25 @@ pub(crate) fn repo_write_file(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn repo_read_file(
|
||||
repo: &Repository,
|
||||
file: &str,
|
||||
) -> Result<String> {
|
||||
use std::io::Read;
|
||||
|
||||
let dir = work_dir(repo)?.join(file);
|
||||
let file_path = dir.to_str().ok_or_else(|| {
|
||||
Error::Generic(String::from("invalid file path"))
|
||||
})?;
|
||||
|
||||
let mut file = File::open(file_path)?;
|
||||
let mut buffer = Vec::new();
|
||||
file.read_to_end(&mut buffer)?;
|
||||
|
||||
Ok(String::from_utf8(buffer)?)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
|||
|
|
@ -494,8 +494,8 @@ impl App {
|
|||
flags.insert(NeedsUpdate::ALL);
|
||||
}
|
||||
}
|
||||
Action::StashDrop(s) => {
|
||||
if StashList::drop(s) {
|
||||
Action::StashDrop(_) | Action::StashPop(_) => {
|
||||
if self.stashlist_tab.action_confirmed(&action) {
|
||||
flags.insert(NeedsUpdate::ALL);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,6 +147,10 @@ impl ResetComponent {
|
|||
),
|
||||
strings::confirm_msg_stashdrop(&self.key_config),
|
||||
),
|
||||
Action::StashPop(_) => (
|
||||
strings::confirm_title_stashpop(&self.key_config),
|
||||
strings::confirm_msg_stashpop(&self.key_config),
|
||||
),
|
||||
Action::ResetHunk(_, _) => (
|
||||
strings::confirm_title_reset(&self.key_config),
|
||||
strings::confirm_msg_resethunk(&self.key_config),
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ pub struct KeyConfig {
|
|||
pub stashing_save: KeyEvent,
|
||||
pub stashing_toggle_untracked: KeyEvent,
|
||||
pub stashing_toggle_index: KeyEvent,
|
||||
pub stash_apply: KeyEvent,
|
||||
pub stash_open: KeyEvent,
|
||||
pub stash_drop: KeyEvent,
|
||||
pub cmd_bar_toggle: KeyEvent,
|
||||
|
|
@ -112,6 +113,7 @@ impl Default for KeyConfig {
|
|||
stashing_save: KeyEvent { code: KeyCode::Char('s'), modifiers: KeyModifiers::empty()},
|
||||
stashing_toggle_untracked: KeyEvent { code: KeyCode::Char('u'), modifiers: KeyModifiers::empty()},
|
||||
stashing_toggle_index: KeyEvent { code: KeyCode::Char('i'), modifiers: KeyModifiers::empty()},
|
||||
stash_apply: KeyEvent { code: KeyCode::Char('a'), modifiers: KeyModifiers::empty()},
|
||||
stash_open: KeyEvent { code: KeyCode::Right, modifiers: KeyModifiers::empty()},
|
||||
stash_drop: KeyEvent { code: KeyCode::Char('D'), modifiers: KeyModifiers::SHIFT},
|
||||
cmd_bar_toggle: KeyEvent { code: KeyCode::Char('.'), modifiers: KeyModifiers::empty()},
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ pub enum Action {
|
|||
ResetHunk(String, u64),
|
||||
ResetLines(String, Vec<DiffLinePosition>),
|
||||
StashDrop(CommitId),
|
||||
StashPop(CommitId),
|
||||
DeleteBranch(String),
|
||||
ForcePush(String, bool),
|
||||
PullMerge { incoming: usize, rebase: bool },
|
||||
|
|
|
|||
|
|
@ -96,6 +96,11 @@ pub fn confirm_title_stashdrop(
|
|||
) -> String {
|
||||
"Drop".to_string()
|
||||
}
|
||||
pub fn confirm_title_stashpop(
|
||||
_key_config: &SharedKeyConfig,
|
||||
) -> String {
|
||||
"Pop".to_string()
|
||||
}
|
||||
pub fn confirm_title_merge(
|
||||
_key_config: &SharedKeyConfig,
|
||||
rebase: bool,
|
||||
|
|
@ -134,6 +139,10 @@ pub fn confirm_msg_stashdrop(
|
|||
) -> String {
|
||||
"confirm stash drop?".to_string()
|
||||
}
|
||||
pub fn confirm_msg_stashpop(_key_config: &SharedKeyConfig) -> String {
|
||||
"The stash will be applied and then remove from the stash list. Confirm stash pop?"
|
||||
.to_string()
|
||||
}
|
||||
pub fn confirm_msg_resethunk(
|
||||
_key_config: &SharedKeyConfig,
|
||||
) -> String {
|
||||
|
|
@ -748,7 +757,7 @@ pub mod commands {
|
|||
CommandText::new(
|
||||
format!(
|
||||
"Apply [{}]",
|
||||
key_config.get_hint(key_config.enter),
|
||||
key_config.get_hint(key_config.stash_apply),
|
||||
),
|
||||
"apply selected stash",
|
||||
CMD_GROUP_STASHES,
|
||||
|
|
@ -766,6 +775,18 @@ pub mod commands {
|
|||
CMD_GROUP_STASHES,
|
||||
)
|
||||
}
|
||||
pub fn stashlist_pop(
|
||||
key_config: &SharedKeyConfig,
|
||||
) -> CommandText {
|
||||
CommandText::new(
|
||||
format!(
|
||||
"Pop [{}]",
|
||||
key_config.get_hint(key_config.enter),
|
||||
),
|
||||
"pop selected stash",
|
||||
CMD_GROUP_STASHES,
|
||||
)
|
||||
}
|
||||
pub fn stashlist_inspect(
|
||||
key_config: &SharedKeyConfig,
|
||||
) -> CommandText {
|
||||
|
|
|
|||
|
|
@ -83,6 +83,14 @@ impl StashList {
|
|||
}
|
||||
}
|
||||
|
||||
fn pop_stash(&mut self) {
|
||||
if let Some(e) = self.list.selected_entry() {
|
||||
self.queue.borrow_mut().push_back(
|
||||
InternalEvent::ConfirmAction(Action::StashPop(e.id)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn inspect(&mut self) {
|
||||
if let Some(e) = self.list.selected_entry() {
|
||||
self.queue
|
||||
|
|
@ -91,10 +99,38 @@ impl StashList {
|
|||
}
|
||||
}
|
||||
|
||||
///
|
||||
pub fn drop(id: CommitId) -> bool {
|
||||
/// Called when a pending stash action has been confirmed
|
||||
pub fn action_confirmed(&self, action: &Action) -> bool {
|
||||
match *action {
|
||||
Action::StashDrop(id) => Self::drop(id),
|
||||
Action::StashPop(id) => self.pop(id),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn drop(id: CommitId) -> bool {
|
||||
sync::stash_drop(CWD, id).is_ok()
|
||||
}
|
||||
|
||||
fn pop(&self, id: CommitId) -> bool {
|
||||
match sync::stash_pop(CWD, id) {
|
||||
Ok(_) => {
|
||||
self.queue
|
||||
.borrow_mut()
|
||||
.push_back(InternalEvent::TabSwitch);
|
||||
true
|
||||
}
|
||||
Err(e) => {
|
||||
self.queue.borrow_mut().push_back(
|
||||
InternalEvent::ShowErrorMsg(format!(
|
||||
"stash pop error:\n{}",
|
||||
e,
|
||||
)),
|
||||
);
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DrawableComponent for StashList {
|
||||
|
|
@ -120,6 +156,11 @@ impl Component for StashList {
|
|||
|
||||
let selection_valid =
|
||||
self.list.selected_entry().is_some();
|
||||
out.push(CommandInfo::new(
|
||||
strings::commands::stashlist_pop(&self.key_config),
|
||||
selection_valid,
|
||||
true,
|
||||
));
|
||||
out.push(CommandInfo::new(
|
||||
strings::commands::stashlist_apply(&self.key_config),
|
||||
selection_valid,
|
||||
|
|
@ -150,6 +191,8 @@ impl Component for StashList {
|
|||
|
||||
if let Event::Key(k) = ev {
|
||||
if k == self.key_config.enter {
|
||||
self.pop_stash()
|
||||
} else if k == self.key_config.stash_apply {
|
||||
self.apply_stash()
|
||||
} else if k == self.key_config.stash_drop {
|
||||
self.drop_stash()
|
||||
|
|
|
|||
Loading…
Reference in a new issue