dotenv 0.10.0.1 → 0.10.1.0
raw patch · 6 files changed
+53/−21 lines, 6 filesdep ~mtlPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: mtl
API changes (from Hackage documentation)
Files
- CHANGELOG.md +8/−0
- README.md +2/−2
- app/Main.hs +1/−0
- dotenv.cabal +2/−2
- spec/Configuration/DotenvSpec.hs +8/−1
- src/Configuration/Dotenv.hs +32/−16
CHANGELOG.md view
@@ -1,4 +1,12 @@ ## MASTER+## Dotenv 0.10.1.0+### Added+* Short `-x` for `--example` flag++### Modified+* Fix `union`/`unionBy` bug, refactor .env.example check, and improve error+message (Kudos to @pbrisbin)+ ## Dotenv 0.10.0.1 ### Modified * Modify docs.
README.md view
@@ -1,4 +1,4 @@-[](https://github.com/stackbuilders/dotenv-hs/actions/workflows/build-and-test.yml) [](http://hackage.haskell.org/package/dotenv)+[](https://github.com/stackbuilders/dotenv-hs/actions/workflows/build.yml)[](http://hackage.haskell.org/package/dotenv) # Dotenv files for Haskell @@ -161,7 +161,7 @@ This will fail: ```shell $ dotenv -f .env --example .env.example "myprogram --myflag myargument"-> dotenv: Missing env vars! Please, check (this/these) var(s) (is/are) set: BAR+> dotenv: The following variables are present in .env.example, but not set in the current environment, or .env: BAR ``` This will succeed:
app/Main.hs view
@@ -62,6 +62,7 @@ <*> many (strOption ( long "example"+ <> short 'x' <> metavar "DOTENV_EXAMPLE" <> help "File to read for needed environmental variables" ))
dotenv.cabal view
@@ -1,5 +1,5 @@ name: dotenv-version: 0.10.0.1+version: 0.10.1.0 synopsis: Loads environment variables from dotenv files homepage: https://github.com/stackbuilders/dotenv-hs description:@@ -96,7 +96,7 @@ , shellwords >= 0.1.3.0 , text , exceptions >= 0.8 && < 0.11- , mtl >= 2.3 && < 2.4+ , mtl >= 2.2.2 && < 2.4 hs-source-dirs: src ghc-options: -Wall
spec/Configuration/DotenvSpec.hs view
@@ -72,7 +72,7 @@ unsetEnv "ANOTHER_ENV" loadFile config `shouldThrow` anyErrorCall - context "when the needed env vars are not missing" $+ context "when the needed env vars are not missing" $ do it "should succeed when loading all of the needed env vars" $ do -- Load extra information me <- init <$> readCreateProcess (shell "whoami") ""@@ -87,6 +87,13 @@ lookupEnv "DOTENV" `shouldReturn` Just "true" lookupEnv "UNICODE_TEST" `shouldReturn` Just "Manabí" lookupEnv "ANOTHER_ENV" `shouldReturn` Just "hello"++ it "succeeds when variable is preset" $ do+ setEnv "DOTENV" "preset"++ loadFile config++ lookupEnv "DOTENV" `shouldReturn` Just "preset" describe "parseFile" $ after_ clearEnvs $ do it "returns variables from a file without changing the environment" $ do
src/Configuration/Dotenv.hs view
@@ -31,8 +31,10 @@ import Control.Monad (unless, when) import Control.Monad.Catch import Control.Monad.IO.Class (MonadIO (..))-import Data.List (intersectBy, union,- unionBy)+import Data.Function (on)+import Data.List.NonEmpty (NonEmpty(..))+import qualified Data.List.NonEmpty as NE+import Data.List ((\\), intercalate, union) import System.IO.Error (isDoesNotExistError) import Text.Megaparsec (errorBundlePretty, parse) @@ -59,22 +61,36 @@ -> m () loadFile config@Config {..} = do environment <- liftIO getEnvironment- readVars <- fmap concat (mapM parseFile configPath)- neededVars <- fmap concat (mapM parseFile configExamplePath)- let coincidences = (environment `union` readVars) `intersectEnvs` neededVars- cmpEnvs env1 env2 = fst env1 == fst env2- intersectEnvs = intersectBy cmpEnvs- unionEnvs = unionBy cmpEnvs- vars =- if (not . null) neededVars- then if length neededVars == length coincidences- then readVars `unionEnvs` neededVars- else error $- "Missing env vars! Please, check (this/these) var(s) (is/are) set:" ++- concatMap ((++) " " . fst) neededVars- else readVars++ vars <- case (NE.nonEmpty configPath, NE.nonEmpty configExamplePath) of+ (Nothing, _) -> pure []+ (Just envs, Nothing) -> concat <$> mapM parseFile envs+ (Just envs, Just envExamples) -> do+ readVars <- concat <$> mapM parseFile envs+ neededKeys <- map fst . concat <$> mapM parseFile envExamples++ let+ presentKeys = (union `on` map fst) environment readVars+ missingKeys = neededKeys \\ presentKeys++ pure $+ if null missingKeys+ then readVars+ else error $ concat+ [ "The following variables are present in "+ , showPaths "one of " envExamples+ , ", but not set in the current environment, or "+ , showPaths "any of " envs+ , ": "+ , intercalate ", " missingKeys+ ]+ unless allowDuplicates $ (lookUpDuplicates . map fst) vars runReaderT (mapM_ applySetting vars) config+ where+ showPaths :: String -> NonEmpty FilePath -> String+ showPaths _ (p:|[]) = p+ showPaths prefix ps = prefix <> intercalate ", " (NE.toList ps) -- | Parses the given dotenv file and returns values /without/ adding them to -- the environment.