fix: disable blame and history popup for untracked files (#2489)

* fix: disable blame and history popup for untracked files

An untracked file does not have any history data. Right now when
you press `B` for the blame popup or the `H` for the history popup
you get an empty popup where the title spins endlessly trying to find
the file in the commit history, and show relevant information.
This commit disables the two actions in the `StatusTreeComponent`, when the
selected item is a file which is not tracked by git.

---------

Co-authored-by: extrawurst <mail@rusticorn.com>
This commit is contained in:
Kristoffer Plagborg Bak Sørensen 2025-10-28 22:41:36 +01:00 committed by GitHub
parent 7c7698d5a2
commit 2ced3f9acc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 60 additions and 28 deletions

View file

@ -35,6 +35,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* yanking commit ranges no longer generates incorrect dotted range notations, but lists each individual commit [[@naseschwarz](https://github.com/naseschwarz)] (https://github.com/gitui-org/gitui/issues/2576) * yanking commit ranges no longer generates incorrect dotted range notations, but lists each individual commit [[@naseschwarz](https://github.com/naseschwarz)] (https://github.com/gitui-org/gitui/issues/2576)
* print slightly nicer errors when failing to create a directory [[@linkmauve](https://github.com/linkmauve)] (https://github.com/gitui-org/gitui/pull/2728) * print slightly nicer errors when failing to create a directory [[@linkmauve](https://github.com/linkmauve)] (https://github.com/gitui-org/gitui/pull/2728)
* When the terminal is insufficient to display all the commands, the cmdbar_bg configuration color does not fully take effect. ([#2347](https://github.com/extrawurst/gitui/issues/2347)) * When the terminal is insufficient to display all the commands, the cmdbar_bg configuration color does not fully take effect. ([#2347](https://github.com/extrawurst/gitui/issues/2347))
* disable blame and history popup keybinds for untracked files [[@kpbaks](https://github.com/kpbaks)] ([#2489](https://github.com/gitui-org/gitui/pull/2489))
## [0.27.0] - 2024-01-14 ## [0.27.0] - 2024-01-14

View file

@ -308,6 +308,25 @@ impl StatusTreeComponent {
} }
} }
} }
fn open_history(&mut self) {
match self.selection_file() {
Some(status_item)
if !matches!(
status_item.status,
StatusItemType::New
) =>
{
self.hide();
self.queue.push(InternalEvent::OpenPopup(
StackablePopupOpen::FileRevlog(FileRevOpen::new(
status_item.path,
)),
));
}
_ => {}
}
}
} }
/// Used for drawing the `FileTreeComponent` /// Used for drawing the `FileTreeComponent`
@ -395,11 +414,18 @@ impl Component for StatusTreeComponent {
out: &mut Vec<CommandInfo>, out: &mut Vec<CommandInfo>,
force_all: bool, force_all: bool,
) -> CommandBlocking { ) -> CommandBlocking {
let available = self.focused || force_all;
let selection = self.selection_file();
let selected_is_file = selection.is_some();
let tracked = selection.is_some_and(|s| {
!matches!(s.status, StatusItemType::New)
});
out.push( out.push(
CommandInfo::new( CommandInfo::new(
strings::commands::navigate_tree(&self.key_config), strings::commands::navigate_tree(&self.key_config),
!self.is_empty(), !self.is_empty(),
self.focused || force_all, available,
) )
.order(order::NAV), .order(order::NAV),
); );
@ -407,8 +433,8 @@ impl Component for StatusTreeComponent {
out.push( out.push(
CommandInfo::new( CommandInfo::new(
strings::commands::blame_file(&self.key_config), strings::commands::blame_file(&self.key_config),
self.selection_file().is_some(), selected_is_file && tracked,
self.focused || force_all, available,
) )
.order(order::RARE_ACTION), .order(order::RARE_ACTION),
); );
@ -418,8 +444,8 @@ impl Component for StatusTreeComponent {
strings::commands::open_file_history( strings::commands::open_file_history(
&self.key_config, &self.key_config,
), ),
self.selection_file().is_some(), selected_is_file && tracked,
self.focused || force_all, available,
) )
.order(order::RARE_ACTION), .order(order::RARE_ACTION),
); );
@ -427,8 +453,8 @@ impl Component for StatusTreeComponent {
out.push( out.push(
CommandInfo::new( CommandInfo::new(
strings::commands::edit_item(&self.key_config), strings::commands::edit_item(&self.key_config),
self.selection_file().is_some(), selected_is_file,
self.focused || force_all, available,
) )
.order(order::RARE_ACTION), .order(order::RARE_ACTION),
); );
@ -436,8 +462,8 @@ impl Component for StatusTreeComponent {
out.push( out.push(
CommandInfo::new( CommandInfo::new(
strings::commands::copy_path(&self.key_config), strings::commands::copy_path(&self.key_config),
self.selection_file().is_some(), selected_is_file,
self.focused || force_all, available,
) )
.order(order::RARE_ACTION), .order(order::RARE_ACTION),
); );
@ -445,35 +471,40 @@ impl Component for StatusTreeComponent {
CommandBlocking::PassingOn CommandBlocking::PassingOn
} }
#[expect(clippy::cognitive_complexity)]
fn event(&mut self, ev: &Event) -> Result<EventState> { fn event(&mut self, ev: &Event) -> Result<EventState> {
if self.focused { if self.focused {
if let Event::Key(e) = ev { if let Event::Key(e) = ev {
return if key_match(e, self.key_config.keys.blame) { return if key_match(e, self.key_config.keys.blame) {
if let Some(status_item) = self.selection_file() { match self.selection_file() {
self.hide(); Some(status_item)
self.queue.push(InternalEvent::OpenPopup( if !matches!(
StackablePopupOpen::BlameFile( status_item.status,
BlameFileOpen { StatusItemType::New
file_path: status_item.path, ) =>
commit_id: self.revision, {
selection: None, self.hide();
}, self.queue.push(
), InternalEvent::OpenPopup(
)); StackablePopupOpen::BlameFile(
BlameFileOpen {
file_path: status_item
.path,
commit_id: self.revision,
selection: None,
},
),
),
);
}
_ => {}
} }
Ok(EventState::Consumed) Ok(EventState::Consumed)
} else if key_match( } else if key_match(
e, e,
self.key_config.keys.file_history, self.key_config.keys.file_history,
) { ) {
if let Some(status_item) = self.selection_file() { self.open_history();
self.hide();
self.queue.push(InternalEvent::OpenPopup(
StackablePopupOpen::FileRevlog(
FileRevOpen::new(status_item.path),
),
));
}
Ok(EventState::Consumed) Ok(EventState::Consumed)
} else if key_match(e, self.key_config.keys.edit_file) } else if key_match(e, self.key_config.keys.edit_file)
{ {