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.
This commit is contained in:
Eelco Dolstra 2020-07-15 20:22:52 +02:00
parent dfe8f3ebc6
commit 3624c042ac
6 changed files with 46 additions and 14 deletions

View file

@ -63,7 +63,7 @@ void StorePathsCommand::run(ref<Store> 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> store)
void StorePathCommand::run(ref<Store> 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");

View file

@ -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<Path> file;
std::optional<std::string> expr;
// FIXME: move this; not all commands (e.g. 'nix run') use it.
OperateOn operateOn = OperateOn::Output;
SourceExprCommand();
std::vector<std::shared_ptr<Installable>> parseInstallables(
@ -176,10 +187,12 @@ static RegisterCommand registerCommand(const std::string & name)
Buildables build(ref<Store> store, Realise mode,
std::vector<std::shared_ptr<Installable>> installables);
std::set<StorePath> toStorePaths(ref<Store> store, Realise mode,
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,
StorePath toStorePath(ref<Store> store,
Realise mode, OperateOn operateOn,
std::shared_ptr<Installable> installable);
std::set<StorePath> toDerivations(ref<Store> store,

View file

@ -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();
}

View file

@ -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> store, Realise mode,
return buildables;
}
StorePathSet toStorePaths(ref<Store> store, Realise mode,
StorePathSet toStorePaths(ref<Store> store,
Realise mode, OperateOn operateOn,
std::vector<std::shared_ptr<Installable>> installables)
{
StorePathSet outPaths;
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> store, Realise mode,
StorePath toStorePath(ref<Store> store,
Realise mode, OperateOn operateOn,
std::shared_ptr<Installable> 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());

View file

@ -104,7 +104,7 @@ struct CmdShell : InstallablesCommand, RunCommon, MixEnvironment
void run(ref<Store> store) override
{
auto outPaths = toStorePaths(store, Realise::Outputs, installables);
auto outPaths = toStorePaths(store, Realise::Outputs, OperateOn::Output, installables);
auto accessor = store->getFSAccessor();

View file

@ -73,9 +73,9 @@ struct CmdWhyDepends : SourceExprCommand
void run(ref<Store> 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;