Skip to content

Commit

Permalink
refactor: add closure for markdown commit section generation
Browse files Browse the repository at this point in the history
  • Loading branch information
oknozor committed Sep 8, 2020
1 parent 3cd77b6 commit 2537a32
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 90 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
/target
Cargo.lock
tests/dummy_repo
.idea
Empty file added README.md
Empty file.
4 changes: 2 additions & 2 deletions src/bin/dummy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use cocha::get_changelog_from_tags;
use cocha::get_changelog;

fn main() {
let oid_ch = get_changelog("f09ead914c65ceedf06d0daf5d920d7bd26e6a84", "6cb24ca7befdbf24dee1c98a3f29d3c4e0474b75").unwrap();
let oid_ch = get_changelog("ed849a93096262f4eb706061dee71af730572946", "396c3f29c55e0905609e6641b99897b8a5d50f33").unwrap();
println!("{}", oid_ch);
println!("TAGS =================");
let tag_ch = get_changelog_from_tags("0.0.1", "0.0.2").unwrap();
let tag_ch = get_changelog_from_tags("0.1.0", "0.2.0").unwrap();
println!("{}", tag_ch);
}
130 changes: 79 additions & 51 deletions src/git/changelog.rs
Original file line number Diff line number Diff line change
@@ -1,70 +1,98 @@
use crate::git::commit::Commit;
use crate::git::changelog::CommitType::*;

pub struct Changelog {
pub from: String,
pub to: String,
pub date: String,
pub commits: Vec<Commit>,
pub from: String,
pub to: String,
pub date: String,
pub commits: Vec<Commit>,
}

impl Changelog {
pub fn markdown_header() -> String {
let mut out =
#"# Changelog
const HEADER: &str = r#"# Changelog
All notable changes to this project will be documented in this file. See [conventional commits](https://www.conventionalcommits.org/) for commit guidelines.
"#;
}
pub fn tag_diff_to_markdown(&mut self) -> String {
let mut out = String::new();
out.push_str(&format!("## {}..{} - {}\n\n", self.from, self.to, self.date));

out.push_str("### Features\n\n");
self.commits.drain_filter(|commit|commit.commit_type == "feat")
.for_each(|commit|out.push_str(&commit.description));

out.push_str("### Bug Fixes\n\n");
self.commits.drain_filter(|commit|commit.commit_type == "fix")
.for_each(|commit|out.push_str(&commit.description));

out.push_str("### Performance Improvements\n\n");
self.commits.drain_filter(|commit|commit.commit_type == "perf")
.for_each(|commit|out.push_str(&commit.description));

out.push_str("### Revert\n\n");
self.commits.drain_filter(|commit|commit.commit_type == "revert")
.for_each(|commit|out.push_str(&commit.description));
enum CommitType<'a> {
Feature,
BugFix,
Chore,
Revert,
Performances,
Documentation,
Style,
Refactoring,
Test,
Build,
Ci,
Custom(&'a str, &'a str),
}

out.push_str("### Misellaneous Chores\n\n");
self.commits.drain_filter(|commit|commit.commit_type == "chore")
.for_each(|commit|out.push_str(&commit.description));
impl CommitType<'_> {
fn get_key(&self) -> &str {
match self {
Feature => "feat",
BugFix => "fix",
Chore => "chore",
Revert => "revert",
Performances => "perf",
Documentation => "docs",
Style => "style",
Refactoring => "refactor",
Test => "test",
Build => "build",
Ci => "ci",
Custom(key, _) => key
}
}

out.push_str("### Documentation\n\n");
self.commits.drain_filter(|commit|commit.commit_type == "docs")
.for_each(|commit|out.push_str(&commit.description));
fn get_markdown_title(&self) -> &str {
match self {
Feature => "Feature",
BugFix => "Bug Fixes",
Chore => "Misellaneous Chores",
Revert => "Revert",
Performances => "Performance Improvements",
Documentation => "Documentation",
Style => "Style",
Refactoring => "Refactoring",
Test => "Tests",
Build => "Build System",
Ci => "Continuous Integration",
Custom(_, value) => value,
}
}
}

out.push_str("### Style\n\n");
self.commits.drain_filter(|commit|commit.commit_type == "style")
.for_each(|commit|out.push_str(&commit.description));
impl Changelog {
pub fn tag_diff_to_markdown(&mut self) -> String {
let mut out = String::new();
out.push_str(&format!("## {}..{} - {}\n\n", self.from, self.to, self.date));

out.push_str("### Refactoring\n\n");
self.commits.drain_filter(|commit|commit.commit_type == "refactor")
.for_each(|commit|out.push_str(&commit.description));
let mut add_commit_section = |commit_type: CommitType| {
let commits: Vec<Commit> = self.commits.drain_filter(|commit| commit.commit_type == commit_type.get_key()).collect();

out.push_str("### Tests\n\n");
self.commits.drain_filter(|commit|commit.commit_type == "test")
.for_each(|commit|out.push_str(&commit.description));

out.push_str("### Build System\n\n");
self.commits.drain_filter(|commit|commit.commit_type == "build")
.for_each(|commit|out.push_str(&commit.description));
if !commits.is_empty() {
out.push_str(&format!("### {}\n\n", commit_type.get_markdown_title()));
commits.iter().for_each(|commit| out.push_str(&commit.description));
}
};

out.push_str("### Continuous Integration\n\n");
self.commits.drain_filter(|commit|commit.commit_type == "ci")
.for_each(|commit|out.push_str(&commit.description));
add_commit_section(CommitType::Feature);
add_commit_section(CommitType::BugFix);
add_commit_section(CommitType::Performances);
add_commit_section(CommitType::Revert);
add_commit_section(CommitType::Chore);
add_commit_section(CommitType::Documentation);
add_commit_section(CommitType::Style);
add_commit_section(CommitType::Refactoring);
add_commit_section(CommitType::Test);
add_commit_section(CommitType::Build);
add_commit_section(CommitType::Ci);

// TODO: add commit type from config
// TODO: add commit type from config

out
}
out
}
}
84 changes: 48 additions & 36 deletions src/git/commit.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1,58 @@
use std::cmp::Ordering;

#[derive(Debug, Eq, PartialEq)]
pub struct Commit {
pub commit_type: String,
pub scope: Option<String>,
pub description: String,
pub commit_type: String,
pub scope: Option<String>,
pub description: String,
}

impl Commit {
pub(crate) fn from_raw_message(message: &str) -> Self {


let split : Vec<&str> = message.split(": ").collect();
let description = split[1].to_owned();

let left_part: Vec<&str> = split[0].split("(").collect();
let commit_type = left_part[0].to_owned();
let scope = left_part
.get(1)
.map(|scope| scope[0..scope.len() -1 ].to_owned());

Commit {
commit_type,
scope,
description,
}
pub(crate) fn from_raw_message(message: &str) -> Self {
let split: Vec<&str> = message.split(": ").collect();
let description = split[1].to_owned();

let left_part: Vec<&str> = split[0].split("(").collect();
let commit_type = left_part[0].to_owned();
let scope = left_part
.get(1)
.map(|scope| scope[0..scope.len() - 1].to_owned());

Commit {
commit_type,
scope,
description,
}
}
}

impl PartialOrd for Commit {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.scope.partial_cmp(&other.scope)
}
}

impl Ord for Commit {
fn cmp(&self, other: &Self) -> Ordering {
self.scope.cmp(&other.scope)
}
}

#[cfg(test)]
#[cfg(test)]
mod test {
use super::Commit;

#[test]
fn should_map_conventional_commit_message_to_struct() {
// Arrange
let message = "feat(database): add postgresql driver";

// Act
let commit = Commit::from_raw_message(message);
// Assert
assert_eq!(commit.commit_type, "feat".to_owned());
assert_eq!(commit.scope, Some("database".to_owned()));
assert_eq!(commit.description, "add postgresql driver".to_owned());
}
use super::Commit;

#[test]
fn should_map_conventional_commit_message_to_struct() {
// Arrange
let message = "feat(database): add postgresql driver";

// Act
let commit = Commit::from_raw_message(message);

// Assert
assert_eq!(commit.commit_type, "feat".to_owned());
assert_eq!(commit.scope, Some("database".to_owned()));
assert_eq!(commit.description, "add postgresql driver".to_owned());
}
}
1 change: 0 additions & 1 deletion tests/dummy_repo
Submodule dummy_repo deleted from bbbfc9

0 comments on commit 2537a32

Please sign in to comment.