Skip to content

Commit

Permalink
Merge pull request #7763 from obsidiansystems/installable-wide-info
Browse files Browse the repository at this point in the history
Stratify `ExtraPathInfo` along `Installable` hierarchy
  • Loading branch information
edolstra authored Mar 27, 2023
2 parents 237587b + 256f3e3 commit 5e3f855
Show file tree
Hide file tree
Showing 12 changed files with 254 additions and 76 deletions.
2 changes: 1 addition & 1 deletion src/libcmd/command.hh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#include "installables.hh"
#include "installable-value.hh"
#include "args.hh"
#include "common-eval-args.hh"
#include "path.hh"
Expand Down
4 changes: 4 additions & 0 deletions src/libcmd/installable-attr-path.cc
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ DerivedPathsWithInfo InstallableAttrPath::toDerivedPaths()
.drvPath = drvPath,
.outputs = outputs,
},
.info = make_ref<ExtraPathInfoValue>(ExtraPathInfoValue::Value {
/* FIXME: reconsider backwards compatibility above
so we can fill in this info. */
}),
});

return res;
Expand Down
5 changes: 4 additions & 1 deletion src/libcmd/installable-derived-path.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ std::string InstallableDerivedPath::what() const

DerivedPathsWithInfo InstallableDerivedPath::toDerivedPaths()
{
return {{.path = derivedPath, .info = {} }};
return {{
.path = derivedPath,
.info = make_ref<ExtraPathInfo>(),
}};
}

std::optional<StorePath> InstallableDerivedPath::getStorePath()
Expand Down
26 changes: 16 additions & 10 deletions src/libcmd/installable-flake.cc
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ DerivedPathsWithInfo InstallableFlake::toDerivedPaths()
return {{
.path = DerivedPath::Opaque {
.path = std::move(storePath),
}
},
.info = make_ref<ExtraPathInfo>(),
}};
}

Expand All @@ -113,7 +114,8 @@ DerivedPathsWithInfo InstallableFlake::toDerivedPaths()
return {{
.path = DerivedPath::Opaque {
.path = std::move(*storePath),
}
},
.info = make_ref<ExtraPathInfo>(),
}};
} else
throw Error("flake output attribute '%s' evaluates to the string '%s' which is not a store path", attrPath, s);
Expand Down Expand Up @@ -160,13 +162,16 @@ DerivedPathsWithInfo InstallableFlake::toDerivedPaths()
},
}, extendedOutputsSpec.raw()),
},
.info = {
.priority = priority,
.originalRef = flakeRef,
.resolvedRef = getLockedFlake()->flake.lockedRef,
.attrPath = attrPath,
.extendedOutputsSpec = extendedOutputsSpec,
}
.info = make_ref<ExtraPathInfoFlake>(
ExtraPathInfoValue::Value {
.priority = priority,
.attrPath = attrPath,
.extendedOutputsSpec = extendedOutputsSpec,
},
ExtraPathInfoFlake::Flake {
.originalRef = flakeRef,
.resolvedRef = getLockedFlake()->flake.lockedRef,
}),
}};
}

Expand Down Expand Up @@ -212,6 +217,7 @@ std::shared_ptr<flake::LockedFlake> InstallableFlake::getLockedFlake() const
{
if (!_lockedFlake) {
flake::LockFlags lockFlagsApplyConfig = lockFlags;
// FIXME why this side effect?
lockFlagsApplyConfig.applyNixConfig = true;
_lockedFlake = std::make_shared<flake::LockedFlake>(lockFlake(*state, flakeRef, lockFlagsApplyConfig));
}
Expand All @@ -229,7 +235,7 @@ FlakeRef InstallableFlake::nixpkgsFlakeRef() const
}
}

return Installable::nixpkgsFlakeRef();
return InstallableValue::nixpkgsFlakeRef();
}

}
30 changes: 28 additions & 2 deletions src/libcmd/installable-flake.hh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,30 @@

namespace nix {

/**
* Extra info about a \ref DerivedPath "derived path" that ultimately
* come from a Flake.
*
* Invariant: every ExtraPathInfo gotten from an InstallableFlake should
* be possible to downcast to an ExtraPathInfoFlake.
*/
struct ExtraPathInfoFlake : ExtraPathInfoValue
{
/**
* Extra struct to get around C++ designated initializer limitations
*/
struct Flake {
FlakeRef originalRef;
FlakeRef resolvedRef;
};

Flake flake;

ExtraPathInfoFlake(Value && v, Flake && f)
: ExtraPathInfoValue(std::move(v)), flake(f)
{ }
};

struct InstallableFlake : InstallableValue
{
FlakeRef flakeRef;
Expand Down Expand Up @@ -33,8 +57,10 @@ struct InstallableFlake : InstallableValue

std::pair<Value *, PosIdx> toValue(EvalState & state) override;

/* Get a cursor to every attrpath in getActualAttrPaths()
that exists. However if none exists, throw an exception. */
/**
* Get a cursor to every attrpath in getActualAttrPaths() that
* exists. However if none exists, throw an exception.
*/
std::vector<ref<eval_cache::AttrCursor>>
getCursors(EvalState & state) override;

Expand Down
71 changes: 67 additions & 4 deletions src/libcmd/installable-value.hh
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
#pragma once

#include "installables.hh"
#include "flake/flake.hh"

namespace nix {

struct DrvInfo;
struct SourceExprCommand;

namespace eval_cache { class EvalCache; class AttrCursor; }

struct App
{
std::vector<DerivedPath> context;
Expand All @@ -17,26 +23,83 @@ struct UnresolvedApp
App resolve(ref<Store> evalStore, ref<Store> store);
};

/**
* Extra info about a \ref DerivedPath "derived path" that ultimately
* come from a Nix language value.
*
* Invariant: every ExtraPathInfo gotten from an InstallableValue should
* be possible to downcast to an ExtraPathInfoValue.
*/
struct ExtraPathInfoValue : ExtraPathInfo
{
/**
* Extra struct to get around C++ designated initializer limitations
*/
struct Value {
/**
* An optional priority for use with "build envs". See Package
*/
std::optional<NixInt> priority;

/**
* The attribute path associated with this value. The idea is
* that an installable referring to a value typically refers to
* a larger value, from which we project a smaller value out
* with this.
*/
std::string attrPath;

/**
* \todo merge with DerivedPath's 'outputs' field?
*/
ExtendedOutputsSpec extendedOutputsSpec;
};

Value value;

ExtraPathInfoValue(Value && v)
: value(v)
{ }

virtual ~ExtraPathInfoValue() = default;
};

/**
* An Installable which corresponds a Nix langauge value, in addition to
* a collection of \ref DerivedPath "derived paths".
*/
struct InstallableValue : Installable
{
ref<EvalState> state;

InstallableValue(ref<EvalState> state) : state(state) {}

virtual ~InstallableValue() { }

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. */
/**
* 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. */
/**
* 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);

virtual FlakeRef nixpkgsFlakeRef() const
{
return FlakeRef::fromAttrs({{"type","indirect"}, {"id", "nixpkgs"}});
}

static InstallableValue & require(Installable & installable);
static ref<InstallableValue> require(ref<Installable> installable);
};
Expand Down
2 changes: 1 addition & 1 deletion src/libcmd/installables.cc
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ std::vector<std::pair<ref<Installable>, BuiltPathWithResult>> Installable::build

struct Aux
{
ExtraPathInfo info;
ref<ExtraPathInfo> info;
ref<Installable> installable;
};

Expand Down
Loading

0 comments on commit 5e3f855

Please sign in to comment.