git.iko.soy/typeable/cabal2nix
on bc9bdb2 help sign in
91 lines 3.5 kB history raw
1{-# LANGUAGE RecordWildCards #-}
3module Cabal2Nix.Normalize ( normalize, normalizeList, normalizeSet, normalizeCabalFlags ) where
5import Cabal2Nix.CorePackages
6import Cabal2Nix.Name
7import Data.Char
8import Data.Set ( Set )
9import qualified Data.Set as Set
10import Data.Function
11import Data.List
12import Distribution.Nixpkgs.Haskell
13import Distribution.Nixpkgs.Util.Regex ( regsubmatch )
14import Distribution.PackageDescription ( FlagAssignment, FlagName(..) )
15import Distribution.Simple.Utils ( lowercase )
17normalize :: Derivation -> Derivation
18normalize deriv@(MkDerivation {..}) = deriv
19 { buildDepends = normalizeNixNames (Set.delete pname buildDepends)
20 , testDepends = normalizeNixNames (Set.delete pname testDepends)
21 , buildTools = normalizeNixBuildTools (Set.filter (`notElem` coreBuildTools) buildTools)
22 , extraLibs = normalizeNixLibs extraLibs
23 , pkgConfDeps = normalizeNixLibs pkgConfDeps
24 , configureFlags = normalizeSet configureFlags
25 , cabalFlags = normalizeCabalFlags cabalFlags
26 , metaSection = normalizeMeta metaSection
27 }
29normalizeMeta :: Meta -> Meta
30normalizeMeta meta@(Meta {..}) = meta
31 { description = normalizeDescription description
32 , maintainers = normalizeMaintainers maintainers
33 , platforms = normalizePlatforms platforms
34 }
36normalizeDescription :: String -> String
37normalizeDescription desc
38 | null desc = []
39 | last desc == '.' && length (filter ('.'==) desc) == 1 = normalizeDescription (init desc)
40 | otherwise = quote (unwords (words desc))
42quote :: String -> String
43quote ('\\':c:cs) = '\\' : c : quote cs
44quote ('"':cs) = '\\' : '"' : quote cs
45quote (c:cs) = c : quote cs
46quote [] = []
48normalizeList :: [String] -> [String]
49normalizeList = nub . sortBy (compare `on` map toLower) . filter (not . null)
51normalizeSet :: Set String -> Set String
52normalizeSet = Set.filter (not . null)
54normalizeNixNames :: Set String -> Set String
55normalizeNixNames = normalizeSet . Set.map toNixName
57normalizeNixLibs :: Set String -> Set String
58normalizeNixLibs = normalizeSet . Set.fromList . concatMap libNixName . Set.toList
60normalizeNixBuildTools :: Set String -> Set String
61normalizeNixBuildTools = normalizeSet . Set.fromList . concatMap buildToolNixName . Set.toList
63-- |Strip any kind of path prefix from maintainer names, filter duplicates, and
64-- sort the resulting list alphabetically.
65--
66-- >>> normalizeMaintainers $ Set.fromList ["self.stdenv.lib.maintainers.foobar", "foobar"]
67-- fromList ["foobar"]
68--
69-- >>> normalizeMaintainers $ Set.fromList ["any.prefix.is.recognized.yo", "abc.def"]
70-- fromList ["def","yo"]
72normalizeMaintainers :: Set String -> Set String
73normalizeMaintainers = normalizeSet . Set.map
74 (\m -> (m `regsubmatch` "^([^.].*\\.)?([^.]+)$") !! 1)
76normalizePlatforms :: Set String -> Set String
77normalizePlatforms = normalizeSet . Set.map
78 (\p -> if '.' `elem` p then p else "stdenv.lib.platforms." ++ p)
81-- |When a flag is specified multiple times, the first occurrence
82-- counts. This is counter-intuitive, IMHO, but it's how cabal does it.
83-- Flag names are spelled in all lowercase.
84--
85-- >>> normalizeCabalFlags [(FlagName "foo", True), (FlagName "FOO", True), (FlagName "Foo", False)]
86-- [(FlagName "foo",True)]
88normalizeCabalFlags :: FlagAssignment -> FlagAssignment
89normalizeCabalFlags flags' = nubBy ((==) `on` fst) (sortBy (compare `on` fst) flags)
90 where
91 flags = [ (FlagName (lowercase n), b) | (FlagName n, b) <- flags' ]