nix build: Only download the requested derivation outputs

Also some refactoring.
This commit is contained in:
Eelco Dolstra 2017-09-10 15:58:30 +02:00
parent 3ed8290e53
commit ad228d84e5
5 changed files with 52 additions and 18 deletions

View file

@ -51,7 +51,7 @@ struct CmdBuild : MixDryRun, InstallablesCommand
void run(ref<Store> store) override void run(ref<Store> 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) { for (size_t i = 0; i < buildables.size(); ++i) {
auto & b(buildables[i]); auto & b(buildables[i]);

View file

@ -118,7 +118,7 @@ void StorePathsCommand::run(ref<Store> store)
} }
else { else {
for (auto & p : toStorePaths(store, NoBuild)) for (auto & p : toStorePaths(store, NoBuild, installables))
storePaths.push_back(p); storePaths.push_back(p);
if (recursive) { if (recursive) {
@ -134,7 +134,7 @@ void StorePathsCommand::run(ref<Store> store)
void StorePathCommand::run(ref<Store> store) void StorePathCommand::run(ref<Store> store)
{ {
auto storePaths = toStorePaths(store, NoBuild); auto storePaths = toStorePaths(store, NoBuild, installables);
if (storePaths.size() != 1) if (storePaths.size() != 1)
throw UsageError("this command requires exactly one store path"); throw UsageError("this command requires exactly one store path");

View file

@ -93,6 +93,8 @@ private:
Value * vSourceExpr = 0; Value * vSourceExpr = 0;
}; };
enum RealiseMode { Build, NoBuild, DryRun };
/* A command that operates on a list of "installables", which can be /* A command that operates on a list of "installables", which can be
store paths, attribute paths, Nix expressions, etc. */ store paths, attribute paths, Nix expressions, etc. */
struct InstallablesCommand : virtual Args, SourceExprCommand struct InstallablesCommand : virtual Args, SourceExprCommand
@ -104,12 +106,6 @@ struct InstallablesCommand : virtual Args, SourceExprCommand
expectArgs("installables", &_installables); expectArgs("installables", &_installables);
} }
enum RealiseMode { Build, NoBuild, DryRun };
Buildables toBuildables(ref<Store> store, RealiseMode mode);
PathSet toStorePaths(ref<Store> store, RealiseMode mode);
void prepare() override; void prepare() override;
virtual bool useDefaultInstallables() { return true; } virtual bool useDefaultInstallables() { return true; }
@ -198,4 +194,17 @@ struct RegisterCommand
} }
}; };
std::shared_ptr<Installable> parseInstallable(
SourceExprCommand & cmd, ref<Store> store, const std::string & installable,
bool useDefaultInstallables);
Buildables toBuildables(ref<Store> store, RealiseMode mode,
std::vector<std::shared_ptr<Installable>> installables);
PathSet toStorePaths(ref<Store> store, RealiseMode mode,
std::vector<std::shared_ptr<Installable>> installables);
Path toStorePath(ref<Store> store, RealiseMode mode,
std::shared_ptr<Installable> installable);
} }

View file

@ -240,7 +240,17 @@ static std::vector<std::shared_ptr<Installable>> parseInstallables(
return result; return result;
} }
Buildables InstallablesCommand::toBuildables(ref<Store> store, RealiseMode mode) std::shared_ptr<Installable> parseInstallable(
SourceExprCommand & cmd, ref<Store> 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> store, RealiseMode mode,
std::vector<std::shared_ptr<Installable>> installables)
{ {
if (mode != Build) if (mode != Build)
settings.readOnlyMode = true; settings.readOnlyMode = true;
@ -251,8 +261,13 @@ Buildables InstallablesCommand::toBuildables(ref<Store> store, RealiseMode mode)
for (auto & i : installables) { for (auto & i : installables) {
for (auto & b : i->toBuildables()) { for (auto & b : i->toBuildables()) {
if (b.drvPath != "") if (b.drvPath != "") {
pathsToBuild.insert(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)); buildables.push_back(std::move(b));
} }
} }
@ -265,17 +280,29 @@ Buildables InstallablesCommand::toBuildables(ref<Store> store, RealiseMode mode)
return buildables; return buildables;
} }
PathSet InstallablesCommand::toStorePaths(ref<Store> store, RealiseMode mode) PathSet toStorePaths(ref<Store> store, RealiseMode mode,
std::vector<std::shared_ptr<Installable>> installables)
{ {
PathSet outPaths; PathSet outPaths;
for (auto & b : toBuildables(store, mode)) for (auto & b : toBuildables(store, mode, installables))
for (auto & output : b.outputs) for (auto & output : b.outputs)
outPaths.insert(output.second); outPaths.insert(output.second);
return outPaths; return outPaths;
} }
Path toStorePath(ref<Store> store, RealiseMode mode,
std::shared_ptr<Installable> 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() void InstallablesCommand::prepare()
{ {
installables = parseInstallables(*this, getStore(), _installables, useDefaultInstallables()); installables = parseInstallables(*this, getStore(), _installables, useDefaultInstallables());
@ -283,9 +310,7 @@ void InstallablesCommand::prepare()
void InstallableCommand::prepare() void InstallableCommand::prepare()
{ {
auto installables = parseInstallables(*this, getStore(), {_installable}, false); installable = parseInstallable(*this, getStore(), _installable, false);
assert(installables.size() == 1);
installable = installables.front();
} }
} }

View file

@ -90,7 +90,7 @@ struct CmdRun : InstallablesCommand
void run(ref<Store> store) override void run(ref<Store> store) override
{ {
auto outPaths = toStorePaths(store, Build); auto outPaths = toStorePaths(store, Build, installables);
auto accessor = store->getFSAccessor(); auto accessor = store->getFSAccessor();