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 +6/−0
- cbits/string.cxx +2/−1
- hercules-ci-cnix-store.cabal +25/−6
- include/hercules-ci-cnix/store.hxx +8/−0
- src/Hercules/CNix.hs +0/−1
- src/Hercules/CNix/Settings.hs +20/−2
- src/Hercules/CNix/Store.hs +331/−303
- src/Hercules/CNix/Util.hs +5/−4
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"