daml/daml-assistant/daml-project-config/DAML/Project/Consts.hs
Andreas Herrmann 1a80106753
damlc test --files (#1409)
* Add test case for damlc test-files

* Separate damlc test-files from damlc test

* Fix rules_daml/daml.bzl daml_test

* damlc test-files --> damlc test --files

The project options are still relevant for the --files case, as it may
be necessary to change into the project root directory in order to
locate the project package database.
2019-05-28 15:36:42 +02:00

188 lines
6.3 KiB
Haskell

-- Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
-- SPDX-License-Identifier: Apache-2.0
module DAML.Project.Consts
( damlPathEnvVar
, projectPathEnvVar
, sdkPathEnvVar
, sdkVersionEnvVar
, sdkVersionLatestEnvVar
, damlAssistantEnvVar
, damlAssistantVersionEnvVar
, damlConfigName
, projectConfigName
, sdkConfigName
, damlEnvVars
, getDamlPath
, getProjectPath
, getSdkPath
, getSdkVersion
, getDamlAssistant
, ProjectCheck(..)
, withProjectRoot
, withExpectProjectRoot
) where
import Control.Monad
import System.Directory
import System.Environment
import System.Exit
import System.FilePath
import System.IO
import DAML.Project.Types
-- | The DAML_HOME environment variable determines the path of the daml
-- assistant data directory. This defaults to:
--
-- System.Directory.getAppUserDataDirectory "daml"
--
-- On Linux and Mac, that's ~/.daml
-- On Windows, that's %APPDATA%/daml
damlPathEnvVar :: String
damlPathEnvVar = "DAML_HOME"
-- | The DAML_PROJECT environment variable determines the path of
-- the current daml project. By default, this is done by traversing
-- up the directory structure until we find a "daml.yaml" file.
projectPathEnvVar :: String
projectPathEnvVar = "DAML_PROJECT"
-- | The DAML_SDK environment variable determines the path of the
-- sdk folder. By default, this is calculated as
-- $DAML_HOME/sdk/$DAML_SDK_VERSION.
sdkPathEnvVar :: String
sdkPathEnvVar = "DAML_SDK"
-- | The DAML_SDK_VERSION environment variable determines the
-- current or preferred sdk version. By default this is, in order
-- of preference:
--
-- 1. taken from the current $DAML_PROJECT config file, if it exists
-- 2. read from $DAML_SDK/VERSION file, if DAML_SDK is explicitly set
-- 3. the latest stable SDK version available in $DAML_HOME/sdk.
sdkVersionEnvVar :: String
sdkVersionEnvVar = "DAML_SDK_VERSION"
-- | Latest stable version available from GitHub. Note that this is
-- updated based on the update-check property in the user's daml-config.yaml
-- file, which means it will possibly never be available.
sdkVersionLatestEnvVar :: String
sdkVersionLatestEnvVar = "DAML_SDK_VERSION_LATEST"
-- | The absolute path to the daml assistant executable.
damlAssistantEnvVar :: String
damlAssistantEnvVar = "DAML_ASSISTANT"
-- | The SDK version of the daml assistant. This does not necessarily equal
-- the DAML_SDK_VERSION, e.g. when working with a project with an older
-- pinned SDK version.
damlAssistantVersionEnvVar :: String
damlAssistantVersionEnvVar = "DAML_ASSISTANT_VERSION"
-- | File name of config file in DAML_HOME (~/.daml).
damlConfigName :: FilePath
damlConfigName = "daml-config.yaml"
-- | File name of config file in DAML_PROJECT (the project path).
projectConfigName :: FilePath
projectConfigName = "daml.yaml"
-- | File name of config file in DAML_SDK (the sdk path)
sdkConfigName :: FilePath
sdkConfigName = "sdk-config.yaml"
-- | List of all environment variables handled by daml assistant.
damlEnvVars :: [String]
damlEnvVars =
[ damlPathEnvVar
, projectPathEnvVar
, sdkPathEnvVar
, sdkVersionEnvVar
, sdkVersionLatestEnvVar
, damlAssistantEnvVar
, damlAssistantVersionEnvVar
]
-- | Returns the path to the daml assistant data directory.
--
-- This will throw an `IOException` if the environment has not been setup by
-- the assistant.
getDamlPath :: IO FilePath
getDamlPath = getEnv damlPathEnvVar
-- | Returns the path of the current daml project or
--`Nothing` if invoked outside of a project.
getProjectPath :: IO (Maybe FilePath)
getProjectPath = do
mbProjectPath <- lookupEnv projectPathEnvVar
pure ((\p -> if null p then Nothing else Just p) =<< mbProjectPath)
-- | Returns the path of the sdk folder.
--
-- This will throw an `IOException` if the environment has not been setup by
-- the assistant.
getSdkPath :: IO FilePath
getSdkPath = getEnv sdkPathEnvVar
-- | Returns the current SDK version.
--
-- This will throw an `IOException` if the environment has not been setup by
-- the assistant.
getSdkVersion :: IO String
getSdkVersion = getEnv sdkVersionEnvVar
-- | Returns the absolute path to the assistant.
--
-- This will throw an `IOException` if the environment has not been setup by
-- the assistant.
getDamlAssistant :: IO FilePath
getDamlAssistant = getEnv damlAssistantEnvVar
-- | Whether we should check if a command is invoked inside of a project.
-- The string is the command name used in error messages
data ProjectCheck = ProjectCheck String Bool
-- | Execute an action within the project root, if available.
--
-- Determines the project root, if available, using 'getProjectPath' unless it
-- is passed explicitly.
--
-- If no project root is found and 'ProjectCheck' requires a project root, then
-- an error is printed and the program is terminated before executing the given
-- action.
--
-- The provided action is executed on 'Just' the project root, if available,
-- otherwise on 'Nothing'. Additionally, it is passed a function to make
-- filepaths relative to the new working directory.
withProjectRoot
:: Maybe ProjectPath
-> ProjectCheck
-> (Maybe FilePath -> (FilePath -> IO FilePath) -> IO a)
-> IO a
withProjectRoot mbProjectDir (ProjectCheck cmdName check) act = do
previousCwd <- getCurrentDirectory
mbProjectPath <- maybe getProjectPath (pure . Just . unwrapProjectPath) mbProjectDir
case mbProjectPath of
Nothing -> do
when check $ do
hPutStrLn stderr (cmdName <> ": Not in project.")
exitFailure
act mbProjectPath pure
Just projectPath -> do
projectPath <- canonicalizePath projectPath
withCurrentDirectory projectPath $ act mbProjectPath $ \f -> do
absF <- canonicalizePath (previousCwd </> f)
pure (projectPath `makeRelative` absF)
-- | Same as 'withProjectRoot' but always requires project root.
withExpectProjectRoot
:: Maybe ProjectPath -- ^ optionally specified project root
-> String -- ^ command name for error message
-> (FilePath -> (FilePath -> IO FilePath) -> IO a) -- ^ action
-> IO a
withExpectProjectRoot mbProjectDir cmdName act = do
withProjectRoot mbProjectDir (ProjectCheck cmdName True) $ \case
Nothing -> error "withProjectRoot should terminated the program"
Just projectPath -> act projectPath