packages feed

dotenv (empty) → 0.1.0.0

raw patch · 8 files changed

+274/−0 lines, 8 filesdep +basedep +hspecdep +optparse-applicativesetup-changed

Dependencies added: base, hspec, optparse-applicative, parsec, process

Files

+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2015 Justin Leitgeb++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ dotenv.cabal view
@@ -0,0 +1,82 @@+name:                dotenv+version:             0.1.0.0+synopsis:            Loads environment variables dotenv files++description:+  .+  In most applications,+  <http://12factor.net/config configuration should be separated from code>.+  While it usually works well to keep configuration in the+  environment, there are cases where you may want to store+  configuration in a file outside of version control.+  .+  "Dotenv" files have become popular for storing configuration,+  especially in development and test environments. In+  <https://github.com/bkeepers/dotenv Ruby>,+  <https://github.com/theskumar/python-dotenv Python> and+  <https://www.npmjs.com/package/dotenv Javascript> there are libraries+  to facilitate loading of configuration options from configuration+  files. This library loads configuration to environment variables for+  programs written in Haskell.+  .+  To use, call `loadFile` from your application:+  .+  > import Configuration.Dotenv+  > loadFile False "/my/dotenvfile"+  .+  This package also includes an executable that can be used+  to inspect the results of applying one or more Dotenv files+  to the environment, or for invoking your executables with+  an environment after one or more Dotenv files is applied.+  .+  See the <https://github.com/stackbuilders/dotenv-hs Github>+  page for more information on this package.+license:             MIT+license-file:        LICENSE+author:              Justin Leitgeb+maintainer:          justin@stackbuilders.com+copyright:           2015 Stack Builders Inc.+category:            Configuration+build-type:          Simple+extra-source-files:  spec/fixtures/.dotenv+cabal-version:       >=1.10++executable dotenv+  main-is:             Main.hs+  -- other-modules:+  -- other-extensions:+  build-depends:         base >=4.7 && <4.8+                       , optparse-applicative >=0.11 && <0.12+                       , parsec >= 3.1.0 && <= 3.2+                       , process++  hs-source-dirs:      src+  default-language:    Haskell2010++library+  exposed-modules:    Configuration.Dotenv.Parse+                    , Configuration.Dotenv++  build-depends:         base >=4.7 && <4.8+                       , parsec >= 3.1.0 && <= 3.2++  hs-source-dirs:      src+  default-language:    Haskell2010+  ghc-options:         -Wall+++test-suite dotenv-test+  type: exitcode-stdio-1.0+  hs-source-dirs: spec, src+  main-is: Spec.hs+  build-depends:       base >=4.7 && <4.8+                       , parsec >= 3.1.0 && <= 3.2++                       , hspec++  default-language:    Haskell2010+  ghc-options:         -Wall++source-repository head+  type:     git+  location: https://github.com/stackbuilders/dotenv-hs
+ spec/Spec.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
+ spec/fixtures/.dotenv view
@@ -0,0 +1,1 @@+DOTENV=true
+ src/Configuration/Dotenv.hs view
@@ -0,0 +1,41 @@+module Configuration.Dotenv (load, loadFile) where++import System.Environment (lookupEnv, setEnv)++import Configuration.Dotenv.Parse (configParser)++import Text.Parsec (parse)++-- | Loads the given list of options into the environment. Optionally+-- override existing variables with values from Dotenv files.+load ::+  Bool -- ^ Override existing settings?+  -> [(String, String)] -- ^ List of values to be set in environment+  -> IO ()+load override = mapM_ (applySetting override)++-- | Loads the options in the given file to the environment. Optionally+-- override existing variables with values from Dotenv files.+loadFile ::+  Bool        -- ^ Override existing settings?+  -> FilePath -- ^ A file containing options to load into the environment+  -> IO ()+loadFile override f = do+  contents <- readFile f++  case parse configParser f contents of+    Left e        -> error $ "Failed to read file" ++ show e+    Right options -> load override options+++applySetting :: Bool -> (String, String) -> IO ()+applySetting override (key, value) =+  if override then+    setEnv key value++  else do+    res <- lookupEnv key++    case res of+      Nothing -> setEnv key value+      Just _  -> return ()
+ src/Configuration/Dotenv/Parse.hs view
@@ -0,0 +1,85 @@+module Configuration.Dotenv.Parse (configParser) where++import Data.Maybe (catMaybes)++import Text.Parsec+  ((<|>), many, try, lookAhead, manyTill, char, anyChar, many1)++import Text.Parsec.String (Parser)++import Text.ParserCombinators.Parsec.Prim (GenParser)++import Text.ParserCombinators.Parsec.Char (space, newline, oneOf, noneOf)++import Control.Monad (liftM2)++import Text.Parsec.Combinator (eof)++import Control.Applicative ((<*), (*>), (<$>))++-- | Returns a parser for a Dotenv configuration file.+-- Accepts key and value arguments separated by "=".+-- Comments are allowed on lines by themselves and on+-- blank lines.+configParser :: Parser [(String, String)]+configParser = catMaybes <$> many lineWithArguments++lineWithArguments :: Parser (Maybe (String, String))+lineWithArguments =+  comment *> return Nothing+  <|> newline *> return Nothing+  <|> many1 (oneOf "\t ") *> return Nothing+  <|> Just <$> configurationOptionWithArguments++configurationOptionWithArguments :: Parser (String, String)+configurationOptionWithArguments = do+  _ <- many space++  keyword   <- manyTill1 (noneOf "\n ") keywordArgSeparator++  arguments <- argumentParser++  return (keyword, arguments)++argumentParser :: Parser String+argumentParser = try quotedArgument <|> try unquotedArgument++-- | Based on a commented-string parser in:+-- http://hub.darcs.net/navilan/XMonadTasks/raw/Data/Config/Lexer.hs+quotedWith :: Char -> Parser String+quotedWith c =+  char c+  *> many chr+  <* char c+  where chr = esc <|> noneOf [c]+        esc = escape *> char c++quotedArgument :: Parser String+quotedArgument = quotedWith '\'' <|> quotedWith '\"'++unquotedArgument :: Parser String+unquotedArgument =+  many (noneOf " \t\n#") <* (try comment <|> try verticalSpace *> return () <|>+                             lookAhead (try endOfLineOrInput))++comment :: Parser ()+comment =+  try (many verticalSpace *> char '#')+  *> manyTill anyChar endOfLineOrInput+  *> return ()++endOfLineOrInput :: Parser ()+endOfLineOrInput = newline *> return () <|> eof++manyTill1 :: GenParser tok st a -> GenParser tok st end -> GenParser tok st [a]+manyTill1 p end = liftM2 (:) p (manyTill p end)++keywordArgSeparator :: Parser ()+keywordArgSeparator =+  many verticalSpace *> char '=' *> many verticalSpace *> return ()++escape :: Parser Char+escape = char '\\'++verticalSpace :: Parser Char+verticalSpace = oneOf " \t"
+ src/Main.hs view
@@ -0,0 +1,42 @@+module Main where++import Options.Applicative++import Configuration.Dotenv (loadFile)++import System.Process (system)+import System.Exit (exitWith)++data Options = Options+  { files    :: [String]+  , program  :: String+  , overload :: Bool+  } deriving (Show)++main :: IO ()+main = execParser opts >>= dotEnv+  where+    opts = info (helper <*> config)+      ( fullDesc+     <> progDesc "Runs PROGRAM after loading options from FILE"+     <> header "dotenv - loads options from dotenv files" )++config :: Parser Options+config = Options+     <$> some (strOption (+                  long "file"+                  <> short 'f'+                  <> metavar "FILE"+                  <> help "File to read for options" ))++     <*> argument str (metavar "PROGRAM")++     <*> switch ( long "overload"+                  <> short 'o'+                  <> help "Specify this flag to override existing variables" )++dotEnv :: Options -> IO ()+dotEnv opts = do+  mapM_ (loadFile (overload opts)) (files opts)+  code <- system $ program opts+  exitWith code