Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 38 additions & 20 deletions src/Language/Docker/Parser/Copy.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,29 @@
| FlagChmod Chmod
| FlagLink Link
| FlagSource CopySource
| FlagExclude Exclude
| FlagInvalid (Text, Text)

parseCopy :: (?esc :: Char) => Parser (Instruction Text)
parseCopy = do
reserved "COPY"
flags <- copyFlag `sepEndBy` requiredWhitespace
let chownFlags = [c | FlagChown c <- flags]

Check warning on line 25 in src/Language/Docker/Parser/Copy.hs

View workflow job for this annotation

GitHub Actions / hlint

Suggestion in parseCopy, parseAdd in module Language.Docker.Parser.Copy: Reduce duplication ▫︎ Found: "let chownFlags = [c | FlagChown c <- flags]\nlet chmodFlags = [c | FlagChmod c <- flags]\nlet linkFlags = [l | FlagLink l <- flags]\n" ▫︎ Perhaps: "Combine with src/Language/Docker/Parser/Copy.hs:68:3-45"
let chmodFlags = [c | FlagChmod c <- flags]
let linkFlags = [l | FlagLink l <- flags]
let sourceFlags = [f | FlagSource f <- flags]
let excludeFlags = [e | FlagExclude e <- flags]
let invalid = [i | FlagInvalid i <- flags]
-- Let's do some validation on the flags
case (invalid, chownFlags, chmodFlags, linkFlags, sourceFlags) of
((k, v) : _, _, _, _, _) -> unexpectedFlag k v
(_, _ : _ : _, _, _, _) -> customError $ DuplicateFlagError "--chown"
(_, _, _ : _ : _, _, _) -> customError $ DuplicateFlagError "--chmod"
(_, _, _, _ : _ : _, _) -> customError $ DuplicateFlagError "--link"
(_, _, _, _, _ : _ : _) -> customError $ DuplicateFlagError "--from"
case (invalid, chownFlags, chmodFlags, linkFlags, sourceFlags, excludeFlags) of
((k, v) : _, _, _, _, _, _) -> unexpectedFlag k v
(_, _ : _ : _, _, _, _, _) -> customError $ DuplicateFlagError "--chown"
(_, _, _ : _ : _, _, _, _) -> customError $ DuplicateFlagError "--chmod"
(_, _, _, _ : _ : _, _, _) -> customError $ DuplicateFlagError "--link"
(_, _, _, _, _ : _ : _, _) -> customError $ DuplicateFlagError "--from"
(_, _, _, _, _, _ : _ : _) -> customError $ DuplicateFlagError "--exclude"
_ -> do
let cho =

Check warning on line 40 in src/Language/Docker/Parser/Copy.hs

View workflow job for this annotation

GitHub Actions / hlint

Suggestion in parseCopy, parseAdd in module Language.Docker.Parser.Copy: Reduce duplication ▫︎ Found: "let cho\n = case chownFlags of\n [] -> NoChown\n c : _ -> c\nlet chm\n = case chmodFlags of\n [] -> NoChmod\n c : _ -> c\nlet lnk\n = case linkFlags of\n [] -> NoLink\n l : _ -> l\n" ▫︎ Perhaps: "Combine with src/Language/Docker/Parser/Copy.hs:(86,7)-(88,28)"
case chownFlags of
[] -> NoChown
c : _ -> c
Expand All @@ -50,8 +53,12 @@
case sourceFlags of
[] -> NoSource
f : _ -> f
try (heredocList (\src dest -> Copy (CopyArgs src dest) (CopyFlags cho chm lnk fr)))
<|> fileList "COPY" (\src dest -> Copy (CopyArgs src dest) (CopyFlags cho chm lnk fr))
let exc =
case excludeFlags of
[] -> NoExclude

Check failure on line 58 in src/Language/Docker/Parser/Copy.hs

View workflow job for this annotation

GitHub Actions / hadolint (ubuntu-latest)

Data constructor not in scope: NoExclude :: Exclude
e : _ -> e
try (heredocList (\src dest -> Copy (CopyArgs src dest) (CopyFlags cho chm lnk fr exc)))

Check failure on line 60 in src/Language/Docker/Parser/Copy.hs

View workflow job for this annotation

GitHub Actions / hadolint (ubuntu-latest)

• Couldn't match expected type ‘[Exclude]’
<|> fileList "COPY" (\src dest -> Copy (CopyArgs src dest) (CopyFlags cho chm lnk fr exc))

Check failure on line 61 in src/Language/Docker/Parser/Copy.hs

View workflow job for this annotation

GitHub Actions / hadolint (ubuntu-latest)

• Couldn't match expected type ‘[Exclude]’

parseAdd :: (?esc :: Char) => Parser (Instruction Text)
parseAdd = do
Expand All @@ -61,15 +68,17 @@
let chownFlags = [c | FlagChown c <- flags]
let chmodFlags = [c | FlagChmod c <- flags]
let linkFlags = [l | FlagLink l <- flags]
let excludeFlags = [e | FlagExclude e <- flags]
let invalidFlags = [i | FlagInvalid i <- flags]
notFollowedBy (string "--") <?>
"only the --checksum, --chown, --chmod, --link flags or the src and dest paths"
case (invalidFlags, checksumFlags, chownFlags, linkFlags, chmodFlags) of
((k, v) : _, _, _, _, _) -> unexpectedFlag k v
(_, _ : _ : _, _, _, _) -> customError $ DuplicateFlagError "--checksum"
(_, _, _ : _ : _, _, _) -> customError $ DuplicateFlagError "--chown"
(_, _, _, _ : _ : _, _) -> customError $ DuplicateFlagError "--chmod"
(_, _, _, _, _ : _ : _) -> customError $ DuplicateFlagError "--link"
"only the --checksum, --chown, --chmod, --link, --exclude flags or the src and dest paths"
case (invalidFlags, checksumFlags, chownFlags, linkFlags, chmodFlags, excludeFlags) of
((k, v) : _, _, _, _, _, _) -> unexpectedFlag k v
(_, _ : _ : _, _, _, _, _) -> customError $ DuplicateFlagError "--checksum"
(_, _, _ : _ : _, _, _, _) -> customError $ DuplicateFlagError "--chown"
(_, _, _, _ : _ : _, _, _) -> customError $ DuplicateFlagError "--chmod"
(_, _, _, _, _ : _ : _, _) -> customError $ DuplicateFlagError "--link"
(_, _, _, _, _, _ : _ : _) -> customError $ DuplicateFlagError "--exclude"
_ -> do
let chk = case checksumFlags of
[] -> NoChecksum
Expand All @@ -80,11 +89,13 @@
let chm = case chmodFlags of
[] -> NoChmod
c : _ -> c
let lnk =
case linkFlags of
[] -> NoLink
l : _ -> l
fileList "ADD" (\src dest -> Add (AddArgs src dest) (AddFlags chk cho chm lnk))
let lnk = case linkFlags of
[] -> NoLink
l : _ -> l
let exc = case excludeFlags of
[] -> NoExclude

Check failure on line 96 in src/Language/Docker/Parser/Copy.hs

View workflow job for this annotation

GitHub Actions / hadolint (ubuntu-latest)

Data constructor not in scope: NoExclude :: Exclude
e : _ -> e
fileList "ADD" (\src dest -> Add (AddArgs src dest) (AddFlags chk cho chm lnk exc))

Check failure on line 98 in src/Language/Docker/Parser/Copy.hs

View workflow job for this annotation

GitHub Actions / hadolint (ubuntu-latest)

• Couldn't match expected type ‘[Exclude]’

heredocList :: (?esc :: Char) =>
(NonEmpty SourcePath -> TargetPath -> Instruction Text) ->
Expand Down Expand Up @@ -124,6 +135,7 @@
<|> (FlagChown <$> try chown <?> "--chown")
<|> (FlagChmod <$> try chmod <?> "--chmod")
<|> (FlagLink <$> try link <?> "--link")
<|> (FlagExclude <$> try exclude <?> "--exclude")
<|> (FlagInvalid <$> try anyFlag <?> "other flag")

checksum :: (?esc :: Char) => Parser Checksum
Expand Down Expand Up @@ -155,6 +167,12 @@
src <- someUnless "the copy source path" isNl
return $ CopySource src

exclude :: (?esc :: Char) => Parser Exclude
exclude = do
void $ string "--exclude="
exc <- someUnless "the exclude pattern" (== ' ')
return $ Exclude exc

anyFlag :: (?esc :: Char) => Parser (Text, Text)
anyFlag = do
void $ string "--"
Expand Down
12 changes: 10 additions & 2 deletions src/Language/Docker/PrettyPrint.hs
Original file line number Diff line number Diff line change
Expand Up @@ -288,12 +288,13 @@
prettyPrintArguments c
Copy
CopyArgs {sourcePaths, targetPath}
CopyFlags {chmodFlag, chownFlag, linkFlag, sourceFlag} -> do
CopyFlags {chmodFlag, chownFlag, linkFlag, sourceFlag, excludeFlags} -> do
"COPY"
prettyPrintChown chownFlag

Check warning on line 293 in src/Language/Docker/PrettyPrint.hs

View workflow job for this annotation

GitHub Actions / hlint

Suggestion in prettyPrintInstruction in module Language.Docker.PrettyPrint: Reduce duplication ▫︎ Found: "prettyPrintChown chownFlag\nprettyPrintChmod chmodFlag\nprettyPrintLink linkFlag\n" ▫︎ Perhaps: "Combine with src/Language/Docker/PrettyPrint.hs:328:9-34"
prettyPrintChmod chmodFlag
prettyPrintLink linkFlag
prettyPrintCopySource sourceFlag
prettyPrintExcludes excludeFlags
prettyPrintFileList sourcePaths targetPath
Cmd c -> do
"CMD"
Expand Down Expand Up @@ -321,12 +322,13 @@
prettyPrintBaseImage b
Add
AddArgs {sourcePaths, targetPath}
AddFlags {checksumFlag, chownFlag, chmodFlag, linkFlag} -> do
AddFlags {checksumFlag, chownFlag, chmodFlag, linkFlag, excludeFlags} -> do
"ADD"
prettyPrintChecksum checksumFlag
prettyPrintChown chownFlag
prettyPrintChmod chmodFlag
prettyPrintLink linkFlag
prettyPrintExcludes excludeFlags
prettyPrintFileList sourcePaths targetPath
Shell args -> do
"SHELL"
Expand All @@ -343,6 +345,12 @@
where
(>>) = spaceCat

prettyPrintExcludes :: [Exclude] -> Doc ann
prettyPrintExcludes excludes = hsep (fmap prettyPrintExclude excludes)

prettyPrintExclude :: Exclude -> Doc ann
prettyPrintExclude (Exclude e) = "--exclude=" <> pretty e

spaceCat :: Doc ann -> Doc ann -> Doc ann
spaceCat a Empty = a
spaceCat Empty b = b
Expand Down
16 changes: 12 additions & 4 deletions src/Language/Docker/Syntax.hs
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@
if "/" `isInfixOf` img
then
let parts = endBy "/" img
in if "." `isInfixOf` head parts

Check warning on line 45 in src/Language/Docker/Syntax.hs

View workflow job for this annotation

GitHub Actions / hadolint (ubuntu-latest)

In the use of ‘head’
then
Image
(Just (Registry (Text.pack (head parts))))

Check warning on line 48 in src/Language/Docker/Syntax.hs

View workflow job for this annotation

GitHub Actions / hadolint (ubuntu-latest)

In the use of ‘head’
(Text.pack . intercalate "/" $ tail parts)

Check warning on line 49 in src/Language/Docker/Syntax.hs

View workflow job for this annotation

GitHub Actions / hadolint (ubuntu-latest)

In the use of ‘tail’
else Image Nothing (Text.pack img)
else Image Nothing (Text.pack img)

Expand Down Expand Up @@ -192,12 +192,13 @@
{ chownFlag :: !Chown,
chmodFlag :: !Chmod,
linkFlag :: !Link,
sourceFlag :: !CopySource
sourceFlag :: !CopySource,
excludeFlags :: ![Exclude]
}
deriving (Show, Eq, Ord)

instance Default CopyFlags where
def = CopyFlags NoChown NoChmod NoLink NoSource
def = CopyFlags NoChown NoChmod NoLink NoSource []

data AddArgs
= AddArgs
Expand All @@ -211,12 +212,19 @@
{ checksumFlag :: !Checksum,
chownFlag :: !Chown,
chmodFlag :: !Chmod,
linkFlag :: !Link
linkFlag :: !Link,
excludeFlags :: ![Exclude]
}
deriving (Show, Eq, Ord)

instance Default AddFlags where
def = AddFlags NoChecksum NoChown NoChmod NoLink
def = AddFlags NoChecksum NoChown NoChmod NoLink []

newtype Exclude
= Exclude
{ unExclude :: Text
}
deriving (Show, Eq, Ord, IsString)

data Check args
= Check !(CheckArgs args)
Expand Down
24 changes: 24 additions & 0 deletions test/Language/Docker/ParseAddSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,27 @@ spec = do
)
( AddFlags NoChecksum (Chown "user:group") NoChmod NoLink )
]
it "with exclude flag" $
let file = Text.unlines ["ADD --exclude=*.tmp foo bar"]
in assertAst
file
[ Add
( AddArgs (fmap SourcePath ["foo"]) (TargetPath "bar") )
( AddFlags NoChecksum NoChown NoChmod NoLink (Exclude "*.tmp") )
]
it "with multiple exclude flags" $
let file = Text.unlines ["ADD --exclude=*.tmp --exclude=*.log foo bar"]
in assertAst
file
[ Add
( AddArgs (fmap SourcePath ["foo"]) (TargetPath "bar") )
( AddFlags NoChecksum NoChown NoChmod NoLink (Exclude "*.tmp") (Exclude "*.log") )
]
it "with exclude and other flags" $
let file = Text.unlines ["ADD --chown=root:root --exclude=*.tmp foo bar"]
in assertAst
file
[ Add
( AddArgs (fmap SourcePath ["foo"]) (TargetPath "bar") )
( AddFlags NoChecksum (Chown "root:root") NoChmod NoLink (Exclude "*.tmp") )
]
24 changes: 24 additions & 0 deletions test/Language/Docker/ParseCopySpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,30 @@ spec = do
(CopySource "node")
)
]
it "with exclude flag" $
let file = Text.unlines ["COPY --exclude=*.tmp foo bar"]
in assertAst
file
[ Copy
( CopyArgs [ SourcePath "foo" ] (TargetPath "bar") )
( CopyFlags NoChown NoChmod NoLink NoSource [Exclude "*.tmp"] )
]
it "with multiple exclude flags" $
let file = Text.unlines ["COPY --exclude=*.tmp --exclude=*.log foo bar"]
in assertAst
file
[ Copy
( CopyArgs [ SourcePath "foo" ] (TargetPath "bar") )
( CopyFlags NoChown NoChmod NoLink NoSource [Exclude "*.tmp", Exclude "*.log"] )
]
it "with exclude and other flags" $
let file = Text.unlines ["COPY --chown=root:root --exclude=*.tmp foo bar"]
in assertAst
file
[ Copy
( CopyArgs [ SourcePath "foo" ] (TargetPath "bar") )
( CopyFlags (Chown "root:root") NoChmod NoLink NoSource [Exclude "*.tmp"] )
]

describe "Copy with Heredocs" $ do
it "empty heredoc" $
Expand Down
30 changes: 30 additions & 0 deletions test/Language/Docker/PrettyPrintSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,21 @@ spec = do
( AddArgs [SourcePath "foo"] (TargetPath "bar") )
( AddFlags NoChecksum ( Chown "root:root" ) ( Chmod "751" ) Link )
in assertPretty "ADD --chown=root:root --chmod=751 --link foo bar" add
it "with just exclude" $ do
let add = Add
( AddArgs [SourcePath "foo"] (TargetPath "bar") )
( AddFlags NoChecksum NoChown NoChmod NoLink [Exclude "*.tmp"] )
in assertPretty "ADD --exclude=*.tmp foo bar" add
it "with multiple exclude flags" $ do
let add = Add
( AddArgs [SourcePath "foo"] (TargetPath "bar") )
( AddFlags NoChecksum NoChown NoChmod NoLink [Exclude "*.tmp", Exclude "*.log"] )
in assertPretty "ADD --exclude=*.tmp --exclude=*.log foo bar" add
it "with exclude and other flags" $ do
let add = Add
( AddArgs [SourcePath "foo"] (TargetPath "bar") )
( AddFlags NoChecksum (Chown "root:root") NoChmod NoLink [Exclude "*.tmp"] )
in assertPretty "ADD --chown=root:root --exclude=*.tmp foo bar" add

describe "pretty print COPY" $ do
it "with just copy" $ do
Expand Down Expand Up @@ -95,6 +110,21 @@ spec = do
in assertPretty
"COPY --chown=root:root --chmod=751 --link --from=baseimage foo bar"
copy
it "with just exclude" $ do
let copy = Copy
( CopyArgs [SourcePath "foo"] (TargetPath "bar") )
( CopyFlags NoChown NoChmod NoLink NoSource [Exclude "*.tmp"] )
in assertPretty "COPY --exclude=*.tmp foo bar" copy
it "with multiple exclude flags" $ do
let copy = Copy
( CopyArgs [SourcePath "foo"] (TargetPath "bar") )
( CopyFlags NoChown NoChmod NoLink NoSource [Exclude "*.tmp", Exclude "*.log"] )
in assertPretty "COPY --exclude=*.tmp --exclude=*.log foo bar" copy
it "with exclude and other flags" $ do
let copy = Copy
( CopyArgs [SourcePath "foo"] (TargetPath "bar") )
( CopyFlags (Chown "root:root") NoChmod NoLink NoSource [Exclude "*.tmp"] )
in assertPretty "COPY --chown=root:root --exclude=*.tmp foo bar" copy

describe "pretty print # escape" $ do
it "# escape = \\" $ do
Expand Down
Loading