From caa6ec31abdcf0f9115204c968eb01ec571abdcc Mon Sep 17 00:00:00 2001 From: Paul Delafosse Date: Tue, 13 Jul 2021 11:18:08 +0200 Subject: [PATCH] feat: add check from latest tag option coucou --- README.md | 9 +++++++++ src/bin/cog.rs | 11 ++++++++++- src/conventional/commit.rs | 2 +- src/git/hook.rs | 4 ++-- src/hook/parser.rs | 9 +++------ src/lib.rs | 16 ++++++++++++--- tests/git_test.rs | 40 ++++++++++++++++++++++++++++++++++++-- 7 files changed, 76 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 6dd09453..3a6e6ff1 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ features related to the conventional commit specification. Anything else shall b - [Pre bump hooks](#pre-bump-hooks) - [Post bump hooks](#post-bump-hooks) - [Builtin git hooks](#Builtin-git-hooks) + - [Github action](#Github action) - [Contributing](#Contributing) - [Licence](#Licence) @@ -233,6 +234,10 @@ ERROR - Your Mother Was A Hamster, And Your Father Smelt Of Elderberries - (c82c cause: invalid commit format : missing `: ` separator ``` +Additionally, you can check your history, starting from the latest tag to HEAD using `from-latest-tag` flag. +This is useful when your git repo started to use conventional commits from a certain point in history, and you +don't care about editing old commits. + ### Edit commit history Once you have spotted invalid commits you can quickly fix your commit history by running `cog edit`. @@ -466,6 +471,10 @@ Or one by one, specifying the hook name : cog install-hook pre-commit ``` +## Github action + +You can run cog check on github action using [cog-conventional-check](https://github.com/oknozor/cog-conventional-check) + ## Contributing Found a bug, have a suggestion for a new feature ? Please read the contribution guideline and submit an issue. diff --git a/src/bin/cog.rs b/src/bin/cog.rs index bb856194..ef0672ba 100644 --- a/src/bin/cog.rs +++ b/src/bin/cog.rs @@ -81,7 +81,9 @@ fn main() -> Result<()> { CHECK => { let cocogitto = CocoGitto::get()?; - cocogitto.check()?; + let subcommand = matches.subcommand_matches(CHECK).unwrap(); + let from_tag = subcommand.is_present("from-latest-tag"); + cocogitto.check(from_tag)?; } EDIT => { let cocogitto = CocoGitto::get()?; @@ -186,6 +188,13 @@ fn app<'a, 'b>() -> App<'a, 'b> { let check_command = SubCommand::with_name(CHECK) .settings(SUBCOMMAND_SETTINGS) .about("Verify all commit message against the conventional commit specification") + .arg( + Arg::with_name("from-latest-tag") + .help("Check commit history, starting from the latest tag to HEAD") + .short("l") + .takes_value(false) + .long("from-latest-tag"), + ) .display_order(1); let edit_command = SubCommand::with_name(EDIT) diff --git a/src/conventional/commit.rs b/src/conventional/commit.rs index d3c73143..08c7c196 100644 --- a/src/conventional/commit.rs +++ b/src/conventional/commit.rs @@ -180,11 +180,11 @@ impl Commit { ); Ok(CommitMessage { - description, commit_type, scope, body, footer, + description, is_breaking_change, }) } diff --git a/src/git/hook.rs b/src/git/hook.rs index af67a437..b0c20780 100644 --- a/src/git/hook.rs +++ b/src/git/hook.rs @@ -1,12 +1,12 @@ use crate::CocoGitto; use anyhow::Result; -use std::path::PathBuf; use std::fs::Permissions; #[cfg(target_family = "unix")] use std::os::unix::fs::PermissionsExt; use std::fs; +use std::path::Path; pub static PRE_PUSH_HOOK: &[u8] = include_bytes!("assets/pre-push"); pub static PREPARE_COMMIT_HOOK: &[u8] = include_bytes!("assets/prepare-commit-msg"); @@ -40,7 +40,7 @@ impl CocoGitto { } } -fn create_hook(path: &PathBuf, kind: HookKind) -> Result<()> { +fn create_hook(path: &Path, kind: HookKind) -> Result<()> { let (hook_path, hook_content) = match kind { HookKind::PrepareCommit => (path.join(PRE_COMMIT_HOOK_PATH), PREPARE_COMMIT_HOOK), HookKind::PrePush => (path.join(PRE_PUSH_HOOK_PATH), PRE_PUSH_HOOK), diff --git a/src/hook/parser.rs b/src/hook/parser.rs index fc8e1ca0..298a76e4 100644 --- a/src/hook/parser.rs +++ b/src/hook/parser.rs @@ -60,12 +60,9 @@ impl HookExpr { fn scan_hook_entry(hook_entry: &str) -> Option { match hook_entry.find(DELIMITER_START) { - Some(start) => match hook_entry.find(DELIMITER_END) { - Some(end) => Some(HookExpr::from_str( - &hook_entry[start + DELIMITER_START.len()..end], - )), - None => None, - }, + Some(start) => hook_entry + .find(DELIMITER_END) + .map(|end| HookExpr::from_str(&hook_entry[start + DELIMITER_START.len()..end])), None => None, } } diff --git a/src/lib.rs b/src/lib.rs index 22cf49bf..16a5a582 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,7 +27,6 @@ use conventional::version::{parse_pre_release, VersionIncrement}; use git::repository::Repository; use git2::{Oid, RebaseOptions}; use hook::Hook; -use itertools::Itertools; use log::filter::CommitFilters; use semver::Version; use settings::AuthorSetting; @@ -269,8 +268,17 @@ impl CocoGitto { Ok(()) } - pub fn check(&self) -> Result<()> { - let from = self.repository.get_first_commit()?; + #[allow(unstable_name_collisions)] + pub fn check(&self, check_from_latest_tag: bool) -> Result<()> { + let from = if check_from_latest_tag { + self.repository.get_latest_tag_oid().unwrap_or_else(|_err| { + println!("No previous tag found, falling back to first commit"); + self.repository.get_first_commit().unwrap() + }) + } else { + self.repository.get_first_commit()? + }; + let to = self.repository.get_head_commit_oid()?; let commits = self.repository.get_commit_range(from, to)?; let errors: Vec = commits @@ -281,6 +289,8 @@ impl CocoGitto { .map(|err| err.unwrap_err()) .collect(); + use itertools::Itertools; + if errors.is_empty() { let msg = "No errored commits".green(); println!("{}", msg); diff --git a/tests/git_test.rs b/tests/git_test.rs index ee5717ad..3ed6c9c1 100644 --- a/tests/git_test.rs +++ b/tests/git_test.rs @@ -44,7 +44,7 @@ fn check_commit_history_ok() -> Result<()> { let gitto = CocoGitto::get()?; - assert!(gitto.check().is_ok()); + assert!(gitto.check(false).is_ok()); Ok(()) } @@ -61,6 +61,42 @@ fn check_commit_history_err() -> Result<()> { let gitto = CocoGitto::get()?; - assert!(gitto.check().is_err()); + assert!(gitto.check(false).is_err()); + Ok(()) +} + +#[test] +fn check_commit_ok_from_latest_tag() -> Result<()> { + let tmp = TempDir::new()?; + std::env::set_current_dir(&tmp)?; + git_init("commit_ok_from_tag")?; + std::env::set_current_dir(&tmp.path().join("commit_ok_from_tag"))?; + + create_empty_config()?; + git_commit("this one should not be picked")?; + git_tag("0.1.0")?; + git_commit("feat: another commit")?; + + let gitto = CocoGitto::get()?; + + assert!(gitto.check(true).is_ok()); + Ok(()) +} + +#[test] +fn check_commit_err_from_latest_tag() -> Result<()> { + let tmp = TempDir::new()?; + std::env::set_current_dir(&tmp)?; + git_init("commit_err_from_tag")?; + std::env::set_current_dir(&tmp.path().join("commit_err_from_tag"))?; + + create_empty_config()?; + git_commit("this one should not be picked")?; + git_tag("0.1.0")?; + git_commit("Oh no!")?; + + let gitto = CocoGitto::get()?; + + assert!(gitto.check(true).is_err()); Ok(()) }