mirror of
https://github.com/extrawurst/gitui.git
synced 2024-12-27 11:03:03 +03:00
allow rebase with conflicts (#897)
This commit is contained in:
parent
9f8fc6b907
commit
e4c7867564
@ -1,13 +1,18 @@
|
||||
use crate::{
|
||||
error::{Error, Result},
|
||||
sync::{
|
||||
branch::merge_commit::commit_merge_with_head, reset_stage,
|
||||
reset_workdir, utils, CommitId,
|
||||
branch::merge_commit::commit_merge_with_head,
|
||||
rebase::{
|
||||
abort_rebase, continue_rebase, get_rebase_progress,
|
||||
},
|
||||
reset_stage, reset_workdir, utils, CommitId,
|
||||
},
|
||||
};
|
||||
use git2::{BranchType, Commit, MergeOptions, Repository};
|
||||
use scopetime::scope_time;
|
||||
|
||||
use super::rebase::{RebaseProgress, RebaseState};
|
||||
|
||||
///
|
||||
pub fn mergehead_ids(repo_path: &str) -> Result<Vec<CommitId>> {
|
||||
scope_time!("mergehead_ids");
|
||||
@ -51,6 +56,35 @@ pub fn merge_branch(repo_path: &str, branch: &str) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
///
|
||||
pub fn rebase_progress(repo_path: &str) -> Result<RebaseProgress> {
|
||||
scope_time!("rebase_progress");
|
||||
|
||||
let repo = utils::repo(repo_path)?;
|
||||
|
||||
get_rebase_progress(&repo)
|
||||
}
|
||||
|
||||
///
|
||||
pub fn continue_pending_rebase(
|
||||
repo_path: &str,
|
||||
) -> Result<RebaseState> {
|
||||
scope_time!("continue_pending_rebase");
|
||||
|
||||
let repo = utils::repo(repo_path)?;
|
||||
|
||||
continue_rebase(&repo)
|
||||
}
|
||||
|
||||
///
|
||||
pub fn abort_pending_rebase(repo_path: &str) -> Result<()> {
|
||||
scope_time!("abort_pending_rebase");
|
||||
|
||||
let repo = utils::repo(repo_path)?;
|
||||
|
||||
abort_rebase(&repo)
|
||||
}
|
||||
|
||||
///
|
||||
pub fn merge_branch_repo(
|
||||
repo: &Repository,
|
||||
|
@ -58,7 +58,9 @@ pub use hunks::{reset_hunk, stage_hunk, unstage_hunk};
|
||||
pub use ignore::add_to_ignore;
|
||||
pub use logwalker::{LogWalker, LogWalkerFilter};
|
||||
pub use merge::{
|
||||
abort_merge, merge_branch, merge_commit, merge_msg, mergehead_ids,
|
||||
abort_merge, abort_pending_rebase, continue_pending_rebase,
|
||||
merge_branch, merge_commit, merge_msg, mergehead_ids,
|
||||
rebase_progress,
|
||||
};
|
||||
pub use rebase::rebase_branch;
|
||||
pub use remotes::{
|
||||
|
@ -12,7 +12,7 @@ use super::CommitId;
|
||||
pub fn rebase_branch(
|
||||
repo_path: &str,
|
||||
branch: &str,
|
||||
) -> Result<CommitId> {
|
||||
) -> Result<RebaseState> {
|
||||
scope_time!("rebase_branch");
|
||||
|
||||
let repo = utils::repo(repo_path)?;
|
||||
@ -23,13 +23,13 @@ pub fn rebase_branch(
|
||||
fn rebase_branch_repo(
|
||||
repo: &Repository,
|
||||
branch_name: &str,
|
||||
) -> Result<CommitId> {
|
||||
) -> Result<RebaseState> {
|
||||
let branch = repo.find_branch(branch_name, BranchType::Local)?;
|
||||
|
||||
let annotated =
|
||||
repo.reference_to_annotated_commit(&branch.into_reference())?;
|
||||
|
||||
conflict_free_rebase(repo, &annotated)
|
||||
rebase(repo, &annotated)
|
||||
}
|
||||
|
||||
/// rebase attempt which aborts and undo's rebase if any conflict appears
|
||||
@ -66,16 +66,133 @@ pub fn conflict_free_rebase(
|
||||
})
|
||||
}
|
||||
|
||||
///
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum RebaseState {
|
||||
///
|
||||
Finished,
|
||||
///
|
||||
Conflicted,
|
||||
}
|
||||
|
||||
/// rebase
|
||||
pub fn rebase(
|
||||
repo: &git2::Repository,
|
||||
commit: &git2::AnnotatedCommit,
|
||||
) -> Result<RebaseState> {
|
||||
let mut rebase = repo.rebase(None, Some(commit), None, None)?;
|
||||
let signature =
|
||||
crate::sync::commit::signature_allow_undefined_name(repo)?;
|
||||
|
||||
while let Some(op) = rebase.next() {
|
||||
let _op = op?;
|
||||
// dbg!(op.id());
|
||||
|
||||
if repo.index()?.has_conflicts() {
|
||||
return Ok(RebaseState::Conflicted);
|
||||
}
|
||||
|
||||
rebase.commit(None, &signature, None)?;
|
||||
}
|
||||
|
||||
if repo.index()?.has_conflicts() {
|
||||
return Ok(RebaseState::Conflicted);
|
||||
}
|
||||
|
||||
rebase.finish(Some(&signature))?;
|
||||
|
||||
Ok(RebaseState::Finished)
|
||||
}
|
||||
|
||||
/// continue pending rebase
|
||||
pub fn continue_rebase(
|
||||
repo: &git2::Repository,
|
||||
) -> Result<RebaseState> {
|
||||
let mut rebase = repo.open_rebase(None)?;
|
||||
let signature =
|
||||
crate::sync::commit::signature_allow_undefined_name(repo)?;
|
||||
|
||||
if repo.index()?.has_conflicts() {
|
||||
return Ok(RebaseState::Conflicted);
|
||||
}
|
||||
|
||||
// try commit current rebase step
|
||||
if !repo.index()?.is_empty() {
|
||||
rebase.commit(None, &signature, None)?;
|
||||
}
|
||||
|
||||
while let Some(op) = rebase.next() {
|
||||
let _op = op?;
|
||||
// dbg!(op.id());
|
||||
|
||||
if repo.index()?.has_conflicts() {
|
||||
return Ok(RebaseState::Conflicted);
|
||||
}
|
||||
|
||||
rebase.commit(None, &signature, None)?;
|
||||
}
|
||||
|
||||
if repo.index()?.has_conflicts() {
|
||||
return Ok(RebaseState::Conflicted);
|
||||
}
|
||||
|
||||
rebase.finish(Some(&signature))?;
|
||||
|
||||
Ok(RebaseState::Finished)
|
||||
}
|
||||
|
||||
///
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub struct RebaseProgress {
|
||||
///
|
||||
pub steps: usize,
|
||||
///
|
||||
pub current: usize,
|
||||
///
|
||||
pub current_commit: Option<CommitId>,
|
||||
}
|
||||
|
||||
///
|
||||
pub fn get_rebase_progress(
|
||||
repo: &git2::Repository,
|
||||
) -> Result<RebaseProgress> {
|
||||
let mut rebase = repo.open_rebase(None)?;
|
||||
|
||||
let current_commit: Option<CommitId> = rebase
|
||||
.operation_current()
|
||||
.and_then(|idx| rebase.nth(idx))
|
||||
.map(|op| op.id().into());
|
||||
|
||||
let progress = RebaseProgress {
|
||||
steps: rebase.len(),
|
||||
current: rebase.operation_current().unwrap_or_default(),
|
||||
current_commit,
|
||||
};
|
||||
|
||||
Ok(progress)
|
||||
}
|
||||
|
||||
///
|
||||
pub fn abort_rebase(repo: &git2::Repository) -> Result<()> {
|
||||
let mut rebase = repo.open_rebase(None)?;
|
||||
|
||||
rebase.abort()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
mod test_conflict_free_rebase {
|
||||
use crate::sync::{
|
||||
checkout_branch, create_branch,
|
||||
rebase::rebase_branch,
|
||||
rebase::{rebase_branch, RebaseState},
|
||||
repo_state,
|
||||
tests::{repo_init, write_commit_file},
|
||||
CommitId, RepoState,
|
||||
utils, CommitId, RepoState,
|
||||
};
|
||||
use git2::Repository;
|
||||
use git2::{BranchType, Repository};
|
||||
|
||||
use super::conflict_free_rebase;
|
||||
|
||||
fn parent_ids(repo: &Repository, c: CommitId) -> Vec<CommitId> {
|
||||
let foo = repo
|
||||
@ -88,6 +205,23 @@ mod tests {
|
||||
foo
|
||||
}
|
||||
|
||||
///
|
||||
fn test_rebase_branch_repo(
|
||||
repo_path: &str,
|
||||
branch_name: &str,
|
||||
) -> CommitId {
|
||||
let repo = utils::repo(repo_path).unwrap();
|
||||
|
||||
let branch =
|
||||
repo.find_branch(branch_name, BranchType::Local).unwrap();
|
||||
|
||||
let annotated = repo
|
||||
.reference_to_annotated_commit(&branch.into_reference())
|
||||
.unwrap();
|
||||
|
||||
conflict_free_rebase(&repo, &annotated).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_smoke() {
|
||||
let (_td, repo) = repo_init().unwrap();
|
||||
@ -111,7 +245,7 @@ mod tests {
|
||||
|
||||
checkout_branch(repo_path, "refs/heads/foo").unwrap();
|
||||
|
||||
let r = rebase_branch(repo_path, "master").unwrap();
|
||||
let r = test_rebase_branch_repo(repo_path, "master");
|
||||
|
||||
assert_eq!(parent_ids(&repo, r), vec![c3]);
|
||||
}
|
||||
@ -136,7 +270,64 @@ mod tests {
|
||||
|
||||
let res = rebase_branch(repo_path, "master");
|
||||
|
||||
assert!(res.is_err());
|
||||
assert!(matches!(res.unwrap(), RebaseState::Conflicted));
|
||||
|
||||
assert_eq!(repo_state(repo_path).unwrap(), RepoState::Rebase);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_rebase {
|
||||
use crate::sync::{
|
||||
checkout_branch, create_branch,
|
||||
rebase::{
|
||||
abort_rebase, get_rebase_progress, RebaseProgress,
|
||||
RebaseState,
|
||||
},
|
||||
rebase_branch, repo_state,
|
||||
tests::{repo_init, write_commit_file},
|
||||
RepoState,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_conflicted_abort() {
|
||||
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", "test1", "commit1");
|
||||
|
||||
create_branch(repo_path, "foo").unwrap();
|
||||
|
||||
let c =
|
||||
write_commit_file(&repo, "test.txt", "test2", "commit2");
|
||||
|
||||
checkout_branch(repo_path, "refs/heads/master").unwrap();
|
||||
|
||||
write_commit_file(&repo, "test.txt", "test3", "commit3");
|
||||
|
||||
checkout_branch(repo_path, "refs/heads/foo").unwrap();
|
||||
|
||||
assert!(get_rebase_progress(&repo).is_err());
|
||||
|
||||
// rebase
|
||||
|
||||
let r = rebase_branch(repo_path, "master").unwrap();
|
||||
|
||||
assert_eq!(r, RebaseState::Conflicted);
|
||||
assert_eq!(repo_state(repo_path).unwrap(), RepoState::Rebase);
|
||||
assert_eq!(
|
||||
get_rebase_progress(&repo).unwrap(),
|
||||
RebaseProgress {
|
||||
current: 0,
|
||||
steps: 1,
|
||||
current_commit: Some(c)
|
||||
}
|
||||
);
|
||||
|
||||
// abort
|
||||
|
||||
abort_rebase(&repo).unwrap();
|
||||
|
||||
assert_eq!(repo_state(repo_path).unwrap(), RepoState::Clean);
|
||||
}
|
||||
|
@ -10,6 +10,8 @@ pub enum RepoState {
|
||||
///
|
||||
Merge,
|
||||
///
|
||||
Rebase,
|
||||
///
|
||||
Other,
|
||||
}
|
||||
|
||||
@ -18,6 +20,7 @@ impl From<RepositoryState> for RepoState {
|
||||
match state {
|
||||
RepositoryState::Clean => Self::Clean,
|
||||
RepositoryState::Merge => Self::Merge,
|
||||
RepositoryState::RebaseMerge => Self::Rebase,
|
||||
_ => Self::Other,
|
||||
}
|
||||
}
|
||||
@ -29,5 +32,9 @@ pub fn repo_state(repo_path: &str) -> Result<RepoState> {
|
||||
|
||||
let repo = utils::repo(repo_path)?;
|
||||
|
||||
Ok(repo.state().into())
|
||||
let state = repo.state();
|
||||
|
||||
// dbg!(&state);
|
||||
|
||||
Ok(state.into())
|
||||
}
|
||||
|
@ -821,6 +821,10 @@ impl App {
|
||||
self.status_tab.abort_merge();
|
||||
flags.insert(NeedsUpdate::ALL);
|
||||
}
|
||||
Action::AbortRebase => {
|
||||
self.status_tab.abort_rebase();
|
||||
flags.insert(NeedsUpdate::ALL);
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
|
@ -192,43 +192,35 @@ impl Component for ChangesComponent {
|
||||
if self.is_working_dir {
|
||||
out.push(CommandInfo::new(
|
||||
strings::commands::stage_all(&self.key_config),
|
||||
some_selection,
|
||||
self.focused(),
|
||||
true,
|
||||
some_selection && self.focused(),
|
||||
));
|
||||
out.push(CommandInfo::new(
|
||||
strings::commands::stage_item(&self.key_config),
|
||||
some_selection,
|
||||
self.focused(),
|
||||
true,
|
||||
some_selection && self.focused(),
|
||||
));
|
||||
out.push(CommandInfo::new(
|
||||
strings::commands::reset_item(&self.key_config),
|
||||
some_selection,
|
||||
self.focused(),
|
||||
true,
|
||||
some_selection && self.focused(),
|
||||
));
|
||||
out.push(CommandInfo::new(
|
||||
strings::commands::ignore_item(&self.key_config),
|
||||
some_selection,
|
||||
self.focused(),
|
||||
true,
|
||||
some_selection && self.focused(),
|
||||
));
|
||||
} else {
|
||||
out.push(CommandInfo::new(
|
||||
strings::commands::unstage_item(&self.key_config),
|
||||
some_selection,
|
||||
self.focused(),
|
||||
true,
|
||||
some_selection && self.focused(),
|
||||
));
|
||||
out.push(CommandInfo::new(
|
||||
strings::commands::unstage_all(&self.key_config),
|
||||
some_selection,
|
||||
self.focused(),
|
||||
true,
|
||||
some_selection && self.focused(),
|
||||
));
|
||||
out.push(
|
||||
CommandInfo::new(
|
||||
strings::commands::commit_open(&self.key_config),
|
||||
!self.is_empty(),
|
||||
self.focused() || force_all,
|
||||
)
|
||||
.order(-1),
|
||||
);
|
||||
}
|
||||
|
||||
CommandBlocking::PassingOn
|
||||
@ -241,13 +233,7 @@ impl Component for ChangesComponent {
|
||||
|
||||
if self.focused() {
|
||||
if let Event::Key(e) = ev {
|
||||
return if e == self.key_config.open_commit
|
||||
&& !self.is_working_dir
|
||||
&& !self.is_empty()
|
||||
{
|
||||
self.queue.push(InternalEvent::OpenCommit);
|
||||
Ok(EventState::Consumed)
|
||||
} else if e == self.key_config.enter {
|
||||
return if e == self.key_config.enter {
|
||||
try_or_popup!(
|
||||
self,
|
||||
"staging error:",
|
||||
|
@ -200,6 +200,10 @@ impl ConfirmComponent {
|
||||
Action::AbortMerge => (
|
||||
strings::confirm_title_abortmerge(),
|
||||
strings::confirm_msg_abortmerge(),
|
||||
),
|
||||
Action::AbortRebase => (
|
||||
strings::confirm_title_abortrebase(),
|
||||
strings::confirm_msg_abortrebase(),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ impl Default for KeyConfig {
|
||||
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},
|
||||
abort_merge: KeyEvent { code: KeyCode::Char('A'), modifiers: KeyModifiers::SHIFT},
|
||||
open_file_tree: KeyEvent { code: KeyCode::Char('F'), modifiers: KeyModifiers::SHIFT},
|
||||
file_find: KeyEvent { code: KeyCode::Char('f'), modifiers: KeyModifiers::empty()},
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ pub enum Action {
|
||||
ForcePush(String, bool),
|
||||
PullMerge { incoming: usize, rebase: bool },
|
||||
AbortMerge,
|
||||
AbortRebase,
|
||||
}
|
||||
|
||||
///
|
||||
|
@ -153,6 +153,13 @@ pub fn confirm_msg_abortmerge() -> String {
|
||||
"This will revert all uncommitted changes. Are you sure?"
|
||||
.to_string()
|
||||
}
|
||||
pub fn confirm_title_abortrebase() -> String {
|
||||
"Abort rebase?".to_string()
|
||||
}
|
||||
pub fn confirm_msg_abortrebase() -> String {
|
||||
"This will revert all uncommitted changes. Are you sure?"
|
||||
.to_string()
|
||||
}
|
||||
pub fn confirm_msg_reset() -> String {
|
||||
"confirm file reset?".to_string()
|
||||
}
|
||||
@ -628,6 +635,31 @@ pub mod commands {
|
||||
CMD_GROUP_GENERAL,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn continue_rebase(
|
||||
key_config: &SharedKeyConfig,
|
||||
) -> CommandText {
|
||||
CommandText::new(
|
||||
format!(
|
||||
"Continue rebase [{}]",
|
||||
key_config.get_hint(key_config.rebase_branch),
|
||||
),
|
||||
"continue ongoing rebase",
|
||||
CMD_GROUP_GENERAL,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn abort_rebase(key_config: &SharedKeyConfig) -> CommandText {
|
||||
CommandText::new(
|
||||
format!(
|
||||
"Abort rebase [{}]",
|
||||
key_config.get_hint(key_config.abort_merge),
|
||||
),
|
||||
"abort ongoing rebase",
|
||||
CMD_GROUP_GENERAL,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn select_staging(
|
||||
key_config: &SharedKeyConfig,
|
||||
) -> CommandText {
|
||||
|
@ -14,8 +14,8 @@ use crate::{
|
||||
use anyhow::Result;
|
||||
use asyncgit::{
|
||||
cached,
|
||||
sync::BranchCompare,
|
||||
sync::{self, status::StatusType, RepoState},
|
||||
sync::{BranchCompare, CommitId},
|
||||
AsyncDiff, AsyncGitNotification, AsyncStatus, DiffParams,
|
||||
DiffType, StatusParams, CWD,
|
||||
};
|
||||
@ -215,14 +215,12 @@ impl Status {
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_repo_state<B: tui::backend::Backend>(
|
||||
f: &mut tui::Frame<B>,
|
||||
r: tui::layout::Rect,
|
||||
) -> Result<()> {
|
||||
if let Ok(state) = sync::repo_state(CWD) {
|
||||
if state != RepoState::Clean {
|
||||
fn repo_state_text(state: &RepoState) -> String {
|
||||
match state {
|
||||
RepoState::Merge => {
|
||||
let ids =
|
||||
sync::mergehead_ids(CWD).unwrap_or_default();
|
||||
|
||||
let ids = format!(
|
||||
"({})",
|
||||
ids.iter()
|
||||
@ -231,7 +229,39 @@ impl Status {
|
||||
))
|
||||
.join(",")
|
||||
);
|
||||
let txt = format!("{:?} {}", state, ids);
|
||||
|
||||
format!("{:?} {}", state, ids)
|
||||
}
|
||||
RepoState::Rebase => {
|
||||
let progress =
|
||||
if let Ok(p) = sync::rebase_progress(CWD) {
|
||||
format!(
|
||||
"[{}] {}/{}",
|
||||
p.current_commit
|
||||
.as_ref()
|
||||
.map(CommitId::get_short_string)
|
||||
.unwrap_or_default(),
|
||||
p.current + 1,
|
||||
p.steps
|
||||
)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
format!("{:?} ({})", state, progress)
|
||||
}
|
||||
_ => format!("{:?}", state),
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_repo_state<B: tui::backend::Backend>(
|
||||
f: &mut tui::Frame<B>,
|
||||
r: tui::layout::Rect,
|
||||
) -> Result<()> {
|
||||
if let Ok(state) = sync::repo_state(CWD) {
|
||||
if state != RepoState::Clean {
|
||||
let txt = Self::repo_state_text(&state);
|
||||
|
||||
let txt_len = u16::try_from(txt.len())?;
|
||||
let w = Paragraph::new(txt)
|
||||
.style(Style::default().fg(Color::Red))
|
||||
@ -519,10 +549,31 @@ impl Status {
|
||||
== RepoState::Merge
|
||||
}
|
||||
|
||||
fn pending_rebase() -> bool {
|
||||
sync::repo_state(CWD).unwrap_or(RepoState::Clean)
|
||||
== RepoState::Rebase
|
||||
}
|
||||
|
||||
pub fn abort_merge(&self) {
|
||||
try_or_popup!(self, "abort merge", sync::abort_merge(CWD));
|
||||
}
|
||||
|
||||
pub fn abort_rebase(&self) {
|
||||
try_or_popup!(
|
||||
self,
|
||||
"abort rebase",
|
||||
sync::abort_pending_rebase(CWD)
|
||||
);
|
||||
}
|
||||
|
||||
fn continue_rebase(&self) {
|
||||
try_or_popup!(
|
||||
self,
|
||||
"continue rebase",
|
||||
sync::continue_pending_rebase(CWD)
|
||||
);
|
||||
}
|
||||
|
||||
fn commands_nav(
|
||||
&self,
|
||||
out: &mut Vec<CommandInfo>,
|
||||
@ -566,6 +617,12 @@ impl Status {
|
||||
.order(strings::order::NAV),
|
||||
);
|
||||
}
|
||||
|
||||
fn can_commit(&self) -> bool {
|
||||
self.index.focused()
|
||||
&& !self.index.is_empty()
|
||||
&& !Self::pending_rebase()
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Status {
|
||||
@ -583,6 +640,15 @@ impl Component for Status {
|
||||
self.components().as_slice(),
|
||||
);
|
||||
|
||||
out.push(
|
||||
CommandInfo::new(
|
||||
strings::commands::commit_open(&self.key_config),
|
||||
true,
|
||||
self.can_commit() || force_all,
|
||||
)
|
||||
.order(-1),
|
||||
);
|
||||
|
||||
out.push(CommandInfo::new(
|
||||
strings::commands::open_branch_select_popup(
|
||||
&self.key_config,
|
||||
@ -612,7 +678,8 @@ impl Component for Status {
|
||||
out.push(CommandInfo::new(
|
||||
strings::commands::undo_commit(&self.key_config),
|
||||
true,
|
||||
!focus_on_diff,
|
||||
(!Self::pending_rebase() && !focus_on_diff)
|
||||
|| force_all,
|
||||
));
|
||||
|
||||
out.push(CommandInfo::new(
|
||||
@ -620,6 +687,17 @@ impl Component for Status {
|
||||
true,
|
||||
Self::can_abort_merge() || force_all,
|
||||
));
|
||||
|
||||
out.push(CommandInfo::new(
|
||||
strings::commands::continue_rebase(&self.key_config),
|
||||
true,
|
||||
Self::pending_rebase() || force_all,
|
||||
));
|
||||
out.push(CommandInfo::new(
|
||||
strings::commands::abort_rebase(&self.key_config),
|
||||
true,
|
||||
Self::pending_rebase() || force_all,
|
||||
));
|
||||
}
|
||||
|
||||
{
|
||||
@ -639,6 +717,7 @@ impl Component for Status {
|
||||
visibility_blocking(self)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
|
||||
fn event(
|
||||
&mut self,
|
||||
ev: crossterm::event::Event,
|
||||
@ -664,6 +743,11 @@ impl Component for Status {
|
||||
);
|
||||
}
|
||||
Ok(EventState::Consumed)
|
||||
} else if k == self.key_config.open_commit
|
||||
&& self.can_commit()
|
||||
{
|
||||
self.queue.push(InternalEvent::OpenCommit);
|
||||
Ok(EventState::Consumed)
|
||||
} else if k == self.key_config.toggle_workarea
|
||||
&& !self.is_focus_on_diff()
|
||||
{
|
||||
@ -725,6 +809,22 @@ impl Component for Status {
|
||||
Action::AbortMerge,
|
||||
));
|
||||
|
||||
Ok(EventState::Consumed)
|
||||
} else if k == self.key_config.abort_merge
|
||||
&& Self::pending_rebase()
|
||||
{
|
||||
self.queue.push(InternalEvent::ConfirmAction(
|
||||
Action::AbortRebase,
|
||||
));
|
||||
|
||||
Ok(EventState::Consumed)
|
||||
} else if k == self.key_config.rebase_branch
|
||||
&& Self::pending_rebase()
|
||||
{
|
||||
self.continue_rebase();
|
||||
self.queue.push(InternalEvent::Update(
|
||||
NeedsUpdate::ALL,
|
||||
));
|
||||
Ok(EventState::Consumed)
|
||||
} else {
|
||||
Ok(EventState::NotConsumed)
|
||||
|
Loading…
Reference in New Issue
Block a user