22
33module 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)
1922import Data.Bifunctor qualified
2023import Data.ByteString.Char8 qualified
2124import Data.Set qualified
25+ import Data.List qualified
2226import Data.Text qualified
2327import System.Nix.OutputName qualified
2428import 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+
3345data 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+
4867parseOutputsSpec :: Text -> Either ParseOutputsError OutputsSpec
4968parseOutputsSpec 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+
72114parseDerivedPath
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
108157derivedPathToText :: StoreDir -> DerivedPath -> Text
109158derivedPathToText 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
0 commit comments