Skip to content

Commit

Permalink
Reorganize + implement dm workdir resolution
Browse files Browse the repository at this point in the history
1. *.Types are not exposed, just re-exported from *.Parser
2. Removed Locator since its logic was mostly depended on Config.Parser
  • Loading branch information
samtay committed Dec 13, 2016
1 parent a04ab51 commit 6635875
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 49 deletions.
6 changes: 3 additions & 3 deletions dockmaster.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@ description:
library
hs-source-dirs: src
exposed-modules: Dockmaster
, Dockmaster.Types
, Dockmaster.Config.Types
other-modules: Dockmaster.Locator
, Dockmaster.Parser
, Dockmaster.Config.Parser
other-modules: Dockmaster.Types
, Dockmaster.Config.Types
, Dockmaster.Utils
build-depends: base >= 4.7 && < 5
, yaml
Expand All @@ -34,6 +33,7 @@ library
, text
, bytestring
, regex-posix
, system-filepath >= 0.4.7 && < 0.5
default-language: Haskell2010

executable dm
Expand Down
5 changes: 3 additions & 2 deletions src/Dockmaster.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ module Dockmaster
( dm
) where

-- Base modules
import Data.Either
import Data.Monoid ((<>))
import Data.Maybe

-- Local modules
import Dockmaster.Locator
import Dockmaster.Parser
import Dockmaster.Types
import Dockmaster.Config.Parser

-- External modules
import Shelly
Expand All @@ -27,6 +27,7 @@ type DCCommand = T.Text
-- See usage docs for more info. Tries to find a dockmaster.yml file based on
-- the initial path argument
-- TODO monad >>= and >> the shit out of this to remove the casing structure
-- TODO Possibly remove Either return types & just error out whenever
-- REMEMBER you can do `when weAreDone exitSuccess` as control flow in do statement
dm :: FilePath -> DCCommand -> [T.Text] -> Sh ()
dm path command args = do
Expand Down
78 changes: 69 additions & 9 deletions src/Dockmaster/Config/Parser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,17 @@
{-# LANGUAGE ExtendedDefaultRules #-}
{-# OPTIONS_GHC -fno-warn-type-defaults #-}
module Dockmaster.Config.Parser
( config
(
-- * Getting global config
config
, baseConfig

-- * Resolving relative paths
, getWorkDir
, getWorkDir'

-- * Re-exported for convenience
, module Dockmaster.Config.Types
) where

-- Local modules
Expand All @@ -16,13 +25,15 @@ import qualified Data.ByteString as BS
import Shelly
import Prelude hiding (FilePath)
import qualified Data.Text as T
import qualified Filesystem.Path.CurrentOS as FP
import Data.Monoid ((<>), mconcat, First(..))
import Control.Monad (liftM)
default (T.Text)

-- | Get global dockmaster config
-- If config.yml fails to parse, returns Left error
-- If config.yml is not found, returns Right baseConfig (default configuration)
--
-- If config.yml fails to parse, returns Left error.
-- If config.yml is not found, returns Right baseConfig (default configuration).
config :: Sh (Either T.Text Config)
config = do
mPath <- resolvePath
Expand All @@ -33,10 +44,15 @@ config = do
return $
eitherWrap T.pack id (decodeEither contents :: Either String Config)

-- | Get base config options
baseConfig :: Config
baseConfig = Config { dmcPaths = [] }

-- | Resolves path to dockmaster config.yml in the following order of precedence:
-- - DOCKMASTER_CONFIG environment variable
-- - $HOME/.dockmaster/config.yml
-- - /etc/dockmaster/config.yml
--
-- (1) DOCKMASTER_CONFIG environment variable
-- (2) $HOME/.dockmaster/config.yml
-- (3) /etc/dockmaster/config.yml
resolvePath :: Sh (Maybe FilePath)
resolvePath = do
envPathT <- get_env "DOCKMASTER_CONFIG"
Expand All @@ -45,6 +61,50 @@ resolvePath = do
return $
getFirst . mconcat $ map First [envPathT >>= (return . fromText), homePath, etcPath]

-- | Get base config options
baseConfig :: Config
baseConfig = Config { dmcPaths = [] }
-- | Resolve the appropriate dockmaster workdir.
--
-- For example, if @$CWD/dockmaster.yml@ exists, then
-- >>> getWorkDir "."
-- Right "."
--
-- If @$CWD/dockmaster.yml@ does /not/ exist, then
-- >>> getWorkDir "."
-- Left "dockmaster.yml file not found"
--
-- This function will also try to resolve relative paths against the 'dmcPath'
-- composition listing directories, if any are specified by global config.
-- For example, if:
--
-- (1) @$HOME/git@ is a PATH specified in global config.yml
-- (2) @$HOME/git/deploybot/dockmaster.yml@ exists
-- (3) @$CWD/deploybot/dockmaster.yml@ does /not/ exist, then
-- >>> getWorkDir "deploybot"
-- Right "$HOME/git/deploybot"
getWorkDir :: FilePath -> Sh (Either T.Text FilePath)
getWorkDir p = undefined

-- | Same thing as 'getWorkDir' but uses a 'Config' argument instead of
-- resolving one.
getWorkDir' :: Config -> FilePath -> Sh (Either T.Text FilePath)
getWorkDir' cfg p = do
-- If absolute path is given, it is the only one attempted
mPath <- getFirst <$> if FP.absolute p
then tryPath p
else mconcat <$> mapM tryPath (map (</> p) $ "." : dmcPaths cfg)

return $ maybe workDirNotFound Right mPath

-- | Check if directory @dir@ contains a @dockmaster.yml@ file
-- If it does, return @First dir@, otherwise Nothing
-- Using the @First@ monoid so we can have precedence for composition listings
tryPath :: FilePath -> Sh (First FilePath)
tryPath dir = do
found <- test_e (dir </> "dockmaster.yml")
return . First $ if found
then Just dir
else Nothing


-- | Just a small abstraction to keep error message on its own
workDirNotFound :: Either T.Text b
workDirNotFound = Left "dockmaster.yml file not found"
32 changes: 0 additions & 32 deletions src/Dockmaster/Locator.hs

This file was deleted.

9 changes: 7 additions & 2 deletions src/Dockmaster/Parser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
{-# LANGUAGE ExtendedDefaultRules #-}
{-# OPTIONS_GHC -fno-warn-type-defaults #-}
module Dockmaster.Parser
(
dockmasterYml
( dockmasterYml
-- * Re-exported for convenience
, module Dockmaster.Types
) where

-- Local modules
import Dockmaster.Utils (eitherWrap)
import Dockmaster.Config.Parser

-- External modules
import Data.Yaml
Expand All @@ -19,6 +21,9 @@ import Prelude hiding (FilePath)
import qualified Data.Text as T
default (T.Text)

-- | Parse $CWD/dockmaster.yml
--
-- Note this assumes we are already in the correct dockmaster workdir
dockmasterYml :: Sh (Either T.Text Dockmaster)
dockmasterYml = do
contents <- readBinary "dockmaster.yml"
Expand Down
4 changes: 3 additions & 1 deletion test/Spec.hs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
module Main where

import Data.Yaml
import Dockmaster.Types
import Dockmaster.Parser
import qualified Data.ByteString as BS
import Data.Maybe
import System.Exit
import System.Directory

-- TODO test Dockmaster.Parser.dockmasterYml instead of using this parse function

parseDockmasterYml :: FilePath -> IO Bool
parseDockmasterYml "." = return True
parseDockmasterYml ".." = return True
Expand Down

0 comments on commit 6635875

Please sign in to comment.