hercules-ci-cnix-expr 0.3.5.1 → 0.3.6.0
raw patch · 6 files changed
+115/−29 lines, 6 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Hercules.CNix.Expr: instance Hercules.CNix.Expr.ToRawValue Data.ByteString.Internal.ByteString
- Hercules.CNix.Expr: instance Hercules.CNix.Expr.ToRawValue a => Hercules.CNix.Expr.ToRawValue (Data.Map.Internal.Map Data.ByteString.Internal.ByteString a)
- Hercules.CNix.Expr: instance Hercules.CNix.Expr.ToRawValue a => Hercules.CNix.Expr.ToValue (Data.Map.Internal.Map Data.ByteString.Internal.ByteString a)
- Hercules.CNix.Expr: instance Hercules.CNix.Expr.ToValue Data.ByteString.Internal.ByteString
- Hercules.CNix.Expr.Schema: instance Hercules.CNix.Expr.Schema.FromPSObject Hercules.CNix.Expr.Schema.StringWithoutContext Data.ByteString.Internal.ByteString
+ Hercules.CNix.Expr: allowThreads :: IO ()
+ Hercules.CNix.Expr: instance Hercules.CNix.Expr.ToRawValue Data.ByteString.Internal.Type.ByteString
+ Hercules.CNix.Expr: instance Hercules.CNix.Expr.ToRawValue a => Hercules.CNix.Expr.ToRawValue (Data.Map.Internal.Map Data.ByteString.Internal.Type.ByteString a)
+ Hercules.CNix.Expr: instance Hercules.CNix.Expr.ToRawValue a => Hercules.CNix.Expr.ToValue (Data.Map.Internal.Map Data.ByteString.Internal.Type.ByteString a)
+ Hercules.CNix.Expr: instance Hercules.CNix.Expr.ToValue Data.ByteString.Internal.Type.ByteString
+ Hercules.CNix.Expr: runGcRegisteredThread :: IO a -> IO a
+ Hercules.CNix.Expr.Schema: instance Hercules.CNix.Expr.Schema.FromPSObject Hercules.CNix.Expr.Schema.StringWithoutContext Data.ByteString.Internal.Type.ByteString
- Hercules.CNix.Expr.Schema: (#.) :: (KnownSymbol s, (as . s) ~ b, MonadEval m) => PSObject (Attrs' as w) -> AttrLabel s -> m (PSObject b)
+ Hercules.CNix.Expr.Schema: (#.) :: (KnownSymbol s, MonadEval m) => PSObject (Attrs' as w) -> AttrLabel s -> m (PSObject (as . s))
- Hercules.CNix.Expr.Schema: (#?!) :: (KnownSymbol s, (as ? s) ~ b, MonadEval m) => PSObject (Attrs' as w) -> AttrLabel s -> m (PSObject b)
+ Hercules.CNix.Expr.Schema: (#?!) :: (KnownSymbol s, MonadEval m) => PSObject (Attrs' as w) -> AttrLabel s -> m (PSObject (as ? s))
- Hercules.CNix.Expr.Schema: (#?) :: (KnownSymbol s, (as ? s) ~ b, MonadEval m) => PSObject (Attrs' as w) -> AttrLabel s -> m (Maybe (PSObject b))
+ Hercules.CNix.Expr.Schema: (#?) :: (KnownSymbol s, MonadEval m) => PSObject (Attrs' as w) -> AttrLabel s -> m (Maybe (PSObject (as ? s)))
- Hercules.CNix.Expr.Schema: ($?) :: (MonadEval m, PossibleTypesForSchema a, PossibleTypesForSchema b) => PSObject (a ->? b) -> PSObject a -> m (PSObject b)
+ Hercules.CNix.Expr.Schema: ($?) :: (MonadEval m, PossibleTypesForSchema b) => PSObject (a ->? b) -> PSObject a -> m (PSObject b)
- Hercules.CNix.Expr.Schema: (>>$.) :: (MonadEval m, PossibleTypesForSchema a, PossibleTypesForSchema b) => m (PSObject (a ->. b)) -> m (PSObject a) -> m (PSObject b)
+ Hercules.CNix.Expr.Schema: (>>$.) :: MonadEval m => m (PSObject (a ->. b)) -> m (PSObject a) -> m (PSObject b)
- Hercules.CNix.Expr.Schema: (>>$?) :: (MonadEval m, PossibleTypesForSchema a, PossibleTypesForSchema b) => m (PSObject (a ->? b)) -> m (PSObject a) -> m (PSObject b)
+ Hercules.CNix.Expr.Schema: (>>$?) :: (MonadEval m, PossibleTypesForSchema b) => m (PSObject (a ->? b)) -> m (PSObject a) -> m (PSObject b)
- Hercules.CNix.Expr.Schema: (>>.) :: (KnownSymbol s, (as . s) ~ b, MonadEval m) => m (PSObject (Attrs' as w)) -> AttrLabel s -> m (PSObject b)
+ Hercules.CNix.Expr.Schema: (>>.) :: (KnownSymbol s, MonadEval m) => m (PSObject (Attrs' as w)) -> AttrLabel s -> m (PSObject (as . s))
- Hercules.CNix.Expr.Schema: (>>?) :: (KnownSymbol s, (as ? s) ~ b, MonadEval m) => m (PSObject (Attrs' as w)) -> AttrLabel s -> m (Maybe (PSObject b))
+ Hercules.CNix.Expr.Schema: (>>?) :: (KnownSymbol s, MonadEval m) => m (PSObject (Attrs' as w)) -> AttrLabel s -> m (Maybe (PSObject (as ? s)))
- Hercules.CNix.Expr.Schema: (|!) :: forall a b c m. (CheckType (NixTypeForSchema a), MonadIO m, MonadEval m, PossibleTypesForSchema a, PossibleTypesForSchema b) => (PSObject a -> m c) -> (PSObject b -> m c) -> PSObject (a |. b) -> m c
+ Hercules.CNix.Expr.Schema: (|!) :: forall a b c m. (CheckType (NixTypeForSchema a), MonadEval m, PossibleTypesForSchema a, PossibleTypesForSchema b) => (PSObject a -> m c) -> (PSObject b -> m c) -> PSObject (a |. b) -> m c
Files
- CHANGELOG.md +10/−0
- hercules-ci-cnix-expr.cabal +24/−13
- src/Hercules/CNix/Expr.hs +71/−5
- src/Hercules/CNix/Expr/Schema.hs +8/−9
- test/Hercules/CNix/Expr/SchemaSpec.hs +0/−1
- test/Hercules/CNix/ExprSpec.hs +2/−1
CHANGELOG.md view
@@ -5,6 +5,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## 0.3.6.0 - 2023-06-28++### Added++ - `allowThreads`, `runInGcSafeThread`++ - Nix 2.15 support++ - Nix 2.16 support+ ## 0.3.5.1 - 2023-03-06 ### Added
hercules-ci-cnix-expr.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.4 name: hercules-ci-cnix-expr-version: 0.3.5.1+version: 0.3.6.0 synopsis: Bindings for the Nix evaluator category: Nix, CI, Testing, DevOps homepage: https://docs.hercules-ci.com@@ -34,32 +34,42 @@ description: Build for Nix >=2.4pre* default: True -flag nix-2_5+flag nix-2_15 description: Build for Nix >=2.5pre* default: False +flag ide+ description: Whether to enable IDE workarounds. You shouldn't need this.+ default: False+ -- match the C++ language standard Nix is using common cxx-opts+ if flag(nix-2_15)+ cxx-options:+ -std=c++2a+ else+ cxx-options:+ -std=c++17+ cxx-options:- -std=c++17 -Wall extra-libraries: stdc++ - if flag(nix-2_5)- cxx-options:- -DNIX_2_5- cpp-options:- -DNIX_2_5- if os(darwin) -- avoid https://gitlab.haskell.org/ghc/ghc/issues/11829 ld-options: -Wl,-keep_dwarf_unwind if impl(ghc >= 8.10) ghc-options:- -optcxx-std=c++17 -optcxx-Wall+ if flag(nix-2_15)+ ghc-options:+ -optcxx-std=c++2a+ else+ ghc-options:+ -optcxx-std=c++17 else+ -- Remove soon ghc-options: -optc-std=c++17 -optc-Wall@@ -113,8 +123,9 @@ include install-includes: hercules-ci-cnix/expr.hxx- extra-libraries:- boost_context+ if ! flag(ide)+ extra-libraries:+ boost_context pkgconfig-depends: nix-store >= 2.4 , nix-expr >= 2.4@@ -125,7 +136,7 @@ nix-cmd >= 2.8 -test-suite hercules-ci-cnix-expr-tests+test-suite hercules-ci-cnix-expr-unit-tests type: exitcode-stdio-1.0 main-is: TestMain.hs other-modules:
src/Hercules/CNix/Expr.hs view
@@ -8,6 +8,10 @@ {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-}++-- redundant-constraints: False positive in default signature for `toRawValue`+{-# OPTIONS_GHC -Wno-redundant-constraints #-}+ #ifdef __GHCIDE__ # define NIX_IS_AT_LEAST(mm,m,p) 1 #endif@@ -20,6 +24,8 @@ setOption, setExtraStackOverflowHandlerToSleep, initThread,+ allowThreads,+ runGcRegisteredThread, logInfo, withEvalState, withEvalStateConduit,@@ -91,6 +97,8 @@ C.context (Hercules.CNix.Store.Context.context <> Hercules.CNix.Expr.Context.evalContext) +C.verbatim "#define GC_THREADS 1"+ C.include "<stdio.h>" C.include "<cstring>"@@ -137,7 +145,10 @@ [C.throwBlock| void { nix::initNix(); nix::initGC();-#ifdef NIX_2_5+#if NIX_IS_AT_LEAST(2,15,0)+ globalConfig.set("extra-experimental-features", "flakes");+#else+#if NIX_IS_AT_LEAST(2,5,0) std::set<nix::ExperimentalFeature> features(nix::settings.experimentalFeatures.get()); features.insert(nix::ExperimentalFeature::Flakes); #else@@ -145,8 +156,10 @@ features.push_back("flakes"); #endif nix::settings.experimentalFeatures.assign(features);+#endif } |] +-- | Initialize the current (main) thread for stack overflow detection. initThread :: IO () initThread = void@@ -154,6 +167,47 @@ nix::detectStackOverflow(); }|] +-- | Configure the garbage collector to support threads.+--+-- This is not needed when all evaluation happens on the main thread.+allowThreads :: IO ()+allowThreads =+ void+ [C.block| void {+ GC_allow_register_threads();+ }|]++-- | Run in a thread from which GC may be triggered safely.+--+-- This also installs the stack overflow handler.+--+-- NOTE: Before using this, you must call 'allowThreads' once.+runGcRegisteredThread :: IO a -> IO a+runGcRegisteredThread io =+ runInBoundThread do+ bracket+ start+ (const end)+ (const io)+ where+ start =+ do+ initThread+ [C.block| void {+ struct GC_stack_base sb;+ int r = GC_get_stack_base(&sb);+ assert(r == GC_SUCCESS);+ GC_register_my_thread(&sb);+ }|]+ pass+ end =+ do+ [C.block| void {+ GC_unregister_my_thread();+ }|]+ pass++ {- | Configure the stack overflow handler to sleep before returning, allowing other threads to continue for a bit. @@ -265,7 +319,13 @@ mkRawValue =<< [C.throwBlock| Value* { Value value;- $(EvalState *evalState)->evalFile($(const char *filename'), value);+ auto cstr = $(const char *filename');+#if NIX_IS_AT_LEAST(2,16,0)+ SourcePath path = CanonPath(cstr);+#else+ std::string path = cstr;+#endif+ $(EvalState *evalState)->evalFile(path, value); return new (NoGC) Value(value); }|] @@ -462,7 +522,13 @@ mkRawValue =<< [C.throwBlock| Value *{ EvalState &evalState = *$(EvalState *evalState);- Expr *expr = evalState.parseExprFromString(std::string($bs-ptr:s, $bs-len:s), std::string($bs-ptr:basePath, $bs-len:basePath));+ std::string basePathStr = std::string($bs-ptr:basePath, $bs-len:basePath);+#if NIX_IS_AT_LEAST(2,16,0)+ SourcePath basePath = CanonPath(basePathStr);+#else+ auto & basePath = basePathStr;+#endif+ Expr *expr = evalState.parseExprFromString(std::string($bs-ptr:s, $bs-len:s), basePath); Value *r = new (NoGC) Value(); evalState.eval(expr, *r); return r;@@ -628,10 +694,10 @@ toRawValue _ = pure -- | Upcast-instance ToRawValue (Value a)+instance forall (a :: Type). ToRawValue (Value a) -- | Identity-instance ToValue (Value a) where+instance forall (a :: Type). ToValue (Value a) where type NixTypeFor (Value a) = a toValue _ = pure
src/Hercules/CNix/Expr/Schema.hs view
@@ -270,11 +270,11 @@ type MonadEval m = (MonadIO m, MonadReader (Ptr EvalState) m) -- | A combination of '>>=' and '#.'.-(>>.) :: (KnownSymbol s, as . s ~ b, MonadEval m) => m (PSObject (Attrs' as w)) -> AttrLabel s -> m (PSObject b)+(>>.) :: (KnownSymbol s, MonadEval m) => m (PSObject (Attrs' as w)) -> AttrLabel s -> m (PSObject (as . s)) mas >>. p = mas >>= \as -> as #. p -- | Attribute selector. @a #. #b@ is @a.b@ in Nix. Operates on attributes that are required (@_.@) in the schema, throwing an error if necessary.-(#.) :: (KnownSymbol s, as . s ~ b, MonadEval m) => PSObject (Attrs' as w) -> AttrLabel s -> m (PSObject b)+(#.) :: (KnownSymbol s, MonadEval m) => PSObject (Attrs' as w) -> AttrLabel s -> m (PSObject (as . s)) as #. p = do evalState <- ask let name = T.pack (symbolVal p)@@ -284,11 +284,11 @@ Just b -> pure PSObject {value = b, provenance = Attribute (provenance as) name} -- | A combination of '>>=' and '#?'.-(>>?) :: (KnownSymbol s, as ? s ~ b, MonadEval m) => m (PSObject (Attrs' as w)) -> AttrLabel s -> m (Maybe (PSObject b))+(>>?) :: (KnownSymbol s, MonadEval m) => m (PSObject (Attrs' as w)) -> AttrLabel s -> m (Maybe (PSObject (as ? s))) mas >>? p = mas >>= \as -> as #? p -- | Attribute selector. @a #? #b@ is @a.b@ in Nix, but handles the missing case without exception. Operates on attributes that are optional (@_?@) in the schema, throwing an error if necessary.-(#?) :: (KnownSymbol s, as ? s ~ b, MonadEval m) => PSObject (Attrs' as w) -> AttrLabel s -> m (Maybe (PSObject b))+(#?) :: (KnownSymbol s, MonadEval m) => PSObject (Attrs' as w) -> AttrLabel s -> m (Maybe (PSObject (as ? s))) as #? p = do evalState <- ask let name = T.pack (symbolVal p)@@ -306,7 +306,7 @@ -- -- It provides a decent error message with attrset provenance, but can't provide -- extra context like you can when manually handling the @a '#?' b@ 'Nothing' case.-(#?!) :: (KnownSymbol s, as ? s ~ b, MonadEval m) => PSObject (Attrs' as w) -> AttrLabel s -> m (PSObject b)+(#?!) :: (KnownSymbol s, MonadEval m) => PSObject (Attrs' as w) -> AttrLabel s -> m (PSObject (as ? s)) as #?! p = do as #? p >>= \case Nothing -> throwIO $ MissingAttribute (provenance as) (T.pack (symbolVal p))@@ -392,7 +392,6 @@ (|!) :: forall a b c m. ( CheckType (NixTypeForSchema a),- MonadIO m, MonadEval m, PossibleTypesForSchema a, PossibleTypesForSchema b@@ -421,12 +420,12 @@ englishOr (a : as) = a <> ", " <> englishOr as -- | Optional application.-($?) :: (MonadEval m, PossibleTypesForSchema a, PossibleTypesForSchema b) => PSObject (a ->? b) -> PSObject a -> m (PSObject b)+($?) :: (MonadEval m, PossibleTypesForSchema b) => PSObject (a ->? b) -> PSObject a -> m (PSObject b) x $? a = pure x >>$? pure a -- | Optional application. Like '$?' but takes care of monadic binding as a convenience.-(>>$?) :: (MonadEval m, PossibleTypesForSchema a, PossibleTypesForSchema b) => m (PSObject (a ->? b)) -> m (PSObject a) -> m (PSObject b)+(>>$?) :: (MonadEval m, PossibleTypesForSchema b) => m (PSObject (a ->? b)) -> m (PSObject a) -> m (PSObject b) x >>$? a = ( (\f -> a >>= (f .$)) |! pure@@ -434,7 +433,7 @@ =<< x -- | Application. Like '$.' but takes care of monadic binding as a convenience.-(>>$.) :: (MonadEval m, PossibleTypesForSchema a, PossibleTypesForSchema b) => m (PSObject (a ->. b)) -> m (PSObject a) -> m (PSObject b)+(>>$.) :: (MonadEval m) => m (PSObject (a ->. b)) -> m (PSObject a) -> m (PSObject b) f >>$. a = do f' <- f a' <- a
test/Hercules/CNix/Expr/SchemaSpec.hs view
@@ -8,7 +8,6 @@ import qualified Hercules.CNix.Expr as Expr import Hercules.CNix.Expr.Raw (RawValueType (Attrs, Bool, Lambda, Null, String)) import Hercules.CNix.Expr.Schema-import Hercules.CNix.Expr.Schema (FromPSObject (fromPSObject)) import Protolude hiding (TypeError, check, evalState) import SingleState (evalState) import Test.Hspec
test/Hercules/CNix/ExprSpec.hs view
@@ -136,7 +136,8 @@ ExitSuccess -> pass readProc exe args = do -- putErrText $ "Reading " <> show exe <> " " <> show args- (t, r) <- System.Process.withCreateProcess ((System.Process.proc exe args) {System.Process.cwd = Just dir, System.Process.std_out = System.Process.CreatePipe}) \_ (Just stdo) _ p -> do+ (t, r) <- System.Process.withCreateProcess ((System.Process.proc exe args) {System.Process.cwd = Just dir, System.Process.std_out = System.Process.CreatePipe}) \_ stdom _ p -> do+ stdo <- maybe (panic "no stdout") pure stdom t <- T.hGetContents stdo (t,) <$> waitForProcess p case r of