content: -- | etlas CLI command: configure
  --
  module Distribution.Client.CmdConfigure (
      configureCommand,
      configureAction,
    ) where
  
  import System.Directory
  import Control.Monad
  import qualified Data.Map as Map
  
  import Distribution.Client.ProjectOrchestration
  import Distribution.Client.ProjectConfig
           ( writeProjectLocalExtraConfig )
  
  import Distribution.Client.Setup
           ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags )
  import Distribution.Simple.Setup
           ( HaddockFlags, fromFlagOrDefault )
  import Distribution.Verbosity
           ( normal )
  
  import Distribution.Simple.Command
           ( CommandUI(..), usageAlternatives )
  import Distribution.Simple.Utils
           ( wrapText, notice )
  import qualified Distribution.Client.Setup as Client
  
  configureCommand :: CommandUI (ConfigFlags, ConfigExFlags
                                ,InstallFlags, HaddockFlags)
  configureCommand = Client.installCommand {
    commandName         = "configure",
    commandSynopsis     = "Add extra project configuration",
    commandUsage        = usageAlternatives "configure" [ "[FLAGS]" ],
    commandDescription  = Just $ \_ -> wrapText $
          "Adjust how the project is built by setting additional package flags "
       ++ "and other flags.\n\n"
  
       ++ "The configuration options are written to the 'cabal.project.local' "
       ++ "file (or '$project_file.local', if '--project-file' is specified) "
       ++ "which extends the configuration from the 'cabal.project' file "
       ++ "(if any). This combination is used as the project configuration for "
       ++ "all other commands (such as 'build', 'repl' etc) though it "
       ++ "can be extended/overridden on a per-command basis.\n\n"
  
       ++ "The configure command also checks that the project configuration "
       ++ "will work. In particular it checks that there is a consistent set of "
       ++ "dependencies for the project as a whole.\n\n"
  
       ++ "The 'cabal.project.local' file persists across 'new-clean' but is "
       ++ "overwritten on the next use of the 'configure' command. The "
       ++ "intention is that the 'cabal.project' file should be kept in source "
       ++ "control but the 'cabal.project.local' should not.\n\n"
  
       ++ "It is never necessary to use the 'configure' command. It is "
       ++ "merely a convenience in cases where you do not want to specify flags "
       ++ "to 'build' (and other commands) every time and yet do not want "
       ++ "to alter the 'cabal.project' persistently.",
    commandNotes        = Just $ \pname ->
          "Examples:\n"
       ++ "  " ++ pname ++ " configure --with-compiler ghc-7.10.3\n"
       ++ "    Adjust the project configuration to use the given compiler\n"
       ++ "    program and check the resulting configuration works.\n"
       ++ "  " ++ pname ++ " configure\n"
       ++ "    Reset the local configuration to empty and check the overall\n"
       ++ "    project configuration works.\n\n"
  
       ++ cmdCommonHelpTextNewBuildBeta
     }
  
  -- | To a first approximation, the @configure@ just runs the first phase of
  -- the @build@ command where we bring the install plan up to date (thus
  -- checking that it's possible).
  --
  -- The only difference is that @configure@ also allows the user to specify
  -- some extra config flags which we save in the file @cabal.project.local@.
  --
  -- For more details on how this works, see the module
  -- "Distribution.Client.ProjectOrchestration"
  --
  configureAction :: (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags)
                  -> [String] -> GlobalFlags -> IO ()
  configureAction (configFlags, configExFlags, installFlags, haddockFlags)
                  _extraArgs globalFlags = do
      --TODO: deal with _extraArgs, since flags with wrong syntax end up there
  
      baseCtx <- establishProjectBaseContext verbosity cliConfig
  
      -- Write out the @cabal.project.local@ so it gets picked up by the
      -- planning phase. If old config exists, then print the contents
      -- before overwriting
      exists <- doesFileExist "cabal.project.local"
      when exists $ do
          notice verbosity "'cabal.project.local' file already exists. Now overwriting it."
          copyFile "cabal.project.local" "cabal.project.local~"
      writeProjectLocalExtraConfig (distDirLayout baseCtx)
                                   cliConfig
  
      (buildCtx, _) <-
        runProjectPreBuildPhase verbosity baseCtx $ \elaboratedPlan -> do
  
              -- TODO: Select the same subset of targets as 'CmdBuild' would
              -- pick (ignoring, for example, executables in libraries
              -- we depend on). But we don't want it to fail, so actually we
              -- have to do it slightly differently from build.
              return (elaboratedPlan, Map.empty, ())
  
      let baseCtx' = baseCtx {
                        buildSettings = (buildSettings baseCtx) {
                          buildSettingDryRun = True
                        }
                      }
  
      -- TODO: Hmm, but we don't have any targets. Currently this prints
      -- what we would build if we were to build everything. Could pick
      -- implicit target like "."
      --
      -- TODO: should we say what's in the project (+deps) as a whole?
      printPlan verbosity baseCtx' buildCtx
    where
      verbosity = fromFlagOrDefault normal (configVerbosity configFlags)
      cliConfig = commandLineFlagsToProjectConfig
                    globalFlags configFlags configExFlags
                    installFlags haddockFlags
  