Sebastian Thielthanks clippydd94cc53 years agoHistory
177 lines · 4.6 KB · Rust
RawDownload
use std::sync::atomic::{AtomicUsize, Ordering}; use git::bstr::{BStr, ByteSlice};use git_repository as git;use itertools::Itertools; use crate::hours::core::HOURS_PER_WORKDAY; #[derive(Debug)]pub struct WorkByPerson {    pub name: Vec<&'static BStr>,    pub email: Vec<&'static BStr>,    pub hours: f32,    pub num_commits: u32,    pub files: FileStats,    pub lines: LineStats,} impl<'a> WorkByPerson {    pub fn merge(&mut self, other: &'a WorkByEmail) {        if !self.name.contains(&other.name) {            self.name.push(other.name);        }        if !self.email.contains(&other.email) {            self.email.push(other.email);        }        self.num_commits += other.num_commits;        self.hours += other.hours;        self.files.add(&other.files);        self.lines.add(&other.lines);    }} impl<'a> From<&'a WorkByEmail> for WorkByPerson {    fn from(w: &'a WorkByEmail) -> Self {        WorkByPerson {            name: vec![w.name],            email: vec![w.email],            hours: w.hours,            num_commits: w.num_commits,            files: w.files,            lines: w.lines,        }    }} impl WorkByPerson {    pub fn write_to(        &self,        total_hours: f32,        total_files: Option<FileStats>,        total_lines: Option<LineStats>,        mut out: impl std::io::Write,    ) -> std::io::Result<()> {        writeln!(            out,            "{} <{}>",            self.name.iter().join(", "),            self.email.iter().join(", ")        )?;        writeln!(out, "{} commits found", self.num_commits)?;        writeln!(            out,            "total time spent: {:.02}h ({:.02} 8h days, {:.02}%)",            self.hours,            self.hours / HOURS_PER_WORKDAY,            (self.hours / total_hours) * 100.0        )?;        if let Some(total) = total_files {            writeln!(                out,                "total files added/removed/modified: {}/{}/{} ({:.02}%)",                self.files.added,                self.files.removed,                self.files.modified,                (self.files.sum() / total.sum()) * 100.0            )?;        }        if let Some(total) = total_lines {            writeln!(                out,                "total lines added/removed: {}/{} ({:.02}%)",                self.lines.added,                self.lines.removed,                (self.lines.sum() / total.sum()) * 100.0            )?;        }        Ok(())    }} #[derive(Debug)]pub struct WorkByEmail {    pub name: &'static BStr,    pub email: &'static BStr,    pub hours: f32,    pub num_commits: u32,    pub files: FileStats,    pub lines: LineStats,} /// File statistics for a particular commit.#[derive(Debug, Default, Copy, Clone)]pub struct FileStats {    /// amount of added files    pub added: usize,    /// amount of removed files    pub removed: usize,    /// amount of modified files    pub modified: usize,} /// Line statistics for a particular commit.#[derive(Debug, Default, Copy, Clone)]pub struct LineStats {    /// amount of added lines    pub added: usize,    /// amount of removed lines    pub removed: usize,} impl FileStats {    pub fn add(&mut self, other: &FileStats) -> &mut Self {        self.added += other.added;        self.removed += other.removed;        self.modified += other.modified;        self    }     pub fn added(&self, other: &FileStats) -> Self {        let mut a = *self;        a.add(other);        a    }     pub fn sum(&self) -> f32 {        (self.added + self.removed + self.modified) as f32    }} impl LineStats {    pub fn add(&mut self, other: &LineStats) -> &mut Self {        self.added += other.added;        self.removed += other.removed;        self    }     pub fn added(&self, other: &LineStats) -> Self {        let mut a = *self;        a.add(other);        a    }     pub fn sum(&self) -> f32 {        (self.added + self.removed) as f32    }} pub fn add_lines(line_stats: bool, lines_counter: Option<&AtomicUsize>, mut lines: &mut LineStats, id: git::Id<'_>) {    if let Some(Ok(blob)) = line_stats.then(|| id.object()) {        let nl = blob.data.lines_with_terminator().count();        lines.added += nl;        if let Some(c) = lines_counter {            c.fetch_add(nl, Ordering::SeqCst);        }    }} pub fn remove_lines(line_stats: bool, lines_counter: Option<&AtomicUsize>, mut lines: &mut LineStats, id: git::Id<'_>) {    if let Some(Ok(blob)) = line_stats.then(|| id.object()) {        let nl = blob.data.lines_with_terminator().count();        lines.removed += nl;        if let Some(c) = lines_counter {            c.fetch_add(nl, Ordering::SeqCst);        }    }}