@@ -8,16 +8,23 @@ import System.Directory
88import System.Environment
99import System.Exit
1010import Data.List
11+-- import Distribution.Package
1112import qualified Data.Set as Set
1213import Control.Monad.State
1314import Control.Exception ( bracket )
1415import Text.Regex.Posix
1516import Data.Version
16−import Text.ParserCombinators.ReadP ( readP_to_S )
17+-- import Text.ParserCombinators.ReadP ( readP_to_S, readS_to_P )
1718import Distribution.PackageDescription.Parse ( parsePackageDescription, ParseResult(..) )
1819import Distribution.PackageDescription ( GenericPackageDescription() )
20+import Distribution.Text
1921import System.Console.GetOpt ( OptDescr(..), ArgDescr(..), ArgOrder(..), usageInfo, getOpt )
20−import Cabal2Nix.Package ( cabal2nix, showNixPkg, PkgName, PkgVersion, PkgSHA256, PkgPlatforms, PkgMaintainers, PkgNoHaddock )
22+import Cabal2Nix.Package
23+import Distribution.NixOS.Derivation.Cabal
24+import Distribution.NixOS.Derivation.Meta
25+
26+data Pkg = Pkg Derivation FilePath Bool
27+ deriving (Show, Eq, Ord)
2128
2229type PkgSet = Set.Set Pkg
2330
@@ -70,19 +77,10 @@ discoverNixFiles yield dirOrFile
7077 (True,_) -> return ()
7178 (False,_) -> io (readDirectory dirOrFile) >>= mapM_ (discoverNixFiles yield . (dirOrFile </>))
7279
73−type Regenerate = Bool
74−data Pkg = Pkg PkgName PkgVersion PkgSHA256 PkgNoHaddock PkgPlatforms PkgMaintainers FilePath Regenerate
75− deriving (Show, Eq, Ord)
76−
77−regsubmatch :: String -> String -> [String]
78−regsubmatch buf patt = let (_,_,_,x) = f in x
79− where f :: (String,String,String,[String])
80− f = match (makeRegexOpts compExtended execBlank patt) buf
80+regenerateDerivation :: Derivation -> String -> Bool
81+regenerateDerivation deriv buf = not (display (pname deriv) `elem` patchedPackages) &&
82+ not (buf =~ "preConfigure|configureFlags|postInstall|patchPhase")
8183
82−normalizeMaintainer :: String -> String
83−normalizeMaintainer x
84− | "self.stdenv.lib.maintainers." `isPrefixOf` x = drop 28 x
85− | otherwise = x
8684
8785parseNixFile :: FilePath -> String -> Hackage4Nix (Maybe Pkg)
8886parseNixFile path buf
@@ -92,46 +90,24 @@ parseNixFile path buf
9290 = msgDebug ("ignore known bad package " ++ path) >> return Nothing
9391 | buf =~ "src = (fetchurl|fetchgit|sourceFromHead)"
9492 = msgDebug ("ignore non-hackage package " ++ path) >> return Nothing
95− | [name] <- buf `regsubmatch` "name *= *\"([^\"]+)\""
96− , [vers] <- buf `regsubmatch` "version *= *\"([^\"]+)\""
97− , [sha] <- buf `regsubmatch` "sha256 *= *\"([^\"]+)\""
98− , plats <- buf `regsubmatch` "platforms *= *([^;]+);"
99− , maint <- buf `regsubmatch` "maintainers *= *\\[([^\"]+)]"
100− , haddock <- buf `regsubmatch` "noHaddock *= *(true|false) *;"
101− = let plats' = concatMap words (map (map (\c -> if c == '+' then ' ' else c)) plats)
102− maint' = concatMap words maint
103− noHaddock
104− | "true":[] <- haddock = True
105− | otherwise = False
106− regenerate = not (name `elem` patchedPackages) &&
107− not (buf =~ "preConfigure|configureFlags|postInstall|patchPhase")
108− in
109− return $ Just $ Pkg name vers sha noHaddock plats'
110− (map normalizeMaintainer maint')
111− path regenerate
93+ | Just deriv <- parseDerivation buf
94+ = return (Just (Pkg deriv path (regenerateDerivation deriv buf)))
11295 | otherwise = msgInfo ("failed to parse file " ++ path) >> return Nothing
11396
114−readVersion :: String -> Version
115−readVersion str =
116− case [ v | (v,[]) <- readP_to_S parseVersion str ] of
117− [ v' ] -> v'
118− _ -> error ("invalid version specifier " ++ show str)
119−
12097selectLatestVersions :: PkgSet -> PkgSet
12198selectLatestVersions = Set.fromList . nubBy f2 . sortBy f1 . Set.toList
12299 where
123− f1 (Pkg n1 v1 _ _ _ _ _ _) (Pkg n2 v2 _ _ _ _ _ _)
124− | n1 == n2 = compare v2 v1
125− | otherwise = compare n1 n2
126− f2 (Pkg n1 _ _ _ _ _ _ _) (Pkg n2 _ _ _ _ _ _ _)
127− = n1 == n2
100+ f1 (Pkg deriv1 _ _) (Pkg deriv2 _ _)
101+ | pname deriv1 == pname deriv2 = compare (version deriv2) (version deriv1)
102+ | otherwise = compare (pname deriv1) (pname deriv2)
103+ f2 (Pkg deriv1 _ _) (Pkg deriv2 _ _) = pname deriv1 == pname deriv2
128104
129−discoverUpdates :: PkgName -> PkgVersion -> Hackage4Nix [PkgVersion]
105+discoverUpdates :: String -> String -> Hackage4Nix [String]
130106discoverUpdates name vers = do
131107 hackage <- gets _hackageDb
132108 versionStrings <- io $ readDirectory (hackage </> name)
133109 let versions = map readVersion versionStrings
134− return (sort [ showVersion v | v <- versions, v > readVersion vers ])
110+ return [ showVersion v | v <- versions, v > readVersion vers ]
135111
136112updateNixPkgs :: [FilePath] -> Hackage4Nix ()
137113updateNixPkgs paths = do
@@ -140,45 +116,55 @@ updateNixPkgs paths = do
140116 flip discoverNixFiles fileOrDir $ \file -> do
141117 nix' <- io (readFile file) >>= parseNixFile file
142118 flip (maybe (return ())) nix' $ \nix -> do
143− let Pkg name vers sha noHaddock plats maints path regenerate = nix
119+ let Pkg deriv path regenerate = nix
120+ maints = maintainers (metaSection deriv)
121+ plats = platforms (metaSection deriv)
122+ when (null maints) (msgInfo ("no maintainers configured for " ++ path))
144123 modify $ \cfg -> cfg { _pkgset = Set.insert nix (_pkgset cfg) }
145124 when regenerate $ do
146125 msgDebug ("re-generate " ++ path)
147− let maints' = nub (sort (maints ++ ["andres","simons"]))
126+ let maints' = nub (sort (maints ++ ["self.stdenv.lib.maintainers.andres","self.stdenv.lib.maintainers.simons"]))
148127 plats'
149128 | null plats && not (null maints) = ["self.ghc.meta.platforms"]
150129 | otherwise = plats
151− when (null maints) (msgInfo ("no maintainers configured for " ++ path))
152− pkg <- readCabalFile name vers
153− io $ writeFile path (showNixPkg (cabal2nix pkg sha noHaddock plats' maints'))
130+ pkg <- readCabalFile (display (pname deriv)) (display (version deriv))
131+ let deriv' = (cabal2nix pkg) { sha256 = sha256 deriv, runHaddock = runHaddock deriv }
132+ deriv'' = deriv' { metaSection = (metaSection deriv')
133+ { maintainers = maints'
134+ , platforms = plats'
135+ }
136+ }
137+ io $ writeFile path (show (disp deriv''))
154138 pkgset <- gets (selectLatestVersions . _pkgset)
155139 updates' <- flip mapM (Set.elems pkgset) $ \pkg -> do
156− let Pkg name vers _ _ _ _ _ _ = pkg
157− updates <- discoverUpdates name vers
140+ let Pkg deriv _ _ = pkg
141+ updates <- discoverUpdates (display (pname deriv)) (display (version deriv))
158142 return (pkg,updates)
159143 let updates = [ u | u@(_,(_:_)) <- updates' ]
160144 when (not (null updates)) $ do
161145 msgInfo "The following updates are available:"
162146 flip mapM_ updates $ \(pkg,versions) -> do
163− let Pkg name vers _ noHaddock plats maints path regenerate = pkg
147+ let Pkg deriv path regenerate = pkg
164148 msgInfo ""
165− msgInfo $ name ++ "-" ++ vers ++ ":"
149+ msgInfo $ (display (pname deriv)) ++ "-" ++ (display (version deriv)) ++ ":"
166150 flip mapM_ versions $ \newVersion -> do
167− msgInfo $ " " ++ genCabal2NixCmdline (Pkg name newVersion undefined noHaddock plats maints path regenerate)
151+ let deriv' = deriv { version = readVersion newVersion }
152+ msgInfo $ " " ++ genCabal2NixCmdline (Pkg deriv' path regenerate)
168153 return ()
169154
170155genCabal2NixCmdline :: Pkg -> String
171−genCabal2NixCmdline (Pkg name vers _ noHaddock plats maints path _) = unwords $ ["cabal2nix"] ++ opts ++ [">"++path']
172− where
173− opts = [cabal] ++ maints' ++ plats' ++ if noHaddock then ["--no-haddock"] else []
174− cabal = "cabal://" ++ name ++ "-" ++ vers
175− maints' = [ "--maintainer=" ++ m | m <- maints ]
176− plats'
177− | ["self.ghc.meta.platforms"] == plats = []
178− | otherwise = [ "--platform=" ++ p | p <- plats ]
179− path'
180− | path =~ "/[0-9\\.]+\\.nix$" = replaceFileName path (vers <.> "nix")
181− | otherwise = path
156+genCabal2NixCmdline (Pkg deriv path _) = unwords $ ["cabal2nix"] ++ opts ++ [">"++path']
157+ where
158+ meta = metaSection deriv
159+ opts = [cabal] ++ maints' ++ plats' ++ if runHaddock deriv then [] else ["--no-haddock"]
160+ cabal = "cabal://" ++ display (pname deriv) ++ "-" ++ display (version deriv)
161+ maints' = [ "--maintainer=" ++ m | m <- maintainers meta ]
162+ plats'
163+ | ["self.ghc.meta.platforms"] == platforms meta = []
164+ | otherwise = [ "--platform=" ++ p | p <- platforms meta ]
165+ path'
166+ | path =~ "/[0-9\\.]+\\.nix$" = replaceFileName path (display (version deriv) <.> "nix")
167+ | otherwise = path
182168
183169data CliOption = PrintHelp | Verbose | HackageDB FilePath
184170 deriving (Eq)