Skip to content

Commit

Permalink
feat(commit): add markdown formating
Browse files Browse the repository at this point in the history
  • Loading branch information
oknozor committed Sep 8, 2020
1 parent 2537a32 commit 925adb4
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 76 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ edition = "2018"

[dependencies]
git2 = "0.13.6"
anyhow = "1.0.31"
anyhow = "1.0.31"
clap = "2.33.3"
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Work in progress

basic steps :
1. generate markdown changelog from commit/tag to commit/tag
2. optionally open for edition
3. merge with existing CHANGELOG.md or create it
4. optionally commit the result

To do :
- [ ] project name
- [ ] clap CLI
- [ ] append to existing changelog file
- [ ] edit commmand vs auto commit mode
6 changes: 2 additions & 4 deletions src/bin/dummy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ use cocha::get_changelog_from_tags;
use cocha::get_changelog;

fn main() {
let oid_ch = get_changelog("ed849a93096262f4eb706061dee71af730572946", "396c3f29c55e0905609e6641b99897b8a5d50f33").unwrap();
let oid_ch = get_changelog("8806a55727b6c1767cca5d494599623fbb5dd1dd", "7672d8405f9736729bc275fcbdaa8676085fd00c" ).unwrap();
println!("{}", oid_ch);
println!("TAGS =================");
let tag_ch = get_changelog_from_tags("0.1.0", "0.2.0").unwrap();
println!("{}", tag_ch);
//let tag_ch = get_changelog_from_tags("0.1.0", "0.2.0").unwrap();
}
64 changes: 6 additions & 58 deletions src/git/changelog.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use crate::git::commit::Commit;
use crate::git::changelog::CommitType::*;
use crate::git::commit::{Commit, CommitType};

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

const HEADER: &str = r#"# Changelog
Expand All @@ -14,68 +13,17 @@ const HEADER: &str = r#"# Changelog
"#;


enum CommitType<'a> {
Feature,
BugFix,
Chore,
Revert,
Performances,
Documentation,
Style,
Refactoring,
Test,
Build,
Ci,
Custom(&'a str, &'a str),
}

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
}
}

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,
}
}
}

impl Changelog {
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));

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();
let commits: Vec<Commit> = self.commits.drain_filter(|commit| commit.commit_type == commit_type).collect();

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));
commits.iter().for_each(|commit| out.push_str(&commit.to_markdown()));
}
};

Expand Down
103 changes: 94 additions & 9 deletions src/git/commit.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,123 @@
use std::cmp::Ordering;
use git2::Commit as Git2Commit;
use crate::git::commit::CommitType::*;


#[derive(Debug, Eq, PartialEq)]
pub struct Commit {
pub commit_type: String,
pub scope: Option<String>,
pub description: String,
pub struct Commit<'a> {
pub(crate) shorthand: String,
pub(crate) commit_type: CommitType<'a>,
pub(crate) scope: Option<String>,
pub(crate) description: String,
pub(crate) author: String,
}

impl Commit {
pub(crate) fn from_raw_message(message: &str) -> Self {
impl Commit<'_> {
pub fn from_git_commit(commit: Git2Commit) -> Self {
let shorthand = commit.as_object().short_id().unwrap().as_str().unwrap().to_string();
let message = commit.message().unwrap();
let author = commit.author().name().unwrap_or_else(|| "").to_string();
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 commit_type = CommitType::from(left_part[0]);
let scope = left_part
.get(1)
.map(|scope| scope[0..scope.len() - 1].to_owned());

Commit {
shorthand,
commit_type,
scope,
description,
author,
}
}

pub fn to_markdown(&self) -> String {
format!("{} - {} - {}", self.shorthand, self.description, self.author)
}
}

#[derive(Eq, PartialEq, Debug)]
pub(crate) enum CommitType<'a> {
Feature,
BugFix,
Chore,
Revert,
Performances,
Documentation,
Style,
Refactoring,
Test,
Build,
Ci,
Custom(&'a str, &'a str),
}

impl CommitType<'_> {
pub(crate) 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
}
}

pub(crate) 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,
}
}
}

impl From<&str> for CommitType<'_> {
fn from(commit_type: &str) -> Self {
match commit_type {
"feat" => Feature,
"fix" => BugFix,
"chore" => Chore,
"revert" => Revert,
"perf" => Performances,
"docs" => Documentation,
"style" => Style,
"refactor" => Refactoring,
"test" => Test,
"build" => Build,
"ci" => Ci,
_ => panic!("unknown commit type {}", commit_type)
}
}
}

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

impl Ord for Commit {
impl Ord for Commit<'_> {
fn cmp(&self, other: &Self) -> Ordering {
self.scope.cmp(&other.scope)
}
Expand Down
7 changes: 3 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub fn get_changelog_from_tags(from: &str, to: &str) -> anyhow::Result<String> {
Ok(changelog.tag_diff_to_markdown())
}

fn get_changelog_from_oid_range(from: Oid, to: Oid) -> anyhow::Result<Vec<Commit>> {
fn get_changelog_from_oid_range<'a>(from: Oid, to: Oid) -> anyhow::Result<Vec<Commit<'a>>> {
let repo = Repository::open("./")?;

// Ensure commit exists
Expand All @@ -57,9 +57,8 @@ fn get_changelog_from_oid_range(from: Oid, to: Oid) -> anyhow::Result<Vec<Commit
break
}

let git_commit = repo.find_commit(oid)?;
let raw_message = git_commit.message().unwrap();
commits.push(Commit::from_raw_message(raw_message));
let commit = repo.find_commit(oid)?;
commits.push(Commit::from_git_commit(commit));
}

Ok(commits)
Expand Down

0 comments on commit 925adb4

Please sign in to comment.