Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for the --exclude flag #102

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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,6 +15,7 @@ data Flag
| FlagChmod Chmod
| FlagLink Link
| FlagSource CopySource
| FlagExclude Exclude
| FlagInvalid (Text, Text)

parseCopy :: (?esc :: Char) => Parser (Instruction Text)
Expand All @@ -25,14 +26,16 @@ parseCopy = do
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 =
case chownFlags of
Expand All @@ -50,8 +53,12 @@ parseCopy = do
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
e : _ -> e
try (heredocList (\src dest -> Copy (CopyArgs src dest) (CopyFlags cho chm lnk fr exc)))
<|> fileList "COPY" (\src dest -> Copy (CopyArgs src dest) (CopyFlags cho chm lnk fr exc))

parseAdd :: (?esc :: Char) => Parser (Instruction Text)
parseAdd = do
Expand All @@ -61,15 +68,17 @@ parseAdd = do
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 @@ parseAdd = do
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
e : _ -> e
fileList "ADD" (\src dest -> Add (AddArgs src dest) (AddFlags chk cho chm lnk exc))

heredocList :: (?esc :: Char) =>
(NonEmpty SourcePath -> TargetPath -> Instruction Text) ->
Expand Down Expand Up @@ -124,6 +135,7 @@ addFlag = (FlagChecksum <$> try checksum <?> "--checksum")
<|> (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 @@ copySource = do
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 @@ prettyPrintInstruction i =
prettyPrintArguments c
Copy
CopyArgs {sourcePaths, targetPath}
CopyFlags {chmodFlag, chownFlag, linkFlag, sourceFlag} -> do
CopyFlags {chmodFlag, chownFlag, linkFlag, sourceFlag, excludeFlags} -> do
"COPY"
prettyPrintChown chownFlag
prettyPrintChmod chmodFlag
prettyPrintLink linkFlag
prettyPrintCopySource sourceFlag
prettyPrintExcludes excludeFlags
prettyPrintFileList sourcePaths targetPath
Cmd c -> do
"CMD"
Expand Down Expand Up @@ -321,12 +322,13 @@ prettyPrintInstruction i =
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 @@ prettyPrintInstruction i =
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 @@ -192,12 +192,13 @@ data CopyFlags
{ 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 @@ data AddFlags
{ 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