cabal2nix 2.6 → 2.7
raw patch · 8 files changed
+112/−32 lines, 8 filesdep +hpackPVP ok
version bump matches the API change (PVP)
Dependencies added: hpack
API changes (from Hackage documentation)
+ Distribution.Nixpkgs.Haskell.FromCabal.PostProcess: pkg :: Identifier -> Binding
+ Distribution.Nixpkgs.Haskell.OrphanInstances: instance Data.String.IsString Distribution.Version.VersionRange
+ Distribution.Nixpkgs.Haskell.PackageSourceSpec: [pkgRanHpack] :: Package -> Bool
- Distribution.Nixpkgs.Haskell.PackageSourceSpec: Package :: DerivationSource -> GenericPackageDescription -> Package
+ Distribution.Nixpkgs.Haskell.PackageSourceSpec: Package :: DerivationSource -> Bool -> GenericPackageDescription -> Package
- Distribution.Nixpkgs.Haskell.PackageSourceSpec: getPackage :: Maybe FilePath -> Source -> IO Package
+ Distribution.Nixpkgs.Haskell.PackageSourceSpec: getPackage :: Bool -> Maybe FilePath -> Maybe UTCTime -> Source -> IO Package
Files
- cabal2nix.cabal +5/−1
- src/Cabal2nix.hs +22/−2
- src/Distribution/Nixpkgs/Haskell/FromCabal.hs +1/−1
- src/Distribution/Nixpkgs/Haskell/FromCabal/Flags.hs +2/−2
- src/Distribution/Nixpkgs/Haskell/FromCabal/Name.hs +1/−0
- src/Distribution/Nixpkgs/Haskell/FromCabal/PostProcess.hs +8/−2
- src/Distribution/Nixpkgs/Haskell/OrphanInstances.hs +3/−0
- src/Distribution/Nixpkgs/Haskell/PackageSourceSpec.hs +70/−24
cabal2nix.cabal view
@@ -3,7 +3,7 @@ -- see: https://github.com/sol/hpack name: cabal2nix-version: 2.6+version: 2.7 synopsis: Convert Cabal files into Nix build instructions. description: Convert Cabal files into Nix build instructions. Users of Nix can install the latest version by running: .@@ -101,6 +101,7 @@ , filepath , hackage-db > 2 , hopenssl >= 2+ , hpack , language-nix , lens , optparse-applicative@@ -150,6 +151,7 @@ , filepath , hackage-db > 2 , hopenssl >= 2+ , hpack , language-nix , lens , optparse-applicative@@ -183,6 +185,7 @@ , filepath , hackage-db > 2 , hopenssl >= 2+ , hpack , language-nix , lens , optparse-applicative@@ -223,6 +226,7 @@ , filepath , hackage-db > 2 , hopenssl >= 2+ , hpack , language-nix , lens , optparse-applicative
src/Cabal2nix.hs view
@@ -12,11 +12,13 @@ import Data.Monoid ( (<>) ) import qualified Data.Set as Set import Data.String+import Data.Time import qualified Distribution.Compat.ReadP as P import Distribution.Compiler import Distribution.Nixpkgs.Fetch import Distribution.Nixpkgs.Haskell import Distribution.Nixpkgs.Haskell.FromCabal+import qualified Distribution.Nixpkgs.Haskell.FromCabal.PostProcess as PP (pkg) import Distribution.Nixpkgs.Haskell.PackageSourceSpec import Distribution.Nixpkgs.Meta import Distribution.PackageDescription ( mkFlagName, FlagAssignment )@@ -36,6 +38,7 @@ , optMaintainer :: [String] --, optPlatform :: [String] -- TODO: fix command line handling of platforms , optHaddock :: Bool+ , optHpack :: Bool , optDoCheck :: Bool , optJailbreak :: Bool , optRevision :: Maybe String@@ -50,6 +53,7 @@ , optCompiler :: CompilerId , optSystem :: Platform , optSubpath :: Maybe FilePath+ , optHackageSnapshot :: Maybe UTCTime , optUrl :: String } deriving (Show)@@ -60,6 +64,7 @@ <*> many (strOption $ long "maintainer" <> metavar "MAINTAINER" <> help "maintainer of this package (may be specified multiple times)") -- <*> many (strOption $ long "platform" <> metavar "PLATFORM" <> help "supported build platforms (may be specified multiple times)") <*> flag True False (long "no-haddock" <> help "don't run Haddock when building this package")+ <*> switch (long "hpack" <> help "run hpack before configuring this package (only non-hackage packages)") <*> flag True False (long "no-check" <> help "don't run regression test suites of this package") <*> switch (long "jailbreak" <> help "disregard version restrictions on build inputs") <*> optional (strOption $ long "revision" <> help "revision to use when fetching from VCS")@@ -74,8 +79,17 @@ <*> option (readP parse) (long "compiler" <> help "compiler to use when evaluating the Cabal file" <> value buildCompilerId <> showDefaultWith display) <*> option (readP parsePlatform) (long "system" <> help "target system to use when evaluating the Cabal file" <> value buildPlatform <> showDefaultWith display) <*> optional (strOption $ long "subpath" <> metavar "PATH" <> help "Path to Cabal file's directory relative to the URI (default is root directory)")+ <*> optional (option utcTimeReader (long "hackage-snapshot" <> help "hackage snapshot time, ISO format")) <*> strArgument (metavar "URI") +-- | A parser for the date. Hackage updates happen maybe once or twice a month.+-- Example: parseTime defaultTimeLocale "%FT%T%QZ" "2017-11-20T12:18:35Z" :: Maybe UTCTime+utcTimeReader :: ReadM UTCTime+utcTimeReader = eitherReader $ \arg ->+ case parseTimeM True defaultTimeLocale "%FT%T%QZ" arg of+ Nothing -> Left $ "Cannot parse date, ISO format used ('2017-11-20T12:18:35Z'): " ++ arg+ Just utcTime -> Right utcTime+ readP :: P.ReadP a a -> ReadM a readP p = eitherReader $ \s -> case [ r' | (r',"") <- P.readP_to_S p s ] of (r:_) -> Right r@@ -118,15 +132,21 @@ main = bracket (return ()) (\() -> hFlush stdout >> hFlush stderr) $ \() -> cabal2nix =<< getArgs +hpackOverrides :: Derivation -> Derivation+hpackOverrides = over phaseOverrides (++ "preConfigure = \"hpack\";")+ . set (libraryDepends . tool . contains (PP.pkg "hpack")) True+ cabal2nix' :: [String] -> IO (Either Doc Derivation) cabal2nix' args = do Options {..} <- handleParseResult $ execParserPure defaultPrefs pinfo args - pkg <- getPackage optHackageDb $ Source optUrl (fromMaybe "" optRevision) (maybe UnknownHash Guess optSha256) (fromMaybe "" optSubpath)+ pkg <- getPackage optHpack optHackageDb optHackageSnapshot $ Source optUrl (fromMaybe "" optRevision) (maybe UnknownHash Guess optSha256) (fromMaybe "" optSubpath) let+ withHpackOverrides :: Derivation -> Derivation+ withHpackOverrides = if pkgRanHpack pkg then hpackOverrides else id deriv :: Derivation- deriv = fromGenericPackageDescription (const True)+ deriv = withHpackOverrides $ fromGenericPackageDescription (const True) (\i -> Just (binding # (i, path # [i]))) optSystem (unknownCompilerInfo optCompiler NoAbiTag)
src/Distribution/Nixpkgs/Haskell/FromCabal.hs view
@@ -17,7 +17,7 @@ import Distribution.Nixpkgs.Haskell.FromCabal.License import Distribution.Nixpkgs.Haskell.FromCabal.Name import Distribution.Nixpkgs.Haskell.FromCabal.Normalize-import Distribution.Nixpkgs.Haskell.FromCabal.PostProcess+import Distribution.Nixpkgs.Haskell.FromCabal.PostProcess (postProcess) import qualified Distribution.Nixpkgs.Meta as Nix import Distribution.Package import Distribution.PackageDescription
src/Distribution/Nixpkgs/Haskell/FromCabal/Flags.hs view
@@ -28,7 +28,7 @@ , enable "s3" , enable "tahoe" , enable "tdfa"- , enable "testsuite"+ , ("testsuite", version `withinRange` "< 6.20170925") , enable "torrentparser" , enable "webapp" , enable "webapp-secure"@@ -42,7 +42,7 @@ = [enable "externalLibsass"] | name == "hmatrix" = [enable "openblas"] | name == "hslua" = [enable "system-lua"]- | name == "idris" = [enable "gmp", enable "ffi", enable "curses"]+ | name == "idris" = [enable "gmp", enable "ffi", enable "curses", ("execonly", version `withinRange` (orLaterVersion (mkVersion [1,1,1]))) ] | name == "io-streams" = [enable "NoInteractiveTests"] | name == "liquid-fixpoint" = [enable "build-external"] | name == "pandoc" = [enable "https", disable "trypandoc"]
src/Distribution/Nixpkgs/Haskell/FromCabal/Name.hs view
@@ -130,6 +130,7 @@ libNixName "sass" = return "libsass" libNixName "sctp" = return "lksctp-tools" -- This is linux-specific, we should create a common attribute if we ever add sctp support for other systems. libNixName "sdl2" = return "SDL2"+libNixName "ssh2" = return "libssh2" libNixName "sndfile" = return "libsndfile" libNixName "sodium" = return "libsodium" libNixName "sqlite3" = return "sqlite"
src/Distribution/Nixpkgs/Haskell/FromCabal/PostProcess.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} -module Distribution.Nixpkgs.Haskell.FromCabal.PostProcess ( postProcess ) where+module Distribution.Nixpkgs.Haskell.FromCabal.PostProcess ( postProcess, pkg ) where import Control.Lens import Data.List.Split@@ -61,6 +61,7 @@ , ("gi-pangocairo", giCairoPhaseOverrides) -- https://github.com/haskell-gi/haskell-gi/issues/36 , ("gi-pango", giCairoPhaseOverrides) -- https://github.com/haskell-gi/haskell-gi/issues/36 , ("git-annex", gitAnnexHook)+ , ("git-annex >= 6.20170925", set doCheck False) -- new version of git-annex require their test suite to be run inside of a git checkout , ("github-backup", set (executableDepends . tool . contains (pkg "git")) True) , ("git", set doCheck False) -- https://github.com/vincenthz/hit/issues/33 , ("gi-webkit", webkitgtk24xHook) -- https://github.com/haskell-gi/haskell-gi/issues/36@@ -70,10 +71,11 @@ , ("haddock", haddockHook) -- https://github.com/haskell/haddock/issues/511 , ("hakyll", set (testDepends . tool . contains (pkg "utillinux")) True) -- test suite depends on "rev" , ("haskell-src-exts", set doCheck False)+ , ("hspec-core >= 2.4.4", hspecCoreOverrides) , ("hfsevents", hfseventsOverrides) , ("HFuse", set phaseOverrides hfusePreConfigure) , ("hlibgit2 >= 0.18.0.14", set (testDepends . tool . contains (pkg "git")) True)- , ("hmatrix", set phaseOverrides "preConfigure = \"sed -i hmatrix.cabal -e 's@/usr/@/dont/hardcode/paths/@'\";")+ , ("hmatrix", set phaseOverrides "preConfigure = \"sed -i hmatrix.cabal -e '/\\\\/usr\\\\//D'\";") , ("holy-project", set doCheck False) -- attempts to access the network , ("hoogle", set testTarget "--test-option=--no-net") , ("hsignal < 0.2.7.4", set phaseOverrides "prePatch = \"rm -v Setup.lhs\";") -- https://github.com/amcphail/hsignal/issues/1@@ -102,6 +104,7 @@ , ("qtah-cpp-qt5", set (libraryDepends . system . contains (bind "pkgs.qt5.qtbase")) True) , ("qtah-qt5", set (libraryDepends . tool . contains (bind "pkgs.qt5.qtbase")) True) , ("readline", over (libraryDepends . system) (Set.union (pkgs ["readline", "ncurses"])))+ , ("req", set doCheck False) -- test suite requires network access , ("sbv > 7", set (testDepends . system . contains (pkg "z3")) True) , ("sdr", over (metaSection . platforms) (Set.filter (\(Platform arch _) -> arch == X86_64))) -- https://github.com/adamwalker/sdr/issues/2 , ("shake-language-c", set doCheck False) -- https://github.com/samplecount/shake-language-c/issues/26@@ -296,3 +299,6 @@ . over (libraryDepends . pkgconfig) (replace (pkg "opencv") (pkg "opencv3")) . set (configureFlags . contains "--with-gcc=${stdenv.cc}/bin/c++") True . set (configureFlags . contains "--with-ld=${stdenv.cc}/bin/c++") True++hspecCoreOverrides :: Derivation -> Derivation -- https://github.com/hspec/hspec/issues/330+hspecCoreOverrides = set phaseOverrides "testTarget = \"--test-option=--skip --test-option='Test.Hspec.Core.Runner.hspecResult runs specs in parallel'\";"
src/Distribution/Nixpkgs/Haskell/OrphanInstances.hs view
@@ -69,6 +69,9 @@ instance IsString Version where fromString = text2isString "Version" +instance IsString VersionRange where+ fromString = text2isString "VersionRange"+ instance IsString PackageIdentifier where fromString = text2isString "PackageIdentifier"
src/Distribution/Nixpkgs/Haskell/PackageSourceSpec.hs view
@@ -9,6 +9,7 @@ import Data.List ( isSuffixOf, isPrefixOf ) import qualified Data.Map as DB import Data.Maybe+import Data.Time import Distribution.Nixpkgs.Fetch import Distribution.Nixpkgs.Hashes import qualified Distribution.Nixpkgs.Haskell.Hackage as DB@@ -18,6 +19,8 @@ import Distribution.PackageDescription.Parse as Cabal import Distribution.Text ( simpleParse, display ) import Distribution.Version+import qualified Hpack.Run as Hpack+import qualified Hpack.Config as Hpack import OpenSSL.Digest ( digestString, digestByName ) import System.Directory ( doesDirectoryExist, doesFileExist, createDirectoryIfMissing, getHomeDirectory, getDirectoryContents ) import System.Exit ( exitFailure )@@ -25,30 +28,50 @@ import System.IO ( hPutStrLn, stderr, hPutStr ) data Package = Package- { pkgSource :: DerivationSource- , pkgCabal :: Cabal.GenericPackageDescription+ { pkgSource :: DerivationSource+ , pkgRanHpack :: Bool -- ^ If hpack generated a new cabal file+ , pkgCabal :: Cabal.GenericPackageDescription } deriving (Show) -getPackage :: Maybe FilePath -> Source -> IO Package-getPackage optHackageDB source = do- (derivSource, pkgDesc) <- fetchOrFromDB optHackageDB source- flip Package pkgDesc <$> maybe (sourceFromHackage (sourceHash source) (showPackageIdentifier pkgDesc) $ sourceCabalDir source) return derivSource+getPackage :: Bool+ -- ^ Whether hpack should regenerate the cabal file.+ -> Maybe FilePath+ -- ^ The path to the Hackage database.+ -> Maybe UTCTime+ -- ^ If we have hackage-snapshot time.+ -> Source+ -> IO Package+getPackage optHpack optHackageDB optHackageSnapshot source = do+ (derivSource, ranHpack, pkgDesc) <- fetchOrFromDB optHpack optHackageDB optHackageSnapshot source+ (\s -> Package s ranHpack pkgDesc) <$> maybe (sourceFromHackage (sourceHash source) (showPackageIdentifier pkgDesc) $ sourceCabalDir source) return derivSource -fetchOrFromDB :: Maybe FilePath -> Source -> IO (Maybe DerivationSource, Cabal.GenericPackageDescription)-fetchOrFromDB optHackageDB src- | "cabal://" `isPrefixOf` sourceUrl src = fromDB optHackageDB . drop (length "cabal://") $ sourceUrl src+fetchOrFromDB :: Bool+ -- ^ Whether hpack should regenerate the cabal file+ -> Maybe FilePath+ -- ^ The path to the Hackage database.+ -> Maybe UTCTime+ -- ^ If we have hackage-snapshot time.+ -> Source+ -> IO (Maybe DerivationSource, Bool, Cabal.GenericPackageDescription)+fetchOrFromDB optHpack optHackageDB optHackageSnapshot src+ | "cabal://" `isPrefixOf` sourceUrl src = do+ (msrc, pkgDesc) <- fromDB optHackageDB optHackageSnapshot . drop (length "cabal://") $ sourceUrl src+ return (msrc, False, pkgDesc) | otherwise = do- r <- fetch (\dir -> cabalFromPath (dir </> sourceCabalDir src)) src+ r <- fetch (\dir -> cabalFromPath optHpack (dir </> sourceCabalDir src)) src case r of Nothing -> fail "Failed to fetch source. Does the URL exist?"- Just (derivSource, (externalSource, pkgDesc)) -> do- return (derivSource <$ guard externalSource, pkgDesc)+ Just (derivSource, (externalSource, ranHpack, pkgDesc)) -> do+ return (derivSource <$ guard externalSource, ranHpack, pkgDesc) -fromDB :: Maybe FilePath -> String -> IO (Maybe DerivationSource, Cabal.GenericPackageDescription)-fromDB optHackageDB pkg = do+fromDB :: Maybe FilePath+ -> Maybe UTCTime+ -> String+ -> IO (Maybe DerivationSource, Cabal.GenericPackageDescription)+fromDB optHackageDB optHackageSnapshot pkg = do dbPath <- maybe DB.hackageTarball return optHackageDB- db <- DB.readTarball Nothing dbPath+ db <- DB.readTarball optHackageSnapshot dbPath vd <- maybe unknownPackageError return (DB.lookup name db >>= lookupVersion) let ds = case DB.tarballSha256 vd of Nothing -> Nothing@@ -129,22 +152,45 @@ name = Cabal.unPackageName (Cabal.packageName pkgId) version = Cabal.packageVersion pkgId -cabalFromPath :: FilePath -> MaybeT IO (Bool, Cabal.GenericPackageDescription)-cabalFromPath path = do+cabalFromPath :: Bool -- ^ Whether hpack should regenerate the cabal file+ -> FilePath -> MaybeT IO (Bool, Bool, Cabal.GenericPackageDescription)+cabalFromPath optHpack path = do d <- liftIO $ doesDirectoryExist path- (,) d <$> if d- then cabalFromDirectory path- else cabalFromFile False path+ if d+ then do+ (ranHpack, pkg) <- cabalFromDirectory optHpack path+ return (d, ranHpack, pkg)+ else (,,) d False <$> cabalFromFile False path -cabalFromDirectory :: FilePath -> MaybeT IO Cabal.GenericPackageDescription-cabalFromDirectory dir = do+cabalFromDirectory :: Bool -- ^ Whether hpack should regenerate the cabal file+ -> FilePath -> MaybeT IO (Bool, Cabal.GenericPackageDescription)+cabalFromDirectory True dir = hpackDirectory dir+cabalFromDirectory False dir = do cabals <- liftIO $ getDirectoryContents dir >>= filterM doesFileExist . map (dir </>) . filter (".cabal" `isSuffixOf`) case cabals of- [cabalFile] -> cabalFromFile True cabalFile- _ -> liftIO $ fail ("Found zero or more than one cabal files: " ++ show cabals ++ ". Exiting.")+ [] -> do+ liftIO $ hPutStrLn stderr "*** found zero cabal files. Trying hpack..."+ hpackDirectory dir+ [cabalFile] -> (,) False <$> cabalFromFile True cabalFile+ _ -> liftIO $ fail ("*** found more than one cabal file (" ++ show cabals ++ "). Exiting.") handleIO :: (Exception.IOException -> IO a) -> IO a -> IO a handleIO = Exception.handle++hpackDirectory :: FilePath -> MaybeT IO (Bool, Cabal.GenericPackageDescription)+hpackDirectory dir = do+ mPackage <- liftIO $ Hpack.readPackageConfig $ dir </> "package.yaml"+ case mPackage of+ Left err -> liftIO $ hPutStrLn stderr ("*** hpack error: " ++ show err ++ ". Exiting.") >> exitFailure+ Right (_, pkg') -> do+ let hpackOutput = Hpack.renderPackage Hpack.defaultRenderSettings 2 [] [] pkg'+ hash = printSHA256 $ digestString (digestByName "sha256") hpackOutput+ case parseGenericPackageDescription hpackOutput of+ ParseFailed perr -> liftIO $ do+ hPutStrLn stderr $ "*** cannot parse hpack output: " ++ show perr+ hPutStrLn stderr $ "*** hpack output:\n" ++ hpackOutput+ fail "*** Exiting."+ ParseOk _ pkg -> MaybeT $ return $ Just $ (,) True $ setCabalFileHash hash pkg cabalFromFile :: Bool -> FilePath -> MaybeT IO Cabal.GenericPackageDescription cabalFromFile failHard file =