From cab6459db5f3f28704993921a24c2de3d2df534d Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Sun, 4 Jun 2017 19:39:27 -0700 Subject: [PATCH 01/58] Initial commit --- .travis.yml | 85 +++++++++++++++++++++ LICENSE | 24 ++++++ Setup.hs | 2 + default.nix | 14 ++++ nix-derivation.cabal | 47 ++++++++++++ release.nix | 27 +++++++ src/Nix/Derivation.hs | 10 +++ src/Nix/Derivation/Builder.hs | 94 +++++++++++++++++++++++ src/Nix/Derivation/Parser.hs | 136 ++++++++++++++++++++++++++++++++++ src/Nix/Derivation/Types.hs | 28 +++++++ tests/Example.hs | 20 +++++ tests/example.drv | 1 + 12 files changed, 488 insertions(+) create mode 100644 .travis.yml create mode 100644 LICENSE create mode 100644 Setup.hs create mode 100644 default.nix create mode 100644 nix-derivation.cabal create mode 100644 release.nix create mode 100644 src/Nix/Derivation.hs create mode 100644 src/Nix/Derivation/Builder.hs create mode 100644 src/Nix/Derivation/Parser.hs create mode 100644 src/Nix/Derivation/Types.hs create mode 100644 tests/Example.hs create mode 100644 tests/example.drv diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..58b9b37f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,85 @@ +# This file has been generated -- see https://github.com/hvr/multi-ghc-travis +language: c +sudo: false + +cache: + directories: + - $HOME/.cabsnap + - $HOME/.cabal/packages + +before_cache: + - rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log + - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.tar + +matrix: + include: + - env: CABALVER=1.16 GHCVER=7.6.3 + compiler: ": #GHC 7.6.3" + addons: {apt: {packages: [cabal-install-1.16,ghc-7.6.3], sources: [hvr-ghc]}} + - env: CABALVER=1.18 GHCVER=7.8.4 + compiler: ": #GHC 7.8.4" + addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4], sources: [hvr-ghc]}} + - env: CABALVER=1.22 GHCVER=7.10.3 + compiler: ": #GHC 7.10.3" + addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3], sources: [hvr-ghc]}} + - env: CABALVER=1.24 GHCVER=8.0.2 + compiler: ": #GHC 8.0.2" + addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.2], sources: [hvr-ghc]}} + +before_install: + - unset CC + - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH + +install: + - cabal --version + - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]" + - if [ -f $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz ]; + then + zcat $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz > + $HOME/.cabal/packages/hackage.haskell.org/00-index.tar; + fi + - travis_retry cabal update -v + - sed -i 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config + - cabal install --only-dependencies --enable-tests --enable-benchmarks --dry -v > installplan.txt + - sed -i -e '1,/^Resolving /d' installplan.txt; cat installplan.txt + +# check whether current requested install-plan matches cached package-db snapshot + - if diff -u $HOME/.cabsnap/installplan.txt installplan.txt; + then + echo "cabal build-cache HIT"; + rm -rfv .ghc; + cp -a $HOME/.cabsnap/ghc $HOME/.ghc; + cp -a $HOME/.cabsnap/lib $HOME/.cabsnap/share $HOME/.cabsnap/bin $HOME/.cabal/; + else + echo "cabal build-cache MISS"; + rm -rf $HOME/.cabsnap; + mkdir -p $HOME/.ghc $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin; + cabal install --only-dependencies --enable-tests --enable-benchmarks; + fi + +# snapshot package-db on cache miss + - if [ ! -d $HOME/.cabsnap ]; + then + echo "snapshotting package-db to build-cache"; + mkdir $HOME/.cabsnap; + cp -a $HOME/.ghc $HOME/.cabsnap/ghc; + cp -a $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin installplan.txt $HOME/.cabsnap/; + fi + +# Here starts the actual work to be performed for the package under test; +# any command which exits with a non-zero exit code causes the build to fail. +script: + - if [ -f configure.ac ]; then autoreconf -i; fi + - cabal configure --enable-tests --enable-benchmarks -v2 # -v2 provides useful information for debugging + - cabal build # this builds all libraries and executables (including tests/benchmarks) + - cabal test + - cabal check + - cabal sdist # tests that a source-distribution can be generated + +# Check that the resulting source distribution can be built & installed. +# If there are no other `.tar.gz` files in `dist`, this can be even simpler: +# `cabal install --force-reinstalls dist/*-*.tar.gz` + - SRC_TGZ=$(cabal info . | awk '{print $2;exit}').tar.gz && + (cd dist && cabal install --force-reinstalls "$SRC_TGZ") + +# EOF diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..f821e299 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2017 Gabriel Gonzalez +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 Gabriel Gonzalez 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. diff --git a/Setup.hs b/Setup.hs new file mode 100644 index 00000000..9a994af6 --- /dev/null +++ b/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/default.nix b/default.nix new file mode 100644 index 00000000..7df9d9b8 --- /dev/null +++ b/default.nix @@ -0,0 +1,14 @@ +{ mkDerivation, attoparsec, base, containers, stdenv +, system-filepath, text, vector +}: +mkDerivation { + pname = "nix-derivation"; + version = "1.0.0"; + src = ./.; + libraryHaskellDepends = [ + attoparsec base containers system-filepath text vector + ]; + testHaskellDepends = [ attoparsec base text ]; + description = "Parse and render *.drv files"; + license = stdenv.lib.licenses.bsd3; +} diff --git a/nix-derivation.cabal b/nix-derivation.cabal new file mode 100644 index 00000000..703fea49 --- /dev/null +++ b/nix-derivation.cabal @@ -0,0 +1,47 @@ +Name: nix-derivation +Version: 1.0.0 +Cabal-Version: >=1.8.0.2 +Build-Type: Simple +Tested-With: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2 +License: BSD3 +License-File: LICENSE +Copyright: 2017 Gabriel Gonzalez +Author: Gabriel Gonzalez +Maintainer: Gabriel439@gmail.com +Bug-Reports: https://github.com/Gabriel439/Haskell-Nix-Derivation-Library/issues +Synopsis: Parse and render *.drv files +Description: + Use this package to parse and render Nix derivation files (i.e. *.drv files) +Category: System +Extra-Source-Files: + tests/example.drv +Source-Repository head + Type: git + Location: https://github.com/Gabriel439/Haskell-Nix-Derivation-Library + +Library + Hs-Source-Dirs: src + Build-Depends: + base >= 4.6.0.0 && < 5 , + attoparsec >= 0.12.0.0 && < 0.14, + containers < 0.6 , + system-filepath >= 0.3.1 && < 0.5 , + text >= 0.8.0.0 && < 1.3 , + vector < 0.13 + Exposed-Modules: + Nix.Derivation, + Nix.Derivation.Builder, + Nix.Derivation.Parser, + Nix.Derivation.Types + GHC-Options: -Wall + +Test-Suite example + Type: exitcode-stdio-1.0 + Hs-Source-Dirs: tests + Main-Is: Example.hs + GHC-Options: -Wall + Build-Depends: + base >= 4.6.0.0 && < 5 , + attoparsec >= 0.12.0.0 && < 0.14, + nix-derivation , + text >= 0.8.0.0 && < 1.3 diff --git a/release.nix b/release.nix new file mode 100644 index 00000000..eca790dd --- /dev/null +++ b/release.nix @@ -0,0 +1,27 @@ +# You can build this repository using Nix by running: +# +# $ nix-build -A nix-derivation release.nix +# +# You can also open up this repository inside of a Nix shell by running: +# +# $ nix-shell -A nix-derivation.env release.nix +# +# ... and then Nix will supply the correct Haskell development environment for +# you +let + config = { + packageOverrides = pkgs: { + haskellPackages = pkgs.haskellPackages.override { + overrides = haskellPackagesNew: haskellPackagesOld: { + nix-derivation = haskellPackagesNew.callPackage ./default.nix { }; + }; + }; + }; + }; + + pkgs = + import { inherit config; }; + +in + { nix-derivation = pkgs.haskellPackages.nix-derivation; + } diff --git a/src/Nix/Derivation.hs b/src/Nix/Derivation.hs new file mode 100644 index 00000000..726ea3dd --- /dev/null +++ b/src/Nix/Derivation.hs @@ -0,0 +1,10 @@ +module Nix.Derivation + ( -- Re-exports + module Nix.Derivation.Types + , module Nix.Derivation.Parser + , module Nix.Derivation.Builder + ) where + +import Nix.Derivation.Builder +import Nix.Derivation.Parser +import Nix.Derivation.Types diff --git a/src/Nix/Derivation/Builder.hs b/src/Nix/Derivation/Builder.hs new file mode 100644 index 00000000..ae5ddc7a --- /dev/null +++ b/src/Nix/Derivation/Builder.hs @@ -0,0 +1,94 @@ +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RecordWildCards #-} + +module Nix.Derivation.Builder where + +import Data.Foldable (foldMap) +import Data.Map (Map) +import Data.Monoid ((<>)) +import Data.Set (Set) +import Data.Text (Text) +import Data.Text.Lazy.Builder (Builder) +import Data.Vector (Vector) +import Filesystem.Path.CurrentOS (FilePath) +import Nix.Derivation.Types (Derivation(..), DerivationOutput(..)) +import Prelude hiding (FilePath) + +import qualified Data.Map +import qualified Data.Set +import qualified Data.Text +import qualified Data.Text.Lazy.Builder +import qualified Data.Vector +import qualified Filesystem.Path.CurrentOS + +buildDerivation :: Derivation -> Builder +buildDerivation (Derivation {..}) = + "Derive(" + <> mapOf keyValue0 outputs + <> "," + <> mapOf keyValue1 inputDrvs + <> "," + <> setOf filepath inputSrcs + <> "," + <> string platform + <> "," + <> filepath builder + <> "," + <> vectorOf string args + <> "," + <> mapOf keyValue2 env + <> ")" + where + keyValue0 (key, DerivationOutput {..}) = + "(" + <> string key + <> "," + <> filepath path + <> "," + <> string hashAlgo + <> "," + <> string hash + <> ")" + + keyValue1 (key, value) = + "(" + <> filepath key + <> "," + <> setOf string value + <> ")" + + keyValue2 (key, value) = + "(" + <> string key + <> "," + <> string value + <> ")" + +mapOf :: ((k, v) -> Builder) -> Map k v -> Builder +mapOf keyValue m = listOf keyValue (Data.Map.toList m) + +listOf :: (a -> Builder) -> [a] -> Builder +listOf _ [] = "[]" +listOf element (x:xs) = + "[" + <> element x + <> foldMap rest xs + <> "]" + where + rest y = "," <> element y + +setOf :: (a -> Builder) -> Set a -> Builder +setOf element xs = listOf element (Data.Set.toList xs) + +vectorOf :: (a -> Builder) -> Vector a -> Builder +vectorOf element xs = listOf element (Data.Vector.toList xs) + +string :: Text -> Builder +string = Data.Text.Lazy.Builder.fromText . Data.Text.pack . show + +filepath :: FilePath -> Builder +filepath p = string text + where + text = case Filesystem.Path.CurrentOS.toText p of + Left t -> t + Right t -> t diff --git a/src/Nix/Derivation/Parser.hs b/src/Nix/Derivation/Parser.hs new file mode 100644 index 00000000..b813c27e --- /dev/null +++ b/src/Nix/Derivation/Parser.hs @@ -0,0 +1,136 @@ +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RecordWildCards #-} + +{-# OPTIONS_GHC -fno-warn-unused-do-bind #-} + +module Nix.Derivation.Parser + ( parseDerivation + ) where + +import Data.Attoparsec.Text.Lazy (Parser) +import Data.Map (Map) +import Data.Monoid ((<>)) +import Data.Set (Set) +import Data.Text (Text) +import Data.Vector (Vector) +import Nix.Derivation.Types (Derivation(..), DerivationOutput(..)) +import Prelude hiding (FilePath) +import Filesystem.Path.CurrentOS (FilePath) + +import qualified Data.Attoparsec.Text.Lazy +import qualified Data.Map +import qualified Data.Set +import qualified Data.Text +import qualified Data.Vector +import qualified Filesystem.Path.CurrentOS + +listOf :: Parser a -> Parser [a] +listOf element = do + "[" + es <- Data.Attoparsec.Text.Lazy.sepBy element "," + "]" + return es + +parseDerivation :: Parser Derivation +parseDerivation = do + "Derive(" + + let keyValue0 = do + "(" + key <- string + "," + path <- filepath + "," + hashAlgo <- string + "," + hash <- string + ")" + return (key, DerivationOutput {..}) + outputs <- mapOf keyValue0 + + "," + + let keyValue1 = do + "(" + key <- filepath + "," + value <- setOf string + ")" + return (key, value) + inputDrvs <- mapOf keyValue1 + + "," + + inputSrcs <- setOf filepath + + "," + + platform <- string + + "," + + builder <- filepath + + "," + + args <- vectorOf string + + "," + + let keyValue2 = do + "(" + key <- string + "," + value <- string + ")" + return (key, value) + env <- mapOf keyValue2 + + ")" + + return (Derivation {..}) + +string :: Parser Text +string = do + "\"" + let predicate c = not (c == '"' || c == '\\') + let loop = do + text0 <- Data.Attoparsec.Text.Lazy.takeWhile predicate + char0 <- Data.Attoparsec.Text.Lazy.anyChar + text2 <- case char0 of + '"' -> return "" + _ -> do + char1 <- Data.Attoparsec.Text.Lazy.anyChar + char2 <- case char1 of + 'n' -> return '\n' + 'r' -> return '\r' + 't' -> return '\t' + _ -> return char1 + text1 <- loop + return (Data.Text.cons char2 text1) + return (text0 <> text2) + loop + +filepath :: Parser FilePath +filepath = do + text <- string + case Data.Text.uncons text of + Just ('/', _) -> do + return (Filesystem.Path.CurrentOS.fromText text) + _ -> do + fail ("bad path ‘" <> Data.Text.unpack text <> "’ in derivation") + +setOf :: Ord a => Parser a -> Parser (Set a) +setOf element = do + es <- listOf element + return (Data.Set.fromList es) + +vectorOf :: Parser a -> Parser (Vector a) +vectorOf element = do + es <- listOf element + return (Data.Vector.fromList es) + +mapOf :: Ord k => Parser (k, v) -> Parser (Map k v) +mapOf parseKeyValue = do + keyValues <- listOf parseKeyValue + return (Data.Map.fromList keyValues) diff --git a/src/Nix/Derivation/Types.hs b/src/Nix/Derivation/Types.hs new file mode 100644 index 00000000..9881af2e --- /dev/null +++ b/src/Nix/Derivation/Types.hs @@ -0,0 +1,28 @@ +module Nix.Derivation.Types + ( -- * Types + Derivation(..) + , DerivationOutput(..) + ) where + +import Data.Map (Map) +import Data.Set (Set) +import Data.Text (Text) +import Data.Vector (Vector) +import Filesystem.Path.CurrentOS (FilePath) +import Prelude hiding (FilePath) + +data Derivation = Derivation + { outputs :: Map Text DerivationOutput + , inputDrvs :: Map FilePath (Set Text) + , inputSrcs :: Set FilePath + , platform :: Text + , builder :: FilePath + , args :: Vector Text + , env :: Map Text Text + } deriving (Eq, Ord, Show) + +data DerivationOutput = DerivationOutput + { path :: FilePath + , hashAlgo :: Text + , hash :: Text + } deriving (Eq, Ord, Show) diff --git a/tests/Example.hs b/tests/Example.hs new file mode 100644 index 00000000..e41dc1a3 --- /dev/null +++ b/tests/Example.hs @@ -0,0 +1,20 @@ +module Main where + +import qualified Nix.Derivation +import qualified Data.Attoparsec.Text.Lazy +import qualified Data.Text.Lazy.Builder +import qualified Data.Text.Lazy.IO + +import Data.Attoparsec.Text.Lazy (Result(..)) + +main :: IO () +main = do + text0 <- Data.Text.Lazy.IO.readFile "tests/example.drv" + derivation <- case Data.Attoparsec.Text.Lazy.parse Nix.Derivation.parseDerivation text0 of + Fail _ _ string -> fail string + Done _ derivation -> return derivation + let builder = Nix.Derivation.buildDerivation derivation + let text1 = Data.Text.Lazy.Builder.toLazyText builder + if text0 == text1 + then return () + else fail "Parsing and rendering the example derivation does not round-trip" diff --git a/tests/example.drv b/tests/example.drv new file mode 100644 index 00000000..f607eaf4 --- /dev/null +++ b/tests/example.drv @@ -0,0 +1 @@ +Derive([("devdoc","/nix/store/15x9ii8c3n5wb5lg80cm8x0yk6zy7rha-perl-MIME-Types-2.13-devdoc","",""),("out","/nix/store/93d75ghjyibmbxgfzwhh4b5zwsxzs44w-perl-MIME-Types-2.13","","")],[("/nix/store/57h2hjsdkdiwbzilcjqkn46138n1xb4a-perl-5.22.3.drv",["out"]),("/nix/store/cvdbbvnvg131bz9bwyyk97jpq1crclqr-MIME-Types-2.13.tar.gz.drv",["out"]),("/nix/store/p5g31bc5x92awghx9dlm065d7j773l0r-stdenv.drv",["out"]),("/nix/store/x50y5qihwsn0lfjhrf1s81b5hgb9w632-bash-4.4-p5.drv",["out"])],["/nix/store/cdips4lakfk1qbf1x68fq18wnn3r5r14-builder.sh"],"x86_64-linux","/nix/store/fi3mbd2ml4pbgzyasrlnp0wyy6qi48fh-bash-4.4-p5/bin/bash",["-e","/nix/store/cdips4lakfk1qbf1x68fq18wnn3r5r14-builder.sh"],[("AUTOMATED_TESTING","1"),("PERL_AUTOINSTALL","--skipdeps"),("buildInputs",""),("builder","/nix/store/fi3mbd2ml4pbgzyasrlnp0wyy6qi48fh-bash-4.4-p5/bin/bash"),("checkTarget","test"),("devdoc","/nix/store/15x9ii8c3n5wb5lg80cm8x0yk6zy7rha-perl-MIME-Types-2.13-devdoc"),("doCheck","1"),("installTargets","pure_install"),("name","perl-MIME-Types-2.13"),("nativeBuildInputs","/nix/store/nsa311yg8h93wfaacjk16c96a98bs09f-perl-5.22.3"),("out","/nix/store/93d75ghjyibmbxgfzwhh4b5zwsxzs44w-perl-MIME-Types-2.13"),("outputs","out devdoc"),("propagatedBuildInputs",""),("propagatedNativeBuildInputs",""),("src","/nix/store/5smhymz7viq8p47mc3jgyvqd003ab732-MIME-Types-2.13.tar.gz"),("stdenv","/nix/store/s3rlr45jzlzx0d6k2azlpxa5zwzr7xyy-stdenv"),("system","x86_64-linux")]) \ No newline at end of file From 60439ee92551134fe9d211c5b149def57c34fbcd Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Sun, 4 Jun 2017 20:36:51 -0700 Subject: [PATCH 02/58] Add property tests --- default.nix | 6 +++-- nix-derivation.cabal | 14 ++++++++++ tests/Property.hs | 63 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 tests/Property.hs diff --git a/default.nix b/default.nix index 7df9d9b8..6352d07f 100644 --- a/default.nix +++ b/default.nix @@ -1,4 +1,4 @@ -{ mkDerivation, attoparsec, base, containers, stdenv +{ mkDerivation, attoparsec, base, containers, QuickCheck, stdenv , system-filepath, text, vector }: mkDerivation { @@ -8,7 +8,9 @@ mkDerivation { libraryHaskellDepends = [ attoparsec base containers system-filepath text vector ]; - testHaskellDepends = [ attoparsec base text ]; + testHaskellDepends = [ + attoparsec base QuickCheck system-filepath text vector + ]; description = "Parse and render *.drv files"; license = stdenv.lib.licenses.bsd3; } diff --git a/nix-derivation.cabal b/nix-derivation.cabal index 703fea49..b6ad213a 100644 --- a/nix-derivation.cabal +++ b/nix-derivation.cabal @@ -45,3 +45,17 @@ Test-Suite example attoparsec >= 0.12.0.0 && < 0.14, nix-derivation , text >= 0.8.0.0 && < 1.3 + +Test-Suite property + Type: exitcode-stdio-1.0 + Hs-Source-Dirs: tests + Main-Is: Property.hs + GHC-Options: -Wall + Build-Depends: + base >= 4.6.0.0 && < 5 , + attoparsec >= 0.12.0.0 && < 0.14, + nix-derivation , + QuickCheck < 2.10, + system-filepath >= 0.3.1 && < 0.5 , + text >= 0.8.0.0 && < 1.3 , + vector < 0.13 diff --git a/tests/Property.hs b/tests/Property.hs new file mode 100644 index 00000000..33f26cc7 --- /dev/null +++ b/tests/Property.hs @@ -0,0 +1,63 @@ +{-# LANGUAGE RecordWildCards #-} + +{-# OPTIONS_GHC -fno-warn-orphans #-} + +module Main where + +import Data.Text (Text) +import Data.Vector (Vector) +import Filesystem.Path.CurrentOS (FilePath) +import Nix.Derivation (Derivation(..), DerivationOutput(..)) +import Prelude hiding (FilePath, either) +import Test.QuickCheck (Arbitrary(..)) + +import qualified Data.Attoparsec.Text.Lazy +import qualified Data.Text +import qualified Data.Text.Lazy.Builder +import qualified Data.Vector +import qualified Filesystem.Path.CurrentOS +import qualified Nix.Derivation +import qualified Test.QuickCheck + +instance Arbitrary Text where + arbitrary = fmap Data.Text.pack arbitrary + +instance Arbitrary FilePath where + arbitrary = fmap Filesystem.Path.CurrentOS.decodeString arbitrary + +instance Arbitrary a => Arbitrary (Vector a) where + arbitrary = fmap Data.Vector.fromList arbitrary + +instance Arbitrary DerivationOutput where + arbitrary = do + path <- arbitrary + hashAlgo <- arbitrary + hash <- arbitrary + return (DerivationOutput {..}) + +instance Arbitrary Derivation where + arbitrary = do + outputs <- arbitrary + inputDrvs <- arbitrary + inputSrcs <- arbitrary + platform <- arbitrary + builder <- arbitrary + args <- arbitrary + env <- arbitrary + return (Derivation {..}) + +property :: Derivation -> Bool +property derivation0 = either == Right derivation0 + where + builder = Nix.Derivation.buildDerivation derivation0 + + text = Data.Text.Lazy.Builder.toLazyText builder + + result = + Data.Attoparsec.Text.Lazy.parse Nix.Derivation.parseDerivation text + + either = + Data.Attoparsec.Text.Lazy.eitherResult result + +main :: IO () +main = Test.QuickCheck.quickCheck property From c035165acd50028fa41953c494ca84033579bcfa Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Sun, 4 Jun 2017 21:12:22 -0700 Subject: [PATCH 03/58] Update documentation --- nix-derivation.cabal | 3 +- src/Nix/Derivation.hs | 91 +++++++++++++++++++++++++++++++++-- src/Nix/Derivation/Builder.hs | 8 ++- src/Nix/Derivation/Parser.hs | 6 ++- src/Nix/Derivation/Types.hs | 16 ++++++ 5 files changed, 117 insertions(+), 7 deletions(-) diff --git a/nix-derivation.cabal b/nix-derivation.cabal index b6ad213a..48beb48c 100644 --- a/nix-derivation.cabal +++ b/nix-derivation.cabal @@ -29,7 +29,8 @@ Library text >= 0.8.0.0 && < 1.3 , vector < 0.13 Exposed-Modules: - Nix.Derivation, + Nix.Derivation + Other-Modules: Nix.Derivation.Builder, Nix.Derivation.Parser, Nix.Derivation.Types diff --git a/src/Nix/Derivation.hs b/src/Nix/Derivation.hs index 726ea3dd..9268c58b 100644 --- a/src/Nix/Derivation.hs +++ b/src/Nix/Derivation.hs @@ -1,8 +1,91 @@ +-- | Use this package to parse and render Nix derivations such as those stored +-- in @/nix/store*.drv@ files. For example, if you had the following derivation +-- saved at +-- @\/nix\/store\/zzhs4fb83x5ygvjqn5rdpmpnishpdgy6-perl-MIME-Types-2.13.drv@: +-- +-- > Derive([("devdoc","/nix/store/15x9ii8c3n5wb5lg80cm8x0yk6zy7rha-perl-MIME-Types-2 +-- > .13-devdoc","",""),("out","/nix/store/93d75ghjyibmbxgfzwhh4b5zwsxzs44w-perl-MIME +-- > -Types-2.13","","")],[("/nix/store/57h2hjsdkdiwbzilcjqkn46138n1xb4a-perl-5.22.3. +-- > drv",["out"]),("/nix/store/cvdbbvnvg131bz9bwyyk97jpq1crclqr-MIME-Types-2.13.tar. +-- > gz.drv",["out"]),("/nix/store/p5g31bc5x92awghx9dlm065d7j773l0r-stdenv.drv",["out +-- > "]),("/nix/store/x50y5qihwsn0lfjhrf1s81b5hgb9w632-bash-4.4-p5.drv",["out"])],["/ +-- > nix/store/cdips4lakfk1qbf1x68fq18wnn3r5r14-builder.sh"],"x86_64-linux","/nix/sto +-- > re/fi3mbd2ml4pbgzyasrlnp0wyy6qi48fh-bash-4.4-p5/bin/bash",["-e","/nix/store/cdip +-- > s4lakfk1qbf1x68fq18wnn3r5r14-builder.sh"],[("AUTOMATED_TESTING","1"),("PERL_AUTO +-- > INSTALL","--skipdeps"),("buildInputs",""),("builder","/nix/store/fi3mbd2ml4pbgzy +-- > asrlnp0wyy6qi48fh-bash-4.4-p5/bin/bash"),("checkTarget","test"),("devdoc","/nix/ +-- > store/15x9ii8c3n5wb5lg80cm8x0yk6zy7rha-perl-MIME-Types-2.13-devdoc"),("doCheck", +-- > "1"),("installTargets","pure_install"),("name","perl-MIME-Types-2.13"),("nativeB +-- > uildInputs","/nix/store/nsa311yg8h93wfaacjk16c96a98bs09f-perl-5.22.3"),("out","/ +-- > nix/store/93d75ghjyibmbxgfzwhh4b5zwsxzs44w-perl-MIME-Types-2.13"),("outputs","ou +-- > t devdoc"),("propagatedBuildInputs",""),("propagatedNativeBuildInputs",""),("src +-- > ","/nix/store/5smhymz7viq8p47mc3jgyvqd003ab732-MIME-Types-2.13.tar.gz"),("stdenv +-- > ","/nix/store/s3rlr45jzlzx0d6k2azlpxa5zwzr7xyy-stdenv"),("system","x86_64-linux" +-- > )]) +-- +-- ... you could parse that derivation using: +-- +-- >>> text <- Data.Text.Lazy.IO.readFile "/nix/store/zzhs4fb83x5ygvjqn5rdpmpnishpdgy6-perl-MIME-Types-2.13.drv" +-- >>> let result = Data.Attoparsec.Text.Lazy.parse Nix.Derivation.parseDerivation text +-- >>> result +-- Done "" (Derivation {outputs = fromList [("devdoc",DerivationOutput {path = File +-- Path "/nix/store/15x9ii8c3n5wb5lg80cm8x0yk6zy7rha-perl-MIME-Types-2.13-devdoc", +-- hashAlgo = "", hash = ""}),("out",DerivationOutput {path = FilePath "/nix/store/ +-- 93d75ghjyibmbxgfzwhh4b5zwsxzs44w-perl-MIME-Types-2.13", hashAlgo = "", hash = "" +-- })], inputDrvs = fromList [(FilePath "/nix/store/57h2hjsdkdiwbzilcjqkn46138n1xb4 +-- a-perl-5.22.3.drv",fromList ["out"]),(FilePath "/nix/store/cvdbbvnvg131bz9bwyyk9 +-- 7jpq1crclqr-MIME-Types-2.13.tar.gz.drv",fromList ["out"]),(FilePath "/nix/store/ +-- p5g31bc5x92awghx9dlm065d7j773l0r-stdenv.drv",fromList ["out"]),(FilePath "/nix/s +-- tore/x50y5qihwsn0lfjhrf1s81b5hgb9w632-bash-4.4-p5.drv",fromList ["out"])], input +-- Srcs = fromList [FilePath "/nix/store/cdips4lakfk1qbf1x68fq18wnn3r5r14-builder.s +-- h"], platform = "x86_64-linux", builder = FilePath "/nix/store/fi3mbd2ml4pbgzyas +-- rlnp0wyy6qi48fh-bash-4.4-p5/bin/bash", args = ["-e","/nix/store/cdips4lakfk1qbf1 +-- x68fq18wnn3r5r14-builder.sh"], env = fromList [("AUTOMATED_TESTING","1"),("PERL_ +-- AUTOINSTALL","--skipdeps"),("buildInputs",""),("builder","/nix/store/fi3mbd2ml4p +-- bgzyasrlnp0wyy6qi48fh-bash-4.4-p5/bin/bash"),("checkTarget","test"),("devdoc","/ +-- nix/store/15x9ii8c3n5wb5lg80cm8x0yk6zy7rha-perl-MIME-Types-2.13-devdoc"),("doChe +-- ck","1"),("installTargets","pure_install"),("name","perl-MIME-Types-2.13"),("nat +-- iveBuildInputs","/nix/store/nsa311yg8h93wfaacjk16c96a98bs09f-perl-5.22.3"),("out +-- ","/nix/store/93d75ghjyibmbxgfzwhh4b5zwsxzs44w-perl-MIME-Types-2.13"),("outputs" +-- ,"out devdoc"),("propagatedBuildInputs",""),("propagatedNativeBuildInputs",""),( +-- "src","/nix/store/5smhymz7viq8p47mc3jgyvqd003ab732-MIME-Types-2.13.tar.gz"),("st +-- denv","/nix/store/s3rlr45jzlzx0d6k2azlpxa5zwzr7xyy-stdenv"),("system","x86_64-li +-- nux")]}) +-- +-- ... and render the result back to the original derivation: +-- +-- >>> fmap buildDerivation result +-- Done "" "Derive([(\"devdoc\",\"/nix/store/15x9ii8c3n5wb5lg80cm8x0yk6zy7rha-perl- +-- MIME-Types-2.13-devdoc\",\"\",\"\"),(\"out\",\"/nix/store/93d75ghjyibmbxgfzwhh4b +-- 5zwsxzs44w-perl-MIME-Types-2.13\",\"\",\"\")],[(\"/nix/store/57h2hjsdkdiwbzilcjq +-- kn46138n1xb4a-perl-5.22.3.drv\",[\"out\"]),(\"/nix/store/cvdbbvnvg131bz9bwyyk97j +-- pq1crclqr-MIME-Types-2.13.tar.gz.drv\",[\"out\"]),(\"/nix/store/p5g31bc5x92awghx +-- 9dlm065d7j773l0r-stdenv.drv\",[\"out\"]),(\"/nix/store/x50y5qihwsn0lfjhrf1s81b5h +-- gb9w632-bash-4.4-p5.drv\",[\"out\"])],[\"/nix/store/cdips4lakfk1qbf1x68fq18wnn3r +-- 5r14-builder.sh\"],\"x86_64-linux\",\"/nix/store/fi3mbd2ml4pbgzyasrlnp0wyy6qi48f +-- h-bash-4.4-p5/bin/bash\",[\"-e\",\"/nix/store/cdips4lakfk1qbf1x68fq18wnn3r5r14-b +-- uilder.sh\"],[(\"AUTOMATED_TESTING\",\"1\"),(\"PERL_AUTOINSTALL\",\"--skipdeps\" +-- ),(\"buildInputs\",\"\"),(\"builder\",\"/nix/store/fi3mbd2ml4pbgzyasrlnp0wyy6qi4 +-- 8fh-bash-4.4-p5/bin/bash\"),(\"checkTarget\",\"test\"),(\"devdoc\",\"/nix/store/ +-- 15x9ii8c3n5wb5lg80cm8x0yk6zy7rha-perl-MIME-Types-2.13-devdoc\"),(\"doCheck\",\"1 +-- \"),(\"installTargets\",\"pure_install\"),(\"name\",\"perl-MIME-Types-2.13\"),(\ +-- "nativeBuildInputs\",\"/nix/store/nsa311yg8h93wfaacjk16c96a98bs09f-perl-5.22.3\" +-- ),(\"out\",\"/nix/store/93d75ghjyibmbxgfzwhh4b5zwsxzs44w-perl-MIME-Types-2.13\") +-- ,(\"outputs\",\"out devdoc\"),(\"propagatedBuildInputs\",\"\"),(\"propagatedNati +-- veBuildInputs\",\"\"),(\"src\",\"/nix/store/5smhymz7viq8p47mc3jgyvqd003ab732-MIM +-- E-Types-2.13.tar.gz\"),(\"stdenv\",\"/nix/store/s3rlr45jzlzx0d6k2azlpxa5zwzr7xyy +-- -stdenv\"),(\"system\",\"x86_64-linux\")])" + module Nix.Derivation - ( -- Re-exports - module Nix.Derivation.Types - , module Nix.Derivation.Parser - , module Nix.Derivation.Builder + ( -- * Types + Derivation(..) + , DerivationOutput(..) + + -- * Parse derivations + , parseDerivation + + -- * Render derivations + , buildDerivation ) where import Nix.Derivation.Builder diff --git a/src/Nix/Derivation/Builder.hs b/src/Nix/Derivation/Builder.hs index ae5ddc7a..a8cc60f8 100644 --- a/src/Nix/Derivation/Builder.hs +++ b/src/Nix/Derivation/Builder.hs @@ -1,7 +1,12 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} -module Nix.Derivation.Builder where +-- | Rendering logic + +module Nix.Derivation.Builder + ( -- * Builder + buildDerivation + ) where import Data.Foldable (foldMap) import Data.Map (Map) @@ -21,6 +26,7 @@ import qualified Data.Text.Lazy.Builder import qualified Data.Vector import qualified Filesystem.Path.CurrentOS +-- | Render a derivation as a `Builder` buildDerivation :: Derivation -> Builder buildDerivation (Derivation {..}) = "Derive(" diff --git a/src/Nix/Derivation/Parser.hs b/src/Nix/Derivation/Parser.hs index b813c27e..47d18272 100644 --- a/src/Nix/Derivation/Parser.hs +++ b/src/Nix/Derivation/Parser.hs @@ -3,8 +3,11 @@ {-# OPTIONS_GHC -fno-warn-unused-do-bind #-} +-- | Parsing logic + module Nix.Derivation.Parser - ( parseDerivation + ( -- * Parser + parseDerivation ) where import Data.Attoparsec.Text.Lazy (Parser) @@ -31,6 +34,7 @@ listOf element = do "]" return es +-- | Parse a derivation parseDerivation :: Parser Derivation parseDerivation = do "Derive(" diff --git a/src/Nix/Derivation/Types.hs b/src/Nix/Derivation/Types.hs index 9881af2e..a1dee7a2 100644 --- a/src/Nix/Derivation/Types.hs +++ b/src/Nix/Derivation/Types.hs @@ -1,3 +1,5 @@ +-- | Shared types + module Nix.Derivation.Types ( -- * Types Derivation(..) @@ -11,18 +13,32 @@ import Data.Vector (Vector) import Filesystem.Path.CurrentOS (FilePath) import Prelude hiding (FilePath) +-- | A Nix derivation data Derivation = Derivation { outputs :: Map Text DerivationOutput + -- ^ Outputs produced by this derivation where keys are output names , inputDrvs :: Map FilePath (Set Text) + -- ^ Inputs that are derivations where keys specify derivation paths and + -- values specify which output names are used by this derivation , inputSrcs :: Set FilePath + -- ^ Inputs that are sources , platform :: Text + -- ^ Platform required for this derivation , builder :: FilePath + -- ^ Executable to build the derivation , args :: Vector Text + -- ^ Arguments passed to the executable used to build to derivation , env :: Map Text Text + -- ^ Environment variables provided to the executable used to build the + -- derivation } deriving (Eq, Ord, Show) +-- | An output of a Nix derivation data DerivationOutput = DerivationOutput { path :: FilePath + -- ^ Path where the output will be saved , hashAlgo :: Text + -- ^ Hash used for expected hash computation , hash :: Text + -- ^ Expected hash } deriving (Eq, Ord, Show) From 8b129127d47582a50b132c159ccb29dbe3009f04 Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Sun, 4 Jun 2017 21:23:30 -0700 Subject: [PATCH 04/58] Add `README.md` --- README.md | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..f0d05927 --- /dev/null +++ b/README.md @@ -0,0 +1,119 @@ +# `nix-derivation 1.0.0` + +Use this package to parse and render Nix derivations such as those stored +in `/nix/store/*.drv` files. For example, if you had the following derivation +saved at +`/nix/store/zzhs4fb83x5ygvjqn5rdpmpnishpdgy6-perl-MIME-Types-2.13.drv`: + +``` +Derive([("devdoc","/nix/store/15x9ii8c3n5wb5lg80cm8x0yk6zy7rha-perl-MIME-Types-2 +.13-devdoc","",""),("out","/nix/store/93d75ghjyibmbxgfzwhh4b5zwsxzs44w-perl-MIME +-Types-2.13","","")],[("/nix/store/57h2hjsdkdiwbzilcjqkn46138n1xb4a-perl-5.22.3. +drv",["out"]),("/nix/store/cvdbbvnvg131bz9bwyyk97jpq1crclqr-MIME-Types-2.13.tar. +gz.drv",["out"]),("/nix/store/p5g31bc5x92awghx9dlm065d7j773l0r-stdenv.drv",["out +"]),("/nix/store/x50y5qihwsn0lfjhrf1s81b5hgb9w632-bash-4.4-p5.drv",["out"])],["/ +nix/store/cdips4lakfk1qbf1x68fq18wnn3r5r14-builder.sh"],"x86_64-linux","/nix/sto +re/fi3mbd2ml4pbgzyasrlnp0wyy6qi48fh-bash-4.4-p5/bin/bash",["-e","/nix/store/cdip +s4lakfk1qbf1x68fq18wnn3r5r14-builder.sh"],[("AUTOMATED_TESTING","1"),("PERL_AUTO +INSTALL","--skipdeps"),("buildInputs",""),("builder","/nix/store/fi3mbd2ml4pbgzy +asrlnp0wyy6qi48fh-bash-4.4-p5/bin/bash"),("checkTarget","test"),("devdoc","/nix/ +store/15x9ii8c3n5wb5lg80cm8x0yk6zy7rha-perl-MIME-Types-2.13-devdoc"),("doCheck", +"1"),("installTargets","pure_install"),("name","perl-MIME-Types-2.13"),("nativeB +uildInputs","/nix/store/nsa311yg8h93wfaacjk16c96a98bs09f-perl-5.22.3"),("out","/ +nix/store/93d75ghjyibmbxgfzwhh4b5zwsxzs44w-perl-MIME-Types-2.13"),("outputs","ou +t devdoc"),("propagatedBuildInputs",""),("propagatedNativeBuildInputs",""),("src +","/nix/store/5smhymz7viq8p47mc3jgyvqd003ab732-MIME-Types-2.13.tar.gz"),("stdenv +","/nix/store/s3rlr45jzlzx0d6k2azlpxa5zwzr7xyy-stdenv"),("system","x86_64-linux" +)]) +``` + +... you could parse that derivation using: + +``` +>>> text <- Data.Text.Lazy.IO.readFile "/nix/store/zzhs4fb83x5ygvjqn5rdpmpnishpdgy6-perl-MIME-Types-2.13.drv" +>>> let result = Data.Attoparsec.Text.Lazy.parse Nix.Derivation.parseDerivation text +>>> result +Done "" (Derivation {outputs = fromList [("devdoc",DerivationOutput {path = File +Path "/nix/store/15x9ii8c3n5wb5lg80cm8x0yk6zy7rha-perl-MIME-Types-2.13-devdoc", +hashAlgo = "", hash = ""}),("out",DerivationOutput {path = FilePath "/nix/store/ +93d75ghjyibmbxgfzwhh4b5zwsxzs44w-perl-MIME-Types-2.13", hashAlgo = "", hash = "" +})], inputDrvs = fromList [(FilePath "/nix/store/57h2hjsdkdiwbzilcjqkn46138n1xb4 +a-perl-5.22.3.drv",fromList ["out"]),(FilePath "/nix/store/cvdbbvnvg131bz9bwyyk9 +7jpq1crclqr-MIME-Types-2.13.tar.gz.drv",fromList ["out"]),(FilePath "/nix/store/ +p5g31bc5x92awghx9dlm065d7j773l0r-stdenv.drv",fromList ["out"]),(FilePath "/nix/s +tore/x50y5qihwsn0lfjhrf1s81b5hgb9w632-bash-4.4-p5.drv",fromList ["out"])], input +Srcs = fromList [FilePath "/nix/store/cdips4lakfk1qbf1x68fq18wnn3r5r14-builder.s +h"], platform = "x86_64-linux", builder = FilePath "/nix/store/fi3mbd2ml4pbgzyas +rlnp0wyy6qi48fh-bash-4.4-p5/bin/bash", args = ["-e","/nix/store/cdips4lakfk1qbf1 +x68fq18wnn3r5r14-builder.sh"], env = fromList [("AUTOMATED_TESTING","1"),("PERL_ +AUTOINSTALL","--skipdeps"),("buildInputs",""),("builder","/nix/store/fi3mbd2ml4p +bgzyasrlnp0wyy6qi48fh-bash-4.4-p5/bin/bash"),("checkTarget","test"),("devdoc","/ +nix/store/15x9ii8c3n5wb5lg80cm8x0yk6zy7rha-perl-MIME-Types-2.13-devdoc"),("doChe +ck","1"),("installTargets","pure_install"),("name","perl-MIME-Types-2.13"),("nat +iveBuildInputs","/nix/store/nsa311yg8h93wfaacjk16c96a98bs09f-perl-5.22.3"),("out +","/nix/store/93d75ghjyibmbxgfzwhh4b5zwsxzs44w-perl-MIME-Types-2.13"),("outputs" +,"out devdoc"),("propagatedBuildInputs",""),("propagatedNativeBuildInputs",""),( +"src","/nix/store/5smhymz7viq8p47mc3jgyvqd003ab732-MIME-Types-2.13.tar.gz"),("st +denv","/nix/store/s3rlr45jzlzx0d6k2azlpxa5zwzr7xyy-stdenv"),("system","x86_64-li +nux")]}) +``` + +... and render the result back to the original derivation: + +``` +>>> fmap buildDerivation result +Done "" "Derive([(\"devdoc\",\"/nix/store/15x9ii8c3n5wb5lg80cm8x0yk6zy7rha-perl- +MIME-Types-2.13-devdoc\",\"\",\"\"),(\"out\",\"/nix/store/93d75ghjyibmbxgfzwhh4b +5zwsxzs44w-perl-MIME-Types-2.13\",\"\",\"\")],[(\"/nix/store/57h2hjsdkdiwbzilcjq +kn46138n1xb4a-perl-5.22.3.drv\",[\"out\"]),(\"/nix/store/cvdbbvnvg131bz9bwyyk97j +pq1crclqr-MIME-Types-2.13.tar.gz.drv\",[\"out\"]),(\"/nix/store/p5g31bc5x92awghx +9dlm065d7j773l0r-stdenv.drv\",[\"out\"]),(\"/nix/store/x50y5qihwsn0lfjhrf1s81b5h +gb9w632-bash-4.4-p5.drv\",[\"out\"])],[\"/nix/store/cdips4lakfk1qbf1x68fq18wnn3r +5r14-builder.sh\"],\"x86_64-linux\",\"/nix/store/fi3mbd2ml4pbgzyasrlnp0wyy6qi48f +h-bash-4.4-p5/bin/bash\",[\"-e\",\"/nix/store/cdips4lakfk1qbf1x68fq18wnn3r5r14-b +uilder.sh\"],[(\"AUTOMATED_TESTING\",\"1\"),(\"PERL_AUTOINSTALL\",\"--skipdeps\" +),(\"buildInputs\",\"\"),(\"builder\",\"/nix/store/fi3mbd2ml4pbgzyasrlnp0wyy6qi4 +8fh-bash-4.4-p5/bin/bash\"),(\"checkTarget\",\"test\"),(\"devdoc\",\"/nix/store/ +15x9ii8c3n5wb5lg80cm8x0yk6zy7rha-perl-MIME-Types-2.13-devdoc\"),(\"doCheck\",\"1 +\"),(\"installTargets\",\"pure_install\"),(\"name\",\"perl-MIME-Types-2.13\"),(\ +"nativeBuildInputs\",\"/nix/store/nsa311yg8h93wfaacjk16c96a98bs09f-perl-5.22.3\" +),(\"out\",\"/nix/store/93d75ghjyibmbxgfzwhh4b5zwsxzs44w-perl-MIME-Types-2.13\") +,(\"outputs\",\"out devdoc\"),(\"propagatedBuildInputs\",\"\"),(\"propagatedNati +veBuildInputs\",\"\"),(\"src\",\"/nix/store/5smhymz7viq8p47mc3jgyvqd003ab732-MIM +E-Types-2.13.tar.gz\"),(\"stdenv\",\"/nix/store/s3rlr45jzlzx0d6k2azlpxa5zwzr7xyy +-stdenv\"),(\"system\",\"x86_64-linux\")])" +``` + +## Development status + +[![Build Status](https://travis-ci.org/Gabriel439/Haskell-Nix-Derivation-Library.png)](https://travis-ci.org/Gabriel439/Haskell-Nix-Derivation-Library) + +If you would like to add support for additional functionality, just open an +issue or pull request + +## License (BSD 3-clause) + + Copyright (c) 2017 Gabriel Gonzalez + 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 Gabriel Gonzalez 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. From c5cea2d95b20a720a01a6f85c083772537e32002 Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Sun, 4 Jun 2017 21:24:13 -0700 Subject: [PATCH 05/58] Fix typo in haddocks --- src/Nix/Derivation.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nix/Derivation.hs b/src/Nix/Derivation.hs index 9268c58b..39c28e92 100644 --- a/src/Nix/Derivation.hs +++ b/src/Nix/Derivation.hs @@ -1,5 +1,5 @@ -- | Use this package to parse and render Nix derivations such as those stored --- in @/nix/store*.drv@ files. For example, if you had the following derivation +-- in @\/nix\/store\/*.drv@ files. For example, if you had the following derivation -- saved at -- @\/nix\/store\/zzhs4fb83x5ygvjqn5rdpmpnishpdgy6-perl-MIME-Types-2.13.drv@: -- From 9821e1acf8f8de1e2197d6bc4ba991d3a813fce9 Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Wed, 7 Jun 2017 05:43:20 -0700 Subject: [PATCH 06/58] Change the `builder` field to a `String` This field is not always a `FilePath`. For example, `builder` can be `"builtins.fetchURL` --- src/Nix/Derivation/Builder.hs | 2 +- src/Nix/Derivation/Parser.hs | 2 +- src/Nix/Derivation/Types.hs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Nix/Derivation/Builder.hs b/src/Nix/Derivation/Builder.hs index a8cc60f8..17947d6c 100644 --- a/src/Nix/Derivation/Builder.hs +++ b/src/Nix/Derivation/Builder.hs @@ -38,7 +38,7 @@ buildDerivation (Derivation {..}) = <> "," <> string platform <> "," - <> filepath builder + <> string builder <> "," <> vectorOf string args <> "," diff --git a/src/Nix/Derivation/Parser.hs b/src/Nix/Derivation/Parser.hs index 47d18272..b13461af 100644 --- a/src/Nix/Derivation/Parser.hs +++ b/src/Nix/Derivation/Parser.hs @@ -73,7 +73,7 @@ parseDerivation = do "," - builder <- filepath + builder <- string "," diff --git a/src/Nix/Derivation/Types.hs b/src/Nix/Derivation/Types.hs index a1dee7a2..8d17c6d2 100644 --- a/src/Nix/Derivation/Types.hs +++ b/src/Nix/Derivation/Types.hs @@ -24,8 +24,8 @@ data Derivation = Derivation -- ^ Inputs that are sources , platform :: Text -- ^ Platform required for this derivation - , builder :: FilePath - -- ^ Executable to build the derivation + , builder :: Text + -- ^ Code to build the derivation, which can be a path or a builtin function , args :: Vector Text -- ^ Arguments passed to the executable used to build to derivation , env :: Map Text Text From 8df67c74b6e44367009823634688f58b54d641b8 Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Wed, 7 Jun 2017 07:33:03 -0700 Subject: [PATCH 07/58] Polish source code --- src/Nix/Derivation/Parser.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nix/Derivation/Parser.hs b/src/Nix/Derivation/Parser.hs index b13461af..3f76e08c 100644 --- a/src/Nix/Derivation/Parser.hs +++ b/src/Nix/Derivation/Parser.hs @@ -135,6 +135,6 @@ vectorOf element = do return (Data.Vector.fromList es) mapOf :: Ord k => Parser (k, v) -> Parser (Map k v) -mapOf parseKeyValue = do - keyValues <- listOf parseKeyValue +mapOf keyValue = do + keyValues <- listOf keyValue return (Data.Map.fromList keyValues) From c178a6defa5cb55fd9d01794a9efc7dc56bbf1a6 Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Wed, 7 Jun 2017 21:42:59 -0700 Subject: [PATCH 08/58] Add benchmark --- .travis.yml | 11 ++++------- bench/Main.hs | 23 +++++++++++++++++++++++ default.nix | 7 ++++--- nix-derivation.cabal | 20 ++++++++++++++++++-- release.nix | 8 +++++++- src/Nix/Derivation/Parser.hs | 8 +++++--- src/Nix/Derivation/Types.hs | 12 ++++++++++-- tests/Example.hs | 2 +- tests/{example.drv => example0.drv} | 0 tests/example1.drv | 1 + 10 files changed, 73 insertions(+), 19 deletions(-) create mode 100644 bench/Main.hs rename tests/{example.drv => example0.drv} (100%) create mode 100644 tests/example1.drv diff --git a/.travis.yml b/.travis.yml index 58b9b37f..46c63923 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,9 +13,6 @@ before_cache: matrix: include: - - env: CABALVER=1.16 GHCVER=7.6.3 - compiler: ": #GHC 7.6.3" - addons: {apt: {packages: [cabal-install-1.16,ghc-7.6.3], sources: [hvr-ghc]}} - env: CABALVER=1.18 GHCVER=7.8.4 compiler: ": #GHC 7.8.4" addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4], sources: [hvr-ghc]}} @@ -40,7 +37,7 @@ install: fi - travis_retry cabal update -v - sed -i 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config - - cabal install --only-dependencies --enable-tests --enable-benchmarks --dry -v > installplan.txt + - cabal install --only-dependencies --enable-tests --dry -v > installplan.txt - sed -i -e '1,/^Resolving /d' installplan.txt; cat installplan.txt # check whether current requested install-plan matches cached package-db snapshot @@ -54,7 +51,7 @@ install: echo "cabal build-cache MISS"; rm -rf $HOME/.cabsnap; mkdir -p $HOME/.ghc $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin; - cabal install --only-dependencies --enable-tests --enable-benchmarks; + cabal install --only-dependencies --enable-tests; fi # snapshot package-db on cache miss @@ -70,8 +67,8 @@ install: # any command which exits with a non-zero exit code causes the build to fail. script: - if [ -f configure.ac ]; then autoreconf -i; fi - - cabal configure --enable-tests --enable-benchmarks -v2 # -v2 provides useful information for debugging - - cabal build # this builds all libraries and executables (including tests/benchmarks) + - cabal configure --enable-tests -v2 # -v2 provides useful information for debugging + - cabal build # this builds all libraries and executables (including tests) - cabal test - cabal check - cabal sdist # tests that a source-distribution can be generated diff --git a/bench/Main.hs b/bench/Main.hs new file mode 100644 index 00000000..bab4b2d1 --- /dev/null +++ b/bench/Main.hs @@ -0,0 +1,23 @@ +import Criterion (Benchmark) + +import qualified Criterion +import qualified Criterion.Main +import qualified Data.Attoparsec.Text.Lazy +import qualified Data.Text.Lazy.IO +import qualified Nix.Derivation + +main :: IO () +main = Criterion.Main.defaultMain benchmarks + +benchmarks :: [Benchmark] +benchmarks = + [ Criterion.Main.env + (Data.Text.Lazy.IO.readFile "tests/example1.drv") + bench0 + ] + where + bench0 example = + Criterion.bench "example" (Criterion.nf parseExample example) + + parseExample = + Data.Attoparsec.Text.Lazy.parse Nix.Derivation.parseDerivation diff --git a/default.nix b/default.nix index 6352d07f..948fd041 100644 --- a/default.nix +++ b/default.nix @@ -1,16 +1,17 @@ -{ mkDerivation, attoparsec, base, containers, QuickCheck, stdenv -, system-filepath, text, vector +{ mkDerivation, attoparsec, base, containers, criterion, deepseq +, QuickCheck, stdenv, system-filepath, text, vector }: mkDerivation { pname = "nix-derivation"; version = "1.0.0"; src = ./.; libraryHaskellDepends = [ - attoparsec base containers system-filepath text vector + attoparsec base containers deepseq system-filepath text vector ]; testHaskellDepends = [ attoparsec base QuickCheck system-filepath text vector ]; + benchmarkHaskellDepends = [ attoparsec base criterion text ]; description = "Parse and render *.drv files"; license = stdenv.lib.licenses.bsd3; } diff --git a/nix-derivation.cabal b/nix-derivation.cabal index 48beb48c..55400bc4 100644 --- a/nix-derivation.cabal +++ b/nix-derivation.cabal @@ -2,7 +2,7 @@ Name: nix-derivation Version: 1.0.0 Cabal-Version: >=1.8.0.2 Build-Type: Simple -Tested-With: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2 +Tested-With: GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2 License: BSD3 License-File: LICENSE Copyright: 2017 Gabriel Gonzalez @@ -14,7 +14,8 @@ Description: Use this package to parse and render Nix derivation files (i.e. *.drv files) Category: System Extra-Source-Files: - tests/example.drv + tests/example0.drv + tests/example1.drv Source-Repository head Type: git Location: https://github.com/Gabriel439/Haskell-Nix-Derivation-Library @@ -25,6 +26,7 @@ Library base >= 4.6.0.0 && < 5 , attoparsec >= 0.12.0.0 && < 0.14, containers < 0.6 , + deepseq >= 1.4.0.0 && < 1.5 , system-filepath >= 0.3.1 && < 0.5 , text >= 0.8.0.0 && < 1.3 , vector < 0.13 @@ -60,3 +62,17 @@ Test-Suite property system-filepath >= 0.3.1 && < 0.5 , text >= 0.8.0.0 && < 1.3 , vector < 0.13 + +Benchmark benchmark + Default-Language: Haskell2010 + Type: exitcode-stdio-1.0 + HS-Source-Dirs: bench + Main-Is: Main.hs + GHC-Options: -Wall + + Build-Depends: + base >= 4.6.0.0 && < 5 , + attoparsec >= 0.12.0.0 && < 0.14, + criterion >= 1.1.4.0 && < 1.3 , + nix-derivation , + text >= 0.8.0.0 && < 1.3 diff --git a/release.nix b/release.nix index eca790dd..3f184dab 100644 --- a/release.nix +++ b/release.nix @@ -13,7 +13,13 @@ let packageOverrides = pkgs: { haskellPackages = pkgs.haskellPackages.override { overrides = haskellPackagesNew: haskellPackagesOld: { - nix-derivation = haskellPackagesNew.callPackage ./default.nix { }; + nix-derivation = + pkgs.haskell.lib.overrideCabal + (haskellPackagesNew.callPackage ./default.nix { }) + (_: { + withBenchmarkDepends = true; + } + ); }; }; }; diff --git a/src/Nix/Derivation/Parser.hs b/src/Nix/Derivation/Parser.hs index 3f76e08c..18139b97 100644 --- a/src/Nix/Derivation/Parser.hs +++ b/src/Nix/Derivation/Parser.hs @@ -24,6 +24,7 @@ import qualified Data.Attoparsec.Text.Lazy import qualified Data.Map import qualified Data.Set import qualified Data.Text +import qualified Data.Text.Lazy import qualified Data.Vector import qualified Filesystem.Path.CurrentOS @@ -111,9 +112,10 @@ string = do 't' -> return '\t' _ -> return char1 text1 <- loop - return (Data.Text.cons char2 text1) - return (text0 <> text2) - loop + return (Data.Text.Lazy.cons char2 text1) + return (Data.Text.Lazy.fromStrict text0 <> text2) + text <- loop + return (Data.Text.Lazy.toStrict text) filepath :: Parser FilePath filepath = do diff --git a/src/Nix/Derivation/Types.hs b/src/Nix/Derivation/Types.hs index 8d17c6d2..31d853e1 100644 --- a/src/Nix/Derivation/Types.hs +++ b/src/Nix/Derivation/Types.hs @@ -1,3 +1,5 @@ +{-# LANGUAGE DeriveGeneric #-} + -- | Shared types module Nix.Derivation.Types @@ -6,11 +8,13 @@ module Nix.Derivation.Types , DerivationOutput(..) ) where +import Control.DeepSeq (NFData) import Data.Map (Map) import Data.Set (Set) import Data.Text (Text) import Data.Vector (Vector) import Filesystem.Path.CurrentOS (FilePath) +import GHC.Generics (Generic) import Prelude hiding (FilePath) -- | A Nix derivation @@ -31,7 +35,9 @@ data Derivation = Derivation , env :: Map Text Text -- ^ Environment variables provided to the executable used to build the -- derivation - } deriving (Eq, Ord, Show) + } deriving (Eq, Generic, Ord, Show) + +instance NFData Derivation -- | An output of a Nix derivation data DerivationOutput = DerivationOutput @@ -41,4 +47,6 @@ data DerivationOutput = DerivationOutput -- ^ Hash used for expected hash computation , hash :: Text -- ^ Expected hash - } deriving (Eq, Ord, Show) + } deriving (Eq, Generic, Ord, Show) + +instance NFData DerivationOutput diff --git a/tests/Example.hs b/tests/Example.hs index e41dc1a3..035b69cf 100644 --- a/tests/Example.hs +++ b/tests/Example.hs @@ -9,7 +9,7 @@ import Data.Attoparsec.Text.Lazy (Result(..)) main :: IO () main = do - text0 <- Data.Text.Lazy.IO.readFile "tests/example.drv" + text0 <- Data.Text.Lazy.IO.readFile "tests/example0.drv" derivation <- case Data.Attoparsec.Text.Lazy.parse Nix.Derivation.parseDerivation text0 of Fail _ _ string -> fail string Done _ derivation -> return derivation diff --git a/tests/example.drv b/tests/example0.drv similarity index 100% rename from tests/example.drv rename to tests/example0.drv diff --git a/tests/example1.drv b/tests/example1.drv new file mode 100644 index 00000000..0d913b6d --- /dev/null +++ b/tests/example1.drv @@ -0,0 +1 @@ +Derive([("out","/nix/store/w3zbr9zj9mn08hnirn34wsxhry40qi3c-ghc-8.0.2-with-packages","","")],[("/nix/store/0cyv377kjnhjc9j1pb0m530lczqj4ksm-optparse-generic-1.1.5.drv",["out"]),("/nix/store/0w9vy2hmz50j0yhlbj519hnpjbvqhjrj-cookie-0.4.2.1.drv",["out"]),("/nix/store/1b75igh40c9agy3sfyl5n7av4070swvn-old-locale-1.0.0.7.drv",["out"]),("/nix/store/1g2qxhbpk7qjyz8qbami29bn7qmnmgpk-tagged-0.8.5.drv",["out"]),("/nix/store/20m5alpbwyvyhh43aq3prw07g48apdnj-parsers-0.12.4.drv",["out"]),("/nix/store/2bmxgjskcw4vdmcqrw9pc9yjffsqn3i9-byteable-0.1.1.drv",["out"]),("/nix/store/3fji5p4x9j0cb3q3lp8amrj0qak9d471-asn1-encoding-0.9.5.drv",["out"]),("/nix/store/43hyjsydndk7vsdjs94why36s8isn6fw-kan-extensions-5.0.1.drv",["out"]),("/nix/store/4hkya8j2isw660pj6b0q3by85q2wz1zw-free-4.12.4.drv",["out"]),("/nix/store/56l353i7v6i7i5vkk2qx4wi4r6p4xll1-void-0.7.2.drv",["out"]),("/nix/store/5c748d8gmrmg2gy4792a0kzp5bjw8sgr-cereal-0.5.4.0.drv",["out"]),("/nix/store/5d3v9g9jjqznbpxrlgvcyvmqqz2ffpgc-fingertree-0.1.1.0.drv",["out"]),("/nix/store/5hx7hjjrwqa4zjd9ql224aif86ncj764-hook.drv",["out"]),("/nix/store/5rpa05i9i5p3i0a06lhyvgg1nvlwnlfi-unordered-containers-0.2.8.0.drv",["out"]),("/nix/store/5x6d3f9krpqlmzhmk71qf7m97g38hba1-base-prelude-1.0.1.1.drv",["out"]),("/nix/store/61fzrmaxsfc9q4qzsdcrsaqgg05hr6xi-bifunctors-5.4.2.drv",["out"]),("/nix/store/6l4s2nlxc9fq8c3y3j2k2c7af5llx278-hashable-1.2.6.0.drv",["out"]),("/nix/store/6n2kl1fnn66a24ipjm1dxjhhvni1404r-mtl-2.2.1.drv",["out"]),("/nix/store/6qggipw2ra59q6333y25gywllbbcx3p5-hourglass-0.2.10.drv",["out"]),("/nix/store/7545pmiaccgvkxjfvl9cm0qk7y1x96wi-reflection-2.1.2.drv",["out"]),("/nix/store/75iir4x52007r0fq41kwk5cdfvmi02jp-profunctors-5.2.drv",["out"]),("/nix/store/7ah4kd8kbwsfr350wkr0y4i0h6gm7vc8-base64-bytestring-1.0.0.1.drv",["out"]),("/nix/store/7d6yxihb828lgs4199f81k17jh8987z6-lndir-1.0.3.drv",["out"]),("/nix/store/7f6ddryzkw9jckayqs1gdz18njrqd0fq-random-1.1.drv",["out"]),("/nix/store/8p1f0rs49czq74yxlfcimlag9wnbwsc5-http-client-tls-0.3.4.1.drv",["out"]),("/nix/store/9w2n7jqc9ll78r7xj31ckrqcq6g8g8kf-integer-logarithms-1.0.1.drv",["out"]),("/nix/store/a2ar311g8chbi4ila55qzi3dfp9g5zr6-blaze-html-0.8.1.3.drv",["out"]),("/nix/store/ahypsxsxcczsllax40jnccdg5ilps2lq-http-client-0.5.6.1.drv",["out"]),("/nix/store/as62r0pdaq0q76rxz719xy33vqa7xcal-double-conversion-2.0.2.0.drv",["out"]),("/nix/store/b67b65arib97rsl4z5iqz03gf24ymvz5-http-types-0.9.1.drv",["out"]),("/nix/store/bczn7hbvp39aplp70gvmyijdysvkyspg-primitive-0.6.1.0.drv",["out"]),("/nix/store/bwf0a834k4jf5ss2ccribn9w7g2r3j3m-stdenv.drv",["out"]),("/nix/store/ckl2x2vkqj82k4b7c5l8p611g6jmfbsz-zlib-0.6.1.2.drv",["out"]),("/nix/store/clxg57lhlflbjrk6w3fv51fxjnqkk7q4-transformers-compat-0.5.1.4.drv",["out"]),("/nix/store/d1n1p6mdabwkgkc7y6151j37c4kqh1a2-exceptions-0.8.3.drv",["out"]),("/nix/store/dg6n7519y227s9c867wqi2v40cj41zqy-attoparsec-0.13.1.0.drv",["out"]),("/nix/store/f3l740wl94r84fgsiindy88jppcjya6l-text-format-0.3.1.1.drv",["out"]),("/nix/store/f67vqhk71lrab7ncx8fz8bj7iggmm66f-cryptonite-0.21.drv",["out"]),("/nix/store/fdq2dn4gal13xl9jbyk8igvaw5f2x9b5-blaze-builder-0.4.0.2.drv",["out"]),("/nix/store/fr1acpclaljwizrvic520wdf36kmxjwr-blaze-markup-0.7.1.1.drv",["out"]),("/nix/store/fyi4gg70v1lgjz03v07flnmjr8x55mqk-async-2.1.1.1.drv",["out"]),("/nix/store/ginljsxbpxli394mc06gvqkmvddhqwlc-x509-store-1.6.2.drv",["out"]),("/nix/store/gq055a1910w9q6mbb5kf6p6igzg6b5ai-StateVar-1.1.0.4.drv",["out"]),("/nix/store/hhx5xjb6cm5rdkri763669bf6karrnpn-parsec-3.1.11.drv",["out"]),("/nix/store/ip7nh1r7mj4qwgra27x8i6nyz6yd1ggd-prelude-extras-0.4.0.3.drv",["out"]),("/nix/store/iqd84gv7b8dq5kddxyjimaqqlxjpqdzk-vector-0.11.0.0.drv",["out"]),("/nix/store/j24c6d5zv7nim3rkmzzapk6x61lzgizq-charset-0.3.7.1.drv",["out"]),("/nix/store/j6zji0jn6cm8b4i0fmakksk1cp54bhn0-asn1-types-0.3.2.drv",["out"]),("/nix/store/l3wmibr3b1b3a8ql8ypy860209iqbasg-connection-0.2.8.drv",["out"]),("/nix/store/lg64zgciix9644hzkfc02rfbq4qgcrf8-memory-0.14.3.drv",["out"]),("/nix/store/lnxgjiywc89iaby3g0na1sc4hryvnikq-trifecta-1.6.2.1.drv",["out"]),("/nix/store/lvm3zp40qfdqr0v9i27z7dqpdwlxprbl-text-1.2.2.1.drv",["out"]),("/nix/store/m7l8bg4k82snsl759k2mlkjlb8g0352a-foundation-0.0.7.drv",["out"]),("/nix/store/mi1fdfdkc5qc7iq2ry6095ayp9cqn075-x509-system-1.6.4.drv",["out"]),("/nix/store/mpql2q0b6a1m2vkb114f9l2s8dhy09zv-asn1-parse-0.9.4.drv",["out"]),("/nix/store/mq338r0an8lj00g88c6rpylbnmds7fbx-adjunctions-4.3.drv",["out"]),("/nix/store/n4wyn46xw0nw8a3rhqw47xd4h6bgnn5w-lens-4.15.1.drv",["out"]),("/nix/store/nv7frilmipcpylijp492l3hc0s2cmgw6-tls-1.3.10.drv",["out"]),("/nix/store/nwapw7zf014frf49c0b7y5694jyc38hm-streaming-commons-0.1.17.drv",["out"]),("/nix/store/pcg29qa8fm9niixbjy0r7bbp3s4jxk62-neat-interpolation-0.3.2.1.drv",["out"]),("/nix/store/pg609c09rfqzyfn8l4hsc1q2xy50w4p8-semigroupoids-5.1.drv",["out"]),("/nix/store/pra6ynwnksgks1xxv2l7h48swjq4vb2j-data-default-class-0.1.2.0.drv",["out"]),("/nix/store/pz3s86hbxvwr7m4x7cpz5h8z124wgk4x-x509-1.6.5.drv",["out"]),("/nix/store/qi0668xlc3q03n74k1wrqri7ss7bvphk-stm-2.4.4.1.drv",["out"]),("/nix/store/ql8bpbnl7x7ybn3rnsknpkpwvlz7s2nz-distributive-0.5.2.drv",["out"]),("/nix/store/qr8wf0b1lqwxwi6ban2k307jy91bj640-reducers-3.12.1.drv",["out"]),("/nix/store/r44a3jm3q5rhi75rl1m6jr1vgwpiyw02-hnix-0.3.4.drv",["out"]),("/nix/store/rqcq6jigs1sj53f8wrbff3s06wzazfqw-comonad-5.0.1.drv",["out"]),("/nix/store/s1ymda8d763cn5gq4cw107h19xs1ddz0-ansi-wl-pprint-0.6.7.3.drv",["out"]),("/nix/store/sdx411558r03fdvfi3p6wzfsi701sv4w-system-fileio-0.3.16.3.drv",["out"]),("/nix/store/v0srwl68sz6dirasq53bd3ddjipa1d5b-deriving-compat-0.3.6.drv",["out"]),("/nix/store/vpqjk2wral953nnqnhvp8zbmkbhnyxls-x509-validation-1.6.5.drv",["out"]),("/nix/store/vr8scnq8lxgc0m6k7bqjwi4fg0k55lxn-data-fix-0.0.4.drv",["out"]),("/nix/store/vwhic7ibwkzqk65mqicb29d5qz06gkns-socks-0.5.5.drv",["out"]),("/nix/store/w6a3c55nhmpcia6cvdg31nqsc7v910lc-ansi-terminal-0.6.2.3.drv",["out"]),("/nix/store/wdgbs33iwqadfmlaymw00k6iwnf3as7z-mime-types-0.1.0.7.drv",["out"]),("/nix/store/wld7wjy6lws02rky68mpg0x591wv0j6v-pem-0.2.2.drv",["out"]),("/nix/store/wx9vx1z55bzkzym0lzbgpzd7rrsx9w9b-scientific-0.3.4.12.drv",["out"]),("/nix/store/x2dkgpklc1adq1cgg1k8ykdqv7ghwhzm-system-filepath-0.4.13.4.drv",["out"]),("/nix/store/x50y5qihwsn0lfjhrf1s81b5hgb9w632-bash-4.4-p5.drv",["out"]),("/nix/store/x8k0rsb1ig82vdls0dc6jdlny7r04izj-parallel-3.2.1.1.drv",["out"]),("/nix/store/xbygsq84395vhj7bnh7786i9864jf9i9-ghc-8.0.2.drv",["out"]),("/nix/store/xp7jayhmiphx0zqxx9dxrk673shhj89l-optparse-applicative-0.13.2.0.drv",["out"]),("/nix/store/xzda3rxckhf0h3lp1hr6wanyig9s9y1p-utf8-string-1.0.1.1.drv",["out"]),("/nix/store/y4ll9c29g76jzycl7zhdmqzxgciyrfr1-case-insensitive-1.2.0.9.drv",["out"]),("/nix/store/y8l0lv08hfi6qnrzd25dxgi4712yjf9f-base-orphans-0.5.4.drv",["out"]),("/nix/store/z036z61lsrk2gqbwljix0akzhz2bgl8j-semigroups-0.18.2.drv",["out"]),("/nix/store/z8vpk1rwkikc8pg20vyg5kvsdv626ksw-dhall-1.3.0.drv",["out"]),("/nix/store/zdx2r8q401h7xcyh7jg0cnp092iwlhmv-contravariant-1.4.drv",["out"]),("/nix/store/zg5as9jrs5vfa5iw7539vihmwm436g1q-network-uri-2.6.1.0.drv",["out"]),("/nix/store/zvxd18a65gwcg3bz7v1rb0h59w9wwi9d-network-2.6.3.1.drv",["out"])],["/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"],"x86_64-linux","/nix/store/fi3mbd2ml4pbgzyasrlnp0wyy6qi48fh-bash-4.4-p5/bin/bash",["-e","/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"],[("allowSubstitutes",""),("buildCommand","mkdir -p $out\nfor i in $paths; do\n /nix/store/lnai0im3lcpb03arxfi0wx1dm7anf4f8-lndir-1.0.3/bin/lndir $i $out\ndone\n. /nix/store/plmya6mkfvq658ba7z6j6n36r5pdbxk5-hook/nix-support/setup-hook\n\n# wrap compiler executables with correct env variables\n\nfor prg in ghc ghci ghc-8.0.2 ghci-8.0.2; do\n if [[ -x \"/nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg\" ]]; then\n rm -f $out/bin/$prg\n makeWrapper /nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg $out/bin/$prg \\\n --add-flags '\"-B$NIX_GHC_LIBDIR\"' \\\n --set \"NIX_GHC\" \"$out/bin/ghc\" \\\n --set \"NIX_GHCPKG\" \"$out/bin/ghc-pkg\" \\\n --set \"NIX_GHC_DOCDIR\" \"$out/share/doc/ghc/html\" \\\n --set \"NIX_GHC_LIBDIR\" \"$out/lib/ghc-8.0.2\" \\\n \n fi\ndone\n\nfor prg in runghc runhaskell; do\n if [[ -x \"/nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg\" ]]; then\n rm -f $out/bin/$prg\n makeWrapper /nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg $out/bin/$prg \\\n --add-flags \"-f $out/bin/ghc\" \\\n --set \"NIX_GHC\" \"$out/bin/ghc\" \\\n --set \"NIX_GHCPKG\" \"$out/bin/ghc-pkg\" \\\n --set \"NIX_GHC_DOCDIR\" \"$out/share/doc/ghc/html\" \\\n --set \"NIX_GHC_LIBDIR\" \"$out/lib/ghc-8.0.2\"\n fi\ndone\n\nfor prg in ghc-pkg ghc-pkg-8.0.2; do\n if [[ -x \"/nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg\" ]]; then\n rm -f $out/bin/$prg\n makeWrapper /nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg $out/bin/$prg --add-flags \"--global-package-db=$out/lib/ghc-8.0.2/package.conf.d\"\n fi\ndone\n$out/bin/ghc-pkg recache\n\n$out/bin/ghc-pkg check\n\n"),("buildInputs",""),("builder","/nix/store/fi3mbd2ml4pbgzyasrlnp0wyy6qi48fh-bash-4.4-p5/bin/bash"),("extraOutputsToInstall","out doc"),("ignoreCollisions",""),("name","ghc-8.0.2-with-packages"),("nativeBuildInputs",""),("out","/nix/store/w3zbr9zj9mn08hnirn34wsxhry40qi3c-ghc-8.0.2-with-packages"),("passAsFile","buildCommand"),("paths","/nix/store/rlsammwp1ib8d3d9qgbppmdhkbdfg3i9-deriving-compat-0.3.6 /nix/store/v2qsqznrik64f46msahvgg7dmaiag18k-hnix-0.3.4 /nix/store/vbkqj8zdckqqiyjh08ykx75fwc90gwg4-optparse-applicative-0.13.2.0 /nix/store/6m7qia8q0rkdkzvmiak38kdscf27malf-optparse-generic-1.1.5 /nix/store/r687llig7vn9x15hhkmfak01ff7082n6-utf8-string-1.0.1.1 /nix/store/j6gvad67dav8fl3vdbqmar84kgmh5gar-reducers-3.12.1 /nix/store/i8wf08764lknc0f9ja12miqvg509jn1k-fingertree-0.1.1.0 /nix/store/301hq4fabrpbi3l47n908gvakkzq1s88-blaze-markup-0.7.1.1 /nix/store/055mhi44s20x5xgxdjr82vmhnyv79pzl-blaze-html-0.8.1.3 /nix/store/vnc1yyig90skcwx3l1xrbp1jqwmmb9xv-trifecta-1.6.2.1 /nix/store/vraffi24marw5sks8b78xrim6c8i1ng6-double-conversion-2.0.2.0 /nix/store/kwdk03p0lyk5lyll1fp7a6z20j17b3sx-text-format-0.3.1.1 /nix/store/zn5hlw3y94sbli4ssygr2w04mpb396zs-system-filepath-0.4.13.4 /nix/store/jn7lbnk0gsirj8kb02an31v8idy7ym3c-system-fileio-0.3.16.3 /nix/store/9frfci9ywf9lc216ci9nwc1yy0qwrn1b-integer-logarithms-1.0.1 /nix/store/rps46jwa7yyab629p27lar094gk8dal2-scientific-0.3.4.12 /nix/store/c4a3ynvnv3kdxgd7ngmnjhka4mvfk8ll-attoparsec-0.13.1.0 /nix/store/kc34l1gpzh65y4gclmv4dgv6agpmagdi-parsers-0.12.4 /nix/store/1kf78yxf3lliagb5rc5din24iq40g96y-base-prelude-1.0.1.1 /nix/store/hi868d12pkzcbzyvp7a7cigc58mp2lmg-neat-interpolation-0.3.2.1 /nix/store/h00jrbdvzj4yfy796j8vq00lkd1gxr6w-primitive-0.6.1.0 /nix/store/vys8qsf317rn8qwy00p80zlywb47lqwz-vector-0.11.0.0 /nix/store/wchch11312m3lxkwl8rad04x02svcs3i-reflection-2.1.2 /nix/store/jj1kfv52mjxp54flz8v5ba64va3hvy22-parallel-3.2.1.1 /nix/store/jwj23y7vfvs14jdrkw1py9q7lm9fyhy4-adjunctions-4.3 /nix/store/px4979la9b98knwv36551zg3p5jb69lw-kan-extensions-5.0.1 /nix/store/2cp1ar0f73jrcn231ai07zpwayy735j2-semigroupoids-5.1 /nix/store/3nkxw5wdadckz28laijrvwdkkfqp07sb-profunctors-5.2 /nix/store/bd3njvy0ahcsqw47vaz5zayhx34hari7-prelude-extras-0.4.0.3 /nix/store/zdp7zqasz1l1wifpngbg6ngq189gbbqh-free-4.12.4 /nix/store/n7c5ynfqc6j570bbyaajqx34c3pvfvph-tagged-0.8.5 /nix/store/xdkhd7mkqj2mmcami8ycmf7j0valwp5h-distributive-0.5.2 /nix/store/9dxba4g9x0xjj21r3vchqnh4rdwbc31b-void-0.7.2 /nix/store/dahah2ivrn4hc5gjygnlvxlad2399zqh-StateVar-1.1.0.4 /nix/store/f2rdi1bx46fs165n1j316k5w90ab6lwy-contravariant-1.4 /nix/store/mgg9rsvhvn4dd4qzv559nn24iqvspjnb-comonad-5.0.1 /nix/store/18n8i570pf4gpszdyc0bki9qxm1p9xd7-bifunctors-5.4.2 /nix/store/d8ys5wq4wrvdjqw0bzv3y23zqprkhjs2-base-orphans-0.5.4 /nix/store/j4hbyhnj4a2z4z4vb1437vk7ha0b287a-lens-4.15.1 /nix/store/ra3jh12mbyz82n4gvj2bam77vl8aabbq-x509-system-1.6.4 /nix/store/ps8915q1047frp891jg1anp85ads0s9b-x509-validation-1.6.5 /nix/store/5vrgrls6l1cdsbbznis39chx8scq2r98-x509-store-1.6.2 /nix/store/7vvg8y8fp0s50qiciq11irfvh31f1q58-pem-0.2.2 /nix/store/myv75wk9s19f8vms2dcy6sl773288zy4-asn1-parse-0.9.4 /nix/store/kwyc1jdz09lazw21qpc96wyamxalcg11-x509-1.6.5 /nix/store/gadc7c6d1lqn0wqk29bhn56is67x0r45-cryptonite-0.21 /nix/store/ix26y5rpidwpgjzrsixz0ff59j1p1swr-foundation-0.0.7 /nix/store/n784p4qh18zx9v8ag3n3ypszq1kifjjr-memory-0.14.3 /nix/store/h3qq6m5ahdb4kw784gcvx2skil8ilks8-hourglass-0.2.10 /nix/store/dn65dl65spk4j0sky2zpdig75c42ycj1-asn1-types-0.3.2 /nix/store/s5jklkk0y6i7d8h3akgsciv1kv2js786-asn1-encoding-0.9.5 /nix/store/g5qjgns5cyz9c5xw4w5s2iji1kbhg47z-tls-1.3.10 /nix/store/iyllk46by75f428pwis9v74jpr1rmk4x-cereal-0.5.4.0 /nix/store/b22wyyl3wdl6kb7gkpk3yxnynk340lya-socks-0.5.5 /nix/store/05r3i8w2n7hbxqyb4w8rina9rldyacd3-byteable-0.1.1 /nix/store/xjbl6w60czyfqlfwwfs5q93by144yr1n-connection-0.2.8 /nix/store/j10yqzk323rvnwgsk3nj7rgmvqlv035a-http-client-tls-0.3.4.1 /nix/store/vf84v2398g55mai2gjh2d9gipwizhhzd-zlib-0.6.1.2 /nix/store/7h7vy3mi603y536dgvxwfglaacxw5ra8-async-2.1.1.1 /nix/store/y6hh2ifv35afw1j5phpzp1y72x532izn-streaming-commons-0.1.17 /nix/store/f5jdarp8djisa1wrv4bv1saimrabcb3f-random-1.1 /nix/store/18vpnmd28bnjib6andw8bx522wcb3zwa-parsec-3.1.11 /nix/store/i3ra66pcpj0v9wq3m00gh9i72br2bki3-network-uri-2.6.1.0 /nix/store/2ck9avbwacfpi16p2ib2shw951mx33pz-network-2.6.3.1 /nix/store/rz0227nv8n8kdrxjg3arya6r2ixxjh4h-mime-types-0.1.0.7 /nix/store/rx71j4kg0l02dginiswnmwswdq9i9msv-http-types-0.9.1 /nix/store/y2ca4scn0n2f9qsmvsiixcnx11793jlf-transformers-compat-0.5.1.4 /nix/store/bzicr83ibzzzbab6cjkb3i95sc8cvxy9-stm-2.4.4.1 /nix/store/qk5pl6r2h0vfkhhwjgrv8x1ldf8dyj5a-mtl-2.2.1 /nix/store/0d6k71ljl108dgq1l7l3pz12bfwv0z4h-exceptions-0.8.3 /nix/store/z5k23ymwjhhpd670a7mcsm1869hlpncf-old-locale-1.0.0.7 /nix/store/k4an783d4j3m48fqhx7gpnizqg2ns38j-data-default-class-0.1.2.0 /nix/store/p5867jsig02zi0ynww9w4916nm0k527s-cookie-0.4.2.1 /nix/store/wy7j42kqlw1sskagmyc1bzb0xv04s2na-case-insensitive-1.2.0.9 /nix/store/j35339b0nk7k3qaq3m75nl3i4x603rqf-blaze-builder-0.4.0.2 /nix/store/33mip0ql9x1jjbhi34kf8izh4ilyf2k0-base64-bytestring-1.0.0.1 /nix/store/29a73kd2jkwvfdcrhysmi5xjr7nysrxf-http-client-0.5.6.1 /nix/store/d2hy666g79qvhmbh520x5jclwvnr1gk2-text-1.2.2.1 /nix/store/2bdzia66lg08d5zngmllcjry2c08m96j-hashable-1.2.6.0 /nix/store/7kdgc6c0b21s9j5qgg0s0gxj7iid2wk5-unordered-containers-0.2.8.0 /nix/store/zsryzwadshszfnkm740b2412v88iqgi4-semigroups-0.18.2 /nix/store/h2c0kz3m83x6fkl2jzkmin8xvkmfgs7s-charset-0.3.7.1 /nix/store/gapj6j0ya5bi9q9dxspda15k50gx8f1v-ansi-terminal-0.6.2.3 /nix/store/l46769n2p6rlh936zrbwznq3zxxa6mjd-ansi-wl-pprint-0.6.7.3 /nix/store/p7zmpgz0sq5pamgrf1xvhvidc3m4cfmk-dhall-1.3.0 /nix/store/938ndd0mqfm148367lwhl6pk5smv5bm0-data-fix-0.0.4 /nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2"),("preferLocalBuild","1"),("propagatedBuildInputs",""),("propagatedNativeBuildInputs",""),("stdenv","/nix/store/685n25b9yc8sds57vljk459ldly1xyhn-stdenv"),("system","x86_64-linux")]) \ No newline at end of file From 1e1830a6aa8e0fced1f7bfc19c626713a756e28a Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Sat, 21 Oct 2017 13:26:11 -0700 Subject: [PATCH 09/58] Add `shell.nix` --- shell.nix | 1 + 1 file changed, 1 insertion(+) create mode 100644 shell.nix diff --git a/shell.nix b/shell.nix new file mode 100644 index 00000000..29b0da9a --- /dev/null +++ b/shell.nix @@ -0,0 +1 @@ +(import ./release.nix).nix-derivation.env From 52270b779089cdd6c10d751fcd2eda1fbdfdafde Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Sat, 21 Oct 2017 13:28:42 -0700 Subject: [PATCH 10/58] Add `pretty-derivation` executable --- default.nix | 6 ++++-- nix-derivation.cabal | 15 +++++++++++++++ pretty-derivation/Main.hs | 15 +++++++++++++++ release.nix | 2 +- 4 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 pretty-derivation/Main.hs diff --git a/default.nix b/default.nix index 948fd041..4834aa17 100644 --- a/default.nix +++ b/default.nix @@ -1,17 +1,19 @@ -{ mkDerivation, attoparsec, base, containers, criterion, deepseq +{ mkDerivation, attoparsec, base, containers, deepseq, pretty-show , QuickCheck, stdenv, system-filepath, text, vector }: mkDerivation { pname = "nix-derivation"; version = "1.0.0"; src = ./.; + isLibrary = true; + isExecutable = true; libraryHaskellDepends = [ attoparsec base containers deepseq system-filepath text vector ]; + executableHaskellDepends = [ attoparsec base pretty-show text ]; testHaskellDepends = [ attoparsec base QuickCheck system-filepath text vector ]; - benchmarkHaskellDepends = [ attoparsec base criterion text ]; description = "Parse and render *.drv files"; license = stdenv.lib.licenses.bsd3; } diff --git a/nix-derivation.cabal b/nix-derivation.cabal index 55400bc4..e8f35756 100644 --- a/nix-derivation.cabal +++ b/nix-derivation.cabal @@ -12,6 +12,10 @@ Bug-Reports: https://github.com/Gabriel439/Haskell-Nix-Derivation-Library/issues Synopsis: Parse and render *.drv files Description: Use this package to parse and render Nix derivation files (i.e. *.drv files) + . + This package also provides a @pretty-derivation@ executable which reads a + derivation on standard input and outputs the pretty-printed Haskell + representation on standard output Category: System Extra-Source-Files: tests/example0.drv @@ -38,6 +42,17 @@ Library Nix.Derivation.Types GHC-Options: -Wall +Executable pretty-derivation + Hs-Source-Dirs: pretty-derivation + Build-Depends: + base >= 4.6.0.0 && < 5 , + attoparsec >= 0.12.0.0 && < 0.14, + pretty-show >= 1.6.11 && < 1.7 , + text >= 0.8.0.0 && < 1.3 , + nix-derivation + GHC-Options: -Wall + Main-Is: Main.hs + Test-Suite example Type: exitcode-stdio-1.0 Hs-Source-Dirs: tests diff --git a/pretty-derivation/Main.hs b/pretty-derivation/Main.hs new file mode 100644 index 00000000..a405c2cc --- /dev/null +++ b/pretty-derivation/Main.hs @@ -0,0 +1,15 @@ +module Main where + +import Data.Attoparsec.Text.Lazy (Result(..)) + +import qualified Data.Attoparsec.Text.Lazy +import qualified Data.Text.Lazy.IO +import qualified Nix.Derivation +import qualified Text.Show.Pretty + +main :: IO () +main = do + text <- Data.Text.Lazy.IO.getContents + case Data.Attoparsec.Text.Lazy.parse Nix.Derivation.parseDerivation text of + Fail _ _ err -> fail err + Done _ derivation -> Text.Show.Pretty.pPrint derivation diff --git a/release.nix b/release.nix index 3f184dab..cfec2822 100644 --- a/release.nix +++ b/release.nix @@ -17,7 +17,7 @@ let pkgs.haskell.lib.overrideCabal (haskellPackagesNew.callPackage ./default.nix { }) (_: { - withBenchmarkDepends = true; +# withBenchmarkDepends = true; } ); }; From ad19d04c3f2e926b18728fbb4804bfef47b0d5b3 Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Sat, 21 Oct 2017 13:31:34 -0700 Subject: [PATCH 11/58] Document `pretty-derivation` in the `README` --- README.md | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/README.md b/README.md index f0d05927..21f38c27 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,95 @@ E-Types-2.13.tar.gz\"),(\"stdenv\",\"/nix/store/s3rlr45jzlzx0d6k2azlpxa5zwzr7xyy -stdenv\"),(\"system\",\"x86_64-linux\")])" ``` +You can also use the `pretty-derivation` executable installed as part of this +package to pretty-print the Haskell representation of a Nix derivations: + +```shell +$ pretty-derivation < /nix/store/0008hdcdvkrr5mcqahy416hv6rmb5fwg-void-0.7.1.tar.gz.drv +Derivation + { outputs = + fromList + [ ( "out" + , DerivationOutput + { path = + FilePath + "/nix/store/fbbqa4x05q9x0w6s1fqmx7k676d2zyz1-void-0.7.1.tar.gz" + , hashAlgo = "sha256" + , hash = + "c9f0fd93680c029abb9654b5464be260652829961b18b7046f96a0df95e825f4" + } + ) + ] + , inputDrvs = + fromList + [ ( FilePath + "/nix/store/cwnn2alfww3six2ywph5hnnlmxwhv9c7-curl-7.52.1.drv" + , fromList [ "dev" ] + ) + , ( FilePath + "/nix/store/kzs0g1ch3a59ar14xnms1wj22p2bnr9l-stdenv.drv" + , fromList [ "out" ] + ) + , ( FilePath + "/nix/store/qq7pqyfn98314fd30xspb1hi3rqda2lh-bash-4.3-p48.drv" + , fromList [ "out" ] + ) + , ( FilePath + "/nix/store/r1b0rbna957biiy63m75yxsw3aphps9b-mirrors-list.drv" + , fromList [ "out" ] + ) + ] + , inputSrcs = + fromList + [ FilePath "/nix/store/5pqfb6ik1cxqq1d0irlx3060jx1qjmsn-builder.sh" + ] + , platform = "x86_64-linux" + , builder = + "/nix/store/gabjbkwga2dhhp2wzyaxl83r8hjjfc37-bash-4.3-p48/bin/bash" + , args = + [ "-e" , "/nix/store/5pqfb6ik1cxqq1d0irlx3060jx1qjmsn-builder.sh" ] + , env = + fromList + [ ( "buildInputs" , "" ) + , ( "builder" + , "/nix/store/gabjbkwga2dhhp2wzyaxl83r8hjjfc37-bash-4.3-p48/bin/bash" + ) + , ( "curlOpts" , "" ) + , ( "downloadToTemp" , "" ) + , ( "executable" , "" ) + , ( "impureEnvVars" + , "http_proxy https_proxy ftp_proxy all_proxy no_proxy NIX_CURL_FLAGS NIX_HASHED_MIRRORS NIX_CONNECT_TIMEOUT NIX_MIRRORS_apache NIX_MIRRORS_bioc NIX_MIRRORS_bitlbee NIX_MIRRORS_cpan NIX_MIRRORS_debian NIX_MIRRORS_fedora NIX_MIRRORS_gcc NIX_MIRRORS_gentoo NIX_MIRRORS_gnome NIX_MIRRORS_gnu NIX_MIRRORS_gnupg NIX_MIRRORS_hackage NIX_MIRRORS_hashedMirrors NIX_MIRRORS_imagemagick NIX_MIRRORS_kde NIX_MIRRORS_kernel NIX_MIRRORS_metalab NIX_MIRRORS_mozilla NIX_MIRRORS_mysql NIX_MIRRORS_oldsuse NIX_MIRRORS_openbsd NIX_MIRRORS_opensuse NIX_MIRRORS_postgresql NIX_MIRRORS_pypi NIX_MIRRORS_roy NIX_MIRRORS_sagemath NIX_MIRRORS_samba NIX_MIRRORS_savannah NIX_MIRRORS_sourceforge NIX_MIRRORS_sourceforgejp NIX_MIRRORS_steamrt NIX_MIRRORS_ubuntu NIX_MIRRORS_xfce NIX_MIRRORS_xorg" + ) + , ( "mirrorsFile" + , "/nix/store/ab4zh0ga99y5xj441arp89zl8s4jfc7y-mirrors-list" + ) + , ( "name" , "void-0.7.1.tar.gz" ) + , ( "nativeBuildInputs" + , "/nix/store/3ngwsbzhibvc434nqwq6jph6w7c2was6-curl-7.52.1-dev" + ) + , ( "out" + , "/nix/store/fbbqa4x05q9x0w6s1fqmx7k676d2zyz1-void-0.7.1.tar.gz" + ) + , ( "outputHash" + , "c9f0fd93680c029abb9654b5464be260652829961b18b7046f96a0df95e825f4" + ) + , ( "outputHashAlgo" , "sha256" ) + , ( "outputHashMode" , "flat" ) + , ( "postFetch" , "" ) + , ( "preferHashedMirrors" , "1" ) + , ( "preferLocalBuild" , "1" ) + , ( "propagatedBuildInputs" , "" ) + , ( "propagatedNativeBuildInputs" , "" ) + , ( "showURLs" , "" ) + , ( "stdenv" + , "/nix/store/985d95clq0216a6pcp3qzw4igp84ajvr-stdenv" + ) + , ( "system" , "x86_64-linux" ) + , ( "urls" , "mirror://hackage/void-0.7.1.tar.gz" ) + ] + } +``` + ## Development status [![Build Status](https://travis-ci.org/Gabriel439/Haskell-Nix-Derivation-Library.png)](https://travis-ci.org/Gabriel439/Haskell-Nix-Derivation-Library) From 3b6ca711292a9571c501655cd10291ec28614ec0 Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Sat, 21 Oct 2017 13:32:21 -0700 Subject: [PATCH 12/58] =?UTF-8?q?Version=201.0.0=20=E2=86=92=201.0.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- default.nix | 2 +- nix-derivation.cabal | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 21f38c27..dfdab0dc 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# `nix-derivation 1.0.0` +# `nix-derivation 1.0.1` Use this package to parse and render Nix derivations such as those stored in `/nix/store/*.drv` files. For example, if you had the following derivation diff --git a/default.nix b/default.nix index 4834aa17..3578902a 100644 --- a/default.nix +++ b/default.nix @@ -3,7 +3,7 @@ }: mkDerivation { pname = "nix-derivation"; - version = "1.0.0"; + version = "1.0.1"; src = ./.; isLibrary = true; isExecutable = true; diff --git a/nix-derivation.cabal b/nix-derivation.cabal index e8f35756..d24955ef 100644 --- a/nix-derivation.cabal +++ b/nix-derivation.cabal @@ -1,5 +1,5 @@ Name: nix-derivation -Version: 1.0.0 +Version: 1.0.1 Cabal-Version: >=1.8.0.2 Build-Type: Simple Tested-With: GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2 From eea98e0819472aadc0f5cd06a507e6cf76fc8a9a Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Sat, 21 Oct 2017 13:34:23 -0700 Subject: [PATCH 13/58] Fix `.cabal` file --- nix-derivation.cabal | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/nix-derivation.cabal b/nix-derivation.cabal index d24955ef..7ab8224d 100644 --- a/nix-derivation.cabal +++ b/nix-derivation.cabal @@ -1,6 +1,6 @@ Name: nix-derivation Version: 1.0.1 -Cabal-Version: >=1.8.0.2 +Cabal-Version: >=1.10 Build-Type: Simple Tested-With: GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2 License: BSD3 @@ -25,6 +25,7 @@ Source-Repository head Location: https://github.com/Gabriel439/Haskell-Nix-Derivation-Library Library + Default-Language: Haskell2010 Hs-Source-Dirs: src Build-Depends: base >= 4.6.0.0 && < 5 , @@ -43,6 +44,7 @@ Library GHC-Options: -Wall Executable pretty-derivation + Default-Language: Haskell2010 Hs-Source-Dirs: pretty-derivation Build-Depends: base >= 4.6.0.0 && < 5 , @@ -54,6 +56,7 @@ Executable pretty-derivation Main-Is: Main.hs Test-Suite example + Default-Language: Haskell2010 Type: exitcode-stdio-1.0 Hs-Source-Dirs: tests Main-Is: Example.hs @@ -65,6 +68,7 @@ Test-Suite example text >= 0.8.0.0 && < 1.3 Test-Suite property + Default-Language: Haskell2010 Type: exitcode-stdio-1.0 Hs-Source-Dirs: tests Main-Is: Property.hs From a932ba47e1bc754ea94aa349cee7176b1372eeb7 Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Sun, 4 Nov 2018 08:46:12 -0800 Subject: [PATCH 14/58] Increase upper bounds on dependencies (#2) Fixes #1 --- .travis.yml | 84 ++------------------------------------------ default.nix | 5 +-- nix-derivation.cabal | 8 ++--- 3 files changed, 9 insertions(+), 88 deletions(-) diff --git a/.travis.yml b/.travis.yml index 46c63923..c60be3f5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,82 +1,2 @@ -# This file has been generated -- see https://github.com/hvr/multi-ghc-travis -language: c -sudo: false - -cache: - directories: - - $HOME/.cabsnap - - $HOME/.cabal/packages - -before_cache: - - rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log - - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.tar - -matrix: - include: - - env: CABALVER=1.18 GHCVER=7.8.4 - compiler: ": #GHC 7.8.4" - addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4], sources: [hvr-ghc]}} - - env: CABALVER=1.22 GHCVER=7.10.3 - compiler: ": #GHC 7.10.3" - addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3], sources: [hvr-ghc]}} - - env: CABALVER=1.24 GHCVER=8.0.2 - compiler: ": #GHC 8.0.2" - addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.2], sources: [hvr-ghc]}} - -before_install: - - unset CC - - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH - -install: - - cabal --version - - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]" - - if [ -f $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz ]; - then - zcat $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz > - $HOME/.cabal/packages/hackage.haskell.org/00-index.tar; - fi - - travis_retry cabal update -v - - sed -i 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config - - cabal install --only-dependencies --enable-tests --dry -v > installplan.txt - - sed -i -e '1,/^Resolving /d' installplan.txt; cat installplan.txt - -# check whether current requested install-plan matches cached package-db snapshot - - if diff -u $HOME/.cabsnap/installplan.txt installplan.txt; - then - echo "cabal build-cache HIT"; - rm -rfv .ghc; - cp -a $HOME/.cabsnap/ghc $HOME/.ghc; - cp -a $HOME/.cabsnap/lib $HOME/.cabsnap/share $HOME/.cabsnap/bin $HOME/.cabal/; - else - echo "cabal build-cache MISS"; - rm -rf $HOME/.cabsnap; - mkdir -p $HOME/.ghc $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin; - cabal install --only-dependencies --enable-tests; - fi - -# snapshot package-db on cache miss - - if [ ! -d $HOME/.cabsnap ]; - then - echo "snapshotting package-db to build-cache"; - mkdir $HOME/.cabsnap; - cp -a $HOME/.ghc $HOME/.cabsnap/ghc; - cp -a $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin installplan.txt $HOME/.cabsnap/; - fi - -# Here starts the actual work to be performed for the package under test; -# any command which exits with a non-zero exit code causes the build to fail. -script: - - if [ -f configure.ac ]; then autoreconf -i; fi - - cabal configure --enable-tests -v2 # -v2 provides useful information for debugging - - cabal build # this builds all libraries and executables (including tests) - - cabal test - - cabal check - - cabal sdist # tests that a source-distribution can be generated - -# Check that the resulting source distribution can be built & installed. -# If there are no other `.tar.gz` files in `dist`, this can be even simpler: -# `cabal install --force-reinstalls dist/*-*.tar.gz` - - SRC_TGZ=$(cabal info . | awk '{print $2;exit}').tar.gz && - (cd dist && cabal install --force-reinstalls "$SRC_TGZ") - -# EOF +language: nix +script: nix-build release.nix diff --git a/default.nix b/default.nix index 3578902a..8cee778c 100644 --- a/default.nix +++ b/default.nix @@ -1,5 +1,5 @@ -{ mkDerivation, attoparsec, base, containers, deepseq, pretty-show -, QuickCheck, stdenv, system-filepath, text, vector +{ mkDerivation, attoparsec, base, containers, criterion, deepseq +, pretty-show, QuickCheck, stdenv, system-filepath, text, vector }: mkDerivation { pname = "nix-derivation"; @@ -14,6 +14,7 @@ mkDerivation { testHaskellDepends = [ attoparsec base QuickCheck system-filepath text vector ]; + benchmarkHaskellDepends = [ attoparsec base criterion text ]; description = "Parse and render *.drv files"; license = stdenv.lib.licenses.bsd3; } diff --git a/nix-derivation.cabal b/nix-derivation.cabal index 7ab8224d..ff575d5d 100644 --- a/nix-derivation.cabal +++ b/nix-derivation.cabal @@ -30,7 +30,7 @@ Library Build-Depends: base >= 4.6.0.0 && < 5 , attoparsec >= 0.12.0.0 && < 0.14, - containers < 0.6 , + containers < 0.7 , deepseq >= 1.4.0.0 && < 1.5 , system-filepath >= 0.3.1 && < 0.5 , text >= 0.8.0.0 && < 1.3 , @@ -49,7 +49,7 @@ Executable pretty-derivation Build-Depends: base >= 4.6.0.0 && < 5 , attoparsec >= 0.12.0.0 && < 0.14, - pretty-show >= 1.6.11 && < 1.7 , + pretty-show >= 1.6.11 && < 1.10, text >= 0.8.0.0 && < 1.3 , nix-derivation GHC-Options: -Wall @@ -77,7 +77,7 @@ Test-Suite property base >= 4.6.0.0 && < 5 , attoparsec >= 0.12.0.0 && < 0.14, nix-derivation , - QuickCheck < 2.10, + QuickCheck < 2.13, system-filepath >= 0.3.1 && < 0.5 , text >= 0.8.0.0 && < 1.3 , vector < 0.13 @@ -92,6 +92,6 @@ Benchmark benchmark Build-Depends: base >= 4.6.0.0 && < 5 , attoparsec >= 0.12.0.0 && < 0.14, - criterion >= 1.1.4.0 && < 1.3 , + criterion >= 1.1.4.0 && < 1.6 , nix-derivation , text >= 0.8.0.0 && < 1.3 From 69cfd0e37f2628645785f74e63732fa3abeced57 Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Sun, 4 Nov 2018 09:02:05 -0800 Subject: [PATCH 15/58] =?UTF-8?q?Version=201.0.1=20=E2=86=92=201.0.2=20(#3?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- default.nix | 2 +- nix-derivation.cabal | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index dfdab0dc..6447d7de 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# `nix-derivation 1.0.1` +# `nix-derivation 1.0.2` Use this package to parse and render Nix derivations such as those stored in `/nix/store/*.drv` files. For example, if you had the following derivation diff --git a/default.nix b/default.nix index 8cee778c..b72c91ad 100644 --- a/default.nix +++ b/default.nix @@ -3,7 +3,7 @@ }: mkDerivation { pname = "nix-derivation"; - version = "1.0.1"; + version = "1.0.2"; src = ./.; isLibrary = true; isExecutable = true; diff --git a/nix-derivation.cabal b/nix-derivation.cabal index ff575d5d..9cf3a81c 100644 --- a/nix-derivation.cabal +++ b/nix-derivation.cabal @@ -1,5 +1,5 @@ Name: nix-derivation -Version: 1.0.1 +Version: 1.0.2 Cabal-Version: >=1.10 Build-Type: Simple Tested-With: GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2 From b108aa5218b59b84281ac5b36d1f018850c81ab1 Mon Sep 17 00:00:00 2001 From: Richard Marko Date: Mon, 27 Apr 2020 23:09:14 +0200 Subject: [PATCH 16/58] Higher order Derivation, filepath (#4) --- .travis.yml | 2 +- default.nix | 53 ++++++++++++++++++++++------------- nix-derivation.cabal | 16 +++++------ release.nix | 33 ---------------------- src/Nix/Derivation/Builder.hs | 30 ++++++++++---------- src/Nix/Derivation/Parser.hs | 32 ++++++++++++--------- src/Nix/Derivation/Types.hs | 34 +++++++++++----------- tests/Property.hs | 14 ++++----- 8 files changed, 98 insertions(+), 116 deletions(-) delete mode 100644 release.nix diff --git a/.travis.yml b/.travis.yml index c60be3f5..d3413d11 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,2 +1,2 @@ language: nix -script: nix-build release.nix +script: nix-build diff --git a/default.nix b/default.nix index b72c91ad..a6444e4d 100644 --- a/default.nix +++ b/default.nix @@ -1,20 +1,33 @@ -{ mkDerivation, attoparsec, base, containers, criterion, deepseq -, pretty-show, QuickCheck, stdenv, system-filepath, text, vector -}: -mkDerivation { - pname = "nix-derivation"; - version = "1.0.2"; - src = ./.; - isLibrary = true; - isExecutable = true; - libraryHaskellDepends = [ - attoparsec base containers deepseq system-filepath text vector - ]; - executableHaskellDepends = [ attoparsec base pretty-show text ]; - testHaskellDepends = [ - attoparsec base QuickCheck system-filepath text vector - ]; - benchmarkHaskellDepends = [ attoparsec base criterion text ]; - description = "Parse and render *.drv files"; - license = stdenv.lib.licenses.bsd3; -} +# You can build this repository using Nix by running: +# +# $ nix-build -A nix-derivation release.nix +# +# You can also open up this repository inside of a Nix shell by running: +# +# $ nix-shell -A nix-derivation.env release.nix +# +# ... and then Nix will supply the correct Haskell development environment for +# you +let + config = { + packageOverrides = pkgs: { + haskellPackages = pkgs.haskellPackages.override { + overrides = haskellPackagesNew: haskellPackagesOld: { + nix-derivation = + pkgs.haskell.lib.overrideCabal + (haskellPackagesNew.callCabal2nix "nix-derivation" ./. { }) + (_: { +# withBenchmarkDepends = true; + } + ); + }; + }; + }; + }; + + pkgs = + import { inherit config; }; + +in + { nix-derivation = pkgs.haskellPackages.nix-derivation; + } diff --git a/nix-derivation.cabal b/nix-derivation.cabal index 9cf3a81c..84373173 100644 --- a/nix-derivation.cabal +++ b/nix-derivation.cabal @@ -1,8 +1,8 @@ Name: nix-derivation -Version: 1.0.2 +Version: 1.1.0 Cabal-Version: >=1.10 Build-Type: Simple -Tested-With: GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2 +Tested-With: GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2, GHC == 8.8.3 License: BSD3 License-File: LICENSE Copyright: 2017 Gabriel Gonzalez @@ -32,9 +32,9 @@ Library attoparsec >= 0.12.0.0 && < 0.14, containers < 0.7 , deepseq >= 1.4.0.0 && < 1.5 , - system-filepath >= 0.3.1 && < 0.5 , text >= 0.8.0.0 && < 1.3 , - vector < 0.13 + vector < 0.13, + filepath < 1.5 Exposed-Modules: Nix.Derivation Other-Modules: @@ -49,7 +49,7 @@ Executable pretty-derivation Build-Depends: base >= 4.6.0.0 && < 5 , attoparsec >= 0.12.0.0 && < 0.14, - pretty-show >= 1.6.11 && < 1.10, + pretty-show >= 1.6.11 && < 1.11, text >= 0.8.0.0 && < 1.3 , nix-derivation GHC-Options: -Wall @@ -77,10 +77,10 @@ Test-Suite property base >= 4.6.0.0 && < 5 , attoparsec >= 0.12.0.0 && < 0.14, nix-derivation , - QuickCheck < 2.13, - system-filepath >= 0.3.1 && < 0.5 , + QuickCheck < 2.14, text >= 0.8.0.0 && < 1.3 , - vector < 0.13 + vector < 0.13, + filepath < 1.5 Benchmark benchmark Default-Language: Haskell2010 diff --git a/release.nix b/release.nix deleted file mode 100644 index cfec2822..00000000 --- a/release.nix +++ /dev/null @@ -1,33 +0,0 @@ -# You can build this repository using Nix by running: -# -# $ nix-build -A nix-derivation release.nix -# -# You can also open up this repository inside of a Nix shell by running: -# -# $ nix-shell -A nix-derivation.env release.nix -# -# ... and then Nix will supply the correct Haskell development environment for -# you -let - config = { - packageOverrides = pkgs: { - haskellPackages = pkgs.haskellPackages.override { - overrides = haskellPackagesNew: haskellPackagesOld: { - nix-derivation = - pkgs.haskell.lib.overrideCabal - (haskellPackagesNew.callPackage ./default.nix { }) - (_: { -# withBenchmarkDepends = true; - } - ); - }; - }; - }; - }; - - pkgs = - import { inherit config; }; - -in - { nix-derivation = pkgs.haskellPackages.nix-derivation; - } diff --git a/src/Nix/Derivation/Builder.hs b/src/Nix/Derivation/Builder.hs index 17947d6c..b906a40e 100644 --- a/src/Nix/Derivation/Builder.hs +++ b/src/Nix/Derivation/Builder.hs @@ -6,29 +6,33 @@ module Nix.Derivation.Builder ( -- * Builder buildDerivation + , buildDerivationWith ) where -import Data.Foldable (foldMap) import Data.Map (Map) -import Data.Monoid ((<>)) import Data.Set (Set) import Data.Text (Text) import Data.Text.Lazy.Builder (Builder) import Data.Vector (Vector) -import Filesystem.Path.CurrentOS (FilePath) import Nix.Derivation.Types (Derivation(..), DerivationOutput(..)) -import Prelude hiding (FilePath) import qualified Data.Map import qualified Data.Set import qualified Data.Text import qualified Data.Text.Lazy.Builder import qualified Data.Vector -import qualified Filesystem.Path.CurrentOS -- | Render a derivation as a `Builder` -buildDerivation :: Derivation -> Builder -buildDerivation (Derivation {..}) = +buildDerivation :: Derivation FilePath Text -> Builder +buildDerivation = buildDerivationWith filepath' string' + +-- | Render a derivation as a `Builder` using custom +-- renderer for filepath and string +buildDerivationWith :: (fp -> Builder) + -> (txt -> Builder) + -> Derivation fp txt + -> Builder +buildDerivationWith filepath string (Derivation {..}) = "Derive(" <> mapOf keyValue0 outputs <> "," @@ -89,12 +93,8 @@ setOf element xs = listOf element (Data.Set.toList xs) vectorOf :: (a -> Builder) -> Vector a -> Builder vectorOf element xs = listOf element (Data.Vector.toList xs) -string :: Text -> Builder -string = Data.Text.Lazy.Builder.fromText . Data.Text.pack . show +string' :: Text -> Builder +string' = Data.Text.Lazy.Builder.fromText . Data.Text.pack . show -filepath :: FilePath -> Builder -filepath p = string text - where - text = case Filesystem.Path.CurrentOS.toText p of - Left t -> t - Right t -> t +filepath' :: FilePath -> Builder +filepath' p = string' $ Data.Text.pack p diff --git a/src/Nix/Derivation/Parser.hs b/src/Nix/Derivation/Parser.hs index 18139b97..181ef264 100644 --- a/src/Nix/Derivation/Parser.hs +++ b/src/Nix/Derivation/Parser.hs @@ -8,17 +8,15 @@ module Nix.Derivation.Parser ( -- * Parser parseDerivation + , parseDerivationWith ) where import Data.Attoparsec.Text.Lazy (Parser) import Data.Map (Map) -import Data.Monoid ((<>)) import Data.Set (Set) import Data.Text (Text) import Data.Vector (Vector) import Nix.Derivation.Types (Derivation(..), DerivationOutput(..)) -import Prelude hiding (FilePath) -import Filesystem.Path.CurrentOS (FilePath) import qualified Data.Attoparsec.Text.Lazy import qualified Data.Map @@ -26,7 +24,7 @@ import qualified Data.Set import qualified Data.Text import qualified Data.Text.Lazy import qualified Data.Vector -import qualified Filesystem.Path.CurrentOS +import qualified System.FilePath listOf :: Parser a -> Parser [a] listOf element = do @@ -36,8 +34,13 @@ listOf element = do return es -- | Parse a derivation -parseDerivation :: Parser Derivation -parseDerivation = do +parseDerivation :: Parser (Derivation FilePath Text) +parseDerivation = parseDerivationWith filepathParser textParser + +-- | Parse a derivation using custom +-- parsers for filepaths and text fields +parseDerivationWith :: (Ord fp, Ord txt) => Parser fp -> Parser txt -> Parser (Derivation fp txt) +parseDerivationWith filepath string = do "Derive(" let keyValue0 = do @@ -95,8 +98,8 @@ parseDerivation = do return (Derivation {..}) -string :: Parser Text -string = do +textParser :: Parser Text +textParser = do "\"" let predicate c = not (c == '"' || c == '\\') let loop = do @@ -117,12 +120,13 @@ string = do text <- loop return (Data.Text.Lazy.toStrict text) -filepath :: Parser FilePath -filepath = do - text <- string - case Data.Text.uncons text of - Just ('/', _) -> do - return (Filesystem.Path.CurrentOS.fromText text) +filepathParser :: Parser FilePath +filepathParser = do + text <- textParser + let str = Data.Text.unpack text + case (Data.Text.uncons text, System.FilePath.isValid str) of + (Just ('/', _), True) -> do + return str _ -> do fail ("bad path ‘" <> Data.Text.unpack text <> "’ in derivation") diff --git a/src/Nix/Derivation/Types.hs b/src/Nix/Derivation/Types.hs index 31d853e1..caadc420 100644 --- a/src/Nix/Derivation/Types.hs +++ b/src/Nix/Derivation/Types.hs @@ -1,4 +1,7 @@ {-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DeriveFunctor #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE KindSignatures #-} -- | Shared types @@ -11,42 +14,39 @@ module Nix.Derivation.Types import Control.DeepSeq (NFData) import Data.Map (Map) import Data.Set (Set) -import Data.Text (Text) import Data.Vector (Vector) -import Filesystem.Path.CurrentOS (FilePath) import GHC.Generics (Generic) -import Prelude hiding (FilePath) -- | A Nix derivation -data Derivation = Derivation - { outputs :: Map Text DerivationOutput +data Derivation fp txt = Derivation + { outputs :: Map txt (DerivationOutput fp txt) -- ^ Outputs produced by this derivation where keys are output names - , inputDrvs :: Map FilePath (Set Text) + , inputDrvs :: Map fp (Set txt) -- ^ Inputs that are derivations where keys specify derivation paths and -- values specify which output names are used by this derivation - , inputSrcs :: Set FilePath + , inputSrcs :: Set fp -- ^ Inputs that are sources - , platform :: Text + , platform :: txt -- ^ Platform required for this derivation - , builder :: Text + , builder :: txt -- ^ Code to build the derivation, which can be a path or a builtin function - , args :: Vector Text + , args :: Vector txt -- ^ Arguments passed to the executable used to build to derivation - , env :: Map Text Text + , env :: Map txt txt -- ^ Environment variables provided to the executable used to build the -- derivation } deriving (Eq, Generic, Ord, Show) -instance NFData Derivation +instance (NFData a, NFData b) => NFData (Derivation a b) -- | An output of a Nix derivation -data DerivationOutput = DerivationOutput - { path :: FilePath +data DerivationOutput fp txt = DerivationOutput + { path :: fp -- ^ Path where the output will be saved - , hashAlgo :: Text + , hashAlgo :: txt -- ^ Hash used for expected hash computation - , hash :: Text + , hash :: txt -- ^ Expected hash } deriving (Eq, Generic, Ord, Show) -instance NFData DerivationOutput +instance (NFData a, NFData b) => NFData (DerivationOutput a b) diff --git a/tests/Property.hs b/tests/Property.hs index 33f26cc7..287f501c 100644 --- a/tests/Property.hs +++ b/tests/Property.hs @@ -1,4 +1,6 @@ {-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE TypeSynonymInstances #-} +{-# LANGUAGE FlexibleInstances #-} {-# OPTIONS_GHC -fno-warn-orphans #-} @@ -6,7 +8,7 @@ module Main where import Data.Text (Text) import Data.Vector (Vector) -import Filesystem.Path.CurrentOS (FilePath) +import System.FilePath import Nix.Derivation (Derivation(..), DerivationOutput(..)) import Prelude hiding (FilePath, either) import Test.QuickCheck (Arbitrary(..)) @@ -15,27 +17,23 @@ import qualified Data.Attoparsec.Text.Lazy import qualified Data.Text import qualified Data.Text.Lazy.Builder import qualified Data.Vector -import qualified Filesystem.Path.CurrentOS import qualified Nix.Derivation import qualified Test.QuickCheck instance Arbitrary Text where arbitrary = fmap Data.Text.pack arbitrary -instance Arbitrary FilePath where - arbitrary = fmap Filesystem.Path.CurrentOS.decodeString arbitrary - instance Arbitrary a => Arbitrary (Vector a) where arbitrary = fmap Data.Vector.fromList arbitrary -instance Arbitrary DerivationOutput where +instance Arbitrary (DerivationOutput FilePath Text) where arbitrary = do path <- arbitrary hashAlgo <- arbitrary hash <- arbitrary return (DerivationOutput {..}) -instance Arbitrary Derivation where +instance Arbitrary (Derivation FilePath Text) where arbitrary = do outputs <- arbitrary inputDrvs <- arbitrary @@ -46,7 +44,7 @@ instance Arbitrary Derivation where env <- arbitrary return (Derivation {..}) -property :: Derivation -> Bool +property :: Derivation FilePath Text -> Bool property derivation0 = either == Right derivation0 where builder = Nix.Derivation.buildDerivation derivation0 From db6d4616420fdd2450211d6d7016742c46c7e8e9 Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Mon, 27 Apr 2020 16:00:56 -0700 Subject: [PATCH 17/58] Fix `shell.nix` (#6) --- shell.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell.nix b/shell.nix index 29b0da9a..fc78129c 100644 --- a/shell.nix +++ b/shell.nix @@ -1 +1 @@ -(import ./release.nix).nix-derivation.env +(import ./default.nix).nix-derivation.env From 7e335a4fc5c2c125befe45a5358de025f1bc12c6 Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Mon, 27 Apr 2020 16:05:43 -0700 Subject: [PATCH 18/58] =?UTF-8?q?Version=201.0.2=20=E2=86=92=201.1.0=20(#5?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6447d7de..3c5dad52 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# `nix-derivation 1.0.2` +# `nix-derivation` Use this package to parse and render Nix derivations such as those stored in `/nix/store/*.drv` files. For example, if you had the following derivation From 3f95b84acc5e98865d98817b8b0aa73b7750c5f9 Mon Sep 17 00:00:00 2001 From: Richard Marko Date: Thu, 30 Apr 2020 05:52:52 +0200 Subject: [PATCH 19/58] Delete references to release.nix from default.nix (#7) --- default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/default.nix b/default.nix index a6444e4d..41e9bf2b 100644 --- a/default.nix +++ b/default.nix @@ -1,10 +1,10 @@ # You can build this repository using Nix by running: # -# $ nix-build -A nix-derivation release.nix +# $ nix-build # # You can also open up this repository inside of a Nix shell by running: # -# $ nix-shell -A nix-derivation.env release.nix +# $ nix-shell # # ... and then Nix will supply the correct Haskell development environment for # you From 69fb26ae75e1980409ef19d76b7cd9dcf06d0c98 Mon Sep 17 00:00:00 2001 From: Richard Marko Date: Tue, 19 May 2020 16:56:31 +0200 Subject: [PATCH 20/58] Add missing re-exports (#8) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Expose parseDerivationWith, buildDerivationWith and textParser * Version 1.1.0 → 1.1.1 (#8) --- nix-derivation.cabal | 2 +- src/Nix/Derivation.hs | 3 +++ src/Nix/Derivation/Parser.hs | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/nix-derivation.cabal b/nix-derivation.cabal index 84373173..ff68f115 100644 --- a/nix-derivation.cabal +++ b/nix-derivation.cabal @@ -1,5 +1,5 @@ Name: nix-derivation -Version: 1.1.0 +Version: 1.1.1 Cabal-Version: >=1.10 Build-Type: Simple Tested-With: GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2, GHC == 8.8.3 diff --git a/src/Nix/Derivation.hs b/src/Nix/Derivation.hs index 39c28e92..4d8e00d4 100644 --- a/src/Nix/Derivation.hs +++ b/src/Nix/Derivation.hs @@ -83,9 +83,12 @@ module Nix.Derivation -- * Parse derivations , parseDerivation + , parseDerivationWith + , textParser -- * Render derivations , buildDerivation + , buildDerivationWith ) where import Nix.Derivation.Builder diff --git a/src/Nix/Derivation/Parser.hs b/src/Nix/Derivation/Parser.hs index 181ef264..9c60e1fa 100644 --- a/src/Nix/Derivation/Parser.hs +++ b/src/Nix/Derivation/Parser.hs @@ -9,6 +9,7 @@ module Nix.Derivation.Parser ( -- * Parser parseDerivation , parseDerivationWith + , textParser ) where import Data.Attoparsec.Text.Lazy (Parser) From 4fb51cff1047dbbfebcceeb12d454aa6c96f09b0 Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Tue, 19 May 2020 08:08:54 -0700 Subject: [PATCH 21/58] =?UTF-8?q?Version=201.1.0=20=E2=86=92=201.1.1=20(#9?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From 73e2ee56bf0e388693cca1429c82e1c3984498ac Mon Sep 17 00:00:00 2001 From: Dennis Gosnell Date: Sat, 2 Jan 2021 11:51:27 +0900 Subject: [PATCH 22/58] Bump QuickCheck dep to < 2.15 (#10) --- nix-derivation.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix-derivation.cabal b/nix-derivation.cabal index ff68f115..d1b79a03 100644 --- a/nix-derivation.cabal +++ b/nix-derivation.cabal @@ -77,7 +77,7 @@ Test-Suite property base >= 4.6.0.0 && < 5 , attoparsec >= 0.12.0.0 && < 0.14, nix-derivation , - QuickCheck < 2.14, + QuickCheck < 2.15, text >= 0.8.0.0 && < 1.3 , vector < 0.13, filepath < 1.5 From bd19633a9d35d307724e55666d33506ee95a4d59 Mon Sep 17 00:00:00 2001 From: Richard Marko Date: Sat, 20 Mar 2021 17:42:58 +0100 Subject: [PATCH 23/58] GitHub Actions CI (#12) Similar to https://github.com/Gabriel439/nix-diff/pull/37 --- .github/workflows/ci.yaml | 38 ++++++++++++++++++++++++++++++++++++++ .travis.yml | 2 -- ci.dhall | 16 ++++++++++++++++ ci.sh | 11 +++++++++++ 4 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/ci.yaml delete mode 100644 .travis.yml create mode 100644 ci.dhall create mode 100755 ci.sh diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 00000000..f2539a86 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,38 @@ +jobs: + build: + runs-on: ubuntu-18.04 + steps: + - uses: "actions/checkout@v1" + - id: setup-haskell-cabal + uses: "haskell/actions/setup@v1.2" + with: + cabal-version: "${{ matrix.cabal }}" + enable-stack: false + ghc-version: "${{ matrix.ghc }}" + - uses: "actions/cache@v1" + with: + key: "${{ runner.os }}-${{ matrix.ghc }}-cabal" + path: "${{ steps.setup-haskell-cabal.outputs.cabal-store }}" + - name: Install dependencies + run: | + cabal update + cabal build --enable-tests --enable-benchmarks --only-dependencies + - name: build + run: cabal build --enable-tests --enable-benchmarks + - name: test + run: cabal test --enable-tests + - name: haddock + run: cabal haddock + strategy: + matrix: + cabal: + - '3.2' + ghc: + - '8.10.4' + - '8.8.4' + - '8.6.5' + - '9.0.1' +name: Haskell CI +on: + - push + - pull_request diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index d3413d11..00000000 --- a/.travis.yml +++ /dev/null @@ -1,2 +0,0 @@ -language: nix -script: nix-build diff --git a/ci.dhall b/ci.dhall new file mode 100644 index 00000000..b2b567cb --- /dev/null +++ b/ci.dhall @@ -0,0 +1,16 @@ +let haskellCi = + https://raw.githubusercontent.com/sorki/github-actions-dhall/pending/haskell-ci.dhall + +in haskellCi.generalCi + haskellCi.matrixSteps + ( Some + { ghc = + [ haskellCi.GHC.GHC8104 + , haskellCi.GHC.GHC884 + , haskellCi.GHC.GHC865 + , haskellCi.GHC.GHC901 + ] + , cabal = [ haskellCi.Cabal.Cabal32 ] + } + ) + : haskellCi.CI.Type diff --git a/ci.sh b/ci.sh new file mode 100755 index 00000000..766811da --- /dev/null +++ b/ci.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +# Script by @fisx + +set -eo pipefail +cd "$( dirname "${BASH_SOURCE[0]}" )" + +echo "regenerating .github/workflows/ci.yaml..." + +# based on https://github.com/vmchale/github-actions-dhall +which dhall-to-yaml || cabal install dhall-yaml +dhall-to-yaml --file ci.dhall > .github/workflows/ci.yaml From 33acefc033869972aff9f4e3b5eb13a73fed05ae Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Sun, 21 Mar 2021 08:53:04 -0700 Subject: [PATCH 24/58] Improve performance of `textParser` (#13) Fixes #11 --- src/Nix/Derivation/Parser.hs | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/Nix/Derivation/Parser.hs b/src/Nix/Derivation/Parser.hs index 9c60e1fa..3aac359f 100644 --- a/src/Nix/Derivation/Parser.hs +++ b/src/Nix/Derivation/Parser.hs @@ -19,11 +19,11 @@ import Data.Text (Text) import Data.Vector (Vector) import Nix.Derivation.Types (Derivation(..), DerivationOutput(..)) +import qualified Data.Attoparsec.Text import qualified Data.Attoparsec.Text.Lazy import qualified Data.Map import qualified Data.Set import qualified Data.Text -import qualified Data.Text.Lazy import qualified Data.Vector import qualified System.FilePath @@ -102,24 +102,34 @@ parseDerivationWith filepath string = do textParser :: Parser Text textParser = do "\"" + let predicate c = not (c == '"' || c == '\\') + let loop = do - text0 <- Data.Attoparsec.Text.Lazy.takeWhile predicate - char0 <- Data.Attoparsec.Text.Lazy.anyChar - text2 <- case char0 of - '"' -> return "" + text0 <- Data.Attoparsec.Text.takeWhile predicate + + char0 <- Data.Attoparsec.Text.anyChar + + case char0 of + '"' -> do + return [ text0 ] + _ -> do - char1 <- Data.Attoparsec.Text.Lazy.anyChar + char1 <- Data.Attoparsec.Text.anyChar + char2 <- case char1 of 'n' -> return '\n' 'r' -> return '\r' 't' -> return '\t' _ -> return char1 - text1 <- loop - return (Data.Text.Lazy.cons char2 text1) - return (Data.Text.Lazy.fromStrict text0 <> text2) - text <- loop - return (Data.Text.Lazy.toStrict text) + + textChunks <- loop + + return (text0 : Data.Text.singleton char2 : textChunks) + + textChunks <- loop + + return (Data.Text.concat textChunks) filepathParser :: Parser FilePath filepathParser = do From 249bfc53c7aa77beb0c9baef21ed1a1d310583dd Mon Sep 17 00:00:00 2001 From: Daniel Wilson-Thomas Date: Mon, 22 Mar 2021 11:29:49 -0400 Subject: [PATCH 25/58] Add installation instructions to readme (#14) Only including instructions for Nix, since if you're using this project I think it's safe to assume you'll have Nix available. --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 3c5dad52..75629155 100644 --- a/README.md +++ b/README.md @@ -173,6 +173,14 @@ Derivation } ``` +## Installation + +With Nix: + +``` +$ nix-env -iA nixpkgs.haskellPackages.nix-derivation +``` + ## Development status [![Build Status](https://travis-ci.org/Gabriel439/Haskell-Nix-Derivation-Library.png)](https://travis-ci.org/Gabriel439/Haskell-Nix-Derivation-Library) From 97c1fae039c07be327bcdf2e638fda946cedafb5 Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Thu, 25 Mar 2021 23:58:03 -0700 Subject: [PATCH 26/58] Build against `attoparsec-0.14` (#15) Related to https://github.com/commercialhaskell/stackage/issues/5959 --- nix-derivation.cabal | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/nix-derivation.cabal b/nix-derivation.cabal index d1b79a03..c14034fc 100644 --- a/nix-derivation.cabal +++ b/nix-derivation.cabal @@ -29,7 +29,7 @@ Library Hs-Source-Dirs: src Build-Depends: base >= 4.6.0.0 && < 5 , - attoparsec >= 0.12.0.0 && < 0.14, + attoparsec >= 0.12.0.0 && < 0.15, containers < 0.7 , deepseq >= 1.4.0.0 && < 1.5 , text >= 0.8.0.0 && < 1.3 , @@ -48,7 +48,7 @@ Executable pretty-derivation Hs-Source-Dirs: pretty-derivation Build-Depends: base >= 4.6.0.0 && < 5 , - attoparsec >= 0.12.0.0 && < 0.14, + attoparsec >= 0.12.0.0 && < 0.15, pretty-show >= 1.6.11 && < 1.11, text >= 0.8.0.0 && < 1.3 , nix-derivation @@ -63,7 +63,7 @@ Test-Suite example GHC-Options: -Wall Build-Depends: base >= 4.6.0.0 && < 5 , - attoparsec >= 0.12.0.0 && < 0.14, + attoparsec >= 0.12.0.0 && < 0.15, nix-derivation , text >= 0.8.0.0 && < 1.3 @@ -75,7 +75,7 @@ Test-Suite property GHC-Options: -Wall Build-Depends: base >= 4.6.0.0 && < 5 , - attoparsec >= 0.12.0.0 && < 0.14, + attoparsec >= 0.12.0.0 && < 0.15, nix-derivation , QuickCheck < 2.15, text >= 0.8.0.0 && < 1.3 , @@ -91,7 +91,7 @@ Benchmark benchmark Build-Depends: base >= 4.6.0.0 && < 5 , - attoparsec >= 0.12.0.0 && < 0.14, + attoparsec >= 0.12.0.0 && < 0.15, criterion >= 1.1.4.0 && < 1.6 , nix-derivation , text >= 0.8.0.0 && < 1.3 From 196a51f2ab75f1179b06dd90501f240b80098329 Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Fri, 26 Mar 2021 00:08:27 -0700 Subject: [PATCH 27/58] =?UTF-8?q?Version=201.1.1=20=E2=86=92=201.1.2=20(#1?= =?UTF-8?q?6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nix-derivation.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix-derivation.cabal b/nix-derivation.cabal index c14034fc..9f2278a7 100644 --- a/nix-derivation.cabal +++ b/nix-derivation.cabal @@ -1,5 +1,5 @@ Name: nix-derivation -Version: 1.1.1 +Version: 1.1.2 Cabal-Version: >=1.10 Build-Type: Simple Tested-With: GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2, GHC == 8.8.3 From 97ed33b258f4ec72df7cbbfe4d80d0db285c146c Mon Sep 17 00:00:00 2001 From: Simon Jakobi Date: Thu, 30 Dec 2021 23:57:22 +0100 Subject: [PATCH 28/58] Allow text-2.0 (#17) https://hackage.haskell.org/package/text-2.0/changelog --- nix-derivation.cabal | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/nix-derivation.cabal b/nix-derivation.cabal index 9f2278a7..db3bfe1a 100644 --- a/nix-derivation.cabal +++ b/nix-derivation.cabal @@ -32,7 +32,7 @@ Library attoparsec >= 0.12.0.0 && < 0.15, containers < 0.7 , deepseq >= 1.4.0.0 && < 1.5 , - text >= 0.8.0.0 && < 1.3 , + text >= 0.8.0.0 && < 2.1 , vector < 0.13, filepath < 1.5 Exposed-Modules: @@ -50,7 +50,7 @@ Executable pretty-derivation base >= 4.6.0.0 && < 5 , attoparsec >= 0.12.0.0 && < 0.15, pretty-show >= 1.6.11 && < 1.11, - text >= 0.8.0.0 && < 1.3 , + text , nix-derivation GHC-Options: -Wall Main-Is: Main.hs @@ -65,7 +65,7 @@ Test-Suite example base >= 4.6.0.0 && < 5 , attoparsec >= 0.12.0.0 && < 0.15, nix-derivation , - text >= 0.8.0.0 && < 1.3 + text Test-Suite property Default-Language: Haskell2010 @@ -78,7 +78,7 @@ Test-Suite property attoparsec >= 0.12.0.0 && < 0.15, nix-derivation , QuickCheck < 2.15, - text >= 0.8.0.0 && < 1.3 , + text , vector < 0.13, filepath < 1.5 @@ -94,4 +94,4 @@ Benchmark benchmark attoparsec >= 0.12.0.0 && < 0.15, criterion >= 1.1.4.0 && < 1.6 , nix-derivation , - text >= 0.8.0.0 && < 1.3 + text From 216fc995d5299d55b83a7661dd479fa7299d0211 Mon Sep 17 00:00:00 2001 From: Richard Marko Date: Fri, 22 Apr 2022 18:11:38 +0200 Subject: [PATCH 29/58] ci: Update versions (#19) --- .github/workflows/ci.yaml | 45 +++++++++++++++++++++++---------------- ci.dhall | 6 +++--- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index f2539a86..56beccd2 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1,37 +1,46 @@ jobs: build: - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest steps: - - uses: "actions/checkout@v1" + - uses: "actions/checkout@v3" - id: setup-haskell-cabal - uses: "haskell/actions/setup@v1.2" + uses: "haskell/actions/setup@v2" with: cabal-version: "${{ matrix.cabal }}" enable-stack: false ghc-version: "${{ matrix.ghc }}" - - uses: "actions/cache@v1" + - name: Update Hackage repository + run: cabal update + - name: cabal.project.local.ci + run: | + if [ -e cabal.project.local.ci ]; then + cp cabal.project.local.ci cabal.project.local + fi + - name: freeze + run: cabal freeze + - uses: "actions/cache@v3" with: - key: "${{ runner.os }}-${{ matrix.ghc }}-cabal" - path: "${{ steps.setup-haskell-cabal.outputs.cabal-store }}" + key: "${{ runner.os }}-${{ matrix.ghc }}-cabal-${{ hashFiles('cabal.project.freeze') }}" + path: | + ${{ steps.setup-haskell-cabal.outputs.cabal-store }} + dist-newstyle - name: Install dependencies - run: | - cabal update - cabal build --enable-tests --enable-benchmarks --only-dependencies - - name: build - run: cabal build --enable-tests --enable-benchmarks - - name: test - run: cabal test --enable-tests - - name: haddock - run: cabal haddock + run: cabal build all --enable-tests --enable-benchmarks --only-dependencies + - name: build all + run: cabal build all --enable-tests --enable-benchmarks + - name: test all + run: cabal test all --enable-tests + - name: haddock all + run: cabal haddock all strategy: matrix: cabal: - - '3.2' + - '3.4' ghc: - - '8.10.4' + - '9.0.2' + - '8.10.7' - '8.8.4' - '8.6.5' - - '9.0.1' name: Haskell CI on: - push diff --git a/ci.dhall b/ci.dhall index b2b567cb..ad9e6aa6 100644 --- a/ci.dhall +++ b/ci.dhall @@ -5,12 +5,12 @@ in haskellCi.generalCi haskellCi.matrixSteps ( Some { ghc = - [ haskellCi.GHC.GHC8104 + [ haskellCi.GHC.GHC902 + , haskellCi.GHC.GHC8107 , haskellCi.GHC.GHC884 , haskellCi.GHC.GHC865 - , haskellCi.GHC.GHC901 ] - , cabal = [ haskellCi.Cabal.Cabal32 ] + , cabal = [ haskellCi.Cabal.Cabal34 ] } ) : haskellCi.CI.Type From 4d22dd55370143d4370b39edc7c2ae9066d3ec9a Mon Sep 17 00:00:00 2001 From: Gabriella Gonzalez Date: Sat, 2 Jul 2022 15:34:56 -0700 Subject: [PATCH 30/58] Build against `vector-0.13` (#20) Related to https://github.com/commercialhaskell/stackage/issues/6624 --- .github/workflows/ci.yaml | 7 ------- nix-derivation.cabal | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 56beccd2..7677f8b8 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -11,13 +11,6 @@ jobs: ghc-version: "${{ matrix.ghc }}" - name: Update Hackage repository run: cabal update - - name: cabal.project.local.ci - run: | - if [ -e cabal.project.local.ci ]; then - cp cabal.project.local.ci cabal.project.local - fi - - name: freeze - run: cabal freeze - uses: "actions/cache@v3" with: key: "${{ runner.os }}-${{ matrix.ghc }}-cabal-${{ hashFiles('cabal.project.freeze') }}" diff --git a/nix-derivation.cabal b/nix-derivation.cabal index db3bfe1a..76632046 100644 --- a/nix-derivation.cabal +++ b/nix-derivation.cabal @@ -33,7 +33,7 @@ Library containers < 0.7 , deepseq >= 1.4.0.0 && < 1.5 , text >= 0.8.0.0 && < 2.1 , - vector < 0.13, + vector < 0.14, filepath < 1.5 Exposed-Modules: Nix.Derivation From 7ace1d4a3c6a785e0740a81f4ca74ec6d407b4c1 Mon Sep 17 00:00:00 2001 From: Rickard Nilsson Date: Sat, 23 Jul 2022 20:16:38 +0200 Subject: [PATCH 31/58] Support derivations with content-addressed outputs --- src/Nix/Derivation/Builder.hs | 25 ++++++++++++++++++++++++- src/Nix/Derivation/Parser.hs | 15 +++++++++++++-- src/Nix/Derivation/Types.hs | 26 ++++++++++++++++++-------- tests/Property.hs | 29 +++++++++++++++++++++++------ 4 files changed, 78 insertions(+), 17 deletions(-) diff --git a/src/Nix/Derivation/Builder.hs b/src/Nix/Derivation/Builder.hs index b906a40e..4708b0a5 100644 --- a/src/Nix/Derivation/Builder.hs +++ b/src/Nix/Derivation/Builder.hs @@ -28,7 +28,8 @@ buildDerivation = buildDerivationWith filepath' string' -- | Render a derivation as a `Builder` using custom -- renderer for filepath and string -buildDerivationWith :: (fp -> Builder) +buildDerivationWith :: (Monoid fp, Monoid txt) + => (fp -> Builder) -> (txt -> Builder) -> Derivation fp txt -> Builder @@ -55,11 +56,33 @@ buildDerivationWith filepath string (Derivation {..}) = <> "," <> filepath path <> "," + <> string mempty + <> "," + <> string mempty + <> ")" + + keyValue0 (key, FixedDerivationOutput {..}) = + "(" + <> string key + <> "," + <> filepath path + <> "," <> string hashAlgo <> "," <> string hash <> ")" + keyValue0 (key, ContentAddressedDerivationOutput {..}) = + "(" + <> string key + <> "," + <> filepath mempty + <> "," + <> string hashAlgo + <> "," + <> string mempty + <> ")" + keyValue1 (key, value) = "(" <> filepath key diff --git a/src/Nix/Derivation/Parser.hs b/src/Nix/Derivation/Parser.hs index 3aac359f..14a58a57 100644 --- a/src/Nix/Derivation/Parser.hs +++ b/src/Nix/Derivation/Parser.hs @@ -40,7 +40,7 @@ parseDerivation = parseDerivationWith filepathParser textParser -- | Parse a derivation using custom -- parsers for filepaths and text fields -parseDerivationWith :: (Ord fp, Ord txt) => Parser fp -> Parser txt -> Parser (Derivation fp txt) +parseDerivationWith :: (Ord fp, Monoid fp, Ord txt, Monoid txt) => Parser fp -> Parser txt -> Parser (Derivation fp txt) parseDerivationWith filepath string = do "Derive(" @@ -54,7 +54,8 @@ parseDerivationWith filepath string = do "," hash <- string ")" - return (key, DerivationOutput {..}) + drvOutput <- derivationOutput path hashAlgo hash + return (key, drvOutput) outputs <- mapOf keyValue0 "," @@ -99,6 +100,16 @@ parseDerivationWith filepath string = do return (Derivation {..}) +derivationOutput :: (Ord fp, Monoid fp, Ord txt, Monoid txt) => fp -> txt -> txt -> Parser (DerivationOutput fp txt) +derivationOutput path hashAlgo hash + | path /= mempty && hashAlgo == mempty && hash == mempty = + return DerivationOutput {..} + | path /= mempty && hashAlgo /= mempty && hash /= mempty = + return FixedDerivationOutput {..} + | path == mempty && hashAlgo /= mempty && hash == mempty = + return ContentAddressedDerivationOutput {..} + | otherwise = fail "bad output in derivation" + textParser :: Parser Text textParser = do "\"" diff --git a/src/Nix/Derivation/Types.hs b/src/Nix/Derivation/Types.hs index caadc420..8dc4ffd9 100644 --- a/src/Nix/Derivation/Types.hs +++ b/src/Nix/Derivation/Types.hs @@ -40,13 +40,23 @@ data Derivation fp txt = Derivation instance (NFData a, NFData b) => NFData (Derivation a b) -- | An output of a Nix derivation -data DerivationOutput fp txt = DerivationOutput - { path :: fp - -- ^ Path where the output will be saved - , hashAlgo :: txt - -- ^ Hash used for expected hash computation - , hash :: txt - -- ^ Expected hash - } deriving (Eq, Generic, Ord, Show) +data DerivationOutput fp txt + = DerivationOutput + { path :: fp + -- ^ Path where the output will be saved + } + | FixedDerivationOutput + { path :: fp + -- ^ Path where the output will be saved + , hashAlgo :: txt + -- ^ Hash used for expected hash computation + , hash :: txt + -- ^ Expected hash + } + | ContentAddressedDerivationOutput + { hashAlgo :: txt + -- ^ Hash used for expected hash computation + } + deriving (Eq, Generic, Ord, Show) instance (NFData a, NFData b) => NFData (DerivationOutput a b) diff --git a/tests/Property.hs b/tests/Property.hs index 287f501c..f18491b5 100644 --- a/tests/Property.hs +++ b/tests/Property.hs @@ -11,7 +11,7 @@ import Data.Vector (Vector) import System.FilePath import Nix.Derivation (Derivation(..), DerivationOutput(..)) import Prelude hiding (FilePath, either) -import Test.QuickCheck (Arbitrary(..)) +import Test.QuickCheck (Gen, Arbitrary(..), oneof) import qualified Data.Attoparsec.Text.Lazy import qualified Data.Text @@ -27,11 +27,28 @@ instance Arbitrary a => Arbitrary (Vector a) where arbitrary = fmap Data.Vector.fromList arbitrary instance Arbitrary (DerivationOutput FilePath Text) where - arbitrary = do - path <- arbitrary - hashAlgo <- arbitrary - hash <- arbitrary - return (DerivationOutput {..}) + arbitrary = oneof + [ derivationOutput + , fixedDerivationOutput + , contentAddressedDerivationOutput + ] + +derivationOutput :: Gen (DerivationOutput FilePath Text) +derivationOutput = do + path <- arbitrary + return (DerivationOutput {..}) + +fixedDerivationOutput :: Gen (DerivationOutput FilePath Text) +fixedDerivationOutput = do + path <- arbitrary + hashAlgo <- arbitrary + hash <- arbitrary + return (FixedDerivationOutput {..}) + +contentAddressedDerivationOutput :: Gen (DerivationOutput FilePath Text) +contentAddressedDerivationOutput = do + hashAlgo <- arbitrary + return (ContentAddressedDerivationOutput {..}) instance Arbitrary (Derivation FilePath Text) where arbitrary = do From a581bc19510fc552817bbf2d53f06bf5b306e453 Mon Sep 17 00:00:00 2001 From: Gabriella Gonzalez Date: Sun, 24 Jul 2022 12:44:11 -0700 Subject: [PATCH 32/58] Also update `vector` bound for test suite, too --- nix-derivation.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix-derivation.cabal b/nix-derivation.cabal index 76632046..ac674985 100644 --- a/nix-derivation.cabal +++ b/nix-derivation.cabal @@ -79,7 +79,7 @@ Test-Suite property nix-derivation , QuickCheck < 2.15, text , - vector < 0.13, + vector < 0.14, filepath < 1.5 Benchmark benchmark From f4e9a41d463d98f7276a9588f380efab8beec6b7 Mon Sep 17 00:00:00 2001 From: Gabriella Gonzalez Date: Thu, 1 Sep 2022 21:24:33 -0700 Subject: [PATCH 33/58] Increase upper bound on `criterion` (#21) Related to https://github.com/commercialhaskell/stackage/issues/6677 --- nix-derivation.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix-derivation.cabal b/nix-derivation.cabal index ac674985..98a2077b 100644 --- a/nix-derivation.cabal +++ b/nix-derivation.cabal @@ -92,6 +92,6 @@ Benchmark benchmark Build-Depends: base >= 4.6.0.0 && < 5 , attoparsec >= 0.12.0.0 && < 0.15, - criterion >= 1.1.4.0 && < 1.6 , + criterion >= 1.1.4.0 && < 1.7 , nix-derivation , text From 974d8f1d559c8c91e4fbbf72a7d250bef69c42ca Mon Sep 17 00:00:00 2001 From: Gabriella Gonzalez Date: Sun, 4 Sep 2022 16:28:44 -0700 Subject: [PATCH 34/58] Fix deadname --- LICENSE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index f821e299..28508197 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2017 Gabriel Gonzalez +Copyright (c) 2017 Gabriella Gonzalez All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -8,7 +8,7 @@ are permitted provided that the following conditions are met: * 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 Gabriel Gonzalez nor the names of other contributors + * Neither the name of Gabriella Gonzalez nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission. From e1789cc5ce8f2526fb16903615d4a7a403146846 Mon Sep 17 00:00:00 2001 From: Gabriella Gonzalez Date: Sun, 4 Sep 2022 16:29:21 -0700 Subject: [PATCH 35/58] Fix deadname --- nix-derivation.cabal | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/nix-derivation.cabal b/nix-derivation.cabal index 98a2077b..8ff6375e 100644 --- a/nix-derivation.cabal +++ b/nix-derivation.cabal @@ -5,10 +5,10 @@ Build-Type: Simple Tested-With: GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2, GHC == 8.8.3 License: BSD3 License-File: LICENSE -Copyright: 2017 Gabriel Gonzalez -Author: Gabriel Gonzalez -Maintainer: Gabriel439@gmail.com -Bug-Reports: https://github.com/Gabriel439/Haskell-Nix-Derivation-Library/issues +Copyright: 2017 Gabriella Gonzalez +Author: Gabriella Gonzalez +Maintainer: GenuineGabriella@gmail.com +Bug-Reports: https://github.com/Gabriella439/Haskell-Nix-Derivation-Library/issues Synopsis: Parse and render *.drv files Description: Use this package to parse and render Nix derivation files (i.e. *.drv files) @@ -22,7 +22,7 @@ Extra-Source-Files: tests/example1.drv Source-Repository head Type: git - Location: https://github.com/Gabriel439/Haskell-Nix-Derivation-Library + Location: https://github.com/Gabriella439/Haskell-Nix-Derivation-Library Library Default-Language: Haskell2010 From 188155e71d226b10e8fc96b0b641ed57cb02f316 Mon Sep 17 00:00:00 2001 From: Gabriella Gonzalez Date: Sun, 4 Sep 2022 16:30:00 -0700 Subject: [PATCH 36/58] Fix deadname --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 75629155..559e2ea8 100644 --- a/README.md +++ b/README.md @@ -183,14 +183,14 @@ $ nix-env -iA nixpkgs.haskellPackages.nix-derivation ## Development status -[![Build Status](https://travis-ci.org/Gabriel439/Haskell-Nix-Derivation-Library.png)](https://travis-ci.org/Gabriel439/Haskell-Nix-Derivation-Library) +[![Build Status](https://travis-ci.org/Gabriella439/Haskell-Nix-Derivation-Library.png)](https://travis-ci.org/Gabriella439/Haskell-Nix-Derivation-Library) If you would like to add support for additional functionality, just open an issue or pull request ## License (BSD 3-clause) - Copyright (c) 2017 Gabriel Gonzalez + Copyright (c) 2017 Gabriella Gonzalez All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -200,7 +200,7 @@ issue or pull request * 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 Gabriel Gonzalez nor the names of other contributors + * Neither the name of Gabriella Gonzalez nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission. From ac33b21d135aa60bcc03848d877d44ef77f6205f Mon Sep 17 00:00:00 2001 From: Richard Marko Date: Mon, 20 Nov 2023 01:36:18 +0100 Subject: [PATCH 37/58] Bump bounds, update CI (#22) * ci: Update switch to proper fork, use `defaultCi3`. * Bump upper bounds of containers, deepseq, text Allow - containers 0.7 - deepseq 1.5 - text 2.1 * Drop travis build status badge, add new ones * Add Functor and Bifunctor for DerivationOutput --- .github/workflows/ci.yaml | 77 ++++++++++++++++++++++--------------- README.md | 6 ++- ci.dhall | 16 +------- ci.sh | 5 +-- nix-derivation.cabal | 6 +-- src/Nix/Derivation/Types.hs | 23 +++++++++-- 6 files changed, 75 insertions(+), 58 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7677f8b8..85914730 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1,40 +1,53 @@ +# Code generated by dhall-to-yaml. DO NOT EDIT. jobs: build: - runs-on: ubuntu-latest + name: "GHC ${{ matrix.ghc }}, Cabal ${{ matrix.cabal }}, OS ${{ matrix.os }}" + "runs-on": "${{ matrix.os }}" steps: - - uses: "actions/checkout@v3" - - id: setup-haskell-cabal - uses: "haskell/actions/setup@v2" - with: - cabal-version: "${{ matrix.cabal }}" - enable-stack: false - ghc-version: "${{ matrix.ghc }}" - - name: Update Hackage repository - run: cabal update - - uses: "actions/cache@v3" - with: - key: "${{ runner.os }}-${{ matrix.ghc }}-cabal-${{ hashFiles('cabal.project.freeze') }}" - path: | - ${{ steps.setup-haskell-cabal.outputs.cabal-store }} - dist-newstyle - - name: Install dependencies - run: cabal build all --enable-tests --enable-benchmarks --only-dependencies - - name: build all - run: cabal build all --enable-tests --enable-benchmarks - - name: test all - run: cabal test all --enable-tests - - name: haddock all - run: cabal haddock all + - uses: "actions/checkout@v4" + with: + submodules: recursive + - id: "setup-haskell-cabal" + uses: "haskell-actions/setup@v2" + with: + "cabal-version": "${{ matrix.cabal }}" + "ghc-version": "${{ matrix.ghc }}" + - name: Update Hackage repository + run: cabal update + - name: cabal.project.local.ci + run: | + if [ -e cabal.project.local.ci ]; then + cp cabal.project.local.ci cabal.project.local + fi + - name: freeze + run: "cabal freeze --enable-tests --enable-benchmarks" + - uses: "actions/cache@v3" + with: + key: "${{ matrix.os }}-${{ matrix.ghc }}-${{ matrix.cabal}}-${{ hashFiles('cabal.project.freeze') }}" + path: | + ${{ steps.setup-haskell-cabal.outputs.cabal-store }} + dist-newstyle + - name: Install dependencies + run: "cabal build all --enable-tests --enable-benchmarks --only-dependencies" + - name: build all + run: "cabal build all --enable-tests --enable-benchmarks" + - name: test all + run: "cabal test all --enable-tests" + - name: haddock all + run: cabal haddock all strategy: matrix: cabal: - - '3.4' + - '3.10' ghc: - - '9.0.2' - - '8.10.7' - - '8.8.4' - - '8.6.5' + - '9.6.3' + - '9.4.7' + - '9.2.8' + os: + - "ubuntu-latest" name: Haskell CI -on: - - push - - pull_request +'on': + pull_request: {} + push: {} + schedule: + - cron: "4 20 10 * *" diff --git a/README.md b/README.md index 559e2ea8..3657dd75 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # `nix-derivation` +[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/Gabriella439/Haskell-Nix-Derivation-Library/ci.yaml?branch=main)](https://github.com/Gabriella439/Haskell-Nix-Derivation-Library/actions/workflows/ci.yaml) +[![Hackage version](https://img.shields.io/hackage/v/nix-derivation.svg?color=success)](https://hackage.haskell.org/package/nix-derivation) +[![Dependencies](https://img.shields.io/hackage-deps/v/nix-derivation?label=Dependencies)](https://packdeps.haskellers.com/feed?needle=nix-derivation) + Use this package to parse and render Nix derivations such as those stored in `/nix/store/*.drv` files. For example, if you had the following derivation saved at @@ -183,8 +187,6 @@ $ nix-env -iA nixpkgs.haskellPackages.nix-derivation ## Development status -[![Build Status](https://travis-ci.org/Gabriella439/Haskell-Nix-Derivation-Library.png)](https://travis-ci.org/Gabriella439/Haskell-Nix-Derivation-Library) - If you would like to add support for additional functionality, just open an issue or pull request diff --git a/ci.dhall b/ci.dhall index ad9e6aa6..3c422998 100644 --- a/ci.dhall +++ b/ci.dhall @@ -1,16 +1,4 @@ let haskellCi = - https://raw.githubusercontent.com/sorki/github-actions-dhall/pending/haskell-ci.dhall + https://raw.githubusercontent.com/sorki/github-actions-dhall/main/haskell-ci.dhall -in haskellCi.generalCi - haskellCi.matrixSteps - ( Some - { ghc = - [ haskellCi.GHC.GHC902 - , haskellCi.GHC.GHC8107 - , haskellCi.GHC.GHC884 - , haskellCi.GHC.GHC865 - ] - , cabal = [ haskellCi.Cabal.Cabal34 ] - } - ) - : haskellCi.CI.Type +in haskellCi.defaultCi3 diff --git a/ci.sh b/ci.sh index 766811da..28ee2ee1 100755 --- a/ci.sh +++ b/ci.sh @@ -4,8 +4,7 @@ set -eo pipefail cd "$( dirname "${BASH_SOURCE[0]}" )" -echo "regenerating .github/workflows/ci.yaml..." +echo "regenerating .github/workflows/ci.yaml" -# based on https://github.com/vmchale/github-actions-dhall which dhall-to-yaml || cabal install dhall-yaml -dhall-to-yaml --file ci.dhall > .github/workflows/ci.yaml +dhall-to-yaml-ng --generated-comment --file ci.dhall > .github/workflows/ci.yaml diff --git a/nix-derivation.cabal b/nix-derivation.cabal index 8ff6375e..f856f781 100644 --- a/nix-derivation.cabal +++ b/nix-derivation.cabal @@ -30,9 +30,9 @@ Library Build-Depends: base >= 4.6.0.0 && < 5 , attoparsec >= 0.12.0.0 && < 0.15, - containers < 0.7 , - deepseq >= 1.4.0.0 && < 1.5 , - text >= 0.8.0.0 && < 2.1 , + containers < 0.8 , + deepseq >= 1.4.0.0 && < 1.6 , + text >= 0.8.0.0 && < 2.2 , vector < 0.14, filepath < 1.5 Exposed-Modules: diff --git a/src/Nix/Derivation/Types.hs b/src/Nix/Derivation/Types.hs index caadc420..1772a7fb 100644 --- a/src/Nix/Derivation/Types.hs +++ b/src/Nix/Derivation/Types.hs @@ -1,7 +1,7 @@ -{-# LANGUAGE DeriveGeneric #-} -{-# LANGUAGE DeriveFunctor #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE KindSignatures #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE KindSignatures #-} +{-# LANGUAGE RecordWildCards #-} -- | Shared types @@ -12,6 +12,7 @@ module Nix.Derivation.Types ) where import Control.DeepSeq (NFData) +import Data.Bifunctor (Bifunctor(bimap)) import Data.Map (Map) import Data.Set (Set) import Data.Vector (Vector) @@ -50,3 +51,17 @@ data DerivationOutput fp txt = DerivationOutput } deriving (Eq, Generic, Ord, Show) instance (NFData a, NFData b) => NFData (DerivationOutput a b) + +instance Functor (DerivationOutput fp) where + fmap f DerivationOutput{..} = DerivationOutput + { path = path + , hashAlgo = f hashAlgo + , hash = f hash + } + +instance Bifunctor DerivationOutput where + bimap f g DerivationOutput{..} = DerivationOutput + { path = f path + , hashAlgo = g hashAlgo + , hash = g hash + } From 0165fd49bb7c5bc678264c3231f13ecac28afa2f Mon Sep 17 00:00:00 2001 From: Gabriella Gonzalez Date: Sun, 19 Nov 2023 17:10:53 -0800 Subject: [PATCH 38/58] =?UTF-8?q?Version=201.1.2=20=E2=86=92=201.1.3=20(#2?= =?UTF-8?q?3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nix-derivation.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix-derivation.cabal b/nix-derivation.cabal index f856f781..bd0d4b37 100644 --- a/nix-derivation.cabal +++ b/nix-derivation.cabal @@ -1,5 +1,5 @@ Name: nix-derivation -Version: 1.1.2 +Version: 1.1.3 Cabal-Version: >=1.10 Build-Type: Simple Tested-With: GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2, GHC == 8.8.3 From 1d9742545357a91c558f80de8245960500116561 Mon Sep 17 00:00:00 2001 From: sorki Date: Tue, 5 Dec 2023 08:53:32 +0100 Subject: [PATCH 39/58] Add outputName and drvOutput type parameters to Derivation Allows to use custom types for both sides of the map. The main reason for this is `hnix-store` which now uses `DSum HashAlgo Digest` which combines `hashAlgo` and `hash` fields of the `DerivationOutput` and `OutputName` type for the keys, which is similar to how the newtype is done in the mainline Nix. --- src/Nix/Derivation/Builder.hs | 49 +++++++++++++++++++++++------------ src/Nix/Derivation/Parser.hs | 48 ++++++++++++++++++++++++---------- src/Nix/Derivation/Types.hs | 35 ++++++++++--------------- tests/Property.hs | 6 ++--- 4 files changed, 83 insertions(+), 55 deletions(-) diff --git a/src/Nix/Derivation/Builder.hs b/src/Nix/Derivation/Builder.hs index b906a40e..e8ffef29 100644 --- a/src/Nix/Derivation/Builder.hs +++ b/src/Nix/Derivation/Builder.hs @@ -23,16 +23,24 @@ import qualified Data.Text.Lazy.Builder import qualified Data.Vector -- | Render a derivation as a `Builder` -buildDerivation :: Derivation FilePath Text -> Builder -buildDerivation = buildDerivationWith filepath' string' +buildDerivation :: Derivation FilePath Text Text DerivationOutput -> Builder +buildDerivation = + buildDerivationWith + filepath' + string' + string' + (buildDerivationOutputWith filepath') -- | Render a derivation as a `Builder` using custom --- renderer for filepath and string -buildDerivationWith :: (fp -> Builder) - -> (txt -> Builder) - -> Derivation fp txt - -> Builder -buildDerivationWith filepath string (Derivation {..}) = +-- renderer for filepaths, texts, outputNames and @DerivationOutput@s +buildDerivationWith + :: (fp -> Builder) + -> (txt -> Builder) + -> (outputName -> Builder) + -> (drvOutput fp -> Builder) + -> Derivation fp txt outputName drvOutput + -> Builder +buildDerivationWith filepath string outputName drvOutput (Derivation {..}) = "Derive(" <> mapOf keyValue0 outputs <> "," @@ -49,15 +57,11 @@ buildDerivationWith filepath string (Derivation {..}) = <> mapOf keyValue2 env <> ")" where - keyValue0 (key, DerivationOutput {..}) = + keyValue0 (key, output) = "(" - <> string key - <> "," - <> filepath path - <> "," - <> string hashAlgo + <> outputName key <> "," - <> string hash + <> drvOutput output <> ")" keyValue1 (key, value) = @@ -74,13 +78,26 @@ buildDerivationWith filepath string (Derivation {..}) = <> string value <> ")" +-- | Render a @DerivationOutput@ as a `Builder` using custom +-- renderer for filepaths +buildDerivationOutputWith + :: (fp -> Builder) + -> DerivationOutput fp + -> Builder +buildDerivationOutputWith filepath (DerivationOutput {..}) = + filepath path + <> "," + <> string' hashAlgo + <> "," + <> string' hash + mapOf :: ((k, v) -> Builder) -> Map k v -> Builder mapOf keyValue m = listOf keyValue (Data.Map.toList m) listOf :: (a -> Builder) -> [a] -> Builder listOf _ [] = "[]" listOf element (x:xs) = - "[" + "[" <> element x <> foldMap rest xs <> "]" diff --git a/src/Nix/Derivation/Parser.hs b/src/Nix/Derivation/Parser.hs index 3aac359f..2bbec62c 100644 --- a/src/Nix/Derivation/Parser.hs +++ b/src/Nix/Derivation/Parser.hs @@ -35,26 +35,36 @@ listOf element = do return es -- | Parse a derivation -parseDerivation :: Parser (Derivation FilePath Text) -parseDerivation = parseDerivationWith filepathParser textParser +parseDerivation :: Parser (Derivation FilePath Text Text DerivationOutput) +parseDerivation = + parseDerivationWith + filepathParser + textParser + textParser + (parseDerivationOutputWith filepathParser) -- | Parse a derivation using custom --- parsers for filepaths and text fields -parseDerivationWith :: (Ord fp, Ord txt) => Parser fp -> Parser txt -> Parser (Derivation fp txt) -parseDerivationWith filepath string = do +-- parsers for filepaths, texts, outputNames and derivation outputs +parseDerivationWith + :: ( Ord fp + , Ord txt + , Ord outputName + ) + => Parser fp + -> Parser txt + -> Parser outputName + -> Parser (drvOutput fp) + -> Parser (Derivation fp txt outputName drvOutput) +parseDerivationWith filepath string outputName parseOutput = do "Derive(" let keyValue0 = do "(" - key <- string - "," - path <- filepath + key <- outputName "," - hashAlgo <- string - "," - hash <- string + out <- parseOutput ")" - return (key, DerivationOutput {..}) + pure (key, out) outputs <- mapOf keyValue0 "," @@ -86,19 +96,29 @@ parseDerivationWith filepath string = do "," - let keyValue2 = do + let keyValue1 = do "(" key <- string "," value <- string ")" return (key, value) - env <- mapOf keyValue2 + env <- mapOf keyValue1 ")" return (Derivation {..}) +-- | Parse a derivation output +parseDerivationOutputWith :: Parser fp -> Parser (DerivationOutput fp) +parseDerivationOutputWith filepath = do + path <- filepath + "," + hashAlgo <- textParser + "," + hash <- textParser + pure DerivationOutput {..} + textParser :: Parser Text textParser = do "\"" diff --git a/src/Nix/Derivation/Types.hs b/src/Nix/Derivation/Types.hs index 1772a7fb..846d2337 100644 --- a/src/Nix/Derivation/Types.hs +++ b/src/Nix/Derivation/Types.hs @@ -12,15 +12,15 @@ module Nix.Derivation.Types ) where import Control.DeepSeq (NFData) -import Data.Bifunctor (Bifunctor(bimap)) import Data.Map (Map) import Data.Set (Set) +import Data.Text (Text) import Data.Vector (Vector) import GHC.Generics (Generic) -- | A Nix derivation -data Derivation fp txt = Derivation - { outputs :: Map txt (DerivationOutput fp txt) +data Derivation fp txt outputName drvOutput = Derivation + { outputs :: Map outputName (drvOutput fp) -- ^ Outputs produced by this derivation where keys are output names , inputDrvs :: Map fp (Set txt) -- ^ Inputs that are derivations where keys specify derivation paths and @@ -38,30 +38,21 @@ data Derivation fp txt = Derivation -- derivation } deriving (Eq, Generic, Ord, Show) -instance (NFData a, NFData b) => NFData (Derivation a b) +instance ( NFData fp + , NFData txt + , NFData outputName + , NFData (drvOutput fp) + ) + => NFData (Derivation fp txt outputName drvOutput) -- | An output of a Nix derivation -data DerivationOutput fp txt = DerivationOutput +data DerivationOutput fp = DerivationOutput { path :: fp -- ^ Path where the output will be saved - , hashAlgo :: txt + , hashAlgo :: Text -- ^ Hash used for expected hash computation - , hash :: txt + , hash :: Text -- ^ Expected hash } deriving (Eq, Generic, Ord, Show) -instance (NFData a, NFData b) => NFData (DerivationOutput a b) - -instance Functor (DerivationOutput fp) where - fmap f DerivationOutput{..} = DerivationOutput - { path = path - , hashAlgo = f hashAlgo - , hash = f hash - } - -instance Bifunctor DerivationOutput where - bimap f g DerivationOutput{..} = DerivationOutput - { path = f path - , hashAlgo = g hashAlgo - , hash = g hash - } +instance (NFData a) => NFData (DerivationOutput a) diff --git a/tests/Property.hs b/tests/Property.hs index 287f501c..9182bcf2 100644 --- a/tests/Property.hs +++ b/tests/Property.hs @@ -26,14 +26,14 @@ instance Arbitrary Text where instance Arbitrary a => Arbitrary (Vector a) where arbitrary = fmap Data.Vector.fromList arbitrary -instance Arbitrary (DerivationOutput FilePath Text) where +instance Arbitrary (DerivationOutput FilePath) where arbitrary = do path <- arbitrary hashAlgo <- arbitrary hash <- arbitrary return (DerivationOutput {..}) -instance Arbitrary (Derivation FilePath Text) where +instance Arbitrary (Derivation FilePath Text Text DerivationOutput) where arbitrary = do outputs <- arbitrary inputDrvs <- arbitrary @@ -44,7 +44,7 @@ instance Arbitrary (Derivation FilePath Text) where env <- arbitrary return (Derivation {..}) -property :: Derivation FilePath Text -> Bool +property :: Derivation FilePath Text Text DerivationOutput -> Bool property derivation0 = either == Right derivation0 where builder = Nix.Derivation.buildDerivation derivation0 From 92dd4e754ee514547f811a2629b4e26751a1bb8c Mon Sep 17 00:00:00 2001 From: sorki Date: Tue, 5 Dec 2023 09:40:17 +0100 Subject: [PATCH 40/58] Add drvInputs parameter to Derivation, DerivationInputs type Normalizes `inputsSrcs` and `inputsDrvs` into `inputs`. Similar reasons as the previous commit. Allows to embed mainline Nixes `BasicDerivation` into `Derivation` by using `inputs` type that only provides source inputs. --- src/Nix/Derivation.hs | 1 + src/Nix/Derivation/Builder.hs | 60 ++++++++++++++++++++++----------- src/Nix/Derivation/Parser.hs | 63 ++++++++++++++++++++++++----------- src/Nix/Derivation/Types.hs | 23 +++++++++---- tests/Property.hs | 19 ++++++++--- 5 files changed, 115 insertions(+), 51 deletions(-) diff --git a/src/Nix/Derivation.hs b/src/Nix/Derivation.hs index 4d8e00d4..ee5e24fe 100644 --- a/src/Nix/Derivation.hs +++ b/src/Nix/Derivation.hs @@ -79,6 +79,7 @@ module Nix.Derivation ( -- * Types Derivation(..) + , DerivationInputs(..) , DerivationOutput(..) -- * Parse derivations diff --git a/src/Nix/Derivation/Builder.hs b/src/Nix/Derivation/Builder.hs index e8ffef29..d3483fca 100644 --- a/src/Nix/Derivation/Builder.hs +++ b/src/Nix/Derivation/Builder.hs @@ -14,7 +14,11 @@ import Data.Set (Set) import Data.Text (Text) import Data.Text.Lazy.Builder (Builder) import Data.Vector (Vector) -import Nix.Derivation.Types (Derivation(..), DerivationOutput(..)) +import Nix.Derivation.Types + ( Derivation(..) + , DerivationInputs(..) + , DerivationOutput(..) + ) import qualified Data.Map import qualified Data.Set @@ -23,30 +27,35 @@ import qualified Data.Text.Lazy.Builder import qualified Data.Vector -- | Render a derivation as a `Builder` -buildDerivation :: Derivation FilePath Text Text DerivationOutput -> Builder +buildDerivation + :: Derivation + FilePath + Text + Text + DerivationOutput + DerivationInputs + -> Builder buildDerivation = buildDerivationWith - filepath' string' string' (buildDerivationOutputWith filepath') + (buildDerivationInputsWith filepath' string') -- | Render a derivation as a `Builder` using custom --- renderer for filepaths, texts, outputNames and @DerivationOutput@s +-- renderer for filepaths, texts, outputNames and derivation inputs/outputs buildDerivationWith - :: (fp -> Builder) - -> (txt -> Builder) + :: (txt -> Builder) -> (outputName -> Builder) -> (drvOutput fp -> Builder) - -> Derivation fp txt outputName drvOutput + -> (drvInputs fp outputName -> Builder) + -> Derivation fp txt outputName drvOutput drvInputs -> Builder -buildDerivationWith filepath string outputName drvOutput (Derivation {..}) = +buildDerivationWith string outputName drvOutput drvInputs (Derivation {..}) = "Derive(" <> mapOf keyValue0 outputs <> "," - <> mapOf keyValue1 inputDrvs - <> "," - <> setOf filepath inputSrcs + <> drvInputs inputs <> "," <> string platform <> "," @@ -54,7 +63,7 @@ buildDerivationWith filepath string outputName drvOutput (Derivation {..}) = <> "," <> vectorOf string args <> "," - <> mapOf keyValue2 env + <> mapOf keyValue1 env <> ")" where keyValue0 (key, output) = @@ -66,13 +75,6 @@ buildDerivationWith filepath string outputName drvOutput (Derivation {..}) = keyValue1 (key, value) = "(" - <> filepath key - <> "," - <> setOf string value - <> ")" - - keyValue2 (key, value) = - "(" <> string key <> "," <> string value @@ -91,6 +93,26 @@ buildDerivationOutputWith filepath (DerivationOutput {..}) = <> "," <> string' hash +-- | Render a @DerivationInputs@ as a `Builder` using custom +-- renderer for filepaths and output names +buildDerivationInputsWith + :: (fp -> Builder) + -> (outputName -> Builder) + -> DerivationInputs fp outputName + -> Builder +buildDerivationInputsWith filepath outputName (DerivationInputs {..}) = + mapOf keyValue drvs + <> "," + <> setOf filepath srcs + + where + keyValue (key, value) = + "(" + <> filepath key + <> "," + <> setOf outputName value + <> ")" + mapOf :: ((k, v) -> Builder) -> Map k v -> Builder mapOf keyValue m = listOf keyValue (Data.Map.toList m) diff --git a/src/Nix/Derivation/Parser.hs b/src/Nix/Derivation/Parser.hs index 2bbec62c..2cd1b9ba 100644 --- a/src/Nix/Derivation/Parser.hs +++ b/src/Nix/Derivation/Parser.hs @@ -17,7 +17,11 @@ import Data.Map (Map) import Data.Set (Set) import Data.Text (Text) import Data.Vector (Vector) -import Nix.Derivation.Types (Derivation(..), DerivationOutput(..)) +import Nix.Derivation.Types + ( Derivation(..) + , DerivationInputs(..) + , DerivationOutput(..) + ) import qualified Data.Attoparsec.Text import qualified Data.Attoparsec.Text.Lazy @@ -35,27 +39,34 @@ listOf element = do return es -- | Parse a derivation -parseDerivation :: Parser (Derivation FilePath Text Text DerivationOutput) +parseDerivation + :: Parser (Derivation + FilePath + Text + Text + DerivationOutput + DerivationInputs + ) parseDerivation = parseDerivationWith - filepathParser textParser textParser (parseDerivationOutputWith filepathParser) + (parseDerivationInputsWith filepathParser textParser) -- | Parse a derivation using custom --- parsers for filepaths, texts, outputNames and derivation outputs +-- parsers for filepaths, texts, outputNames and derivation inputs/outputs parseDerivationWith :: ( Ord fp , Ord txt , Ord outputName ) - => Parser fp - -> Parser txt + => Parser txt -> Parser outputName -> Parser (drvOutput fp) - -> Parser (Derivation fp txt outputName drvOutput) -parseDerivationWith filepath string outputName parseOutput = do + -> Parser (drvInputs fp outputName) + -> Parser (Derivation fp txt outputName drvOutput drvInputs) +parseDerivationWith string outputName parseOutput parseInputs = do "Derive(" let keyValue0 = do @@ -69,18 +80,7 @@ parseDerivationWith filepath string outputName parseOutput = do "," - let keyValue1 = do - "(" - key <- filepath - "," - value <- setOf string - ")" - return (key, value) - inputDrvs <- mapOf keyValue1 - - "," - - inputSrcs <- setOf filepath + inputs <- parseInputs "," @@ -119,6 +119,29 @@ parseDerivationOutputWith filepath = do hash <- textParser pure DerivationOutput {..} +-- | Parse a derivation inputs +parseDerivationInputsWith + :: ( Ord fp + , Ord outputName + ) + => Parser fp + -> Parser outputName + -> Parser (DerivationInputs fp outputName) +parseDerivationInputsWith filepath outputName = do + let keyValue = do + "(" + key <- filepath + "," + value <- setOf outputName + ")" + return (key, value) + drvs <- mapOf keyValue + + "," + + srcs <- setOf filepath + pure DerivationInputs {..} + textParser :: Parser Text textParser = do "\"" diff --git a/src/Nix/Derivation/Types.hs b/src/Nix/Derivation/Types.hs index 846d2337..f9508e41 100644 --- a/src/Nix/Derivation/Types.hs +++ b/src/Nix/Derivation/Types.hs @@ -8,6 +8,7 @@ module Nix.Derivation.Types ( -- * Types Derivation(..) + , DerivationInputs(..) , DerivationOutput(..) ) where @@ -19,14 +20,11 @@ import Data.Vector (Vector) import GHC.Generics (Generic) -- | A Nix derivation -data Derivation fp txt outputName drvOutput = Derivation +data Derivation fp txt outputName drvOutput drvInputs = Derivation { outputs :: Map outputName (drvOutput fp) -- ^ Outputs produced by this derivation where keys are output names - , inputDrvs :: Map fp (Set txt) - -- ^ Inputs that are derivations where keys specify derivation paths and - -- values specify which output names are used by this derivation - , inputSrcs :: Set fp - -- ^ Inputs that are sources + , inputs :: drvInputs fp outputName + -- ^ Inputs (sources and derivations) , platform :: txt -- ^ Platform required for this derivation , builder :: txt @@ -42,8 +40,19 @@ instance ( NFData fp , NFData txt , NFData outputName , NFData (drvOutput fp) + , NFData (drvInputs fp outputName) ) - => NFData (Derivation fp txt outputName drvOutput) + => NFData (Derivation fp txt outputName drvOutput drvInputs) + +data DerivationInputs fp drvOutput = DerivationInputs + { drvs :: Map fp (Set drvOutput) + -- ^ Inputs that are derivations where keys specify derivation paths and + -- values specify which output names are used by this derivation + , srcs :: Set fp + -- ^ Inputs that are sources + } deriving (Eq, Generic, Ord, Show) + +instance (NFData a, NFData b) => NFData (DerivationInputs a b) -- | An output of a Nix derivation data DerivationOutput fp = DerivationOutput diff --git a/tests/Property.hs b/tests/Property.hs index 9182bcf2..6563c8ee 100644 --- a/tests/Property.hs +++ b/tests/Property.hs @@ -9,7 +9,11 @@ module Main where import Data.Text (Text) import Data.Vector (Vector) import System.FilePath -import Nix.Derivation (Derivation(..), DerivationOutput(..)) +import Nix.Derivation + ( Derivation(..) + , DerivationInputs(..) + , DerivationOutput(..) + ) import Prelude hiding (FilePath, either) import Test.QuickCheck (Arbitrary(..)) @@ -26,6 +30,12 @@ instance Arbitrary Text where instance Arbitrary a => Arbitrary (Vector a) where arbitrary = fmap Data.Vector.fromList arbitrary +instance Arbitrary (DerivationInputs FilePath Text) where + arbitrary = do + drvs <- arbitrary + srcs <- arbitrary + return (DerivationInputs {..}) + instance Arbitrary (DerivationOutput FilePath) where arbitrary = do path <- arbitrary @@ -33,18 +43,17 @@ instance Arbitrary (DerivationOutput FilePath) where hash <- arbitrary return (DerivationOutput {..}) -instance Arbitrary (Derivation FilePath Text Text DerivationOutput) where +instance Arbitrary (Derivation FilePath Text Text DerivationOutput DerivationInputs) where arbitrary = do outputs <- arbitrary - inputDrvs <- arbitrary - inputSrcs <- arbitrary + inputs <- arbitrary platform <- arbitrary builder <- arbitrary args <- arbitrary env <- arbitrary return (Derivation {..}) -property :: Derivation FilePath Text Text DerivationOutput -> Bool +property :: Derivation FilePath Text Text DerivationOutput DerivationInputs -> Bool property derivation0 = either == Right derivation0 where builder = Nix.Derivation.buildDerivation derivation0 From 25c9c15c0ee0738bf9172d99ad7b0ade6eb06424 Mon Sep 17 00:00:00 2001 From: sorki Date: Tue, 5 Dec 2023 09:46:33 +0100 Subject: [PATCH 41/58] Align nicely, return -> pure --- src/Nix/Derivation/Builder.hs | 1 - src/Nix/Derivation/Parser.hs | 72 +++++++++++++++++------------------ tests/Property.hs | 6 +-- 3 files changed, 39 insertions(+), 40 deletions(-) diff --git a/src/Nix/Derivation/Builder.hs b/src/Nix/Derivation/Builder.hs index d3483fca..2c3f7034 100644 --- a/src/Nix/Derivation/Builder.hs +++ b/src/Nix/Derivation/Builder.hs @@ -104,7 +104,6 @@ buildDerivationInputsWith filepath outputName (DerivationInputs {..}) = mapOf keyValue drvs <> "," <> setOf filepath srcs - where keyValue (key, value) = "(" diff --git a/src/Nix/Derivation/Parser.hs b/src/Nix/Derivation/Parser.hs index 2cd1b9ba..d45d643d 100644 --- a/src/Nix/Derivation/Parser.hs +++ b/src/Nix/Derivation/Parser.hs @@ -36,36 +36,36 @@ listOf element = do "[" es <- Data.Attoparsec.Text.Lazy.sepBy element "," "]" - return es + pure es -- | Parse a derivation parseDerivation - :: Parser (Derivation - FilePath - Text - Text - DerivationOutput - DerivationInputs - ) + :: Parser (Derivation + FilePath + Text + Text + DerivationOutput + DerivationInputs + ) parseDerivation = - parseDerivationWith - textParser - textParser - (parseDerivationOutputWith filepathParser) - (parseDerivationInputsWith filepathParser textParser) + parseDerivationWith + textParser + textParser + (parseDerivationOutputWith filepathParser) + (parseDerivationInputsWith filepathParser textParser) -- | Parse a derivation using custom -- parsers for filepaths, texts, outputNames and derivation inputs/outputs parseDerivationWith - :: ( Ord fp - , Ord txt - , Ord outputName - ) - => Parser txt - -> Parser outputName - -> Parser (drvOutput fp) - -> Parser (drvInputs fp outputName) - -> Parser (Derivation fp txt outputName drvOutput drvInputs) + :: ( Ord fp + , Ord txt + , Ord outputName + ) + => Parser txt + -> Parser outputName + -> Parser (drvOutput fp) + -> Parser (drvInputs fp outputName) + -> Parser (Derivation fp txt outputName drvOutput drvInputs) parseDerivationWith string outputName parseOutput parseInputs = do "Derive(" @@ -102,12 +102,12 @@ parseDerivationWith string outputName parseOutput parseInputs = do "," value <- string ")" - return (key, value) + pure (key, value) env <- mapOf keyValue1 ")" - return (Derivation {..}) + pure Derivation {..} -- | Parse a derivation output parseDerivationOutputWith :: Parser fp -> Parser (DerivationOutput fp) @@ -134,7 +134,7 @@ parseDerivationInputsWith filepath outputName = do "," value <- setOf outputName ")" - return (key, value) + pure (key, value) drvs <- mapOf keyValue "," @@ -155,24 +155,24 @@ textParser = do case char0 of '"' -> do - return [ text0 ] + pure [ text0 ] _ -> do char1 <- Data.Attoparsec.Text.anyChar char2 <- case char1 of - 'n' -> return '\n' - 'r' -> return '\r' - 't' -> return '\t' - _ -> return char1 + 'n' -> pure '\n' + 'r' -> pure '\r' + 't' -> pure '\t' + _ -> pure char1 textChunks <- loop - return (text0 : Data.Text.singleton char2 : textChunks) + pure (text0 : Data.Text.singleton char2 : textChunks) textChunks <- loop - return (Data.Text.concat textChunks) + pure (Data.Text.concat textChunks) filepathParser :: Parser FilePath filepathParser = do @@ -180,21 +180,21 @@ filepathParser = do let str = Data.Text.unpack text case (Data.Text.uncons text, System.FilePath.isValid str) of (Just ('/', _), True) -> do - return str + pure str _ -> do fail ("bad path ‘" <> Data.Text.unpack text <> "’ in derivation") setOf :: Ord a => Parser a -> Parser (Set a) setOf element = do es <- listOf element - return (Data.Set.fromList es) + pure (Data.Set.fromList es) vectorOf :: Parser a -> Parser (Vector a) vectorOf element = do es <- listOf element - return (Data.Vector.fromList es) + pure (Data.Vector.fromList es) mapOf :: Ord k => Parser (k, v) -> Parser (Map k v) mapOf keyValue = do keyValues <- listOf keyValue - return (Data.Map.fromList keyValues) + pure (Data.Map.fromList keyValues) diff --git a/tests/Property.hs b/tests/Property.hs index 6563c8ee..c380cc29 100644 --- a/tests/Property.hs +++ b/tests/Property.hs @@ -34,14 +34,14 @@ instance Arbitrary (DerivationInputs FilePath Text) where arbitrary = do drvs <- arbitrary srcs <- arbitrary - return (DerivationInputs {..}) + pure DerivationInputs {..} instance Arbitrary (DerivationOutput FilePath) where arbitrary = do path <- arbitrary hashAlgo <- arbitrary hash <- arbitrary - return (DerivationOutput {..}) + pure DerivationOutput {..} instance Arbitrary (Derivation FilePath Text Text DerivationOutput DerivationInputs) where arbitrary = do @@ -51,7 +51,7 @@ instance Arbitrary (Derivation FilePath Text Text DerivationOutput DerivationInp builder <- arbitrary args <- arbitrary env <- arbitrary - return (Derivation {..}) + pure Derivation {..} property :: Derivation FilePath Text Text DerivationOutput DerivationInputs -> Bool property derivation0 = either == Right derivation0 From 9d7cb76953c202a7d23117faa406171d5155a63c Mon Sep 17 00:00:00 2001 From: sorki Date: Tue, 5 Dec 2023 09:48:18 +0100 Subject: [PATCH 42/58] hlint: drop unused RecordWildcards, use <$> --- src/Nix/Derivation/Parser.hs | 4 +--- src/Nix/Derivation/Types.hs | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Nix/Derivation/Parser.hs b/src/Nix/Derivation/Parser.hs index d45d643d..848f4de4 100644 --- a/src/Nix/Derivation/Parser.hs +++ b/src/Nix/Derivation/Parser.hs @@ -170,9 +170,7 @@ textParser = do pure (text0 : Data.Text.singleton char2 : textChunks) - textChunks <- loop - - pure (Data.Text.concat textChunks) + Data.Text.concat <$> loop filepathParser :: Parser FilePath filepathParser = do diff --git a/src/Nix/Derivation/Types.hs b/src/Nix/Derivation/Types.hs index f9508e41..f2dcdd0f 100644 --- a/src/Nix/Derivation/Types.hs +++ b/src/Nix/Derivation/Types.hs @@ -1,7 +1,6 @@ {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE KindSignatures #-} -{-# LANGUAGE RecordWildCards #-} -- | Shared types From cbc257264ebdcb1a2170b7b83aa131356e00ecbf Mon Sep 17 00:00:00 2001 From: Rickard Nilsson Date: Sun, 10 Dec 2023 08:33:18 +0100 Subject: [PATCH 43/58] Support derivations with content-addressed outputs Forward port of #26 --- src/Nix/Derivation/Builder.hs | 15 ++++++++++++++- src/Nix/Derivation/Parser.hs | 18 ++++++++++++++++-- src/Nix/Derivation/Types.hs | 26 ++++++++++++++++++-------- tests/Property.hs | 29 +++++++++++++++++++++++------ 4 files changed, 71 insertions(+), 17 deletions(-) diff --git a/src/Nix/Derivation/Builder.hs b/src/Nix/Derivation/Builder.hs index 2c3f7034..17c61157 100644 --- a/src/Nix/Derivation/Builder.hs +++ b/src/Nix/Derivation/Builder.hs @@ -83,15 +83,28 @@ buildDerivationWith string outputName drvOutput drvInputs (Derivation {..}) = -- | Render a @DerivationOutput@ as a `Builder` using custom -- renderer for filepaths buildDerivationOutputWith - :: (fp -> Builder) + :: Monoid fp + => (fp -> Builder) -> DerivationOutput fp -> Builder buildDerivationOutputWith filepath (DerivationOutput {..}) = filepath path <> "," + <> string' mempty + <> "," + <> string' mempty +buildDerivationOutputWith filepath (FixedDerivationOutput {..}) = + filepath path + <> "," <> string' hashAlgo <> "," <> string' hash +buildDerivationOutputWith filepath (ContentAddressedDerivationOutput {..}) = + filepath mempty + <> "," + <> string' hashAlgo + <> "," + <> string' mempty -- | Render a @DerivationInputs@ as a `Builder` using custom -- renderer for filepaths and output names diff --git a/src/Nix/Derivation/Parser.hs b/src/Nix/Derivation/Parser.hs index 848f4de4..2036b6ed 100644 --- a/src/Nix/Derivation/Parser.hs +++ b/src/Nix/Derivation/Parser.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE MultiWayIf #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} @@ -110,14 +111,27 @@ parseDerivationWith string outputName parseOutput parseInputs = do pure Derivation {..} -- | Parse a derivation output -parseDerivationOutputWith :: Parser fp -> Parser (DerivationOutput fp) +parseDerivationOutputWith + :: ( Eq fp + , Monoid fp + ) + => Parser fp + -> Parser (DerivationOutput fp) parseDerivationOutputWith filepath = do path <- filepath "," hashAlgo <- textParser "," hash <- textParser - pure DerivationOutput {..} + if + | path /= mempty && hashAlgo == mempty && hash == mempty -> + pure DerivationOutput {..} + | path /= mempty && hashAlgo /= mempty && hash /= mempty -> + pure FixedDerivationOutput {..} + | path == mempty && hashAlgo /= mempty && hash == mempty -> + pure ContentAddressedDerivationOutput {..} + | otherwise -> + fail "bad output in derivation" -- | Parse a derivation inputs parseDerivationInputsWith diff --git a/src/Nix/Derivation/Types.hs b/src/Nix/Derivation/Types.hs index f2dcdd0f..f4b07df3 100644 --- a/src/Nix/Derivation/Types.hs +++ b/src/Nix/Derivation/Types.hs @@ -54,13 +54,23 @@ data DerivationInputs fp drvOutput = DerivationInputs instance (NFData a, NFData b) => NFData (DerivationInputs a b) -- | An output of a Nix derivation -data DerivationOutput fp = DerivationOutput - { path :: fp - -- ^ Path where the output will be saved - , hashAlgo :: Text - -- ^ Hash used for expected hash computation - , hash :: Text - -- ^ Expected hash - } deriving (Eq, Generic, Ord, Show) +data DerivationOutput fp + = DerivationOutput + { path :: fp + -- ^ Path where the output will be saved + } + | FixedDerivationOutput + { path :: fp + -- ^ Path where the output will be saved + , hashAlgo :: Text + -- ^ Hash used for expected hash computation + , hash :: Text + -- ^ Expected hash + } + | ContentAddressedDerivationOutput + { hashAlgo :: Text + -- ^ Hash used for expected hash computation + } + deriving (Eq, Generic, Ord, Show) instance (NFData a) => NFData (DerivationOutput a) diff --git a/tests/Property.hs b/tests/Property.hs index c380cc29..0edf9eaf 100644 --- a/tests/Property.hs +++ b/tests/Property.hs @@ -15,7 +15,7 @@ import Nix.Derivation , DerivationOutput(..) ) import Prelude hiding (FilePath, either) -import Test.QuickCheck (Arbitrary(..)) +import Test.QuickCheck (Arbitrary(..), Gen, oneof) import qualified Data.Attoparsec.Text.Lazy import qualified Data.Text @@ -37,11 +37,28 @@ instance Arbitrary (DerivationInputs FilePath Text) where pure DerivationInputs {..} instance Arbitrary (DerivationOutput FilePath) where - arbitrary = do - path <- arbitrary - hashAlgo <- arbitrary - hash <- arbitrary - pure DerivationOutput {..} + arbitrary = oneof + [ derivationOutput + , fixedDerivationOutput + , contentAddressedDerivationOutput + ] + +derivationOutput :: Gen (DerivationOutput FilePath) +derivationOutput = do + path <- arbitrary + return (DerivationOutput {..}) + +fixedDerivationOutput :: Gen (DerivationOutput FilePath) +fixedDerivationOutput = do + path <- arbitrary + hashAlgo <- arbitrary + hash <- arbitrary + return (FixedDerivationOutput {..}) + +contentAddressedDerivationOutput :: Gen (DerivationOutput FilePath) +contentAddressedDerivationOutput = do + hashAlgo <- arbitrary + return (ContentAddressedDerivationOutput {..}) instance Arbitrary (Derivation FilePath Text Text DerivationOutput DerivationInputs) where arbitrary = do From 3f5b5939ddb053f92e1f58e4ef68dcc10a2543ac Mon Sep 17 00:00:00 2001 From: gabby Date: Sat, 5 Oct 2024 15:32:37 -0700 Subject: [PATCH 44/58] Build against `QuickCheck-2.15` (#27) --- nix-derivation.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix-derivation.cabal b/nix-derivation.cabal index bd0d4b37..221ecdbd 100644 --- a/nix-derivation.cabal +++ b/nix-derivation.cabal @@ -77,7 +77,7 @@ Test-Suite property base >= 4.6.0.0 && < 5 , attoparsec >= 0.12.0.0 && < 0.15, nix-derivation , - QuickCheck < 2.15, + QuickCheck < 2.16, text , vector < 0.14, filepath < 1.5 From ad1adfdb775024c1f1c98d83246580ad4acb3967 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Thu, 31 Oct 2024 13:27:03 -0400 Subject: [PATCH 45/58] Complete build with new `nix-derivation` Tests don't pass, more work is needed. --- cabal.project | 1 + cabal.project.local.ci | 3 + default.nix | 1 + hnix-store-core/src/System/Nix/Derivation.hs | 38 ++++++++-- .../src/System/Nix/Store/Remote/Client.hs | 8 ++- .../src/System/Nix/Store/Remote/Serializer.hs | 71 +++++++++++++------ .../Nix/Store/Remote/Types/StoreRequest.hs | 9 ++- hnix-store-remote/tests/NixSerializerSpec.hs | 6 +- .../src/System/Nix/Arbitrary/Derivation.hs | 32 ++++++++- nix-derivation/.github/workflows/ci.yaml | 53 -------------- nix-derivation/ci.dhall | 4 -- nix-derivation/ci.sh | 10 --- nix-derivation/default.nix | 33 --------- nix-derivation/shell.nix | 1 - nix-derivation/src/Nix/Derivation.hs | 6 +- nix-derivation/src/Nix/Derivation/Builder.hs | 37 +++++----- nix-derivation/src/Nix/Derivation/Parser.hs | 42 ++++++----- nix-derivation/src/Nix/Derivation/Types.hs | 11 ++- nix-derivation/tests/Property.hs | 26 +++++-- overlay.nix | 6 ++ 20 files changed, 212 insertions(+), 186 deletions(-) delete mode 100644 nix-derivation/.github/workflows/ci.yaml delete mode 100644 nix-derivation/ci.dhall delete mode 100755 nix-derivation/ci.sh delete mode 100644 nix-derivation/default.nix delete mode 100644 nix-derivation/shell.nix diff --git a/cabal.project b/cabal.project index 6c26f75b..04971545 100644 --- a/cabal.project +++ b/cabal.project @@ -2,6 +2,7 @@ tests: true benchmarks: true packages: + ./nix-derivation/nix-derivation.cabal ./hnix-store-core/hnix-store-core.cabal ./hnix-store-db/hnix-store-db.cabal ./hnix-store-json/hnix-store-json.cabal diff --git a/cabal.project.local.ci b/cabal.project.local.ci index 764e06a8..3c2afadb 100644 --- a/cabal.project.local.ci +++ b/cabal.project.local.ci @@ -1,3 +1,6 @@ +package nix-derivation + ghc-options: -Wunused-packages -Wall -Werror + package hnix-store-core ghc-options: -Wunused-packages -Wall -Werror diff --git a/default.nix b/default.nix index f42d46ec..178983fa 100644 --- a/default.nix +++ b/default.nix @@ -20,6 +20,7 @@ let haskellPackages = packageSet.override overrideHaskellPackages; in { inherit (haskellPackages) + nix-derivation hnix-store-core hnix-store-db hnix-store-json diff --git a/hnix-store-core/src/System/Nix/Derivation.hs b/hnix-store-core/src/System/Nix/Derivation.hs index 0feb2ecf..ff9f7259 100644 --- a/hnix-store-core/src/System/Nix/Derivation.hs +++ b/hnix-store-core/src/System/Nix/Derivation.hs @@ -1,16 +1,26 @@ module System.Nix.Derivation ( parseDerivation , buildDerivation + , Derivation' -- Re-exports , Derivation(..) , DerivationOutput(..) + , DerivationInputs(..) ) where import Data.Attoparsec.Text.Lazy (Parser) import Data.Text (Text) import Data.Text.Lazy.Builder (Builder) -import Nix.Derivation (Derivation(..), DerivationOutput(..)) +import Nix.Derivation + ( Derivation(..) + , DerivationOutput(..) + , DerivationInputs(..) + , parseDerivationOutputWith + , parseDerivationInputsWith + , buildDerivationOutputWith + , buildDerivationInputsWith + ) import System.Nix.StorePath (StoreDir, StorePath) import qualified Data.Attoparsec.Text.Lazy @@ -21,11 +31,22 @@ import qualified Data.Text.Lazy.Builder import qualified Nix.Derivation import qualified System.Nix.StorePath -parseDerivation :: StoreDir -> Parser (Derivation StorePath Text) +type Derivation' = Derivation + StorePath + Text + Text + (DerivationOutput StorePath Text) + (DerivationInputs StorePath Text) + +parseDerivation + :: StoreDir + -> Parser (Derivation') parseDerivation expectedRoot = Nix.Derivation.parseDerivationWith - pathParser Nix.Derivation.textParser + Nix.Derivation.textParser + (parseDerivationOutputWith pathParser Nix.Derivation.textParser) + (parseDerivationInputsWith pathParser Nix.Derivation.textParser) where pathParser = do text <- Nix.Derivation.textParser @@ -36,10 +57,17 @@ parseDerivation expectedRoot = Right p -> pure p Left e -> fail e -buildDerivation :: StoreDir -> Derivation StorePath Text -> Builder +buildDerivation + :: StoreDir + -> Derivation' + -> Builder buildDerivation storeDir = Nix.Derivation.buildDerivationWith - (string . System.Nix.StorePath.storePathToText storeDir) string + string + (buildDerivationOutputWith path string emptyString) + (buildDerivationInputsWith path string) where + emptyString = string Data.Text.empty + path = string . System.Nix.StorePath.storePathToText storeDir string = Data.Text.Lazy.Builder.fromText . Data.Text.pack . show diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs index 55933e65..60d1c892 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs @@ -147,7 +147,13 @@ buildDerivation sp mode = do case Data.Attoparsec.Text.parseOnly (System.Nix.Derivation.parseDerivation sd) drvContents of Left e -> throwError $ RemoteStoreError_DerivationParse e - Right drv -> doReq (BuildDerivation sp drv mode) + Right drv -> do + let drv' = drv + { System.Nix.Derivation.inputs = + System.Nix.Derivation.srcs + (System.Nix.Derivation.inputs drv) + } + doReq (BuildDerivation sp drv' mode) -- | Build paths if they are an actual derivations. -- diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs index 37e7253b..a88dc3e7 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs @@ -54,7 +54,7 @@ module System.Nix.Store.Remote.Serializer -- * DSum HashAlgo Digest , namedDigest -- * Derivation - , derivation + , basicDerivation -- * Derivation , derivedPath -- * Build @@ -127,7 +127,11 @@ import GHC.Generics (Generic) import System.Nix.Base (BaseEncoding(Base16, NixBase32)) import System.Nix.Build (BuildMode, BuildResult(..)) import System.Nix.ContentAddress (ContentAddress) -import System.Nix.Derivation (Derivation(..), DerivationOutput(..)) +import System.Nix.Derivation + ( Derivation(..) + , DerivationOutput(..) + -- , DerivationInputs(..) + ) import System.Nix.DerivedPath (DerivedPath(..), ParseOutputsError) import System.Nix.Hash (HashAlgo(..)) import System.Nix.JSON () @@ -250,6 +254,7 @@ data SError , badPaddingPads :: [Word8] } | SError_ContentAddress String + | SError_DerivingPath | SError_DerivedPath ParseOutputsError | SError_DerivationOutput DerivationOutputError | SError_Digest String @@ -264,6 +269,7 @@ data SError | SError_Name InvalidNameError | SError_Path InvalidPathError | SError_Signature String + | SError_DerivationOutputInvalidCombo Bool Bool Bool deriving (Eq, Ord, Generic, Show) data ForPV a @@ -715,30 +721,51 @@ derivationOutput => NixSerializer r SError (DerivationOutput StorePath Text) derivationOutput = Serializer { getS = do - path <- getS storePath - hashAlgo <- getS text - hash <- getS text - pure DerivationOutput{..} - , putS = \DerivationOutput{..} -> do - putS storePath path - putS text hashAlgo - putS text hash + mPath <- getS maybePath + mHashAlgo <- getS maybeText + mHash <- getS maybeText + case (mPath, mHashAlgo, mHash) of + (Just path, Nothing, Nothing) -> + pure InputAddressedDerivationOutput {..} + (Just path, Just hashAlgo, Just hash) -> + pure FixedDerivationOutput {..} + (Nothing, Just hashAlgo, Nothing) -> + pure ContentAddressedDerivationOutput {..} + _ -> + throwError $ SError_DerivationOutputInvalidCombo + (Data.Maybe.isJust mPath) + (Data.Maybe.isJust mHashAlgo) + (Data.Maybe.isJust mHash) + , putS = \case + InputAddressedDerivationOutput{..} -> do + putS storePath path + putS text Data.Text.empty + putS text Data.Text.empty + FixedDerivationOutput{..} -> do + putS storePath path + putS text hashAlgo + putS text hash + ContentAddressedDerivationOutput{..} -> do + putS text Data.Text.empty + putS text hashAlgo + putS text Data.Text.empty } -- * Derivation -derivation +basicDerivation :: HasStoreDir r - => NixSerializer r SError (Derivation StorePath Text) -derivation = Serializer + => NixSerializer r SError + (Derivation + StorePath + Text + Text + (DerivationOutput StorePath Text) + (Set StorePath)) +basicDerivation = Serializer { getS = do outputs <- getS (mapS text derivationOutput) - -- Our type is Derivation, but in Nix - -- the type sent over the wire is BasicDerivation - -- which omits inputDrvs - inputDrvs <- pure mempty - inputSrcs <- getS (set storePath) - + inputs <- getS (set storePath) platform <- getS text builder <- getS text args <- getS (vector text) @@ -746,7 +773,7 @@ derivation = Serializer pure Derivation{..} , putS = \Derivation{..} -> do putS (mapS text derivationOutput) outputs - putS (set storePath) inputSrcs + putS (set storePath) inputs putS text platform putS text builder putS (vector text) args @@ -1119,7 +1146,7 @@ storeRequest = Serializer WorkerOp_BuildDerivation -> mapGetE $ do path <- getS storePath - drv <- getS derivation + drv <- getS basicDerivation buildMode' <- getS buildMode pure $ Some (BuildDerivation path drv buildMode') @@ -1264,7 +1291,7 @@ storeRequest = Serializer putS workerOp WorkerOp_BuildDerivation putS storePath path - putS derivation drv + putS basicDerivation drv putS buildMode buildMode' Some (CollectGarbage GCOptions{..}) -> mapPutE $ do diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Types/StoreRequest.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Types/StoreRequest.hs index 542ddcbd..17c59bdf 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Types/StoreRequest.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Types/StoreRequest.hs @@ -16,7 +16,7 @@ import Data.Text (Text) import Data.Some (Some(Some)) import System.Nix.Build (BuildMode, BuildResult) -import System.Nix.Derivation (Derivation) +import System.Nix.Derivation (Derivation, DerivationOutput) import System.Nix.DerivedPath (DerivedPath) import System.Nix.Hash (HashAlgo) import System.Nix.Signature (Signature) @@ -85,7 +85,12 @@ data StoreRequest :: Type -> Type where BuildDerivation :: StorePath - -> Derivation StorePath Text + -> Derivation + StorePath + Text + Text + (DerivationOutput StorePath Text) + (Set StorePath) -> BuildMode -> StoreRequest BuildResult diff --git a/hnix-store-remote/tests/NixSerializerSpec.hs b/hnix-store-remote/tests/NixSerializerSpec.hs index e229fff6..7f9aaa83 100644 --- a/hnix-store-remote/tests/NixSerializerSpec.hs +++ b/hnix-store-remote/tests/NixSerializerSpec.hs @@ -10,7 +10,7 @@ import Test.Hspec.QuickCheck (prop) import Test.QuickCheck (Gen, arbitrary, forAll, suchThat) import System.Nix.Arbitrary () -import System.Nix.Derivation (Derivation(inputDrvs)) +import System.Nix.Derivation (Derivation) import System.Nix.Build (BuildResult(..)) import System.Nix.StorePath (StoreDir) import System.Nix.Store.Remote.Arbitrary () @@ -115,8 +115,7 @@ spec = parallel $ do prop "SHA512" $ roundtripS . digest @SHA512 prop "Derivation" $ \sd -> - roundtripSReader @StoreDir derivation sd - . (\drv -> drv { inputDrvs = mempty }) + roundtripSReader @StoreDir basicDerivation sd prop "ProtoVersion" $ roundtripS @ProtoVersion @() protoVersion @@ -158,7 +157,6 @@ spec = parallel $ do restrictProtoVersion :: ProtoVersion -> Some StoreRequest -> Bool restrictProtoVersion v (Some (BuildPaths _ _)) | v < ProtoVersion 1 30 = False -restrictProtoVersion _ (Some (BuildDerivation _ drv _)) = inputDrvs drv == mempty restrictProtoVersion v (Some (QueryMissing _)) | v < ProtoVersion 1 30 = False restrictProtoVersion _ _ = True diff --git a/hnix-store-tests/src/System/Nix/Arbitrary/Derivation.hs b/hnix-store-tests/src/System/Nix/Arbitrary/Derivation.hs index 9910dee9..ce5aba4c 100644 --- a/hnix-store-tests/src/System/Nix/Arbitrary/Derivation.hs +++ b/hnix-store-tests/src/System/Nix/Arbitrary/Derivation.hs @@ -10,10 +10,36 @@ import System.Nix.Derivation import System.Nix.StorePath (StorePath) import Test.QuickCheck (Arbitrary(..)) -import Test.QuickCheck.Arbitrary.Generic (GenericArbitrary(..)) +import Test.QuickCheck.Arbitrary.Generic (Arg, GenericArbitrary(..)) import System.Nix.Arbitrary.StorePath () -deriving via GenericArbitrary (Derivation StorePath Text) - instance Arbitrary (Derivation StorePath Text) +deriving via GenericArbitrary + (Derivation + StorePath + Text + Text + (DerivationOutput StorePath Text) + inputs) + instance + ( Arbitrary inputs + , Arg + (Derivation + StorePath + Text + Text + (DerivationOutput StorePath Text) + inputs) + inputs + ) => Arbitrary + (Derivation + StorePath + Text + Text + (DerivationOutput StorePath Text) + inputs) + deriving via GenericArbitrary (DerivationOutput StorePath Text) instance Arbitrary (DerivationOutput StorePath Text) + +deriving via GenericArbitrary (DerivationInputs StorePath Text) + instance Arbitrary (DerivationInputs StorePath Text) diff --git a/nix-derivation/.github/workflows/ci.yaml b/nix-derivation/.github/workflows/ci.yaml deleted file mode 100644 index 85914730..00000000 --- a/nix-derivation/.github/workflows/ci.yaml +++ /dev/null @@ -1,53 +0,0 @@ -# Code generated by dhall-to-yaml. DO NOT EDIT. -jobs: - build: - name: "GHC ${{ matrix.ghc }}, Cabal ${{ matrix.cabal }}, OS ${{ matrix.os }}" - "runs-on": "${{ matrix.os }}" - steps: - - uses: "actions/checkout@v4" - with: - submodules: recursive - - id: "setup-haskell-cabal" - uses: "haskell-actions/setup@v2" - with: - "cabal-version": "${{ matrix.cabal }}" - "ghc-version": "${{ matrix.ghc }}" - - name: Update Hackage repository - run: cabal update - - name: cabal.project.local.ci - run: | - if [ -e cabal.project.local.ci ]; then - cp cabal.project.local.ci cabal.project.local - fi - - name: freeze - run: "cabal freeze --enable-tests --enable-benchmarks" - - uses: "actions/cache@v3" - with: - key: "${{ matrix.os }}-${{ matrix.ghc }}-${{ matrix.cabal}}-${{ hashFiles('cabal.project.freeze') }}" - path: | - ${{ steps.setup-haskell-cabal.outputs.cabal-store }} - dist-newstyle - - name: Install dependencies - run: "cabal build all --enable-tests --enable-benchmarks --only-dependencies" - - name: build all - run: "cabal build all --enable-tests --enable-benchmarks" - - name: test all - run: "cabal test all --enable-tests" - - name: haddock all - run: cabal haddock all - strategy: - matrix: - cabal: - - '3.10' - ghc: - - '9.6.3' - - '9.4.7' - - '9.2.8' - os: - - "ubuntu-latest" -name: Haskell CI -'on': - pull_request: {} - push: {} - schedule: - - cron: "4 20 10 * *" diff --git a/nix-derivation/ci.dhall b/nix-derivation/ci.dhall deleted file mode 100644 index 3c422998..00000000 --- a/nix-derivation/ci.dhall +++ /dev/null @@ -1,4 +0,0 @@ -let haskellCi = - https://raw.githubusercontent.com/sorki/github-actions-dhall/main/haskell-ci.dhall - -in haskellCi.defaultCi3 diff --git a/nix-derivation/ci.sh b/nix-derivation/ci.sh deleted file mode 100755 index 28ee2ee1..00000000 --- a/nix-derivation/ci.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash -# Script by @fisx - -set -eo pipefail -cd "$( dirname "${BASH_SOURCE[0]}" )" - -echo "regenerating .github/workflows/ci.yaml" - -which dhall-to-yaml || cabal install dhall-yaml -dhall-to-yaml-ng --generated-comment --file ci.dhall > .github/workflows/ci.yaml diff --git a/nix-derivation/default.nix b/nix-derivation/default.nix deleted file mode 100644 index 41e9bf2b..00000000 --- a/nix-derivation/default.nix +++ /dev/null @@ -1,33 +0,0 @@ -# You can build this repository using Nix by running: -# -# $ nix-build -# -# You can also open up this repository inside of a Nix shell by running: -# -# $ nix-shell -# -# ... and then Nix will supply the correct Haskell development environment for -# you -let - config = { - packageOverrides = pkgs: { - haskellPackages = pkgs.haskellPackages.override { - overrides = haskellPackagesNew: haskellPackagesOld: { - nix-derivation = - pkgs.haskell.lib.overrideCabal - (haskellPackagesNew.callCabal2nix "nix-derivation" ./. { }) - (_: { -# withBenchmarkDepends = true; - } - ); - }; - }; - }; - }; - - pkgs = - import { inherit config; }; - -in - { nix-derivation = pkgs.haskellPackages.nix-derivation; - } diff --git a/nix-derivation/shell.nix b/nix-derivation/shell.nix deleted file mode 100644 index fc78129c..00000000 --- a/nix-derivation/shell.nix +++ /dev/null @@ -1 +0,0 @@ -(import ./default.nix).nix-derivation.env diff --git a/nix-derivation/src/Nix/Derivation.hs b/nix-derivation/src/Nix/Derivation.hs index ee5e24fe..c3f64020 100644 --- a/nix-derivation/src/Nix/Derivation.hs +++ b/nix-derivation/src/Nix/Derivation.hs @@ -79,17 +79,21 @@ module Nix.Derivation ( -- * Types Derivation(..) - , DerivationInputs(..) , DerivationOutput(..) + , DerivationInputs(..) -- * Parse derivations , parseDerivation , parseDerivationWith + , parseDerivationOutputWith + , parseDerivationInputsWith , textParser -- * Render derivations , buildDerivation , buildDerivationWith + , buildDerivationOutputWith + , buildDerivationInputsWith ) where import Nix.Derivation.Builder diff --git a/nix-derivation/src/Nix/Derivation/Builder.hs b/nix-derivation/src/Nix/Derivation/Builder.hs index 5b093d13..4430be89 100644 --- a/nix-derivation/src/Nix/Derivation/Builder.hs +++ b/nix-derivation/src/Nix/Derivation/Builder.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} @@ -7,6 +8,8 @@ module Nix.Derivation.Builder ( -- * Builder buildDerivation , buildDerivationWith + , buildDerivationOutputWith + , buildDerivationInputsWith ) where import Data.Map (Map) @@ -32,24 +35,25 @@ buildDerivation FilePath Text Text - DerivationOutput - DerivationInputs + (DerivationOutput FilePath Text) + (DerivationInputs FilePath Text) -> Builder buildDerivation = buildDerivationWith string' string' - (buildDerivationOutputWith filepath' string') + (buildDerivationOutputWith filepath' string' emptyString') (buildDerivationInputsWith filepath' string') + where + emptyString' = string' Data.Text.empty -- | Render a derivation as a `Builder` using custom -- renderer for filepaths, texts, outputNames and derivation inputs/outputs buildDerivationWith - :: (Monoid fp, Monoid txt) - => (txt -> Builder) + :: (txt -> Builder) -> (outputName -> Builder) - -> (drvOutput fp txt -> Builder) - -> (drvInputs fp outputName -> Builder) + -> (drvOutput -> Builder) + -> (drvInputs -> Builder) -> Derivation fp txt outputName drvOutput drvInputs -> Builder buildDerivationWith string outputName drvOutput drvInputs (Derivation {..}) = @@ -84,29 +88,30 @@ buildDerivationWith string outputName drvOutput drvInputs (Derivation {..}) = -- | Render a @DerivationOutput@ as a `Builder` using custom -- renderer for filepaths buildDerivationOutputWith - :: (Monoid fp, Monoid txt) - => (fp -> Builder) + :: (fp -> Builder) -> (txt -> Builder) + -> Builder -> DerivationOutput fp txt -> Builder -buildDerivationOutputWith filepath string (DerivationOutput {..}) = +buildDerivationOutputWith filepath string emptyString = \case + InputAddressedDerivationOutput {..} -> filepath path <> "," - <> string mempty + <> emptyString <> "," - <> string mempty -buildDerivationOutputWith filepath string (FixedDerivationOutput {..}) = + <> emptyString + FixedDerivationOutput {..} -> filepath path <> "," <> string hashAlgo <> "," <> string hash -buildDerivationOutputWith filepath string (ContentAddressedDerivationOutput {..}) = - filepath mempty + ContentAddressedDerivationOutput {..} -> + emptyString <> "," <> string hashAlgo <> "," - <> string mempty + <> emptyString -- | Render a @DerivationInputs@ as a `Builder` using custom -- renderer for filepaths and output names diff --git a/nix-derivation/src/Nix/Derivation/Parser.hs b/nix-derivation/src/Nix/Derivation/Parser.hs index 0393bd9c..6dda3fb3 100644 --- a/nix-derivation/src/Nix/Derivation/Parser.hs +++ b/nix-derivation/src/Nix/Derivation/Parser.hs @@ -10,6 +10,8 @@ module Nix.Derivation.Parser ( -- * Parser parseDerivation , parseDerivationWith + , parseDerivationOutputWith + , parseDerivationInputsWith , textParser ) where @@ -45,8 +47,8 @@ parseDerivation FilePath Text Text - DerivationOutput - DerivationInputs + (DerivationOutput FilePath Text) + (DerivationInputs FilePath Text) ) parseDerivation = parseDerivationWith @@ -64,8 +66,8 @@ parseDerivationWith ) => Parser txt -> Parser outputName - -> Parser (drvOutput fp txt) - -> Parser (drvInputs fp outputName) + -> Parser drvOutput + -> Parser drvInputs -> Parser (Derivation fp txt outputName drvOutput drvInputs) parseDerivationWith string outputName parseOutput parseInputs = do "Derive(" @@ -112,28 +114,23 @@ parseDerivationWith string outputName parseOutput parseInputs = do -- | Parse a derivation output parseDerivationOutputWith - :: ( Eq fp - , Eq txt - , Monoid fp - , Monoid txt - ) - => Parser fp + :: Parser fp -> Parser txt -> Parser (DerivationOutput fp txt) parseDerivationOutputWith filepath textParser = do - path <- filepath + mPath <- maybeTextParser filepath "," - hashAlgo <- textParser + mHashAlgo <- maybeTextParser textParser "," - hash <- textParser - if - | path /= mempty && hashAlgo == mempty && hash == mempty -> - pure DerivationOutput {..} - | path /= mempty && hashAlgo /= mempty && hash /= mempty -> + mHash <- maybeTextParser textParser + case (mPath, mHashAlgo, mHash) of + (Just path, Nothing, Nothing) -> + pure InputAddressedDerivationOutput {..} + (Just path, Just hashAlgo, Just hash) -> pure FixedDerivationOutput {..} - | path == mempty && hashAlgo /= mempty && hash == mempty -> + (Nothing, Just hashAlgo, Nothing) -> pure ContentAddressedDerivationOutput {..} - | otherwise -> + _ -> fail "bad output in derivation" -- | Parse a derivation inputs @@ -159,6 +156,13 @@ parseDerivationInputsWith filepath outputName = do srcs <- setOf filepath pure DerivationInputs {..} +maybeTextParser :: Parser a -> Parser (Maybe a) +maybeTextParser p = do + t <- textParser + if t == "" + then pure Nothing + else Just <$> p + textParser :: Parser Text textParser = do "\"" diff --git a/nix-derivation/src/Nix/Derivation/Types.hs b/nix-derivation/src/Nix/Derivation/Types.hs index cbcd1478..b5048bc2 100644 --- a/nix-derivation/src/Nix/Derivation/Types.hs +++ b/nix-derivation/src/Nix/Derivation/Types.hs @@ -14,15 +14,14 @@ module Nix.Derivation.Types import Control.DeepSeq (NFData) import Data.Map (Map) import Data.Set (Set) -import Data.Text (Text) import Data.Vector (Vector) import GHC.Generics (Generic) -- | A Nix derivation data Derivation fp txt outputName drvOutput drvInputs = Derivation - { outputs :: Map outputName (drvOutput fp txt) + { outputs :: Map outputName drvOutput -- ^ Outputs produced by this derivation where keys are output names - , inputs :: drvInputs fp outputName + , inputs :: drvInputs -- ^ Inputs (sources and derivations) , platform :: txt -- ^ Platform required for this derivation @@ -38,8 +37,8 @@ data Derivation fp txt outputName drvOutput drvInputs = Derivation instance ( NFData fp , NFData txt , NFData outputName - , NFData (drvOutput fp txt) - , NFData (drvInputs fp outputName) + , NFData drvOutput + , NFData drvInputs ) => NFData (Derivation fp txt outputName drvOutput drvInputs) @@ -55,7 +54,7 @@ instance (NFData a, NFData b) => NFData (DerivationInputs a b) -- | An output of a Nix derivation data DerivationOutput fp txt - = DerivationOutput + = InputAddressedDerivationOutput { path :: fp -- ^ Path where the output will be saved } diff --git a/nix-derivation/tests/Property.hs b/nix-derivation/tests/Property.hs index 2b90942b..dff059c9 100644 --- a/nix-derivation/tests/Property.hs +++ b/nix-derivation/tests/Property.hs @@ -32,15 +32,15 @@ instance Arbitrary a => Arbitrary (Vector a) where instance Arbitrary (DerivationOutput FilePath Text) where arbitrary = oneof - [ derivationOutput + [ inputAddressedDerivationOutput , fixedDerivationOutput , contentAddressedDerivationOutput ] -derivationOutput :: Gen (DerivationOutput FilePath Text) -derivationOutput = do +inputAddressedDerivationOutput :: Gen (DerivationOutput FilePath Text) +inputAddressedDerivationOutput = do path <- arbitrary - return (DerivationOutput {..}) + return (InputAddressedDerivationOutput {..}) fixedDerivationOutput :: Gen (DerivationOutput FilePath Text) fixedDerivationOutput = do @@ -60,7 +60,14 @@ instance Arbitrary (DerivationInputs FilePath Text) where srcs <- arbitrary pure DerivationInputs {..} -instance Arbitrary (Derivation FilePath Text Text DerivationOutput DerivationInputs) where +instance Arbitrary + (Derivation + FilePath + Text + Text + (DerivationOutput FilePath Text) + (DerivationInputs FilePath Text) + ) where arbitrary = do outputs <- arbitrary inputs <- arbitrary @@ -70,7 +77,14 @@ instance Arbitrary (Derivation FilePath Text Text DerivationOutput DerivationInp env <- arbitrary pure Derivation {..} -property :: Derivation FilePath Text Text DerivationOutput DerivationInputs -> Bool +property + :: Derivation + FilePath + Text + Text + (DerivationOutput FilePath Text) + (DerivationInputs FilePath Text) + -> Bool property derivation0 = either == Right derivation0 where builder = Nix.Derivation.buildDerivation derivation0 diff --git a/overlay.nix b/overlay.nix index e19b142d..3a479158 100644 --- a/overlay.nix +++ b/overlay.nix @@ -21,6 +21,12 @@ in haskellLib.doJailbreak hsuper.dependent-sum-template_0_2_0_1; + nix-derivation = + lib.pipe + (hself.callCabal2nix "nix-derivation" ./nix-derivation {}) + [ + haskellLib.compose.buildFromSdist + ]; hnix-store-core = lib.pipe (hself.callCabal2nix "hnix-store-core" ./hnix-store-core {}) From b76952d2d54e3eb8283b6b4c73af958f22396b0d Mon Sep 17 00:00:00 2001 From: John Ericson Date: Thu, 31 Oct 2024 15:06:38 -0400 Subject: [PATCH 46/58] Add support for dynamic derivations --- hnix-store-core/src/System/Nix/Derivation.hs | 2 + hnix-store-core/src/System/Nix/DerivedPath.hs | 81 +++++++++++++++---- hnix-store-tests/hnix-store-tests.cabal | 1 + .../src/System/Nix/Arbitrary/Derivation.hs | 12 +++ .../src/System/Nix/Arbitrary/DerivedPath.hs | 5 +- nix-derivation/nix-derivation.cabal | 2 + nix-derivation/src/Nix/Derivation.hs | 1 + nix-derivation/src/Nix/Derivation/Builder.hs | 9 ++- nix-derivation/src/Nix/Derivation/Parser.hs | 8 +- nix-derivation/src/Nix/Derivation/Types.hs | 18 ++++- nix-derivation/tests/Property.hs | 7 +- 11 files changed, 120 insertions(+), 26 deletions(-) diff --git a/hnix-store-core/src/System/Nix/Derivation.hs b/hnix-store-core/src/System/Nix/Derivation.hs index ff9f7259..3fc4b738 100644 --- a/hnix-store-core/src/System/Nix/Derivation.hs +++ b/hnix-store-core/src/System/Nix/Derivation.hs @@ -6,6 +6,7 @@ module System.Nix.Derivation , Derivation(..) , DerivationOutput(..) , DerivationInputs(..) + , DerivedPathMap(..) ) where import Data.Attoparsec.Text.Lazy (Parser) @@ -16,6 +17,7 @@ import Nix.Derivation ( Derivation(..) , DerivationOutput(..) , DerivationInputs(..) + , DerivedPathMap(..) , parseDerivationOutputWith , parseDerivationInputsWith , buildDerivationOutputWith diff --git a/hnix-store-core/src/System/Nix/DerivedPath.hs b/hnix-store-core/src/System/Nix/DerivedPath.hs index 16c8f93f..bdd9850e 100644 --- a/hnix-store-core/src/System/Nix/DerivedPath.hs +++ b/hnix-store-core/src/System/Nix/DerivedPath.hs @@ -2,6 +2,7 @@ module System.Nix.DerivedPath ( OutputsSpec(..) + , SingleDerivedPath(..) , DerivedPath(..) , ParseOutputsError(..) , parseOutputsSpec @@ -30,11 +31,19 @@ data OutputsSpec = -- ^ Set of specific outputs deriving (Eq, Generic, Ord, Show) +data SingleDerivedPath = + SingleDerivedPath_Opaque StorePath + -- ^ Fully evaluated store path that can't be built + -- but can be fetched + | SingleDerivedPath_Built SingleDerivedPath OutputName + -- ^ Derivation path and the output built from it + deriving (Eq, Generic, Ord, Show) + data DerivedPath = DerivedPath_Opaque StorePath -- ^ Fully evaluated store path that can't be built -- but can be fetched - | DerivedPath_Built StorePath OutputsSpec + | DerivedPath_Built SingleDerivedPath OutputsSpec -- ^ Derivation path and the outputs built from it deriving (Eq, Generic, Ord, Show) @@ -45,15 +54,19 @@ data ParseOutputsError = | ParseOutputsError_NoPrefix StoreDir Text deriving (Eq, Ord, Show) +parseOutputName :: Text -> Either ParseOutputsError OutputName +parseOutputName = + ( Data.Bifunctor.first + ParseOutputsError_InvalidName + . System.Nix.OutputName.mkOutputName + ) + parseOutputsSpec :: Text -> Either ParseOutputsError OutputsSpec parseOutputsSpec t | t == "*" = Right OutputsSpec_All | otherwise = do names <- mapM - ( Data.Bifunctor.first - ParseOutputsError_InvalidName - . System.Nix.OutputName.mkOutputName - ) + parseOutputName (Data.Text.splitOn "," t) if null names then Left ParseOutputsError_NoNames @@ -69,6 +82,35 @@ outputsSpecToText = \case (Data.Set.toList ns) ) +parseSingleDerivedPath + :: StoreDir + -> Text + -> Either ParseOutputsError SingleDerivedPath +parseSingleDerivedPath root@(StoreDir sd) path = + let -- We need to do a bit more legwork for case + -- when StoreDir contains '!' + -- which is generated by its Arbitrary instance + textRoot = Data.Text.pack + $ Data.ByteString.Char8.unpack sd + + in case Data.Text.stripPrefix textRoot path of + Nothing -> Left $ ParseOutputsError_NoPrefix root path + Just woRoot -> + case Data.Text.breakOn "!" woRoot of + (pathNoPrefix, r) -> + if Data.Text.null r + then SingleDerivedPath_Opaque + <$> (convertError + $ System.Nix.StorePath.parsePathFromText + root + path + ) + else SingleDerivedPath_Built + <$> parseSingleDerivedPath + root + (textRoot <> pathNoPrefix) + <*> parseOutputName (Data.Text.drop (Data.Text.length "!") r) + parseDerivedPath :: StoreDir -> Text @@ -93,23 +135,30 @@ parseDerivedPath root@(StoreDir sd) path = path ) else DerivedPath_Built - <$> (convertError - $ System.Nix.StorePath.parsePathFromText - root - (textRoot <> pathNoPrefix) - ) + <$> parseSingleDerivedPath + root + (textRoot <> pathNoPrefix) <*> parseOutputsSpec (Data.Text.drop (Data.Text.length "!") r) - where - convertError - :: Either InvalidPathError a - -> Either ParseOutputsError a - convertError = Data.Bifunctor.first ParseOutputsError_InvalidPath + +convertError + :: Either InvalidPathError a + -> Either ParseOutputsError a +convertError = Data.Bifunctor.first ParseOutputsError_InvalidPath + +singleDerivedPathToText :: StoreDir -> SingleDerivedPath -> Text +singleDerivedPathToText root = \case + SingleDerivedPath_Opaque p -> + System.Nix.StorePath.storePathToText root p + SingleDerivedPath_Built p o -> + singleDerivedPathToText root p + <> "!" + <> System.Nix.OutputName.unOutputName o derivedPathToText :: StoreDir -> DerivedPath -> Text derivedPathToText root = \case DerivedPath_Opaque p -> System.Nix.StorePath.storePathToText root p DerivedPath_Built p os -> - System.Nix.StorePath.storePathToText root p + singleDerivedPathToText root p <> "!" <> outputsSpecToText os diff --git a/hnix-store-tests/hnix-store-tests.cabal b/hnix-store-tests/hnix-store-tests.cabal index 837da6b4..76a5cd2b 100644 --- a/hnix-store-tests/hnix-store-tests.cabal +++ b/hnix-store-tests/hnix-store-tests.cabal @@ -68,6 +68,7 @@ library , hspec , QuickCheck , text + , these , time , unordered-containers , vector diff --git a/hnix-store-tests/src/System/Nix/Arbitrary/Derivation.hs b/hnix-store-tests/src/System/Nix/Arbitrary/Derivation.hs index ce5aba4c..a57dc2ec 100644 --- a/hnix-store-tests/src/System/Nix/Arbitrary/Derivation.hs +++ b/hnix-store-tests/src/System/Nix/Arbitrary/Derivation.hs @@ -3,6 +3,7 @@ {-# OPTIONS_GHC -Wno-orphans #-} module System.Nix.Arbitrary.Derivation where +import Data.These import Data.Text (Text) import Data.Text.Arbitrary () import Data.Vector.Arbitrary () @@ -43,3 +44,14 @@ deriving via GenericArbitrary (DerivationOutput StorePath Text) deriving via GenericArbitrary (DerivationInputs StorePath Text) instance Arbitrary (DerivationInputs StorePath Text) + +deriving via GenericArbitrary (DerivedPathMap StorePath Text) + instance Arbitrary (DerivedPathMap StorePath Text) + +-- TODO this belongs elsewhere +deriving via GenericArbitrary (These a b) + instance ( Arg (These a b) a + , Arg (These a b) b + , Arbitrary a + , Arbitrary b + ) => Arbitrary (These a b) diff --git a/hnix-store-tests/src/System/Nix/Arbitrary/DerivedPath.hs b/hnix-store-tests/src/System/Nix/Arbitrary/DerivedPath.hs index 1a3c56dc..5cea4fb4 100644 --- a/hnix-store-tests/src/System/Nix/Arbitrary/DerivedPath.hs +++ b/hnix-store-tests/src/System/Nix/Arbitrary/DerivedPath.hs @@ -8,7 +8,7 @@ import Test.QuickCheck (Arbitrary(..), oneof) import Test.QuickCheck.Arbitrary.Generic (GenericArbitrary(..)) import System.Nix.Arbitrary.OutputName () import System.Nix.Arbitrary.StorePath () -import System.Nix.DerivedPath (DerivedPath, OutputsSpec(..)) +import System.Nix.DerivedPath (SingleDerivedPath, DerivedPath, OutputsSpec(..)) instance Arbitrary OutputsSpec where arbitrary = oneof @@ -18,5 +18,8 @@ instance Arbitrary OutputsSpec where <$> ((:) <$> arbitrary <*> arbitrary) ] +deriving via GenericArbitrary SingleDerivedPath + instance Arbitrary SingleDerivedPath + deriving via GenericArbitrary DerivedPath instance Arbitrary DerivedPath diff --git a/nix-derivation/nix-derivation.cabal b/nix-derivation/nix-derivation.cabal index 221ecdbd..a1699610 100644 --- a/nix-derivation/nix-derivation.cabal +++ b/nix-derivation/nix-derivation.cabal @@ -33,6 +33,7 @@ Library containers < 0.8 , deepseq >= 1.4.0.0 && < 1.6 , text >= 0.8.0.0 && < 2.2 , + these, vector < 0.14, filepath < 1.5 Exposed-Modules: @@ -79,6 +80,7 @@ Test-Suite property nix-derivation , QuickCheck < 2.16, text , + these , vector < 0.14, filepath < 1.5 diff --git a/nix-derivation/src/Nix/Derivation.hs b/nix-derivation/src/Nix/Derivation.hs index c3f64020..872d181d 100644 --- a/nix-derivation/src/Nix/Derivation.hs +++ b/nix-derivation/src/Nix/Derivation.hs @@ -81,6 +81,7 @@ module Nix.Derivation Derivation(..) , DerivationOutput(..) , DerivationInputs(..) + , DerivedPathMap(..) -- * Parse derivations , parseDerivation diff --git a/nix-derivation/src/Nix/Derivation/Builder.hs b/nix-derivation/src/Nix/Derivation/Builder.hs index 4430be89..494568cf 100644 --- a/nix-derivation/src/Nix/Derivation/Builder.hs +++ b/nix-derivation/src/Nix/Derivation/Builder.hs @@ -13,14 +13,17 @@ module Nix.Derivation.Builder ) where import Data.Map (Map) +import Data.Maybe (fromMaybe) import Data.Set (Set) import Data.Text (Text) import Data.Text.Lazy.Builder (Builder) +import Data.These.Combinators (justThis) import Data.Vector (Vector) import Nix.Derivation.Types ( Derivation(..) - , DerivationInputs(..) , DerivationOutput(..) + , DerivationInputs(..) + , DerivedPathMap(..) ) import qualified Data.Map @@ -121,7 +124,7 @@ buildDerivationInputsWith -> DerivationInputs fp outputName -> Builder buildDerivationInputsWith filepath outputName (DerivationInputs {..}) = - mapOf keyValue drvs + mapOf keyValue (unDerivedPathMap drvs) <> "," <> setOf filepath srcs where @@ -129,7 +132,7 @@ buildDerivationInputsWith filepath outputName (DerivationInputs {..}) = "(" <> filepath key <> "," - <> setOf outputName value + <> setOf outputName (fromMaybe Data.Set.empty $ justThis value) <> ")" mapOf :: ((k, v) -> Builder) -> Map k v -> Builder diff --git a/nix-derivation/src/Nix/Derivation/Parser.hs b/nix-derivation/src/Nix/Derivation/Parser.hs index 6dda3fb3..c5237ac1 100644 --- a/nix-derivation/src/Nix/Derivation/Parser.hs +++ b/nix-derivation/src/Nix/Derivation/Parser.hs @@ -16,14 +16,16 @@ module Nix.Derivation.Parser ) where import Data.Attoparsec.Text.Lazy (Parser) +import Data.These (These(This)) import Data.Map (Map) import Data.Set (Set) import Data.Text (Text) import Data.Vector (Vector) import Nix.Derivation.Types ( Derivation(..) - , DerivationInputs(..) , DerivationOutput(..) + , DerivedPathMap(..) + , DerivationInputs(..) ) import qualified Data.Attoparsec.Text @@ -148,8 +150,8 @@ parseDerivationInputsWith filepath outputName = do "," value <- setOf outputName ")" - pure (key, value) - drvs <- mapOf keyValue + pure (key, This value) + drvs <- DerivedPathMap <$> mapOf keyValue "," diff --git a/nix-derivation/src/Nix/Derivation/Types.hs b/nix-derivation/src/Nix/Derivation/Types.hs index b5048bc2..f882be6e 100644 --- a/nix-derivation/src/Nix/Derivation/Types.hs +++ b/nix-derivation/src/Nix/Derivation/Types.hs @@ -7,13 +7,15 @@ module Nix.Derivation.Types ( -- * Types Derivation(..) - , DerivationInputs(..) , DerivationOutput(..) + , DerivedPathMap(..) + , DerivationInputs(..) ) where import Control.DeepSeq (NFData) import Data.Map (Map) import Data.Set (Set) +import Data.These import Data.Vector (Vector) import GHC.Generics (Generic) @@ -43,7 +45,7 @@ instance ( NFData fp => NFData (Derivation fp txt outputName drvOutput drvInputs) data DerivationInputs fp drvOutput = DerivationInputs - { drvs :: Map fp (Set drvOutput) + { drvs :: DerivedPathMap fp drvOutput -- ^ Inputs that are derivations where keys specify derivation paths and -- values specify which output names are used by this derivation , srcs :: Set fp @@ -52,6 +54,18 @@ data DerivationInputs fp drvOutput = DerivationInputs instance (NFData a, NFData b) => NFData (DerivationInputs a b) +-- | A recursive map to handle dependencies on dynamic derivations in +-- addition to static ones +newtype DerivedPathMap fp drvOutput = DerivedPathMap + { unDerivedPathMap :: Map + fp + (These + (Set drvOutput) + (DerivedPathMap fp drvOutput)) + } deriving (Eq, Generic, Ord, Show) + +instance (NFData a, NFData b) => NFData (DerivedPathMap a b) + -- | An output of a Nix derivation data DerivationOutput fp txt = InputAddressedDerivationOutput diff --git a/nix-derivation/tests/Property.hs b/nix-derivation/tests/Property.hs index dff059c9..5bb47232 100644 --- a/nix-derivation/tests/Property.hs +++ b/nix-derivation/tests/Property.hs @@ -6,13 +6,15 @@ module Main where +import Data.These import Data.Text (Text) import Data.Vector (Vector) import System.FilePath import Nix.Derivation ( Derivation(..) - , DerivationInputs(..) , DerivationOutput(..) + , DerivationInputs(..) + , DerivedPathMap(..) ) import Prelude hiding (FilePath, either) import Test.QuickCheck (Arbitrary(..), Gen, oneof) @@ -60,6 +62,9 @@ instance Arbitrary (DerivationInputs FilePath Text) where srcs <- arbitrary pure DerivationInputs {..} +instance Arbitrary (DerivedPathMap FilePath Text) where + arbitrary = DerivedPathMap . fmap This <$> arbitrary + instance Arbitrary (Derivation FilePath From 61dc13501bdce15d3f23749b2a4533e2a81c609e Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 5 Nov 2024 11:20:28 -0500 Subject: [PATCH 47/58] Progress integrating the derivation type - The type is now in `hnix-store-core` - The serialization logic (the rest of `nix-derivation`) is now called `hnix-store-aterm` Most type errors are fixed. --- cabal.project | 2 +- cabal.project.local.ci | 2 +- default.nix | 2 +- {nix-derivation => hnix-store-aterm}/LICENSE | 0 .../README.md | 8 +- {nix-derivation => hnix-store-aterm}/Setup.hs | 0 .../bench/Main.hs | 0 .../hnix-store-aterm.cabal | 17 +- .../pretty-derivation/Main.hs | 0 .../src/Nix/Derivation.hs | 0 .../src/Nix/Derivation/Builder.hs | 0 .../src/Nix/Derivation/Parser.hs | 0 .../tests/Derivation.hs | 1 - hnix-store-aterm/tests/DerivationSpec.hs | 27 ++ .../tests/Example.hs | 0 .../tests/Property.hs | 0 .../tests/example0.drv | 0 .../tests/example1.drv | 0 hnix-store-core/hnix-store-core.cabal | 7 +- .../src/System/Nix/ContentAddress.hs | 3 + hnix-store-core/src/System/Nix/Derivation.hs | 252 +++++++++++++----- .../src/System/Nix/Derivation/Aterm.hs | 75 ++++++ hnix-store-core/src/System/Nix/DerivedPath.hs | 32 +-- hnix-store-core/src/System/Nix/Hash.hs | 12 + hnix-store-core/src/System/Nix/OutputName.hs | 12 +- hnix-store-core/src/System/Nix/StorePath.hs | 7 + hnix-store-json/src/System/Nix/JSON.hs | 6 +- .../src/System/Nix/Store/Remote/Serializer.hs | 13 +- .../Nix/Store/Remote/Types/StoreRequest.hs | 9 +- hnix-store-tests/hnix-store-tests.cabal | 1 + .../src/System/Nix/Arbitrary/Derivation.hs | 61 ++--- hnix-store-tests/tests/DerivationSpec.hs | 30 +-- hnix-store-tests/tests/DerivedPathSpec.hs | 6 + hnix-store-tests/tests/RealisationSpec.hs | 3 +- nix-derivation/src/Nix/Derivation/Types.hs | 89 ------- overlay.nix | 12 +- 36 files changed, 412 insertions(+), 277 deletions(-) rename {nix-derivation => hnix-store-aterm}/LICENSE (100%) rename {nix-derivation => hnix-store-aterm}/README.md (96%) rename {nix-derivation => hnix-store-aterm}/Setup.hs (100%) rename {nix-derivation => hnix-store-aterm}/bench/Main.hs (100%) rename nix-derivation/nix-derivation.cabal => hnix-store-aterm/hnix-store-aterm.cabal (88%) rename {nix-derivation => hnix-store-aterm}/pretty-derivation/Main.hs (100%) rename {nix-derivation => hnix-store-aterm}/src/Nix/Derivation.hs (100%) rename {nix-derivation => hnix-store-aterm}/src/Nix/Derivation/Builder.hs (100%) rename {nix-derivation => hnix-store-aterm}/src/Nix/Derivation/Parser.hs (100%) rename {hnix-store-core => hnix-store-aterm}/tests/Derivation.hs (99%) create mode 100644 hnix-store-aterm/tests/DerivationSpec.hs rename {nix-derivation => hnix-store-aterm}/tests/Example.hs (100%) rename {nix-derivation => hnix-store-aterm}/tests/Property.hs (100%) rename {nix-derivation => hnix-store-aterm}/tests/example0.drv (100%) rename {nix-derivation => hnix-store-aterm}/tests/example1.drv (100%) create mode 100644 hnix-store-core/src/System/Nix/Derivation/Aterm.hs delete mode 100644 nix-derivation/src/Nix/Derivation/Types.hs diff --git a/cabal.project b/cabal.project index 04971545..fa5275b6 100644 --- a/cabal.project +++ b/cabal.project @@ -2,7 +2,7 @@ tests: true benchmarks: true packages: - ./nix-derivation/nix-derivation.cabal + ./hnix-store-aterm/hnix-store-aterm.cabal ./hnix-store-core/hnix-store-core.cabal ./hnix-store-db/hnix-store-db.cabal ./hnix-store-json/hnix-store-json.cabal diff --git a/cabal.project.local.ci b/cabal.project.local.ci index 3c2afadb..58530e17 100644 --- a/cabal.project.local.ci +++ b/cabal.project.local.ci @@ -1,4 +1,4 @@ -package nix-derivation +package hnix-store-aterm ghc-options: -Wunused-packages -Wall -Werror package hnix-store-core diff --git a/default.nix b/default.nix index 178983fa..a198197e 100644 --- a/default.nix +++ b/default.nix @@ -20,7 +20,7 @@ let haskellPackages = packageSet.override overrideHaskellPackages; in { inherit (haskellPackages) - nix-derivation + hnix-store-aterm hnix-store-core hnix-store-db hnix-store-json diff --git a/nix-derivation/LICENSE b/hnix-store-aterm/LICENSE similarity index 100% rename from nix-derivation/LICENSE rename to hnix-store-aterm/LICENSE diff --git a/nix-derivation/README.md b/hnix-store-aterm/README.md similarity index 96% rename from nix-derivation/README.md rename to hnix-store-aterm/README.md index 3657dd75..eb5564b7 100644 --- a/nix-derivation/README.md +++ b/hnix-store-aterm/README.md @@ -1,8 +1,8 @@ -# `nix-derivation` +# `hnix-store-aterm` [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/Gabriella439/Haskell-Nix-Derivation-Library/ci.yaml?branch=main)](https://github.com/Gabriella439/Haskell-Nix-Derivation-Library/actions/workflows/ci.yaml) -[![Hackage version](https://img.shields.io/hackage/v/nix-derivation.svg?color=success)](https://hackage.haskell.org/package/nix-derivation) -[![Dependencies](https://img.shields.io/hackage-deps/v/nix-derivation?label=Dependencies)](https://packdeps.haskellers.com/feed?needle=nix-derivation) +[![Hackage version](https://img.shields.io/hackage/v/hnix-store-aterm.svg?color=success)](https://hackage.haskell.org/package/hnix-store-aterm) +[![Dependencies](https://img.shields.io/hackage-deps/v/hnix-store-aterm?label=Dependencies)](https://packdeps.haskellers.com/feed?needle=hnix-store-aterm) Use this package to parse and render Nix derivations such as those stored in `/nix/store/*.drv` files. For example, if you had the following derivation @@ -182,7 +182,7 @@ Derivation With Nix: ``` -$ nix-env -iA nixpkgs.haskellPackages.nix-derivation +$ nix-env -iA nixpkgs.haskellPackages.hnix-store-aterm ``` ## Development status diff --git a/nix-derivation/Setup.hs b/hnix-store-aterm/Setup.hs similarity index 100% rename from nix-derivation/Setup.hs rename to hnix-store-aterm/Setup.hs diff --git a/nix-derivation/bench/Main.hs b/hnix-store-aterm/bench/Main.hs similarity index 100% rename from nix-derivation/bench/Main.hs rename to hnix-store-aterm/bench/Main.hs diff --git a/nix-derivation/nix-derivation.cabal b/hnix-store-aterm/hnix-store-aterm.cabal similarity index 88% rename from nix-derivation/nix-derivation.cabal rename to hnix-store-aterm/hnix-store-aterm.cabal index a1699610..1b2e4d4a 100644 --- a/nix-derivation/nix-derivation.cabal +++ b/hnix-store-aterm/hnix-store-aterm.cabal @@ -1,4 +1,4 @@ -Name: nix-derivation +Name: hnix-store-aterm Version: 1.1.3 Cabal-Version: >=1.10 Build-Type: Simple @@ -11,7 +11,12 @@ Maintainer: GenuineGabriella@gmail.com Bug-Reports: https://github.com/Gabriella439/Haskell-Nix-Derivation-Library/issues Synopsis: Parse and render *.drv files Description: - Use this package to parse and render Nix derivation files (i.e. *.drv files) + Use this package to parse and render Nix derivation files (i.e. *.drv files), + i.e. Nix Derivations in "ATerm" format. + . + See + https://nix.dev/manual/nix/latest/protocols/derivation-aterm.html + for more details about this format. . This package also provides a @pretty-derivation@ executable which reads a derivation on standard input and outputs the pretty-printed Haskell @@ -52,7 +57,7 @@ Executable pretty-derivation attoparsec >= 0.12.0.0 && < 0.15, pretty-show >= 1.6.11 && < 1.11, text , - nix-derivation + hnix-store-aterm GHC-Options: -Wall Main-Is: Main.hs @@ -65,7 +70,7 @@ Test-Suite example Build-Depends: base >= 4.6.0.0 && < 5 , attoparsec >= 0.12.0.0 && < 0.15, - nix-derivation , + hnix-store-aterm , text Test-Suite property @@ -77,7 +82,7 @@ Test-Suite property Build-Depends: base >= 4.6.0.0 && < 5 , attoparsec >= 0.12.0.0 && < 0.15, - nix-derivation , + hnix-store-aterm , QuickCheck < 2.16, text , these , @@ -95,5 +100,5 @@ Benchmark benchmark base >= 4.6.0.0 && < 5 , attoparsec >= 0.12.0.0 && < 0.15, criterion >= 1.1.4.0 && < 1.7 , - nix-derivation , + hnix-store-aterm , text diff --git a/nix-derivation/pretty-derivation/Main.hs b/hnix-store-aterm/pretty-derivation/Main.hs similarity index 100% rename from nix-derivation/pretty-derivation/Main.hs rename to hnix-store-aterm/pretty-derivation/Main.hs diff --git a/nix-derivation/src/Nix/Derivation.hs b/hnix-store-aterm/src/Nix/Derivation.hs similarity index 100% rename from nix-derivation/src/Nix/Derivation.hs rename to hnix-store-aterm/src/Nix/Derivation.hs diff --git a/nix-derivation/src/Nix/Derivation/Builder.hs b/hnix-store-aterm/src/Nix/Derivation/Builder.hs similarity index 100% rename from nix-derivation/src/Nix/Derivation/Builder.hs rename to hnix-store-aterm/src/Nix/Derivation/Builder.hs diff --git a/nix-derivation/src/Nix/Derivation/Parser.hs b/hnix-store-aterm/src/Nix/Derivation/Parser.hs similarity index 100% rename from nix-derivation/src/Nix/Derivation/Parser.hs rename to hnix-store-aterm/src/Nix/Derivation/Parser.hs diff --git a/hnix-store-core/tests/Derivation.hs b/hnix-store-aterm/tests/Derivation.hs similarity index 99% rename from hnix-store-core/tests/Derivation.hs rename to hnix-store-aterm/tests/Derivation.hs index 2a178e39..aa8010dd 100644 --- a/hnix-store-core/tests/Derivation.hs +++ b/hnix-store-aterm/tests/Derivation.hs @@ -1,4 +1,3 @@ - module Derivation where import Test.Tasty (TestTree, testGroup) diff --git a/hnix-store-aterm/tests/DerivationSpec.hs b/hnix-store-aterm/tests/DerivationSpec.hs new file mode 100644 index 00000000..39e90fed --- /dev/null +++ b/hnix-store-aterm/tests/DerivationSpec.hs @@ -0,0 +1,27 @@ +module DerivationSpec where + +import Test.Hspec (Spec, describe) +import Test.Hspec.QuickCheck (xprop) +import Test.Hspec.Nix (roundtrips) + +import System.Nix.Arbitrary () +import System.Nix.Derivation (parseDerivation, buildDerivation) + +import qualified Data.Attoparsec.Text +import qualified Data.Text.Lazy +import qualified Data.Text.Lazy.Builder + +-- TODO(srk): this won't roundtrip as Arbitrary Text +-- contains wild stuff like control characters and UTF8 sequences. +-- Either fix in hnix-store-aterm or use wrapper type +-- (but we use Nix.Derivation.textParser so we need Text for now) +spec :: Spec +spec = do + describe "Derivation" $ do + xprop "roundtrips via Text" $ \sd -> + roundtrips + ( Data.Text.Lazy.toStrict + . Data.Text.Lazy.Builder.toLazyText + . buildDerivation sd + ) + (Data.Attoparsec.Text.parseOnly (parseDerivation sd)) diff --git a/nix-derivation/tests/Example.hs b/hnix-store-aterm/tests/Example.hs similarity index 100% rename from nix-derivation/tests/Example.hs rename to hnix-store-aterm/tests/Example.hs diff --git a/nix-derivation/tests/Property.hs b/hnix-store-aterm/tests/Property.hs similarity index 100% rename from nix-derivation/tests/Property.hs rename to hnix-store-aterm/tests/Property.hs diff --git a/nix-derivation/tests/example0.drv b/hnix-store-aterm/tests/example0.drv similarity index 100% rename from nix-derivation/tests/example0.drv rename to hnix-store-aterm/tests/example0.drv diff --git a/nix-derivation/tests/example1.drv b/hnix-store-aterm/tests/example1.drv similarity index 100% rename from nix-derivation/tests/example1.drv rename to hnix-store-aterm/tests/example1.drv diff --git a/hnix-store-core/hnix-store-core.cabal b/hnix-store-core/hnix-store-core.cabal index 3fd12e39..925c7454 100644 --- a/hnix-store-core/hnix-store-core.cabal +++ b/hnix-store-core/hnix-store-core.cabal @@ -79,18 +79,20 @@ library , base16-bytestring >= 1.0 , base64-bytestring >= 1.2.1 , bytestring - , containers , constraints-extras + , containers , crypton , data-default-class + , deepseq , dependent-sum > 0.7 , dependent-sum-template >= 0.2.0.1 && < 0.3 , filepath , hashable -- Required for crypton low-level type convertion , memory - , nix-derivation >= 1.1.1 && <2 + , monoidal-containers , some > 1.0.5 && < 2 + , these , time , text , unordered-containers @@ -102,7 +104,6 @@ test-suite core type: exitcode-stdio-1.0 main-is: Driver.hs other-modules: - Derivation Fingerprint Hash Signature diff --git a/hnix-store-core/src/System/Nix/ContentAddress.hs b/hnix-store-core/src/System/Nix/ContentAddress.hs index 33541ee2..c5875401 100644 --- a/hnix-store-core/src/System/Nix/ContentAddress.hs +++ b/hnix-store-core/src/System/Nix/ContentAddress.hs @@ -10,6 +10,7 @@ module System.Nix.ContentAddress ( ) where import Control.Applicative +import Control.DeepSeq (NFData) import Crypto.Hash (Digest) import Data.Attoparsec.Text (Parser) import Data.Dependent.Sum (DSum) @@ -32,6 +33,8 @@ data ContentAddressMethod -- file contents. deriving (Eq, Generic, Ord, Show) +instance NFData ContentAddressMethod + -- | An address for a content-addressable store path, i.e. one whose -- store path hash is purely a function of its contents (as opposed to -- paths that are derivation outputs, whose hashes are a function of diff --git a/hnix-store-core/src/System/Nix/Derivation.hs b/hnix-store-core/src/System/Nix/Derivation.hs index 3fc4b738..dd9c4439 100644 --- a/hnix-store-core/src/System/Nix/Derivation.hs +++ b/hnix-store-core/src/System/Nix/Derivation.hs @@ -1,75 +1,181 @@ +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE KindSignatures #-} +{-# LANGUAGE QuantifiedConstraints #-} + +-- | Shared types + module System.Nix.Derivation - ( parseDerivation - , buildDerivation - , Derivation' - -- Re-exports - , Derivation(..) - , DerivationOutput(..) - , DerivationInputs(..) - , DerivedPathMap(..) - ) where - -import Data.Attoparsec.Text.Lazy (Parser) + ( -- * Types + Derivation'(..) + , Derivation + , BasicDerivation + + , DerivationOutput(..) + + , DerivationInputs(..) + , derivationInputsFromSingleDerivedPath + , derivationInputsToDerivedPaths + + , DerivedPathMap(..) + , ChildNode(..) + , derivedPathMapFromSingleDerivedPathBuilt + , derivedPathMapToSet + ) where + +import Control.DeepSeq (NFData(..)) +import Crypto.Hash (Digest) +import Data.Dependent.Sum (DSum(..)) +import Data.Map (Map) +import Data.Map.Monoidal (MonoidalMap) +import qualified Data.Map.Monoidal +import Data.Set (Set) +import qualified Data.Set +import Data.Some (Some(..)) +import Data.GADT.DeepSeq (GNFData(..)) import Data.Text (Text) -import Data.Text.Lazy.Builder (Builder) - -import Nix.Derivation - ( Derivation(..) - , DerivationOutput(..) - , DerivationInputs(..) - , DerivedPathMap(..) - , parseDerivationOutputWith - , parseDerivationInputsWith - , buildDerivationOutputWith - , buildDerivationInputsWith - ) -import System.Nix.StorePath (StoreDir, StorePath) - -import qualified Data.Attoparsec.Text.Lazy -import qualified Data.Text -import qualified Data.Text.Lazy -import qualified Data.Text.Lazy.Builder - -import qualified Nix.Derivation -import qualified System.Nix.StorePath - -type Derivation' = Derivation - StorePath - Text - Text - (DerivationOutput StorePath Text) - (DerivationInputs StorePath Text) - -parseDerivation - :: StoreDir - -> Parser (Derivation') -parseDerivation expectedRoot = - Nix.Derivation.parseDerivationWith - Nix.Derivation.textParser - Nix.Derivation.textParser - (parseDerivationOutputWith pathParser Nix.Derivation.textParser) - (parseDerivationInputsWith pathParser Nix.Derivation.textParser) - where - pathParser = do - text <- Nix.Derivation.textParser - case Data.Attoparsec.Text.Lazy.parseOnly - (System.Nix.StorePath.pathParser expectedRoot) - (Data.Text.Lazy.fromStrict text) - of - Right p -> pure p - Left e -> fail e - -buildDerivation - :: StoreDir - -> Derivation' - -> Builder -buildDerivation storeDir = - Nix.Derivation.buildDerivationWith - string - string - (buildDerivationOutputWith path string emptyString) - (buildDerivationInputsWith path string) - where - emptyString = string Data.Text.empty - path = string . System.Nix.StorePath.storePathToText storeDir - string = Data.Text.Lazy.Builder.fromText . Data.Text.pack . show +import Data.These (These(..), fromThese) +import Data.Vector (Vector) +import GHC.Generics (Generic) + +import System.Nix.ContentAddress (ContentAddressMethod) +import System.Nix.Hash (HashAlgo) +import System.Nix.DerivedPath (SingleDerivedPath(..)) +import System.Nix.StorePath (StorePath) +import System.Nix.OutputName (OutputName) + +data Derivation' inputs output = Derivation + { outputs :: output + -- ^ Outputs produced by this derivation where keys are output names + , inputs :: inputs + -- ^ Inputs (sources and derivations) + , platform :: Text + -- ^ Platform required for this derivation + , builder :: Text + -- ^ Code to build the derivation, which can be a path or a builtin function + , args :: Vector Text + -- ^ Arguments passed to the executable used to build to derivation + , env :: Map Text Text + -- ^ Environment variables provided to the executable used to build the + -- derivation + } deriving (Eq, Generic, Ord, Show) + +instance (NFData inputs, NFData output) => NFData (Derivation' inputs output) + +-- | A regular Nix derivation +type Derivation = Derivation' DerivationInputs DerivationOutput + +-- | A Nix derivation that only depends on other store objects directly, +-- not (the outputs of) other derivations +type BasicDerivation = Derivation' (Set StorePath) DerivationOutput + +---------------- + +data DerivationInputs = DerivationInputs + { srcs :: Set StorePath + -- ^ Inputs that are sources + , drvs :: DerivedPathMap + -- ^ Inputs that are derivations where keys specify derivation paths and + -- values specify which output names are used by this derivation + } deriving (Eq, Generic, Ord, Show) + +instance NFData DerivationInputs + +instance Semigroup DerivationInputs where + DerivationInputs x0 x1 <> DerivationInputs y0 y1 = DerivationInputs + (x0 <> y0) + (x1 <> y1) + +instance Monoid DerivationInputs where + mempty = DerivationInputs mempty mempty + +derivationInputsFromSingleDerivedPath :: SingleDerivedPath -> DerivationInputs +derivationInputsFromSingleDerivedPath = \case + SingleDerivedPath_Opaque storePath -> DerivationInputs + { srcs = Data.Set.singleton storePath + , drvs = mempty + } + SingleDerivedPath_Built drvDPath outputName -> DerivationInputs + { srcs = mempty + , drvs = derivedPathMapFromSingleDerivedPathBuilt drvDPath outputName + } + +derivationInputsToDerivedPaths :: DerivationInputs -> Set SingleDerivedPath +derivationInputsToDerivedPaths inputs = + Data.Set.mapMonotonic SingleDerivedPath_Opaque (srcs inputs) + <> + derivedPathMapToSet (drvs inputs) + +-- | A recursive map to handle dependencies on dynamic derivations in +-- addition to static ones +newtype DerivedPathMap = DerivedPathMap + { unDerivedPathMap :: MonoidalMap StorePath ChildNode + } deriving (Eq, Generic, Ord, Show) + deriving newtype (Semigroup, Monoid) + +instance NFData DerivedPathMap + +newtype ChildNode = ChildNode + { unChildNode :: These (Set OutputName) (MonoidalMap OutputName ChildNode) + } deriving (Eq, Generic, Ord, Show) + deriving newtype (Semigroup) + +instance NFData ChildNode + +derivedPathMapFromSingleDerivedPathBuilt :: SingleDerivedPath -> OutputName -> DerivedPathMap +derivedPathMapFromSingleDerivedPathBuilt drvDPath outputName0 = go drvDPath $ ChildNode $ This $ Data.Set.singleton outputName0 + where + go :: SingleDerivedPath -> ChildNode -> DerivedPathMap + go d child = case d of + SingleDerivedPath_Opaque drvPath -> DerivedPathMap $ Data.Map.Monoidal.singleton drvPath child + SingleDerivedPath_Built nestedPath nestedOutputName -> go nestedPath $ ChildNode $ That $ Data.Map.Monoidal.singleton nestedOutputName child + +derivedPathMapToSet :: DerivedPathMap -> Set SingleDerivedPath +derivedPathMapToSet (DerivedPathMap m) = Data.Set.unions $ fmap + (\(p, c) -> go (SingleDerivedPath_Opaque p) c) + (Data.Map.Monoidal.toList m) + where + go :: SingleDerivedPath -> ChildNode -> Set SingleDerivedPath + go accum (ChildNode child) = + Data.Set.mapMonotonic (SingleDerivedPath_Built accum) shallows + <> + Data.Set.unions (fmap + (\(outputName, child') -> go (SingleDerivedPath_Built accum outputName) child') + $ Data.Map.Monoidal.toList deeps) + where (shallows, deeps) = fromThese mempty mempty child + +---------------- + +-- | An output of a Nix derivation +data DerivationOutput + = InputAddressedDerivationOutput + { path :: StorePath + -- ^ Path where the output will be saved + } + | FixedDerivationOutput + { method :: ContentAddressMethod + -- ^ How this output is serialized into a hash / what sort of CA + -- store path is used. + , hash :: DSum HashAlgo Digest + -- ^ Expected hash of this output + } + | ContentAddressedDerivationOutput + { method :: ContentAddressMethod + -- ^ How this output is serialized into a hash / what sort of CA + -- store path is used. + , hashAlgo :: Some HashAlgo + -- ^ What sort of hash function is used with the above + -- content-addressing method to produce the (content-addressed) + -- store path we'll use for the output. + } + deriving (Eq, Generic, Ord, Show) + +instance NFData DerivationOutput + +-- | TODO this should go in `dependent-sum` +instance (GNFData k, GNFData v) => NFData (DSum k v) where + rnf (x :=> y) = grnf x `seq` grnf y +-- | TODO this needs a home +instance GNFData Digest where + grnf = rnf diff --git a/hnix-store-core/src/System/Nix/Derivation/Aterm.hs b/hnix-store-core/src/System/Nix/Derivation/Aterm.hs new file mode 100644 index 00000000..3fc4b738 --- /dev/null +++ b/hnix-store-core/src/System/Nix/Derivation/Aterm.hs @@ -0,0 +1,75 @@ +module System.Nix.Derivation + ( parseDerivation + , buildDerivation + , Derivation' + -- Re-exports + , Derivation(..) + , DerivationOutput(..) + , DerivationInputs(..) + , DerivedPathMap(..) + ) where + +import Data.Attoparsec.Text.Lazy (Parser) +import Data.Text (Text) +import Data.Text.Lazy.Builder (Builder) + +import Nix.Derivation + ( Derivation(..) + , DerivationOutput(..) + , DerivationInputs(..) + , DerivedPathMap(..) + , parseDerivationOutputWith + , parseDerivationInputsWith + , buildDerivationOutputWith + , buildDerivationInputsWith + ) +import System.Nix.StorePath (StoreDir, StorePath) + +import qualified Data.Attoparsec.Text.Lazy +import qualified Data.Text +import qualified Data.Text.Lazy +import qualified Data.Text.Lazy.Builder + +import qualified Nix.Derivation +import qualified System.Nix.StorePath + +type Derivation' = Derivation + StorePath + Text + Text + (DerivationOutput StorePath Text) + (DerivationInputs StorePath Text) + +parseDerivation + :: StoreDir + -> Parser (Derivation') +parseDerivation expectedRoot = + Nix.Derivation.parseDerivationWith + Nix.Derivation.textParser + Nix.Derivation.textParser + (parseDerivationOutputWith pathParser Nix.Derivation.textParser) + (parseDerivationInputsWith pathParser Nix.Derivation.textParser) + where + pathParser = do + text <- Nix.Derivation.textParser + case Data.Attoparsec.Text.Lazy.parseOnly + (System.Nix.StorePath.pathParser expectedRoot) + (Data.Text.Lazy.fromStrict text) + of + Right p -> pure p + Left e -> fail e + +buildDerivation + :: StoreDir + -> Derivation' + -> Builder +buildDerivation storeDir = + Nix.Derivation.buildDerivationWith + string + string + (buildDerivationOutputWith path string emptyString) + (buildDerivationInputsWith path string) + where + emptyString = string Data.Text.empty + path = string . System.Nix.StorePath.storePathToText storeDir + string = Data.Text.Lazy.Builder.fromText . Data.Text.pack . show diff --git a/hnix-store-core/src/System/Nix/DerivedPath.hs b/hnix-store-core/src/System/Nix/DerivedPath.hs index bdd9850e..a6d88b82 100644 --- a/hnix-store-core/src/System/Nix/DerivedPath.hs +++ b/hnix-store-core/src/System/Nix/DerivedPath.hs @@ -3,6 +3,8 @@ module System.Nix.DerivedPath ( OutputsSpec(..) , SingleDerivedPath(..) + , parseSingleDerivedPath + , singleDerivedPathToText , DerivedPath(..) , ParseOutputsError(..) , parseOutputsSpec @@ -20,6 +22,7 @@ import System.Nix.StorePath (StoreDir(..), StorePath, InvalidPathError) import qualified Data.Bifunctor import qualified Data.ByteString.Char8 import qualified Data.Set +import qualified Data.List import qualified Data.Text import qualified System.Nix.OutputName import qualified System.Nix.StorePath @@ -78,7 +81,7 @@ outputsSpecToText = \case OutputsSpec_Names ns -> Data.Text.intercalate "," - (fmap System.Nix.OutputName.unOutputName + (fmap (System.Nix.StorePath.unStorePathName . System.Nix.OutputName.unOutputName) (Data.Set.toList ns) ) @@ -96,20 +99,17 @@ parseSingleDerivedPath root@(StoreDir sd) path = in case Data.Text.stripPrefix textRoot path of Nothing -> Left $ ParseOutputsError_NoPrefix root path Just woRoot -> - case Data.Text.breakOn "!" woRoot of - (pathNoPrefix, r) -> - if Data.Text.null r - then SingleDerivedPath_Opaque + case Data.Text.splitOn "!" woRoot of + [] -> error "internal error, this function should return NonEmpty" + (pathNoPrefix : outputs) -> Data.List.foldl' + (liftA2 SingleDerivedPath_Built) + (SingleDerivedPath_Opaque <$> (convertError $ System.Nix.StorePath.parsePathFromText - root - path - ) - else SingleDerivedPath_Built - <$> parseSingleDerivedPath root (textRoot <> pathNoPrefix) - <*> parseOutputName (Data.Text.drop (Data.Text.length "!") r) + )) + (parseOutputName <$> outputs) parseDerivedPath :: StoreDir @@ -125,8 +125,8 @@ parseDerivedPath root@(StoreDir sd) path = in case Data.Text.stripPrefix textRoot path of Nothing -> Left $ ParseOutputsError_NoPrefix root path Just woRoot -> - case Data.Text.breakOn "!" woRoot of - (pathNoPrefix, r) -> + case Data.Text.breakOnEnd "!" woRoot of + (r, suffix) -> if Data.Text.null r then DerivedPath_Opaque <$> (convertError @@ -137,8 +137,8 @@ parseDerivedPath root@(StoreDir sd) path = else DerivedPath_Built <$> parseSingleDerivedPath root - (textRoot <> pathNoPrefix) - <*> parseOutputsSpec (Data.Text.drop (Data.Text.length "!") r) + (textRoot <> Data.Text.dropEnd (Data.Text.length "!") r) + <*> parseOutputsSpec suffix convertError :: Either InvalidPathError a @@ -152,7 +152,7 @@ singleDerivedPathToText root = \case SingleDerivedPath_Built p o -> singleDerivedPathToText root p <> "!" - <> System.Nix.OutputName.unOutputName o + <> System.Nix.StorePath.unStorePathName (System.Nix.OutputName.unOutputName o) derivedPathToText :: StoreDir -> DerivedPath -> Text derivedPathToText root = \case diff --git a/hnix-store-core/src/System/Nix/Hash.hs b/hnix-store-core/src/System/Nix/Hash.hs index 79fb7fd6..0d91883f 100644 --- a/hnix-store-core/src/System/Nix/Hash.hs +++ b/hnix-store-core/src/System/Nix/Hash.hs @@ -25,12 +25,14 @@ module System.Nix.Hash , digestBuilder ) where +import Control.DeepSeq (NFData(..)) import Crypto.Hash (Digest, HashAlgorithm, MD5(..), SHA1(..), SHA256(..), SHA512(..)) import Data.ByteString (ByteString) import Data.Constraint.Extras (Has(has)) import Data.Constraint.Extras.TH (deriveArgDict) import Data.Dependent.Sum (DSum((:=>))) import Data.GADT.Compare.TH (deriveGEq, deriveGCompare) +import Data.GADT.DeepSeq (GNFData(..)) import Data.GADT.Show.TH (deriveGShow) import Data.Kind (Type) import Data.Some (Some(Some)) @@ -73,6 +75,16 @@ deriveGCompare ''HashAlgo deriveGShow ''HashAlgo deriveArgDict ''HashAlgo +instance NFData (HashAlgo a) where + rnf = \case + HashAlgo_MD5 -> () + HashAlgo_SHA1 -> () + HashAlgo_SHA256 -> () + HashAlgo_SHA512 -> () + +instance GNFData HashAlgo where + grnf = rnf + algoToText :: forall t. HashAlgo t -> Text algoToText x = has @NamedAlgo x (algoName @t) diff --git a/hnix-store-core/src/System/Nix/OutputName.hs b/hnix-store-core/src/System/Nix/OutputName.hs index 8634d5d2..87ff3e4d 100644 --- a/hnix-store-core/src/System/Nix/OutputName.hs +++ b/hnix-store-core/src/System/Nix/OutputName.hs @@ -8,22 +8,22 @@ module System.Nix.OutputName , mkOutputName -- * Re-exports , System.Nix.StorePath.InvalidNameError(..) - , System.Nix.StorePath.parseNameText ) where +import Control.DeepSeq (NFData) import Data.Hashable (Hashable) import Data.Text (Text) import GHC.Generics (Generic) -import System.Nix.StorePath (InvalidNameError) - -import qualified System.Nix.StorePath +import System.Nix.StorePath (StorePathName, InvalidNameError(..), mkStorePathName) -- | Name of the derived path output -- Typically used for "dev", "doc" sub-outputs newtype OutputName = OutputName { -- | Extract the contents of the name. - unOutputName :: Text + unOutputName :: StorePathName } deriving (Eq, Generic, Hashable, Ord, Show) +instance NFData OutputName + mkOutputName :: Text -> Either InvalidNameError OutputName -mkOutputName = fmap OutputName . System.Nix.StorePath.parseNameText +mkOutputName = fmap OutputName . System.Nix.StorePath.mkStorePathName diff --git a/hnix-store-core/src/System/Nix/StorePath.hs b/hnix-store-core/src/System/Nix/StorePath.hs index 18bcf11d..bf24c715 100644 --- a/hnix-store-core/src/System/Nix/StorePath.hs +++ b/hnix-store-core/src/System/Nix/StorePath.hs @@ -38,6 +38,7 @@ module System.Nix.StorePath , unsafeMakeStorePathHashPart ) where +import Control.DeepSeq (NFData) import Crypto.Hash (HashAlgorithm) import Data.Attoparsec.Text.Lazy (Parser, ()) import Data.ByteString (ByteString) @@ -78,6 +79,8 @@ data StorePath = StorePath } deriving (Eq, Generic, Ord) +instance NFData StorePath + instance Hashable StorePath where hashWithSalt s StorePath{..} = s `hashWithSalt` storePathHash `hashWithSalt` storePathName @@ -98,6 +101,8 @@ newtype StorePathName = StorePathName unStorePathName :: Text } deriving (Eq, Generic, Hashable, Ord, Show) +instance NFData StorePathName + -- | The hash algorithm used for store path hashes. newtype StorePathHashPart = StorePathHashPart { -- | Extract the contents of the hash. @@ -105,6 +110,8 @@ newtype StorePathHashPart = StorePathHashPart } deriving (Eq, Generic, Hashable, Ord, Show) +instance NFData StorePathHashPart + -- | Make @StorePathHashPart@ from @ByteString@ (hash part of the @StorePath@) -- using specific @HashAlgorithm@ mkStorePathHashPart diff --git a/hnix-store-json/src/System/Nix/JSON.hs b/hnix-store-json/src/System/Nix/JSON.hs index b4d037bc..f2e029f1 100644 --- a/hnix-store-json/src/System/Nix/JSON.hs +++ b/hnix-store-json/src/System/Nix/JSON.hs @@ -83,14 +83,14 @@ instance ToJSON (DerivationOutput OutputName) where . Data.Text.Lazy.toStrict . Data.Text.Lazy.Builder.toLazyText . System.Nix.Realisation.derivationOutputBuilder - System.Nix.OutputName.unOutputName + (System.Nix.StorePath.unStorePathName . System.Nix.OutputName.unOutputName) toEncoding = toEncoding . Data.Text.Lazy.toStrict . Data.Text.Lazy.Builder.toLazyText . System.Nix.Realisation.derivationOutputBuilder - System.Nix.OutputName.unOutputName + (System.Nix.StorePath.unStorePathName . System.Nix.OutputName.unOutputName) instance ToJSONKey (DerivationOutput OutputName) where toJSONKey = @@ -98,7 +98,7 @@ instance ToJSONKey (DerivationOutput OutputName) where $ Data.Text.Lazy.toStrict . Data.Text.Lazy.Builder.toLazyText . System.Nix.Realisation.derivationOutputBuilder - System.Nix.OutputName.unOutputName + (System.Nix.StorePath.unStorePathName . System.Nix.OutputName.unOutputName) instance FromJSON (DerivationOutput OutputName) where parseJSON = diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs index a88dc3e7..a6bd984b 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs @@ -128,7 +128,8 @@ import System.Nix.Base (BaseEncoding(Base16, NixBase32)) import System.Nix.Build (BuildMode, BuildResult(..)) import System.Nix.ContentAddress (ContentAddress) import System.Nix.Derivation - ( Derivation(..) + ( BasicDerivation + , Derivation'(..) , DerivationOutput(..) -- , DerivationInputs(..) ) @@ -718,7 +719,7 @@ namedDigest = Serializer derivationOutput :: HasStoreDir r - => NixSerializer r SError (DerivationOutput StorePath Text) + => NixSerializer r SError DerivationOutput derivationOutput = Serializer { getS = do mPath <- getS maybePath @@ -755,13 +756,7 @@ derivationOutput = Serializer basicDerivation :: HasStoreDir r - => NixSerializer r SError - (Derivation - StorePath - Text - Text - (DerivationOutput StorePath Text) - (Set StorePath)) + => NixSerializer r SError BasicDerivation basicDerivation = Serializer { getS = do outputs <- getS (mapS text derivationOutput) diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Types/StoreRequest.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Types/StoreRequest.hs index 17c59bdf..a8d85ab5 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Types/StoreRequest.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Types/StoreRequest.hs @@ -16,7 +16,7 @@ import Data.Text (Text) import Data.Some (Some(Some)) import System.Nix.Build (BuildMode, BuildResult) -import System.Nix.Derivation (Derivation, DerivationOutput) +import System.Nix.Derivation (BasicDerivation, DerivationOutput) import System.Nix.DerivedPath (DerivedPath) import System.Nix.Hash (HashAlgo) import System.Nix.Signature (Signature) @@ -85,12 +85,7 @@ data StoreRequest :: Type -> Type where BuildDerivation :: StorePath - -> Derivation - StorePath - Text - Text - (DerivationOutput StorePath Text) - (Set StorePath) + -> BasicDerivation -> BuildMode -> StoreRequest BuildResult diff --git a/hnix-store-tests/hnix-store-tests.cabal b/hnix-store-tests/hnix-store-tests.cabal index 76a5cd2b..1ffd1551 100644 --- a/hnix-store-tests/hnix-store-tests.cabal +++ b/hnix-store-tests/hnix-store-tests.cabal @@ -66,6 +66,7 @@ library , generic-arbitrary < 1.1 , hashable , hspec + , monoidal-containers , QuickCheck , text , these diff --git a/hnix-store-tests/src/System/Nix/Arbitrary/Derivation.hs b/hnix-store-tests/src/System/Nix/Arbitrary/Derivation.hs index a57dc2ec..9c57115f 100644 --- a/hnix-store-tests/src/System/Nix/Arbitrary/Derivation.hs +++ b/hnix-store-tests/src/System/Nix/Arbitrary/Derivation.hs @@ -1,8 +1,10 @@ +{-# LANGUAGE GeneralizedNewtypeDeriving #-} -- due to recent generic-arbitrary {-# OPTIONS_GHC -fconstraint-solver-iterations=0 #-} {-# OPTIONS_GHC -Wno-orphans #-} module System.Nix.Arbitrary.Derivation where +import Data.Map.Monoidal import Data.These import Data.Text (Text) import Data.Text.Arbitrary () @@ -12,43 +14,36 @@ import System.Nix.StorePath (StorePath) import Test.QuickCheck (Arbitrary(..)) import Test.QuickCheck.Arbitrary.Generic (Arg, GenericArbitrary(..)) +import System.Nix.Arbitrary.ContentAddress () +import System.Nix.Arbitrary.Hash () import System.Nix.Arbitrary.StorePath () +import System.Nix.Arbitrary.OutputName () deriving via GenericArbitrary - (Derivation - StorePath - Text - Text - (DerivationOutput StorePath Text) - inputs) - instance + (Derivation' inputs output) + instance ( Arbitrary inputs - , Arg - (Derivation - StorePath - Text - Text - (DerivationOutput StorePath Text) - inputs) - inputs - ) => Arbitrary - (Derivation - StorePath - Text - Text - (DerivationOutput StorePath Text) - inputs) - -deriving via GenericArbitrary (DerivationOutput StorePath Text) - instance Arbitrary (DerivationOutput StorePath Text) - -deriving via GenericArbitrary (DerivationInputs StorePath Text) - instance Arbitrary (DerivationInputs StorePath Text) - -deriving via GenericArbitrary (DerivedPathMap StorePath Text) - instance Arbitrary (DerivedPathMap StorePath Text) - --- TODO this belongs elsewhere + , Arbitrary output + , Arg (Derivation' inputs output) inputs + , Arg (Derivation' inputs output) output + ) => Arbitrary (Derivation' inputs output) + +deriving via GenericArbitrary DerivationOutput + instance Arbitrary DerivationOutput + +deriving via GenericArbitrary DerivationInputs + instance Arbitrary DerivationInputs + +deriving via GenericArbitrary DerivedPathMap + instance Arbitrary DerivedPathMap + +deriving via GenericArbitrary ChildNode + instance Arbitrary ChildNode + +-- TODO these belong elsewhere + +deriving newtype instance (Arbitrary k, Arbitrary v, Ord k) => Arbitrary (MonoidalMap k v) + deriving via GenericArbitrary (These a b) instance ( Arg (These a b) a , Arg (These a b) b diff --git a/hnix-store-tests/tests/DerivationSpec.hs b/hnix-store-tests/tests/DerivationSpec.hs index 650de752..ccaa5046 100644 --- a/hnix-store-tests/tests/DerivationSpec.hs +++ b/hnix-store-tests/tests/DerivationSpec.hs @@ -1,27 +1,23 @@ module DerivationSpec where +import Data.Functor.Identity (Identity(..)) import Test.Hspec (Spec, describe) -import Test.Hspec.QuickCheck (xprop) +import Test.Hspec.QuickCheck (prop) import Test.Hspec.Nix (roundtrips) import System.Nix.Arbitrary () -import System.Nix.Derivation (parseDerivation, buildDerivation) +import System.Nix.Derivation + ( derivationInputsFromSingleDerivedPath + , derivationInputsToDerivedPaths + ) -import qualified Data.Attoparsec.Text -import qualified Data.Text.Lazy -import qualified Data.Text.Lazy.Builder - --- TODO(srk): this won't roundtrip as Arbitrary Text --- contains wild stuff like control characters and UTF8 sequences. --- Either fix in nix-derivation or use wrapper type --- (but we use Nix.Derivation.textParser so we need Text for now) spec :: Spec spec = do - describe "Derivation" $ do - xprop "roundtrips via Text" $ \sd -> + describe "DerivationInput" $ do + prop "roundtrips to (Set SingleDerivedPath)" $ + -- Order is important, 'Set SingleDerivedPath' is the normal from, + -- since the arbitrary instance for 'DerivationInput' doesn't + -- properly avoid empty child maps. roundtrips - ( Data.Text.Lazy.toStrict - . Data.Text.Lazy.Builder.toLazyText - . buildDerivation sd - ) - (Data.Attoparsec.Text.parseOnly (parseDerivation sd)) + (foldMap derivationInputsFromSingleDerivedPath) + (Identity . derivationInputsToDerivedPaths) diff --git a/hnix-store-tests/tests/DerivedPathSpec.hs b/hnix-store-tests/tests/DerivedPathSpec.hs index 7debac2e..442de3fa 100644 --- a/hnix-store-tests/tests/DerivedPathSpec.hs +++ b/hnix-store-tests/tests/DerivedPathSpec.hs @@ -10,6 +10,12 @@ import qualified System.Nix.DerivedPath spec :: Spec spec = do + describe "SingleDerivedPath" $ do + prop "roundtrips" $ \sd -> + roundtrips + (System.Nix.DerivedPath.singleDerivedPathToText sd) + (System.Nix.DerivedPath.parseSingleDerivedPath sd) + describe "DerivedPath" $ do prop "roundtrips" $ \sd -> roundtrips diff --git a/hnix-store-tests/tests/RealisationSpec.hs b/hnix-store-tests/tests/RealisationSpec.hs index 022b5402..d35f3967 100644 --- a/hnix-store-tests/tests/RealisationSpec.hs +++ b/hnix-store-tests/tests/RealisationSpec.hs @@ -8,6 +8,7 @@ import System.Nix.Arbitrary () import qualified Data.Text.Lazy import qualified Data.Text.Lazy.Builder +import qualified System.Nix.StorePath import qualified System.Nix.OutputName import qualified System.Nix.Realisation @@ -19,7 +20,7 @@ spec = do ( Data.Text.Lazy.toStrict . Data.Text.Lazy.Builder.toLazyText . System.Nix.Realisation.derivationOutputBuilder - System.Nix.OutputName.unOutputName + (System.Nix.StorePath.unStorePathName . System.Nix.OutputName.unOutputName) ) ( System.Nix.Realisation.derivationOutputParser System.Nix.OutputName.mkOutputName diff --git a/nix-derivation/src/Nix/Derivation/Types.hs b/nix-derivation/src/Nix/Derivation/Types.hs deleted file mode 100644 index f882be6e..00000000 --- a/nix-derivation/src/Nix/Derivation/Types.hs +++ /dev/null @@ -1,89 +0,0 @@ -{-# LANGUAGE DeriveGeneric #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE KindSignatures #-} - --- | Shared types - -module Nix.Derivation.Types - ( -- * Types - Derivation(..) - , DerivationOutput(..) - , DerivedPathMap(..) - , DerivationInputs(..) - ) where - -import Control.DeepSeq (NFData) -import Data.Map (Map) -import Data.Set (Set) -import Data.These -import Data.Vector (Vector) -import GHC.Generics (Generic) - --- | A Nix derivation -data Derivation fp txt outputName drvOutput drvInputs = Derivation - { outputs :: Map outputName drvOutput - -- ^ Outputs produced by this derivation where keys are output names - , inputs :: drvInputs - -- ^ Inputs (sources and derivations) - , platform :: txt - -- ^ Platform required for this derivation - , builder :: txt - -- ^ Code to build the derivation, which can be a path or a builtin function - , args :: Vector txt - -- ^ Arguments passed to the executable used to build to derivation - , env :: Map txt txt - -- ^ Environment variables provided to the executable used to build the - -- derivation - } deriving (Eq, Generic, Ord, Show) - -instance ( NFData fp - , NFData txt - , NFData outputName - , NFData drvOutput - , NFData drvInputs - ) - => NFData (Derivation fp txt outputName drvOutput drvInputs) - -data DerivationInputs fp drvOutput = DerivationInputs - { drvs :: DerivedPathMap fp drvOutput - -- ^ Inputs that are derivations where keys specify derivation paths and - -- values specify which output names are used by this derivation - , srcs :: Set fp - -- ^ Inputs that are sources - } deriving (Eq, Generic, Ord, Show) - -instance (NFData a, NFData b) => NFData (DerivationInputs a b) - --- | A recursive map to handle dependencies on dynamic derivations in --- addition to static ones -newtype DerivedPathMap fp drvOutput = DerivedPathMap - { unDerivedPathMap :: Map - fp - (These - (Set drvOutput) - (DerivedPathMap fp drvOutput)) - } deriving (Eq, Generic, Ord, Show) - -instance (NFData a, NFData b) => NFData (DerivedPathMap a b) - --- | An output of a Nix derivation -data DerivationOutput fp txt - = InputAddressedDerivationOutput - { path :: fp - -- ^ Path where the output will be saved - } - | FixedDerivationOutput - { path :: fp - -- ^ Path where the output will be saved - , hashAlgo :: txt - -- ^ Hash used for expected hash computation - , hash :: txt - -- ^ Expected hash - } - | ContentAddressedDerivationOutput - { hashAlgo :: txt - -- ^ Hash used for expected hash computation - } - deriving (Eq, Generic, Ord, Show) - -instance (NFData a, NFData b) => NFData (DerivationOutput a b) diff --git a/overlay.nix b/overlay.nix index 3a479158..1940751e 100644 --- a/overlay.nix +++ b/overlay.nix @@ -21,12 +21,6 @@ in haskellLib.doJailbreak hsuper.dependent-sum-template_0_2_0_1; - nix-derivation = - lib.pipe - (hself.callCabal2nix "nix-derivation" ./nix-derivation {}) - [ - haskellLib.compose.buildFromSdist - ]; hnix-store-core = lib.pipe (hself.callCabal2nix "hnix-store-core" ./hnix-store-core {}) @@ -39,6 +33,12 @@ in [ haskellLib.compose.buildFromSdist ]; + hnix-store-aterm = + lib.pipe + (hself.callCabal2nix "hnix-store-aterm" ./hnix-store-aterm {}) + [ + haskellLib.compose.buildFromSdist + ]; hnix-store-json = lib.pipe (hself.callCabal2nix "hnix-store-json" ./hnix-store-json {}) From 1ebff0d26d5e96e604a7fde5e6750059be004550 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sat, 9 Nov 2024 12:33:58 -0500 Subject: [PATCH 48/58] WIP daemon protocol --- hnix-store-core/src/System/Nix/Derivation.hs | 2 +- hnix-store-remote/hnix-store-remote.cabal | 2 +- hnix-store-remote/src/Data/Serializer.hs | 70 +- .../src/Data/Serializer/Example.hs | 99 +-- .../System/Nix/Store/Remote/Client/Core.hs | 20 +- .../src/System/Nix/Store/Remote/Logger.hs | 6 +- .../src/System/Nix/Store/Remote/Serializer.hs | 771 ++++++++---------- .../src/System/Nix/Store/Remote/Socket.hs | 16 +- .../Nix/Store/Remote/Types/StoreReply.hs | 61 -- 9 files changed, 440 insertions(+), 607 deletions(-) delete mode 100644 hnix-store-remote/src/System/Nix/Store/Remote/Types/StoreReply.hs diff --git a/hnix-store-core/src/System/Nix/Derivation.hs b/hnix-store-core/src/System/Nix/Derivation.hs index dd9c4439..96adf44d 100644 --- a/hnix-store-core/src/System/Nix/Derivation.hs +++ b/hnix-store-core/src/System/Nix/Derivation.hs @@ -46,7 +46,7 @@ import System.Nix.StorePath (StorePath) import System.Nix.OutputName (OutputName) data Derivation' inputs output = Derivation - { outputs :: output + { outputs :: Map Text output -- ^ Outputs produced by this derivation where keys are output names , inputs :: inputs -- ^ Inputs (sources and derivations) diff --git a/hnix-store-remote/hnix-store-remote.cabal b/hnix-store-remote/hnix-store-remote.cabal index bfc45b18..cacbe1eb 100644 --- a/hnix-store-remote/hnix-store-remote.cabal +++ b/hnix-store-remote/hnix-store-remote.cabal @@ -92,7 +92,6 @@ library , System.Nix.Store.Remote.Types.Query.Missing , System.Nix.Store.Remote.Types.StoreConfig , System.Nix.Store.Remote.Types.StoreRequest - , System.Nix.Store.Remote.Types.StoreReply , System.Nix.Store.Remote.Types.StoreText , System.Nix.Store.Remote.Types.SubstituteMode , System.Nix.Store.Remote.Types.SuccessCodeReply @@ -122,6 +121,7 @@ library , exceptions , generic-arbitrary < 1.1 , hashable + , mmorph , text , time , transformers diff --git a/hnix-store-remote/src/Data/Serializer.hs b/hnix-store-remote/src/Data/Serializer.hs index d1e525dd..cd37a209 100644 --- a/hnix-store-remote/src/Data/Serializer.hs +++ b/hnix-store-remote/src/Data/Serializer.hs @@ -29,18 +29,18 @@ module Data.Serializer , SimpleSerializer -- ** Simple runners , runGetSimple - , runPutSimple -- * From Get/Put, Serialize , lift2 , liftSerialize -- * Combinators + , AlmostPrism(..) + , maybeAlmostPrism , mapIsoSerializer , mapPrismSerializer , tup -- * Utility , GetSerializerError(..) , transformGetError - , transformPutError -- * Re-exports , Get , PutM @@ -49,16 +49,16 @@ module Data.Serializer #if !MIN_VERSION_base(4,18,0) import Control.Applicative (liftA2) #endif -import Control.Monad.Except (MonadError, throwError) -import Control.Monad.Trans (lift) -import Control.Monad.Trans (MonadTrans) +import Control.Monad.Morph import Control.Monad.Trans.Identity (IdentityT, runIdentityT) import Data.ByteString (ByteString) +import Data.Functor.Identity import Data.Serialize (Serialize) +import qualified Data.Serialize import Data.Serialize.Get (Get, runGet) import Data.Serialize.Put (Putter, PutM, runPutM) +import Data.Traversable -import qualified Data.Serialize -- * Serializer @@ -68,21 +68,17 @@ import qualified Data.Serialize -- for e.g. adding @ExceptT@ or @ReaderT@ layers. data Serializer t a = Serializer { getS :: t Get a - , putS :: a -> t PutM () + , putS :: a -> PutM () } -- ** Runners -- | Runner for putS of @Serializer@ runPutS - :: ( Monad (t PutM) - , MonadTrans t - ) - => Serializer t a -- ^ Serializer - -> (t PutM () -> PutM b) -- ^ Tranformer runner + :: Serializer t a -- ^ Serializer -> a -- ^ Value to (out)put - -> (b, ByteString) -runPutS s run a = runPutM $ run $ (putS s) a + -> ByteString +runPutS s = snd . runPutM . putS s -- | Runner for getS of @Serializer@ runGetS @@ -110,15 +106,6 @@ runGetSimple runGetSimple s b = runGetS s (runIdentityT) b --- | Runner for putS of @SimpleSerializer@ -runPutSimple - :: SimpleSerializer a - -> a - -> ByteString -runPutSimple s = - snd - . runPutS s runIdentityT - -- * From Get/Put, Serialize -- | Lift @Get a@ and @Putter a@ into @Serializer@ @@ -130,7 +117,7 @@ lift2 -> Serializer t a lift2 f g = Serializer { getS = lift f - , putS = lift . g + , putS = g } -- | Lift @Serialize a@ instance into @Serializer@ @@ -158,17 +145,34 @@ mapIsoSerializer f g s = Serializer , putS = putS s . g } +data AlmostPrism t a b = AlmostPrism + { _almostPrism_get :: a -> t Identity b + -- ^ Map over @getS@ + , _almostPrism_put :: b -> a + -- ^ Map over @putS@ + } + +maybeAlmostPrism + :: Applicative (t Identity) + => AlmostPrism t a b + -> AlmostPrism t (Maybe a) (Maybe b) +maybeAlmostPrism ap = AlmostPrism + { _almostPrism_get = traverse $ _almostPrism_get ap + , _almostPrism_put = fmap $ _almostPrism_put ap + } + -- | Map over @Serializer@ where @getS@ -- can return @Either@ mapPrismSerializer - :: MonadError eGet (t Get) - => (a -> Either eGet b) -- ^ Map over @getS@ - -> (b -> a) -- ^ Map over @putS@ + :: ( Monad (t Get) + , MFunctor t + ) + => AlmostPrism t a b -> Serializer t a -> Serializer t b -mapPrismSerializer f g s = Serializer - { getS = either throwError pure . f =<< getS s - , putS = putS s . g +mapPrismSerializer p s = Serializer + { getS = hoist generalize . _almostPrism_get p =<< getS s + , putS = putS s . _almostPrism_put p } -- | Tuple combinator @@ -206,9 +210,3 @@ transformGetError = \case Left stringyRunGetError -> Left (SerializerError_GetFail stringyRunGetError) Right (Left myGetError) -> Left (SerializerError_Get myGetError) Right (Right res) -> Right res - --- | Helper for transforming @runPutM@ result -transformPutError - :: (Either customPutError (), ByteString) - -> Either customPutError ByteString -transformPutError (e, r) = either Left (pure $ Right r) e diff --git a/hnix-store-remote/src/Data/Serializer/Example.hs b/hnix-store-remote/src/Data/Serializer/Example.hs index a53d6dc9..ab15bc8d 100644 --- a/hnix-store-remote/src/Data/Serializer/Example.hs +++ b/hnix-store-remote/src/Data/Serializer/Example.hs @@ -11,16 +11,11 @@ module Data.Serializer.Example , runP -- * Custom errors , MyGetError(..) - , MyPutError(..) -- ** Erroring variants of cmdS - -- *** putS with throwError and MyPutError - , cmdSPutError -- *** getS with throwError and MyGetError , cmdSGetError -- *** getS with fail , cmdSGetFail - -- *** putS with fail - , cmdSPutFail -- * Elaborate , cmdSRest , runGRest @@ -28,13 +23,13 @@ module Data.Serializer.Example ) where import Control.Monad.Except (MonadError, throwError) -import Control.Monad.Reader (MonadReader, ask) +import Control.Monad.Reader (MonadReader) import Control.Monad.State (MonadState) import Control.Monad.Trans (MonadTrans, lift) import Control.Monad.Trans.Reader (ReaderT, runReaderT) import Control.Monad.Trans.Except (ExceptT, runExceptT) import Control.Monad.Trans.State (StateT, runStateT) -import Data.Bifunctor (first, second) +import Data.Bifunctor (second) import Data.ByteString (ByteString) import Data.Int (Int8) import Data.GADT.Show (GShow(..), defaultGshowsPrec) @@ -48,7 +43,6 @@ import Data.Serializer , runGetS , runPutS , transformGetError - , transformPutError ) import Data.Some (Some(..)) import GHC.Generics (Generic) @@ -97,25 +91,26 @@ instance Arbitrary (Some Cmd) where opcode :: MonadTrans t => Serializer t OpCode opcode = Serializer { getS = lift getEnum - , putS = lift . putEnum + , putS = putEnum } -- * Cmd Serializer -- | @Cmd@ @Serializer@ cmdS - :: forall t . ( MonadTrans t - , Monad (t Get) - , Monad (t PutM) - ) + :: forall t + . ( MonadTrans t + , Monad (t Get) + , Monad (t PutM) + ) => Serializer t (Some Cmd) cmdS = Serializer { getS = getS opcode >>= \case OpCode_Int -> Some . Cmd_Int <$> lift getInt8 OpCode_Bool -> Some . Cmd_Bool <$> lift getBool , putS = \case - Some (Cmd_Int i) -> putS opcode OpCode_Int >> lift (putInt8 i) - Some (Cmd_Bool b) -> putS opcode OpCode_Bool >> lift (putBool b) + Some (Cmd_Int i) -> putS (opcode @t) OpCode_Int >> putInt8 i + Some (Cmd_Bool b) -> putS (opcode @t) OpCode_Bool >> putBool b } -- * Runners @@ -133,10 +128,8 @@ runG s = runP :: Serializer (ExceptT e) a -> a - -> Either e ByteString -runP s = - (\(e, r) -> either Left (pure $ Right r) e) - . runPutS s runExceptT + -> ByteString +runP = runPutS -- * Custom errors @@ -144,22 +137,8 @@ data MyGetError = MyGetError_Example deriving (Eq, Show) -data MyPutError - = MyPutError_NoLongerSupported -- no longer supported protocol version - deriving (Eq, Show) - -- ** Erroring variants of cmdS --- *** putS with throwError and MyPutError - -cmdSPutError :: Serializer (ExceptT MyPutError) (Some Cmd) -cmdSPutError = Serializer - { getS = getS cmdS - , putS = \case - Some (Cmd_Int i) -> putS opcode OpCode_Int >> lift (putInt8 i) - Some (Cmd_Bool _b) -> throwError MyPutError_NoLongerSupported - } - -- *** getS with throwError and MyGetError cmdSGetError :: Serializer (ExceptT MyGetError) (Some Cmd) @@ -167,13 +146,14 @@ cmdSGetError = Serializer { getS = getS opcode >>= \case OpCode_Int -> Some . Cmd_Int <$> lift getInt8 OpCode_Bool -> throwError MyGetError_Example - , putS = putS cmdS + , putS = putS $ cmdS @(ExceptT MyGetError) } -- *** getS with fail cmdSGetFail - :: ( MonadTrans t + :: forall t + . ( MonadTrans t , MonadFail (t Get) , Monad (t PutM) ) @@ -182,26 +162,7 @@ cmdSGetFail = Serializer { getS = getS opcode >>= \case OpCode_Int -> Some . Cmd_Int <$> lift getInt8 OpCode_Bool -> fail "no parse" - , putS = putS cmdS - } - --- *** putS with fail - --- | Unused as PutM doesn't have @MonadFail@ --- >>> serializerPutFail = cmdPutFail @(ExceptT MyGetError) --- No instance for (MonadFail PutM) --- as expected -cmdSPutFail - :: ( MonadTrans t - , MonadFail (t PutM) - , Monad (t Get) - ) - => Serializer t (Some Cmd) -cmdSPutFail = Serializer - { getS = getS cmdS - , putS = \case - Some (Cmd_Int i) -> putS opcode OpCode_Int >> lift (putInt8 i) - Some (Cmd_Bool _b) -> fail "can't" + , putS = putS $ cmdS @t } -- * Elaborate @@ -250,35 +211,29 @@ runGRest serializer r s = runPRest :: Serializer (REST r e s) a - -> r - -> s -> a - -> Either e ByteString -runPRest serializer r s = - transformPutError - . first fst - . runPutS - serializer - (restRunner r s) + -> ByteString +runPRest = runPutS cmdSRest - :: Serializer (REST Bool e Int) (Some Cmd) -cmdSRest = Serializer + :: forall t e + . t ~ REST Bool e Int + => Bool + -> Serializer t (Some Cmd) +cmdSRest isTrue = Serializer { getS = getS opcode >>= \case OpCode_Int -> do - isTrue <- ask if isTrue then Some . Cmd_Int . (+1) <$> lift getInt8 else Some . Cmd_Int <$> lift getInt8 OpCode_Bool -> Some . Cmd_Bool <$> lift getBool , putS = \case Some (Cmd_Int i) -> do - putS opcode OpCode_Int - isTrue <- ask + putS (opcode @t) OpCode_Int if isTrue - then lift (putInt8 (i - 1)) - else lift (putInt8 i) - Some (Cmd_Bool b) -> putS opcode OpCode_Bool >> lift (putBool b) + then putInt8 (i - 1) + else putInt8 i + Some (Cmd_Bool b) -> putS (opcode @t) OpCode_Bool >> putBool b } -- Primitives helpers diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Client/Core.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Client/Core.hs index 5373dd19..9c768eec 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Client/Core.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Client/Core.hs @@ -30,12 +30,13 @@ import System.Nix.Store.Remote.Serializer , trustedFlag , workerMagic ) + +import System.Nix.Store.Remote.Serializer import System.Nix.Store.Remote.Types.Handshake (ClientHandshakeOutput(..)) import System.Nix.Store.Remote.Types.Logger (Logger) import System.Nix.Store.Remote.Types.NoReply (NoReply(..)) import System.Nix.Store.Remote.Types.ProtoVersion (ProtoVersion(..)) import System.Nix.Store.Remote.Types.StoreRequest (StoreRequest(..)) -import System.Nix.Store.Remote.Types.StoreReply (StoreReply(..)) import System.Nix.Store.Remote.Types.WorkerMagic (WorkerMagic(..)) import qualified Data.ByteString @@ -48,17 +49,19 @@ doReq :: forall m a . ( MonadIO m , MonadRemoteStore m - , StoreReply a , Show a ) => StoreRequest a -> m a doReq = \case x -> do + storeDir <- getStoreDir + protoVersion <- getProtoVersion + sockPutS (mapErrorS RemoteStoreError_SerializerRequest - storeRequest + $ storeRequest storeDir protoVersion ) (Some x) @@ -76,7 +79,7 @@ doReq = \case throwError RemoteStoreError_NoNarSourceProvided processOutput - processReply + sockGetS $ mapErrorS (RemoteStoreError_SerializerReply . ReplySError_PrimGet) $ storePath storeDir AddToStoreNar _ meta _ _ -> do let narBytes = maybe 0 id $ metadataNarBytes meta @@ -109,13 +112,8 @@ doReq = \case _ -> do processOutput - processReply - - where - processReply = sockGetS - (mapErrorS RemoteStoreError_SerializerReply - $ getReplyS @a - ) + error "need to keep casing on arguments" + --sockGetS $ mapErrorS (RemoteStoreError_SerializerReply . ReplySError_PrimGet) copyToSink :: forall m diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Logger.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Logger.hs index 4e9afa3d..668a46a1 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Logger.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Logger.hs @@ -2,11 +2,11 @@ module System.Nix.Store.Remote.Logger ( processOutput ) where -import Control.Monad.Except (throwError) +import Control.Monad.Except (runExceptT, throwError) import Control.Monad.IO.Class (liftIO) import Data.ByteString (ByteString) import Data.Serialize (Result(..)) -import System.Nix.Store.Remote.Serializer (LoggerSError, logger, runSerialT) +import System.Nix.Store.Remote.Serializer (LoggerSError, logger) import System.Nix.Store.Remote.Socket (sockGet8) import System.Nix.Store.Remote.MonadStore (MonadRemoteStore, RemoteStoreError(..), appendLog, getDataSource, getDataSink, getStoreSocket, getProtoVersion) import System.Nix.Store.Remote.Types.Logger (Logger(..)) @@ -30,7 +30,7 @@ processOutput = do -> Result (Either LoggerSError Logger) decoder protoVersion = Data.Serialize.Get.runGetPartial - (runSerialT protoVersion $ Data.Serializer.getS logger) + (runExceptT $ Data.Serializer.getS $ logger protoVersion) go :: MonadRemoteStore m diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs index a6bd984b..7716079d 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs @@ -9,12 +9,11 @@ module System.Nix.Store.Remote.Serializer ( -- * NixSerializer NixSerializer - , mapReaderS , mapErrorS -- * Errors , SError(..) -- ** Runners - , runSerialT + , runExceptT , runG , runP -- * Primitives @@ -106,12 +105,14 @@ import Control.Monad.Except (MonadError, throwError, ) import Control.Monad.Reader (MonadReader) import Control.Monad.Trans (MonadTrans, lift) import Control.Monad.Trans.Reader (ReaderT, runReaderT, withReaderT) -import Control.Monad.Trans.Except (ExceptT, mapExceptT, runExceptT, withExceptT) +import Control.Monad.Trans.Except (ExceptT(..), mapExceptT, runExceptT, withExceptT) import Crypto.Hash (Digest, HashAlgorithm, SHA256) import Data.Aeson (FromJSON, ToJSON) import Data.ByteString (ByteString) +import qualified Data.ByteString.Lazy import Data.Dependent.Sum (DSum((:=>))) import Data.Fixed (Uni) +import Data.Functor.Identity import Data.Hashable (Hashable) import Data.HashSet (HashSet) import Data.Map (Map) @@ -141,7 +142,7 @@ import System.Nix.Realisation (DerivationOutputError, Realisation(..), Realisati import System.Nix.Signature (Signature, NarSignature) import System.Nix.FileContentAddress (FileIngestionMethod(..)) import System.Nix.Store.Types (RepairMode(..)) -import System.Nix.StorePath (HasStoreDir(..), InvalidNameError, InvalidPathError, StorePath, StorePathHashPart, StorePathName) +import System.Nix.StorePath (StoreDir, InvalidNameError, InvalidPathError, StorePath, StorePathHashPart, StorePathName) import System.Nix.StorePath.Metadata (Metadata(..), StorePathTrust(..)) import System.Nix.Store.Remote.Types @@ -177,73 +178,18 @@ import qualified System.Nix.Realisation import qualified System.Nix.Signature import qualified System.Nix.StorePath --- | Transformer for @Serializer@ -newtype SerialT r e m a = SerialT - { _unSerialT :: ExceptT e (ReaderT r m) a } - deriving - ( Applicative - , Functor - , Monad - , MonadError e - , MonadReader r - , MonadFail - ) - -instance MonadTrans (SerialT r e) where - lift = SerialT . lift . lift - --- | Runner for @SerialT@ -runSerialT - :: Monad m - => r - -> SerialT r e m a - -> m (Either e a) -runSerialT r = - (`runReaderT` r) - . runExceptT - . _unSerialT - -mapErrorST - :: Functor m - => (e -> e') - -> SerialT r e m a - -> SerialT r e' m a -mapErrorST f = - SerialT - . withExceptT f - . _unSerialT - mapErrorS :: (e -> e') - -> NixSerializer r e a - -> NixSerializer r e' a + -> NixSerializer e a + -> NixSerializer e' a mapErrorS f s = Serializer - { getS = mapErrorST f $ getS s - , putS = mapErrorST f . putS s - } - -mapReaderST - :: Functor m - => (r' -> r) - -> SerialT r e m a - -> SerialT r' e m a -mapReaderST f = - SerialT - . (mapExceptT . withReaderT) f - . _unSerialT - -mapReaderS - :: (r' -> r) - -> NixSerializer r e a - -> NixSerializer r' e a -mapReaderS f s = Serializer - { getS = mapReaderST f $ getS s - , putS = mapReaderST f . putS s + { getS = withExceptT f $ getS s + , putS = putS s } -- * NixSerializer -type NixSerializer r e = Serializer (SerialT r e) +type NixSerializer e = Serializer (ExceptT e) -- * Errors @@ -265,7 +211,7 @@ data SError | SError_IllegalBool Word64 | SError_InvalidNixBase32 | SError_JSONDecoding String - | SError_NarHashMustBeSHA256 + -- | SError_NarHashMustBeSHA256 | SError_NotYetImplemented String (ForPV ProtoVersion) | SError_Name InvalidNameError | SError_Path InvalidPathError @@ -281,7 +227,7 @@ data ForPV a -- ** Runners runG - :: NixSerializer r e a + :: NixSerializer e a -> r -> ByteString -> Either (GetSerializerError e) a @@ -289,28 +235,23 @@ runG serializer r = transformGetError . runGetS serializer - (runSerialT r) + (runExceptT) runP - :: NixSerializer r e a - -> r + :: NixSerializer e a -> a - -> Either e ByteString -runP serializer r = - transformPutError - . runPutS - serializer - (runSerialT r) + -> ByteString +runP = runPutS -- * Primitives -int :: Integral a => NixSerializer r e a +int :: Integral a => NixSerializer e a int = Serializer { getS = fromIntegral <$> lift Data.Serialize.Get.getWord64le - , putS = lift . Data.Serialize.Put.putWord64le . fromIntegral + , putS = Data.Serialize.Put.putWord64le . fromIntegral } -bool :: NixSerializer r SError Bool +bool :: NixSerializer SError Bool bool = Serializer { getS = getS (int @Word64) >>= \case 0 -> pure False @@ -321,7 +262,7 @@ bool = Serializer True -> putS (int @Word8) 1 } -byteString :: NixSerializer r SError ByteString +byteString :: NixSerializer SError ByteString byteString = Serializer { getS = do len <- getS int @@ -336,7 +277,7 @@ byteString = Serializer , putS = \x -> do let len = Data.ByteString.length x putS int len - lift $ Data.Serialize.Put.putByteString x + Data.Serialize.Put.putByteString x Control.Monad.when (len `mod` 8 /= 0) $ pad $ 8 - (len `mod` 8) @@ -349,7 +290,16 @@ byteString = Serializer pad count = Control.Monad.replicateM_ count - (lift $ Data.Serialize.Put.putWord8 0) + (Data.Serialize.Put.putWord8 0) + +maybeByteString :: NixSerializer SError (Maybe ByteString) +maybeByteString = mapIsoSerializer + (\case + t | Data.ByteString.null t -> Nothing + t | otherwise -> Just t + ) + (Data.Maybe.fromMaybe mempty) + byteString -- | Utility toEnum version checking bounds using Bounded class toEnumCheckBoundsM @@ -369,26 +319,26 @@ enum :: ( Bounded a , Enum a ) - => NixSerializer r SError a + => NixSerializer SError a enum = Serializer { getS = getS int >>= toEnumCheckBoundsM , putS = putS int . fromEnum } -text :: NixSerializer r SError Text +text :: NixSerializer SError Text text = mapIsoSerializer Data.Text.Encoding.decodeUtf8 Data.Text.Encoding.encodeUtf8 byteString -- TODO Parser Builder -_textBuilder :: NixSerializer r SError Builder +_textBuilder :: NixSerializer SError Builder _textBuilder = Serializer { getS = Data.Text.Lazy.Builder.fromText <$> getS text , putS = putS text . Data.Text.Lazy.toStrict . Data.Text.Lazy.Builder.toLazyText } -maybeText :: NixSerializer r SError (Maybe Text) +maybeText :: NixSerializer SError (Maybe Text) maybeText = mapIsoSerializer (\case t | Data.Text.null t -> Nothing @@ -399,7 +349,7 @@ maybeText = mapIsoSerializer -- * UTCTime -time :: NixSerializer r e UTCTime +time :: NixSerializer e UTCTime time = Serializer { getS = Data.Time.Clock.POSIX.posixSecondsToUTCTime @@ -422,8 +372,8 @@ time = Serializer -- * Combinators list - :: NixSerializer r e a - -> NixSerializer r e [a] + :: NixSerializer e a + -> NixSerializer e [a] list s = Serializer { getS = do count <- getS int @@ -435,8 +385,8 @@ list s = Serializer set :: Ord a - => NixSerializer r e a - -> NixSerializer r e (Set a) + => NixSerializer e a + -> NixSerializer e (Set a) set = mapIsoSerializer Data.Set.fromList @@ -447,8 +397,8 @@ hashSet :: ( Eq a , Hashable a ) - => NixSerializer r e a - -> NixSerializer r e (HashSet a) + => NixSerializer e a + -> NixSerializer e (HashSet a) hashSet = mapIsoSerializer Data.HashSet.fromList @@ -457,9 +407,9 @@ hashSet = mapS :: Ord k - => NixSerializer r e k - -> NixSerializer r e v - -> NixSerializer r e (Map k v) + => NixSerializer e k + -> NixSerializer e v + -> NixSerializer e (Map k v) mapS k v = mapIsoSerializer Data.Map.Strict.fromList @@ -469,8 +419,8 @@ mapS k v = vector :: Ord a - => NixSerializer r e a - -> NixSerializer r e (Vector a) + => NixSerializer e a + -> NixSerializer e (Vector a) vector = mapIsoSerializer Data.Vector.fromList @@ -481,23 +431,31 @@ json :: ( FromJSON a , ToJSON a ) - => NixSerializer r SError a -json = - mapPrismSerializer - ( Data.Bifunctor.first SError_JSONDecoding - . Data.Aeson.eitherDecode - ) - Data.Aeson.encode + => NixSerializer SError a +json = mapPrismSerializer jsonP $ mapIsoSerializer Data.ByteString.Lazy.fromStrict Data.ByteString.Lazy.toStrict byteString +jsonP + :: ( FromJSON a + , ToJSON a + ) + => AlmostPrism (ExceptT SError) Data.ByteString.Lazy.ByteString a +jsonP = AlmostPrism + ( ExceptT + . Identity + . Data.Bifunctor.first SError_JSONDecoding + . Data.Aeson.eitherDecode + ) + Data.Aeson.encode + -- * ProtoVersion -- protoVersion_major & 0xFF00 -- protoVersion_minor & 0x00FF -protoVersion :: NixSerializer r e ProtoVersion +protoVersion :: NixSerializer e ProtoVersion protoVersion = Serializer { getS = do v <- getS (int @Word32) @@ -513,73 +471,62 @@ protoVersion = Serializer -- * StorePath -storePath :: HasStoreDir r => NixSerializer r SError StorePath -storePath = Serializer - { getS = do - sd <- Control.Monad.Reader.asks hasStoreDir - System.Nix.StorePath.parsePath sd <$> getS byteString - >>= - either - (throwError . SError_Path) - pure - , putS = \p -> do - sd <- Control.Monad.Reader.asks hasStoreDir - putS - byteString - $ System.Nix.StorePath.storePathToRawFilePath sd p +storePath :: StoreDir -> NixSerializer SError StorePath +storePath storeDir = mapPrismSerializer (storePathP storeDir) byteString + +storePathP :: StoreDir -> AlmostPrism (ExceptT SError) ByteString StorePath +storePathP storeDir = AlmostPrism + { _almostPrism_get = + ExceptT + . Identity + . Data.Bifunctor.first SError_Path + . System.Nix.StorePath.parsePath storeDir + , _almostPrism_put = System.Nix.StorePath.storePathToRawFilePath storeDir } maybePath - :: HasStoreDir r - => NixSerializer r SError (Maybe StorePath) -maybePath = Serializer - { getS = do - getS maybeText >>= \case - Nothing -> pure Nothing - Just t -> do - sd <- Control.Monad.Reader.asks hasStoreDir - either - (throwError . SError_Path) - (pure . pure) - $ System.Nix.StorePath.parsePathFromText sd t + :: StoreDir + -> NixSerializer SError (Maybe StorePath) +maybePath storeDir = mapPrismSerializer (maybeAlmostPrism $ storePathP storeDir) maybeByteString - , putS = \case - Nothing -> putS maybeText Nothing - Just p -> do - sd <- Control.Monad.Reader.asks hasStoreDir - putS text $ System.Nix.StorePath.storePathToText sd p - } - -storePathHashPart :: NixSerializer r SError StorePathHashPart +storePathHashPart :: NixSerializer SError StorePathHashPart storePathHashPart = mapIsoSerializer System.Nix.StorePath.unsafeMakeStorePathHashPart System.Nix.StorePath.unStorePathHashPart $ mapPrismSerializer - (Data.Bifunctor.first (pure SError_InvalidNixBase32) - . System.Nix.Base.decodeWith NixBase32) - (System.Nix.Base.encodeWith NixBase32) + (AlmostPrism + (ExceptT + . Identity + . Data.Bifunctor.first (pure SError_InvalidNixBase32) + . System.Nix.Base.decodeWith NixBase32) + (System.Nix.Base.encodeWith NixBase32) + ) text -storePathName :: NixSerializer r SError StorePathName +storePathName :: NixSerializer SError StorePathName storePathName = mapPrismSerializer - (Data.Bifunctor.first SError_Name - . System.Nix.StorePath.mkStorePathName) - System.Nix.StorePath.unStorePathName + (AlmostPrism + (ExceptT + . Identity + . Data.Bifunctor.first SError_Name + . System.Nix.StorePath.mkStorePathName) + System.Nix.StorePath.unStorePathName + ) text pathMetadata - :: HasStoreDir r - => NixSerializer r SError (Metadata StorePath) -pathMetadata = Serializer + :: StoreDir + -> NixSerializer SError (Metadata StorePath) +pathMetadata storeDir = Serializer { getS = do - metadataDeriverPath <- getS maybePath + metadataDeriverPath <- getS $ maybePath storeDir digest' <- getS $ digest Base16 let metadataNarHash = System.Nix.Hash.HashAlgo_SHA256 :=> digest' - metadataReferences <- getS $ hashSet storePath + metadataReferences <- getS $ hashSet $ storePath storeDir metadataRegistrationTime <- getS time metadataNarBytes <- (\case @@ -594,19 +541,20 @@ pathMetadata = Serializer pure $ Metadata{..} , putS = \Metadata{..} -> do - putS maybePath metadataDeriverPath + putS (maybePath storeDir) metadataDeriverPath let putNarHash :: DSum HashAlgo Digest - -> SerialT r SError PutM () + -> PutM () putNarHash = \case System.Nix.Hash.HashAlgo_SHA256 :=> d -> putS (digest @SHA256 Base16) d - _ -> throwError SError_NarHashMustBeSHA256 + _ -> error "nar hash must be SHA 256" + -- throwError SError_NarHashMustBeSHA256 putNarHash metadataNarHash - putS (hashSet storePath) metadataReferences + putS (hashSet $ storePath storeDir) metadataReferences putS time metadataRegistrationTime putS int $ Data.Maybe.fromMaybe 0 metadataNarBytes putS storePathTrust metadataTrust @@ -615,21 +563,21 @@ pathMetadata = Serializer } where maybeContentAddress - :: NixSerializer r SError (Maybe ContentAddress) + :: NixSerializer SError (Maybe ContentAddress) maybeContentAddress = mapPrismSerializer - (maybe - (pure Nothing) - $ Data.Bifunctor.bimap - SError_ContentAddress - Just + (maybeAlmostPrism $ AlmostPrism + (ExceptT + . Identity + . Data.Bifunctor.first SError_ContentAddress . System.Nix.ContentAddress.parseContentAddress + ) + System.Nix.ContentAddress.buildContentAddress ) - (fmap System.Nix.ContentAddress.buildContentAddress) maybeText storePathTrust - :: NixSerializer r SError StorePathTrust + :: NixSerializer SError StorePathTrust storePathTrust = mapIsoSerializer (\case False -> BuiltElsewhere; True -> BuiltLocally) @@ -638,44 +586,55 @@ pathMetadata = Serializer -- * OutputName -outputName :: NixSerializer r SError OutputName +outputName :: NixSerializer SError OutputName outputName = - mapPrismSerializer - (Data.Bifunctor.first SError_Name - . System.Nix.OutputName.mkOutputName) - System.Nix.OutputName.unOutputName - text + mapIsoSerializer + System.Nix.OutputName.OutputName + System.Nix.OutputName.unOutputName + storePathName -- * Signatures signature - :: NixSerializer r SError Signature + :: NixSerializer SError Signature signature = mapPrismSerializer - (Data.Bifunctor.first SError_Signature - . Data.Attoparsec.Text.parseOnly - System.Nix.Signature.signatureParser) - (System.Nix.Signature.signatureToText) + (AlmostPrism + (ExceptT + . Identity + . Data.Bifunctor.first SError_Signature + . Data.Attoparsec.Text.parseOnly + System.Nix.Signature.signatureParser) + (System.Nix.Signature.signatureToText) + ) text narSignature - :: NixSerializer r SError NarSignature + :: NixSerializer SError NarSignature narSignature = mapPrismSerializer - (Data.Bifunctor.first SError_Signature - . Data.Attoparsec.Text.parseOnly - System.Nix.Signature.narSignatureParser) - (System.Nix.Signature.narSignatureToText) + (AlmostPrism + (ExceptT + . Identity + . Data.Bifunctor.first SError_Signature + . Data.Attoparsec.Text.parseOnly + System.Nix.Signature.narSignatureParser) + (System.Nix.Signature.narSignatureToText) + ) text -- * Some HashAlgo -someHashAlgo :: NixSerializer r SError (Some HashAlgo) +someHashAlgo :: NixSerializer SError (Some HashAlgo) someHashAlgo = mapPrismSerializer - (Data.Bifunctor.first SError_HashAlgo - . System.Nix.Hash.textToAlgo) - (Data.Some.foldSome System.Nix.Hash.algoToText) + (AlmostPrism + (ExceptT + . Identity + . Data.Bifunctor.first SError_HashAlgo + . System.Nix.Hash.textToAlgo) + (Data.Some.foldSome System.Nix.Hash.algoToText) + ) text -- * Digest @@ -684,20 +643,24 @@ digest :: forall a r . HashAlgorithm a => BaseEncoding - -> NixSerializer r SError (Digest a) -digest base = - mapIsoSerializer - Data.Coerce.coerce - Data.Coerce.coerce - $ mapPrismSerializer - (Data.Bifunctor.first SError_Digest - . System.Nix.Hash.decodeDigestWith @a base) - (System.Nix.Hash.encodeDigestWith base) - $ text + -> NixSerializer SError (Digest a) +digest base = mapPrismSerializer (digestP base) $ text + +digestP + :: forall a + . HashAlgorithm a + => BaseEncoding + -> AlmostPrism (ExceptT SError) Text (Digest a) +digestP base = AlmostPrism + (ExceptT + . Identity + . Data.Bifunctor.first SError_Digest + . System.Nix.Hash.decodeDigestWith @a base) + (System.Nix.Hash.encodeDigestWith base) -- * DSum HashAlgo Digest -namedDigest :: NixSerializer r SError (DSum HashAlgo Digest) +namedDigest :: NixSerializer SError (DSum HashAlgo Digest) namedDigest = Serializer { getS = do sriHash <- getS text @@ -718,20 +681,22 @@ namedDigest = Serializer } derivationOutput - :: HasStoreDir r - => NixSerializer r SError DerivationOutput -derivationOutput = Serializer + :: StoreDir + -> NixSerializer SError DerivationOutput +derivationOutput storeDir = Serializer { getS = do - mPath <- getS maybePath + mPath <- getS $ maybePath storeDir mHashAlgo <- getS maybeText mHash <- getS maybeText case (mPath, mHashAlgo, mHash) of (Just path, Nothing, Nothing) -> pure InputAddressedDerivationOutput {..} (Just path, Just hashAlgo, Just hash) -> - pure FixedDerivationOutput {..} + error "TODO" + -- pure FixedDerivationOutput {..} (Nothing, Just hashAlgo, Nothing) -> - pure ContentAddressedDerivationOutput {..} + error "TODO" + -- pure ContentAddressedDerivationOutput {..} _ -> throwError $ SError_DerivationOutputInvalidCombo (Data.Maybe.isJust mPath) @@ -739,36 +704,38 @@ derivationOutput = Serializer (Data.Maybe.isJust mHash) , putS = \case InputAddressedDerivationOutput{..} -> do - putS storePath path + putS (storePath storeDir) path putS text Data.Text.empty putS text Data.Text.empty FixedDerivationOutput{..} -> do - putS storePath path - putS text hashAlgo - putS text hash + pure () + --putS storePath path + --putS text hashAlgo + --putS text hash ContentAddressedDerivationOutput{..} -> do - putS text Data.Text.empty - putS text hashAlgo - putS text Data.Text.empty + pure () + --putS text Data.Text.empty + --putS text hashAlgo + --putS text Data.Text.empty } -- * Derivation basicDerivation - :: HasStoreDir r - => NixSerializer r SError BasicDerivation -basicDerivation = Serializer + :: StoreDir + -> NixSerializer SError BasicDerivation +basicDerivation storeDir = Serializer { getS = do - outputs <- getS (mapS text derivationOutput) - inputs <- getS (set storePath) + outputs <- getS $ mapS text $ derivationOutput storeDir + inputs <- getS $ set $ storePath storeDir platform <- getS text builder <- getS text - args <- getS (vector text) - env <- getS (mapS text text) + args <- getS $ vector text + env <- getS $ mapS text text pure Derivation{..} , putS = \Derivation{..} -> do - putS (mapS text derivationOutput) outputs - putS (set storePath) inputs + putS (mapS text $ derivationOutput storeDir) outputs + putS (set $ storePath storeDir) inputs putS text platform putS text builder putS (vector text) args @@ -778,46 +745,42 @@ basicDerivation = Serializer -- * DerivedPath derivedPathNew - :: HasStoreDir r - => NixSerializer r SError DerivedPath -derivedPathNew = Serializer + :: StoreDir + -> NixSerializer SError DerivedPath +derivedPathNew storeDir = Serializer { getS = do - root <- Control.Monad.Reader.asks hasStoreDir p <- getS text - case System.Nix.DerivedPath.parseDerivedPath root p of + case System.Nix.DerivedPath.parseDerivedPath storeDir p of Left err -> throwError $ SError_DerivedPath err Right x -> pure x , putS = \d -> do - root <- Control.Monad.Reader.asks hasStoreDir - putS text (System.Nix.DerivedPath.derivedPathToText root d) + putS text (System.Nix.DerivedPath.derivedPathToText storeDir d) } derivedPath - :: ( HasProtoVersion r - , HasStoreDir r - ) - => NixSerializer r SError DerivedPath -derivedPath = Serializer - { getS = do - pv <- Control.Monad.Reader.asks hasProtoVersion + :: StoreDir + -> ProtoVersion + -> NixSerializer SError DerivedPath +derivedPath storeDir pv = Serializer + { getS = if pv < ProtoVersion 1 30 - then DerivedPath_Opaque <$> getS storePath - else getS derivedPathNew - , putS = \d -> do - pv <- Control.Monad.Reader.asks hasProtoVersion + then DerivedPath_Opaque <$> getS (storePath storeDir) + else getS $ derivedPathNew storeDir + , putS = \d -> if pv < ProtoVersion 1 30 then case d of - DerivedPath_Opaque p -> putS storePath p - _ -> throwError - $ SError_NotYetImplemented - "DerivedPath_Built" - (ForPV_Older pv) - else putS derivedPathNew d + DerivedPath_Opaque p -> putS (storePath storeDir) p + _ -> error "not yet implemented" + -- throwError + -- $ SError_NotYetImplemented + -- "DerivedPath_Built" + -- (ForPV_Older pv) + else putS (derivedPathNew storeDir) d } -- * Build -buildMode :: NixSerializer r SError BuildMode +buildMode :: NixSerializer SError BuildMode buildMode = enum -- * Logger @@ -832,11 +795,11 @@ data LoggerSError mapPrimE :: Functor m - => SerialT r SError m a - -> SerialT r LoggerSError m a -mapPrimE = mapErrorST LoggerSError_Prim + => ExceptT SError m a + -> ExceptT LoggerSError m a +mapPrimE = withExceptT LoggerSError_Prim -maybeActivity :: NixSerializer r LoggerSError (Maybe Activity) +maybeActivity :: NixSerializer LoggerSError (Maybe Activity) maybeActivity = Serializer { getS = getS (int @Int) >>= \case 0 -> pure Nothing @@ -846,22 +809,22 @@ maybeActivity = Serializer Just act -> putS activity act } -activity :: NixSerializer r LoggerSError Activity +activity :: NixSerializer LoggerSError Activity activity = Serializer { getS = mapPrimE $ getS int >>= toEnumCheckBoundsM . (+(-100)) , putS = putS int . (+100) . fromEnum } -activityID :: NixSerializer r LoggerSError ActivityID +activityID :: NixSerializer LoggerSError ActivityID activityID = mapIsoSerializer ActivityID unActivityID int -activityResult :: NixSerializer r LoggerSError ActivityResult +activityResult :: NixSerializer LoggerSError ActivityResult activityResult = Serializer { getS = mapPrimE $ getS int >>= toEnumCheckBoundsM . (+(-100)) , putS = putS int . (+100) . fromEnum } -field :: NixSerializer r LoggerSError Field +field :: NixSerializer LoggerSError Field field = Serializer { getS = getS (int @Word8) >>= \case 0 -> Field_LogInt <$> getS int @@ -869,10 +832,10 @@ field = Serializer x -> throwError $ LoggerSError_UnknownLogFieldType x , putS = \case Field_LogInt x -> putS int (0 :: Word8) >> putS int x - Field_LogStr x -> putS int (1 :: Word8) >> mapPrimE (putS text x) + Field_LogStr x -> putS int (1 :: Word8) >> putS text x } -trace :: NixSerializer r LoggerSError Trace +trace :: NixSerializer LoggerSError Trace trace = Serializer { getS = do tracePosition <- (\case 0 -> Nothing; x -> Just x) <$> getS (int @Int) @@ -880,10 +843,10 @@ trace = Serializer pure Trace{..} , putS = \Trace{..} -> do putS int $ Data.Maybe.fromMaybe 0 tracePosition - mapPrimE $ putS text traceHint + putS text traceHint } -basicError :: NixSerializer r LoggerSError BasicError +basicError :: NixSerializer LoggerSError BasicError basicError = Serializer { getS = do basicErrorMessage <- mapPrimE $ getS text @@ -891,11 +854,11 @@ basicError = Serializer pure BasicError{..} , putS = \BasicError{..} -> do - mapPrimE $ putS text basicErrorMessage + putS text basicErrorMessage putS int basicErrorExitStatus } -errorInfo :: NixSerializer r LoggerSError ErrorInfo +errorInfo :: NixSerializer LoggerSError ErrorInfo errorInfo = Serializer { getS = do etyp <- mapPrimE $ getS text @@ -910,17 +873,17 @@ errorInfo = Serializer pure ErrorInfo{..} , putS = \ErrorInfo{..} -> do - mapPrimE $ do + do putS text $ Data.Text.pack "Error" putS verbosity errorInfoLevel - mapPrimE $ do + do putS text $ Data.Text.pack "Error" -- removed error name putS text errorInfoMessage putS int $ Data.Maybe.fromMaybe 0 errorInfoPosition putS (list trace) errorInfoTraces } -loggerOpCode :: NixSerializer r LoggerSError LoggerOpCode +loggerOpCode :: NixSerializer LoggerSError LoggerOpCode loggerOpCode = Serializer { getS = do c <- getS int @@ -932,9 +895,9 @@ loggerOpCode = Serializer } logger - :: HasProtoVersion r - => NixSerializer r LoggerSError Logger -logger = Serializer + :: ProtoVersion + -> NixSerializer LoggerSError Logger +logger pv = Serializer { getS = getS loggerOpCode >>= \case LoggerOpCode_Next -> mapPrimE $ @@ -951,7 +914,6 @@ logger = Serializer pure Logger_Last LoggerOpCode_Error -> do - pv <- Control.Monad.Reader.asks hasProtoVersion Logger_Error <$> if protoVersion_minor pv >= 26 then Right <$> getS errorInfo @@ -979,7 +941,7 @@ logger = Serializer , putS = \case Logger_Next s -> do putS loggerOpCode LoggerOpCode_Next - mapPrimE $ putS text s + putS text s Logger_Read i -> do putS loggerOpCode LoggerOpCode_Read @@ -987,7 +949,7 @@ logger = Serializer Logger_Write s -> do putS loggerOpCode LoggerOpCode_Write - mapPrimE $ putS byteString s + putS byteString s Logger_Last -> putS loggerOpCode LoggerOpCode_Last @@ -995,12 +957,12 @@ logger = Serializer Logger_Error basicOrInfo -> do putS loggerOpCode LoggerOpCode_Error - minor <- protoVersion_minor <$> Control.Monad.Reader.asks hasProtoVersion + let minor = protoVersion_minor pv case basicOrInfo of - Left _ | minor >= 26 -> throwError $ LoggerSError_TooNewForBasicError + Left _ | minor >= 26 -> error "protocol too new" -- throwError $ LoggerSError_TooNewForBasicError Left e | otherwise -> putS basicError e - Right _ | minor < 26 -> throwError $ LoggerSError_TooOldForErrorInfo + Right _ | minor < 26 -> error "protocol too old" -- throwError $ LoggerSError_TooOldForErrorInfo Right e -> putS errorInfo e Logger_StartActivity{..} -> do @@ -1008,8 +970,7 @@ logger = Serializer putS activityID startActivityID putS verbosity startActivityVerbosity putS maybeActivity startActivityType - mapPrimE $ - putS byteString startActivityString + putS byteString startActivityString putS (list field) startActivityFields putS activityID startActivityParentID @@ -1024,10 +985,10 @@ logger = Serializer putS (list field) resultFields } -verbosity :: NixSerializer r LoggerSError Verbosity +verbosity :: NixSerializer LoggerSError Verbosity verbosity = Serializer { getS = mapPrimE $ getS enum - , putS = mapPrimE . putS enum + , putS = putS enum } -- * Handshake @@ -1037,7 +998,7 @@ data HandshakeSError | HandshakeSError_InvalidTrustedFlag Word8 deriving (Eq, Ord, Generic, Show) -workerMagic :: NixSerializer r HandshakeSError WorkerMagic +workerMagic :: NixSerializer HandshakeSError WorkerMagic workerMagic = Serializer { getS = do c <- getS int @@ -1048,7 +1009,7 @@ workerMagic = Serializer , putS = putS int . workerMagicToWord64 } -trustedFlag :: NixSerializer r HandshakeSError (Maybe TrustedFlag) +trustedFlag :: NixSerializer HandshakeSError (Maybe TrustedFlag) trustedFlag = Serializer { getS = do n :: Word8 <- getS int @@ -1065,7 +1026,7 @@ trustedFlag = Serializer -- * Worker protocol -storeText :: NixSerializer r SError StoreText +storeText :: NixSerializer SError StoreText storeText = Serializer { getS = do storeTextName <- getS storePathName @@ -1076,7 +1037,7 @@ storeText = Serializer putS text storeTextText } -workerOp :: NixSerializer r SError WorkerOp +workerOp :: NixSerializer SError WorkerOp workerOp = enum -- * Request @@ -1085,17 +1046,15 @@ data RequestSError = RequestSError_NotYetImplemented WorkerOp | RequestSError_ReservedOp WorkerOp | RequestSError_PrimGet SError - | RequestSError_PrimPut SError | RequestSError_PrimWorkerOp SError deriving (Eq, Ord, Generic, Show) storeRequest - :: ( HasProtoVersion r - , HasStoreDir r - ) - => NixSerializer r RequestSError (Some StoreRequest) -storeRequest = Serializer - { getS = mapErrorST RequestSError_PrimWorkerOp (getS workerOp) >>= \case + :: StoreDir + -> ProtoVersion + -> NixSerializer RequestSError (Some StoreRequest) +storeRequest storeDir pv = Serializer + { getS = withExceptT RequestSError_PrimWorkerOp (getS workerOp) >>= \case WorkerOp_AddToStore -> mapGetE $ do pathName <- getS storePathName _fixed <- getS bool -- obsolete @@ -1108,8 +1067,8 @@ storeRequest = Serializer pure $ Some (AddToStore pathName recursive hashAlgo repair) WorkerOp_AddToStoreNar -> mapGetE $ do - storePath' <- getS storePath - metadata <- getS pathMetadata + storePath' <- getS $ storePath storeDir + metadata <- getS $ pathMetadata storeDir repair <- getS bool let repairMode = if repair then RepairMode_DoRepair else RepairMode_DontRepair dontCheckSigs <- getS bool @@ -1119,35 +1078,35 @@ storeRequest = Serializer WorkerOp_AddTextToStore -> mapGetE $ do txt <- getS storeText - paths <- getS (hashSet storePath) + paths <- getS $ hashSet $ storePath storeDir let repair = RepairMode_DontRepair pure $ Some (AddTextToStore txt paths repair) WorkerOp_AddSignatures -> mapGetE $ do - path <- getS storePath + path <- getS $ storePath storeDir signatures <- getS (set signature) pure $ Some (AddSignatures path signatures) WorkerOp_AddIndirectRoot -> mapGetE $ do - Some . AddIndirectRoot <$> getS storePath + Some . AddIndirectRoot <$> getS (storePath storeDir) WorkerOp_AddTempRoot -> mapGetE $ do - Some . AddTempRoot <$> getS storePath + Some . AddTempRoot <$> getS (storePath storeDir) WorkerOp_BuildPaths -> mapGetE $ do - derived <- getS (set derivedPath) + derived <- getS (set $ derivedPath storeDir pv) buildMode' <- getS buildMode pure $ Some (BuildPaths derived buildMode') WorkerOp_BuildDerivation -> mapGetE $ do - path <- getS storePath - drv <- getS basicDerivation + path <- getS $ storePath storeDir + drv <- getS $ basicDerivation storeDir buildMode' <- getS buildMode pure $ Some (BuildDerivation path drv buildMode') WorkerOp_CollectGarbage -> mapGetE $ do gcOptionsOperation <- getS enum - gcOptionsPathsToDelete <- getS (hashSet storePath) + gcOptionsPathsToDelete <- getS (hashSet $ storePath storeDir) gcOptionsIgnoreLiveness <- getS bool gcOptionsMaxFreed <- getS int -- obsolete fields @@ -1156,19 +1115,19 @@ storeRequest = Serializer pure $ Some (CollectGarbage GCOptions{..}) WorkerOp_EnsurePath -> mapGetE $ do - Some . EnsurePath <$> getS storePath + Some . EnsurePath <$> getS (storePath storeDir) WorkerOp_FindRoots -> mapGetE $ do pure $ Some FindRoots WorkerOp_IsValidPath -> mapGetE $ do - Some . IsValidPath <$> getS storePath + Some . IsValidPath <$> getS (storePath storeDir) WorkerOp_NarFromPath -> mapGetE $ do - Some . NarFromPath <$> getS storePath + Some . NarFromPath <$> getS (storePath storeDir) WorkerOp_QueryValidPaths -> mapGetE $ do - paths <- getS (hashSet storePath) + paths <- getS (hashSet $ storePath storeDir) substituteMode <- getS enum pure $ Some (QueryValidPaths paths substituteMode) @@ -1176,28 +1135,28 @@ storeRequest = Serializer pure $ Some QueryAllValidPaths WorkerOp_QuerySubstitutablePaths -> mapGetE $ do - Some . QuerySubstitutablePaths <$> getS (hashSet storePath) + Some . QuerySubstitutablePaths <$> getS (hashSet $ storePath storeDir) WorkerOp_QueryPathInfo -> mapGetE $ do - Some . QueryPathInfo <$> getS storePath + Some . QueryPathInfo <$> getS (storePath storeDir) WorkerOp_QueryReferrers -> mapGetE $ do - Some . QueryReferrers <$> getS storePath + Some . QueryReferrers <$> getS (storePath storeDir) WorkerOp_QueryValidDerivers -> mapGetE $ do - Some . QueryValidDerivers <$> getS storePath + Some . QueryValidDerivers <$> getS (storePath storeDir) WorkerOp_QueryDerivationOutputs -> mapGetE $ do - Some . QueryDerivationOutputs <$> getS storePath + Some . QueryDerivationOutputs <$> getS (storePath storeDir) WorkerOp_QueryDerivationOutputNames -> mapGetE $ do - Some . QueryDerivationOutputNames <$> getS storePath + Some . QueryDerivationOutputNames <$> getS (storePath storeDir) WorkerOp_QueryPathFromHashPart -> mapGetE $ do Some . QueryPathFromHashPart <$> getS storePathHashPart WorkerOp_QueryMissing -> mapGetE $ do - Some . QueryMissing <$> getS (set derivedPath) + Some . QueryMissing <$> getS (set $ derivedPath storeDir pv) WorkerOp_OptimiseStore -> mapGetE $ do pure $ Some OptimiseStore @@ -1235,7 +1194,7 @@ storeRequest = Serializer w@WorkerOp_SetOptions -> notYet w , putS = \case - Some (AddToStore pathName recursive hashAlgo _repair) -> mapPutE $ do + Some (AddToStore pathName recursive hashAlgo _repair) -> do putS workerOp WorkerOp_AddToStore putS storePathName pathName @@ -1248,121 +1207,121 @@ storeRequest = Serializer putS bool (recursive == FileIngestionMethod_NixArchive) putS someHashAlgo hashAlgo - Some (AddToStoreNar storePath' metadata repair checkSigs) -> mapPutE $ do + Some (AddToStoreNar storePath' metadata repair checkSigs) -> do putS workerOp WorkerOp_AddToStoreNar - putS storePath storePath' - putS pathMetadata metadata + putS (storePath storeDir) storePath' + putS (pathMetadata storeDir) metadata putS bool $ repair == RepairMode_DoRepair putS bool $ checkSigs == CheckMode_DontCheck - Some (AddTextToStore txt paths _repair) -> mapPutE $ do + Some (AddTextToStore txt paths _repair) -> do putS workerOp WorkerOp_AddTextToStore putS storeText txt - putS (hashSet storePath) paths + putS (hashSet $ storePath storeDir) paths - Some (AddSignatures path signatures) -> mapPutE $ do + Some (AddSignatures path signatures) -> do putS workerOp WorkerOp_AddSignatures - putS storePath path + putS (storePath storeDir) path putS (set signature) signatures - Some (AddIndirectRoot path) -> mapPutE $ do + Some (AddIndirectRoot path) -> do putS workerOp WorkerOp_AddIndirectRoot - putS storePath path + putS (storePath storeDir) path - Some (AddTempRoot path) -> mapPutE $ do + Some (AddTempRoot path) -> do putS workerOp WorkerOp_AddTempRoot - putS storePath path + putS (storePath storeDir) path - Some (BuildPaths derived buildMode') -> mapPutE $ do + Some (BuildPaths derived buildMode') -> do putS workerOp WorkerOp_BuildPaths - putS (set derivedPath) derived + putS (set $ derivedPath storeDir pv) derived putS buildMode buildMode' - Some (BuildDerivation path drv buildMode') -> mapPutE $ do + Some (BuildDerivation path drv buildMode') -> do putS workerOp WorkerOp_BuildDerivation - putS storePath path - putS basicDerivation drv + putS (storePath storeDir) path + putS (basicDerivation storeDir) drv putS buildMode buildMode' - Some (CollectGarbage GCOptions{..}) -> mapPutE $ do + Some (CollectGarbage GCOptions{..}) -> do putS workerOp WorkerOp_CollectGarbage putS enum gcOptionsOperation - putS (hashSet storePath) gcOptionsPathsToDelete + putS (hashSet $ storePath storeDir) gcOptionsPathsToDelete putS bool gcOptionsIgnoreLiveness putS int gcOptionsMaxFreed -- obsolete fields Control.Monad.forM_ [0..(2 :: Word8)] $ pure $ putS int (0 :: Word8) - Some (EnsurePath path) -> mapPutE $ do + Some (EnsurePath path) -> do putS workerOp WorkerOp_EnsurePath - putS storePath path + putS (storePath storeDir) path - Some FindRoots -> mapPutE $ do + Some FindRoots -> do putS workerOp WorkerOp_FindRoots - Some (IsValidPath path) -> mapPutE $ do + Some (IsValidPath path) -> do putS workerOp WorkerOp_IsValidPath - putS storePath path + putS (storePath storeDir) path - Some (NarFromPath path) -> mapPutE $ do + Some (NarFromPath path) -> do putS workerOp WorkerOp_NarFromPath - putS storePath path + putS (storePath storeDir) path - Some (QueryValidPaths paths substituteMode) -> mapPutE $ do + Some (QueryValidPaths paths substituteMode) -> do putS workerOp WorkerOp_QueryValidPaths - putS (hashSet storePath) paths + putS (hashSet $ storePath storeDir) paths putS enum substituteMode - Some QueryAllValidPaths -> mapPutE $ do + Some QueryAllValidPaths -> do putS workerOp WorkerOp_QueryAllValidPaths - Some (QuerySubstitutablePaths paths) -> mapPutE $ do + Some (QuerySubstitutablePaths paths) -> do putS workerOp WorkerOp_QuerySubstitutablePaths - putS (hashSet storePath) paths + putS (hashSet $ storePath storeDir) paths - Some (QueryPathInfo path) -> mapPutE $ do + Some (QueryPathInfo path) -> do putS workerOp WorkerOp_QueryPathInfo - putS storePath path + putS (storePath storeDir) path - Some (QueryReferrers path) -> mapPutE $ do + Some (QueryReferrers path) -> do putS workerOp WorkerOp_QueryReferrers - putS storePath path + putS (storePath storeDir) path - Some (QueryValidDerivers path) -> mapPutE $ do + Some (QueryValidDerivers path) -> do putS workerOp WorkerOp_QueryValidDerivers - putS storePath path + putS (storePath storeDir) path - Some (QueryDerivationOutputs path) -> mapPutE $ do + Some (QueryDerivationOutputs path) -> do putS workerOp WorkerOp_QueryDerivationOutputs - putS storePath path + putS (storePath storeDir) path - Some (QueryDerivationOutputNames path) -> mapPutE $ do + Some (QueryDerivationOutputNames path) -> do putS workerOp WorkerOp_QueryDerivationOutputNames - putS storePath path + putS (storePath storeDir) path - Some (QueryPathFromHashPart pathHashPart) -> mapPutE $ do + Some (QueryPathFromHashPart pathHashPart) -> do putS workerOp WorkerOp_QueryPathFromHashPart putS storePathHashPart pathHashPart - Some (QueryMissing derived) -> mapPutE $ do + Some (QueryMissing derived) -> do putS workerOp WorkerOp_QueryMissing - putS (set derivedPath) derived + putS (set $ derivedPath storeDir pv) derived - Some OptimiseStore -> mapPutE $ do + Some OptimiseStore -> do putS workerOp WorkerOp_OptimiseStore - Some SyncWithGC -> mapPutE $ do + Some SyncWithGC -> do putS workerOp WorkerOp_SyncWithGC - Some (VerifyStore checkMode repairMode) -> mapPutE $ do + Some (VerifyStore checkMode repairMode) -> do putS workerOp WorkerOp_VerifyStore putS enum checkMode putS enum repairMode @@ -1370,15 +1329,9 @@ storeRequest = Serializer where mapGetE :: Functor m - => SerialT r SError m a - -> SerialT r RequestSError m a - mapGetE = mapErrorST RequestSError_PrimGet - - mapPutE - :: Functor m - => SerialT r SError m a - -> SerialT r RequestSError m a - mapPutE = mapErrorST RequestSError_PrimPut + => ExceptT SError m a + -> ExceptT RequestSError m a + mapGetE = withExceptT RequestSError_PrimGet notYet :: MonadError RequestSError m @@ -1396,7 +1349,6 @@ storeRequest = Serializer data ReplySError = ReplySError_PrimGet SError - | ReplySError_PrimPut SError | ReplySError_DerivationOutput SError | ReplySError_GCResult SError | ReplySError_Metadata SError @@ -1408,20 +1360,14 @@ data ReplySError mapGetER :: Functor m - => SerialT r SError m a - -> SerialT r ReplySError m a -mapGetER = mapErrorST ReplySError_PrimGet - -mapPutER - :: Functor m - => SerialT r SError m a - -> SerialT r ReplySError m a -mapPutER = mapErrorST ReplySError_PrimPut + => ExceptT SError m a + -> ExceptT ReplySError m a +mapGetER = withExceptT ReplySError_PrimGet -- | Parse a bool returned at the end of simple operations. -- This is always 1 (@True@) so we assert that it really is so. -- Errors for these operations are indicated via @Logger_Error@. -opSuccess :: NixSerializer r ReplySError SuccessCodeReply +opSuccess :: NixSerializer ReplySError SuccessCodeReply opSuccess = Serializer { getS = do retCode <- mapGetER $ getS bool @@ -1429,10 +1375,10 @@ opSuccess = Serializer (retCode == True) $ throwError ReplySError_UnexpectedFalseOpSuccess pure SuccessCodeReply - , putS = \_ -> mapPutER $ putS bool True + , putS = \_ -> putS bool True } -noop :: a -> NixSerializer r ReplySError a +noop :: a -> NixSerializer ReplySError a noop ret = Serializer { getS = pure ret , putS = \_ -> pure () @@ -1440,37 +1386,38 @@ noop ret = Serializer -- *** Realisation -derivationOutputTyped :: NixSerializer r ReplySError (System.Nix.Realisation.DerivationOutput OutputName) +derivationOutputTyped :: NixSerializer ReplySError (System.Nix.Realisation.DerivationOutput OutputName) derivationOutputTyped = mapErrorS ReplySError_DerivationOutput $ mapPrismSerializer - ( Data.Bifunctor.first SError_DerivationOutput + AlmostPrism + { _almostPrism_get = + ExceptT + . Identity + . Data.Bifunctor.first SError_DerivationOutput . System.Nix.Realisation.derivationOutputParser System.Nix.OutputName.mkOutputName - ) - ( Data.Text.Lazy.toStrict + , _almostPrism_put = + Data.Text.Lazy.toStrict . Data.Text.Lazy.Builder.toLazyText . System.Nix.Realisation.derivationOutputBuilder - System.Nix.OutputName.unOutputName - ) + (System.Nix.StorePath.unStorePathName . System.Nix.OutputName.unOutputName) + } text -realisation :: NixSerializer r ReplySError Realisation +realisation :: NixSerializer ReplySError Realisation realisation = mapErrorS ReplySError_Realisation json -realisationWithId :: NixSerializer r ReplySError RealisationWithId +realisationWithId :: NixSerializer ReplySError RealisationWithId realisationWithId = mapErrorS ReplySError_RealisationWithId json -- *** BuildResult buildResult - :: ( HasProtoVersion r - , HasStoreDir r - ) - => NixSerializer r ReplySError BuildResult -buildResult = Serializer + :: StoreDir + -> ProtoVersion + -> NixSerializer ReplySError BuildResult +buildResult storeDir pv = Serializer { getS = do - pv <- Control.Monad.Reader.asks hasProtoVersion - buildResultStatus <- mapGetER $ getS enum buildResultErrorMessage <- mapGetER $ getS maybeText @@ -1500,11 +1447,9 @@ buildResult = Serializer pure BuildResult{..} , putS = \BuildResult{..} -> do - pv <- Control.Monad.Reader.asks hasProtoVersion - - mapPutER $ putS enum buildResultStatus - mapPutER $ putS maybeText buildResultErrorMessage - Control.Monad.when (protoVersion_minor pv >= 29) $ mapPutER $ do + putS enum buildResultStatus + putS maybeText buildResultErrorMessage + Control.Monad.when (protoVersion_minor pv >= 29) $ do putS int $ Data.Maybe.fromMaybe 0 buildResultTimesBuilt putS bool $ Data.Maybe.fromMaybe False buildResultIsNonDeterministic putS time $ Data.Maybe.fromMaybe t0 buildResultStartTime @@ -1523,29 +1468,29 @@ buildResult = Serializer -- *** GCResult gcResult - :: HasStoreDir r - => NixSerializer r ReplySError GCResult -gcResult = mapErrorS ReplySError_GCResult $ Serializer + :: StoreDir + -> NixSerializer ReplySError GCResult +gcResult storeDir = mapErrorS ReplySError_GCResult $ Serializer { getS = do - gcResultDeletedPaths <- getS (hashSet storePath) + gcResultDeletedPaths <- getS (hashSet $ storePath storeDir) gcResultBytesFreed <- getS int Control.Monad.void $ getS (int @Word64) -- obsolete pure GCResult{..} , putS = \GCResult{..} -> do - putS (hashSet storePath) gcResultDeletedPaths + putS (hashSet $ storePath storeDir) gcResultDeletedPaths putS int gcResultBytesFreed putS (int @Word64) 0 -- obsolete } -- *** GCRoot -gcRoot :: NixSerializer r ReplySError GCRoot +gcRoot :: NixSerializer ReplySError GCRoot gcRoot = Serializer { getS = mapGetER $ do getS byteString >>= \case p | p == censored -> pure GCRoot_Censored p -> pure (GCRoot_Path p) - , putS = mapPutER . putS byteString . \case + , putS = putS byteString . \case GCRoot_Censored -> censored GCRoot_Path p -> p } @@ -1554,21 +1499,21 @@ gcRoot = Serializer -- *** Missing missing - :: HasStoreDir r - => NixSerializer r ReplySError Missing -missing = mapErrorS ReplySError_Missing $ Serializer + :: StoreDir + -> NixSerializer ReplySError Missing +missing storeDir = mapErrorS ReplySError_Missing $ Serializer { getS = do - missingWillBuild <- getS (hashSet storePath) - missingWillSubstitute <- getS (hashSet storePath) - missingUnknownPaths <- getS (hashSet storePath) + missingWillBuild <- getS (hashSet $ storePath storeDir) + missingWillSubstitute <- getS (hashSet $ storePath storeDir) + missingUnknownPaths <- getS (hashSet $ storePath storeDir) missingDownloadSize <- getS int missingNarSize <- getS int pure Missing{..} , putS = \Missing{..} -> do - putS (hashSet storePath) missingWillBuild - putS (hashSet storePath) missingWillSubstitute - putS (hashSet storePath) missingUnknownPaths + putS (hashSet $ storePath storeDir) missingWillBuild + putS (hashSet $ storePath storeDir) missingWillSubstitute + putS (hashSet $ storePath storeDir) missingUnknownPaths putS int missingDownloadSize putS int missingNarSize } @@ -1576,15 +1521,15 @@ missing = mapErrorS ReplySError_Missing $ Serializer -- *** Maybe (Metadata StorePath) maybePathMetadata - :: HasStoreDir r - => NixSerializer r ReplySError (Maybe (Metadata StorePath)) -maybePathMetadata = mapErrorS ReplySError_Metadata $ Serializer + :: StoreDir + -> NixSerializer ReplySError (Maybe (Metadata StorePath)) +maybePathMetadata storeDir = mapErrorS ReplySError_Metadata $ Serializer { getS = do valid <- getS bool if valid - then pure <$> getS pathMetadata + then pure <$> getS (pathMetadata storeDir) else pure Nothing , putS = \case Nothing -> putS bool False - Just pm -> putS bool True >> putS pathMetadata pm + Just pm -> putS bool True >> putS (pathMetadata storeDir) pm } diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Socket.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Socket.hs index 8c321529..f021628a 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Socket.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Socket.hs @@ -1,13 +1,14 @@ module System.Nix.Store.Remote.Socket where import Control.Monad.Except (MonadError, throwError) +import Control.Monad.Trans.Except (runExceptT) import Control.Monad.IO.Class (MonadIO(..)) import Data.ByteString (ByteString) import Data.Serialize.Get (Get, Result(..)) import Data.Serialize.Put (Put, runPut) import Network.Socket.ByteString (recv, sendAll) import System.Nix.Store.Remote.MonadStore (MonadRemoteStore(..), RemoteStoreError(..)) -import System.Nix.Store.Remote.Serializer (NixSerializer, runP, runSerialT) +import System.Nix.Store.Remote.Serializer (NixSerializer, runP) import System.Nix.Store.Remote.Types (ProtoStoreConfig) import qualified Control.Exception @@ -73,15 +74,13 @@ sockPutS :: ( MonadRemoteStore m , MonadError e m ) - => NixSerializer ProtoStoreConfig e a + => NixSerializer e a -> a -> m () sockPutS s a = do - cfg <- getConfig sock <- getStoreSocket - case runP s cfg a of - Right x -> liftIO $ sendAll sock x - Left e -> throwError e + let x = runP s a + liftIO $ sendAll sock x sockGetS :: ( MonadRemoteStore m @@ -89,12 +88,11 @@ sockGetS , Show a , Show e ) - => NixSerializer ProtoStoreConfig e a + => NixSerializer e a -> m a sockGetS s = do - cfg <- getConfig res <- genericIncremental sockGet8 - $ runSerialT cfg $ Data.Serializer.getS s + $ runExceptT $ Data.Serializer.getS s case res of Right x -> pure x diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Types/StoreReply.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Types/StoreReply.hs deleted file mode 100644 index 33108210..00000000 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Types/StoreReply.hs +++ /dev/null @@ -1,61 +0,0 @@ -module System.Nix.Store.Remote.Types.StoreReply - ( StoreReply(..) - ) where - -import Data.HashSet (HashSet) -import Data.Map (Map) -import System.Nix.Build (BuildResult) -import System.Nix.StorePath (StorePath, StorePathName) -import System.Nix.StorePath.Metadata (Metadata) -import System.Nix.Store.Remote.Serializer -import System.Nix.Store.Remote.Types.NoReply (NoReply(..)) -import System.Nix.Store.Remote.Types.SuccessCodeReply (SuccessCodeReply) -import System.Nix.Store.Remote.Types.GC (GCResult, GCRoot) -import System.Nix.Store.Remote.Types.Query.Missing (Missing) -import System.Nix.Store.Remote.Types.StoreConfig (ProtoStoreConfig) - --- | Get @NixSerializer@ for some type @a@ --- This could also be generalized for every type --- we have a serializer for but we mostly need --- this for replies and it would make look serializers --- quite hodor, like @a <- getS get; b <- getS get@ -class StoreReply a where - getReplyS :: NixSerializer ProtoStoreConfig ReplySError a - -instance StoreReply SuccessCodeReply where - getReplyS = opSuccess - -instance StoreReply NoReply where - getReplyS = noop NoReply - -instance StoreReply Bool where - getReplyS = mapPrimE bool - -instance StoreReply BuildResult where - getReplyS = buildResult - -instance StoreReply GCResult where - getReplyS = gcResult - -instance StoreReply (Map GCRoot StorePath) where - getReplyS = mapS gcRoot (mapPrimE storePath) - -instance StoreReply Missing where - getReplyS = missing - -instance StoreReply (Maybe (Metadata StorePath)) where - getReplyS = maybePathMetadata - -instance StoreReply StorePath where - getReplyS = mapPrimE storePath - -instance StoreReply (HashSet StorePath) where - getReplyS = mapPrimE (hashSet storePath) - -instance StoreReply (HashSet StorePathName) where - getReplyS = mapPrimE (hashSet storePathName) - -mapPrimE - :: NixSerializer r SError a - -> NixSerializer r ReplySError a -mapPrimE = mapErrorS ReplySError_PrimGet From 115af91bcb4672d8dfdbad77a370b69d9b367141 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 25 Dec 2024 00:30:25 -0500 Subject: [PATCH 49/58] Progress on `hnix-core-aterm` --- hnix-store-aterm/hnix-store-aterm.cabal | 17 ++- .../Nix/Derivation/ATerm.hs} | 13 +- .../Nix/Derivation/ATerm}/Builder.hs | 116 ++++++++------- .../Nix/Derivation/ATerm}/Parser.hs | 137 ++++++++++-------- hnix-store-aterm/tests/Property.hs | 12 +- hnix-store-core/src/System/Nix/Derivation.hs | 2 +- .../src/System/Nix/Derivation/Aterm.hs | 75 ---------- hnix-store-remote/hnix-store-remote.cabal | 1 + .../src/System/Nix/Store/Remote/Client.hs | 3 +- .../System/Nix/Store/Remote/Types/WorkerOp.hs | 2 +- hnix-store-remote/tests/EnumSpec.hs | 2 +- 11 files changed, 167 insertions(+), 213 deletions(-) rename hnix-store-aterm/src/{Nix/Derivation.hs => System/Nix/Derivation/ATerm.hs} (95%) rename hnix-store-aterm/src/{Nix/Derivation => System/Nix/Derivation/ATerm}/Builder.hs (52%) rename hnix-store-aterm/src/{Nix/Derivation => System/Nix/Derivation/ATerm}/Parser.hs (54%) delete mode 100644 hnix-store-core/src/System/Nix/Derivation/Aterm.hs diff --git a/hnix-store-aterm/hnix-store-aterm.cabal b/hnix-store-aterm/hnix-store-aterm.cabal index 1b2e4d4a..e799fd34 100644 --- a/hnix-store-aterm/hnix-store-aterm.cabal +++ b/hnix-store-aterm/hnix-store-aterm.cabal @@ -33,20 +33,23 @@ Library Default-Language: Haskell2010 Hs-Source-Dirs: src Build-Depends: - base >= 4.6.0.0 && < 5 , attoparsec >= 0.12.0.0 && < 0.15, + base >= 4.6.0.0 && < 5 , + constraints-extras, containers < 0.8 , deepseq >= 1.4.0.0 && < 1.6 , + dependent-sum, + hnix-store-core, + monoidal-containers, + some, text >= 0.8.0.0 && < 2.2 , these, - vector < 0.14, - filepath < 1.5 + vector < 0.14 Exposed-Modules: - Nix.Derivation + System.Nix.Derivation.ATerm Other-Modules: - Nix.Derivation.Builder, - Nix.Derivation.Parser, - Nix.Derivation.Types + System.Nix.Derivation.ATerm.Builder, + System.Nix.Derivation.ATerm.Parser GHC-Options: -Wall Executable pretty-derivation diff --git a/hnix-store-aterm/src/Nix/Derivation.hs b/hnix-store-aterm/src/System/Nix/Derivation/ATerm.hs similarity index 95% rename from hnix-store-aterm/src/Nix/Derivation.hs rename to hnix-store-aterm/src/System/Nix/Derivation/ATerm.hs index 872d181d..85c6f546 100644 --- a/hnix-store-aterm/src/Nix/Derivation.hs +++ b/hnix-store-aterm/src/System/Nix/Derivation/ATerm.hs @@ -26,7 +26,7 @@ -- ... you could parse that derivation using: -- -- >>> text <- Data.Text.Lazy.IO.readFile "/nix/store/zzhs4fb83x5ygvjqn5rdpmpnishpdgy6-perl-MIME-Types-2.13.drv" --- >>> let result = Data.Attoparsec.Text.Lazy.parse Nix.Derivation.parseDerivation text +-- >>> let result = Data.Attoparsec.Text.Lazy.parse System.Nix.Derivation.ATerm.parseDerivation text -- >>> result -- Done "" (Derivation {outputs = fromList [("devdoc",DerivationOutput {path = File -- Path "/nix/store/15x9ii8c3n5wb5lg80cm8x0yk6zy7rha-perl-MIME-Types-2.13-devdoc", @@ -76,9 +76,10 @@ -- E-Types-2.13.tar.gz\"),(\"stdenv\",\"/nix/store/s3rlr45jzlzx0d6k2azlpxa5zwzr7xyy -- -stdenv\"),(\"system\",\"x86_64-linux\")])" -module Nix.Derivation +module System.Nix.Derivation.ATerm ( -- * Types - Derivation(..) + Derivation + , Derivation'(..) , DerivationOutput(..) , DerivationInputs(..) , DerivedPathMap(..) @@ -97,6 +98,6 @@ module Nix.Derivation , buildDerivationInputsWith ) where -import Nix.Derivation.Builder -import Nix.Derivation.Parser -import Nix.Derivation.Types +import System.Nix.Derivation +import System.Nix.Derivation.ATerm.Builder +import System.Nix.Derivation.ATerm.Parser diff --git a/hnix-store-aterm/src/Nix/Derivation/Builder.hs b/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Builder.hs similarity index 52% rename from hnix-store-aterm/src/Nix/Derivation/Builder.hs rename to hnix-store-aterm/src/System/Nix/Derivation/ATerm/Builder.hs index 494568cf..59bf6a9a 100644 --- a/hnix-store-aterm/src/Nix/Derivation/Builder.hs +++ b/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Builder.hs @@ -4,7 +4,7 @@ -- | Rendering logic -module Nix.Derivation.Builder +module System.Nix.Derivation.ATerm.Builder ( -- * Builder buildDerivation , buildDerivationWith @@ -12,19 +12,29 @@ module Nix.Derivation.Builder , buildDerivationInputsWith ) where +import Data.Dependent.Sum import Data.Map (Map) +import Data.Map.Monoidal (MonoidalMap(..)) import Data.Maybe (fromMaybe) import Data.Set (Set) +import Data.Some +import Data.These (These(..)) import Data.Text (Text) import Data.Text.Lazy.Builder (Builder) import Data.These.Combinators (justThis) import Data.Vector (Vector) -import Nix.Derivation.Types - ( Derivation(..) +import System.Nix.ContentAddress +import System.Nix.Derivation + ( Derivation + , Derivation'(..) , DerivationOutput(..) , DerivationInputs(..) , DerivedPathMap(..) + , unChildNode ) +import System.Nix.Hash +import System.Nix.StorePath +import System.Nix.OutputName import qualified Data.Map import qualified Data.Set @@ -34,32 +44,22 @@ import qualified Data.Vector -- | Render a derivation as a `Builder` buildDerivation - :: Derivation - FilePath - Text - Text - (DerivationOutput FilePath Text) - (DerivationInputs FilePath Text) + :: StoreDir + -> Derivation -> Builder -buildDerivation = +buildDerivation sd = buildDerivationWith - string' - string' - (buildDerivationOutputWith filepath' string' emptyString') - (buildDerivationInputsWith filepath' string') - where - emptyString' = string' Data.Text.empty + (buildDerivationInputs sd) + (buildDerivationOutput sd) -- | Render a derivation as a `Builder` using custom --- renderer for filepaths, texts, outputNames and derivation inputs/outputs +-- renderer for storePaths, texts, outputNames and derivation inputs/outputs buildDerivationWith - :: (txt -> Builder) - -> (outputName -> Builder) + :: (drvInputs -> Builder) -> (drvOutput -> Builder) - -> (drvInputs -> Builder) - -> Derivation fp txt outputName drvOutput drvInputs + -> Derivation' drvInputs drvOutput -> Builder -buildDerivationWith string outputName drvOutput drvInputs (Derivation {..}) = +buildDerivationWith drvInputs drvOutput (Derivation {..}) = "Derive(" <> mapOf keyValue0 outputs <> "," @@ -88,52 +88,63 @@ buildDerivationWith string outputName drvOutput drvInputs (Derivation {..}) = <> string value <> ")" +buildMethodHashAlgo method hashAlgo = Data.Text.intercalate ":" $ + (case method of + ContentAddressMethod_NixArchive -> ["r"] + ContentAddressMethod_Text -> ["text"] + ContentAddressMethod_Flat -> []) + <> + [withSome hashAlgo algoToText] + -- | Render a @DerivationOutput@ as a `Builder` using custom --- renderer for filepaths -buildDerivationOutputWith - :: (fp -> Builder) - -> (txt -> Builder) +-- renderer for storePaths +buildDerivationOutput + :: StoreDir + -> DerivationOutput -> Builder - -> DerivationOutput fp txt - -> Builder -buildDerivationOutputWith filepath string emptyString = \case +buildDerivationOutput storeDir = \case InputAddressedDerivationOutput {..} -> - filepath path + storePath storeDir path <> "," <> emptyString <> "," <> emptyString - FixedDerivationOutput {..} -> - filepath path - <> "," - <> string hashAlgo - <> "," - <> string hash + FixedDerivationOutput {..} -> case hash of + hashAlgo :=> hash' -> + storePath storeDir _path -- TODO compute path + <> "," + <> string (buildMethodHashAlgo method $ Some hashAlgo) + <> "," + <> string (encodeDigestWith NixBase32 hash') ContentAddressedDerivationOutput {..} -> emptyString <> "," - <> string hashAlgo + <> string (buildMethodHashAlgo method hashAlgo) <> "," <> emptyString + where + emptyString = string Data.Text.empty -- | Render a @DerivationInputs@ as a `Builder` using custom --- renderer for filepaths and output names -buildDerivationInputsWith - :: (fp -> Builder) - -> (outputName -> Builder) - -> DerivationInputs fp outputName +-- renderer for storePaths and output names +buildDerivationInputs + :: StoreDir + -> DerivationInputs -> Builder -buildDerivationInputsWith filepath outputName (DerivationInputs {..}) = - mapOf keyValue (unDerivedPathMap drvs) +buildDerivationInputs storeDir (DerivationInputs {..}) = + mapOf keyValue (getMonoidalMap $ unDerivedPathMap drvs) <> "," - <> setOf filepath srcs + <> setOf (storePath storeDir) srcs where keyValue (key, value) = "(" - <> filepath key + <> storePath storeDir key <> "," - <> setOf outputName (fromMaybe Data.Set.empty $ justThis value) + <> setOf outputName outputNames <> ")" + where outputNames = case unChildNode value of + This os -> os + _ -> error "dynamic derivations are not supported in the ATerm format yet" mapOf :: ((k, v) -> Builder) -> Map k v -> Builder mapOf keyValue m = listOf keyValue (Data.Map.toList m) @@ -154,8 +165,11 @@ setOf element xs = listOf element (Data.Set.toList xs) vectorOf :: (a -> Builder) -> Vector a -> Builder vectorOf element xs = listOf element (Data.Vector.toList xs) -string' :: Text -> Builder -string' = Data.Text.Lazy.Builder.fromText . Data.Text.pack . show +string :: Text -> Builder +string = Data.Text.Lazy.Builder.fromText . Data.Text.pack . show + +outputName :: OutputName -> Builder +outputName = string . unStorePathName . unOutputName -filepath' :: FilePath -> Builder -filepath' p = string' $ Data.Text.pack p +storePath :: StoreDir -> StorePath -> Builder +storePath sd = string . storePathToText sd diff --git a/hnix-store-aterm/src/Nix/Derivation/Parser.hs b/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Parser.hs similarity index 54% rename from hnix-store-aterm/src/Nix/Derivation/Parser.hs rename to hnix-store-aterm/src/System/Nix/Derivation/ATerm/Parser.hs index c5237ac1..02362760 100644 --- a/hnix-store-aterm/src/Nix/Derivation/Parser.hs +++ b/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Parser.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE TypeApplications #-} {-# LANGUAGE MultiWayIf #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} @@ -6,27 +7,37 @@ -- | Parsing logic -module Nix.Derivation.Parser +module System.Nix.Derivation.ATerm.Parser ( -- * Parser parseDerivation , parseDerivationWith - , parseDerivationOutputWith - , parseDerivationInputsWith + , parseDerivationOutput + , parseDerivationInputs , textParser ) where import Data.Attoparsec.Text.Lazy (Parser) +import Data.Constraint.Extras (Has(has)) +import Data.Dependent.Sum import Data.These (These(This)) import Data.Map (Map) +import Data.Map.Monoidal (MonoidalMap(..)) import Data.Set (Set) +import Data.Some import Data.Text (Text) import Data.Vector (Vector) -import Nix.Derivation.Types - ( Derivation(..) +import System.Nix.ContentAddress +import System.Nix.Derivation + ( Derivation + , Derivation'(..) , DerivationOutput(..) , DerivedPathMap(..) + , ChildNode(..) , DerivationInputs(..) ) +import System.Nix.Hash +import System.Nix.StorePath +import System.Nix.OutputName import qualified Data.Attoparsec.Text import qualified Data.Attoparsec.Text.Lazy @@ -34,7 +45,6 @@ import qualified Data.Map import qualified Data.Set import qualified Data.Text import qualified Data.Vector -import qualified System.FilePath listOf :: Parser a -> Parser [a] listOf element = do @@ -44,39 +54,24 @@ listOf element = do pure es -- | Parse a derivation -parseDerivation - :: Parser (Derivation - FilePath - Text - Text - (DerivationOutput FilePath Text) - (DerivationInputs FilePath Text) - ) -parseDerivation = +parseDerivation :: StoreDir -> Parser Derivation +parseDerivation sd = parseDerivationWith - textParser - textParser - (parseDerivationOutputWith filepathParser textParser) - (parseDerivationInputsWith filepathParser textParser) + (parseDerivationInputs sd) + (parseDerivationOutput sd) -- | Parse a derivation using custom -- parsers for filepaths, texts, outputNames and derivation inputs/outputs parseDerivationWith - :: ( Ord fp - , Ord txt - , Ord outputName - ) - => Parser txt - -> Parser outputName + :: Parser drvInputs -> Parser drvOutput - -> Parser drvInputs - -> Parser (Derivation fp txt outputName drvOutput drvInputs) -parseDerivationWith string outputName parseOutput parseInputs = do + -> Parser (Derivation' drvInputs drvOutput) +parseDerivationWith parseInputs parseOutput = do "Derive(" let keyValue0 = do "(" - key <- outputName + key <- outputNameParser "," drvOutput <- parseOutput ")" @@ -89,23 +84,23 @@ parseDerivationWith string outputName parseOutput parseInputs = do "," - platform <- string + platform <- textParser "," - builder <- string + builder <- textParser "," - args <- vectorOf string + args <- vectorOf textParser "," let keyValue1 = do "(" - key <- string + key <- textParser "," - value <- string + value <- textParser ")" pure (key, value) env <- mapOf keyValue1 @@ -114,13 +109,20 @@ parseDerivationWith string outputName parseOutput parseInputs = do pure Derivation {..} +splitMethodHashAlgo :: Text -> Parser (ContentAddressMethod, Some HashAlgo) +splitMethodHashAlgo methodHashAlgo = do + (method, hashAlgoS) <- case Data.Text.splitOn ":" methodHashAlgo of + ["r", hashAlgo] -> pure (ContentAddressMethod_NixArchive, hashAlgo) + ["text", hashAlgo] -> pure (ContentAddressMethod_NixArchive, hashAlgo) + [hashAlgo] -> pure (ContentAddressMethod_Flat, hashAlgo) + _ -> fail "invalid number of colons or unknown CA method prefix" + hashAlgo <- either fail pure $ textToAlgo hashAlgoS + pure (method, hashAlgo) + -- | Parse a derivation output -parseDerivationOutputWith - :: Parser fp - -> Parser txt - -> Parser (DerivationOutput fp txt) -parseDerivationOutputWith filepath textParser = do - mPath <- maybeTextParser filepath +parseDerivationOutput :: StoreDir -> Parser DerivationOutput +parseDerivationOutput sd = do + mPath <- maybeTextParser $ storePathParser sd "," mHashAlgo <- maybeTextParser textParser "," @@ -128,34 +130,37 @@ parseDerivationOutputWith filepath textParser = do case (mPath, mHashAlgo, mHash) of (Just path, Nothing, Nothing) -> pure InputAddressedDerivationOutput {..} - (Just path, Just hashAlgo, Just hash) -> + (Just _pathS, Just methodHashAlgo, Just hash0) -> do + -- TODO double check pathS + (method, Some hashAlgo) <- splitMethodHashAlgo methodHashAlgo + hash' <- either fail pure $ has @NamedAlgo hashAlgo $ + decodeDigestWith NixBase32 hash0 + let hash = hashAlgo :=> hash' pure FixedDerivationOutput {..} - (Nothing, Just hashAlgo, Nothing) -> + (Nothing, Just methodHashAlgo, Nothing) -> do + (method, hashAlgo) <- splitMethodHashAlgo methodHashAlgo pure ContentAddressedDerivationOutput {..} _ -> fail "bad output in derivation" -- | Parse a derivation inputs -parseDerivationInputsWith - :: ( Ord fp - , Ord outputName - ) - => Parser fp - -> Parser outputName - -> Parser (DerivationInputs fp outputName) -parseDerivationInputsWith filepath outputName = do +parseDerivationInputs :: StoreDir -> Parser DerivationInputs +parseDerivationInputs sd = do let keyValue = do "(" - key <- filepath + key <- storePathParser sd "," - value <- setOf outputName + value <- setOf outputNameParser ")" - pure (key, This value) - drvs <- DerivedPathMap <$> mapOf keyValue + pure + ( key + , ChildNode $ This value + ) + drvs <- DerivedPathMap . MonoidalMap <$> mapOf keyValue "," - srcs <- setOf filepath + srcs <- setOf $ storePathParser sd pure DerivationInputs {..} maybeTextParser :: Parser a -> Parser (Maybe a) @@ -195,15 +200,19 @@ textParser = do Data.Text.concat <$> loop -filepathParser :: Parser FilePath -filepathParser = do - text <- textParser - let str = Data.Text.unpack text - case (Data.Text.uncons text, System.FilePath.isValid str) of - (Just ('/', _), True) -> do - pure str - _ -> do - fail ("bad path ‘" <> Data.Text.unpack text <> "’ in derivation") +outputNameParser :: Parser OutputName +outputNameParser = do + n <- textParser + case mkOutputName n of + Left e -> fail $ show e -- TODO + Right sp -> pure sp + +storePathParser :: StoreDir -> Parser StorePath +storePathParser sd = do + f <- textParser + case System.Nix.StorePath.parsePathFromText sd f of + Left e -> fail $ show e -- TODO + Right sp -> pure sp setOf :: Ord a => Parser a -> Parser (Set a) setOf element = do diff --git a/hnix-store-aterm/tests/Property.hs b/hnix-store-aterm/tests/Property.hs index 5bb47232..420175b1 100644 --- a/hnix-store-aterm/tests/Property.hs +++ b/hnix-store-aterm/tests/Property.hs @@ -65,8 +65,8 @@ instance Arbitrary (DerivationInputs FilePath Text) where instance Arbitrary (DerivedPathMap FilePath Text) where arbitrary = DerivedPathMap . fmap This <$> arbitrary -instance Arbitrary - (Derivation +instance Arbitrary + (Derivation FilePath Text Text @@ -83,10 +83,10 @@ instance Arbitrary pure Derivation {..} property - :: Derivation - FilePath - Text - Text + :: Derivation + FilePath + Text + Text (DerivationOutput FilePath Text) (DerivationInputs FilePath Text) -> Bool diff --git a/hnix-store-core/src/System/Nix/Derivation.hs b/hnix-store-core/src/System/Nix/Derivation.hs index 96adf44d..741bcf33 100644 --- a/hnix-store-core/src/System/Nix/Derivation.hs +++ b/hnix-store-core/src/System/Nix/Derivation.hs @@ -46,7 +46,7 @@ import System.Nix.StorePath (StorePath) import System.Nix.OutputName (OutputName) data Derivation' inputs output = Derivation - { outputs :: Map Text output + { outputs :: Map OutputName output -- ^ Outputs produced by this derivation where keys are output names , inputs :: inputs -- ^ Inputs (sources and derivations) diff --git a/hnix-store-core/src/System/Nix/Derivation/Aterm.hs b/hnix-store-core/src/System/Nix/Derivation/Aterm.hs deleted file mode 100644 index 3fc4b738..00000000 --- a/hnix-store-core/src/System/Nix/Derivation/Aterm.hs +++ /dev/null @@ -1,75 +0,0 @@ -module System.Nix.Derivation - ( parseDerivation - , buildDerivation - , Derivation' - -- Re-exports - , Derivation(..) - , DerivationOutput(..) - , DerivationInputs(..) - , DerivedPathMap(..) - ) where - -import Data.Attoparsec.Text.Lazy (Parser) -import Data.Text (Text) -import Data.Text.Lazy.Builder (Builder) - -import Nix.Derivation - ( Derivation(..) - , DerivationOutput(..) - , DerivationInputs(..) - , DerivedPathMap(..) - , parseDerivationOutputWith - , parseDerivationInputsWith - , buildDerivationOutputWith - , buildDerivationInputsWith - ) -import System.Nix.StorePath (StoreDir, StorePath) - -import qualified Data.Attoparsec.Text.Lazy -import qualified Data.Text -import qualified Data.Text.Lazy -import qualified Data.Text.Lazy.Builder - -import qualified Nix.Derivation -import qualified System.Nix.StorePath - -type Derivation' = Derivation - StorePath - Text - Text - (DerivationOutput StorePath Text) - (DerivationInputs StorePath Text) - -parseDerivation - :: StoreDir - -> Parser (Derivation') -parseDerivation expectedRoot = - Nix.Derivation.parseDerivationWith - Nix.Derivation.textParser - Nix.Derivation.textParser - (parseDerivationOutputWith pathParser Nix.Derivation.textParser) - (parseDerivationInputsWith pathParser Nix.Derivation.textParser) - where - pathParser = do - text <- Nix.Derivation.textParser - case Data.Attoparsec.Text.Lazy.parseOnly - (System.Nix.StorePath.pathParser expectedRoot) - (Data.Text.Lazy.fromStrict text) - of - Right p -> pure p - Left e -> fail e - -buildDerivation - :: StoreDir - -> Derivation' - -> Builder -buildDerivation storeDir = - Nix.Derivation.buildDerivationWith - string - string - (buildDerivationOutputWith path string emptyString) - (buildDerivationInputsWith path string) - where - emptyString = string Data.Text.empty - path = string . System.Nix.StorePath.storePathToText storeDir - string = Data.Text.Lazy.Builder.fromText . Data.Text.pack . show diff --git a/hnix-store-remote/hnix-store-remote.cabal b/hnix-store-remote/hnix-store-remote.cabal index cacbe1eb..6c0cc460 100644 --- a/hnix-store-remote/hnix-store-remote.cabal +++ b/hnix-store-remote/hnix-store-remote.cabal @@ -106,6 +106,7 @@ library , hnix-store-json >= 0.1 , hnix-store-nar >= 0.1 , hnix-store-tests >= 0.1 + , hnix-store-aterm , aeson , attoparsec , bytestring diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs index 60d1c892..b3f58b98 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs @@ -38,6 +38,7 @@ import Data.Some (Some) import Data.Word (Word64) import System.Nix.Build (BuildMode, BuildResult) +import qualified System.Nix.Derivation.Aterm import System.Nix.DerivedPath (DerivedPath) import System.Nix.Hash (HashAlgo(..)) import System.Nix.Nar (NarSource) @@ -149,7 +150,7 @@ buildDerivation sp mode = do Left e -> throwError $ RemoteStoreError_DerivationParse e Right drv -> do let drv' = drv - { System.Nix.Derivation.inputs = + { System.Nix.Derivation.inputs = System.Nix.Derivation.srcs (System.Nix.Derivation.inputs drv) } diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Types/WorkerOp.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Types/WorkerOp.hs index 1839fad4..0b3040ac 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Types/WorkerOp.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Types/WorkerOp.hs @@ -1,4 +1,4 @@ -module System.Nix.Store.Remote.Types.WorkerOp +module System.Nix.Store.Remote.Types.WorkerOp ( WorkerOp(..) ) where diff --git a/hnix-store-remote/tests/EnumSpec.hs b/hnix-store-remote/tests/EnumSpec.hs index d77eaf5a..47e6e320 100644 --- a/hnix-store-remote/tests/EnumSpec.hs +++ b/hnix-store-remote/tests/EnumSpec.hs @@ -7,7 +7,7 @@ import Test.Hspec (SpecWith, Spec, describe, it, shouldBe) import Data.ByteString (ByteString) import Data.Word (Word64) import System.Nix.Build (BuildMode(..), BuildStatus(..)) -import System.Nix.Store.Remote.Serializer +import System.Nix.Store.Remote.Serializer ( activity , activityResult , enum From e39462b0f26e1314326e7fab31ff8d0b38576481 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 25 Dec 2024 03:07:01 -0500 Subject: [PATCH 50/58] Everything builds but the ATerm tests --- .../src/System/Nix/Derivation/ATerm.hs | 8 +- .../System/Nix/Derivation/ATerm/Builder.hs | 26 +++-- .../src/System/Nix/Derivation/ATerm/Parser.hs | 21 ++-- hnix-store-core/hnix-store-core.cabal | 1 + hnix-store-core/src/System/Nix/Derivation.hs | 6 +- hnix-store-core/src/System/Nix/OutputName.hs | 22 +++- .../System/Nix/StorePath/ContentAddressed.hs | 109 ++++++++++++++++++ .../src/System/Nix/Store/ReadOnly.hs | 101 +--------------- hnix-store-readonly/tests/ReadOnlySpec.hs | 1 + hnix-store-remote/hnix-store-remote.cabal | 1 + hnix-store-remote/src/Data/Serializer.hs | 1 - .../src/Data/Serializer/Example.hs | 1 - .../src/System/Nix/Store/Remote/Client.hs | 4 +- .../System/Nix/Store/Remote/Client/Core.hs | 9 +- .../src/System/Nix/Store/Remote/Serializer.hs | 30 +++-- .../src/System/Nix/Store/Remote/Server.hs | 81 ++++++++++--- .../src/System/Nix/Store/Remote/Socket.hs | 1 - .../Nix/Store/Remote/Types/StoreRequest.hs | 3 +- .../tests/Data/SerializerSpec.hs | 31 ++--- hnix-store-remote/tests/EnumSpec.hs | 11 +- hnix-store-remote/tests/NixSerializerSpec.hs | 63 +++++----- 21 files changed, 304 insertions(+), 227 deletions(-) create mode 100644 hnix-store-core/src/System/Nix/StorePath/ContentAddressed.hs diff --git a/hnix-store-aterm/src/System/Nix/Derivation/ATerm.hs b/hnix-store-aterm/src/System/Nix/Derivation/ATerm.hs index 85c6f546..907b6300 100644 --- a/hnix-store-aterm/src/System/Nix/Derivation/ATerm.hs +++ b/hnix-store-aterm/src/System/Nix/Derivation/ATerm.hs @@ -87,15 +87,15 @@ module System.Nix.Derivation.ATerm -- * Parse derivations , parseDerivation , parseDerivationWith - , parseDerivationOutputWith - , parseDerivationInputsWith + , parseDerivationOutput + , parseDerivationInputs , textParser -- * Render derivations , buildDerivation , buildDerivationWith - , buildDerivationOutputWith - , buildDerivationInputsWith + , buildDerivationOutput + , buildDerivationInputs ) where import System.Nix.Derivation diff --git a/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Builder.hs b/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Builder.hs index 59bf6a9a..63833867 100644 --- a/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Builder.hs +++ b/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Builder.hs @@ -8,20 +8,18 @@ module System.Nix.Derivation.ATerm.Builder ( -- * Builder buildDerivation , buildDerivationWith - , buildDerivationOutputWith - , buildDerivationInputsWith + , buildDerivationOutput + , buildDerivationInputs ) where import Data.Dependent.Sum import Data.Map (Map) import Data.Map.Monoidal (MonoidalMap(..)) -import Data.Maybe (fromMaybe) import Data.Set (Set) import Data.Some import Data.These (These(..)) import Data.Text (Text) import Data.Text.Lazy.Builder (Builder) -import Data.These.Combinators (justThis) import Data.Vector (Vector) import System.Nix.ContentAddress import System.Nix.Derivation @@ -34,6 +32,7 @@ import System.Nix.Derivation ) import System.Nix.Hash import System.Nix.StorePath +import System.Nix.StorePath.ContentAddressed import System.Nix.OutputName import qualified Data.Map @@ -56,7 +55,7 @@ buildDerivation sd = -- renderer for storePaths, texts, outputNames and derivation inputs/outputs buildDerivationWith :: (drvInputs -> Builder) - -> (drvOutput -> Builder) + -> (StorePathName -> OutputName -> drvOutput -> Builder) -> Derivation' drvInputs drvOutput -> Builder buildDerivationWith drvInputs drvOutput (Derivation {..}) = @@ -76,9 +75,9 @@ buildDerivationWith drvInputs drvOutput (Derivation {..}) = where keyValue0 (key, output) = "(" - <> outputName key + <> buildOutputName key <> "," - <> drvOutput output + <> drvOutput name key output <> ")" keyValue1 (key, value) = @@ -88,6 +87,7 @@ buildDerivationWith drvInputs drvOutput (Derivation {..}) = <> string value <> ")" +buildMethodHashAlgo :: ContentAddressMethod -> Some HashAlgo -> Text buildMethodHashAlgo method hashAlgo = Data.Text.intercalate ":" $ (case method of ContentAddressMethod_NixArchive -> ["r"] @@ -100,9 +100,11 @@ buildMethodHashAlgo method hashAlgo = Data.Text.intercalate ":" $ -- renderer for storePaths buildDerivationOutput :: StoreDir + -> StorePathName + -> OutputName -> DerivationOutput -> Builder -buildDerivationOutput storeDir = \case +buildDerivationOutput storeDir drvName outputName = \case InputAddressedDerivationOutput {..} -> storePath storeDir path <> "," @@ -111,7 +113,7 @@ buildDerivationOutput storeDir = \case <> emptyString FixedDerivationOutput {..} -> case hash of hashAlgo :=> hash' -> - storePath storeDir _path -- TODO compute path + storePath storeDir (makeFixedOutputPath storeDir method hash mempty $ outputStoreObjectName drvName outputName) <> "," <> string (buildMethodHashAlgo method $ Some hashAlgo) <> "," @@ -140,7 +142,7 @@ buildDerivationInputs storeDir (DerivationInputs {..}) = "(" <> storePath storeDir key <> "," - <> setOf outputName outputNames + <> setOf buildOutputName outputNames <> ")" where outputNames = case unChildNode value of This os -> os @@ -168,8 +170,8 @@ vectorOf element xs = listOf element (Data.Vector.toList xs) string :: Text -> Builder string = Data.Text.Lazy.Builder.fromText . Data.Text.pack . show -outputName :: OutputName -> Builder -outputName = string . unStorePathName . unOutputName +buildOutputName :: OutputName -> Builder +buildOutputName = string . unStorePathName . unOutputName storePath :: StoreDir -> StorePath -> Builder storePath sd = string . storePathToText sd diff --git a/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Parser.hs b/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Parser.hs index 02362760..eba9c23d 100644 --- a/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Parser.hs +++ b/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Parser.hs @@ -16,6 +16,7 @@ module System.Nix.Derivation.ATerm.Parser , textParser ) where +import Control.Monad (when) import Data.Attoparsec.Text.Lazy (Parser) import Data.Constraint.Extras (Has(has)) import Data.Dependent.Sum @@ -37,6 +38,7 @@ import System.Nix.Derivation ) import System.Nix.Hash import System.Nix.StorePath +import System.Nix.StorePath.ContentAddressed import System.Nix.OutputName import qualified Data.Attoparsec.Text @@ -54,7 +56,7 @@ listOf element = do pure es -- | Parse a derivation -parseDerivation :: StoreDir -> Parser Derivation +parseDerivation :: StoreDir -> StorePathName -> Parser Derivation parseDerivation sd = parseDerivationWith (parseDerivationInputs sd) @@ -64,16 +66,17 @@ parseDerivation sd = -- parsers for filepaths, texts, outputNames and derivation inputs/outputs parseDerivationWith :: Parser drvInputs - -> Parser drvOutput + -> (StorePathName -> OutputName -> Parser drvOutput) + -> StorePathName -> Parser (Derivation' drvInputs drvOutput) -parseDerivationWith parseInputs parseOutput = do +parseDerivationWith parseInputs parseOutput name = do "Derive(" let keyValue0 = do "(" key <- outputNameParser "," - drvOutput <- parseOutput + drvOutput <- parseOutput name key ")" return (key, drvOutput) outputs <- mapOf keyValue0 @@ -120,8 +123,8 @@ splitMethodHashAlgo methodHashAlgo = do pure (method, hashAlgo) -- | Parse a derivation output -parseDerivationOutput :: StoreDir -> Parser DerivationOutput -parseDerivationOutput sd = do +parseDerivationOutput :: StoreDir -> StorePathName -> OutputName -> Parser DerivationOutput +parseDerivationOutput sd drvName outputName = do mPath <- maybeTextParser $ storePathParser sd "," mHashAlgo <- maybeTextParser textParser @@ -130,12 +133,14 @@ parseDerivationOutput sd = do case (mPath, mHashAlgo, mHash) of (Just path, Nothing, Nothing) -> pure InputAddressedDerivationOutput {..} - (Just _pathS, Just methodHashAlgo, Just hash0) -> do - -- TODO double check pathS + (Just path, Just methodHashAlgo, Just hash0) -> do (method, Some hashAlgo) <- splitMethodHashAlgo methodHashAlgo hash' <- either fail pure $ has @NamedAlgo hashAlgo $ decodeDigestWith NixBase32 hash0 let hash = hashAlgo :=> hash' + let expectedPath = makeFixedOutputPath sd method hash mempty $ outputStoreObjectName drvName outputName + when (path /= expectedPath) $ + fail "fixed output path does not match info" pure FixedDerivationOutput {..} (Nothing, Just methodHashAlgo, Nothing) -> do (method, hashAlgo) <- splitMethodHashAlgo methodHashAlgo diff --git a/hnix-store-core/hnix-store-core.cabal b/hnix-store-core/hnix-store-core.cabal index 925c7454..62516bbf 100644 --- a/hnix-store-core/hnix-store-core.cabal +++ b/hnix-store-core/hnix-store-core.cabal @@ -72,6 +72,7 @@ library , System.Nix.Signature , System.Nix.Store.Types , System.Nix.StorePath + , System.Nix.StorePath.ContentAddressed , System.Nix.StorePath.Metadata build-depends: base >=4.12 && <5 diff --git a/hnix-store-core/src/System/Nix/Derivation.hs b/hnix-store-core/src/System/Nix/Derivation.hs index 741bcf33..b45ea179 100644 --- a/hnix-store-core/src/System/Nix/Derivation.hs +++ b/hnix-store-core/src/System/Nix/Derivation.hs @@ -42,11 +42,13 @@ import GHC.Generics (Generic) import System.Nix.ContentAddress (ContentAddressMethod) import System.Nix.Hash (HashAlgo) import System.Nix.DerivedPath (SingleDerivedPath(..)) -import System.Nix.StorePath (StorePath) +import System.Nix.StorePath (StorePath, StorePathName) import System.Nix.OutputName (OutputName) data Derivation' inputs output = Derivation - { outputs :: Map OutputName output + { name :: StorePathName + -- ^ Name of the derivation, needed for calculating output paths + , outputs :: Map OutputName output -- ^ Outputs produced by this derivation where keys are output names , inputs :: inputs -- ^ Inputs (sources and derivations) diff --git a/hnix-store-core/src/System/Nix/OutputName.hs b/hnix-store-core/src/System/Nix/OutputName.hs index 87ff3e4d..6073679e 100644 --- a/hnix-store-core/src/System/Nix/OutputName.hs +++ b/hnix-store-core/src/System/Nix/OutputName.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE DeriveAnyClass #-} {-| Description : Derived path output names @@ -6,6 +7,7 @@ Description : Derived path output names module System.Nix.OutputName ( OutputName(..) , mkOutputName + , outputStoreObjectName -- * Re-exports , System.Nix.StorePath.InvalidNameError(..) ) where @@ -14,7 +16,12 @@ import Control.DeepSeq (NFData) import Data.Hashable (Hashable) import Data.Text (Text) import GHC.Generics (Generic) -import System.Nix.StorePath (StorePathName, InvalidNameError(..), mkStorePathName) +import System.Nix.StorePath + ( StorePathName + , InvalidNameError(..) + , mkStorePathName + , unStorePathName + ) -- | Name of the derived path output -- Typically used for "dev", "doc" sub-outputs @@ -27,3 +34,16 @@ instance NFData OutputName mkOutputName :: Text -> Either InvalidNameError OutputName mkOutputName = fmap OutputName . System.Nix.StorePath.mkStorePathName + +-- | Compute the name of an output (store object) from the output name +-- and the derivation name +outputStoreObjectName :: StorePathName -> OutputName -> StorePathName +outputStoreObjectName drvName outputName = case outputNameS of + "out" -> drvName + _ -> either (error "impossible, internal error") id $ + System.Nix.StorePath.mkStorePathName $ + unStorePathName drvName + <> "-" + <> outputNameS + where + outputNameS = unStorePathName $ unOutputName outputName diff --git a/hnix-store-core/src/System/Nix/StorePath/ContentAddressed.hs b/hnix-store-core/src/System/Nix/StorePath/ContentAddressed.hs new file mode 100644 index 00000000..18fccd92 --- /dev/null +++ b/hnix-store-core/src/System/Nix/StorePath/ContentAddressed.hs @@ -0,0 +1,109 @@ +{-# LANGUAGE GADTs #-} +{-# LANGUAGE OverloadedStrings #-} + +module System.Nix.StorePath.ContentAddressed + ( References(..) + , makeStorePath + , makeFixedOutputPath + ) where + +import Crypto.Hash (Digest, SHA256, HashAlgorithm) +import Data.ByteString (ByteString) +import Data.Constraint.Extras (Has(has)) +import Data.Dependent.Sum (DSum((:=>))) +import Data.HashSet (HashSet) +import Data.Some (Some(Some)) +import System.Nix.ContentAddress (ContentAddressMethod (..)) +import System.Nix.Hash (BaseEncoding(Base16), HashAlgo(..)) +import System.Nix.StorePath (StoreDir, StorePath, StorePathName) + +import qualified Crypto.Hash +import qualified Data.ByteString.Char8 +import qualified Data.ByteString +import qualified Data.HashSet +import qualified Data.List +import qualified Data.Text +import qualified Data.Text.Encoding +import qualified System.Nix.Hash +import qualified System.Nix.StorePath + +data References = References + { references_others :: HashSet StorePath + , references_self :: Bool + } + +instance Semigroup References where + a <> b = References + { references_others = references_others a <> references_others b + , references_self = references_self a || references_self b + } + +instance Monoid References where + mempty = References + { references_others = mempty + , references_self = False + } + +-- | TODO this isn't just for content-addrssed paths, move elsewhere +makeStorePath + :: StoreDir + -> ByteString + -> DSum HashAlgo Digest + -> StorePathName + -> StorePath +makeStorePath storeDir ty (hashAlgo :=> (digest :: Digest a)) nm = + System.Nix.StorePath.unsafeMakeStorePath storeHash nm + where + storeHash = has @HashAlgorithm hashAlgo $ System.Nix.StorePath.mkStorePathHashPart @a s + s = + Data.ByteString.intercalate ":" $ + ty:fmap Data.Text.Encoding.encodeUtf8 + [ System.Nix.Hash.algoToText hashAlgo + , System.Nix.Hash.encodeDigestWith Base16 digest + , Data.Text.pack . Data.ByteString.Char8.unpack $ System.Nix.StorePath.unStoreDir storeDir + , System.Nix.StorePath.unStorePathName nm + ] + +makeType + :: StoreDir + -> ByteString + -> References + -> ByteString +makeType storeDir ty refs = + Data.ByteString.intercalate ":" $ ty : (others ++ self) + where + others = Data.List.sort + $ fmap (System.Nix.StorePath.storePathToRawFilePath storeDir) + $ Data.HashSet.toList + $ references_others refs + self = ["self" | references_self refs] + +makeFixedOutputPath + :: StoreDir + -> ContentAddressMethod + -> DSum HashAlgo Digest + -> References + -> StorePathName + -> StorePath +makeFixedOutputPath storeDir method digest@(hashAlgo :=> h) refs = + makeStorePath storeDir ty digest' + where + (ty, digest') = case method of + ContentAddressMethod_Text -> + case hashAlgo of + HashAlgo_SHA256 + | references_self refs == False -> (makeType storeDir "text" refs, digest) + _ -> error "unsupported" -- TODO do better; maybe we'll just remove this restriction too? + _ -> + if method == ContentAddressMethod_NixArchive + && Some hashAlgo == Some HashAlgo_SHA256 + then (makeType storeDir "source" refs, digest) + else let + h' = + Crypto.Hash.hash @ByteString @SHA256 + $ "fixed:out:" + <> Data.Text.Encoding.encodeUtf8 (System.Nix.Hash.algoToText hashAlgo) + <> (if method == ContentAddressMethod_NixArchive then ":r:" else ":") + <> Data.Text.Encoding.encodeUtf8 (System.Nix.Hash.encodeDigestWith Base16 h) + <> ":" + in ("output:out", HashAlgo_SHA256 :=> h') diff --git a/hnix-store-readonly/src/System/Nix/Store/ReadOnly.hs b/hnix-store-readonly/src/System/Nix/Store/ReadOnly.hs index 2f45efef..1d70daf8 100644 --- a/hnix-store-readonly/src/System/Nix/Store/ReadOnly.hs +++ b/hnix-store-readonly/src/System/Nix/Store/ReadOnly.hs @@ -2,114 +2,21 @@ {-# LANGUAGE OverloadedStrings #-} module System.Nix.Store.ReadOnly - ( References(..) - , makeStorePath - , makeFixedOutputPath - , computeStorePathForPath + ( computeStorePathForPath ) where import Control.Monad.State (StateT, execStateT, modify) -import Crypto.Hash (Context, Digest, SHA256, HashAlgorithm) +import Crypto.Hash (Context, Digest, SHA256) import Data.ByteString (ByteString) -import Data.Constraint.Extras (Has(has)) import Data.Dependent.Sum (DSum((:=>))) -import Data.HashSet (HashSet) -import Data.Some (Some(Some)) +import System.Nix.StorePath.ContentAddressed import System.Nix.ContentAddress (ContentAddressMethod (..)) -import System.Nix.Hash (BaseEncoding(Base16), HashAlgo(..)) +import System.Nix.Hash (HashAlgo(..)) import System.Nix.Store.Types (PathFilter, RepairMode) import System.Nix.StorePath (StoreDir, StorePath, StorePathName) import qualified Crypto.Hash -import qualified Data.ByteString.Char8 -import qualified Data.ByteString -import qualified Data.HashSet -import qualified Data.List -import qualified Data.Text -import qualified Data.Text.Encoding -import qualified System.Nix.Hash import qualified System.Nix.Nar -import qualified System.Nix.StorePath - -data References = References - { references_others :: HashSet StorePath - , references_self :: Bool - } - -instance Semigroup References where - a <> b = References - { references_others = references_others a <> references_others b - , references_self = references_self a || references_self b - } - -instance Monoid References where - mempty = References - { references_others = mempty - , references_self = False - } - -makeStorePath - :: StoreDir - -> ByteString - -> DSum HashAlgo Digest - -> StorePathName - -> StorePath -makeStorePath storeDir ty (hashAlgo :=> (digest :: Digest a)) nm = - System.Nix.StorePath.unsafeMakeStorePath storeHash nm - where - storeHash = has @HashAlgorithm hashAlgo $ System.Nix.StorePath.mkStorePathHashPart @a s - s = - Data.ByteString.intercalate ":" $ - ty:fmap Data.Text.Encoding.encodeUtf8 - [ System.Nix.Hash.algoToText hashAlgo - , System.Nix.Hash.encodeDigestWith Base16 digest - , Data.Text.pack . Data.ByteString.Char8.unpack $ System.Nix.StorePath.unStoreDir storeDir - , System.Nix.StorePath.unStorePathName nm - ] - -makeType - :: StoreDir - -> ByteString - -> References - -> ByteString -makeType storeDir ty refs = - Data.ByteString.intercalate ":" $ ty : (others ++ self) - where - others = Data.List.sort - $ fmap (System.Nix.StorePath.storePathToRawFilePath storeDir) - $ Data.HashSet.toList - $ references_others refs - self = ["self" | references_self refs] - -makeFixedOutputPath - :: StoreDir - -> ContentAddressMethod - -> DSum HashAlgo Digest - -> References - -> StorePathName - -> StorePath -makeFixedOutputPath storeDir method digest@(hashAlgo :=> h) refs = - makeStorePath storeDir ty digest' - where - (ty, digest') = case method of - ContentAddressMethod_Text -> - case hashAlgo of - HashAlgo_SHA256 - | references_self refs == False -> (makeType storeDir "text" refs, digest) - _ -> error "unsupported" -- TODO do better; maybe we'll just remove this restriction too? - _ -> - if method == ContentAddressMethod_NixArchive - && Some hashAlgo == Some HashAlgo_SHA256 - then (makeType storeDir "source" refs, digest) - else let - h' = - Crypto.Hash.hash @ByteString @SHA256 - $ "fixed:out:" - <> Data.Text.Encoding.encodeUtf8 (System.Nix.Hash.algoToText hashAlgo) - <> (if method == ContentAddressMethod_NixArchive then ":r:" else ":") - <> Data.Text.Encoding.encodeUtf8 (System.Nix.Hash.encodeDigestWith Base16 h) - <> ":" - in ("output:out", HashAlgo_SHA256 :=> h') digestPath :: FilePath -- ^ Local `FilePath` to add diff --git a/hnix-store-readonly/tests/ReadOnlySpec.hs b/hnix-store-readonly/tests/ReadOnlySpec.hs index ff5c9166..cef695ba 100644 --- a/hnix-store-readonly/tests/ReadOnlySpec.hs +++ b/hnix-store-readonly/tests/ReadOnlySpec.hs @@ -10,6 +10,7 @@ import Data.ByteString (ByteString) import Data.Dependent.Sum (DSum(..)) import System.Nix.Hash (HashAlgo(..)) import System.Nix.StorePath (StorePath, StorePathName) +import System.Nix.StorePath.ContentAddressed import System.Nix.ContentAddress (ContentAddressMethod(..)) import qualified Data.HashSet diff --git a/hnix-store-remote/hnix-store-remote.cabal b/hnix-store-remote/hnix-store-remote.cabal index 6c0cc460..73d683ce 100644 --- a/hnix-store-remote/hnix-store-remote.cabal +++ b/hnix-store-remote/hnix-store-remote.cabal @@ -185,6 +185,7 @@ test-suite remote , time , hspec , QuickCheck + , transformers test-suite remote-io import: commons diff --git a/hnix-store-remote/src/Data/Serializer.hs b/hnix-store-remote/src/Data/Serializer.hs index cd37a209..34ca9f78 100644 --- a/hnix-store-remote/src/Data/Serializer.hs +++ b/hnix-store-remote/src/Data/Serializer.hs @@ -57,7 +57,6 @@ import Data.Serialize (Serialize) import qualified Data.Serialize import Data.Serialize.Get (Get, runGet) import Data.Serialize.Put (Putter, PutM, runPutM) -import Data.Traversable -- * Serializer diff --git a/hnix-store-remote/src/Data/Serializer/Example.hs b/hnix-store-remote/src/Data/Serializer/Example.hs index ab15bc8d..ea37070e 100644 --- a/hnix-store-remote/src/Data/Serializer/Example.hs +++ b/hnix-store-remote/src/Data/Serializer/Example.hs @@ -101,7 +101,6 @@ cmdS :: forall t . ( MonadTrans t , Monad (t Get) - , Monad (t PutM) ) => Serializer t (Some Cmd) cmdS = Serializer diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs index b3f58b98..501e9379 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs @@ -38,7 +38,7 @@ import Data.Some (Some) import Data.Word (Word64) import System.Nix.Build (BuildMode, BuildResult) -import qualified System.Nix.Derivation.Aterm +import qualified System.Nix.Derivation.ATerm import System.Nix.DerivedPath (DerivedPath) import System.Nix.Hash (HashAlgo(..)) import System.Nix.Nar (NarSource) @@ -146,7 +146,7 @@ buildDerivation sp mode = do $ Data.Text.IO.readFile $ System.Nix.StorePath.storePathToFilePath sd sp case Data.Attoparsec.Text.parseOnly - (System.Nix.Derivation.parseDerivation sd) drvContents of + (System.Nix.Derivation.ATerm.parseDerivation sd $ System.Nix.StorePath.storePathName sp) drvContents of Left e -> throwError $ RemoteStoreError_DerivationParse e Right drv -> do let drv' = drv diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Client/Core.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Client/Core.hs index 9c768eec..5dc0470a 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Client/Core.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Client/Core.hs @@ -21,17 +21,18 @@ import System.Nix.Store.Remote.MonadStore ) import System.Nix.Store.Remote.Socket (sockPutS, sockGetS) import System.Nix.Store.Remote.Serializer - ( bool + ( ReplySError(ReplySError_PrimGet) + , bool , int , mapErrorS , protoVersion + , storePath , storeRequest , text , trustedFlag , workerMagic ) -import System.Nix.Store.Remote.Serializer import System.Nix.Store.Remote.Types.Handshake (ClientHandshakeOutput(..)) import System.Nix.Store.Remote.Types.Logger (Logger) import System.Nix.Store.Remote.Types.NoReply (NoReply(..)) @@ -56,12 +57,12 @@ doReq doReq = \case x -> do storeDir <- getStoreDir - protoVersion <- getProtoVersion + pv <- getProtoVersion sockPutS (mapErrorS RemoteStoreError_SerializerRequest - $ storeRequest storeDir protoVersion + $ storeRequest storeDir pv ) (Some x) diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs index 7716079d..7abda102 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs @@ -102,10 +102,8 @@ module System.Nix.Store.Remote.Serializer ) where import Control.Monad.Except (MonadError, throwError, ) -import Control.Monad.Reader (MonadReader) -import Control.Monad.Trans (MonadTrans, lift) -import Control.Monad.Trans.Reader (ReaderT, runReaderT, withReaderT) -import Control.Monad.Trans.Except (ExceptT(..), mapExceptT, runExceptT, withExceptT) +import Control.Monad.Trans (lift) +import Control.Monad.Trans.Except (ExceptT(..), runExceptT, withExceptT) import Crypto.Hash (Digest, HashAlgorithm, SHA256) import Data.Aeson (FromJSON, ToJSON) import Data.ByteString (ByteString) @@ -147,15 +145,12 @@ import System.Nix.StorePath.Metadata (Metadata(..), StorePathTrust(..)) import System.Nix.Store.Remote.Types import qualified Control.Monad -import qualified Control.Monad.Reader import qualified Data.Aeson import qualified Data.Attoparsec.Text import qualified Data.Bifunctor import qualified Data.Bits import qualified Data.ByteString import qualified Data.ByteString.Char8 -import qualified Data.ByteString.Lazy -import qualified Data.Coerce import qualified Data.HashSet import qualified Data.Map.Strict import qualified Data.Maybe @@ -228,10 +223,9 @@ data ForPV a runG :: NixSerializer e a - -> r -> ByteString -> Either (GetSerializerError e) a -runG serializer r = +runG serializer = transformGetError . runGetS serializer @@ -640,7 +634,7 @@ someHashAlgo = -- * Digest digest - :: forall a r + :: forall a . HashAlgorithm a => BaseEncoding -> NixSerializer SError (Digest a) @@ -723,18 +717,20 @@ derivationOutput storeDir = Serializer basicDerivation :: StoreDir - -> NixSerializer SError BasicDerivation + -> NixSerializer SError (StorePathName -> BasicDerivation) basicDerivation storeDir = Serializer { getS = do - outputs <- getS $ mapS text $ derivationOutput storeDir + outputs <- getS $ mapS outputName $ derivationOutput storeDir inputs <- getS $ set $ storePath storeDir platform <- getS text builder <- getS text args <- getS $ vector text env <- getS $ mapS text text - pure Derivation{..} - , putS = \Derivation{..} -> do - putS (mapS text $ derivationOutput storeDir) outputs + pure $ \name -> Derivation{..} + , putS = \f -> do + -- We don't use the name here + let Derivation{..} = f $ error "must not matter" + putS (mapS outputName $ derivationOutput storeDir) outputs putS (set $ storePath storeDir) inputs putS text platform putS text builder @@ -1100,7 +1096,7 @@ storeRequest storeDir pv = Serializer WorkerOp_BuildDerivation -> mapGetE $ do path <- getS $ storePath storeDir - drv <- getS $ basicDerivation storeDir + drv <- getS (basicDerivation storeDir) <*> pure (System.Nix.StorePath.storePathName path) buildMode' <- getS buildMode pure $ Some (BuildDerivation path drv buildMode') @@ -1245,7 +1241,7 @@ storeRequest storeDir pv = Serializer putS workerOp WorkerOp_BuildDerivation putS (storePath storeDir) path - putS (basicDerivation storeDir) drv + putS (basicDerivation storeDir) $ \_ -> drv putS buildMode buildMode' Some (CollectGarbage GCOptions{..}) -> do diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Server.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Server.hs index 47557b73..357c55ae 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Server.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Server.hs @@ -21,10 +21,11 @@ import Data.Word (Word32) import Network.Socket (Socket, accept, close, listen, maxListenQueue) import System.Nix.Nar (NarSource) import System.Nix.Store.Remote.Client (Run, doReq) -import System.Nix.Store.Remote.Serializer (LoggerSError, mapErrorS, storeRequest, workerMagic, protoVersion, int, logger, text, trustedFlag) +import System.Nix.Store.Remote.Serializer + --(LoggerSError, mapErrorS, storeRequest, workerMagic, protoVersion, int, logger, text, trustedFlag) import System.Nix.Store.Remote.Socket +import System.Nix.Store.Remote.Types.NoReply import System.Nix.Store.Remote.Types.StoreRequest as R -import System.Nix.Store.Remote.Types.StoreReply import System.Nix.Store.Remote.Types.ProtoVersion (ProtoVersion(..)) import System.Nix.Store.Remote.Types.Logger (BasicError(..), ErrorInfo, Logger(..)) import System.Nix.Store.Remote.MonadStore (MonadRemoteStore(..), WorkerError(..), WorkerException(..), RemoteStoreError(..), RemoteStoreT, runRemoteStoreT) @@ -39,7 +40,7 @@ import qualified Network.Socket.ByteString type WorkerHelper m = forall a . ( Show a - , StoreReply a + --, StoreReply a ) => RemoteStoreT m a -> Run m a @@ -116,7 +117,7 @@ processConnection workerHelper postGreet sock = do let perform :: ( Show a - , StoreReply a + --, StoreReply a ) => StoreRequest a -> RemoteStoreT m () @@ -149,21 +150,55 @@ processConnection workerHelper postGreet sock = do case fst res of Left e -> throwError e - Right reply -> + Right reply -> do + sd <- getStoreDir + pv <- getProtoVersion + let + mapE = mapErrorS ReplySError_PrimGet + storePath' = mapE $ storePath sd sockPutS (mapErrorS RemoteStoreError_SerializerReply - $ getReplyS + -- no guarantee we always return the same type in the same way across different commands; type class is not recommended. + $ case req of + AddToStore {} -> storePath' + AddToStoreNar {} -> noop NoReply + AddTextToStore {} -> storePath' + AddSignatures {} -> opSuccess + AddTempRoot {} -> opSuccess + AddIndirectRoot {} -> opSuccess + BuildDerivation {} -> buildResult sd pv + BuildPaths {} -> opSuccess + CollectGarbage {} -> gcResult sd + EnsurePath {} -> opSuccess + FindRoots {} -> mapS gcRoot $ storePath' + IsValidPath {} -> mapE bool + NarFromPath {} -> noop NoReply + QueryValidPaths {} -> hashSet storePath' + QueryAllValidPaths {} -> hashSet storePath' + QuerySubstitutablePaths {} -> hashSet $ storePath' + QueryPathInfo {} -> maybePathMetadata sd + QueryReferrers {} -> hashSet storePath' + QueryValidDerivers {} -> hashSet storePath' + QueryDerivationOutputs {} -> hashSet storePath' + QueryDerivationOutputNames {} -> mapE $ hashSet $ storePathName + QueryPathFromHashPart {} -> storePath' + QueryMissing {} -> missing sd + OptimiseStore {} -> opSuccess + SyncWithGC {} -> opSuccess + VerifyStore {} -> mapE bool ) reply -- Process client requests. let loop = do + sd <- getStoreDir + pv <- getProtoVersion someReq <- sockGetS $ mapErrorS RemoteStoreError_SerializerRequest - storeRequest + $ storeRequest sd pv -- have to be explicit here -- because otherwise GHC can't conjure Show a, StoreReply a @@ -305,9 +340,11 @@ enqueueMsg => TunnelLogger -> Logger -> m () -enqueueMsg x l = updateLogger x $ \st@(TunnelLoggerState c p) -> case c of - True -> (st, sockPutS logger l) - False -> (TunnelLoggerState c (l:p), pure ()) +enqueueMsg x l = do + pv <- getProtoVersion + updateLogger x $ \st@(TunnelLoggerState c p) -> case c of + True -> (st, sockPutS (logger pv) l) + False -> (TunnelLoggerState c (l:p), pure ()) _log :: ( MonadRemoteStore m @@ -322,18 +359,23 @@ startWork :: MonadRemoteStore m => TunnelLogger -> m () -startWork x = updateLogger x $ \(TunnelLoggerState _ p) -> (,) - (TunnelLoggerState True []) $ - (traverse_ (sockPutS logger') $ reverse p) - where logger' = mapErrorS RemoteStoreError_SerializerLogger logger +startWork x = do + pv <- getProtoVersion + let logger' = mapErrorS RemoteStoreError_SerializerLogger $ logger pv + updateLogger x $ \(TunnelLoggerState _ p) -> (,) + (TunnelLoggerState True []) $ + (traverse_ (sockPutS logger') $ reverse p) stopWork :: MonadRemoteStore m => TunnelLogger -> m () -stopWork x = updateLogger x $ \_ -> (,) - (TunnelLoggerState False []) - (sockPutS (mapErrorS RemoteStoreError_SerializerLogger logger) Logger_Last) +stopWork x = do + pv <- getProtoVersion + let logger' = mapErrorS RemoteStoreError_SerializerLogger $ logger pv + updateLogger x $ \_ -> (,) + (TunnelLoggerState False []) + (sockPutS logger' Logger_Last) -- | Stop sending logging and report an error. -- @@ -351,11 +393,12 @@ _stopWorkOnError x ex = updateLogger x $ \st -> case _tunnelLoggerState_canSendStderr st of False -> (st, pure False) True -> (,) (TunnelLoggerState False []) $ do - getProtoVersion >>= \pv -> if protoVersion_minor pv >= 26 + pv <- getProtoVersion + let logger' = mapErrorS RemoteStoreError_SerializerLogger $ logger pv + if protoVersion_minor pv >= 26 then sockPutS logger' (Logger_Error (Right ex)) else sockPutS logger' (Logger_Error (Left (BasicError 0 (Data.Text.pack $ show ex)))) pure True - where logger' = mapErrorS RemoteStoreError_SerializerLogger logger updateLogger :: MonadRemoteStore m diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Socket.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Socket.hs index f021628a..58aece81 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Socket.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Socket.hs @@ -9,7 +9,6 @@ import Data.Serialize.Put (Put, runPut) import Network.Socket.ByteString (recv, sendAll) import System.Nix.Store.Remote.MonadStore (MonadRemoteStore(..), RemoteStoreError(..)) import System.Nix.Store.Remote.Serializer (NixSerializer, runP) -import System.Nix.Store.Remote.Types (ProtoStoreConfig) import qualified Control.Exception import qualified Data.ByteString diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Types/StoreRequest.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Types/StoreRequest.hs index a8d85ab5..77338a44 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Types/StoreRequest.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Types/StoreRequest.hs @@ -12,11 +12,10 @@ import Data.HashSet (HashSet) import Data.Kind (Type) import Data.Map (Map) import Data.Set (Set) -import Data.Text (Text) import Data.Some (Some(Some)) import System.Nix.Build (BuildMode, BuildResult) -import System.Nix.Derivation (BasicDerivation, DerivationOutput) +import System.Nix.Derivation (BasicDerivation) import System.Nix.DerivedPath (DerivedPath) import System.Nix.Hash (HashAlgo) import System.Nix.Signature (Signature) diff --git a/hnix-store-remote/tests/Data/SerializerSpec.hs b/hnix-store-remote/tests/Data/SerializerSpec.hs index a5188600..108642a8 100644 --- a/hnix-store-remote/tests/Data/SerializerSpec.hs +++ b/hnix-store-remote/tests/Data/SerializerSpec.hs @@ -1,5 +1,6 @@ module Data.SerializerSpec (spec) where +import Control.Monad.Trans.Identity import Data.Some import Data.Serializer import Data.Serializer.Example @@ -10,34 +11,26 @@ import Test.Hspec.QuickCheck (prop) spec :: Spec spec = describe "Serializer" $ do prop "Roundtrips GADT protocol" $ \someCmd -> - (runG cmdS - <$> (runP cmdS someCmd)) + (runG cmdS $ runP cmdS someCmd) `shouldBe` - ((pure $ pure someCmd) :: - Either MyPutError - (Either (GetSerializerError MyGetError) - (Some Cmd))) - - it "Handles putS error" $ - runP cmdSPutError (Some (Cmd_Bool True)) - `shouldBe` - Left MyPutError_NoLongerSupported + (pure someCmd :: + Either (GetSerializerError MyGetError) + (Some Cmd)) it "Handles getS error" $ - runG cmdSGetError (runPutSimple cmdS (Some (Cmd_Bool True))) + runG cmdSGetError (runPutS (cmdS @IdentityT) (Some (Cmd_Bool True))) `shouldBe` Left (SerializerError_Get MyGetError_Example) it "Handles getS fail" $ - runG cmdSGetFail (runPutSimple cmdS (Some (Cmd_Bool True))) + runG cmdSGetFail (runPutS (cmdS @IdentityT) (Some (Cmd_Bool True))) `shouldBe` Left (SerializerError_GetFail @MyGetError "Failed reading: no parse\nEmpty call stack\n") prop "Roundtrips elaborate example" $ \someCmd readerBool -> - (runGRest cmdSRest readerBool 0 - <$> (runPRest cmdSRest readerBool 0 someCmd)) + (runGRest (cmdSRest readerBool) readerBool 0 + $ runPRest (cmdSRest readerBool) someCmd) `shouldBe` - ((pure $ pure $ someCmd) :: - Either MyPutError - (Either (GetSerializerError MyGetError) - (Some Cmd))) + (pure someCmd :: + Either (GetSerializerError MyGetError) + (Some Cmd)) diff --git a/hnix-store-remote/tests/EnumSpec.hs b/hnix-store-remote/tests/EnumSpec.hs index 47e6e320..167ff27f 100644 --- a/hnix-store-remote/tests/EnumSpec.hs +++ b/hnix-store-remote/tests/EnumSpec.hs @@ -16,7 +16,6 @@ import System.Nix.Store.Remote.Serializer , runP , LoggerSError , NixSerializer - , SError ) import System.Nix.Store.Remote.Types @@ -34,22 +33,22 @@ spec = do -> SpecWith () itE name constr value = it name - $ ((runP enum () constr) :: Either SError ByteString) + $ ((runP enum constr) :: ByteString) `shouldBe` - (runP (int @Word64) () value) + (runP (int @Word64) value) itE' :: Show a - => NixSerializer () LoggerSError a + => NixSerializer LoggerSError a -> String -> a -> Word64 -> SpecWith () itE' s name constr value = it name - $ ((runP s () constr) :: Either LoggerSError ByteString) + $ ((runP s constr) :: ByteString) `shouldBe` - (runP (int @Word64) () (value)) + (runP (int @Word64) (value)) describe "Enums" $ do describe "BuildMode enum order matches Nix" $ do diff --git a/hnix-store-remote/tests/NixSerializerSpec.hs b/hnix-store-remote/tests/NixSerializerSpec.hs index 7f9aaa83..c1c55efc 100644 --- a/hnix-store-remote/tests/NixSerializerSpec.hs +++ b/hnix-store-remote/tests/NixSerializerSpec.hs @@ -4,15 +4,13 @@ module NixSerializerSpec (spec) where import Crypto.Hash (MD5, SHA1, SHA256, SHA512) import Data.Some (Some(Some)) -import Data.Time (UTCTime) import Test.Hspec (Expectation, Spec, describe, parallel, shouldBe) import Test.Hspec.QuickCheck (prop) import Test.QuickCheck (Gen, arbitrary, forAll, suchThat) +import Data.Serializer (mapIsoSerializer) import System.Nix.Arbitrary () -import System.Nix.Derivation (Derivation) import System.Nix.Build (BuildResult(..)) -import System.Nix.StorePath (StoreDir) import System.Nix.Store.Remote.Arbitrary () import System.Nix.Store.Remote.Serializer import System.Nix.Store.Remote.Types.Logger (Logger(..)) @@ -21,45 +19,46 @@ import System.Nix.Store.Remote.Types.StoreConfig (ProtoStoreConfig(..)) import System.Nix.Store.Remote.Types.StoreRequest (StoreRequest(..)) -- | Test for roundtrip using @NixSerializer@ -roundtripSReader - :: forall r e a +roundtripS + :: forall e a . ( Eq a , Show a , Eq e , Show e ) - => NixSerializer r e a - -> r + => NixSerializer e a -> a -> Expectation -roundtripSReader serializer readerVal a = - (runG serializer readerVal - <$> runP serializer readerVal a) - `shouldBe` (pure $ pure a) +roundtripS serializer a = + (runG serializer + $ runP serializer a) + `shouldBe` (pure a) -roundtripS - :: ( Eq a +roundtripSReader + :: forall r e a + . ( Eq a , Show a , Eq e , Show e ) - => NixSerializer () e a + => (r -> NixSerializer e a) + -> r -> a -> Expectation -roundtripS serializer = roundtripSReader serializer () +roundtripSReader serializer r = roundtripS $ serializer r spec :: Spec spec = parallel $ do describe "Prim" $ do - prop "Int" $ roundtripS @Int @() int + prop "Int" $ roundtripS @() $ int @Int prop "Bool" $ roundtripS bool prop "ByteString" $ roundtripS byteString prop "Text" $ roundtripS text prop "Maybe Text" $ roundtripS maybeText - prop "UTCTime" $ roundtripS @UTCTime @() time + prop "UTCTime" $ roundtripS @() time describe "Combinators" $ do - prop "list" $ roundtripS @[Int] @() (list int) + prop "list" $ roundtripS @() (list $ int @Int) prop "set" $ roundtripS (set byteString) prop "hashSet" $ roundtripS (hashSet byteString) prop "mapS" $ roundtripS (mapS (int @Int) byteString) @@ -71,7 +70,7 @@ spec = parallel $ do prop "< 1.28" $ \sd -> forAll (arbitrary `suchThat` ((< 28) . protoVersion_minor)) $ \pv -> - roundtripSReader @ProtoStoreConfig buildResult (ProtoStoreConfig sd pv) + roundtripS (buildResult sd pv) . (\x -> x { buildResultBuiltOutputs = Nothing }) . (\x -> x { buildResultTimesBuilt = Nothing , buildResultIsNonDeterministic = Nothing @@ -81,7 +80,7 @@ spec = parallel $ do ) prop "= 1.28" $ \sd -> - roundtripSReader @ProtoStoreConfig buildResult (ProtoStoreConfig sd (ProtoVersion 1 28)) + roundtripS (buildResult sd $ ProtoVersion 1 28) . (\x -> x { buildResultTimesBuilt = Nothing , buildResultIsNonDeterministic = Nothing , buildResultStartTime = Nothing @@ -91,10 +90,10 @@ spec = parallel $ do prop "> 1.28" $ \sd -> forAll (arbitrary `suchThat` ((> 28) . protoVersion_minor)) $ \pv -> - roundtripSReader @ProtoStoreConfig buildResult (ProtoStoreConfig sd pv) + roundtripS $ buildResult sd pv prop "StorePath" $ - roundtripSReader @StoreDir storePath + roundtripSReader storePath prop "StorePathHashPart" $ roundtripS storePathHashPart @@ -103,7 +102,7 @@ spec = parallel $ do roundtripS storePathName prop "Metadata (StorePath)" $ - roundtripSReader @StoreDir pathMetadata + roundtripSReader pathMetadata prop "Some HashAlgo" $ roundtripS someHashAlgo @@ -114,10 +113,10 @@ spec = parallel $ do prop "SHA256" $ roundtripS . digest @SHA256 prop "SHA512" $ roundtripS . digest @SHA512 - prop "Derivation" $ \sd -> - roundtripSReader @StoreDir basicDerivation sd + prop "Derivation" $ \sd name -> + roundtripS $ mapIsoSerializer ($ name) const $ basicDerivation sd - prop "ProtoVersion" $ roundtripS @ProtoVersion @() protoVersion + prop "ProtoVersion" $ roundtripS @() protoVersion describe "Logger" $ do prop "ActivityID" $ roundtripS activityID @@ -133,7 +132,7 @@ spec = parallel $ do $ forAll (arbitrary :: Gen ProtoVersion) $ \pv -> forAll (arbitrary `suchThat` errorInfoIf (protoVersion_minor pv >= 26)) - $ roundtripSReader logger pv + $ roundtripS $ logger pv describe "Handshake" $ do prop "WorkerMagic" $ roundtripS workerMagic @@ -146,14 +145,16 @@ spec = parallel $ do prop "StoreRequest" $ \testStoreConfig -> forAll (arbitrary `suchThat` (restrictProtoVersion (hasProtoVersion testStoreConfig))) - $ roundtripSReader @ProtoStoreConfig storeRequest testStoreConfig + $ roundtripS $ storeRequest + (protoStoreConfigDir testStoreConfig) + (protoStoreConfigProtoVersion testStoreConfig) describe "StoreReply" $ do prop "()" $ roundtripS opSuccess - prop "GCResult" $ roundtripSReader @StoreDir gcResult + prop "GCResult" $ roundtripSReader gcResult prop "GCRoot" $ roundtripS gcRoot - prop "Missing" $ roundtripSReader @StoreDir missing - prop "Maybe (Metadata StorePath)" $ roundtripSReader @StoreDir maybePathMetadata + prop "Missing" $ roundtripSReader missing + prop "Maybe (Metadata StorePath)" $ roundtripSReader maybePathMetadata restrictProtoVersion :: ProtoVersion -> Some StoreRequest -> Bool restrictProtoVersion v (Some (BuildPaths _ _)) | v < ProtoVersion 1 30 = False From 16cf064d4c09912f82e136c57b65ef7ab3391de7 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 1 Jan 2025 18:16:12 -0500 Subject: [PATCH 51/58] Import qualified post, derivation outputs in protocol --- hnix-store-aterm/bench/Main.hs | 10 +- hnix-store-aterm/hnix-store-aterm.cabal | 20 ++- hnix-store-aterm/pretty-derivation/Main.hs | 8 +- .../System/Nix/Derivation/ATerm/Builder.hs | 75 +++----- .../src/System/Nix/Derivation/ATerm/Parser.hs | 97 +++-------- .../src/System/Nix/Derivation/Traditional.hs | 160 ++++++++++++++++++ hnix-store-aterm/tests/Derivation.hs | 6 +- hnix-store-aterm/tests/DerivationSpec.hs | 6 +- hnix-store-aterm/tests/Example.hs | 8 +- hnix-store-aterm/tests/Property.hs | 12 +- hnix-store-core/hnix-store-core.cabal | 24 +-- hnix-store-core/src/System/Nix/Base.hs | 8 +- hnix-store-core/src/System/Nix/Base32.hs | 18 +- .../src/System/Nix/ContentAddress.hs | 8 +- hnix-store-core/src/System/Nix/Derivation.hs | 4 +- hnix-store-core/src/System/Nix/DerivedPath.hs | 14 +- hnix-store-core/src/System/Nix/Fingerprint.hs | 4 +- hnix-store-core/src/System/Nix/Hash.hs | 12 +- .../src/System/Nix/Hash/Truncation.hs | 8 +- hnix-store-core/src/System/Nix/Realisation.hs | 8 +- hnix-store-core/src/System/Nix/Signature.hs | 10 +- hnix-store-core/src/System/Nix/StorePath.hs | 22 +-- .../System/Nix/StorePath/ContentAddressed.hs | 18 +- hnix-store-core/tests/Fingerprint.hs | 8 +- hnix-store-core/tests/Hash.hs | 8 +- hnix-store-core/tests/Signature.hs | 6 +- hnix-store-core/tests/StorePath.hs | 2 +- hnix-store-db/README.md | 12 +- hnix-store-db/apps/Bench.hs | 2 +- hnix-store-db/hnix-store-db.cabal | 23 +-- .../src/System/Nix/Store/DB/Instances.hs | 12 +- .../src/System/Nix/Store/DB/Query.hs | 10 +- hnix-store-db/src/System/Nix/Store/DB/Run.hs | 22 +-- hnix-store-db/src/System/Nix/Store/DB/Util.hs | 4 +- hnix-store-db/tests/Smoke.hs | 2 +- hnix-store-json/hnix-store-json.cabal | 1 + hnix-store-json/src/System/Nix/JSON.hs | 24 +-- hnix-store-json/tests/JSONSpec.hs | 12 +- hnix-store-nar/hnix-store-nar.cabal | 1 + hnix-store-nar/src/System/Nix/Nar.hs | 14 +- hnix-store-nar/src/System/Nix/Nar/Effects.hs | 12 +- hnix-store-nar/src/System/Nix/Nar/Options.hs | 2 +- hnix-store-nar/src/System/Nix/Nar/Parser.hs | 50 +++--- hnix-store-nar/src/System/Nix/Nar/Streamer.hs | 22 +-- hnix-store-nar/tests/NarFormat.hs | 34 ++-- hnix-store-readonly/hnix-store-readonly.cabal | 1 + .../src/System/Nix/Store/ReadOnly.hs | 4 +- hnix-store-readonly/tests/ReadOnlySpec.hs | 4 +- hnix-store-remote/app/BuildDerivation.hs | 10 +- hnix-store-remote/hnix-store-remote.cabal | 5 +- hnix-store-remote/src/Data/Serializer.hs | 21 ++- .../src/System/Nix/Store/Remote.hs | 8 +- .../src/System/Nix/Store/Remote/Client.hs | 15 +- .../System/Nix/Store/Remote/Client/Core.hs | 4 +- .../src/System/Nix/Store/Remote/Logger.hs | 8 +- .../src/System/Nix/Store/Remote/MonadStore.hs | 2 +- .../src/System/Nix/Store/Remote/Serializer.hs | 148 ++++++++-------- .../src/System/Nix/Store/Remote/Server.hs | 10 +- .../src/System/Nix/Store/Remote/Socket.hs | 8 +- hnix-store-remote/tests-io/Main.hs | 4 +- hnix-store-remote/tests-io/NixDaemonSpec.hs | 40 ++--- hnix-store-remote/tests-io/SampleNar.hs | 4 +- hnix-store-remote/tests/NixSerializerSpec.hs | 6 +- hnix-store-tests/hnix-store-tests.cabal | 1 + .../src/Data/ByteString/Arbitrary.hs | 2 +- .../src/Data/HashSet/Arbitrary.hs | 2 +- hnix-store-tests/src/Data/Text/Arbitrary.hs | 2 +- hnix-store-tests/src/Data/Vector/Arbitrary.hs | 2 +- .../src/System/Nix/Arbitrary/Build.hs | 2 +- .../src/System/Nix/Arbitrary/DerivedPath.hs | 2 +- .../src/System/Nix/Arbitrary/Hash.hs | 2 +- .../src/System/Nix/Arbitrary/OutputName.hs | 4 +- .../src/System/Nix/Arbitrary/Signature.hs | 6 +- .../src/System/Nix/Arbitrary/StorePath.hs | 6 +- .../Nix/Arbitrary/StorePath/Metadata.hs | 2 +- hnix-store-tests/tests/ContentAddressSpec.hs | 2 +- hnix-store-tests/tests/DerivedPathSpec.hs | 2 +- hnix-store-tests/tests/RealisationSpec.hs | 10 +- hnix-store-tests/tests/StorePathSpec.hs | 2 +- 79 files changed, 645 insertions(+), 549 deletions(-) create mode 100644 hnix-store-aterm/src/System/Nix/Derivation/Traditional.hs diff --git a/hnix-store-aterm/bench/Main.hs b/hnix-store-aterm/bench/Main.hs index bab4b2d1..30314692 100644 --- a/hnix-store-aterm/bench/Main.hs +++ b/hnix-store-aterm/bench/Main.hs @@ -1,10 +1,10 @@ import Criterion (Benchmark) -import qualified Criterion -import qualified Criterion.Main -import qualified Data.Attoparsec.Text.Lazy -import qualified Data.Text.Lazy.IO -import qualified Nix.Derivation +import Criterion qualified +import Criterion.Main qualified +import Data.Attoparsec.Text.Lazy qualified +import Data.Text.Lazy.IO qualified +import Nix.Derivation qualified main :: IO () main = Criterion.Main.defaultMain benchmarks diff --git a/hnix-store-aterm/hnix-store-aterm.cabal b/hnix-store-aterm/hnix-store-aterm.cabal index e799fd34..dcef4714 100644 --- a/hnix-store-aterm/hnix-store-aterm.cabal +++ b/hnix-store-aterm/hnix-store-aterm.cabal @@ -1,9 +1,9 @@ +Cabal-Version: 2.2 Name: hnix-store-aterm Version: 1.1.3 -Cabal-Version: >=1.10 Build-Type: Simple Tested-With: GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2, GHC == 8.8.3 -License: BSD3 +License: BSD-3-Clause License-File: LICENSE Copyright: 2017 Gabriella Gonzalez Author: Gabriella Gonzalez @@ -29,8 +29,13 @@ Source-Repository head Type: git Location: https://github.com/Gabriella439/Haskell-Nix-Derivation-Library -Library +Common commons + Default-Extensions: + ImportQualifiedPost Default-Language: Haskell2010 + +Library + Import: commons Hs-Source-Dirs: src Build-Depends: attoparsec >= 0.12.0.0 && < 0.15, @@ -47,13 +52,14 @@ Library vector < 0.14 Exposed-Modules: System.Nix.Derivation.ATerm + System.Nix.Derivation.Traditional Other-Modules: System.Nix.Derivation.ATerm.Builder, System.Nix.Derivation.ATerm.Parser GHC-Options: -Wall Executable pretty-derivation - Default-Language: Haskell2010 + Import: commons Hs-Source-Dirs: pretty-derivation Build-Depends: base >= 4.6.0.0 && < 5 , @@ -65,7 +71,7 @@ Executable pretty-derivation Main-Is: Main.hs Test-Suite example - Default-Language: Haskell2010 + Import: commons Type: exitcode-stdio-1.0 Hs-Source-Dirs: tests Main-Is: Example.hs @@ -77,7 +83,7 @@ Test-Suite example text Test-Suite property - Default-Language: Haskell2010 + Import: commons Type: exitcode-stdio-1.0 Hs-Source-Dirs: tests Main-Is: Property.hs @@ -93,7 +99,7 @@ Test-Suite property filepath < 1.5 Benchmark benchmark - Default-Language: Haskell2010 + Import: commons Type: exitcode-stdio-1.0 HS-Source-Dirs: bench Main-Is: Main.hs diff --git a/hnix-store-aterm/pretty-derivation/Main.hs b/hnix-store-aterm/pretty-derivation/Main.hs index a405c2cc..5e410de3 100644 --- a/hnix-store-aterm/pretty-derivation/Main.hs +++ b/hnix-store-aterm/pretty-derivation/Main.hs @@ -2,10 +2,10 @@ module Main where import Data.Attoparsec.Text.Lazy (Result(..)) -import qualified Data.Attoparsec.Text.Lazy -import qualified Data.Text.Lazy.IO -import qualified Nix.Derivation -import qualified Text.Show.Pretty +import Data.Attoparsec.Text.Lazy qualified +import Data.Text.Lazy.IO qualified +import Nix.Derivation qualified +import Text.Show.Pretty qualified main :: IO () main = do diff --git a/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Builder.hs b/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Builder.hs index 63833867..95fad44d 100644 --- a/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Builder.hs +++ b/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Builder.hs @@ -12,39 +12,29 @@ module System.Nix.Derivation.ATerm.Builder , buildDerivationInputs ) where -import Data.Dependent.Sum import Data.Map (Map) -import Data.Map.Monoidal (MonoidalMap(..)) import Data.Set (Set) -import Data.Some -import Data.These (These(..)) import Data.Text (Text) import Data.Text.Lazy.Builder (Builder) import Data.Vector (Vector) -import System.Nix.ContentAddress import System.Nix.Derivation - ( Derivation - , Derivation'(..) + ( Derivation'(..) , DerivationOutput(..) - , DerivationInputs(..) - , DerivedPathMap(..) - , unChildNode ) -import System.Nix.Hash +import System.Nix.Derivation.Traditional import System.Nix.StorePath -import System.Nix.StorePath.ContentAddressed import System.Nix.OutputName -import qualified Data.Map -import qualified Data.Set -import qualified Data.Text -import qualified Data.Text.Lazy.Builder -import qualified Data.Vector +import Data.Map qualified +import Data.Set qualified +import Data.Text qualified +import Data.Text.Lazy.Builder qualified +import Data.Vector qualified -- | Render a derivation as a `Builder` buildDerivation :: StoreDir - -> Derivation + -> Derivation' TraditionalDerivationInputs DerivationOutput -> Builder buildDerivation sd = buildDerivationWith @@ -87,15 +77,6 @@ buildDerivationWith drvInputs drvOutput (Derivation {..}) = <> string value <> ")" -buildMethodHashAlgo :: ContentAddressMethod -> Some HashAlgo -> Text -buildMethodHashAlgo method hashAlgo = Data.Text.intercalate ":" $ - (case method of - ContentAddressMethod_NixArchive -> ["r"] - ContentAddressMethod_Text -> ["text"] - ContentAddressMethod_Flat -> []) - <> - [withSome hashAlgo algoToText] - -- | Render a @DerivationOutput@ as a `Builder` using custom -- renderer for storePaths buildDerivationOutput @@ -104,49 +85,33 @@ buildDerivationOutput -> OutputName -> DerivationOutput -> Builder -buildDerivationOutput storeDir drvName outputName = \case - InputAddressedDerivationOutput {..} -> - storePath storeDir path - <> "," - <> emptyString +buildDerivationOutput storeDir drvName outputName = + ( \RawDerivationOutput {..} -> + string rawPath <> "," - <> emptyString - FixedDerivationOutput {..} -> case hash of - hashAlgo :=> hash' -> - storePath storeDir (makeFixedOutputPath storeDir method hash mempty $ outputStoreObjectName drvName outputName) - <> "," - <> string (buildMethodHashAlgo method $ Some hashAlgo) - <> "," - <> string (encodeDigestWith NixBase32 hash') - ContentAddressedDerivationOutput {..} -> - emptyString + <> string rawMethodHashAlgo <> "," - <> string (buildMethodHashAlgo method hashAlgo) - <> "," - <> emptyString - where - emptyString = string Data.Text.empty + <> string rawHash + ) + . renderRawDerivationOutput storeDir drvName outputName -- | Render a @DerivationInputs@ as a `Builder` using custom -- renderer for storePaths and output names buildDerivationInputs :: StoreDir - -> DerivationInputs + -> TraditionalDerivationInputs -> Builder -buildDerivationInputs storeDir (DerivationInputs {..}) = - mapOf keyValue (getMonoidalMap $ unDerivedPathMap drvs) +buildDerivationInputs storeDir (TraditionalDerivationInputs {..}) = + mapOf keyValue traditionalDrvs <> "," - <> setOf (storePath storeDir) srcs + <> setOf (storePath storeDir) traditionalSrcs where keyValue (key, value) = "(" <> storePath storeDir key <> "," - <> setOf buildOutputName outputNames + <> setOf buildOutputName value <> ")" - where outputNames = case unChildNode value of - This os -> os - _ -> error "dynamic derivations are not supported in the ATerm format yet" mapOf :: ((k, v) -> Builder) -> Map k v -> Builder mapOf keyValue m = listOf keyValue (Data.Map.toList m) diff --git a/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Parser.hs b/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Parser.hs index eba9c23d..5813eccf 100644 --- a/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Parser.hs +++ b/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Parser.hs @@ -16,38 +16,26 @@ module System.Nix.Derivation.ATerm.Parser , textParser ) where -import Control.Monad (when) +import Data.Attoparsec.Text qualified import Data.Attoparsec.Text.Lazy (Parser) -import Data.Constraint.Extras (Has(has)) -import Data.Dependent.Sum -import Data.These (These(This)) +import Data.Attoparsec.Text.Lazy qualified import Data.Map (Map) -import Data.Map.Monoidal (MonoidalMap(..)) +import Data.Map qualified import Data.Set (Set) -import Data.Some +import Data.Set qualified import Data.Text (Text) +import Data.Text qualified import Data.Vector (Vector) -import System.Nix.ContentAddress +import Data.Vector qualified + +import System.Nix.Derivation.Traditional import System.Nix.Derivation - ( Derivation - , Derivation'(..) + ( Derivation'(..) , DerivationOutput(..) - , DerivedPathMap(..) - , ChildNode(..) - , DerivationInputs(..) ) -import System.Nix.Hash import System.Nix.StorePath -import System.Nix.StorePath.ContentAddressed import System.Nix.OutputName -import qualified Data.Attoparsec.Text -import qualified Data.Attoparsec.Text.Lazy -import qualified Data.Map -import qualified Data.Set -import qualified Data.Text -import qualified Data.Vector - listOf :: Parser a -> Parser [a] listOf element = do "[" @@ -56,7 +44,7 @@ listOf element = do pure es -- | Parse a derivation -parseDerivation :: StoreDir -> StorePathName -> Parser Derivation +parseDerivation :: StoreDir -> StorePathName -> Parser (Derivation' TraditionalDerivationInputs DerivationOutput) parseDerivation sd = parseDerivationWith (parseDerivationInputs sd) @@ -112,68 +100,31 @@ parseDerivationWith parseInputs parseOutput name = do pure Derivation {..} -splitMethodHashAlgo :: Text -> Parser (ContentAddressMethod, Some HashAlgo) -splitMethodHashAlgo methodHashAlgo = do - (method, hashAlgoS) <- case Data.Text.splitOn ":" methodHashAlgo of - ["r", hashAlgo] -> pure (ContentAddressMethod_NixArchive, hashAlgo) - ["text", hashAlgo] -> pure (ContentAddressMethod_NixArchive, hashAlgo) - [hashAlgo] -> pure (ContentAddressMethod_Flat, hashAlgo) - _ -> fail "invalid number of colons or unknown CA method prefix" - hashAlgo <- either fail pure $ textToAlgo hashAlgoS - pure (method, hashAlgo) - -- | Parse a derivation output parseDerivationOutput :: StoreDir -> StorePathName -> OutputName -> Parser DerivationOutput parseDerivationOutput sd drvName outputName = do - mPath <- maybeTextParser $ storePathParser sd + rawPath <- textParser "," - mHashAlgo <- maybeTextParser textParser + rawMethodHashAlgo <- textParser "," - mHash <- maybeTextParser textParser - case (mPath, mHashAlgo, mHash) of - (Just path, Nothing, Nothing) -> - pure InputAddressedDerivationOutput {..} - (Just path, Just methodHashAlgo, Just hash0) -> do - (method, Some hashAlgo) <- splitMethodHashAlgo methodHashAlgo - hash' <- either fail pure $ has @NamedAlgo hashAlgo $ - decodeDigestWith NixBase32 hash0 - let hash = hashAlgo :=> hash' - let expectedPath = makeFixedOutputPath sd method hash mempty $ outputStoreObjectName drvName outputName - when (path /= expectedPath) $ - fail "fixed output path does not match info" - pure FixedDerivationOutput {..} - (Nothing, Just methodHashAlgo, Nothing) -> do - (method, hashAlgo) <- splitMethodHashAlgo methodHashAlgo - pure ContentAddressedDerivationOutput {..} - _ -> - fail "bad output in derivation" + rawHash <- textParser + parseRawDerivationOutput sd drvName outputName $ RawDerivationOutput {..} -- | Parse a derivation inputs -parseDerivationInputs :: StoreDir -> Parser DerivationInputs +parseDerivationInputs :: StoreDir -> Parser TraditionalDerivationInputs parseDerivationInputs sd = do - let keyValue = do - "(" - key <- storePathParser sd - "," - value <- setOf outputNameParser - ")" - pure - ( key - , ChildNode $ This value - ) - drvs <- DerivedPathMap . MonoidalMap <$> mapOf keyValue + traditionalDrvs <- mapOf $ do + "(" + key <- storePathParser sd + "," + value <- setOf outputNameParser + ")" + pure (key, value) "," - srcs <- setOf $ storePathParser sd - pure DerivationInputs {..} - -maybeTextParser :: Parser a -> Parser (Maybe a) -maybeTextParser p = do - t <- textParser - if t == "" - then pure Nothing - else Just <$> p + traditionalSrcs <- setOf $ storePathParser sd + pure TraditionalDerivationInputs {..} textParser :: Parser Text textParser = do diff --git a/hnix-store-aterm/src/System/Nix/Derivation/Traditional.hs b/hnix-store-aterm/src/System/Nix/Derivation/Traditional.hs new file mode 100644 index 00000000..b468478c --- /dev/null +++ b/hnix-store-aterm/src/System/Nix/Derivation/Traditional.hs @@ -0,0 +1,160 @@ +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE KindSignatures #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications #-} + +-- | Shared types + +module System.Nix.Derivation.Traditional + ( RawDerivationOutput(..) + , parseRawDerivationOutput + , renderRawDerivationOutput + , TraditionalDerivationInputs(..) + , inputsToTraditional + ) where + + +import Control.Monad (when) +import Control.DeepSeq (NFData(..)) +import Data.Constraint.Extras (Has(has)) +import Data.Dependent.Sum (DSum(..)) +import Data.Map (Map) +import Data.Map.Monoidal (MonoidalMap(..)) +import Data.Map.Monoidal qualified +import Data.Set (Set) +import Data.Some +import Data.Text (Text) +import Data.Text qualified +import Data.These (These(..)) +import GHC.Generics (Generic) + +import System.Nix.ContentAddress (ContentAddressMethod(..)) +import System.Nix.Derivation +import System.Nix.Hash +import System.Nix.OutputName (OutputName, outputStoreObjectName) +import System.Nix.StorePath +import System.Nix.StorePath.ContentAddressed + +-- | Useful for the ATerm format, and remote protocols that need the same parsing +-- If it won't for the protocol, we would just inline this into the ATerm code proper. +data RawDerivationOutput = RawDerivationOutput + { rawPath :: Text + , rawMethodHashAlgo :: Text + , rawHash :: Text + } deriving (Eq, Generic, Ord, Show) + +parseRawDerivationOutput + :: forall m + . MonadFail m + => StoreDir + -> StorePathName + -> OutputName + -> RawDerivationOutput + -> m DerivationOutput +parseRawDerivationOutput storeDir drvName outputName (RawDerivationOutput {..}) = do + let onNonEmptyText :: Text -> (Text -> m a) -> m (Maybe a) + onNonEmptyText = flip $ \f -> \case + "" -> pure Nothing + t -> Just <$> f t + mPath <- onNonEmptyText rawPath $ \t -> case System.Nix.StorePath.parsePathFromText storeDir t of + Left e -> fail $ show e -- TODO + Right sp -> pure sp + mHashAlgo <- onNonEmptyText rawMethodHashAlgo splitMethodHashAlgo + mHash <- onNonEmptyText rawHash pure + case (mPath, mHashAlgo, mHash) of + (Just path, Nothing, Nothing) -> + pure InputAddressedDerivationOutput {..} + (Just path, Just (method, Some hashAlgo), Just hash0) -> do + hash' <- either fail pure $ has @NamedAlgo hashAlgo $ + decodeDigestWith NixBase32 hash0 + let hash = hashAlgo :=> hash' + let expectedPath = makeFixedOutputPath storeDir method hash mempty $ outputStoreObjectName drvName outputName + when (path /= expectedPath) $ + fail "fixed output path does not match info" + pure FixedDerivationOutput {..} + (Nothing, Just (method, hashAlgo), Nothing) -> do + pure ContentAddressedDerivationOutput {..} + _ -> + fail "bad output in derivation" + +renderRawDerivationOutput + :: StoreDir + -> StorePathName + -> OutputName + -> DerivationOutput + -> RawDerivationOutput +renderRawDerivationOutput storeDir drvName outputName = \case + InputAddressedDerivationOutput {..} -> RawDerivationOutput + { rawPath = storePathToText storeDir path + , rawMethodHashAlgo = "" + , rawHash = "" + } + FixedDerivationOutput {..} -> case hash of + hashAlgo :=> hash' -> RawDerivationOutput + { rawPath = storePathToText storeDir $ makeFixedOutputPath storeDir method hash mempty $ outputStoreObjectName drvName outputName + , rawMethodHashAlgo = buildMethodHashAlgo method $ Some hashAlgo + , rawHash = encodeDigestWith NixBase32 hash' + } + ContentAddressedDerivationOutput {..} -> RawDerivationOutput + { rawPath = "" + , rawMethodHashAlgo = buildMethodHashAlgo method hashAlgo + , rawHash = "" + } + +buildMethodHashAlgo :: ContentAddressMethod -> Some HashAlgo -> Text +buildMethodHashAlgo method hashAlgo = Data.Text.intercalate ":" $ + (case method of + ContentAddressMethod_NixArchive -> ["r"] + ContentAddressMethod_Text -> ["text"] + ContentAddressMethod_Flat -> []) + <> + [withSome hashAlgo algoToText] + +splitMethodHashAlgo :: MonadFail m => Text -> m (ContentAddressMethod, Some HashAlgo) +splitMethodHashAlgo methodHashAlgo = do + (method, hashAlgoS) <- case Data.Text.splitOn ":" methodHashAlgo of + ["r", hashAlgo] -> pure (ContentAddressMethod_NixArchive, hashAlgo) + ["text", hashAlgo] -> pure (ContentAddressMethod_NixArchive, hashAlgo) + [hashAlgo] -> pure (ContentAddressMethod_Flat, hashAlgo) + _ -> fail "invalid number of colons or unknown CA method prefix" + hashAlgo <- either fail pure $ textToAlgo hashAlgoS + pure (method, hashAlgo) + +-- | Useful for the ATerm format +data TraditionalDerivationInputs = TraditionalDerivationInputs + { traditionalSrcs :: Set StorePath + -- ^ Inputs that are sources + , traditionalDrvs :: Map StorePath (Set OutputName) + -- ^ Inputs that are derivations where keys specify derivation paths and + -- values specify which output names are used by this derivation + } deriving (Eq, Generic, Ord, Show) + +instance NFData TraditionalDerivationInputs + +instance Semigroup TraditionalDerivationInputs where + TraditionalDerivationInputs x0 x1 <> TraditionalDerivationInputs y0 y1 = TraditionalDerivationInputs + (x0 <> y0) + (x1 <> y1) + +instance Monoid TraditionalDerivationInputs where + mempty = TraditionalDerivationInputs mempty mempty + +inputsToTraditional :: DerivationInputs -> Either StorePath TraditionalDerivationInputs +inputsToTraditional is = (\drvs -> TraditionalDerivationInputs + { traditionalSrcs = srcs is + , traditionalDrvs = drvs + }) <$> go (drvs is) + where + go = fmap getMonoidalMap + . Data.Map.Monoidal.traverseWithKey + (\storePath -> (\case + This os -> Right os + _ -> Left storePath -- TODO make better error, e.g. by partitioning the map + ) . unChildNode) + . unDerivedPathMap diff --git a/hnix-store-aterm/tests/Derivation.hs b/hnix-store-aterm/tests/Derivation.hs index aa8010dd..c7312999 100644 --- a/hnix-store-aterm/tests/Derivation.hs +++ b/hnix-store-aterm/tests/Derivation.hs @@ -6,9 +6,9 @@ import Test.Tasty.Golden (goldenVsFile) import System.Nix.Derivation (parseDerivation, buildDerivation) import Data.Default.Class (Default(def)) -import qualified Data.Attoparsec.Text.Lazy -import qualified Data.Text.Lazy.IO -import qualified Data.Text.Lazy.Builder +import Data.Attoparsec.Text.Lazy qualified +import Data.Text.Lazy.IO qualified +import Data.Text.Lazy.Builder qualified processDerivation :: FilePath -> FilePath -> IO () processDerivation source dest = do diff --git a/hnix-store-aterm/tests/DerivationSpec.hs b/hnix-store-aterm/tests/DerivationSpec.hs index 39e90fed..1a86c70f 100644 --- a/hnix-store-aterm/tests/DerivationSpec.hs +++ b/hnix-store-aterm/tests/DerivationSpec.hs @@ -7,9 +7,9 @@ import Test.Hspec.Nix (roundtrips) import System.Nix.Arbitrary () import System.Nix.Derivation (parseDerivation, buildDerivation) -import qualified Data.Attoparsec.Text -import qualified Data.Text.Lazy -import qualified Data.Text.Lazy.Builder +import Data.Attoparsec.Text qualified +import Data.Text.Lazy qualified +import Data.Text.Lazy.Builder qualified -- TODO(srk): this won't roundtrip as Arbitrary Text -- contains wild stuff like control characters and UTF8 sequences. diff --git a/hnix-store-aterm/tests/Example.hs b/hnix-store-aterm/tests/Example.hs index 035b69cf..d819b9ec 100644 --- a/hnix-store-aterm/tests/Example.hs +++ b/hnix-store-aterm/tests/Example.hs @@ -1,9 +1,9 @@ module Main where -import qualified Nix.Derivation -import qualified Data.Attoparsec.Text.Lazy -import qualified Data.Text.Lazy.Builder -import qualified Data.Text.Lazy.IO +import Nix.Derivation qualified +import Data.Attoparsec.Text.Lazy qualified +import Data.Text.Lazy.Builder qualified +import Data.Text.Lazy.IO qualified import Data.Attoparsec.Text.Lazy (Result(..)) diff --git a/hnix-store-aterm/tests/Property.hs b/hnix-store-aterm/tests/Property.hs index 420175b1..d5bc7680 100644 --- a/hnix-store-aterm/tests/Property.hs +++ b/hnix-store-aterm/tests/Property.hs @@ -19,12 +19,12 @@ import Nix.Derivation import Prelude hiding (FilePath, either) import Test.QuickCheck (Arbitrary(..), Gen, oneof) -import qualified Data.Attoparsec.Text.Lazy -import qualified Data.Text -import qualified Data.Text.Lazy.Builder -import qualified Data.Vector -import qualified Nix.Derivation -import qualified Test.QuickCheck +import Data.Attoparsec.Text.Lazy qualified +import Data.Text qualified +import Data.Text.Lazy.Builder qualified +import Data.Vector qualified +import Nix.Derivation qualified +import Test.QuickCheck qualified instance Arbitrary Text where arbitrary = fmap Data.Text.pack arbitrary diff --git a/hnix-store-core/hnix-store-core.cabal b/hnix-store-core/hnix-store-core.cabal index 62516bbf..9f30f9f1 100644 --- a/hnix-store-core/hnix-store-core.cabal +++ b/hnix-store-core/hnix-store-core.cabal @@ -24,33 +24,35 @@ common commons ghc-options: -Wall default-extensions: ConstraintKinds + , BangPatterns , DataKinds - , DeriveGeneric , DeriveDataTypeable - , DeriveFunctor , DeriveFoldable - , DeriveTraversable + , DeriveFunctor + , DeriveGeneric , DeriveLift + , DeriveTraversable , DerivingStrategies , DerivingVia , ExistentialQuantification + , ImportQualifiedPost , FlexibleContexts , FlexibleInstances , GADTs + , ImportQualifiedPost + , InstanceSigs + , KindSignatures + , LambdaCase + , MultiParamTypeClasses + , MultiWayIf + , RecordWildCards , ScopedTypeVariables , StandaloneDeriving - , RecordWildCards + , TupleSections , TypeApplications , TypeFamilies , TypeOperators , TypeSynonymInstances - , InstanceSigs - , KindSignatures - , MultiParamTypeClasses - , MultiWayIf - , TupleSections - , LambdaCase - , BangPatterns , ViewPatterns default-language: Haskell2010 diff --git a/hnix-store-core/src/System/Nix/Base.hs b/hnix-store-core/src/System/Nix/Base.hs index 37a9c687..bff1bd10 100644 --- a/hnix-store-core/src/System/Nix/Base.hs +++ b/hnix-store-core/src/System/Nix/Base.hs @@ -8,11 +8,11 @@ import Data.ByteString (ByteString) import Data.Text (Text) import GHC.Generics (Generic) -import qualified Data.Text.Encoding -import qualified Data.ByteString.Base16 -import qualified Data.ByteString.Base64 +import Data.Text.Encoding qualified +import Data.ByteString.Base16 qualified +import Data.ByteString.Base64 qualified -import qualified System.Nix.Base32 -- Nix has own Base32 encoding +import System.Nix.Base32 qualified -- Nix has own Base32 encoding -- | Constructors to indicate the base encodings data BaseEncoding diff --git a/hnix-store-core/src/System/Nix/Base32.hs b/hnix-store-core/src/System/Nix/Base32.hs index cb9e54f4..4cae649e 100644 --- a/hnix-store-core/src/System/Nix/Base32.hs +++ b/hnix-store-core/src/System/Nix/Base32.hs @@ -12,15 +12,15 @@ import Data.Text (Text) import Data.Vector (Vector) import Data.Word (Word8) -import qualified Data.Bits -import qualified Data.Bool -import qualified Data.ByteString -import qualified Data.ByteString.Char8 -import qualified Data.List -import qualified Data.Maybe -import qualified Data.Text -import qualified Data.Vector -import qualified Numeric +import Data.Bits qualified +import Data.Bool qualified +import Data.ByteString qualified +import Data.ByteString.Char8 qualified +import Data.List qualified +import Data.Maybe qualified +import Data.Text qualified +import Data.Vector qualified +import Numeric qualified -- omitted: E O U T digits32 :: Vector Char diff --git a/hnix-store-core/src/System/Nix/ContentAddress.hs b/hnix-store-core/src/System/Nix/ContentAddress.hs index c5875401..71747672 100644 --- a/hnix-store-core/src/System/Nix/ContentAddress.hs +++ b/hnix-store-core/src/System/Nix/ContentAddress.hs @@ -19,10 +19,10 @@ import Data.Text.Lazy.Builder (Builder) import GHC.Generics (Generic) import System.Nix.Hash (HashAlgo) -import qualified Data.Attoparsec.Text -import qualified Data.Text.Lazy -import qualified Data.Text.Lazy.Builder -import qualified System.Nix.Hash +import Data.Attoparsec.Text qualified +import Data.Text.Lazy qualified +import Data.Text.Lazy.Builder qualified +import System.Nix.Hash qualified data ContentAddressMethod = ContentAddressMethod_Flat diff --git a/hnix-store-core/src/System/Nix/Derivation.hs b/hnix-store-core/src/System/Nix/Derivation.hs index b45ea179..b4080b63 100644 --- a/hnix-store-core/src/System/Nix/Derivation.hs +++ b/hnix-store-core/src/System/Nix/Derivation.hs @@ -29,9 +29,9 @@ import Crypto.Hash (Digest) import Data.Dependent.Sum (DSum(..)) import Data.Map (Map) import Data.Map.Monoidal (MonoidalMap) -import qualified Data.Map.Monoidal +import Data.Map.Monoidal qualified import Data.Set (Set) -import qualified Data.Set +import Data.Set qualified import Data.Some (Some(..)) import Data.GADT.DeepSeq (GNFData(..)) import Data.Text (Text) diff --git a/hnix-store-core/src/System/Nix/DerivedPath.hs b/hnix-store-core/src/System/Nix/DerivedPath.hs index a6d88b82..13dc85da 100644 --- a/hnix-store-core/src/System/Nix/DerivedPath.hs +++ b/hnix-store-core/src/System/Nix/DerivedPath.hs @@ -19,13 +19,13 @@ import Data.Text (Text) import System.Nix.OutputName (OutputName, InvalidNameError) import System.Nix.StorePath (StoreDir(..), StorePath, InvalidPathError) -import qualified Data.Bifunctor -import qualified Data.ByteString.Char8 -import qualified Data.Set -import qualified Data.List -import qualified Data.Text -import qualified System.Nix.OutputName -import qualified System.Nix.StorePath +import Data.Bifunctor qualified +import Data.ByteString.Char8 qualified +import Data.Set qualified +import Data.List qualified +import Data.Text qualified +import System.Nix.OutputName qualified +import System.Nix.StorePath qualified data OutputsSpec = OutputsSpec_All diff --git a/hnix-store-core/src/System/Nix/Fingerprint.hs b/hnix-store-core/src/System/Nix/Fingerprint.hs index 4eb7f309..6ba71edc 100644 --- a/hnix-store-core/src/System/Nix/Fingerprint.hs +++ b/hnix-store-core/src/System/Nix/Fingerprint.hs @@ -20,8 +20,8 @@ import System.Nix.Hash (HashAlgo, algoDigestBuilder) import System.Nix.StorePath import System.Nix.StorePath.Metadata (Metadata(..)) -import qualified Data.HashSet as HashSet -import qualified Data.Text as Text +import Data.HashSet qualified as HashSet +import Data.Text qualified as Text -- | Produce the message signed by a NAR signature metadataFingerprint :: StoreDir -> StorePath -> Metadata StorePath -> Text diff --git a/hnix-store-core/src/System/Nix/Hash.hs b/hnix-store-core/src/System/Nix/Hash.hs index 0d91883f..037f6d1b 100644 --- a/hnix-store-core/src/System/Nix/Hash.hs +++ b/hnix-store-core/src/System/Nix/Hash.hs @@ -40,12 +40,12 @@ import Data.Text (Text) import Data.Text.Lazy.Builder (Builder) import System.Nix.Base (BaseEncoding(..)) -import qualified Crypto.Hash -import qualified Data.ByteArray -import qualified Data.Text -import qualified Data.Text.Lazy.Builder -import qualified System.Nix.Base -import qualified System.Nix.Hash.Truncation +import Crypto.Hash qualified +import Data.ByteArray qualified +import Data.Text qualified +import Data.Text.Lazy.Builder qualified +import System.Nix.Base qualified +import System.Nix.Hash.Truncation qualified -- | A 'HashAlgorithm' with a canonical name, for serialization -- purposes (e.g. SRI hashes) diff --git a/hnix-store-core/src/System/Nix/Hash/Truncation.hs b/hnix-store-core/src/System/Nix/Hash/Truncation.hs index 975f65fe..dafaa0b2 100644 --- a/hnix-store-core/src/System/Nix/Hash/Truncation.hs +++ b/hnix-store-core/src/System/Nix/Hash/Truncation.hs @@ -5,10 +5,10 @@ module System.Nix.Hash.Truncation import Data.Word (Word8) import Data.ByteString (ByteString) -import qualified Data.ByteString -import qualified Data.Bits -import qualified Data.Bool -import qualified Data.List +import Data.ByteString qualified +import Data.Bits qualified +import Data.Bool qualified +import Data.List qualified -- | Bytewise truncation of a 'Digest'. -- diff --git a/hnix-store-core/src/System/Nix/Realisation.hs b/hnix-store-core/src/System/Nix/Realisation.hs index 353fe5e5..fd799221 100644 --- a/hnix-store-core/src/System/Nix/Realisation.hs +++ b/hnix-store-core/src/System/Nix/Realisation.hs @@ -23,10 +23,10 @@ import System.Nix.OutputName (OutputName, InvalidNameError) import System.Nix.Signature (Signature) import System.Nix.StorePath (StorePath) -import qualified Data.Bifunctor -import qualified Data.Text -import qualified Data.Text.Lazy.Builder -import qualified System.Nix.Hash +import Data.Bifunctor qualified +import Data.Text qualified +import Data.Text.Lazy.Builder qualified +import System.Nix.Hash qualified -- | Output of the derivation data DerivationOutput a = DerivationOutput diff --git a/hnix-store-core/src/System/Nix/Signature.hs b/hnix-store-core/src/System/Nix/Signature.hs index c8e55b73..ac7b7223 100644 --- a/hnix-store-core/src/System/Nix/Signature.hs +++ b/hnix-store-core/src/System/Nix/Signature.hs @@ -22,11 +22,11 @@ import Data.Text (Text) import GHC.Generics (Generic) import System.Nix.Base (decodeWith, encodeWith, BaseEncoding(Base64)) -import qualified Crypto.PubKey.Ed25519 as Ed25519 -import qualified Data.Attoparsec.Text -import qualified Data.ByteArray -import qualified Data.Char -import qualified Data.Text +import Crypto.PubKey.Ed25519 qualified as Ed25519 +import Data.Attoparsec.Text qualified +import Data.ByteArray qualified +import Data.Char qualified +import Data.Text qualified -- | An ed25519 signature. newtype Signature = Signature Ed25519.Signature diff --git a/hnix-store-core/src/System/Nix/StorePath.hs b/hnix-store-core/src/System/Nix/StorePath.hs index bf24c715..e13574a8 100644 --- a/hnix-store-core/src/System/Nix/StorePath.hs +++ b/hnix-store-core/src/System/Nix/StorePath.hs @@ -48,17 +48,17 @@ import Data.Text (Text) import GHC.Generics (Generic) import System.Nix.Base (BaseEncoding(NixBase32)) -import qualified Data.Bifunctor -import qualified Data.ByteString.Char8 -import qualified Data.Char -import qualified Data.Text -import qualified Data.Text.Encoding -import qualified Data.Attoparsec.Text.Lazy -import qualified System.FilePath - -import qualified System.Nix.Base -import qualified System.Nix.Hash -import qualified System.Nix.Base32 +import Data.Bifunctor qualified +import Data.ByteString.Char8 qualified +import Data.Char qualified +import Data.Text qualified +import Data.Text.Encoding qualified +import Data.Attoparsec.Text.Lazy qualified +import System.FilePath qualified + +import System.Nix.Base qualified +import System.Nix.Hash qualified +import System.Nix.Base32 qualified -- | A path in a Nix store. -- diff --git a/hnix-store-core/src/System/Nix/StorePath/ContentAddressed.hs b/hnix-store-core/src/System/Nix/StorePath/ContentAddressed.hs index 18fccd92..47d2c4c5 100644 --- a/hnix-store-core/src/System/Nix/StorePath/ContentAddressed.hs +++ b/hnix-store-core/src/System/Nix/StorePath/ContentAddressed.hs @@ -17,15 +17,15 @@ import System.Nix.ContentAddress (ContentAddressMethod (..)) import System.Nix.Hash (BaseEncoding(Base16), HashAlgo(..)) import System.Nix.StorePath (StoreDir, StorePath, StorePathName) -import qualified Crypto.Hash -import qualified Data.ByteString.Char8 -import qualified Data.ByteString -import qualified Data.HashSet -import qualified Data.List -import qualified Data.Text -import qualified Data.Text.Encoding -import qualified System.Nix.Hash -import qualified System.Nix.StorePath +import Crypto.Hash qualified +import Data.ByteString.Char8 qualified +import Data.ByteString qualified +import Data.HashSet qualified +import Data.List qualified +import Data.Text qualified +import Data.Text.Encoding qualified +import System.Nix.Hash qualified +import System.Nix.StorePath qualified data References = References { references_others :: HashSet StorePath diff --git a/hnix-store-core/tests/Fingerprint.hs b/hnix-store-core/tests/Fingerprint.hs index 3a53db90..90679bf7 100644 --- a/hnix-store-core/tests/Fingerprint.hs +++ b/hnix-store-core/tests/Fingerprint.hs @@ -16,10 +16,10 @@ import Data.Time.Clock (UTCTime(..)) import Data.Time.Calendar.OrdinalDate (fromOrdinalDate) import Test.Hspec -import qualified Crypto.PubKey.Ed25519 as Ed25519 -import qualified Data.HashSet as HashSet -import qualified Data.Set as Set -import qualified Data.Text.Encoding as Text +import Crypto.PubKey.Ed25519 qualified as Ed25519 +import Data.HashSet qualified as HashSet +import Data.Set qualified as Set +import Data.Text.Encoding qualified as Text spec_fingerprint :: Spec spec_fingerprint = do diff --git a/hnix-store-core/tests/Hash.hs b/hnix-store-core/tests/Hash.hs index 2d735818..0834895b 100644 --- a/hnix-store-core/tests/Hash.hs +++ b/hnix-store-core/tests/Hash.hs @@ -7,10 +7,10 @@ import Data.ByteString (ByteString) import Control.Monad (forM_) import Crypto.Hash (MD5, SHA1, SHA256, hash) -import qualified Data.ByteString.Base16 as B16 -import qualified System.Nix.Base32 as B32 -import qualified Data.ByteString.Base64.Lazy as B64 -import qualified Data.ByteString.Lazy as BSL +import Data.ByteString.Base16 qualified as B16 +import System.Nix.Base32 qualified as B32 +import Data.ByteString.Base64.Lazy qualified as B64 +import Data.ByteString.Lazy qualified as BSL import System.Nix.Base diff --git a/hnix-store-core/tests/Signature.hs b/hnix-store-core/tests/Signature.hs index 5841a2be..6102050e 100644 --- a/hnix-store-core/tests/Signature.hs +++ b/hnix-store-core/tests/Signature.hs @@ -5,11 +5,11 @@ module Signature where -import qualified Data.ByteString as BS +import Data.ByteString qualified as BS import Test.Hspec import Data.Text (Text) -import qualified Crypto.PubKey.Ed25519 -import qualified System.Nix.Base +import Crypto.PubKey.Ed25519 qualified +import System.Nix.Base qualified import System.Nix.Base (BaseEncoding(Base64)) import Crypto.Error (CryptoFailable(..)) diff --git a/hnix-store-core/tests/StorePath.hs b/hnix-store-core/tests/StorePath.hs index 46a28f9f..3c9c742e 100644 --- a/hnix-store-core/tests/StorePath.hs +++ b/hnix-store-core/tests/StorePath.hs @@ -4,7 +4,7 @@ module StorePath where import Test.Hspec (Spec, describe, it, shouldBe) -import qualified Data.Text +import Data.Text qualified import System.Nix.StorePath (parseNameText, InvalidNameError(..)) diff --git a/hnix-store-db/README.md b/hnix-store-db/README.md index e8067540..e93c53c0 100644 --- a/hnix-store-db/README.md +++ b/hnix-store-db/README.md @@ -24,14 +24,14 @@ This example is runnable via `cabal run db-readme`. import Data.Default.Class (Default(def)) -import qualified Control.Monad -import qualified Control.Monad.IO.Class +import Control.Monad qualified +import Control.Monad.IO.Class qualified -import qualified Database.Esqueleto.Experimental +import Database.Esqueleto.Experimental qualified -import qualified System.Nix.StorePath -import qualified System.Nix.Store.DB.Run -import qualified System.Nix.Store.DB.Schema +import System.Nix.StorePath qualified +import System.Nix.Store.DB.Run qualified +import System.Nix.Store.DB.Schema qualified import System.Nix.Store.DB.Query diff --git a/hnix-store-db/apps/Bench.hs b/hnix-store-db/apps/Bench.hs index 9328a485..e0260023 100644 --- a/hnix-store-db/apps/Bench.hs +++ b/hnix-store-db/apps/Bench.hs @@ -1,6 +1,6 @@ module Main where -import qualified System.Nix.Store.DB.Run +import System.Nix.Store.DB.Run qualified main :: IO () main = System.Nix.Store.DB.Run.bench diff --git a/hnix-store-db/hnix-store-db.cabal b/hnix-store-db/hnix-store-db.cabal index 5f14c387..e281009a 100644 --- a/hnix-store-db/hnix-store-db.cabal +++ b/hnix-store-db/hnix-store-db.cabal @@ -32,31 +32,32 @@ flag build-readme common commons ghc-options: -Wall -Wunused-packages default-extensions: - OverloadedStrings + BangPatterns , DataKinds - , DeriveGeneric , DeriveDataTypeable - , DeriveFunctor , DeriveFoldable - , DeriveTraversable + , DeriveFunctor + , DeriveGeneric , DeriveLift + , DeriveTraversable , DerivingStrategies , FlexibleContexts , FlexibleInstances , GADTs , GeneralizedNewtypeDeriving + , ImportQualifiedPost + , InstanceSigs + , LambdaCase + , MultiParamTypeClasses + , OverloadedStrings , RecordWildCards , ScopedTypeVariables , StandaloneDeriving + , TupleSections , TypeApplications , TypeFamilies , TypeOperators , TypeSynonymInstances - , InstanceSigs - , MultiParamTypeClasses - , TupleSections - , LambdaCase - , BangPatterns , ViewPatterns default-language: Haskell2010 @@ -91,6 +92,7 @@ library , unliftio-core executable db-readme + import: commons if !flag(build-readme) buildable: False build-depends: @@ -101,17 +103,16 @@ executable db-readme , hnix-store-db build-tool-depends: markdown-unlit:markdown-unlit - default-language: Haskell2010 main-is: README.lhs ghc-options: -pgmL markdown-unlit -Wall executable db-bench + import: commons if !flag(build-bench) buildable: False build-depends: base >=4.12 && <5 , hnix-store-db - default-language: Haskell2010 hs-source-dirs: apps main-is: Bench.hs ghc-options: -Wall diff --git a/hnix-store-db/src/System/Nix/Store/DB/Instances.hs b/hnix-store-db/src/System/Nix/Store/DB/Instances.hs index c9301651..fe3425e3 100644 --- a/hnix-store-db/src/System/Nix/Store/DB/Instances.hs +++ b/hnix-store-db/src/System/Nix/Store/DB/Instances.hs @@ -15,13 +15,13 @@ import System.Nix.ContentAddress (ContentAddress) import System.Nix.StorePath (StorePath) import System.Nix.StorePath.Metadata (StorePathTrust(..)) -import qualified Data.Attoparsec.Text -import qualified Data.Bifunctor -import qualified Data.Text -import qualified Data.Time.Clock.POSIX +import Data.Attoparsec.Text qualified +import Data.Bifunctor qualified +import Data.Text qualified +import Data.Time.Clock.POSIX qualified -import qualified System.Nix.ContentAddress -import qualified System.Nix.StorePath +import System.Nix.ContentAddress qualified +import System.Nix.StorePath qualified instance PersistField StorePath where toPersistValue = PersistText . System.Nix.StorePath.storePathToText def diff --git a/hnix-store-db/src/System/Nix/Store/DB/Query.hs b/hnix-store-db/src/System/Nix/Store/DB/Query.hs index d50fac51..acf56092 100644 --- a/hnix-store-db/src/System/Nix/Store/DB/Query.hs +++ b/hnix-store-db/src/System/Nix/Store/DB/Query.hs @@ -29,11 +29,11 @@ import Database.Esqueleto.Experimental import System.Nix.StorePath (StoreDir, StorePath, StorePathHashPart) import System.Nix.Store.DB.Schema -import qualified Data.ByteString.Char8 -import qualified Data.Maybe -import qualified Data.Text -import qualified System.Nix.StorePath -import qualified System.Nix.StorePath.Metadata +import Data.ByteString.Char8 qualified +import Data.Maybe qualified +import Data.Text qualified +import System.Nix.StorePath qualified +import System.Nix.StorePath.Metadata qualified -- * Queries diff --git a/hnix-store-db/src/System/Nix/Store/DB/Run.hs b/hnix-store-db/src/System/Nix/Store/DB/Run.hs index 2811ac2a..2e0161f2 100644 --- a/hnix-store-db/src/System/Nix/Store/DB/Run.hs +++ b/hnix-store-db/src/System/Nix/Store/DB/Run.hs @@ -24,17 +24,17 @@ import Database.Persist.Sqlite (SqliteConnectionInfo) import System.Nix.Store.DB.Query -import qualified Control.Monad -import qualified Control.Monad.IO.Class -import qualified Control.Monad.Logger -import qualified Data.ByteString.Char8 -import qualified Database.Esqueleto.Experimental -import qualified Database.Persist.Sql -import qualified Database.Persist.Sqlite -import qualified System.Log.FastLogger -import qualified System.Nix.StorePath -import qualified System.Nix.Store.DB.Schema -import qualified System.Nix.Store.DB.Util +import Control.Monad qualified +import Control.Monad.IO.Class qualified +import Control.Monad.Logger qualified +import Data.ByteString.Char8 qualified +import Database.Esqueleto.Experimental qualified +import Database.Persist.Sql qualified +import Database.Persist.Sqlite qualified +import System.Log.FastLogger qualified +import System.Nix.StorePath qualified +import System.Nix.Store.DB.Schema qualified +import System.Nix.Store.DB.Util qualified -- | @SqliteConnectionInfo@ for accessing -- systems database in /nix/var/nix/db/db.sqlite diff --git a/hnix-store-db/src/System/Nix/Store/DB/Util.hs b/hnix-store-db/src/System/Nix/Store/DB/Util.hs index a1bac515..a6a1ce95 100644 --- a/hnix-store-db/src/System/Nix/Store/DB/Util.hs +++ b/hnix-store-db/src/System/Nix/Store/DB/Util.hs @@ -14,8 +14,8 @@ import Database.Persist.Quasi import Database.Persist.Sqlite (SqliteConnectionInfo) import Database.Persist.TH (persistWith) -import qualified Database.Persist.Sqlite -import qualified Lens.Micro +import Database.Persist.Sqlite qualified +import Lens.Micro qualified -- | Coerce table names to their plural names -- i.e. ValidPath -> ValidPaths diff --git a/hnix-store-db/tests/Smoke.hs b/hnix-store-db/tests/Smoke.hs index c358110f..055d1f49 100644 --- a/hnix-store-db/tests/Smoke.hs +++ b/hnix-store-db/tests/Smoke.hs @@ -1,6 +1,6 @@ module Main where -import qualified System.Nix.Store.DB.Run +import System.Nix.Store.DB.Run qualified -- This only tests that database can be created -- in-memory using migrateAll and that queryEverything diff --git a/hnix-store-json/hnix-store-json.cabal b/hnix-store-json/hnix-store-json.cabal index 624ceb08..01cd2e28 100644 --- a/hnix-store-json/hnix-store-json.cabal +++ b/hnix-store-json/hnix-store-json.cabal @@ -25,6 +25,7 @@ common commons , DeriveGeneric , DerivingVia , FlexibleInstances + , ImportQualifiedPost , LambdaCase , RecordWildCards , StandaloneDeriving diff --git a/hnix-store-json/src/System/Nix/JSON.hs b/hnix-store-json/src/System/Nix/JSON.hs index f2e029f1..436e28dd 100644 --- a/hnix-store-json/src/System/Nix/JSON.hs +++ b/hnix-store-json/src/System/Nix/JSON.hs @@ -17,18 +17,18 @@ import System.Nix.Realisation (DerivationOutput, Realisation, RealisationWithId( import System.Nix.Signature (Signature) import System.Nix.StorePath (StoreDir(..), StorePath, StorePathName, StorePathHashPart) -import qualified Data.Aeson.KeyMap -import qualified Data.Aeson.Types -import qualified Data.Attoparsec.Text -import qualified Data.Char -import qualified Data.Text -import qualified Data.Text.Lazy -import qualified Data.Text.Lazy.Builder -import qualified System.Nix.Base -import qualified System.Nix.OutputName -import qualified System.Nix.Realisation -import qualified System.Nix.Signature -import qualified System.Nix.StorePath +import Data.Aeson.KeyMap qualified +import Data.Aeson.Types qualified +import Data.Attoparsec.Text qualified +import Data.Char qualified +import Data.Text qualified +import Data.Text.Lazy qualified +import Data.Text.Lazy.Builder qualified +import System.Nix.Base qualified +import System.Nix.OutputName qualified +import System.Nix.Realisation qualified +import System.Nix.Signature qualified +import System.Nix.StorePath qualified instance ToJSON StorePathName where toJSON = toJSON . System.Nix.StorePath.unStorePathName diff --git a/hnix-store-json/tests/JSONSpec.hs b/hnix-store-json/tests/JSONSpec.hs index 6aad8a84..8bf4ac96 100644 --- a/hnix-store-json/tests/JSONSpec.hs +++ b/hnix-store-json/tests/JSONSpec.hs @@ -14,12 +14,12 @@ import System.Nix.Realisation (DerivationOutput(..), Realisation(..)) import System.Nix.Signature (Signature) import System.Nix.StorePath (StorePath, StorePathName, StorePathHashPart) -import qualified Data.Map -import qualified Data.Set -import qualified System.Nix.Hash -import qualified System.Nix.OutputName -import qualified System.Nix.Signature -import qualified System.Nix.StorePath +import Data.Map qualified +import Data.Set qualified +import System.Nix.Hash qualified +import System.Nix.OutputName qualified +import System.Nix.Signature qualified +import System.Nix.StorePath qualified roundtripsJSON :: ( Eq a diff --git a/hnix-store-nar/hnix-store-nar.cabal b/hnix-store-nar/hnix-store-nar.cabal index e8d7c33d..452548bd 100644 --- a/hnix-store-nar/hnix-store-nar.cabal +++ b/hnix-store-nar/hnix-store-nar.cabal @@ -40,6 +40,7 @@ common commons , FlexibleContexts , FlexibleInstances , GADTs + , ImportQualifiedPost , StandaloneDeriving , ScopedTypeVariables , StandaloneDeriving diff --git a/hnix-store-nar/src/System/Nix/Nar.hs b/hnix-store-nar/src/System/Nix/Nar.hs index 05fb9e1b..012a8de3 100644 --- a/hnix-store-nar/src/System/Nix/Nar.hs +++ b/hnix-store-nar/src/System/Nix/Nar.hs @@ -33,14 +33,14 @@ module System.Nix.Nar , Nar.NarSource ) where -import qualified Control.Concurrent as Concurrent -import qualified Data.ByteString as BS -import qualified System.IO as IO +import Control.Concurrent qualified as Concurrent +import Data.ByteString qualified as BS +import System.IO qualified as IO -import qualified System.Nix.Nar.Effects as Nar -import qualified System.Nix.Nar.Options as Nar -import qualified System.Nix.Nar.Parser as Nar -import qualified System.Nix.Nar.Streamer as Nar +import System.Nix.Nar.Effects qualified as Nar +import System.Nix.Nar.Options qualified as Nar +import System.Nix.Nar.Parser qualified as Nar +import System.Nix.Nar.Streamer qualified as Nar -- For a description of the NAR format, see Eelco's thesis -- https://nixos.org/~eelco/pubs/phd-thesis.pdf diff --git a/hnix-store-nar/src/System/Nix/Nar/Effects.hs b/hnix-store-nar/src/System/Nix/Nar/Effects.hs index b2219105..483ef883 100644 --- a/hnix-store-nar/src/System/Nix/Nar/Effects.hs +++ b/hnix-store-nar/src/System/Nix/Nar/Effects.hs @@ -16,10 +16,10 @@ import Data.Int (Int64) import Data.Kind (Type) import System.IO (Handle, IOMode(WriteMode)) -import qualified Control.Monad -import qualified Data.ByteString -import qualified Data.ByteString.Lazy as Bytes.Lazy -import qualified System.Directory as Directory +import Control.Monad qualified +import Data.ByteString qualified +import Data.ByteString.Lazy qualified as Bytes.Lazy +import System.Directory qualified as Directory import System.Posix.Files ( createSymbolicLink , fileMode , fileSize @@ -37,8 +37,8 @@ import System.Posix.Files ( createSymbolicLink , setFileMode , unionFileModes ) -import qualified System.IO as IO -import qualified Control.Exception.Lifted as Exception.Lifted +import System.IO qualified as IO +import Control.Exception.Lifted qualified as Exception.Lifted data IsExecutable = NonExecutable | Executable deriving (Eq, Show) diff --git a/hnix-store-nar/src/System/Nix/Nar/Options.hs b/hnix-store-nar/src/System/Nix/Nar/Options.hs index 867026a1..f16738f4 100644 --- a/hnix-store-nar/src/System/Nix/Nar/Options.hs +++ b/hnix-store-nar/src/System/Nix/Nar/Options.hs @@ -6,7 +6,7 @@ module System.Nix.Nar.Options ) where import Data.Text (Text) -import qualified System.Info +import System.Info qualified -- | Options for configuring how NAR files are encoded and decoded. data NarOptions = NarOptions { diff --git a/hnix-store-nar/src/System/Nix/Nar/Parser.hs b/hnix-store-nar/src/System/Nix/Nar/Parser.hs index 52bc3152..6e64b2e9 100644 --- a/hnix-store-nar/src/System/Nix/Nar/Parser.hs +++ b/hnix-store-nar/src/System/Nix/Nar/Parser.hs @@ -11,42 +11,42 @@ module System.Nix.Nar.Parser ) where -import qualified Algebra.Graph as Graph -import qualified Algebra.Graph.ToGraph as Graph -import qualified Control.Concurrent as Concurrent -import qualified Control.Exception.Lifted as Exception.Lifted +import Algebra.Graph qualified as Graph +import Algebra.Graph.ToGraph qualified as Graph +import Control.Concurrent qualified as Concurrent +import Control.Exception.Lifted qualified as Exception.Lifted import Control.Monad ( forM , when , forM_ ) -import qualified Control.Monad.Except as Except -import qualified Control.Monad.Fail as Fail -import qualified Control.Monad.IO.Class as IO -import qualified Control.Monad.Reader as Reader -import qualified Control.Monad.State as State -import qualified Control.Monad.Trans as Trans -import qualified Control.Monad.Trans.Control as Base +import Control.Monad.Except qualified as Except +import Control.Monad.Fail qualified as Fail +import Control.Monad.IO.Class qualified as IO +import Control.Monad.Reader qualified as Reader +import Control.Monad.State qualified as State +import Control.Monad.Trans qualified as Trans +import Control.Monad.Trans.Control qualified as Base import Data.ByteString (ByteString) -import qualified Data.ByteString as Bytes +import Data.ByteString qualified as Bytes import Data.Bool ( bool ) -import qualified Data.Either as Either +import Data.Either qualified as Either import Data.Int ( Int64 ) -import qualified Data.IORef as IORef -import qualified Data.CaseInsensitive as CI -import qualified Data.HashMap.Strict as HashMap -import qualified Data.List as List -import qualified Data.Map as Map +import Data.IORef qualified as IORef +import Data.CaseInsensitive qualified as CI +import Data.HashMap.Strict qualified as HashMap +import Data.List qualified as List +import Data.Map qualified as Map import Data.Maybe ( catMaybes ) -import qualified Data.Serialize as Serialize +import Data.Serialize qualified as Serialize import Data.Text ( Text ) -import qualified Data.Text as Text -import qualified Data.Text.Encoding as Text -import qualified System.Directory as Directory +import Data.Text qualified as Text +import Data.Text.Encoding qualified as Text +import System.Directory qualified as Directory import System.FilePath as FilePath -import qualified System.IO as IO +import System.IO qualified as IO -import qualified System.Nix.Nar.Effects as Nar -import qualified System.Nix.Nar.Options as Nar +import System.Nix.Nar.Effects qualified as Nar +import System.Nix.Nar.Options qualified as Nar -- | NarParser is a monad for parsing a Nar file as a byte stream -- and reconstructing the file system objects inside diff --git a/hnix-store-nar/src/System/Nix/Nar/Streamer.hs b/hnix-store-nar/src/System/Nix/Nar/Streamer.hs index 315e8ba3..19dd43c1 100644 --- a/hnix-store-nar/src/System/Nix/Nar/Streamer.hs +++ b/hnix-store-nar/src/System/Nix/Nar/Streamer.hs @@ -12,23 +12,23 @@ module System.Nix.Nar.Streamer import Data.ByteString (ByteString) import Data.Int (Int64) -import qualified Data.Map.Strict as Map +import Data.Map.Strict qualified as Map import Control.Monad ( forM_ , when ) -import qualified Control.Monad.IO.Class as IO -import qualified Data.ByteString as Bytes -import qualified Data.ByteString.Lazy as Bytes.Lazy -import qualified Data.Foldable -import qualified Data.List -import qualified Data.Serialize as Serial -import qualified Data.Text as T (pack, unpack) -import qualified Data.Text.Encoding as TE (encodeUtf8) +import Control.Monad.IO.Class qualified as IO +import Data.ByteString qualified as Bytes +import Data.ByteString.Lazy qualified as Bytes.Lazy +import Data.Foldable qualified +import Data.List qualified +import Data.Serialize qualified as Serial +import Data.Text qualified as T (pack, unpack) +import Data.Text.Encoding qualified as TE (encodeUtf8) import System.FilePath (()) -import qualified System.Nix.Nar.Effects as Nar -import qualified System.Nix.Nar.Options as Nar +import System.Nix.Nar.Effects qualified as Nar +import System.Nix.Nar.Options qualified as Nar -- | NarSource -- The source to provide nar to the handler `(ByteString -> m ())`. diff --git a/hnix-store-nar/tests/NarFormat.hs b/hnix-store-nar/tests/NarFormat.hs index 28d58046..57b3662f 100644 --- a/hnix-store-nar/tests/NarFormat.hs +++ b/hnix-store-nar/tests/NarFormat.hs @@ -4,7 +4,7 @@ module NarFormat where import Control.Applicative (many, optional, (<|>)) -import qualified Control.Concurrent as Concurrent +import Control.Concurrent qualified as Concurrent import Control.Exception (SomeException, try) import Control.Monad (replicateM, void, forM_, when) import Crypto.Hash (hash, Digest, SHA256) @@ -15,35 +15,35 @@ import Data.Serialize (Get, getByteString, import Data.Serialize (Putter, putInt64le, putByteString, runPut) import Data.Bool (bool) -import qualified Data.ByteString as BS -import qualified Data.ByteString.Base64 as B64 -import qualified Data.ByteString.Char8 as BSC -import qualified Data.ByteString.Lazy as BSL -import qualified Data.ByteString.Lazy.Char8 as BSLC +import Data.ByteString qualified as BS +import Data.ByteString.Base64 qualified as B64 +import Data.ByteString.Char8 qualified as BSC +import Data.ByteString.Lazy qualified as BSL +import Data.ByteString.Lazy.Char8 qualified as BSLC import Data.Int ( Int64 ) -import qualified Data.Map as Map +import Data.Map qualified as Map import Data.Maybe (fromMaybe) -import qualified Data.Text as T -import qualified Data.Text.Encoding as E +import Data.Text qualified as T +import Data.Text.Encoding qualified as E import GHC.Generics ( Generic ) import System.Directory ( doesDirectoryExist , doesPathExist , removeDirectoryRecursive , removeFile ) -import qualified System.Directory as Directory +import System.Directory qualified as Directory import System.Environment (getEnv) import System.FilePath ((<.>), ()) -import qualified System.IO as IO -import qualified System.IO.Temp as Temp -import qualified System.Posix.Files as Unix -import qualified System.Posix.Process as Unix -import qualified System.Process as P +import System.IO qualified as IO +import System.IO.Temp qualified as Temp +import System.Posix.Files qualified as Unix +import System.Posix.Process qualified as Unix +import System.Process qualified as P import Test.Tasty as T import Test.Hspec -import qualified Test.Tasty.HUnit as HU +import Test.Tasty.HUnit qualified as HU import Test.Tasty.QuickCheck -import qualified Text.Printf as Printf +import Text.Printf qualified as Printf import Text.Read (readMaybe) import System.Nix.Nar.Streamer (IsExecutable(Executable, NonExecutable)) diff --git a/hnix-store-readonly/hnix-store-readonly.cabal b/hnix-store-readonly/hnix-store-readonly.cabal index ae4c6d3e..ef4628eb 100644 --- a/hnix-store-readonly/hnix-store-readonly.cabal +++ b/hnix-store-readonly/hnix-store-readonly.cabal @@ -22,6 +22,7 @@ common commons default-extensions: Rank2Types , ScopedTypeVariables + , ImportQualifiedPost , TypeApplications default-language: Haskell2010 diff --git a/hnix-store-readonly/src/System/Nix/Store/ReadOnly.hs b/hnix-store-readonly/src/System/Nix/Store/ReadOnly.hs index 1d70daf8..f6dfd397 100644 --- a/hnix-store-readonly/src/System/Nix/Store/ReadOnly.hs +++ b/hnix-store-readonly/src/System/Nix/Store/ReadOnly.hs @@ -15,8 +15,8 @@ import System.Nix.Hash (HashAlgo(..)) import System.Nix.Store.Types (PathFilter, RepairMode) import System.Nix.StorePath (StoreDir, StorePath, StorePathName) -import qualified Crypto.Hash -import qualified System.Nix.Nar +import Crypto.Hash qualified +import System.Nix.Nar qualified digestPath :: FilePath -- ^ Local `FilePath` to add diff --git a/hnix-store-readonly/tests/ReadOnlySpec.hs b/hnix-store-readonly/tests/ReadOnlySpec.hs index cef695ba..889de623 100644 --- a/hnix-store-readonly/tests/ReadOnlySpec.hs +++ b/hnix-store-readonly/tests/ReadOnlySpec.hs @@ -13,8 +13,8 @@ import System.Nix.StorePath (StorePath, StorePathName) import System.Nix.StorePath.ContentAddressed import System.Nix.ContentAddress (ContentAddressMethod(..)) -import qualified Data.HashSet -import qualified System.Nix.StorePath +import Data.HashSet qualified +import System.Nix.StorePath qualified import System.Nix.Store.ReadOnly diff --git a/hnix-store-remote/app/BuildDerivation.hs b/hnix-store-remote/app/BuildDerivation.hs index 1d321c79..416d824c 100644 --- a/hnix-store-remote/app/BuildDerivation.hs +++ b/hnix-store-remote/app/BuildDerivation.hs @@ -3,11 +3,11 @@ module Main where import Data.Default.Class (Default(def)) -import qualified Data.Text -import qualified System.Environment -import qualified System.Nix.Build -import qualified System.Nix.StorePath -import qualified System.Nix.Store.Remote +import Data.Text qualified +import System.Environment qualified +import System.Nix.Build qualified +import System.Nix.StorePath qualified +import System.Nix.Store.Remote qualified main :: IO () main = System.Environment.getArgs >>= \case diff --git a/hnix-store-remote/hnix-store-remote.cabal b/hnix-store-remote/hnix-store-remote.cabal index 73d683ce..065e33c1 100644 --- a/hnix-store-remote/hnix-store-remote.cabal +++ b/hnix-store-remote/hnix-store-remote.cabal @@ -31,6 +31,7 @@ common commons , DerivingVia , FlexibleContexts , FlexibleInstances + , ImportQualifiedPost , GADTs , RecordWildCards , ScopedTypeVariables @@ -136,6 +137,7 @@ library ghc-options: -Wall executable build-derivation + import: commons if !flag(build-derivation) buildable: False build-depends: @@ -144,12 +146,12 @@ executable build-derivation , hnix-store-remote , data-default-class , text - default-language: Haskell2010 main-is: BuildDerivation.hs hs-source-dirs: app ghc-options: -Wall -threaded -rtsopts "-with-rtsopts -N" executable remote-readme + import: commons if !flag(build-readme) buildable: False build-depends: @@ -158,7 +160,6 @@ executable remote-readme , hnix-store-remote build-tool-depends: markdown-unlit:markdown-unlit - default-language: Haskell2010 main-is: README.lhs ghc-options: -pgmL markdown-unlit -Wall diff --git a/hnix-store-remote/src/Data/Serializer.hs b/hnix-store-remote/src/Data/Serializer.hs index 34ca9f78..b5630a5b 100644 --- a/hnix-store-remote/src/Data/Serializer.hs +++ b/hnix-store-remote/src/Data/Serializer.hs @@ -38,6 +38,7 @@ module Data.Serializer , mapIsoSerializer , mapPrismSerializer , tup + , depTup -- * Utility , GetSerializerError(..) , transformGetError @@ -54,7 +55,7 @@ import Control.Monad.Trans.Identity (IdentityT, runIdentityT) import Data.ByteString (ByteString) import Data.Functor.Identity import Data.Serialize (Serialize) -import qualified Data.Serialize +import Data.Serialize qualified import Data.Serialize.Get (Get, runGet) import Data.Serialize.Put (Putter, PutM, runPutM) @@ -189,6 +190,24 @@ tup a b = Serializer putS b y } +-- | Dependent tuple combinator +depTup + :: ( Monad (t Get) + , Monad (t PutM) + ) + => Serializer t a + -> (a -> Serializer t b) + -> Serializer t (a, b) +depTup sa sb = Serializer + { getS = do + a <- getS sa + b <- getS $ sb a + pure (a, b) + , putS = \(x, y) -> do + putS sa x + putS (sb x) y + } + -- * Utilities -- | Wrapper for both GetS errors diff --git a/hnix-store-remote/src/System/Nix/Store/Remote.hs b/hnix-store-remote/src/System/Nix/Store/Remote.hs index 2128ca94..61b05858 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote.hs @@ -33,14 +33,14 @@ import System.Nix.Store.Remote.Client import System.Nix.Store.Remote.Server (WorkerHelper, runProxyDaemon) import System.Nix.Store.Remote.Types -import qualified Control.Monad.Catch -import qualified Network.Socket +import Control.Monad.Catch qualified +import Network.Socket qualified -- see TODO bellow ---import qualified System.Directory +--import System.Directory qualified -- wip justdoit import System.Nix.StorePath (StorePath) -import qualified System.Nix.StorePath +import System.Nix.StorePath qualified -- * Compat diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs index 501e9379..b17b045a 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs @@ -38,7 +38,8 @@ import Data.Some (Some) import Data.Word (Word64) import System.Nix.Build (BuildMode, BuildResult) -import qualified System.Nix.Derivation.ATerm +import System.Nix.Derivation.Traditional qualified +import System.Nix.Derivation.ATerm qualified import System.Nix.DerivedPath (DerivedPath) import System.Nix.Hash (HashAlgo(..)) import System.Nix.Nar (NarSource) @@ -56,11 +57,11 @@ import System.Nix.Store.Remote.Client.Core import System.Nix.FileContentAddress (FileIngestionMethod(..)) import System.Nix.Store.Types (RepairMode(..)) -import qualified Control.Monad.IO.Class -import qualified Data.Attoparsec.Text -import qualified Data.Text.IO -import qualified System.Nix.Derivation -import qualified System.Nix.StorePath +import Control.Monad.IO.Class qualified +import Data.Attoparsec.Text qualified +import Data.Text.IO qualified +import System.Nix.Derivation qualified +import System.Nix.StorePath qualified -- | Add `NarSource` to the store addToStore @@ -151,7 +152,7 @@ buildDerivation sp mode = do Right drv -> do let drv' = drv { System.Nix.Derivation.inputs = - System.Nix.Derivation.srcs + System.Nix.Derivation.Traditional.traditionalSrcs (System.Nix.Derivation.inputs drv) } doReq (BuildDerivation sp drv' mode) diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Client/Core.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Client/Core.hs index 5dc0470a..422aade0 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Client/Core.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Client/Core.hs @@ -40,8 +40,8 @@ import System.Nix.Store.Remote.Types.ProtoVersion (ProtoVersion(..)) import System.Nix.Store.Remote.Types.StoreRequest (StoreRequest(..)) import System.Nix.Store.Remote.Types.WorkerMagic (WorkerMagic(..)) -import qualified Data.ByteString -import qualified Network.Socket.ByteString +import Data.ByteString qualified +import Network.Socket.ByteString qualified type Run m a = m (Either RemoteStoreError a, DList Logger) diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Logger.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Logger.hs index 668a46a1..ba7e0415 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Logger.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Logger.hs @@ -12,10 +12,10 @@ import System.Nix.Store.Remote.MonadStore (MonadRemoteStore, RemoteStoreError(.. import System.Nix.Store.Remote.Types.Logger (Logger(..)) import System.Nix.Store.Remote.Types.ProtoVersion (ProtoVersion) -import qualified Control.Monad -import qualified Data.Serialize.Get -import qualified Data.Serializer -import qualified Network.Socket.ByteString +import Control.Monad qualified +import Data.Serialize.Get qualified +import Data.Serializer qualified +import Network.Socket.ByteString qualified processOutput :: MonadRemoteStore m diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/MonadStore.hs b/hnix-store-remote/src/System/Nix/Store/Remote/MonadStore.hs index ab147b04..0b32f588 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/MonadStore.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/MonadStore.hs @@ -33,7 +33,7 @@ import System.Nix.Store.Remote.Types.Logger (Logger, BasicError, ErrorInfo) import System.Nix.Store.Remote.Types.ProtoVersion (HasProtoVersion(..), ProtoVersion) import System.Nix.Store.Remote.Types.StoreConfig (ProtoStoreConfig(..)) -import qualified Data.DList +import Data.DList qualified data RemoteStoreState = RemoteStoreState { remoteStoreStateConfig :: ProtoStoreConfig diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs index 7abda102..e2672e74 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs @@ -101,31 +101,55 @@ module System.Nix.Store.Remote.Serializer , maybePathMetadata ) where + +import Control.Monad qualified import Control.Monad.Except (MonadError, throwError, ) import Control.Monad.Trans (lift) import Control.Monad.Trans.Except (ExceptT(..), runExceptT, withExceptT) import Crypto.Hash (Digest, HashAlgorithm, SHA256) import Data.Aeson (FromJSON, ToJSON) +import Data.Aeson qualified +import Data.Attoparsec.Text qualified +import Data.Bifunctor qualified +import Data.Bits qualified import Data.ByteString (ByteString) -import qualified Data.ByteString.Lazy +import Data.ByteString qualified +import Data.ByteString.Char8 qualified +import Data.ByteString.Lazy qualified import Data.Dependent.Sum (DSum((:=>))) import Data.Fixed (Uni) import Data.Functor.Identity -import Data.Hashable (Hashable) import Data.HashSet (HashSet) +import Data.HashSet qualified +import Data.Hashable (Hashable) import Data.Map (Map) +import Data.Map.Strict qualified +import Data.Maybe qualified +import Data.Serialize.Get qualified +import Data.Serialize.Put qualified import Data.Serializer import Data.Set (Set) +import Data.Set qualified import Data.Some (Some(Some)) +import Data.Some qualified import Data.Text (Text) +import Data.Text qualified +import Data.Text.Encoding qualified +import Data.Text.Lazy qualified import Data.Text.Lazy.Builder (Builder) +import Data.Text.Lazy.Builder qualified import Data.Time (NominalDiffTime, UTCTime) +import Data.Time.Clock.POSIX qualified import Data.Vector (Vector) +import Data.Vector qualified import Data.Word (Word8, Word32, Word64) import GHC.Generics (Generic) import System.Nix.Base (BaseEncoding(Base16, NixBase32)) +import System.Nix.Base qualified import System.Nix.Build (BuildMode, BuildResult(..)) import System.Nix.ContentAddress (ContentAddress) +import System.Nix.ContentAddress qualified +import System.Nix.Derivation.Traditional import System.Nix.Derivation ( BasicDerivation , Derivation'(..) @@ -133,45 +157,22 @@ import System.Nix.Derivation -- , DerivationInputs(..) ) import System.Nix.DerivedPath (DerivedPath(..), ParseOutputsError) +import System.Nix.DerivedPath qualified +import System.Nix.FileContentAddress (FileIngestionMethod(..)) import System.Nix.Hash (HashAlgo(..)) +import System.Nix.Hash qualified import System.Nix.JSON () import System.Nix.OutputName (OutputName) +import System.Nix.OutputName qualified import System.Nix.Realisation (DerivationOutputError, Realisation(..), RealisationWithId(..)) +import System.Nix.Realisation qualified import System.Nix.Signature (Signature, NarSignature) -import System.Nix.FileContentAddress (FileIngestionMethod(..)) +import System.Nix.Signature qualified +import System.Nix.Store.Remote.Types import System.Nix.Store.Types (RepairMode(..)) import System.Nix.StorePath (StoreDir, InvalidNameError, InvalidPathError, StorePath, StorePathHashPart, StorePathName) +import System.Nix.StorePath qualified import System.Nix.StorePath.Metadata (Metadata(..), StorePathTrust(..)) -import System.Nix.Store.Remote.Types - -import qualified Control.Monad -import qualified Data.Aeson -import qualified Data.Attoparsec.Text -import qualified Data.Bifunctor -import qualified Data.Bits -import qualified Data.ByteString -import qualified Data.ByteString.Char8 -import qualified Data.HashSet -import qualified Data.Map.Strict -import qualified Data.Maybe -import qualified Data.Serialize.Get -import qualified Data.Serialize.Put -import qualified Data.Set -import qualified Data.Some -import qualified Data.Text -import qualified Data.Text.Encoding -import qualified Data.Text.Lazy -import qualified Data.Text.Lazy.Builder -import qualified Data.Time.Clock.POSIX -import qualified Data.Vector -import qualified System.Nix.Base -import qualified System.Nix.ContentAddress -import qualified System.Nix.DerivedPath -import qualified System.Nix.Hash -import qualified System.Nix.OutputName -import qualified System.Nix.Realisation -import qualified System.Nix.Signature -import qualified System.Nix.StorePath mapErrorS :: (e -> e') @@ -399,17 +400,23 @@ hashSet = Data.HashSet.toList . list -mapS +mapS' :: Ord k - => NixSerializer e k - -> NixSerializer e v + => NixSerializer e (k, v) -> NixSerializer e (Map k v) -mapS k v = +mapS' kv = mapIsoSerializer Data.Map.Strict.fromList Data.Map.Strict.toList $ list - $ tup k v + $ kv + +mapS + :: Ord k + => NixSerializer e k + -> NixSerializer e v + -> NixSerializer e (Map k v) +mapS k v = mapS' $ tup k v vector :: Ord a @@ -676,61 +683,40 @@ namedDigest = Serializer derivationOutput :: StoreDir + -> StorePathName + -> OutputName -> NixSerializer SError DerivationOutput -derivationOutput storeDir = Serializer +derivationOutput storeDir drvName outputName' = Serializer { getS = do - mPath <- getS $ maybePath storeDir - mHashAlgo <- getS maybeText - mHash <- getS maybeText - case (mPath, mHashAlgo, mHash) of - (Just path, Nothing, Nothing) -> - pure InputAddressedDerivationOutput {..} - (Just path, Just hashAlgo, Just hash) -> - error "TODO" - -- pure FixedDerivationOutput {..} - (Nothing, Just hashAlgo, Nothing) -> - error "TODO" - -- pure ContentAddressedDerivationOutput {..} - _ -> - throwError $ SError_DerivationOutputInvalidCombo - (Data.Maybe.isJust mPath) - (Data.Maybe.isJust mHashAlgo) - (Data.Maybe.isJust mHash) - , putS = \case - InputAddressedDerivationOutput{..} -> do - putS (storePath storeDir) path - putS text Data.Text.empty - putS text Data.Text.empty - FixedDerivationOutput{..} -> do - pure () - --putS storePath path - --putS text hashAlgo - --putS text hash - ContentAddressedDerivationOutput{..} -> do - pure () - --putS text Data.Text.empty - --putS text hashAlgo - --putS text Data.Text.empty + rawPath <- getS text + rawMethodHashAlgo <- getS text + rawHash <- getS text + parseRawDerivationOutput storeDir drvName outputName' $ RawDerivationOutput {..} + , putS = \output -> do + let RawDerivationOutput {..} = renderRawDerivationOutput storeDir drvName outputName' output + putS text rawPath + putS text rawMethodHashAlgo + putS text rawHash } -- * Derivation basicDerivation :: StoreDir - -> NixSerializer SError (StorePathName -> BasicDerivation) -basicDerivation storeDir = Serializer + -> StorePathName + -> NixSerializer SError BasicDerivation +basicDerivation storeDir drvName = Serializer { getS = do - outputs <- getS $ mapS outputName $ derivationOutput storeDir + outputs <- getS $ mapS' $ depTup outputName $ derivationOutput storeDir drvName inputs <- getS $ set $ storePath storeDir platform <- getS text builder <- getS text args <- getS $ vector text env <- getS $ mapS text text - pure $ \name -> Derivation{..} - , putS = \f -> do - -- We don't use the name here - let Derivation{..} = f $ error "must not matter" - putS (mapS outputName $ derivationOutput storeDir) outputs + let name = drvName + pure $ Derivation{..} + , putS = \Derivation{..} -> do + putS (mapS' $ depTup outputName $ derivationOutput storeDir drvName) outputs putS (set $ storePath storeDir) inputs putS text platform putS text builder @@ -1096,7 +1082,7 @@ storeRequest storeDir pv = Serializer WorkerOp_BuildDerivation -> mapGetE $ do path <- getS $ storePath storeDir - drv <- getS (basicDerivation storeDir) <*> pure (System.Nix.StorePath.storePathName path) + drv <- getS (basicDerivation storeDir $ System.Nix.StorePath.storePathName path) buildMode' <- getS buildMode pure $ Some (BuildDerivation path drv buildMode') @@ -1241,7 +1227,7 @@ storeRequest storeDir pv = Serializer putS workerOp WorkerOp_BuildDerivation putS (storePath storeDir) path - putS (basicDerivation storeDir) $ \_ -> drv + putS (basicDerivation storeDir $ name drv) drv putS buildMode buildMode' Some (CollectGarbage GCOptions{..}) -> do diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Server.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Server.hs index 357c55ae..1c61349b 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Server.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Server.hs @@ -31,11 +31,11 @@ import System.Nix.Store.Remote.Types.Logger (BasicError(..), ErrorInfo, Logger(. import System.Nix.Store.Remote.MonadStore (MonadRemoteStore(..), WorkerError(..), WorkerException(..), RemoteStoreError(..), RemoteStoreT, runRemoteStoreT) import System.Nix.Store.Remote.Types.Handshake (ServerHandshakeInput(..), ServerHandshakeOutput(..)) import System.Nix.Store.Remote.Types.WorkerMagic (WorkerMagic(..)) -import qualified Data.Some -import qualified Data.Text -import qualified Data.Text.IO -import qualified System.Timeout -import qualified Network.Socket.ByteString +import Data.Some qualified +import Data.Text qualified +import Data.Text.IO qualified +import System.Timeout qualified +import Network.Socket.ByteString qualified type WorkerHelper m = forall a diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Socket.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Socket.hs index 58aece81..46ed9085 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Socket.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Socket.hs @@ -10,10 +10,10 @@ import Network.Socket.ByteString (recv, sendAll) import System.Nix.Store.Remote.MonadStore (MonadRemoteStore(..), RemoteStoreError(..)) import System.Nix.Store.Remote.Serializer (NixSerializer, runP) -import qualified Control.Exception -import qualified Data.ByteString -import qualified Data.Serializer -import qualified Data.Serialize.Get +import Control.Exception qualified +import Data.ByteString qualified +import Data.Serializer qualified +import Data.Serialize.Get qualified genericIncremental :: ( MonadIO m diff --git a/hnix-store-remote/tests-io/Main.hs b/hnix-store-remote/tests-io/Main.hs index 41032de9..9ccf339b 100644 --- a/hnix-store-remote/tests-io/Main.hs +++ b/hnix-store-remote/tests-io/Main.hs @@ -1,7 +1,7 @@ module Main where -import qualified Test.Hspec -import qualified NixDaemonSpec +import Test.Hspec qualified +import NixDaemonSpec qualified -- we run remote tests in -- Linux namespaces to avoid interacting with systems store diff --git a/hnix-store-remote/tests-io/NixDaemonSpec.hs b/hnix-store-remote/tests-io/NixDaemonSpec.hs index ef327412..1f61179e 100644 --- a/hnix-store-remote/tests-io/NixDaemonSpec.hs +++ b/hnix-store-remote/tests-io/NixDaemonSpec.hs @@ -28,26 +28,26 @@ import System.Nix.StorePath.Metadata (Metadata(..)) import System.Nix.Store.Remote import System.Nix.Store.Remote.Server (WorkerHelper) import System.Process (CreateProcess(..), ProcessHandle) -import qualified Control.Concurrent -import qualified Control.Exception -import qualified Data.ByteString.Char8 -import qualified Data.Either -import qualified Data.HashSet -import qualified Data.Map -import qualified Data.Set -import qualified Data.Text -import qualified Data.Text.Encoding -import qualified DataSink -import qualified SampleNar -import qualified System.Directory -import qualified System.Environment -import qualified System.IO.Temp -import qualified System.Linux.Namespaces -import qualified System.Nix.StorePath -import qualified System.Nix.Nar -import qualified System.Posix.User -import qualified System.Process -import qualified Test.Hspec +import Control.Concurrent qualified +import Control.Exception qualified +import Data.ByteString.Char8 qualified +import Data.Either qualified +import Data.HashSet qualified +import Data.Map qualified +import Data.Set qualified +import Data.Text qualified +import Data.Text.Encoding qualified +import DataSink qualified +import SampleNar qualified +import System.Directory qualified +import System.Environment qualified +import System.IO.Temp qualified +import System.Linux.Namespaces qualified +import System.Nix.StorePath qualified +import System.Nix.Nar qualified +import System.Posix.User qualified +import System.Process qualified +import Test.Hspec qualified createProcessEnv :: FilePath diff --git a/hnix-store-remote/tests-io/SampleNar.hs b/hnix-store-remote/tests-io/SampleNar.hs index c6ea2915..0abf9854 100644 --- a/hnix-store-remote/tests-io/SampleNar.hs +++ b/hnix-store-remote/tests-io/SampleNar.hs @@ -25,8 +25,8 @@ import Data.Default.Class import Data.STRef import Data.Word -import qualified Data.ByteString -import qualified System.Nix.Nar +import Data.ByteString qualified +import System.Nix.Nar qualified -- | Sample data for an AddToStoreNar operation data SampleNar diff --git a/hnix-store-remote/tests/NixSerializerSpec.hs b/hnix-store-remote/tests/NixSerializerSpec.hs index c1c55efc..34ce3d0a 100644 --- a/hnix-store-remote/tests/NixSerializerSpec.hs +++ b/hnix-store-remote/tests/NixSerializerSpec.hs @@ -8,9 +8,9 @@ import Test.Hspec (Expectation, Spec, describe, parallel, shouldBe) import Test.Hspec.QuickCheck (prop) import Test.QuickCheck (Gen, arbitrary, forAll, suchThat) -import Data.Serializer (mapIsoSerializer) import System.Nix.Arbitrary () import System.Nix.Build (BuildResult(..)) +import System.Nix.Derivation qualified import System.Nix.Store.Remote.Arbitrary () import System.Nix.Store.Remote.Serializer import System.Nix.Store.Remote.Types.Logger (Logger(..)) @@ -113,8 +113,8 @@ spec = parallel $ do prop "SHA256" $ roundtripS . digest @SHA256 prop "SHA512" $ roundtripS . digest @SHA512 - prop "Derivation" $ \sd name -> - roundtripS $ mapIsoSerializer ($ name) const $ basicDerivation sd + prop "Derivation" $ \sd drv -> + roundtripS (basicDerivation sd $ System.Nix.Derivation.name drv) drv prop "ProtoVersion" $ roundtripS @() protoVersion diff --git a/hnix-store-tests/hnix-store-tests.cabal b/hnix-store-tests/hnix-store-tests.cabal index 1ffd1551..54f9ac2d 100644 --- a/hnix-store-tests/hnix-store-tests.cabal +++ b/hnix-store-tests/hnix-store-tests.cabal @@ -28,6 +28,7 @@ common commons , FlexibleInstances , ScopedTypeVariables , StandaloneDeriving + , ImportQualifiedPost , RecordWildCards , TypeApplications , LambdaCase diff --git a/hnix-store-tests/src/Data/ByteString/Arbitrary.hs b/hnix-store-tests/src/Data/ByteString/Arbitrary.hs index 00248002..b0287787 100644 --- a/hnix-store-tests/src/Data/ByteString/Arbitrary.hs +++ b/hnix-store-tests/src/Data/ByteString/Arbitrary.hs @@ -3,7 +3,7 @@ module Data.ByteString.Arbitrary () where import Data.ByteString (ByteString) import Test.QuickCheck (Arbitrary(..)) -import qualified Data.ByteString.Char8 +import Data.ByteString.Char8 qualified instance Arbitrary ByteString where arbitrary = Data.ByteString.Char8.pack <$> arbitrary diff --git a/hnix-store-tests/src/Data/HashSet/Arbitrary.hs b/hnix-store-tests/src/Data/HashSet/Arbitrary.hs index a992a5a4..fb4dd2d6 100644 --- a/hnix-store-tests/src/Data/HashSet/Arbitrary.hs +++ b/hnix-store-tests/src/Data/HashSet/Arbitrary.hs @@ -4,7 +4,7 @@ module Data.HashSet.Arbitrary where import Data.Hashable (Hashable) import Data.HashSet (HashSet) import Test.QuickCheck (Arbitrary(..)) -import qualified Data.HashSet +import Data.HashSet qualified instance (Hashable a, Eq a, Arbitrary a) => Arbitrary (HashSet a) where arbitrary = Data.HashSet.fromList <$> arbitrary diff --git a/hnix-store-tests/src/Data/Text/Arbitrary.hs b/hnix-store-tests/src/Data/Text/Arbitrary.hs index 34cba8e9..7cdf1357 100644 --- a/hnix-store-tests/src/Data/Text/Arbitrary.hs +++ b/hnix-store-tests/src/Data/Text/Arbitrary.hs @@ -3,7 +3,7 @@ module Data.Text.Arbitrary () where import Data.Text (Text) import Test.QuickCheck (Arbitrary(..), frequency, suchThat) -import qualified Data.Text +import Data.Text qualified instance Arbitrary Text where arbitrary = Data.Text.pack <$> arbitrary diff --git a/hnix-store-tests/src/Data/Vector/Arbitrary.hs b/hnix-store-tests/src/Data/Vector/Arbitrary.hs index 0d006dc7..abde12fd 100644 --- a/hnix-store-tests/src/Data/Vector/Arbitrary.hs +++ b/hnix-store-tests/src/Data/Vector/Arbitrary.hs @@ -4,7 +4,7 @@ module Data.Vector.Arbitrary () where import Data.Vector (Vector) import Test.QuickCheck (Arbitrary(..), Arbitrary1(..), arbitrary1, shrink1) -import qualified Data.Vector +import Data.Vector qualified instance Arbitrary1 Vector where liftArbitrary = diff --git a/hnix-store-tests/src/System/Nix/Arbitrary/Build.hs b/hnix-store-tests/src/System/Nix/Arbitrary/Build.hs index 3cd24296..3d7a0f7d 100644 --- a/hnix-store-tests/src/System/Nix/Arbitrary/Build.hs +++ b/hnix-store-tests/src/System/Nix/Arbitrary/Build.hs @@ -13,7 +13,7 @@ import System.Nix.Arbitrary.UTCTime () import System.Nix.Build -import qualified Data.Time.Clock.POSIX +import Data.Time.Clock.POSIX qualified deriving via GenericArbitrary BuildMode instance Arbitrary BuildMode diff --git a/hnix-store-tests/src/System/Nix/Arbitrary/DerivedPath.hs b/hnix-store-tests/src/System/Nix/Arbitrary/DerivedPath.hs index 5cea4fb4..19b1717f 100644 --- a/hnix-store-tests/src/System/Nix/Arbitrary/DerivedPath.hs +++ b/hnix-store-tests/src/System/Nix/Arbitrary/DerivedPath.hs @@ -3,7 +3,7 @@ {-# OPTIONS_GHC -Wno-orphans #-} module System.Nix.Arbitrary.DerivedPath where -import qualified Data.Set +import Data.Set qualified import Test.QuickCheck (Arbitrary(..), oneof) import Test.QuickCheck.Arbitrary.Generic (GenericArbitrary(..)) import System.Nix.Arbitrary.OutputName () diff --git a/hnix-store-tests/src/System/Nix/Arbitrary/Hash.hs b/hnix-store-tests/src/System/Nix/Arbitrary/Hash.hs index ad9b3086..fe4aa266 100644 --- a/hnix-store-tests/src/System/Nix/Arbitrary/Hash.hs +++ b/hnix-store-tests/src/System/Nix/Arbitrary/Hash.hs @@ -12,7 +12,7 @@ import System.Nix.Hash (HashAlgo(..)) import Test.QuickCheck (Arbitrary(arbitrary), oneof) -import qualified Crypto.Hash +import Crypto.Hash qualified -- * Arbitrary @Digest@s diff --git a/hnix-store-tests/src/System/Nix/Arbitrary/OutputName.hs b/hnix-store-tests/src/System/Nix/Arbitrary/OutputName.hs index 0ef7ba21..1a1f3b3b 100644 --- a/hnix-store-tests/src/System/Nix/Arbitrary/OutputName.hs +++ b/hnix-store-tests/src/System/Nix/Arbitrary/OutputName.hs @@ -3,8 +3,8 @@ module System.Nix.Arbitrary.OutputName where import System.Nix.OutputName (OutputName) -import qualified Data.Text -import qualified System.Nix.OutputName +import Data.Text qualified +import System.Nix.OutputName qualified import Test.QuickCheck (Arbitrary(arbitrary), choose, elements, vectorOf) diff --git a/hnix-store-tests/src/System/Nix/Arbitrary/Signature.hs b/hnix-store-tests/src/System/Nix/Arbitrary/Signature.hs index b11f9ae7..95792e18 100644 --- a/hnix-store-tests/src/System/Nix/Arbitrary/Signature.hs +++ b/hnix-store-tests/src/System/Nix/Arbitrary/Signature.hs @@ -4,10 +4,10 @@ {-# LANGUAGE OverloadedStrings #-} module System.Nix.Arbitrary.Signature where -import qualified Crypto.PubKey.Ed25519 +import Crypto.PubKey.Ed25519 qualified import Crypto.Random (drgNewTest, withDRG) -import qualified Data.ByteString as BS -import qualified Data.Text as Text +import Data.ByteString qualified as BS +import Data.Text qualified as Text import Test.QuickCheck.Arbitrary.Generic (GenericArbitrary(..)) import Test.QuickCheck diff --git a/hnix-store-tests/src/System/Nix/Arbitrary/StorePath.hs b/hnix-store-tests/src/System/Nix/Arbitrary/StorePath.hs index c07c9b39..7e1db845 100644 --- a/hnix-store-tests/src/System/Nix/Arbitrary/StorePath.hs +++ b/hnix-store-tests/src/System/Nix/Arbitrary/StorePath.hs @@ -6,14 +6,14 @@ module System.Nix.Arbitrary.StorePath where import Control.Applicative (liftA2) #endif import Crypto.Hash (MD5, SHA1, SHA256, SHA512) -import qualified Data.ByteString.Char8 -import qualified Data.Text +import Data.ByteString.Char8 qualified +import Data.Text qualified import System.Nix.StorePath (StoreDir(..) , StorePath , StorePathName , StorePathHashPart ) -import qualified System.Nix.StorePath +import System.Nix.StorePath qualified import Test.QuickCheck (Arbitrary(arbitrary), choose, elements, oneof, vectorOf) diff --git a/hnix-store-tests/src/System/Nix/Arbitrary/StorePath/Metadata.hs b/hnix-store-tests/src/System/Nix/Arbitrary/StorePath/Metadata.hs index 8cd26b67..23625846 100644 --- a/hnix-store-tests/src/System/Nix/Arbitrary/StorePath/Metadata.hs +++ b/hnix-store-tests/src/System/Nix/Arbitrary/StorePath/Metadata.hs @@ -14,7 +14,7 @@ import System.Nix.Arbitrary.UTCTime () import System.Nix.StorePath (StorePath) import System.Nix.StorePath.Metadata (Metadata(..), StorePathTrust) -import qualified System.Nix.Hash +import System.Nix.Hash qualified import Test.QuickCheck (Arbitrary(..), suchThat) import Test.QuickCheck.Arbitrary.Generic (GenericArbitrary(..)) diff --git a/hnix-store-tests/tests/ContentAddressSpec.hs b/hnix-store-tests/tests/ContentAddressSpec.hs index 7acbd6c7..398fe801 100644 --- a/hnix-store-tests/tests/ContentAddressSpec.hs +++ b/hnix-store-tests/tests/ContentAddressSpec.hs @@ -5,7 +5,7 @@ import Test.Hspec.QuickCheck (prop) import Test.Hspec.Nix (roundtrips) import System.Nix.Arbitrary () -import qualified System.Nix.ContentAddress +import System.Nix.ContentAddress qualified spec :: Spec spec = do diff --git a/hnix-store-tests/tests/DerivedPathSpec.hs b/hnix-store-tests/tests/DerivedPathSpec.hs index 442de3fa..d9423f67 100644 --- a/hnix-store-tests/tests/DerivedPathSpec.hs +++ b/hnix-store-tests/tests/DerivedPathSpec.hs @@ -6,7 +6,7 @@ import Test.Hspec.Nix (roundtrips) import System.Nix.Arbitrary () -import qualified System.Nix.DerivedPath +import System.Nix.DerivedPath qualified spec :: Spec spec = do diff --git a/hnix-store-tests/tests/RealisationSpec.hs b/hnix-store-tests/tests/RealisationSpec.hs index d35f3967..30f74f5d 100644 --- a/hnix-store-tests/tests/RealisationSpec.hs +++ b/hnix-store-tests/tests/RealisationSpec.hs @@ -6,11 +6,11 @@ import Test.Hspec.Nix (roundtrips) import System.Nix.Arbitrary () -import qualified Data.Text.Lazy -import qualified Data.Text.Lazy.Builder -import qualified System.Nix.StorePath -import qualified System.Nix.OutputName -import qualified System.Nix.Realisation +import Data.Text.Lazy qualified +import Data.Text.Lazy.Builder qualified +import System.Nix.StorePath qualified +import System.Nix.OutputName qualified +import System.Nix.Realisation qualified spec :: Spec spec = do diff --git a/hnix-store-tests/tests/StorePathSpec.hs b/hnix-store-tests/tests/StorePathSpec.hs index 7c83f354..2e791afd 100644 --- a/hnix-store-tests/tests/StorePathSpec.hs +++ b/hnix-store-tests/tests/StorePathSpec.hs @@ -7,7 +7,7 @@ import Test.Hspec.Nix (roundtrips) import System.Nix.Arbitrary () import System.Nix.StorePath -import qualified Data.Attoparsec.Text +import Data.Attoparsec.Text qualified spec :: Spec spec = do From a0f0a86903d78b47d10379fc00f1fe7ebd44333b Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 1 Jan 2025 19:01:13 -0500 Subject: [PATCH 52/58] Get `hnix-store-aterm` tests building --- hnix-store-aterm/README.md | 2 +- hnix-store-aterm/bench/Main.hs | 12 ++- hnix-store-aterm/hnix-store-aterm.cabal | 12 ++- hnix-store-aterm/pretty-derivation/Main.hs | 14 ++- hnix-store-aterm/tests/DerivationSpec.hs | 2 +- hnix-store-aterm/tests/Example.hs | 17 +++- hnix-store-aterm/tests/Property.hs | 108 ++++++--------------- 7 files changed, 73 insertions(+), 94 deletions(-) diff --git a/hnix-store-aterm/README.md b/hnix-store-aterm/README.md index eb5564b7..1528f2aa 100644 --- a/hnix-store-aterm/README.md +++ b/hnix-store-aterm/README.md @@ -35,7 +35,7 @@ t devdoc"),("propagatedBuildInputs",""),("propagatedNativeBuildInputs",""),("src ``` >>> text <- Data.Text.Lazy.IO.readFile "/nix/store/zzhs4fb83x5ygvjqn5rdpmpnishpdgy6-perl-MIME-Types-2.13.drv" ->>> let result = Data.Attoparsec.Text.Lazy.parse Nix.Derivation.parseDerivation text +>>> let result = Data.Attoparsec.Text.Lazy.parse System.Nix.Derivation.ATerm.parseDerivation text >>> result Done "" (Derivation {outputs = fromList [("devdoc",DerivationOutput {path = File Path "/nix/store/15x9ii8c3n5wb5lg80cm8x0yk6zy7rha-perl-MIME-Types-2.13-devdoc", diff --git a/hnix-store-aterm/bench/Main.hs b/hnix-store-aterm/bench/Main.hs index 30314692..30cdf87c 100644 --- a/hnix-store-aterm/bench/Main.hs +++ b/hnix-store-aterm/bench/Main.hs @@ -1,10 +1,13 @@ +{-# LANGUAGE OverloadedStrings #-} import Criterion (Benchmark) import Criterion qualified import Criterion.Main qualified import Data.Attoparsec.Text.Lazy qualified import Data.Text.Lazy.IO qualified -import Nix.Derivation qualified + +import System.Nix.StorePath +import System.Nix.Derivation.ATerm qualified main :: IO () main = Criterion.Main.defaultMain benchmarks @@ -19,5 +22,10 @@ benchmarks = bench0 example = Criterion.bench "example" (Criterion.nf parseExample example) + name = either (error . show) id $ mkStorePathName "ghc-8.0.2-with-packages" + parseExample = - Data.Attoparsec.Text.Lazy.parse Nix.Derivation.parseDerivation + Data.Attoparsec.Text.Lazy.parse $ + System.Nix.Derivation.ATerm.parseDerivation + (StoreDir "/nix/store") + name diff --git a/hnix-store-aterm/hnix-store-aterm.cabal b/hnix-store-aterm/hnix-store-aterm.cabal index dcef4714..78a5c137 100644 --- a/hnix-store-aterm/hnix-store-aterm.cabal +++ b/hnix-store-aterm/hnix-store-aterm.cabal @@ -66,6 +66,7 @@ Executable pretty-derivation attoparsec >= 0.12.0.0 && < 0.15, pretty-show >= 1.6.11 && < 1.11, text , + hnix-store-core , hnix-store-aterm GHC-Options: -Wall Main-Is: Main.hs @@ -79,7 +80,8 @@ Test-Suite example Build-Depends: base >= 4.6.0.0 && < 5 , attoparsec >= 0.12.0.0 && < 0.15, - hnix-store-aterm , + hnix-store-core , + hnix-store-aterm , text Test-Suite property @@ -91,7 +93,10 @@ Test-Suite property Build-Depends: base >= 4.6.0.0 && < 5 , attoparsec >= 0.12.0.0 && < 0.15, - hnix-store-aterm , + hnix-store-core , + hnix-store-aterm , + hnix-store-tests , + generic-arbitrary < 1.1 , QuickCheck < 2.16, text , these , @@ -109,5 +114,6 @@ Benchmark benchmark base >= 4.6.0.0 && < 5 , attoparsec >= 0.12.0.0 && < 0.15, criterion >= 1.1.4.0 && < 1.7 , - hnix-store-aterm , + hnix-store-core , + hnix-store-aterm , text diff --git a/hnix-store-aterm/pretty-derivation/Main.hs b/hnix-store-aterm/pretty-derivation/Main.hs index 5e410de3..f1f7b1a4 100644 --- a/hnix-store-aterm/pretty-derivation/Main.hs +++ b/hnix-store-aterm/pretty-derivation/Main.hs @@ -1,15 +1,23 @@ +{-# LANGUAGE OverloadedStrings #-} module Main where import Data.Attoparsec.Text.Lazy (Result(..)) - import Data.Attoparsec.Text.Lazy qualified import Data.Text.Lazy.IO qualified -import Nix.Derivation qualified import Text.Show.Pretty qualified +import System.Nix.StorePath +import System.Nix.Derivation.ATerm qualified + main :: IO () main = do text <- Data.Text.Lazy.IO.getContents - case Data.Attoparsec.Text.Lazy.parse Nix.Derivation.parseDerivation text of + case + Data.Attoparsec.Text.Lazy.parse + (System.Nix.Derivation.ATerm.parseDerivation + (StoreDir "/nix/store") + (error "todo get name from outputs if needed")) + text + of Fail _ _ err -> fail err Done _ derivation -> Text.Show.Pretty.pPrint derivation diff --git a/hnix-store-aterm/tests/DerivationSpec.hs b/hnix-store-aterm/tests/DerivationSpec.hs index 1a86c70f..05867220 100644 --- a/hnix-store-aterm/tests/DerivationSpec.hs +++ b/hnix-store-aterm/tests/DerivationSpec.hs @@ -14,7 +14,7 @@ import Data.Text.Lazy.Builder qualified -- TODO(srk): this won't roundtrip as Arbitrary Text -- contains wild stuff like control characters and UTF8 sequences. -- Either fix in hnix-store-aterm or use wrapper type --- (but we use Nix.Derivation.textParser so we need Text for now) +-- (but we use System.Nix.Derivation.ATerm.textParser so we need Text for now) spec :: Spec spec = do describe "Derivation" $ do diff --git a/hnix-store-aterm/tests/Example.hs b/hnix-store-aterm/tests/Example.hs index d819b9ec..707ab293 100644 --- a/hnix-store-aterm/tests/Example.hs +++ b/hnix-store-aterm/tests/Example.hs @@ -1,19 +1,28 @@ +{-# LANGUAGE OverloadedStrings #-} module Main where -import Nix.Derivation qualified import Data.Attoparsec.Text.Lazy qualified import Data.Text.Lazy.Builder qualified import Data.Text.Lazy.IO qualified - import Data.Attoparsec.Text.Lazy (Result(..)) +import System.Nix.StorePath +import System.Nix.Derivation.ATerm qualified + main :: IO () main = do + name <- either (fail . show) pure $ mkStorePathName "perl-MIME-Types-2.13-devdoc" + let storeDir = StoreDir "/nix/store" text0 <- Data.Text.Lazy.IO.readFile "tests/example0.drv" - derivation <- case Data.Attoparsec.Text.Lazy.parse Nix.Derivation.parseDerivation text0 of + derivation <- + case + Data.Attoparsec.Text.Lazy.parse + (System.Nix.Derivation.ATerm.parseDerivation storeDir name) + text0 + of Fail _ _ string -> fail string Done _ derivation -> return derivation - let builder = Nix.Derivation.buildDerivation derivation + let builder = System.Nix.Derivation.ATerm.buildDerivation storeDir derivation let text1 = Data.Text.Lazy.Builder.toLazyText builder if text0 == text1 then return () diff --git a/hnix-store-aterm/tests/Property.hs b/hnix-store-aterm/tests/Property.hs index d5bc7680..3b79a98f 100644 --- a/hnix-store-aterm/tests/Property.hs +++ b/hnix-store-aterm/tests/Property.hs @@ -1,103 +1,51 @@ +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TypeSynonymInstances #-} -{-# LANGUAGE FlexibleInstances #-} - -{-# OPTIONS_GHC -fno-warn-orphans #-} +{-# LANGUAGE DerivingVia #-} +{-# LANGUAGE StandaloneDeriving #-} +-- due to recent generic-arbitrary +{-# OPTIONS_GHC -fconstraint-solver-iterations=0 #-} +{-# OPTIONS_GHC -Wno-orphans #-} module Main where -import Data.These -import Data.Text (Text) -import Data.Vector (Vector) -import System.FilePath -import Nix.Derivation - ( Derivation(..) - , DerivationOutput(..) - , DerivationInputs(..) - , DerivedPathMap(..) - ) import Prelude hiding (FilePath, either) -import Test.QuickCheck (Arbitrary(..), Gen, oneof) import Data.Attoparsec.Text.Lazy qualified -import Data.Text qualified import Data.Text.Lazy.Builder qualified -import Data.Vector qualified -import Nix.Derivation qualified +import Test.QuickCheck (Arbitrary(..)) import Test.QuickCheck qualified +import Test.QuickCheck.Arbitrary.Generic (GenericArbitrary(..)) -instance Arbitrary Text where - arbitrary = fmap Data.Text.pack arbitrary - -instance Arbitrary a => Arbitrary (Vector a) where - arbitrary = fmap Data.Vector.fromList arbitrary - -instance Arbitrary (DerivationOutput FilePath Text) where - arbitrary = oneof - [ inputAddressedDerivationOutput - , fixedDerivationOutput - , contentAddressedDerivationOutput - ] - -inputAddressedDerivationOutput :: Gen (DerivationOutput FilePath Text) -inputAddressedDerivationOutput = do - path <- arbitrary - return (InputAddressedDerivationOutput {..}) - -fixedDerivationOutput :: Gen (DerivationOutput FilePath Text) -fixedDerivationOutput = do - path <- arbitrary - hashAlgo <- arbitrary - hash <- arbitrary - return (FixedDerivationOutput {..}) - -contentAddressedDerivationOutput :: Gen (DerivationOutput FilePath Text) -contentAddressedDerivationOutput = do - hashAlgo <- arbitrary - return (ContentAddressedDerivationOutput {..}) - -instance Arbitrary (DerivationInputs FilePath Text) where - arbitrary = do - drvs <- arbitrary - srcs <- arbitrary - pure DerivationInputs {..} - -instance Arbitrary (DerivedPathMap FilePath Text) where - arbitrary = DerivedPathMap . fmap This <$> arbitrary +import System.Nix.StorePath +import System.Nix.Derivation + ( Derivation'(..) + , DerivationOutput(..) + ) +import System.Nix.Arbitrary.Derivation () +import System.Nix.Derivation.ATerm qualified +import System.Nix.Derivation.Traditional -instance Arbitrary - (Derivation - FilePath - Text - Text - (DerivationOutput FilePath Text) - (DerivationInputs FilePath Text) - ) where - arbitrary = do - outputs <- arbitrary - inputs <- arbitrary - platform <- arbitrary - builder <- arbitrary - args <- arbitrary - env <- arbitrary - pure Derivation {..} +deriving via GenericArbitrary TraditionalDerivationInputs + instance Arbitrary TraditionalDerivationInputs property - :: Derivation - FilePath - Text - Text - (DerivationOutput FilePath Text) - (DerivationInputs FilePath Text) + :: StoreDir + -> Derivation' + TraditionalDerivationInputs + DerivationOutput -> Bool -property derivation0 = either == Right derivation0 +property storeDir derivation0 = either == Right derivation0 where - builder = Nix.Derivation.buildDerivation derivation0 + builder = System.Nix.Derivation.ATerm.buildDerivation storeDir derivation0 text = Data.Text.Lazy.Builder.toLazyText builder result = - Data.Attoparsec.Text.Lazy.parse Nix.Derivation.parseDerivation text + Data.Attoparsec.Text.Lazy.parse + (System.Nix.Derivation.ATerm.parseDerivation storeDir (name derivation0)) + text either = Data.Attoparsec.Text.Lazy.eitherResult result From 35017eb4b59e2893f9f3372830ed7972c7885483 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 1 Jan 2025 19:38:49 -0500 Subject: [PATCH 53/58] Sort inputs in test file The example sorted names before hashes, but `Nix` (at least these days) and `hnix-store` do not do that. Delete the redundant copies in `hnix-store-core` --- hnix-store-aterm/tests/example0.drv | 2 +- hnix-store-aterm/tests/example1.drv | 2 +- hnix-store-core/hnix-store-core.cabal | 2 -- hnix-store-core/tests/samples/example0.actual | 1 - hnix-store-core/tests/samples/example1.actual | 1 - 5 files changed, 2 insertions(+), 6 deletions(-) delete mode 100644 hnix-store-core/tests/samples/example0.actual delete mode 100644 hnix-store-core/tests/samples/example1.actual diff --git a/hnix-store-aterm/tests/example0.drv b/hnix-store-aterm/tests/example0.drv index f607eaf4..68db5764 100644 --- a/hnix-store-aterm/tests/example0.drv +++ b/hnix-store-aterm/tests/example0.drv @@ -1 +1 @@ -Derive([("devdoc","/nix/store/15x9ii8c3n5wb5lg80cm8x0yk6zy7rha-perl-MIME-Types-2.13-devdoc","",""),("out","/nix/store/93d75ghjyibmbxgfzwhh4b5zwsxzs44w-perl-MIME-Types-2.13","","")],[("/nix/store/57h2hjsdkdiwbzilcjqkn46138n1xb4a-perl-5.22.3.drv",["out"]),("/nix/store/cvdbbvnvg131bz9bwyyk97jpq1crclqr-MIME-Types-2.13.tar.gz.drv",["out"]),("/nix/store/p5g31bc5x92awghx9dlm065d7j773l0r-stdenv.drv",["out"]),("/nix/store/x50y5qihwsn0lfjhrf1s81b5hgb9w632-bash-4.4-p5.drv",["out"])],["/nix/store/cdips4lakfk1qbf1x68fq18wnn3r5r14-builder.sh"],"x86_64-linux","/nix/store/fi3mbd2ml4pbgzyasrlnp0wyy6qi48fh-bash-4.4-p5/bin/bash",["-e","/nix/store/cdips4lakfk1qbf1x68fq18wnn3r5r14-builder.sh"],[("AUTOMATED_TESTING","1"),("PERL_AUTOINSTALL","--skipdeps"),("buildInputs",""),("builder","/nix/store/fi3mbd2ml4pbgzyasrlnp0wyy6qi48fh-bash-4.4-p5/bin/bash"),("checkTarget","test"),("devdoc","/nix/store/15x9ii8c3n5wb5lg80cm8x0yk6zy7rha-perl-MIME-Types-2.13-devdoc"),("doCheck","1"),("installTargets","pure_install"),("name","perl-MIME-Types-2.13"),("nativeBuildInputs","/nix/store/nsa311yg8h93wfaacjk16c96a98bs09f-perl-5.22.3"),("out","/nix/store/93d75ghjyibmbxgfzwhh4b5zwsxzs44w-perl-MIME-Types-2.13"),("outputs","out devdoc"),("propagatedBuildInputs",""),("propagatedNativeBuildInputs",""),("src","/nix/store/5smhymz7viq8p47mc3jgyvqd003ab732-MIME-Types-2.13.tar.gz"),("stdenv","/nix/store/s3rlr45jzlzx0d6k2azlpxa5zwzr7xyy-stdenv"),("system","x86_64-linux")]) \ No newline at end of file +Derive([("devdoc","/nix/store/15x9ii8c3n5wb5lg80cm8x0yk6zy7rha-perl-MIME-Types-2.13-devdoc","",""),("out","/nix/store/93d75ghjyibmbxgfzwhh4b5zwsxzs44w-perl-MIME-Types-2.13","","")],[("/nix/store/cvdbbvnvg131bz9bwyyk97jpq1crclqr-MIME-Types-2.13.tar.gz.drv",["out"]),("/nix/store/p5g31bc5x92awghx9dlm065d7j773l0r-stdenv.drv",["out"]),("/nix/store/x50y5qihwsn0lfjhrf1s81b5hgb9w632-bash-4.4-p5.drv",["out"]),("/nix/store/57h2hjsdkdiwbzilcjqkn46138n1xb4a-perl-5.22.3.drv",["out"])],["/nix/store/cdips4lakfk1qbf1x68fq18wnn3r5r14-builder.sh"],"x86_64-linux","/nix/store/fi3mbd2ml4pbgzyasrlnp0wyy6qi48fh-bash-4.4-p5/bin/bash",["-e","/nix/store/cdips4lakfk1qbf1x68fq18wnn3r5r14-builder.sh"],[("AUTOMATED_TESTING","1"),("PERL_AUTOINSTALL","--skipdeps"),("buildInputs",""),("builder","/nix/store/fi3mbd2ml4pbgzyasrlnp0wyy6qi48fh-bash-4.4-p5/bin/bash"),("checkTarget","test"),("devdoc","/nix/store/15x9ii8c3n5wb5lg80cm8x0yk6zy7rha-perl-MIME-Types-2.13-devdoc"),("doCheck","1"),("installTargets","pure_install"),("name","perl-MIME-Types-2.13"),("nativeBuildInputs","/nix/store/nsa311yg8h93wfaacjk16c96a98bs09f-perl-5.22.3"),("out","/nix/store/93d75ghjyibmbxgfzwhh4b5zwsxzs44w-perl-MIME-Types-2.13"),("outputs","out devdoc"),("propagatedBuildInputs",""),("propagatedNativeBuildInputs",""),("src","/nix/store/5smhymz7viq8p47mc3jgyvqd003ab732-MIME-Types-2.13.tar.gz"),("stdenv","/nix/store/s3rlr45jzlzx0d6k2azlpxa5zwzr7xyy-stdenv"),("system","x86_64-linux")]) \ No newline at end of file diff --git a/hnix-store-aterm/tests/example1.drv b/hnix-store-aterm/tests/example1.drv index 0d913b6d..1530d8d3 100644 --- a/hnix-store-aterm/tests/example1.drv +++ b/hnix-store-aterm/tests/example1.drv @@ -1 +1 @@ -Derive([("out","/nix/store/w3zbr9zj9mn08hnirn34wsxhry40qi3c-ghc-8.0.2-with-packages","","")],[("/nix/store/0cyv377kjnhjc9j1pb0m530lczqj4ksm-optparse-generic-1.1.5.drv",["out"]),("/nix/store/0w9vy2hmz50j0yhlbj519hnpjbvqhjrj-cookie-0.4.2.1.drv",["out"]),("/nix/store/1b75igh40c9agy3sfyl5n7av4070swvn-old-locale-1.0.0.7.drv",["out"]),("/nix/store/1g2qxhbpk7qjyz8qbami29bn7qmnmgpk-tagged-0.8.5.drv",["out"]),("/nix/store/20m5alpbwyvyhh43aq3prw07g48apdnj-parsers-0.12.4.drv",["out"]),("/nix/store/2bmxgjskcw4vdmcqrw9pc9yjffsqn3i9-byteable-0.1.1.drv",["out"]),("/nix/store/3fji5p4x9j0cb3q3lp8amrj0qak9d471-asn1-encoding-0.9.5.drv",["out"]),("/nix/store/43hyjsydndk7vsdjs94why36s8isn6fw-kan-extensions-5.0.1.drv",["out"]),("/nix/store/4hkya8j2isw660pj6b0q3by85q2wz1zw-free-4.12.4.drv",["out"]),("/nix/store/56l353i7v6i7i5vkk2qx4wi4r6p4xll1-void-0.7.2.drv",["out"]),("/nix/store/5c748d8gmrmg2gy4792a0kzp5bjw8sgr-cereal-0.5.4.0.drv",["out"]),("/nix/store/5d3v9g9jjqznbpxrlgvcyvmqqz2ffpgc-fingertree-0.1.1.0.drv",["out"]),("/nix/store/5hx7hjjrwqa4zjd9ql224aif86ncj764-hook.drv",["out"]),("/nix/store/5rpa05i9i5p3i0a06lhyvgg1nvlwnlfi-unordered-containers-0.2.8.0.drv",["out"]),("/nix/store/5x6d3f9krpqlmzhmk71qf7m97g38hba1-base-prelude-1.0.1.1.drv",["out"]),("/nix/store/61fzrmaxsfc9q4qzsdcrsaqgg05hr6xi-bifunctors-5.4.2.drv",["out"]),("/nix/store/6l4s2nlxc9fq8c3y3j2k2c7af5llx278-hashable-1.2.6.0.drv",["out"]),("/nix/store/6n2kl1fnn66a24ipjm1dxjhhvni1404r-mtl-2.2.1.drv",["out"]),("/nix/store/6qggipw2ra59q6333y25gywllbbcx3p5-hourglass-0.2.10.drv",["out"]),("/nix/store/7545pmiaccgvkxjfvl9cm0qk7y1x96wi-reflection-2.1.2.drv",["out"]),("/nix/store/75iir4x52007r0fq41kwk5cdfvmi02jp-profunctors-5.2.drv",["out"]),("/nix/store/7ah4kd8kbwsfr350wkr0y4i0h6gm7vc8-base64-bytestring-1.0.0.1.drv",["out"]),("/nix/store/7d6yxihb828lgs4199f81k17jh8987z6-lndir-1.0.3.drv",["out"]),("/nix/store/7f6ddryzkw9jckayqs1gdz18njrqd0fq-random-1.1.drv",["out"]),("/nix/store/8p1f0rs49czq74yxlfcimlag9wnbwsc5-http-client-tls-0.3.4.1.drv",["out"]),("/nix/store/9w2n7jqc9ll78r7xj31ckrqcq6g8g8kf-integer-logarithms-1.0.1.drv",["out"]),("/nix/store/a2ar311g8chbi4ila55qzi3dfp9g5zr6-blaze-html-0.8.1.3.drv",["out"]),("/nix/store/ahypsxsxcczsllax40jnccdg5ilps2lq-http-client-0.5.6.1.drv",["out"]),("/nix/store/as62r0pdaq0q76rxz719xy33vqa7xcal-double-conversion-2.0.2.0.drv",["out"]),("/nix/store/b67b65arib97rsl4z5iqz03gf24ymvz5-http-types-0.9.1.drv",["out"]),("/nix/store/bczn7hbvp39aplp70gvmyijdysvkyspg-primitive-0.6.1.0.drv",["out"]),("/nix/store/bwf0a834k4jf5ss2ccribn9w7g2r3j3m-stdenv.drv",["out"]),("/nix/store/ckl2x2vkqj82k4b7c5l8p611g6jmfbsz-zlib-0.6.1.2.drv",["out"]),("/nix/store/clxg57lhlflbjrk6w3fv51fxjnqkk7q4-transformers-compat-0.5.1.4.drv",["out"]),("/nix/store/d1n1p6mdabwkgkc7y6151j37c4kqh1a2-exceptions-0.8.3.drv",["out"]),("/nix/store/dg6n7519y227s9c867wqi2v40cj41zqy-attoparsec-0.13.1.0.drv",["out"]),("/nix/store/f3l740wl94r84fgsiindy88jppcjya6l-text-format-0.3.1.1.drv",["out"]),("/nix/store/f67vqhk71lrab7ncx8fz8bj7iggmm66f-cryptonite-0.21.drv",["out"]),("/nix/store/fdq2dn4gal13xl9jbyk8igvaw5f2x9b5-blaze-builder-0.4.0.2.drv",["out"]),("/nix/store/fr1acpclaljwizrvic520wdf36kmxjwr-blaze-markup-0.7.1.1.drv",["out"]),("/nix/store/fyi4gg70v1lgjz03v07flnmjr8x55mqk-async-2.1.1.1.drv",["out"]),("/nix/store/ginljsxbpxli394mc06gvqkmvddhqwlc-x509-store-1.6.2.drv",["out"]),("/nix/store/gq055a1910w9q6mbb5kf6p6igzg6b5ai-StateVar-1.1.0.4.drv",["out"]),("/nix/store/hhx5xjb6cm5rdkri763669bf6karrnpn-parsec-3.1.11.drv",["out"]),("/nix/store/ip7nh1r7mj4qwgra27x8i6nyz6yd1ggd-prelude-extras-0.4.0.3.drv",["out"]),("/nix/store/iqd84gv7b8dq5kddxyjimaqqlxjpqdzk-vector-0.11.0.0.drv",["out"]),("/nix/store/j24c6d5zv7nim3rkmzzapk6x61lzgizq-charset-0.3.7.1.drv",["out"]),("/nix/store/j6zji0jn6cm8b4i0fmakksk1cp54bhn0-asn1-types-0.3.2.drv",["out"]),("/nix/store/l3wmibr3b1b3a8ql8ypy860209iqbasg-connection-0.2.8.drv",["out"]),("/nix/store/lg64zgciix9644hzkfc02rfbq4qgcrf8-memory-0.14.3.drv",["out"]),("/nix/store/lnxgjiywc89iaby3g0na1sc4hryvnikq-trifecta-1.6.2.1.drv",["out"]),("/nix/store/lvm3zp40qfdqr0v9i27z7dqpdwlxprbl-text-1.2.2.1.drv",["out"]),("/nix/store/m7l8bg4k82snsl759k2mlkjlb8g0352a-foundation-0.0.7.drv",["out"]),("/nix/store/mi1fdfdkc5qc7iq2ry6095ayp9cqn075-x509-system-1.6.4.drv",["out"]),("/nix/store/mpql2q0b6a1m2vkb114f9l2s8dhy09zv-asn1-parse-0.9.4.drv",["out"]),("/nix/store/mq338r0an8lj00g88c6rpylbnmds7fbx-adjunctions-4.3.drv",["out"]),("/nix/store/n4wyn46xw0nw8a3rhqw47xd4h6bgnn5w-lens-4.15.1.drv",["out"]),("/nix/store/nv7frilmipcpylijp492l3hc0s2cmgw6-tls-1.3.10.drv",["out"]),("/nix/store/nwapw7zf014frf49c0b7y5694jyc38hm-streaming-commons-0.1.17.drv",["out"]),("/nix/store/pcg29qa8fm9niixbjy0r7bbp3s4jxk62-neat-interpolation-0.3.2.1.drv",["out"]),("/nix/store/pg609c09rfqzyfn8l4hsc1q2xy50w4p8-semigroupoids-5.1.drv",["out"]),("/nix/store/pra6ynwnksgks1xxv2l7h48swjq4vb2j-data-default-class-0.1.2.0.drv",["out"]),("/nix/store/pz3s86hbxvwr7m4x7cpz5h8z124wgk4x-x509-1.6.5.drv",["out"]),("/nix/store/qi0668xlc3q03n74k1wrqri7ss7bvphk-stm-2.4.4.1.drv",["out"]),("/nix/store/ql8bpbnl7x7ybn3rnsknpkpwvlz7s2nz-distributive-0.5.2.drv",["out"]),("/nix/store/qr8wf0b1lqwxwi6ban2k307jy91bj640-reducers-3.12.1.drv",["out"]),("/nix/store/r44a3jm3q5rhi75rl1m6jr1vgwpiyw02-hnix-0.3.4.drv",["out"]),("/nix/store/rqcq6jigs1sj53f8wrbff3s06wzazfqw-comonad-5.0.1.drv",["out"]),("/nix/store/s1ymda8d763cn5gq4cw107h19xs1ddz0-ansi-wl-pprint-0.6.7.3.drv",["out"]),("/nix/store/sdx411558r03fdvfi3p6wzfsi701sv4w-system-fileio-0.3.16.3.drv",["out"]),("/nix/store/v0srwl68sz6dirasq53bd3ddjipa1d5b-deriving-compat-0.3.6.drv",["out"]),("/nix/store/vpqjk2wral953nnqnhvp8zbmkbhnyxls-x509-validation-1.6.5.drv",["out"]),("/nix/store/vr8scnq8lxgc0m6k7bqjwi4fg0k55lxn-data-fix-0.0.4.drv",["out"]),("/nix/store/vwhic7ibwkzqk65mqicb29d5qz06gkns-socks-0.5.5.drv",["out"]),("/nix/store/w6a3c55nhmpcia6cvdg31nqsc7v910lc-ansi-terminal-0.6.2.3.drv",["out"]),("/nix/store/wdgbs33iwqadfmlaymw00k6iwnf3as7z-mime-types-0.1.0.7.drv",["out"]),("/nix/store/wld7wjy6lws02rky68mpg0x591wv0j6v-pem-0.2.2.drv",["out"]),("/nix/store/wx9vx1z55bzkzym0lzbgpzd7rrsx9w9b-scientific-0.3.4.12.drv",["out"]),("/nix/store/x2dkgpklc1adq1cgg1k8ykdqv7ghwhzm-system-filepath-0.4.13.4.drv",["out"]),("/nix/store/x50y5qihwsn0lfjhrf1s81b5hgb9w632-bash-4.4-p5.drv",["out"]),("/nix/store/x8k0rsb1ig82vdls0dc6jdlny7r04izj-parallel-3.2.1.1.drv",["out"]),("/nix/store/xbygsq84395vhj7bnh7786i9864jf9i9-ghc-8.0.2.drv",["out"]),("/nix/store/xp7jayhmiphx0zqxx9dxrk673shhj89l-optparse-applicative-0.13.2.0.drv",["out"]),("/nix/store/xzda3rxckhf0h3lp1hr6wanyig9s9y1p-utf8-string-1.0.1.1.drv",["out"]),("/nix/store/y4ll9c29g76jzycl7zhdmqzxgciyrfr1-case-insensitive-1.2.0.9.drv",["out"]),("/nix/store/y8l0lv08hfi6qnrzd25dxgi4712yjf9f-base-orphans-0.5.4.drv",["out"]),("/nix/store/z036z61lsrk2gqbwljix0akzhz2bgl8j-semigroups-0.18.2.drv",["out"]),("/nix/store/z8vpk1rwkikc8pg20vyg5kvsdv626ksw-dhall-1.3.0.drv",["out"]),("/nix/store/zdx2r8q401h7xcyh7jg0cnp092iwlhmv-contravariant-1.4.drv",["out"]),("/nix/store/zg5as9jrs5vfa5iw7539vihmwm436g1q-network-uri-2.6.1.0.drv",["out"]),("/nix/store/zvxd18a65gwcg3bz7v1rb0h59w9wwi9d-network-2.6.3.1.drv",["out"])],["/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"],"x86_64-linux","/nix/store/fi3mbd2ml4pbgzyasrlnp0wyy6qi48fh-bash-4.4-p5/bin/bash",["-e","/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"],[("allowSubstitutes",""),("buildCommand","mkdir -p $out\nfor i in $paths; do\n /nix/store/lnai0im3lcpb03arxfi0wx1dm7anf4f8-lndir-1.0.3/bin/lndir $i $out\ndone\n. /nix/store/plmya6mkfvq658ba7z6j6n36r5pdbxk5-hook/nix-support/setup-hook\n\n# wrap compiler executables with correct env variables\n\nfor prg in ghc ghci ghc-8.0.2 ghci-8.0.2; do\n if [[ -x \"/nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg\" ]]; then\n rm -f $out/bin/$prg\n makeWrapper /nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg $out/bin/$prg \\\n --add-flags '\"-B$NIX_GHC_LIBDIR\"' \\\n --set \"NIX_GHC\" \"$out/bin/ghc\" \\\n --set \"NIX_GHCPKG\" \"$out/bin/ghc-pkg\" \\\n --set \"NIX_GHC_DOCDIR\" \"$out/share/doc/ghc/html\" \\\n --set \"NIX_GHC_LIBDIR\" \"$out/lib/ghc-8.0.2\" \\\n \n fi\ndone\n\nfor prg in runghc runhaskell; do\n if [[ -x \"/nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg\" ]]; then\n rm -f $out/bin/$prg\n makeWrapper /nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg $out/bin/$prg \\\n --add-flags \"-f $out/bin/ghc\" \\\n --set \"NIX_GHC\" \"$out/bin/ghc\" \\\n --set \"NIX_GHCPKG\" \"$out/bin/ghc-pkg\" \\\n --set \"NIX_GHC_DOCDIR\" \"$out/share/doc/ghc/html\" \\\n --set \"NIX_GHC_LIBDIR\" \"$out/lib/ghc-8.0.2\"\n fi\ndone\n\nfor prg in ghc-pkg ghc-pkg-8.0.2; do\n if [[ -x \"/nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg\" ]]; then\n rm -f $out/bin/$prg\n makeWrapper /nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg $out/bin/$prg --add-flags \"--global-package-db=$out/lib/ghc-8.0.2/package.conf.d\"\n fi\ndone\n$out/bin/ghc-pkg recache\n\n$out/bin/ghc-pkg check\n\n"),("buildInputs",""),("builder","/nix/store/fi3mbd2ml4pbgzyasrlnp0wyy6qi48fh-bash-4.4-p5/bin/bash"),("extraOutputsToInstall","out doc"),("ignoreCollisions",""),("name","ghc-8.0.2-with-packages"),("nativeBuildInputs",""),("out","/nix/store/w3zbr9zj9mn08hnirn34wsxhry40qi3c-ghc-8.0.2-with-packages"),("passAsFile","buildCommand"),("paths","/nix/store/rlsammwp1ib8d3d9qgbppmdhkbdfg3i9-deriving-compat-0.3.6 /nix/store/v2qsqznrik64f46msahvgg7dmaiag18k-hnix-0.3.4 /nix/store/vbkqj8zdckqqiyjh08ykx75fwc90gwg4-optparse-applicative-0.13.2.0 /nix/store/6m7qia8q0rkdkzvmiak38kdscf27malf-optparse-generic-1.1.5 /nix/store/r687llig7vn9x15hhkmfak01ff7082n6-utf8-string-1.0.1.1 /nix/store/j6gvad67dav8fl3vdbqmar84kgmh5gar-reducers-3.12.1 /nix/store/i8wf08764lknc0f9ja12miqvg509jn1k-fingertree-0.1.1.0 /nix/store/301hq4fabrpbi3l47n908gvakkzq1s88-blaze-markup-0.7.1.1 /nix/store/055mhi44s20x5xgxdjr82vmhnyv79pzl-blaze-html-0.8.1.3 /nix/store/vnc1yyig90skcwx3l1xrbp1jqwmmb9xv-trifecta-1.6.2.1 /nix/store/vraffi24marw5sks8b78xrim6c8i1ng6-double-conversion-2.0.2.0 /nix/store/kwdk03p0lyk5lyll1fp7a6z20j17b3sx-text-format-0.3.1.1 /nix/store/zn5hlw3y94sbli4ssygr2w04mpb396zs-system-filepath-0.4.13.4 /nix/store/jn7lbnk0gsirj8kb02an31v8idy7ym3c-system-fileio-0.3.16.3 /nix/store/9frfci9ywf9lc216ci9nwc1yy0qwrn1b-integer-logarithms-1.0.1 /nix/store/rps46jwa7yyab629p27lar094gk8dal2-scientific-0.3.4.12 /nix/store/c4a3ynvnv3kdxgd7ngmnjhka4mvfk8ll-attoparsec-0.13.1.0 /nix/store/kc34l1gpzh65y4gclmv4dgv6agpmagdi-parsers-0.12.4 /nix/store/1kf78yxf3lliagb5rc5din24iq40g96y-base-prelude-1.0.1.1 /nix/store/hi868d12pkzcbzyvp7a7cigc58mp2lmg-neat-interpolation-0.3.2.1 /nix/store/h00jrbdvzj4yfy796j8vq00lkd1gxr6w-primitive-0.6.1.0 /nix/store/vys8qsf317rn8qwy00p80zlywb47lqwz-vector-0.11.0.0 /nix/store/wchch11312m3lxkwl8rad04x02svcs3i-reflection-2.1.2 /nix/store/jj1kfv52mjxp54flz8v5ba64va3hvy22-parallel-3.2.1.1 /nix/store/jwj23y7vfvs14jdrkw1py9q7lm9fyhy4-adjunctions-4.3 /nix/store/px4979la9b98knwv36551zg3p5jb69lw-kan-extensions-5.0.1 /nix/store/2cp1ar0f73jrcn231ai07zpwayy735j2-semigroupoids-5.1 /nix/store/3nkxw5wdadckz28laijrvwdkkfqp07sb-profunctors-5.2 /nix/store/bd3njvy0ahcsqw47vaz5zayhx34hari7-prelude-extras-0.4.0.3 /nix/store/zdp7zqasz1l1wifpngbg6ngq189gbbqh-free-4.12.4 /nix/store/n7c5ynfqc6j570bbyaajqx34c3pvfvph-tagged-0.8.5 /nix/store/xdkhd7mkqj2mmcami8ycmf7j0valwp5h-distributive-0.5.2 /nix/store/9dxba4g9x0xjj21r3vchqnh4rdwbc31b-void-0.7.2 /nix/store/dahah2ivrn4hc5gjygnlvxlad2399zqh-StateVar-1.1.0.4 /nix/store/f2rdi1bx46fs165n1j316k5w90ab6lwy-contravariant-1.4 /nix/store/mgg9rsvhvn4dd4qzv559nn24iqvspjnb-comonad-5.0.1 /nix/store/18n8i570pf4gpszdyc0bki9qxm1p9xd7-bifunctors-5.4.2 /nix/store/d8ys5wq4wrvdjqw0bzv3y23zqprkhjs2-base-orphans-0.5.4 /nix/store/j4hbyhnj4a2z4z4vb1437vk7ha0b287a-lens-4.15.1 /nix/store/ra3jh12mbyz82n4gvj2bam77vl8aabbq-x509-system-1.6.4 /nix/store/ps8915q1047frp891jg1anp85ads0s9b-x509-validation-1.6.5 /nix/store/5vrgrls6l1cdsbbznis39chx8scq2r98-x509-store-1.6.2 /nix/store/7vvg8y8fp0s50qiciq11irfvh31f1q58-pem-0.2.2 /nix/store/myv75wk9s19f8vms2dcy6sl773288zy4-asn1-parse-0.9.4 /nix/store/kwyc1jdz09lazw21qpc96wyamxalcg11-x509-1.6.5 /nix/store/gadc7c6d1lqn0wqk29bhn56is67x0r45-cryptonite-0.21 /nix/store/ix26y5rpidwpgjzrsixz0ff59j1p1swr-foundation-0.0.7 /nix/store/n784p4qh18zx9v8ag3n3ypszq1kifjjr-memory-0.14.3 /nix/store/h3qq6m5ahdb4kw784gcvx2skil8ilks8-hourglass-0.2.10 /nix/store/dn65dl65spk4j0sky2zpdig75c42ycj1-asn1-types-0.3.2 /nix/store/s5jklkk0y6i7d8h3akgsciv1kv2js786-asn1-encoding-0.9.5 /nix/store/g5qjgns5cyz9c5xw4w5s2iji1kbhg47z-tls-1.3.10 /nix/store/iyllk46by75f428pwis9v74jpr1rmk4x-cereal-0.5.4.0 /nix/store/b22wyyl3wdl6kb7gkpk3yxnynk340lya-socks-0.5.5 /nix/store/05r3i8w2n7hbxqyb4w8rina9rldyacd3-byteable-0.1.1 /nix/store/xjbl6w60czyfqlfwwfs5q93by144yr1n-connection-0.2.8 /nix/store/j10yqzk323rvnwgsk3nj7rgmvqlv035a-http-client-tls-0.3.4.1 /nix/store/vf84v2398g55mai2gjh2d9gipwizhhzd-zlib-0.6.1.2 /nix/store/7h7vy3mi603y536dgvxwfglaacxw5ra8-async-2.1.1.1 /nix/store/y6hh2ifv35afw1j5phpzp1y72x532izn-streaming-commons-0.1.17 /nix/store/f5jdarp8djisa1wrv4bv1saimrabcb3f-random-1.1 /nix/store/18vpnmd28bnjib6andw8bx522wcb3zwa-parsec-3.1.11 /nix/store/i3ra66pcpj0v9wq3m00gh9i72br2bki3-network-uri-2.6.1.0 /nix/store/2ck9avbwacfpi16p2ib2shw951mx33pz-network-2.6.3.1 /nix/store/rz0227nv8n8kdrxjg3arya6r2ixxjh4h-mime-types-0.1.0.7 /nix/store/rx71j4kg0l02dginiswnmwswdq9i9msv-http-types-0.9.1 /nix/store/y2ca4scn0n2f9qsmvsiixcnx11793jlf-transformers-compat-0.5.1.4 /nix/store/bzicr83ibzzzbab6cjkb3i95sc8cvxy9-stm-2.4.4.1 /nix/store/qk5pl6r2h0vfkhhwjgrv8x1ldf8dyj5a-mtl-2.2.1 /nix/store/0d6k71ljl108dgq1l7l3pz12bfwv0z4h-exceptions-0.8.3 /nix/store/z5k23ymwjhhpd670a7mcsm1869hlpncf-old-locale-1.0.0.7 /nix/store/k4an783d4j3m48fqhx7gpnizqg2ns38j-data-default-class-0.1.2.0 /nix/store/p5867jsig02zi0ynww9w4916nm0k527s-cookie-0.4.2.1 /nix/store/wy7j42kqlw1sskagmyc1bzb0xv04s2na-case-insensitive-1.2.0.9 /nix/store/j35339b0nk7k3qaq3m75nl3i4x603rqf-blaze-builder-0.4.0.2 /nix/store/33mip0ql9x1jjbhi34kf8izh4ilyf2k0-base64-bytestring-1.0.0.1 /nix/store/29a73kd2jkwvfdcrhysmi5xjr7nysrxf-http-client-0.5.6.1 /nix/store/d2hy666g79qvhmbh520x5jclwvnr1gk2-text-1.2.2.1 /nix/store/2bdzia66lg08d5zngmllcjry2c08m96j-hashable-1.2.6.0 /nix/store/7kdgc6c0b21s9j5qgg0s0gxj7iid2wk5-unordered-containers-0.2.8.0 /nix/store/zsryzwadshszfnkm740b2412v88iqgi4-semigroups-0.18.2 /nix/store/h2c0kz3m83x6fkl2jzkmin8xvkmfgs7s-charset-0.3.7.1 /nix/store/gapj6j0ya5bi9q9dxspda15k50gx8f1v-ansi-terminal-0.6.2.3 /nix/store/l46769n2p6rlh936zrbwznq3zxxa6mjd-ansi-wl-pprint-0.6.7.3 /nix/store/p7zmpgz0sq5pamgrf1xvhvidc3m4cfmk-dhall-1.3.0 /nix/store/938ndd0mqfm148367lwhl6pk5smv5bm0-data-fix-0.0.4 /nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2"),("preferLocalBuild","1"),("propagatedBuildInputs",""),("propagatedNativeBuildInputs",""),("stdenv","/nix/store/685n25b9yc8sds57vljk459ldly1xyhn-stdenv"),("system","x86_64-linux")]) \ No newline at end of file +Derive([("out","/nix/store/w3zbr9zj9mn08hnirn34wsxhry40qi3c-ghc-8.0.2-with-packages","","")],[("/nix/store/r44a3jm3q5rhi75rl1m6jr1vgwpiyw02-hnix-0.3.4.drv",["out"]),("/nix/store/clxg57lhlflbjrk6w3fv51fxjnqkk7q4-transformers-compat-0.5.1.4.drv",["out"]),("/nix/store/z036z61lsrk2gqbwljix0akzhz2bgl8j-semigroups-0.18.2.drv",["out"]),("/nix/store/fyi4gg70v1lgjz03v07flnmjr8x55mqk-async-2.1.1.1.drv",["out"]),("/nix/store/qi0668xlc3q03n74k1wrqri7ss7bvphk-stm-2.4.4.1.drv",["out"]),("/nix/store/nwapw7zf014frf49c0b7y5694jyc38hm-streaming-commons-0.1.17.drv",["out"]),("/nix/store/rqcq6jigs1sj53f8wrbff3s06wzazfqw-comonad-5.0.1.drv",["out"]),("/nix/store/dg6n7519y227s9c867wqi2v40cj41zqy-attoparsec-0.13.1.0.drv",["out"]),("/nix/store/y4ll9c29g76jzycl7zhdmqzxgciyrfr1-case-insensitive-1.2.0.9.drv",["out"]),("/nix/store/a2ar311g8chbi4ila55qzi3dfp9g5zr6-blaze-html-0.8.1.3.drv",["out"]),("/nix/store/2bmxgjskcw4vdmcqrw9pc9yjffsqn3i9-byteable-0.1.1.drv",["out"]),("/nix/store/xbygsq84395vhj7bnh7786i9864jf9i9-ghc-8.0.2.drv",["out"]),("/nix/store/wx9vx1z55bzkzym0lzbgpzd7rrsx9w9b-scientific-0.3.4.12.drv",["out"]),("/nix/store/zvxd18a65gwcg3bz7v1rb0h59w9wwi9d-network-2.6.3.1.drv",["out"]),("/nix/store/y8l0lv08hfi6qnrzd25dxgi4712yjf9f-base-orphans-0.5.4.drv",["out"]),("/nix/store/0w9vy2hmz50j0yhlbj519hnpjbvqhjrj-cookie-0.4.2.1.drv",["out"]),("/nix/store/xp7jayhmiphx0zqxx9dxrk673shhj89l-optparse-applicative-0.13.2.0.drv",["out"]),("/nix/store/xzda3rxckhf0h3lp1hr6wanyig9s9y1p-utf8-string-1.0.1.1.drv",["out"]),("/nix/store/zg5as9jrs5vfa5iw7539vihmwm436g1q-network-uri-2.6.1.0.drv",["out"]),("/nix/store/5x6d3f9krpqlmzhmk71qf7m97g38hba1-base-prelude-1.0.1.1.drv",["out"]),("/nix/store/d1n1p6mdabwkgkc7y6151j37c4kqh1a2-exceptions-0.8.3.drv",["out"]),("/nix/store/m7l8bg4k82snsl759k2mlkjlb8g0352a-foundation-0.0.7.drv",["out"]),("/nix/store/l3wmibr3b1b3a8ql8ypy860209iqbasg-connection-0.2.8.drv",["out"]),("/nix/store/gq055a1910w9q6mbb5kf6p6igzg6b5ai-StateVar-1.1.0.4.drv",["out"]),("/nix/store/pra6ynwnksgks1xxv2l7h48swjq4vb2j-data-default-class-0.1.2.0.drv",["out"]),("/nix/store/as62r0pdaq0q76rxz719xy33vqa7xcal-double-conversion-2.0.2.0.drv",["out"]),("/nix/store/0cyv377kjnhjc9j1pb0m530lczqj4ksm-optparse-generic-1.1.5.drv",["out"]),("/nix/store/75iir4x52007r0fq41kwk5cdfvmi02jp-profunctors-5.2.drv",["out"]),("/nix/store/z8vpk1rwkikc8pg20vyg5kvsdv626ksw-dhall-1.3.0.drv",["out"]),("/nix/store/ckl2x2vkqj82k4b7c5l8p611g6jmfbsz-zlib-0.6.1.2.drv",["out"]),("/nix/store/x50y5qihwsn0lfjhrf1s81b5hgb9w632-bash-4.4-p5.drv",["out"]),("/nix/store/fdq2dn4gal13xl9jbyk8igvaw5f2x9b5-blaze-builder-0.4.0.2.drv",["out"]),("/nix/store/9w2n7jqc9ll78r7xj31ckrqcq6g8g8kf-integer-logarithms-1.0.1.drv",["out"]),("/nix/store/lvm3zp40qfdqr0v9i27z7dqpdwlxprbl-text-1.2.2.1.drv",["out"]),("/nix/store/bwf0a834k4jf5ss2ccribn9w7g2r3j3m-stdenv.drv",["out"]),("/nix/store/1b75igh40c9agy3sfyl5n7av4070swvn-old-locale-1.0.0.7.drv",["out"]),("/nix/store/lnxgjiywc89iaby3g0na1sc4hryvnikq-trifecta-1.6.2.1.drv",["out"]),("/nix/store/mq338r0an8lj00g88c6rpylbnmds7fbx-adjunctions-4.3.drv",["out"]),("/nix/store/qr8wf0b1lqwxwi6ban2k307jy91bj640-reducers-3.12.1.drv",["out"]),("/nix/store/56l353i7v6i7i5vkk2qx4wi4r6p4xll1-void-0.7.2.drv",["out"]),("/nix/store/8p1f0rs49czq74yxlfcimlag9wnbwsc5-http-client-tls-0.3.4.1.drv",["out"]),("/nix/store/nv7frilmipcpylijp492l3hc0s2cmgw6-tls-1.3.10.drv",["out"]),("/nix/store/7ah4kd8kbwsfr350wkr0y4i0h6gm7vc8-base64-bytestring-1.0.0.1.drv",["out"]),("/nix/store/ginljsxbpxli394mc06gvqkmvddhqwlc-x509-store-1.6.2.drv",["out"]),("/nix/store/w6a3c55nhmpcia6cvdg31nqsc7v910lc-ansi-terminal-0.6.2.3.drv",["out"]),("/nix/store/7545pmiaccgvkxjfvl9cm0qk7y1x96wi-reflection-2.1.2.drv",["out"]),("/nix/store/ahypsxsxcczsllax40jnccdg5ilps2lq-http-client-0.5.6.1.drv",["out"]),("/nix/store/6n2kl1fnn66a24ipjm1dxjhhvni1404r-mtl-2.2.1.drv",["out"]),("/nix/store/fr1acpclaljwizrvic520wdf36kmxjwr-blaze-markup-0.7.1.1.drv",["out"]),("/nix/store/vpqjk2wral953nnqnhvp8zbmkbhnyxls-x509-validation-1.6.5.drv",["out"]),("/nix/store/sdx411558r03fdvfi3p6wzfsi701sv4w-system-fileio-0.3.16.3.drv",["out"]),("/nix/store/pz3s86hbxvwr7m4x7cpz5h8z124wgk4x-x509-1.6.5.drv",["out"]),("/nix/store/v0srwl68sz6dirasq53bd3ddjipa1d5b-deriving-compat-0.3.6.drv",["out"]),("/nix/store/61fzrmaxsfc9q4qzsdcrsaqgg05hr6xi-bifunctors-5.4.2.drv",["out"]),("/nix/store/vr8scnq8lxgc0m6k7bqjwi4fg0k55lxn-data-fix-0.0.4.drv",["out"]),("/nix/store/zdx2r8q401h7xcyh7jg0cnp092iwlhmv-contravariant-1.4.drv",["out"]),("/nix/store/n4wyn46xw0nw8a3rhqw47xd4h6bgnn5w-lens-4.15.1.drv",["out"]),("/nix/store/j6zji0jn6cm8b4i0fmakksk1cp54bhn0-asn1-types-0.3.2.drv",["out"]),("/nix/store/pcg29qa8fm9niixbjy0r7bbp3s4jxk62-neat-interpolation-0.3.2.1.drv",["out"]),("/nix/store/5hx7hjjrwqa4zjd9ql224aif86ncj764-hook.drv",["out"]),("/nix/store/lg64zgciix9644hzkfc02rfbq4qgcrf8-memory-0.14.3.drv",["out"]),("/nix/store/f67vqhk71lrab7ncx8fz8bj7iggmm66f-cryptonite-0.21.drv",["out"]),("/nix/store/5rpa05i9i5p3i0a06lhyvgg1nvlwnlfi-unordered-containers-0.2.8.0.drv",["out"]),("/nix/store/20m5alpbwyvyhh43aq3prw07g48apdnj-parsers-0.12.4.drv",["out"]),("/nix/store/f3l740wl94r84fgsiindy88jppcjya6l-text-format-0.3.1.1.drv",["out"]),("/nix/store/7f6ddryzkw9jckayqs1gdz18njrqd0fq-random-1.1.drv",["out"]),("/nix/store/vwhic7ibwkzqk65mqicb29d5qz06gkns-socks-0.5.5.drv",["out"]),("/nix/store/wld7wjy6lws02rky68mpg0x591wv0j6v-pem-0.2.2.drv",["out"]),("/nix/store/43hyjsydndk7vsdjs94why36s8isn6fw-kan-extensions-5.0.1.drv",["out"]),("/nix/store/ql8bpbnl7x7ybn3rnsknpkpwvlz7s2nz-distributive-0.5.2.drv",["out"]),("/nix/store/s1ymda8d763cn5gq4cw107h19xs1ddz0-ansi-wl-pprint-0.6.7.3.drv",["out"]),("/nix/store/3fji5p4x9j0cb3q3lp8amrj0qak9d471-asn1-encoding-0.9.5.drv",["out"]),("/nix/store/mi1fdfdkc5qc7iq2ry6095ayp9cqn075-x509-system-1.6.4.drv",["out"]),("/nix/store/6qggipw2ra59q6333y25gywllbbcx3p5-hourglass-0.2.10.drv",["out"]),("/nix/store/b67b65arib97rsl4z5iqz03gf24ymvz5-http-types-0.9.1.drv",["out"]),("/nix/store/7d6yxihb828lgs4199f81k17jh8987z6-lndir-1.0.3.drv",["out"]),("/nix/store/pg609c09rfqzyfn8l4hsc1q2xy50w4p8-semigroupoids-5.1.drv",["out"]),("/nix/store/6l4s2nlxc9fq8c3y3j2k2c7af5llx278-hashable-1.2.6.0.drv",["out"]),("/nix/store/5d3v9g9jjqznbpxrlgvcyvmqqz2ffpgc-fingertree-0.1.1.0.drv",["out"]),("/nix/store/ip7nh1r7mj4qwgra27x8i6nyz6yd1ggd-prelude-extras-0.4.0.3.drv",["out"]),("/nix/store/bczn7hbvp39aplp70gvmyijdysvkyspg-primitive-0.6.1.0.drv",["out"]),("/nix/store/x8k0rsb1ig82vdls0dc6jdlny7r04izj-parallel-3.2.1.1.drv",["out"]),("/nix/store/iqd84gv7b8dq5kddxyjimaqqlxjpqdzk-vector-0.11.0.0.drv",["out"]),("/nix/store/1g2qxhbpk7qjyz8qbami29bn7qmnmgpk-tagged-0.8.5.drv",["out"]),("/nix/store/x2dkgpklc1adq1cgg1k8ykdqv7ghwhzm-system-filepath-0.4.13.4.drv",["out"]),("/nix/store/hhx5xjb6cm5rdkri763669bf6karrnpn-parsec-3.1.11.drv",["out"]),("/nix/store/j24c6d5zv7nim3rkmzzapk6x61lzgizq-charset-0.3.7.1.drv",["out"]),("/nix/store/5c748d8gmrmg2gy4792a0kzp5bjw8sgr-cereal-0.5.4.0.drv",["out"]),("/nix/store/mpql2q0b6a1m2vkb114f9l2s8dhy09zv-asn1-parse-0.9.4.drv",["out"]),("/nix/store/4hkya8j2isw660pj6b0q3by85q2wz1zw-free-4.12.4.drv",["out"]),("/nix/store/wdgbs33iwqadfmlaymw00k6iwnf3as7z-mime-types-0.1.0.7.drv",["out"])],["/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"],"x86_64-linux","/nix/store/fi3mbd2ml4pbgzyasrlnp0wyy6qi48fh-bash-4.4-p5/bin/bash",["-e","/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"],[("allowSubstitutes",""),("buildCommand","mkdir -p $out\nfor i in $paths; do\n /nix/store/lnai0im3lcpb03arxfi0wx1dm7anf4f8-lndir-1.0.3/bin/lndir $i $out\ndone\n. /nix/store/plmya6mkfvq658ba7z6j6n36r5pdbxk5-hook/nix-support/setup-hook\n\n# wrap compiler executables with correct env variables\n\nfor prg in ghc ghci ghc-8.0.2 ghci-8.0.2; do\n if [[ -x \"/nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg\" ]]; then\n rm -f $out/bin/$prg\n makeWrapper /nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg $out/bin/$prg \\\n --add-flags '\"-B$NIX_GHC_LIBDIR\"' \\\n --set \"NIX_GHC\" \"$out/bin/ghc\" \\\n --set \"NIX_GHCPKG\" \"$out/bin/ghc-pkg\" \\\n --set \"NIX_GHC_DOCDIR\" \"$out/share/doc/ghc/html\" \\\n --set \"NIX_GHC_LIBDIR\" \"$out/lib/ghc-8.0.2\" \\\n \n fi\ndone\n\nfor prg in runghc runhaskell; do\n if [[ -x \"/nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg\" ]]; then\n rm -f $out/bin/$prg\n makeWrapper /nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg $out/bin/$prg \\\n --add-flags \"-f $out/bin/ghc\" \\\n --set \"NIX_GHC\" \"$out/bin/ghc\" \\\n --set \"NIX_GHCPKG\" \"$out/bin/ghc-pkg\" \\\n --set \"NIX_GHC_DOCDIR\" \"$out/share/doc/ghc/html\" \\\n --set \"NIX_GHC_LIBDIR\" \"$out/lib/ghc-8.0.2\"\n fi\ndone\n\nfor prg in ghc-pkg ghc-pkg-8.0.2; do\n if [[ -x \"/nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg\" ]]; then\n rm -f $out/bin/$prg\n makeWrapper /nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg $out/bin/$prg --add-flags \"--global-package-db=$out/lib/ghc-8.0.2/package.conf.d\"\n fi\ndone\n$out/bin/ghc-pkg recache\n\n$out/bin/ghc-pkg check\n\n"),("buildInputs",""),("builder","/nix/store/fi3mbd2ml4pbgzyasrlnp0wyy6qi48fh-bash-4.4-p5/bin/bash"),("extraOutputsToInstall","out doc"),("ignoreCollisions",""),("name","ghc-8.0.2-with-packages"),("nativeBuildInputs",""),("out","/nix/store/w3zbr9zj9mn08hnirn34wsxhry40qi3c-ghc-8.0.2-with-packages"),("passAsFile","buildCommand"),("paths","/nix/store/rlsammwp1ib8d3d9qgbppmdhkbdfg3i9-deriving-compat-0.3.6 /nix/store/v2qsqznrik64f46msahvgg7dmaiag18k-hnix-0.3.4 /nix/store/vbkqj8zdckqqiyjh08ykx75fwc90gwg4-optparse-applicative-0.13.2.0 /nix/store/6m7qia8q0rkdkzvmiak38kdscf27malf-optparse-generic-1.1.5 /nix/store/r687llig7vn9x15hhkmfak01ff7082n6-utf8-string-1.0.1.1 /nix/store/j6gvad67dav8fl3vdbqmar84kgmh5gar-reducers-3.12.1 /nix/store/i8wf08764lknc0f9ja12miqvg509jn1k-fingertree-0.1.1.0 /nix/store/301hq4fabrpbi3l47n908gvakkzq1s88-blaze-markup-0.7.1.1 /nix/store/055mhi44s20x5xgxdjr82vmhnyv79pzl-blaze-html-0.8.1.3 /nix/store/vnc1yyig90skcwx3l1xrbp1jqwmmb9xv-trifecta-1.6.2.1 /nix/store/vraffi24marw5sks8b78xrim6c8i1ng6-double-conversion-2.0.2.0 /nix/store/kwdk03p0lyk5lyll1fp7a6z20j17b3sx-text-format-0.3.1.1 /nix/store/zn5hlw3y94sbli4ssygr2w04mpb396zs-system-filepath-0.4.13.4 /nix/store/jn7lbnk0gsirj8kb02an31v8idy7ym3c-system-fileio-0.3.16.3 /nix/store/9frfci9ywf9lc216ci9nwc1yy0qwrn1b-integer-logarithms-1.0.1 /nix/store/rps46jwa7yyab629p27lar094gk8dal2-scientific-0.3.4.12 /nix/store/c4a3ynvnv3kdxgd7ngmnjhka4mvfk8ll-attoparsec-0.13.1.0 /nix/store/kc34l1gpzh65y4gclmv4dgv6agpmagdi-parsers-0.12.4 /nix/store/1kf78yxf3lliagb5rc5din24iq40g96y-base-prelude-1.0.1.1 /nix/store/hi868d12pkzcbzyvp7a7cigc58mp2lmg-neat-interpolation-0.3.2.1 /nix/store/h00jrbdvzj4yfy796j8vq00lkd1gxr6w-primitive-0.6.1.0 /nix/store/vys8qsf317rn8qwy00p80zlywb47lqwz-vector-0.11.0.0 /nix/store/wchch11312m3lxkwl8rad04x02svcs3i-reflection-2.1.2 /nix/store/jj1kfv52mjxp54flz8v5ba64va3hvy22-parallel-3.2.1.1 /nix/store/jwj23y7vfvs14jdrkw1py9q7lm9fyhy4-adjunctions-4.3 /nix/store/px4979la9b98knwv36551zg3p5jb69lw-kan-extensions-5.0.1 /nix/store/2cp1ar0f73jrcn231ai07zpwayy735j2-semigroupoids-5.1 /nix/store/3nkxw5wdadckz28laijrvwdkkfqp07sb-profunctors-5.2 /nix/store/bd3njvy0ahcsqw47vaz5zayhx34hari7-prelude-extras-0.4.0.3 /nix/store/zdp7zqasz1l1wifpngbg6ngq189gbbqh-free-4.12.4 /nix/store/n7c5ynfqc6j570bbyaajqx34c3pvfvph-tagged-0.8.5 /nix/store/xdkhd7mkqj2mmcami8ycmf7j0valwp5h-distributive-0.5.2 /nix/store/9dxba4g9x0xjj21r3vchqnh4rdwbc31b-void-0.7.2 /nix/store/dahah2ivrn4hc5gjygnlvxlad2399zqh-StateVar-1.1.0.4 /nix/store/f2rdi1bx46fs165n1j316k5w90ab6lwy-contravariant-1.4 /nix/store/mgg9rsvhvn4dd4qzv559nn24iqvspjnb-comonad-5.0.1 /nix/store/18n8i570pf4gpszdyc0bki9qxm1p9xd7-bifunctors-5.4.2 /nix/store/d8ys5wq4wrvdjqw0bzv3y23zqprkhjs2-base-orphans-0.5.4 /nix/store/j4hbyhnj4a2z4z4vb1437vk7ha0b287a-lens-4.15.1 /nix/store/ra3jh12mbyz82n4gvj2bam77vl8aabbq-x509-system-1.6.4 /nix/store/ps8915q1047frp891jg1anp85ads0s9b-x509-validation-1.6.5 /nix/store/5vrgrls6l1cdsbbznis39chx8scq2r98-x509-store-1.6.2 /nix/store/7vvg8y8fp0s50qiciq11irfvh31f1q58-pem-0.2.2 /nix/store/myv75wk9s19f8vms2dcy6sl773288zy4-asn1-parse-0.9.4 /nix/store/kwyc1jdz09lazw21qpc96wyamxalcg11-x509-1.6.5 /nix/store/gadc7c6d1lqn0wqk29bhn56is67x0r45-cryptonite-0.21 /nix/store/ix26y5rpidwpgjzrsixz0ff59j1p1swr-foundation-0.0.7 /nix/store/n784p4qh18zx9v8ag3n3ypszq1kifjjr-memory-0.14.3 /nix/store/h3qq6m5ahdb4kw784gcvx2skil8ilks8-hourglass-0.2.10 /nix/store/dn65dl65spk4j0sky2zpdig75c42ycj1-asn1-types-0.3.2 /nix/store/s5jklkk0y6i7d8h3akgsciv1kv2js786-asn1-encoding-0.9.5 /nix/store/g5qjgns5cyz9c5xw4w5s2iji1kbhg47z-tls-1.3.10 /nix/store/iyllk46by75f428pwis9v74jpr1rmk4x-cereal-0.5.4.0 /nix/store/b22wyyl3wdl6kb7gkpk3yxnynk340lya-socks-0.5.5 /nix/store/05r3i8w2n7hbxqyb4w8rina9rldyacd3-byteable-0.1.1 /nix/store/xjbl6w60czyfqlfwwfs5q93by144yr1n-connection-0.2.8 /nix/store/j10yqzk323rvnwgsk3nj7rgmvqlv035a-http-client-tls-0.3.4.1 /nix/store/vf84v2398g55mai2gjh2d9gipwizhhzd-zlib-0.6.1.2 /nix/store/7h7vy3mi603y536dgvxwfglaacxw5ra8-async-2.1.1.1 /nix/store/y6hh2ifv35afw1j5phpzp1y72x532izn-streaming-commons-0.1.17 /nix/store/f5jdarp8djisa1wrv4bv1saimrabcb3f-random-1.1 /nix/store/18vpnmd28bnjib6andw8bx522wcb3zwa-parsec-3.1.11 /nix/store/i3ra66pcpj0v9wq3m00gh9i72br2bki3-network-uri-2.6.1.0 /nix/store/2ck9avbwacfpi16p2ib2shw951mx33pz-network-2.6.3.1 /nix/store/rz0227nv8n8kdrxjg3arya6r2ixxjh4h-mime-types-0.1.0.7 /nix/store/rx71j4kg0l02dginiswnmwswdq9i9msv-http-types-0.9.1 /nix/store/y2ca4scn0n2f9qsmvsiixcnx11793jlf-transformers-compat-0.5.1.4 /nix/store/bzicr83ibzzzbab6cjkb3i95sc8cvxy9-stm-2.4.4.1 /nix/store/qk5pl6r2h0vfkhhwjgrv8x1ldf8dyj5a-mtl-2.2.1 /nix/store/0d6k71ljl108dgq1l7l3pz12bfwv0z4h-exceptions-0.8.3 /nix/store/z5k23ymwjhhpd670a7mcsm1869hlpncf-old-locale-1.0.0.7 /nix/store/k4an783d4j3m48fqhx7gpnizqg2ns38j-data-default-class-0.1.2.0 /nix/store/p5867jsig02zi0ynww9w4916nm0k527s-cookie-0.4.2.1 /nix/store/wy7j42kqlw1sskagmyc1bzb0xv04s2na-case-insensitive-1.2.0.9 /nix/store/j35339b0nk7k3qaq3m75nl3i4x603rqf-blaze-builder-0.4.0.2 /nix/store/33mip0ql9x1jjbhi34kf8izh4ilyf2k0-base64-bytestring-1.0.0.1 /nix/store/29a73kd2jkwvfdcrhysmi5xjr7nysrxf-http-client-0.5.6.1 /nix/store/d2hy666g79qvhmbh520x5jclwvnr1gk2-text-1.2.2.1 /nix/store/2bdzia66lg08d5zngmllcjry2c08m96j-hashable-1.2.6.0 /nix/store/7kdgc6c0b21s9j5qgg0s0gxj7iid2wk5-unordered-containers-0.2.8.0 /nix/store/zsryzwadshszfnkm740b2412v88iqgi4-semigroups-0.18.2 /nix/store/h2c0kz3m83x6fkl2jzkmin8xvkmfgs7s-charset-0.3.7.1 /nix/store/gapj6j0ya5bi9q9dxspda15k50gx8f1v-ansi-terminal-0.6.2.3 /nix/store/l46769n2p6rlh936zrbwznq3zxxa6mjd-ansi-wl-pprint-0.6.7.3 /nix/store/p7zmpgz0sq5pamgrf1xvhvidc3m4cfmk-dhall-1.3.0 /nix/store/938ndd0mqfm148367lwhl6pk5smv5bm0-data-fix-0.0.4 /nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2"),("preferLocalBuild","1"),("propagatedBuildInputs",""),("propagatedNativeBuildInputs",""),("stdenv","/nix/store/685n25b9yc8sds57vljk459ldly1xyhn-stdenv"),("system","x86_64-linux")]) \ No newline at end of file diff --git a/hnix-store-core/hnix-store-core.cabal b/hnix-store-core/hnix-store-core.cabal index 9f30f9f1..8b545410 100644 --- a/hnix-store-core/hnix-store-core.cabal +++ b/hnix-store-core/hnix-store-core.cabal @@ -17,8 +17,6 @@ extra-doc-files: CHANGELOG.md extra-source-files: README.md - , tests/samples/example0.drv - , tests/samples/example1.drv common commons ghc-options: -Wall diff --git a/hnix-store-core/tests/samples/example0.actual b/hnix-store-core/tests/samples/example0.actual deleted file mode 100644 index 68db5764..00000000 --- a/hnix-store-core/tests/samples/example0.actual +++ /dev/null @@ -1 +0,0 @@ -Derive([("devdoc","/nix/store/15x9ii8c3n5wb5lg80cm8x0yk6zy7rha-perl-MIME-Types-2.13-devdoc","",""),("out","/nix/store/93d75ghjyibmbxgfzwhh4b5zwsxzs44w-perl-MIME-Types-2.13","","")],[("/nix/store/cvdbbvnvg131bz9bwyyk97jpq1crclqr-MIME-Types-2.13.tar.gz.drv",["out"]),("/nix/store/p5g31bc5x92awghx9dlm065d7j773l0r-stdenv.drv",["out"]),("/nix/store/x50y5qihwsn0lfjhrf1s81b5hgb9w632-bash-4.4-p5.drv",["out"]),("/nix/store/57h2hjsdkdiwbzilcjqkn46138n1xb4a-perl-5.22.3.drv",["out"])],["/nix/store/cdips4lakfk1qbf1x68fq18wnn3r5r14-builder.sh"],"x86_64-linux","/nix/store/fi3mbd2ml4pbgzyasrlnp0wyy6qi48fh-bash-4.4-p5/bin/bash",["-e","/nix/store/cdips4lakfk1qbf1x68fq18wnn3r5r14-builder.sh"],[("AUTOMATED_TESTING","1"),("PERL_AUTOINSTALL","--skipdeps"),("buildInputs",""),("builder","/nix/store/fi3mbd2ml4pbgzyasrlnp0wyy6qi48fh-bash-4.4-p5/bin/bash"),("checkTarget","test"),("devdoc","/nix/store/15x9ii8c3n5wb5lg80cm8x0yk6zy7rha-perl-MIME-Types-2.13-devdoc"),("doCheck","1"),("installTargets","pure_install"),("name","perl-MIME-Types-2.13"),("nativeBuildInputs","/nix/store/nsa311yg8h93wfaacjk16c96a98bs09f-perl-5.22.3"),("out","/nix/store/93d75ghjyibmbxgfzwhh4b5zwsxzs44w-perl-MIME-Types-2.13"),("outputs","out devdoc"),("propagatedBuildInputs",""),("propagatedNativeBuildInputs",""),("src","/nix/store/5smhymz7viq8p47mc3jgyvqd003ab732-MIME-Types-2.13.tar.gz"),("stdenv","/nix/store/s3rlr45jzlzx0d6k2azlpxa5zwzr7xyy-stdenv"),("system","x86_64-linux")]) \ No newline at end of file diff --git a/hnix-store-core/tests/samples/example1.actual b/hnix-store-core/tests/samples/example1.actual deleted file mode 100644 index 1530d8d3..00000000 --- a/hnix-store-core/tests/samples/example1.actual +++ /dev/null @@ -1 +0,0 @@ -Derive([("out","/nix/store/w3zbr9zj9mn08hnirn34wsxhry40qi3c-ghc-8.0.2-with-packages","","")],[("/nix/store/r44a3jm3q5rhi75rl1m6jr1vgwpiyw02-hnix-0.3.4.drv",["out"]),("/nix/store/clxg57lhlflbjrk6w3fv51fxjnqkk7q4-transformers-compat-0.5.1.4.drv",["out"]),("/nix/store/z036z61lsrk2gqbwljix0akzhz2bgl8j-semigroups-0.18.2.drv",["out"]),("/nix/store/fyi4gg70v1lgjz03v07flnmjr8x55mqk-async-2.1.1.1.drv",["out"]),("/nix/store/qi0668xlc3q03n74k1wrqri7ss7bvphk-stm-2.4.4.1.drv",["out"]),("/nix/store/nwapw7zf014frf49c0b7y5694jyc38hm-streaming-commons-0.1.17.drv",["out"]),("/nix/store/rqcq6jigs1sj53f8wrbff3s06wzazfqw-comonad-5.0.1.drv",["out"]),("/nix/store/dg6n7519y227s9c867wqi2v40cj41zqy-attoparsec-0.13.1.0.drv",["out"]),("/nix/store/y4ll9c29g76jzycl7zhdmqzxgciyrfr1-case-insensitive-1.2.0.9.drv",["out"]),("/nix/store/a2ar311g8chbi4ila55qzi3dfp9g5zr6-blaze-html-0.8.1.3.drv",["out"]),("/nix/store/2bmxgjskcw4vdmcqrw9pc9yjffsqn3i9-byteable-0.1.1.drv",["out"]),("/nix/store/xbygsq84395vhj7bnh7786i9864jf9i9-ghc-8.0.2.drv",["out"]),("/nix/store/wx9vx1z55bzkzym0lzbgpzd7rrsx9w9b-scientific-0.3.4.12.drv",["out"]),("/nix/store/zvxd18a65gwcg3bz7v1rb0h59w9wwi9d-network-2.6.3.1.drv",["out"]),("/nix/store/y8l0lv08hfi6qnrzd25dxgi4712yjf9f-base-orphans-0.5.4.drv",["out"]),("/nix/store/0w9vy2hmz50j0yhlbj519hnpjbvqhjrj-cookie-0.4.2.1.drv",["out"]),("/nix/store/xp7jayhmiphx0zqxx9dxrk673shhj89l-optparse-applicative-0.13.2.0.drv",["out"]),("/nix/store/xzda3rxckhf0h3lp1hr6wanyig9s9y1p-utf8-string-1.0.1.1.drv",["out"]),("/nix/store/zg5as9jrs5vfa5iw7539vihmwm436g1q-network-uri-2.6.1.0.drv",["out"]),("/nix/store/5x6d3f9krpqlmzhmk71qf7m97g38hba1-base-prelude-1.0.1.1.drv",["out"]),("/nix/store/d1n1p6mdabwkgkc7y6151j37c4kqh1a2-exceptions-0.8.3.drv",["out"]),("/nix/store/m7l8bg4k82snsl759k2mlkjlb8g0352a-foundation-0.0.7.drv",["out"]),("/nix/store/l3wmibr3b1b3a8ql8ypy860209iqbasg-connection-0.2.8.drv",["out"]),("/nix/store/gq055a1910w9q6mbb5kf6p6igzg6b5ai-StateVar-1.1.0.4.drv",["out"]),("/nix/store/pra6ynwnksgks1xxv2l7h48swjq4vb2j-data-default-class-0.1.2.0.drv",["out"]),("/nix/store/as62r0pdaq0q76rxz719xy33vqa7xcal-double-conversion-2.0.2.0.drv",["out"]),("/nix/store/0cyv377kjnhjc9j1pb0m530lczqj4ksm-optparse-generic-1.1.5.drv",["out"]),("/nix/store/75iir4x52007r0fq41kwk5cdfvmi02jp-profunctors-5.2.drv",["out"]),("/nix/store/z8vpk1rwkikc8pg20vyg5kvsdv626ksw-dhall-1.3.0.drv",["out"]),("/nix/store/ckl2x2vkqj82k4b7c5l8p611g6jmfbsz-zlib-0.6.1.2.drv",["out"]),("/nix/store/x50y5qihwsn0lfjhrf1s81b5hgb9w632-bash-4.4-p5.drv",["out"]),("/nix/store/fdq2dn4gal13xl9jbyk8igvaw5f2x9b5-blaze-builder-0.4.0.2.drv",["out"]),("/nix/store/9w2n7jqc9ll78r7xj31ckrqcq6g8g8kf-integer-logarithms-1.0.1.drv",["out"]),("/nix/store/lvm3zp40qfdqr0v9i27z7dqpdwlxprbl-text-1.2.2.1.drv",["out"]),("/nix/store/bwf0a834k4jf5ss2ccribn9w7g2r3j3m-stdenv.drv",["out"]),("/nix/store/1b75igh40c9agy3sfyl5n7av4070swvn-old-locale-1.0.0.7.drv",["out"]),("/nix/store/lnxgjiywc89iaby3g0na1sc4hryvnikq-trifecta-1.6.2.1.drv",["out"]),("/nix/store/mq338r0an8lj00g88c6rpylbnmds7fbx-adjunctions-4.3.drv",["out"]),("/nix/store/qr8wf0b1lqwxwi6ban2k307jy91bj640-reducers-3.12.1.drv",["out"]),("/nix/store/56l353i7v6i7i5vkk2qx4wi4r6p4xll1-void-0.7.2.drv",["out"]),("/nix/store/8p1f0rs49czq74yxlfcimlag9wnbwsc5-http-client-tls-0.3.4.1.drv",["out"]),("/nix/store/nv7frilmipcpylijp492l3hc0s2cmgw6-tls-1.3.10.drv",["out"]),("/nix/store/7ah4kd8kbwsfr350wkr0y4i0h6gm7vc8-base64-bytestring-1.0.0.1.drv",["out"]),("/nix/store/ginljsxbpxli394mc06gvqkmvddhqwlc-x509-store-1.6.2.drv",["out"]),("/nix/store/w6a3c55nhmpcia6cvdg31nqsc7v910lc-ansi-terminal-0.6.2.3.drv",["out"]),("/nix/store/7545pmiaccgvkxjfvl9cm0qk7y1x96wi-reflection-2.1.2.drv",["out"]),("/nix/store/ahypsxsxcczsllax40jnccdg5ilps2lq-http-client-0.5.6.1.drv",["out"]),("/nix/store/6n2kl1fnn66a24ipjm1dxjhhvni1404r-mtl-2.2.1.drv",["out"]),("/nix/store/fr1acpclaljwizrvic520wdf36kmxjwr-blaze-markup-0.7.1.1.drv",["out"]),("/nix/store/vpqjk2wral953nnqnhvp8zbmkbhnyxls-x509-validation-1.6.5.drv",["out"]),("/nix/store/sdx411558r03fdvfi3p6wzfsi701sv4w-system-fileio-0.3.16.3.drv",["out"]),("/nix/store/pz3s86hbxvwr7m4x7cpz5h8z124wgk4x-x509-1.6.5.drv",["out"]),("/nix/store/v0srwl68sz6dirasq53bd3ddjipa1d5b-deriving-compat-0.3.6.drv",["out"]),("/nix/store/61fzrmaxsfc9q4qzsdcrsaqgg05hr6xi-bifunctors-5.4.2.drv",["out"]),("/nix/store/vr8scnq8lxgc0m6k7bqjwi4fg0k55lxn-data-fix-0.0.4.drv",["out"]),("/nix/store/zdx2r8q401h7xcyh7jg0cnp092iwlhmv-contravariant-1.4.drv",["out"]),("/nix/store/n4wyn46xw0nw8a3rhqw47xd4h6bgnn5w-lens-4.15.1.drv",["out"]),("/nix/store/j6zji0jn6cm8b4i0fmakksk1cp54bhn0-asn1-types-0.3.2.drv",["out"]),("/nix/store/pcg29qa8fm9niixbjy0r7bbp3s4jxk62-neat-interpolation-0.3.2.1.drv",["out"]),("/nix/store/5hx7hjjrwqa4zjd9ql224aif86ncj764-hook.drv",["out"]),("/nix/store/lg64zgciix9644hzkfc02rfbq4qgcrf8-memory-0.14.3.drv",["out"]),("/nix/store/f67vqhk71lrab7ncx8fz8bj7iggmm66f-cryptonite-0.21.drv",["out"]),("/nix/store/5rpa05i9i5p3i0a06lhyvgg1nvlwnlfi-unordered-containers-0.2.8.0.drv",["out"]),("/nix/store/20m5alpbwyvyhh43aq3prw07g48apdnj-parsers-0.12.4.drv",["out"]),("/nix/store/f3l740wl94r84fgsiindy88jppcjya6l-text-format-0.3.1.1.drv",["out"]),("/nix/store/7f6ddryzkw9jckayqs1gdz18njrqd0fq-random-1.1.drv",["out"]),("/nix/store/vwhic7ibwkzqk65mqicb29d5qz06gkns-socks-0.5.5.drv",["out"]),("/nix/store/wld7wjy6lws02rky68mpg0x591wv0j6v-pem-0.2.2.drv",["out"]),("/nix/store/43hyjsydndk7vsdjs94why36s8isn6fw-kan-extensions-5.0.1.drv",["out"]),("/nix/store/ql8bpbnl7x7ybn3rnsknpkpwvlz7s2nz-distributive-0.5.2.drv",["out"]),("/nix/store/s1ymda8d763cn5gq4cw107h19xs1ddz0-ansi-wl-pprint-0.6.7.3.drv",["out"]),("/nix/store/3fji5p4x9j0cb3q3lp8amrj0qak9d471-asn1-encoding-0.9.5.drv",["out"]),("/nix/store/mi1fdfdkc5qc7iq2ry6095ayp9cqn075-x509-system-1.6.4.drv",["out"]),("/nix/store/6qggipw2ra59q6333y25gywllbbcx3p5-hourglass-0.2.10.drv",["out"]),("/nix/store/b67b65arib97rsl4z5iqz03gf24ymvz5-http-types-0.9.1.drv",["out"]),("/nix/store/7d6yxihb828lgs4199f81k17jh8987z6-lndir-1.0.3.drv",["out"]),("/nix/store/pg609c09rfqzyfn8l4hsc1q2xy50w4p8-semigroupoids-5.1.drv",["out"]),("/nix/store/6l4s2nlxc9fq8c3y3j2k2c7af5llx278-hashable-1.2.6.0.drv",["out"]),("/nix/store/5d3v9g9jjqznbpxrlgvcyvmqqz2ffpgc-fingertree-0.1.1.0.drv",["out"]),("/nix/store/ip7nh1r7mj4qwgra27x8i6nyz6yd1ggd-prelude-extras-0.4.0.3.drv",["out"]),("/nix/store/bczn7hbvp39aplp70gvmyijdysvkyspg-primitive-0.6.1.0.drv",["out"]),("/nix/store/x8k0rsb1ig82vdls0dc6jdlny7r04izj-parallel-3.2.1.1.drv",["out"]),("/nix/store/iqd84gv7b8dq5kddxyjimaqqlxjpqdzk-vector-0.11.0.0.drv",["out"]),("/nix/store/1g2qxhbpk7qjyz8qbami29bn7qmnmgpk-tagged-0.8.5.drv",["out"]),("/nix/store/x2dkgpklc1adq1cgg1k8ykdqv7ghwhzm-system-filepath-0.4.13.4.drv",["out"]),("/nix/store/hhx5xjb6cm5rdkri763669bf6karrnpn-parsec-3.1.11.drv",["out"]),("/nix/store/j24c6d5zv7nim3rkmzzapk6x61lzgizq-charset-0.3.7.1.drv",["out"]),("/nix/store/5c748d8gmrmg2gy4792a0kzp5bjw8sgr-cereal-0.5.4.0.drv",["out"]),("/nix/store/mpql2q0b6a1m2vkb114f9l2s8dhy09zv-asn1-parse-0.9.4.drv",["out"]),("/nix/store/4hkya8j2isw660pj6b0q3by85q2wz1zw-free-4.12.4.drv",["out"]),("/nix/store/wdgbs33iwqadfmlaymw00k6iwnf3as7z-mime-types-0.1.0.7.drv",["out"])],["/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"],"x86_64-linux","/nix/store/fi3mbd2ml4pbgzyasrlnp0wyy6qi48fh-bash-4.4-p5/bin/bash",["-e","/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"],[("allowSubstitutes",""),("buildCommand","mkdir -p $out\nfor i in $paths; do\n /nix/store/lnai0im3lcpb03arxfi0wx1dm7anf4f8-lndir-1.0.3/bin/lndir $i $out\ndone\n. /nix/store/plmya6mkfvq658ba7z6j6n36r5pdbxk5-hook/nix-support/setup-hook\n\n# wrap compiler executables with correct env variables\n\nfor prg in ghc ghci ghc-8.0.2 ghci-8.0.2; do\n if [[ -x \"/nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg\" ]]; then\n rm -f $out/bin/$prg\n makeWrapper /nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg $out/bin/$prg \\\n --add-flags '\"-B$NIX_GHC_LIBDIR\"' \\\n --set \"NIX_GHC\" \"$out/bin/ghc\" \\\n --set \"NIX_GHCPKG\" \"$out/bin/ghc-pkg\" \\\n --set \"NIX_GHC_DOCDIR\" \"$out/share/doc/ghc/html\" \\\n --set \"NIX_GHC_LIBDIR\" \"$out/lib/ghc-8.0.2\" \\\n \n fi\ndone\n\nfor prg in runghc runhaskell; do\n if [[ -x \"/nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg\" ]]; then\n rm -f $out/bin/$prg\n makeWrapper /nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg $out/bin/$prg \\\n --add-flags \"-f $out/bin/ghc\" \\\n --set \"NIX_GHC\" \"$out/bin/ghc\" \\\n --set \"NIX_GHCPKG\" \"$out/bin/ghc-pkg\" \\\n --set \"NIX_GHC_DOCDIR\" \"$out/share/doc/ghc/html\" \\\n --set \"NIX_GHC_LIBDIR\" \"$out/lib/ghc-8.0.2\"\n fi\ndone\n\nfor prg in ghc-pkg ghc-pkg-8.0.2; do\n if [[ -x \"/nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg\" ]]; then\n rm -f $out/bin/$prg\n makeWrapper /nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2/bin/$prg $out/bin/$prg --add-flags \"--global-package-db=$out/lib/ghc-8.0.2/package.conf.d\"\n fi\ndone\n$out/bin/ghc-pkg recache\n\n$out/bin/ghc-pkg check\n\n"),("buildInputs",""),("builder","/nix/store/fi3mbd2ml4pbgzyasrlnp0wyy6qi48fh-bash-4.4-p5/bin/bash"),("extraOutputsToInstall","out doc"),("ignoreCollisions",""),("name","ghc-8.0.2-with-packages"),("nativeBuildInputs",""),("out","/nix/store/w3zbr9zj9mn08hnirn34wsxhry40qi3c-ghc-8.0.2-with-packages"),("passAsFile","buildCommand"),("paths","/nix/store/rlsammwp1ib8d3d9qgbppmdhkbdfg3i9-deriving-compat-0.3.6 /nix/store/v2qsqznrik64f46msahvgg7dmaiag18k-hnix-0.3.4 /nix/store/vbkqj8zdckqqiyjh08ykx75fwc90gwg4-optparse-applicative-0.13.2.0 /nix/store/6m7qia8q0rkdkzvmiak38kdscf27malf-optparse-generic-1.1.5 /nix/store/r687llig7vn9x15hhkmfak01ff7082n6-utf8-string-1.0.1.1 /nix/store/j6gvad67dav8fl3vdbqmar84kgmh5gar-reducers-3.12.1 /nix/store/i8wf08764lknc0f9ja12miqvg509jn1k-fingertree-0.1.1.0 /nix/store/301hq4fabrpbi3l47n908gvakkzq1s88-blaze-markup-0.7.1.1 /nix/store/055mhi44s20x5xgxdjr82vmhnyv79pzl-blaze-html-0.8.1.3 /nix/store/vnc1yyig90skcwx3l1xrbp1jqwmmb9xv-trifecta-1.6.2.1 /nix/store/vraffi24marw5sks8b78xrim6c8i1ng6-double-conversion-2.0.2.0 /nix/store/kwdk03p0lyk5lyll1fp7a6z20j17b3sx-text-format-0.3.1.1 /nix/store/zn5hlw3y94sbli4ssygr2w04mpb396zs-system-filepath-0.4.13.4 /nix/store/jn7lbnk0gsirj8kb02an31v8idy7ym3c-system-fileio-0.3.16.3 /nix/store/9frfci9ywf9lc216ci9nwc1yy0qwrn1b-integer-logarithms-1.0.1 /nix/store/rps46jwa7yyab629p27lar094gk8dal2-scientific-0.3.4.12 /nix/store/c4a3ynvnv3kdxgd7ngmnjhka4mvfk8ll-attoparsec-0.13.1.0 /nix/store/kc34l1gpzh65y4gclmv4dgv6agpmagdi-parsers-0.12.4 /nix/store/1kf78yxf3lliagb5rc5din24iq40g96y-base-prelude-1.0.1.1 /nix/store/hi868d12pkzcbzyvp7a7cigc58mp2lmg-neat-interpolation-0.3.2.1 /nix/store/h00jrbdvzj4yfy796j8vq00lkd1gxr6w-primitive-0.6.1.0 /nix/store/vys8qsf317rn8qwy00p80zlywb47lqwz-vector-0.11.0.0 /nix/store/wchch11312m3lxkwl8rad04x02svcs3i-reflection-2.1.2 /nix/store/jj1kfv52mjxp54flz8v5ba64va3hvy22-parallel-3.2.1.1 /nix/store/jwj23y7vfvs14jdrkw1py9q7lm9fyhy4-adjunctions-4.3 /nix/store/px4979la9b98knwv36551zg3p5jb69lw-kan-extensions-5.0.1 /nix/store/2cp1ar0f73jrcn231ai07zpwayy735j2-semigroupoids-5.1 /nix/store/3nkxw5wdadckz28laijrvwdkkfqp07sb-profunctors-5.2 /nix/store/bd3njvy0ahcsqw47vaz5zayhx34hari7-prelude-extras-0.4.0.3 /nix/store/zdp7zqasz1l1wifpngbg6ngq189gbbqh-free-4.12.4 /nix/store/n7c5ynfqc6j570bbyaajqx34c3pvfvph-tagged-0.8.5 /nix/store/xdkhd7mkqj2mmcami8ycmf7j0valwp5h-distributive-0.5.2 /nix/store/9dxba4g9x0xjj21r3vchqnh4rdwbc31b-void-0.7.2 /nix/store/dahah2ivrn4hc5gjygnlvxlad2399zqh-StateVar-1.1.0.4 /nix/store/f2rdi1bx46fs165n1j316k5w90ab6lwy-contravariant-1.4 /nix/store/mgg9rsvhvn4dd4qzv559nn24iqvspjnb-comonad-5.0.1 /nix/store/18n8i570pf4gpszdyc0bki9qxm1p9xd7-bifunctors-5.4.2 /nix/store/d8ys5wq4wrvdjqw0bzv3y23zqprkhjs2-base-orphans-0.5.4 /nix/store/j4hbyhnj4a2z4z4vb1437vk7ha0b287a-lens-4.15.1 /nix/store/ra3jh12mbyz82n4gvj2bam77vl8aabbq-x509-system-1.6.4 /nix/store/ps8915q1047frp891jg1anp85ads0s9b-x509-validation-1.6.5 /nix/store/5vrgrls6l1cdsbbznis39chx8scq2r98-x509-store-1.6.2 /nix/store/7vvg8y8fp0s50qiciq11irfvh31f1q58-pem-0.2.2 /nix/store/myv75wk9s19f8vms2dcy6sl773288zy4-asn1-parse-0.9.4 /nix/store/kwyc1jdz09lazw21qpc96wyamxalcg11-x509-1.6.5 /nix/store/gadc7c6d1lqn0wqk29bhn56is67x0r45-cryptonite-0.21 /nix/store/ix26y5rpidwpgjzrsixz0ff59j1p1swr-foundation-0.0.7 /nix/store/n784p4qh18zx9v8ag3n3ypszq1kifjjr-memory-0.14.3 /nix/store/h3qq6m5ahdb4kw784gcvx2skil8ilks8-hourglass-0.2.10 /nix/store/dn65dl65spk4j0sky2zpdig75c42ycj1-asn1-types-0.3.2 /nix/store/s5jklkk0y6i7d8h3akgsciv1kv2js786-asn1-encoding-0.9.5 /nix/store/g5qjgns5cyz9c5xw4w5s2iji1kbhg47z-tls-1.3.10 /nix/store/iyllk46by75f428pwis9v74jpr1rmk4x-cereal-0.5.4.0 /nix/store/b22wyyl3wdl6kb7gkpk3yxnynk340lya-socks-0.5.5 /nix/store/05r3i8w2n7hbxqyb4w8rina9rldyacd3-byteable-0.1.1 /nix/store/xjbl6w60czyfqlfwwfs5q93by144yr1n-connection-0.2.8 /nix/store/j10yqzk323rvnwgsk3nj7rgmvqlv035a-http-client-tls-0.3.4.1 /nix/store/vf84v2398g55mai2gjh2d9gipwizhhzd-zlib-0.6.1.2 /nix/store/7h7vy3mi603y536dgvxwfglaacxw5ra8-async-2.1.1.1 /nix/store/y6hh2ifv35afw1j5phpzp1y72x532izn-streaming-commons-0.1.17 /nix/store/f5jdarp8djisa1wrv4bv1saimrabcb3f-random-1.1 /nix/store/18vpnmd28bnjib6andw8bx522wcb3zwa-parsec-3.1.11 /nix/store/i3ra66pcpj0v9wq3m00gh9i72br2bki3-network-uri-2.6.1.0 /nix/store/2ck9avbwacfpi16p2ib2shw951mx33pz-network-2.6.3.1 /nix/store/rz0227nv8n8kdrxjg3arya6r2ixxjh4h-mime-types-0.1.0.7 /nix/store/rx71j4kg0l02dginiswnmwswdq9i9msv-http-types-0.9.1 /nix/store/y2ca4scn0n2f9qsmvsiixcnx11793jlf-transformers-compat-0.5.1.4 /nix/store/bzicr83ibzzzbab6cjkb3i95sc8cvxy9-stm-2.4.4.1 /nix/store/qk5pl6r2h0vfkhhwjgrv8x1ldf8dyj5a-mtl-2.2.1 /nix/store/0d6k71ljl108dgq1l7l3pz12bfwv0z4h-exceptions-0.8.3 /nix/store/z5k23ymwjhhpd670a7mcsm1869hlpncf-old-locale-1.0.0.7 /nix/store/k4an783d4j3m48fqhx7gpnizqg2ns38j-data-default-class-0.1.2.0 /nix/store/p5867jsig02zi0ynww9w4916nm0k527s-cookie-0.4.2.1 /nix/store/wy7j42kqlw1sskagmyc1bzb0xv04s2na-case-insensitive-1.2.0.9 /nix/store/j35339b0nk7k3qaq3m75nl3i4x603rqf-blaze-builder-0.4.0.2 /nix/store/33mip0ql9x1jjbhi34kf8izh4ilyf2k0-base64-bytestring-1.0.0.1 /nix/store/29a73kd2jkwvfdcrhysmi5xjr7nysrxf-http-client-0.5.6.1 /nix/store/d2hy666g79qvhmbh520x5jclwvnr1gk2-text-1.2.2.1 /nix/store/2bdzia66lg08d5zngmllcjry2c08m96j-hashable-1.2.6.0 /nix/store/7kdgc6c0b21s9j5qgg0s0gxj7iid2wk5-unordered-containers-0.2.8.0 /nix/store/zsryzwadshszfnkm740b2412v88iqgi4-semigroups-0.18.2 /nix/store/h2c0kz3m83x6fkl2jzkmin8xvkmfgs7s-charset-0.3.7.1 /nix/store/gapj6j0ya5bi9q9dxspda15k50gx8f1v-ansi-terminal-0.6.2.3 /nix/store/l46769n2p6rlh936zrbwznq3zxxa6mjd-ansi-wl-pprint-0.6.7.3 /nix/store/p7zmpgz0sq5pamgrf1xvhvidc3m4cfmk-dhall-1.3.0 /nix/store/938ndd0mqfm148367lwhl6pk5smv5bm0-data-fix-0.0.4 /nix/store/s0hpng652hsn40jy4kjdh1x0jm86dx9l-ghc-8.0.2"),("preferLocalBuild","1"),("propagatedBuildInputs",""),("propagatedNativeBuildInputs",""),("stdenv","/nix/store/685n25b9yc8sds57vljk459ldly1xyhn-stdenv"),("system","x86_64-linux")]) \ No newline at end of file From 7b274436882cd833aefa81bdbdc3f8de673d621a Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 1 Jan 2025 20:03:50 -0500 Subject: [PATCH 54/58] Better errors for quick check test --- hnix-store-aterm/tests/Property.hs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/hnix-store-aterm/tests/Property.hs b/hnix-store-aterm/tests/Property.hs index 3b79a98f..87e6f2ca 100644 --- a/hnix-store-aterm/tests/Property.hs +++ b/hnix-store-aterm/tests/Property.hs @@ -16,6 +16,7 @@ import Data.Attoparsec.Text.Lazy qualified import Data.Text.Lazy.Builder qualified import Test.QuickCheck (Arbitrary(..)) import Test.QuickCheck qualified +import Test.QuickCheck.Property (failed, succeeded, Result(..)) import Test.QuickCheck.Arbitrary.Generic (GenericArbitrary(..)) import System.Nix.StorePath @@ -35,8 +36,11 @@ property -> Derivation' TraditionalDerivationInputs DerivationOutput - -> Bool -property storeDir derivation0 = either == Right derivation0 + -> Result +property storeDir derivation0 = + if either == expected + then succeeded + else failed { reason = unlines ["", show either, show expected] } where builder = System.Nix.Derivation.ATerm.buildDerivation storeDir derivation0 @@ -47,8 +51,12 @@ property storeDir derivation0 = either == Right derivation0 (System.Nix.Derivation.ATerm.parseDerivation storeDir (name derivation0)) text + either, expected :: Either String (Derivation' TraditionalDerivationInputs DerivationOutput) + either = Data.Attoparsec.Text.Lazy.eitherResult result + expected = Right derivation0 + main :: IO () main = Test.QuickCheck.quickCheck property From 50a1cd6bb3d499963f6b580f47e9a353dc21516a Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 1 Jan 2025 21:10:44 -0500 Subject: [PATCH 55/58] Get `hnix-store-aterm` tests passing! --- .../System/Nix/Derivation/ATerm/Builder.hs | 12 +++- .../src/System/Nix/Derivation/Traditional.hs | 10 +++- hnix-store-core/src/System/Nix/OutputName.hs | 9 +-- .../src/System/Nix/Arbitrary/Derivation.hs | 56 +++++++++++++------ .../src/System/Nix/Arbitrary/OutputName.hs | 17 ++---- 5 files changed, 68 insertions(+), 36 deletions(-) diff --git a/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Builder.hs b/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Builder.hs index 95fad44d..bc66c204 100644 --- a/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Builder.hs +++ b/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Builder.hs @@ -133,7 +133,17 @@ vectorOf :: (a -> Builder) -> Vector a -> Builder vectorOf element xs = listOf element (Data.Vector.toList xs) string :: Text -> Builder -string = Data.Text.Lazy.Builder.fromText . Data.Text.pack . show +string = + Data.Text.Lazy.Builder.fromText + . (\input -> Data.Text.concat ["\"", Data.Text.concatMap escapeChar input, "\""]) + where + escapeChar :: Char -> Text + escapeChar '\"' = "\\\"" + escapeChar '\\' = "\\\\" + escapeChar '\n' = "\\n" + escapeChar '\r' = "\\r" + escapeChar '\t' = "\\t" + escapeChar c = Data.Text.singleton c buildOutputName :: OutputName -> Builder buildOutputName = string . unStorePathName . unOutputName diff --git a/hnix-store-aterm/src/System/Nix/Derivation/Traditional.hs b/hnix-store-aterm/src/System/Nix/Derivation/Traditional.hs index b468478c..8367371d 100644 --- a/hnix-store-aterm/src/System/Nix/Derivation/Traditional.hs +++ b/hnix-store-aterm/src/System/Nix/Derivation/Traditional.hs @@ -74,7 +74,9 @@ parseRawDerivationOutput storeDir drvName outputName (RawDerivationOutput {..}) hash' <- either fail pure $ has @NamedAlgo hashAlgo $ decodeDigestWith NixBase32 hash0 let hash = hashAlgo :=> hash' - let expectedPath = makeFixedOutputPath storeDir method hash mempty $ outputStoreObjectName drvName outputName + fullOutputName <- either (fail . show) pure $ + outputStoreObjectName drvName outputName + let expectedPath = makeFixedOutputPath storeDir method hash mempty fullOutputName when (path /= expectedPath) $ fail "fixed output path does not match info" pure FixedDerivationOutput {..} @@ -97,7 +99,9 @@ renderRawDerivationOutput storeDir drvName outputName = \case } FixedDerivationOutput {..} -> case hash of hashAlgo :=> hash' -> RawDerivationOutput - { rawPath = storePathToText storeDir $ makeFixedOutputPath storeDir method hash mempty $ outputStoreObjectName drvName outputName + { rawPath = storePathToText storeDir $ makeFixedOutputPath storeDir method hash mempty + $ either (error . show) id -- TODO do better + $ outputStoreObjectName drvName outputName , rawMethodHashAlgo = buildMethodHashAlgo method $ Some hashAlgo , rawHash = encodeDigestWith NixBase32 hash' } @@ -120,7 +124,7 @@ splitMethodHashAlgo :: MonadFail m => Text -> m (ContentAddressMethod, Some Hash splitMethodHashAlgo methodHashAlgo = do (method, hashAlgoS) <- case Data.Text.splitOn ":" methodHashAlgo of ["r", hashAlgo] -> pure (ContentAddressMethod_NixArchive, hashAlgo) - ["text", hashAlgo] -> pure (ContentAddressMethod_NixArchive, hashAlgo) + ["text", hashAlgo] -> pure (ContentAddressMethod_Text, hashAlgo) [hashAlgo] -> pure (ContentAddressMethod_Flat, hashAlgo) _ -> fail "invalid number of colons or unknown CA method prefix" hashAlgo <- either fail pure $ textToAlgo hashAlgoS diff --git a/hnix-store-core/src/System/Nix/OutputName.hs b/hnix-store-core/src/System/Nix/OutputName.hs index 6073679e..f25089bf 100644 --- a/hnix-store-core/src/System/Nix/OutputName.hs +++ b/hnix-store-core/src/System/Nix/OutputName.hs @@ -37,11 +37,12 @@ mkOutputName = fmap OutputName . System.Nix.StorePath.mkStorePathName -- | Compute the name of an output (store object) from the output name -- and the derivation name -outputStoreObjectName :: StorePathName -> OutputName -> StorePathName +-- +-- Invalid character errors are not possible, but total length errors are +outputStoreObjectName :: StorePathName -> OutputName -> Either InvalidNameError StorePathName outputStoreObjectName drvName outputName = case outputNameS of - "out" -> drvName - _ -> either (error "impossible, internal error") id $ - System.Nix.StorePath.mkStorePathName $ + "out" -> Right drvName + _ -> System.Nix.StorePath.mkStorePathName $ unStorePathName drvName <> "-" <> outputNameS diff --git a/hnix-store-tests/src/System/Nix/Arbitrary/Derivation.hs b/hnix-store-tests/src/System/Nix/Arbitrary/Derivation.hs index 9c57115f..0a80b7d6 100644 --- a/hnix-store-tests/src/System/Nix/Arbitrary/Derivation.hs +++ b/hnix-store-tests/src/System/Nix/Arbitrary/Derivation.hs @@ -1,35 +1,57 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE GADTs #-} -- due to recent generic-arbitrary {-# OPTIONS_GHC -fconstraint-solver-iterations=0 #-} {-# OPTIONS_GHC -Wno-orphans #-} module System.Nix.Arbitrary.Derivation where +import Data.Dependent.Sum +import Data.Either (isRight) +import Data.Map qualified import Data.Map.Monoidal -import Data.These -import Data.Text (Text) +import Data.Some import Data.Text.Arbitrary () +import Data.These import Data.Vector.Arbitrary () -import System.Nix.Derivation -import System.Nix.StorePath (StorePath) +import Test.QuickCheck.Arbitrary.Generic +import Test.QuickCheck.Gen -import Test.QuickCheck (Arbitrary(..)) -import Test.QuickCheck.Arbitrary.Generic (Arg, GenericArbitrary(..)) +import System.Nix.Derivation +import System.Nix.ContentAddress +import System.Nix.Hash +import System.Nix.OutputName import System.Nix.Arbitrary.ContentAddress () import System.Nix.Arbitrary.Hash () import System.Nix.Arbitrary.StorePath () import System.Nix.Arbitrary.OutputName () -deriving via GenericArbitrary - (Derivation' inputs output) - instance - ( Arbitrary inputs - , Arbitrary output - , Arg (Derivation' inputs output) inputs - , Arg (Derivation' inputs output) output - ) => Arbitrary (Derivation' inputs output) - -deriving via GenericArbitrary DerivationOutput - instance Arbitrary DerivationOutput +instance + ( Arbitrary inputs + , Arbitrary output + , Arg (Derivation' inputs output) inputs + , Arg (Derivation' inputs output) output + ) => Arbitrary (Derivation' inputs output) + where + arbitrary = genericArbitrary `suchThat` \drv -> + -- ensure output path name is not too long + all (\on -> isRight $ outputStoreObjectName (name drv) on) + $ Data.Map.keys (outputs drv) + shrink = genericShrink + +instance Arbitrary DerivationOutput where + arbitrary = genericArbitrary `suchThat` \case + InputAddressedDerivationOutput {} -> True + FixedDerivationOutput {method, hash = hashAlgo :=> _} -> f method hashAlgo + ContentAddressedDerivationOutput {method, hashAlgo = Some hashAlgo } -> f method hashAlgo + where + -- Ensure a valid combination + f = \case + ContentAddressMethod_Text -> \case + HashAlgo_SHA256 -> True + _ -> False + _ -> \_ -> True + shrink = genericShrink deriving via GenericArbitrary DerivationInputs instance Arbitrary DerivationInputs diff --git a/hnix-store-tests/src/System/Nix/Arbitrary/OutputName.hs b/hnix-store-tests/src/System/Nix/Arbitrary/OutputName.hs index 1a1f3b3b..f749ea9d 100644 --- a/hnix-store-tests/src/System/Nix/Arbitrary/OutputName.hs +++ b/hnix-store-tests/src/System/Nix/Arbitrary/OutputName.hs @@ -3,20 +3,15 @@ module System.Nix.Arbitrary.OutputName where import System.Nix.OutputName (OutputName) -import Data.Text qualified import System.Nix.OutputName qualified +import System.Nix.StorePath qualified -import Test.QuickCheck (Arbitrary(arbitrary), choose, elements, vectorOf) +import Test.QuickCheck (Arbitrary(arbitrary)) +import System.Nix.Arbitrary.StorePath () instance Arbitrary OutputName where arbitrary = - either (error . show) id + either (error . show) id . System.Nix.OutputName.mkOutputName - . Data.Text.pack <$> ((:) <$> s1 <*> limited sn) - where - alphanum = ['a' .. 'z'] <> ['A' .. 'Z'] <> ['0' .. '9'] - s1 = elements $ alphanum <> "+-_?=" - sn = elements $ alphanum <> "+-._?=" - limited n = do - k <- choose (0, 210) - vectorOf k n + . System.Nix.StorePath.unStorePathName + <$> arbitrary From 9274e45632c22a89ded822b1987620397e1a88f1 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sun, 19 Jan 2025 02:17:53 -0500 Subject: [PATCH 56/58] Make the main derivation representation better typed --- hnix-store-aterm/bench/Main.hs | 5 +- hnix-store-aterm/hnix-store-aterm.cabal | 1 + hnix-store-aterm/pretty-derivation/Main.hs | 5 +- .../src/System/Nix/Derivation/ATerm.hs | 25 +- .../System/Nix/Derivation/ATerm/Builder.hs | 64 +++-- .../src/System/Nix/Derivation/ATerm/Parser.hs | 61 ++--- .../src/System/Nix/Derivation/Traditional.hs | 147 ++++++---- hnix-store-aterm/tests/Example.hs | 5 +- hnix-store-aterm/tests/Property.hs | 28 +- hnix-store-core/hnix-store-core.cabal | 1 + hnix-store-core/src/System/Nix/Derivation.hs | 255 +++++++++++++++--- hnix-store-remote/hnix-store-remote.cabal | 1 + .../src/System/Nix/Store/Remote/Client.hs | 21 +- .../src/System/Nix/Store/Remote/Serializer.hs | 63 +++-- hnix-store-remote/tests/NixSerializerSpec.hs | 5 +- hnix-store-tests/hnix-store-tests.cabal | 4 + .../src/System/Nix/Arbitrary/Derivation.hs | 98 +++++-- .../src/System/Nix/Arbitrary/Hash.hs | 32 ++- hnix-store-tests/tests/DerivationSpec.hs | 28 +- 19 files changed, 586 insertions(+), 263 deletions(-) diff --git a/hnix-store-aterm/bench/Main.hs b/hnix-store-aterm/bench/Main.hs index 30cdf87c..dae3e228 100644 --- a/hnix-store-aterm/bench/Main.hs +++ b/hnix-store-aterm/bench/Main.hs @@ -22,10 +22,7 @@ benchmarks = bench0 example = Criterion.bench "example" (Criterion.nf parseExample example) - name = either (error . show) id $ mkStorePathName "ghc-8.0.2-with-packages" - parseExample = Data.Attoparsec.Text.Lazy.parse $ - System.Nix.Derivation.ATerm.parseDerivation + System.Nix.Derivation.ATerm.parseTraditionalDerivation (StoreDir "/nix/store") - name diff --git a/hnix-store-aterm/hnix-store-aterm.cabal b/hnix-store-aterm/hnix-store-aterm.cabal index 78a5c137..38bd8921 100644 --- a/hnix-store-aterm/hnix-store-aterm.cabal +++ b/hnix-store-aterm/hnix-store-aterm.cabal @@ -96,6 +96,7 @@ Test-Suite property hnix-store-core , hnix-store-aterm , hnix-store-tests , + containers , generic-arbitrary < 1.1 , QuickCheck < 2.16, text , diff --git a/hnix-store-aterm/pretty-derivation/Main.hs b/hnix-store-aterm/pretty-derivation/Main.hs index f1f7b1a4..259b3489 100644 --- a/hnix-store-aterm/pretty-derivation/Main.hs +++ b/hnix-store-aterm/pretty-derivation/Main.hs @@ -14,9 +14,8 @@ main = do text <- Data.Text.Lazy.IO.getContents case Data.Attoparsec.Text.Lazy.parse - (System.Nix.Derivation.ATerm.parseDerivation - (StoreDir "/nix/store") - (error "todo get name from outputs if needed")) + (System.Nix.Derivation.ATerm.parseTraditionalDerivation + (StoreDir "/nix/store")) text of Fail _ _ err -> fail err diff --git a/hnix-store-aterm/src/System/Nix/Derivation/ATerm.hs b/hnix-store-aterm/src/System/Nix/Derivation/ATerm.hs index 907b6300..d8e7075e 100644 --- a/hnix-store-aterm/src/System/Nix/Derivation/ATerm.hs +++ b/hnix-store-aterm/src/System/Nix/Derivation/ATerm.hs @@ -78,26 +78,27 @@ module System.Nix.Derivation.ATerm ( -- * Types - Derivation - , Derivation'(..) - , DerivationOutput(..) - , DerivationInputs(..) + TraditionalDerivation'(..) + , FreeformDerivationOutput(..) + , FreeformDerivationOutputs + , TraditionalDerivationInputs(..) , DerivedPathMap(..) -- * Parse derivations - , parseDerivation - , parseDerivationWith - , parseDerivationOutput - , parseDerivationInputs + , parseTraditionalDerivation + , parseTraditionalDerivationWith + , parseFreeformDerivationOutput + , parseTraditionalDerivationInputs , textParser -- * Render derivations - , buildDerivation - , buildDerivationWith - , buildDerivationOutput - , buildDerivationInputs + , buildTraditionalDerivation + , buildTraditionalDerivationWith + , buildFreeformDerivationOutput + , buildTraditionalDerivationInputs ) where import System.Nix.Derivation +import System.Nix.Derivation.Traditional import System.Nix.Derivation.ATerm.Builder import System.Nix.Derivation.ATerm.Parser diff --git a/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Builder.hs b/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Builder.hs index bc66c204..8849a91f 100644 --- a/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Builder.hs +++ b/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Builder.hs @@ -6,10 +6,10 @@ module System.Nix.Derivation.ATerm.Builder ( -- * Builder - buildDerivation - , buildDerivationWith - , buildDerivationOutput - , buildDerivationInputs + buildTraditionalDerivation + , buildTraditionalDerivationWith + , buildFreeformDerivationOutput + , buildTraditionalDerivationInputs ) where import Data.Map (Map) @@ -18,8 +18,8 @@ import Data.Text (Text) import Data.Text.Lazy.Builder (Builder) import Data.Vector (Vector) import System.Nix.Derivation - ( Derivation'(..) - , DerivationOutput(..) + ( FreeformDerivationOutput(..) + , FreeformDerivationOutputs ) import System.Nix.Derivation.Traditional import System.Nix.StorePath @@ -32,42 +32,42 @@ import Data.Text.Lazy.Builder qualified import Data.Vector qualified -- | Render a derivation as a `Builder` -buildDerivation +buildTraditionalDerivation :: StoreDir - -> Derivation' TraditionalDerivationInputs DerivationOutput + -> TraditionalDerivation' TraditionalDerivationInputs FreeformDerivationOutputs -> Builder -buildDerivation sd = - buildDerivationWith - (buildDerivationInputs sd) - (buildDerivationOutput sd) +buildTraditionalDerivation sd = + buildTraditionalDerivationWith + (buildTraditionalDerivationInputs sd) + (\_ -> buildFreeformDerivationOutput sd) -- | Render a derivation as a `Builder` using custom -- renderer for storePaths, texts, outputNames and derivation inputs/outputs -buildDerivationWith +buildTraditionalDerivationWith :: (drvInputs -> Builder) - -> (StorePathName -> OutputName -> drvOutput -> Builder) - -> Derivation' drvInputs drvOutput + -> (OutputName -> drvOutput -> Builder) + -> TraditionalDerivation' drvInputs (Map OutputName drvOutput) -> Builder -buildDerivationWith drvInputs drvOutput (Derivation {..}) = +buildTraditionalDerivationWith drvInputs drvOutput (TraditionalDerivation {..}) = "Derive(" - <> mapOf keyValue0 outputs + <> mapOf keyValue0 anonOutputs <> "," - <> drvInputs inputs + <> drvInputs anonInputs <> "," - <> string platform + <> string anonPlatform <> "," - <> string builder + <> string anonBuilder <> "," - <> vectorOf string args + <> vectorOf string anonArgs <> "," - <> mapOf keyValue1 env + <> mapOf keyValue1 anonEnv <> ")" where keyValue0 (key, output) = "(" <> buildOutputName key <> "," - <> drvOutput name key output + <> drvOutput key output <> ")" keyValue1 (key, value) = @@ -77,15 +77,13 @@ buildDerivationWith drvInputs drvOutput (Derivation {..}) = <> string value <> ")" --- | Render a @DerivationOutput@ as a `Builder` using custom +-- | Render a @FreeformDerivationOutput@ as a `Builder` using custom -- renderer for storePaths -buildDerivationOutput +buildFreeformDerivationOutput :: StoreDir - -> StorePathName - -> OutputName - -> DerivationOutput + -> FreeformDerivationOutput -> Builder -buildDerivationOutput storeDir drvName outputName = +buildFreeformDerivationOutput storeDir = ( \RawDerivationOutput {..} -> string rawPath <> "," @@ -93,15 +91,15 @@ buildDerivationOutput storeDir drvName outputName = <> "," <> string rawHash ) - . renderRawDerivationOutput storeDir drvName outputName + . renderRawDerivationOutput storeDir --- | Render a @DerivationInputs@ as a `Builder` using custom +-- | Render a @TraditionalDerivationInputs@ as a `Builder` using custom -- renderer for storePaths and output names -buildDerivationInputs +buildTraditionalDerivationInputs :: StoreDir -> TraditionalDerivationInputs -> Builder -buildDerivationInputs storeDir (TraditionalDerivationInputs {..}) = +buildTraditionalDerivationInputs storeDir (TraditionalDerivationInputs {..}) = mapOf keyValue traditionalDrvs <> "," <> setOf (storePath storeDir) traditionalSrcs diff --git a/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Parser.hs b/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Parser.hs index 5813eccf..b7ba9af5 100644 --- a/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Parser.hs +++ b/hnix-store-aterm/src/System/Nix/Derivation/ATerm/Parser.hs @@ -9,10 +9,10 @@ module System.Nix.Derivation.ATerm.Parser ( -- * Parser - parseDerivation - , parseDerivationWith - , parseDerivationOutput - , parseDerivationInputs + parseTraditionalDerivation + , parseTraditionalDerivationWith + , parseFreeformDerivationOutput + , parseTraditionalDerivationInputs , textParser ) where @@ -28,11 +28,11 @@ import Data.Text qualified import Data.Vector (Vector) import Data.Vector qualified -import System.Nix.Derivation.Traditional import System.Nix.Derivation - ( Derivation'(..) - , DerivationOutput(..) + ( FreeformDerivationOutput(..) + , FreeformDerivationOutputs ) +import System.Nix.Derivation.Traditional import System.Nix.StorePath import System.Nix.OutputName @@ -44,46 +44,47 @@ listOf element = do pure es -- | Parse a derivation -parseDerivation :: StoreDir -> StorePathName -> Parser (Derivation' TraditionalDerivationInputs DerivationOutput) -parseDerivation sd = - parseDerivationWith - (parseDerivationInputs sd) - (parseDerivationOutput sd) +parseTraditionalDerivation + :: StoreDir + -> Parser (TraditionalDerivation' TraditionalDerivationInputs FreeformDerivationOutputs) +parseTraditionalDerivation sd = + parseTraditionalDerivationWith + (parseTraditionalDerivationInputs sd) + (\_ -> parseFreeformDerivationOutput sd) -- | Parse a derivation using custom -- parsers for filepaths, texts, outputNames and derivation inputs/outputs -parseDerivationWith +parseTraditionalDerivationWith :: Parser drvInputs - -> (StorePathName -> OutputName -> Parser drvOutput) - -> StorePathName - -> Parser (Derivation' drvInputs drvOutput) -parseDerivationWith parseInputs parseOutput name = do + -> (OutputName -> Parser drvOutput) + -> Parser (TraditionalDerivation' drvInputs (Map OutputName drvOutput)) +parseTraditionalDerivationWith parseInputs parseOutput = do "Derive(" let keyValue0 = do "(" key <- outputNameParser "," - drvOutput <- parseOutput name key + drvOutput <- parseOutput key ")" return (key, drvOutput) - outputs <- mapOf keyValue0 + anonOutputs <- mapOf keyValue0 "," - inputs <- parseInputs + anonInputs <- parseInputs "," - platform <- textParser + anonPlatform <- textParser "," - builder <- textParser + anonBuilder <- textParser "," - args <- vectorOf textParser + anonArgs <- vectorOf textParser "," @@ -94,25 +95,25 @@ parseDerivationWith parseInputs parseOutput name = do value <- textParser ")" pure (key, value) - env <- mapOf keyValue1 + anonEnv <- mapOf keyValue1 ")" - pure Derivation {..} + pure TraditionalDerivation {..} -- | Parse a derivation output -parseDerivationOutput :: StoreDir -> StorePathName -> OutputName -> Parser DerivationOutput -parseDerivationOutput sd drvName outputName = do +parseFreeformDerivationOutput :: StoreDir -> Parser FreeformDerivationOutput +parseFreeformDerivationOutput sd = do rawPath <- textParser "," rawMethodHashAlgo <- textParser "," rawHash <- textParser - parseRawDerivationOutput sd drvName outputName $ RawDerivationOutput {..} + parseRawDerivationOutput sd $ RawDerivationOutput {..} -- | Parse a derivation inputs -parseDerivationInputs :: StoreDir -> Parser TraditionalDerivationInputs -parseDerivationInputs sd = do +parseTraditionalDerivationInputs :: StoreDir -> Parser TraditionalDerivationInputs +parseTraditionalDerivationInputs sd = do traditionalDrvs <- mapOf $ do "(" key <- storePathParser sd diff --git a/hnix-store-aterm/src/System/Nix/Derivation/Traditional.hs b/hnix-store-aterm/src/System/Nix/Derivation/Traditional.hs index 8367371d..f36a3383 100644 --- a/hnix-store-aterm/src/System/Nix/Derivation/Traditional.hs +++ b/hnix-store-aterm/src/System/Nix/Derivation/Traditional.hs @@ -4,6 +4,7 @@ {-# LANGUAGE KindSignatures #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} @@ -15,31 +16,37 @@ module System.Nix.Derivation.Traditional ( RawDerivationOutput(..) , parseRawDerivationOutput , renderRawDerivationOutput + , TraditionalDerivation'(..) + , withName + , withoutName , TraditionalDerivationInputs(..) , inputsToTraditional + , inputsFromTraditional ) where -import Control.Monad (when) import Control.DeepSeq (NFData(..)) import Data.Constraint.Extras (Has(has)) import Data.Dependent.Sum (DSum(..)) import Data.Map (Map) +import Data.Map qualified import Data.Map.Monoidal (MonoidalMap(..)) import Data.Map.Monoidal qualified +import Data.Maybe (fromMaybe) import Data.Set (Set) import Data.Some import Data.Text (Text) import Data.Text qualified import Data.These (These(..)) -import GHC.Generics (Generic) +import Data.Vector (Vector) +import Data.Traversable (for) +import GHC.Generics (Generic, (:.:)(..)) import System.Nix.ContentAddress (ContentAddressMethod(..)) import System.Nix.Derivation import System.Nix.Hash -import System.Nix.OutputName (OutputName, outputStoreObjectName) +import System.Nix.OutputName (OutputName) import System.Nix.StorePath -import System.Nix.StorePath.ContentAddressed -- | Useful for the ATerm format, and remote protocols that need the same parsing -- If it won't for the protocol, we would just inline this into the ATerm code proper. @@ -53,63 +60,41 @@ parseRawDerivationOutput :: forall m . MonadFail m => StoreDir - -> StorePathName - -> OutputName -> RawDerivationOutput - -> m DerivationOutput -parseRawDerivationOutput storeDir drvName outputName (RawDerivationOutput {..}) = do - let onNonEmptyText :: Text -> (Text -> m a) -> m (Maybe a) - onNonEmptyText = flip $ \f -> \case - "" -> pure Nothing - t -> Just <$> f t - mPath <- onNonEmptyText rawPath $ \t -> case System.Nix.StorePath.parsePathFromText storeDir t of - Left e -> fail $ show e -- TODO - Right sp -> pure sp - mHashAlgo <- onNonEmptyText rawMethodHashAlgo splitMethodHashAlgo - mHash <- onNonEmptyText rawHash pure - case (mPath, mHashAlgo, mHash) of - (Just path, Nothing, Nothing) -> - pure InputAddressedDerivationOutput {..} - (Just path, Just (method, Some hashAlgo), Just hash0) -> do - hash' <- either fail pure $ has @NamedAlgo hashAlgo $ - decodeDigestWith NixBase32 hash0 - let hash = hashAlgo :=> hash' - fullOutputName <- either (fail . show) pure $ - outputStoreObjectName drvName outputName - let expectedPath = makeFixedOutputPath storeDir method hash mempty fullOutputName - when (path /= expectedPath) $ - fail "fixed output path does not match info" - pure FixedDerivationOutput {..} - (Nothing, Just (method, hashAlgo), Nothing) -> do - pure ContentAddressedDerivationOutput {..} - _ -> - fail "bad output in derivation" + -> m FreeformDerivationOutput +parseRawDerivationOutput storeDir (RawDerivationOutput {..}) = do + let onNonEmptyText :: Text -> (Text -> m a) -> m (Maybe a) + onNonEmptyText = flip $ \f -> \case + "" -> pure Nothing + t -> Just <$> f t + mPath <- onNonEmptyText rawPath $ \t -> case System.Nix.StorePath.parsePathFromText storeDir t of + Left e -> fail $ show e -- TODO + Right sp -> pure sp + mMethodHashAlgo <- onNonEmptyText rawMethodHashAlgo splitMethodHashAlgo + mHash0 <- onNonEmptyText rawHash pure + mContentAddressing <- case mMethodHashAlgo of + Nothing -> case mHash0 of + Nothing -> pure Nothing + Just _ -> fail "Hash without method and hash algo is not allowed" + Just (method, Some hashAlgo) -> do + mHash <- for mHash0 $ \hash0 -> + either fail pure $ has @NamedAlgo hashAlgo $ + decodeDigestWith NixBase32 hash0 + pure $ Just (method, hashAlgo :=> Comp1 mHash) + pure FreeformDerivationOutput { mPath, mContentAddressing } renderRawDerivationOutput :: StoreDir - -> StorePathName - -> OutputName - -> DerivationOutput + -> FreeformDerivationOutput -> RawDerivationOutput -renderRawDerivationOutput storeDir drvName outputName = \case - InputAddressedDerivationOutput {..} -> RawDerivationOutput - { rawPath = storePathToText storeDir path - , rawMethodHashAlgo = "" - , rawHash = "" +renderRawDerivationOutput storeDir (FreeformDerivationOutput {..}) = + RawDerivationOutput + { rawPath = fromMaybe "" $ storePathToText storeDir <$> mPath + , rawMethodHashAlgo = flip (maybe "") mContentAddressing $ \(method, hashAlgo :=> _) -> + buildMethodHashAlgo method $ Some hashAlgo + , rawHash = fromMaybe "" $ mContentAddressing >>= \(_, _ :=> Comp1 hash') -> + encodeDigestWith NixBase32 <$> hash' } - FixedDerivationOutput {..} -> case hash of - hashAlgo :=> hash' -> RawDerivationOutput - { rawPath = storePathToText storeDir $ makeFixedOutputPath storeDir method hash mempty - $ either (error . show) id -- TODO do better - $ outputStoreObjectName drvName outputName - , rawMethodHashAlgo = buildMethodHashAlgo method $ Some hashAlgo - , rawHash = encodeDigestWith NixBase32 hash' - } - ContentAddressedDerivationOutput {..} -> RawDerivationOutput - { rawPath = "" - , rawMethodHashAlgo = buildMethodHashAlgo method hashAlgo - , rawHash = "" - } buildMethodHashAlgo :: ContentAddressMethod -> Some HashAlgo -> Text buildMethodHashAlgo method hashAlgo = Data.Text.intercalate ":" $ @@ -130,6 +115,51 @@ splitMethodHashAlgo methodHashAlgo = do hashAlgo <- either fail pure $ textToAlgo hashAlgoS pure (method, hashAlgo) +---------------- + +-- | The ATerm format doesn't include the derivation name. That must +-- instead be gotten out of band, e.g. from the Store Path. +data TraditionalDerivation' inputs outputs = TraditionalDerivation + { anonOutputs :: outputs + -- ^ Outputs produced by this derivation where keys are output names + , anonInputs :: inputs + -- ^ Inputs (sources and derivations) + , anonPlatform :: Text + -- ^ Platform required for this derivation + , anonBuilder :: Text + -- ^ Code to build the derivation, which can be a path or a builtin function + , anonArgs :: Vector Text + -- ^ Arguments passed to the executable used to build to derivation + , anonEnv :: Map Text Text + -- ^ Environment variables provided to the executable used to build the + -- derivation + } deriving (Eq, Generic, Ord, Show) + +instance (NFData inputs, NFData outputs) => NFData (TraditionalDerivation' inputs outputs) + +withName :: StorePathName -> TraditionalDerivation' inputs outputs -> Derivation' inputs outputs +withName name drv0 = Derivation + { name = name + , outputs = anonOutputs drv0 + , inputs = anonInputs drv0 + , platform = anonPlatform drv0 + , builder = anonBuilder drv0 + , args = anonArgs drv0 + , env = anonEnv drv0 + } + +withoutName :: Derivation' inputs outputs -> TraditionalDerivation' inputs outputs +withoutName drv0 = TraditionalDerivation + { anonOutputs = outputs drv0 + , anonPlatform = platform drv0 + , anonInputs = inputs drv0 + , anonBuilder = builder drv0 + , anonArgs = args drv0 + , anonEnv = env drv0 + } + +---------------- + -- | Useful for the ATerm format data TraditionalDerivationInputs = TraditionalDerivationInputs { traditionalSrcs :: Set StorePath @@ -162,3 +192,10 @@ inputsToTraditional is = (\drvs -> TraditionalDerivationInputs _ -> Left storePath -- TODO make better error, e.g. by partitioning the map ) . unChildNode) . unDerivedPathMap + +inputsFromTraditional :: TraditionalDerivationInputs -> DerivationInputs +inputsFromTraditional TraditionalDerivationInputs { traditionalSrcs, traditionalDrvs } = DerivationInputs + { srcs = traditionalSrcs + , drvs = DerivedPathMap $ Data.Map.Monoidal.fromList $ + fmap (fmap ChildNode . fmap This) (Data.Map.toList traditionalDrvs) + } diff --git a/hnix-store-aterm/tests/Example.hs b/hnix-store-aterm/tests/Example.hs index 707ab293..59fb4ac0 100644 --- a/hnix-store-aterm/tests/Example.hs +++ b/hnix-store-aterm/tests/Example.hs @@ -11,18 +11,17 @@ import System.Nix.Derivation.ATerm qualified main :: IO () main = do - name <- either (fail . show) pure $ mkStorePathName "perl-MIME-Types-2.13-devdoc" let storeDir = StoreDir "/nix/store" text0 <- Data.Text.Lazy.IO.readFile "tests/example0.drv" derivation <- case Data.Attoparsec.Text.Lazy.parse - (System.Nix.Derivation.ATerm.parseDerivation storeDir name) + (System.Nix.Derivation.ATerm.parseTraditionalDerivation storeDir) text0 of Fail _ _ string -> fail string Done _ derivation -> return derivation - let builder = System.Nix.Derivation.ATerm.buildDerivation storeDir derivation + let builder = System.Nix.Derivation.ATerm.buildTraditionalDerivation storeDir derivation let text1 = Data.Text.Lazy.Builder.toLazyText builder if text0 == text1 then return () diff --git a/hnix-store-aterm/tests/Property.hs b/hnix-store-aterm/tests/Property.hs index 87e6f2ca..f0727253 100644 --- a/hnix-store-aterm/tests/Property.hs +++ b/hnix-store-aterm/tests/Property.hs @@ -4,6 +4,7 @@ {-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE DerivingVia #-} {-# LANGUAGE StandaloneDeriving #-} +{-# LANGUAGE UndecidableInstances #-} -- due to recent generic-arbitrary {-# OPTIONS_GHC -fconstraint-solver-iterations=0 #-} {-# OPTIONS_GHC -Wno-orphans #-} @@ -14,44 +15,49 @@ import Prelude hiding (FilePath, either) import Data.Attoparsec.Text.Lazy qualified import Data.Text.Lazy.Builder qualified -import Test.QuickCheck (Arbitrary(..)) +import Test.QuickCheck (Arbitrary) import Test.QuickCheck qualified import Test.QuickCheck.Property (failed, succeeded, Result(..)) -import Test.QuickCheck.Arbitrary.Generic (GenericArbitrary(..)) +import Test.QuickCheck.Arbitrary.Generic (Arg, GenericArbitrary(..)) import System.Nix.StorePath -import System.Nix.Derivation - ( Derivation'(..) - , DerivationOutput(..) - ) import System.Nix.Arbitrary.Derivation () +import System.Nix.Derivation import System.Nix.Derivation.ATerm qualified import System.Nix.Derivation.Traditional deriving via GenericArbitrary TraditionalDerivationInputs instance Arbitrary TraditionalDerivationInputs +deriving via GenericArbitrary (TraditionalDerivation' inputs outputs) + instance + ( Arbitrary inputs + , Arbitrary outputs + , Arg (TraditionalDerivation' inputs outputs) inputs + , Arg (TraditionalDerivation' inputs outputs) outputs + ) => Arbitrary (TraditionalDerivation' inputs outputs) + property :: StoreDir - -> Derivation' + -> TraditionalDerivation' TraditionalDerivationInputs - DerivationOutput + FreeformDerivationOutputs -> Result property storeDir derivation0 = if either == expected then succeeded else failed { reason = unlines ["", show either, show expected] } where - builder = System.Nix.Derivation.ATerm.buildDerivation storeDir derivation0 + builder = System.Nix.Derivation.ATerm.buildTraditionalDerivation storeDir derivation0 text = Data.Text.Lazy.Builder.toLazyText builder result = Data.Attoparsec.Text.Lazy.parse - (System.Nix.Derivation.ATerm.parseDerivation storeDir (name derivation0)) + (System.Nix.Derivation.ATerm.parseTraditionalDerivation storeDir) text - either, expected :: Either String (Derivation' TraditionalDerivationInputs DerivationOutput) + either, expected :: Either String (TraditionalDerivation' TraditionalDerivationInputs FreeformDerivationOutputs) either = Data.Attoparsec.Text.Lazy.eitherResult result diff --git a/hnix-store-core/hnix-store-core.cabal b/hnix-store-core/hnix-store-core.cabal index 8b545410..8582895c 100644 --- a/hnix-store-core/hnix-store-core.cabal +++ b/hnix-store-core/hnix-store-core.cabal @@ -87,6 +87,7 @@ library , deepseq , dependent-sum > 0.7 , dependent-sum-template >= 0.2.0.1 && < 0.3 + , dependent-monoidal-map , filepath , hashable -- Required for crypton low-level type convertion diff --git a/hnix-store-core/src/System/Nix/Derivation.hs b/hnix-store-core/src/System/Nix/Derivation.hs index b4080b63..e6f6dc73 100644 --- a/hnix-store-core/src/System/Nix/Derivation.hs +++ b/hnix-store-core/src/System/Nix/Derivation.hs @@ -2,7 +2,10 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE KindSignatures #-} +{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE QuantifiedConstraints #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE UndecidableInstances #-} -- | Shared types @@ -12,7 +15,18 @@ module System.Nix.Derivation , Derivation , BasicDerivation - , DerivationOutput(..) + , DerivationType(..) + , DerivationOutputs + , InputAddressedDerivationOutput(..) + , FixedDerivationOutput(..) + , ContentAddressedDerivationOutput(..) + + , FreeformDerivationOutput(..) + , FreeformDerivationOutputs + , toSpecificOutput + , fromSpecificOutput + , toSpecificOutputs + , fromSpecificOutputs , DerivationInputs(..) , derivationInputsFromSingleDerivedPath @@ -24,31 +38,113 @@ module System.Nix.Derivation , derivedPathMapToSet ) where +import Control.Monad (when) import Control.DeepSeq (NFData(..)) import Crypto.Hash (Digest) +import Data.Constraint.Extras +import Data.Constraint.Extras.TH (deriveArgDict) +import Data.Dependent.Map.Monoidal qualified as MonoidalDMap import Data.Dependent.Sum (DSum(..)) +import Data.Functor.Identity +import Data.GADT.Compare.TH +import Data.GADT.Show.TH +import Data.GADT.DeepSeq (GNFData(..)) +import Data.Kind import Data.Map (Map) +import Data.Map qualified import Data.Map.Monoidal (MonoidalMap) import Data.Map.Monoidal qualified import Data.Set (Set) import Data.Set qualified import Data.Some (Some(..)) -import Data.GADT.DeepSeq (GNFData(..)) import Data.Text (Text) import Data.These (These(..), fromThese) import Data.Vector (Vector) -import GHC.Generics (Generic) +import GHC.Generics (Generic, (:.:)(..)) import System.Nix.ContentAddress (ContentAddressMethod) -import System.Nix.Hash (HashAlgo) import System.Nix.DerivedPath (SingleDerivedPath(..)) -import System.Nix.StorePath (StorePath, StorePathName) -import System.Nix.OutputName (OutputName) +import System.Nix.Hash (HashAlgo) +import System.Nix.OutputName (OutputName, outputStoreObjectName) +import System.Nix.StorePath (StoreDir, StorePath, StorePathName) +import System.Nix.StorePath.ContentAddressed + +-- | The type of the derivation +data DerivationType :: Type -> Type where + + -- | The outputs are input-addressed. + DerivationType_InputAddressing :: DerivationType InputAddressedDerivationOutput + + -- | The outputs are content-addressed, and the content addresses are + -- "fixed", i.e. required to be specific values (or the build fails) + -- by the derivation itself. + DerivationType_Fixed :: DerivationType FixedDerivationOutput + + -- | The outputs are content-addressed, and the content addresses are + -- "floating", i.e. they are not required to be a specific value like + -- in the "fixed" case. + DerivationType_ContentAddressing :: DerivationType ContentAddressedDerivationOutput + +---------------- + +type DerivationOutputs = DSum DerivationType (Map OutputName) + +-- | An output of a Nix derivation +data InputAddressedDerivationOutput = InputAddressedDerivationOutput + { iaPath :: StorePath + -- ^ Path where the output will be saved + } + deriving (Eq, Generic, Ord, Show) + +instance NFData InputAddressedDerivationOutput + +data FixedDerivationOutput = FixedDerivationOutput + { fMethod :: ContentAddressMethod + -- ^ How this output is serialized into a hash / what sort of CA + -- store path is used. + , fHash :: DSum HashAlgo Digest + -- ^ Expected hash of this output + } + deriving (Eq, Generic, Ord, Show) + +instance NFData FixedDerivationOutput + +data ContentAddressedDerivationOutput = ContentAddressedDerivationOutput + { caMethod :: ContentAddressMethod + -- ^ How this output is serialized into a hash / what sort of CA + -- store path is used. + , caHashAlgo :: Some HashAlgo + -- ^ What sort of hash function is used with the above + -- content-addressing method to produce the (content-addressed) + -- store path we'll use for the output. + } + deriving (Eq, Generic, Ord, Show) + +instance NFData ContentAddressedDerivationOutput -data Derivation' inputs output = Derivation +---------------- + +-- | TODO this should go in `dependent-sum` +instance (GNFData k, Has' NFData k v) => NFData (DSum k v) where + rnf (x :=> y) = grnf x `seq` has' @NFData @v x (rnf y) + +-- | TODO this needs a home +instance GNFData Digest where + grnf = rnf + +---------------- + +deriveGEq ''DerivationType +deriveGCompare ''DerivationType +deriveGShow ''DerivationType +deriveArgDict ''DerivationType + +---------------- + +data Derivation' inputs outputs = Derivation { name :: StorePathName -- ^ Name of the derivation, needed for calculating output paths - , outputs :: Map OutputName output + , outputs :: outputs -- ^ Outputs produced by this derivation where keys are output names , inputs :: inputs -- ^ Inputs (sources and derivations) @@ -66,11 +162,11 @@ data Derivation' inputs output = Derivation instance (NFData inputs, NFData output) => NFData (Derivation' inputs output) -- | A regular Nix derivation -type Derivation = Derivation' DerivationInputs DerivationOutput +type Derivation = Derivation' DerivationInputs DerivationOutputs -- | A Nix derivation that only depends on other store objects directly, -- not (the outputs of) other derivations -type BasicDerivation = Derivation' (Set StorePath) DerivationOutput +type BasicDerivation = Derivation' (Set StorePath) DerivationOutputs ---------------- @@ -149,35 +245,120 @@ derivedPathMapToSet (DerivedPathMap m) = Data.Set.unions $ fmap ---------------- --- | An output of a Nix derivation -data DerivationOutput - = InputAddressedDerivationOutput - { path :: StorePath - -- ^ Path where the output will be saved - } - | FixedDerivationOutput - { method :: ContentAddressMethod - -- ^ How this output is serialized into a hash / what sort of CA +-- | This single data type can represent all types of derivation +-- outputs, but allows for many illegal states. This is here as a +-- simpler intermediate data type to aid with derivation parsing (both +-- JSON and ATerm). +data FreeformDerivationOutput + = FreeformDerivationOutput + { mPath :: Maybe StorePath + -- ^ Optional: Path where the output will be saved + , mContentAddressing :: Maybe (ContentAddressMethod, DSum HashAlgo (Maybe :.: Digest)) + -- ^ Optional: How this output is serialized into a hash / what sort of CA -- store path is used. - , hash :: DSum HashAlgo Digest - -- ^ Expected hash of this output - } - | ContentAddressedDerivationOutput - { method :: ContentAddressMethod - -- ^ How this output is serialized into a hash / what sort of CA - -- store path is used. - , hashAlgo :: Some HashAlgo - -- ^ What sort of hash function is used with the above - -- content-addressing method to produce the (content-addressed) - -- store path we'll use for the output. + -- + -- Inner Optional: Expected hash algorithm and also possibly hash + -- for this output. } deriving (Eq, Generic, Ord, Show) -instance NFData DerivationOutput +instance NFData FreeformDerivationOutput --- | TODO this should go in `dependent-sum` -instance (GNFData k, GNFData v) => NFData (DSum k v) where - rnf (x :=> y) = grnf x `seq` grnf y --- | TODO this needs a home -instance GNFData Digest where - grnf = rnf +-- | TODO upstream +instance NFData (f (g a)) => NFData ((f :.: g) a) where + rnf (Comp1 x) = rnf x + +type FreeformDerivationOutputs = Map OutputName FreeformDerivationOutput + +-- | Convert a 'FreeformDerivationOutput' to a derivation type and +-- output +toSpecificOutput + :: forall m + . MonadFail m + => StoreDir + -> StorePathName + -> OutputName + -> FreeformDerivationOutput + -> m (DSum DerivationType Identity) +toSpecificOutput storeDir drvName outputName = \case + FreeformDerivationOutput + { mPath = Just path + , mContentAddressing = Nothing + } -> pure $ DerivationType_InputAddressing :=> Identity (InputAddressedDerivationOutput path) + FreeformDerivationOutput + { mPath = Just path + , mContentAddressing = Just (method, algo :=> Comp1 (Just hash)) + } -> do + fullOutputName <- either (fail . show) pure $ + outputStoreObjectName drvName outputName + let hash' = algo :=> hash + let expectedPath = makeFixedOutputPath storeDir method hash' mempty fullOutputName + when (path /= expectedPath) $ + fail "fixed output path does not match info" + pure $ DerivationType_Fixed :=> Identity (FixedDerivationOutput method hash') + FreeformDerivationOutput + { mPath = Nothing + , mContentAddressing = Just (method, algo :=> Comp1 Nothing) + } -> pure $ DerivationType_ContentAddressing :=> Identity (ContentAddressedDerivationOutput method (Some algo)) + _ -> fail "Invalid combination of path/method/hash being present or absent" + +-- | Convert a derivation type and output to a 'FreeformDerivationOutput' +fromSpecificOutput + :: StoreDir + -> StorePathName + -> OutputName + -> DSum DerivationType Identity + -> FreeformDerivationOutput +fromSpecificOutput storeDir drvName outputName (ty :=> Identity output) = case ty of + DerivationType_InputAddressing -> + case output of + InputAddressedDerivationOutput { iaPath } -> + FreeformDerivationOutput + { mPath = Just iaPath + , mContentAddressing = Nothing + } + DerivationType_Fixed -> + case output of + FixedDerivationOutput { fMethod, fHash = hash'@(algo :=> hash) } -> + FreeformDerivationOutput + { mPath = Just $ makeFixedOutputPath storeDir fMethod hash' mempty + $ either (error . show) id -- TODO do better + $ outputStoreObjectName drvName outputName + , mContentAddressing = Just (fMethod, algo :=> Comp1 (Just hash)) + } + DerivationType_ContentAddressing -> + case output of + ContentAddressedDerivationOutput { caMethod, caHashAlgo = Some algo } -> + FreeformDerivationOutput + { mPath = Nothing + , mContentAddressing = Just (caMethod, algo :=> Comp1 Nothing) + } + +-- | Convert a map of 'FreeformDerivationOutput' to 'DerivationOutputs' +toSpecificOutputs + :: forall m + . MonadFail m + => StoreDir + -> StorePathName + -> FreeformDerivationOutputs + -> m DerivationOutputs +toSpecificOutputs storeDir drvName outputs = do + -- Traverse and convert each output + converted <- Data.Map.traverseWithKey (toSpecificOutput storeDir drvName) outputs + -- Group outputs by their derivation type + let grouped = foldMap + (\(name, ty :=> Identity output) -> MonoidalDMap.singleton ty $ Data.Map.singleton name output) + (Data.Map.toList converted) + case MonoidalDMap.toList grouped of + [res] -> pure res + _ -> fail "derivation outputs did not agree on derivation type" + +-- | Convert a map of specific derivation outputs to a 'FreeformDerivationOutputs' +fromSpecificOutputs + :: StoreDir + -> StorePathName + -> DerivationOutputs + -> FreeformDerivationOutputs +fromSpecificOutputs storeDir drvName (drvType :=> outputs) = + flip Data.Map.mapWithKey outputs $ \outputName output -> + fromSpecificOutput storeDir drvName outputName $ drvType :=> Identity output diff --git a/hnix-store-remote/hnix-store-remote.cabal b/hnix-store-remote/hnix-store-remote.cabal index 065e33c1..c324d156 100644 --- a/hnix-store-remote/hnix-store-remote.cabal +++ b/hnix-store-remote/hnix-store-remote.cabal @@ -180,6 +180,7 @@ test-suite remote , hnix-store-core , hnix-store-remote , hnix-store-tests + , hnix-store-aterm , bytestring , crypton , some > 1.0.5 && < 2 diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs index b17b045a..2325b831 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs @@ -147,14 +147,23 @@ buildDerivation sp mode = do $ Data.Text.IO.readFile $ System.Nix.StorePath.storePathToFilePath sd sp case Data.Attoparsec.Text.parseOnly - (System.Nix.Derivation.ATerm.parseDerivation sd $ System.Nix.StorePath.storePathName sp) drvContents of + (System.Nix.Derivation.ATerm.parseTraditionalDerivation sd) drvContents of Left e -> throwError $ RemoteStoreError_DerivationParse e Right drv -> do - let drv' = drv - { System.Nix.Derivation.inputs = - System.Nix.Derivation.Traditional.traditionalSrcs - (System.Nix.Derivation.inputs drv) - } + let name = System.Nix.StorePath.storePathName sp + outputs <- case + System.Nix.Derivation.toSpecificOutputs sd name $ + System.Nix.Derivation.Traditional.anonOutputs drv + of + Nothing -> throwError $ RemoteStoreError_DerivationParse "TODO get error" + Just os -> pure os + let drv' = System.Nix.Derivation.Traditional.withName name $ + System.Nix.Derivation.Traditional.TraditionalDerivation + { System.Nix.Derivation.Traditional.anonOutputs = outputs + , System.Nix.Derivation.Traditional.anonInputs = + System.Nix.Derivation.Traditional.traditionalSrcs + (System.Nix.Derivation.Traditional.anonInputs drv) + } doReq (BuildDerivation sp drv' mode) -- | Build paths if they are an actual derivations. diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs index e2672e74..78fa4217 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs @@ -151,11 +151,6 @@ import System.Nix.ContentAddress (ContentAddress) import System.Nix.ContentAddress qualified import System.Nix.Derivation.Traditional import System.Nix.Derivation - ( BasicDerivation - , Derivation'(..) - , DerivationOutput(..) - -- , DerivationInputs(..) - ) import System.Nix.DerivedPath (DerivedPath(..), ParseOutputsError) import System.Nix.DerivedPath qualified import System.Nix.FileContentAddress (FileIngestionMethod(..)) @@ -683,17 +678,15 @@ namedDigest = Serializer derivationOutput :: StoreDir - -> StorePathName - -> OutputName - -> NixSerializer SError DerivationOutput -derivationOutput storeDir drvName outputName' = Serializer + -> NixSerializer SError FreeformDerivationOutput +derivationOutput storeDir = Serializer { getS = do rawPath <- getS text rawMethodHashAlgo <- getS text rawHash <- getS text - parseRawDerivationOutput storeDir drvName outputName' $ RawDerivationOutput {..} + parseRawDerivationOutput storeDir $ RawDerivationOutput {..} , putS = \output -> do - let RawDerivationOutput {..} = renderRawDerivationOutput storeDir drvName outputName' output + let RawDerivationOutput {..} = renderRawDerivationOutput storeDir output putS text rawPath putS text rawMethodHashAlgo putS text rawHash @@ -703,25 +696,23 @@ derivationOutput storeDir drvName outputName' = Serializer basicDerivation :: StoreDir - -> StorePathName - -> NixSerializer SError BasicDerivation -basicDerivation storeDir drvName = Serializer + -> NixSerializer SError (TraditionalDerivation' (Set StorePath) FreeformDerivationOutputs) +basicDerivation storeDir = Serializer { getS = do - outputs <- getS $ mapS' $ depTup outputName $ derivationOutput storeDir drvName - inputs <- getS $ set $ storePath storeDir - platform <- getS text - builder <- getS text - args <- getS $ vector text - env <- getS $ mapS text text - let name = drvName - pure $ Derivation{..} - , putS = \Derivation{..} -> do - putS (mapS' $ depTup outputName $ derivationOutput storeDir drvName) outputs - putS (set $ storePath storeDir) inputs - putS text platform - putS text builder - putS (vector text) args - putS (mapS text text) env + anonOutputs <- getS $ mapS' $ tup outputName $ derivationOutput storeDir + anonInputs <- getS $ set $ storePath storeDir + anonPlatform <- getS text + anonBuilder <- getS text + anonArgs <- getS $ vector text + anonEnv <- getS $ mapS text text + pure $ TraditionalDerivation{..} + , putS = \TraditionalDerivation{..} -> do + putS (mapS' $ tup outputName $ derivationOutput storeDir) anonOutputs + putS (set $ storePath storeDir) anonInputs + putS text anonPlatform + putS text anonBuilder + putS (vector text) anonArgs + putS (mapS text text) anonEnv } -- * DerivedPath @@ -1082,9 +1073,13 @@ storeRequest storeDir pv = Serializer WorkerOp_BuildDerivation -> mapGetE $ do path <- getS $ storePath storeDir - drv <- getS (basicDerivation storeDir $ System.Nix.StorePath.storePathName path) + let name = System.Nix.StorePath.storePathName path + drv0 <- getS $ basicDerivation storeDir + let drv1 = withName name drv0 + outputs <- toSpecificOutputs storeDir name $ outputs drv1 + let drv2 = drv1 { outputs = outputs } buildMode' <- getS buildMode - pure $ Some (BuildDerivation path drv buildMode') + pure $ Some (BuildDerivation path drv2 buildMode') WorkerOp_CollectGarbage -> mapGetE $ do gcOptionsOperation <- getS enum @@ -1223,11 +1218,13 @@ storeRequest storeDir pv = Serializer putS (set $ derivedPath storeDir pv) derived putS buildMode buildMode' - Some (BuildDerivation path drv buildMode') -> do + Some (BuildDerivation path drv0 buildMode') -> do putS workerOp WorkerOp_BuildDerivation putS (storePath storeDir) path - putS (basicDerivation storeDir $ name drv) drv + let drv1 = drv0 { outputs = fromSpecificOutputs storeDir (name drv0) $ outputs drv0 } + let drv2 = withoutName drv1 + putS (basicDerivation storeDir) drv2 putS buildMode buildMode' Some (CollectGarbage GCOptions{..}) -> do diff --git a/hnix-store-remote/tests/NixSerializerSpec.hs b/hnix-store-remote/tests/NixSerializerSpec.hs index 34ce3d0a..efda9a16 100644 --- a/hnix-store-remote/tests/NixSerializerSpec.hs +++ b/hnix-store-remote/tests/NixSerializerSpec.hs @@ -10,7 +10,7 @@ import Test.QuickCheck (Gen, arbitrary, forAll, suchThat) import System.Nix.Arbitrary () import System.Nix.Build (BuildResult(..)) -import System.Nix.Derivation qualified +import System.Nix.Derivation.Traditional qualified import System.Nix.Store.Remote.Arbitrary () import System.Nix.Store.Remote.Serializer import System.Nix.Store.Remote.Types.Logger (Logger(..)) @@ -114,7 +114,8 @@ spec = parallel $ do prop "SHA512" $ roundtripS . digest @SHA512 prop "Derivation" $ \sd drv -> - roundtripS (basicDerivation sd $ System.Nix.Derivation.name drv) drv + roundtripS (basicDerivation sd) $ + System.Nix.Derivation.Traditional.withoutName drv prop "ProtoVersion" $ roundtripS @() protoVersion diff --git a/hnix-store-tests/hnix-store-tests.cabal b/hnix-store-tests/hnix-store-tests.cabal index 54f9ac2d..3f9c99da 100644 --- a/hnix-store-tests/hnix-store-tests.cabal +++ b/hnix-store-tests/hnix-store-tests.cabal @@ -62,6 +62,7 @@ library , hnix-store-core >= 0.8 , bytestring , containers + , constraints-extras , crypton , dependent-sum > 0.7 , generic-arbitrary < 1.1 @@ -97,5 +98,8 @@ test-suite props , hnix-store-core , hnix-store-tests , attoparsec + , dependent-sum + , containers , text , hspec + , QuickCheck diff --git a/hnix-store-tests/src/System/Nix/Arbitrary/Derivation.hs b/hnix-store-tests/src/System/Nix/Arbitrary/Derivation.hs index 0a80b7d6..2d08ca15 100644 --- a/hnix-store-tests/src/System/Nix/Arbitrary/Derivation.hs +++ b/hnix-store-tests/src/System/Nix/Arbitrary/Derivation.hs @@ -1,13 +1,16 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} -- due to recent generic-arbitrary {-# OPTIONS_GHC -fconstraint-solver-iterations=0 #-} {-# OPTIONS_GHC -Wno-orphans #-} module System.Nix.Arbitrary.Derivation where +import Data.Constraint.Extras import Data.Dependent.Sum import Data.Either (isRight) +import Data.Map (Map) import Data.Map qualified import Data.Map.Monoidal import Data.Some @@ -17,42 +20,95 @@ import Data.Vector.Arbitrary () import Test.QuickCheck.Arbitrary.Generic import Test.QuickCheck.Gen -import System.Nix.Derivation +import System.Nix.StorePath import System.Nix.ContentAddress import System.Nix.Hash +import System.Nix.Derivation import System.Nix.OutputName import System.Nix.Arbitrary.ContentAddress () -import System.Nix.Arbitrary.Hash () +import System.Nix.Arbitrary.Hash (genDSum) import System.Nix.Arbitrary.StorePath () import System.Nix.Arbitrary.OutputName () +-- | ensure output path name is not too long +shortEnoughOutputName :: StorePathName -> Gen (OutputName) +shortEnoughOutputName drvName = + arbitrary `suchThat` \outputName -> isRight $ outputStoreObjectName drvName outputName + +-- | Also ensures at least one output +shortEnoughOutputsName :: Arbitrary a => StorePathName -> Gen (Map OutputName a) +shortEnoughOutputsName drvName = fmap Data.Map.fromList $ listOf1 $ (,) <$> shortEnoughOutputName drvName <*> arbitrary + +shortEnoughOutputs :: StorePathName -> Gen DerivationOutputs +shortEnoughOutputs drvName = + genDSum arbitrary $ \tag -> has @Arbitrary tag $ shortEnoughOutputsName drvName + +-- | Ensure a valid combination +ensureValidMethodAlgo :: ContentAddressMethod -> HashAlgo a -> Bool +ensureValidMethodAlgo = \case + ContentAddressMethod_Text -> \case + HashAlgo_SHA256 -> True + _ -> False + _ -> \_ -> True + instance ( Arbitrary inputs , Arbitrary output - , Arg (Derivation' inputs output) inputs - , Arg (Derivation' inputs output) output - ) => Arbitrary (Derivation' inputs output) + , Arg (Derivation' inputs (Map OutputName output)) inputs + , Arg (Derivation' inputs (Map OutputName output)) output + ) => Arbitrary (Derivation' inputs (Map OutputName output)) where - arbitrary = genericArbitrary `suchThat` \drv -> - -- ensure output path name is not too long - all (\on -> isRight $ outputStoreObjectName (name drv) on) - $ Data.Map.keys (outputs drv) + arbitrary = do + drv <- genericArbitrary + om <- shortEnoughOutputsName $ name drv + let + drv' = drv { outputs = om } + -- type inference hint + _ = [drv, drv'] + pure drv' shrink = genericShrink -instance Arbitrary DerivationOutput where - arbitrary = genericArbitrary `suchThat` \case - InputAddressedDerivationOutput {} -> True - FixedDerivationOutput {method, hash = hashAlgo :=> _} -> f method hashAlgo - ContentAddressedDerivationOutput {method, hashAlgo = Some hashAlgo } -> f method hashAlgo - where - -- Ensure a valid combination - f = \case - ContentAddressMethod_Text -> \case - HashAlgo_SHA256 -> True - _ -> False - _ -> \_ -> True +instance + ( Arbitrary inputs + , Arg (Derivation' inputs DerivationOutputs) inputs + ) => Arbitrary (Derivation' inputs DerivationOutputs) + where + arbitrary = do + drv <- genericArbitrary + os <- shortEnoughOutputs $ name drv + let + drv' = drv { outputs = os } + -- type inference hint + _ = [drv, drv'] + pure drv' shrink = genericShrink +deriving via GenericArbitrary FreeformDerivationOutput + instance Arbitrary FreeformDerivationOutput + +deriving via GenericArbitrary InputAddressedDerivationOutput + instance Arbitrary InputAddressedDerivationOutput + +instance Arbitrary FixedDerivationOutput where + arbitrary = genericArbitrary `suchThat` + \(FixedDerivationOutput {fMethod, fHash = hashAlgo :=> _}) -> + ensureValidMethodAlgo fMethod hashAlgo + +instance Arbitrary ContentAddressedDerivationOutput where + arbitrary = genericArbitrary `suchThat` + \(ContentAddressedDerivationOutput {caMethod, caHashAlgo = Some hashAlgo }) -> + ensureValidMethodAlgo caMethod hashAlgo + +instance Arbitrary (Some DerivationType) where + arbitrary = + oneof + $ pure + <$> [ + Some DerivationType_InputAddressing + , Some DerivationType_Fixed + , Some DerivationType_ContentAddressing + ] + deriving via GenericArbitrary DerivationInputs instance Arbitrary DerivationInputs diff --git a/hnix-store-tests/src/System/Nix/Arbitrary/Hash.hs b/hnix-store-tests/src/System/Nix/Arbitrary/Hash.hs index fe4aa266..639a94c6 100644 --- a/hnix-store-tests/src/System/Nix/Arbitrary/Hash.hs +++ b/hnix-store-tests/src/System/Nix/Arbitrary/Hash.hs @@ -1,3 +1,8 @@ +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE TypeOperators #-} + -- due to recent generic-arbitrary {-# OPTIONS_GHC -fconstraint-solver-iterations=0 #-} {-# OPTIONS_GHC -Wno-orphans #-} @@ -5,12 +10,15 @@ module System.Nix.Arbitrary.Hash where import Data.ByteString (ByteString) import Data.ByteString.Arbitrary () +import Data.Constraint.Extras import Crypto.Hash (Digest, MD5(..), SHA1(..), SHA256(..), SHA512(..)) import Data.Dependent.Sum (DSum((:=>))) import Data.Some (Some(Some)) +import GHC.Generics + import System.Nix.Hash (HashAlgo(..)) -import Test.QuickCheck (Arbitrary(arbitrary), oneof) +import Test.QuickCheck (Arbitrary(arbitrary), Gen, oneof) import Crypto.Hash qualified @@ -28,15 +36,7 @@ instance Arbitrary (Digest SHA256) where instance Arbitrary (Digest SHA512) where arbitrary = Crypto.Hash.hash @ByteString <$> arbitrary --- * Arbitrary @DSum HashAlgo Digest@s - -instance Arbitrary (DSum HashAlgo Digest) where - arbitrary = oneof - [ (HashAlgo_MD5 :=>) <$> arbitrary - , (HashAlgo_SHA1 :=>) <$> arbitrary - , (HashAlgo_SHA256 :=>) <$> arbitrary - , (HashAlgo_SHA512 :=>) <$> arbitrary - ] +-- * Arbitrary @Some HashAlgo@ instance Arbitrary (Some HashAlgo) where arbitrary = @@ -48,3 +48,15 @@ instance Arbitrary (Some HashAlgo) where , Some HashAlgo_SHA256 , Some HashAlgo_SHA512 ] + +-- * TODO Upstream + +genDSum :: Gen (Some f) -> (forall a. f a -> Gen (g a)) -> Gen (DSum f g) +genDSum genTag genValue = genTag >>= \(Some tag) -> + (tag :=>) <$> genValue tag + +instance (Arbitrary (Some f), Has' Arbitrary f g) => Arbitrary (DSum f g) where + arbitrary = genDSum arbitrary (\tag -> has' @Arbitrary @g tag arbitrary) + +instance (Arbitrary (f (g a))) => Arbitrary ((f :.: g) a) where + arbitrary = Comp1 <$> arbitrary diff --git a/hnix-store-tests/tests/DerivationSpec.hs b/hnix-store-tests/tests/DerivationSpec.hs index ccaa5046..c317a470 100644 --- a/hnix-store-tests/tests/DerivationSpec.hs +++ b/hnix-store-tests/tests/DerivationSpec.hs @@ -3,13 +3,12 @@ module DerivationSpec where import Data.Functor.Identity (Identity(..)) import Test.Hspec (Spec, describe) import Test.Hspec.QuickCheck (prop) +import Test.QuickCheck import Test.Hspec.Nix (roundtrips) import System.Nix.Arbitrary () +import System.Nix.Arbitrary.Derivation import System.Nix.Derivation - ( derivationInputsFromSingleDerivedPath - , derivationInputsToDerivedPaths - ) spec :: Spec spec = do @@ -21,3 +20,26 @@ spec = do roundtrips (foldMap derivationInputsFromSingleDerivedPath) (Identity . derivationInputsToDerivedPaths) + + describe "DerivationOutput" $ do + prop "roundtrips to FreeformDerivationOutput" $ \storeDir storePathName output -> do + outputName <- generate $ shortEnoughOutputName storePathName + roundtrips + (fromSpecificOutput storeDir storePathName outputName) + (toSpecificOutput @Maybe storeDir storePathName outputName) + output + + -- Sometimes infinite loops, not sure why + + -- describe "DerivationOutputs" $ do + -- prop "roundtrips to FreeformDerivationOutputs" $ verboseCheck $ \storeDir storePathName -> do + -- outputs <- generate $ shortEnoughOutputs storePathName + -- _ <- roundtrips + -- (fromSpecificOutputs storeDir storePathName) + -- (toSpecificOutputs @Maybe storeDir storePathName) + -- outputs + -- pure () + +-- -- | Useful for debugging +-- instance MonadFail (Either String) where +-- fail = Left From 6a5639a2898580b62127ff083de6f7ff3e595185 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sun, 19 Jan 2025 02:24:24 -0500 Subject: [PATCH 57/58] Fix mistake --- hnix-store-remote/src/System/Nix/Store/Remote/Client.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs index 2325b831..3f592af3 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Client.hs @@ -158,7 +158,7 @@ buildDerivation sp mode = do Nothing -> throwError $ RemoteStoreError_DerivationParse "TODO get error" Just os -> pure os let drv' = System.Nix.Derivation.Traditional.withName name $ - System.Nix.Derivation.Traditional.TraditionalDerivation + drv { System.Nix.Derivation.Traditional.anonOutputs = outputs , System.Nix.Derivation.Traditional.anonInputs = System.Nix.Derivation.Traditional.traditionalSrcs From 4ab6dbefc7aa2790761fddba35d82bd46539c0b7 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sun, 19 Jan 2025 02:25:06 -0500 Subject: [PATCH 58/58] Rename Realisation's `DerivationOutput` to `BuildTraceKey` This is to avoid conflict with the type which is actually a derivations output field. --- hnix-store-core/src/System/Nix/Build.hs | 4 +- hnix-store-core/src/System/Nix/Realisation.hs | 64 +++++++++---------- hnix-store-json/src/System/Nix/JSON.hs | 26 ++++---- hnix-store-json/tests/JSONSpec.hs | 18 +++--- .../src/System/Nix/Store/Remote/Serializer.hs | 22 +++---- .../src/System/Nix/Arbitrary/Realisation.hs | 6 +- hnix-store-tests/tests/RealisationSpec.hs | 6 +- 7 files changed, 73 insertions(+), 73 deletions(-) diff --git a/hnix-store-core/src/System/Nix/Build.hs b/hnix-store-core/src/System/Nix/Build.hs index 17e484cd..dbfe755f 100644 --- a/hnix-store-core/src/System/Nix/Build.hs +++ b/hnix-store-core/src/System/Nix/Build.hs @@ -15,7 +15,7 @@ import Data.Text (Text) import GHC.Generics (Generic) import System.Nix.OutputName (OutputName) -import System.Nix.Realisation (DerivationOutput, Realisation) +import System.Nix.Realisation (BuildTraceKey, Realisation) -- | Mode of the build operation -- Keep the order of these Enums to match enums from reference implementations @@ -59,7 +59,7 @@ data BuildResult = BuildResult -- ^ Start time of this build (since 1.29) , buildResultStopTime :: Maybe UTCTime -- ^ Stop time of this build (since 1.29) - , buildResultBuiltOutputs :: Maybe (Map (DerivationOutput OutputName) Realisation) + , buildResultBuiltOutputs :: Maybe (Map (BuildTraceKey OutputName) Realisation) -- ^ Mapping of the output names to @Realisation@s (since 1.28) -- (paths with additional info and their dependencies) } diff --git a/hnix-store-core/src/System/Nix/Realisation.hs b/hnix-store-core/src/System/Nix/Realisation.hs index fd799221..ccafc40e 100644 --- a/hnix-store-core/src/System/Nix/Realisation.hs +++ b/hnix-store-core/src/System/Nix/Realisation.hs @@ -3,10 +3,10 @@ Description : Derivation realisations -} module System.Nix.Realisation ( - DerivationOutput(..) - , DerivationOutputError(..) - , derivationOutputBuilder - , derivationOutputParser + BuildTraceKey(..) + , BuildTraceKeyError(..) + , buildTraceKeyBuilder + , buildTraceKeyParser , Realisation(..) , RealisationWithId(..) ) where @@ -29,75 +29,75 @@ import Data.Text.Lazy.Builder qualified import System.Nix.Hash qualified -- | Output of the derivation -data DerivationOutput a = DerivationOutput - { derivationOutputHash :: DSum HashAlgo Digest +data BuildTraceKey a = BuildTraceKey + { buildTraceKeyHash :: DSum HashAlgo Digest -- ^ Hash modulo of the derivation - , derivationOutputOutput :: a + , buildTraceKeyOutput :: a -- ^ Output (either a OutputName or StorePatH) } deriving (Eq, Generic, Ord, Show) -data DerivationOutputError - = DerivationOutputError_Digest String - | DerivationOutputError_Name InvalidNameError - | DerivationOutputError_NoExclamationMark - | DerivationOutputError_NoColon - | DerivationOutputError_TooManyParts [Text] +data BuildTraceKeyError + = BuildTraceKeyError_Digest String + | BuildTraceKeyError_Name InvalidNameError + | BuildTraceKeyError_NoExclamationMark + | BuildTraceKeyError_NoColon + | BuildTraceKeyError_TooManyParts [Text] deriving (Eq, Ord, Show) -derivationOutputParser +buildTraceKeyParser :: (Text -> Either InvalidNameError outputName) -> Text - -> Either DerivationOutputError (DerivationOutput outputName) -derivationOutputParser outputName dOut = + -> Either BuildTraceKeyError (BuildTraceKey outputName) +buildTraceKeyParser outputName dOut = case Data.Text.splitOn (Data.Text.singleton '!') dOut of - [] -> Left DerivationOutputError_NoColon + [] -> Left BuildTraceKeyError_NoColon [sriHash, oName] -> do hash <- case Data.Text.splitOn (Data.Text.singleton ':') sriHash of - [] -> Left DerivationOutputError_NoColon + [] -> Left BuildTraceKeyError_NoColon [hashName, digest] -> Data.Bifunctor.first - DerivationOutputError_Digest + BuildTraceKeyError_Digest $ System.Nix.Hash.mkNamedDigest hashName digest - x -> Left $ DerivationOutputError_TooManyParts x + x -> Left $ BuildTraceKeyError_TooManyParts x name <- Data.Bifunctor.first - DerivationOutputError_Name + BuildTraceKeyError_Name $ outputName oName - pure $ DerivationOutput hash name - x -> Left $ DerivationOutputError_TooManyParts x + pure $ BuildTraceKey hash name + x -> Left $ BuildTraceKeyError_TooManyParts x -derivationOutputBuilder +buildTraceKeyBuilder :: (outputName -> Text) - -> DerivationOutput outputName + -> BuildTraceKey outputName -> Builder -derivationOutputBuilder outputName DerivationOutput{..} = - System.Nix.Hash.algoDigestBuilder derivationOutputHash +buildTraceKeyBuilder outputName BuildTraceKey{..} = + System.Nix.Hash.algoDigestBuilder buildTraceKeyHash <> Data.Text.Lazy.Builder.singleton '!' - <> Data.Text.Lazy.Builder.fromText (outputName derivationOutputOutput) + <> Data.Text.Lazy.Builder.fromText (outputName buildTraceKeyOutput) -- | Build realisation context -- -- realisationId is ommited since it is a key --- of type @DerivationOutput OutputName@ so +-- of type @BuildTraceKey OutputName@ so -- we will use @RealisationWithId@ newtype data Realisation = Realisation { realisationOutPath :: StorePath -- ^ Output path , realisationSignatures :: Set Signature -- ^ Signatures - , realisationDependencies :: Map (DerivationOutput OutputName) StorePath + , realisationDependencies :: Map (BuildTraceKey OutputName) StorePath -- ^ Dependent realisations required for this one to be valid } deriving (Eq, Generic, Ord, Show) -- | For wire protocol -- -- We store this normalized in @Build.buildResultBuiltOutputs@ --- as @Map (DerivationOutput OutputName) Realisation@ +-- as @Map (BuildTraceKey OutputName) Realisation@ -- but wire protocol needs it de-normalized so we -- need a special (From|To)JSON instances for it newtype RealisationWithId = RealisationWithId - { unRealisationWithId :: (DerivationOutput OutputName, Realisation) + { unRealisationWithId :: (BuildTraceKey OutputName, Realisation) } deriving (Eq, Generic, Ord, Show) diff --git a/hnix-store-json/src/System/Nix/JSON.hs b/hnix-store-json/src/System/Nix/JSON.hs index 436e28dd..8ad4be88 100644 --- a/hnix-store-json/src/System/Nix/JSON.hs +++ b/hnix-store-json/src/System/Nix/JSON.hs @@ -13,7 +13,7 @@ import Data.Aeson import Deriving.Aeson import System.Nix.Base (BaseEncoding(NixBase32)) import System.Nix.OutputName (OutputName) -import System.Nix.Realisation (DerivationOutput, Realisation, RealisationWithId(..)) +import System.Nix.Realisation (BuildTraceKey, Realisation, RealisationWithId(..)) import System.Nix.Signature (Signature) import System.Nix.StorePath (StoreDir(..), StorePath, StorePathName, StorePathHashPart) @@ -77,46 +77,46 @@ instance FromJSON StorePath where . Data.Text.cons '/' ) -instance ToJSON (DerivationOutput OutputName) where +instance ToJSON (BuildTraceKey OutputName) where toJSON = toJSON . Data.Text.Lazy.toStrict . Data.Text.Lazy.Builder.toLazyText - . System.Nix.Realisation.derivationOutputBuilder + . System.Nix.Realisation.buildTraceKeyBuilder (System.Nix.StorePath.unStorePathName . System.Nix.OutputName.unOutputName) toEncoding = toEncoding . Data.Text.Lazy.toStrict . Data.Text.Lazy.Builder.toLazyText - . System.Nix.Realisation.derivationOutputBuilder + . System.Nix.Realisation.buildTraceKeyBuilder (System.Nix.StorePath.unStorePathName . System.Nix.OutputName.unOutputName) -instance ToJSONKey (DerivationOutput OutputName) where +instance ToJSONKey (BuildTraceKey OutputName) where toJSONKey = Data.Aeson.Types.toJSONKeyText $ Data.Text.Lazy.toStrict . Data.Text.Lazy.Builder.toLazyText - . System.Nix.Realisation.derivationOutputBuilder + . System.Nix.Realisation.buildTraceKeyBuilder (System.Nix.StorePath.unStorePathName . System.Nix.OutputName.unOutputName) -instance FromJSON (DerivationOutput OutputName) where +instance FromJSON (BuildTraceKey OutputName) where parseJSON = - withText "DerivationOutput OutputName" + withText "BuildTraceKey OutputName" ( either (fail . show) pure - . System.Nix.Realisation.derivationOutputParser + . System.Nix.Realisation.buildTraceKeyParser System.Nix.OutputName.mkOutputName ) -instance FromJSONKey (DerivationOutput OutputName) where +instance FromJSONKey (BuildTraceKey OutputName) where fromJSONKey = FromJSONKeyTextParser ( either (fail . show) pure - . System.Nix.Realisation.derivationOutputParser + . System.Nix.Realisation.buildTraceKeyParser System.Nix.OutputName.mkOutputName ) @@ -159,8 +159,8 @@ deriving instance FromJSON Realisation -- For a keyed version of Realisation --- we use RealisationWithId (DerivationOutput OutputName, Realisation) --- instead of Realisation.id :: (DerivationOutput OutputName) +-- we use RealisationWithId (BuildTraceKey OutputName, Realisation) +-- instead of Realisation.id :: (BuildTraceKey OutputName) -- field. instance ToJSON RealisationWithId where toJSON (RealisationWithId (drvOut, r)) = diff --git a/hnix-store-json/tests/JSONSpec.hs b/hnix-store-json/tests/JSONSpec.hs index 8bf4ac96..c9ce9263 100644 --- a/hnix-store-json/tests/JSONSpec.hs +++ b/hnix-store-json/tests/JSONSpec.hs @@ -10,7 +10,7 @@ import Test.Hspec.Nix (forceRight, roundtrips) import System.Nix.Arbitrary () import System.Nix.JSON () import System.Nix.OutputName (OutputName) -import System.Nix.Realisation (DerivationOutput(..), Realisation(..)) +import System.Nix.Realisation (BuildTraceKey(..), Realisation(..)) import System.Nix.Signature (Signature) import System.Nix.StorePath (StorePath, StorePathName, StorePathHashPart) @@ -31,14 +31,14 @@ roundtripsJSON -> Expectation roundtripsJSON = roundtrips encode decode -sampleDerivationOutput :: DerivationOutput OutputName -sampleDerivationOutput = DerivationOutput - { derivationOutputHash = +sampleBuildTraceKey :: BuildTraceKey OutputName +sampleBuildTraceKey = BuildTraceKey + { buildTraceKeyHash = forceRight $ System.Nix.Hash.mkNamedDigest "sha256" "1b4sb93wp679q4zx9k1ignby1yna3z7c4c2ri3wphylbc2dwsys0" - , derivationOutputOutput = + , buildTraceKeyOutput = forceRight $ System.Nix.OutputName.mkOutputName "foo" } @@ -70,7 +70,7 @@ sampleRealisation1 = Realisation ] , realisationDependencies = Data.Map.fromList - [ ( sampleDerivationOutput + [ ( sampleBuildTraceKey , forceRight $ System.Nix.StorePath.parsePathFromText def @@ -86,13 +86,13 @@ spec = do prop "StorePathName" $ roundtripsJSON @StorePathName prop "StorePathHashPart" $ roundtripsJSON @StorePathHashPart prop "StorePath" $ roundtripsJSON @StorePath - prop "DerivationOutput OutputName" $ roundtripsJSON @(DerivationOutput OutputName) + prop "BuildTraceKey OutputName" $ roundtripsJSON @(BuildTraceKey OutputName) prop "Signature" $ roundtripsJSON @Signature prop "Realisation" $ roundtripsJSON @Realisation describe "ground truth" $ do - it "sampleDerivationOutput matches preimage" $ - encode sampleDerivationOutput `shouldBe` "\"sha256:1b4sb93wp679q4zx9k1ignby1yna3z7c4c2ri3wphylbc2dwsys0!foo\"" + it "sampleBuildTraceKey matches preimage" $ + encode sampleBuildTraceKey `shouldBe` "\"sha256:1b4sb93wp679q4zx9k1ignby1yna3z7c4c2ri3wphylbc2dwsys0!foo\"" it "sampleRealisation0 matches preimage" $ encode sampleRealisation0 `shouldBe` "{\"outPath\":\"cdips4lakfk1qbf1x68fq18wnn3r5r14-builder.sh\",\"signatures\":[],\"dependentRealisations\":{}}" diff --git a/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs b/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs index 78fa4217..16a77d31 100644 --- a/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs +++ b/hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs @@ -86,7 +86,7 @@ module System.Nix.Store.Remote.Serializer , opSuccess , noop -- *** Realisation - , derivationOutputTyped + , buildTraceKeyTyped , realisation , realisationWithId -- *** BuildResult @@ -159,7 +159,7 @@ import System.Nix.Hash qualified import System.Nix.JSON () import System.Nix.OutputName (OutputName) import System.Nix.OutputName qualified -import System.Nix.Realisation (DerivationOutputError, Realisation(..), RealisationWithId(..)) +import System.Nix.Realisation (BuildTraceKeyError, Realisation(..), RealisationWithId(..)) import System.Nix.Realisation qualified import System.Nix.Signature (Signature, NarSignature) import System.Nix.Signature qualified @@ -194,7 +194,7 @@ data SError | SError_ContentAddress String | SError_DerivingPath | SError_DerivedPath ParseOutputsError - | SError_DerivationOutput DerivationOutputError + | SError_BuildTraceKey BuildTraceKeyError | SError_Digest String | SError_EnumOutOfMinBound Int | SError_EnumOutOfMaxBound Int @@ -1328,7 +1328,7 @@ storeRequest storeDir pv = Serializer data ReplySError = ReplySError_PrimGet SError - | ReplySError_DerivationOutput SError + | ReplySError_BuildTraceKey SError | ReplySError_GCResult SError | ReplySError_Metadata SError | ReplySError_Missing SError @@ -1365,20 +1365,20 @@ noop ret = Serializer -- *** Realisation -derivationOutputTyped :: NixSerializer ReplySError (System.Nix.Realisation.DerivationOutput OutputName) -derivationOutputTyped = mapErrorS ReplySError_DerivationOutput $ +buildTraceKeyTyped :: NixSerializer ReplySError (System.Nix.Realisation.BuildTraceKey OutputName) +buildTraceKeyTyped = mapErrorS ReplySError_BuildTraceKey $ mapPrismSerializer AlmostPrism { _almostPrism_get = ExceptT . Identity - . Data.Bifunctor.first SError_DerivationOutput - . System.Nix.Realisation.derivationOutputParser + . Data.Bifunctor.first SError_BuildTraceKey + . System.Nix.Realisation.buildTraceKeyParser System.Nix.OutputName.mkOutputName , _almostPrism_put = Data.Text.Lazy.toStrict . Data.Text.Lazy.Builder.toLazyText - . System.Nix.Realisation.derivationOutputBuilder + . System.Nix.Realisation.buildTraceKeyBuilder (System.Nix.StorePath.unStorePathName . System.Nix.OutputName.unOutputName) } text @@ -1421,7 +1421,7 @@ buildResult storeDir pv = Serializer . Data.Map.Strict.fromList . map (\(_, RealisationWithId (a, b)) -> (a, b)) . Data.Map.Strict.toList - <$> getS (mapS derivationOutputTyped realisationWithId) + <$> getS (mapS buildTraceKeyTyped realisationWithId) else pure Nothing pure BuildResult{..} @@ -1434,7 +1434,7 @@ buildResult storeDir pv = Serializer putS time $ Data.Maybe.fromMaybe t0 buildResultStartTime putS time $ Data.Maybe.fromMaybe t0 buildResultStopTime Control.Monad.when (protoVersion_minor pv >= 28) - $ putS (mapS derivationOutputTyped realisationWithId) + $ putS (mapS buildTraceKeyTyped realisationWithId) $ Data.Map.Strict.fromList $ map (\(a, b) -> (a, RealisationWithId (a, b))) $ Data.Map.Strict.toList diff --git a/hnix-store-tests/src/System/Nix/Arbitrary/Realisation.hs b/hnix-store-tests/src/System/Nix/Arbitrary/Realisation.hs index 509b26af..5fa26e51 100644 --- a/hnix-store-tests/src/System/Nix/Arbitrary/Realisation.hs +++ b/hnix-store-tests/src/System/Nix/Arbitrary/Realisation.hs @@ -9,16 +9,16 @@ import System.Nix.Arbitrary.Hash () import System.Nix.Arbitrary.OutputName () import System.Nix.Arbitrary.Signature () import System.Nix.Arbitrary.StorePath () -import System.Nix.Realisation (DerivationOutput, Realisation) +import System.Nix.Realisation (BuildTraceKey, Realisation) import Test.QuickCheck (Arbitrary(..)) import Test.QuickCheck.Arbitrary.Generic (Arg, GenericArbitrary(..), genericArbitrary, genericShrink) instance - ( Arg (DerivationOutput outputName) outputName + ( Arg (BuildTraceKey outputName) outputName , Arbitrary outputName ) => - Arbitrary (DerivationOutput outputName) + Arbitrary (BuildTraceKey outputName) where arbitrary = genericArbitrary shrink = genericShrink diff --git a/hnix-store-tests/tests/RealisationSpec.hs b/hnix-store-tests/tests/RealisationSpec.hs index 30f74f5d..1f0c9f65 100644 --- a/hnix-store-tests/tests/RealisationSpec.hs +++ b/hnix-store-tests/tests/RealisationSpec.hs @@ -14,14 +14,14 @@ import System.Nix.Realisation qualified spec :: Spec spec = do - describe "DerivationOutput" $ do + describe "BuildTraceKey" $ do prop "roundtrips" $ roundtrips ( Data.Text.Lazy.toStrict . Data.Text.Lazy.Builder.toLazyText - . System.Nix.Realisation.derivationOutputBuilder + . System.Nix.Realisation.buildTraceKeyBuilder (System.Nix.StorePath.unStorePathName . System.Nix.OutputName.unOutputName) ) - ( System.Nix.Realisation.derivationOutputParser + ( System.Nix.Realisation.buildTraceKeyParser System.Nix.OutputName.mkOutputName )