From 3624c042ace05db88794e87ee37f3296bab19bc8 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 15 Jul 2020 20:22:52 +0200 Subject: [PATCH] nix: Add --derivation flag to operate on .drv paths For instance, 'nix why-depends --use-derivation nixpkgs#hello nixpkgs#glibc' shows why hello's .drv depends on glibc's .drv. --- src/nix/command.cc | 4 ++-- src/nix/command.hh | 17 +++++++++++++++-- src/nix/develop.cc | 3 ++- src/nix/installables.cc | 30 ++++++++++++++++++++++++------ src/nix/run.cc | 2 +- src/nix/why-depends.cc | 4 ++-- 6 files changed, 46 insertions(+), 14 deletions(-) diff --git a/src/nix/command.cc b/src/nix/command.cc index a4faccb6d..af36dda89 100644 --- a/src/nix/command.cc +++ b/src/nix/command.cc @@ -63,7 +63,7 @@ void StorePathsCommand::run(ref store) } else { - for (auto & p : toStorePaths(store, realiseMode, installables)) + for (auto & p : toStorePaths(store, realiseMode, operateOn, installables)) storePaths.push_back(p); if (recursive) { @@ -80,7 +80,7 @@ void StorePathsCommand::run(ref store) void StorePathCommand::run(ref store) { - auto storePaths = toStorePaths(store, Realise::Nothing, installables); + auto storePaths = toStorePaths(store, Realise::Nothing, operateOn, installables); if (storePaths.size() != 1) throw UsageError("this command requires exactly one store path"); diff --git a/src/nix/command.hh b/src/nix/command.hh index 5fa8f9333..1c7413300 100644 --- a/src/nix/command.hh +++ b/src/nix/command.hh @@ -50,11 +50,22 @@ struct MixFlakeOptions : virtual Args, EvalCommand { 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 { std::optional file; std::optional expr; + // FIXME: move this; not all commands (e.g. 'nix run') use it. + OperateOn operateOn = OperateOn::Output; + SourceExprCommand(); std::vector> parseInstallables( @@ -176,10 +187,12 @@ static RegisterCommand registerCommand(const std::string & name) Buildables build(ref store, Realise mode, std::vector> installables); -std::set toStorePaths(ref store, Realise mode, +std::set toStorePaths(ref store, + Realise mode, OperateOn operateOn, std::vector> installables); -StorePath toStorePath(ref store, Realise mode, +StorePath toStorePath(ref store, + Realise mode, OperateOn operateOn, std::shared_ptr installable); std::set toDerivations(ref store, diff --git a/src/nix/develop.cc b/src/nix/develop.cc index bf4890e95..a6d7d6add 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -321,7 +321,8 @@ struct CmdDevelop : Common, MixEnvironment Strings{"legacyPackages." + settings.thisSystem.get() + "."}, lockFlags); - shell = state->store->printStorePath(toStorePath(state->store, Realise::Outputs, bashInstallable)) + "/bin/bash"; + shell = state->store->printStorePath( + toStorePath(state->store, Realise::Outputs, OperateOn::Output, bashInstallable)) + "/bin/bash"; } catch (Error &) { ignoreException(); } diff --git a/src/nix/installables.cc b/src/nix/installables.cc index d464efc35..a13e5a3df 100644 --- a/src/nix/installables.cc +++ b/src/nix/installables.cc @@ -128,6 +128,12 @@ SourceExprCommand::SourceExprCommand() .labels = {"expr"}, .handler = {&expr} }); + + addFlag({ + .longName ="derivation", + .description = "operate on the store derivation rather than its outputs", + .handler = {&operateOn, OperateOn::Derivation}, + }); } Strings SourceExprCommand::getDefaultFlakeAttrPaths() @@ -667,22 +673,34 @@ Buildables build(ref store, Realise mode, return buildables; } -StorePathSet toStorePaths(ref store, Realise mode, +StorePathSet toStorePaths(ref store, + Realise mode, OperateOn operateOn, std::vector> installables) { StorePathSet outPaths; - for (auto & b : build(store, mode, installables)) - for (auto & output : b.outputs) - outPaths.insert(output.second); + if (operateOn == OperateOn::Output) { + for (auto & b : build(store, mode, installables)) + for (auto & output : b.outputs) + outPaths.insert(output.second); + } else { + if (mode == Realise::Nothing) + settings.readOnlyMode = true; + + for (auto & i : installables) + for (auto & b : i->toBuildables()) + if (b.drvPath) + outPaths.insert(*b.drvPath); + } return outPaths; } -StorePath toStorePath(ref store, Realise mode, +StorePath toStorePath(ref store, + Realise mode, OperateOn operateOn, std::shared_ptr installable) { - auto paths = toStorePaths(store, mode, {installable}); + auto paths = toStorePaths(store, mode, operateOn, {installable}); if (paths.size() != 1) throw Error("argument '%s' should evaluate to one store path", installable->what()); diff --git a/src/nix/run.cc b/src/nix/run.cc index a27538085..cbaba9d90 100644 --- a/src/nix/run.cc +++ b/src/nix/run.cc @@ -104,7 +104,7 @@ struct CmdShell : InstallablesCommand, RunCommon, MixEnvironment void run(ref store) override { - auto outPaths = toStorePaths(store, Realise::Outputs, installables); + auto outPaths = toStorePaths(store, Realise::Outputs, OperateOn::Output, installables); auto accessor = store->getFSAccessor(); diff --git a/src/nix/why-depends.cc b/src/nix/why-depends.cc index 55bb43f95..f854bedb2 100644 --- a/src/nix/why-depends.cc +++ b/src/nix/why-depends.cc @@ -73,9 +73,9 @@ struct CmdWhyDepends : SourceExprCommand void run(ref store) override { auto package = parseInstallable(store, _package); - auto packagePath = toStorePath(store, Realise::Outputs, package); + auto packagePath = toStorePath(store, Realise::Outputs, operateOn, package); auto dependency = parseInstallable(store, _dependency); - auto dependencyPath = toStorePath(store, Realise::Derivation, dependency); + auto dependencyPath = toStorePath(store, Realise::Derivation, operateOn, dependency); auto dependencyPathHash = dependencyPath.hashPart(); StorePathSet closure;