From bde2d866b6f57e8df443660dba97d7780877a9a4 Mon Sep 17 00:00:00 2001 From: Nikos Filippakis Date: Tue, 1 Oct 2019 17:46:00 +0200 Subject: [PATCH] Display current commit and its references' names Signed-off-by: Nikos Filippakis --- src/main.rs | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index e5d94daf4..f3c5a901f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ extern crate clap; use colored::Color; use colored::*; -use git2::Repository; +use git2::{Repository, Oid}; use license::License; use clap::{App, Arg}; use std::{ @@ -28,6 +28,7 @@ type Result = result::Result; struct Info { project_name: String, + current_commit: CommitInfo, version: String, dominant_language: Language, languages: Vec<(Language, f64)>, @@ -54,6 +55,13 @@ impl fmt::Display for Info { self.project_name )?; + writeln!( + buffer, + "{}{}", + "HEAD: ".color(color).bold(), + self.current_commit + )?; + writeln!( buffer, "{}{}", @@ -220,6 +228,30 @@ fn true_len(line: &str) -> usize { .len() } +struct CommitInfo { + commit: Oid, + refs: Vec, +} + +impl CommitInfo { + fn new(commit: Oid, refs: Vec) -> CommitInfo { + CommitInfo { commit, refs } + } +} + +impl fmt::Display for CommitInfo { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.refs.len() > 0 { + let refs_str = self.refs.iter().map(|ref_name| { + ref_name.as_str() + }).collect::>().join(", "); + write!(f, "{} ({})", self.commit, refs_str) + } else { + write!(f, "{}", self.commit) + } + } +} + #[derive(PartialEq, Eq, Hash, Clone)] enum Language { Assembly, @@ -303,6 +335,7 @@ fn main() -> Result<()> { let dominant_language = languages_stat_vec[0].0.clone(); let authors = get_authors(&dir, 3); + let current_commit_info = get_current_commit_info(&dir)?; let config = get_configuration(&dir)?; let version = get_version(&dir)?; let commits = get_commits(&dir)?; @@ -310,6 +343,7 @@ fn main() -> Result<()> { let info = Info { project_name: config.repository_name, + current_commit: current_commit_info, version, dominant_language, languages: languages_stat_vec, @@ -527,6 +561,31 @@ fn get_authors(dir: &str, n: usize) -> Vec { authors } +fn get_current_commit_info(dir: &str) -> Result { + let repo = Repository::open(dir).map_err(|_| Error::NotGitRepo)?; + let head = repo.head().map_err(|_| Error::ReferenceInfoError)?; + let head_oid = head.target().ok_or(Error::ReferenceInfoError)?; + let refs = repo.references().map_err(|_| Error::ReferenceInfoError)?; + let refs_info = refs.into_iter().filter_map(|reference| { + match reference { + Ok(reference) => { + match (reference.target(), reference.shorthand()) { + (Some(oid), Some(shorthand)) if oid == head_oid => { + Some(if reference.is_tag() { + String::from("tags/") + shorthand + } else { + String::from(shorthand) + }) + }, + _ => None + } + }, + Err(_) => None, + } + }).collect::>(); + Ok(CommitInfo::new(head_oid, refs_info)) +} + fn get_total_loc(languages: &tokei::Languages) -> usize { languages .values() @@ -670,6 +729,8 @@ enum Error { ReadDirectory, /// Not in a Git Repo NotGitRepo, + /// Error while getting branch info + ReferenceInfoError, } impl fmt::Debug for Error { @@ -680,6 +741,7 @@ impl fmt::Debug for Error { Error::NoGitData => "Could not retrieve git configuration data", Error::ReadDirectory => "Could not read directory", Error::NotGitRepo => "This is not a Git Repo", + Error::ReferenceInfoError => "Error while retrieving reference information", }; write!(f, "{}", content) }