diff --git a/src/nix/build.cc b/src/nix/build.cc index 42b3e42c6..915a06649 100644 --- a/src/nix/build.cc +++ b/src/nix/build.cc @@ -51,7 +51,7 @@ struct CmdBuild : MixDryRun, InstallablesCommand void run(ref store) override { - auto buildables = toBuildables(store, dryRun ? DryRun : Build); + auto buildables = toBuildables(store, dryRun ? DryRun : Build, installables); for (size_t i = 0; i < buildables.size(); ++i) { auto & b(buildables[i]); diff --git a/src/nix/command.cc b/src/nix/command.cc index 058a7548c..f69c56896 100644 --- a/src/nix/command.cc +++ b/src/nix/command.cc @@ -118,7 +118,7 @@ void StorePathsCommand::run(ref store) } else { - for (auto & p : toStorePaths(store, NoBuild)) + for (auto & p : toStorePaths(store, NoBuild, installables)) storePaths.push_back(p); if (recursive) { @@ -134,7 +134,7 @@ void StorePathsCommand::run(ref store) void StorePathCommand::run(ref store) { - auto storePaths = toStorePaths(store, NoBuild); + auto storePaths = toStorePaths(store, NoBuild, 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 b052c42b1..182b01ef9 100644 --- a/src/nix/command.hh +++ b/src/nix/command.hh @@ -93,6 +93,8 @@ private: Value * vSourceExpr = 0; }; +enum RealiseMode { Build, NoBuild, DryRun }; + /* A command that operates on a list of "installables", which can be store paths, attribute paths, Nix expressions, etc. */ struct InstallablesCommand : virtual Args, SourceExprCommand @@ -104,12 +106,6 @@ struct InstallablesCommand : virtual Args, SourceExprCommand expectArgs("installables", &_installables); } - enum RealiseMode { Build, NoBuild, DryRun }; - - Buildables toBuildables(ref store, RealiseMode mode); - - PathSet toStorePaths(ref store, RealiseMode mode); - void prepare() override; virtual bool useDefaultInstallables() { return true; } @@ -198,4 +194,17 @@ struct RegisterCommand } }; +std::shared_ptr parseInstallable( + SourceExprCommand & cmd, ref store, const std::string & installable, + bool useDefaultInstallables); + +Buildables toBuildables(ref store, RealiseMode mode, + std::vector> installables); + +PathSet toStorePaths(ref store, RealiseMode mode, + std::vector> installables); + +Path toStorePath(ref store, RealiseMode mode, + std::shared_ptr installable); + } diff --git a/src/nix/installables.cc b/src/nix/installables.cc index f3c7d3075..76df05fa3 100644 --- a/src/nix/installables.cc +++ b/src/nix/installables.cc @@ -240,7 +240,17 @@ static std::vector> parseInstallables( return result; } -Buildables InstallablesCommand::toBuildables(ref store, RealiseMode mode) +std::shared_ptr parseInstallable( + SourceExprCommand & cmd, ref store, const std::string & installable, + bool useDefaultInstallables) +{ + auto installables = parseInstallables(cmd, store, {installable}, false); + assert(installables.size() == 1); + return installables.front(); +} + +Buildables toBuildables(ref store, RealiseMode mode, + std::vector> installables) { if (mode != Build) settings.readOnlyMode = true; @@ -251,8 +261,13 @@ Buildables InstallablesCommand::toBuildables(ref store, RealiseMode mode) for (auto & i : installables) { for (auto & b : i->toBuildables()) { - if (b.drvPath != "") - pathsToBuild.insert(b.drvPath); + if (b.drvPath != "") { + StringSet outputNames; + for (auto & output : b.outputs) + outputNames.insert(output.first); + pathsToBuild.insert( + b.drvPath + "!" + concatStringsSep(",", outputNames)); + } buildables.push_back(std::move(b)); } } @@ -265,17 +280,29 @@ Buildables InstallablesCommand::toBuildables(ref store, RealiseMode mode) return buildables; } -PathSet InstallablesCommand::toStorePaths(ref store, RealiseMode mode) +PathSet toStorePaths(ref store, RealiseMode mode, + std::vector> installables) { PathSet outPaths; - for (auto & b : toBuildables(store, mode)) + for (auto & b : toBuildables(store, mode, installables)) for (auto & output : b.outputs) outPaths.insert(output.second); return outPaths; } +Path toStorePath(ref store, RealiseMode mode, + std::shared_ptr installable) +{ + auto paths = toStorePaths(store, mode, {installable}); + + if (paths.size() != 1) + throw Error("argument '%s' should evaluate to one store path", installable->what()); + + return *paths.begin(); +} + void InstallablesCommand::prepare() { installables = parseInstallables(*this, getStore(), _installables, useDefaultInstallables()); @@ -283,9 +310,7 @@ void InstallablesCommand::prepare() void InstallableCommand::prepare() { - auto installables = parseInstallables(*this, getStore(), {_installable}, false); - assert(installables.size() == 1); - installable = installables.front(); + installable = parseInstallable(*this, getStore(), _installable, false); } } diff --git a/src/nix/run.cc b/src/nix/run.cc index 31c3c1464..c72ede99c 100644 --- a/src/nix/run.cc +++ b/src/nix/run.cc @@ -90,7 +90,7 @@ struct CmdRun : InstallablesCommand void run(ref store) override { - auto outPaths = toStorePaths(store, Build); + auto outPaths = toStorePaths(store, Build, installables); auto accessor = store->getFSAccessor();