use acorn_lib::prelude::PathBuf;
use acorn_lib::util::{files_all, files_from_git_branch, files_from_git_commit, files_from_gitlab_merge_request, filter_ignored};
use bon::Builder;
use clap::builder::{
styling::{Ansi256Color, AnsiColor},
Styles,
};
use clap::{ArgAction, Parser, Subcommand, ValueHint};
use clap_verbosity_flag::Verbosity;
pub mod arguments;
use arguments::{CheckCategory, Diagnostic, FileFormat, ReadabilityTypeArgument, Size, Target};
const PRIMARY_COLOR: u8 = 135;
const STYLES: Styles = Styles::styled()
.header(Ansi256Color(PRIMARY_COLOR).on_default().bold())
.usage(Ansi256Color(PRIMARY_COLOR).on_default().bold())
.literal(AnsiColor::White.on_default())
.placeholder(Ansi256Color(183).on_default());
#[derive(Builder, Clone, Debug, Default)]
#[builder(start_fn = init)]
pub struct CommandLineOptions {
pub path: Option<PathBuf>,
pub branch: Option<String>,
pub commit: Option<String>,
pub ignore: Option<String>,
pub output: Option<PathBuf>,
pub reference: Option<PathBuf>,
pub size: Option<Size>,
pub target: Option<Target>,
#[builder(default)]
pub exit_on_first_error: bool,
#[builder(default)]
pub merge_request: bool,
}
pub fn paths_from_options(path: &Option<PathBuf>, options: &Option<CommandLineOptions>) -> Vec<PathBuf> {
let extensions = Some(vec!["JSON", "YAML"]);
match options {
| Some(CommandLineOptions {
branch,
commit,
ignore,
merge_request,
..
}) => {
let files = if *merge_request {
files_from_gitlab_merge_request(extensions)
} else {
match commit {
| Some(hash) => files_from_git_commit(hash, extensions),
| None => match branch {
| Some(name) => files_from_git_branch(name, extensions),
| None => {
let value = match path {
| Some(x) => x.clone(),
| None => PathBuf::from("."),
};
files_all(value, extensions)
}
},
}
};
filter_ignored(files, ignore.clone())
}
| None => {
let value = match path {
| Some(x) => x.clone(),
| None => PathBuf::from("."),
};
files_all(value, extensions)
}
}
}
#[derive(Debug, Parser)]
#[command(
author,
version,
about,
verbatim_doc_comment,
styles(STYLES),
disable_help_flag = true,
disable_version_flag = true,
next_help_heading = "FLAGS",
subcommand_help_heading = "COMMANDS",
override_usage = "acorn [FLAGS] [COMMAND]"
)]
pub struct Arguments {
#[arg(short = 'X', long, value_name = "BOOL", help_heading = "FLAGS")]
pub offline: bool,
#[arg(default_value_t, short, long, value_name = "N", help_heading = "FLAGS")]
pub threads: usize,
#[command(flatten)]
pub verbose: Verbosity,
#[arg(short = 'V', long, help = "Prints version information", help_heading = "FLAGS")]
pub version: bool,
#[command(subcommand)]
pub command: Option<Commands>,
#[arg(short, long, action = ArgAction::Help, global = true, help = "Print help (see a summary with '-h')", help_heading = "FLAGS")]
pub help: Option<bool>,
}
#[derive(Debug, Subcommand)]
#[command(long_about = None)]
pub enum Commands {
#[clap(
verbatim_doc_comment,
next_help_heading = "FLAGS",
override_usage = "acorn check [OPTIONS] [FLAGS] <PATH>"
)]
Check {
#[arg(default_value = "./", required = false, value_name = "PATH", value_hint = ValueHint::DirPath, help_heading = "OPTIONS")]
path: Option<PathBuf>,
#[arg(short, long, value_name = "BRANCH", help_heading = "OPTIONS")]
branch: Option<String>,
#[arg(short, long, value_name = "COMMIT", help_heading = "OPTIONS")]
commit: Option<String>,
#[arg(short, long, value_name = "BOOL", help_heading = "FLAGS")]
disable_website_checks: bool,
#[arg(short, long = "exit-on-first-error", value_name = "BOOL", help_heading = "FLAGS")]
exit_on_first_error: bool,
#[arg(short, long, value_name = "REGEX", help_heading = "OPTIONS")]
ignore: Option<String>,
#[arg(short, long, value_name = "BOOL", help_heading = "FLAGS")]
format: bool,
#[arg(short, long = "merge-request", value_name = "BOOL", help_heading = "FLAGS")]
merge_request: bool,
#[arg(default_value_t, short, long = "readability-test", value_name = "METRIC", help_heading = "OPTIONS")]
readability_metric: ReadabilityTypeArgument,
#[arg(short, long, value_name = "LIST", value_delimiter = ',', help_heading = "OPTIONS")]
skip: Vec<CheckCategory>,
#[arg(long, value_name = "BOOL", help_heading = "FLAGS")]
skip_verify_checksum: bool,
#[command(flatten)]
verbose: Verbosity,
},
#[clap(verbatim_doc_comment, next_help_heading = "FLAGS")]
Doctor {
#[arg(short, long, value_name = "BOOL", help_heading = "FLAGS")]
fix: bool,
#[arg(short, long, value_name = "BOOL", help_heading = "FLAGS")]
interactive: bool,
#[arg(short, long, value_name = "BOOL", help_heading = "FLAGS")]
report: bool,
#[arg(default_value = "all", short, long, value_name = "LIST", value_delimiter = ',', help_heading = "OPTIONS")]
check: Vec<Diagnostic>,
#[command(flatten)]
verbose: Verbosity,
},
#[clap(verbatim_doc_comment, next_help_heading = "FLAGS")]
Download {
#[arg(default_value = "./buckets.json", short, long, value_name = "PATH", value_hint = ValueHint::FilePath, help_heading = "OPTIONS")]
buckets: Option<PathBuf>,
#[arg(default_value = "./content", short, long, value_name = "PATH", value_hint = ValueHint::DirPath, help_heading = "OPTIONS")]
output: Option<PathBuf>,
#[command(flatten)]
verbose: Verbosity,
},
#[clap(verbatim_doc_comment, next_help_heading = "FLAGS")]
Export {
#[arg(default_value = "./", required = false, value_name = "PATH", value_hint = ValueHint::DirPath, help_heading = "OPTIONS")]
path: Option<PathBuf>,
#[arg(short, long, value_name = "BRANCH", help_heading = "OPTIONS")]
branch: Option<String>,
#[arg(short, long, value_name = "COMMIT", help_heading = "OPTIONS")]
commit: Option<String>,
#[arg(default_value_t, short, long, value_name = "FORMAT", help_heading = "OPTIONS")]
format: FileFormat,
#[arg(short, long = "merge-request", value_name = "BOOL", help_heading = "FLAGS")]
merge_request: bool,
#[arg(default_value = "./export", short, long, value_name = "DIRECTORY", value_hint = ValueHint::DirPath, help_heading = "OPTIONS")]
output: Option<PathBuf>,
#[arg(short, long, value_name = "PATH", value_hint = ValueHint::FilePath, help_heading = "OPTIONS")]
reference: Option<PathBuf>,
#[arg(default_value_t, short, long, value_name = "SIZE", help_heading = "OPTIONS")]
size: Size,
#[arg(default_value_t, short, long, value_name = "TARGET", help_heading = "OPTIONS")]
target: Target,
#[command(flatten)]
verbose: Verbosity,
},
#[clap(verbatim_doc_comment, next_help_heading = "FLAGS")]
Format {
#[arg(default_value = "./", required = false, value_name = "PATH", value_hint = ValueHint::DirPath, help_heading = "OPTIONS")]
path: Option<PathBuf>,
#[arg(short, long, value_name = "BRANCH", help_heading = "OPTIONS")]
branch: Option<String>,
#[arg(short, long, value_name = "COMMIT", help_heading = "OPTIONS")]
commit: Option<String>,
#[arg(short, long = "dry-run", value_name = "BOOL", help_heading = "FLAGS")]
dry_run: bool,
#[arg(short, long, value_name = "REGEX", help_heading = "OPTIONS")]
ignore: Option<String>,
#[arg(short, long = "merge-request", value_name = "BOOL", help_heading = "FLAGS")]
merge_request: bool,
#[command(flatten)]
verbose: Verbosity,
},
#[clap(verbatim_doc_comment, next_help_heading = "FLAGS")]
Link {
#[arg(default_value = "./", required = false, value_name = "PATH", value_hint = ValueHint::DirPath, help_heading = "OPTIONS")]
path: Option<PathBuf>,
#[arg(short, long, value_name = "BRANCH", help_heading = "OPTIONS")]
branch: Option<String>,
#[arg(short, long, value_name = "COMMIT", help_heading = "OPTIONS")]
commit: Option<String>,
#[arg(short, long = "dry-run", value_name = "BOOL", help_heading = "FLAGS")]
dry_run: bool,
#[arg(short, long, value_name = "REGEX", help_heading = "OPTIONS")]
ignore: Option<String>,
#[arg(short, long = "merge-request", value_name = "BOOL", help_heading = "FLAGS")]
merge_request: bool,
#[command(flatten)]
verbose: Verbosity,
},
#[clap(verbatim_doc_comment)]
#[command(long_about = None)]
Schema {
#[command(subcommand)]
command: Option<SchemaCommands>,
},
}
#[derive(Debug, Subcommand)]
#[command(long_about = None)]
pub enum SchemaCommands {
Rad {},
Raid {},
}
#[cfg(test)]
mod tests;