-
Notifications
You must be signed in to change notification settings - Fork 25
Improve digests generation and parsing #64
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,63 +2,54 @@ | |
| {-# LANGUAGE OverloadedStrings #-} | ||
| {-# LANGUAGE ScopedTypeVariables #-} | ||
| {-# LANGUAGE RankNTypes #-} | ||
| {-# LANGUAGE DataKinds #-} | ||
| {-# LANGUAGE TypeApplications #-} | ||
|
|
||
| module System.Nix.Store.Remote.Parsers ( | ||
| parseContentAddressableAddress | ||
| ) where | ||
| module System.Nix.Store.Remote.Parsers | ||
| ( parseContentAddressableAddress | ||
| ) | ||
| where | ||
|
|
||
| import Control.Applicative ((<|>)) | ||
| import Data.Attoparsec.ByteString.Char8 (Parser, (<?>)) | ||
| import Data.ByteString (ByteString) | ||
| import System.Nix.Hash (Digest, NamedAlgo, SomeNamedDigest(SomeDigest)) | ||
| import System.Nix.StorePath (ContentAddressableAddress(..), NarHashMode(..)) | ||
|
|
||
| import qualified Data.Attoparsec.ByteString.Char8 | ||
| import qualified Data.ByteString.Char8 | ||
| import Control.Applicative ( (<|>) ) | ||
| import Data.Attoparsec.ByteString.Char8 | ||
| import Data.ByteString.Char8 | ||
| import qualified Data.Text | ||
|
|
||
| import qualified System.Nix.Internal.Base32 | ||
| import qualified System.Nix.Hash | ||
| import Data.Text.Encoding ( decodeUtf8 ) | ||
| import System.Nix.Hash | ||
| import System.Nix.StorePath ( ContentAddressableAddress(..) | ||
| , NarHashMode(..) | ||
| ) | ||
|
|
||
| -- | Parse `ContentAddressableAddress` from `ByteString` | ||
| parseContentAddressableAddress :: forall hashAlgo . NamedAlgo hashAlgo | ||
| => ByteString | ||
| -> Either String ContentAddressableAddress | ||
| parseContentAddressableAddress | ||
| :: ByteString -> Either String ContentAddressableAddress | ||
| parseContentAddressableAddress = | ||
| Data.Attoparsec.ByteString.Char8.parseOnly | ||
| (contentAddressableAddressParser @hashAlgo) | ||
| Data.Attoparsec.ByteString.Char8.parseOnly contentAddressableAddressParser | ||
|
|
||
| -- | Parser for content addressable field | ||
| contentAddressableAddressParser :: forall hashAlgo . NamedAlgo hashAlgo | ||
| => Parser ContentAddressableAddress | ||
| contentAddressableAddressParser = | ||
| caText | ||
| <|> caFixed @hashAlgo | ||
| contentAddressableAddressParser :: Parser ContentAddressableAddress | ||
| contentAddressableAddressParser = caText <|> caFixed | ||
|
|
||
| -- | Parser for @text:sha256:<h>@ | ||
| caText :: Parser ContentAddressableAddress | ||
| caText = do | ||
| _ <- "text:sha256:" | ||
| digest <- parseDigest | ||
| either fail return | ||
| $ Text <$> digest | ||
| _ <- "text:sha256:" | ||
| digest <- decodeBase32 @'SHA256 <$> parseHash | ||
| either fail return $ Text <$> digest | ||
|
|
||
| -- | Parser for @fixed:<r?>:<ht>:<h>@ | ||
| caFixed :: forall hashAlgo . NamedAlgo hashAlgo => Parser ContentAddressableAddress | ||
| caFixed :: Parser ContentAddressableAddress | ||
| caFixed = do | ||
| _ <- "fixed:" | ||
| narHashMode <- (pure Recursive <$> "true") <|> (pure RegularFile <$> "false") | ||
| <?> "Invalid Base32 part" | ||
| digest <- parseDigest | ||
| _ <- "fixed:" | ||
| narHashMode <- (pure Recursive <$> "r:") <|> (pure RegularFile <$> "") | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not too sure here. Maybe it's really "true" and "false" ? In mkFixedOutputDerivation we also have a name after fixed:, as in fixed:out:... How can I properly test this ?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks good, in my repo I have a similar fix pending: but I've stopped at the For testing this I'll draft |
||
| digest <- parseTypedDigest | ||
| either fail return $ Fixed narHashMode <$> digest | ||
|
|
||
| parseTypedDigest :: Parser (Either String SomeNamedDigest) | ||
| parseTypedDigest = mkNamedDigest <$> parseHashType <*> parseHash | ||
|
|
||
| either fail return | ||
| $ Fixed <$> pure narHashMode <*> (SomeDigest @hashAlgo <$> digest) | ||
| parseHashType :: Parser Data.Text.Text | ||
| parseHashType = decodeUtf8 <$> ("sha256" <|> "sha1" <|> "md5") <* ":" | ||
|
|
||
| parseDigest :: forall a . Parser (Either String (Digest a)) | ||
| parseDigest = | ||
| System.Nix.Hash.decodeBase32 | ||
| . Data.Text.pack | ||
| . Data.ByteString.Char8.unpack | ||
| <$> Data.Attoparsec.ByteString.Char8.takeWhile1 | ||
| (\c -> c `elem` System.Nix.Internal.Base32.digits32) | ||
| parseHash :: Parser Data.Text.Text | ||
| parseHash = decodeUtf8 <$> takeWhile1 (/= ':') | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also had this one simplified:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I kept this one on purpose to fail on "text:xxx" where xxx is not sha256, which is the only allowed value.
We could however decide to be permissive here. Not sure which is best.