From 8b096fb9e1e5499577d3ff8d34997764f3ae2d2d Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Sat, 16 May 2020 20:14:27 +0200 Subject: [PATCH] support multiple tags per commit (#62) * support multiple tags per commit * update changelog * make sure clippy works in CI --- .github/workflows/ci.yml | 1 + CHANGELOG.md | 3 +++ Makefile | 2 +- asyncgit/src/sync/tags.rs | 53 ++++++++++++++++++++++++++++++++++++--- src/tabs/revlog/mod.rs | 14 +++++------ 5 files changed, 62 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 98882b0e..88762cf7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,6 +26,7 @@ jobs: - name: Run clippy run: | rustup component add clippy + cargo clean make clippy - name: Build Release run: make build-release diff --git a/CHANGELOG.md b/CHANGELOG.md index 2902ee05..1ac70f3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - better error message when trying to run outside of a valid git repo ([#56](https://github.com/extrawurst/gitui/issues/56)) - improve ctrl+c handling so it is checked first and no component needs to worry of blocking it +### Fixed +- support multiple tags per commit in log ([#61](https://github.com/extrawurst/gitui/issues/61)) + ## [0.2.3] - 2020-05-12 ### Added - support more navigation keys: home/end/pageUp/pageDown ([#43](https://github.com/extrawurst/gitui/issues/43)) diff --git a/Makefile b/Makefile index a61934fc..d060bb15 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ test: cargo test --workspace clippy: - cargo clean + cargo clean -p gitui -p asyncgit -p scopetime cargo clippy --all-features clippy-pedantic: diff --git a/asyncgit/src/sync/tags.rs b/asyncgit/src/sync/tags.rs index 3ef2dc80..ae84257f 100644 --- a/asyncgit/src/sync/tags.rs +++ b/asyncgit/src/sync/tags.rs @@ -3,14 +3,21 @@ use crate::error::Result; use scopetime::scope_time; use std::collections::HashMap; -/// hashmap of tag target commit hash to tag name -pub type Tags = HashMap; +/// hashmap of tag target commit hash to tag names +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 mut adder = |key: String, value: String| { + if let Some(key) = res.get_mut(&key) { + key.push(value) + } else { + res.insert(key, vec![value]); + } + }; let repo = repo(repo_path)?; @@ -21,10 +28,50 @@ pub fn get_tags(repo_path: &str) -> Result { 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); + adder(target_hash, tag_name); } } } Ok(res) } + +#[cfg(test)] +mod tests { + use super::*; + use crate::sync::tests::repo_init; + use git2::ObjectType; + + #[test] + fn test_smoke() { + let (_td, repo) = repo_init().unwrap(); + let root = repo.path().parent().unwrap(); + let repo_path = root.as_os_str().to_str().unwrap(); + + assert_eq!(get_tags(repo_path).unwrap().is_empty(), true); + } + + #[test] + fn test_multitags() { + let (_td, repo) = repo_init().unwrap(); + let root = repo.path().parent().unwrap(); + let repo_path = root.as_os_str().to_str().unwrap(); + + let sig = repo.signature().unwrap(); + let head_id = repo.head().unwrap().target().unwrap(); + let target = repo + .find_object( + repo.head().unwrap().target().unwrap(), + Some(ObjectType::Commit), + ) + .unwrap(); + + repo.tag("a", &target, &sig, "", false).unwrap(); + repo.tag("b", &target, &sig, "", false).unwrap(); + + assert_eq!( + get_tags(repo_path).unwrap()[&head_id.to_string()], + vec!["a", "b"] + ); + } +} diff --git a/src/tabs/revlog/mod.rs b/src/tabs/revlog/mod.rs index 7fc244ad..b380299c 100644 --- a/src/tabs/revlog/mod.rs +++ b/src/tabs/revlog/mod.rs @@ -167,7 +167,7 @@ impl Revlog { e: &'a LogEntry, selected: bool, txt: &mut Vec>, - tag: &'a str, + tags: Option, ) { let count_before = txt.len(); @@ -209,10 +209,10 @@ impl Revlog { )); txt.push(splitter.clone()); txt.push(Text::Styled( - Cow::from(if tag.is_empty() { - String::from("") + Cow::from(if let Some(tags) = tags { + format!(" {}", tags) } else { - format!(" {}", tag) + String::from("") }), if selected { STYLE_TAG_SELECTED @@ -250,10 +250,10 @@ impl DrawableComponent for Revlog { let mut txt = Vec::new(); for (idx, e) in self.items.items.iter().enumerate() { - let tag = if let Some(tag_name) = self.tags.get(&e.hash) { - tag_name.as_str() + let tag = if let Some(tags) = self.tags.get(&e.hash) { + Some(tags.join(" ")) } else { - "" + None }; Self::add_entry(e, idx == selection, &mut txt, tag); }