diff --git a/asyncgit/src/sync/tags.rs b/asyncgit/src/sync/tags.rs index 531505d1..c5b168e6 100644 --- a/asyncgit/src/sync/tags.rs +++ b/asyncgit/src/sync/tags.rs @@ -4,7 +4,10 @@ use crate::{ sync::{repository::repo, utils::bytes2string}, }; use scopetime::scope_time; -use std::collections::{BTreeMap, HashMap, HashSet}; +use std::{ + collections::{BTreeMap, HashMap, HashSet}, + ops::Not, +}; /// #[derive(Clone, Hash, PartialEq, Debug)] @@ -42,6 +45,8 @@ pub struct TagWithMetadata { pub message: String, /// pub commit_id: CommitId, + /// + pub annotation: Option, } static MAX_MESSAGE_WIDTH: usize = 100; @@ -87,7 +92,12 @@ pub fn get_tags(repo_path: &RepoPath) -> Result { .ok() .as_ref() .and_then(git2::Tag::message_bytes) - .and_then(|msg| bytes2string(msg).ok()); + .and_then(|msg| { + msg.is_empty() + .not() + .then(|| bytes2string(msg).ok()) + .flatten() + }); if let Some(commit) = commit { adder(commit, Tag { name, annotation }); @@ -109,20 +119,26 @@ pub fn get_tags_with_metadata( let tags_grouped_by_commit_id = get_tags(repo_path)?; - let tags_with_commit_id: Vec<(&str, &CommitId)> = + let tags_with_commit_id: Vec<(&str, Option<&str>, &CommitId)> = tags_grouped_by_commit_id .iter() .flat_map(|(commit_id, tags)| { tags.iter() - .map(|tag| (tag.name.as_ref(), commit_id)) - .collect::>() + .map(|tag| { + ( + tag.name.as_ref(), + tag.annotation.as_deref(), + commit_id, + ) + }) + .collect::>() }) .collect(); let unique_commit_ids: HashSet<_> = tags_with_commit_id .iter() .copied() - .map(|(_, &commit_id)| commit_id) + .map(|(_, _, &commit_id)| commit_id) .collect(); let mut commit_ids = Vec::with_capacity(unique_commit_ids.len()); commit_ids.extend(unique_commit_ids); @@ -136,7 +152,7 @@ pub fn get_tags_with_metadata( let mut tags: Vec = tags_with_commit_id .into_iter() - .filter_map(|(tag, commit_id)| { + .filter_map(|(tag, annotation, commit_id)| { unique_commit_infos.get(commit_id).map(|commit_info| { TagWithMetadata { name: String::from(tag), @@ -144,6 +160,7 @@ pub fn get_tags_with_metadata( time: commit_info.time, message: commit_info.message.clone(), commit_id: *commit_id, + annotation: annotation.map(String::from), } }) }) diff --git a/src/app.rs b/src/app.rs index 78c2f98c..37c70588 100644 --- a/src/app.rs +++ b/src/app.rs @@ -674,6 +674,11 @@ impl App { flags .insert(NeedsUpdate::ALL | NeedsUpdate::COMMANDS); } + InternalEvent::ShowInfoMsg(msg) => { + self.msg.show_info(msg.as_str())?; + flags + .insert(NeedsUpdate::ALL | NeedsUpdate::COMMANDS); + } InternalEvent::Update(u) => flags.insert(u), InternalEvent::OpenCommit => self.commit.show()?, InternalEvent::PopupStashing(opts) => { diff --git a/src/components/msg.rs b/src/components/msg.rs index d0839bf9..15806bd6 100644 --- a/src/components/msg.rs +++ b/src/components/msg.rs @@ -139,4 +139,13 @@ impl MsgComponent { Ok(()) } + + /// + pub fn show_info(&mut self, msg: &str) -> Result<()> { + self.title = strings::msg_title_info(&self.key_config); + self.msg = msg.to_string(); + self.show()?; + + Ok(()) + } } diff --git a/src/components/taglist.rs b/src/components/taglist.rs index db02bcff..db097fb1 100644 --- a/src/components/taglist.rs +++ b/src/components/taglist.rs @@ -85,6 +85,8 @@ impl DrawableComponent for TagListComponent { Constraint::Length(10), // author width Constraint::Length(19), + // attachement + Constraint::Length(1), // commit id Constraint::Percentage(100), ]; @@ -171,6 +173,13 @@ impl Component for TagListComponent { true, true, )); + out.push(CommandInfo::new( + strings::commands::show_tag_annotation( + &self.key_config, + ), + self.can_show_annotation(), + true, + )); } visibility_blocking(self) } @@ -196,6 +205,10 @@ impl Component for TagListComponent { self.move_selection(ScrollType::PageDown); } else if key == self.key_config.keys.page_up { self.move_selection(ScrollType::PageUp); + } else if key == self.key_config.keys.move_right + && self.can_show_annotation() + { + self.show_annotation(); } else if key == self.key_config.keys.delete_tag { return self.selected_tag().map_or( Ok(EventState::NotConsumed), @@ -372,6 +385,22 @@ impl TagListComponent { needs_update } + fn show_annotation(&self) { + if let Some(tag) = self.selected_tag() { + if let Some(annotation) = &tag.annotation { + self.queue.push(InternalEvent::ShowInfoMsg( + annotation.clone(), + )); + } + } + } + + fn can_show_annotation(&self) -> bool { + self.selected_tag() + .and_then(|t| t.annotation.as_ref()) + .is_some() + } + /// fn get_rows(&self) -> Vec { self.tags.as_ref().map_or_else(Vec::new, |tags| { @@ -382,6 +411,7 @@ impl TagListComponent { /// fn get_row(&self, tag: &TagWithMetadata) -> Row { const UPSTREAM_SYMBOL: &str = "\u{2191}"; + const ATTACHEMENT_SYMBOL: &str = "!"; const EMPTY_SYMBOL: &str = " "; let is_tag_missing_on_remote = self @@ -399,6 +429,12 @@ impl TagListComponent { EMPTY_SYMBOL }; + let has_attachement_str = if tag.annotation.is_some() { + ATTACHEMENT_SYMBOL + } else { + EMPTY_SYMBOL + }; + let cells: Vec = vec![ Cell::from(has_remote_str) .style(self.theme.commit_author(false)), @@ -408,6 +444,8 @@ impl TagListComponent { .style(self.theme.commit_time(false)), Cell::from(tag.author.clone()) .style(self.theme.commit_author(false)), + Cell::from(has_attachement_str) + .style(self.theme.commit_time(false)), Cell::from(tag.message.clone()) .style(self.theme.text(true, false)), ]; diff --git a/src/queue.rs b/src/queue.rs index 8f7c06f6..abdeac5f 100644 --- a/src/queue.rs +++ b/src/queue.rs @@ -57,6 +57,8 @@ pub enum InternalEvent { /// ShowErrorMsg(String), /// + ShowInfoMsg(String), + /// Update(NeedsUpdate), /// StatusLastFileMoved, diff --git a/src/strings.rs b/src/strings.rs index 495528c6..5d3211b9 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -87,6 +87,9 @@ pub fn msg_opening_editor(_key_config: &SharedKeyConfig) -> String { pub fn msg_title_error(_key_config: &SharedKeyConfig) -> String { "Error".to_string() } +pub fn msg_title_info(_key_config: &SharedKeyConfig) -> String { + "Info".to_string() +} pub fn commit_title() -> String { "Commit".to_string() } @@ -530,6 +533,18 @@ pub mod commands { CMD_GROUP_LOG, ) } + pub fn show_tag_annotation( + key_config: &SharedKeyConfig, + ) -> CommandText { + CommandText::new( + format!( + "Annotation [{}]", + key_config.get_hint(key_config.keys.move_right), + ), + "show tag annotation", + CMD_GROUP_LOG, + ) + } pub fn diff_home_end( key_config: &SharedKeyConfig, ) -> CommandText {