core: improve mkStorePathName and its errors, add test

This commit is contained in:
sorki 2023-12-05 07:38:35 +01:00
parent 9cf2e1aa34
commit 70443c884b
3 changed files with 57 additions and 21 deletions

View File

@ -102,6 +102,7 @@ test-suite core
Fingerprint Fingerprint
Hash Hash
Signature Signature
StorePath
hs-source-dirs: hs-source-dirs:
tests tests
build-tool-depends: build-tool-depends:

View File

@ -20,7 +20,6 @@ module System.Nix.StorePath
-- * Manipulating 'StorePathName' -- * Manipulating 'StorePathName'
, InvalidNameError(..) , InvalidNameError(..)
, mkStorePathName , mkStorePathName
, validStorePathName
-- * Reason why a path is not valid -- * Reason why a path is not valid
, InvalidPathError(..) , InvalidPathError(..)
, -- * Rendering out 'StorePath's , -- * Rendering out 'StorePath's
@ -119,9 +118,9 @@ mkStorePathHashPart =
-- | Reason why a path name or output name is not valid -- | Reason why a path name or output name is not valid
data InvalidNameError data InvalidNameError
= EmptyName = EmptyName
| NameTooLong | NameTooLong Int
| LeadingDot | LeadingDot
| InvalidCharacter | InvalidCharacters Text
deriving (Eq, Generic, Hashable, Ord, Show) deriving (Eq, Generic, Hashable, Ord, Show)
-- | Reason why a path is not valid -- | Reason why a path is not valid
@ -137,24 +136,22 @@ data InvalidPathError
-- | Make @StorePathName@ from @Text@ (name part of the @StorePath@) -- | Make @StorePathName@ from @Text@ (name part of the @StorePath@)
-- or fail with @InvalidNameError@ if it isn't valid -- or fail with @InvalidNameError@ if it isn't valid
mkStorePathName :: Text -> Either InvalidNameError StorePathName mkStorePathName :: Text -> Either InvalidNameError StorePathName
mkStorePathName n = mkStorePathName n
if validStorePathName n | n == ""
then pure $ StorePathName n = Left EmptyName
else Left $ reasonInvalid n | Data.Text.length n > 211
= Left $ NameTooLong (Data.Text.length n)
reasonInvalid :: Text -> InvalidNameError | Data.Text.head n == '.'
reasonInvalid n = Left $ LeadingDot
| n == "" = EmptyName | not
| Data.Text.length n > 211 = NameTooLong $ Data.Text.null
| Data.Text.head n == '.' = LeadingDot $ Data.Text.filter
| otherwise = InvalidCharacter (not . validStorePathNameChar)
n
validStorePathName :: Text -> Bool = Left
validStorePathName n = $ InvalidCharacters
n /= "" $ Data.Text.filter (not . validStorePathNameChar) n
&& Data.Text.length n <= 211 | otherwise = pure $ StorePathName n
&& Data.Text.head n /= '.'
&& Data.Text.all validStorePathNameChar n
validStorePathNameChar :: Char -> Bool validStorePathNameChar :: Char -> Bool
validStorePathNameChar c = validStorePathNameChar c =

View File

@ -0,0 +1,38 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
module StorePath where
import Test.Hspec (Spec, describe, it, shouldBe, shouldSatisfy)
import qualified Data.Either
import qualified Data.Text
import System.Nix.StorePath (mkStorePathName)
spec_storePath :: Spec
spec_storePath = do
describe "StorePathName" $ do
it "parses valid name" $
mkStorePathName "name-dev.dotok"
`shouldSatisfy`
Data.Either.isRight
it "fails on empty" $
mkStorePathName mempty
`shouldBe`
Left EmptyName
it "fails on too long" $
mkStorePathName (Data.Text.replicate 256 "n")
`shouldBe`
Left (NameTooLong 256)
it "fails on leading dot" $
mkStorePathName ".ab"
`shouldBe`
Left LeadingDot
it "fails on invalid characters" $
mkStorePathName "ab!cd#@"
`shouldBe`
Left (InvalidCharacters "!#@")