mirror of
https://github.com/NixOS/nix
synced 2025-06-28 17:51:15 +02:00
Merge remote-tracking branch 'upstream/master' into indexed-store-path-outputs
This commit is contained in:
commit
1ef88da350
304 changed files with 32818 additions and 3348 deletions
|
@ -54,7 +54,31 @@ void StoreCommand::run()
|
|||
run(getStore());
|
||||
}
|
||||
|
||||
RealisedPathsCommand::RealisedPathsCommand(bool recursive)
|
||||
EvalCommand::EvalCommand()
|
||||
{
|
||||
}
|
||||
|
||||
EvalCommand::~EvalCommand()
|
||||
{
|
||||
if (evalState)
|
||||
evalState->printStats();
|
||||
}
|
||||
|
||||
ref<Store> EvalCommand::getEvalStore()
|
||||
{
|
||||
if (!evalStore)
|
||||
evalStore = evalStoreUrl ? openStore(*evalStoreUrl) : getStore();
|
||||
return ref<Store>(evalStore);
|
||||
}
|
||||
|
||||
ref<EvalState> EvalCommand::getEvalState()
|
||||
{
|
||||
if (!evalState)
|
||||
evalState = std::make_shared<EvalState>(searchPath, getEvalStore(), getStore());
|
||||
return ref<EvalState>(evalState);
|
||||
}
|
||||
|
||||
BuiltPathsCommand::BuiltPathsCommand(bool recursive)
|
||||
: recursive(recursive)
|
||||
{
|
||||
if (recursive)
|
||||
|
@ -81,44 +105,53 @@ RealisedPathsCommand::RealisedPathsCommand(bool recursive)
|
|||
});
|
||||
}
|
||||
|
||||
void RealisedPathsCommand::run(ref<Store> store)
|
||||
void BuiltPathsCommand::run(ref<Store> store)
|
||||
{
|
||||
std::vector<RealisedPath> paths;
|
||||
BuiltPaths paths;
|
||||
if (all) {
|
||||
if (installables.size())
|
||||
throw UsageError("'--all' does not expect arguments");
|
||||
// XXX: Only uses opaque paths, ignores all the realisations
|
||||
for (auto & p : store->queryAllValidPaths())
|
||||
paths.push_back(p);
|
||||
paths.push_back(BuiltPath::Opaque{p});
|
||||
} else {
|
||||
auto pathSet = toRealisedPaths(store, realiseMode, operateOn, installables);
|
||||
paths = toBuiltPaths(getEvalStore(), store, realiseMode, operateOn, installables);
|
||||
if (recursive) {
|
||||
auto roots = std::move(pathSet);
|
||||
pathSet = {};
|
||||
RealisedPath::closure(*store, roots, pathSet);
|
||||
// XXX: This only computes the store path closure, ignoring
|
||||
// intermediate realisations
|
||||
StorePathSet pathsRoots, pathsClosure;
|
||||
for (auto & root : paths) {
|
||||
auto rootFromThis = root.outPaths();
|
||||
pathsRoots.insert(rootFromThis.begin(), rootFromThis.end());
|
||||
}
|
||||
store->computeFSClosure(pathsRoots, pathsClosure);
|
||||
for (auto & path : pathsClosure)
|
||||
paths.push_back(BuiltPath::Opaque{path});
|
||||
}
|
||||
for (auto & path : pathSet)
|
||||
paths.push_back(path);
|
||||
}
|
||||
|
||||
run(store, std::move(paths));
|
||||
}
|
||||
|
||||
StorePathsCommand::StorePathsCommand(bool recursive)
|
||||
: RealisedPathsCommand(recursive)
|
||||
: BuiltPathsCommand(recursive)
|
||||
{
|
||||
}
|
||||
|
||||
void StorePathsCommand::run(ref<Store> store, std::vector<RealisedPath> paths)
|
||||
void StorePathsCommand::run(ref<Store> store, BuiltPaths && paths)
|
||||
{
|
||||
StorePaths storePaths;
|
||||
for (auto & p : paths)
|
||||
storePaths.push_back(p.path());
|
||||
StorePathSet storePaths;
|
||||
for (auto & builtPath : paths)
|
||||
for (auto & p : builtPath.outPaths())
|
||||
storePaths.insert(p);
|
||||
|
||||
run(store, std::move(storePaths));
|
||||
auto sorted = store->topoSortPaths(storePaths);
|
||||
std::reverse(sorted.begin(), sorted.end());
|
||||
|
||||
run(store, std::move(sorted));
|
||||
}
|
||||
|
||||
void StorePathCommand::run(ref<Store> store, std::vector<StorePath> storePaths)
|
||||
void StorePathCommand::run(ref<Store> store, std::vector<StorePath> && storePaths)
|
||||
{
|
||||
if (storePaths.size() != 1)
|
||||
throw UsageError("this command requires exactly one store path");
|
||||
|
@ -162,7 +195,7 @@ void MixProfile::updateProfile(const StorePath & storePath)
|
|||
profile2, storePath));
|
||||
}
|
||||
|
||||
void MixProfile::updateProfile(const DerivedPathsWithHints & buildables)
|
||||
void MixProfile::updateProfile(const BuiltPaths & buildables)
|
||||
{
|
||||
if (!profile) return;
|
||||
|
||||
|
@ -170,22 +203,19 @@ void MixProfile::updateProfile(const DerivedPathsWithHints & buildables)
|
|||
|
||||
for (auto & buildable : buildables) {
|
||||
std::visit(overloaded {
|
||||
[&](DerivedPathWithHints::Opaque bo) {
|
||||
[&](BuiltPath::Opaque bo) {
|
||||
result.push_back(bo.path);
|
||||
},
|
||||
[&](DerivedPathWithHints::Built bfd) {
|
||||
[&](BuiltPath::Built bfd) {
|
||||
for (auto & output : bfd.outputs) {
|
||||
/* Output path should be known because we just tried to
|
||||
build it. */
|
||||
assert(output.second);
|
||||
result.push_back(*output.second);
|
||||
result.push_back(output.second);
|
||||
}
|
||||
},
|
||||
}, buildable.raw());
|
||||
}
|
||||
|
||||
if (result.size() != 1)
|
||||
throw Error("'--profile' requires that the arguments produce a single store path, but there are %d", result.size());
|
||||
throw UsageError("'--profile' requires that the arguments produce a single store path, but there are %d", result.size());
|
||||
|
||||
updateProfile(result[0]);
|
||||
}
|
||||
|
|
|
@ -45,11 +45,18 @@ private:
|
|||
|
||||
struct EvalCommand : virtual StoreCommand, MixEvalArgs
|
||||
{
|
||||
ref<EvalState> getEvalState();
|
||||
|
||||
std::shared_ptr<EvalState> evalState;
|
||||
EvalCommand();
|
||||
|
||||
~EvalCommand();
|
||||
|
||||
ref<Store> getEvalStore();
|
||||
|
||||
ref<EvalState> getEvalState();
|
||||
|
||||
private:
|
||||
std::shared_ptr<Store> evalStore;
|
||||
|
||||
std::shared_ptr<EvalState> evalState;
|
||||
};
|
||||
|
||||
struct MixFlakeOptions : virtual Args, EvalCommand
|
||||
|
@ -101,6 +108,8 @@ enum class Realise {
|
|||
exists. */
|
||||
Derivation,
|
||||
/* Evaluate in dry-run mode. Postcondition: nothing. */
|
||||
// FIXME: currently unused, but could be revived if we can
|
||||
// evaluate derivations in-memory.
|
||||
Nothing
|
||||
};
|
||||
|
||||
|
@ -143,7 +152,7 @@ private:
|
|||
};
|
||||
|
||||
/* A command that operates on zero or more store paths. */
|
||||
struct RealisedPathsCommand : public InstallablesCommand
|
||||
struct BuiltPathsCommand : public InstallablesCommand
|
||||
{
|
||||
private:
|
||||
|
||||
|
@ -156,26 +165,26 @@ protected:
|
|||
|
||||
public:
|
||||
|
||||
RealisedPathsCommand(bool recursive = false);
|
||||
BuiltPathsCommand(bool recursive = false);
|
||||
|
||||
using StoreCommand::run;
|
||||
|
||||
virtual void run(ref<Store> store, std::vector<RealisedPath> paths) = 0;
|
||||
virtual void run(ref<Store> store, BuiltPaths && paths) = 0;
|
||||
|
||||
void run(ref<Store> store) override;
|
||||
|
||||
bool useDefaultInstallables() override { return !all; }
|
||||
};
|
||||
|
||||
struct StorePathsCommand : public RealisedPathsCommand
|
||||
struct StorePathsCommand : public BuiltPathsCommand
|
||||
{
|
||||
StorePathsCommand(bool recursive = false);
|
||||
|
||||
using RealisedPathsCommand::run;
|
||||
using BuiltPathsCommand::run;
|
||||
|
||||
virtual void run(ref<Store> store, std::vector<StorePath> storePaths) = 0;
|
||||
virtual void run(ref<Store> store, std::vector<StorePath> && storePaths) = 0;
|
||||
|
||||
void run(ref<Store> store, std::vector<RealisedPath> paths) override;
|
||||
void run(ref<Store> store, BuiltPaths && paths) override;
|
||||
};
|
||||
|
||||
/* A command that operates on exactly one store path. */
|
||||
|
@ -185,7 +194,7 @@ struct StorePathCommand : public StorePathsCommand
|
|||
|
||||
virtual void run(ref<Store> store, const StorePath & storePath) = 0;
|
||||
|
||||
void run(ref<Store> store, std::vector<StorePath> storePaths) override;
|
||||
void run(ref<Store> store, std::vector<StorePath> && storePaths) override;
|
||||
};
|
||||
|
||||
/* A helper class for registering commands globally. */
|
||||
|
@ -216,26 +225,37 @@ static RegisterCommand registerCommand2(std::vector<std::string> && name)
|
|||
return RegisterCommand(std::move(name), [](){ return make_ref<T>(); });
|
||||
}
|
||||
|
||||
DerivedPathsWithHints build(ref<Store> store, Realise mode,
|
||||
std::vector<std::shared_ptr<Installable>> installables, BuildMode bMode = bmNormal);
|
||||
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> store,
|
||||
Realise mode, OperateOn operateOn,
|
||||
std::vector<std::shared_ptr<Installable>> installables);
|
||||
|
||||
StorePath toStorePath(ref<Store> store,
|
||||
Realise mode, OperateOn operateOn,
|
||||
std::shared_ptr<Installable> installable);
|
||||
|
||||
std::set<StorePath> toDerivations(ref<Store> store,
|
||||
std::vector<std::shared_ptr<Installable>> installables,
|
||||
bool useDeriver = false);
|
||||
|
||||
std::set<RealisedPath> toRealisedPaths(
|
||||
std::set<StorePath> toStorePaths(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
OperateOn operateOn,
|
||||
std::vector<std::shared_ptr<Installable>> installables);
|
||||
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
|
||||
filename:lineno. */
|
||||
|
@ -252,7 +272,7 @@ struct MixProfile : virtual StoreCommand
|
|||
|
||||
/* If 'profile' is set, make it point at the store path produced
|
||||
by 'buildables'. */
|
||||
void updateProfile(const DerivedPathsWithHints & buildables);
|
||||
void updateProfile(const BuiltPaths & buildables);
|
||||
};
|
||||
|
||||
struct MixDefaultProfile : MixProfile
|
||||
|
|
|
@ -58,9 +58,13 @@ MixFlakeOptions::MixFlakeOptions()
|
|||
|
||||
addFlag({
|
||||
.longName = "no-registries",
|
||||
.description = "Don't allow lookups in the flake registries.",
|
||||
.description =
|
||||
"Don't allow lookups in the flake registries. This option is deprecated; use `--no-use-registries`.",
|
||||
.category = category,
|
||||
.handler = {&lockFlags.useRegistries, false}
|
||||
.handler = {[&]() {
|
||||
lockFlags.useRegistries = false;
|
||||
warn("'--no-registries' is deprecated; use '--no-use-registries'");
|
||||
}}
|
||||
});
|
||||
|
||||
addFlag({
|
||||
|
@ -171,14 +175,50 @@ Strings SourceExprCommand::getDefaultFlakeAttrPathPrefixes()
|
|||
|
||||
void SourceExprCommand::completeInstallable(std::string_view prefix)
|
||||
{
|
||||
if (file) return; // FIXME
|
||||
if (file) {
|
||||
evalSettings.pureEval = false;
|
||||
auto state = getEvalState();
|
||||
Expr *e = state->parseExprFromFile(
|
||||
resolveExprPath(state->checkSourcePath(lookupFileArg(*state, *file)))
|
||||
);
|
||||
|
||||
completeFlakeRefWithFragment(
|
||||
getEvalState(),
|
||||
lockFlags,
|
||||
getDefaultFlakeAttrPathPrefixes(),
|
||||
getDefaultFlakeAttrPaths(),
|
||||
prefix);
|
||||
Value root;
|
||||
state->eval(e, root);
|
||||
|
||||
auto autoArgs = getAutoArgs(*state);
|
||||
|
||||
std::string prefix_ = std::string(prefix);
|
||||
auto sep = prefix_.rfind('.');
|
||||
std::string searchWord;
|
||||
if (sep != std::string::npos) {
|
||||
searchWord = prefix_.substr(sep, std::string::npos);
|
||||
prefix_ = prefix_.substr(0, sep);
|
||||
} else {
|
||||
searchWord = prefix_;
|
||||
prefix_ = "";
|
||||
}
|
||||
|
||||
Value &v1(*findAlongAttrPath(*state, prefix_, *autoArgs, root).first);
|
||||
state->forceValue(v1);
|
||||
Value v2;
|
||||
state->autoCallFunction(*autoArgs, v1, v2);
|
||||
|
||||
if (v2.type() == nAttrs) {
|
||||
for (auto & i : *v2.attrs) {
|
||||
std::string name = i.name;
|
||||
if (name.find(searchWord) == 0) {
|
||||
completions->add(i.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
completeFlakeRefWithFragment(
|
||||
getEvalState(),
|
||||
lockFlags,
|
||||
getDefaultFlakeAttrPathPrefixes(),
|
||||
getDefaultFlakeAttrPaths(),
|
||||
prefix);
|
||||
}
|
||||
}
|
||||
|
||||
void completeFlakeRefWithFragment(
|
||||
|
@ -249,19 +289,6 @@ void completeFlakeRefWithFragment(
|
|||
completeFlakeRef(evalState->store, prefix);
|
||||
}
|
||||
|
||||
ref<EvalState> EvalCommand::getEvalState()
|
||||
{
|
||||
if (!evalState)
|
||||
evalState = std::make_shared<EvalState>(searchPath, getStore());
|
||||
return ref<EvalState>(evalState);
|
||||
}
|
||||
|
||||
EvalCommand::~EvalCommand()
|
||||
{
|
||||
if (evalState)
|
||||
evalState->printStats();
|
||||
}
|
||||
|
||||
void completeFlakeRef(ref<Store> store, std::string_view prefix)
|
||||
{
|
||||
if (prefix == "")
|
||||
|
@ -285,9 +312,9 @@ void completeFlakeRef(ref<Store> store, std::string_view prefix)
|
|||
}
|
||||
}
|
||||
|
||||
DerivedPathWithHints Installable::toDerivedPathWithHints()
|
||||
DerivedPath Installable::toDerivedPath()
|
||||
{
|
||||
auto buildables = toDerivedPathsWithHints();
|
||||
auto buildables = toDerivedPaths();
|
||||
if (buildables.size() != 1)
|
||||
throw Error("installable '%s' evaluates to %d derivations, where only one is expected", what(), buildables.size());
|
||||
return std::move(buildables[0]);
|
||||
|
@ -321,22 +348,19 @@ struct InstallableStorePath : Installable
|
|||
|
||||
std::string what() override { return store->printStorePath(storePath); }
|
||||
|
||||
DerivedPathsWithHints toDerivedPathsWithHints() override
|
||||
DerivedPaths toDerivedPaths() override
|
||||
{
|
||||
if (storePath.isDerivation()) {
|
||||
std::map<std::string, std::optional<StorePath>> outputs;
|
||||
auto drv = store->readDerivation(storePath);
|
||||
for (auto & [name, output] : drv.outputsAndOptPaths(*store))
|
||||
outputs.emplace(name, output.second);
|
||||
return {
|
||||
DerivedPathWithHints::Built {
|
||||
DerivedPath::Built {
|
||||
.drvPath = storePath,
|
||||
.outputs = std::move(outputs)
|
||||
.outputs = drv.outputNames(),
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
DerivedPathWithHints::Opaque {
|
||||
DerivedPath::Opaque {
|
||||
.path = storePath,
|
||||
}
|
||||
};
|
||||
|
@ -363,33 +387,30 @@ struct InstallableIndexedStorePath : Installable
|
|||
return req.to_string(*store);
|
||||
}
|
||||
|
||||
DerivedPathsWithHints toDerivedPathsWithHints() override
|
||||
DerivedPaths toDerivedPaths() override
|
||||
{
|
||||
std::map<std::string, std::optional<StorePath>> outputs;
|
||||
for (auto & output : req.outputs)
|
||||
outputs.insert_or_assign(output, std::nullopt);
|
||||
return {
|
||||
DerivedPathWithHints { DerivedPathWithHints::Built { req.drvPath, std::move(outputs) } }
|
||||
};
|
||||
return { req };
|
||||
}
|
||||
};
|
||||
|
||||
DerivedPathsWithHints InstallableValue::toDerivedPathsWithHints()
|
||||
DerivedPaths InstallableValue::toDerivedPaths()
|
||||
{
|
||||
DerivedPathsWithHints res;
|
||||
DerivedPaths res;
|
||||
|
||||
std::map<StorePath, std::map<std::string, std::optional<StorePath>>> drvsToOutputs;
|
||||
std::map<StorePath, std::set<std::string>> drvsToOutputs;
|
||||
RealisedPath::Set drvsToCopy;
|
||||
|
||||
// Group by derivation, helps with .all in particular
|
||||
for (auto & drv : toDerivations()) {
|
||||
auto outputName = drv.outputName;
|
||||
if (outputName == "")
|
||||
throw Error("derivation '%s' lacks an 'outputName' attribute", state->store->printStorePath(drv.drvPath));
|
||||
drvsToOutputs[drv.drvPath].insert_or_assign(outputName, drv.outPath);
|
||||
drvsToOutputs[drv.drvPath].insert(outputName);
|
||||
drvsToCopy.insert(drv.drvPath);
|
||||
}
|
||||
|
||||
for (auto & i : drvsToOutputs)
|
||||
res.push_back(DerivedPathWithHints::Built { i.first, i.second });
|
||||
res.push_back(DerivedPath::Built { i.first, i.second });
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -528,7 +549,11 @@ std::tuple<std::string, FlakeRef, InstallableValue::DerivationInfo> InstallableF
|
|||
auto root = cache->getRoot();
|
||||
|
||||
for (auto & attrPath : getActualAttrPaths()) {
|
||||
auto attr = root->findAlongAttrPath(parseAttrPath(*state, attrPath));
|
||||
auto attr = root->findAlongAttrPath(
|
||||
parseAttrPath(*state, attrPath),
|
||||
true
|
||||
);
|
||||
|
||||
if (!attr) continue;
|
||||
|
||||
if (!attr->isDerivation())
|
||||
|
@ -597,10 +622,10 @@ InstallableFlake::getCursors(EvalState & state)
|
|||
|
||||
std::shared_ptr<flake::LockedFlake> InstallableFlake::getLockedFlake() const
|
||||
{
|
||||
flake::LockFlags lockFlagsApplyConfig = lockFlags;
|
||||
lockFlagsApplyConfig.applyNixConfig = true;
|
||||
if (!_lockedFlake) {
|
||||
_lockedFlake = std::make_shared<flake::LockedFlake>(lockFlake(*state, flakeRef, lockFlags));
|
||||
_lockedFlake->flake.config.apply();
|
||||
// FIXME: send new config to the daemon.
|
||||
_lockedFlake = std::make_shared<flake::LockedFlake>(lockFlake(*state, flakeRef, lockFlagsApplyConfig));
|
||||
}
|
||||
return _lockedFlake;
|
||||
}
|
||||
|
@ -649,6 +674,30 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
|
|||
for (auto & s : ss) {
|
||||
std::exception_ptr ex;
|
||||
|
||||
if (s.rfind('!') != std::string::npos) {
|
||||
try {
|
||||
result.push_back(std::make_shared<InstallableIndexedStorePath>(
|
||||
store,
|
||||
DerivedPath::Built::parse(*store, s)));
|
||||
continue;
|
||||
} catch (BadStorePath &) {
|
||||
} catch (...) {
|
||||
if (!ex)
|
||||
ex = std::current_exception();
|
||||
}
|
||||
}
|
||||
|
||||
if (s.find('/') != std::string::npos) {
|
||||
try {
|
||||
result.push_back(std::make_shared<InstallableStorePath>(store, store->followLinksToStorePath(s)));
|
||||
continue;
|
||||
} catch (BadStorePath &) {
|
||||
} catch (...) {
|
||||
if (!ex)
|
||||
ex = std::current_exception();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
auto [flakeRef, fragment] = parseFlakeRefWithFragment(s, absPath("."));
|
||||
result.push_back(std::make_shared<InstallableFlake>(
|
||||
|
@ -663,40 +712,7 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
|
|||
ex = std::current_exception();
|
||||
}
|
||||
|
||||
auto found = s.rfind('!');
|
||||
if (found != std::string::npos) {
|
||||
try {
|
||||
result.push_back(std::make_shared<InstallableIndexedStorePath>(
|
||||
store,
|
||||
DerivedPath::Built::parse(*store, s)));
|
||||
continue;
|
||||
} catch (BadStorePath &) {
|
||||
} catch (...) {
|
||||
if (!ex)
|
||||
ex = std::current_exception();
|
||||
}
|
||||
}
|
||||
|
||||
found = s.find('/');
|
||||
if (found != std::string::npos) {
|
||||
try {
|
||||
result.push_back(std::make_shared<InstallableStorePath>(store, store->followLinksToStorePath(s)));
|
||||
continue;
|
||||
} catch (BadStorePath &) {
|
||||
} catch (...) {
|
||||
if (!ex)
|
||||
ex = std::current_exception();
|
||||
}
|
||||
}
|
||||
|
||||
std::rethrow_exception(ex);
|
||||
|
||||
/*
|
||||
throw Error(
|
||||
pathExists(s)
|
||||
? "path '%s' is not a flake or a store path"
|
||||
: "don't know how to handle argument '%s'", s);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -711,109 +727,121 @@ std::shared_ptr<Installable> SourceExprCommand::parseInstallable(
|
|||
return installables.front();
|
||||
}
|
||||
|
||||
DerivedPathsWithHints build(ref<Store> store, Realise mode,
|
||||
std::vector<std::shared_ptr<Installable>> installables, BuildMode bMode)
|
||||
BuiltPaths getBuiltPaths(ref<Store> evalStore, ref<Store> store, const DerivedPaths & hopefullyBuiltPaths)
|
||||
{
|
||||
if (mode == Realise::Nothing)
|
||||
settings.readOnlyMode = true;
|
||||
|
||||
DerivedPathsWithHints buildables;
|
||||
|
||||
std::vector<DerivedPath> pathsToBuild;
|
||||
|
||||
for (auto & i : installables) {
|
||||
for (auto & b : i->toDerivedPathsWithHints()) {
|
||||
std::visit(overloaded {
|
||||
[&](DerivedPathWithHints::Opaque bo) {
|
||||
pathsToBuild.push_back(bo);
|
||||
BuiltPaths res;
|
||||
for (auto & b : hopefullyBuiltPaths)
|
||||
std::visit(
|
||||
overloaded{
|
||||
[&](DerivedPath::Opaque bo) {
|
||||
res.push_back(BuiltPath::Opaque{bo.path});
|
||||
},
|
||||
[&](DerivedPathWithHints::Built bfd) {
|
||||
StringSet outputNames;
|
||||
for (auto & output : bfd.outputs)
|
||||
outputNames.insert(output.first);
|
||||
pathsToBuild.push_back(
|
||||
DerivedPath::Built{bfd.drvPath, outputNames});
|
||||
},
|
||||
}, b.raw());
|
||||
buildables.push_back(std::move(b));
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == Realise::Nothing)
|
||||
printMissing(store, pathsToBuild, lvlError);
|
||||
else if (mode == Realise::Outputs)
|
||||
store->buildPaths(pathsToBuild, bMode);
|
||||
|
||||
return buildables;
|
||||
}
|
||||
|
||||
std::set<RealisedPath> toRealisedPaths(
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
OperateOn operateOn,
|
||||
std::vector<std::shared_ptr<Installable>> installables)
|
||||
{
|
||||
std::set<RealisedPath> res;
|
||||
if (operateOn == OperateOn::Output) {
|
||||
for (auto & b : build(store, mode, installables))
|
||||
std::visit(overloaded {
|
||||
[&](DerivedPathWithHints::Opaque bo) {
|
||||
res.insert(bo.path);
|
||||
},
|
||||
[&](DerivedPathWithHints::Built bfd) {
|
||||
auto drv = store->readDerivation(bfd.drvPath);
|
||||
auto outputHashes = staticOutputHashes(*store, drv);
|
||||
[&](DerivedPath::Built bfd) {
|
||||
OutputPathMap outputs;
|
||||
auto drv = evalStore->readDerivation(bfd.drvPath);
|
||||
auto outputHashes = staticOutputHashes(*evalStore, drv); // FIXME: expensive
|
||||
auto drvOutputs = drv.outputsAndOptPaths(*store);
|
||||
for (auto & output : bfd.outputs) {
|
||||
if (settings.isExperimentalFeatureEnabled("ca-derivations")) {
|
||||
if (!outputHashes.count(output.first))
|
||||
throw Error(
|
||||
"the derivation '%s' doesn't have an output named '%s'",
|
||||
store->printStorePath(bfd.drvPath),
|
||||
output.first);
|
||||
auto outputId = DrvOutput{outputHashes.at(output.first), output.first};
|
||||
auto realisation = store->queryRealisation(outputId);
|
||||
if (!outputHashes.count(output))
|
||||
throw Error(
|
||||
"the derivation '%s' doesn't have an output named '%s'",
|
||||
store->printStorePath(bfd.drvPath), output);
|
||||
if (settings.isExperimentalFeatureEnabled(
|
||||
"ca-derivations")) {
|
||||
auto outputId =
|
||||
DrvOutput{outputHashes.at(output), output};
|
||||
auto realisation =
|
||||
store->queryRealisation(outputId);
|
||||
if (!realisation)
|
||||
throw Error("cannot operate on an output of unbuilt content-addresed derivation '%s'", outputId.to_string());
|
||||
res.insert(RealisedPath{*realisation});
|
||||
}
|
||||
else {
|
||||
// If ca-derivations isn't enabled, behave as if
|
||||
// all the paths are opaque to keep the default
|
||||
// behavior
|
||||
assert(output.second);
|
||||
res.insert(*output.second);
|
||||
throw Error(
|
||||
"cannot operate on an output of unbuilt "
|
||||
"content-addressed derivation '%s'",
|
||||
outputId.to_string());
|
||||
outputs.insert_or_assign(
|
||||
output, realisation->outPath);
|
||||
} else {
|
||||
// If ca-derivations isn't enabled, assume that
|
||||
// the output path is statically known.
|
||||
assert(drvOutputs.count(output));
|
||||
assert(drvOutputs.at(output).second);
|
||||
outputs.insert_or_assign(
|
||||
output, *drvOutputs.at(output).second);
|
||||
}
|
||||
}
|
||||
res.push_back(BuiltPath::Built{bfd.drvPath, outputs});
|
||||
},
|
||||
}, b.raw());
|
||||
} else {
|
||||
if (mode == Realise::Nothing)
|
||||
settings.readOnlyMode = true;
|
||||
|
||||
for (auto & i : installables)
|
||||
for (auto & b : i->toDerivedPathsWithHints())
|
||||
if (auto bfd = std::get_if<DerivedPathWithHints::Built>(&b))
|
||||
res.insert(bfd->drvPath);
|
||||
}
|
||||
},
|
||||
b.raw());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
StorePathSet toStorePaths(ref<Store> store,
|
||||
BuiltPaths build(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
const std::vector<std::shared_ptr<Installable>> & installables,
|
||||
BuildMode bMode)
|
||||
{
|
||||
if (mode == Realise::Nothing)
|
||||
settings.readOnlyMode = true;
|
||||
|
||||
std::vector<DerivedPath> pathsToBuild;
|
||||
|
||||
for (auto & i : installables) {
|
||||
auto b = i->toDerivedPaths();
|
||||
pathsToBuild.insert(pathsToBuild.end(), b.begin(), b.end());
|
||||
}
|
||||
|
||||
if (mode == Realise::Nothing || mode == Realise::Derivation)
|
||||
printMissing(store, pathsToBuild, lvlError);
|
||||
else if (mode == Realise::Outputs)
|
||||
store->buildPaths(pathsToBuild, bMode, evalStore);
|
||||
|
||||
return getBuiltPaths(evalStore, store, pathsToBuild);
|
||||
}
|
||||
|
||||
BuiltPaths toBuiltPaths(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode,
|
||||
OperateOn operateOn,
|
||||
const std::vector<std::shared_ptr<Installable>> & installables)
|
||||
{
|
||||
if (operateOn == OperateOn::Output)
|
||||
return build(evalStore, store, mode, installables);
|
||||
else {
|
||||
if (mode == Realise::Nothing)
|
||||
settings.readOnlyMode = true;
|
||||
|
||||
BuiltPaths res;
|
||||
for (auto & drvPath : toDerivations(store, installables, true))
|
||||
res.push_back(BuiltPath::Opaque{drvPath});
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
StorePathSet toStorePaths(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode, OperateOn operateOn,
|
||||
std::vector<std::shared_ptr<Installable>> installables)
|
||||
const std::vector<std::shared_ptr<Installable>> & installables)
|
||||
{
|
||||
StorePathSet outPaths;
|
||||
for (auto & path : toRealisedPaths(store, mode, operateOn, installables))
|
||||
outPaths.insert(path.path());
|
||||
for (auto & path : toBuiltPaths(evalStore, store, mode, operateOn, installables)) {
|
||||
auto thisOutPaths = path.outPaths();
|
||||
outPaths.insert(thisOutPaths.begin(), thisOutPaths.end());
|
||||
}
|
||||
return outPaths;
|
||||
}
|
||||
|
||||
StorePath toStorePath(ref<Store> store,
|
||||
StorePath toStorePath(
|
||||
ref<Store> evalStore,
|
||||
ref<Store> store,
|
||||
Realise mode, OperateOn operateOn,
|
||||
std::shared_ptr<Installable> installable)
|
||||
{
|
||||
auto paths = toStorePaths(store, mode, operateOn, {installable});
|
||||
auto paths = toStorePaths(evalStore, store, mode, operateOn, {installable});
|
||||
|
||||
if (paths.size() != 1)
|
||||
throw Error("argument '%s' should evaluate to one store path", installable->what());
|
||||
|
@ -821,15 +849,17 @@ StorePath toStorePath(ref<Store> store,
|
|||
return *paths.begin();
|
||||
}
|
||||
|
||||
StorePathSet toDerivations(ref<Store> store,
|
||||
std::vector<std::shared_ptr<Installable>> installables, bool useDeriver)
|
||||
StorePathSet toDerivations(
|
||||
ref<Store> store,
|
||||
const std::vector<std::shared_ptr<Installable>> & installables,
|
||||
bool useDeriver)
|
||||
{
|
||||
StorePathSet drvPaths;
|
||||
|
||||
for (auto & i : installables)
|
||||
for (auto & b : i->toDerivedPathsWithHints())
|
||||
for (auto & b : i->toDerivedPaths())
|
||||
std::visit(overloaded {
|
||||
[&](DerivedPathWithHints::Opaque bo) {
|
||||
[&](DerivedPath::Opaque bo) {
|
||||
if (!useDeriver)
|
||||
throw Error("argument '%s' did not evaluate to a derivation", i->what());
|
||||
auto derivers = store->queryValidDerivers(bo.path);
|
||||
|
@ -838,7 +868,7 @@ StorePathSet toDerivations(ref<Store> store,
|
|||
// FIXME: use all derivers?
|
||||
drvPaths.insert(*derivers.begin());
|
||||
},
|
||||
[&](DerivedPathWithHints::Built bfd) {
|
||||
[&](DerivedPath::Built bfd) {
|
||||
drvPaths.insert(bfd.drvPath);
|
||||
},
|
||||
}, b.raw());
|
||||
|
|
|
@ -23,17 +23,23 @@ struct App
|
|||
// FIXME: add args, sandbox settings, metadata, ...
|
||||
};
|
||||
|
||||
struct UnresolvedApp
|
||||
{
|
||||
App unresolved;
|
||||
App resolve(ref<Store> evalStore, ref<Store> store);
|
||||
};
|
||||
|
||||
struct Installable
|
||||
{
|
||||
virtual ~Installable() { }
|
||||
|
||||
virtual std::string what() = 0;
|
||||
|
||||
virtual DerivedPathsWithHints toDerivedPathsWithHints() = 0;
|
||||
virtual DerivedPaths toDerivedPaths() = 0;
|
||||
|
||||
DerivedPathWithHints toDerivedPathWithHints();
|
||||
DerivedPath toDerivedPath();
|
||||
|
||||
App toApp(EvalState & state);
|
||||
UnresolvedApp toApp(EvalState & state);
|
||||
|
||||
virtual std::pair<Value *, Pos> toValue(EvalState & state)
|
||||
{
|
||||
|
@ -74,7 +80,7 @@ struct InstallableValue : Installable
|
|||
|
||||
virtual std::vector<DerivationInfo> toDerivations() = 0;
|
||||
|
||||
DerivedPathsWithHints toDerivedPathsWithHints() override;
|
||||
DerivedPaths toDerivedPaths() override;
|
||||
};
|
||||
|
||||
struct InstallableFlake : InstallableValue
|
||||
|
|
|
@ -8,8 +8,8 @@ libcmd_SOURCES := $(wildcard $(d)/*.cc)
|
|||
|
||||
libcmd_CXXFLAGS += -I src/libutil -I src/libstore -I src/libexpr -I src/libmain -I src/libfetchers
|
||||
|
||||
libcmd_LDFLAGS = -llowdown
|
||||
libcmd_LDFLAGS += -llowdown -pthread
|
||||
|
||||
libcmd_LIBS = libstore libutil libexpr libmain libfetchers
|
||||
|
||||
$(eval $(call install-file-in, $(d)/nix-cmd.pc, $(prefix)/lib/pkgconfig, 0644))
|
||||
$(eval $(call install-file-in, $(d)/nix-cmd.pc, $(libdir)/pkgconfig, 0644))
|
||||
|
|
|
@ -12,7 +12,7 @@ std::string renderMarkdownToTerminal(std::string_view markdown)
|
|||
struct lowdown_opts opts {
|
||||
.type = LOWDOWN_TERM,
|
||||
.maxdepth = 20,
|
||||
.cols = std::min(getWindowSize().second, (unsigned short) 80),
|
||||
.cols = std::max(getWindowSize().second, (unsigned short) 80),
|
||||
.hmargin = 0,
|
||||
.vmargin = 0,
|
||||
.feat = LOWDOWN_COMMONMARK | LOWDOWN_FENCED | LOWDOWN_DEFLIST | LOWDOWN_TABLES,
|
||||
|
@ -25,7 +25,7 @@ std::string renderMarkdownToTerminal(std::string_view markdown)
|
|||
Finally freeDoc([&]() { lowdown_doc_free(doc); });
|
||||
|
||||
size_t maxn = 0;
|
||||
auto node = lowdown_doc_parse(doc, &maxn, markdown.data(), markdown.size());
|
||||
auto node = lowdown_doc_parse(doc, &maxn, markdown.data(), markdown.size(), nullptr);
|
||||
if (!node)
|
||||
throw Error("cannot parse Markdown document");
|
||||
Finally freeNode([&]() { lowdown_node_free(node); });
|
||||
|
@ -40,11 +40,11 @@ std::string renderMarkdownToTerminal(std::string_view markdown)
|
|||
throw Error("cannot allocate Markdown output buffer");
|
||||
Finally freeBuffer([&]() { lowdown_buf_free(buf); });
|
||||
|
||||
int rndr_res = lowdown_term_rndr(buf, nullptr, renderer, node);
|
||||
int rndr_res = lowdown_term_rndr(buf, renderer, node);
|
||||
if (!rndr_res)
|
||||
throw Error("allocation error while rendering Markdown");
|
||||
|
||||
return std::string(buf->data, buf->size);
|
||||
return filterANSIEscapes(std::string(buf->data, buf->size), !shouldANSI());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue