Skip to content

Commit a187937

Browse files
cgibbardsorki
andcommitted
rework ContentAddress
Co-Authored-By: Richard Marko <[email protected]>
1 parent ce0b360 commit a187937

File tree

3 files changed

+90
-83
lines changed

3 files changed

+90
-83
lines changed
Lines changed: 83 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,52 @@
1-
{-# LANGUAGE DeriveAnyClass #-}
21
{-# LANGUAGE OverloadedStrings #-}
32

43
module System.Nix.ContentAddress (
54
ContentAddress
65
, contentAddressBuilder
76
, contentAddressParser
7+
, buildContentAddress
8+
, parseContentAddress
89
) where
910

1011
import Control.Applicative
11-
import Crypto.Hash (Digest, SHA256)
12-
import Data.Hashable (Hashable)
12+
import Crypto.Hash (Digest)
13+
import Data.Attoparsec.Text (Parser)
14+
import Data.Dependent.Sum (DSum)
15+
import Data.Text (Text)
1316
import Data.Text.Lazy.Builder (Builder)
1417
import GHC.Generics (Generic)
15-
import System.Nix.Base (BaseEncoding(NixBase32))
16-
import System.Nix.Hash (SomeNamedDigest(SomeDigest))
18+
import System.Nix.Hash (HashAlgo)
1719
import Test.QuickCheck (Arbitrary)
1820
import Test.QuickCheck.Arbitrary.Generic (GenericArbitrary(..))
1921
import Test.QuickCheck.Instances ()
2022

21-
import qualified Data.Attoparsec.ByteString.Char8
22-
import qualified Data.Text.Encoding
23+
import qualified Data.Attoparsec.Text
24+
import qualified Data.Text.Lazy
25+
import qualified Data.Text.Lazy.Builder
2326
import qualified System.Nix.Hash
2427

28+
data FileIngestionMethod
29+
= Flat
30+
| FileRecursive
31+
deriving (Eq, Bounded, Generic, Enum, Ord, Show)
32+
33+
deriving via GenericArbitrary FileIngestionMethod
34+
instance Arbitrary FileIngestionMethod
35+
36+
data ContentAddressMethod
37+
= FileIngestionMethod !FileIngestionMethod
38+
-- ^ The path was added to the store via makeFixedOutputPath or
39+
-- addToStore. It is addressed according to some hash algorithm
40+
-- applied to the nar serialization via some 'NarHashMode'.
41+
| TextIngestionMethod
42+
-- ^ The path is a plain file added via makeTextPath or
43+
-- addTextToStore. It is addressed according to a sha256sum of the
44+
-- file contents.
45+
deriving (Eq, Generic, Ord, Show)
46+
47+
deriving via GenericArbitrary ContentAddressMethod
48+
instance Arbitrary ContentAddressMethod
49+
2550
-- | An address for a content-addressable store path, i.e. one whose
2651
-- store path hash is purely a function of its contents (as opposed to
2752
-- paths that are derivation outputs, whose hashes are a function of
@@ -31,74 +56,63 @@ import qualified System.Nix.Hash
3156
-- encodable in multiple ways, depending on the method used to add the
3257
-- path to the store. These unfortunately result in separate store
3358
-- paths.
34-
data ContentAddress
35-
= -- | The path is a plain file added via makeTextPath or
36-
-- addTextToStore. It is addressed according to a sha256sum of the
37-
-- file contents.
38-
Text !(Digest SHA256)
39-
| -- | The path was added to the store via makeFixedOutputPath or
40-
-- addToStore. It is addressed according to some hash algorithm
41-
-- applied to the nar serialization via some 'NarHashMode'.
42-
Fixed !NarHashMode !SomeNamedDigest
59+
data ContentAddress = ContentAddress
60+
ContentAddressMethod
61+
(DSum HashAlgo Digest)
4362
deriving (Eq, Generic, Ord, Show)
4463

4564
deriving via GenericArbitrary ContentAddress
4665
instance Arbitrary ContentAddress
4766

48-
-- | Builder for `ContentAddress`
67+
-- | Marshall `ContentAddressableAddress` to `Text`
68+
-- in form suitable for remote protocol usage.
69+
buildContentAddress :: ContentAddress -> Text
70+
buildContentAddress =
71+
Data.Text.Lazy.toStrict
72+
. Data.Text.Lazy.Builder.toLazyText
73+
. contentAddressBuilder
74+
4975
contentAddressBuilder :: ContentAddress -> Builder
50-
contentAddressBuilder (Text digest) =
51-
"text:"
52-
<> System.Nix.Hash.digestBuilder digest
53-
contentAddressBuilder (Fixed narHashMode (SomeDigest (digest :: Digest hashAlgo))) =
54-
"fixed:"
55-
<> (if narHashMode == Recursive then "r:" else mempty)
56-
-- <> Data.Text.Lazy.Builder.fromText (System.Nix.Hash.algoName @hashAlgo)
57-
<> System.Nix.Hash.digestBuilder digest
76+
contentAddressBuilder (ContentAddress method digest) = case method of
77+
TextIngestionMethod ->
78+
"text:"
79+
<> System.Nix.Hash.algoDigestBuilder digest
80+
FileIngestionMethod r ->
81+
"fixed:"
82+
<> fileIngestionMethodBuilder r
83+
<> System.Nix.Hash.algoDigestBuilder digest
84+
85+
fileIngestionMethodBuilder :: FileIngestionMethod -> Builder
86+
fileIngestionMethodBuilder = \case
87+
Flat -> ""
88+
FileRecursive -> "r:"
89+
90+
-- | Parse `ContentAddressableAddress` from `ByteString`
91+
parseContentAddress
92+
:: Text -> Either String ContentAddress
93+
parseContentAddress =
94+
Data.Attoparsec.Text.parseOnly contentAddressParser
5895

5996
-- | Parser for content addressable field
60-
contentAddressParser :: Data.Attoparsec.ByteString.Char8.Parser ContentAddress
61-
contentAddressParser = caText <|> caFixed
97+
contentAddressParser :: Parser ContentAddress
98+
contentAddressParser = do
99+
method <- parseContentAddressMethod
100+
digest <- parseTypedDigest
101+
case digest of
102+
Left e -> fail e
103+
Right x -> return $ ContentAddress method x
104+
105+
parseContentAddressMethod :: Parser ContentAddressMethod
106+
parseContentAddressMethod =
107+
TextIngestionMethod <$ "text:"
108+
<|> FileIngestionMethod <$ "fixed:" <*> (FileRecursive <$ "r:" <|> pure Flat)
109+
110+
parseTypedDigest :: Parser (Either String (DSum HashAlgo Digest))
111+
parseTypedDigest = System.Nix.Hash.mkNamedDigest <$> parseHashType <*> parseHash
62112
where
63-
-- | Parser for @text:sha256:<h>@
64-
--caText :: Parser ContentAddress
65-
caText = do
66-
_ <- "text:sha256:"
67-
digest <- System.Nix.Hash.decodeDigestWith @SHA256 NixBase32 <$> parseHash
68-
either fail pure $ Text <$> digest
69-
70-
-- | Parser for @fixed:<r?>:<ht>:<h>@
71-
--caFixed :: Parser ContentAddress
72-
caFixed = do
73-
_ <- "fixed:"
74-
narHashMode <- (Recursive <$ "r:") <|> (RegularFile <$ "")
75-
digest <- parseTypedDigest
76-
either fail pure $ Fixed narHashMode <$> digest
77-
78-
--parseTypedDigest :: Parser (Either String SomeNamedDigest)
79-
parseTypedDigest = System.Nix.Hash.mkNamedDigest <$> parseHashType <*> parseHash
80-
81-
--parseHashType :: Parser Text
82-
parseHashType =
83-
Data.Text.Encoding.decodeUtf8
84-
<$> ("sha256" <|> "sha512" <|> "sha1" <|> "md5") <* (":" <|> "-")
85-
86-
--parseHash :: Parser Text
87-
parseHash =
88-
Data.Text.Encoding.decodeUtf8
89-
<$> Data.Attoparsec.ByteString.Char8.takeWhile1 (/= ':')
90-
91-
-- | Schemes for hashing a Nix archive.
92-
--
93-
-- For backwards-compatibility reasons, there are two different modes
94-
-- here, even though 'Recursive' should be able to cover both.
95-
data NarHashMode
96-
= -- | Require the nar to represent a non-executable regular file.
97-
RegularFile
98-
| -- | Hash an arbitrary nar, including a non-executable regular
99-
-- file if so desired.
100-
Recursive
101-
deriving (Eq, Enum, Generic, Hashable, Ord, Show)
102-
103-
deriving via GenericArbitrary NarHashMode
104-
instance Arbitrary NarHashMode
113+
parseHashType :: Parser Text
114+
parseHashType =
115+
("sha256" <|> "sha512" <|> "sha1" <|> "md5") <* (":" <|> "-")
116+
117+
parseHash :: Parser Text
118+
parseHash = Data.Attoparsec.Text.takeWhile1 (/= ':')
Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,18 @@
1-
21
module ContentAddress where
32

43
import Test.Tasty.QuickCheck
54
import System.Nix.ContentAddress (ContentAddress)
65

7-
import qualified Data.Attoparsec.ByteString.Char8
8-
import qualified Data.Text.Lazy
6+
import qualified Data.Attoparsec.Text.Lazy
97
import qualified Data.Text.Lazy.Builder
10-
import qualified Data.Text.Encoding
118

129
import qualified System.Nix.ContentAddress
1310

1411
prop_caAddrRoundTrip :: ContentAddress -> Property
1512
prop_caAddrRoundTrip = \caAddr ->
16-
Data.Attoparsec.ByteString.Char8.parseOnly
13+
Data.Attoparsec.Text.Lazy.parseOnly
1714
System.Nix.ContentAddress.contentAddressParser
18-
( Data.Text.Encoding.encodeUtf8
19-
. Data.Text.Lazy.toStrict
20-
. Data.Text.Lazy.Builder.toLazyText
21-
$ System.Nix.ContentAddress.contentAddressBuilder
22-
caAddr
23-
)
15+
(Data.Text.Lazy.Builder.toLazyText
16+
(System.Nix.ContentAddress.contentAddressBuilder caAddr))
2417
=== pure caAddr
2518

hnix-store-remote/src/System/Nix/Store/Remote.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import Data.HashSet (HashSet)
3535
import Data.Map (Map)
3636
import Data.Text (Text)
3737
import qualified Control.Monad
38-
import qualified Data.Attoparsec.ByteString.Char8
38+
import qualified Data.Attoparsec.Text
3939
import qualified Data.Text.Encoding
4040
import qualified System.Nix.Hash
4141
--
@@ -246,15 +246,15 @@ queryPathInfoUncached path = do
246246
ultimate <- sockGetBool
247247

248248
_sigStrings <- fmap bsToText <$> sockGetStrings
249-
caString <- sockGetStr
249+
caString <- bsToText <$> sockGetStr
250250

251251
let
252252
-- XXX: signatures need pubkey from config
253253
sigs = Data.Set.empty
254254

255255
contentAddress =
256256
case
257-
Data.Attoparsec.ByteString.Char8.parseOnly
257+
Data.Attoparsec.Text.parseOnly
258258
System.Nix.ContentAddress.contentAddressParser
259259
caString
260260
of

0 commit comments

Comments
 (0)