cblrepo-0.11: src/Add.hs
{-
- Copyright 2011-2014 Per Magnus Therning
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-}
module Add where
-- {{{1 imports
-- {{{2 local
import PkgDB
import Util.Misc
-- {{{2 system
import Control.Monad.Error
import Data.List
import Data.Maybe
import Distribution.PackageDescription
import Distribution.Text
import Distribution.Version
import qualified Distribution.Package as P
-- {{{1 types
data PkgType
= GhcType String Version
| DistroType String Version String
| RepoType GenericPackageDescription
deriving (Eq, Show)
-- {{{1 add
add :: Command ()
add = do
dbFn <- cfgGet dbFile
db <- liftIO $ readDb dbFn
pd <- cfgGet $ patchDir . optsCmd
dr <- cfgGet dryRun
ghcVersion <- cfgGet $ ghcVer . optsCmd
--
ghcPkgs <- cfgGet $ cmdAddGhcPkgs . optsCmd
distroPkgs <- cfgGet $ cmdAddDistroPkgs . optsCmd
genUrlPkgs <- cfgGet (cmdAddUrlCbls . optsCmd) >>= mapM (runErrorT . withTempDirErrT "/tmp/cblrepo." . readCabalFromUrl pd)
genFilePkgs <- cfgGet (cmdAddFileCbls . optsCmd) >>= mapM (runErrorT . withTempDirErrT "/tmp/cblrepo." . readCabalFromFile pd)
genIdxPkgs <- cfgGet (cmdAddCbls . optsCmd) >>= mapM (runErrorT . withTempDirErrT "/tmp/cblrepo." . readCabalFromIdx pd)
pkgs <- exitOnErrors $ argsToPkgType ghcPkgs distroPkgs (genUrlPkgs ++ genFilePkgs ++ genIdxPkgs)
--
let pkgNames = map getName pkgs
let tmpDb = foldl delPkg db pkgNames
case addPkgs ghcVersion tmpDb pkgs of
Left (unsatisfiables, breaksOthers) -> liftIO (mapM_ printUnSat unsatisfiables >> mapM_ printBrksOth breaksOthers)
Right newDb -> liftIO $ unless dr $ saveDb newDb dbFn
argsToPkgType ghcPkgs distroPkgs repoPkgs = let
toGhcType (n, v) = maybe
(Left $ "Not a valid version given for " ++ n ++ " (" ++ v ++ ")")
(Right . GhcType n)
(simpleParse v :: Maybe Version)
toDistroType (n, v, r) = maybe
(Left $ "Not a valid version given for " ++ n ++ " (" ++ v ++ ")")
(\ v' -> Right $ DistroType n v' r)
(simpleParse v :: Maybe Version)
toRepoType = either Left (Right . RepoType)
in map toGhcType ghcPkgs ++ map toDistroType distroPkgs ++ map toRepoType repoPkgs
getName (GhcType n _) = n
getName (DistroType n _ _) = n
getName (RepoType gpd) = (\ (P.PackageName n) -> n) $ P.pkgName $ package $ packageDescription gpd
-- {{{1 addPkgs
addPkgs ghcVer db pkgs = let
(succs, fails) = partition (canBeAdded ghcVer db) pkgs
newDb = foldl addPkg2 db (map (pkgTypeToCblPkg ghcVer db) succs)
unsatisfieds = mapMaybe (finalizeToUnsatisfiableDeps ghcVer db) fails
breaksOthers = mapMaybe (findBreaking db) fails
in case (succs, fails) of
(_, []) -> Right newDb
([], _) -> Left (unsatisfieds, breaksOthers)
(_, _) -> addPkgs ghcVer newDb fails
canBeAdded _ db (GhcType n v) = null $ checkDependants db n v
canBeAdded _ db (DistroType n v _) = null $ checkDependants db n v
canBeAdded ghcVer db (RepoType gpd) = let
finable = either (const False) (const True) (finalizePkg ghcVer db gpd)
n = ((\ (P.PackageName n) -> n ) . P.pkgName . package . packageDescription) gpd
v = P.pkgVersion $ package $ packageDescription gpd
depsOK = null $ checkDependants db n v
in finable && depsOK
pkgTypeToCblPkg _ _ (GhcType n v) = createGhcPkg n v
pkgTypeToCblPkg _ _ (DistroType n v r) = createDistroPkg n v r
pkgTypeToCblPkg ghcVer db (RepoType gpd) = fromJust $ case finalizePkg ghcVer db gpd of
Right (pd, fa) -> Just $ createCblPkg pd fa
Left _ -> Nothing
finalizeToUnsatisfiableDeps ghcVer db (RepoType gpd) = case finalizePkg ghcVer db gpd of
Left ds -> Just (((\ (P.PackageName n) -> n ) . P.pkgName . package . packageDescription) gpd, ds)
_ -> Nothing
finalizeToUnsatisfiableDeps _ _ _ = Nothing
findBreaking db (GhcType n v) = let
d = checkDependants db n v
in if null d
then Nothing
else Just ((n, v), d)
findBreaking db (DistroType n v _) = let
d = checkDependants db n v
in if null d
then Nothing
else Just ((n, v), d)
findBreaking db (RepoType gpd) = let
n = (\ (P.PackageName n) -> n) $ P.pkgName $ package $ packageDescription gpd
v = P.pkgVersion $ package $ packageDescription gpd
d = checkDependants db n v
in if null d
then Nothing
else Just ((n, v), d)