Skip to content

Commit

Permalink
nix: Add --derivation flag to operate on .drv paths
Browse files Browse the repository at this point in the history
For instance, 'nix why-depends --use-derivation nixpkgs#hello
nixpkgs#glibc' shows why hello's .drv depends on glibc's .drv.
  • Loading branch information
edolstra committed Jul 15, 2020
1 parent dfe8f3e commit 3624c04
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 14 deletions.
4 changes: 2 additions & 2 deletions src/nix/command.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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");
Expand Down
17 changes: 15 additions & 2 deletions src/nix/command.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion src/nix/develop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
30 changes: 24 additions & 6 deletions src/nix/installables.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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;

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> 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());
Expand Down
2 changes: 1 addition & 1 deletion src/nix/run.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
4 changes: 2 additions & 2 deletions src/nix/why-depends.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 3624c04

Please sign in to comment.