    {-# LANGUAGE CPP #-}
    {-# LANGUAGE ViewPatterns #-}
    {-# LANGUAGE RecordWildCards #-}
    module Hpack (
    -- | /__NOTE:__/ This module is exposed to allow integration of Hpack into
    -- other tools.  It is not meant for general use by end users.  The following
    -- caveats apply:
    --
    -- * The API is undocumented, consult the source instead.
    --
    -- * The exposed types and functions primarily serve Hpack's own needs, not
    -- that of a public API.  Breaking changes can happen as Hpack evolves.
    --
    -- As an Hpack user you either want to use the @hpack@ executable or a build
    -- tool that supports Hpack (e.g. @stack@ or @cabal2nix@).

    -- * Version
      version

    -- * Running Hpack
    , hpack
    , hpackResult
    , printResult
    , Result(..)
    , Status(..)

    -- * Options
    , defaultOptions
    , setProgramName
    , setTarget
    , setDecode
    , getOptions
    , Verbose(..)
    , Options(..)
    , Force(..)
    , GenerateHashStrategy(..)

    #ifdef TEST
    , hpackResultWithVersion
    , header
    , renderCabalFile
    #endif
    ) where

    import           Control.Monad
    import           Data.Version (Version)
    import qualified Data.Version as Version
    import           System.FilePath
    import           System.Environment
    import           System.Exit
    import           System.IO (stderr)
    import           Data.Aeson (Value)
    import           Data.Maybe

    import           Paths_hpack (version)
    import           Hpack.Options
    import           Hpack.Config
    import           Hpack.Render
    import           Hpack.Util
    import           Hpack.Utf8 as Utf8
    import           Hpack.CabalFile

    programVersion :: Maybe Version -> String
    programVersion :: Maybe Version -> String
    programVersion Nothing = "hpack"
    programVersion (Just v :: Version
    v) = "hpack version " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ Version -> String
    Version.showVersion Version
    v

    header :: FilePath -> Maybe Version -> (Maybe Hash) -> [String]
    header :: String -> Maybe Version -> Maybe String -> [String]
    header p :: String
    p v :: Maybe Version
    v hash :: Maybe String
    hash = [
        "-- This file has been generated from " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String -> String
    takeFileName String
    p String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ " by " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ Maybe Version -> String
    programVersion Maybe Version
    v String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ "."
      , "--"
      , "-- see: https://github.com/sol/hpack"
      ] [String] -> [String] -> [String]
    forall a. [a] -> [a] -> [a]
    ++ case Maybe String
    hash of
        Just h :: String
    h -> ["--" , "-- hash: " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    h, ""]
        Nothing -> [""]

    data Options = Options {
      Options -> DecodeOptions
    optionsDecodeOptions :: DecodeOptions
    , Options -> Force
    optionsForce :: Force
    , Options -> GenerateHashStrategy
    optionsGenerateHashStrategy :: GenerateHashStrategy
    , Options -> Bool
    optionsToStdout :: Bool
    }

    data GenerateHashStrategy = ForceHash | ForceNoHash | PreferHash | PreferNoHash
      deriving (GenerateHashStrategy -> GenerateHashStrategy -> Bool
    (GenerateHashStrategy -> GenerateHashStrategy -> Bool)
    -> (GenerateHashStrategy -> GenerateHashStrategy -> Bool)
    -> Eq GenerateHashStrategy
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: GenerateHashStrategy -> GenerateHashStrategy -> Bool
    $c/= :: GenerateHashStrategy -> GenerateHashStrategy -> Bool
    == :: GenerateHashStrategy -> GenerateHashStrategy -> Bool
    $c== :: GenerateHashStrategy -> GenerateHashStrategy -> Bool
    Eq, Int -> GenerateHashStrategy -> String -> String
    [GenerateHashStrategy] -> String -> String
    GenerateHashStrategy -> String
    (Int -> GenerateHashStrategy -> String -> String)
    -> (GenerateHashStrategy -> String)
    -> ([GenerateHashStrategy] -> String -> String)
    -> Show GenerateHashStrategy
    forall a.
    (Int -> a -> String -> String)
    -> (a -> String) -> ([a] -> String -> String) -> Show a
    showList :: [GenerateHashStrategy] -> String -> String
    $cshowList :: [GenerateHashStrategy] -> String -> String
    show :: GenerateHashStrategy -> String
    $cshow :: GenerateHashStrategy -> String
    showsPrec :: Int -> GenerateHashStrategy -> String -> String
    $cshowsPrec :: Int -> GenerateHashStrategy -> String -> String
    Show)

    getOptions :: FilePath -> [String] -> IO (Maybe (Verbose, Options))
    getOptions :: String -> [String] -> IO (Maybe (Verbose, Options))
    getOptions defaultPackageConfig :: String
    defaultPackageConfig args :: [String]
    args = do
      ParseResult
    result <- String -> [String] -> IO ParseResult
    parseOptions String
    defaultPackageConfig [String]
    args
      case ParseResult
    result of
        PrintVersion -> do
          String -> IO ()
    putStrLn (Maybe Version -> String
    programVersion (Maybe Version -> String) -> Maybe Version -> String
    forall a b. (a -> b) -> a -> b
    $ Version -> Maybe Version
    forall a. a -> Maybe a
    Just Version
    version)
          Maybe (Verbose, Options) -> IO (Maybe (Verbose, Options))
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe (Verbose, Options)
    forall a. Maybe a
    Nothing
        PrintNumericVersion -> do
          String -> IO ()
    putStrLn (Version -> String
    Version.showVersion Version
    version)
          Maybe (Verbose, Options) -> IO (Maybe (Verbose, Options))
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe (Verbose, Options)
    forall a. Maybe a
    Nothing
        Help -> do
          IO ()
    printHelp
          Maybe (Verbose, Options) -> IO (Maybe (Verbose, Options))
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe (Verbose, Options)
    forall a. Maybe a
    Nothing
        Run (ParseOptions verbose :: Verbose
    verbose force :: Force
    force hash :: Maybe Bool
    hash toStdout :: Bool
    toStdout file :: String
    file) -> do
          let generateHash :: GenerateHashStrategy
    generateHash = case Maybe Bool
    hash of
                Just True -> GenerateHashStrategy
    ForceHash
                Just False -> GenerateHashStrategy
    ForceNoHash
                Nothing -> GenerateHashStrategy
    PreferNoHash
          Maybe (Verbose, Options) -> IO (Maybe (Verbose, Options))
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe (Verbose, Options) -> IO (Maybe (Verbose, Options)))
    -> Maybe (Verbose, Options) -> IO (Maybe (Verbose, Options))
    forall a b. (a -> b) -> a -> b
    $ (Verbose, Options) -> Maybe (Verbose, Options)
    forall a. a -> Maybe a
    Just (Verbose
    verbose, DecodeOptions -> Force -> GenerateHashStrategy -> Bool -> Options
    Options DecodeOptions
    defaultDecodeOptions {decodeOptionsTarget :: String
    decodeOptionsTarget = String
    file} Force
    force GenerateHashStrategy
    generateHash Bool
    toStdout)
        ParseError -> do
          IO ()
    printHelp
          IO (Maybe (Verbose, Options))
    forall a. IO a
    exitFailure

    printHelp :: IO ()
    printHelp :: IO ()
    printHelp = do
      String
    name <- IO String
    getProgName
      Handle -> String -> IO ()
    Utf8.hPutStrLn Handle
    stderr (String -> IO ()) -> String -> IO ()
    forall a b. (a -> b) -> a -> b
    $ [String] -> String
    unlines [
          "Usage: " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    name String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ " [ --silent ] [ --force | -f ] [ --[no-]hash ] [ PATH ] [ - ]"
        , "       " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    name String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ " --version"
        , "       " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    name String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ " --numeric-version"
        , "       " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    name String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ " --help"
        ]

    hpack :: Verbose -> Options -> IO ()
    hpack :: Verbose -> Options -> IO ()
    hpack verbose :: Verbose
    verbose options :: Options
    options = Options -> IO Result
    hpackResult Options
    options IO Result -> (Result -> IO ()) -> IO ()
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Verbose -> Result -> IO ()
    printResult Verbose
    verbose

    defaultOptions :: Options
    defaultOptions :: Options
    defaultOptions = DecodeOptions -> Force -> GenerateHashStrategy -> Bool -> Options
    Options DecodeOptions
    defaultDecodeOptions Force
    NoForce GenerateHashStrategy
    PreferNoHash Bool
    False

    setTarget :: FilePath -> Options -> Options
    setTarget :: String -> Options -> Options
    setTarget target :: String
    target options :: Options
    options@Options{..} =
      Options
    options {optionsDecodeOptions :: DecodeOptions
    optionsDecodeOptions = DecodeOptions
    optionsDecodeOptions {decodeOptionsTarget :: String
    decodeOptionsTarget = String
    target}}

    setProgramName :: ProgramName -> Options -> Options
    setProgramName :: ProgramName -> Options -> Options
    setProgramName name :: ProgramName
    name options :: Options
    options@Options{..} =
      Options
    options {optionsDecodeOptions :: DecodeOptions
    optionsDecodeOptions = DecodeOptions
    optionsDecodeOptions {decodeOptionsProgramName :: ProgramName
    decodeOptionsProgramName = ProgramName
    name}}

    setDecode :: (FilePath -> IO (Either String ([String], Value))) -> Options -> Options
    setDecode :: (String -> IO (Either String ([String], Value)))
    -> Options -> Options
    setDecode decode :: String -> IO (Either String ([String], Value))
    decode options :: Options
    options@Options{..} =
      Options
    options {optionsDecodeOptions :: DecodeOptions
    optionsDecodeOptions = DecodeOptions
    optionsDecodeOptions {decodeOptionsDecode :: String -> IO (Either String ([String], Value))
    decodeOptionsDecode = String -> IO (Either String ([String], Value))
    decode}}

    data Result = Result {
      Result -> [String]
    resultWarnings :: [String]
    , Result -> String
    resultCabalFile :: String
    , Result -> Status
    resultStatus :: Status
    } deriving (Result -> Result -> Bool
    (Result -> Result -> Bool)
    -> (Result -> Result -> Bool) -> Eq Result
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: Result -> Result -> Bool
    $c/= :: Result -> Result -> Bool
    == :: Result -> Result -> Bool
    $c== :: Result -> Result -> Bool
    Eq, Int -> Result -> String -> String
    [Result] -> String -> String
    Result -> String
    (Int -> Result -> String -> String)
    -> (Result -> String)
    -> ([Result] -> String -> String)
    -> Show Result
    forall a.
    (Int -> a -> String -> String)
    -> (a -> String) -> ([a] -> String -> String) -> Show a
    showList :: [Result] -> String -> String
    $cshowList :: [Result] -> String -> String
    show :: Result -> String
    $cshow :: Result -> String
    showsPrec :: Int -> Result -> String -> String
    $cshowsPrec :: Int -> Result -> String -> String
    Show)

    data Status =
        Generated
      | ExistingCabalFileWasModifiedManually
      | AlreadyGeneratedByNewerHpack
      | OutputUnchanged
      deriving (Status -> Status -> Bool
    (Status -> Status -> Bool)
    -> (Status -> Status -> Bool) -> Eq Status
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: Status -> Status -> Bool
    $c/= :: Status -> Status -> Bool
    == :: Status -> Status -> Bool
    $c== :: Status -> Status -> Bool
    Eq, Int -> Status -> String -> String
    [Status] -> String -> String
    Status -> String
    (Int -> Status -> String -> String)
    -> (Status -> String)
    -> ([Status] -> String -> String)
    -> Show Status
    forall a.
    (Int -> a -> String -> String)
    -> (a -> String) -> ([a] -> String -> String) -> Show a
    showList :: [Status] -> String -> String
    $cshowList :: [Status] -> String -> String
    show :: Status -> String
    $cshow :: Status -> String
    showsPrec :: Int -> Status -> String -> String
    $cshowsPrec :: Int -> Status -> String -> String
    Show)

    printResult :: Verbose -> Result -> IO ()
    printResult :: Verbose -> Result -> IO ()
    printResult verbose :: Verbose
    verbose r :: Result
    r = do
      [String] -> IO ()
    printWarnings (Result -> [String]
    resultWarnings Result
    r)
      Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (Verbose
    verbose Verbose -> Verbose -> Bool
    forall a. Eq a => a -> a -> Bool
    == Verbose
    Verbose) (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ String -> IO ()
    putStrLn (String -> IO ()) -> String -> IO ()
    forall a b. (a -> b) -> a -> b
    $
        case Result -> Status
    resultStatus Result
    r of
          Generated -> "generated " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ Result -> String
    resultCabalFile Result
    r
          OutputUnchanged -> Result -> String
    resultCabalFile Result
    r String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ " is up-to-date"
          AlreadyGeneratedByNewerHpack -> Result -> String
    resultCabalFile Result
    r String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ " was generated with a newer version of hpack, please upgrade and try again."
          ExistingCabalFileWasModifiedManually -> Result -> String
    resultCabalFile Result
    r String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ " was modified manually, please use --force to overwrite."
      case Result -> Status
    resultStatus Result
    r of
          Generated -> () -> IO ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
          OutputUnchanged -> () -> IO ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
          AlreadyGeneratedByNewerHpack -> IO ()
    forall a. IO a
    exitFailure
          ExistingCabalFileWasModifiedManually -> IO ()
    forall a. IO a
    exitFailure

    printWarnings :: [String] -> IO ()
    printWarnings :: [String] -> IO ()
    printWarnings = (String -> IO ()) -> [String] -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ ((String -> IO ()) -> [String] -> IO ())
    -> (String -> IO ()) -> [String] -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Handle -> String -> IO ()
    Utf8.hPutStrLn Handle
    stderr (String -> IO ()) -> (String -> String) -> String -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ("WARNING: " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++)

    mkStatus :: CabalFile -> CabalFile -> Status
    mkStatus :: CabalFile -> CabalFile -> Status
    mkStatus new :: CabalFile
    new@(CabalFile _ mNewVersion :: Maybe Version
    mNewVersion mNewHash :: Maybe String
    mNewHash _) existing :: CabalFile
    existing@(CabalFile _ mExistingVersion :: Maybe Version
    mExistingVersion _ _)
      | CabalFile
    new CabalFile -> CabalFile -> Bool
    `hasSameContent` CabalFile
    existing = Status
    OutputUnchanged
      | Bool
    otherwise = case Maybe Version
    mExistingVersion of
          Nothing -> Status
    ExistingCabalFileWasModifiedManually
          Just _
            | Maybe Version
    mNewVersion Maybe Version -> Maybe Version -> Bool
    forall a. Ord a => a -> a -> Bool
    < Maybe Version
    mExistingVersion -> Status
    AlreadyGeneratedByNewerHpack
            | Maybe String -> Bool
    forall a. Maybe a -> Bool
    isJust Maybe String
    mNewHash Bool -> Bool -> Bool
    && CabalFile -> Bool
    hashMismatch CabalFile
    existing -> Status
    ExistingCabalFileWasModifiedManually
            | Bool
    otherwise -> Status
    Generated

    hasSameContent :: CabalFile -> CabalFile -> Bool
    hasSameContent :: CabalFile -> CabalFile -> Bool
    hasSameContent (CabalFile cabalVersionA :: [String]
    cabalVersionA _ _ a :: [String]
    a) (CabalFile cabalVersionB :: [String]
    cabalVersionB _ _ b :: [String]
    b) = [String]
    cabalVersionA [String] -> [String] -> Bool
    forall a. Eq a => a -> a -> Bool
    == [String]
    cabalVersionB Bool -> Bool -> Bool
    && [String]
    a [String] -> [String] -> Bool
    forall a. Eq a => a -> a -> Bool
    == [String]
    b

    hashMismatch :: CabalFile -> Bool
    hashMismatch :: CabalFile -> Bool
    hashMismatch cabalFile :: CabalFile
    cabalFile = case CabalFile -> Maybe String
    cabalFileHash CabalFile
    cabalFile of
      Nothing -> Bool
    False
      Just hash :: String
    hash -> String
    hash String -> String -> Bool
    forall a. Eq a => a -> a -> Bool
    /= CabalFile -> String
    calculateHash CabalFile
    cabalFile

    calculateHash :: CabalFile -> Hash
    calculateHash :: CabalFile -> String
    calculateHash (CabalFile cabalVersion :: [String]
    cabalVersion _ _ body :: [String]
    body) = String -> String
    sha256 ([String] -> String
    unlines ([String] -> String) -> [String] -> String
    forall a b. (a -> b) -> a -> b
    $ [String]
    cabalVersion [String] -> [String] -> [String]
    forall a. [a] -> [a] -> [a]
    ++ [String]
    body)

    hpackResult :: Options -> IO Result
    hpackResult :: Options -> IO Result
    hpackResult = Version -> Options -> IO Result
    hpackResultWithVersion Version
    version

    hpackResultWithVersion :: Version -> Options -> IO Result
    hpackResultWithVersion :: Version -> Options -> IO Result
    hpackResultWithVersion v :: Version
    v (Options options :: DecodeOptions
    options force :: Force
    force generateHashStrategy :: GenerateHashStrategy
    generateHashStrategy toStdout :: Bool
    toStdout) = do
      DecodeResult pkg :: Package
    pkg (String -> [String]
    lines -> [String]
    cabalVersion) cabalFileName :: String
    cabalFileName warnings :: [String]
    warnings <- DecodeOptions -> IO (Either String DecodeResult)
    readPackageConfig DecodeOptions
    options IO (Either String DecodeResult)
    -> (Either String DecodeResult -> IO DecodeResult)
    -> IO DecodeResult
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= (String -> IO DecodeResult)
    -> (DecodeResult -> IO DecodeResult)
    -> Either String DecodeResult
    -> IO DecodeResult
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either String -> IO DecodeResult
    forall a. String -> IO a
    die DecodeResult -> IO DecodeResult
    forall (m :: * -> *) a. Monad m => a -> m a
    return
      Maybe CabalFile
    mExistingCabalFile <- String -> IO (Maybe CabalFile)
    readCabalFile String
    cabalFileName
      let
        newCabalFile :: CabalFile
    newCabalFile = GenerateHashStrategy
    -> Maybe CabalFile -> [String] -> Version -> Package -> CabalFile
    makeCabalFile GenerateHashStrategy
    generateHashStrategy Maybe CabalFile
    mExistingCabalFile [String]
    cabalVersion Version
    v Package
    pkg

        status :: Status
    status = case Force
    force of
          Force -> Status
    Generated
          NoForce -> Status -> (CabalFile -> Status) -> Maybe CabalFile -> Status
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe Status
    Generated (CabalFile -> CabalFile -> Status
    mkStatus CabalFile
    newCabalFile) Maybe CabalFile
    mExistingCabalFile

      case Status
    status of
        Generated -> DecodeOptions -> Bool -> String -> CabalFile -> IO ()
    writeCabalFile DecodeOptions
    options Bool
    toStdout String
    cabalFileName CabalFile
    newCabalFile
        _ -> () -> IO ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()

      Result -> IO Result
    forall (m :: * -> *) a. Monad m => a -> m a
    return Result :: [String] -> String -> Status -> Result
    Result {
        resultWarnings :: [String]
    resultWarnings = [String]
    warnings
      , resultCabalFile :: String
    resultCabalFile = String
    cabalFileName
      , resultStatus :: Status
    resultStatus = Status
    status
      }

    writeCabalFile :: DecodeOptions -> Bool -> FilePath -> CabalFile -> IO ()
    writeCabalFile :: DecodeOptions -> Bool -> String -> CabalFile -> IO ()
    writeCabalFile options :: DecodeOptions
    options toStdout :: Bool
    toStdout name :: String
    name cabalFile :: CabalFile
    cabalFile = do
      String -> IO ()
    write (String -> IO ()) -> ([String] -> String) -> [String] -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [String] -> String
    unlines ([String] -> IO ()) -> [String] -> IO ()
    forall a b. (a -> b) -> a -> b
    $ String -> CabalFile -> [String]
    renderCabalFile (DecodeOptions -> String
    decodeOptionsTarget DecodeOptions
    options) CabalFile
    cabalFile
      where
        write :: String -> IO ()
    write = if Bool
    toStdout then String -> IO ()
    Utf8.putStr else String -> String -> IO ()
    Utf8.writeFile String
    name

    makeCabalFile :: GenerateHashStrategy -> Maybe CabalFile -> [String] -> Version -> Package -> CabalFile
    makeCabalFile :: GenerateHashStrategy
    -> Maybe CabalFile -> [String] -> Version -> Package -> CabalFile
    makeCabalFile strategy :: GenerateHashStrategy
    strategy mExistingCabalFile :: Maybe CabalFile
    mExistingCabalFile cabalVersion :: [String]
    cabalVersion v :: Version
    v pkg :: Package
    pkg = CabalFile
    cabalFile
      where
        cabalFile :: CabalFile
    cabalFile = [String] -> Maybe Version -> Maybe String -> [String] -> CabalFile
    CabalFile [String]
    cabalVersion (Version -> Maybe Version
    forall a. a -> Maybe a
    Just Version
    v) Maybe String
    hash [String]
    body

        hash :: Maybe String
    hash
          | Maybe CabalFile -> GenerateHashStrategy -> Bool
    shouldGenerateHash Maybe CabalFile
    mExistingCabalFile GenerateHashStrategy
    strategy = String -> Maybe String
    forall a. a -> Maybe a
    Just (String -> Maybe String) -> String -> Maybe String
    forall a b. (a -> b) -> a -> b
    $ CabalFile -> String
    calculateHash CabalFile
    cabalFile
          | Bool
    otherwise = Maybe String
    forall a. Maybe a
    Nothing

        body :: [String]
    body = String -> [String]
    lines (String -> [String]) -> String -> [String]
    forall a b. (a -> b) -> a -> b
    $ [String] -> Package -> String
    renderPackage ([String] -> (CabalFile -> [String]) -> Maybe CabalFile -> [String]
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe [] CabalFile -> [String]
    cabalFileContents Maybe CabalFile
    mExistingCabalFile) Package
    pkg

    shouldGenerateHash :: Maybe CabalFile -> GenerateHashStrategy -> Bool
    shouldGenerateHash :: Maybe CabalFile -> GenerateHashStrategy -> Bool
    shouldGenerateHash mExistingCabalFile :: Maybe CabalFile
    mExistingCabalFile strategy :: GenerateHashStrategy
    strategy = case (GenerateHashStrategy
    strategy, Maybe CabalFile
    mExistingCabalFile) of
      (ForceHash, _) -> Bool
    True
      (ForceNoHash, _) -> Bool
    False
      (PreferHash, Nothing) -> Bool
    True
      (PreferNoHash, Nothing) -> Bool
    False
      (_, Just CabalFile {cabalFileHash :: CabalFile -> Maybe String
    cabalFileHash = Maybe String
    Nothing}) -> Bool
    False
      (_, Just CabalFile {cabalFileHash :: CabalFile -> Maybe String
    cabalFileHash = Just _}) -> Bool
    True

    renderCabalFile :: FilePath -> CabalFile -> [String]
    renderCabalFile :: String -> CabalFile -> [String]
    renderCabalFile file :: String
    file (CabalFile cabalVersion :: [String]
    cabalVersion hpackVersion :: Maybe Version
    hpackVersion hash :: Maybe String
    hash body :: [String]
    body) = [String]
    cabalVersion [String] -> [String] -> [String]
    forall a. [a] -> [a] -> [a]
    ++ String -> Maybe Version -> Maybe String -> [String]
    header String
    file Maybe Version
    hpackVersion Maybe String
    hash [String] -> [String] -> [String]
    forall a. [a] -> [a] -> [a]
    ++ [String]
    body