Add additional continuous integration checks (#574)

Add GitHub Actions checks:

- Clippy is placated
- Rustfmt doesn't produce any changes
- Shell completion scripts are current
This commit is contained in:
Casey Rodarmor 2020-01-15 02:16:13 -08:00 committed by GitHub
parent 85e8015702
commit ed991cb509
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 173 additions and 106 deletions

32
.github/workflows/rust.yaml vendored Normal file
View File

@ -0,0 +1,32 @@
name: Rust
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Install
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
components: clippy, rustfmt
override: true
- name: Version
run: |
rustup --version
cargo --version
cargo clippy --version
- name: Lint
run: cargo clippy
- name: Format
run: cargo fmt -- --check
- name: Completion Scripts
run: |
for script in completions/*; do
shell=${script##*.}
cargo run -- --completions $shell > $script
done
git diff --no-ext-diff --quiet --exit-code

View File

@ -1,5 +1,5 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.11. .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.11.
.TH JUST "1" "December 2019" "just 0.5.4" "JUST MANUAL" .TH JUST "1" "January 2020" "just 0.5.4" "JUST MANUAL"
.SH NAME .SH NAME
just \- save and run commands just \- save and run commands
.SH DESCRIPTION .SH DESCRIPTION
@ -57,6 +57,10 @@ Print version information
.TP .TP
Print colorful output [default: auto] Print colorful output [default: auto]
[possible values: auto, always, never] [possible values: auto, always, never]
.HP
\fB\-\-completions\fR <SHELL>
.IP
Print shell completion script for <SHELL> [possible values: zsh, bash, fish, powershell, elvish]
.TP .TP
\fB\-f\fR, \fB\-\-justfile\fR <JUSTFILE> \fB\-f\fR, \fB\-\-justfile\fR <JUSTFILE>
Use <JUSTFILE> as justfile. Use <JUSTFILE> as justfile.

View File

@ -73,7 +73,7 @@ impl<'src> Analyzer<'src> {
let mut settings = Settings::new(); let mut settings = Settings::new();
for (_, set) in self.sets.into_iter() { for (_, set) in self.sets {
match set.value { match set.value {
Setting::Shell(shell) => { Setting::Shell(shell) => {
assert!(settings.shell.is_none()); assert!(settings.shell.is_none());
@ -191,7 +191,7 @@ impl<'src> Analyzer<'src> {
// Make sure the target recipe exists // Make sure the target recipe exists
match recipes.get(alias.target.lexeme()) { match recipes.get(alias.target.lexeme()) {
Some(target) => Ok(alias.resolve(target.clone())), Some(target) => Ok(alias.resolve(Rc::clone(target))),
None => Err(token.error(UnknownAliasTarget { None => Err(token.error(UnknownAliasTarget {
alias: alias.name.lexeme(), alias: alias.name.lexeme(),
target: alias.target.lexeme(), target: alias.target.lexeme(),

View File

@ -12,12 +12,12 @@ pub(crate) struct Color {
} }
impl Color { impl Color {
fn restyle(self, style: Style) -> Color { fn restyle(self, style: Style) -> Self {
Color { style, ..self } Self { style, ..self }
} }
fn redirect(self, stream: Stream) -> Color { fn redirect(self, stream: Stream) -> Self {
Color { Self {
atty: atty::is(stream), atty: atty::is(stream),
..self ..self
} }
@ -31,76 +31,76 @@ impl Color {
} }
} }
pub(crate) fn fmt(fmt: &Formatter) -> Color { pub(crate) fn fmt(fmt: &Formatter) -> Self {
if fmt.alternate() { if fmt.alternate() {
Color::always() Self::always()
} else { } else {
Color::never() Self::never()
} }
} }
pub(crate) fn auto() -> Color { pub(crate) fn auto() -> Self {
Color { Self {
use_color: UseColor::Auto, use_color: UseColor::Auto,
..default() ..default()
} }
} }
pub(crate) fn always() -> Color { pub(crate) fn always() -> Self {
Color { Self {
use_color: UseColor::Always, use_color: UseColor::Always,
..default() ..default()
} }
} }
pub(crate) fn never() -> Color { pub(crate) fn never() -> Self {
Color { Self {
use_color: UseColor::Never, use_color: UseColor::Never,
..default() ..default()
} }
} }
pub(crate) fn stderr(self) -> Color { pub(crate) fn stderr(self) -> Self {
self.redirect(Stream::Stderr) self.redirect(Stream::Stderr)
} }
pub(crate) fn stdout(self) -> Color { pub(crate) fn stdout(self) -> Self {
self.redirect(Stream::Stdout) self.redirect(Stream::Stdout)
} }
pub(crate) fn doc(self) -> Color { pub(crate) fn doc(self) -> Self {
self.restyle(Style::new().fg(Blue)) self.restyle(Style::new().fg(Blue))
} }
pub(crate) fn error(self) -> Color { pub(crate) fn error(self) -> Self {
self.restyle(Style::new().fg(Red).bold()) self.restyle(Style::new().fg(Red).bold())
} }
pub(crate) fn warning(self) -> Color { pub(crate) fn warning(self) -> Self {
self.restyle(Style::new().fg(Yellow).bold()) self.restyle(Style::new().fg(Yellow).bold())
} }
pub(crate) fn banner(self) -> Color { pub(crate) fn banner(self) -> Self {
self.restyle(Style::new().fg(Cyan).bold()) self.restyle(Style::new().fg(Cyan).bold())
} }
pub(crate) fn command(self) -> Color { pub(crate) fn command(self) -> Self {
self.restyle(Style::new().bold()) self.restyle(Style::new().bold())
} }
pub(crate) fn parameter(self) -> Color { pub(crate) fn parameter(self) -> Self {
self.restyle(Style::new().fg(Cyan)) self.restyle(Style::new().fg(Cyan))
} }
pub(crate) fn message(self) -> Color { pub(crate) fn message(self) -> Self {
self.restyle(Style::new().bold()) self.restyle(Style::new().bold())
} }
pub(crate) fn annotation(self) -> Color { pub(crate) fn annotation(self) -> Self {
self.restyle(Style::new().fg(Purple)) self.restyle(Style::new().fg(Purple))
} }
pub(crate) fn string(self) -> Color { pub(crate) fn string(self) -> Self {
self.restyle(Style::new().fg(Green)) self.restyle(Style::new().fg(Green))
} }
@ -126,8 +126,8 @@ impl Color {
} }
impl Default for Color { impl Default for Color {
fn default() -> Color { fn default() -> Self {
Color { Self {
use_color: UseColor::Auto, use_color: UseColor::Auto,
atty: false, atty: false,
style: Style::new(), style: Style::new(),

View File

@ -237,7 +237,7 @@ impl Config {
} }
} }
pub(crate) fn from_matches(matches: &ArgMatches) -> ConfigResult<Config> { pub(crate) fn from_matches(matches: &ArgMatches) -> ConfigResult<Self> {
let invocation_directory = env::current_dir().context(config_error::CurrentDir)?; let invocation_directory = env::current_dir().context(config_error::CurrentDir)?;
let verbosity = Verbosity::from_flag_occurrences(matches.occurrences_of(arg::VERBOSE)); let verbosity = Verbosity::from_flag_occurrences(matches.occurrences_of(arg::VERBOSE));
@ -368,7 +368,7 @@ impl Config {
|| matches.occurrences_of(arg::SHELL) > 0 || matches.occurrences_of(arg::SHELL) > 0
|| matches.occurrences_of(arg::SHELL_ARG) > 0; || matches.occurrences_of(arg::SHELL_ARG) > 0;
Ok(Config { Ok(Self {
dry_run: matches.is_present(arg::DRY_RUN), dry_run: matches.is_present(arg::DRY_RUN),
highlight: !matches.is_present(arg::NO_HIGHLIGHT), highlight: !matches.is_present(arg::NO_HIGHLIGHT),
quiet: matches.is_present(arg::QUIET), quiet: matches.is_present(arg::QUIET),
@ -394,7 +394,7 @@ impl Config {
Search::find(&self.search_config, &self.invocation_directory).eprint(self.color)?; Search::find(&self.search_config, &self.invocation_directory).eprint(self.color)?;
if self.subcommand == Edit { if self.subcommand == Edit {
return self.edit(&search); return Self::edit(&search);
} }
let src = fs::read_to_string(&search.justfile) let src = fs::read_to_string(&search.justfile)
@ -415,7 +415,7 @@ impl Config {
} }
match &self.subcommand { match &self.subcommand {
Dump => self.dump(justfile), Dump => Self::dump(justfile),
Completions { shell } => Self::completions(&shell), Completions { shell } => Self::completions(&shell),
Evaluate { overrides } => self.run(justfile, &search, overrides, &Vec::new()), Evaluate { overrides } => self.run(justfile, &search, overrides, &Vec::new()),
Run { Run {
@ -423,8 +423,8 @@ impl Config {
overrides, overrides,
} => self.run(justfile, &search, overrides, arguments), } => self.run(justfile, &search, overrides, arguments),
List => self.list(justfile), List => self.list(justfile),
Show { ref name } => self.show(&name, justfile), Show { ref name } => Self::show(&name, justfile),
Summary => self.summary(justfile), Summary => Self::summary(justfile),
Edit | Init => unreachable!(), Edit | Init => unreachable!(),
} }
} }
@ -439,12 +439,12 @@ impl Config {
Ok(()) Ok(())
} }
fn dump(&self, justfile: Justfile) -> Result<(), i32> { fn dump(justfile: Justfile) -> Result<(), i32> {
println!("{}", justfile); println!("{}", justfile);
Ok(()) Ok(())
} }
pub(crate) fn edit(&self, search: &Search) -> Result<(), i32> { pub(crate) fn edit(search: &Search) -> Result<(), i32> {
let editor = env::var_os("VISUAL") let editor = env::var_os("VISUAL")
.or_else(|| env::var_os("EDITOR")) .or_else(|| env::var_os("EDITOR"))
.unwrap_or_else(|| "vim".into()); .unwrap_or_else(|| "vim".into());
@ -601,7 +601,7 @@ impl Config {
} }
} }
fn show(&self, name: &str, justfile: Justfile) -> Result<(), i32> { fn show(name: &str, justfile: Justfile) -> Result<(), i32> {
if let Some(alias) = justfile.get_alias(name) { if let Some(alias) = justfile.get_alias(name) {
let recipe = justfile.get_recipe(alias.target.name.lexeme()).unwrap(); let recipe = justfile.get_recipe(alias.target.name.lexeme()).unwrap();
println!("{}", alias); println!("{}", alias);
@ -619,7 +619,7 @@ impl Config {
} }
} }
fn summary(&self, justfile: Justfile) -> Result<(), i32> { fn summary(justfile: Justfile) -> Result<(), i32> {
if justfile.count() == 0 { if justfile.count() == 0 {
eprintln!("Justfile contains no recipes."); eprintln!("Justfile contains no recipes.");
} else { } else {

View File

@ -48,8 +48,8 @@ pub(crate) enum ConfigError {
} }
impl ConfigError { impl ConfigError {
pub(crate) fn internal(message: impl Into<String>) -> ConfigError { pub(crate) fn internal(message: impl Into<String>) -> Self {
ConfigError::Internal { Self::Internal {
message: message.into(), message: message.into(),
} }
} }

View File

@ -1,3 +1,6 @@
// `Self` cannot be used where type takes generic arguments
#![allow(clippy::use_self)]
use crate::common::*; use crate::common::*;
pub struct Enclosure<T: Display> { pub struct Enclosure<T: Display> {
@ -7,7 +10,7 @@ pub struct Enclosure<T: Display> {
impl<T: Display> Enclosure<T> { impl<T: Display> Enclosure<T> {
pub fn tick(value: T) -> Enclosure<T> { pub fn tick(value: T) -> Enclosure<T> {
Enclosure { Self {
enclosure: "`", enclosure: "`",
value, value,
} }

View File

@ -66,13 +66,14 @@ impl<'src, 'run> Evaluator<'src, 'run> {
} }
} }
Expression::Call { thunk } => { Expression::Call { thunk } => {
use Thunk::*;
let context = FunctionContext { let context = FunctionContext {
dotenv: self.dotenv, dotenv: self.dotenv,
invocation_directory: &self.config.invocation_directory, invocation_directory: &self.config.invocation_directory,
search: self.search, search: self.search,
}; };
use Thunk::*;
match thunk { match thunk {
Nullary { name, function, .. } => { Nullary { name, function, .. } => {
function(&context).map_err(|message| RuntimeError::FunctionCall { function(&context).map_err(|message| RuntimeError::FunctionCall {
@ -183,14 +184,13 @@ impl<'src, 'run> Evaluator<'src, 'run> {
let mut rest = arguments; let mut rest = arguments;
for parameter in parameters { for parameter in parameters {
let value = if rest.is_empty() { let value = if rest.is_empty() {
match parameter.default { if let Some(ref default) = parameter.default {
Some(ref default) => evaluator.evaluate_expression(default)?, evaluator.evaluate_expression(default)?
None => { } else {
return Err(RuntimeError::Internal { return Err(RuntimeError::Internal {
message: "missing parameter without default".to_string(), message: "missing parameter without default".to_string(),
}); });
} }
}
} else if parameter.variadic { } else if parameter.variadic {
let value = rest.to_vec().join(" "); let value = rest.to_vec().join(" ");
rest = &[]; rest = &[];

View File

@ -109,11 +109,12 @@ fn env_var_or_default(
key: &str, key: &str,
default: &str, default: &str,
) -> Result<String, String> { ) -> Result<String, String> {
use std::env::VarError::*;
if let Some(value) = context.dotenv.get(key) { if let Some(value) = context.dotenv.get(key) {
return Ok(value.clone()); return Ok(value.clone());
} }
use std::env::VarError::*;
match env::var(key) { match env::var(key) {
Err(NotPresent) => Ok(default.to_string()), Err(NotPresent) => Ok(default.to_string()),
Err(NotUnicode(os_string)) => Err(format!( Err(NotUnicode(os_string)) => Err(format!(

View File

@ -3,9 +3,9 @@ use crate::common::*;
pub(crate) struct InterruptGuard; pub(crate) struct InterruptGuard;
impl InterruptGuard { impl InterruptGuard {
pub(crate) fn new() -> InterruptGuard { pub(crate) fn new() -> Self {
InterruptHandler::instance().block(); InterruptHandler::instance().block();
InterruptGuard Self
} }
} }

View File

@ -7,10 +7,10 @@ pub(crate) struct InterruptHandler {
impl InterruptHandler { impl InterruptHandler {
pub(crate) fn install() -> Result<(), ctrlc::Error> { pub(crate) fn install() -> Result<(), ctrlc::Error> {
ctrlc::set_handler(|| InterruptHandler::instance().interrupt()) ctrlc::set_handler(|| Self::instance().interrupt())
} }
pub(crate) fn instance() -> MutexGuard<'static, InterruptHandler> { pub(crate) fn instance() -> MutexGuard<'static, Self> {
lazy_static! { lazy_static! {
static ref INSTANCE: Mutex<InterruptHandler> = Mutex::new(InterruptHandler::new()); static ref INSTANCE: Mutex<InterruptHandler> = Mutex::new(InterruptHandler::new());
} }
@ -29,8 +29,8 @@ impl InterruptHandler {
} }
} }
fn new() -> InterruptHandler { fn new() -> Self {
InterruptHandler { Self {
blocks: 0, blocks: 0,
interrupted: false, interrupted: false,
} }

View File

@ -51,7 +51,7 @@ impl<'src> Justfile<'src> {
arguments: &'run [String], arguments: &'run [String],
) -> RunResult<'run, ()> { ) -> RunResult<'run, ()> {
let argvec: Vec<&str> = if !arguments.is_empty() { let argvec: Vec<&str> = if !arguments.is_empty() {
arguments.iter().map(|argument| argument.as_str()).collect() arguments.iter().map(String::as_str).collect()
} else if let Some(recipe) = self.first() { } else if let Some(recipe) = self.first() {
let min_arguments = recipe.min_arguments(); let min_arguments = recipe.min_arguments();
if min_arguments > 0 { if min_arguments > 0 {
@ -70,7 +70,7 @@ impl<'src> Justfile<'src> {
let unknown_overrides = overrides let unknown_overrides = overrides
.keys() .keys()
.filter(|name| !self.assignments.contains_key(name.as_str())) .filter(|name| !self.assignments.contains_key(name.as_str()))
.map(|name| name.as_str()) .map(String::as_str)
.collect::<Vec<&str>>(); .collect::<Vec<&str>>();
if !unknown_overrides.is_empty() { if !unknown_overrides.is_empty() {

View File

@ -73,16 +73,12 @@ impl<'src> Lexer<'src> {
let len_utf8 = c.len_utf8(); let len_utf8 = c.len_utf8();
self.token_end.offset += len_utf8; self.token_end.offset += len_utf8;
self.token_end.column += len_utf8;
match c { if c == '\n' {
'\n' => {
self.token_end.column = 0; self.token_end.column = 0;
self.token_end.line += 1; self.token_end.line += 1;
} }
_ => {
self.token_end.column += len_utf8;
}
}
self.next = self.chars.next(); self.next = self.chars.next();
@ -203,10 +199,7 @@ impl<'src> Lexer<'src> {
CompilationError { token, kind } CompilationError { token, kind }
} }
fn unterminated_interpolation_error( fn unterminated_interpolation_error(interpolation_start: Token<'src>) -> CompilationError<'src> {
&self,
interpolation_start: Token<'src>,
) -> CompilationError<'src> {
CompilationError { CompilationError {
token: interpolation_start, token: interpolation_start,
kind: UnterminatedInterpolation, kind: UnterminatedInterpolation,
@ -275,7 +268,7 @@ impl<'src> Lexer<'src> {
} }
if let Some(interpolation_start) = self.interpolation_start { if let Some(interpolation_start) = self.interpolation_start {
return Err(self.unterminated_interpolation_error(interpolation_start)); return Err(Self::unterminated_interpolation_error(interpolation_start));
} }
while self.indented() { while self.indented() {
@ -486,7 +479,7 @@ impl<'src> Lexer<'src> {
self.lex_double(InterpolationEnd) self.lex_double(InterpolationEnd)
} else if self.at_eol_or_eof() { } else if self.at_eol_or_eof() {
// Return unterminated interpolation error that highlights the opening {{ // Return unterminated interpolation error that highlights the opening {{
Err(self.unterminated_interpolation_error(interpolation_start)) Err(Self::unterminated_interpolation_error(interpolation_start))
} else { } else {
// Otherwise lex as per normal // Otherwise lex as per normal
self.lex_normal(start) self.lex_normal(start)

View File

@ -1,3 +1,37 @@
#![deny(clippy::all, clippy::pedantic, clippy::restriction)]
#![allow(
clippy::print_stdout,
clippy::else_if_without_else,
clippy::use_debug,
clippy::implicit_return,
clippy::if_not_else,
clippy::missing_docs_in_private_items,
clippy::enum_glob_use,
clippy::integer_arithmetic,
clippy::option_unwrap_used,
clippy::indexing_slicing,
clippy::non_ascii_literal,
clippy::missing_inline_in_public_items,
clippy::option_expect_used,
clippy::comparison_chain,
clippy::wildcard_enum_match_arm,
clippy::too_many_lines,
clippy::shadow_unrelated,
clippy::needless_pass_by_value,
clippy::option_map_unwrap_or,
clippy::filter_map,
clippy::result_expect_used,
clippy::unreachable,
clippy::string_add,
clippy::panic,
clippy::match_same_arms
)]
// clippy::option_map_unwrap_or_else,
// clippy::result_expect_used,
// clippy::result_unwrap_used,
// clippy::unreachable
// )]
#[macro_use] #[macro_use]
extern crate lazy_static; extern crate lazy_static;

View File

@ -1,3 +1,6 @@
// `Self` cannot be used where type takes generic arguments
#![allow(clippy::use_self)]
use crate::common::*; use crate::common::*;
pub struct List<T: Display, I: Iterator<Item = T> + Clone> { pub struct List<T: Display, I: Iterator<Item = T> + Clone> {
@ -70,7 +73,7 @@ impl<T: Display, I: Iterator<Item = T> + Clone> Display for List<T, I> {
write!(f, ", {} {}", self.conjunction, c)?; write!(f, ", {} {}", self.conjunction, c)?;
return Ok(()); return Ok(());
} }
_ => panic!("Iterator was fused, but returned Some after None"), _ => unreachable!("Iterator was fused, but returned Some after None"),
} }
} }
} }

View File

@ -17,11 +17,11 @@ pub(crate) enum OutputError {
impl Display for OutputError { impl Display for OutputError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self { match *self {
OutputError::Code(code) => write!(f, "Process exited with status code {}", code), Self::Code(code) => write!(f, "Process exited with status code {}", code),
OutputError::Io(ref io_error) => write!(f, "Error executing process: {}", io_error), Self::Io(ref io_error) => write!(f, "Error executing process: {}", io_error),
OutputError::Signal(signal) => write!(f, "Process terminated by signal {}", signal), Self::Signal(signal) => write!(f, "Process terminated by signal {}", signal),
OutputError::Unknown => write!(f, "Process experienced an unknown failure"), Self::Unknown => write!(f, "Process experienced an unknown failure"),
OutputError::Utf8(ref err) => write!(f, "Could not convert process stdout to UTF-8: {}", err), Self::Utf8(ref err) => write!(f, "Could not convert process stdout to UTF-8: {}", err),
} }
} }
} }

View File

@ -10,7 +10,7 @@ use crate::common::*;
/// ///
/// - Overrides are of the form `NAME=.*` /// - Overrides are of the form `NAME=.*`
/// ///
/// - After overrides comes a single optional search_directory argument. /// - After overrides comes a single optional search directory argument.
/// This is either '.', '..', or an argument that contains a `/`. /// This is either '.', '..', or an argument that contains a `/`.
/// ///
/// If the argument contains a `/`, everything before and including /// If the argument contains a `/`, everything before and including
@ -40,9 +40,7 @@ pub struct Positional {
} }
impl Positional { impl Positional {
pub fn from_values<'values>( pub fn from_values<'values>(values: Option<impl IntoIterator<Item = &'values str>>) -> Self {
values: Option<impl IntoIterator<Item = &'values str>>,
) -> Positional {
let mut overrides = Vec::new(); let mut overrides = Vec::new();
let mut search_directory = None; let mut search_directory = None;
let mut arguments = Vec::new(); let mut arguments = Vec::new();
@ -71,7 +69,7 @@ impl Positional {
} }
} }
Positional { Self {
overrides, overrides,
search_directory, search_directory,
arguments, arguments,

View File

@ -50,7 +50,7 @@ impl<'src, D> Recipe<'src, D> {
pub(crate) fn max_arguments(&self) -> usize { pub(crate) fn max_arguments(&self) -> usize {
if self.parameters.iter().any(|p| p.variadic) { if self.parameters.iter().any(|p| p.variadic) {
usize::MAX - 1 usize::max_value() - 1
} else { } else {
self.parameters.len() self.parameters.len()
} }

View File

@ -76,7 +76,7 @@ impl<'src: 'run, 'run> RecipeResolver<'src, 'run> {
recipe: UnresolvedRecipe<'src>, recipe: UnresolvedRecipe<'src>,
) -> CompilationResult<'src, Rc<Recipe<'src>>> { ) -> CompilationResult<'src, Rc<Recipe<'src>>> {
if let Some(resolved) = self.resolved_recipes.get(recipe.name()) { if let Some(resolved) = self.resolved_recipes.get(recipe.name()) {
return Ok(resolved.clone()); return Ok(Rc::clone(resolved));
} }
stack.push(recipe.name()); stack.push(recipe.name());
@ -87,7 +87,7 @@ impl<'src: 'run, 'run> RecipeResolver<'src, 'run> {
if let Some(resolved) = self.resolved_recipes.get(name) { if let Some(resolved) = self.resolved_recipes.get(name) {
// dependency already resolved // dependency already resolved
dependencies.push(resolved.clone()); dependencies.push(Rc::clone(&resolved));
} else if stack.contains(&name) { } else if stack.contains(&name) {
let first = stack[0]; let first = stack[0];
stack.push(first); stack.push(first);
@ -114,7 +114,7 @@ impl<'src: 'run, 'run> RecipeResolver<'src, 'run> {
} }
let resolved = Rc::new(recipe.resolve(dependencies)?); let resolved = Rc::new(recipe.resolve(dependencies)?);
self.resolved_recipes.insert(resolved.clone()); self.resolved_recipes.insert(Rc::clone(&resolved));
stack.pop(); stack.pop();
Ok(resolved) Ok(resolved)
} }

View File

@ -72,8 +72,8 @@ pub(crate) enum RuntimeError<'src> {
impl<'src> Error for RuntimeError<'src> { impl<'src> Error for RuntimeError<'src> {
fn code(&self) -> i32 { fn code(&self) -> i32 {
match *self { match *self {
Self::Code { code, .. } => code, Self::Code { code, .. }
Self::Backtick { | Self::Backtick {
output_error: OutputError::Code(code), output_error: OutputError::Code(code),
.. ..
} => code, } => code,

View File

@ -14,14 +14,14 @@ impl Search {
pub(crate) fn find( pub(crate) fn find(
search_config: &SearchConfig, search_config: &SearchConfig,
invocation_directory: &Path, invocation_directory: &Path,
) -> SearchResult<Search> { ) -> SearchResult<Self> {
match search_config { match search_config {
SearchConfig::FromInvocationDirectory => { SearchConfig::FromInvocationDirectory => {
let justfile = Self::justfile(&invocation_directory)?; let justfile = Self::justfile(&invocation_directory)?;
let working_directory = Self::working_directory_from_justfile(&justfile)?; let working_directory = Self::working_directory_from_justfile(&justfile)?;
Ok(Search { Ok(Self {
justfile, justfile,
working_directory, working_directory,
}) })
@ -34,7 +34,7 @@ impl Search {
let working_directory = Self::working_directory_from_justfile(&justfile)?; let working_directory = Self::working_directory_from_justfile(&justfile)?;
Ok(Search { Ok(Self {
justfile, justfile,
working_directory, working_directory,
}) })
@ -45,7 +45,7 @@ impl Search {
let working_directory = Self::working_directory_from_justfile(&justfile)?; let working_directory = Self::working_directory_from_justfile(&justfile)?;
Ok(Search { Ok(Self {
justfile, justfile,
working_directory, working_directory,
}) })
@ -54,7 +54,7 @@ impl Search {
SearchConfig::WithJustfileAndWorkingDirectory { SearchConfig::WithJustfileAndWorkingDirectory {
justfile, justfile,
working_directory, working_directory,
} => Ok(Search { } => Ok(Self {
justfile: Self::clean(invocation_directory, justfile), justfile: Self::clean(invocation_directory, justfile),
working_directory: Self::clean(invocation_directory, working_directory), working_directory: Self::clean(invocation_directory, working_directory),
}), }),
@ -64,14 +64,14 @@ impl Search {
pub(crate) fn init( pub(crate) fn init(
search_config: &SearchConfig, search_config: &SearchConfig,
invocation_directory: &Path, invocation_directory: &Path,
) -> SearchResult<Search> { ) -> SearchResult<Self> {
match search_config { match search_config {
SearchConfig::FromInvocationDirectory => { SearchConfig::FromInvocationDirectory => {
let working_directory = Self::project_root(&invocation_directory)?; let working_directory = Self::project_root(&invocation_directory)?;
let justfile = working_directory.join(FILENAME); let justfile = working_directory.join(FILENAME);
Ok(Search { Ok(Self {
justfile, justfile,
working_directory, working_directory,
}) })
@ -84,7 +84,7 @@ impl Search {
let justfile = working_directory.join(FILENAME); let justfile = working_directory.join(FILENAME);
Ok(Search { Ok(Self {
justfile, justfile,
working_directory, working_directory,
}) })
@ -95,7 +95,7 @@ impl Search {
let working_directory = Self::working_directory_from_justfile(&justfile)?; let working_directory = Self::working_directory_from_justfile(&justfile)?;
Ok(Search { Ok(Self {
justfile, justfile,
working_directory, working_directory,
}) })
@ -104,7 +104,7 @@ impl Search {
SearchConfig::WithJustfileAndWorkingDirectory { SearchConfig::WithJustfileAndWorkingDirectory {
justfile, justfile,
working_directory, working_directory,
} => Ok(Search { } => Ok(Self {
justfile: Self::clean(invocation_directory, justfile), justfile: Self::clean(invocation_directory, justfile),
working_directory: Self::clean(invocation_directory, working_directory), working_directory: Self::clean(invocation_directory, working_directory),
}), }),

View File

@ -85,6 +85,7 @@ impl<'table, V: Keyed<'table> + 'table> IntoIterator for &'table Table<'table, V
type Item = (&'table &'table str, &'table V); type Item = (&'table &'table str, &'table V);
type IntoIter = btree_map::Iter<'table, &'table str, V>; type IntoIter = btree_map::Iter<'table, &'table str, V>;
#[must_use]
fn into_iter(self) -> btree_map::Iter<'table, &'table str, V> { fn into_iter(self) -> btree_map::Iter<'table, &'table str, V> {
self.map.iter() self.map.iter()
} }

View File

@ -8,7 +8,7 @@ pub(crate) enum Verbosity {
} }
impl Verbosity { impl Verbosity {
pub(crate) fn from_flag_occurrences(flag_occurences: u64) -> Verbosity { pub(crate) fn from_flag_occurrences(flag_occurences: u64) -> Self {
match flag_occurences { match flag_occurences {
0 => Taciturn, 0 => Taciturn,
1 => Loquacious, 1 => Loquacious,
@ -19,15 +19,13 @@ impl Verbosity {
pub(crate) fn loquacious(self) -> bool { pub(crate) fn loquacious(self) -> bool {
match self { match self {
Taciturn => false, Taciturn => false,
Loquacious => true, Loquacious | Grandiloquent => true,
Grandiloquent => true,
} }
} }
pub(crate) fn grandiloquent(self) -> bool { pub(crate) fn grandiloquent(self) -> bool {
match self { match self {
Taciturn => false, Taciturn | Loquacious => false,
Loquacious => false,
Grandiloquent => true, Grandiloquent => true,
} }
} }