packages feed

hackager-1.0.1: src/BuildManager.hs

-- | Handle building a set of packages (usually all of Hackage)
module BuildManager (
        getPackages,
        tryBuildingPackages
    ) where

import Control.Concurrent
import Control.Monad
import Control.Monad.State

import Build
import BuildTools
import HackageMonad
import Utils

-- | Get a list of all packages on hackage.
getPackages :: Hkg [PkgName]
getPackages = do
    info "===> Grabbing a list of all packages on hackage..."
    m <- runCabalResults False ["list", "--simple-output", "-v0"]
    -- m: abc 0.0.1
    --    abc 0.0.2
    --    dff 0.1.2
    --    ...
    case m of
        Left (_, out) -> die $ "Failed to get package list: " ++ concat out
        Right xs ->
            let ls = map (takeWhile (' ' /=)) $ xs
                ps = uniq $ filter (not . null) ls
            in return ps

-- | Loop over given packages and try to build each of them, recording the
-- results.
tryBuildingPackages :: [PkgName] -> Hkg ()
tryBuildingPackages ps = do
    let n = length ps
    info $ "===> Testing against " ++ show n ++ " packages..."
    runOnAllPkgs ps statPkg
    dumpStats n
    psAll    <- getInstallablePackages
    runOnAllPkgs psAll buildPkg
    dumpResults
    rmTempDir
    info $ "===> Hackager finished! (" ++ show n ++ " packages tested)"

-- | Run in parallel a PkgProcessor function over the given list
-- of packages with the specified number of threads.
runOnAllPkgs :: [PkgName] -> PkgProcessor -> Hkg ()
runOnAllPkgs pkgs pkgFun = do
    nthreads <- getThreads
    mpkgs <- liftIO . newMVar $ zip [1..] pkgs
    let runner = builder pkgFun (length pkgs) mpkgs
    children <- replicateM nthreads $ forkChild runner
    waitForChildren children
    info ""
    info ""

-- | Function to go through a package list and build them. Thread safe so can
-- be forked as child processes.
builder :: PkgProcessor -> Int -> MVar [(Int, PkgName)] -> Hkg ()
builder pkgFun n mpkgs = go
  where
    go = do
        pkgs <- liftIO $ takeMVar mpkgs
        case pkgs of
            []            -> liftIO (putMVar mpkgs []) >> return ()
            ((i, p) : ps) -> do
                liftIO $ putMVar mpkgs ps
                pkgFun n i p
                go