Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cabal revisions #393

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions src/Cabal2nix.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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 " <git/svn/bzr/hg URL> 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,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"
, P2.text " /local/path abbreviated version of file URI"
, P2.text " <git/svn/bzr/hg URL> 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 "
Expand Down
18 changes: 11 additions & 7 deletions src/Distribution/Nixpkgs/Haskell/Hackage.hs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
module Distribution.Nixpkgs.Haskell.Hackage
( HackageDB, PackageData, VersionData(..)
( HackageDB, PackageData, VersionData(..), NixSha256
, hackageTarball, readTarball, parsePackageData
)
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
Expand All @@ -19,10 +21,11 @@ type HackageDB = Map PackageName PackageData

type PackageData = Map Version VersionData

type NixSha256 = String

data VersionData = VersionData
{ cabalFile :: !GenericPackageDescription
, cabalFileSha256 :: !String
, tarballSha256 :: !(Maybe String)
{ cabalFilesWithHashes :: !(NonEmpty (NixSha256, GenericPackageDescription))
, tarballSha256 :: !(Maybe NixSha256)
}
deriving (Show)

Expand All @@ -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))
31 changes: 28 additions & 3 deletions src/Distribution/Nixpkgs/Haskell/PackageSourceSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ 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
import Data.Time
Expand All @@ -29,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

Expand Down Expand Up @@ -90,17 +92,40 @@ loadHackageDB optHackageDB optHackageSnapshot = do
dbPath <- maybe DB.hackageTarball return optHackageDB
DB.readTarball optHackageSnapshot dbPath

data Revision = RevisionLatest | RevisionN Int | RevisionSha256 DB.NixSha256

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)
return (ds, setCabalFileHash (DB.cabalFileSha256 vd) (DB.cabalFile 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 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
Expand Down