packages feed

hercules-ci-cnix-store 0.4.0.0 → 0.4.1.0

raw patch · 8 files changed

+397/−317 lines, 8 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Hercules.CNix.Store: instance GHC.Show.Show Hercules.CNix.Store.DerivationOutput
- Hercules.CNix.Store: instance GHC.Show.Show Hercules.CNix.Store.DerivationOutputDetail
- Hercules.CNix.Store: instance GHC.Show.Show Hercules.CNix.Store.FileIngestionMethod
- Hercules.CNix.Store: instance GHC.Show.Show Hercules.CNix.Store.FixedOutputHash
- Hercules.CNix.Store: instance GHC.Show.Show Hercules.CNix.Store.Hash
- Hercules.CNix.Store: instance GHC.Show.Show Hercules.CNix.Store.HashType
- Hercules.CNix.Store: instance GHC.Show.Show Hercules.CNix.Store.StorePath
- Hercules.CNix.Store.Instances: instance Hercules.CNix.Std.Vector.HasStdVector (GHC.Ptr.Ptr Hercules.CNix.Store.Context.NixStorePath)
- Hercules.CNix.Store.Instances: instance Hercules.CNix.Std.Vector.HasStdVector (GHC.Ptr.Ptr Hercules.CNix.Store.Context.NixStorePathWithOutputs)
- Hercules.CNix.Store.Instances: instance Hercules.CNix.Std.Vector.HasStdVectorCopyable (GHC.Ptr.Ptr Hercules.CNix.Store.Context.NixStorePath)
- Hercules.CNix.Verbosity: instance GHC.Enum.Bounded Hercules.CNix.Verbosity.Verbosity
- Hercules.CNix.Verbosity: instance GHC.Enum.Enum Hercules.CNix.Verbosity.Verbosity
- Hercules.CNix.Verbosity: instance GHC.Read.Read Hercules.CNix.Verbosity.Verbosity
- Hercules.CNix.Verbosity: instance GHC.Show.Show Hercules.CNix.Verbosity.Verbosity
+ Hercules.CNix.Store: instance GHC.Internal.Show.Show Hercules.CNix.Store.DerivationOutput
+ Hercules.CNix.Store: instance GHC.Internal.Show.Show Hercules.CNix.Store.DerivationOutputDetail
+ Hercules.CNix.Store: instance GHC.Internal.Show.Show Hercules.CNix.Store.FileIngestionMethod
+ Hercules.CNix.Store: instance GHC.Internal.Show.Show Hercules.CNix.Store.FixedOutputHash
+ Hercules.CNix.Store: instance GHC.Internal.Show.Show Hercules.CNix.Store.Hash
+ Hercules.CNix.Store: instance GHC.Internal.Show.Show Hercules.CNix.Store.HashType
+ Hercules.CNix.Store: instance GHC.Internal.Show.Show Hercules.CNix.Store.StorePath
+ Hercules.CNix.Store.Instances: instance Hercules.CNix.Std.Vector.HasStdVector (GHC.Internal.Ptr.Ptr Hercules.CNix.Store.Context.NixStorePath)
+ Hercules.CNix.Store.Instances: instance Hercules.CNix.Std.Vector.HasStdVector (GHC.Internal.Ptr.Ptr Hercules.CNix.Store.Context.NixStorePathWithOutputs)
+ Hercules.CNix.Store.Instances: instance Hercules.CNix.Std.Vector.HasStdVectorCopyable (GHC.Internal.Ptr.Ptr Hercules.CNix.Store.Context.NixStorePath)
+ Hercules.CNix.Verbosity: instance GHC.Internal.Enum.Bounded Hercules.CNix.Verbosity.Verbosity
+ Hercules.CNix.Verbosity: instance GHC.Internal.Enum.Enum Hercules.CNix.Verbosity.Verbosity
+ Hercules.CNix.Verbosity: instance GHC.Internal.Read.Read Hercules.CNix.Verbosity.Verbosity
+ Hercules.CNix.Verbosity: instance GHC.Internal.Show.Show Hercules.CNix.Verbosity.Verbosity

Files

CHANGELOG.md view
@@ -5,6 +5,12 @@  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## 0.4.1.0 - 2026-01-06++### Added++ - Nix 2.29 - 2.33 support+ ## 0.4.0.0 - 2025-07-18  ### Changed
cbits/string.cxx view
@@ -1,10 +1,11 @@ #include "hercules-ci-cnix/string.hxx"+#include <cstring>  namespace hercules_ci_cnix {  char * stringdup(const std::string & s) {     char * p = (char *)malloc(s.size() + 1);-    std::copy(s.begin(), s.end(), p);+    std::memcpy(p, s.data(), s.size());     p[s.size()] = '\0';     return p; }
hercules-ci-cnix-store.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.4  name:           hercules-ci-cnix-store-version:        0.4.0.0+version:        0.4.1.0 synopsis:       Haskell bindings for Nix's libstore category:       Nix homepage:       https://docs.hercules-ci.com@@ -24,10 +24,19 @@   description: Whether to enable IDE workarounds. You shouldn't need this.   default: False +flag nix-2_31+  description: nix-store >= 2.31+  default: False+  manual: False+ -- match the C++ language standard Nix is using common cxx-opts-  cxx-options:-    -std=c++2a+  if flag(nix-2_31)+    cxx-options:+      -std=c++23+  else+    cxx-options:+      -std=c++2a    cxx-options:     -Wall@@ -42,12 +51,22 @@   if impl(ghc >= 8.10)     ghc-options:       -optcxx-Wall-      -optcxx-std=c++2a+    if flag(nix-2_31)+      ghc-options:+        -optcxx-std=c++23+    else+      ghc-options:+        -optcxx-std=c++2a   else     -- Remove soon     ghc-options:-      -optc-std=c++2a       -optc-Wall+    if flag(nix-2_31)+      ghc-options:+        -optc-std=c++23+    else+      ghc-options:+        -optc-std=c++2a     if os(darwin)       ghc-options: -pgmc=clang++ @@ -79,7 +98,7 @@       include       cbits   pkgconfig-depends:-      nix-store >= 2.28 && < 2.29+      nix-store >= 2.28 && < 2.34   install-includes:       hercules-ci-cnix/store.hxx       hercules-ci-cnix/string.hxx
include/hercules-ci-cnix/store.hxx view
@@ -2,6 +2,9 @@ #pragma once  #include <nix/store/path-info.hh>+#if NIX_IS_AT_LEAST(2, 29, 0)+#include <nix/store/derived-path-map.hh>+#endif  typedef nix::ref<nix::Store> refStore; @@ -11,4 +14,9 @@ typedef nix::PathSet::iterator PathSetIterator; typedef nix::ref<const nix::ValidPathInfo> refValidPathInfo; +// https://github.com/NixOS/nix/pull/13129+#if NIX_IS_AT_LEAST(2, 29, 0)+typedef nix::DerivedPathMap<nix::StringSet>::Map::iterator DerivationInputsIterator;+#else typedef nix::DerivedPathMap<std::set<nix::OutputName>>::Map::iterator DerivationInputsIterator;+#endif
src/Hercules/CNix.hs view
@@ -38,7 +38,6 @@ C.include "<nix/util/config-global.hh>" C.include "<nix/store/derivations.hh>" C.include "<nix/store/globals.hh>"-C.include "<nix/main/shared.hh>"  C.include "<gc/gc.h>" C.include "<gc/gc_cpp.h>"
src/Hercules/CNix/Settings.hs view
@@ -62,11 +62,20 @@     >>= traverse Std.String.copyToByteString  getExtraPlatforms :: IO (Set ByteString)+#if NIX_IS_AT_LEAST(2, 29, 0) getExtraPlatforms =   byteStringSet     [C.block| std::set<std::string>*{-      return new nix::StringSet(nix::settings.extraPlatforms.get());+      auto extraPlatforms = nix::settings.extraPlatforms.get();+      return new std::set<std::string>(extraPlatforms.begin(), extraPlatforms.end());     }|]+#else+getExtraPlatforms =+  byteStringSet+    [C.block| std::set<std::string>*{+      return new std::set<std::string>(nix::settings.extraPlatforms.get());+    }|]+#endif  getSystem :: IO ByteString getSystem =@@ -76,11 +85,20 @@     }|]  getSystemFeatures :: IO (Set ByteString)+#if NIX_IS_AT_LEAST(2, 29, 0) getSystemFeatures =   byteStringSet     [C.block| std::set<std::string>*{-      return new nix::StringSet(nix::settings.systemFeatures.get());+      auto systemFeatures = nix::settings.systemFeatures.get();+      return new std::set<std::string>(systemFeatures.begin(), systemFeatures.end());     }|]+#else+getSystemFeatures =+  byteStringSet+    [C.block| std::set<std::string>*{+      return new std::set<std::string>(nix::settings.systemFeatures.get());+    }|]+#endif  getMaxBuildJobs :: IO Word getMaxBuildJobs = do
src/Hercules/CNix/Store.hs view
@@ -45,9 +45,8 @@     validPathInfoDeriver',     validPathInfoReferences,     validPathInfoReferences',-     computeFSClosure,-    ClosureParams(..),+    ClosureParams (..),     defaultClosureParams,      -- * Realisation@@ -81,7 +80,6 @@     getDerivationSources',     getDerivationInputs,     getDerivationInputs',-     getDerivationOutputNames,     DerivationOutput (..),     DerivationOutputDetail (..),@@ -102,6 +100,7 @@     HashType (..),      -- * Utilities+     --     -- To be moved and deprecated     Strings,@@ -154,6 +153,8 @@ import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr) import Foreign.Storable (peek) import Hercules.CNix.Encapsulation (HasEncapsulation (..), nullableMoveToForeignPtrWrapper)+import Hercules.CNix.Memory (Delete (delete), Finalizer (finalizer), toForeignPtr, withDelete)+import qualified Hercules.CNix.Memory import Hercules.CNix.Std.Set (StdSet, stdSetCtx) import qualified Hercules.CNix.Std.Set as Std.Set import Hercules.CNix.Std.String (stdStringCtx)@@ -174,8 +175,6 @@     unsafeMallocBS,   ) import qualified Hercules.CNix.Store.Context as C hiding (context)-import Hercules.CNix.Memory (Delete(delete), Finalizer (finalizer), withDelete, toForeignPtr)-import qualified Hercules.CNix.Memory import Hercules.CNix.Store.Instances () import qualified Language.C.Inline.Cpp as C import qualified Language.C.Inline.Cpp.Exception as C@@ -197,6 +196,10 @@ C.include "<nix/store/path-with-outputs.hh>" C.include "<nix/util/signals.hh>" +#if NIX_IS_AT_LEAST(2, 29, 0)+C.include "<nix/store/store-open.hh>"+#endif+ C.include "hercules-ci-cnix/store.hxx"  C.include "hercules-ci-cnix/string.hxx"@@ -222,14 +225,14 @@ openStore =   coerce     [C.throwBlock| refStore * {-      refStore s = openStore();+      refStore s = nix::openStore();       return new refStore(s);     } |]  releaseStore :: Store -> IO () releaseStore (Store store) = delete store -withStore :: MonadUnliftIO m => (Store -> m a) -> m a+withStore :: (MonadUnliftIO m) => (Store -> m a) -> m a withStore m = do   UnliftIO ul <- askUnliftIO   liftIO $ withStore' $ \a -> ul (m a)@@ -241,7 +244,7 @@   bracket openStore releaseStore  withStoreFromURI ::-  MonadUnliftIO m =>+  (MonadUnliftIO m) =>   Text ->   (Store -> m r) ->   m r@@ -251,42 +254,52 @@   liftIO $     withDelete       [C.throwBlock| refStore* {-        refStore s = openStore($bs-cstr:storeURI);+        refStore s = nix::openStore($bs-cstr:storeURI);         return new refStore(s);       }|]       (unlift . f . Store) -storeUri :: MonadIO m => Store -> m ByteString+-- | Returns the human-readable URI. A more complete URI (with params)+-- could be obtained via getReference().render() since Nix 2.31,+-- but is currently not implemented.+-- See https://github.com/NixOS/nix/commit/1b7ffa53af168aab255c9ee4c1ca5a192c269738+{- ORMOLU_DISABLE -}+storeUri :: (MonadIO m) => Store -> m ByteString storeUri (Store store) = liftIO do-  BS.unsafePackMallocCString =<<-    [C.block| const char* {-       std::string uri = (*$(refStore* store))->getUri();-       return stringdup(uri);-     } |]+  BS.unsafePackMallocCString+    =<< [C.block| const char* {+#if NIX_IS_AT_LEAST(2, 31, 0)+      std::string uri = (*$(refStore* store))->config.getHumanReadableURI();+#else+      std::string uri = (*$(refStore* store))->getUri();+#endif+      return stringdup(uri);+    }|]+{- ORMOLU_ENABLE -}  -- | Usually @"/nix/store"@-storeDir :: MonadIO m => Store -> m ByteString+storeDir :: (MonadIO m) => Store -> m ByteString storeDir (Store store) = liftIO do-  BS.unsafePackMallocCString =<<-    [C.block| const char* {-       std::string uri = (*$(refStore* store))->storeDir;-       return stringdup(uri);-     } |]+  BS.unsafePackMallocCString+    =<< [C.block| const char* {+      std::string uri = (*$(refStore* store))->storeDir;+      return stringdup(uri);+    }|]  getStoreProtocolVersion :: Store -> IO Int getStoreProtocolVersion (Store store) =   fromIntegral     <$> [C.throwBlock| int {-       Store &store = **$(refStore* store);-       return store.getProtocol();-     } |]+      Store &store = **$(refStore* store);+      return store.getProtocol();+    }|]  getClientProtocolVersion :: IO Int getClientProtocolVersion =   fromIntegral     <$> [C.throwBlock| int {-       return PROTOCOL_VERSION;-     } |]+      return PROTOCOL_VERSION;+    }|]  -- | Store-agnostic store path representation: hash and name. Does not have a storedir or subpath inside the store path. newtype StorePath = StorePath (ForeignPtr NixStorePath)@@ -445,20 +458,23 @@   set <- Std.Set.new   for_ outputs (\o -> Std.String.withString o (Std.Set.insertP set))   moveToForeignPtrWrapper-    =<< [C.exp| nix::StorePathWithOutputs * {-    new StorePathWithOutputs {*$fptr-ptr:(nix::StorePath *storePath), *$fptr-ptr:(std::set<std::string>* set)}-  }|]+    =<< [C.throwBlock| nix::StorePathWithOutputs * {+      auto nixSet = nix::StringSet{$fptr-ptr:(std::set<std::string>* set)->begin(), $fptr-ptr:(std::set<std::string>* set)->end()};+      return new StorePathWithOutputs {*$fptr-ptr:(nix::StorePath *storePath), nixSet};+    }|]  getStorePath :: StorePathWithOutputs -> IO StorePath getStorePath swo = mask_ do   moveToForeignPtrWrapper     =<< [C.exp| nix::StorePath * {-    new StorePath($fptr-ptr:(nix::StorePathWithOutputs *swo)->path)-  }|]+      new StorePath($fptr-ptr:(nix::StorePathWithOutputs *swo)->path)+    }|]  getOutputs :: StorePathWithOutputs -> IO [ByteString] getOutputs swo = mask_ do-  traverse Std.String.moveToByteString =<< toListP =<< moveToForeignPtrWrapper+  traverse Std.String.moveToByteString+    =<< toListP+    =<< moveToForeignPtrWrapper     =<< [C.throwBlock| std::vector<std::string>* {       auto r = new std::vector<std::string>();       for (auto s : $fptr-ptr:(nix::StorePathWithOutputs *swo)->outputs)@@ -491,11 +507,12 @@ finalizeDerivation =   unsafePerformIO     [C.exp|-    void (*)(Derivation *) {-      [](Derivation *v) {-        delete v;+      void (*)(Derivation *) {+        [](Derivation *v) {+          delete v;+        }       }-    } |]+    |] {-# DEPRECATED finalizeDerivation "Use 'finalizer' instead" #-}  getDerivation :: Store -> StorePath -> IO Derivation@@ -507,7 +524,7 @@       return new Derivation(           store.derivationFromPath(*$fptr-ptr:(nix::StorePath *spwo))         );-    } |]+    }|]  -- Useful for testing getDerivationFromString ::@@ -566,174 +583,175 @@ getDerivationOutputs :: Store -> ByteString -> Derivation -> IO [DerivationOutput] getDerivationOutputs (Store store) drvName (Derivation derivationFPtr) =   withForeignPtr derivationFPtr \derivation ->-  withDelete-    [C.exp| DerivationOutputsIterator* {+    withDelete+      [C.exp| DerivationOutputsIterator* {       new DerivationOutputsIterator($(Derivation *derivation)->outputs.begin())-    }|] \i ->-    fix $ \continue -> do-      isEnd <- (0 /=) <$> [C.exp| bool { *$(DerivationOutputsIterator *i) == $(Derivation *derivation)->outputs.end() }|]-      if isEnd-        then pure []-        else-          ( mask_ do-              alloca \nameP -> alloca \pathP -> alloca \typP -> alloca \fimP ->-                alloca \hashTypeP -> alloca \hashValueP -> alloca \hashSizeP -> do-                  [C.throwBlock| void {-                    Store &store = **$(refStore *store);-                    std::string drvName = std::string($bs-ptr:drvName, $bs-len:drvName);-                    nix::DerivationOutputs::iterator &i = *$(DerivationOutputsIterator *i);-                    const char *&name = *$(const char **nameP);-                    int &typ = *$(int *typP);-                    StorePath *& path = *$(nix::StorePath **pathP);-                    int &fim = *$(int *fimP);-                    int &hashType = *$(int *hashTypeP);-                    char *&hashValue = *$(char **hashValueP);-                    int &hashSize = *$(int *hashSizeP);+    }|]+      \i ->+        fix $ \continue -> do+          isEnd <- (0 /=) <$> [C.exp| bool { *$(DerivationOutputsIterator *i) == $(Derivation *derivation)->outputs.end() }|]+          if isEnd+            then pure []+            else+              ( mask_ do+                  alloca \nameP -> alloca \pathP -> alloca \typP -> alloca \fimP ->+                    alloca \hashTypeP -> alloca \hashValueP -> alloca \hashSizeP -> do+                      [C.throwBlock| void {+                        Store &store = **$(refStore *store);+                        std::string drvName = std::string($bs-ptr:drvName, $bs-len:drvName);+                        nix::DerivationOutputs::iterator &i = *$(DerivationOutputsIterator *i);+                        const char *&name = *$(const char **nameP);+                        int &typ = *$(int *typP);+                        StorePath *& path = *$(nix::StorePath **pathP);+                        int &fim = *$(int *fimP);+                        int &hashType = *$(int *hashTypeP);+                        char *&hashValue = *$(char **hashValueP);+                        int &hashSize = *$(int *hashSizeP); -                    std::string nameString = i->first;-                    name = stringdup(nameString);-                    path = nullptr;-                    std::visit(overloaded {-                      [&](DerivationOutput::InputAddressed doi) -> void {-                        typ = 0;-                        path = new StorePath(doi.path);-                      },-                      [&](DerivationOutput::CAFixed dof) -> void {-                        typ = 1;-                        path = new StorePath(dof.path(store, $(Derivation *derivation)->name, nameString));-                        switch (dof.ca.method.raw) {-                          case ContentAddressMethod::Raw::Text:-                            // FIXME (RFC 92)-                            fim = -1;-                            break;-                          case ContentAddressMethod::Raw::Flat:-                            fim = 0;-                            break;-                          case ContentAddressMethod::Raw::NixArchive:-                            fim = 1;-                            break;-                          case ContentAddressMethod::Raw::Git:-                            // FIXME (git-hashing)-                            fim = -1;-                            break;-                          default:-                            fim = -1;-                            break;-                        }+                        std::string nameString = i->first;+                        name = stringdup(nameString);+                        path = nullptr;+                        std::visit(overloaded {+                          [&](DerivationOutput::InputAddressed doi) -> void {+                            typ = 0;+                            path = new StorePath(doi.path);+                          },+                          [&](DerivationOutput::CAFixed dof) -> void {+                            typ = 1;+                            path = new StorePath(dof.path(store, $(Derivation *derivation)->name, nameString));+                            switch (dof.ca.method.raw) {+                              case ContentAddressMethod::Raw::Text:+                                // FIXME (RFC 92)+                                fim = -1;+                                break;+                              case ContentAddressMethod::Raw::Flat:+                                fim = 0;+                                break;+                              case ContentAddressMethod::Raw::NixArchive:+                                fim = 1;+                                break;+                              case ContentAddressMethod::Raw::Git:+                                // FIXME (git-hashing)+                                fim = -1;+                                break;+                              default:+                                fim = -1;+                                break;+                            } -                        const Hash & hash = dof.ca.hash;+                            const Hash & hash = dof.ca.hash; -                        switch (hash.algo) {-                          case HashAlgorithm::MD5:-                            hashType = 0;-                            break;-                          case HashAlgorithm::SHA1:-                            hashType = 1;-                            break;-                          case HashAlgorithm::SHA256:-                            hashType = 2;-                            break;-                          case HashAlgorithm::SHA512:-                            hashType = 3;-                            break;-                          default:-                            hashType = -1;-                            break;-                        }-                        hashSize = hash.hashSize;-                        hashValue = (char*)malloc(hashSize);-                        std::memcpy((void*)(hashValue),-                                    (void*)(hash.hash),-                                    hashSize);-                      },-                      [&](DerivationOutput::CAFloating dof) -> void {-                        typ = 2;-                        switch(dof.method.raw) {-                          case ContentAddressMethod::Raw::Text:-                            // FIXME (RFC 92)-                            fim = -1;-                            break;-                          case ContentAddressMethod::Raw::Flat:-                            fim = 0;-                            break;-                          case ContentAddressMethod::Raw::NixArchive:-                            fim = 1;-                            break;-                          case ContentAddressMethod::Raw::Git:-                            // FIXME (git-hashing)-                            fim = -1;-                            break;-                          default:-                            fim = -1;-                            break;-                        }-                        switch (dof.hashAlgo) {-                          case HashAlgorithm::MD5:-                            hashType = 0;-                            break;-                          case HashAlgorithm::SHA1:-                            hashType = 1;-                            break;-                          case HashAlgorithm::SHA256:-                            hashType = 2;-                            break;-                          case HashAlgorithm::SHA512:-                            hashType = 3;-                            break;-                          default:-                            hashType = -1;-                            break;-                        }-                      },-                      [&](DerivationOutput::Deferred) -> void {-                        typ = 3;-                      },-                      [&](DerivationOutput::Impure) -> void {-                        typ = 4;-                      },-                    },-                    i->second.raw-                    );-                    i++;-                  }|]-                  name <- unsafePackMallocCString =<< peek nameP-                  path <- nullableMoveToForeignPtrWrapper =<< peek pathP-                  typ <- peek typP-                  let getFileIngestionMethod = peek fimP <&> \case 0 -> Flat; 1 -> Recursive; _ -> panic "getDerivationOutputs: unknown fim"-                      getHashType =-                        peek hashTypeP <&> \case-                          0 -> MD5-                          1 -> SHA1-                          2 -> SHA256-                          3 -> SHA512-                          _ -> panic "getDerivationOutputs: unknown hashType"-                  detail <- case typ of-                    0 -> pure $ DerivationOutputInputAddressed (fromMaybe (panic "getDerivationOutputs: impossible DOIA path missing") path)-                    1 -> do-                      hashValue <- peek hashValueP-                      hashSize <- peek hashSizeP-                      hashString <- SBS.packCStringLen (hashValue, fromIntegral hashSize)-                      free hashValue-                      hashType <- getHashType-                      fim <- getFileIngestionMethod-                      pure $ DerivationOutputCAFixed (FixedOutputHash fim (Hash hashType hashString)) (fromMaybe (panic "getDerivationOutputs: impossible DOCF path missing") path)-                    2 -> do-                      hashType <- getHashType-                      fim <- getFileIngestionMethod-                      pure $ DerivationOutputCAFloating fim hashType-                    3 -> pure DerivationOutputDeferred-                    4 -> panic "getDerivationOutputs: impure derivations not supported yet"-                    _ -> panic "getDerivationOutputs: impossible getDerivationOutputs typ"-                  pure-                    ( DerivationOutput-                        { derivationOutputName = name,-                          derivationOutputPath = path,-                          derivationOutputDetail = detail-                        }-                        :-                    )-          )-            <*> continue+                            switch (hash.algo) {+                              case HashAlgorithm::MD5:+                                hashType = 0;+                                break;+                              case HashAlgorithm::SHA1:+                                hashType = 1;+                                break;+                              case HashAlgorithm::SHA256:+                                hashType = 2;+                                break;+                              case HashAlgorithm::SHA512:+                                hashType = 3;+                                break;+                              default:+                                hashType = -1;+                                break;+                            }+                            hashSize = hash.hashSize;+                            hashValue = (char*)malloc(hashSize);+                            std::memcpy((void*)(hashValue),+                                        (void*)(hash.hash),+                                        hashSize);+                          },+                          [&](DerivationOutput::CAFloating dof) -> void {+                            typ = 2;+                            switch(dof.method.raw) {+                              case ContentAddressMethod::Raw::Text:+                                // FIXME (RFC 92)+                                fim = -1;+                                break;+                              case ContentAddressMethod::Raw::Flat:+                                fim = 0;+                                break;+                              case ContentAddressMethod::Raw::NixArchive:+                                fim = 1;+                                break;+                              case ContentAddressMethod::Raw::Git:+                                // FIXME (git-hashing)+                                fim = -1;+                                break;+                              default:+                                fim = -1;+                                break;+                            }+                            switch (dof.hashAlgo) {+                              case HashAlgorithm::MD5:+                                hashType = 0;+                                break;+                              case HashAlgorithm::SHA1:+                                hashType = 1;+                                break;+                              case HashAlgorithm::SHA256:+                                hashType = 2;+                                break;+                              case HashAlgorithm::SHA512:+                                hashType = 3;+                                break;+                              default:+                                hashType = -1;+                                break;+                            }+                          },+                          [&](DerivationOutput::Deferred) -> void {+                            typ = 3;+                          },+                          [&](DerivationOutput::Impure) -> void {+                            typ = 4;+                          },+                        },+                        i->second.raw+                        );+                        i++;+                      }|]+                      name <- unsafePackMallocCString =<< peek nameP+                      path <- nullableMoveToForeignPtrWrapper =<< peek pathP+                      typ <- peek typP+                      let getFileIngestionMethod = peek fimP <&> \case 0 -> Flat; 1 -> Recursive; _ -> panic "getDerivationOutputs: unknown fim"+                          getHashType =+                            peek hashTypeP <&> \case+                              0 -> MD5+                              1 -> SHA1+                              2 -> SHA256+                              3 -> SHA512+                              _ -> panic "getDerivationOutputs: unknown hashType"+                      detail <- case typ of+                        0 -> pure $ DerivationOutputInputAddressed (fromMaybe (panic "getDerivationOutputs: impossible DOIA path missing") path)+                        1 -> do+                          hashValue <- peek hashValueP+                          hashSize <- peek hashSizeP+                          hashString <- SBS.packCStringLen (hashValue, fromIntegral hashSize)+                          free hashValue+                          hashType <- getHashType+                          fim <- getFileIngestionMethod+                          pure $ DerivationOutputCAFixed (FixedOutputHash fim (Hash hashType hashString)) (fromMaybe (panic "getDerivationOutputs: impossible DOCF path missing") path)+                        2 -> do+                          hashType <- getHashType+                          fim <- getFileIngestionMethod+                          pure $ DerivationOutputCAFloating fim hashType+                        3 -> pure DerivationOutputDeferred+                        4 -> panic "getDerivationOutputs: impure derivations not supported yet"+                        _ -> panic "getDerivationOutputs: impossible getDerivationOutputs typ"+                      pure+                        ( DerivationOutput+                            { derivationOutputName = name,+                              derivationOutputPath = path,+                              derivationOutputDetail = detail+                            }+                            :+                        )+              )+                <*> continue  instance Delete DerivationOutputsIterator where   delete a = [C.block| void { delete $(DerivationOutputsIterator *a); }|]@@ -744,17 +762,17 @@  getDerivationPlatform :: Derivation -> IO ByteString getDerivationPlatform derivation =-  BS.unsafePackMallocCString =<<-    [C.exp| const char* {-       stringdup($fptr-ptr:(Derivation *derivation)->platform)-     } |]+  BS.unsafePackMallocCString+    =<< [C.exp| const char* {+      stringdup($fptr-ptr:(Derivation *derivation)->platform)+    }|]  getDerivationBuilder :: Derivation -> IO ByteString getDerivationBuilder derivation =-  BS.unsafePackMallocCString =<<-    [C.exp| const char* {-       stringdup($fptr-ptr:(Derivation *derivation)->builder)-     } |]+  BS.unsafePackMallocCString+    =<< [C.exp| const char* {+      stringdup($fptr-ptr:(Derivation *derivation)->builder)+    }|]  getDerivationArguments :: Derivation -> IO [ByteString] getDerivationArguments derivation =@@ -790,38 +808,48 @@ getDerivationInputs' :: Derivation -> IO [(StorePath, [ByteString])] getDerivationInputs' (Derivation derivationFPtr) =   withForeignPtr derivationFPtr \derivation ->-  withDelete-    [C.exp| DerivationInputsIterator* {-      new DerivationInputsIterator($(Derivation *derivation)->inputDrvs.map.begin())-    }|]-    $ \i -> fix $ \continue -> do-      isEnd <- (0 /=) <$> [C.exp| bool { *$(DerivationInputsIterator *i) == $(Derivation *derivation)->inputDrvs.map.end() }|]-      if isEnd-        then pure []-        else do-          name <--            [C.throwBlock| nix::StorePath *{-              return new StorePath((*$(DerivationInputsIterator *i))->first);-            }|]-              >>= moveToForeignPtrWrapper-          outs <--            withDelete-              [C.block| Strings* {-                Strings *r = new Strings();+    withDelete+      [C.exp| DerivationInputsIterator* {+        new DerivationInputsIterator($(Derivation *derivation)->inputDrvs.map.begin())+      }|]+      $ \i -> fix $ \continue -> do+        isEnd <- checkIteratorEnd i derivation+        if isEnd+          then pure []+          else do+            name <-+              [C.throwBlock| nix::StorePath *{+                return new StorePath((*$(DerivationInputsIterator *i))->first);+              }|]+                >>= moveToForeignPtrWrapper+            outs <-+              withDelete+                [C.block| Strings* {+                  Strings *r = new Strings(); -                for (const auto & i : (*$(DerivationInputsIterator *i))->second.value) {-                  r->push_back(i);-                }+                  for (const auto & i : (*$(DerivationInputsIterator *i))->second.value) {+                    r->push_back(i);+                  } -                // for (const auto &i : iter->second.childMap) {-                // TODO (RFC 92)-                //}+                  // for (const auto &i : iter->second.childMap) {+                  // TODO (RFC 92)+                  //} -                return r;-              }|]-              toByteStrings-          [C.block| void { (*$(DerivationInputsIterator *i))++; }|]-          ((name, outs) :) <$> continue+                  return r;+                }|]+                toByteStrings+            [C.block| void { (*$(DerivationInputsIterator *i))++; }|]+            ((name, outs) :) <$> continue+  where+#if NIX_IS_AT_LEAST(2, 29, 0)+    checkIteratorEnd i derivation = (0 /=) <$> [C.exp| bool {+      (*$(DerivationInputsIterator *i)) == $(Derivation *derivation)->inputDrvs.map.end()+    }|]+#else+    checkIteratorEnd i derivation = (0 /=) <$> [C.exp| bool {+      *$(DerivationInputsIterator *i) == $(Derivation *derivation)->inputDrvs.map.end()+    }|]+#endif  instance Delete DerivationInputsIterator where   delete a = [C.block| void { delete $(DerivationInputsIterator *a); }|]@@ -838,15 +866,16 @@  getDerivationOutputNames :: ForeignPtr C.Derivation -> IO [ByteString] getDerivationOutputNames fptr =-  withForeignPtr fptr \ptr -> withDelete-    [C.throwBlock| Strings* {+  withForeignPtr fptr \ptr ->+    withDelete+      [C.throwBlock| Strings* {       Strings *r = new Strings();       for (auto i : $(Derivation *ptr)->outputs) {         r->push_back(i.first);       }       return r;     }|]-    toByteStrings+      toByteStrings  instance Delete StringPairs where   delete s = [C.block| void { delete $(StringPairs *s); }|]@@ -965,12 +994,11 @@ {-# NOINLINE finalizeSecretKey #-} finalizeSecretKey =   unsafePerformIO-    [C.exp|-    void (*)(SecretKey *) {+    [C.exp| void (*)(SecretKey *) {       [](SecretKey *v) {         delete v;       }-    } |]+    }|] {-# DEPRECATED finalizeSecretKey "Use 'finalizer' instead" #-}  signPath ::@@ -984,28 +1012,28 @@ signPath (Store store) secretKey (StorePath path) =   (== 1) <$> do     [C.throwBlock| int {-    ReceiveInterrupts _;-    nix::ref<nix::Store> store = *$(refStore *store);-    const StorePath &storePath = *$fptr-ptr:(nix::StorePath *path);-    const SecretKey &secretKey = *$(SecretKey *secretKey);-    auto currentInfo = store->queryPathInfo(storePath);+      ReceiveInterrupts _;+      nix::ref<nix::Store> store = *$(refStore *store);+      const StorePath &storePath = *$fptr-ptr:(nix::StorePath *path);+      const SecretKey &secretKey = *$(SecretKey *secretKey);+      auto currentInfo = store->queryPathInfo(storePath); -    auto info2(*currentInfo);-    info2.sigs.clear();-    {-      auto signer = std::make_unique<LocalSigner>(SecretKey { secretKey });-      info2.sign(*store, *signer);-    }-    assert(!info2.sigs.empty());-    auto sig = *info2.sigs.begin();+      auto info2(*currentInfo);+      info2.sigs.clear();+      {+        auto signer = std::make_unique<LocalSigner>(SecretKey { secretKey });+        info2.sign(*store, *signer);+      }+      assert(!info2.sigs.empty());+      auto sig = *info2.sigs.begin(); -    if (currentInfo->sigs.count(sig)) {-      return 0;-    } else {-      store->addSignatures(storePath, info2.sigs);-      return 1;-    }-  }|]+      if (currentInfo->sigs.count(sig)) {+        return 0;+      } else {+        store->addSignatures(storePath, info2.sigs);+        return 1;+      }+    }|]  -- | Follow symlinks to the store and chop off the parts after the top-level store name followLinksToStorePath :: Store -> ByteString -> IO StorePath@@ -1035,16 +1063,16 @@   StorePath ->   -- | ValidPathInfo or exception   IO (ForeignPtr (Ref ValidPathInfo))-queryPathInfo (Store store) (StorePath pathFPtr) = +queryPathInfo (Store store) (StorePath pathFPtr) =   withForeignPtr pathFPtr \path -> do-  vpi <--    [C.throwBlock| refValidPathInfo* {-      ReceiveInterrupts _;-      Store &store = **$(refStore* store);-      StorePath &path = *$(nix::StorePath *path);-      return new refValidPathInfo(store.queryPathInfo(path));-    }|]-  toForeignPtr vpi+    vpi <-+      [C.throwBlock| refValidPathInfo* {+        ReceiveInterrupts _;+        Store &store = **$(refStore* store);+        StorePath &path = *$(nix::StorePath *path);+        return new refValidPathInfo(store.queryPathInfo(path));+      }|]+    toForeignPtr vpi  -- | Query only the local client cache ("narinfo cache") - does not query the actual store or daemon. --@@ -1057,30 +1085,31 @@   IO (Maybe (Maybe (ForeignPtr (Ref ValidPathInfo)))) queryPathInfoFromClientCache (Store store) (StorePath pathFPtr) =   withForeignPtr pathFPtr \path ->-  alloca \isKnownP -> do-    mvpi <- [C.throwBlock| refValidPathInfo* {-        ReceiveInterrupts _;-        Store &store = **$(refStore* store);-        StorePath &path = *$(nix::StorePath *path);-        bool &isKnown = *$(bool* isKnownP);-        std::optional<std::shared_ptr<const ValidPathInfo>> maybeVPI =-            store.queryPathInfoFromClientCache(path);-        if (!maybeVPI) {-          isKnown = false;-          return nullptr;-        }-        else {-          isKnown = true;-          std::shared_ptr<const ValidPathInfo> &vpi = *maybeVPI;-          if (vpi)-            return new refValidPathInfo(vpi);-          else+    alloca \isKnownP -> do+      mvpi <-+        [C.throwBlock| refValidPathInfo* {+          ReceiveInterrupts _;+          Store &store = **$(refStore* store);+          StorePath &path = *$(nix::StorePath *path);+          bool &isKnown = *$(bool* isKnownP);+          std::optional<std::shared_ptr<const ValidPathInfo>> maybeVPI =+              store.queryPathInfoFromClientCache(path);+          if (!maybeVPI) {+            isKnown = false;             return nullptr;-        }-      }|]-    isKnown <- peek isKnownP <&> (/= 0)-    for (guard isKnown) \_ -> do-      mvpi & traverseNonNull toForeignPtr+          }+          else {+            isKnown = true;+            std::shared_ptr<const ValidPathInfo> &vpi = *maybeVPI;+            if (vpi)+              return new refValidPathInfo(vpi);+            else+              return nullptr;+          }+        }|]+      isKnown <- peek isKnownP <&> (/= 0)+      for (guard isKnown) \_ -> do+        mvpi & traverseNonNull toForeignPtr  instance Finalizer (Ref ValidPathInfo) where   finalizer = finalizeRefValidPathInfo -- must be CAF@@ -1089,10 +1118,9 @@ {-# NOINLINE finalizeRefValidPathInfo #-} finalizeRefValidPathInfo =   unsafePerformIO-    [C.exp|-      void (*)(refValidPathInfo *) {-        [](refValidPathInfo *v){ delete v; }-      }|]+    [C.exp| void (*)(refValidPathInfo *) {+      [](refValidPathInfo *v){ delete v; }+    }|] {-# DEPRECATED finalizeRefValidPathInfo "Use 'finalizer' instead" #-}  -- | The narSize field of a ValidPathInfo struct. Source: path-info.hh / store-api.hh@@ -1100,9 +1128,9 @@ validPathInfoNarSize vpi =   fromIntegral $     toInteger-      [C.pure| long-        { (*$fptr-ptr:(refValidPathInfo* vpi))->narSize }-      |]+      [C.pure| long {+        (*$fptr-ptr:(refValidPathInfo* vpi))->narSize+      }|]  -- | Copy the narHash field of a ValidPathInfo struct. Source: path-info.hh / store-api.hh validPathInfoNarHash32 :: ForeignPtr (Ref ValidPathInfo) -> IO ByteString
src/Hercules/CNix/Util.hs view
@@ -35,13 +35,13 @@ setInterruptThrown =   [C.throwBlock| void {     nix::setInterruptThrown();-  } |]+  }|]  triggerInterrupt :: IO () triggerInterrupt =   [C.throwBlock| void {     nix::unix::triggerInterrupt();-  } |]+  }|]  -- | Install a signal handler that will put Nix into the interrupted state and -- throws 'UserInterrupt' in the main thread (as is usual), assuming this@@ -67,7 +67,8 @@   for_ [sigINT, sigTERM, sigHUP] \sig -> do     result <- [C.exp| int { hercules_install_signal_handler($(int sig)) } |]     when (result /= 0) $-      panic $ "Failed to install synchronous signal handler for signal " <> show sig+      panic $+        "Failed to install synchronous signal handler for signal " <> show sig    -- Install dummy SIGUSR1 handler for Nix interrupt signal propagation   -- (installHandler uses process-wide sigprocmask, so this should apply to all@@ -89,7 +90,7 @@   -- leaks onInterruptPtr   [C.throwBlock| void {     nix::createInterruptCallback($(void (*onInterruptPtr)()));-  } |]+  }|]  #ifndef __GHCIDE__ foreign import ccall "wrapper"