@@ -106,7 +106,8 @@ import Distribution.Simple.Compiler
106
106
)
107
107
import Distribution.Simple.Program.GHC
108
108
import Distribution.Simple.Setup
109
- ( ReplOptions (.. )
109
+ ( Flag
110
+ , ReplOptions (.. )
110
111
, commonSetupTempFileOptions
111
112
)
112
113
import Distribution.Simple.Utils
@@ -170,8 +171,8 @@ import Data.List
170
171
import qualified Data.Map as Map
171
172
import qualified Data.Set as Set
172
173
import Distribution.Client.ProjectConfig
173
- ( ProjectConfig (projectConfigShared )
174
- , ProjectConfigShared (projectConfigConstraints , projectConfigMultiRepl )
174
+ ( ProjectConfig (.. )
175
+ , ProjectConfigShared (.. )
175
176
)
176
177
import Distribution.Client.ReplFlags
177
178
( EnvFlags (envIncludeTransitive , envPackages )
@@ -195,6 +196,8 @@ import System.FilePath
195
196
, splitSearchPath
196
197
, (</>)
197
198
)
199
+ import Text.PrettyPrint hiding ((<>) )
200
+ import Distribution.Types.PackageName.Magic ( fakePackageId )
198
201
199
202
replCommand :: CommandUI (NixStyleFlags ReplFlags )
200
203
replCommand =
@@ -281,17 +284,29 @@ multiReplDecision ctx compiler flags =
281
284
-- For more details on how this works, see the module
282
285
-- "Distribution.Client.ProjectOrchestration"
283
286
replAction :: NixStyleFlags ReplFlags -> [String ] -> GlobalFlags -> IO ()
284
- replAction flags@ NixStyleFlags {extraFlags = r @ ReplFlags {.. }, .. } targetStrings globalFlags =
285
- withContextAndSelectors verbosity AcceptNoTargets ( Just LibKind ) flags targetStrings globalFlags ReplCommand $ \ targetCtx ctx targetSelectors -> do
287
+ replAction flags@ NixStyleFlags {extraFlags = replFlags @ ReplFlags {.. }, configFlags } targetStrings globalFlags = do
288
+ withCtx verbosity targetStrings $ \ targetCtx ctx userTargetSelectors -> do
286
289
when (buildSettingOnlyDeps (buildSettings ctx)) $
287
290
dieWithException verbosity ReplCommandDoesn'tSupport
288
291
let projectRoot = distProjectRootDirectory $ distDirLayout ctx
289
292
distDir = distDirectory $ distDirLayout ctx
290
293
291
- baseCtx <- case targetCtx of
292
- ProjectContext -> return ctx
294
+ -- After ther user selectors have been resolved, and it's decided what context
295
+ -- we're in, implement repl-specific behaviour.
296
+ (baseCtx, targetSelectors) <- case targetCtx of
297
+ -- If in the project context, and no selectors are provided
298
+ -- then produce an error.
299
+ ProjectContext -> do
300
+ let projectFile = projectConfigProjectFile . projectConfigShared $ projectConfig ctx
301
+ let pkgs = projectPackages $ projectConfig ctx
302
+ case userTargetSelectors of
303
+ [] -> dieWithException verbosity $
304
+ RenderReplTargetProblem [render (reportProjectNoTarget projectFile pkgs)]
305
+ _ -> return (ctx, userTargetSelectors)
306
+ -- In the global context, construct a fake package which can be used to start
307
+ -- a repl with extra arguments if `-b` is given.
293
308
GlobalContext -> do
294
- unless (null targetStrings ) $
309
+ unless (null userTargetSelectors ) $
295
310
dieWithException verbosity $
296
311
ReplTakesNoArguments targetStrings
297
312
let
@@ -303,12 +318,18 @@ replAction flags@NixStyleFlags{extraFlags = r@ReplFlags{..}, ..} targetStrings g
303
318
library = emptyLibrary{libBuildInfo = lBuildInfo}
304
319
lBuildInfo =
305
320
emptyBuildInfo
306
- { targetBuildDepends = [baseDep]
321
+ { targetBuildDepends = [baseDep] ++ envPackages replEnvFlags
307
322
, defaultLanguage = Just Haskell2010
308
323
}
309
324
baseDep = Dependency " base" anyVersion mainLibSet
310
325
311
- updateContextAndWriteProjectFile' ctx sourcePackage
326
+ -- Write the fake package
327
+ updatedCtx <- updateContextAndWriteProjectFile' ctx sourcePackage
328
+ -- Specify the selector for this package
329
+ let fakeSelector = TargetPackage TargetExplicitNamed [fakePackageId] Nothing
330
+ return (updatedCtx, [fakeSelector])
331
+
332
+ -- For the script context, no special behaviour.
312
333
ScriptContext scriptPath scriptExecutable -> do
313
334
unless (length targetStrings == 1 ) $
314
335
dieWithException verbosity $
@@ -318,7 +339,8 @@ replAction flags@NixStyleFlags{extraFlags = r@ReplFlags{..}, ..} targetStrings g
318
339
dieWithException verbosity $
319
340
ReplTakesSingleArgument targetStrings
320
341
321
- updateContextAndWriteProjectFile ctx scriptPath scriptExecutable
342
+ updatedCtx <- updateContextAndWriteProjectFile ctx scriptPath scriptExecutable
343
+ return (updatedCtx, userTargetSelectors)
322
344
323
345
-- If multi-repl is used, we need a Cabal recent enough to handle it.
324
346
-- We need to do this before solving, but the compiler version is only known
@@ -361,7 +383,7 @@ replAction flags@NixStyleFlags{extraFlags = r@ReplFlags{..}, ..} targetStrings g
361
383
-- especially in the no-project case.
362
384
withInstallPlan (lessVerbose verbosity) baseCtx' $ \ elaboratedPlan sharedConfig -> do
363
385
-- targets should be non-empty map, but there's no NonEmptyMap yet.
364
- targets <- validatedTargets (projectConfigShared (projectConfig ctx)) (pkgConfigCompiler sharedConfig) elaboratedPlan targetSelectors
386
+ targets <- validatedTargets' (projectConfigShared (projectConfig ctx)) (pkgConfigCompiler sharedConfig) elaboratedPlan targetSelectors
365
387
366
388
let
367
389
(unitId, _) = fromMaybe (error " panic: targets should be non-empty" ) $ safeHead $ Map. toList targets
@@ -385,7 +407,7 @@ replAction flags@NixStyleFlags{extraFlags = r@ReplFlags{..}, ..} targetStrings g
385
407
let ProjectBaseContext {.. } = baseCtx''
386
408
387
409
-- Recalculate with updated project.
388
- targets <- validatedTargets (projectConfigShared projectConfig) (pkgConfigCompiler elaboratedShared') elaboratedPlan targetSelectors
410
+ targets <- validatedTargets' (projectConfigShared projectConfig) (pkgConfigCompiler elaboratedShared') elaboratedPlan targetSelectors
389
411
390
412
let
391
413
elaboratedPlan' =
@@ -518,31 +540,13 @@ replAction flags@NixStyleFlags{extraFlags = r@ReplFlags{..}, ..} targetStrings g
518
540
go m (" PATH" , Just s) = foldl' (\ m' f -> Map. insertWith (+) f 1 m') m (splitSearchPath s)
519
541
go m _ = m
520
542
543
+ withCtx ctxVerbosity strings =
544
+ withContextAndSelectors ctxVerbosity AcceptNoTargets (Just LibKind ) flags strings globalFlags ReplCommand
545
+
521
546
verbosity = cfgVerbosity normal flags
522
547
tempFileOptions = commonSetupTempFileOptions $ configCommonFlags configFlags
523
548
524
- validatedTargets ctx compiler elaboratedPlan targetSelectors = do
525
- let multi_repl_enabled = multiReplDecision ctx compiler r
526
- -- Interpret the targets on the command line as repl targets
527
- -- (as opposed to say build or haddock targets).
528
- targets <-
529
- either (reportTargetProblems verbosity) return $
530
- resolveTargetsFromSolver
531
- (selectPackageTargets multi_repl_enabled)
532
- selectComponentTarget
533
- elaboratedPlan
534
- Nothing
535
- targetSelectors
536
-
537
- -- Reject multiple targets, or at least targets in different
538
- -- components. It is ok to have two module/file targets in the
539
- -- same component, but not two that live in different components.
540
- when (Set. size (distinctTargetComponents targets) > 1 && not (useMultiRepl multi_repl_enabled)) $
541
- reportTargetProblems
542
- verbosity
543
- [multipleTargetsProblem multi_repl_enabled targets]
544
-
545
- return targets
549
+ validatedTargets' = validatedTargets verbosity replFlags
546
550
547
551
-- | Create a constraint which requires a later version of Cabal.
548
552
-- This is used for commands which require a specific feature from the Cabal library
@@ -555,6 +559,69 @@ requireCabal version source =
555
559
, source
556
560
)
557
561
562
+ reportProjectNoTarget :: Flag FilePath -> [String ] -> Doc
563
+ reportProjectNoTarget projectFile pkgs =
564
+ case (null pkgs, projectName) of
565
+ (True , Just project) ->
566
+ text " There are no packages in"
567
+ <+> (project <> char ' .' )
568
+ <+> text " Please add a package to the project and"
569
+ <+> pickComponent
570
+ (True , Nothing ) ->
571
+ text " Please add a package to the project and" <+> pickComponent
572
+ (False , Just project) ->
573
+ text " Please"
574
+ <+> pickComponent
575
+ <+> text " The packages in"
576
+ <+> project
577
+ <+> (text " from which to select a component target are" <> colon)
578
+ $+$ nest 1 (vcat [text " -" <+> text pkg | pkg <- sort pkgs])
579
+ (False , Nothing ) ->
580
+ text " Please"
581
+ <+> pickComponent
582
+ <+> (text " The packages from which to select a component in 'cabal.project'" <> comma)
583
+ <+> (text " the implicit default as if `--project-file=cabal.project` was added as a command option" <> comma)
584
+ <+> (text " are" <> colon)
585
+ $+$ nest 1 (vcat [text " -" <+> text pkg | pkg <- sort pkgs])
586
+ where
587
+ projectName = case projectFile of
588
+ Flag " " -> Nothing
589
+ Flag n -> Just $ quotes (text n)
590
+ _ -> Nothing
591
+ pickComponent = text " pick a single [package:][ctype:]component (or all) as target for the REPL command."
592
+
593
+ -- | Invariant: validatedTargets returns at least one target for the REPL.
594
+ validatedTargets
595
+ :: Verbosity
596
+ -> ReplFlags
597
+ -> ProjectConfigShared
598
+ -> Compiler
599
+ -> ElaboratedInstallPlan
600
+ -> [TargetSelector ]
601
+ -> IO TargetsMap
602
+ validatedTargets verbosity replFlags ctx compiler elaboratedPlan targetSelectors = do
603
+ let multi_repl_enabled = multiReplDecision ctx compiler replFlags
604
+ -- Interpret the targets on the command line as repl targets (as opposed to
605
+ -- say build or haddock targets).
606
+ targets <-
607
+ either (reportTargetProblems verbosity) return $
608
+ resolveTargetsFromSolver
609
+ (selectPackageTargets multi_repl_enabled)
610
+ selectComponentTarget
611
+ elaboratedPlan
612
+ Nothing
613
+ targetSelectors
614
+
615
+ -- Reject multiple targets, or at least targets in different components. It is
616
+ -- ok to have two module/file targets in the same component, but not two that
617
+ -- live in different components.
618
+ when (Set. size (distinctTargetComponents targets) > 1 && not (useMultiRepl multi_repl_enabled)) $
619
+ reportTargetProblems
620
+ verbosity
621
+ [multipleTargetsProblem multi_repl_enabled targets]
622
+
623
+ return targets
624
+
558
625
-- | First version of GHC which supports multiple home packages
559
626
minMultipleHomeUnitsVersion :: Version
560
627
minMultipleHomeUnitsVersion = mkVersion [9 , 4 ]
0 commit comments