diff --git a/Cargo.toml b/Cargo.toml index 16ac689..aacbe37 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "dockerfile-parser" description = "a Rust library for parsing, validating, and modifying Dockerfiles" authors = ["Tim Buckley "] -edition = "2018" +edition = "2021" license = "MIT" keywords = ["parser", "docker", "dockerfile", "pest"] homepage = "https://github.com/HewlettPackard/dockerfile-parser-rs/" @@ -18,16 +18,15 @@ version = "0.1.0" circle-ci = { repository = "HewlettPackard/dockerfile-parser-rs", branch = "master" } [dependencies] -pest = "2.1" -pest_derive = "2.1" -snafu = "0.6" +pest = "2.7" +pest_derive = "2.7" +snafu = "0.8" enquote = "1.1" -regex = "1.5" -lazy_static = "1.4" +regex = "1.11" [dev-dependencies] -indoc = "1.0" -pretty_assertions = "1.0.0" +indoc = "2.0.5" +pretty_assertions = "1.4.1" [lib] name = "dockerfile_parser" diff --git a/src/dockerfile_parser.rs b/src/dockerfile_parser.rs index 6387e39..92ba31f 100644 --- a/src/dockerfile_parser.rs +++ b/src/dockerfile_parser.rs @@ -315,7 +315,7 @@ pub struct Dockerfile { fn parse_dockerfile(input: &str) -> Result { let dockerfile = DockerfileParser::parse(Rule::dockerfile, input) - .context(ParseError)? + .context(ParseSnafu)? .next() .ok_or(Error::UnknownParseError)?; @@ -374,7 +374,7 @@ impl Dockerfile { { let mut buf = String::new(); let mut buf_reader = BufReader::new(reader); - buf_reader.read_to_string(&mut buf).context(ReadError)?; + buf_reader.read_to_string(&mut buf).context(ReadSnafu)?; Dockerfile::parse(&buf) } diff --git a/src/image.rs b/src/image.rs index f58ef54..5b51250 100644 --- a/src/image.rs +++ b/src/image.rs @@ -3,8 +3,8 @@ use std::collections::{HashMap, HashSet}; use std::fmt; use std::iter::FromIterator; +use std::sync::LazyLock; -use lazy_static::lazy_static; use regex::Regex; use crate::{Dockerfile, Span, Splicer}; @@ -58,9 +58,9 @@ pub fn substitute<'a, 'b>( used_vars: &mut HashSet, max_recursion_depth: u8 ) -> Option { - lazy_static! { - static ref VAR: Regex = Regex::new(r"\$(?:([A-Za-z0-9_]+)|\{([A-Za-z0-9_]+)\})").unwrap(); - } + static VAR: LazyLock = LazyLock::new(|| + Regex::new(r"\$(?:([A-Za-z0-9_]+)|\{([A-Za-z0-9_]+)\})").unwrap() + ); // note: docker also allows defaults in FROMs, e.g. // ARG tag @@ -156,19 +156,13 @@ impl ImageRef { let vars: HashMap<&'a str, &'a str> = HashMap::from_iter( dockerfile.global_args .iter() - .filter_map(|a| match a.value.as_ref() { - Some(v) => Some((a.name.as_ref(), v.as_ref())), - None => None - }) + .filter_map(|a| a.value.as_ref().map(|v| (a.name.as_ref(), v.as_ref()))) ); let mut used_vars = HashSet::new(); - if let Some(s) = substitute(&self.to_string(), &vars, &mut used_vars, 16) { - Some((ImageRef::parse(&s), used_vars)) - } else { - None - } + substitute(&self.to_string(), &vars, &mut used_vars, 16) + .map(|s| (ImageRef::parse(&s), used_vars)) } /// Given a Dockerfile (and its global `ARG`s), perform any necessary diff --git a/src/instructions/copy.rs b/src/instructions/copy.rs index 9292f44..fe87746 100644 --- a/src/instructions/copy.rs +++ b/src/instructions/copy.rs @@ -76,7 +76,7 @@ impl CopyInstruction { ensure!( paths.len() >= 2, - GenericParseError { + GenericParseSnafu { message: "copy requires at least one source and a destination" } ); diff --git a/src/instructions/env.rs b/src/instructions/env.rs index 97c7eac..c71d9a0 100644 --- a/src/instructions/env.rs +++ b/src/instructions/env.rs @@ -23,7 +23,7 @@ impl EnvVar { pub fn new(span: Span, key: SpannedString, value: impl Into) -> Self { EnvVar { span, - key: key, + key, value: value.into(), } } @@ -53,7 +53,7 @@ fn parse_env_pair(record: Pair) -> Result { ); }, Rule::env_pair_quoted_value => { - let v = unquote(field.as_str()).context(UnescapeError)?; + let v = unquote(field.as_str()).context(UnescapeSnafu)?; value = Some( BreakableString::new(&field).add_string(&field, v) @@ -116,7 +116,7 @@ impl EnvInstruction { Rule::env_name => key = Some(parse_string(&field)?), Rule::env_single_value => value = Some(parse_any_breakable(field)?), Rule::env_single_quoted_value => { - let v = unquote(field.as_str()).context(UnescapeError)?; + let v = unquote(field.as_str()).context(UnescapeSnafu)?; value = Some( BreakableString::new(&field).add_string(&field, v) diff --git a/src/instructions/from.rs b/src/instructions/from.rs index 8118bc5..5e2766b 100644 --- a/src/instructions/from.rs +++ b/src/instructions/from.rs @@ -1,6 +1,7 @@ // (C) Copyright 2019-2020 Hewlett Packard Enterprise Development LP use std::convert::TryFrom; +use std::sync::LazyLock; use crate::dockerfile_parser::Instruction; use crate::image::ImageRef; @@ -10,7 +11,6 @@ use crate::SpannedString; use crate::splicer::*; use crate::error::*; -use lazy_static::lazy_static; use regex::Regex; /// A key/value pair passed to a `FROM` instruction as a flag. @@ -71,10 +71,7 @@ pub struct FromInstruction { impl FromInstruction { pub(crate) fn from_record(record: Pair, index: usize) -> Result { - lazy_static! { - static ref HEX: Regex = - Regex::new(r"[0-9a-fA-F]+").unwrap(); - } + static HEX: LazyLock = LazyLock::new(|| Regex::new(r"[0-9a-fA-F]+").unwrap()); let span = Span::from_pair(&record); let mut image_field = None; @@ -83,7 +80,7 @@ impl FromInstruction { for field in record.into_inner() { match field.as_rule() { - Rule::from_flag => flags.push(FromFlag::from_record(field)?), + Rule::from_flag => flags.push(FromFlag::from_record(field)?), Rule::from_image => image_field = Some(field), Rule::from_alias => alias_field = Some(field), Rule::comment => continue, @@ -99,7 +96,7 @@ impl FromInstruction { }); }; - let image_parsed = ImageRef::parse(&image.as_ref()); + let image_parsed = ImageRef::parse(image.as_ref()); if let Some(hash) = &image_parsed.hash { let parts: Vec<&str> = hash.split(":").collect(); diff --git a/src/instructions/label.rs b/src/instructions/label.rs index d37a805..198eff3 100644 --- a/src/instructions/label.rs +++ b/src/instructions/label.rs @@ -40,7 +40,7 @@ impl Label { Rule::label_quoted_name | Rule::label_single_quoted_name => { // label seems to be uniquely able to span multiple lines when quoted let v = unquote(&clean_escaped_breaks(field.as_str())) - .context(UnescapeError)?; + .context(UnescapeSnafu)?; name = Some(SpannedString { content: v, @@ -51,7 +51,7 @@ impl Label { Rule::label_value => value = Some(parse_string(&field)?), Rule::label_quoted_value => { let v = unquote(&clean_escaped_breaks(field.as_str())) - .context(UnescapeError)?; + .context(UnescapeSnafu)?; value = Some(SpannedString { content: v, diff --git a/src/splicer.rs b/src/splicer.rs index 90182bb..94c81aa 100644 --- a/src/splicer.rs +++ b/src/splicer.rs @@ -88,7 +88,7 @@ impl From<(usize, usize)> for Span { impl From<&Pair<'_>> for Span { fn from(pair: &Pair<'_>) -> Self { - Span::from_pair(&pair) + Span::from_pair(pair) } } diff --git a/src/stage.rs b/src/stage.rs index f2afd24..5eccb32 100644 --- a/src/stage.rs +++ b/src/stage.rs @@ -71,7 +71,7 @@ impl<'a> Ord for Stage<'a> { impl<'a> PartialOrd for Stage<'a> { fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(&other)) + Some(self.cmp(other)) } } diff --git a/src/test_util.rs b/src/test_util.rs index 83b50c9..0140577 100644 --- a/src/test_util.rs +++ b/src/test_util.rs @@ -16,7 +16,7 @@ use crate::parser::{DockerfileParser, Pair, Rule}; /// per-instruction unit tests. pub fn parse_single(input: &str, rule: Rule) -> Result { let record = DockerfileParser::parse(rule, input) - .context(ParseError)? + .context(ParseSnafu)? .next() .ok_or(Error::UnknownParseError)?; @@ -28,7 +28,7 @@ where F: Fn(Pair) -> Result { let pair = DockerfileParser::parse(rule, input) - .context(ParseError)? + .context(ParseSnafu)? .next() .ok_or(Error::UnknownParseError)?; diff --git a/src/util.rs b/src/util.rs index e5c66c1..c69aa1f 100644 --- a/src/util.rs +++ b/src/util.rs @@ -35,7 +35,7 @@ pub(crate) fn parse_string(field: &Pair) -> Result { let str_span = Span::from_pair(field); let field_str = field.as_str(); let content = if matches!(field_str.chars().next(), Some('"' | '\'' | '`')) { - unquote(field_str).context(UnescapeError)? + unquote(field_str).context(UnescapeSnafu)? } else { field_str.to_string() };