117 lines
4.5 KiB
Plaintext
Executable File
117 lines
4.5 KiB
Plaintext
Executable File
#!/usr/bin/env run-cargo-script
|
|
// cargo-deps: regex="1.3.9"
|
|
use std::{ env, fs, process };
|
|
use std::path::PathBuf;
|
|
use std::process::Command;
|
|
|
|
/// Git commit message format check util
|
|
///
|
|
/// Commit format MUST be <type>(<scope>): subject
|
|
///
|
|
/// Usage:
|
|
/// `commit-msg.crs usage`
|
|
///
|
|
/// Install:
|
|
/// `commit-msg.crs install`
|
|
fn main() {
|
|
let arg1 = env::args().nth(1).unwrap_or_else(|| {
|
|
exit_with_error_message("Commit message is EMPTY!");
|
|
});
|
|
|
|
if arg1 == "usage" || arg1 == "USAGE" {
|
|
print_usage(); return;
|
|
}
|
|
|
|
let is_install = arg1 == "install" || arg1 == "INSTALL";
|
|
let is_force_install = arg1 == "forceinstall" || arg1 == "FORCEINSTALL"
|
|
|| arg1 == "force-install" || arg1 == "FORCE-INSTALL"
|
|
|| arg1 == "force_install" || arg1 == "FORCE_INSTALL";
|
|
if is_install || is_force_install {
|
|
install_commit_msg(is_force_install); return;
|
|
}
|
|
|
|
let commit_message = fs::read_to_string(arg1).unwrap_or_else(|e| {
|
|
exit_with_error_message(&format!("Read commit message failed: {}", e));
|
|
});
|
|
|
|
let re = regex::Regex::new("^(feat|fix|docs|style|refactor|test|chore)(\\([\\w\\-_]+\\))?:\\s*.*").unwrap();
|
|
let is_commit_message_matches = re.is_match(&commit_message);
|
|
|
|
print_info(&format!("Commit message: {}{}{}", UNDER, commit_message.trim(), END));
|
|
if is_commit_message_matches {
|
|
print_ok("Commit message rule matches");
|
|
} else {
|
|
print_usage();
|
|
exit_with_error_message("Commit message rule is NOT matched");
|
|
}
|
|
}
|
|
|
|
const RED: &str = "\x1B[91m";
|
|
const GREEN: &str = "\x1B[92m";
|
|
const BOLD: &str = "\x1B[1m";
|
|
const UNDER: &str = "\x1B[4m";
|
|
const END: &str = "\x1B[0m";
|
|
|
|
fn print_usage() {
|
|
print_info(&format!(r#"Please follow the commit spec:
|
|
Format: {}<type>{}(<scope>){}: <subject>{}
|
|
<scope> is optional
|
|
|
|
feat: add hat wobble
|
|
^--^ ^------------^
|
|
| |
|
|
| +-> Summary in present tense.
|
|
|
|
|
+-------> Type: chore, docs, feat, fix, refactor, style, or test.
|
|
|
|
feat : new feature for the user, not a new feature for build script
|
|
fix : bug fix for the user, not a fix to a build script
|
|
docs : changes to the documentation
|
|
style : formatting, missing semi colons, etc; no production code change
|
|
refactor : refactoring production code, eg. renaming a variable
|
|
test : adding missing tests, refactoring tests; no production code change
|
|
chore : updating grunt tasks etc; no production code change
|
|
|
|
Reference: {}https://gist.github.com/joshbuchea/6f47e86d2510bce28f8e7f42ae84c716{}
|
|
or mirror: {}https://hatter.ink/wiki/view_raw.action?__access_token=PUBLIC&id=42{}
|
|
"#, BOLD, END, BOLD, END, UNDER, END, UNDER, END));
|
|
}
|
|
|
|
fn install_commit_msg(force: bool) {
|
|
let home_path = PathBuf::from(env::var("HOME").unwrap_or_else(|e| {
|
|
exit_with_error_message(&format!("Get env HOME failed: {}!", e));
|
|
}));
|
|
let commit_msg_crs = home_path.join("bin").join("commit-msg.crs");
|
|
if !commit_msg_crs.exists() {
|
|
exit_with_error_message(&format!("File {:?} NOT exists!", commit_msg_crs));
|
|
}
|
|
|
|
let git_hooks = PathBuf::from(".git").join("hooks");
|
|
if !git_hooks.exists() {
|
|
exit_with_error_message(&format!("Path {:?} NOT exists!", git_hooks));
|
|
}
|
|
let git_hooks_commit_msg = git_hooks.join("commit-msg");
|
|
if git_hooks_commit_msg.exists() && !force {
|
|
exit_with_error_message(&format!("File {:?} exists! or try forceinstall.", git_hooks_commit_msg));
|
|
}
|
|
|
|
let commit_msg_crs_content = fs::read_to_string(&commit_msg_crs).unwrap_or_else(|e| {
|
|
exit_with_error_message(&format!("Read file: {:?} failed: {}.", commit_msg_crs, e));
|
|
});
|
|
fs::write(&git_hooks_commit_msg, commit_msg_crs_content).unwrap_or_else(|e| {
|
|
exit_with_error_message(&format!("Write file: {:?} failed: {}.", git_hooks_commit_msg, e));
|
|
});
|
|
Command::new("chmod").args(&["+x", git_hooks_commit_msg.to_str().unwrap()]).output().unwrap_or_else(|e| {
|
|
exit_with_error_message(&format!("Apply executable permission on file: {:?} failed: {}.", git_hooks_commit_msg, e));
|
|
});
|
|
|
|
print_ok("Install commit-msg to repo successed!");
|
|
}
|
|
|
|
fn exit_with_error() -> ! { process::exit(1) }
|
|
fn exit_with_error_message(msg: &str) -> ! { print_error(msg); exit_with_error() }
|
|
|
|
fn print_info(msg: &str) { println!("{}[INFO ]{} {}", BOLD, END, msg); }
|
|
fn print_ok(msg: &str) { println!("{}{}[OK ]{} {}{}{}", GREEN, BOLD, END, GREEN, msg, END); }
|
|
fn print_error(msg: &str) { println!("{}{}[ERROR]{} {}{}{}", RED, BOLD, END, RED, msg, END); }
|