diff --git a/asyncgit/src/sync/mod.rs b/asyncgit/src/sync/mod.rs index c61cc7d68b..ba76509af0 100644 --- a/asyncgit/src/sync/mod.rs +++ b/asyncgit/src/sync/mod.rs @@ -7,6 +7,7 @@ mod hunks; mod logwalker; mod reset; pub mod status; +mod tags; pub mod utils; pub use commits_info::{get_commits_info, CommitInfo}; @@ -16,6 +17,7 @@ pub use logwalker::LogWalker; pub use reset::{ reset_stage, reset_workdir_file, reset_workdir_folder, }; +pub use tags::{get_tags, Tags}; pub use utils::{ commit, stage_add_all, stage_add_file, stage_addremoved, }; diff --git a/asyncgit/src/sync/tags.rs b/asyncgit/src/sync/tags.rs new file mode 100644 index 0000000000..e9a0f18bc8 --- /dev/null +++ b/asyncgit/src/sync/tags.rs @@ -0,0 +1,30 @@ +use super::utils::repo; +use git2::Error; +use scopetime::scope_time; +use std::collections::HashMap; + +/// hashmap of tag target commit hash to tag name +pub type Tags = HashMap; + +/// returns `Tags` type filled with all tags found in repo +pub fn get_tags(repo_path: &str) -> Result { + scope_time!("get_tags"); + + let mut res = Tags::new(); + + let repo = repo(repo_path); + + for name in repo.tag_names(None)?.iter() { + if let Some(name) = name { + let obj = repo.revparse_single(name)?; + + if let Some(tag) = obj.as_tag() { + let target_hash = tag.target_id().to_string(); + let tag_name = String::from(name); + res.insert(target_hash, tag_name); + } + } + } + + Ok(res) +} diff --git a/src/tabs/revlog.rs b/src/tabs/revlog.rs index a7acc961d9..37154dc227 100644 --- a/src/tabs/revlog.rs +++ b/src/tabs/revlog.rs @@ -8,7 +8,7 @@ use chrono::prelude::*; use crossbeam_channel::Sender; use crossterm::event::Event; use std::{borrow::Cow, cmp, convert::TryFrom, time::Instant}; -use sync::CommitInfo; +use sync::{CommitInfo, Tags}; use tui::{ backend::Backend, layout::{Alignment, Rect}, @@ -24,29 +24,32 @@ struct LogEntry { hash: String, } -impl From<&CommitInfo> for LogEntry { - fn from(c: &CommitInfo) -> Self { +impl From for LogEntry { + fn from(c: CommitInfo) -> Self { let time = DateTime::::from(DateTime::::from_utc( NaiveDateTime::from_timestamp(c.time, 0), Utc, )); Self { - author: c.author.clone(), - msg: c.message.clone(), + author: c.author, + msg: c.message, time: time.format("%Y-%m-%d %H:%M:%S").to_string(), - hash: c.hash[0..7].to_string(), + hash: c.hash, } } } const COLOR_SELECTION_BG: Color = Color::Blue; +const STYLE_TAG: Style = Style::new().fg(Color::Yellow); const STYLE_HASH: Style = Style::new().fg(Color::Magenta); const STYLE_TIME: Style = Style::new().fg(Color::Blue); const STYLE_AUTHOR: Style = Style::new().fg(Color::Green); const STYLE_MSG: Style = Style::new().fg(Color::Reset); +const STYLE_TAG_SELECTED: Style = + Style::new().fg(Color::Yellow).bg(COLOR_SELECTION_BG); const STYLE_HASH_SELECTED: Style = Style::new().fg(Color::Magenta).bg(COLOR_SELECTION_BG); const STYLE_TIME_SELECTED: Style = @@ -56,7 +59,7 @@ const STYLE_AUTHOR_SELECTED: Style = const STYLE_MSG_SELECTED: Style = Style::new().fg(Color::Reset).bg(COLOR_SELECTION_BG); -static ELEMENTS_PER_LINE: usize = 8; +static ELEMENTS_PER_LINE: usize = 10; static SLICE_SIZE: usize = 1000; static SLICE_OFFSET_RELOAD_THRESHOLD: usize = 100; @@ -69,6 +72,7 @@ pub struct Revlog { visible: bool, first_open_done: bool, scroll_state: (Instant, f32), + tags: Tags, } impl Revlog { @@ -82,6 +86,7 @@ impl Revlog { visible: false, first_open_done: false, scroll_state: (Instant::now(), 0_f32), + tags: Tags::new(), } } @@ -94,7 +99,12 @@ impl Revlog { let mut txt = Vec::new(); for (idx, e) in self.items.iter().enumerate() { - Self::add_entry(e, idx == selection, &mut txt); + let tag = if let Some(tag_name) = self.tags.get(&e.hash) { + tag_name.as_str() + } else { + "" + }; + Self::add_entry(e, idx == selection, &mut txt, tag); } let title = @@ -138,9 +148,14 @@ impl Revlog { ); if let Ok(commits) = commits { - self.items.extend(commits.iter().map(LogEntry::from)); + self.items + .extend(commits.into_iter().map(LogEntry::from)); } } + + if self.tags.is_empty() { + self.tags = sync::get_tags(CWD).unwrap(); + } } fn move_selection(&mut self, up: bool) { @@ -190,6 +205,7 @@ impl Revlog { e: &'a LogEntry, selected: bool, txt: &mut Vec>, + tag: &'a str, ) { let count_before = txt.len(); @@ -204,7 +220,7 @@ impl Revlog { }; txt.push(Text::Styled( - Cow::from(e.hash.as_str()), + Cow::from(&e.hash[0..7]), if selected { STYLE_HASH_SELECTED } else { @@ -229,6 +245,19 @@ impl Revlog { STYLE_AUTHOR }, )); + txt.push(splitter.clone()); + txt.push(Text::Styled( + Cow::from(if tag.is_empty() { + String::from("") + } else { + format!(" {}", tag) + }), + if selected { + STYLE_TAG_SELECTED + } else { + STYLE_TAG + }, + )); txt.push(splitter); txt.push(Text::Styled( Cow::from(e.msg.as_str()),