22#include " build/derivation-check.hh"
33#include " nix/store/globals.hh"
44#include " nix/store/local-store.hh"
5+ #include " nix/store/restricted-store.hh"
56#include " nix/store/path-references.hh"
67#include " nix/store/posix-fs-canonicalise.hh"
78#include " nix/util/archive.hh"
@@ -100,7 +101,7 @@ static void replaceValidPath(const std::filesystem::path & storePath, const std:
100101 deletePath (oldPath);
101102}
102103
103- SingleDrvOutputs DerivationBuilderImpl::registerOutputs ()
104+ SingleDrvOutputs DerivationBuilderImpl::registerOutputs (LocalStore & localStore )
104105{
105106 std::map<std::string, ValidPathInfo> infos;
106107
@@ -326,7 +327,7 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs()
326327 /* Put the temporary copy in a directory inaccessible to the builder.
327328 actualPath might point inside the build chroot, which is controlled
328329 by the derivation builder. */
329- auto [rewriteTempDir, rewriteTempDirFd] = store .createTempDirInStore ();
330+ auto [rewriteTempDir, rewriteTempDirFd] = localStore .createTempDirInStore ();
330331 AutoDelete delRewriteTempDir (rewriteTempDir);
331332 std::filesystem::path tmpPath = rewriteTempDir / " x" ;
332333 restorePath (tmpPath, *source);
@@ -410,7 +411,7 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs()
410411 }();
411412
412413 auto newInfo0 = ValidPathInfo::makeFromCA (
413- store ,
414+ storeDirConfig ,
414415 outputPathName (drv.name , outputName),
415416 ContentAddressWithReferences::fromParts (outputHash.method , std::move (got), rewriteRefs ()),
416417 Hash::dummy);
@@ -438,15 +439,15 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs()
438439
439440 auto moveOutputToTempDir = [&]() -> void {
440441 std::filesystem::path tempDir;
441- std::tie (tempDir, tempDirFd) = store .createTempDirInStore ();
442+ std::tie (tempDir, tempDirFd) = localStore .createTempDirInStore ();
442443 delTempDir = AutoDelete (tempDir);
443444
444445 auto tmpOutput = tempDir / " x" ;
445446
446447 /* Copy files to break stale file descriptors. copyRecursive below will use
447448 reflinking to optimise the copying overhead. */
448449 auto pathAccessor = makeFSSourceAccessor (actualPath);
449- RestoreSink restoreSink{store. config ->getLocalSettings ().fsyncStorePaths };
450+ RestoreSink restoreSink{store->getLocalSettings ().fsyncStorePaths };
450451 restoreSink.dstPath = tmpOutput;
451452 copyRecursive (*pathAccessor, CanonPath::root, restoreSink, CanonPath::root);
452453 /* This makes it slightly harder to make sense of the control flow. The rule
@@ -471,7 +472,7 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs()
471472 {makeFSSourceAccessor (actualPath), CanonPath::root},
472473 FileSerialisationMethod::NixArchive,
473474 HashAlgorithm::SHA256 );
474- ValidPathInfo newInfo0{requiredFinalPath, {store , narHashAndSize.hash }};
475+ ValidPathInfo newInfo0{requiredFinalPath, {storeDirConfig , narHashAndSize.hash }};
475476 newInfo0.narSize = narHashAndSize.numBytesDigested ;
476477 auto refs = rewriteRefs ();
477478 newInfo0.references = std::move (refs.others );
@@ -532,44 +533,44 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs()
532533 derivations. */
533534 PathLocks dynamicOutputLock;
534535 dynamicOutputLock.setDeletion (true );
535- auto optFixedPath = output->path (store , drv.name , outputName);
536+ auto optFixedPath = output->path (storeDirConfig , drv.name , outputName);
536537 if (!optFixedPath || storeDirConfig.printStorePath (*optFixedPath) != finalDestPath) {
537538 assert (newInfo.ca );
538539
539540 /* Don't wait on lock for the hash-mismatching fixed-output
540541 derivation case, to avoid a deadlock in the case where a build
541542 with the correct hash is in progress. */
542- bool locked = dynamicOutputLock.lockPaths ({store. toRealPath (newInfo.path )}, " " , !optFixedPath);
543+ bool locked = dynamicOutputLock.lockPaths ({store-> toRealPath (newInfo.path )}, " " , !optFixedPath);
543544
544545 /* If we can't lock the correct path, clean up and bail now. */
545546 if (!locked) {
546547 debug (
547548 " failed to lock correct output path of %s, namely %s, not moving output" ,
548549 storeDirConfig.printStorePath (drvPath),
549- PathFmt (store. toRealPath (newInfo.path )));
550+ PathFmt (store-> toRealPath (newInfo.path )));
550551 deletePath (actualPath);
551552 /* Trigger the hash-mismatch error. */
552- checkCAOutput (store , drvPath, *output, newInfo, outputName);
553+ checkCAOutput (storeDirConfig , drvPath, *output, newInfo, outputName);
553554 unreachable ();
554555 }
555556 }
556557
557558 /* Move files, if needed */
558- if (store. toRealPath (newInfo.path ) != actualPath) {
559+ if (store-> toRealPath (newInfo.path ) != actualPath) {
559560 if (buildMode == bmRepair) {
560561 /* Path already exists, need to replace it */
561- replaceValidPath (store. toRealPath (newInfo.path ), actualPath);
562+ replaceValidPath (store-> toRealPath (newInfo.path ), actualPath);
562563 } else if (buildMode == bmCheck) {
563564 /* Path already exists, and we want to compare, so we leave out
564565 new path in place. */
565- } else if (store .isValidPath (newInfo.path )) {
566+ } else if (localStore .isValidPath (newInfo.path )) {
566567 /* Path already exists because CA path produced by something
567568 else. No moving needed. */
568569 assert (newInfo.ca );
569570 /* Can delete our scratch copy now. */
570571 deletePath (actualPath);
571572 } else {
572- auto destPath = store. toRealPath (newInfo.path );
573+ auto destPath = store-> toRealPath (newInfo.path );
573574 deletePath (destPath);
574575 movePath (actualPath, destPath);
575576 }
@@ -578,12 +579,12 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs()
578579 if (buildMode == bmCheck) {
579580 /* Check against already registered outputs */
580581
581- if (store .isValidPath (newInfo.path )) {
582- ValidPathInfo oldInfo (*store .queryPathInfo (newInfo.path ));
582+ if (localStore .isValidPath (newInfo.path )) {
583+ ValidPathInfo oldInfo (*localStore .queryPathInfo (newInfo.path ));
583584 if (newInfo.narHash != oldInfo.narHash ) {
584585 auto * diffHook = localSettings.getDiffHook ();
585586 if (diffHook || settings.keepFailed ) {
586- auto dst = store. toRealPath (newInfo.path );
587+ auto dst = store-> toRealPath (newInfo.path );
587588 dst += " .check" ;
588589 deletePath (dst);
589590 movePath (actualPath, dst);
@@ -604,20 +605,20 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs()
604605 throw NotDeterministic (
605606 " derivation '%s' may not be deterministic: output %s differs from %s" ,
606607 storeDirConfig.printStorePath (drvPath),
607- PathFmt (store. toRealPath (newInfo.path )),
608+ PathFmt (store-> toRealPath (newInfo.path )),
608609 PathFmt (dst));
609610 } else
610611 throw NotDeterministic (
611612 " derivation '%s' may not be deterministic: output %s differs" ,
612613 storeDirConfig.printStorePath (drvPath),
613- PathFmt (store. toRealPath (newInfo.path )));
614+ PathFmt (store-> toRealPath (newInfo.path )));
614615 }
615616
616617 /* Since we verified the build, it's now ultimately trusted. */
617618 if (!oldInfo.ultimate ) {
618619 oldInfo.ultimate = true ;
619- store .signPathInfo (oldInfo);
620- store .registerValidPaths ({{oldInfo.path , oldInfo}});
620+ localStore .signPathInfo (oldInfo);
621+ localStore .registerValidPaths ({{oldInfo.path , oldInfo}});
621622 }
622623 }
623624 } else {
@@ -631,12 +632,13 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs()
631632 debug (" unreferenced input: '%1%'" , storeDirConfig.printStorePath (i));
632633 }
633634
634- if (!store.isValidPath (newInfo.path ))
635- store.optimisePath (store.toRealPath (newInfo.path ), NoRepair); // FIXME: combine with scanForReferences()
635+ if (!localStore.isValidPath (newInfo.path ))
636+ localStore.optimisePath (
637+ store->toRealPath (newInfo.path ), NoRepair); // FIXME: combine with scanForReferences()
636638
637639 newInfo.deriver = drvPath;
638640 newInfo.ultimate = true ;
639- store .signPathInfo (newInfo);
641+ localStore .signPathInfo (newInfo);
640642
641643 finish (newInfo.path );
642644
@@ -651,7 +653,7 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs()
651653 possibly quite slow thing it was) doesn't have to be done
652654 again. */
653655 if (newInfo.ca )
654- store .registerValidPaths ({{newInfo.path , newInfo}});
656+ localStore .registerValidPaths ({{newInfo.path , newInfo}});
655657 }
656658
657659 /* Do this in both the check and non-check cases, because we
@@ -662,7 +664,7 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs()
662664
663665 /* Apply output checks. This includes checking of the wanted vs got
664666 hash of fixed-outputs. */
665- checkOutputs (store , drvPath, drv, drvOptions.outputChecks , infos);
667+ checkOutputs (localStore , drvPath, drv, drvOptions.outputChecks , infos);
666668
667669 if (buildMode == bmCheck) {
668670 return {};
@@ -676,7 +678,7 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs()
676678 for (auto & [outputName, newInfo] : infos) {
677679 infos2.insert_or_assign (newInfo.path , newInfo);
678680 }
679- store .registerValidPaths (infos2);
681+ localStore .registerValidPaths (infos2);
680682 }
681683
682684 /* If we made it this far, we are sure the output matches the
@@ -699,16 +701,16 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs()
699701 },
700702 };
701703 if (experimentalFeatureSettings.isEnabled (Xp::CaDerivations) && !type (drv).isImpure ()) {
702- store .signRealisation (thisRealisation);
703- store .registerDrvOutput (thisRealisation, NoCheckSigs);
704+ localStore .signRealisation (thisRealisation);
705+ localStore .registerDrvOutput (thisRealisation, NoCheckSigs);
704706 }
705707 builtOutputs.emplace (outputName, thisRealisation);
706708 }
707709
708710 return builtOutputs;
709711}
710712
711- SingleDrvOutputs DerivationBuilderImpl::checkSubmittedOutputs ()
713+ SingleDrvOutputs DerivationBuilderImpl::checkSubmittedOutputs (LocalStore & localStore )
712714{
713715 // Submitted outputs from the recursive nix daemon
714716 // It's fine to lock here since all other threads with the reference have been shut down.
@@ -719,12 +721,12 @@ SingleDrvOutputs DerivationBuilderImpl::checkSubmittedOutputs()
719721 std::map<std::string, ValidPathInfo> infos;
720722
721723 for (auto & [outputName, outputPath] : *submittedOutputs) {
722- infos.emplace (outputName, *store .queryPathInfo (outputPath));
724+ infos.emplace (outputName, *localStore .queryPathInfo (outputPath));
723725 }
724726
725727 // checkOutputs only performs checks that make sense for both submitting and non-submitting derivations,
726728 // more verification steps needed afterward
727- checkOutputs (store , drvPath, drv, drvOptions.outputChecks , infos);
729+ checkOutputs (localStore , drvPath, drv, drvOptions.outputChecks , infos);
728730
729731 for (auto & [outputName, output] : drv.outputs ) {
730732 // For some reason cannot be moved to checkOutputs, needs debugging
@@ -754,8 +756,8 @@ SingleDrvOutputs DerivationBuilderImpl::checkSubmittedOutputs()
754756 },
755757 };
756758
757- store .signRealisation (realisation);
758- store .registerDrvOutput (realisation, NoCheckSigs);
759+ localStore .signRealisation (realisation);
760+ localStore .registerDrvOutput (realisation, NoCheckSigs);
759761 builtOutputs.emplace (outputName, realisation);
760762
761763 // TODO: handle --check
@@ -764,4 +766,55 @@ SingleDrvOutputs DerivationBuilderImpl::checkSubmittedOutputs()
764766 return builtOutputs;
765767}
766768
769+ BuildingStore::~BuildingStore () = default ;
770+
771+ namespace {
772+
773+ struct LocalBuildingStore : BuildingStore
774+ {
775+ LocalStore & localStore;
776+
777+ LocalBuildingStore (LocalStore & localStore)
778+ : BuildingStore{localStore.storeDir }
779+ , localStore{localStore}
780+ {
781+ }
782+
783+ std::filesystem::path getRealStoreDir () const override
784+ {
785+ return localStore.config ->realStoreDir .get ();
786+ }
787+
788+ std::filesystem::path getBuildDir () const override
789+ {
790+ return localStore.config ->getBuildDir ();
791+ }
792+
793+ const LocalSettings & getLocalSettings () const override
794+ {
795+ return localStore.config ->getLocalSettings ();
796+ }
797+
798+ ref<Store> makeRecursiveNixStore (RestrictionContext & ctx) override
799+ {
800+ return makeRestrictedStore (
801+ [&] {
802+ auto config = make_ref<LocalStore::Config>(*localStore.config );
803+ config->pathInfoCacheSize = 0 ;
804+ config->stateDir = " /no-such-path" ;
805+ config->logDir = " /no-such-path" ;
806+ return config;
807+ }(),
808+ ref<LocalStore>(std::dynamic_pointer_cast<LocalStore>(localStore.shared_from_this ())),
809+ ctx);
810+ }
811+ };
812+
813+ } // namespace
814+
815+ std::unique_ptr<BuildingStore> makeBuildingStoreFromLocalStore (LocalStore & localStore)
816+ {
817+ return std::make_unique<LocalBuildingStore>(localStore);
818+ }
819+
767820} // namespace nix
0 commit comments