@@ -15,13 +15,14 @@ import qualified Data.List as L
1515import qualified Data.Map.Strict as Map
1616import qualified Data.Set as Set
1717import qualified Data.Text as T
18+ import Distribution.Types.PackageName ( unPackageName )
1819import RIO.NonEmpty ( head , nonEmpty )
1920import RIO.Process ( exec )
2021import Stack.Build ( build )
21- import Stack.Build.Target ( NeedTargets (.. ) )
22+ import Stack.Build.Target
23+ ( NeedTargets (.. ), RawTarget (.. ), parseRawTarget )
2224import Stack.GhcPkg ( findGhcPkgField )
2325import Stack.Setup ( withNewLocalBuildTargets )
24- import Stack.Types.NamedComponent ( NamedComponent (.. ), isCExe )
2526import Stack.Prelude
2627import Stack.Runners ( ShouldReexec (.. ), withConfig , withEnvConfig )
2728import Stack.Types.BuildConfig
@@ -33,6 +34,7 @@ import Stack.Types.CompilerPaths
3334import Stack.Types.Config ( Config (.. ), HasConfig (.. ) )
3435import Stack.Types.EnvConfig ( EnvConfig )
3536import Stack.Types.EnvSettings ( EnvSettings (.. ) )
37+ import Stack.Types.NamedComponent ( NamedComponent (.. ), isCExe )
3638import Stack.Types.Runner ( Runner )
3739import Stack.Types.SourceMap ( SMWanted (.. ), ppComponents )
3840import System.Directory ( withCurrentDirectory )
@@ -58,6 +60,7 @@ data ExecPrettyException
5860 = PackageIdNotFoundBug ! String
5961 | ExecutableToRunNotFound
6062 | NoPackageIdReportedBug
63+ | InvalidExecTargets ! [Text ]
6164 deriving (Show , Typeable )
6265
6366instance Pretty ExecPrettyException where
@@ -72,6 +75,20 @@ instance Pretty ExecPrettyException where
7275 <> flow " No executables found."
7376 pretty NoPackageIdReportedBug = bugPrettyReport " S-8600" $
7477 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 )
7592
7693instance Exception ExecPrettyException
7794
@@ -99,12 +116,17 @@ data ExecOpts = ExecOpts
99116 }
100117 deriving Show
101118
119+ -- Type representing valid targets for --package option.
120+ data ExecTarget = ExecTarget PackageName (Maybe Version )
121+
102122-- | The function underlying Stack's @exec@, @ghc@, @run@, @runghc@ and
103123-- @runhaskell@ commands. Execute a command.
104124execCmd :: ExecOpts -> RIO Runner ()
105125execCmd opts =
106126 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
108130
109131 config <- view configL
110132 menv <- liftIO $ config. processContextSettings eo. envSettings
@@ -116,18 +138,32 @@ execCmd opts =
116138 (cmd, args) <- case (opts. cmd, argsWithRts opts. args) of
117139 (ExecCmd cmd, args) -> pure (cmd, args)
118140 (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
121143
122144 runWithPath eo. cwd $ exec cmd args
123145 where
124146 eo = opts. extra
125147
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)
128163
129164 -- 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
131167 pkg <- getGhcPkgExe
132168 mId <- findGhcPkgField pkg [] name " id"
133169 case mId of
0 commit comments