@@ -15,13 +15,14 @@ import qualified Data.List as L
15
15
import qualified Data.Map.Strict as Map
16
16
import qualified Data.Set as Set
17
17
import qualified Data.Text as T
18
+ import Distribution.Types.PackageName ( unPackageName )
18
19
import RIO.NonEmpty ( head , nonEmpty )
19
20
import RIO.Process ( exec )
20
21
import Stack.Build ( build )
21
- import Stack.Build.Target ( NeedTargets (.. ) )
22
+ import Stack.Build.Target
23
+ ( NeedTargets (.. ), RawTarget (.. ), parseRawTarget )
22
24
import Stack.GhcPkg ( findGhcPkgField )
23
25
import Stack.Setup ( withNewLocalBuildTargets )
24
- import Stack.Types.NamedComponent ( NamedComponent (.. ), isCExe )
25
26
import Stack.Prelude
26
27
import Stack.Runners ( ShouldReexec (.. ), withConfig , withEnvConfig )
27
28
import Stack.Types.BuildConfig
@@ -33,6 +34,7 @@ import Stack.Types.CompilerPaths
33
34
import Stack.Types.Config ( Config (.. ), HasConfig (.. ) )
34
35
import Stack.Types.EnvConfig ( EnvConfig )
35
36
import Stack.Types.EnvSettings ( EnvSettings (.. ) )
37
+ import Stack.Types.NamedComponent ( NamedComponent (.. ), isCExe )
36
38
import Stack.Types.Runner ( Runner )
37
39
import Stack.Types.SourceMap ( SMWanted (.. ), ppComponents )
38
40
import System.Directory ( withCurrentDirectory )
@@ -58,6 +60,7 @@ data ExecPrettyException
58
60
= PackageIdNotFoundBug ! String
59
61
| ExecutableToRunNotFound
60
62
| NoPackageIdReportedBug
63
+ | InvalidExecTargets ! [Text ]
61
64
deriving (Show , Typeable )
62
65
63
66
instance Pretty ExecPrettyException where
@@ -72,6 +75,20 @@ instance Pretty ExecPrettyException where
72
75
<> flow " No executables found."
73
76
pretty NoPackageIdReportedBug = bugPrettyReport " S-8600" $
74
77
flow " execCmd: findGhcPkgField returned Just \"\" ."
78
+ pretty (InvalidExecTargets targets) =
79
+ " [S-7371]"
80
+ <> line
81
+ <> fillSep
82
+ [ flow " The following are invalid"
83
+ , style Shell " --package"
84
+ , " values for"
85
+ , style Shell (flow " stack ghc" ) <> " ,"
86
+ , style Shell (flow " stack runghc" ) <> " ,"
87
+ , " or"
88
+ , style Shell (flow " stack runhaskell" ) <> " :"
89
+ ]
90
+ <> line
91
+ <> bulletedList (map (style Target . string . T. unpack) targets )
75
92
76
93
instance Exception ExecPrettyException
77
94
@@ -99,12 +116,17 @@ data ExecOpts = ExecOpts
99
116
}
100
117
deriving Show
101
118
119
+ -- Type representing valid targets for --package option.
120
+ data ExecTarget = ExecTarget PackageName (Maybe Version )
121
+
102
122
-- | The function underlying Stack's @exec@, @ghc@, @run@, @runghc@ and
103
123
-- @runhaskell@ commands. Execute a command.
104
124
execCmd :: ExecOpts -> RIO Runner ()
105
125
execCmd opts =
106
126
withConfig YesReexec $ withEnvConfig AllowNoTargets boptsCLI $ do
107
- unless (null targets) $ build Nothing
127
+ let (errs, execTargets) = partitionEithers $ map fromTarget targets
128
+ unless (null errs) $ prettyThrowM $ InvalidExecTargets errs
129
+ unless (null execTargets) $ build Nothing
108
130
109
131
config <- view configL
110
132
menv <- liftIO $ config. processContextSettings eo. envSettings
@@ -116,18 +138,32 @@ execCmd opts =
116
138
(cmd, args) <- case (opts. cmd, argsWithRts opts. args) of
117
139
(ExecCmd cmd, args) -> pure (cmd, args)
118
140
(ExecRun , args) -> getRunCmd args
119
- (ExecGhc , args) -> getGhcCmd eo . packages args
120
- (ExecRunGhc , args) -> getRunGhcCmd eo . packages args
141
+ (ExecGhc , args) -> getGhcCmd execTargets args
142
+ (ExecRunGhc , args) -> getRunGhcCmd execTargets args
121
143
122
144
runWithPath eo. cwd $ exec cmd args
123
145
where
124
146
eo = opts. extra
125
147
126
- targets = concatMap words eo. packages
127
- boptsCLI = defaultBuildOptsCLI { targetsCLI = map T. pack targets }
148
+ targets = concatMap (T. words . T. pack) eo. packages
149
+ boptsCLI = defaultBuildOptsCLI { targetsCLI = targets }
150
+
151
+ fromTarget :: Text -> Either Text ExecTarget
152
+ fromTarget target =
153
+ case parseRawTarget target >>= toExecTarget of
154
+ Nothing -> Left target
155
+ Just execTarget -> Right execTarget
156
+
157
+ toExecTarget :: RawTarget -> Maybe ExecTarget
158
+ toExecTarget (RTPackageComponent _ _) = Nothing
159
+ toExecTarget (RTComponent _) = Nothing
160
+ toExecTarget (RTPackage name) = Just $ ExecTarget name Nothing
161
+ toExecTarget (RTPackageIdentifier (PackageIdentifier name pkgId)) =
162
+ Just $ ExecTarget name (Just pkgId)
128
163
129
164
-- return the package-id of the first package in GHC_PACKAGE_PATH
130
- getPkgId name = do
165
+ getPkgId (ExecTarget pkgName _) = do
166
+ let name = unPackageName pkgName
131
167
pkg <- getGhcPkgExe
132
168
mId <- findGhcPkgField pkg [] name " id"
133
169
case mId of
0 commit comments