packageRules :: Rules ()
packageRules = do
    packageSourceDir PackageWildCard %/> \srcDir -> do
        let pkg = extractPackage srcDir
        let destDir = takeDirectory srcDir
        let providedDir = sourceForPackageDir pkg
        provided <- doesDirectoryExist providedDir
        if provided
            then command_ [] "cp" ["-pR", providedDir, srcDir]
            else do
                command_ [Cwd destDir] "cabal" ["unpack", show pkg]
                command_ [Cwd destDir] "mv" [show pkg, "source"]

    packageDepsFile PackageWildCard %> \depFile -> do
        hpRel <- askHpRelease
        bc <- askBuildConfig
        installAction depFile (bcIncludeExtra bc) hpRel

    listBuild %> \out -> do
        hpRel <- askHpRelease
        bc <- askBuildConfig
        let pkgs = platformPackages (bcIncludeExtra bc) hpRel
        need $ map packageDepsFile pkgs
        nodes <- mapM buildNode pkgs
        writeFileLinesChanged out $ flattenSCCs $ stronglyConnComp nodes
  where
    buildNode p = do
        ns <- map (pkgName . read) <$> (readFileLines $ packageDepsFile p)
        return (show p, Down $ pkgName p, map Down ns)
            -- Having the package names reverse sort as graph keys makes the SCC
            -- components come out closer to normal sort order. Go figure!

--TODO choose proper "allPackages" based on minimal or full build
packageRules :: Rules ()
packageRules = do
    packageSourceDir PackageWildCard %/> \srcDir -> do
        let pkg = extractPackage srcDir
        let destDir = takeDirectory srcDir
        let providedDir = sourceForPackageDir pkg
        provided <- doesDirectoryExist providedDir
        if provided
            then command_ [] "cp" ["-pR", providedDir, srcDir]
            else do
                command_ [Cwd destDir] "cabal" ["unpack", show pkg]
                command_ [Cwd destDir] "mv" [show pkg, "source"]

    packageDepsFile PackageWildCard %> \depFile -> do
        hpRel <- askHpRelease
        bc <- askBuildConfig
        installAction depFile (bcIncludeExtra bc) hpRel

    listBuild %> \out -> do
        hpRel <- askHpRelease
        bc <- askBuildConfig
        let pkgs = platformPackages (bcIncludeExtra bc) hpRel
        need $ map packageDepsFile pkgs
        nodes <- mapM buildNode pkgs
        writeFileLinesChanged out $ flattenSCCs $ stronglyConnComp nodes
  where
    buildNode p = do
        ns <- map (pkgName . read) <$> (readFileLines $ packageDepsFile p)
        return (show p, Down $ pkgName p, map Down ns)
            -- Having the package names reverse sort as graph keys makes the SCC
            -- components come out closer to normal sort order. Go figure!

--TODO choose proper "allPackages" based on minimal or full build
packageRules = do
    packageSourceDir PackageWildCard %/> \srcDir -> do
        let pkg = extractPackage srcDir
        let destDir = takeDirectory srcDir
        let providedDir = sourceForPackageDir pkg
        provided <- doesDirectoryExist providedDir
        if provided
            then command_ [] "cp" ["-pR", providedDir, srcDir]
            else do
                command_ [Cwd destDir] "cabal" ["unpack", show pkg]
                command_ [Cwd destDir] "mv" [show pkg, "source"]

    packageDepsFile PackageWildCard %> \depFile -> do
        hpRel <- askHpRelease
        bc <- askBuildConfig
        installAction depFile (bcIncludeExtra bc) hpRel

    listBuild %> \out -> do
        hpRel <- askHpRelease
        bc <- askBuildConfig
        let pkgs = platformPackages (bcIncludeExtra bc) hpRel
        need $ map packageDepsFile pkgs
        nodes <- mapM buildNode pkgs
        writeFileLinesChanged out $ flattenSCCs $ stronglyConnComp nodes
  where
    buildNode p = do
        ns <- map (pkgName . read) <$> (readFileLines $ packageDepsFile p)
        return (show p, Down $ pkgName p, map Down ns)
            -- Having the package names reverse sort as graph keys makes the SCC
            -- components come out closer to normal sort order. Go figure!

--TODO choose proper "allPackages" based on minimal or full build