<commit_before>{-# Language StandaloneDeriving, PatternGuards, CPP #-}

module CabalBounds.Main
   ( cabalBounds
   ) where

import Distribution.PackageDescription (GenericPackageDescription)
import Distribution.PackageDescription.Parse (parsePackageDescription, ParseResult(..))
import Distribution.PackageDescription.PrettyPrint (showGenericPackageDescription)
import Distribution.Simple.Configure (tryGetConfigStateFile)

#if MIN_VERSION_Cabal(1,22,0) == 0
import Distribution.Simple.Configure (ConfigStateFileErrorType(..))
#endif

import Distribution.Simple.LocalBuildInfo (LocalBuildInfo)
import qualified Distribution.Simple.LocalBuildInfo as BI
import qualified Distribution.Package as P
import qualified Distribution.Simple.PackageIndex as PX
import qualified Distribution.InstalledPackageInfo as PI
import qualified Distribution.Version as V
import qualified CabalBounds.Args as A
import qualified CabalBounds.Bound as B
import qualified CabalBounds.Sections as S
import qualified CabalBounds.Dependencies as DP
import qualified CabalBounds.Drop as D
import qualified CabalBounds.Update as U
import qualified CabalBounds.Dump as D
import qualified CabalBounds.HaskellPlatform as HP
import qualified CabalLenses as CL
import qualified System.IO.Strict as SIO
import Control.Applicative ((<$>))
import Control.Monad.Trans.Either (EitherT, runEitherT, bimapEitherT, hoistEither, left, right)
import Control.Monad.IO.Class
import Control.Lens
import qualified Data.HashMap.Strict as HM
import Data.List (foldl', sortBy)
import Data.Function (on)
import Data.Char (toLower)

type Error = String

cabalBounds :: A.Args -> IO (Maybe Error)
cabalBounds args@A.Drop {} =
   leftToJust <$> runEitherT (do
      pkgDescrp <- packageDescription $ A.cabalFile args
      let pkgDescrp' = D.drop (B.boundOfDrop args) (S.sections args pkgDescrp) (DP.dependencies args) pkgDescrp
      liftIO $ writeFile (A.outputFile args) (showGenericPackageDescription . clearTargetBuildDepends $ pkgDescrp'))

cabalBounds args@A.Update {} =
   leftToJust <$> runEitherT (do
      pkgDescrp <- packageDescription $ A.cabalFile args
      libs      <- libraries (A.haskellPlatform args) (A.fromFile args) setupConfigFile
      let pkgDescrp' = U.update (B.boundOfUpdate args) (S.sections args pkgDescrp) (DP.dependencies args) libs pkgDescrp
      liftIO $ writeFile (A.outputFile args) (showGenericPackageDescription . clearTargetBuildDepends $ pkgDescrp'))
   where
      setupConfigFile
         | (file:_) <- A.setupConfigFile args
         = file

         | otherwise
         = ""

cabalBounds args@A.Dump {} =
   leftToJust <$> runEitherT (do
      pkgDescrps <- packageDescriptions $ A.cabalFiles args
      let libs = sortBy (compare `on` (map toLower . fst)) $ D.dump pkgDescrps
      if (not . null . A.outputFile $ args)
         then liftIO $ writeFile (A.outputFile args) (prettyPrint libs)
         else liftIO $ putStrLn (prettyPrint libs))
   where
      prettyPrint []     = "[]"
      prettyPrint (l:ls) =
         "[ " ++ show l ++ "\n" ++ foldl' (\str l -> str ++ ", " ++ show l ++ "\n") "" ls ++ "]";


packageDescription :: FilePath -> EitherT Error IO GenericPackageDescription
packageDescription file = do
   contents <- liftIO $ SIO.readFile file
   case parsePackageDescription contents of
        ParseFailed error   -> left $ show error
        ParseOk _ pkgDescrp -> right pkgDescrp


-- | clear the 'targetBuildDepends' field of all 'BuildInfo'
clearTargetBuildDepends :: GenericPackageDescription -> GenericPackageDescription
clearTargetBuildDepends pkgDescrp =
   pkgDescrp & CL.allBuildInfo . CL.targetBuildDependsL .~ []


packageDescriptions :: [FilePath] -> EitherT Error IO [GenericPackageDescription]
packageDescriptions []    = left "Missing cabal file"
packageDescriptions files = mapM packageDescription files


type SetupConfigFile = String
type LibraryFile     = String

libraries :: HP.HPVersion -> LibraryFile -> SetupConfigFile -> EitherT Error IO U.Libraries
libraries "" "" ""                   = left "Missing library file, haskell platform version and setup config file"
libraries hpVersion libFile confFile = do
   hpLibs       <- haskellPlatformLibraries hpVersion
   libsFromFile <- librariesFromFile libFile
   instLibs     <- installedLibraries confFile
   right $ HM.union (HM.union hpLibs libsFromFile) instLibs


librariesFromFile :: LibraryFile -> EitherT Error IO U.Libraries
librariesFromFile ""      = right HM.empty
librariesFromFile libFile = do
   contents <- liftIO $ SIO.readFile libFile
   libsFrom contents
   where<commit_msg>Remove clearing of 'targetBuildDepends' field<commit_after>{-# Language StandaloneDeriving, PatternGuards, CPP #-}

module CabalBounds.Main
   ( cabalBounds
   ) where

import Distribution.PackageDescription (GenericPackageDescription)
import Distribution.PackageDescription.Parse (parsePackageDescription, ParseResult(..))
import Distribution.PackageDescription.PrettyPrint (showGenericPackageDescription)
import Distribution.Simple.Configure (tryGetConfigStateFile)

#if MIN_VERSION_Cabal(1,22,0) == 0
import Distribution.Simple.Configure (ConfigStateFileErrorType(..))
#endif

import Distribution.Simple.LocalBuildInfo (LocalBuildInfo)
import qualified Distribution.Simple.LocalBuildInfo as BI
import qualified Distribution.Package as P
import qualified Distribution.Simple.PackageIndex as PX
import qualified Distribution.InstalledPackageInfo as PI
import qualified Distribution.Version as V
import qualified CabalBounds.Args as A
import qualified CabalBounds.Bound as B
import qualified CabalBounds.Sections as S
import qualified CabalBounds.Dependencies as DP
import qualified CabalBounds.Drop as D
import qualified CabalBounds.Update as U
import qualified CabalBounds.Dump as D
import qualified CabalBounds.HaskellPlatform as HP
import qualified CabalLenses as CL
import qualified System.IO.Strict as SIO
import Control.Applicative ((<$>))
import Control.Monad.Trans.Either (EitherT, runEitherT, bimapEitherT, hoistEither, left, right)
import Control.Monad.IO.Class
import Control.Lens
import qualified Data.HashMap.Strict as HM
import Data.List (foldl', sortBy)
import Data.Function (on)
import Data.Char (toLower)

type Error = String

cabalBounds :: A.Args -> IO (Maybe Error)
cabalBounds args@A.Drop {} =
   leftToJust <$> runEitherT (do
      pkgDescrp <- packageDescription $ A.cabalFile args
      let pkgDescrp' = D.drop (B.boundOfDrop args) (S.sections args pkgDescrp) (DP.dependencies args) pkgDescrp
      liftIO $ writeFile (A.outputFile args) (showGenericPackageDescription pkgDescrp'))

cabalBounds args@A.Update {} =
   leftToJust <$> runEitherT (do
      pkgDescrp <- packageDescription $ A.cabalFile args
      libs      <- libraries (A.haskellPlatform args) (A.fromFile args) setupConfigFile
      let pkgDescrp' = U.update (B.boundOfUpdate args) (S.sections args pkgDescrp) (DP.dependencies args) libs pkgDescrp
      liftIO $ writeFile (A.outputFile args) (showGenericPackageDescription pkgDescrp'))
   where
      setupConfigFile
         | (file:_) <- A.setupConfigFile args
         = file

         | otherwise
         = ""

cabalBounds args@A.Dump {} =
   leftToJust <$> runEitherT (do
      pkgDescrps <- packageDescriptions $ A.cabalFiles args
      let libs = sortBy (compare `on` (map toLower . fst)) $ D.dump pkgDescrps
      if (not . null . A.outputFile $ args)
         then liftIO $ writeFile (A.outputFile args) (prettyPrint libs)
         else liftIO $ putStrLn (prettyPrint libs))
   where
      prettyPrint []     = "[]"
      prettyPrint (l:ls) =
         "[ " ++ show l ++ "\n" ++ foldl' (\str l -> str ++ ", " ++ show l ++ "\n") "" ls ++ "]";


packageDescription :: FilePath -> EitherT Error IO GenericPackageDescription
packageDescription file = do
   contents <- liftIO $ SIO.readFile file
   case parsePackageDescription contents of
        ParseFailed error   -> left $ show error
        ParseOk _ pkgDescrp -> right pkgDescrp


packageDescriptions :: [FilePath] -> EitherT Error IO [GenericPackageDescription]
packageDescriptions []    = left "Missing cabal file"
packageDescriptions files = mapM packageDescription files


type SetupConfigFile = String
type LibraryFile     = String

libraries :: HP.HPVersion -> LibraryFile -> SetupConfigFile -> EitherT Error IO U.Libraries
libraries "" "" ""                   = left "Missing library file, haskell platform version and setup config file"
libraries hpVersion libFile confFile = do
   hpLibs       <- haskellPlatformLibraries hpVersion
   libsFromFile <- librariesFromFile libFile
   instLibs     <- installedLibraries confFile
   right $ HM.union (HM.union hpLibs libsFromFile) instLibs


librariesFromFile :: LibraryFile -> EitherT Error IO U.Libraries
librariesFromFile ""      = right HM.empty
librariesFromFile libFile = do
   contents <- liftIO $ SIO.readFile libFile
   libsFrom contents
   where
{'fraction_non_alphanumeric': 0.08482393970075373, 'fraction_numerical': 0.001124985937675779, 'mean_word_length': 4.123919308357348, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 6, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '885921', 'n_tokens_mistral': 2622, 'n_tokens_neox': 2500, 'n_words': 758}