Skip to content

Commit 6b496b7

Browse files
authored
Merge pull request #296 from haskell-nix/test-json
Sync a number of JSON instances with upstream Nix
2 parents 22bb94d + 4591e65 commit 6b496b7

29 files changed

+1163
-182
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "nix"]
2+
path = upstream-nix
3+
url = https://github.com/NixOS/nix

hnix-store-core/hnix-store-core.cabal

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ common commons
3535
, DerivingStrategies
3636
, DerivingVia
3737
, ExistentialQuantification
38+
, ImportQualifiedPost
3839
, FlexibleContexts
3940
, FlexibleInstances
4041
, GADTs
@@ -64,6 +65,7 @@ library
6465
, System.Nix.ContentAddress
6566
, System.Nix.Derivation
6667
, System.Nix.DerivedPath
68+
, System.Nix.Placeholder
6769
, System.Nix.Fingerprint
6870
, System.Nix.FileContentAddress
6971
, System.Nix.Hash
@@ -73,6 +75,7 @@ library
7375
, System.Nix.Signature
7476
, System.Nix.Store.Types
7577
, System.Nix.StorePath
78+
, System.Nix.StorePath.ContentAddressed
7679
, System.Nix.StorePath.Metadata
7780
build-depends:
7881
base >=4.12 && <5
@@ -106,6 +109,7 @@ test-suite core
106109
Derivation
107110
Fingerprint
108111
Hash
112+
Placeholder
109113
Signature
110114
StorePath
111115
hs-source-dirs:

hnix-store-core/src/System/Nix/Base.hs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
{-# LANGUAGE OverloadedStrings #-}
12
module System.Nix.Base
23
( BaseEncoding(Base16,NixBase32,Base64)
4+
, baseEncodingToText
5+
, textToBaseEncoding
36
, encodeWith
47
, decodeWith
58
) where
@@ -8,6 +11,7 @@ import Data.ByteString (ByteString)
811
import Data.Text (Text)
912
import GHC.Generics (Generic)
1013

14+
import Data.Text qualified
1115
import Data.Text.Encoding qualified
1216
import Data.ByteString.Base16 qualified
1317
import Data.ByteString.Base64 qualified
@@ -24,6 +28,21 @@ data BaseEncoding
2428
| Base64
2529
deriving (Bounded, Eq, Enum, Generic, Ord, Show)
2630

31+
-- | Convert BaseEncoding to its textual representation
32+
baseEncodingToText :: BaseEncoding -> Text
33+
baseEncodingToText = \case
34+
Base16 -> "base16"
35+
NixBase32 -> "nix32"
36+
Base64 -> "base64"
37+
38+
-- | Parse BaseEncoding from its textual representation
39+
textToBaseEncoding :: Text -> Either String BaseEncoding
40+
textToBaseEncoding = \case
41+
"base16" -> Right Base16
42+
"nix32" -> Right NixBase32
43+
"base64" -> Right Base64
44+
other -> Left $ "Unknown base encoding: " ++ Data.Text.unpack other
45+
2746
-- | Encode @ByteString@ with @Base@ encoding, produce @Text@.
2847
encodeWith :: BaseEncoding -> ByteString -> Text
2948
encodeWith Base16 =

hnix-store-core/src/System/Nix/ContentAddress.hs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
module System.Nix.ContentAddress (
44
ContentAddress (..)
5+
, methodToText
6+
, textToMethod
57
, ContentAddressMethod (..)
68
, contentAddressBuilder
79
, contentAddressParser
@@ -12,15 +14,16 @@ module System.Nix.ContentAddress (
1214
import Control.Applicative
1315
import Crypto.Hash (Digest)
1416
import Data.Attoparsec.Text (Parser)
17+
import Data.Attoparsec.Text qualified
1518
import Data.Dependent.Sum (DSum)
1619
import Data.Text (Text)
20+
import Data.Text qualified
21+
import Data.Text.Lazy qualified
1722
import Data.Text.Lazy.Builder (Builder)
23+
import Data.Text.Lazy.Builder qualified
1824
import GHC.Generics (Generic)
19-
import System.Nix.Hash (HashAlgo)
2025

21-
import Data.Attoparsec.Text qualified
22-
import Data.Text.Lazy qualified
23-
import Data.Text.Lazy.Builder qualified
26+
import System.Nix.Hash (HashAlgo)
2427
import System.Nix.Hash qualified
2528

2629
data ContentAddressMethod
@@ -32,6 +35,19 @@ data ContentAddressMethod
3235
-- file contents.
3336
deriving (Eq, Generic, Ord, Show)
3437

38+
methodToText :: ContentAddressMethod -> Text
39+
methodToText = \case
40+
ContentAddressMethod_Flat -> "flat"
41+
ContentAddressMethod_NixArchive -> "nar"
42+
ContentAddressMethod_Text -> "text"
43+
44+
textToMethod :: Text -> Either String ContentAddressMethod
45+
textToMethod = \case
46+
"flat" -> Right ContentAddressMethod_Flat
47+
"nar" -> Right ContentAddressMethod_NixArchive
48+
"text" -> Right ContentAddressMethod_Text
49+
name -> Left $ "Unknown store object content-addressing method " <> Data.Text.unpack name
50+
3551
-- | An address for a content-addressable store path, i.e. one whose
3652
-- store path hash is purely a function of its contents (as opposed to
3753
-- paths that are derivation outputs, whose hashes are a function of

hnix-store-core/src/System/Nix/DerivedPath.hs

Lines changed: 69 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
module System.Nix.DerivedPath (
44
OutputsSpec(..)
5+
, SingleDerivedPath(..)
6+
, parseSingleDerivedPath
7+
, singleDerivedPathToText
58
, DerivedPath(..)
69
, ParseOutputsError(..)
710
, parseOutputsSpec
@@ -19,6 +22,7 @@ import System.Nix.StorePath (StoreDir(..), StorePath, InvalidPathError)
1922
import Data.Bifunctor qualified
2023
import Data.ByteString.Char8 qualified
2124
import Data.Set qualified
25+
import Data.List qualified
2226
import Data.Text qualified
2327
import System.Nix.OutputName qualified
2428
import System.Nix.StorePath qualified
@@ -30,11 +34,19 @@ data OutputsSpec =
3034
-- ^ Set of specific outputs
3135
deriving (Eq, Generic, Ord, Show)
3236

37+
data SingleDerivedPath =
38+
SingleDerivedPath_Opaque StorePath
39+
-- ^ Fully evaluated store path that can't be built
40+
-- but can be fetched
41+
| SingleDerivedPath_Built SingleDerivedPath OutputName
42+
-- ^ Derivation path and the output built from it
43+
deriving (Eq, Generic, Ord, Show)
44+
3345
data DerivedPath =
3446
DerivedPath_Opaque StorePath
3547
-- ^ Fully evaluated store path that can't be built
3648
-- but can be fetched
37-
| DerivedPath_Built StorePath OutputsSpec
49+
| DerivedPath_Built SingleDerivedPath OutputsSpec
3850
-- ^ Derivation path and the outputs built from it
3951
deriving (Eq, Generic, Ord, Show)
4052

@@ -45,15 +57,19 @@ data ParseOutputsError =
4557
| ParseOutputsError_NoPrefix StoreDir Text
4658
deriving (Eq, Ord, Show)
4759

60+
parseOutputName :: Text -> Either ParseOutputsError OutputName
61+
parseOutputName =
62+
( Data.Bifunctor.first
63+
ParseOutputsError_InvalidName
64+
. System.Nix.OutputName.mkOutputName
65+
)
66+
4867
parseOutputsSpec :: Text -> Either ParseOutputsError OutputsSpec
4968
parseOutputsSpec t
5069
| t == "*" = Right OutputsSpec_All
5170
| otherwise = do
5271
names <- mapM
53-
( Data.Bifunctor.first
54-
ParseOutputsError_InvalidName
55-
. System.Nix.OutputName.mkOutputName
56-
)
72+
parseOutputName
5773
(Data.Text.splitOn "," t)
5874
if null names
5975
then Left ParseOutputsError_NoNames
@@ -65,10 +81,36 @@ outputsSpecToText = \case
6581
OutputsSpec_Names ns ->
6682
Data.Text.intercalate
6783
","
68-
(fmap System.Nix.OutputName.unOutputName
84+
(fmap (System.Nix.StorePath.unStorePathName . System.Nix.OutputName.unOutputName)
6985
(Data.Set.toList ns)
7086
)
7187

88+
parseSingleDerivedPath
89+
:: StoreDir
90+
-> Text
91+
-> Either ParseOutputsError SingleDerivedPath
92+
parseSingleDerivedPath root@(StoreDir sd) path =
93+
let -- We need to do a bit more legwork for case
94+
-- when StoreDir contains '!'
95+
-- which is generated by its Arbitrary instance
96+
textRoot = Data.Text.pack
97+
$ Data.ByteString.Char8.unpack sd
98+
99+
in case Data.Text.stripPrefix textRoot path of
100+
Nothing -> Left $ ParseOutputsError_NoPrefix root path
101+
Just woRoot ->
102+
case Data.Text.splitOn "!" woRoot of
103+
[] -> error "internal error, this function should return NonEmpty"
104+
(pathNoPrefix : outputs) -> Data.List.foldl'
105+
(liftA2 SingleDerivedPath_Built)
106+
(SingleDerivedPath_Opaque
107+
<$> (convertError
108+
$ System.Nix.StorePath.parsePathFromText
109+
root
110+
(textRoot <> pathNoPrefix)
111+
))
112+
(parseOutputName <$> outputs)
113+
72114
parseDerivedPath
73115
:: StoreDir
74116
-> Text
@@ -83,8 +125,8 @@ parseDerivedPath root@(StoreDir sd) path =
83125
in case Data.Text.stripPrefix textRoot path of
84126
Nothing -> Left $ ParseOutputsError_NoPrefix root path
85127
Just woRoot ->
86-
case Data.Text.breakOn "!" woRoot of
87-
(pathNoPrefix, r) ->
128+
case Data.Text.breakOnEnd "!" woRoot of
129+
(r, suffix) ->
88130
if Data.Text.null r
89131
then DerivedPath_Opaque
90132
<$> (convertError
@@ -93,23 +135,30 @@ parseDerivedPath root@(StoreDir sd) path =
93135
path
94136
)
95137
else DerivedPath_Built
96-
<$> (convertError
97-
$ System.Nix.StorePath.parsePathFromText
98-
root
99-
(textRoot <> pathNoPrefix)
100-
)
101-
<*> parseOutputsSpec (Data.Text.drop (Data.Text.length "!") r)
102-
where
103-
convertError
104-
:: Either InvalidPathError a
105-
-> Either ParseOutputsError a
106-
convertError = Data.Bifunctor.first ParseOutputsError_InvalidPath
138+
<$> parseSingleDerivedPath
139+
root
140+
(textRoot <> Data.Text.dropEnd (Data.Text.length "!") r)
141+
<*> parseOutputsSpec suffix
142+
143+
convertError
144+
:: Either InvalidPathError a
145+
-> Either ParseOutputsError a
146+
convertError = Data.Bifunctor.first ParseOutputsError_InvalidPath
147+
148+
singleDerivedPathToText :: StoreDir -> SingleDerivedPath -> Text
149+
singleDerivedPathToText root = \case
150+
SingleDerivedPath_Opaque p ->
151+
System.Nix.StorePath.storePathToText root p
152+
SingleDerivedPath_Built p o ->
153+
singleDerivedPathToText root p
154+
<> "!"
155+
<> System.Nix.StorePath.unStorePathName (System.Nix.OutputName.unOutputName o)
107156

108157
derivedPathToText :: StoreDir -> DerivedPath -> Text
109158
derivedPathToText root = \case
110159
DerivedPath_Opaque p ->
111160
System.Nix.StorePath.storePathToText root p
112161
DerivedPath_Built p os ->
113-
System.Nix.StorePath.storePathToText root p
162+
singleDerivedPathToText root p
114163
<> "!"
115164
<> outputsSpecToText os
Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{-# LANGUAGE OverloadedStrings #-}
12
{-# LANGUAGE DeriveAnyClass #-}
23
{-|
34
Description : Derived path output names
@@ -6,24 +7,41 @@ Description : Derived path output names
67
module System.Nix.OutputName
78
( OutputName(..)
89
, mkOutputName
10+
, outputStoreObjectName
911
-- * Re-exports
1012
, System.Nix.StorePath.InvalidNameError(..)
11-
, System.Nix.StorePath.parseNameText
1213
) where
1314

1415
import Data.Hashable (Hashable)
1516
import Data.Text (Text)
1617
import GHC.Generics (Generic)
17-
import System.Nix.StorePath (InvalidNameError)
18-
19-
import System.Nix.StorePath qualified
18+
import System.Nix.StorePath
19+
( StorePathName
20+
, InvalidNameError(..)
21+
, mkStorePathName
22+
, unStorePathName
23+
)
2024

2125
-- | Name of the derived path output
2226
-- Typically used for "dev", "doc" sub-outputs
2327
newtype OutputName = OutputName
2428
{ -- | Extract the contents of the name.
25-
unOutputName :: Text
29+
unOutputName :: StorePathName
2630
} deriving (Eq, Generic, Hashable, Ord, Show)
2731

2832
mkOutputName :: Text -> Either InvalidNameError OutputName
29-
mkOutputName = fmap OutputName . System.Nix.StorePath.parseNameText
33+
mkOutputName = fmap OutputName . System.Nix.StorePath.mkStorePathName
34+
35+
-- | Compute the name of an output (store object) from the output name
36+
-- and the derivation name
37+
--
38+
-- Invalid character errors are not possible, but total length errors are
39+
outputStoreObjectName :: StorePathName -> OutputName -> Either InvalidNameError StorePathName
40+
outputStoreObjectName drvName outputName = case outputNameS of
41+
"out" -> Right drvName
42+
_ -> System.Nix.StorePath.mkStorePathName $
43+
unStorePathName drvName
44+
<> "-"
45+
<> outputNameS
46+
where
47+
outputNameS = unStorePathName $ unOutputName outputName

0 commit comments

Comments
 (0)