From 1dc47dcbf24228076663505562a4ca9cdd8d26c2 Mon Sep 17 00:00:00 2001 From: Kirill Zaborsky Date: Tue, 4 Dec 2018 13:38:11 +0300 Subject: [PATCH 1/3] support cabal revisions from hackage-db --- src/Distribution/Nixpkgs/Haskell/Hackage.hs | 16 ++++++++++------ .../Nixpkgs/Haskell/PackageSourceSpec.hs | 4 +++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/Distribution/Nixpkgs/Haskell/Hackage.hs b/src/Distribution/Nixpkgs/Haskell/Hackage.hs index 4ed8aa505..8f40a82c0 100644 --- a/src/Distribution/Nixpkgs/Haskell/Hackage.hs +++ b/src/Distribution/Nixpkgs/Haskell/Hackage.hs @@ -4,6 +4,8 @@ module Distribution.Nixpkgs.Haskell.Hackage ) where +import qualified Data.List.NonEmpty as NE +import Data.List.NonEmpty (NonEmpty) import Data.Map as Map import qualified Distribution.Hackage.DB.Parsed as P import Distribution.Hackage.DB.Path @@ -19,10 +21,11 @@ type HackageDB = Map PackageName PackageData type PackageData = Map Version VersionData +type Sha256 = String + data VersionData = VersionData - { cabalFile :: !GenericPackageDescription - , cabalFileSha256 :: !String - , tarballSha256 :: !(Maybe String) + { cabalFilesWithHashes :: !(NonEmpty (Sha256, GenericPackageDescription)) + , tarballSha256 :: !(Maybe Sha256) } deriving (Show) @@ -37,9 +40,10 @@ parsePackageData dbu pn = mapWithKey (parseVersionData (dbu ! pn)) parseVersionData :: U.PackageData -> Version -> P.VersionData -> VersionData parseVersionData pdu v vd = VersionData - { cabalFile = P.cabalFile vd - , cabalFileSha256 = printSHA256 (digest (digestByName "sha256") file) + { cabalFilesWithHashes = cfsWithHashes , tarballSha256 = Map.lookup "sha256" (P.tarballHashes vd) } where - file = U.cabalFile (U.versions pdu ! v) + cfsWithHashes = NE.zip sha256s (P.cabalFileRevisions vd) + sha256s = NE.map (\file -> printSHA256 (digest (digestByName "sha256") file)) + (NE.fromList $ U.cabalFileRevisions (U.versions pdu ! v)) diff --git a/src/Distribution/Nixpkgs/Haskell/PackageSourceSpec.hs b/src/Distribution/Nixpkgs/Haskell/PackageSourceSpec.hs index 4b1183c49..059b3a7b4 100644 --- a/src/Distribution/Nixpkgs/Haskell/PackageSourceSpec.hs +++ b/src/Distribution/Nixpkgs/Haskell/PackageSourceSpec.hs @@ -9,6 +9,7 @@ import Control.Monad.Trans.Maybe import Data.Bifunctor import qualified Data.ByteString.Char8 as BS import Data.List ( isSuffixOf, isPrefixOf ) +import qualified Data.List.NonEmpty as NE import qualified Data.Map as DB import Data.Maybe import Data.Time @@ -99,7 +100,8 @@ fromDB hackageDBIO pkg = do let ds = case DB.tarballSha256 vd of Nothing -> Nothing Just hash -> Just (urlDerivationSource url hash) - return (ds, setCabalFileHash (DB.cabalFileSha256 vd) (DB.cabalFile vd)) + (cabalFileSha256, cabalFile) = NE.last (DB.cabalFilesWithHashes vd) + return (ds, setCabalFileHash cabalFileSha256 cabalFile) where pkgId :: Cabal.PackageIdentifier pkgId = fromMaybe (error ("invalid Haskell package id " ++ show pkg)) (simpleParse pkg) From 74fd07536ed2a9d388b2b25ee9e614f0ba18da33 Mon Sep 17 00:00:00 2001 From: Kirill Zaborsky Date: Tue, 4 Dec 2018 15:53:46 +0300 Subject: [PATCH 2/3] Add custom revision support --- src/Cabal2nix.hs | 11 ++++---- src/Distribution/Nixpkgs/Haskell/Hackage.hs | 2 +- .../Nixpkgs/Haskell/PackageSourceSpec.hs | 27 ++++++++++++++++--- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/Cabal2nix.hs b/src/Cabal2nix.hs index 9d07a9db7..9c78050f2 100644 --- a/src/Cabal2nix.hs +++ b/src/Cabal2nix.hs @@ -164,11 +164,12 @@ pinfo = info [ P2.text "" , P2.text "Recognized URI schemes:" , P2.text "" - , P2.text " cabal://pkgname-pkgversion download the specified package from Hackage" - , P2.text " cabal://pkgname download latest version of this package from Hackage" - , P2.text " file:///local/path load the Cabal file from the local disk" - , P2.text " /local/path abbreviated version of file URI" - , P2.text " download the source from the specified repository" + , P2.text " cabal://pkgname-pkgversion@pkgrevision download the specified package from Hackage, use revision N if pkgrevision is 'rev:N' or use revision with cabal file SHA256 equal to S with pkgrevision specified as 'sha256:S'" + , P2.text " cabal://pkgname-pkgversion download the specified package from Hackage, use latest revision" + , P2.text " cabal://pkgname download latest version of this package from Hackage" + , P2.text " file:///local/path load the Cabal file from the local disk" + , P2.text " /local/path abbreviated version of file URI" + , P2.text " download the source from the specified repository" , P2.text "" , P2.fillSep (map P2.text (words ( "If the URI refers to a cabal file, information for building the package " ++ "will be retrieved from that file, but hackage will be used as a source " diff --git a/src/Distribution/Nixpkgs/Haskell/Hackage.hs b/src/Distribution/Nixpkgs/Haskell/Hackage.hs index 8f40a82c0..7908fff24 100644 --- a/src/Distribution/Nixpkgs/Haskell/Hackage.hs +++ b/src/Distribution/Nixpkgs/Haskell/Hackage.hs @@ -1,5 +1,5 @@ module Distribution.Nixpkgs.Haskell.Hackage - ( HackageDB, PackageData, VersionData(..) + ( HackageDB, PackageData, VersionData(..), Sha256 , hackageTarball, readTarball, parsePackageData ) where diff --git a/src/Distribution/Nixpkgs/Haskell/PackageSourceSpec.hs b/src/Distribution/Nixpkgs/Haskell/PackageSourceSpec.hs index 059b3a7b4..530845539 100644 --- a/src/Distribution/Nixpkgs/Haskell/PackageSourceSpec.hs +++ b/src/Distribution/Nixpkgs/Haskell/PackageSourceSpec.hs @@ -8,7 +8,7 @@ import Control.Monad.IO.Class import Control.Monad.Trans.Maybe import Data.Bifunctor import qualified Data.ByteString.Char8 as BS -import Data.List ( isSuffixOf, isPrefixOf ) +import Data.List ( isSuffixOf, isPrefixOf, stripPrefix ) import qualified Data.List.NonEmpty as NE import qualified Data.Map as DB import Data.Maybe @@ -30,6 +30,7 @@ import System.Directory ( doesDirectoryExist, doesFileExist, createDirectoryIfMi import System.Exit ( exitFailure ) import System.FilePath ( (), (<.>) ) import System.IO +import Text.Read ( readMaybe ) import qualified Data.Text as T import qualified Data.Text.Encoding as T @@ -91,18 +92,38 @@ loadHackageDB optHackageDB optHackageSnapshot = do dbPath <- maybe DB.hackageTarball return optHackageDB DB.readTarball optHackageSnapshot dbPath +data Revision = RevisionLatest | RevisionN Int | RevisionSha256 DB.Sha256 + fromDB :: IO DB.HackageDB -> String -> IO (Maybe DerivationSource, Cabal.GenericPackageDescription) -fromDB hackageDBIO pkg = do +fromDB hackageDBIO pkgRev = do hackageDB <- hackageDBIO vd <- maybe unknownPackageError return (DB.lookup name hackageDB >>= lookupVersion) let ds = case DB.tarballSha256 vd of Nothing -> Nothing Just hash -> Just (urlDerivationSource url hash) - (cabalFileSha256, cabalFile) = NE.last (DB.cabalFilesWithHashes vd) + cabalFilesWithHashes = DB.cabalFilesWithHashes vd + (cabalFileSha256, cabalFile) = + case rev of + RevisionLatest -> NE.last cabalFilesWithHashes + RevisionN n -> case NE.drop n cabalFilesWithHashes of + [] -> fail $ "invalid Haskell package " ++ show pkg ++ " revision " ++ show n + x : _ -> x + RevisionSha256 sha -> case NE.filter ((== sha) . fst) cabalFilesWithHashes of + [] -> fail $ "invalid Haskell package " ++ show pkg ++ " revision SHA256" ++ show sha + x : _ -> x return (ds, setCabalFileHash cabalFileSha256 cabalFile) where + (pkg, rev) = case span (/= '@') pkgRev of + (p, "") -> (p, RevisionLatest) + (p, r) | Just nStr <- stripPrefix "@rev:" r, + Just n <- readMaybe nStr, + n >= 0 -> + (p, RevisionN n) + (p, r) | Just sha256 <- stripPrefix "@sha256:" r -> + (p, RevisionSha256 sha256) + _ -> error $ "invalid Haskell package id " ++ show pkgRev pkgId :: Cabal.PackageIdentifier pkgId = fromMaybe (error ("invalid Haskell package id " ++ show pkg)) (simpleParse pkg) name = Cabal.packageName pkgId From ced478e8ee78e0d1bd75e86f0073cc1f30ffa515 Mon Sep 17 00:00:00 2001 From: Kirill Zaborsky Date: Wed, 5 Dec 2018 10:20:26 +0300 Subject: [PATCH 3/3] Use proper custom SHAs: allow Stack's with size and base32 in Nix --- src/Cabal2nix.hs | 2 +- src/Distribution/Nixpkgs/Haskell/Hackage.hs | 8 ++++---- src/Distribution/Nixpkgs/Haskell/PackageSourceSpec.hs | 10 ++++++---- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/Cabal2nix.hs b/src/Cabal2nix.hs index 9c78050f2..ae7ba220d 100644 --- a/src/Cabal2nix.hs +++ b/src/Cabal2nix.hs @@ -164,7 +164,7 @@ pinfo = info [ P2.text "" , P2.text "Recognized URI schemes:" , P2.text "" - , P2.text " cabal://pkgname-pkgversion@pkgrevision download the specified package from Hackage, use revision N if pkgrevision is 'rev:N' or use revision with cabal file SHA256 equal to S with pkgrevision specified as 'sha256:S'" + , P2.text " cabal://pkgname-pkgversion@pkgrevision download the specified package from Hackage, use revision N if pkgrevision is 'rev:N' or use revision with cabal file SHA256 equal to S with pkgrevision specified as 'sha256:S,SZ (SZ part is being ignored)'" , P2.text " cabal://pkgname-pkgversion download the specified package from Hackage, use latest revision" , P2.text " cabal://pkgname download latest version of this package from Hackage" , P2.text " file:///local/path load the Cabal file from the local disk" diff --git a/src/Distribution/Nixpkgs/Haskell/Hackage.hs b/src/Distribution/Nixpkgs/Haskell/Hackage.hs index 7908fff24..2f3ba1feb 100644 --- a/src/Distribution/Nixpkgs/Haskell/Hackage.hs +++ b/src/Distribution/Nixpkgs/Haskell/Hackage.hs @@ -1,5 +1,5 @@ module Distribution.Nixpkgs.Haskell.Hackage - ( HackageDB, PackageData, VersionData(..), Sha256 + ( HackageDB, PackageData, VersionData(..), NixSha256 , hackageTarball, readTarball, parsePackageData ) where @@ -21,11 +21,11 @@ type HackageDB = Map PackageName PackageData type PackageData = Map Version VersionData -type Sha256 = String +type NixSha256 = String data VersionData = VersionData - { cabalFilesWithHashes :: !(NonEmpty (Sha256, GenericPackageDescription)) - , tarballSha256 :: !(Maybe Sha256) + { cabalFilesWithHashes :: !(NonEmpty (NixSha256, GenericPackageDescription)) + , tarballSha256 :: !(Maybe NixSha256) } deriving (Show) diff --git a/src/Distribution/Nixpkgs/Haskell/PackageSourceSpec.hs b/src/Distribution/Nixpkgs/Haskell/PackageSourceSpec.hs index 530845539..85216820b 100644 --- a/src/Distribution/Nixpkgs/Haskell/PackageSourceSpec.hs +++ b/src/Distribution/Nixpkgs/Haskell/PackageSourceSpec.hs @@ -92,7 +92,7 @@ loadHackageDB optHackageDB optHackageSnapshot = do dbPath <- maybe DB.hackageTarball return optHackageDB DB.readTarball optHackageSnapshot dbPath -data Revision = RevisionLatest | RevisionN Int | RevisionSha256 DB.Sha256 +data Revision = RevisionLatest | RevisionN Int | RevisionSha256 DB.NixSha256 fromDB :: IO DB.HackageDB -> String @@ -111,7 +111,7 @@ fromDB hackageDBIO pkgRev = do [] -> fail $ "invalid Haskell package " ++ show pkg ++ " revision " ++ show n x : _ -> x RevisionSha256 sha -> case NE.filter ((== sha) . fst) cabalFilesWithHashes of - [] -> fail $ "invalid Haskell package " ++ show pkg ++ " revision SHA256" ++ show sha + [] -> fail $ "invalid Haskell package " ++ show pkg ++ " revision SHA256 " ++ show sha x : _ -> x return (ds, setCabalFileHash cabalFileSha256 cabalFile) where @@ -121,9 +121,11 @@ fromDB hackageDBIO pkgRev = do Just n <- readMaybe nStr, n >= 0 -> (p, RevisionN n) - (p, r) | Just sha256 <- stripPrefix "@sha256:" r -> - (p, RevisionSha256 sha256) + (p, r) | Just sha256size <- stripPrefix "@sha256:" r, + sha256hex <- takeWhile (/= ',') sha256size -> + (p, RevisionSha256 (toNixSha256 sha256hex)) _ -> error $ "invalid Haskell package id " ++ show pkgRev + toNixSha256 = printSHA256 . packHex pkgId :: Cabal.PackageIdentifier pkgId = fromMaybe (error ("invalid Haskell package id " ++ show pkg)) (simpleParse pkg) name = Cabal.packageName pkgId