Skip to content

Commit

Permalink
Merge pull request #28 from ludicast/allow-from-flags
Browse files Browse the repository at this point in the history
allow `from` flags
  • Loading branch information
jonmcquillan authored Jul 20, 2022
2 parents a3b7e52 + bdea9f0 commit e974fa5
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 2 deletions.
5 changes: 4 additions & 1 deletion src/dockerfile_parser.pest
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,13 @@ string_array = _{
) | "[" ~ arg_ws_maybe ~ "]"
}

from_flag_name = @{ ASCII_ALPHA+ }
from_flag_value = @{ any_whitespace }
from_flag = { "--" ~ from_flag_name ~ "=" ~ from_flag_value }
from_image = @{ (ASCII_ALPHANUMERIC | "_" | "-" | "." | ":" | "/" | "$" | "{" | "}")+ }
from_alias = { identifier_whitespace }
from_alias_outer = _{ arg_ws ~ ^"as" ~ arg_ws ~ from_alias }
from = { ^"from" ~ arg_ws ~ from_image ~ from_alias_outer? }
from = { ^"from" ~ (arg_ws ~ from_flag)* ~ arg_ws ~ from_image ~ from_alias_outer? }

arg_name = @{ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC | "_")* }
arg_value = ${ any_whitespace }
Expand Down
87 changes: 86 additions & 1 deletion src/instructions/from.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,45 @@ use crate::SpannedString;
use crate::splicer::*;
use crate::error::*;

/// A key/value pair passed to a `FROM` instruction as a flag.
///
/// Examples include: `FROM --platform=linux/amd64 node:lts-alpine`
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct FromFlag {
pub span: Span,
pub name: SpannedString,
pub value: SpannedString,
}

impl FromFlag {
fn from_record(record: Pair) -> Result<FromFlag> {
let span = Span::from_pair(&record);
let mut name = None;
let mut value = None;

for field in record.into_inner() {
match field.as_rule() {
Rule::from_flag_name => name = Some(parse_string(&field)?),
Rule::from_flag_value => value = Some(parse_string(&field)?),
_ => return Err(unexpected_token(field))
}
}

let name = name.ok_or_else(|| Error::GenericParseError {
message: "from flags require a key".into(),
})?;

let value = value.ok_or_else(|| Error::GenericParseError {
message: "from flags require a value".into()
})?;

Ok(FromFlag {
span, name, value
})
}
}


/// A Dockerfile [`FROM` instruction][from].
///
/// Contains spans for the entire instruction, the image, and the alias (if
Expand All @@ -19,6 +58,7 @@ use crate::error::*;
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct FromInstruction {
pub span: Span,
pub flags: Vec<FromFlag>,
pub image: SpannedString,
pub image_parsed: ImageRef,

Expand All @@ -31,9 +71,11 @@ impl FromInstruction {
let span = Span::from_pair(&record);
let mut image_field = None;
let mut alias_field = None;
let mut flags = Vec::new();

for field in record.into_inner() {
match field.as_rule() {
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,
Expand All @@ -60,7 +102,7 @@ impl FromInstruction {
Ok(FromInstruction {
span, index,
image, image_parsed,
alias,
flags, alias,
})
}

Expand Down Expand Up @@ -117,6 +159,7 @@ mod tests {
hash: None
},
alias: None,
flags: vec![],
});

Ok(())
Expand Down Expand Up @@ -144,6 +187,47 @@ mod tests {
Ok(())
}

#[test]
fn from_flags() -> Result<()> {
assert_eq!(
parse_single(
"FROM --platform=linux/amd64 alpine:3.10",
Rule::from
)?,
FromInstruction {
index: 0,
span: Span { start: 0, end: 39 },
flags: vec![
FromFlag {
span: Span { start: 5, end: 27 },
name: SpannedString {
content: "platform".into(),
span: Span { start: 7, end: 15 },
},
value: SpannedString {
content: "linux/amd64".into(),
span: Span { start: 16, end: 27 },
}
}
],
image: SpannedString {
span: Span { start: 28, end: 39 },
content: "alpine:3.10".into(),
},
image_parsed: ImageRef {
registry: None,
image: "alpine".into(),
tag: Some("3.10".into()),
hash: None
},
alias: None,
}.into()
);

Ok(())
}


#[test]
fn from_multiline() -> Result<()> {
let from = parse_direct(
Expand Down Expand Up @@ -180,6 +264,7 @@ mod tests {
span: (64, 68).into(),
content: "test".into(),
}),
flags: vec![],
});

Ok(())
Expand Down
1 change: 1 addition & 0 deletions tests/parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ fn parse_basic() -> Result<(), dockerfile_parser::Error> {
},
index: 0,
alias: None,
flags: vec![],
})
);

Expand Down

0 comments on commit e974fa5

Please sign in to comment.