@@ -240,7 +240,7 @@ class Worker
240240 ~Worker ();
241241
242242 /* Make a goal (with caching). */
243- GoalPtr makeDerivationGoal (const Path & drvPath, bool repair = false );
243+ GoalPtr makeDerivationGoal (const Path & drvPath, const StringSet & wantedOutputs, bool repair = false );
244244 GoalPtr makeSubstitutionGoal (const Path & storePath, bool repair = false );
245245
246246 /* Remove a dead goal. */
@@ -756,6 +756,13 @@ class DerivationGoal : public Goal
756756 /* The path of the derivation. */
757757 Path drvPath;
758758
759+ /* The specific outputs that we need to build. Empty means all of
760+ them. */
761+ StringSet wantedOutputs;
762+
763+ /* Whether additional wanted outputs have been added. */
764+ bool needRestart;
765+
759766 /* The derivation stored at drvPath. */
760767 Derivation drv;
761768
@@ -831,7 +838,7 @@ class DerivationGoal : public Goal
831838 const static int childSetupFailed = 189 ;
832839
833840public:
834- DerivationGoal (const Path & drvPath, Worker & worker, bool repair = false );
841+ DerivationGoal (const Path & drvPath, const StringSet & wantedOutputs, Worker & worker, bool repair = false );
835842 ~DerivationGoal ();
836843
837844 void cancel ();
@@ -843,6 +850,9 @@ class DerivationGoal : public Goal
843850 return drvPath;
844851 }
845852
853+ /* Add wanted outputs to an already existing derivation goal. */
854+ void addWantedOutputs (const StringSet & outputs);
855+
846856private:
847857 /* The states. */
848858 void init ();
@@ -897,8 +907,10 @@ class DerivationGoal : public Goal
897907};
898908
899909
900- DerivationGoal::DerivationGoal (const Path & drvPath, Worker & worker, bool repair)
910+ DerivationGoal::DerivationGoal (const Path & drvPath, const StringSet & wantedOutputs, Worker & worker, bool repair)
901911 : Goal(worker)
912+ , wantedOutputs(wantedOutputs)
913+ , needRestart(false )
902914 , fLogFile (0 )
903915 , bzLogFile(0 )
904916 , useChroot(false )
@@ -967,6 +979,23 @@ void DerivationGoal::work()
967979}
968980
969981
982+ void DerivationGoal::addWantedOutputs (const StringSet & outputs)
983+ {
984+ /* If we already want all outputs, there is nothing to do. */
985+ if (wantedOutputs.empty ()) return ;
986+
987+ if (outputs.empty ()) {
988+ wantedOutputs.clear ();
989+ needRestart = true ;
990+ } else
991+ foreach (StringSet::const_iterator, i, outputs)
992+ if (wantedOutputs.find (*i) == wantedOutputs.end ()) {
993+ wantedOutputs.insert (*i);
994+ needRestart = true ;
995+ }
996+ }
997+
998+
970999void DerivationGoal::init ()
9711000{
9721001 trace (" init" );
@@ -1043,6 +1072,12 @@ void DerivationGoal::outputsSubstituted()
10431072
10441073 nrFailed = nrNoSubstituters = 0 ;
10451074
1075+ if (needRestart) {
1076+ needRestart = false ;
1077+ haveDerivation ();
1078+ return ;
1079+ }
1080+
10461081 if (checkPathValidity (false , repair).size () == 0 ) {
10471082 if (repair) repairClosure (); else amDone (ecSuccess);
10481083 return ;
@@ -1051,9 +1086,13 @@ void DerivationGoal::outputsSubstituted()
10511086 /* Otherwise, at least one of the output paths could not be
10521087 produced using a substitute. So we have to build instead. */
10531088
1089+ /* Make sure checkPathValidity() from now on checks all
1090+ outputs. */
1091+ wantedOutputs = PathSet ();
1092+
10541093 /* The inputs must be built before we can build this goal. */
10551094 foreach (DerivationInputs::iterator, i, drv.inputDrvs )
1056- addWaitee (worker.makeDerivationGoal (i->first , repair));
1095+ addWaitee (worker.makeDerivationGoal (i->first , i-> second , repair));
10571096
10581097 foreach (PathSet::iterator, i, drv.inputSrcs )
10591098 addWaitee (worker.makeSubstitutionGoal (*i));
@@ -1103,7 +1142,7 @@ void DerivationGoal::repairClosure()
11031142 if (drvPath2 == " " )
11041143 addWaitee (worker.makeSubstitutionGoal (*i, true ));
11051144 else
1106- addWaitee (worker.makeDerivationGoal (drvPath2, true ));
1145+ addWaitee (worker.makeDerivationGoal (drvPath2, PathSet (), true ));
11071146 }
11081147
11091148 if (waitees.empty ()) {
@@ -2385,6 +2424,7 @@ PathSet DerivationGoal::checkPathValidity(bool returnValid, bool checkHash)
23852424{
23862425 PathSet result;
23872426 foreach (DerivationOutputs::iterator, i, drv.outputs ) {
2427+ if (!wantOutput (i->first , wantedOutputs)) continue ;
23882428 bool good =
23892429 worker.store .isValidPath (i->second .path ) &&
23902430 (!checkHash || worker.store .pathContentsGood (i->second .path ));
@@ -2851,14 +2891,15 @@ Worker::~Worker()
28512891}
28522892
28532893
2854- GoalPtr Worker::makeDerivationGoal (const Path & path, bool repair)
2894+ GoalPtr Worker::makeDerivationGoal (const Path & path, const StringSet & wantedOutputs, bool repair)
28552895{
28562896 GoalPtr goal = derivationGoals[path].lock ();
28572897 if (!goal) {
2858- goal = GoalPtr (new DerivationGoal (path, *this , repair));
2898+ goal = GoalPtr (new DerivationGoal (path, wantedOutputs, *this , repair));
28592899 derivationGoals[path] = goal;
28602900 wakeUp (goal);
2861- }
2901+ } else
2902+ (dynamic_cast <DerivationGoal *>(goal.get ()))->addWantedOutputs (wantedOutputs);
28622903 return goal;
28632904}
28642905
@@ -3200,7 +3241,7 @@ void LocalStore::buildPaths(const PathSet & drvPaths, bool repair)
32003241 foreach (PathSet::const_iterator, i, drvPaths) {
32013242 DrvPathWithOutputs i2 = parseDrvPathWithOutputs (*i);
32023243 if (isDerivation (i2.first ))
3203- goals.insert (worker.makeDerivationGoal (i2.first , repair));
3244+ goals.insert (worker.makeDerivationGoal (i2.first , i2. second , repair));
32043245 else
32053246 goals.insert (worker.makeSubstitutionGoal (*i, repair));
32063247 }
0 commit comments