Skip to content
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
76 changes: 59 additions & 17 deletions src/Language/Docker/Parser/Copy.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ data Flag
| FlagChown Chown
| FlagChmod Chmod
| FlagLink Link
| FlagKeepGitDir KeepGitDir
| FlagParents Parents
| FlagUnpack Unpack
| FlagSource CopySource
| FlagExclude Exclude
| FlagInvalid (Text, Text)
Expand All @@ -25,16 +28,18 @@ parseCopy = do
let chownFlags = [c | FlagChown c <- flags]
let chmodFlags = [c | FlagChmod c <- flags]
let linkFlags = [l | FlagLink l <- flags]
let parentsFlags = [p | FlagParents p <- 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, excludeFlags) of
((k, v) : _, _, _, _, _, _) -> unexpectedFlag k v
(_, _ : _ : _, _, _, _, _) -> customError $ DuplicateFlagError "--chown"
(_, _, _ : _ : _, _, _, _) -> customError $ DuplicateFlagError "--chmod"
(_, _, _, _ : _ : _, _, _) -> customError $ DuplicateFlagError "--link"
(_, _, _, _, _ : _ : _, _) -> customError $ DuplicateFlagError "--from"
case (invalid, chownFlags, chmodFlags, linkFlags, parentsFlags, sourceFlags, excludeFlags) of
((k, v) : _, _, _, _, _, _, _) -> unexpectedFlag k v
(_, _ : _ : _, _, _, _, _, _) -> customError $ DuplicateFlagError "--chown"
(_, _, _ : _ : _, _, _, _, _) -> customError $ DuplicateFlagError "--chmod"
(_, _, _, _ : _ : _, _, _, _) -> customError $ DuplicateFlagError "--link"
(_, _, _, _, _ : _ : _, _, _) -> customError $ DuplicateFlagError "--parents"
(_, _, _, _, _, _ : _ : _, _) -> customError $ DuplicateFlagError "--from"
_ -> do
let cho =
case chownFlags of
Expand All @@ -48,12 +53,16 @@ parseCopy = do
case linkFlags of
[] -> NoLink
l : _ -> l
let par =
case parentsFlags of
[] -> NoParents
p : _ -> p
let fr =
case sourceFlags of
[] -> NoSource
f : _ -> f
try (heredocList (\src dest -> Copy (CopyArgs src dest) (CopyFlags cho chm lnk fr excludeFlags)))
<|> fileList "COPY" (\src dest -> Copy (CopyArgs src dest) (CopyFlags cho chm lnk fr excludeFlags))
try (heredocList (\src dest -> Copy (CopyArgs src dest) (CopyFlags cho chm lnk par fr excludeFlags)))
<|> fileList "COPY" (\src dest -> Copy (CopyArgs src dest) (CopyFlags cho chm lnk par fr excludeFlags))

parseAdd :: (?esc :: Char) => Parser (Instruction Text)
parseAdd = do
Expand All @@ -63,16 +72,20 @@ parseAdd = do
let chownFlags = [c | FlagChown c <- flags]
let chmodFlags = [c | FlagChmod c <- flags]
let linkFlags = [l | FlagLink l <- flags]
let keepGitDirFlags = [k | FlagKeepGitDir k <- flags]
let unpackFlags = [u | FlagUnpack u <- flags]
let excludeFlags = [e | FlagExclude e <- flags]
let invalidFlags = [i | FlagInvalid i <- flags]
notFollowedBy (string "--") <?>
"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"
"only the --checksum, --chown, --chmod, --link, --exclude, --keep-git-dir, --unpack flags or the src and dest paths"
case (invalidFlags, checksumFlags, chownFlags, linkFlags, chmodFlags, keepGitDirFlags, unpackFlags, excludeFlags) of
((k, v) : _, _, _, _, _, _, _, _) -> unexpectedFlag k v
(_, _ : _ : _, _, _, _, _, _, _) -> customError $ DuplicateFlagError "--checksum"
(_, _, _ : _ : _, _, _, _, _, _) -> customError $ DuplicateFlagError "--chown"
(_, _, _, _ : _ : _, _, _, _, _) -> customError $ DuplicateFlagError "--chmod"
(_, _, _, _, _ : _ : _, _, _, _) -> customError $ DuplicateFlagError "--link"
(_, _, _, _, _, _ : _ : _, _, _) -> customError $ DuplicateFlagError "--keep-git-dir"
(_, _, _, _, _, _, _ : _ : _, _) -> customError $ DuplicateFlagError "--unpack"
_ -> do
let chk = case checksumFlags of
[] -> NoChecksum
Expand All @@ -86,7 +99,13 @@ parseAdd = do
let lnk = case linkFlags of
[] -> NoLink
l : _ -> l
fileList "ADD" (\src dest -> Add (AddArgs src dest) (AddFlags chk cho chm lnk excludeFlags))
let kgd = case keepGitDirFlags of
[] -> NoKeepGitDir
k : _ -> k
let unp = case unpackFlags of
[] -> NoUnpack
u : _ -> u
fileList "ADD" (\src dest -> Add (AddArgs src dest) (AddFlags chk cho chm lnk kgd unp excludeFlags))

heredocList :: (?esc :: Char) =>
(NonEmpty SourcePath -> TargetPath -> Instruction Text) ->
Expand Down Expand Up @@ -119,13 +138,21 @@ unexpectedFlag name "" = customFailure $ NoValueFlagError (T.unpack name)
unexpectedFlag name _ = customFailure $ InvalidFlagError (T.unpack name)

copyFlag :: (?esc :: Char) => Parser Flag
copyFlag = (FlagSource <$> try copySource <?> "only one --from") <|> addFlag
copyFlag = (FlagSource <$> try copySource <?> "only one --from")
<|> (FlagChown <$> try chown <?> "--chown")
<|> (FlagChmod <$> try chmod <?> "--chmod")
<|> (FlagLink <$> try link <?> "--link")
<|> (FlagParents <$> try parents <?> "--parents")
<|> (FlagExclude <$> try exclude <?> "--exclude")
<|> (FlagInvalid <$> try anyFlag <?> "other flag")

addFlag :: (?esc :: Char) => Parser Flag
addFlag = (FlagChecksum <$> try checksum <?> "--checksum")
<|> (FlagChown <$> try chown <?> "--chown")
<|> (FlagChmod <$> try chmod <?> "--chmod")
<|> (FlagLink <$> try link <?> "--link")
<|> (FlagKeepGitDir <$> try keepGitDir <?> "--keep-git-dir")
<|> (FlagUnpack <$> try unpack <?> "--unpack")
<|> (FlagExclude <$> try exclude <?> "--exclude")
<|> (FlagInvalid <$> try anyFlag <?> "other flag")

Expand All @@ -152,6 +179,21 @@ link = do
void $ string "--link"
return Link

parents :: Parser Parents
parents = do
void $ string "--parents"
return Parents

keepGitDir :: Parser KeepGitDir
keepGitDir = do
void $ string "--keep-git-dir"
return KeepGitDir

unpack :: Parser Unpack
unpack = do
void $ string "--unpack"
return Unpack

copySource :: (?esc :: Char) => Parser CopySource
copySource = do
void $ string "--from="
Expand Down
25 changes: 23 additions & 2 deletions src/Language/Docker/PrettyPrint.hs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,24 @@ prettyPrintLink link =
Link -> "--link"
NoLink -> mempty

prettyPrintKeepGitDir :: KeepGitDir -> Doc ann
prettyPrintKeepGitDir keepGitDir =
case keepGitDir of
KeepGitDir -> "--keep-git-dir"
NoKeepGitDir -> mempty

prettyPrintParents :: Parents -> Doc ann
prettyPrintParents parents =
case parents of
Parents -> "--parents"
NoParents -> mempty

prettyPrintUnpack :: Unpack -> Doc ann
prettyPrintUnpack unpack =
case unpack of
Unpack -> "--unpack"
NoUnpack -> mempty

prettyPrintCopySource :: CopySource -> Doc ann
prettyPrintCopySource source =
case source of
Expand Down Expand Up @@ -293,11 +311,12 @@ prettyPrintInstruction i =
prettyPrintArguments c
Copy
CopyArgs {sourcePaths, targetPath}
CopyFlags {chmodFlag, chownFlag, linkFlag, sourceFlag, excludeFlags} -> do
CopyFlags {chmodFlag, chownFlag, linkFlag, parentsFlag, sourceFlag, excludeFlags} -> do
"COPY"
prettyPrintChown chownFlag
prettyPrintChmod chmodFlag
prettyPrintLink linkFlag
prettyPrintParents parentsFlag
prettyPrintCopySource sourceFlag
prettyPrintExcludes excludeFlags
prettyPrintFileList sourcePaths targetPath
Expand Down Expand Up @@ -327,12 +346,14 @@ prettyPrintInstruction i =
prettyPrintBaseImage b
Add
AddArgs {sourcePaths, targetPath}
AddFlags {checksumFlag, chownFlag, chmodFlag, linkFlag, excludeFlags} -> do
AddFlags {checksumFlag, chownFlag, chmodFlag, linkFlag, keepGitDirFlag, unpackFlag, excludeFlags} -> do
"ADD"
prettyPrintChecksum checksumFlag
prettyPrintChown chownFlag
prettyPrintChmod chmodFlag
prettyPrintLink linkFlag
prettyPrintKeepGitDir keepGitDirFlag
prettyPrintUnpack unpackFlag
prettyPrintExcludes excludeFlags
prettyPrintFileList sourcePaths targetPath
Shell args -> do
Expand Down
22 changes: 20 additions & 2 deletions src/Language/Docker/Syntax.hs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,21 @@ data Link
| NoLink
deriving (Show, Eq, Ord)

data KeepGitDir
= KeepGitDir
| NoKeepGitDir
deriving (Show, Eq, Ord)

data Parents
= Parents
| NoParents
deriving (Show, Eq, Ord)

data Unpack
= Unpack
| NoUnpack
deriving (Show, Eq, Ord)

data CopySource
= CopySource !Text
| NoSource
Expand Down Expand Up @@ -197,13 +212,14 @@ data CopyFlags
{ chownFlag :: !Chown,
chmodFlag :: !Chmod,
linkFlag :: !Link,
parentsFlag :: !Parents,
sourceFlag :: !CopySource,
excludeFlags :: ![Exclude]
}
deriving (Show, Eq, Ord)

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

data AddArgs
= AddArgs
Expand All @@ -218,12 +234,14 @@ data AddFlags
chownFlag :: !Chown,
chmodFlag :: !Chmod,
linkFlag :: !Link,
keepGitDirFlag :: !KeepGitDir,
unpackFlag :: !Unpack,
excludeFlags :: ![Exclude]
}
deriving (Show, Eq, Ord)

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

newtype Exclude
= Exclude
Expand Down
39 changes: 28 additions & 11 deletions test/Language/Docker/ParseAddSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -47,47 +47,64 @@ spec = do
file
[ Add
( AddArgs (fmap SourcePath ["http://www.example.com/foo"]) (TargetPath "bar") )
( AddFlags (Checksum "sha256:24454f830cdd") NoChown NoChmod NoLink [] )
( AddFlags (Checksum "sha256:24454f830cdd") NoChown NoChmod NoLink NoKeepGitDir NoUnpack [] )
]
it "with chown flag" $
let file = Text.unlines ["ADD --chown=root:root foo bar"]
in assertAst
file
[ Add
( AddArgs (fmap SourcePath ["foo"]) (TargetPath "bar") )
( AddFlags NoChecksum (Chown "root:root") NoChmod NoLink [] )
( AddFlags NoChecksum (Chown "root:root") NoChmod NoLink NoKeepGitDir NoUnpack [] )
]
it "with chmod flag" $
let file = Text.unlines ["ADD --chmod=640 foo bar"]
in assertAst
file
[ Add
( AddArgs (fmap SourcePath ["foo"]) (TargetPath "bar") )
( AddFlags NoChecksum NoChown (Chmod "640") NoLink [] )
( AddFlags NoChecksum NoChown (Chmod "640") NoLink NoKeepGitDir NoUnpack [] )
]
it "with link flag" $
let file = Text.unlines ["ADD --link foo bar"]
in assertAst
file
[ Add
( AddArgs (fmap SourcePath ["foo"]) (TargetPath "bar") )
( AddFlags NoChecksum NoChown NoChmod Link [])
( AddFlags NoChecksum NoChown NoChmod Link NoKeepGitDir NoUnpack [] )
]
it "with keep-git-dir flag" $
let file = Text.unlines ["ADD --keep-git-dir foo bar"]
in assertAst
file
[ Add
( AddArgs (fmap SourcePath ["foo"]) (TargetPath "bar") )
( AddFlags NoChecksum NoChown NoChmod NoLink KeepGitDir NoUnpack [] )
]

it "with unpack flag" $
let file = Text.unlines ["ADD --unpack foo bar"]
in assertAst
file
[ Add
( AddArgs (fmap SourcePath ["foo"]) (TargetPath "bar") )
( AddFlags NoChecksum NoChown NoChmod NoLink NoKeepGitDir Unpack [] )
]
it "with chown and chmod flag" $
let file = Text.unlines ["ADD --chown=root:root --chmod=640 foo bar"]
in assertAst
file
[ Add
( AddArgs (fmap SourcePath ["foo"]) (TargetPath "bar") )
( AddFlags NoChecksum (Chown "root:root") (Chmod "640") NoLink [] )
( AddFlags NoChecksum (Chown "root:root") (Chmod "640") NoLink NoKeepGitDir NoUnpack [] )
]
it "with chown and chmod flag other order" $
let file = Text.unlines ["ADD --chmod=640 --chown=root:root foo bar"]
in assertAst
file
[ Add
( AddArgs (fmap SourcePath ["foo"]) (TargetPath "bar") )
( AddFlags NoChecksum (Chown "root:root") (Chmod "640") NoLink [] )
( AddFlags NoChecksum (Chown "root:root") (Chmod "640") NoLink NoKeepGitDir NoUnpack [] )
]
it "with all flags" $
let file =
Expand All @@ -96,7 +113,7 @@ spec = do
file
[ Add
( AddArgs (fmap SourcePath ["foo"]) (TargetPath "bar") )
( AddFlags (Checksum "sha256:24454f830cdd") (Chown "root:root") (Chmod "640") Link [] )
( AddFlags (Checksum "sha256:24454f830cdd") (Chown "root:root") (Chmod "640") Link NoKeepGitDir NoUnpack [] )
]
it "list of quoted files and chown" $
let file =
Expand All @@ -109,29 +126,29 @@ spec = do
(fmap SourcePath ["foo", "bar", "baz"])
(TargetPath "/app")
)
( AddFlags NoChecksum (Chown "user:group") NoChmod NoLink [] )
( AddFlags NoChecksum (Chown "user:group") NoChmod NoLink NoKeepGitDir NoUnpack [] )
]
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"] )
( AddFlags NoChecksum NoChown NoChmod NoLink NoKeepGitDir NoUnpack [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"] )
( AddFlags NoChecksum NoChown NoChmod NoLink NoKeepGitDir NoUnpack [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"] )
( AddFlags NoChecksum (Chown "root:root") NoChmod NoLink NoKeepGitDir NoUnpack [Exclude "*.tmp"] )
]
Loading