Skip to content

Commit

Permalink
Refactor the executable
Browse files Browse the repository at this point in the history
  • Loading branch information
Bodigrim committed Aug 27, 2024
1 parent 05067d7 commit 2112309
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 23 deletions.
52 changes: 29 additions & 23 deletions app/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module Main (main) where
import Cabal.Project (parseProject, prjPackages, resolveProject)
import Control.Exception (throwIO)
import Control.Monad (filterM)
import Data.Bifunctor (bimap)
import Data.ByteString (ByteString)
import Data.ByteString.Char8 qualified as B
import Data.Either (partitionEithers)
Expand All @@ -20,15 +21,13 @@ import Data.List.NonEmpty (NonEmpty (..))
import Data.Maybe (catMaybes, isJust)
import Distribution.CabalSpecVersion (CabalSpecVersion)
import Distribution.Client.Add
import Distribution.Fields (Field)
import Distribution.PackageDescription (
ComponentName,
GenericPackageDescription,
packageDescription,
specVersion,
)
import Distribution.PackageDescription.Quirks (patchQuirks)
import Distribution.Parsec (Position)
import Options.Applicative (
Parser,
execParser,
Expand Down Expand Up @@ -128,23 +127,27 @@ stripAdd :: [String] -> [String]
stripAdd ("add" : xs) = xs
stripAdd xs = xs

type Input =
( FilePath
, ByteString
, [Field Position]
, GenericPackageDescription
, Either
CommonStanza
ComponentName
, NonEmpty ByteString
)
data Input = Input
{ inpFilePath :: FilePath
, inpPackageDescription :: GenericPackageDescription
, inpConfig :: Config
}
deriving (Show)

mkInputs
:: Bool
-- ^ Must the first argument be a component name?
-- As opposed to interpreting it as one of dependencies to add.
-> FilePath
-- ^ Cabal file name, primarily for error reporting.
-- Note that 'mkInputs' does not do any 'IO'.
-> ByteString
-- ^ Cabal file content.
-> NonEmpty String
-- ^ List of arguments. The first one is either a component name
-- or a dependency (see 'Bool' flag above), the rest are dependencies.
-> Either String Input
-- ^ Either an error or a tuple of input data.
mkInputs isCmpRequired cabalFile origContents args = do
(fields, packDescr) <- parseCabalFile cabalFile origContents
let specVer :: CabalSpecVersion
Expand All @@ -161,25 +164,26 @@ mkInputs isCmpRequired cabalFile origContents args = do
if isCmpRequired
then Left "Component is required"
else (,) <$> mkCmp Nothing <*> mkDeps args
pure (cabalFile, origContents, fields, packDescr, cmp, deps)
pure $ Input cabalFile packDescr (Config origContents fields cmp deps)

disambiguateInputs
:: Maybe FilePath
-> [FilePath]
-> [Either a Input]
-> [(FilePath, Either String Input)]
-> Either String Input
disambiguateInputs mProjectFile cabalFiles inputs = case partitionEithers inputs of
disambiguateInputs mProjectFile inputs = case inputs' of
([], []) -> Left $ case mProjectFile of
Nothing -> "No Cabal files or projects are found in the current folder, please specify --project-file."
Just projFn -> "No Cabal files are found in " ++ projFn
(_errs, []) ->
(errs, []) ->
Left $
"No matching targets found amongst: "
++ L.intercalate ", " cabalFiles
(_, [inp]) -> pure inp
++ L.intercalate ", " (map fst errs)
(_, [inp]) -> pure $ snd inp
(_, _inps) ->
Left
"Target component is ambiguous, please specify it as package:type:component. See https://cabal.readthedocs.io/en/latest/cabal-commands.html#target-forms for reference"
where
inputs' = partitionEithers $ map (\(fn, e) -> bimap (fn,) (fn,) e) inputs

main :: IO ()
main = do
Expand All @@ -197,14 +201,16 @@ main = do
catMaybes
<$> traverse (\fn -> fmap (fn,) <$> readCabalFile fn) cabalFiles
let getInput isCmpRequired =
disambiguateInputs rcnfMProjectFile (fmap fst cabalFilesAndContent) $
map (\(fn, cnt) -> mkInputs isCmpRequired fn cnt rcnfArgs) cabalFilesAndContent
disambiguateInputs rcnfMProjectFile $
map
(\(fn, cnt) -> (fn, mkInputs isCmpRequired fn cnt rcnfArgs))
cabalFilesAndContent

input <- either (const $ either die pure $ getInput True) pure (getInput False)

let (cabalFile, cnfOrigContents, cnfFields, origPackDescr, cnfComponent, cnfDependencies) = input
let Input cabalFile origPackDescr cnf = input

case executeConfig (validateChanges origPackDescr) (Config {..}) of
case executeConfig (validateChanges origPackDescr) cnf of
Nothing ->
die $
"Cannot extend build-depends in "
Expand Down
5 changes: 5 additions & 0 deletions src/Distribution/Client/Add.hs
Original file line number Diff line number Diff line change
Expand Up @@ -291,14 +291,19 @@ resolveComponent
"Target component is ambiguous.\n"
++ knownTargetsHint
where
allTargets :: Set String
allTargets =
S.fromList (mapMaybe (fmap unUnqualComponentName . componentNameString) (S.toList componentNames))
<> S.map (B.unpack . unCommonStanza) commonStanzas
<> specialComponents componentNames

knownTargetsHint :: String
knownTargetsHint =
"Specify one with -c: "
++ L.intercalate ", " (S.toList allTargets)
++ "."

resolution :: Resolution (Either CommonStanza ComponentName)
resolution =
fmap Right (resolveToComponentName componentNames component)
<> fmap Left (resolveToCommonStanza commonStanzas component)
Expand Down

0 comments on commit 2112309

Please sign in to comment.