-- | Utility function for finding a directory relative to the package root
-- directory.
--
-- Copied from
-- <https://github.com/input-output-hk/cardano-wallet/blob/master/lib/test-utils/src/Test/Utils/Paths.hs>
module Test.Util.Paths (
    getGoldenDir
  , getRelPath
  , inNixBuild
  ) where


import           Control.Monad.IO.Class (liftIO)
import           Data.FileEmbed (makeRelativeToProject)
import           Language.Haskell.TH.Syntax (Exp, Q, liftData)
import           System.Environment (lookupEnv)

-- | A TH function to get the path corresponding to the golden output
-- directory relative to the package root directory.
getGoldenDir :: Q Exp
getGoldenDir :: Q Exp
getGoldenDir = FilePath -> Q Exp
getRelPath FilePath
"golden"

-- | A TH function to get the path corresponding to the given 'FilePath' which
-- is relative to the package root directory.
--
-- It combines the current source file location and cabal file to locate the
-- package directory in such a way that works in both the stack/cabal package
-- build and ghci.
--
-- For the Nix build, rather than baking in a path that starts with @/build@, it
-- makes the test data path relative to the current directory.
getRelPath :: FilePath -> Q Exp
getRelPath :: FilePath -> Q Exp
getRelPath FilePath
relPath = do
    absPath <- FilePath -> Q FilePath
makeRelativeToProject FilePath
relPath
    useRel <- liftIO inNixBuild
    liftData (if useRel then relPath else absPath)

-- | Infer from environment variables whether we are running within a Nix build
-- (and not just a nix-shell).
inNixBuild :: IO Bool
inNixBuild :: IO Bool
inNixBuild = do
    let testEnv :: FilePath -> IO Bool
testEnv = (Maybe FilePath -> Bool) -> IO (Maybe FilePath) -> IO Bool
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Bool -> (FilePath -> Bool) -> Maybe FilePath -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False (Bool -> Bool
not (Bool -> Bool) -> (FilePath -> Bool) -> FilePath -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null)) (IO (Maybe FilePath) -> IO Bool)
-> (FilePath -> IO (Maybe FilePath)) -> FilePath -> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO (Maybe FilePath)
lookupEnv
    haveNixBuildDir <- FilePath -> IO Bool
testEnv FilePath
"NIX_BUILD_TOP"
    inNixShell <- testEnv "IN_NIX_SHELL"
    pure (haveNixBuildDir && not inNixShell)