packages feed

dotenv 0.5.0.2 → 0.5.1.0

raw patch · 8 files changed

+71/−6 lines, 8 filesdep ~processPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: process

API changes (from Hackage documentation)

+ Configuration.Dotenv.ParsedVariable: CommandInterpolation :: String -> VarFragment

Files

CHANGELOG.md view
@@ -1,4 +1,8 @@ ## MASTER+## Dotenv 0.5.1.0++* Add support for command substitution on env vars.+ ## Dotenv 0.5.0.2  * Set `.env` file as default file for environment variables.
README.md view
@@ -59,6 +59,38 @@ about this. Fortunately, there is already some work for this issue in [GHC Phabricator](https://phabricator.haskell.org/D3726). +### Variable substitution++In order to use compound env vars use the following sintax within your env vars+${your_env_var}. For instance:++```+DATABASE=postgres://${USER}@localhost/database+```+ +Running it on the CLI:++```+$ dotenv "echo $DATABASE"+postgres://myusername@localhost/database+```++### Command substitution++In order to use the standard output of a command in your env vars use the following+sintax $(your_command). For instance:++```+DATABASE=postgres://$(whoami)@localhost/database+```+ +Running it on the CLI:++```+$ dotenv "echo $DATABASE"+postgres://myusername@localhost/database+```+ ## Configuration  The first argument to `loadFile` specifies whether you want to
dotenv.cabal view
@@ -1,5 +1,5 @@ name:                dotenv-version:             0.5.0.2+version:             0.5.1.0 synopsis:            Loads environment variables from dotenv files homepage:            https://github.com/stackbuilders/dotenv-hs description:@@ -61,7 +61,7 @@                        , dotenv                        , optparse-applicative >=0.11 && < 0.15                        , megaparsec >= 6.0 && < 7.0-                       , process+                       , process >= 1.4.3.0                        , text                        , transformers >=0.4 && < 0.6   other-modules: Paths_dotenv@@ -83,6 +83,7 @@   build-depends:         base >=4.7 && <5.0                        , base-compat >= 0.4                        , megaparsec >= 6.0 && < 7.0+                       , process >= 1.4.3.0                        , text                        , transformers >=0.4 && < 0.6                        , exceptions >= 0.8 && < 0.9@@ -116,6 +117,7 @@                      , dotenv                      , megaparsec >= 6.0 && < 7.0                      , hspec+                     , process >= 1.4.3.0                      , text                      , transformers >=0.4 && < 0.6                      , exceptions >= 0.8 && < 0.9
spec/Configuration/Dotenv/ParseSpec.hs view
@@ -142,5 +142,11 @@   it "doesn't allow more configuration options after a quoted value" $     parseConfig `shouldFailOn` "foo='bar'baz='buz'" +  it "parses a command $(command)" $ do+    parseConfig "FOO=$(command)"+      `shouldParse` [ParsedVariable "FOO" (Unquoted [CommandInterpolation "command"])]+    parseConfig "FOO=asdf_$(command)"+      `shouldParse` [ParsedVariable "FOO" (Unquoted [VarLiteral "asdf_", CommandInterpolation "command"])]+ parseConfig :: String -> Either (ParseError Char Void) [ParsedVariable] parseConfig = parse configParser ""
spec/Configuration/DotenvSpec.hs view
@@ -7,6 +7,7 @@  import Test.Hspec +import System.Process (readCreateProcess, shell) import System.Environment (lookupEnv) import Control.Monad (liftM) import Data.Maybe (fromMaybe)@@ -111,6 +112,11 @@     it "recognises previous variables" $       liftM (!! 3) (parseFile "spec/fixtures/.dotenv") `shouldReturn`         ("PREVIOUS", "true")++    it "recognises commands" $ do+      me <- init <$> readCreateProcess (shell "whoami") ""+      liftM (!! 4) (parseFile "spec/fixtures/.dotenv") `shouldReturn`+        ("ME", me)    describe "onMissingFile" $ after_ (unsetEnv "DOTENV") $ do     context "when target file is present" $
spec/fixtures/.dotenv view
@@ -2,3 +2,4 @@ UNICODE_TEST=Manabí ENVIRONMENT="$HOME" PREVIOUS="$DOTENV"+ME="$(whoami)"
src/Configuration/Dotenv/Parse.hs view
@@ -60,14 +60,24 @@ quotedWith DoubleQuote = DoubleQuoted <$> (between (char '\"') (char '\"') $ many (fragment "\""))  fragment :: [Char] -> Parser VarFragment-fragment charsToEscape = interpolatedValueFragment <|> literalValueFragment ('$' : '\\' : charsToEscape)+fragment charsToEscape =+  interpolatedValueCommandInterpolation+    <|> interpolatedValueVarInterpolation+    <|> literalValueFragment ('$' : '\\' : charsToEscape) -interpolatedValueFragment :: Parser VarFragment-interpolatedValueFragment = VarInterpolation <$>+interpolatedValueVarInterpolation :: Parser VarFragment+interpolatedValueVarInterpolation = VarInterpolation <$>                             ((between (symbol "${") (symbol "}") variableName) <|>                             (char '$' >> variableName))   where     symbol                = L.symbol sc++interpolatedValueCommandInterpolation :: Parser VarFragment+interpolatedValueCommandInterpolation =+  CommandInterpolation+    <$> between (symbol "$(") (symbol ")") (many alphaNumChar)+    where+      symbol = L.symbol sc  literalValueFragment :: [Char] -> Parser VarFragment literalValueFragment charsToEscape = VarLiteral <$> (some $ escapedChar <|> normalChar)
src/Configuration/Dotenv/ParsedVariable.hs view
@@ -13,6 +13,7 @@ #endif import Control.Applicative ((<|>)) import System.Environment (lookupEnv)+import System.Process (readCreateProcess, shell)  data ParsedVariable   = ParsedVariable VarName VarValue deriving (Show, Eq)@@ -28,7 +29,8 @@  data VarFragment   = VarInterpolation String-  | VarLiteral String deriving (Show, Eq)+  | VarLiteral String+  | CommandInterpolation String deriving (Show, Eq)  interpolateParsedVariables :: [ParsedVariable] -> IO [(String, String)] interpolateParsedVariables = fmap reverse . foldM addInterpolated []@@ -49,9 +51,11 @@ interpolateFragment previous (VarInterpolation varname) = fromPreviousOrEnv >>= maybe (return "") return   where     fromPreviousOrEnv = (lookup varname previous <|>) <$> lookupEnv varname+interpolateFragment _ (CommandInterpolation commandName) = init <$> readCreateProcess (shell commandName) ""  joinContents :: VarContents -> String joinContents = concatMap fragmentToString   where+    fragmentToString (CommandInterpolation value) = value     fragmentToString (VarInterpolation value) = value     fragmentToString (VarLiteral value)       = value