Compare commits

..

No commits in common. "e7df35a765185a61a57c04c0cd71dbe59c4e860b" and "260bcb7ca5acb4561c86b48f5798e6e1a026f30a" have entirely different histories.

14 changed files with 474 additions and 768 deletions

996
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -19,22 +19,21 @@ workspace = true
[dependencies]
color-eyre = "0.6.2"
globset = "0.4.14"
lazy_static = "1.4.0"
owo-colors = "4.0.0"
globset = "0.4.9"
owo-colors = "3.5.0"
subprocess = "0.2.9"
supports-color = "2.1.0"
tera = "1.19.1"
supports-color = "1.3.0"
tera = "1.17.1"
[dependencies.clap]
features = ["derive"]
version = "4.4.18"
version = "4.0.18"
[dependencies.hooked-config]
path = "../hooked-config"
version = "0.1.0"
[dev-dependencies]
assert_cmd = "2.0.13"
insta = "1.34.0"
test-case = "3.3.1"
assert_cmd = "2.0.5"
insta = "1.21.0"
test-case = "2.2.2"

View File

@ -2,10 +2,7 @@
use std::path::PathBuf;
use {
clap::{Args as Arguments, Parser, Subcommand},
hooked_config::NoiseLevel,
};
use clap::{Args as Arguments, Parser, Subcommand};
#[cfg(debug_assertions)]
mod cli_reference;
@ -72,10 +69,6 @@ pub struct RunArgs {
/// The hook type to run.
#[clap(value_parser = crate::HOOK_TYPES)]
pub hook_type: String,
/// The noise level to override for all hooks.
#[clap(long)]
pub noise_level: Option<NoiseLevel>,
}
/// The `cli-reference` subcommand arguments.

View File

@ -5,31 +5,34 @@ use std::{io::Read, process::exit};
use {
color_eyre::{eyre::eyre, Result},
hooked_config::{Config, ExitAction},
owo_colors::OwoColorize,
owo_colors::{OwoColorize, Style},
subprocess::{Exec, Redirection},
supports_color::Stream,
};
use crate::{
cli::RunArgs,
printer::{print, PrintType, PRINT_STYLE},
utilities::{globset_from_strings, plural},
};
use crate::utilities::{globset_from_strings, plural};
/// The `run` subcommand.
pub fn hooked_run(config: Config, args: RunArgs) -> Result<()> {
let cli_noise_level = args.noise_level.as_ref();
let global_noise_level = &config.general.noise_level;
pub fn hooked_run(config: Config, hook_type: String) -> Result<()> {
let (success_style, warn_style, error_style, skipped_style) =
if let Some(_support) = supports_color::on(Stream::Stdout) {
let shared_style = Style::new().bold();
(
shared_style.green(),
shared_style.yellow(),
shared_style.red(),
shared_style.blue(),
)
} else {
(Style::new(), Style::new(), Style::new(), Style::new())
};
if args.hook_type == "pre-commit" {
if hook_type == "pre-commit" {
let hook_count = config.pre_commit.len();
print(
format!(
println!(
"Hooked: Running {} pre-commit {}.",
hook_count,
plural(hook_count, "hook", None)
),
cli_noise_level.unwrap_or(global_noise_level),
PrintType::Info,
);
'hook_loop: for hook in config.pre_commit {
@ -43,14 +46,10 @@ pub fn hooked_run(config: Config, args: RunArgs) -> Result<()> {
.capture()?
.stdout_str();
if !staged_files.lines().any(|line| globs.is_match(line)) {
print(
format!(
println!(
"\t{} {}",
"".style(PRINT_STYLE.skipped),
hook_name.style(PRINT_STYLE.skipped)
),
cli_noise_level.unwrap_or(global_noise_level),
PrintType::Info,
"".style(skipped_style),
hook_name.style(skipped_style)
);
continue 'hook_loop;
}
@ -85,32 +84,16 @@ pub fn hooked_run(config: Config, args: RunArgs) -> Result<()> {
output
};
let (stop, print_output, prefix, style, print_type) =
let (stop, print_output, prefix, style) =
match (exit_status.success(), hook.on_failure) {
(true, _) => {
(false, false, "", PRINT_STYLE.success, PrintType::Info)
}
(false, ExitAction::Continue) => {
(false, true, "", PRINT_STYLE.warn, PrintType::Warn)
}
(false, ExitAction::Stop) => {
(true, true, "", PRINT_STYLE.error, PrintType::Error)
}
(true, _) => (false, false, "", success_style),
(false, ExitAction::Continue) => (false, true, "", warn_style),
(false, ExitAction::Stop) => (true, true, "", error_style),
};
let hook_noise_level =
hook.noise_level.as_ref().unwrap_or(global_noise_level);
print(
format!("\t{} {}", prefix.style(style), hook_name.style(style)),
cli_noise_level.unwrap_or(hook_noise_level),
print_type,
);
println!("\t{} {}", prefix.style(style), hook_name.style(style));
if !output.is_empty() && print_output {
print(
output,
cli_noise_level.unwrap_or(hook_noise_level),
PrintType::Info,
);
println!("{}", output);
}
if stop {

View File

@ -17,7 +17,6 @@ pub const DEFAULT_TEMPLATE: &str = include_str!("templates/default.sh");
pub const HOOK_TYPES: [&str; 1] = ["pre-commit"];
mod cli;
mod printer;
mod utilities;
fn main() -> Result<()> {
@ -36,7 +35,7 @@ fn main() -> Result<()> {
}
MainSubcommands::Run(sub_args) => {
cli::hooked_run(config, sub_args)?;
cli::hooked_run(config, sub_args.hook_type)?;
}
#[cfg(debug_assertions)]

View File

@ -1,76 +0,0 @@
//! Shared logic for printing output to the terminal.
use {
hooked_config::NoiseLevel, lazy_static::lazy_static, owo_colors::Style,
std::fmt::Display, supports_color::Stream,
};
/// The available types to print output as.
#[derive(Debug, Eq, PartialEq)]
pub enum PrintType {
/// Print the output as an error line.
Error,
/// Print the output as a warning line.
Warn,
/// Print the output as an information line.
Info,
}
/// The available print styles for colorized output.
#[derive(Debug)]
pub struct PrintStyles {
/// The style for errored hooks output.
pub error: Style,
/// The style for skipped hooks output.
pub skipped: Style,
/// The style for succesful hooks output.
pub success: Style,
/// The style for hooks with warnings.
pub warn: Style,
}
lazy_static! {
pub static ref PRINT_STYLE: PrintStyles = {
let (success_style, warn_style, error_style, skipped_style) =
if let Some(_support) = supports_color::on(Stream::Stdout) {
let shared_style = Style::new().bold();
(
shared_style.green(),
shared_style.yellow(),
shared_style.red(),
shared_style.blue(),
)
} else {
(Style::new(), Style::new(), Style::new(), Style::new())
};
PrintStyles {
error: error_style,
skipped: skipped_style,
success: success_style,
warn: warn_style,
}
};
}
/// Print something to the terminal according to a given [`NoiseLevel`] and
/// [`PrintType`].
pub fn print<D: Display>(
something: D,
noise_level: &NoiseLevel,
print_type: PrintType,
) {
let should_print = match (noise_level, print_type) {
// Only output errors under the quiet noise level.
(NoiseLevel::Quiet, PrintType::Error) => true,
(NoiseLevel::Quiet, _) => false,
// Output everything under loud.
(NoiseLevel::Loud | NoiseLevel::Standard | NoiseLevel::Minimal, _) => true,
};
if !should_print {
return;
}
println!("{something}")
}

View File

@ -18,12 +18,12 @@ workspace = true
[dependencies]
color-eyre = "0.6.2"
toml = "0.8.8"
toml = "0.5.9"
[dependencies.serde]
features = ["derive"]
version = "1.0.195"
version = "1.0.147"
[dev-dependencies]
insta = "1.34.0"
test-case = "3.3.1"
insta = "1.21.0"
test-case = "2.2.2"

View File

@ -3,7 +3,7 @@
use serde::{Deserialize, Serialize};
/// The noise level Hooked should output logs with.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[derive(Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum NoiseLevel {
/// Output only errors.
@ -22,16 +22,3 @@ impl Default for NoiseLevel {
Self::Standard
}
}
// Implement `From<String>` so we can use Clap's automatic parsing in the CLI.
impl From<String> for NoiseLevel {
fn from(value: String) -> Self {
match value.to_lowercase().as_str() {
"quiet" => Self::Quiet,
"loud" => Self::Loud,
"standard" => Self::Standard,
"minimal" => Self::Minimal,
_ => NoiseLevel::default(),
}
}
}

View File

@ -12,7 +12,8 @@ pub struct PreCommit {
pub name: Option<String>,
/// The noise level this task should output with.
pub noise_level: Option<NoiseLevel>,
#[serde(default)]
pub noise_level: NoiseLevel,
/// What to do when the hook exits with a non-zero status code.
#[serde(default)]

View File

@ -5,6 +5,7 @@ template = "test.sh"
[[pre_commit]]
name = "Pre Commit 1"
noise_level = "quiet"
command = "exit 0"
staged = ["*.txt"]
on_failure = "continue"

View File

@ -9,7 +9,7 @@ use insta::assert_snapshot;
fn test_serialize() {
let pre_commit_command = PreCommit {
name: Some("Command Test".to_string()),
noise_level: None,
noise_level: NoiseLevel::Quiet,
on_failure: ExitAction::Continue,
staged: vec!["*.txt".to_string()],
task: Task {
@ -20,7 +20,7 @@ fn test_serialize() {
let pre_commit_script = PreCommit {
name: Some("Script Test".to_string()),
noise_level: Some(NoiseLevel::Loud),
noise_level: NoiseLevel::Loud,
on_failure: ExitAction::Stop,
staged: vec![],
task: Task {

View File

@ -12,7 +12,7 @@ Config {
pre_commit: [
PreCommit {
name: None,
noise_level: None,
noise_level: Standard,
on_failure: Stop,
staged: [],
task: Task {

View File

@ -16,7 +16,7 @@ Config {
name: Some(
"Pre Commit 1",
),
noise_level: None,
noise_level: Quiet,
on_failure: Continue,
staged: [
"*.txt",
@ -32,9 +32,7 @@ Config {
name: Some(
"Pre Commit 2",
),
noise_level: Some(
Loud,
),
noise_level: Loud,
on_failure: Stop,
staged: [],
task: Task {

View File

@ -3,20 +3,21 @@ source: hooked-config/tests/serialize.rs
expression: to_string_pretty(&config).unwrap()
---
[general]
config = "Hooked.toml"
directory = "hooks"
noise_level = "standard"
config = 'Hooked.toml'
directory = 'hooks'
noise_level = 'standard'
[[pre_commit]]
name = "Command Test"
on_failure = "continue"
staged = ["*.txt"]
command = "exit 0"
name = 'Command Test'
noise_level = 'quiet'
on_failure = 'continue'
staged = ['*.txt']
command = 'exit 0'
[[pre_commit]]
name = "Script Test"
noise_level = "loud"
on_failure = "stop"
name = 'Script Test'
noise_level = 'loud'
on_failure = 'stop'
staged = []
script = "test.sh"
script = 'test.sh'