mirror of
https://github.com/gitui-org/gitui
synced 2026-05-23 08:58:21 +00:00
feat: toggle hiding merge commits in revlog
Press Shift+M on the log tab to filter merge commits (like git log --no-merges). Rebuilds the async log walk with a parent-count filter. Fixes #2830 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
8619c07f3f
commit
a426515d2b
7 changed files with 99 additions and 9 deletions
|
|
@ -145,6 +145,13 @@ impl AsyncLog {
|
|||
Ok(false)
|
||||
}
|
||||
|
||||
///
|
||||
pub fn invalidate(&self) {
|
||||
if let Ok(mut head) = self.current_head.lock() {
|
||||
*head = None;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
pub fn fetch(&self) -> Result<FetchStatus> {
|
||||
self.background.store(false, Ordering::Relaxed);
|
||||
|
|
|
|||
|
|
@ -222,3 +222,15 @@ pub fn filter_commit_by_search(
|
|||
},
|
||||
))
|
||||
}
|
||||
|
||||
///
|
||||
pub fn filter_commits_exclude_merges() -> SharedCommitFilterFn {
|
||||
Arc::new(Box::new(
|
||||
move |repo: &Repository,
|
||||
commit_id: &CommitId|
|
||||
-> Result<bool> {
|
||||
let commit = repo.find_commit((*commit_id).into())?;
|
||||
Ok(commit.parent_count() <= 1)
|
||||
},
|
||||
))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@ pub use commit_details::{
|
|||
};
|
||||
pub use commit_files::get_commit_files;
|
||||
pub use commit_filter::{
|
||||
diff_contains_file, filter_commit_by_search, LogFilterSearch,
|
||||
diff_contains_file, filter_commit_by_search,
|
||||
filter_commits_exclude_merges, LogFilterSearch,
|
||||
LogFilterSearchOptions, SearchFields, SearchOptions,
|
||||
SharedCommitFilterFn,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -62,6 +62,10 @@ pub struct CommitList {
|
|||
|
||||
impl CommitList {
|
||||
///
|
||||
pub fn set_title(&mut self, title: impl Into<Box<str>>) {
|
||||
self.title = title.into();
|
||||
}
|
||||
|
||||
pub fn new(env: &Environment, title: &str) -> Self {
|
||||
Self {
|
||||
repo: env.repo.clone(),
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ pub struct KeysList {
|
|||
pub log_reset_commit: GituiKeyEvent,
|
||||
pub log_reword_commit: GituiKeyEvent,
|
||||
pub log_find: GituiKeyEvent,
|
||||
pub log_hide_merges: GituiKeyEvent,
|
||||
pub find_commit_sha: GituiKeyEvent,
|
||||
pub commit_amend: GituiKeyEvent,
|
||||
pub toggle_signoff: GituiKeyEvent,
|
||||
|
|
@ -186,6 +187,7 @@ impl Default for KeysList {
|
|||
log_reset_commit: GituiKeyEvent { code: KeyCode::Char('R'), modifiers: KeyModifiers::SHIFT },
|
||||
log_reword_commit: GituiKeyEvent { code: KeyCode::Char('r'), modifiers: KeyModifiers::empty() },
|
||||
log_find: GituiKeyEvent { code: KeyCode::Char('f'), modifiers: KeyModifiers::empty() },
|
||||
log_hide_merges: GituiKeyEvent::new(KeyCode::Char('M'), KeyModifiers::SHIFT),
|
||||
find_commit_sha: GituiKeyEvent::new(KeyCode::Char('j'), KeyModifiers::CONTROL),
|
||||
commit_amend: GituiKeyEvent::new(KeyCode::Char('a'), KeyModifiers::CONTROL),
|
||||
toggle_signoff: GituiKeyEvent::new(KeyCode::Char('s'), KeyModifiers::CONTROL),
|
||||
|
|
|
|||
|
|
@ -300,8 +300,12 @@ pub fn confirm_msg_force_push(
|
|||
"Confirm force push to branch '{branch_ref}' ? This may rewrite history."
|
||||
)
|
||||
}
|
||||
pub fn log_title(_key_config: &SharedKeyConfig) -> String {
|
||||
"Commit".to_string()
|
||||
pub fn log_title(hide_merge_commits: bool) -> String {
|
||||
if hide_merge_commits {
|
||||
"Commit (no merges)".to_string()
|
||||
} else {
|
||||
"Commit".to_string()
|
||||
}
|
||||
}
|
||||
pub fn file_log_title(
|
||||
file_path: &str,
|
||||
|
|
@ -1576,6 +1580,24 @@ pub mod commands {
|
|||
CMD_GROUP_LOG,
|
||||
)
|
||||
}
|
||||
pub fn log_toggle_hide_merges(
|
||||
key_config: &SharedKeyConfig,
|
||||
hide_merge_commits: bool,
|
||||
) -> CommandText {
|
||||
let action = if hide_merge_commits {
|
||||
"show merge commits"
|
||||
} else {
|
||||
"hide merge commits"
|
||||
};
|
||||
CommandText::new(
|
||||
format!(
|
||||
"No merges [{}]",
|
||||
key_config.get_hint(key_config.keys.log_hide_merges),
|
||||
),
|
||||
action,
|
||||
CMD_GROUP_LOG,
|
||||
)
|
||||
}
|
||||
pub fn log_find_commit(
|
||||
key_config: &SharedKeyConfig,
|
||||
) -> CommandText {
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ use anyhow::Result;
|
|||
use asyncgit::{
|
||||
asyncjob::AsyncSingleJob,
|
||||
sync::{
|
||||
self, filter_commit_by_search, CommitId, LogFilterSearch,
|
||||
LogFilterSearchOptions, RepoPathRef,
|
||||
self, filter_commit_by_search, filter_commits_exclude_merges,
|
||||
CommitId, LogFilterSearch, LogFilterSearchOptions, RepoPathRef,
|
||||
},
|
||||
AsyncBranchesJob, AsyncCommitFilterJob, AsyncGitNotification,
|
||||
AsyncLog, AsyncTags, CommitFilesParams, FetchStatus,
|
||||
|
|
@ -66,6 +66,7 @@ pub struct Revlog {
|
|||
list: CommitList,
|
||||
git_log: AsyncLog,
|
||||
search: LogSearch,
|
||||
hide_merge_commits: bool,
|
||||
git_tags: AsyncTags,
|
||||
git_local_branches: AsyncSingleJob<AsyncBranchesJob>,
|
||||
git_remote_branches: AsyncSingleJob<AsyncBranchesJob>,
|
||||
|
|
@ -83,16 +84,14 @@ impl Revlog {
|
|||
repo: env.repo.clone(),
|
||||
queue: env.queue.clone(),
|
||||
commit_details: CommitDetailsComponent::new(env),
|
||||
list: CommitList::new(
|
||||
env,
|
||||
&strings::log_title(&env.key_config),
|
||||
),
|
||||
list: CommitList::new(env, &strings::log_title(false)),
|
||||
git_log: AsyncLog::new(
|
||||
env.repo.borrow().clone(),
|
||||
&env.sender_git,
|
||||
None,
|
||||
),
|
||||
search: LogSearch::Off,
|
||||
hide_merge_commits: false,
|
||||
git_tags: AsyncTags::new(
|
||||
env.repo.borrow().clone(),
|
||||
&env.sender_git,
|
||||
|
|
@ -404,6 +403,34 @@ impl Revlog {
|
|||
fn can_start_search(&self) -> bool {
|
||||
!self.git_log.is_pending() && !self.is_search_pending()
|
||||
}
|
||||
|
||||
fn can_toggle_hide_merges(&self) -> bool {
|
||||
matches!(self.search, LogSearch::Off) && !self.git_log.is_pending()
|
||||
}
|
||||
|
||||
fn toggle_hide_merge_commits(&mut self) {
|
||||
if !self.can_toggle_hide_merges() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.hide_merge_commits = !self.hide_merge_commits;
|
||||
let filter = if self.hide_merge_commits {
|
||||
Some(filter_commits_exclude_merges())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
self.git_log = AsyncLog::new(
|
||||
self.repo.borrow().clone(),
|
||||
&self.sender,
|
||||
filter,
|
||||
);
|
||||
self.git_log.invalidate();
|
||||
self.list.clear();
|
||||
self.list
|
||||
.set_title(strings::log_title(self.hide_merge_commits));
|
||||
let _ = self.git_log.fetch();
|
||||
}
|
||||
}
|
||||
|
||||
impl DrawableComponent for Revlog {
|
||||
|
|
@ -575,6 +602,13 @@ impl Component for Revlog {
|
|||
self.queue
|
||||
.push(InternalEvent::OpenLogSearchPopup);
|
||||
return Ok(EventState::Consumed);
|
||||
} else if key_match(
|
||||
k,
|
||||
self.key_config.keys.log_hide_merges,
|
||||
) && self.can_toggle_hide_merges()
|
||||
{
|
||||
self.toggle_hide_merge_commits();
|
||||
return Ok(EventState::Consumed);
|
||||
} else if key_match(
|
||||
k,
|
||||
self.key_config.keys.compare_commits,
|
||||
|
|
@ -729,6 +763,14 @@ impl Component for Revlog {
|
|||
self.can_start_search(),
|
||||
self.visible || force_all,
|
||||
));
|
||||
out.push(CommandInfo::new(
|
||||
strings::commands::log_toggle_hide_merges(
|
||||
&self.key_config,
|
||||
self.hide_merge_commits,
|
||||
),
|
||||
self.can_toggle_hide_merges(),
|
||||
self.visible || force_all,
|
||||
));
|
||||
|
||||
visibility_blocking(self)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue