{-# LANGUAGE NoImplicitPrelude #-}

module Stack.Types.LockFileBehavior
  ( LockFileBehavior (..)
  , readLockFileBehavior
  ) where

import qualified Data.Map as Map
import           Options.Applicative ( ReadM )
import qualified Options.Applicative.Types as OA
import qualified RIO.List as List
import           Stack.Prelude

-- | How to interact with lock files

data LockFileBehavior
  = LFBReadWrite
    -- ^ Read and write lock files

  | LFBReadOnly
    -- ^ Read lock files, but do not write them

  | LFBIgnore
    -- ^ Entirely ignore lock files

  | LFBErrorOnWrite
    -- ^ Error out on trying to write a lock file. This can be used to

    -- ensure that lock files in a repository already ensure

    -- reproducible builds.

  deriving (LockFileBehavior
LockFileBehavior -> LockFileBehavior -> Bounded LockFileBehavior
forall a. a -> a -> Bounded a
$cminBound :: LockFileBehavior
minBound :: LockFileBehavior
$cmaxBound :: LockFileBehavior
maxBound :: LockFileBehavior
Bounded, Int -> LockFileBehavior
LockFileBehavior -> Int
LockFileBehavior -> [LockFileBehavior]
LockFileBehavior -> LockFileBehavior
LockFileBehavior -> LockFileBehavior -> [LockFileBehavior]
LockFileBehavior
-> LockFileBehavior -> LockFileBehavior -> [LockFileBehavior]
(LockFileBehavior -> LockFileBehavior)
-> (LockFileBehavior -> LockFileBehavior)
-> (Int -> LockFileBehavior)
-> (LockFileBehavior -> Int)
-> (LockFileBehavior -> [LockFileBehavior])
-> (LockFileBehavior -> LockFileBehavior -> [LockFileBehavior])
-> (LockFileBehavior -> LockFileBehavior -> [LockFileBehavior])
-> (LockFileBehavior
    -> LockFileBehavior -> LockFileBehavior -> [LockFileBehavior])
-> Enum LockFileBehavior
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: LockFileBehavior -> LockFileBehavior
succ :: LockFileBehavior -> LockFileBehavior
$cpred :: LockFileBehavior -> LockFileBehavior
pred :: LockFileBehavior -> LockFileBehavior
$ctoEnum :: Int -> LockFileBehavior
toEnum :: Int -> LockFileBehavior
$cfromEnum :: LockFileBehavior -> Int
fromEnum :: LockFileBehavior -> Int
$cenumFrom :: LockFileBehavior -> [LockFileBehavior]
enumFrom :: LockFileBehavior -> [LockFileBehavior]
$cenumFromThen :: LockFileBehavior -> LockFileBehavior -> [LockFileBehavior]
enumFromThen :: LockFileBehavior -> LockFileBehavior -> [LockFileBehavior]
$cenumFromTo :: LockFileBehavior -> LockFileBehavior -> [LockFileBehavior]
enumFromTo :: LockFileBehavior -> LockFileBehavior -> [LockFileBehavior]
$cenumFromThenTo :: LockFileBehavior
-> LockFileBehavior -> LockFileBehavior -> [LockFileBehavior]
enumFromThenTo :: LockFileBehavior
-> LockFileBehavior -> LockFileBehavior -> [LockFileBehavior]
Enum, Int -> LockFileBehavior -> ShowS
[LockFileBehavior] -> ShowS
LockFileBehavior -> String
(Int -> LockFileBehavior -> ShowS)
-> (LockFileBehavior -> String)
-> ([LockFileBehavior] -> ShowS)
-> Show LockFileBehavior
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> LockFileBehavior -> ShowS
showsPrec :: Int -> LockFileBehavior -> ShowS
$cshow :: LockFileBehavior -> String
show :: LockFileBehavior -> String
$cshowList :: [LockFileBehavior] -> ShowS
showList :: [LockFileBehavior] -> ShowS
Show)

-- | Parser for 'LockFileBehavior'

readLockFileBehavior :: ReadM LockFileBehavior
readLockFileBehavior :: ReadM LockFileBehavior
readLockFileBehavior = do
  String
s <- ReadM String
OA.readerAsk
  case String -> Map String LockFileBehavior -> Maybe LockFileBehavior
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup String
s Map String LockFileBehavior
m of
    Just LockFileBehavior
x -> LockFileBehavior -> ReadM LockFileBehavior
forall a. a -> ReadM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure LockFileBehavior
x
    Maybe LockFileBehavior
Nothing -> String -> ReadM LockFileBehavior
forall a. String -> ReadM a
OA.readerError (String -> ReadM LockFileBehavior)
-> String -> ReadM LockFileBehavior
forall a b. (a -> b) -> a -> b
$ String
"Invalid lock file behavior, valid options: " String -> ShowS
forall a. [a] -> [a] -> [a]
++
                                String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
List.intercalate String
", " (Map String LockFileBehavior -> [String]
forall k a. Map k a -> [k]
Map.keys Map String LockFileBehavior
m)
 where
  m :: Map String LockFileBehavior
m = [(String, LockFileBehavior)] -> Map String LockFileBehavior
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(String, LockFileBehavior)] -> Map String LockFileBehavior)
-> [(String, LockFileBehavior)] -> Map String LockFileBehavior
forall a b. (a -> b) -> a -> b
$ (LockFileBehavior -> (String, LockFileBehavior))
-> [LockFileBehavior] -> [(String, LockFileBehavior)]
forall a b. (a -> b) -> [a] -> [b]
map (\LockFileBehavior
x -> (LockFileBehavior -> String
render LockFileBehavior
x, LockFileBehavior
x)) [LockFileBehavior
forall a. Bounded a => a
minBound..LockFileBehavior
forall a. Bounded a => a
maxBound]
  render :: LockFileBehavior -> String
render LockFileBehavior
LFBReadWrite = String
"read-write"
  render LockFileBehavior
LFBReadOnly = String
"read-only"
  render LockFileBehavior
LFBIgnore = String
"ignore"
  render LockFileBehavior
LFBErrorOnWrite = String
"error-on-write"