Skip to content

Commit

Permalink
Merge pull request #337 from HallerPatrick/master
Browse files Browse the repository at this point in the history
Add JSON Output Support
  • Loading branch information
o2sh authored Dec 9, 2020
2 parents b48efa3 + ffcb73e commit 4be57b5
Show file tree
Hide file tree
Showing 12 changed files with 166 additions and 20 deletions.
14 changes: 8 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ image = "0.23.12"
regex = "1"
error-chain = "0.12"
toml = "0.5.7"
serde = "1.0.118"
serde_json = "1.0.60"

[target.'cfg(windows)'.dependencies]
ansi_term = "0.12"
Expand Down
8 changes: 7 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,17 @@ fn run() -> Result<()> {
return Err("please run onefetch inside of a non-bare git repository".into());
}

let format = config.format.clone();

let info = info::Info::new(config)?;

let mut printer = Printer::new(io::BufWriter::new(io::stdout()), info);

printer.print()?;
match format.as_str() {
"human" => printer.print()?,
"json" => printer.print_json()?,
_ => printer.print()?,
}

Ok(())
}
Expand Down
12 changes: 12 additions & 0 deletions src/onefetch/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub struct Cli {
pub excluded: Vec<String>,
pub print_languages: bool,
pub print_package_managers: bool,
pub format: String,
pub true_color: bool,
pub art_off: bool,
pub text_colors: Vec<String>,
Expand Down Expand Up @@ -228,6 +229,15 @@ impl Cli {
.takes_value(true)
.help("Ignore all files & directories matching EXCLUDE."),
)
.arg(
Arg::with_name("format")
.short("f")
.long("format")
.help("Select a output format.")
.takes_value(true)
.default_value("human")
.possible_values(&["human", "json"])
)
.get_matches();

let true_color = cli_utils::is_truecolor_terminal();
Expand All @@ -236,6 +246,7 @@ impl Cli {
let no_color_palette = matches.is_present("no-color-palette");
let print_languages = matches.is_present("languages");
let print_package_managers = matches.is_present("package-managers");
let format = matches.value_of("format").map(String::from).unwrap();

let fields_to_hide: Vec<String> = if let Some(values) = matches.values_of("disable-fields")
{
Expand Down Expand Up @@ -331,6 +342,7 @@ impl Cli {
excluded,
print_languages,
print_package_managers,
format,
true_color,
text_colors,
art_off,
Expand Down
15 changes: 15 additions & 0 deletions src/onefetch/commit_info.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use git2::Oid;
use serde::ser::SerializeStruct;
use serde::Serialize;

pub struct CommitInfo {
commit: Oid,
Expand Down Expand Up @@ -27,3 +29,16 @@ impl std::fmt::Display for CommitInfo {
}
}
}

impl Serialize for CommitInfo {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut state = serializer.serialize_struct("CommitInfo", 2)?;
state.serialize_field("refs", &self.refs)?;
state
.serialize_field("oid", &self.commit.to_string().chars().take(7).collect::<String>())?;
state.end()
}
}
30 changes: 22 additions & 8 deletions src/onefetch/git_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,20 @@ pub fn get_number_of_commits(git_history: &[String]) -> String {
number_of_commits.to_string()
}

pub fn get_packed_size(dir: &str) -> Result<String> {
pub fn get_packed_size(repo_size: String, files_count: Option<u64>) -> Result<String> {
match files_count {
Some(files_count) => {
let res = format!("{} ({} files)", repo_size, files_count.to_string());
Ok(res)
}
None => {
let res = repo_size;
Ok(res.into())
}
}
}

pub fn get_repo_size(dir: &str) -> String {
let output = Command::new("git")
.arg("-C")
.arg(dir)
Expand All @@ -88,10 +101,13 @@ pub fn get_packed_size(dir: &str) -> Result<String> {
let size_line = lines.split('\n').find(|line| line.starts_with("size-pack:"));

let repo_size = match size_line {
None => "",
Some(size_str) => &(size_str[11..]),
None => String::new(),
Some(size_str) => String::from(&(size_str[11..])),
};
repo_size
}

pub fn get_files_count(dir: &str) -> Option<u64> {
let output = Command::new("git")
.arg("-C")
.arg(dir)
Expand All @@ -106,15 +122,13 @@ pub fn get_packed_size(dir: &str) -> Result<String> {

let lines = output.to_string();
let files_list = lines.split('\n');
let mut files_count: u128 = 0;
let mut files_count: u64 = 0;
for _file in files_list {
files_count += 1;
}
files_count -= 1; // As splitting giving one line extra(blank).
let res = repo_size.to_owned() + (" (") + &(files_count.to_string()) + (" files)");
Ok(res)
Some(files_count)
} else {
let res = repo_size;
Ok(res.into())
None
}
}
61 changes: 58 additions & 3 deletions src/onefetch/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use {
language::Language, license::Detector, repo::Repo, text_color::TextColor,
},
colored::{Color, ColoredString, Colorize},
serde::ser::SerializeStruct,
serde::Serialize,
};

pub struct Info {
Expand All @@ -23,6 +25,8 @@ pub struct Info {
repo_url: String,
number_of_commits: String,
lines_of_code: usize,
packed_repo_size: String,
files_count: Option<u64>,
repo_size: String,
license: String,
pub dominant_language: Language,
Expand Down Expand Up @@ -168,12 +172,12 @@ impl std::fmt::Display for Info {
)?;
}

if !self.config.disabled_fields.size && !self.repo_size.is_empty() {
if !self.config.disabled_fields.size && !self.packed_repo_size.is_empty() {
writeln!(
f,
"{}{}",
&self.get_formatted_subtitle_label("Size"),
&self.repo_size.color(self.text_colors.info),
&self.packed_repo_size.color(self.text_colors.info),
)?;
}

Expand Down Expand Up @@ -222,7 +226,11 @@ impl Info {
let authors = git_utils::get_authors(&git_history, config.number_of_authors);
let last_change = git_utils::get_date_of_last_commit(&git_history)?;
let git_version = cli_utils::get_git_version()?;
let repo_size = git_utils::get_packed_size(&workdir)?;

let files_count = git_utils::get_files_count(&workdir);
let repo_size = git_utils::get_repo_size(&workdir);
let packed_repo_size = git_utils::get_packed_size(repo_size.clone(), files_count)?;

let license = Detector::new()?.get_license(&workdir)?;
let dependencies = deps::DependencyDetector::new().get_dependencies(&workdir)?;
let (languages, lines_of_code) =
Expand Down Expand Up @@ -253,6 +261,8 @@ impl Info {
repo_url,
number_of_commits,
lines_of_code,
packed_repo_size,
files_count,
repo_size,
license,
dominant_language,
Expand Down Expand Up @@ -371,3 +381,48 @@ impl Info {
}
}
}

impl Serialize for Info {
fn serialize<S>(&self, serializer: S) -> serde::export::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut state = serializer.serialize_struct("Info", 21)?;
// Only collect the version number
let git_version_split: Vec<String> =
self.git_version.split(" ").map(|s| s.to_string()).collect();

state.serialize_field("gitVersion", &git_version_split[2])?;
state.serialize_field("gitUsername", &self.git_username)?;
state.serialize_field("repoName", &self.repo_name)?;
state.serialize_field("numberOfTags", &self.number_of_tags)?;
state.serialize_field("numberOfBranches", &self.number_of_branches)?;
state.serialize_field("headRefs", &self.head_refs)?;
state.serialize_field("pendingChanges", &self.pending_changes)?;
state.serialize_field("version", &self.version)?;
state.serialize_field("creationDate", &self.creation_date)?;
state.serialize_field("languages", &self.languages)?;

let dependencies_split: Vec<String> =
self.dependencies.split(" ").map(|s| s.to_string()).collect();

state.serialize_field("dependencies", &dependencies_split[0])?;
state.serialize_field("authors", &self.authors)?;
state.serialize_field("lastChange", &self.last_change)?;
state.serialize_field("repoUrl", &self.repo_url)?;
state.serialize_field("numberOfCommits", &self.number_of_commits)?;
state.serialize_field("linesOfCode", &self.lines_of_code)?;
state.serialize_field("packedRepoSize", &self.packed_repo_size)?;
state.serialize_field("repoSize", &self.repo_size)?;

match &self.files_count {
Some(files_count) => state.serialize_field("filesCount", files_count)?,
None => {}
}

state.serialize_field("license", &self.license)?;
state.serialize_field("dominantLanguage", &self.dominant_language)?;
state.serialize_field("textColors", &self.text_colors)?;
state.end()
}
}
3 changes: 2 additions & 1 deletion src/onefetch/language.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use {
crate::onefetch::{error::*, utils::num_to_color},
colored::Color,
regex::Regex,
serde::Serialize,
std::collections::HashMap,
std::env,
strum::{EnumIter, EnumString, IntoStaticStr},
Expand All @@ -22,7 +23,7 @@ macro_rules! define_languages {
($( { $name:ident, $ascii:literal, $display:literal, $colors:expr $(, $serialize:literal )? } ),* ,) => {

#[strum(serialize_all = "lowercase")]
#[derive(PartialEq, Eq, Hash, Clone, EnumString, EnumIter, IntoStaticStr)]
#[derive(PartialEq, Eq, Hash, Clone, EnumString, EnumIter, IntoStaticStr, Serialize)]
pub enum Language {
$(
$( #[strum(serialize = $serialize)] )?
Expand Down
1 change: 1 addition & 0 deletions src/onefetch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ mod language;
mod license;
pub mod printer;
pub mod repo;
mod serializer;
mod text_color;
mod utils;
5 changes: 5 additions & 0 deletions src/onefetch/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ impl<W: Write> Printer<W> {
Ok(())
}

pub fn print_json(&mut self) -> Result<()> {
write!(self.writer, "{}", serde_json::to_string_pretty(&self.info).unwrap())?;
Ok(())
}

fn get_ascii(&self) -> &str {
let language = if let Some(ascii_language) = &self.info.config.ascii_language {
ascii_language
Expand Down
23 changes: 23 additions & 0 deletions src/onefetch/serializer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use {colored::Color, serde::Serialize};

#[derive(Serialize)]
#[serde(remote = "Color")]
pub enum ColorDef {
Black,
Red,
Green,
Yellow,
Blue,
Magenta,
Cyan,
White,
BrightBlack,
BrightRed,
BrightGreen,
BrightYellow,
BrightBlue,
BrightMagenta,
BrightCyan,
BrightWhite,
TrueColor { r: u8, g: u8, b: u8 },
}
12 changes: 11 additions & 1 deletion src/onefetch/text_color.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
use {crate::onefetch::utils::num_to_color, colored::Color};
use {
crate::onefetch::serializer::ColorDef, crate::onefetch::utils::num_to_color, colored::Color,
serde::Serialize,
};

#[derive(Serialize)]
pub struct TextColor {
#[serde(with = "ColorDef")]
pub title: Color,
#[serde(with = "ColorDef")]
pub tilde: Color,
#[serde(with = "ColorDef")]
pub underline: Color,
#[serde(with = "ColorDef")]
pub subtitle: Color,
#[serde(with = "ColorDef")]
pub colon: Color,
#[serde(with = "ColorDef")]
pub info: Color,
}

Expand Down

0 comments on commit 4be57b5

Please sign in to comment.