2020-10-12 20:08:52 +03:00
|
|
|
#include "worker.hh"
|
|
|
|
#include "substitution-goal.hh"
|
|
|
|
#include "derivation-goal.hh"
|
2021-02-26 17:20:33 +02:00
|
|
|
#include "local-store.hh"
|
2004-06-18 21:09:32 +03:00
|
|
|
|
2020-10-11 19:25:25 +03:00
|
|
|
namespace nix {
|
2004-06-18 21:09:32 +03:00
|
|
|
|
2021-07-19 16:43:08 +03:00
|
|
|
void Store::buildPaths(const std::vector<DerivedPath> & reqs, BuildMode buildMode, std::shared_ptr<Store> evalStore)
|
2003-07-29 13:43:12 +03:00
|
|
|
{
|
2021-07-19 16:43:08 +03:00
|
|
|
Worker worker(*this, evalStore ? *evalStore : *this);
|
2005-01-19 17:02:02 +02:00
|
|
|
|
|
|
|
Goals goals;
|
2021-03-03 03:11:09 +02:00
|
|
|
for (auto & br : reqs)
|
|
|
|
goals.insert(worker.makeGoal(br, buildMode));
|
2005-02-23 13:19:27 +02:00
|
|
|
|
|
|
|
worker.run(goals);
|
|
|
|
|
2019-12-05 20:11:09 +02:00
|
|
|
StorePathSet failed;
|
2020-06-15 20:25:35 +03:00
|
|
|
std::optional<Error> ex;
|
2016-12-07 14:16:06 +02:00
|
|
|
for (auto & i : goals) {
|
2020-06-15 20:25:35 +03:00
|
|
|
if (i->ex) {
|
|
|
|
if (ex)
|
|
|
|
logError(i->ex->info());
|
|
|
|
else
|
2022-12-07 13:58:58 +02:00
|
|
|
ex = std::move(i->ex);
|
2020-06-15 20:25:35 +03:00
|
|
|
}
|
|
|
|
if (i->exitCode != Goal::ecSuccess) {
|
2020-11-18 15:36:15 +02:00
|
|
|
if (auto i2 = dynamic_cast<DerivationGoal *>(i.get())) failed.insert(i2->drvPath);
|
2020-11-09 14:47:06 +02:00
|
|
|
else if (auto i2 = dynamic_cast<PathSubstitutionGoal *>(i.get())) failed.insert(i2->storePath);
|
2005-02-23 13:19:27 +02:00
|
|
|
}
|
2016-12-07 14:16:06 +02:00
|
|
|
}
|
2012-07-27 16:59:18 +03:00
|
|
|
|
2020-06-15 20:25:35 +03:00
|
|
|
if (failed.size() == 1 && ex) {
|
2023-06-22 21:23:25 +03:00
|
|
|
ex->status = worker.failingExitStatus();
|
2022-12-07 13:58:58 +02:00
|
|
|
throw std::move(*ex);
|
2020-06-15 20:25:35 +03:00
|
|
|
} else if (!failed.empty()) {
|
|
|
|
if (ex) logError(ex->info());
|
2023-06-22 21:23:25 +03:00
|
|
|
throw Error(worker.failingExitStatus(), "build of %s failed", showPaths(failed));
|
2020-06-15 20:25:35 +03:00
|
|
|
}
|
2003-07-29 13:43:12 +03:00
|
|
|
}
|
|
|
|
|
Make `KeyedBuildResult`, `BuildResult` like before, and fix bug another way
In https://github.com/NixOS/nix/pull/6311#discussion_r834863823, I
realized since derivation goals' wanted outputs can "grow" due to
overlapping dependencies (See `DerivationGoal::addWantedOutputs`, called
by `Worker::makeDerivationGoalCommon`), the previous bug fix had an
unfortunate side effect of causing more pointless rebuilds.
In paticular, we have this situation:
1. Goal made from `DerivedPath::Built { foo, {a} }`.
2. Goal gives on on substituting, starts building.
3. Goal made from `DerivedPath::Built { foo, {b} }`, in fact is just
modified original goal.
4. Though the goal had gotten as far as building, so all outputs were
going to be produced, `addWantedOutputs` no longer knows that and so
the goal is flagged to be restarted.
This might sound far-fetched with input-addressed drvs, where we usually
basically have all our goals "planned out" before we start doing
anything, but with CA derivation goals and especially RFC 92, where *drv
resolution* means goals are created after some building is completed, it
is more likely to happen.
So the first thing to do was restore the clearing of `wantedOutputs` we
used to do, and then filter the outputs in `buildPathsWithResults` to
only get the ones we care about.
But fix also has its own side effect in that the `DerivedPath` in the
`BuildResult` in `DerivationGoal` cannot be trusted; it is merely the
*first* `DerivedPath` for which this goal was originally created.
To remedy this, I made `BuildResult` be like it was before, and instead
made `KeyedBuildResult` be a subclass wit the path. Only
`buildPathsWithResults` returns `KeyedBuildResult`s, everything else
just becomes like it was before, where the "key" is unambiguous from
context.
I think separating the "primary key" field(s) from the other fields is
good practical in general anyways. (I would like to do the same thing
for `ValidPathInfo`.) Among other things, it allows constructions like
`std::map<Key, ThingWithKey>` where doesn't contain duplicate keys and
just precludes the possibility of those duplicate keys being out of
sync.
We might leverage the above someday to overload `buildPathsWithResults`
to take a *set* of return a *map* per the above.
-----
Unfortunately, we need to avoid C++20 strictness on designated
initializers.
(BTW
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2287r1.html
this offers some new syntax for this use-case. Hopefully this will be
adopted and we can eventually use it.)
No having that yet, maybe it would be better to not make
`KeyedBuildResult` a subclass to just avoid this.
Co-authored-by: Robert Hensing <roberth@users.noreply.github.com>
2022-03-25 03:26:07 +02:00
|
|
|
std::vector<KeyedBuildResult> Store::buildPathsWithResults(
|
2022-03-08 20:50:46 +02:00
|
|
|
const std::vector<DerivedPath> & reqs,
|
|
|
|
BuildMode buildMode,
|
|
|
|
std::shared_ptr<Store> evalStore)
|
|
|
|
{
|
|
|
|
Worker worker(*this, evalStore ? *evalStore : *this);
|
|
|
|
|
|
|
|
Goals goals;
|
Make `KeyedBuildResult`, `BuildResult` like before, and fix bug another way
In https://github.com/NixOS/nix/pull/6311#discussion_r834863823, I
realized since derivation goals' wanted outputs can "grow" due to
overlapping dependencies (See `DerivationGoal::addWantedOutputs`, called
by `Worker::makeDerivationGoalCommon`), the previous bug fix had an
unfortunate side effect of causing more pointless rebuilds.
In paticular, we have this situation:
1. Goal made from `DerivedPath::Built { foo, {a} }`.
2. Goal gives on on substituting, starts building.
3. Goal made from `DerivedPath::Built { foo, {b} }`, in fact is just
modified original goal.
4. Though the goal had gotten as far as building, so all outputs were
going to be produced, `addWantedOutputs` no longer knows that and so
the goal is flagged to be restarted.
This might sound far-fetched with input-addressed drvs, where we usually
basically have all our goals "planned out" before we start doing
anything, but with CA derivation goals and especially RFC 92, where *drv
resolution* means goals are created after some building is completed, it
is more likely to happen.
So the first thing to do was restore the clearing of `wantedOutputs` we
used to do, and then filter the outputs in `buildPathsWithResults` to
only get the ones we care about.
But fix also has its own side effect in that the `DerivedPath` in the
`BuildResult` in `DerivationGoal` cannot be trusted; it is merely the
*first* `DerivedPath` for which this goal was originally created.
To remedy this, I made `BuildResult` be like it was before, and instead
made `KeyedBuildResult` be a subclass wit the path. Only
`buildPathsWithResults` returns `KeyedBuildResult`s, everything else
just becomes like it was before, where the "key" is unambiguous from
context.
I think separating the "primary key" field(s) from the other fields is
good practical in general anyways. (I would like to do the same thing
for `ValidPathInfo`.) Among other things, it allows constructions like
`std::map<Key, ThingWithKey>` where doesn't contain duplicate keys and
just precludes the possibility of those duplicate keys being out of
sync.
We might leverage the above someday to overload `buildPathsWithResults`
to take a *set* of return a *map* per the above.
-----
Unfortunately, we need to avoid C++20 strictness on designated
initializers.
(BTW
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2287r1.html
this offers some new syntax for this use-case. Hopefully this will be
adopted and we can eventually use it.)
No having that yet, maybe it would be better to not make
`KeyedBuildResult` a subclass to just avoid this.
Co-authored-by: Robert Hensing <roberth@users.noreply.github.com>
2022-03-25 03:26:07 +02:00
|
|
|
std::vector<std::pair<const DerivedPath &, GoalPtr>> state;
|
|
|
|
|
|
|
|
for (const auto & req : reqs) {
|
|
|
|
auto goal = worker.makeGoal(req, buildMode);
|
|
|
|
goals.insert(goal);
|
|
|
|
state.push_back({req, goal});
|
|
|
|
}
|
2022-03-08 20:50:46 +02:00
|
|
|
|
|
|
|
worker.run(goals);
|
|
|
|
|
Make `KeyedBuildResult`, `BuildResult` like before, and fix bug another way
In https://github.com/NixOS/nix/pull/6311#discussion_r834863823, I
realized since derivation goals' wanted outputs can "grow" due to
overlapping dependencies (See `DerivationGoal::addWantedOutputs`, called
by `Worker::makeDerivationGoalCommon`), the previous bug fix had an
unfortunate side effect of causing more pointless rebuilds.
In paticular, we have this situation:
1. Goal made from `DerivedPath::Built { foo, {a} }`.
2. Goal gives on on substituting, starts building.
3. Goal made from `DerivedPath::Built { foo, {b} }`, in fact is just
modified original goal.
4. Though the goal had gotten as far as building, so all outputs were
going to be produced, `addWantedOutputs` no longer knows that and so
the goal is flagged to be restarted.
This might sound far-fetched with input-addressed drvs, where we usually
basically have all our goals "planned out" before we start doing
anything, but with CA derivation goals and especially RFC 92, where *drv
resolution* means goals are created after some building is completed, it
is more likely to happen.
So the first thing to do was restore the clearing of `wantedOutputs` we
used to do, and then filter the outputs in `buildPathsWithResults` to
only get the ones we care about.
But fix also has its own side effect in that the `DerivedPath` in the
`BuildResult` in `DerivationGoal` cannot be trusted; it is merely the
*first* `DerivedPath` for which this goal was originally created.
To remedy this, I made `BuildResult` be like it was before, and instead
made `KeyedBuildResult` be a subclass wit the path. Only
`buildPathsWithResults` returns `KeyedBuildResult`s, everything else
just becomes like it was before, where the "key" is unambiguous from
context.
I think separating the "primary key" field(s) from the other fields is
good practical in general anyways. (I would like to do the same thing
for `ValidPathInfo`.) Among other things, it allows constructions like
`std::map<Key, ThingWithKey>` where doesn't contain duplicate keys and
just precludes the possibility of those duplicate keys being out of
sync.
We might leverage the above someday to overload `buildPathsWithResults`
to take a *set* of return a *map* per the above.
-----
Unfortunately, we need to avoid C++20 strictness on designated
initializers.
(BTW
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2287r1.html
this offers some new syntax for this use-case. Hopefully this will be
adopted and we can eventually use it.)
No having that yet, maybe it would be better to not make
`KeyedBuildResult` a subclass to just avoid this.
Co-authored-by: Robert Hensing <roberth@users.noreply.github.com>
2022-03-25 03:26:07 +02:00
|
|
|
std::vector<KeyedBuildResult> results;
|
2022-03-08 20:50:46 +02:00
|
|
|
|
Make `KeyedBuildResult`, `BuildResult` like before, and fix bug another way
In https://github.com/NixOS/nix/pull/6311#discussion_r834863823, I
realized since derivation goals' wanted outputs can "grow" due to
overlapping dependencies (See `DerivationGoal::addWantedOutputs`, called
by `Worker::makeDerivationGoalCommon`), the previous bug fix had an
unfortunate side effect of causing more pointless rebuilds.
In paticular, we have this situation:
1. Goal made from `DerivedPath::Built { foo, {a} }`.
2. Goal gives on on substituting, starts building.
3. Goal made from `DerivedPath::Built { foo, {b} }`, in fact is just
modified original goal.
4. Though the goal had gotten as far as building, so all outputs were
going to be produced, `addWantedOutputs` no longer knows that and so
the goal is flagged to be restarted.
This might sound far-fetched with input-addressed drvs, where we usually
basically have all our goals "planned out" before we start doing
anything, but with CA derivation goals and especially RFC 92, where *drv
resolution* means goals are created after some building is completed, it
is more likely to happen.
So the first thing to do was restore the clearing of `wantedOutputs` we
used to do, and then filter the outputs in `buildPathsWithResults` to
only get the ones we care about.
But fix also has its own side effect in that the `DerivedPath` in the
`BuildResult` in `DerivationGoal` cannot be trusted; it is merely the
*first* `DerivedPath` for which this goal was originally created.
To remedy this, I made `BuildResult` be like it was before, and instead
made `KeyedBuildResult` be a subclass wit the path. Only
`buildPathsWithResults` returns `KeyedBuildResult`s, everything else
just becomes like it was before, where the "key" is unambiguous from
context.
I think separating the "primary key" field(s) from the other fields is
good practical in general anyways. (I would like to do the same thing
for `ValidPathInfo`.) Among other things, it allows constructions like
`std::map<Key, ThingWithKey>` where doesn't contain duplicate keys and
just precludes the possibility of those duplicate keys being out of
sync.
We might leverage the above someday to overload `buildPathsWithResults`
to take a *set* of return a *map* per the above.
-----
Unfortunately, we need to avoid C++20 strictness on designated
initializers.
(BTW
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2287r1.html
this offers some new syntax for this use-case. Hopefully this will be
adopted and we can eventually use it.)
No having that yet, maybe it would be better to not make
`KeyedBuildResult` a subclass to just avoid this.
Co-authored-by: Robert Hensing <roberth@users.noreply.github.com>
2022-03-25 03:26:07 +02:00
|
|
|
for (auto & [req, goalPtr] : state)
|
|
|
|
results.emplace_back(KeyedBuildResult {
|
|
|
|
goalPtr->getBuildResult(req),
|
|
|
|
/* .path = */ req,
|
|
|
|
});
|
2022-03-08 20:50:46 +02:00
|
|
|
|
|
|
|
return results;
|
|
|
|
}
|
|
|
|
|
2020-12-20 19:54:57 +02:00
|
|
|
BuildResult Store::buildDerivation(const StorePath & drvPath, const BasicDerivation & drv,
|
Allow remote builds without sending the derivation closure
Previously, to build a derivation remotely, we had to copy the entire
closure of the .drv file to the remote machine, even though we only
need the top-level derivation. This is very wasteful: the closure can
contain thousands of store paths, and in some Hydra use cases, include
source paths that are very large (e.g. Git/Mercurial checkouts).
So now there is a new operation, StoreAPI::buildDerivation(), that
performs a build from an in-memory representation of a derivation
(BasicDerivation) rather than from a on-disk .drv file. The only files
that need to be in the Nix store are the sources of the derivation
(drv.inputSrcs), and the needed output paths of the dependencies (as
described by drv.inputDrvs). "nix-store --serve" exposes this
interface.
Note that this is a privileged operation, because you can construct a
derivation that builds any store path whatsoever. Fixing this will
require changing the hashing scheme (i.e., the output paths should be
computed from the other fields in BasicDerivation, allowing them to be
verified without access to other derivations). However, this would be
quite nice because it would allow .drv-free building (e.g. "nix-env
-i" wouldn't have to write any .drv files to disk).
Fixes #173.
2015-07-17 18:57:40 +03:00
|
|
|
BuildMode buildMode)
|
|
|
|
{
|
2021-07-19 16:43:08 +03:00
|
|
|
Worker worker(*this, *this);
|
2023-01-11 23:32:30 +02:00
|
|
|
auto goal = worker.makeBasicDerivationGoal(drvPath, drv, OutputsSpec::All {}, buildMode);
|
Allow remote builds without sending the derivation closure
Previously, to build a derivation remotely, we had to copy the entire
closure of the .drv file to the remote machine, even though we only
need the top-level derivation. This is very wasteful: the closure can
contain thousands of store paths, and in some Hydra use cases, include
source paths that are very large (e.g. Git/Mercurial checkouts).
So now there is a new operation, StoreAPI::buildDerivation(), that
performs a build from an in-memory representation of a derivation
(BasicDerivation) rather than from a on-disk .drv file. The only files
that need to be in the Nix store are the sources of the derivation
(drv.inputSrcs), and the needed output paths of the dependencies (as
described by drv.inputDrvs). "nix-store --serve" exposes this
interface.
Note that this is a privileged operation, because you can construct a
derivation that builds any store path whatsoever. Fixing this will
require changing the hashing scheme (i.e., the output paths should be
computed from the other fields in BasicDerivation, allowing them to be
verified without access to other derivations). However, this would be
quite nice because it would allow .drv-free building (e.g. "nix-env
-i" wouldn't have to write any .drv files to disk).
Fixes #173.
2015-07-17 18:57:40 +03:00
|
|
|
|
|
|
|
try {
|
|
|
|
worker.run(Goals{goal});
|
Make `KeyedBuildResult`, `BuildResult` like before, and fix bug another way
In https://github.com/NixOS/nix/pull/6311#discussion_r834863823, I
realized since derivation goals' wanted outputs can "grow" due to
overlapping dependencies (See `DerivationGoal::addWantedOutputs`, called
by `Worker::makeDerivationGoalCommon`), the previous bug fix had an
unfortunate side effect of causing more pointless rebuilds.
In paticular, we have this situation:
1. Goal made from `DerivedPath::Built { foo, {a} }`.
2. Goal gives on on substituting, starts building.
3. Goal made from `DerivedPath::Built { foo, {b} }`, in fact is just
modified original goal.
4. Though the goal had gotten as far as building, so all outputs were
going to be produced, `addWantedOutputs` no longer knows that and so
the goal is flagged to be restarted.
This might sound far-fetched with input-addressed drvs, where we usually
basically have all our goals "planned out" before we start doing
anything, but with CA derivation goals and especially RFC 92, where *drv
resolution* means goals are created after some building is completed, it
is more likely to happen.
So the first thing to do was restore the clearing of `wantedOutputs` we
used to do, and then filter the outputs in `buildPathsWithResults` to
only get the ones we care about.
But fix also has its own side effect in that the `DerivedPath` in the
`BuildResult` in `DerivationGoal` cannot be trusted; it is merely the
*first* `DerivedPath` for which this goal was originally created.
To remedy this, I made `BuildResult` be like it was before, and instead
made `KeyedBuildResult` be a subclass wit the path. Only
`buildPathsWithResults` returns `KeyedBuildResult`s, everything else
just becomes like it was before, where the "key" is unambiguous from
context.
I think separating the "primary key" field(s) from the other fields is
good practical in general anyways. (I would like to do the same thing
for `ValidPathInfo`.) Among other things, it allows constructions like
`std::map<Key, ThingWithKey>` where doesn't contain duplicate keys and
just precludes the possibility of those duplicate keys being out of
sync.
We might leverage the above someday to overload `buildPathsWithResults`
to take a *set* of return a *map* per the above.
-----
Unfortunately, we need to avoid C++20 strictness on designated
initializers.
(BTW
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2287r1.html
this offers some new syntax for this use-case. Hopefully this will be
adopted and we can eventually use it.)
No having that yet, maybe it would be better to not make
`KeyedBuildResult` a subclass to just avoid this.
Co-authored-by: Robert Hensing <roberth@users.noreply.github.com>
2022-03-25 03:26:07 +02:00
|
|
|
return goal->getBuildResult(DerivedPath::Built {
|
|
|
|
.drvPath = drvPath,
|
|
|
|
.outputs = OutputsSpec::All {},
|
|
|
|
});
|
Allow remote builds without sending the derivation closure
Previously, to build a derivation remotely, we had to copy the entire
closure of the .drv file to the remote machine, even though we only
need the top-level derivation. This is very wasteful: the closure can
contain thousands of store paths, and in some Hydra use cases, include
source paths that are very large (e.g. Git/Mercurial checkouts).
So now there is a new operation, StoreAPI::buildDerivation(), that
performs a build from an in-memory representation of a derivation
(BasicDerivation) rather than from a on-disk .drv file. The only files
that need to be in the Nix store are the sources of the derivation
(drv.inputSrcs), and the needed output paths of the dependencies (as
described by drv.inputDrvs). "nix-store --serve" exposes this
interface.
Note that this is a privileged operation, because you can construct a
derivation that builds any store path whatsoever. Fixing this will
require changing the hashing scheme (i.e., the output paths should be
computed from the other fields in BasicDerivation, allowing them to be
verified without access to other derivations). However, this would be
quite nice because it would allow .drv-free building (e.g. "nix-env
-i" wouldn't have to write any .drv files to disk).
Fixes #173.
2015-07-17 18:57:40 +03:00
|
|
|
} catch (Error & e) {
|
2022-03-09 13:25:35 +02:00
|
|
|
return BuildResult {
|
|
|
|
.status = BuildResult::MiscFailure,
|
|
|
|
.errorMsg = e.msg(),
|
|
|
|
};
|
|
|
|
};
|
Allow remote builds without sending the derivation closure
Previously, to build a derivation remotely, we had to copy the entire
closure of the .drv file to the remote machine, even though we only
need the top-level derivation. This is very wasteful: the closure can
contain thousands of store paths, and in some Hydra use cases, include
source paths that are very large (e.g. Git/Mercurial checkouts).
So now there is a new operation, StoreAPI::buildDerivation(), that
performs a build from an in-memory representation of a derivation
(BasicDerivation) rather than from a on-disk .drv file. The only files
that need to be in the Nix store are the sources of the derivation
(drv.inputSrcs), and the needed output paths of the dependencies (as
described by drv.inputDrvs). "nix-store --serve" exposes this
interface.
Note that this is a privileged operation, because you can construct a
derivation that builds any store path whatsoever. Fixing this will
require changing the hashing scheme (i.e., the output paths should be
computed from the other fields in BasicDerivation, allowing them to be
verified without access to other derivations). However, this would be
quite nice because it would allow .drv-free building (e.g. "nix-env
-i" wouldn't have to write any .drv files to disk).
Fixes #173.
2015-07-17 18:57:40 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-12-20 19:54:57 +02:00
|
|
|
void Store::ensurePath(const StorePath & path)
|
2003-07-20 22:29:38 +03:00
|
|
|
{
|
2004-06-18 21:09:32 +03:00
|
|
|
/* If the path is already valid, we're done. */
|
2008-06-09 16:52:45 +03:00
|
|
|
if (isValidPath(path)) return;
|
2004-06-18 21:09:32 +03:00
|
|
|
|
2021-07-19 16:43:08 +03:00
|
|
|
Worker worker(*this, *this);
|
2020-11-09 14:47:06 +02:00
|
|
|
GoalPtr goal = worker.makePathSubstitutionGoal(path);
|
2016-05-04 17:04:52 +03:00
|
|
|
Goals goals = {goal};
|
2005-02-23 13:19:27 +02:00
|
|
|
|
|
|
|
worker.run(goals);
|
|
|
|
|
2020-06-15 20:25:35 +03:00
|
|
|
if (goal->exitCode != Goal::ecSuccess) {
|
|
|
|
if (goal->ex) {
|
2023-06-22 21:23:25 +03:00
|
|
|
goal->ex->status = worker.failingExitStatus();
|
2022-12-07 13:58:58 +02:00
|
|
|
throw std::move(*goal->ex);
|
2020-06-15 20:25:35 +03:00
|
|
|
} else
|
2023-06-22 21:23:25 +03:00
|
|
|
throw Error(worker.failingExitStatus(), "path '%s' does not exist and cannot be created", printStorePath(path));
|
2020-06-15 20:25:35 +03:00
|
|
|
}
|
2003-07-20 22:29:38 +03:00
|
|
|
}
|
2006-09-05 00:06:23 +03:00
|
|
|
|
2012-07-27 16:59:18 +03:00
|
|
|
|
2023-04-13 17:38:35 +03:00
|
|
|
void Store::repairPath(const StorePath & path)
|
2012-10-02 21:08:59 +03:00
|
|
|
{
|
2021-07-19 16:43:08 +03:00
|
|
|
Worker worker(*this, *this);
|
2020-11-09 14:47:06 +02:00
|
|
|
GoalPtr goal = worker.makePathSubstitutionGoal(path, Repair);
|
2016-05-04 17:04:52 +03:00
|
|
|
Goals goals = {goal};
|
2012-10-02 21:08:59 +03:00
|
|
|
|
|
|
|
worker.run(goals);
|
|
|
|
|
2020-06-15 20:25:35 +03:00
|
|
|
if (goal->exitCode != Goal::ecSuccess) {
|
2016-01-06 23:07:59 +02:00
|
|
|
/* Since substituting the path didn't work, if we have a valid
|
|
|
|
deriver, then rebuild the deriver. */
|
2019-12-05 20:11:09 +02:00
|
|
|
auto info = queryPathInfo(path);
|
|
|
|
if (info->deriver && isValidPath(*info->deriver)) {
|
2016-01-06 23:07:59 +02:00
|
|
|
goals.clear();
|
2023-01-12 01:57:18 +02:00
|
|
|
// FIXME: Should just build the specific output we need.
|
|
|
|
goals.insert(worker.makeDerivationGoal(*info->deriver, OutputsSpec::All { }, bmRepair));
|
2016-01-06 23:07:59 +02:00
|
|
|
worker.run(goals);
|
|
|
|
} else
|
2023-06-22 21:23:25 +03:00
|
|
|
throw Error(worker.failingExitStatus(), "cannot repair path '%s'", printStorePath(path));
|
2016-01-06 23:07:59 +02:00
|
|
|
}
|
2012-10-02 21:08:59 +03:00
|
|
|
}
|
|
|
|
|
2006-09-05 00:06:23 +03:00
|
|
|
}
|