From 2b621c8a558e5120292037ca3046de2f2444e8e2 Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 13 Jan 2023 01:56:32 +0100 Subject: [PATCH] libcmd: implement base for Activatables --- src/libcmd/activatables.cc | 46 +++++++++++++++++++++++++ src/libcmd/activatables.hh | 70 ++++++++++++++++++++++++++++++++++++++ src/libcmd/command.hh | 29 ++++++++++++++++ 3 files changed, 145 insertions(+) create mode 100644 src/libcmd/activatables.cc create mode 100644 src/libcmd/activatables.hh diff --git a/src/libcmd/activatables.cc b/src/libcmd/activatables.cc new file mode 100644 index 000000000..490dba75d --- /dev/null +++ b/src/libcmd/activatables.cc @@ -0,0 +1,46 @@ +#include "command.hh" +#include "progress-bar.hh" + +using namespace nix; + +ActivatableCommand::ActivatableCommand(std::string activationPackageAttrPath) + : activationPackageAttrPath(activationPackageAttrPath) +{ } + +void ActivatableCommand::prepare() { + InstallableCommand::prepare(); + auto installableFlake = std::dynamic_pointer_cast(installable); + if (installableFlake) { + auto fragment = *installableFlake->attrPaths.begin(); + installable = std::make_shared( + this, + getEvalState(), + std::move(installableFlake->flakeRef), + activationPackageAttrPath == "" ? fragment : fragment + "." + activationPackageAttrPath, + installableFlake->outputsSpec, + getDefaultFlakeAttrPaths(), + getDefaultFlakeAttrPathPrefixes(), + installableFlake->lockFlags + ); + } +} + +StorePath ActivatableCommand::buildActivatable(nix::ref store, bool dryRun) { + auto installableFlake = std::dynamic_pointer_cast(installable); + std::vector> installableContext; + installableContext.emplace_back(installable); + auto buildables = Installable::build( + getEvalStore(), store, + Realise::Outputs, + installableContext, bmNormal); + + BuiltPaths buildables2; + for (auto & b : buildables) + buildables2.push_back(b.path); + + auto buildable = buildables2.front(); + if (buildables2.size() != 1 || buildable.outPaths().size() != 1) { + throw UsageError("this command requires that the argument produces a single store path"); + } + return *buildable.outPaths().begin(); +} diff --git a/src/libcmd/activatables.hh b/src/libcmd/activatables.hh new file mode 100644 index 000000000..7b564a55b --- /dev/null +++ b/src/libcmd/activatables.hh @@ -0,0 +1,70 @@ +#include "command.hh" +#include "local-fs-store.hh" +#include "progress-bar.hh" +#include "shared.hh" + +using namespace nix; + + +template +ActivatableBuildCommand::ActivatableBuildCommand() +{ + addFlag({ + .longName = "out-link", + .shortName = 'o', + .description = "Use *path* as prefix for the symlinks to the build results. It defaults to `result`.", + .labels = {"path"}, + .handler = {&outLink}, + .completer = completePath + }); + + addFlag({ + .longName = "no-link", + .description = "Do not create symlinks to the build results.", + .handler = {&outLink, Path("")}, + }); + + addFlag({ + .longName = "print-out-paths", + .description = "Print the resulting output paths", + .handler = {&printOutputPaths, true}, + }); +}; + +template +void ActivatableBuildCommand::run(nix::ref store) +{ + auto installableFlake = std::dynamic_pointer_cast(ActivatableCommand::installable); + if (dryRun) { + std::vector> installableContext; + installableContext.emplace_back(ActivatableCommand::installable); + std::vector pathsToBuild; + + for (auto & i : installableContext) { + auto b = i->toDerivedPaths(); + pathsToBuild.insert(pathsToBuild.end(), b.begin(), b.end()); + } + printMissing(store, pathsToBuild, lvlError); + return; + } + + auto out = ActivatableCommand::buildActivatable(store); + + if (outLink != "") { + if (auto store2 = store.dynamic_pointer_cast()) { + std::string symlink = outLink; + store2->addPermRoot(out, absPath(symlink)); + } + } + + if (printOutputPaths) { + stopProgressBar(); + std::cout << store->printStorePath(out) << std::endl; + } +} + +template +ActivationCommand::ActivationCommand(std::string activationType, std::string selfCommandName) + : activationType(activationType), + selfCommandName(selfCommandName) +{ } diff --git a/src/libcmd/command.hh b/src/libcmd/command.hh index 60c575d56..1ee855af0 100644 --- a/src/libcmd/command.hh +++ b/src/libcmd/command.hh @@ -1,5 +1,6 @@ #pragma once +#include "common-args.hh" #include "installables.hh" #include "args.hh" #include "common-eval-args.hh" @@ -272,6 +273,34 @@ struct MixEnvironment : virtual Args { void setEnviron(); }; +/* A command that operates on exactly one "activatable" */ +struct ActivatableCommand : public InstallableCommand +{ + ActivatableCommand(std::string activationPackageAttrPath); + std::string activationPackageAttrPath; + void prepare() override; + StorePath buildActivatable(nix::ref store, bool dryRun = false); +}; + +template +struct ActivatableBuildCommand : public ActivatableCommand, public MixDryRun +{ + ActivatableBuildCommand(); + Path outLink = "result"; + bool printOutputPaths = false; + void run(nix::ref) override; +}; + +/* A command that manages the activation of exactly one "activatable" */ +template +struct ActivationCommand : public ActivatableCommand +{ +public: + ActivationCommand(std::string activationType, std::string selfCommandName); + const std::string activationType; + const std::string selfCommandName; +}; + void completeFlakeRef(ref store, std::string_view prefix); void completeFlakeRefWithFragment(