forked from lix-project/lix
Merge pull request #6197 from edolstra/nix-profile-ca
nix profile: Support CA derivations
This commit is contained in:
commit
3e3d0711d4
|
@ -28,7 +28,7 @@ run_test "$1"
|
||||||
# See https://github.com/NixOS/nix/issues/3605 for more info
|
# See https://github.com/NixOS/nix/issues/3605 for more info
|
||||||
if [[ $status -ne 0 && $status -ne 99 && \
|
if [[ $status -ne 0 && $status -ne 99 && \
|
||||||
"$(uname)" == "Darwin" && \
|
"$(uname)" == "Darwin" && \
|
||||||
"$log" =~ "unexpected EOF reading a line"
|
"$log" =~ "unexpected EOF reading a line" \
|
||||||
]]; then
|
]]; then
|
||||||
echo "$post_run_msg [${yellow}FAIL$normal] (possibly flaky, so will be retried)"
|
echo "$post_run_msg [${yellow}FAIL$normal] (possibly flaky, so will be retried)"
|
||||||
echo "$log" | sed 's/^/ /'
|
echo "$log" | sed 's/^/ /'
|
||||||
|
|
|
@ -153,7 +153,7 @@ void BuiltPathsCommand::run(ref<Store> store)
|
||||||
for (auto & p : store->queryAllValidPaths())
|
for (auto & p : store->queryAllValidPaths())
|
||||||
paths.push_back(BuiltPath::Opaque{p});
|
paths.push_back(BuiltPath::Opaque{p});
|
||||||
} else {
|
} else {
|
||||||
paths = toBuiltPaths(getEvalStore(), store, realiseMode, operateOn, installables);
|
paths = Installable::toBuiltPaths(getEvalStore(), store, realiseMode, operateOn, installables);
|
||||||
if (recursive) {
|
if (recursive) {
|
||||||
// XXX: This only computes the store path closure, ignoring
|
// XXX: This only computes the store path closure, ignoring
|
||||||
// intermediate realisations
|
// intermediate realisations
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include "common-eval-args.hh"
|
#include "common-eval-args.hh"
|
||||||
#include "path.hh"
|
#include "path.hh"
|
||||||
#include "flake/lockfile.hh"
|
#include "flake/lockfile.hh"
|
||||||
#include "store-api.hh"
|
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
|
@ -82,14 +81,6 @@ struct MixFlakeOptions : virtual Args, EvalCommand
|
||||||
{ return {}; }
|
{ return {}; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 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 SourceExprCommand : virtual Args, MixFlakeOptions
|
struct SourceExprCommand : virtual Args, MixFlakeOptions
|
||||||
{
|
{
|
||||||
std::optional<Path> file;
|
std::optional<Path> file;
|
||||||
|
@ -113,19 +104,6 @@ struct SourceExprCommand : virtual Args, MixFlakeOptions
|
||||||
void completeInstallable(std::string_view prefix);
|
void completeInstallable(std::string_view prefix);
|
||||||
};
|
};
|
||||||
|
|
||||||
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
|
|
||||||
};
|
|
||||||
|
|
||||||
/* A command that operates on a list of "installables", which can be
|
/* A command that operates on a list of "installables", which can be
|
||||||
store paths, attribute paths, Nix expressions, etc. */
|
store paths, attribute paths, Nix expressions, etc. */
|
||||||
struct InstallablesCommand : virtual Args, SourceExprCommand
|
struct InstallablesCommand : virtual Args, SourceExprCommand
|
||||||
|
@ -238,38 +216,6 @@ static RegisterCommand registerCommand2(std::vector<std::string> && name)
|
||||||
return RegisterCommand(std::move(name), [](){ return make_ref<T>(); });
|
return RegisterCommand(std::move(name), [](){ return make_ref<T>(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
BuiltPaths build(
|
|
||||||
ref<Store> evalStore,
|
|
||||||
ref<Store> store, Realise mode,
|
|
||||||
const std::vector<std::shared_ptr<Installable>> & installables,
|
|
||||||
BuildMode bMode = bmNormal);
|
|
||||||
|
|
||||||
std::set<StorePath> toStorePaths(
|
|
||||||
ref<Store> evalStore,
|
|
||||||
ref<Store> store,
|
|
||||||
Realise mode,
|
|
||||||
OperateOn operateOn,
|
|
||||||
const std::vector<std::shared_ptr<Installable>> & installables);
|
|
||||||
|
|
||||||
StorePath toStorePath(
|
|
||||||
ref<Store> evalStore,
|
|
||||||
ref<Store> store,
|
|
||||||
Realise mode,
|
|
||||||
OperateOn operateOn,
|
|
||||||
std::shared_ptr<Installable> installable);
|
|
||||||
|
|
||||||
std::set<StorePath> toDerivations(
|
|
||||||
ref<Store> store,
|
|
||||||
const std::vector<std::shared_ptr<Installable>> & installables,
|
|
||||||
bool useDeriver = false);
|
|
||||||
|
|
||||||
BuiltPaths toBuiltPaths(
|
|
||||||
ref<Store> evalStore,
|
|
||||||
ref<Store> store,
|
|
||||||
Realise mode,
|
|
||||||
OperateOn operateOn,
|
|
||||||
const std::vector<std::shared_ptr<Installable>> & installables);
|
|
||||||
|
|
||||||
/* Helper function to generate args that invoke $EDITOR on
|
/* Helper function to generate args that invoke $EDITOR on
|
||||||
filename:lineno. */
|
filename:lineno. */
|
||||||
Strings editorFor(const Pos & pos);
|
Strings editorFor(const Pos & pos);
|
||||||
|
|
|
@ -470,7 +470,6 @@ std::vector<InstallableValue::DerivationInfo> InstallableAttrPath::toDerivations
|
||||||
for (auto & drvInfo : drvInfos) {
|
for (auto & drvInfo : drvInfos) {
|
||||||
res.push_back({
|
res.push_back({
|
||||||
state->store->parseStorePath(drvInfo.queryDrvPath()),
|
state->store->parseStorePath(drvInfo.queryDrvPath()),
|
||||||
state->store->maybeParseStorePath(drvInfo.queryOutPath()),
|
|
||||||
drvInfo.queryOutputName()
|
drvInfo.queryOutputName()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -584,9 +583,8 @@ std::tuple<std::string, FlakeRef, InstallableValue::DerivationInfo> InstallableF
|
||||||
|
|
||||||
auto drvPath = attr->forceDerivation();
|
auto drvPath = attr->forceDerivation();
|
||||||
|
|
||||||
auto drvInfo = DerivationInfo{
|
auto drvInfo = DerivationInfo {
|
||||||
std::move(drvPath),
|
std::move(drvPath),
|
||||||
state->store->maybeParseStorePath(attr->getAttr(state->sOutPath)->getString()),
|
|
||||||
attr->getAttr(state->sOutputName)->getString()
|
attr->getAttr(state->sOutputName)->getString()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -787,7 +785,7 @@ BuiltPaths getBuiltPaths(ref<Store> evalStore, ref<Store> store, const DerivedPa
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
BuiltPaths build(
|
BuiltPaths Installable::build(
|
||||||
ref<Store> evalStore,
|
ref<Store> evalStore,
|
||||||
ref<Store> store,
|
ref<Store> store,
|
||||||
Realise mode,
|
Realise mode,
|
||||||
|
@ -812,7 +810,7 @@ BuiltPaths build(
|
||||||
return getBuiltPaths(evalStore, store, pathsToBuild);
|
return getBuiltPaths(evalStore, store, pathsToBuild);
|
||||||
}
|
}
|
||||||
|
|
||||||
BuiltPaths toBuiltPaths(
|
BuiltPaths Installable::toBuiltPaths(
|
||||||
ref<Store> evalStore,
|
ref<Store> evalStore,
|
||||||
ref<Store> store,
|
ref<Store> store,
|
||||||
Realise mode,
|
Realise mode,
|
||||||
|
@ -820,19 +818,19 @@ BuiltPaths toBuiltPaths(
|
||||||
const std::vector<std::shared_ptr<Installable>> & installables)
|
const std::vector<std::shared_ptr<Installable>> & installables)
|
||||||
{
|
{
|
||||||
if (operateOn == OperateOn::Output)
|
if (operateOn == OperateOn::Output)
|
||||||
return build(evalStore, store, mode, installables);
|
return Installable::build(evalStore, store, mode, installables);
|
||||||
else {
|
else {
|
||||||
if (mode == Realise::Nothing)
|
if (mode == Realise::Nothing)
|
||||||
settings.readOnlyMode = true;
|
settings.readOnlyMode = true;
|
||||||
|
|
||||||
BuiltPaths res;
|
BuiltPaths res;
|
||||||
for (auto & drvPath : toDerivations(store, installables, true))
|
for (auto & drvPath : Installable::toDerivations(store, installables, true))
|
||||||
res.push_back(BuiltPath::Opaque{drvPath});
|
res.push_back(BuiltPath::Opaque{drvPath});
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StorePathSet toStorePaths(
|
StorePathSet Installable::toStorePaths(
|
||||||
ref<Store> evalStore,
|
ref<Store> evalStore,
|
||||||
ref<Store> store,
|
ref<Store> store,
|
||||||
Realise mode, OperateOn operateOn,
|
Realise mode, OperateOn operateOn,
|
||||||
|
@ -846,7 +844,7 @@ StorePathSet toStorePaths(
|
||||||
return outPaths;
|
return outPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
StorePath toStorePath(
|
StorePath Installable::toStorePath(
|
||||||
ref<Store> evalStore,
|
ref<Store> evalStore,
|
||||||
ref<Store> store,
|
ref<Store> store,
|
||||||
Realise mode, OperateOn operateOn,
|
Realise mode, OperateOn operateOn,
|
||||||
|
@ -860,7 +858,7 @@ StorePath toStorePath(
|
||||||
return *paths.begin();
|
return *paths.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
StorePathSet toDerivations(
|
StorePathSet Installable::toDerivations(
|
||||||
ref<Store> store,
|
ref<Store> store,
|
||||||
const std::vector<std::shared_ptr<Installable>> & installables,
|
const std::vector<std::shared_ptr<Installable>> & installables,
|
||||||
bool useDeriver)
|
bool useDeriver)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "path-with-outputs.hh"
|
#include "path-with-outputs.hh"
|
||||||
#include "derived-path.hh"
|
#include "derived-path.hh"
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
|
#include "store-api.hh"
|
||||||
#include "flake/flake.hh"
|
#include "flake/flake.hh"
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
@ -29,6 +30,27 @@ struct UnresolvedApp
|
||||||
App resolve(ref<Store> evalStore, ref<Store> store);
|
App resolve(ref<Store> evalStore, ref<Store> 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
|
struct Installable
|
||||||
{
|
{
|
||||||
virtual ~Installable() { }
|
virtual ~Installable() { }
|
||||||
|
@ -68,6 +90,39 @@ struct Installable
|
||||||
{
|
{
|
||||||
return FlakeRef::fromAttrs({{"type","indirect"}, {"id", "nixpkgs"}});
|
return FlakeRef::fromAttrs({{"type","indirect"}, {"id", "nixpkgs"}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BuiltPaths build(
|
||||||
|
ref<Store> evalStore,
|
||||||
|
ref<Store> store,
|
||||||
|
Realise mode,
|
||||||
|
const std::vector<std::shared_ptr<Installable>> & installables,
|
||||||
|
BuildMode bMode = bmNormal);
|
||||||
|
|
||||||
|
static std::set<StorePath> toStorePaths(
|
||||||
|
ref<Store> evalStore,
|
||||||
|
ref<Store> store,
|
||||||
|
Realise mode,
|
||||||
|
OperateOn operateOn,
|
||||||
|
const std::vector<std::shared_ptr<Installable>> & installables);
|
||||||
|
|
||||||
|
static StorePath toStorePath(
|
||||||
|
ref<Store> evalStore,
|
||||||
|
ref<Store> store,
|
||||||
|
Realise mode,
|
||||||
|
OperateOn operateOn,
|
||||||
|
std::shared_ptr<Installable> installable);
|
||||||
|
|
||||||
|
static std::set<StorePath> toDerivations(
|
||||||
|
ref<Store> store,
|
||||||
|
const std::vector<std::shared_ptr<Installable>> & installables,
|
||||||
|
bool useDeriver = false);
|
||||||
|
|
||||||
|
static BuiltPaths toBuiltPaths(
|
||||||
|
ref<Store> evalStore,
|
||||||
|
ref<Store> store,
|
||||||
|
Realise mode,
|
||||||
|
OperateOn operateOn,
|
||||||
|
const std::vector<std::shared_ptr<Installable>> & installables);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InstallableValue : Installable
|
struct InstallableValue : Installable
|
||||||
|
@ -79,7 +134,6 @@ struct InstallableValue : Installable
|
||||||
struct DerivationInfo
|
struct DerivationInfo
|
||||||
{
|
{
|
||||||
StorePath drvPath;
|
StorePath drvPath;
|
||||||
std::optional<StorePath> outPath;
|
|
||||||
std::string outputName;
|
std::string outputName;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -131,4 +185,9 @@ ref<eval_cache::EvalCache> openEvalCache(
|
||||||
EvalState & state,
|
EvalState & state,
|
||||||
std::shared_ptr<flake::LockedFlake> lockedFlake);
|
std::shared_ptr<flake::LockedFlake> lockedFlake);
|
||||||
|
|
||||||
|
BuiltPaths getBuiltPaths(
|
||||||
|
ref<Store> evalStore,
|
||||||
|
ref<Store> store,
|
||||||
|
const DerivedPaths & hopefullyBuiltPaths);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,7 @@ App UnresolvedApp::resolve(ref<Store> evalStore, ref<Store> store)
|
||||||
installableContext.push_back(
|
installableContext.push_back(
|
||||||
std::make_shared<InstallableDerivedPath>(store, ctxElt.toDerivedPath()));
|
std::make_shared<InstallableDerivedPath>(store, ctxElt.toDerivedPath()));
|
||||||
|
|
||||||
auto builtContext = build(evalStore, store, Realise::Outputs, installableContext);
|
auto builtContext = Installable::build(evalStore, store, Realise::Outputs, installableContext);
|
||||||
res.program = resolveString(*store, unresolved.program, builtContext);
|
res.program = resolveString(*store, unresolved.program, builtContext);
|
||||||
if (!store->isInStore(res.program))
|
if (!store->isInStore(res.program))
|
||||||
throw Error("app program '%s' is not in the Nix store", res.program);
|
throw Error("app program '%s' is not in the Nix store", res.program);
|
||||||
|
|
|
@ -52,7 +52,7 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile
|
||||||
|
|
||||||
void run(ref<Store> store) override
|
void run(ref<Store> store) override
|
||||||
{
|
{
|
||||||
auto buildables = build(
|
auto buildables = Installable::build(
|
||||||
getEvalStore(), store,
|
getEvalStore(), store,
|
||||||
dryRun ? Realise::Derivation : Realise::Outputs,
|
dryRun ? Realise::Derivation : Realise::Outputs,
|
||||||
installables, buildMode);
|
installables, buildMode);
|
||||||
|
|
|
@ -307,7 +307,7 @@ struct Common : InstallableCommand, MixProfile
|
||||||
for (auto & [installable_, dir_] : redirects) {
|
for (auto & [installable_, dir_] : redirects) {
|
||||||
auto dir = absPath(dir_);
|
auto dir = absPath(dir_);
|
||||||
auto installable = parseInstallable(store, installable_);
|
auto installable = parseInstallable(store, installable_);
|
||||||
auto builtPaths = toStorePaths(
|
auto builtPaths = Installable::toStorePaths(
|
||||||
getEvalStore(), store, Realise::Nothing, OperateOn::Output, {installable});
|
getEvalStore(), store, Realise::Nothing, OperateOn::Output, {installable});
|
||||||
for (auto & path: builtPaths) {
|
for (auto & path: builtPaths) {
|
||||||
auto from = store->printStorePath(path);
|
auto from = store->printStorePath(path);
|
||||||
|
@ -347,7 +347,7 @@ struct Common : InstallableCommand, MixProfile
|
||||||
if (path && hasSuffix(path->to_string(), "-env"))
|
if (path && hasSuffix(path->to_string(), "-env"))
|
||||||
return *path;
|
return *path;
|
||||||
else {
|
else {
|
||||||
auto drvs = toDerivations(store, {installable});
|
auto drvs = Installable::toDerivations(store, {installable});
|
||||||
|
|
||||||
if (drvs.size() != 1)
|
if (drvs.size() != 1)
|
||||||
throw Error("'%s' needs to evaluate to a single derivation, but it evaluated to %d derivations",
|
throw Error("'%s' needs to evaluate to a single derivation, but it evaluated to %d derivations",
|
||||||
|
@ -511,7 +511,8 @@ struct CmdDevelop : Common, MixEnvironment
|
||||||
nixpkgsLockFlags);
|
nixpkgsLockFlags);
|
||||||
|
|
||||||
shell = store->printStorePath(
|
shell = store->printStorePath(
|
||||||
toStorePath(getEvalStore(), store, Realise::Outputs, OperateOn::Output, bashInstallable)) + "/bin/bash";
|
Installable::toStorePath(getEvalStore(), store, Realise::Outputs, OperateOn::Output, bashInstallable))
|
||||||
|
+ "/bin/bash";
|
||||||
} catch (Error &) {
|
} catch (Error &) {
|
||||||
ignoreException();
|
ignoreException();
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,9 +131,9 @@ struct CmdDiffClosures : SourceExprCommand
|
||||||
void run(ref<Store> store) override
|
void run(ref<Store> store) override
|
||||||
{
|
{
|
||||||
auto before = parseInstallable(store, _before);
|
auto before = parseInstallable(store, _before);
|
||||||
auto beforePath = toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, before);
|
auto beforePath = Installable::toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, before);
|
||||||
auto after = parseInstallable(store, _after);
|
auto after = parseInstallable(store, _after);
|
||||||
auto afterPath = toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, after);
|
auto afterPath = Installable::toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, after);
|
||||||
printClosureDiff(store, beforePath, afterPath, "");
|
printClosureDiff(store, beforePath, afterPath, "");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -61,6 +61,27 @@ struct ProfileElement
|
||||||
{
|
{
|
||||||
return std::tuple(describe(), storePaths) < std::tuple(other.describe(), other.storePaths);
|
return std::tuple(describe(), storePaths) < std::tuple(other.describe(), other.storePaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateStorePaths(ref<Store> evalStore, ref<Store> store, Installable & installable)
|
||||||
|
{
|
||||||
|
// FIXME: respect meta.outputsToInstall
|
||||||
|
storePaths.clear();
|
||||||
|
for (auto & buildable : getBuiltPaths(evalStore, store, installable.toDerivedPaths())) {
|
||||||
|
std::visit(overloaded {
|
||||||
|
[&](const BuiltPath::Opaque & bo) {
|
||||||
|
storePaths.insert(bo.path);
|
||||||
|
},
|
||||||
|
[&](const BuiltPath::Built & bfd) {
|
||||||
|
// TODO: Why are we querying if we know the output
|
||||||
|
// names already? Is it just to figure out what the
|
||||||
|
// default one is?
|
||||||
|
for (auto & output : store->queryDerivationOutputMap(bfd.drvPath)) {
|
||||||
|
storePaths.insert(output.second);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}, buildable.raw());
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ProfileManifest
|
struct ProfileManifest
|
||||||
|
@ -232,53 +253,25 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
|
||||||
{
|
{
|
||||||
ProfileManifest manifest(*getEvalState(), *profile);
|
ProfileManifest manifest(*getEvalState(), *profile);
|
||||||
|
|
||||||
std::vector<DerivedPath> pathsToBuild;
|
auto builtPaths = Installable::build(getEvalStore(), store, Realise::Outputs, installables, bmNormal);
|
||||||
|
|
||||||
for (auto & installable : installables) {
|
for (auto & installable : installables) {
|
||||||
if (auto installable2 = std::dynamic_pointer_cast<InstallableFlake>(installable)) {
|
ProfileElement element;
|
||||||
auto [attrPath, resolvedRef, drv] = installable2->toDerivation();
|
|
||||||
|
|
||||||
ProfileElement element;
|
if (auto installable2 = std::dynamic_pointer_cast<InstallableFlake>(installable)) {
|
||||||
if (!drv.outPath)
|
// FIXME: make build() return this?
|
||||||
throw UnimplementedError("CA derivations are not yet supported by 'nix profile'");
|
auto [attrPath, resolvedRef, drv] = installable2->toDerivation();
|
||||||
element.storePaths = {*drv.outPath}; // FIXME
|
|
||||||
element.source = ProfileElementSource{
|
element.source = ProfileElementSource{
|
||||||
installable2->flakeRef,
|
installable2->flakeRef,
|
||||||
resolvedRef,
|
resolvedRef,
|
||||||
attrPath,
|
attrPath,
|
||||||
};
|
};
|
||||||
|
|
||||||
pathsToBuild.push_back(DerivedPath::Built{drv.drvPath, StringSet{drv.outputName}});
|
|
||||||
|
|
||||||
manifest.elements.emplace_back(std::move(element));
|
|
||||||
} else {
|
|
||||||
auto buildables = build(getEvalStore(), store, Realise::Outputs, {installable}, bmNormal);
|
|
||||||
|
|
||||||
for (auto & buildable : buildables) {
|
|
||||||
ProfileElement element;
|
|
||||||
|
|
||||||
std::visit(overloaded {
|
|
||||||
[&](const BuiltPath::Opaque & bo) {
|
|
||||||
pathsToBuild.push_back(bo);
|
|
||||||
element.storePaths.insert(bo.path);
|
|
||||||
},
|
|
||||||
[&](const BuiltPath::Built & bfd) {
|
|
||||||
// TODO: Why are we querying if we know the output
|
|
||||||
// names already? Is it just to figure out what the
|
|
||||||
// default one is?
|
|
||||||
for (auto & output : store->queryDerivationOutputMap(bfd.drvPath)) {
|
|
||||||
pathsToBuild.push_back(DerivedPath::Built{bfd.drvPath, {output.first}});
|
|
||||||
element.storePaths.insert(output.second);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}, buildable.raw());
|
|
||||||
|
|
||||||
manifest.elements.emplace_back(std::move(element));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
store->buildPaths(pathsToBuild);
|
element.updateStorePaths(getEvalStore(), store, *installable);
|
||||||
|
|
||||||
|
manifest.elements.push_back(std::move(element));
|
||||||
|
}
|
||||||
|
|
||||||
updateProfile(manifest.build(store));
|
updateProfile(manifest.build(store));
|
||||||
}
|
}
|
||||||
|
@ -407,8 +400,8 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf
|
||||||
|
|
||||||
auto matchers = getMatchers(store);
|
auto matchers = getMatchers(store);
|
||||||
|
|
||||||
// FIXME: code duplication
|
std::vector<std::shared_ptr<Installable>> installables;
|
||||||
std::vector<DerivedPath> pathsToBuild;
|
std::vector<size_t> indices;
|
||||||
|
|
||||||
auto upgradedCount = 0;
|
auto upgradedCount = 0;
|
||||||
|
|
||||||
|
@ -423,32 +416,30 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf
|
||||||
Activity act(*logger, lvlChatty, actUnknown,
|
Activity act(*logger, lvlChatty, actUnknown,
|
||||||
fmt("checking '%s' for updates", element.source->attrPath));
|
fmt("checking '%s' for updates", element.source->attrPath));
|
||||||
|
|
||||||
InstallableFlake installable(
|
auto installable = std::make_shared<InstallableFlake>(
|
||||||
this,
|
this,
|
||||||
getEvalState(),
|
getEvalState(),
|
||||||
FlakeRef(element.source->originalRef),
|
FlakeRef(element.source->originalRef),
|
||||||
"",
|
"",
|
||||||
{element.source->attrPath},
|
Strings{element.source->attrPath},
|
||||||
{},
|
Strings{},
|
||||||
lockFlags);
|
lockFlags);
|
||||||
|
|
||||||
auto [attrPath, resolvedRef, drv] = installable.toDerivation();
|
auto [attrPath, resolvedRef, drv] = installable->toDerivation();
|
||||||
|
|
||||||
if (element.source->resolvedRef == resolvedRef) continue;
|
if (element.source->resolvedRef == resolvedRef) continue;
|
||||||
|
|
||||||
printInfo("upgrading '%s' from flake '%s' to '%s'",
|
printInfo("upgrading '%s' from flake '%s' to '%s'",
|
||||||
element.source->attrPath, element.source->resolvedRef, resolvedRef);
|
element.source->attrPath, element.source->resolvedRef, resolvedRef);
|
||||||
|
|
||||||
if (!drv.outPath)
|
|
||||||
throw UnimplementedError("CA derivations are not yet supported by 'nix profile'");
|
|
||||||
element.storePaths = {*drv.outPath}; // FIXME
|
|
||||||
element.source = ProfileElementSource{
|
element.source = ProfileElementSource{
|
||||||
installable.flakeRef,
|
installable->flakeRef,
|
||||||
resolvedRef,
|
resolvedRef,
|
||||||
attrPath,
|
attrPath,
|
||||||
};
|
};
|
||||||
|
|
||||||
pathsToBuild.push_back(DerivedPath::Built{drv.drvPath, {drv.outputName}});
|
installables.push_back(installable);
|
||||||
|
indices.push_back(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,7 +456,13 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf
|
||||||
warn ("Use 'nix profile list' to see the current profile.");
|
warn ("Use 'nix profile list' to see the current profile.");
|
||||||
}
|
}
|
||||||
|
|
||||||
store->buildPaths(pathsToBuild);
|
auto builtPaths = Installable::build(getEvalStore(), store, Realise::Outputs, installables, bmNormal);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < installables.size(); ++i) {
|
||||||
|
auto & installable = installables.at(i);
|
||||||
|
auto & element = manifest.elements[indices.at(i)];
|
||||||
|
element.updateStorePaths(getEvalStore(), store, *installable);
|
||||||
|
}
|
||||||
|
|
||||||
updateProfile(manifest.build(store));
|
updateProfile(manifest.build(store));
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ struct CmdShell : InstallablesCommand, MixEnvironment
|
||||||
|
|
||||||
void run(ref<Store> store) override
|
void run(ref<Store> store) override
|
||||||
{
|
{
|
||||||
auto outPaths = toStorePaths(getEvalStore(), store, Realise::Outputs, OperateOn::Output, installables);
|
auto outPaths = Installable::toStorePaths(getEvalStore(), store, Realise::Outputs, OperateOn::Output, installables);
|
||||||
|
|
||||||
auto accessor = store->getFSAccessor();
|
auto accessor = store->getFSAccessor();
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ struct CmdShowDerivation : InstallablesCommand
|
||||||
|
|
||||||
void run(ref<Store> store) override
|
void run(ref<Store> store) override
|
||||||
{
|
{
|
||||||
auto drvPaths = toDerivations(store, installables, true);
|
auto drvPaths = Installable::toDerivations(store, installables, true);
|
||||||
|
|
||||||
if (recursive) {
|
if (recursive) {
|
||||||
StorePathSet closure;
|
StorePathSet closure;
|
||||||
|
|
|
@ -82,9 +82,9 @@ struct CmdWhyDepends : SourceExprCommand
|
||||||
void run(ref<Store> store) override
|
void run(ref<Store> store) override
|
||||||
{
|
{
|
||||||
auto package = parseInstallable(store, _package);
|
auto package = parseInstallable(store, _package);
|
||||||
auto packagePath = toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, package);
|
auto packagePath = Installable::toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, package);
|
||||||
auto dependency = parseInstallable(store, _dependency);
|
auto dependency = parseInstallable(store, _dependency);
|
||||||
auto dependencyPath = toStorePath(getEvalStore(), store, Realise::Derivation, operateOn, dependency);
|
auto dependencyPath = Installable::toStorePath(getEvalStore(), store, Realise::Derivation, operateOn, dependency);
|
||||||
auto dependencyPathHash = dependencyPath.hashPart();
|
auto dependencyPathHash = dependencyPath.hashPart();
|
||||||
|
|
||||||
StorePathSet closure;
|
StorePathSet closure;
|
||||||
|
|
|
@ -2,7 +2,7 @@ source common.sh
|
||||||
|
|
||||||
file=build-hook-ca-floating.nix
|
file=build-hook-ca-floating.nix
|
||||||
|
|
||||||
sed -i 's/experimental-features .*/& ca-derivations/' "$NIX_CONF_DIR"/nix.conf
|
enableFeatures "ca-derivations ca-references"
|
||||||
|
|
||||||
CONTENT_ADDRESSED=true
|
CONTENT_ADDRESSED=true
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ testCutoffFor () {
|
||||||
}
|
}
|
||||||
|
|
||||||
testCutoff () {
|
testCutoff () {
|
||||||
# Don't directly build depenentCA, that way we'll make sure we dodn't rely on
|
# Don't directly build dependentCA, that way we'll make sure we don't rely on
|
||||||
# dependent derivations always being already built.
|
# dependent derivations always being already built.
|
||||||
#testDerivation dependentCA
|
#testDerivation dependentCA
|
||||||
testCutoffFor transitivelyDependentCA
|
testCutoffFor transitivelyDependentCA
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
source ../common.sh
|
source ../common.sh
|
||||||
|
|
||||||
sed -i 's/experimental-features .*/& ca-derivations ca-references/' "$NIX_CONF_DIR"/nix.conf
|
enableFeatures "ca-derivations ca-references"
|
||||||
|
|
||||||
restartDaemon
|
restartDaemon
|
||||||
|
|
|
@ -2,8 +2,6 @@ source ./common.sh
|
||||||
|
|
||||||
requireDaemonNewerThan "2.4pre20210625"
|
requireDaemonNewerThan "2.4pre20210625"
|
||||||
|
|
||||||
sed -i 's/experimental-features .*/& ca-derivations ca-references/' "$NIX_CONF_DIR"/nix.conf
|
|
||||||
|
|
||||||
export REMOTE_STORE_DIR="$TEST_ROOT/remote_store"
|
export REMOTE_STORE_DIR="$TEST_ROOT/remote_store"
|
||||||
export REMOTE_STORE="file://$REMOTE_STORE_DIR"
|
export REMOTE_STORE="file://$REMOTE_STORE_DIR"
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,6 @@
|
||||||
|
|
||||||
source common.sh
|
source common.sh
|
||||||
|
|
||||||
# Globally enable the ca derivations experimental flag
|
|
||||||
sed -i 's/experimental-features = .*/& ca-derivations ca-references/' "$NIX_CONF_DIR/nix.conf"
|
|
||||||
|
|
||||||
export REMOTE_STORE_DIR="$TEST_ROOT/remote_store"
|
export REMOTE_STORE_DIR="$TEST_ROOT/remote_store"
|
||||||
export REMOTE_STORE="file://$REMOTE_STORE_DIR"
|
export REMOTE_STORE="file://$REMOTE_STORE_DIR"
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
source common.sh
|
source common.sh
|
||||||
|
|
||||||
sed -i 's/experimental-features .*/& ca-derivations ca-references nix-command flakes/' "$NIX_CONF_DIR"/nix.conf
|
|
||||||
|
|
||||||
FLAKE_PATH=path:$PWD
|
FLAKE_PATH=path:$PWD
|
||||||
|
|
||||||
nix run --no-write-lock-file $FLAKE_PATH#runnable
|
nix run --no-write-lock-file $FLAKE_PATH#runnable
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
source common.sh
|
source common.sh
|
||||||
|
|
||||||
sed -i 's/experimental-features .*/& ca-derivations ca-references nix-command flakes/' "$NIX_CONF_DIR"/nix.conf
|
|
||||||
|
|
||||||
CONTENT_ADDRESSED=true
|
CONTENT_ADDRESSED=true
|
||||||
cd ..
|
cd ..
|
||||||
source ./nix-shell.sh
|
source ./nix-shell.sh
|
||||||
|
|
|
@ -4,8 +4,6 @@ source common.sh
|
||||||
|
|
||||||
requireDaemonNewerThan "2.4pre20210626"
|
requireDaemonNewerThan "2.4pre20210626"
|
||||||
|
|
||||||
sed -i 's/experimental-features .*/& ca-derivations ca-references nix-command flakes/' "$NIX_CONF_DIR"/nix.conf
|
|
||||||
|
|
||||||
export NIX_TESTS_CA_BY_DEFAULT=1
|
export NIX_TESTS_CA_BY_DEFAULT=1
|
||||||
cd ..
|
cd ..
|
||||||
source ./post-hook.sh
|
source ./post-hook.sh
|
||||||
|
|
|
@ -4,8 +4,6 @@ source common.sh
|
||||||
|
|
||||||
requireDaemonNewerThan "2.4pre20210623"
|
requireDaemonNewerThan "2.4pre20210623"
|
||||||
|
|
||||||
sed -i 's/experimental-features .*/& ca-derivations ca-references nix-command flakes/' "$NIX_CONF_DIR"/nix.conf
|
|
||||||
|
|
||||||
export NIX_TESTS_CA_BY_DEFAULT=1
|
export NIX_TESTS_CA_BY_DEFAULT=1
|
||||||
cd ..
|
cd ..
|
||||||
source ./recursive.sh
|
source ./recursive.sh
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
source common.sh
|
source common.sh
|
||||||
|
|
||||||
# Globally enable the ca derivations experimental flag
|
|
||||||
sed -i 's/experimental-features = .*/& ca-derivations ca-references/' "$NIX_CONF_DIR/nix.conf"
|
|
||||||
|
|
||||||
clearStore
|
clearStore
|
||||||
clearCache
|
clearCache
|
||||||
|
|
||||||
|
|
|
@ -87,8 +87,7 @@ startDaemon() {
|
||||||
if [[ "$NIX_REMOTE" == daemon ]]; then
|
if [[ "$NIX_REMOTE" == daemon ]]; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
# Start the daemon, wait for the socket to appear. !!!
|
# Start the daemon, wait for the socket to appear.
|
||||||
# ‘nix-daemon’ should have an option to fork into the background.
|
|
||||||
rm -f $NIX_DAEMON_SOCKET_PATH
|
rm -f $NIX_DAEMON_SOCKET_PATH
|
||||||
PATH=$DAEMON_PATH nix-daemon&
|
PATH=$DAEMON_PATH nix-daemon&
|
||||||
pidDaemon=$!
|
pidDaemon=$!
|
||||||
|
@ -109,10 +108,10 @@ startDaemon() {
|
||||||
killDaemon() {
|
killDaemon() {
|
||||||
kill $pidDaemon
|
kill $pidDaemon
|
||||||
for i in {0..100}; do
|
for i in {0..100}; do
|
||||||
kill -0 $pidDaemon || break
|
kill -0 $pidDaemon 2> /dev/null || break
|
||||||
sleep 0.1
|
sleep 0.1
|
||||||
done
|
done
|
||||||
kill -9 $pidDaemon || true
|
kill -9 $pidDaemon 2> /dev/null || true
|
||||||
wait $pidDaemon || true
|
wait $pidDaemon || true
|
||||||
trap "" EXIT
|
trap "" EXIT
|
||||||
}
|
}
|
||||||
|
@ -173,10 +172,15 @@ needLocalStore() {
|
||||||
}
|
}
|
||||||
|
|
||||||
# Just to make it easy to find which tests should be fixed
|
# Just to make it easy to find which tests should be fixed
|
||||||
buggyNeedLocalStore () {
|
buggyNeedLocalStore() {
|
||||||
needLocalStore
|
needLocalStore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enableFeatures() {
|
||||||
|
local features="$1"
|
||||||
|
sed -i 's/experimental-features .*/& '"$features"'/' "$NIX_CONF_DIR"/nix.conf
|
||||||
|
}
|
||||||
|
|
||||||
set -x
|
set -x
|
||||||
|
|
||||||
if [[ -n "${NIX_DAEMON_PACKAGE:-}" ]]; then
|
if [[ -n "${NIX_DAEMON_PACKAGE:-}" ]]; then
|
||||||
|
|
|
@ -3,6 +3,9 @@ source common.sh
|
||||||
clearStore
|
clearStore
|
||||||
clearProfiles
|
clearProfiles
|
||||||
|
|
||||||
|
enableFeatures "ca-derivations ca-references"
|
||||||
|
restartDaemon
|
||||||
|
|
||||||
# Make a flake.
|
# Make a flake.
|
||||||
flake1Dir=$TEST_ROOT/flake1
|
flake1Dir=$TEST_ROOT/flake1
|
||||||
mkdir -p $flake1Dir
|
mkdir -p $flake1Dir
|
||||||
|
@ -13,7 +16,7 @@ cat > $flake1Dir/flake.nix <<EOF
|
||||||
|
|
||||||
outputs = { self }: with import ./config.nix; rec {
|
outputs = { self }: with import ./config.nix; rec {
|
||||||
packages.$system.default = mkDerivation {
|
packages.$system.default = mkDerivation {
|
||||||
name = "simple-\${builtins.readFile ./version}";
|
name = "profile-test-\${builtins.readFile ./version}";
|
||||||
builder = builtins.toFile "builder.sh"
|
builder = builtins.toFile "builder.sh"
|
||||||
''
|
''
|
||||||
mkdir -p \$out/bin
|
mkdir -p \$out/bin
|
||||||
|
@ -22,7 +25,11 @@ cat > $flake1Dir/flake.nix <<EOF
|
||||||
echo Hello \${builtins.readFile ./who}
|
echo Hello \${builtins.readFile ./who}
|
||||||
EOF
|
EOF
|
||||||
chmod +x \$out/bin/hello
|
chmod +x \$out/bin/hello
|
||||||
|
echo DONE
|
||||||
'';
|
'';
|
||||||
|
__contentAddressed = import ./ca.nix;
|
||||||
|
outputHashMode = "recursive";
|
||||||
|
outputHashAlgo = "sha256";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -30,6 +37,7 @@ EOF
|
||||||
|
|
||||||
printf World > $flake1Dir/who
|
printf World > $flake1Dir/who
|
||||||
printf 1.0 > $flake1Dir/version
|
printf 1.0 > $flake1Dir/version
|
||||||
|
printf false > $flake1Dir/ca.nix
|
||||||
|
|
||||||
cp ./config.nix $flake1Dir/
|
cp ./config.nix $flake1Dir/
|
||||||
|
|
||||||
|
@ -63,6 +71,27 @@ nix profile remove 0
|
||||||
nix profile history | grep 'foo: 1.0 -> ∅'
|
nix profile history | grep 'foo: 1.0 -> ∅'
|
||||||
nix profile diff-closures | grep 'Version 3 -> 4'
|
nix profile diff-closures | grep 'Version 3 -> 4'
|
||||||
|
|
||||||
|
# Test installing a non-flake package.
|
||||||
|
nix profile install --file ./simple.nix ''
|
||||||
|
[[ $(cat $TEST_HOME/.nix-profile/hello) = "Hello World!" ]]
|
||||||
|
nix profile remove 1
|
||||||
|
nix profile install $(nix-build --no-out-link ./simple.nix)
|
||||||
|
[[ $(cat $TEST_HOME/.nix-profile/hello) = "Hello World!" ]]
|
||||||
|
|
||||||
# Test wipe-history.
|
# Test wipe-history.
|
||||||
nix profile wipe-history
|
nix profile wipe-history
|
||||||
[[ $(nix profile history | grep Version | wc -l) -eq 1 ]]
|
[[ $(nix profile history | grep Version | wc -l) -eq 1 ]]
|
||||||
|
|
||||||
|
# Test upgrade to CA package.
|
||||||
|
printf true > $flake1Dir/ca.nix
|
||||||
|
printf 3.0 > $flake1Dir/version
|
||||||
|
nix profile upgrade 0
|
||||||
|
nix profile history | grep "packages.$system.default: 1.0 -> 3.0"
|
||||||
|
|
||||||
|
# Test new install of CA package.
|
||||||
|
nix profile remove 0
|
||||||
|
printf 4.0 > $flake1Dir/version
|
||||||
|
printf Utrecht > $flake1Dir/who
|
||||||
|
nix profile install $flake1Dir
|
||||||
|
[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello Utrecht" ]]
|
||||||
|
[[ $(nix path-info --json $(realpath $TEST_HOME/.nix-profile/bin/hello) | jq -r .[].ca) =~ fixed:r:sha256: ]]
|
||||||
|
|
Loading…
Reference in a new issue