#pragma once #include "util.hh" #include "path.hh" #include "path-with-outputs.hh" #include "derived-path.hh" #include "eval.hh" #include "store-api.hh" #include "flake/flake.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 Installable { virtual ~Installable() { } virtual std::string what() const = 0; virtual DerivedPaths toDerivedPaths() = 0; virtual StorePathSet toDrvPaths(ref store) { throw Error("'%s' cannot be converted to a derivation path", what()); } DerivedPath 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 {}; } virtual std::vector> getCursors(EvalState & state); virtual ref getCursor(EvalState & state); virtual FlakeRef nixpkgsFlakeRef() const { return FlakeRef::fromAttrs({{"type","indirect"}, {"id", "nixpkgs"}}); } static BuiltPaths build( ref evalStore, ref store, Realise mode, const std::vector> & installables, BuildMode bMode = bmNormal); static std::vector, BuiltPath>> 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); }; struct InstallableValue : Installable { ref state; InstallableValue(ref state) : state(state) {} struct DerivationInfo { StorePath drvPath; std::set outputsToInstall; std::optional priority; }; virtual std::vector toDerivations() = 0; DerivedPaths toDerivedPaths() override; StorePathSet toDrvPaths(ref store) override; }; struct InstallableFlake : InstallableValue { FlakeRef flakeRef; Strings attrPaths; Strings prefixes; OutputsSpec outputsSpec; const flake::LockFlags & lockFlags; mutable std::shared_ptr _lockedFlake; InstallableFlake( SourceExprCommand * cmd, ref state, FlakeRef && flakeRef, std::string_view fragment, OutputsSpec outputsSpec, 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); std::tuple toDerivation(); std::vector toDerivations() override; std::pair toValue(EvalState & state) override; /* Get a cursor to every attrpath in getActualAttrPaths() that exists. */ std::vector> getCursors(EvalState & state) override; /* Get a cursor to the first attrpath in getActualAttrPaths() that exists, or throw an exception with suggestions if none exists. */ ref getCursor(EvalState & state) override; std::shared_ptr getLockedFlake() const; FlakeRef nixpkgsFlakeRef() const override; }; ref openEvalCache( EvalState & state, std::shared_ptr lockedFlake); }