Setup.hs 103 KB
Newer Older
Edsko de Vries's avatar
Edsko de Vries committed
1
2
3
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE RankNTypes #-}
4
{-# LANGUAGE DeriveGeneric #-}
5
6
-----------------------------------------------------------------------------
-- |
7
-- Module      :  Distribution.Client.Setup
8
9
10
11
12
13
14
15
16
-- Copyright   :  (c) David Himmelstrup 2005
-- License     :  BSD-like
--
-- Maintainer  :  lemmih@gmail.com
-- Stability   :  provisional
-- Portability :  portable
--
--
-----------------------------------------------------------------------------
17
module Distribution.Client.Setup
Edsko de Vries's avatar
Edsko de Vries committed
18
19
    ( globalCommand, GlobalFlags(..), defaultGlobalFlags
    , RepoContext(..), withRepoContext
20
    , configureCommand, ConfigFlags(..), filterConfigureFlags
21
    , configPackageDB', configCompilerAux'
22
    , configureExCommand, ConfigExFlags(..), defaultConfigExFlags
23
    , buildCommand, BuildFlags(..), BuildExFlags(..), SkipAddSourceDepsCheck(..)
24
    , replCommand, testCommand, benchmarkCommand
ttuegel's avatar
ttuegel committed
25
                        , configureExOptions, reconfigureCommand
26
    , installCommand, InstallFlags(..), installOptions, defaultInstallFlags
27
    , defaultSolver, defaultMaxBackjumps
28
    , listCommand, ListFlags(..)
Moritz Angermann's avatar
Moritz Angermann committed
29
    , updateCommand, UpdateFlags(..), defaultUpdateFlags
ijones's avatar
ijones committed
30
    , upgradeCommand
31
    , uninstallCommand
32
    , infoCommand, InfoFlags(..)
33
    , fetchCommand, FetchFlags(..)
34
    , freezeCommand, FreezeFlags(..)
35
    , genBoundsCommand
36
    , outdatedCommand, OutdatedFlags(..), IgnoreMajorVersionBumps(..)
37
    , getCommand, unpackCommand, GetFlags(..)
38
    , checkCommand
39
    , formatCommand
40
    , uploadCommand, UploadFlags(..), IsCandidate(..)
41
    , reportCommand, ReportFlags(..)
refold's avatar
refold committed
42
    , runCommand
43
    , initCommand, IT.InitFlags(..)
44
    , sdistCommand, SDistFlags(..), SDistExFlags(..), ArchiveFormat(..)
45
    , win32SelfUpgradeCommand, Win32SelfUpgradeFlags(..)
46
    , actAsSetupCommand, ActAsSetupFlags(..)
refold's avatar
refold committed
47
    , sandboxCommand, defaultSandboxLocation, SandboxFlags(..)
Daniel Wagner's avatar
Daniel Wagner committed
48
    , execCommand, ExecFlags(..), defaultExecFlags
49
    , userConfigCommand, UserConfigFlags(..)
Maciek Makowski's avatar
Maciek Makowski committed
50
    , manpageCommand
Duncan Coutts's avatar
Duncan Coutts committed
51

52
    , applyFlagDefaults
Duncan Coutts's avatar
Duncan Coutts committed
53
    , parsePackageArgs
54
55
56
    --TODO: stop exporting these:
    , showRepo
    , parseRepo
57
    , readRepo
58
59
    ) where

60
61
62
import Prelude ()
import Distribution.Client.Compat.Prelude hiding (get)

63
import Distribution.Client.Types
64
65
66
         ( Username(..), Password(..), RemoteRepo(..)
         , AllowNewer(..), AllowOlder(..), RelaxDeps(..)
         )
67
68
import Distribution.Client.BuildReports.Types
         ( ReportLevel(..) )
69
import Distribution.Client.Dependency.Types
70
         ( PreSolver(..) )
71
import Distribution.Client.IndexUtils.Timestamp
72
         ( IndexState(..) )
73
74
import qualified Distribution.Client.Init.Types as IT
         ( InitFlags(..), PackageType(..) )
75
76
import Distribution.Client.Targets
         ( UserConstraint, readUserConstraint )
77
78
import Distribution.Utils.NubList
         ( NubList, toNubList, fromNubList)
79

80
import Distribution.Solver.Types.ConstraintSource
81
import Distribution.Solver.Types.Settings
82

83
84
import Distribution.Simple.Compiler ( Compiler, PackageDB, PackageDBStack )
import Distribution.Simple.Program (ProgramDb, defaultProgramDb)
85
86
import Distribution.Simple.Command hiding (boolOpt, boolOpt')
import qualified Distribution.Simple.Command as Command
87
import Distribution.Simple.Configure
88
       ( configCompilerAuxEx, interpretPackageDbFlags, computeEffectiveProfiling )
Duncan Coutts's avatar
Duncan Coutts committed
89
import qualified Distribution.Simple.Setup as Cabal
90
import Distribution.Simple.Setup
91
92
         ( ConfigFlags(..), BuildFlags(..), ReplFlags
         , TestFlags(..), BenchmarkFlags(..)
93
         , SDistFlags(..), HaddockFlags(..)
94
         , readPackageDbList, showPackageDbList
95
         , Flag(..), toFlag, flagToMaybe, flagToList, maybeToFlag
96
97
         , BooleanFlag(..), optionVerbosity
         , boolOpt, boolOpt', trueArg, falseArg
98
         , optionNumJobs )
99
import Distribution.Simple.InstallDirs
100
101
         ( PathTemplate, InstallDirs(..)
         , toPathTemplate, fromPathTemplate, combinePathTemplate )
102
import Distribution.Version
103
         ( Version, mkVersion, nullVersion, anyVersion, thisVersion )
104
import Distribution.Package
105
         ( PackageIdentifier, PackageName, packageName, packageVersion )
106
import Distribution.Types.Dependency
107
import Distribution.PackageDescription
108
         ( BuildType(..), RepoKind(..) )
109
import Distribution.System ( Platform )
110
import Distribution.Text
111
         ( Text(..), display )
112
import Distribution.ReadE
113
         ( ReadE(..), readP_to_E, succeedReadE )
114
import qualified Distribution.Compat.ReadP as Parse
115
         ( ReadP, char, munch1, pfail, sepBy1, (+++) )
116
117
import Distribution.ParseUtils
         ( readPToMaybe )
118
import Distribution.Verbosity
119
         ( Verbosity, lessVerbose, normal, verboseNoFlags, verboseNoTimestamp )
120
import Distribution.Simple.Utils
121
         ( wrapText, wrapLine )
122
import Distribution.Client.GlobalFlags
Edsko de Vries's avatar
Edsko de Vries committed
123
124
125
         ( GlobalFlags(..), defaultGlobalFlags
         , RepoContext(..), withRepoContext
         )
126

127
import Data.List
128
         ( deleteFirstsBy )
129
130
131
132
import System.FilePath
         ( (</>) )
import Network.URI
         ( parseAbsoluteURI, uriToString )
133

134
135
136
137
138
139
140
141
142
applyFlagDefaults :: (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags)
                  -> (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags)
applyFlagDefaults (configFlags, configExFlags, installFlags, haddockFlags) =
  ( commandDefaultFlags configureCommand <> configFlags
  , defaultConfigExFlags <> configExFlags
  , defaultInstallFlags <> installFlags
  , Cabal.defaultHaddockFlags <> haddockFlags
  )

143
144
globalCommand :: [Command action] -> CommandUI GlobalFlags
globalCommand commands = CommandUI {
145
    commandName         = "",
146
147
    commandSynopsis     =
         "Command line interface to the Haskell Cabal infrastructure.",
148
149
150
151
    commandUsage        = \pname ->
         "See http://www.haskell.org/cabal/ for more information.\n"
      ++ "\n"
      ++ "Usage: " ++ pname ++ " [GLOBAL FLAGS] [COMMAND [FLAGS]]\n",
152
    commandDescription  = Just $ \pname ->
153
154
155
      let
        commands' = commands ++ [commandAddAction helpCommandUI undefined]
        cmdDescs = getNormalCommandDescriptions commands'
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
        -- if new commands are added, we want them to appear even if they
        -- are not included in the custom listing below. Thus, we calculate
        -- the `otherCmds` list and append it under the `other` category.
        -- Alternatively, a new testcase could be added that ensures that
        -- the set of commands listed here is equal to the set of commands
        -- that are actually available.
        otherCmds = deleteFirstsBy (==) (map fst cmdDescs)
          [ "help"
          , "update"
          , "install"
          , "fetch"
          , "list"
          , "info"
          , "user-config"
          , "get"
          , "init"
          , "configure"
173
          , "reconfigure"
174
175
176
177
178
179
180
181
182
183
184
          , "build"
          , "clean"
          , "run"
          , "repl"
          , "test"
          , "bench"
          , "check"
          , "sdist"
          , "upload"
          , "report"
          , "freeze"
185
          , "gen-bounds"
186
          , "outdated"
Moritz Angermann's avatar
Moritz Angermann committed
187
          , "doctest"
188
189
190
191
192
193
          , "haddock"
          , "hscolour"
          , "copy"
          , "register"
          , "sandbox"
          , "exec"
194
195
196
197
          , "new-build"
          , "new-configure"
          , "new-repl"
          , "new-freeze"
198
199
200
          , "new-run"
          , "new-test"
          , "new-bench"
201
          , "new-haddock"
202
          ]
203
204
        maxlen    = maximum $ [length name | (name, _) <- cmdDescs]
        align str = str ++ replicate (maxlen - length str) ' '
205
206
207
208
209
210
211
212
213
        startGroup n = " ["++n++"]"
        par          = ""
        addCmd n     = case lookup n cmdDescs of
                         Nothing -> ""
                         Just d -> "  " ++ align n ++ "    " ++ d
        addCmdCustom n d = case lookup n cmdDescs of -- make sure that the
                                                  -- command still exists.
                         Nothing -> ""
                         Just _ -> "  " ++ align n ++ "    " ++ d
214
215
      in
         "Commands:\n"
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
      ++ unlines (
        [ startGroup "global"
        , addCmd "update"
        , addCmd "install"
        , par
        , addCmd "help"
        , addCmd "info"
        , addCmd "list"
        , addCmd "fetch"
        , addCmd "user-config"
        , par
        , startGroup "package"
        , addCmd "get"
        , addCmd "init"
        , par
        , addCmd "configure"
        , addCmd "build"
        , addCmd "clean"
        , par
        , addCmd "run"
        , addCmd "repl"
        , addCmd "test"
        , addCmd "bench"
        , par
        , addCmd "check"
        , addCmd "sdist"
        , addCmd "upload"
        , addCmd "report"
        , par
        , addCmd "freeze"
246
        , addCmd "gen-bounds"
247
        , addCmd "outdated"
Moritz Angermann's avatar
Moritz Angermann committed
248
        , addCmd "doctest"
249
250
251
252
        , addCmd "haddock"
        , addCmd "hscolour"
        , addCmd "copy"
        , addCmd "register"
253
        , addCmd "reconfigure"
254
255
        , par
        , startGroup "sandbox"
256
        , addCmd "sandbox"
257
258
        , addCmd "exec"
        , addCmdCustom "repl" "Open interpreter with access to sandbox packages."
259
260
261
262
263
        , par
        , startGroup "new-style projects (beta)"
        , addCmd "new-build"
        , addCmd "new-configure"
        , addCmd "new-repl"
264
265
266
        , addCmd "new-run"
        , addCmd "new-test"
        , addCmd "new-bench"
267
268
        , addCmd "new-freeze"
        , addCmd "new-haddock"
269
270
271
        ] ++ if null otherCmds then [] else par
                                           :startGroup "other"
                                           :[addCmd n | n <- otherCmds])
272
273
      ++ "\n"
      ++ "For more information about a command use:\n"
274
275
      ++ "   " ++ pname ++ " COMMAND --help\n"
      ++ "or " ++ pname ++ " help COMMAND\n"
276
      ++ "\n"
277
      ++ "To install Cabal packages from hackage use:\n"
278
279
      ++ "  " ++ pname ++ " install foo [--dry-run]\n"
      ++ "\n"
280
281
      ++ "Occasionally you need to update the list of available packages:\n"
      ++ "  " ++ pname ++ " update\n",
282
    commandNotes = Nothing,
283
    commandDefaultFlags = mempty,
284
285
286
287
288
289
290
291
292
293
294
    commandOptions = args
  }
  where
    args :: ShowOrParseArgs -> [OptionField GlobalFlags]
    args ShowArgs  = argsShown
    args ParseArgs = argsShown ++ argsNotShown

    -- arguments we want to show in the help
    argsShown :: [OptionField GlobalFlags]
    argsShown = [
       option ['V'] ["version"]
295
296
297
298
299
300
301
302
303
304
305
306
307
308
         "Print version information"
         globalVersion (\v flags -> flags { globalVersion = v })
         trueArg

      ,option [] ["numeric-version"]
         "Print just the version number"
         globalNumericVersion (\v flags -> flags { globalNumericVersion = v })
         trueArg

      ,option [] ["config-file"]
         "Set an alternate location for the config file"
         globalConfigFile (\v flags -> flags { globalConfigFile = v })
         (reqArgFlag "FILE")

309
      ,option [] ["sandbox-config-file"]
310
         "Set an alternate location for the sandbox config file (default: './cabal.sandbox.config')"
311
         globalSandboxConfigFile (\v flags -> flags { globalSandboxConfigFile = v })
312
313
         (reqArgFlag "FILE")

U-CIQDEV\gbazerman's avatar
U-CIQDEV\gbazerman committed
314
315
      ,option [] ["default-user-config"]
         "Set a location for a cabal.config file for projects without their own cabal.config freeze file."
316
         globalConstraintsFile (\v flags -> flags {globalConstraintsFile = v})
U-CIQDEV\gbazerman's avatar
U-CIQDEV\gbazerman committed
317
318
         (reqArgFlag "FILE")

319
      ,option [] ["require-sandbox"]
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
320
         "requiring the presence of a sandbox for sandbox-aware commands"
321
322
323
         globalRequireSandbox (\v flags -> flags { globalRequireSandbox = v })
         (boolOpt' ([], ["require-sandbox"]) ([], ["no-require-sandbox"]))

324
325
326
327
328
      ,option [] ["ignore-sandbox"]
         "Ignore any existing sandbox"
         globalIgnoreSandbox (\v flags -> flags { globalIgnoreSandbox = v })
         trueArg

329
      ,option [] ["ignore-expiry"]
Edsko de Vries's avatar
Edsko de Vries committed
330
         "Ignore expiry dates on signed metadata (use only in exceptional circumstances)"
331
332
333
         globalIgnoreExpiry (\v flags -> flags { globalIgnoreExpiry = v })
         trueArg

334
      ,option [] ["http-transport"]
335
         "Set a transport for http(s) requests. Accepts 'curl', 'wget', 'powershell', and 'plain-http'. (default: 'curl')"
336
         globalHttpTransport (\v flags -> flags { globalHttpTransport = v })
337
         (reqArgFlag "HttpTransport")
ttuegel's avatar
ttuegel committed
338
339
340
341
      ,option [] ["nix"]
         "Nix integration: run commands through nix-shell if a 'shell.nix' file exists"
         globalNix (\v flags -> flags { globalNix = v })
         (boolOpt [] [])
342
      ]
343

344
345
346
347
    -- arguments we don't want shown in the help
    argsNotShown :: [OptionField GlobalFlags]
    argsNotShown = [
       option [] ["remote-repo"]
348
349
         "The name and url for a remote repository"
         globalRemoteRepos (\v flags -> flags { globalRemoteRepos = v })
350
         (reqArg' "NAME:URL" (toNubList . maybeToList . readRepo) (map showRepo . fromNubList))
351
352
353
354
355
356
357
358
359

      ,option [] ["remote-repo-cache"]
         "The location where downloads from all remote repos are cached"
         globalCacheDir (\v flags -> flags { globalCacheDir = v })
         (reqArgFlag "DIR")

      ,option [] ["local-repo"]
         "The location of a local repository"
         globalLocalRepos (\v flags -> flags { globalLocalRepos = v })
360
         (reqArg' "DIR" (\x -> toNubList [x]) fromNubList)
361

362
363
364
365
366
      ,option [] ["logs-dir"]
         "The location to put log files"
         globalLogsDir (\v flags -> flags { globalLogsDir = v })
         (reqArgFlag "DIR")

367
368
369
370
      ,option [] ["world-file"]
         "The location of the world file"
         globalWorldFile (\v flags -> flags { globalWorldFile = v })
         (reqArgFlag "FILE")
371
372
373
374
375

      ,option [] ["store-dir"]
         "The location of the nix-local-build store"
         globalStoreDir (\v flags -> flags { globalStoreDir = v })
         (reqArgFlag "DIR")
376
377
378
379
380
      ]

-- ------------------------------------------------------------
-- * Config flags
-- ------------------------------------------------------------
Duncan Coutts's avatar
Duncan Coutts committed
381

382
configureCommand :: CommandUI ConfigFlags
383
384
configureCommand = c
  { commandDefaultFlags = mempty
385
386
387
  , commandNotes = Just $ \pname -> (case commandNotes c of
         Nothing -> ""
         Just n  -> n pname ++ "\n")
388
389
390
391
392
393
       ++ "Examples:\n"
       ++ "  " ++ pname ++ " configure\n"
       ++ "    Configure with defaults;\n"
       ++ "  " ++ pname ++ " configure --enable-tests -fcustomflag\n"
       ++ "    Configure building package including tests,\n"
       ++ "    with some package-specific flag.\n"
Duncan Coutts's avatar
Duncan Coutts committed
394
  }
395
 where
396
  c = Cabal.configureCommand defaultProgramDb
Duncan Coutts's avatar
Duncan Coutts committed
397

398
399
400
configureOptions ::  ShowOrParseArgs -> [OptionField ConfigFlags]
configureOptions = commandOptions configureCommand

401
402
403
404
405
406
407
408
-- | Given some 'ConfigFlags' for the version of Cabal that
-- cabal-install was built with, and a target older 'Version' of
-- Cabal that we want to pass these flags to, convert the
-- flags into a form that will be accepted by the older
-- Setup script.  Generally speaking, this just means filtering
-- out flags that the old Cabal library doesn't understand, but
-- in some cases it may also mean "emulating" a feature using
-- some more legacy flags.
409
filterConfigureFlags :: ConfigFlags -> Version -> ConfigFlags
410
filterConfigureFlags flags cabalLibVersion
411
412
  -- NB: we expect the latest version to be the most common case,
  -- so test it first.
413
  | cabalLibVersion >= mkVersion [2,1,0]  = flags_latest
414
415
416
417
418
  -- The naming convention is that flags_version gives flags with
  -- all flags *introduced* in version eliminated.
  -- It is NOT the latest version of Cabal library that
  -- these flags work for; version of introduction is a more
  -- natural metric.
419
420
421
422
423
424
425
426
427
428
  | cabalLibVersion < mkVersion [1,3,10] = flags_1_3_10
  | cabalLibVersion < mkVersion [1,10,0] = flags_1_10_0
  | cabalLibVersion < mkVersion [1,12,0] = flags_1_12_0
  | cabalLibVersion < mkVersion [1,14,0] = flags_1_14_0
  | cabalLibVersion < mkVersion [1,18,0] = flags_1_18_0
  | cabalLibVersion < mkVersion [1,19,1] = flags_1_19_1
  | cabalLibVersion < mkVersion [1,19,2] = flags_1_19_2
  | cabalLibVersion < mkVersion [1,21,1] = flags_1_21_1
  | cabalLibVersion < mkVersion [1,22,0] = flags_1_22_0
  | cabalLibVersion < mkVersion [1,23,0] = flags_1_23_0
Christiaan Baaij's avatar
Christiaan Baaij committed
429
  | cabalLibVersion < mkVersion [1,25,0] = flags_1_25_0
430
  | cabalLibVersion < mkVersion [2,1,0]  = flags_2_1_0
431
  | otherwise = flags_latest
432
  where
433
434
    flags_latest = flags        {
      -- Cabal >= 1.19.1 uses '--dependency' and does not need '--constraint'.
435
      configConstraints = []
436
      }
437

438
439
    flags_2_1_0 = flags_latest {
      -- Cabal < 2.1 doesn't know about -v +timestamp modifier
Moritz Angermann's avatar
Moritz Angermann committed
440
441
442
        configVerbosity   = fmap verboseNoTimestamp (configVerbosity flags_latest)
      -- Cabal < 2.1 doesn't know about --<enable|disable>-static
      , configStaticLib   = NoFlag
Ben Gamari's avatar
Ben Gamari committed
443
      , configSplitSections = NoFlag
444
445
446
      }

    flags_1_25_0 = flags_2_1_0 {
447
448
449
      -- Cabal < 1.25.0 doesn't know about --dynlibdir.
      configInstallDirs = configInstallDirs_1_25_0,
      -- Cabal < 1.25 doesn't have extended verbosity syntax
450
      configVerbosity   = fmap verboseNoFlags (configVerbosity flags_2_1_0),
451
452
      -- Cabal < 1.25 doesn't support --deterministic
      configDeterministic = mempty
453
      }
454
455
456
457
458
459
460
    configInstallDirs_1_25_0 = let dirs = configInstallDirs flags in
        dirs { dynlibdir = NoFlag
             , libexecsubdir = NoFlag
             , libexecdir = maybeToFlag $
                 combinePathTemplate <$> flagToMaybe (libexecdir dirs)
                                     <*> flagToMaybe (libexecsubdir dirs)
             }
461
    -- Cabal < 1.23 doesn't know about '--profiling-detail'.
462
463
464
    -- Cabal < 1.23 has a hacked up version of 'enable-profiling'
    -- which we shouldn't use.
    (tryLibProfiling, tryExeProfiling) = computeEffectiveProfiling flags
Christiaan Baaij's avatar
Christiaan Baaij committed
465
    flags_1_23_0 = flags_1_25_0 { configProfDetail    = NoFlag
466
                                , configProfLibDetail = NoFlag
467
                                , configIPID          = NoFlag
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
468
469
470
                                , configProf          = NoFlag
                                , configProfExe       = Flag tryExeProfiling
                                , configProfLib       = Flag tryLibProfiling
471
                                }
472

473
    -- Cabal < 1.22 doesn't know about '--disable-debug-info'.
474
    flags_1_22_0 = flags_1_23_0 { configDebugInfo = NoFlag }
475

476
    -- Cabal < 1.21.1 doesn't know about 'disable-relocatable'
477
    -- Cabal < 1.21.1 doesn't know about 'enable-profiling'
478
    -- (but we already dealt with it in flags_1_23_0)
479
480
    flags_1_21_1 =
      flags_1_22_0 { configRelocatable = NoFlag
481
482
                   , configCoverage = NoFlag
                   , configLibCoverage = configCoverage flags
483
                   }
484
485
    -- Cabal < 1.19.2 doesn't know about '--exact-configuration' and
    -- '--enable-library-stripping'.
486
    flags_1_19_2 = flags_1_21_1 { configExactConfiguration = NoFlag
487
                                , configStripLibs = NoFlag }
488
    -- Cabal < 1.19.1 uses '--constraint' instead of '--dependency'.
489
    flags_1_19_1 = flags_1_19_2 { configDependencies = []
490
                                , configConstraints  = configConstraints flags }
491
    -- Cabal < 1.18.0 doesn't know about --extra-prog-path and --sysconfdir.
492
    flags_1_18_0 = flags_1_19_1 { configProgramPathExtra = toNubList []
493
                                , configInstallDirs = configInstallDirs_1_18_0}
Christiaan Baaij's avatar
Christiaan Baaij committed
494
    configInstallDirs_1_18_0 = (configInstallDirs flags_1_19_1) { sysconfdir = NoFlag }
495
    -- Cabal < 1.14.0 doesn't know about '--disable-benchmarks'.
496
    flags_1_14_0 = flags_1_18_0 { configBenchmarks  = NoFlag }
497
498
499
500
    -- Cabal < 1.12.0 doesn't know about '--enable/disable-executable-dynamic'
    -- and '--enable/disable-library-coverage'.
    flags_1_12_0 = flags_1_14_0 { configLibCoverage = NoFlag
                                , configDynExe      = NoFlag }
501
    -- Cabal < 1.10.0 doesn't know about '--disable-tests'.
502
    flags_1_10_0 = flags_1_12_0 { configTests       = NoFlag }
503
    -- Cabal < 1.3.10 does not grok the '--constraints' flag.
504
    flags_1_3_10 = flags_1_10_0 { configConstraints = [] }
505

506
507
-- | Get the package database settings from 'ConfigFlags', accounting for
-- @--package-db@ and @--user@ flags.
508
509
510
511
512
513
configPackageDB' :: ConfigFlags -> PackageDBStack
configPackageDB' cfg =
    interpretPackageDbFlags userInstall (configPackageDBs cfg)
  where
    userInstall = Cabal.fromFlagOrDefault True (configUserInstall cfg)

514
-- | Configure the compiler, but reduce verbosity during this step.
515
516
517
518
519
520
configCompilerAux' :: ConfigFlags -> IO (Compiler, Platform, ProgramDb)
configCompilerAux' configFlags =
  configCompilerAuxEx configFlags
    --FIXME: make configCompilerAux use a sensible verbosity
    { configVerbosity = fmap lessVerbose (configVerbosity configFlags) }

521
522
523
524
525
526
527
528
-- ------------------------------------------------------------
-- * Config extra flags
-- ------------------------------------------------------------

-- | cabal configure takes some extra flags beyond runghc Setup configure
--
data ConfigExFlags = ConfigExFlags {
    configCabalVersion :: Flag Version,
529
    configExConstraints:: [(UserConstraint, ConstraintSource)],
530
    configPreferences  :: [Dependency],
531
532
533
    configSolver       :: Flag PreSolver,
    configAllowNewer   :: Maybe AllowNewer,
    configAllowOlder   :: Maybe AllowOlder
534
  }
535
  deriving (Eq, Generic)
536
537

defaultConfigExFlags :: ConfigExFlags
538
defaultConfigExFlags = mempty { configSolver     = Flag defaultSolver }
539
540
541
542
543

configureExCommand :: CommandUI (ConfigFlags, ConfigExFlags)
configureExCommand = configureCommand {
    commandDefaultFlags = (mempty, defaultConfigExFlags),
    commandOptions      = \showOrParseArgs ->
544
         liftOptions fst setFst
545
         (filter ((`notElem` ["constraint", "dependency", "exact-configuration"])
546
                  . optionName) $ configureOptions  showOrParseArgs)
547
548
      ++ liftOptions snd setSnd
         (configureExOptions showOrParseArgs ConstraintSourceCommandlineFlag)
549
550
551
552
553
  }
  where
    setFst a (_,b) = (a,b)
    setSnd b (a,_) = (a,b)

554
555
556
557
configureExOptions :: ShowOrParseArgs
                   -> ConstraintSource
                   -> [OptionField ConfigExFlags]
configureExOptions _showOrParseArgs src =
558
559
560
561
562
563
564
  [ option [] ["cabal-lib-version"]
      ("Select which version of the Cabal lib to use to build packages "
      ++ "(useful for testing).")
      configCabalVersion (\v flags -> flags { configCabalVersion = v })
      (reqArg "VERSION" (readP_to_E ("Cannot parse cabal lib version: "++)
                                    (fmap toFlag parse))
                        (map display . flagToList))
565
566
567
568
  , option [] ["constraint"]
      "Specify constraints on a package (version, installed/source, flags)"
      configExConstraints (\v flags -> flags { configExConstraints = v })
      (reqArg "CONSTRAINT"
569
570
              ((\x -> [(x, src)]) `fmap` ReadE readUserConstraint)
              (map $ display . fst))
571
572
573
574

  , option [] ["preference"]
      "Specify preferences (soft constraints) on the version of a package"
      configPreferences (\v flags -> flags { configPreferences = v })
575
576
577
578
      (reqArg "CONSTRAINT"
              (readP_to_E (const "dependency expected")
                          (fmap (\x -> [x]) parse))
              (map display))
579
580

  , optionSolver configSolver (\v flags -> flags { configSolver = v })
581

582
  , option [] ["allow-older"]
583
    ("Ignore lower bounds in all dependencies or DEPS")
584
585
586
587
588
589
590
591
592
593
594
595
596
597
    (fmap unAllowOlder . configAllowOlder)
    (\v flags -> flags { configAllowOlder = fmap AllowOlder v})
    (optArg "DEPS"
     (readP_to_E ("Cannot parse the list of packages: " ++) relaxDepsParser)
     (Just RelaxDepsAll) relaxDepsPrinter)

  , option [] ["allow-newer"]
    ("Ignore upper bounds in all dependencies or DEPS")
    (fmap unAllowNewer . configAllowNewer)
    (\v flags -> flags { configAllowNewer = fmap AllowNewer v})
    (optArg "DEPS"
     (readP_to_E ("Cannot parse the list of packages: " ++) relaxDepsParser)
     (Just RelaxDepsAll) relaxDepsPrinter)

598
599
  ]

600
601
602
603
604
605
606
607
608
609
610

relaxDepsParser :: Parse.ReadP r (Maybe RelaxDeps)
relaxDepsParser =
  (Just . RelaxDepsSome) `fmap` Parse.sepBy1 parse (Parse.char ',')

relaxDepsPrinter :: (Maybe RelaxDeps) -> [Maybe String]
relaxDepsPrinter Nothing                     = []
relaxDepsPrinter (Just RelaxDepsAll)         = [Nothing]
relaxDepsPrinter (Just (RelaxDepsSome pkgs)) = map (Just . display) $ pkgs


611
instance Monoid ConfigExFlags where
612
  mempty = gmempty
613
614
615
  mappend = (<>)

instance Semigroup ConfigExFlags where
616
  (<>) = gmappend
617

ttuegel's avatar
ttuegel committed
618
619
620
621
622
623
reconfigureCommand :: CommandUI (ConfigFlags, ConfigExFlags)
reconfigureCommand
  = configureExCommand
    { commandName         = "reconfigure"
    , commandSynopsis     = "Reconfigure the package if necessary."
    , commandDescription  = Just $ \pname -> wrapText $
624
625
         "Run `configure` with the most recently used flags, or append FLAGS "
         ++ "to the most recently used configuration. "
ttuegel's avatar
ttuegel committed
626
         ++ "Accepts the same flags as `" ++ pname ++ " configure'. "
627
628
629
630
631
632
633
634
635
         ++ "If the package has never been configured, the default flags are "
         ++ "used."
    , commandNotes        = Just $ \pname ->
        "Examples:\n"
        ++ "  " ++ pname ++ " reconfigure\n"
        ++ "    Configure with the most recently used flags.\n"
        ++ "  " ++ pname ++ " reconfigure -w PATH\n"
        ++ "    Reconfigure with the most recently used flags,\n"
        ++ "    but use the compiler at PATH.\n\n"
ttuegel's avatar
ttuegel committed
636
637
638
639
    , commandUsage        = usageAlternatives "reconfigure" [ "[FLAGS]" ]
    , commandDefaultFlags = mempty
    }

ttuegel's avatar
ttuegel committed
640
641
642
643
-- ------------------------------------------------------------
-- * Build flags
-- ------------------------------------------------------------

644
645
646
647
648
649
data SkipAddSourceDepsCheck =
  SkipAddSourceDepsCheck | DontSkipAddSourceDepsCheck
  deriving Eq

data BuildExFlags = BuildExFlags {
  buildOnly     :: Flag SkipAddSourceDepsCheck
650
} deriving Generic
651
652
653

buildExOptions :: ShowOrParseArgs -> [OptionField BuildExFlags]
buildExOptions _showOrParseArgs =
654
  option [] ["only"]
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
  "Don't reinstall add-source dependencies (sandbox-only)"
  buildOnly (\v flags -> flags { buildOnly = v })
  (noArg (Flag SkipAddSourceDepsCheck))

  : []

buildCommand :: CommandUI (BuildFlags, BuildExFlags)
buildCommand = parent {
    commandDefaultFlags = (commandDefaultFlags parent, mempty),
    commandOptions      =
      \showOrParseArgs -> liftOptions fst setFst
                          (commandOptions parent showOrParseArgs)
                          ++
                          liftOptions snd setSnd (buildExOptions showOrParseArgs)
  }
  where
    setFst a (_,b) = (a,b)
    setSnd b (a,_) = (a,b)

674
    parent = Cabal.buildCommand defaultProgramDb
675
676

instance Monoid BuildExFlags where
677
  mempty = gmempty
678
679
680
  mappend = (<>)

instance Semigroup BuildExFlags where
681
  (<>) = gmappend
682
683

-- ------------------------------------------------------------
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
-- * Repl command
-- ------------------------------------------------------------

replCommand :: CommandUI (ReplFlags, BuildExFlags)
replCommand = parent {
    commandDefaultFlags = (commandDefaultFlags parent, mempty),
    commandOptions      =
      \showOrParseArgs -> liftOptions fst setFst
                          (commandOptions parent showOrParseArgs)
                          ++
                          liftOptions snd setSnd (buildExOptions showOrParseArgs)
  }
  where
    setFst a (_,b) = (a,b)
    setSnd b (a,_) = (a,b)

700
    parent = Cabal.replCommand defaultProgramDb
701

702
703
704
705
-- ------------------------------------------------------------
-- * Test command
-- ------------------------------------------------------------

706
testCommand :: CommandUI (TestFlags, BuildFlags, BuildExFlags)
707
testCommand = parent {
708
709
  commandDefaultFlags = (commandDefaultFlags parent,
                         Cabal.defaultBuildFlags, mempty),
710
  commandOptions      =
711
    \showOrParseArgs -> liftOptions get1 set1
712
713
                        (commandOptions parent showOrParseArgs)
                        ++
714
                        liftOptions get2 set2
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
715
                        (Cabal.buildOptions progDb showOrParseArgs)
716
717
                        ++
                        liftOptions get3 set3 (buildExOptions showOrParseArgs)
718
719
  }
  where
720
721
722
    get1 (a,_,_) = a; set1 a (_,b,c) = (a,b,c)
    get2 (_,b,_) = b; set2 b (a,_,c) = (a,b,c)
    get3 (_,_,c) = c; set3 c (a,b,_) = (a,b,c)
723

Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
724
725
    parent = Cabal.testCommand
    progDb = defaultProgramDb
726
727
728
729
730

-- ------------------------------------------------------------
-- * Bench command
-- ------------------------------------------------------------

731
benchmarkCommand :: CommandUI (BenchmarkFlags, BuildFlags, BuildExFlags)
732
benchmarkCommand = parent {
733
734
  commandDefaultFlags = (commandDefaultFlags parent,
                         Cabal.defaultBuildFlags, mempty),
735
  commandOptions      =
736
    \showOrParseArgs -> liftOptions get1 set1
737
738
                        (commandOptions parent showOrParseArgs)
                        ++
739
                        liftOptions get2 set2
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
740
                        (Cabal.buildOptions progDb showOrParseArgs)
741
742
                        ++
                        liftOptions get3 set3 (buildExOptions showOrParseArgs)
ttuegel's avatar
ttuegel committed
743
  }
744
  where
745
746
747
    get1 (a,_,_) = a; set1 a (_,b,c) = (a,b,c)
    get2 (_,b,_) = b; set2 b (a,_,c) = (a,b,c)
    get3 (_,_,c) = c; set3 c (a,b,_) = (a,b,c)
748

Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
749
750
    parent = Cabal.benchmarkCommand
    progDb = defaultProgramDb
ttuegel's avatar
ttuegel committed
751

752
-- ------------------------------------------------------------
753
-- * Fetch command
754
-- ------------------------------------------------------------
755

756
757
758
759
data FetchFlags = FetchFlags {
--    fetchOutput    :: Flag FilePath,
      fetchDeps      :: Flag Bool,
      fetchDryRun    :: Flag Bool,
760
      fetchSolver           :: Flag PreSolver,
761
      fetchMaxBackjumps     :: Flag Int,
762
      fetchReorderGoals     :: Flag ReorderGoals,
763
      fetchCountConflicts   :: Flag CountConflicts,
764
765
766
      fetchIndependentGoals :: Flag IndependentGoals,
      fetchShadowPkgs       :: Flag ShadowPkgs,
      fetchStrongFlags      :: Flag StrongFlags,
767
      fetchAllowBootLibInstalls :: Flag AllowBootLibInstalls,
768
769
770
771
772
773
774
775
      fetchVerbosity :: Flag Verbosity
    }

defaultFetchFlags :: FetchFlags
defaultFetchFlags = FetchFlags {
--  fetchOutput    = mempty,
    fetchDeps      = toFlag True,
    fetchDryRun    = toFlag False,
776
777
    fetchSolver           = Flag defaultSolver,
    fetchMaxBackjumps     = Flag defaultMaxBackjumps,
778
    fetchReorderGoals     = Flag (ReorderGoals False),
779
    fetchCountConflicts   = Flag (CountConflicts True),
780
781
782
    fetchIndependentGoals = Flag (IndependentGoals False),
    fetchShadowPkgs       = Flag (ShadowPkgs False),
    fetchStrongFlags      = Flag (StrongFlags False),
783
    fetchAllowBootLibInstalls = Flag (AllowBootLibInstalls False),
784
785
786
787
    fetchVerbosity = toFlag normal
   }

fetchCommand :: CommandUI FetchFlags
Duncan Coutts's avatar
Duncan Coutts committed
788
789
fetchCommand = CommandUI {
    commandName         = "fetch",
790
    commandSynopsis     = "Downloads packages for later installation.",
791
792
793
794
795
    commandUsage        = usageAlternatives "fetch" [ "[FLAGS] PACKAGES"
                                                    ],
    commandDescription  = Just $ \_ ->
          "Note that it currently is not possible to fetch the dependencies for a\n"
       ++ "package in the current directory.\n",
796
    commandNotes        = Nothing,
797
    commandDefaultFlags = defaultFetchFlags,
798
    commandOptions      = \ showOrParseArgs -> [
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
         optionVerbosity fetchVerbosity (\v flags -> flags { fetchVerbosity = v })

--     , option "o" ["output"]
--         "Put the package(s) somewhere specific rather than the usual cache."
--         fetchOutput (\v flags -> flags { fetchOutput = v })
--         (reqArgFlag "PATH")

       , option [] ["dependencies", "deps"]
           "Resolve and fetch dependencies (default)"
           fetchDeps (\v flags -> flags { fetchDeps = v })
           trueArg

       , option [] ["no-dependencies", "no-deps"]
           "Ignore dependencies"
           fetchDeps (\v flags -> flags { fetchDeps = v })
           falseArg

       , option [] ["dry-run"]
           "Do not install anything, only print what would be installed."
           fetchDryRun (\v flags -> flags { fetchDryRun = v })
           trueArg
820
821
822
823

       ] ++

       optionSolver      fetchSolver           (\v flags -> flags { fetchSolver           = v }) :
824
825
       optionSolverFlags showOrParseArgs
                         fetchMaxBackjumps     (\v flags -> flags { fetchMaxBackjumps     = v })
826
                         fetchReorderGoals     (\v flags -> flags { fetchReorderGoals     = v })
827
                         fetchCountConflicts   (\v flags -> flags { fetchCountConflicts   = v })
828
                         fetchIndependentGoals (\v flags -> flags { fetchIndependentGoals = v })
829
                         fetchShadowPkgs       (\v flags -> flags { fetchShadowPkgs       = v })
Andres Löh's avatar
Andres Löh committed
830
                         fetchStrongFlags      (\v flags -> flags { fetchStrongFlags      = v })
831
                         fetchAllowBootLibInstalls (\v flags -> flags { fetchAllowBootLibInstalls = v })
832

Duncan Coutts's avatar
Duncan Coutts committed
833
834
  }

835
836
837
838
839
840
-- ------------------------------------------------------------
-- * Freeze command
-- ------------------------------------------------------------

data FreezeFlags = FreezeFlags {
      freezeDryRun           :: Flag Bool,
841
842
      freezeTests            :: Flag Bool,
      freezeBenchmarks       :: Flag Bool,
843
844
      freezeSolver           :: Flag PreSolver,
      freezeMaxBackjumps     :: Flag Int,
845
      freezeReorderGoals     :: Flag ReorderGoals,
846
      freezeCountConflicts   :: Flag CountConflicts,
847
848
849
      freezeIndependentGoals :: Flag IndependentGoals,
      freezeShadowPkgs       :: Flag ShadowPkgs,
      freezeStrongFlags      :: Flag StrongFlags,
850
      freezeAllowBootLibInstalls :: Flag AllowBootLibInstalls,
851
852
853
854
855
856
      freezeVerbosity        :: Flag Verbosity
    }

defaultFreezeFlags :: FreezeFlags
defaultFreezeFlags = FreezeFlags {
    freezeDryRun           = toFlag False,
857
858
    freezeTests            = toFlag False,
    freezeBenchmarks       = toFlag False,
859
860
    freezeSolver           = Flag defaultSolver,
    freezeMaxBackjumps     = Flag defaultMaxBackjumps,
861
    freezeReorderGoals     = Flag (ReorderGoals False),
862
    freezeCountConflicts   = Flag (CountConflicts True),
863
864
865
    freezeIndependentGoals = Flag (IndependentGoals False),
    freezeShadowPkgs       = Flag (ShadowPkgs False),
    freezeStrongFlags      = Flag (StrongFlags False),
866
    freezeAllowBootLibInstalls = Flag (AllowBootLibInstalls False),
867
868
869
870
871
872
873
    freezeVerbosity        = toFlag normal
   }

freezeCommand :: CommandUI FreezeFlags
freezeCommand = CommandUI {
    commandName         = "freeze",
    commandSynopsis     = "Freeze dependencies.",
874
875
876
877
878
879
880
881
    commandDescription  = Just $ \_ -> wrapText $
         "Calculates a valid set of dependencies and their exact versions. "
      ++ "If successful, saves the result to the file `cabal.config`.\n"
      ++ "\n"
      ++ "The package versions specified in `cabal.config` will be used for "
      ++ "any future installs.\n"
      ++ "\n"
      ++ "An existing `cabal.config` is ignored and overwritten.\n",
882
    commandNotes        = Nothing,
883
    commandUsage        = usageFlags "freeze",
884
885
    commandDefaultFlags = defaultFreezeFlags,
    commandOptions      = \ showOrParseArgs -> [
886
887
         optionVerbosity freezeVerbosity
         (\v flags -> flags { freezeVerbosity = v })
888
889
890
891
892
893

       , option [] ["dry-run"]
           "Do not freeze anything, only print what would be frozen"
           freezeDryRun (\v flags -> flags { freezeDryRun = v })
           trueArg

894
       , option [] ["tests"]
895
896
           ("freezing of the dependencies of any tests suites "
            ++ "in the package description file.")
897
898
899
900
           freezeTests (\v flags -> flags { freezeTests = v })
           (boolOpt [] [])

       , option [] ["benchmarks"]
901
902
           ("freezing of the dependencies of any benchmarks suites "
            ++ "in the package description file.")
903
904
905
           freezeBenchmarks (\v flags -> flags { freezeBenchmarks = v })
           (boolOpt [] [])

906
907
       ] ++

908
909
       optionSolver
         freezeSolver           (\v flags -> flags { freezeSolver           = v }):
910
911
912
       optionSolverFlags showOrParseArgs
                         freezeMaxBackjumps     (\v flags -> flags { freezeMaxBackjumps     = v })
                         freezeReorderGoals     (\v flags -> flags { freezeReorderGoals     = v })
913
                         freezeCountConflicts   (\v flags -> flags { freezeCountConflicts   = v })
914
915
                         freezeIndependentGoals (\v flags -> flags { freezeIndependentGoals = v })
                         freezeShadowPkgs       (\v flags -> flags { freezeShadowPkgs       = v })
Andres Löh's avatar
Andres Löh committed
916
                         freezeStrongFlags      (\v flags -> flags { freezeStrongFlags      = v })
917
                         freezeAllowBootLibInstalls (\v flags -> flags { freezeAllowBootLibInstalls = v })
918
919
920

  }

921
922
923
924
-- ------------------------------------------------------------
-- * 'gen-bounds' command
-- ------------------------------------------------------------

925
926
927
928
929
930
genBoundsCommand :: CommandUI FreezeFlags
genBoundsCommand = CommandUI {
    commandName         = "gen-bounds",
    commandSynopsis     = "Generate dependency bounds.",
    commandDescription  = Just $ \_ -> wrapText $
         "Generates bounds for all dependencies that do not currently have them. "
931
932
      ++ "Generated bounds are printed to stdout.  "
      ++ "You can then paste them into your .cabal file.\n"
933
934
935
936
937
938
939
940
941
      ++ "\n",
    commandNotes        = Nothing,
    commandUsage        = usageFlags "gen-bounds",
    commandDefaultFlags = defaultFreezeFlags,
    commandOptions      = \ _ -> [
     optionVerbosity freezeVerbosity (\v flags -> flags { freezeVerbosity = v })
     ]
  }

942
943
944
945
-- ------------------------------------------------------------
-- * 'outdated' command
-- ------------------------------------------------------------

946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
data IgnoreMajorVersionBumps = IgnoreMajorVersionBumpsNone
                             | IgnoreMajorVersionBumpsAll
                             | IgnoreMajorVersionBumpsSome [PackageName]

instance Monoid IgnoreMajorVersionBumps where
  mempty  = IgnoreMajorVersionBumpsNone
  mappend = (<>)

instance Semigroup IgnoreMajorVersionBumps where
  IgnoreMajorVersionBumpsNone       <> r                               = r
  l@IgnoreMajorVersionBumpsAll      <> _                               = l
  l@(IgnoreMajorVersionBumpsSome _) <> IgnoreMajorVersionBumpsNone     = l
  (IgnoreMajorVersionBumpsSome   _) <> r@IgnoreMajorVersionBumpsAll    = r
  (IgnoreMajorVersionBumpsSome   a) <> (IgnoreMajorVersionBumpsSome b) =
    IgnoreMajorVersionBumpsSome (a ++ b)

962
data OutdatedFlags = OutdatedFlags {
963
964
965
  outdatedVerbosity     :: Flag Verbosity,
  outdatedFreezeFile    :: Flag Bool,
  outdatedNewFreezeFile :: Flag Bool,
966
  outdatedSimpleOutput  :: Flag Bool,
967
  outdatedExitCode      :: Flag Bool,
968
  outdatedQuiet         :: Flag Bool,
969
  outdatedIgnore        :: [PackageName],
970
  outdatedMinor         :: Maybe IgnoreMajorVersionBumps
971
972
973
974
  }

defaultOutdatedFlags :: OutdatedFlags
defaultOutdatedFlags = OutdatedFlags {
975
976
977
  outdatedVerbosity     = toFlag normal,
  outdatedFreezeFile    = mempty,
  outdatedNewFreezeFile = mempty,
978
  outdatedSimpleOutput  = mempty,