Skip to content

Commit

Permalink
feat: release categories for changelog
Browse files Browse the repository at this point in the history
  • Loading branch information
Coenraad Human committed May 29, 2024
1 parent 6f0217a commit 984ae6b
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 57 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"kind": "bin"
}
},
"args": ["version"],
"args": ["changelog"],
"cwd": "${workspaceFolder}"
},
{
Expand Down
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# Changelog

## 1.7.0
## 1.8.0

|Version|Commit Type|Description|Breaking Change|Deprecation|Author|Committer|
|---|---|---|---|---|---|---|
|1.8.0|Feature|Release categories for changelog.| | |Coenraad Human <Coenraad Human>|Coenraad Human <Coenraad Human>|
|1.7.0|Feature|Use gib entrypoint as alias for gib in container.| | |Coenraad Human <Coenraad Human>|Coenraad Human <Coenraad Human>|
|1.6.0|CI|Use entrypoint sh instead of gib directly.| | |Coenraad Human <Coenraad Human>|Coenraad Human <Coenraad Human>|
|1.6.0|Feature|Author and committer on changelog.| | |Coenraad Human <Coenraad Human>|Coenraad Human <Coenraad Human>|
Expand Down
9 changes: 5 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "gib"
version = "1.7.0"
version = "1.8.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand All @@ -9,8 +9,9 @@ edition = "2021"
clap = { version = "4.5.4", features = ["derive"] }
git2 = { version = "0.18.3" }
fancy-regex = { version = "0.13.0" }
chrono = { version = "0.4.38" }
lazy_static = { version = "1.4.0" }
Inflector = { version = "0.11.4" }

openssl = { version = "0.10.64", features = ["vendored"] }
libz-sys = { version = "1.1.16" }
lazy_static = "1.4.0"
Inflector = "0.11.4"
libz-sys = { version = "1.1.16" }
79 changes: 56 additions & 23 deletions src/commands/changelog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,84 @@ extern crate inflector;
use inflector::Inflector;

use crate::conventional::create_conventional_commit;
use crate::git::{retrieve_branch_commits, Commit};
use crate::git::{retrieve_branch_commits, retrieve_tags};
use crate::semantic::{add_commit_to_version, Version};


// Todo: find a nice template engine for Rust to create the changelog document:
// Todo: use map for tag associated with commits on current branch:
pub fn run(path: Option<String>, _commit_git_hook: Option<String>, scope_filter: Option<String>) {
let commits: Vec<Commit> = retrieve_branch_commits(path);
let commits = retrieve_branch_commits(path.clone());
let tags = retrieve_tags(path.clone());

let mut version = Version::new(0, 0, 0);

let mut past_tag_version = Version::new(0, 0, 0);
let mut simple_changelog = "".to_owned();
let mut unreleased_count: usize = 0;

simple_changelog.insert_str(0, "</table>\n");
simple_changelog.insert_str(0, " </tbody>\n");

for commit in commits.iter().rev() {
match commit.message {
Some(ref message) => {
version = add_commit_to_version(version, create_conventional_commit(message), scope_filter.clone());
version = add_commit_to_version(&version, create_conventional_commit(message), scope_filter.clone());

match create_conventional_commit(message) {
Some(conventional_commit) => {
simple_changelog.insert_str(0, " </tr>\n");
simple_changelog.insert_str(0, &format!(" <td>{}</td>\n", commit.committer.to_changelog_string()));
simple_changelog.insert_str(0, &format!(" <td>{}</td>\n", commit.author.to_changelog_string()));
simple_changelog.insert_str(0, &format!(" <td>{}</td>\n", if conventional_commit.is_deprecrated { 'X' } else { ' ' }));
simple_changelog.insert_str(0, &format!(" <td>{}</td>\n", if conventional_commit.is_breaking { 'X' } else { ' ' }));
simple_changelog.insert_str(0, &format!(" <td>{}.</td>\n", conventional_commit.commit_description.to_sentence_case()));
simple_changelog.insert_str(0, &format!(" <td>{}</td>\n", conventional_commit.commit_type));
simple_changelog.insert_str(0, &format!(" <td>{}</td>\n", version.format()));
simple_changelog.insert_str(0, " <tr>\n");
},
None => (),
}

simple_changelog.insert_str(0,
&format!("|{}|{}|{}.|{}|{}|{}|{}|\n",
version.format(),
conventional_commit.commit_type,
conventional_commit.commit_description.to_sentence_case(),
if conventional_commit.is_breaking { 'X' } else { ' ' },
if conventional_commit.is_deprecrated { 'X' } else { ' ' },
commit.author.to_string(),
commit.committer.to_string()
).as_str()
);
let found_version_as_tag = tags.clone()
.into_iter()
.filter(|tag| tag.contains(version.format().as_str()))
.count() > 0;

},
None => todo!(),
let version_updated_since_previous_releate = !past_tag_version.equal(&version);

if found_version_as_tag && version_updated_since_previous_releate && unreleased_count != 0 {
simple_changelog.insert_str(0, " </tr>\n");
simple_changelog.insert_str(0, &format!(" <td colspan=\"7\"><em><strong>Release: {}</strong></em></td>\n", version.format()));
simple_changelog.insert_str(0, " <tr>\n");

past_tag_version = version.clone();
unreleased_count = 0;
} else {
unreleased_count = unreleased_count + 1;
}
},
None => {},
}
}

simple_changelog.insert_str(0, "|---|---|---|---|---|---|---|\n");

simple_changelog.insert_str(0, "|Version|Commit Type|Description|Breaking Change|Deprecation|Author|Committer|\n");

simple_changelog.insert_str(0, &format!("## {}\n\n", version.format()));
if unreleased_count != 0 {
simple_changelog.insert_str(0, " </tr>\n");
simple_changelog.insert_str(0, " <td colspan=\"7\"><em><strong>Unreleased</strong></em>\n");
simple_changelog.insert_str(0, " <tr>\n");
}

simple_changelog.insert_str(0, " <tbody>\n");
simple_changelog.insert_str(0, " </thead>\n");
simple_changelog.insert_str(0, " </tr>\n");
simple_changelog.insert_str(0, " <th>Committer</th>\n");
simple_changelog.insert_str(0, " <th>Author</th>\n");
simple_changelog.insert_str(0, " <th>Deprecation</th>\n");
simple_changelog.insert_str(0, " <th>Breaking Change</th>\n");
simple_changelog.insert_str(0, " <th>Description</th>\n");
simple_changelog.insert_str(0, " <th>Commit Type</th>\n");
simple_changelog.insert_str(0, " <th>Version</th>\n");
simple_changelog.insert_str(0, " <tr>\n");
simple_changelog.insert_str(0, " <thead>\n");
simple_changelog.insert_str(0, "<table>\n");
simple_changelog.insert_str(0, "# Changelog\n\n");

print!("{}", simple_changelog);
Expand Down
10 changes: 5 additions & 5 deletions src/commands/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,29 @@ pub fn run(path: Option<String>, major:bool, minor: bool, patch: bool, commit_gi
for commit in commits.iter().rev() {
match commit.message {
Some(ref message) => {
version = add_commit_to_version(version, create_conventional_commit(message), scope_filter.clone())
version = add_commit_to_version(&version, create_conventional_commit(message), scope_filter.clone())
},
None => {},
}
}

match commit_git_hook {
Some(message) => {
version = add_commit_to_version(version, create_conventional_commit(message.as_str()), scope_filter.clone())
version = add_commit_to_version(&version, create_conventional_commit(message.as_str()), scope_filter.clone())
},
None => {},
}

if major {
version = add_impact_to_version(version, Impact::MAJOR);
version = add_impact_to_version(&version, Impact::MAJOR);
}

if minor {
version = add_impact_to_version(version, Impact::MINOR);
version = add_impact_to_version(&version, Impact::MINOR);
}

if patch {
version = add_impact_to_version(version, Impact::PATCH);
version = add_impact_to_version(&version, Impact::PATCH);
}

version.print();
Expand Down
59 changes: 39 additions & 20 deletions src/git.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use std::env;

use git2::Repository;

pub struct Author {
Expand All @@ -11,18 +10,18 @@ pub struct Author {

impl Author {

pub fn to_string(&self) -> String {
pub fn to_changelog_string(&self) -> String {
let name = match self.name {
Some(ref value) => value,
None => "Not Available",
};

let email = match self.name {
let email = match self.email {
Some(ref value) => value,
None => "not available",
None => return format!("{}", name),
};

format!("{} <{}>", name, email)
format!("<a href=\"{}\">{}</a>", email, name)
}

}
Expand All @@ -36,18 +35,18 @@ pub struct Committer {

impl Committer {

pub fn to_string(&self) -> String {
pub fn to_changelog_string(&self) -> String {
let name = match self.name {
Some(ref value) => value,
None => "Not Available",
};

let email = match self.name {
let email = match self.email {
Some(ref value) => value,
None => "not available",
None => return format!("{}", name),
};

format!("{} <{}>", name, email)
format!("<a href=\"{}\">{}</a>", email, name)
}

}
Expand All @@ -57,16 +56,22 @@ pub struct Commit {
pub message: Option<String>,
pub author: Author,
pub committer: Committer,
pub is_tagged: bool,

}

impl Commit {

}

pub fn retrieve_branch_commits(path: Option<String>) -> Vec<Commit> {
let found_path = match path {
fn retrieve_git_repository(path: String) -> Repository {
match Repository::open(path) {
Ok(repository) => repository,
Err(_) => panic!("Couldn't open repository"),
}
}

fn determine_path(path: Option<String>) -> String {
match path {
Some(path) => path,
None => {
match env::current_dir() {
Expand All @@ -77,12 +82,28 @@ pub fn retrieve_branch_commits(path: Option<String>) -> Vec<Commit> {
Err(_) => panic!("System can't find current directory"),
}
},
};
}
}

let repo: Repository = match Repository::open(found_path) {
Ok(repository) => repository,
Err(_) => panic!("Couldn't open repository"),
};
pub fn retrieve_tags(path: Option<String>) -> Vec<String> {
let found_path = determine_path(path);
let repo = retrieve_git_repository(found_path);

match repo.tag_names(None) {
Ok(found_tags) => {
found_tags
.into_iter()
.filter(|value| value.is_some())
.map(|value| value.unwrap().to_owned())
.collect()
},
Err(_) => Vec::new(),
}
}

pub fn retrieve_branch_commits(path: Option<String>) -> Vec<Commit> {
let found_path = determine_path(path);
let repo = retrieve_git_repository(found_path);

let mut revwalk = match repo.revwalk() {
Ok(found_revwalk) => found_revwalk,
Expand All @@ -97,8 +118,6 @@ pub fn retrieve_branch_commits(path: Option<String>) -> Vec<Commit> {
return revwalk.map(|step| -> Commit {
match step {
Ok(oid) => {
let is_tagged = repo.find_tag(oid).is_ok();

match repo.find_commit(oid) {
Ok(commit) => {
let message = match commit.message() {
Expand Down Expand Up @@ -128,7 +147,7 @@ pub fn retrieve_branch_commits(path: Option<String>) -> Vec<Commit> {
},
};

Commit { message, author, committer, is_tagged }
Commit { message, author, committer }
},
Err(_) => panic!("Could not retrieve oid of commit"),
}
Expand Down
12 changes: 10 additions & 2 deletions src/semantic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ impl Version {
pub fn format(&self) -> String {
format!("{}.{}.{}", self.major, self.minor, self.patch)
}

pub fn equal(&self, comparator: &Version) -> bool {
self.major == comparator.major && self.minor == comparator.minor && self.patch == comparator.patch
}

pub fn clone(&self) -> Version {
Version { major: self.major, minor: self.minor, patch: self.patch }
}
}

pub enum Impact {
Expand All @@ -29,7 +37,7 @@ pub enum Impact {
NONE
}

pub fn add_commit_to_version(version: Version, optional_commit: Option<ConventionalCommit>, scope_filter: Option<String>) -> Version {
pub fn add_commit_to_version(version: &Version, optional_commit: Option<ConventionalCommit>, scope_filter: Option<String>) -> Version {
match optional_commit {
Some(commit) => {

Expand All @@ -53,7 +61,7 @@ pub fn add_commit_to_version(version: Version, optional_commit: Option<Conventio
}
}

pub fn add_impact_to_version(version: Version, impact: Impact) -> Version {
pub fn add_impact_to_version(version: &Version, impact: Impact) -> Version {
match impact {
Impact::MAJOR => Version::new(version.major + 1, 0, 0),
Impact::MINOR => Version::new(version.major, version.minor + 1, 0),
Expand Down
2 changes: 1 addition & 1 deletion src/tests/semantic_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{conventional::create_conventional_commit, semantic::{add_commit_to_v
fn add_commit_to_version_test(expected_major: u8, expected_minor: u8, expected_patch: u8, commit_message: &str, scope_filter: Option<String>) {
let version = Version { major: 0, minor: 0 , patch: 0 };

let result = add_commit_to_version(version, create_conventional_commit(commit_message), scope_filter);
let result = add_commit_to_version(&version, create_conventional_commit(commit_message), scope_filter);
assert_eq!(result.major, expected_major, "Major match");
assert_eq!(result.minor, expected_minor, "Minor match");
assert_eq!(result.patch, expected_patch, "Patch match");
Expand Down

0 comments on commit 984ae6b

Please sign in to comment.