mirror of
https://github.com/NixOS/nix
synced 2025-06-27 08:31:16 +02:00
Move value-only methods to InstallableValue
These methods would previously fail on the other `Installable`s, so moving them to this class is more correct as to where they actually work. Additionally, a `InstallableValueCommand` is created to make it easier (or rather no worse than before) to write commands that just work on `InstallableValue`s. Besides being a cleanup to avoid failing default methods, this gets us closer to https://github.com/NixOS/rfcs/pull/134.
This commit is contained in:
parent
acd707acca
commit
c998e0172f
14 changed files with 127 additions and 71 deletions
11
src/libcmd/command-installable-value.cc
Normal file
11
src/libcmd/command-installable-value.cc
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include "command-installable-value.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
void InstallableValueCommand::run(ref<Store> store, ref<Installable> installable)
|
||||
{
|
||||
auto installableValue = InstallableValue::require(installable);
|
||||
run(store, installableValue);
|
||||
}
|
||||
|
||||
}
|
13
src/libcmd/command-installable-value.hh
Normal file
13
src/libcmd/command-installable-value.hh
Normal file
|
@ -0,0 +1,13 @@
|
|||
#include "installable-value.hh"
|
||||
#include "command.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
struct InstallableValueCommand : InstallableCommand
|
||||
{
|
||||
virtual void run(ref<Store> store, ref<InstallableValue> installable) = 0;
|
||||
|
||||
void run(ref<Store> store, ref<Installable> installable) override;
|
||||
};
|
||||
|
||||
}
|
44
src/libcmd/installable-value.cc
Normal file
44
src/libcmd/installable-value.cc
Normal file
|
@ -0,0 +1,44 @@
|
|||
#include "installable-value.hh"
|
||||
#include "eval-cache.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
std::vector<ref<eval_cache::AttrCursor>>
|
||||
InstallableValue::getCursors(EvalState & state)
|
||||
{
|
||||
auto evalCache =
|
||||
std::make_shared<nix::eval_cache::EvalCache>(std::nullopt, state,
|
||||
[&]() { return toValue(state).first; });
|
||||
return {evalCache->getRoot()};
|
||||
}
|
||||
|
||||
ref<eval_cache::AttrCursor>
|
||||
InstallableValue::getCursor(EvalState & state)
|
||||
{
|
||||
/* Although getCursors should return at least one element, in case it doesn't,
|
||||
bound check to avoid an undefined behavior for vector[0] */
|
||||
return getCursors(state).at(0);
|
||||
}
|
||||
|
||||
static UsageError nonValueInstallable(Installable & installable)
|
||||
{
|
||||
return UsageError("installable '%s' does not correspond to a Nix language value", installable.what());
|
||||
}
|
||||
|
||||
InstallableValue & InstallableValue::require(Installable & installable)
|
||||
{
|
||||
auto * castedInstallable = dynamic_cast<InstallableValue *>(&installable);
|
||||
if (!castedInstallable)
|
||||
throw nonValueInstallable(installable);
|
||||
return *castedInstallable;
|
||||
}
|
||||
|
||||
ref<InstallableValue> InstallableValue::require(ref<Installable> installable)
|
||||
{
|
||||
auto castedInstallable = installable.dynamic_pointer_cast<InstallableValue>();
|
||||
if (!castedInstallable)
|
||||
throw nonValueInstallable(*installable);
|
||||
return ref { castedInstallable };
|
||||
}
|
||||
|
||||
}
|
|
@ -4,11 +4,41 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
struct App
|
||||
{
|
||||
std::vector<DerivedPath> context;
|
||||
Path program;
|
||||
// FIXME: add args, sandbox settings, metadata, ...
|
||||
};
|
||||
|
||||
struct UnresolvedApp
|
||||
{
|
||||
App unresolved;
|
||||
App resolve(ref<Store> evalStore, ref<Store> store);
|
||||
};
|
||||
|
||||
struct InstallableValue : Installable
|
||||
{
|
||||
ref<EvalState> state;
|
||||
|
||||
InstallableValue(ref<EvalState> state) : state(state) {}
|
||||
|
||||
virtual std::pair<Value *, PosIdx> toValue(EvalState & state) = 0;
|
||||
|
||||
/* 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<ref<eval_cache::AttrCursor>>
|
||||
getCursors(EvalState & state);
|
||||
|
||||
/* Get the first and most preferred cursor this Installable could refer
|
||||
to, or throw an exception if none exists. */
|
||||
virtual ref<eval_cache::AttrCursor>
|
||||
getCursor(EvalState & state);
|
||||
|
||||
UnresolvedApp toApp(EvalState & state);
|
||||
|
||||
static InstallableValue & require(Installable & installable);
|
||||
static ref<InstallableValue> require(ref<Installable> installable);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -364,23 +364,6 @@ DerivedPathWithInfo Installable::toDerivedPath()
|
|||
return std::move(buildables[0]);
|
||||
}
|
||||
|
||||
std::vector<ref<eval_cache::AttrCursor>>
|
||||
Installable::getCursors(EvalState & state)
|
||||
{
|
||||
auto evalCache =
|
||||
std::make_shared<nix::eval_cache::EvalCache>(std::nullopt, state,
|
||||
[&]() { return toValue(state).first; });
|
||||
return {evalCache->getRoot()};
|
||||
}
|
||||
|
||||
ref<eval_cache::AttrCursor>
|
||||
Installable::getCursor(EvalState & state)
|
||||
{
|
||||
/* Although getCursors should return at least one element, in case it doesn't,
|
||||
bound check to avoid an undefined behavior for vector[0] */
|
||||
return getCursors(state).at(0);
|
||||
}
|
||||
|
||||
static StorePath getDeriver(
|
||||
ref<Store> store,
|
||||
const Installable & i,
|
||||
|
|
|
@ -18,19 +18,6 @@ struct SourceExprCommand;
|
|||
|
||||
namespace eval_cache { class EvalCache; class AttrCursor; }
|
||||
|
||||
struct App
|
||||
{
|
||||
std::vector<DerivedPath> context;
|
||||
Path program;
|
||||
// FIXME: add args, sandbox settings, metadata, ...
|
||||
};
|
||||
|
||||
struct UnresolvedApp
|
||||
{
|
||||
App unresolved;
|
||||
App resolve(ref<Store> evalStore, ref<Store> store);
|
||||
};
|
||||
|
||||
enum class Realise {
|
||||
/* Build the derivation. Postcondition: the
|
||||
derivation outputs exist. */
|
||||
|
@ -92,13 +79,6 @@ struct Installable
|
|||
|
||||
DerivedPathWithInfo toDerivedPath();
|
||||
|
||||
UnresolvedApp toApp(EvalState & state);
|
||||
|
||||
virtual std::pair<Value *, PosIdx> 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<StorePath> getStorePath()
|
||||
|
@ -106,16 +86,6 @@ struct Installable
|
|||
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<ref<eval_cache::AttrCursor>>
|
||||
getCursors(EvalState & state);
|
||||
|
||||
/* Get the first and most preferred cursor this Installable could refer
|
||||
to, or throw an exception if none exists. */
|
||||
virtual ref<eval_cache::AttrCursor>
|
||||
getCursor(EvalState & state);
|
||||
|
||||
virtual FlakeRef nixpkgsFlakeRef() const
|
||||
{
|
||||
return FlakeRef::fromAttrs({{"type","indirect"}, {"id", "nixpkgs"}});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue