packages feed

ghcup-0.2.6.0: lib/GHCup/Input/SymlinkSpec.hs

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}

module GHCup.Input.SymlinkSpec where

import GHCup.Errors
import GHCup.Input.Parsers.Domain
import GHCup.Prelude.Logger
import GHCup.Query.GHCupDirs
import GHCup.Types
import GHCup.Types.Optics

import Control.Monad                ( forM )
import Control.Monad.IO.Class       ( liftIO )
import Control.Monad.Reader         ( MonadReader )
import Data.Variant.Excepts         ( Excepts, throwE )
import Data.Versions                ( Version, prettyVer )
import System.FilePath              ( takeFileName )
import System.FilePattern.Directory ( getDirectoryFilesIgnore )

import qualified Data.Map.Strict as M
import qualified Data.Text       as T
import qualified Text.Megaparsec as MP


parseSymlinkSpec ::
    Monad m
  => Version
  -> SymlinkSpec String
  -> Excepts
       '[ParseError]
       m
       (SymlinkSpec [Either Char Version])
parseSymlinkSpec ver SymlinkSpec{..} = do
  target <- either (throwE . ParseError . show) pure $ parseDomain _slTarget
  linkName <- either (throwE . ParseError . show) pure $ parseDomain _slLinkName
  setName <- forM _slSetName $ either (throwE . ParseError . show) pure . parseDomain
  pure $ SymlinkSpec target linkName _slPVPMajorLinks setName
 where
   parseDomain = MP.parse (domainParserVer env) "parseSymlinkSpec"
   env = M.fromList [(PKGVER, T.unpack $ prettyVer ver)
                    ]


substituteSpec :: SymlinkSpec [Either Char Version] -> SymlinkFileSpec
substituteSpec SymlinkSpec{..} =
  let target = mconcat $ either (:[]) (T.unpack . prettyVer) <$> _slTarget
      linkName = mconcat $ either (:[]) (T.unpack . prettyVer) <$> _slLinkName
      setName = mconcat . fmap (either (:[]) (T.unpack . prettyVer)) <$> _slSetName
  in SymlinkSpec target linkName _slPVPMajorLinks setName


resolveSymlinkSpec  ::
     ( MonadReader env m
     , HasLog env
     , MonadIOish m
     )
  => GHCupPath
  -> SymlinkInputSpec
  -> Excepts
       '[ParseError]
       m
       [SymlinkSpec String]
resolveSymlinkSpec _ SymlinkInputSpec{..} = pure [SymlinkSpec{..}]
resolveSymlinkSpec (fromGHCupPath -> workDir) SymlinkPatternSpec{..} = do
  binaries <- liftIO $ getDirectoryFilesIgnore workDir _slTargetPattern _slTargetPatternIgnore
  logDebug2 $ "Resolved binaries found in " <> T.pack workDir <> ": " <> T.pack (show binaries)
  forM binaries $ \binary -> do
    let _slTarget = binary
    _slLinkName <- parseDomain (takeFileName binary) _slLinkName
    logDebug2 $ "Parsed slLinkName: " <> T.pack _slLinkName
    _slSetName <- forM _slSetName $ parseDomain (takeFileName binary)
    logDebug2 $ "Parsed slSetName: " <> T.pack (show _slSetName)
    pure SymlinkSpec{..}
 where
   parseDomain targetFn = throwOnParseError . MP.parse (domainParser' env [PKGVER]) "resolveSymlinkSpec"
    where
     env = M.fromList [(TARGETFN, targetFn)
                      ]