#pragma once #include "util.hh" #include "path.hh" #include "outputs-spec.hh" #include "derived-path.hh" #include "eval.hh" #include "store-api.hh" #include "flake/flake.hh" #include "build-result.hh" #include namespace nix { struct DrvInfo; struct SourceExprCommand; namespace eval_cache { class EvalCache; class AttrCursor; } struct App { std::vector context; Path program; // FIXME: add args, sandbox settings, metadata, ... }; struct UnresolvedApp { App unresolved; App resolve(ref evalStore, ref store); }; enum class Realise { /* Build the derivation. Postcondition: the derivation outputs exist. */ Outputs, /* Don't build the derivation. Postcondition: the store derivation exists. */ Derivation, /* Evaluate in dry-run mode. Postcondition: nothing. */ // FIXME: currently unused, but could be revived if we can // evaluate derivations in-memory. Nothing }; /* How to handle derivations in commands that operate on store paths. */ enum class OperateOn { /* Operate on the output path. */ Output, /* Operate on the .drv path. */ Derivation }; struct ExtraPathInfo { std::optional priority; std::optional originalRef; std::optional resolvedRef; std::optional attrPath; // FIXME: merge with DerivedPath's 'outputs' field? std::optional extendedOutputsSpec; }; /* A derived path with any additional info that commands might need from the derivation. */ struct DerivedPathWithInfo { DerivedPath path; ExtraPathInfo info; }; struct BuiltPathWithResult { BuiltPath path; ExtraPathInfo info; std::optional result; }; typedef std::vector DerivedPathsWithInfo; struct Installable { virtual ~Installable() { } virtual std::string what() const = 0; virtual DerivedPathsWithInfo toDerivedPaths() = 0; DerivedPathWithInfo toDerivedPath(); UnresolvedApp toApp(EvalState & state); virtual std::pair toValue(EvalState & state) { throw Error("argument '%s' cannot be evaluated", what()); } /* Return a value only if this installable is a store path or a symlink to it. */ virtual std::optional getStorePath() { return {}; } /* Get a cursor to each value this Installable could refer to. However if none exists, throw exception instead of returning empty vector. */ virtual std::vector> getCursors(EvalState & state); /* Get the first and most preferred cursor this Installable could refer to, or throw an exception if none exists. */ virtual ref getCursor(EvalState & state); virtual FlakeRef nixpkgsFlakeRef() const { return FlakeRef::fromAttrs({{"type","indirect"}, {"id", "nixpkgs"}}); } static std::vector build( ref evalStore, ref store, Realise mode, const std::vector> & installables, BuildMode bMode = bmNormal); static std::vector, BuiltPathWithResult>> build2( ref evalStore, ref store, Realise mode, const std::vector> & installables, BuildMode bMode = bmNormal); static std::set toStorePaths( ref evalStore, ref store, Realise mode, OperateOn operateOn, const std::vector> & installables); static StorePath toStorePath( ref evalStore, ref store, Realise mode, OperateOn operateOn, std::shared_ptr installable); static std::set toDerivations( ref store, const std::vector> & installables, bool useDeriver = false); static BuiltPaths toBuiltPaths( ref evalStore, ref store, Realise mode, OperateOn operateOn, const std::vector> & installables); }; typedef std::vector> Installables; struct InstallableValue : Installable { ref state; InstallableValue(ref state) : state(state) {} }; struct InstallableFlake : InstallableValue { FlakeRef flakeRef; Strings attrPaths; Strings prefixes; ExtendedOutputsSpec extendedOutputsSpec; const flake::LockFlags & lockFlags; mutable std::shared_ptr _lockedFlake; InstallableFlake( SourceExprCommand * cmd, ref state, FlakeRef && flakeRef, std::string_view fragment, ExtendedOutputsSpec extendedOutputsSpec, Strings attrPaths, Strings prefixes, const flake::LockFlags & lockFlags); std::string what() const override { return flakeRef.to_string() + "#" + *attrPaths.begin(); } std::vector getActualAttrPaths(); Value * getFlakeOutputs(EvalState & state, const flake::LockedFlake & lockedFlake); DerivedPathsWithInfo toDerivedPaths() override; std::pair toValue(EvalState & state) override; /* Get a cursor to every attrpath in getActualAttrPaths() that exists. However if none exists, throw an exception. */ std::vector> getCursors(EvalState & state) override; std::shared_ptr getLockedFlake() const; FlakeRef nixpkgsFlakeRef() const override; }; ref openEvalCache( EvalState & state, std::shared_ptr lockedFlake); }