packages feed

nix-narinfo (empty) → 0.1.0.0

raw patch · 13 files changed

+405/−0 lines, 13 filesdep +QuickCheckdep +attoparsecdep +basesetup-changed

Dependencies added: QuickCheck, attoparsec, base, containers, filepath, hspec, nix-narinfo, text

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Richard Marko (c) 2020++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Author name here nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,7 @@+nix-narinfo+===========++Parse and build `.narinfo` files.++Loosely based on [cachix-api](https://github.com/cachix/cachix/tree/master/cachix-api) `NarInfo` type.+Inspired by [nix-derivation](https://github.com/Gabriel439/Haskell-Nix-Derivation-Library/) library.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ app/Main.hs view
@@ -0,0 +1,15 @@+module Main where++import Nix.NarInfo++import Data.Attoparsec.Text+import Data.Text.IO+import Data.Text.Lazy.Builder+import Data.Text.Lazy.IO++main = do+  txt <- Data.Text.IO.readFile "./test/samples/0"+  case Data.Attoparsec.Text.parseOnly parseNarInfo txt of+    Left e -> error e+    Right ni -> Data.Text.Lazy.IO.putStr $+      Data.Text.Lazy.Builder.toLazyText $ buildNarInfo ni
+ nix-narinfo.cabal view
@@ -0,0 +1,68 @@+name:                nix-narinfo+version:             0.1.0.0+synopsis:            Parse and render .narinfo files+description:         Support for parsing and rendering Nix .narinfo files+homepage:            https://github.com/sorki/nix-narinfo+license:             BSD3+license-file:        LICENSE+author:              Richard Marko+maintainer:          srk@48.io+copyright:           2020 Richard Marko+category:            Nix+build-type:          Simple+cabal-version:       >=1.10++extra-source-files:+    README.md++library+  hs-source-dirs:      src+  exposed-modules:     Nix.NarInfo+  other-modules:       Nix.NarInfo.Builder+                     , Nix.NarInfo.Parser+                     , Nix.NarInfo.Types+  build-depends:       base >= 4.7 && < 5+                     , containers+                     , text+                     , attoparsec+  default-language:    Haskell2010++executable pretty-narinfo+  hs-source-dirs:      app+  main-is:             Main.hs+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N+  build-depends:       base+                     , attoparsec+                     , text+                     , nix-narinfo+  default-language:    Haskell2010+++test-suite nix-narinfo-samples+  type:                exitcode-stdio-1.0+  hs-source-dirs:      test+  main-is:             Spec.hs+  other-modules:       ParseSpec+                       SpecHelper+  build-depends:       base >= 4.7 && < 5+                     , attoparsec+                     , text+                     , nix-narinfo+                     , hspec+  default-language:    Haskell2010++test-suite nix-narinfo-property+  type:                exitcode-stdio-1.0+  hs-source-dirs:      test+  main-is:             Property.hs+  build-depends:       base >= 4.7 && < 5+                     , attoparsec+                     , filepath+                     , text+                     , nix-narinfo+                     , QuickCheck+  default-language:    Haskell2010++source-repository head+  type:     git+  location: https://github.com/sorki/nix-narinfo
+ src/Nix/NarInfo.hs view
@@ -0,0 +1,10 @@+module Nix.NarInfo (+    module Nix.NarInfo.Builder+  , module Nix.NarInfo.Parser+  , module Nix.NarInfo.Types+  ) where++import Nix.NarInfo.Builder+import Nix.NarInfo.Parser+import Nix.NarInfo.Types+
+ src/Nix/NarInfo/Builder.hs view
@@ -0,0 +1,58 @@+{-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE OverloadedStrings #-}++module Nix.NarInfo.Builder+    ( -- * Builder+      buildNarInfo+    , buildNarInfoWith+    ) where++import Data.Set (Set)+import Data.Text (Text)+import Data.Text.Lazy.Builder (Builder)+import Nix.NarInfo.Types++import qualified Control.Applicative+import qualified Data.Char+import qualified Data.Set+import qualified Data.List+import qualified Data.Text+import qualified Data.Text.Lazy.Builder++buildNarInfo :: (NarInfo FilePath Text Text) -> Builder+buildNarInfo = buildNarInfoWith+  (\_needPrefix fp -> Data.Text.Lazy.Builder.fromString fp)+  Data.Text.Lazy.Builder.fromText+  Data.Text.Lazy.Builder.fromText++buildNarInfoWith :: (Ord fp)+                 => (Bool -> fp -> Builder)+                 -> (txt -> Builder)+                 -> (hash -> Builder)+                 -> NarInfo fp txt hash+                 -> Builder+buildNarInfoWith filepath string hash (NarInfo{..}) =+     keyPath "StorePath"   storePath+  <> key     "URL"         url+  <> key     "Compression" compression+  <> keyHash "FileHash"    fileHash+  <> keyNum  "FileSize"    fileSize+  <> keyHash "NarHash"     narHash+  <> keyNum  "NarSize"     narSize++  <> key'    "References"  (mconcat+      $ Data.List.intersperse " "+        $ map (filepath False)+          $ Data.List.sort $ Data.Set.toList references)++  <> optKey  "Deriver"     deriver+  <> optKey  "System"      system+  <> optKey  "Sig"         sig+  <> optKey  "Ca"          ca+  where+    key' k v    = k <> ": " <> v <> "\n"+    key k v     = key' k (string v)+    keyNum k v  = key' k (Data.Text.Lazy.Builder.fromString . show $ v)+    keyPath k v = key' k (filepath True v)+    keyHash k v = key' k (hash v)+    optKey k    = maybe mempty (key k)
+ src/Nix/NarInfo/Parser.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE OverloadedStrings #-}++module Nix.NarInfo.Parser+  ( -- * Parser+    parseNarInfo+  , parseNarInfoWith+  ) where++import Data.Set (Set)+import Data.Text (Text)+import Data.Attoparsec.Text (Parser)+import Nix.NarInfo.Types++import qualified Control.Applicative+import qualified Data.Char+import qualified Data.Set+import qualified Data.Text+import qualified Data.Attoparsec.Text++parseNarInfo :: Parser (NarInfo FilePath Text Text)+parseNarInfo = parseNarInfoWith pathParse textParse hashParse+  where+    textParse = Data.Attoparsec.Text.takeWhile (not . Data.Char.isSpace)+    pathParse _hasPrefix = Data.Text.unpack <$> textParse+    hashParse = textParse++parseNarInfoWith :: (Ord fp)+                 => (Bool -> Parser fp) -- True when path prefix is present+                 -> Parser txt+                 -> Parser hash+                 -> Parser (NarInfo fp txt hash)+parseNarInfoWith pathParser textParser hashParser = do+  storePath   <- keyPath "StorePath"+  url         <- key     "URL"+  compression <- key     "Compression"+  fileHash    <- keyHash "FileHash"+  fileSize    <- keyNum  "FileSize"+  narHash     <- keyHash "NarHash"+  narSize     <- keyNum  "NarSize"++  references  <- Data.Set.fromList <$> (parseKey "References" $+    (pathParser False) `Data.Attoparsec.Text.sepBy` Data.Attoparsec.Text.char ' ')++  deriver     <- optKey "Deriver"+  system      <- optKey "System"+  sig         <- optKey "Sig"+  ca          <- optKey "Ca"++  return $ NarInfo {..}+  where+    parseKey key parser = do+      Data.Attoparsec.Text.string key+      Data.Attoparsec.Text.string ": "+      out <- parser+      Data.Attoparsec.Text.char '\n'+      return out++    key = flip parseKey textParser+    optKey = Control.Applicative.optional . key+    keyNum x = parseKey x Data.Attoparsec.Text.decimal+    keyPath x = parseKey x (pathParser True)+    keyHash x = parseKey x hashParser
+ src/Nix/NarInfo/Types.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE DeriveGeneric     #-}+{-# LANGUAGE DeriveAnyClass    #-}+++module Nix.NarInfo.Types+    ( -- * Types+      NarInfo(..)+    , SimpleNarInfo+    ) where++import Data.Set (Set)+import Data.Text (Text)+import GHC.Generics++-- NarInfo URL includes storePath hash and .narinfo suffix+-- Note: storePath is with prefix but references are shortRefs (without /nix/store prefix)+--+-- Both `parseNarInfoWith` and `buildNarInfoWith` need+-- a path parser/printer which takes an argument+-- whether the path is prefixed or not.+--+data NarInfo fp txt hash = NarInfo+  { -- | Absolute path of the derivation in nix store.+    storePath   :: fp+  , -- | Relative url (to current domain) to download nar file.+    url         :: txt+  , -- | Name of the compression algorithm, eg. xz.+    compression :: txt+  , -- | Hash of the compressed nar file.+    -- NOTE: to compute use "nix-hash --type sha256 --flat"+    -- (srk) this isn't fixed to sha256 but a prefix indicates the type e.g.: sha256:1a6lzf...+    -- default is sha256 thought+    fileHash    :: hash+  , -- | File size of compressed nar file.+    -- NOTE: du -b+    fileSize    :: Integer+  , -- | Hash of the decompressed nar file.+    -- NOTE: to compute use "nix-hash --type sha256 --flat --base32"+    -- (srk) this isn't fixed to sha256 but a prefix indicates the type e.g.: sha256:1a6lzf...+    -- default is sha256 thought+    narHash     :: hash+  , -- | File size of decompressed nar file.+    -- NOTE: du -b+    narSize     :: Integer+  , -- | Immediate dependencies of the storePath.+    -- NOTE: nix-store -q --references+    references  :: Set fp+  , -- | Relative store path (to nix store root) of the deriver.+    -- NOTE: nix-store -q --deriver+    deriver     :: Maybe txt+  , -- | System+    system      :: Maybe txt+  , -- | Signature of fields: storePath, narHash, narSize, refs.+    sig         :: Maybe txt+  , -- | Content-addressed+    -- Store path is computed from a cryptographic hash+    -- of the contents of the path, plus some other bits of data like+    -- the "name" part of the path.+    ca          :: Maybe txt+  }+  deriving (Eq, Generic, Show)++type SimpleNarInfo = NarInfo FilePath Text Text
+ test/ParseSpec.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell   #-}++module ParseSpec where++import Data.Attoparsec.Text+import Data.Text.IO+import Data.Text.Lazy+import Data.Text.Lazy.Builder+import Data.Text.Lazy.IO++import SpecHelper++roundTrip fname = do+  txt <- Data.Text.IO.readFile $ "./test/samples/" ++ fname+  case Data.Attoparsec.Text.parseOnly parseNarInfo txt of+    Left e -> error e+    Right ni -> do+      let built = Data.Text.Lazy.Builder.toLazyText $ buildNarInfo ni+      (Data.Text.Lazy.toStrict built) `shouldBe` txt++spec :: Spec+spec = do+  it "roundtrips samples" $ do+    mapM_ (roundTrip . show) [0]++main :: IO ()+main = hspec spec
+ test/Property.hs view
@@ -0,0 +1,53 @@+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE FlexibleInstances #-}++{-# OPTIONS_GHC -fno-warn-orphans #-}++module Main where++import Data.Text (Text)+import System.FilePath+import Nix.NarInfo (NarInfo(..))+import Test.QuickCheck (Arbitrary(..))++import qualified Data.Attoparsec.Text.Lazy+import qualified Data.Text+import qualified Data.Text.Lazy.Builder+import qualified Nix.NarInfo+import qualified Test.QuickCheck++instance Arbitrary Text where+    arbitrary = fmap Data.Text.pack arbitrary++instance Arbitrary (NarInfo FilePath Text Text) where+    arbitrary = do+        storePath   <- arbitrary+        url         <- arbitrary+        compression <- arbitrary+        fileHash    <- arbitrary+        fileSize    <- arbitrary+        narHash     <- arbitrary+        narSize     <- arbitrary+        references  <- arbitrary+        deriver     <- arbitrary+        system      <- arbitrary+        sig         <- arbitrary+        ca          <- arbitrary+        return (NarInfo {..})++property :: NarInfo FilePath Text Text -> Bool+property narinfo0 = eitherRes == Right narinfo0+  where+    builder = Nix.NarInfo.buildNarInfo narinfo0++    text = Data.Text.Lazy.Builder.toLazyText builder++    result =+        Data.Attoparsec.Text.Lazy.parse Nix.NarInfo.parseNarInfo text++    eitherRes =+        Data.Attoparsec.Text.Lazy.eitherResult result++main :: IO ()+main = Test.QuickCheck.quickCheck property
+ test/Spec.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
+ test/SpecHelper.hs view
@@ -0,0 +1,7 @@+module SpecHelper+    ( module Test.Hspec+    , module Nix.NarInfo+    ) where++import Test.Hspec+import Nix.NarInfo