{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}

module Hercules.CNix.Store
  ( module Hercules.CNix.Store,
    module Hercules.CNix.Store.Context,
  )
where

import Control.Exception
import Control.Monad.IO.Unlift
import Data.ByteString.Short (ShortByteString)
import qualified Data.ByteString.Short as SBS
import Data.ByteString.Unsafe (unsafePackMallocCString)
import qualified Data.ByteString.Unsafe as BS
import Data.Coerce (coerce)
import qualified Data.Map as M
import Foreign (alloca, free, nullPtr)
import Foreign.ForeignPtr
import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
import Foreign.Storable (peek)
import Hercules.CNix.Encapsulation (HasEncapsulation (..))
import Hercules.CNix.Std.Set (StdSet, stdSetCtx)
import qualified Hercules.CNix.Std.Set as Std.Set
import Hercules.CNix.Std.String (stdStringCtx)
import qualified Hercules.CNix.Std.String as Std.String
import Hercules.CNix.Std.Vector
import qualified Hercules.CNix.Std.Vector as Std.Vector
import Hercules.CNix.Store.Context
  ( DerivationInputsIterator,
    DerivationOutputsIterator,
    NixStore,
    NixStorePath,
    Ref,
    SecretKey,
    StringPairs,
    Strings,
    ValidPathInfo,
    context,
    unsafeMallocBS,
  )
import qualified Hercules.CNix.Store.Context as C hiding (context)
import Hercules.CNix.Store.Instances ()
import qualified Language.C.Inline.Cpp as C
import qualified Language.C.Inline.Cpp.Exception as C
import Protolude
import System.IO.Unsafe (unsafePerformIO)
import qualified Prelude

C.context (context <> stdVectorCtx <> stdSetCtx <> stdStringCtx)

C.include "<cstring>"

C.include "<nix/config.h>"

C.include "<nix/shared.hh>"

C.include "<nix/store-api.hh>"

C.include "<nix/get-drvs.hh>"

C.include "<nix/derivations.hh>"

C.include "<nix/globals.hh>"

C.include "<nix/path.hh>"

C.include "<variant>"

C.include "<nix/worker-protocol.hh>"

C.include "<nix/path-with-outputs.hh>"

C.include "hercules-ci-cnix/store.hxx"

C.using "namespace nix"

forNonNull :: Applicative m => Ptr a -> (Ptr a -> m b) -> m (Maybe b)
forNonNull :: forall (m :: * -> *) a b.
Applicative m =>
Ptr a -> (Ptr a -> m b) -> m (Maybe b)
forNonNull = ((Ptr a -> m b) -> Ptr a -> m (Maybe b))
-> Ptr a -> (Ptr a -> m b) -> m (Maybe b)
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Ptr a -> m b) -> Ptr a -> m (Maybe b)
forall (m :: * -> *) a b.
Applicative m =>
(Ptr a -> m b) -> Ptr a -> m (Maybe b)
traverseNonNull

traverseNonNull :: Applicative m => (Ptr a -> m b) -> Ptr a -> m (Maybe b)
traverseNonNull :: forall (m :: * -> *) a b.
Applicative m =>
(Ptr a -> m b) -> Ptr a -> m (Maybe b)
traverseNonNull Ptr a -> m b
f Ptr a
p = if Ptr a
p Ptr a -> Ptr a -> Bool
forall a. Eq a => a -> a -> Bool
== Ptr a
forall a. Ptr a
nullPtr then Maybe b -> m (Maybe b)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe b
forall a. Maybe a
Nothing else b -> Maybe b
forall a. a -> Maybe a
Just (b -> Maybe b) -> m b -> m (Maybe b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr a -> m b
f Ptr a
p

newtype Store = Store (Ptr (Ref NixStore))

openStore :: IO Store
openStore :: IO Store
openStore =
  IO (Ptr (Ref NixStore)) -> IO Store
coerce
    [C.throwBlock| refStore * {
      refStore s = openStore();
      return new refStore(s);
    } |]

releaseStore :: Store -> IO ()
releaseStore :: Store -> IO ()
releaseStore (Store Ptr (Ref NixStore)
store) = [C.exp| void { delete $(refStore* store) } |]

withStore :: MonadUnliftIO m => (Store -> m a) -> m a
withStore :: forall (m :: * -> *) a. MonadUnliftIO m => (Store -> m a) -> m a
withStore Store -> m a
m = do
  UnliftIO forall a. m a -> IO a
ul <- m (UnliftIO m)
forall (m :: * -> *). MonadUnliftIO m => m (UnliftIO m)
askUnliftIO
  IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> m a) -> IO a -> m a
forall a b. (a -> b) -> a -> b
$ (Store -> IO a) -> IO a
forall r. (Store -> IO r) -> IO r
withStore' ((Store -> IO a) -> IO a) -> (Store -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Store
a -> m a -> IO a
forall a. m a -> IO a
ul (Store -> m a
m Store
a)

withStore' ::
  (Store -> IO r) ->
  IO r
withStore' :: forall r. (Store -> IO r) -> IO r
withStore' =
  IO Store -> (Store -> IO ()) -> (Store -> IO r) -> IO r
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket IO Store
openStore Store -> IO ()
releaseStore

withStoreFromURI ::
  MonadUnliftIO m =>
  Text ->
  (Store -> m r) ->
  m r
withStoreFromURI :: forall (m :: * -> *) r.
MonadUnliftIO m =>
Text -> (Store -> m r) -> m r
withStoreFromURI Text
storeURIText Store -> m r
f = do
  let storeURI :: ByteString
storeURI = Text -> ByteString
encodeUtf8 Text
storeURIText
  (UnliftIO forall a. m a -> IO a
unlift) <- m (UnliftIO m)
forall (m :: * -> *). MonadUnliftIO m => m (UnliftIO m)
askUnliftIO
  IO r -> m r
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO r -> m r) -> IO r -> m r
forall a b. (a -> b) -> a -> b
$
    IO (Ptr (Ref NixStore))
-> (Ptr (Ref NixStore) -> IO ())
-> (Ptr (Ref NixStore) -> IO r)
-> IO r
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket
      [C.throwBlock| refStore* {
        refStore s = openStore($bs-cstr:storeURI);
        return new refStore(s);
      }|]
      (\Ptr (Ref NixStore)
x -> [C.exp| void { delete $(refStore* x) } |])
      (m r -> IO r
forall a. m a -> IO a
unlift (m r -> IO r)
-> (Ptr (Ref NixStore) -> m r) -> Ptr (Ref NixStore) -> IO r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Store -> m r
f (Store -> m r)
-> (Ptr (Ref NixStore) -> Store) -> Ptr (Ref NixStore) -> m r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr (Ref NixStore) -> Store
Store)

storeUri :: MonadIO m => Store -> m ByteString
storeUri :: forall (m :: * -> *). MonadIO m => Store -> m ByteString
storeUri (Store Ptr (Ref NixStore)
store) =
  IO (Ptr CChar) -> m ByteString
forall (m :: * -> *). MonadIO m => IO (Ptr CChar) -> m ByteString
unsafeMallocBS
    [C.block| const char* {
       std::string uri = (*$(refStore* store))->getUri();
       return strdup(uri.c_str());
     } |]

-- | Usually @"/nix/store"@
storeDir :: MonadIO m => Store -> m ByteString
storeDir :: forall (m :: * -> *). MonadIO m => Store -> m ByteString
storeDir (Store Ptr (Ref NixStore)
store) =
  IO (Ptr CChar) -> m ByteString
forall (m :: * -> *). MonadIO m => IO (Ptr CChar) -> m ByteString
unsafeMallocBS
    [C.block| const char* {
       std::string uri = (*$(refStore* store))->storeDir;
       return strdup(uri.c_str());
     } |]

getStoreProtocolVersion :: Store -> IO Int
getStoreProtocolVersion :: Store -> IO Int
getStoreProtocolVersion (Store Ptr (Ref NixStore)
store) =
  CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral
    (CInt -> Int) -> IO CInt -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [C.throwBlock| int {
       Store &store = **$(refStore* store);
       return store.getProtocol();
     } |]

getClientProtocolVersion :: IO Int
getClientProtocolVersion :: IO Int
getClientProtocolVersion =
  CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral
    (CInt -> Int) -> IO CInt -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [C.throwBlock| int {
       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)

instance HasEncapsulation NixStorePath StorePath where
  moveToForeignPtrWrapper :: Ptr NixStorePath -> IO StorePath
moveToForeignPtrWrapper = Ptr NixStorePath -> IO StorePath
moveStorePath

finalizeStorePath :: FinalizerPtr NixStorePath
{-# NOINLINE finalizeStorePath #-}
finalizeStorePath :: FinalizerPtr NixStorePath
finalizeStorePath =
  IO (FinalizerPtr NixStorePath) -> FinalizerPtr NixStorePath
forall a. IO a -> a
unsafePerformIO
    [C.exp|
      void (*)(nix::StorePath *) {
        [](StorePath *v) {
          delete v;
        }
      }
    |]

-- | Move ownership of a Ptr NixStorePath into 'StorePath'
moveStorePath :: Ptr NixStorePath -> IO StorePath
moveStorePath :: Ptr NixStorePath -> IO StorePath
moveStorePath Ptr NixStorePath
x = ForeignPtr NixStorePath -> StorePath
StorePath (ForeignPtr NixStorePath -> StorePath)
-> IO (ForeignPtr NixStorePath) -> IO StorePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FinalizerPtr NixStorePath
-> Ptr NixStorePath -> IO (ForeignPtr NixStorePath)
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
newForeignPtr FinalizerPtr NixStorePath
finalizeStorePath Ptr NixStorePath
x

-- | Move ownership of a Ptr NixStorePath into 'StorePath'
moveStorePathMaybe :: Ptr NixStorePath -> IO (Maybe StorePath)
moveStorePathMaybe :: Ptr NixStorePath -> IO (Maybe StorePath)
moveStorePathMaybe = (Ptr NixStorePath -> IO StorePath)
-> Ptr NixStorePath -> IO (Maybe StorePath)
forall (m :: * -> *) a b.
Applicative m =>
(Ptr a -> m b) -> Ptr a -> m (Maybe b)
traverseNonNull ((Ptr NixStorePath -> IO StorePath)
 -> Ptr NixStorePath -> IO (Maybe StorePath))
-> (Ptr NixStorePath -> IO StorePath)
-> Ptr NixStorePath
-> IO (Maybe StorePath)
forall a b. (a -> b) -> a -> b
$ (ForeignPtr NixStorePath -> StorePath)
-> IO (ForeignPtr NixStorePath) -> IO StorePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ForeignPtr NixStorePath -> StorePath
StorePath (IO (ForeignPtr NixStorePath) -> IO StorePath)
-> (Ptr NixStorePath -> IO (ForeignPtr NixStorePath))
-> Ptr NixStorePath
-> IO StorePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FinalizerPtr NixStorePath
-> Ptr NixStorePath -> IO (ForeignPtr NixStorePath)
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
newForeignPtr FinalizerPtr NixStorePath
finalizeStorePath

instance Prelude.Show StorePath where
  show :: StorePath -> String
show StorePath
storePath = IO String -> String
forall a. IO a -> a
unsafePerformIO do
    ByteString
bs <-
      Ptr CChar -> IO ByteString
BS.unsafePackMallocCString
        (Ptr CChar -> IO ByteString) -> IO (Ptr CChar) -> IO ByteString
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [C.block| const char* {
          std::string s($fptr-ptr:(nix::StorePath *storePath)->to_string());
          return strdup(s.c_str());
        }|]
    String -> IO String
forall (f :: * -> *) a. Applicative f => a -> f a
pure (String -> IO String) -> String -> IO String
forall a b. (a -> b) -> a -> b
$ Text -> String
forall a b. ConvertText a b => a -> b
toS (Text -> String) -> Text -> String
forall a b. (a -> b) -> a -> b
$ OnDecodeError -> ByteString -> Text
decodeUtf8With OnDecodeError
lenientDecode ByteString
bs

instance Eq StorePath where
  StorePath
a == :: StorePath -> StorePath -> Bool
== StorePath
b = StorePath -> StorePath -> Ordering
forall a. Ord a => a -> a -> Ordering
compare StorePath
a StorePath
b Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
== Ordering
EQ

-- FIXME
instance Ord StorePath where
  compare :: StorePath -> StorePath -> Ordering
compare (StorePath ForeignPtr NixStorePath
a) (StorePath ForeignPtr NixStorePath
b) =
    CInt -> CInt -> Ordering
forall a. Ord a => a -> a -> Ordering
compare
      CInt
0
      [C.pure| int {
        $fptr-ptr:(nix::StorePath *a)->to_string().compare($fptr-ptr:(nix::StorePath *b)->to_string())
      }|]

-- | Create 'StorePath' from hash and name.
--
-- Throws C++ `BadStorePath` exception when invalid.
parseStorePathBaseName :: ByteString -> IO StorePath
parseStorePathBaseName :: ByteString -> IO StorePath
parseStorePathBaseName ByteString
bs =
  Ptr NixStorePath -> IO StorePath
moveStorePath
    (Ptr NixStorePath -> IO StorePath)
-> IO (Ptr NixStorePath) -> IO StorePath
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [C.throwBlock| nix::StorePath *{
      return new StorePath(std::string($bs-ptr:bs, $bs-len:bs));
    }|]

-- | Parse a complete store path including storeDir into a 'StorePath'.
--
-- Throws C++ `BadStorePath` exception when invalid.
parseStorePath :: Store -> ByteString -> IO StorePath
parseStorePath :: Store -> ByteString -> IO StorePath
parseStorePath (Store Ptr (Ref NixStore)
store) ByteString
bs =
  Ptr NixStorePath -> IO StorePath
moveStorePath
    (Ptr NixStorePath -> IO StorePath)
-> IO (Ptr NixStorePath) -> IO StorePath
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [C.throwBlock| nix::StorePath *{
      return new StorePath(std::move((*$(refStore* store))->parseStorePath(std::string($bs-ptr:bs, $bs-len:bs))));
    }|]

getStorePathBaseName :: StorePath -> IO ByteString
getStorePathBaseName :: StorePath -> IO ByteString
getStorePathBaseName (StorePath ForeignPtr NixStorePath
sp) = do
  Ptr CChar -> IO ByteString
BS.unsafePackMallocCString
    (Ptr CChar -> IO ByteString) -> IO (Ptr CChar) -> IO ByteString
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [C.block| const char *{
      std::string s($fptr-ptr:(nix::StorePath *sp)->to_string());
      return strdup(s.c_str());
    }|]

getStorePathHash :: StorePath -> IO ByteString
getStorePathHash :: StorePath -> IO ByteString
getStorePathHash (StorePath ForeignPtr NixStorePath
sp) = do
  Ptr CChar -> IO ByteString
BS.unsafePackMallocCString
    (Ptr CChar -> IO ByteString) -> IO (Ptr CChar) -> IO ByteString
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [C.block| const char *{
      std::string s($fptr-ptr:(nix::StorePath *sp)->hashPart());
      return strdup(s.c_str());
    }|]

storePathToPath :: Store -> StorePath -> IO ByteString
storePathToPath :: Store -> StorePath -> IO ByteString
storePathToPath (Store Ptr (Ref NixStore)
store) (StorePath ForeignPtr NixStorePath
sp) =
  Ptr CChar -> IO ByteString
BS.unsafePackMallocCString
    (Ptr CChar -> IO ByteString) -> IO (Ptr CChar) -> IO ByteString
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [C.block| const char *{
      Store & store = **$(refStore* store);
      StorePath &sp = *$fptr-ptr:(nix::StorePath *sp);
      std::string s(store.printStorePath(sp));
      return strdup(s.c_str());
    }|]

ensurePath :: Store -> StorePath -> IO ()
ensurePath :: Store -> StorePath -> IO ()
ensurePath (Store Ptr (Ref NixStore)
store) (StorePath ForeignPtr NixStorePath
storePath) =
  [C.throwBlock| void {
    ReceiveInterrupts _;
    Store &store = **$(refStore* store);
    StorePath &storePath = *$fptr-ptr:(nix::StorePath *storePath);
    store.ensurePath(storePath);
  } |]

addTemporaryRoot :: Store -> StorePath -> IO ()
addTemporaryRoot :: Store -> StorePath -> IO ()
addTemporaryRoot (Store Ptr (Ref NixStore)
store) StorePath
storePath = do
  [C.throwBlock| void {
    ReceiveInterrupts _;
    Store &store = **$(refStore* store);
    StorePath &storePath = *$fptr-ptr:(nix::StorePath *storePath);
    store.addTempRoot(storePath);
  } |]

clearPathInfoCache :: Store -> IO ()
clearPathInfoCache :: Store -> IO ()
clearPathInfoCache (Store Ptr (Ref NixStore)
store) =
  [C.throwBlock| void {
    (*$(refStore* store))->clearPathInfoCache();
  } |]

clearSubstituterCaches :: IO ()
clearSubstituterCaches :: IO ()
clearSubstituterCaches =
  [C.throwBlock| void {
    auto subs = nix::getDefaultSubstituters();
    for (auto sub : subs) {
      sub->clearPathInfoCache();
    }
  } |]

newtype StorePathWithOutputs = StorePathWithOutputs (ForeignPtr C.NixStorePathWithOutputs)

instance HasEncapsulation C.NixStorePathWithOutputs StorePathWithOutputs where
  moveToForeignPtrWrapper :: Ptr NixStorePathWithOutputs -> IO StorePathWithOutputs
moveToForeignPtrWrapper Ptr NixStorePathWithOutputs
x = ForeignPtr NixStorePathWithOutputs -> StorePathWithOutputs
StorePathWithOutputs (ForeignPtr NixStorePathWithOutputs -> StorePathWithOutputs)
-> IO (ForeignPtr NixStorePathWithOutputs)
-> IO StorePathWithOutputs
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FinalizerPtr NixStorePathWithOutputs
-> Ptr NixStorePathWithOutputs
-> IO (ForeignPtr NixStorePathWithOutputs)
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
newForeignPtr FinalizerPtr NixStorePathWithOutputs
finalizeStorePathWithOutputs Ptr NixStorePathWithOutputs
x

finalizeStorePathWithOutputs :: FinalizerPtr C.NixStorePathWithOutputs
{-# NOINLINE finalizeStorePathWithOutputs #-}
finalizeStorePathWithOutputs :: FinalizerPtr NixStorePathWithOutputs
finalizeStorePathWithOutputs =
  IO (FinalizerPtr NixStorePathWithOutputs)
-> FinalizerPtr NixStorePathWithOutputs
forall a. IO a -> a
unsafePerformIO
    [C.exp|
      void (*)(nix::StorePathWithOutputs *) {
        [](StorePathWithOutputs *v) {
          delete v;
        }
      }
    |]

newStorePathWithOutputs :: StorePath -> [ByteString] -> IO StorePathWithOutputs
newStorePathWithOutputs :: StorePath -> [ByteString] -> IO StorePathWithOutputs
newStorePathWithOutputs StorePath
storePath [ByteString]
outputs = do
  StdSet CStdString
set <- IO (StdSet CStdString)
forall a. HasStdSet a => IO (StdSet a)
Std.Set.new
  [ByteString] -> (ByteString -> IO ()) -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [ByteString]
outputs (\ByteString
o -> ByteString -> (Ptr CStdString -> IO ()) -> IO ()
forall a. ByteString -> (Ptr CStdString -> IO a) -> IO a
Std.String.withString ByteString
o (StdSet CStdString -> Ptr CStdString -> IO ()
forall a. HasStdSet a => StdSet a -> Ptr a -> IO ()
Std.Set.insertP StdSet CStdString
set))
  Ptr NixStorePathWithOutputs -> IO StorePathWithOutputs
forall a b. HasEncapsulation a b => Ptr a -> IO b
moveToForeignPtrWrapper
    (Ptr NixStorePathWithOutputs -> IO StorePathWithOutputs)
-> IO (Ptr NixStorePathWithOutputs) -> IO StorePathWithOutputs
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [C.exp| nix::StorePathWithOutputs * {
    new StorePathWithOutputs {*$fptr-ptr:(nix::StorePath *storePath), *$fptr-ptr:(std::set<std::string>* set)}
  }|]

getStorePath :: StorePathWithOutputs -> IO StorePath
getStorePath :: StorePathWithOutputs -> IO StorePath
getStorePath StorePathWithOutputs
swo = IO StorePath -> IO StorePath
forall a. IO a -> IO a
mask_ do
  Ptr NixStorePath -> IO StorePath
forall a b. HasEncapsulation a b => Ptr a -> IO b
moveToForeignPtrWrapper
    (Ptr NixStorePath -> IO StorePath)
-> IO (Ptr NixStorePath) -> IO StorePath
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [C.exp| nix::StorePath * {
    new StorePath($fptr-ptr:(nix::StorePathWithOutputs *swo)->path)
  }|]

getOutputs :: StorePathWithOutputs -> IO [ByteString]
getOutputs :: StorePathWithOutputs -> IO [ByteString]
getOutputs StorePathWithOutputs
swo = IO [ByteString] -> IO [ByteString]
forall a. IO a -> IO a
mask_ do
  (Ptr CStdString -> IO ByteString)
-> [Ptr CStdString] -> IO [ByteString]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Ptr CStdString -> IO ByteString
Std.String.moveToByteString ([Ptr CStdString] -> IO [ByteString])
-> IO [Ptr CStdString] -> IO [ByteString]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< StdVector CStdString -> IO [Ptr CStdString]
forall a. HasStdVector a => StdVector a -> IO [Ptr a]
toListP (StdVector CStdString -> IO [Ptr CStdString])
-> IO (StdVector CStdString) -> IO [Ptr CStdString]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr (CStdVector CStdString) -> IO (StdVector CStdString)
forall a b. HasEncapsulation a b => Ptr a -> IO b
moveToForeignPtrWrapper
    (Ptr (CStdVector CStdString) -> IO (StdVector CStdString))
-> IO (Ptr (CStdVector CStdString)) -> IO (StdVector CStdString)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [C.throwBlock| std::vector<std::string>* {
      auto r = new std::vector<std::string>();
      for (auto s : $fptr-ptr:(nix::StorePathWithOutputs *swo)->outputs)
        r->push_back(s);
      return r;
    }|]

buildPaths :: Store -> StdVector C.NixStorePathWithOutputs -> IO ()
buildPaths :: Store -> StdVector NixStorePathWithOutputs -> IO ()
buildPaths (Store Ptr (Ref NixStore)
store) (StdVector ForeignPtr (CStdVector NixStorePathWithOutputs)
paths) = do
  [C.throwBlock| void {
    ReceiveInterrupts _;
    Store &store = **$(refStore* store);
    std::vector<StorePathWithOutputs> &paths = *$fptr-ptr:(std::vector<nix::StorePathWithOutputs>* paths);
    store.buildPaths(toDerivedPaths(paths));
  }|]

buildPath :: Store -> StorePathWithOutputs -> IO ()
buildPath :: Store -> StorePathWithOutputs -> IO ()
buildPath Store
store StorePathWithOutputs
spwo = do
  Store -> StdVector NixStorePathWithOutputs -> IO ()
buildPaths Store
store (StdVector NixStorePathWithOutputs -> IO ())
-> IO (StdVector NixStorePathWithOutputs) -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [StorePathWithOutputs] -> IO (StdVector NixStorePathWithOutputs)
forall a' a.
(Coercible a' (ForeignPtr a), HasStdVector a) =>
[a'] -> IO (StdVector a)
Std.Vector.fromListFP [StorePathWithOutputs
spwo]

newtype Derivation = Derivation (ForeignPtr C.Derivation)

instance HasEncapsulation C.Derivation Derivation where
  moveToForeignPtrWrapper :: Ptr Derivation -> IO Derivation
moveToForeignPtrWrapper = (ForeignPtr Derivation -> Derivation)
-> IO (ForeignPtr Derivation) -> IO Derivation
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ForeignPtr Derivation -> Derivation
Derivation (IO (ForeignPtr Derivation) -> IO Derivation)
-> (Ptr Derivation -> IO (ForeignPtr Derivation))
-> Ptr Derivation
-> IO Derivation
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FinalizerPtr Derivation
-> Ptr Derivation -> IO (ForeignPtr Derivation)
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
newForeignPtr FinalizerPtr Derivation
finalizeDerivation

finalizeDerivation :: FinalizerPtr C.Derivation
{-# NOINLINE finalizeDerivation #-}
finalizeDerivation :: FinalizerPtr Derivation
finalizeDerivation =
  IO (FinalizerPtr Derivation) -> FinalizerPtr Derivation
forall a. IO a -> a
unsafePerformIO
    [C.exp|
    void (*)(Derivation *) {
      [](Derivation *v) {
        delete v;
      }
    } |]

getDerivation :: Store -> StorePath -> IO Derivation
getDerivation :: Store -> StorePath -> IO Derivation
getDerivation (Store Ptr (Ref NixStore)
store) (StorePath ForeignPtr NixStorePath
spwo) = do
  Ptr Derivation -> IO Derivation
forall a b. HasEncapsulation a b => Ptr a -> IO b
moveToForeignPtrWrapper
    (Ptr Derivation -> IO Derivation)
-> IO (Ptr Derivation) -> IO Derivation
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [C.throwBlock| Derivation *{
      ReceiveInterrupts _;
      Store &store = **$(refStore* store);
      return new Derivation(
          store.derivationFromPath(*$fptr-ptr:(nix::StorePath *spwo))
        );
    } |]

-- Useful for testing
getDerivationFromString ::
  Store ->
  -- | Derivation name (store path name with ".drv" extension removed)
  ByteString ->
  -- | Contents
  ByteString ->
  IO Derivation
getDerivationFromString :: Store -> ByteString -> ByteString -> IO Derivation
getDerivationFromString (Store Ptr (Ref NixStore)
store) ByteString
name ByteString
contents = do
  Ptr Derivation -> IO Derivation
forall a b. HasEncapsulation a b => Ptr a -> IO b
moveToForeignPtrWrapper
    (Ptr Derivation -> IO Derivation)
-> IO (Ptr Derivation) -> IO Derivation
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [C.throwBlock| Derivation *{
      Store &store = **$(refStore* store);
      std::string name($bs-ptr:name, $bs-len:name);
      return new Derivation(parseDerivation(store, std::string($bs-ptr:contents, $bs-len:contents), name));
    }|]

getDerivationNameFromPath :: StorePath -> IO ByteString
getDerivationNameFromPath :: StorePath -> IO ByteString
getDerivationNameFromPath StorePath
storePath =
  Ptr CChar -> IO ByteString
BS.unsafePackMallocCString
    (Ptr CChar -> IO ByteString) -> IO (Ptr CChar) -> IO ByteString
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [C.throwBlock| const char *{
      StorePath &sp = *$fptr-ptr:(nix::StorePath *storePath);
      std::string s(Derivation::nameFromPath(sp));
      return strdup(s.c_str());
    }|]

data DerivationOutput = DerivationOutput
  { DerivationOutput -> ByteString
derivationOutputName :: !ByteString,
    DerivationOutput -> Maybe StorePath
derivationOutputPath :: !(Maybe StorePath),
    DerivationOutput -> DerivationOutputDetail
derivationOutputDetail :: !DerivationOutputDetail
  }
  deriving (DerivationOutput -> DerivationOutput -> Bool
(DerivationOutput -> DerivationOutput -> Bool)
-> (DerivationOutput -> DerivationOutput -> Bool)
-> Eq DerivationOutput
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DerivationOutput -> DerivationOutput -> Bool
$c/= :: DerivationOutput -> DerivationOutput -> Bool
== :: DerivationOutput -> DerivationOutput -> Bool
$c== :: DerivationOutput -> DerivationOutput -> Bool
Eq, Int -> DerivationOutput -> ShowS
[DerivationOutput] -> ShowS
DerivationOutput -> String
(Int -> DerivationOutput -> ShowS)
-> (DerivationOutput -> String)
-> ([DerivationOutput] -> ShowS)
-> Show DerivationOutput
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DerivationOutput] -> ShowS
$cshowList :: [DerivationOutput] -> ShowS
show :: DerivationOutput -> String
$cshow :: DerivationOutput -> String
showsPrec :: Int -> DerivationOutput -> ShowS
$cshowsPrec :: Int -> DerivationOutput -> ShowS
Show)

data DerivationOutputDetail
  = DerivationOutputInputAddressed StorePath
  | DerivationOutputCAFixed FixedOutputHash StorePath
  | DerivationOutputCAFloating FileIngestionMethod HashType
  | DerivationOutputDeferred
  deriving (DerivationOutputDetail -> DerivationOutputDetail -> Bool
(DerivationOutputDetail -> DerivationOutputDetail -> Bool)
-> (DerivationOutputDetail -> DerivationOutputDetail -> Bool)
-> Eq DerivationOutputDetail
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DerivationOutputDetail -> DerivationOutputDetail -> Bool
$c/= :: DerivationOutputDetail -> DerivationOutputDetail -> Bool
== :: DerivationOutputDetail -> DerivationOutputDetail -> Bool
$c== :: DerivationOutputDetail -> DerivationOutputDetail -> Bool
Eq, Int -> DerivationOutputDetail -> ShowS
[DerivationOutputDetail] -> ShowS
DerivationOutputDetail -> String
(Int -> DerivationOutputDetail -> ShowS)
-> (DerivationOutputDetail -> String)
-> ([DerivationOutputDetail] -> ShowS)
-> Show DerivationOutputDetail
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DerivationOutputDetail] -> ShowS
$cshowList :: [DerivationOutputDetail] -> ShowS
show :: DerivationOutputDetail -> String
$cshow :: DerivationOutputDetail -> String
showsPrec :: Int -> DerivationOutputDetail -> ShowS
$cshowsPrec :: Int -> DerivationOutputDetail -> ShowS
Show)

data FixedOutputHash = FixedOutputHash !FileIngestionMethod {-# UNPACK #-} !Hash
  deriving (FixedOutputHash -> FixedOutputHash -> Bool
(FixedOutputHash -> FixedOutputHash -> Bool)
-> (FixedOutputHash -> FixedOutputHash -> Bool)
-> Eq FixedOutputHash
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FixedOutputHash -> FixedOutputHash -> Bool
$c/= :: FixedOutputHash -> FixedOutputHash -> Bool
== :: FixedOutputHash -> FixedOutputHash -> Bool
$c== :: FixedOutputHash -> FixedOutputHash -> Bool
Eq, Int -> FixedOutputHash -> ShowS
[FixedOutputHash] -> ShowS
FixedOutputHash -> String
(Int -> FixedOutputHash -> ShowS)
-> (FixedOutputHash -> String)
-> ([FixedOutputHash] -> ShowS)
-> Show FixedOutputHash
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FixedOutputHash] -> ShowS
$cshowList :: [FixedOutputHash] -> ShowS
show :: FixedOutputHash -> String
$cshow :: FixedOutputHash -> String
showsPrec :: Int -> FixedOutputHash -> ShowS
$cshowsPrec :: Int -> FixedOutputHash -> ShowS
Show)

-- | See @content-address.hh@
data FileIngestionMethod = Flat | Recursive
  deriving (FileIngestionMethod -> FileIngestionMethod -> Bool
(FileIngestionMethod -> FileIngestionMethod -> Bool)
-> (FileIngestionMethod -> FileIngestionMethod -> Bool)
-> Eq FileIngestionMethod
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FileIngestionMethod -> FileIngestionMethod -> Bool
$c/= :: FileIngestionMethod -> FileIngestionMethod -> Bool
== :: FileIngestionMethod -> FileIngestionMethod -> Bool
$c== :: FileIngestionMethod -> FileIngestionMethod -> Bool
Eq, Int -> FileIngestionMethod -> ShowS
[FileIngestionMethod] -> ShowS
FileIngestionMethod -> String
(Int -> FileIngestionMethod -> ShowS)
-> (FileIngestionMethod -> String)
-> ([FileIngestionMethod] -> ShowS)
-> Show FileIngestionMethod
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FileIngestionMethod] -> ShowS
$cshowList :: [FileIngestionMethod] -> ShowS
show :: FileIngestionMethod -> String
$cshow :: FileIngestionMethod -> String
showsPrec :: Int -> FileIngestionMethod -> ShowS
$cshowsPrec :: Int -> FileIngestionMethod -> ShowS
Show)

-- | See @hash.hh@
data Hash = Hash !HashType {-# UNPACK #-} !ShortByteString
  deriving (Hash -> Hash -> Bool
(Hash -> Hash -> Bool) -> (Hash -> Hash -> Bool) -> Eq Hash
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Hash -> Hash -> Bool
$c/= :: Hash -> Hash -> Bool
== :: Hash -> Hash -> Bool
$c== :: Hash -> Hash -> Bool
Eq, Int -> Hash -> ShowS
[Hash] -> ShowS
Hash -> String
(Int -> Hash -> ShowS)
-> (Hash -> String) -> ([Hash] -> ShowS) -> Show Hash
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Hash] -> ShowS
$cshowList :: [Hash] -> ShowS
show :: Hash -> String
$cshow :: Hash -> String
showsPrec :: Int -> Hash -> ShowS
$cshowsPrec :: Int -> Hash -> ShowS
Show)

-- | See @hash.hh@
data HashType = MD5 | SHA1 | SHA256 | SHA512
  deriving (HashType -> HashType -> Bool
(HashType -> HashType -> Bool)
-> (HashType -> HashType -> Bool) -> Eq HashType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: HashType -> HashType -> Bool
$c/= :: HashType -> HashType -> Bool
== :: HashType -> HashType -> Bool
$c== :: HashType -> HashType -> Bool
Eq, Int -> HashType -> ShowS
[HashType] -> ShowS
HashType -> String
(Int -> HashType -> ShowS)
-> (HashType -> String) -> ([HashType] -> ShowS) -> Show HashType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [HashType] -> ShowS
$cshowList :: [HashType] -> ShowS
show :: HashType -> String
$cshow :: HashType -> String
showsPrec :: Int -> HashType -> ShowS
$cshowsPrec :: Int -> HashType -> ShowS
Show)

getDerivationOutputs :: Store -> ByteString -> Derivation -> IO [DerivationOutput]
getDerivationOutputs :: Store -> ByteString -> Derivation -> IO [DerivationOutput]
getDerivationOutputs (Store Ptr (Ref NixStore)
store) ByteString
drvName (Derivation ForeignPtr Derivation
derivation) =
  IO (Ptr DerivationOutputsIterator)
-> (Ptr DerivationOutputsIterator -> IO ())
-> (Ptr DerivationOutputsIterator -> IO [DerivationOutput])
-> IO [DerivationOutput]
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket
    [C.exp| DerivationOutputsIterator* {
      new DerivationOutputsIterator($fptr-ptr:(Derivation *derivation)->outputs.begin())
    }|]
    Ptr DerivationOutputsIterator -> IO ()
deleteDerivationOutputsIterator
    ((Ptr DerivationOutputsIterator -> IO [DerivationOutput])
 -> IO [DerivationOutput])
-> (Ptr DerivationOutputsIterator -> IO [DerivationOutput])
-> IO [DerivationOutput]
forall a b. (a -> b) -> a -> b
$ \Ptr DerivationOutputsIterator
i -> (IO [DerivationOutput] -> IO [DerivationOutput])
-> IO [DerivationOutput]
forall a. (a -> a) -> a
fix ((IO [DerivationOutput] -> IO [DerivationOutput])
 -> IO [DerivationOutput])
-> (IO [DerivationOutput] -> IO [DerivationOutput])
-> IO [DerivationOutput]
forall a b. (a -> b) -> a -> b
$ \IO [DerivationOutput]
continue -> do
      Bool
isEnd <- (CBool
0 CBool -> CBool -> Bool
forall a. Eq a => a -> a -> Bool
/=) (CBool -> Bool) -> IO CBool -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [C.exp| bool { *$(DerivationOutputsIterator *i) == $fptr-ptr:(Derivation *derivation)->outputs.end() }|]
      if Bool
isEnd
        then [DerivationOutput] -> IO [DerivationOutput]
forall (f :: * -> *) a. Applicative f => a -> f a
pure []
        else
          ( IO ([DerivationOutput] -> [DerivationOutput])
-> IO ([DerivationOutput] -> [DerivationOutput])
forall a. IO a -> IO a
mask_ do
              (Ptr (Ptr CChar) -> IO ([DerivationOutput] -> [DerivationOutput]))
-> IO ([DerivationOutput] -> [DerivationOutput])
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca \Ptr (Ptr CChar)
nameP -> (Ptr (Ptr NixStorePath)
 -> IO ([DerivationOutput] -> [DerivationOutput]))
-> IO ([DerivationOutput] -> [DerivationOutput])
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca \Ptr (Ptr NixStorePath)
pathP -> (Ptr CInt -> IO ([DerivationOutput] -> [DerivationOutput]))
-> IO ([DerivationOutput] -> [DerivationOutput])
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca \Ptr CInt
typP -> (Ptr CInt -> IO ([DerivationOutput] -> [DerivationOutput]))
-> IO ([DerivationOutput] -> [DerivationOutput])
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca \Ptr CInt
fimP ->
                (Ptr CInt -> IO ([DerivationOutput] -> [DerivationOutput]))
-> IO ([DerivationOutput] -> [DerivationOutput])
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca \Ptr CInt
hashTypeP -> (Ptr (Ptr CChar) -> IO ([DerivationOutput] -> [DerivationOutput]))
-> IO ([DerivationOutput] -> [DerivationOutput])
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca \Ptr (Ptr CChar)
hashValueP -> (Ptr CInt -> IO ([DerivationOutput] -> [DerivationOutput]))
-> IO ([DerivationOutput] -> [DerivationOutput])
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca \Ptr CInt
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 = strdup(nameString.c_str());
                    path = nullptr;
                    std::visit(overloaded {
                      [&](DerivationOutputInputAddressed doi) -> void {
                        typ = 0;
                        path = new StorePath(doi.path);
                      },
                      [&](DerivationOutputCAFixed dof) -> void {
                        typ = 1;
                        path = new StorePath(dof.path(store, $fptr-ptr:(Derivation *derivation)->name, nameString));
                        switch (dof.hash.method) {
                          case nix::FileIngestionMethod::Flat:
                            fim = 0;
                            break;
                          case nix::FileIngestionMethod::Recursive:
                            fim = 1;
                            break;
                          default:
                            fim = -1;
                            break;
                        }
                        switch (dof.hash.hash.type) {
                          case htMD5: 
                            hashType = 0;
                            break;
                          case htSHA1: 
                            hashType = 1;
                            break;
                          case htSHA256: 
                            hashType = 2;
                            break;
                          case htSHA512: 
                            hashType = 3;
                            break;
                          default:
                            hashType = -1;
                            break;
                        }
                        hashSize = dof.hash.hash.hashSize;
                        hashValue = (char*)malloc(hashSize);
                        std::memcpy((void*)(hashValue),
                                    (void*)(dof.hash.hash.hash),
                                    hashSize);
                      },
                      [&](DerivationOutputCAFloating dof) -> void {
                        typ = 2;
                        switch (dof.method) {
                          case nix::FileIngestionMethod::Flat:
                            fim = 0;
                            break;
                          case nix::FileIngestionMethod::Recursive:
                            fim = 1;
                            break;
                          default:
                            fim = -1;
                            break;
                        }
                        switch (dof.hashType) {
                          case htMD5: 
                            hashType = 0;
                            break;
                          case htSHA1: 
                            hashType = 1;
                            break;
                          case htSHA256: 
                            hashType = 2;
                            break;
                          case htSHA512: 
                            hashType = 3;
                            break;
                          default:
                            hashType = -1;
                            break;
                        }
                      },
                      [&](DerivationOutputDeferred) -> void {
                        typ = 3;
                      },
#if NIX_IS_AT_LEAST(2,8,0)
                      [&](DerivationOutputImpure) -> void {
                        typ = 4;
                      },
#endif
                    },
#if NIX_IS_AT_LEAST(2,8,0)
                      i->second.raw()
#else
                      i->second.output
#endif
                    );
                    i++;
                  }|]
                  ByteString
name <- Ptr CChar -> IO ByteString
unsafePackMallocCString (Ptr CChar -> IO ByteString) -> IO (Ptr CChar) -> IO ByteString
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr (Ptr CChar) -> IO (Ptr CChar)
forall a. Storable a => Ptr a -> IO a
peek Ptr (Ptr CChar)
nameP
                  Maybe StorePath
path <- Ptr NixStorePath -> IO (Maybe StorePath)
moveStorePathMaybe (Ptr NixStorePath -> IO (Maybe StorePath))
-> IO (Ptr NixStorePath) -> IO (Maybe StorePath)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr (Ptr NixStorePath) -> IO (Ptr NixStorePath)
forall a. Storable a => Ptr a -> IO a
peek Ptr (Ptr NixStorePath)
pathP
                  CInt
typ <- Ptr CInt -> IO CInt
forall a. Storable a => Ptr a -> IO a
peek Ptr CInt
typP
                  let getFileIngestionMethod :: IO FileIngestionMethod
getFileIngestionMethod = Ptr CInt -> IO CInt
forall a. Storable a => Ptr a -> IO a
peek Ptr CInt
fimP IO CInt -> (CInt -> FileIngestionMethod) -> IO FileIngestionMethod
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \case CInt
0 -> FileIngestionMethod
Flat; CInt
1 -> FileIngestionMethod
Recursive; CInt
_ -> Text -> FileIngestionMethod
forall a. HasCallStack => Text -> a
panic Text
"getDerivationOutputs: unknown fim"
                      getHashType :: IO HashType
getHashType =
                        Ptr CInt -> IO CInt
forall a. Storable a => Ptr a -> IO a
peek Ptr CInt
hashTypeP IO CInt -> (CInt -> HashType) -> IO HashType
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \case
                          CInt
0 -> HashType
MD5
                          CInt
1 -> HashType
SHA1
                          CInt
2 -> HashType
SHA256
                          CInt
3 -> HashType
SHA512
                          CInt
_ -> Text -> HashType
forall a. HasCallStack => Text -> a
panic Text
"getDerivationOutputs: unknown hashType"
                  DerivationOutputDetail
detail <- case CInt
typ of
                    CInt
0 -> DerivationOutputDetail -> IO DerivationOutputDetail
forall (f :: * -> *) a. Applicative f => a -> f a
pure (DerivationOutputDetail -> IO DerivationOutputDetail)
-> DerivationOutputDetail -> IO DerivationOutputDetail
forall a b. (a -> b) -> a -> b
$ StorePath -> DerivationOutputDetail
DerivationOutputInputAddressed (StorePath -> Maybe StorePath -> StorePath
forall a. a -> Maybe a -> a
fromMaybe (Text -> StorePath
forall a. HasCallStack => Text -> a
panic Text
"getDerivationOutputs: impossible DOIA path missing") Maybe StorePath
path)
                    CInt
1 -> do
                      Ptr CChar
hashValue <- Ptr (Ptr CChar) -> IO (Ptr CChar)
forall a. Storable a => Ptr a -> IO a
peek Ptr (Ptr CChar)
hashValueP
                      CInt
hashSize <- Ptr CInt -> IO CInt
forall a. Storable a => Ptr a -> IO a
peek Ptr CInt
hashSizeP
                      ShortByteString
hashString <- CStringLen -> IO ShortByteString
SBS.packCStringLen (Ptr CChar
hashValue, CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
hashSize)
                      Ptr CChar -> IO ()
forall a. Ptr a -> IO ()
free Ptr CChar
hashValue
                      HashType
hashType <- IO HashType
getHashType
                      FileIngestionMethod
fim <- IO FileIngestionMethod
getFileIngestionMethod
                      DerivationOutputDetail -> IO DerivationOutputDetail
forall (f :: * -> *) a. Applicative f => a -> f a
pure (DerivationOutputDetail -> IO DerivationOutputDetail)
-> DerivationOutputDetail -> IO DerivationOutputDetail
forall a b. (a -> b) -> a -> b
$ FixedOutputHash -> StorePath -> DerivationOutputDetail
DerivationOutputCAFixed (FileIngestionMethod -> Hash -> FixedOutputHash
FixedOutputHash FileIngestionMethod
fim (HashType -> ShortByteString -> Hash
Hash HashType
hashType ShortByteString
hashString)) (StorePath -> Maybe StorePath -> StorePath
forall a. a -> Maybe a -> a
fromMaybe (Text -> StorePath
forall a. HasCallStack => Text -> a
panic Text
"getDerivationOutputs: impossible DOCF path missing") Maybe StorePath
path)
                    CInt
2 -> do
                      HashType
hashType <- IO HashType
getHashType
                      FileIngestionMethod
fim <- IO FileIngestionMethod
getFileIngestionMethod
                      DerivationOutputDetail -> IO DerivationOutputDetail
forall (f :: * -> *) a. Applicative f => a -> f a
pure (DerivationOutputDetail -> IO DerivationOutputDetail)
-> DerivationOutputDetail -> IO DerivationOutputDetail
forall a b. (a -> b) -> a -> b
$ FileIngestionMethod -> HashType -> DerivationOutputDetail
DerivationOutputCAFloating FileIngestionMethod
fim HashType
hashType
                    CInt
3 -> DerivationOutputDetail -> IO DerivationOutputDetail
forall (f :: * -> *) a. Applicative f => a -> f a
pure DerivationOutputDetail
DerivationOutputDeferred
                    CInt
4 -> Text -> IO DerivationOutputDetail
forall a. HasCallStack => Text -> a
panic Text
"getDerivationOutputs: impure derivations not supported yet"
                    CInt
_ -> Text -> IO DerivationOutputDetail
forall a. HasCallStack => Text -> a
panic Text
"getDerivationOutputs: impossible getDerivationOutputs typ"
                  ([DerivationOutput] -> [DerivationOutput])
-> IO ([DerivationOutput] -> [DerivationOutput])
forall (f :: * -> *) a. Applicative f => a -> f a
pure
                    ( DerivationOutput :: ByteString
-> Maybe StorePath -> DerivationOutputDetail -> DerivationOutput
DerivationOutput
                        { derivationOutputName :: ByteString
derivationOutputName = ByteString
name,
                          derivationOutputPath :: Maybe StorePath
derivationOutputPath = Maybe StorePath
path,
                          derivationOutputDetail :: DerivationOutputDetail
derivationOutputDetail = DerivationOutputDetail
detail
                        }
                        DerivationOutput -> [DerivationOutput] -> [DerivationOutput]
forall a. a -> [a] -> [a]
:
                    )
          )
            IO ([DerivationOutput] -> [DerivationOutput])
-> IO [DerivationOutput] -> IO [DerivationOutput]
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> IO [DerivationOutput]
continue

deleteDerivationOutputsIterator :: Ptr DerivationOutputsIterator -> IO ()
deleteDerivationOutputsIterator :: Ptr DerivationOutputsIterator -> IO ()
deleteDerivationOutputsIterator Ptr DerivationOutputsIterator
a = [C.block| void { delete $(DerivationOutputsIterator *a); }|]

getDerivationPlatform :: Derivation -> IO ByteString
getDerivationPlatform :: Derivation -> IO ByteString
getDerivationPlatform Derivation
derivation =
  IO (Ptr CChar) -> IO ByteString
forall (m :: * -> *). MonadIO m => IO (Ptr CChar) -> m ByteString
unsafeMallocBS
    [C.exp| const char* {
       strdup($fptr-ptr:(Derivation *derivation)->platform.c_str())
     } |]

getDerivationBuilder :: Derivation -> IO ByteString
getDerivationBuilder :: Derivation -> IO ByteString
getDerivationBuilder Derivation
derivation =
  IO (Ptr CChar) -> IO ByteString
forall (m :: * -> *). MonadIO m => IO (Ptr CChar) -> m ByteString
unsafeMallocBS
    [C.exp| const char* {
       strdup($fptr-ptr:(Derivation *derivation)->builder.c_str())
     } |]

getDerivationArguments :: Derivation -> IO [ByteString]
getDerivationArguments :: Derivation -> IO [ByteString]
getDerivationArguments Derivation
derivation =
  IO (Ptr Strings)
-> (Ptr Strings -> IO ())
-> (Ptr Strings -> IO [ByteString])
-> IO [ByteString]
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket
    [C.throwBlock| Strings* {
      Strings *r = new Strings();
      for (auto i : $fptr-ptr:(Derivation *derivation)->args) {
        r->push_back(i);
      }
      return r;
    }|]
    Ptr Strings -> IO ()
deleteStrings
    Ptr Strings -> IO [ByteString]
toByteStrings

getDerivationSources :: Store -> Derivation -> IO [StorePath]
getDerivationSources :: Store -> Derivation -> IO [StorePath]
getDerivationSources Store
_ = Derivation -> IO [StorePath]
getDerivationSources'

getDerivationSources' :: Derivation -> IO [StorePath]
getDerivationSources' :: Derivation -> IO [StorePath]
getDerivationSources' Derivation
derivation = IO [StorePath] -> IO [StorePath]
forall a. IO a -> IO a
mask_ do
  StdVector (Ptr NixStorePath)
vec <-
    Ptr (CStdVector (Ptr NixStorePath))
-> IO (StdVector (Ptr NixStorePath))
forall a b. HasEncapsulation a b => Ptr a -> IO b
moveToForeignPtrWrapper
      (Ptr (CStdVector (Ptr NixStorePath))
 -> IO (StdVector (Ptr NixStorePath)))
-> IO (Ptr (CStdVector (Ptr NixStorePath)))
-> IO (StdVector (Ptr NixStorePath))
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [C.throwBlock| std::vector<nix::StorePath*>* {
        auto r = new std::vector<StorePath *>();
        for (auto s : $fptr-ptr:(Derivation *derivation)->inputSrcs)
          r->push_back(new StorePath(s));
        return r;
      }|]
  (Ptr NixStorePath -> IO StorePath)
-> [Ptr NixStorePath] -> IO [StorePath]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Ptr NixStorePath -> IO StorePath
moveStorePath ([Ptr NixStorePath] -> IO [StorePath])
-> IO [Ptr NixStorePath] -> IO [StorePath]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< StdVector (Ptr NixStorePath) -> IO [Ptr NixStorePath]
forall a.
(HasStdVectorCopyable a, Storable a) =>
StdVector a -> IO [a]
Std.Vector.toList StdVector (Ptr NixStorePath)
vec

getDerivationInputs :: Store -> Derivation -> IO [(StorePath, [ByteString])]
getDerivationInputs :: Store -> Derivation -> IO [(StorePath, [ByteString])]
getDerivationInputs Store
_ = Derivation -> IO [(StorePath, [ByteString])]
getDerivationInputs'

getDerivationInputs' :: Derivation -> IO [(StorePath, [ByteString])]
getDerivationInputs' :: Derivation -> IO [(StorePath, [ByteString])]
getDerivationInputs' Derivation
derivation =
  IO (Ptr DerivationInputsIterator)
-> (Ptr DerivationInputsIterator -> IO ())
-> (Ptr DerivationInputsIterator -> IO [(StorePath, [ByteString])])
-> IO [(StorePath, [ByteString])]
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket
    [C.exp| DerivationInputsIterator* {
      new DerivationInputsIterator($fptr-ptr:(Derivation *derivation)->inputDrvs.begin())
    }|]
    Ptr DerivationInputsIterator -> IO ()
deleteDerivationInputsIterator
    ((Ptr DerivationInputsIterator -> IO [(StorePath, [ByteString])])
 -> IO [(StorePath, [ByteString])])
-> (Ptr DerivationInputsIterator -> IO [(StorePath, [ByteString])])
-> IO [(StorePath, [ByteString])]
forall a b. (a -> b) -> a -> b
$ \Ptr DerivationInputsIterator
i -> (IO [(StorePath, [ByteString])] -> IO [(StorePath, [ByteString])])
-> IO [(StorePath, [ByteString])]
forall a. (a -> a) -> a
fix ((IO [(StorePath, [ByteString])] -> IO [(StorePath, [ByteString])])
 -> IO [(StorePath, [ByteString])])
-> (IO [(StorePath, [ByteString])]
    -> IO [(StorePath, [ByteString])])
-> IO [(StorePath, [ByteString])]
forall a b. (a -> b) -> a -> b
$ \IO [(StorePath, [ByteString])]
continue -> do
      Bool
isEnd <- (CBool
0 CBool -> CBool -> Bool
forall a. Eq a => a -> a -> Bool
/=) (CBool -> Bool) -> IO CBool -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [C.exp| bool { *$(DerivationInputsIterator *i) == $fptr-ptr:(Derivation *derivation)->inputDrvs.end() }|]
      if Bool
isEnd
        then [(StorePath, [ByteString])] -> IO [(StorePath, [ByteString])]
forall (f :: * -> *) a. Applicative f => a -> f a
pure []
        else do
          StorePath
name <-
            [C.throwBlock| nix::StorePath *{
              return new StorePath((*$(DerivationInputsIterator *i))->first);
            }|]
              IO (Ptr NixStorePath)
-> (Ptr NixStorePath -> IO StorePath) -> IO StorePath
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Ptr NixStorePath -> IO StorePath
moveStorePath
          [ByteString]
outs <-
            IO (Ptr Strings)
-> (Ptr Strings -> IO ())
-> (Ptr Strings -> IO [ByteString])
-> IO [ByteString]
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket
              [C.block| Strings*{ 
                Strings *r = new Strings();
                for (auto i : (*$(DerivationInputsIterator *i))->second) {
                  r->push_back(i);
                }
                return r;
              }|]
              Ptr Strings -> IO ()
deleteStrings
              Ptr Strings -> IO [ByteString]
toByteStrings
          [C.block| void { (*$(DerivationInputsIterator *i))++; }|]
          ((StorePath
name, [ByteString]
outs) (StorePath, [ByteString])
-> [(StorePath, [ByteString])] -> [(StorePath, [ByteString])]
forall a. a -> [a] -> [a]
:) ([(StorePath, [ByteString])] -> [(StorePath, [ByteString])])
-> IO [(StorePath, [ByteString])] -> IO [(StorePath, [ByteString])]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO [(StorePath, [ByteString])]
continue

deleteDerivationInputsIterator :: Ptr DerivationInputsIterator -> IO ()
deleteDerivationInputsIterator :: Ptr DerivationInputsIterator -> IO ()
deleteDerivationInputsIterator Ptr DerivationInputsIterator
a = [C.block| void { delete $(DerivationInputsIterator *a); }|]

getDerivationEnv :: Derivation -> IO (Map ByteString ByteString)
getDerivationEnv :: Derivation -> IO (Map ByteString ByteString)
getDerivationEnv Derivation
derivation =
  [C.exp| StringPairs* { &($fptr-ptr:(Derivation *derivation)->env) }|]
    IO (Ptr StringPairs)
-> (Ptr StringPairs -> IO (Map ByteString ByteString))
-> IO (Map ByteString ByteString)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Ptr StringPairs -> IO (Map ByteString ByteString)
toByteStringMap

getDerivationOutputNames :: ForeignPtr Derivation -> IO [ByteString]
getDerivationOutputNames :: ForeignPtr Derivation -> IO [ByteString]
getDerivationOutputNames ForeignPtr Derivation
derivation =
  IO (Ptr Strings)
-> (Ptr Strings -> IO ())
-> (Ptr Strings -> IO [ByteString])
-> IO [ByteString]
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket
    [C.throwBlock| Strings* {
      Strings *r = new Strings();
      for (auto i : $fptr-ptr:(Derivation *derivation)->outputs) {
        r->push_back(i.first);
      }
      return r;
    }|]
    Ptr Strings -> IO ()
deleteStrings
    Ptr Strings -> IO [ByteString]
toByteStrings

deleteStringPairs :: Ptr StringPairs -> IO ()
deleteStringPairs :: Ptr StringPairs -> IO ()
deleteStringPairs Ptr StringPairs
s = [C.block| void { delete $(StringPairs *s); }|]

deleteStrings :: Ptr Strings -> IO ()
deleteStrings :: Ptr Strings -> IO ()
deleteStrings Ptr Strings
s = [C.block| void { delete $(Strings *s); }|]

finalizeStrings :: FinalizerPtr Strings
{-# NOINLINE finalizeStrings #-}
finalizeStrings :: FinalizerPtr Strings
finalizeStrings =
  IO (FinalizerPtr Strings) -> FinalizerPtr Strings
forall a. IO a -> a
unsafePerformIO
    [C.exp|
    void (*)(Strings *) {
      [](Strings *v) {
        delete v;
      }
    } |]

getStringsLength :: Ptr Strings -> IO C.CSize
getStringsLength :: Ptr Strings -> IO CSize
getStringsLength Ptr Strings
strings = [C.exp| size_t { $(Strings *strings)->size() }|]

toByteStrings :: Ptr Strings -> IO [ByteString]
toByteStrings :: Ptr Strings -> IO [ByteString]
toByteStrings Ptr Strings
strings = do
  Ptr StringsIterator
i <- [C.exp| StringsIterator *{ new StringsIterator($(Strings *strings)->begin()) } |]
  (IO [ByteString] -> IO [ByteString]) -> IO [ByteString]
forall a. (a -> a) -> a
fix ((IO [ByteString] -> IO [ByteString]) -> IO [ByteString])
-> (IO [ByteString] -> IO [ByteString]) -> IO [ByteString]
forall a b. (a -> b) -> a -> b
$ \IO [ByteString]
go -> do
    Bool
isEnd <- (CBool
0 CBool -> CBool -> Bool
forall a. Eq a => a -> a -> Bool
/=) (CBool -> Bool) -> IO CBool -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [C.exp| bool { *$(StringsIterator *i) == $(Strings *strings)->end() }|]
    if Bool
isEnd
      then [ByteString] -> IO [ByteString]
forall (f :: * -> *) a. Applicative f => a -> f a
pure []
      else do
        Ptr CChar
s <- [C.exp| const char*{ strdup((*$(StringsIterator *i))->c_str()) }|]
        ByteString
bs <- Ptr CChar -> IO ByteString
BS.unsafePackMallocCString Ptr CChar
s
        [C.block| void { (*$(StringsIterator *i))++; }|]
        (ByteString
bs ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
:) ([ByteString] -> [ByteString])
-> IO [ByteString] -> IO [ByteString]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO [ByteString]
go

toByteStringMap :: Ptr StringPairs -> IO (Map ByteString ByteString)
toByteStringMap :: Ptr StringPairs -> IO (Map ByteString ByteString)
toByteStringMap Ptr StringPairs
strings =
  [(ByteString, ByteString)] -> Map ByteString ByteString
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(ByteString, ByteString)] -> Map ByteString ByteString)
-> IO [(ByteString, ByteString)] -> IO (Map ByteString ByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> do
    Ptr StringPairsIterator
i <- [C.exp| StringPairsIterator *{ new StringPairsIterator($(StringPairs *strings)->begin()) } |]
    (IO [(ByteString, ByteString)] -> IO [(ByteString, ByteString)])
-> IO [(ByteString, ByteString)]
forall a. (a -> a) -> a
fix ((IO [(ByteString, ByteString)] -> IO [(ByteString, ByteString)])
 -> IO [(ByteString, ByteString)])
-> (IO [(ByteString, ByteString)] -> IO [(ByteString, ByteString)])
-> IO [(ByteString, ByteString)]
forall a b. (a -> b) -> a -> b
$ \IO [(ByteString, ByteString)]
go -> do
      Bool
isEnd <- (CBool
0 CBool -> CBool -> Bool
forall a. Eq a => a -> a -> Bool
/=) (CBool -> Bool) -> IO CBool -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [C.exp| bool { *$(StringPairsIterator *i) == $(StringPairs *strings)->end() }|]
      if Bool
isEnd
        then [(ByteString, ByteString)] -> IO [(ByteString, ByteString)]
forall (f :: * -> *) a. Applicative f => a -> f a
pure []
        else do
          Ptr CChar
k <- [C.exp| const char*{ strdup((*$(StringPairsIterator *i))->first.c_str()) }|]
          Ptr CChar
v <- [C.exp| const char*{ strdup((*$(StringPairsIterator *i))->second.c_str()) }|]
          ByteString
bk <- Ptr CChar -> IO ByteString
BS.unsafePackMallocCString Ptr CChar
k
          ByteString
bv <- Ptr CChar -> IO ByteString
BS.unsafePackMallocCString Ptr CChar
v
          [C.block| void { (*$(StringPairsIterator *i))++; }|]
          ((ByteString
bk, ByteString
bv) (ByteString, ByteString)
-> [(ByteString, ByteString)] -> [(ByteString, ByteString)]
forall a. a -> [a] -> [a]
:) ([(ByteString, ByteString)] -> [(ByteString, ByteString)])
-> IO [(ByteString, ByteString)] -> IO [(ByteString, ByteString)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO [(ByteString, ByteString)]
go

withStrings :: (Ptr Strings -> IO a) -> IO a
withStrings :: forall a. (Ptr Strings -> IO a) -> IO a
withStrings =
  IO (Ptr Strings)
-> (Ptr Strings -> IO ()) -> (Ptr Strings -> IO a) -> IO a
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket
    [C.exp| Strings *{ new Strings() }|]
    (\Ptr Strings
sp -> [C.block| void { delete $(Strings *sp); }|])

withStringsOf :: [ByteString] -> (Ptr Strings -> IO a) -> IO a
withStringsOf :: forall a. [ByteString] -> (Ptr Strings -> IO a) -> IO a
withStringsOf [ByteString]
paths Ptr Strings -> IO a
f =
  (Ptr Strings -> IO a) -> IO a
forall a. (Ptr Strings -> IO a) -> IO a
withStrings \Ptr Strings
strings -> do
    [ByteString] -> (ByteString -> IO ()) -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [ByteString]
paths (Ptr Strings -> ByteString -> IO ()
pushString Ptr Strings
strings)
    Ptr Strings -> IO a
f Ptr Strings
strings

pushString :: Ptr Strings -> ByteString -> IO ()
pushString :: Ptr Strings -> ByteString -> IO ()
pushString Ptr Strings
strings ByteString
s =
  [C.block| void { $(Strings *strings)->push_back($bs-cstr:s); }|]

copyClosure :: Store -> Store -> [StorePath] -> IO ()
copyClosure :: Store -> Store -> [StorePath] -> IO ()
copyClosure (Store Ptr (Ref NixStore)
src) (Store Ptr (Ref NixStore)
dest) [StorePath]
pathList = do
  (StdVector ForeignPtr (CStdVector (Ptr NixStorePath))
pathsVector') <- [Ptr NixStorePath] -> IO (StdVector (Ptr NixStorePath))
forall a. HasStdVectorCopyable a => [a] -> IO (StdVector a)
Std.Vector.fromList ([StorePath]
pathList [StorePath]
-> (StorePath -> Ptr NixStorePath) -> [Ptr NixStorePath]
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \(StorePath ForeignPtr NixStorePath
c) -> ForeignPtr NixStorePath -> Ptr NixStorePath
forall a. ForeignPtr a -> Ptr a
unsafeForeignPtrToPtr ForeignPtr NixStorePath
c)
  ForeignPtr (CStdVector (Ptr NixStorePath))
-> (Ptr (CStdVector (Ptr NixStorePath)) -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr (CStdVector (Ptr NixStorePath))
pathsVector' \Ptr (CStdVector (Ptr NixStorePath))
pathsVector ->
    [C.throwBlock| void {
      ReceiveInterrupts _;
      ref<Store> src = *$(refStore* src);
      ref<Store> dest = *$(refStore* dest);
      std::vector<nix::StorePath *> &pathsVector = *$(std::vector<nix::StorePath*>* pathsVector);

      StorePathSet pathSet;
      for (auto spp : pathsVector)
        pathSet.insert(*spp);

      StorePathSet closurePaths;
      src->computeFSClosure(pathSet, closurePaths);

      nix::copyPaths(*src, *dest, closurePaths);
    }|]
  [StorePath] -> (StorePath -> IO ()) -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [StorePath]
pathList (\(StorePath ForeignPtr NixStorePath
c) -> ForeignPtr NixStorePath -> IO ()
forall a. ForeignPtr a -> IO ()
touchForeignPtr ForeignPtr NixStorePath
c)

parseSecretKey :: ByteString -> IO (ForeignPtr SecretKey)
parseSecretKey :: ByteString -> IO (ForeignPtr SecretKey)
parseSecretKey ByteString
bs =
  [C.throwBlock| SecretKey* {
    return new SecretKey($bs-cstr:bs);
  }|]
    IO (Ptr SecretKey)
-> (Ptr SecretKey -> IO (ForeignPtr SecretKey))
-> IO (ForeignPtr SecretKey)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= FinalizerPtr SecretKey
-> Ptr SecretKey -> IO (ForeignPtr SecretKey)
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
newForeignPtr FinalizerPtr SecretKey
finalizeSecretKey

finalizeSecretKey :: FinalizerPtr SecretKey
{-# NOINLINE finalizeSecretKey #-}
finalizeSecretKey :: FinalizerPtr SecretKey
finalizeSecretKey =
  IO (FinalizerPtr SecretKey) -> FinalizerPtr SecretKey
forall a. IO a -> a
unsafePerformIO
    [C.exp|
    void (*)(SecretKey *) {
      [](SecretKey *v) {
        delete v;
      }
    } |]

signPath ::
  Store ->
  -- | Secret signing key
  Ptr SecretKey ->
  -- | Store path
  StorePath ->
  -- | False if the signature was already present, True if the signature was added
  IO Bool
signPath :: Store -> Ptr SecretKey -> StorePath -> IO Bool
signPath (Store Ptr (Ref NixStore)
store) Ptr SecretKey
secretKey (StorePath ForeignPtr NixStorePath
path) =
  (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
1) (CInt -> Bool) -> IO CInt -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> 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);

    auto info2(*currentInfo);
    info2.sigs.clear();
    info2.sign(*store, secretKey);
    assert(!info2.sigs.empty());
    auto sig = *info2.sigs.begin();

    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
followLinksToStorePath :: Store -> ByteString -> IO StorePath
followLinksToStorePath (Store Ptr (Ref NixStore)
store) ByteString
bs =
  Ptr NixStorePath -> IO StorePath
moveStorePath
    (Ptr NixStorePath -> IO StorePath)
-> IO (Ptr NixStorePath) -> IO StorePath
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [C.throwBlock| nix::StorePath *{
      ReceiveInterrupts _;
      Store &store = **$(refStore* store);
      std::string s = std::string($bs-ptr:bs, $bs-len:bs);
      return new StorePath(store.followLinksToStorePath(s));
    }|]

-- | Whether a path exists and is registered.
isValidPath :: Store -> StorePath -> IO Bool
isValidPath :: Store -> StorePath -> IO Bool
isValidPath (Store Ptr (Ref NixStore)
store) StorePath
path =
  [C.throwBlock| bool {
    ReceiveInterrupts _;
    Store &store = **$(refStore* store);
    StorePath &path = *$fptr-ptr:(nix::StorePath *path);
    return store.isValidPath(path);
  }|]
    IO CBool -> (CBool -> Bool) -> IO Bool
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> (CBool -> CBool -> Bool
forall a. Eq a => a -> a -> Bool
/= CBool
0)

queryPathInfo ::
  Store ->
  -- | Exact store path, not a subpath
  StorePath ->
  -- | ValidPathInfo or exception
  IO (ForeignPtr (Ref ValidPathInfo))
queryPathInfo :: Store -> StorePath -> IO (ForeignPtr (Ref ValidPathInfo))
queryPathInfo (Store Ptr (Ref NixStore)
store) (StorePath ForeignPtr NixStorePath
path) = do
  Ptr (Ref ValidPathInfo)
vpi <-
    [C.throwBlock| refValidPathInfo* {
      ReceiveInterrupts _;
      Store &store = **$(refStore* store);
      StorePath &path = *$fptr-ptr:(nix::StorePath *path);
      return new refValidPathInfo(store.queryPathInfo(path));
    }|]
  FinalizerPtr (Ref ValidPathInfo)
-> Ptr (Ref ValidPathInfo) -> IO (ForeignPtr (Ref ValidPathInfo))
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
newForeignPtr FinalizerPtr (Ref ValidPathInfo)
finalizeRefValidPathInfo Ptr (Ref ValidPathInfo)
vpi

finalizeRefValidPathInfo :: FinalizerPtr (Ref ValidPathInfo)
{-# NOINLINE finalizeRefValidPathInfo #-}
finalizeRefValidPathInfo :: FinalizerPtr (Ref ValidPathInfo)
finalizeRefValidPathInfo =
  IO (FinalizerPtr (Ref ValidPathInfo))
-> FinalizerPtr (Ref ValidPathInfo)
forall a. IO a -> a
unsafePerformIO
    [C.exp|
      void (*)(refValidPathInfo *) {
        [](refValidPathInfo *v){ delete v; }
      }|]

-- | The narSize field of a ValidPathInfo struct. Source: path-info.hh / store-api.hh
validPathInfoNarSize :: ForeignPtr (Ref ValidPathInfo) -> Int64
validPathInfoNarSize :: ForeignPtr (Ref ValidPathInfo) -> Int64
validPathInfoNarSize ForeignPtr (Ref ValidPathInfo)
vpi =
  Integer -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Int64) -> Integer -> Int64
forall a b. (a -> b) -> a -> b
$
    CLong -> Integer
forall a. Integral a => a -> Integer
toInteger
      [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
validPathInfoNarHash32 :: ForeignPtr (Ref ValidPathInfo) -> IO ByteString
validPathInfoNarHash32 ForeignPtr (Ref ValidPathInfo)
vpi =
  Ptr CChar -> IO ByteString
unsafePackMallocCString
    (Ptr CChar -> IO ByteString) -> IO (Ptr CChar) -> IO ByteString
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [C.block| const char *{ 
      std::string s((*$fptr-ptr:(refValidPathInfo* vpi))->narHash.to_string(nix::Base32, true));
      return strdup(s.c_str()); }
    |]

-- | Deriver field of a ValidPathInfo struct. Source: store-api.hh
validPathInfoDeriver :: Store -> ForeignPtr (Ref ValidPathInfo) -> IO (Maybe StorePath)
validPathInfoDeriver :: Store -> ForeignPtr (Ref ValidPathInfo) -> IO (Maybe StorePath)
validPathInfoDeriver Store
_ = ForeignPtr (Ref ValidPathInfo) -> IO (Maybe StorePath)
validPathInfoDeriver'

validPathInfoDeriver' :: ForeignPtr (Ref ValidPathInfo) -> IO (Maybe StorePath)
validPathInfoDeriver' :: ForeignPtr (Ref ValidPathInfo) -> IO (Maybe StorePath)
validPathInfoDeriver' ForeignPtr (Ref ValidPathInfo)
vpi =
  Ptr NixStorePath -> IO (Maybe StorePath)
moveStorePathMaybe
    (Ptr NixStorePath -> IO (Maybe StorePath))
-> IO (Ptr NixStorePath) -> IO (Maybe StorePath)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [C.throwBlock| nix::StorePath * {
      std::optional<StorePath> deriver = (*$fptr-ptr:(refValidPathInfo* vpi))->deriver;
      return deriver ? new StorePath(*deriver) : nullptr;
    }|]

-- | References field of a ValidPathInfo struct. Source: store-api.hh
validPathInfoReferences :: Store -> ForeignPtr (Ref ValidPathInfo) -> IO [StorePath]
validPathInfoReferences :: Store -> ForeignPtr (Ref ValidPathInfo) -> IO [StorePath]
validPathInfoReferences Store
_ = ForeignPtr (Ref ValidPathInfo) -> IO [StorePath]
validPathInfoReferences'

validPathInfoReferences' :: ForeignPtr (Ref ValidPathInfo) -> IO [StorePath]
validPathInfoReferences' :: ForeignPtr (Ref ValidPathInfo) -> IO [StorePath]
validPathInfoReferences' ForeignPtr (Ref ValidPathInfo)
vpi = do
  StdVector (Ptr NixStorePath)
sps <-
    Ptr (CStdVector (Ptr NixStorePath))
-> IO (StdVector (Ptr NixStorePath))
forall a b. HasEncapsulation a b => Ptr a -> IO b
moveToForeignPtrWrapper
      (Ptr (CStdVector (Ptr NixStorePath))
 -> IO (StdVector (Ptr NixStorePath)))
-> IO (Ptr (CStdVector (Ptr NixStorePath)))
-> IO (StdVector (Ptr NixStorePath))
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [C.throwBlock| std::vector<nix::StorePath *>* {
        auto sps = new std::vector<nix::StorePath *>();
        for (auto sp : (*$fptr-ptr:(refValidPathInfo* vpi))->references)
          sps->push_back(new StorePath(sp));
        return sps;
      }|]
  [Ptr NixStorePath]
l <- StdVector (Ptr NixStorePath) -> IO [Ptr NixStorePath]
forall a.
(HasStdVectorCopyable a, Storable a) =>
StdVector a -> IO [a]
Std.Vector.toList StdVector (Ptr NixStorePath)
sps
  [Ptr NixStorePath]
-> (Ptr NixStorePath -> IO StorePath) -> IO [StorePath]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
t a -> (a -> f b) -> f (t b)
for [Ptr NixStorePath]
l Ptr NixStorePath -> IO StorePath
moveStorePath

----- computeFSClosure -----
data ClosureParams = ClosureParams
  { ClosureParams -> Bool
flipDirection :: Bool,
    ClosureParams -> Bool
includeOutputs :: Bool,
    ClosureParams -> Bool
includeDerivers :: Bool
  }

defaultClosureParams :: ClosureParams
defaultClosureParams :: ClosureParams
defaultClosureParams =
  ClosureParams :: Bool -> Bool -> Bool -> ClosureParams
ClosureParams
    { flipDirection :: Bool
flipDirection = Bool
False,
      includeOutputs :: Bool
includeOutputs = Bool
False,
      includeDerivers :: Bool
includeDerivers = Bool
False
    }

computeFSClosure :: Store -> ClosureParams -> StdSet NixStorePath -> IO (StdSet NixStorePath)
computeFSClosure :: Store
-> ClosureParams -> StdSet NixStorePath -> IO (StdSet NixStorePath)
computeFSClosure (Store Ptr (Ref NixStore)
store) ClosureParams
params (Std.Set.StdSet ForeignPtr (CStdSet NixStorePath)
startingSet) = do
  let countTrue :: Bool -> C.CInt
      countTrue :: Bool -> CInt
countTrue Bool
True = CInt
1
      countTrue Bool
False = CInt
0
      flipDir :: CInt
flipDir = Bool -> CInt
countTrue (Bool -> CInt) -> Bool -> CInt
forall a b. (a -> b) -> a -> b
$ ClosureParams -> Bool
flipDirection ClosureParams
params
      inclOut :: CInt
inclOut = Bool -> CInt
countTrue (Bool -> CInt) -> Bool -> CInt
forall a b. (a -> b) -> a -> b
$ ClosureParams -> Bool
includeOutputs ClosureParams
params
      inclDrv :: CInt
inclDrv = Bool -> CInt
countTrue (Bool -> CInt) -> Bool -> CInt
forall a b. (a -> b) -> a -> b
$ ClosureParams -> Bool
includeDerivers ClosureParams
params
  ret :: StdSet NixStorePath
ret@(Std.Set.StdSet ForeignPtr (CStdSet NixStorePath)
retSet) <- IO (StdSet NixStorePath)
forall a. HasStdSet a => IO (StdSet a)
Std.Set.new
  [C.throwBlock| void {
    ReceiveInterrupts _;
    Store &store = **$(refStore* store);
    StorePathSet &ret = *$fptr-ptr:(std::set<nix::StorePath>* retSet);
    store.computeFSClosure(*$fptr-ptr:(std::set<nix::StorePath>* startingSet), ret,
      $(int flipDir), $(int inclOut), $(int inclDrv));
  }|]
  StdSet NixStorePath -> IO (StdSet NixStorePath)
forall (f :: * -> *) a. Applicative f => a -> f a
pure StdSet NixStorePath
ret

withPtr' :: (Coercible a' (ForeignPtr a)) => a' -> (Ptr a -> IO b) -> IO b
withPtr' :: forall a' a b.
Coercible a' (ForeignPtr a) =>
a' -> (Ptr a -> IO b) -> IO b
withPtr' a'
p = ForeignPtr a -> (Ptr a -> IO b) -> IO b
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr (a' -> ForeignPtr a
coerce a'
p)