Skip to content

Commit 1bb9f30

Browse files
Ericson2314amaanq
authored andcommitted
Make DerivationBuilder not require a Store
The hope is to make `DerivationBuilder` easier to use with much less of libnixstore.
1 parent 8f239c4 commit 1bb9f30

18 files changed

Lines changed: 229 additions & 121 deletions

src/libstore/build/derivation-builder-impl.cc

Lines changed: 82 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
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,13 +701,64 @@ 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

713+
BuildingStore::~BuildingStore() = default;
714+
715+
namespace {
716+
717+
struct LocalBuildingStore : BuildingStore
718+
{
719+
LocalStore & localStore;
720+
721+
LocalBuildingStore(LocalStore & localStore)
722+
: BuildingStore{localStore.storeDir}
723+
, localStore{localStore}
724+
{
725+
}
726+
727+
std::filesystem::path getRealStoreDir() const override
728+
{
729+
return localStore.config->realStoreDir.get();
730+
}
731+
732+
std::filesystem::path getBuildDir() const override
733+
{
734+
return localStore.config->getBuildDir();
735+
}
736+
737+
const LocalSettings & getLocalSettings() const override
738+
{
739+
return localStore.config->getLocalSettings();
740+
}
741+
742+
ref<Store> makeRecursiveNixStore(RestrictionContext & ctx) override
743+
{
744+
return makeRestrictedStore(
745+
[&] {
746+
auto config = make_ref<LocalStore::Config>(*localStore.config);
747+
config->pathInfoCacheSize = 0;
748+
config->stateDir = "/no-such-path";
749+
config->logDir = "/no-such-path";
750+
return config;
751+
}(),
752+
ref<LocalStore>(std::dynamic_pointer_cast<LocalStore>(localStore.shared_from_this())),
753+
ctx);
754+
}
755+
};
756+
757+
} // namespace
758+
759+
std::unique_ptr<BuildingStore> makeBuildingStoreFromLocalStore(LocalStore & localStore)
760+
{
761+
return std::make_unique<LocalBuildingStore>(localStore);
762+
}
763+
711764
} // namespace nix

src/libstore/build/derivation-builder-impl.hh

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ protected:
3535
*/
3636
Pid pid;
3737

38-
LocalStore & store;
38+
std::unique_ptr<BuildingStore> store;
3939

4040
/**
4141
* Just the store layout, for FFI: a `StoreDirConfig` can be made
@@ -57,7 +57,7 @@ protected:
5757
*/
5858
const derivation::Type derivationType;
5959

60-
const LocalSettings & localSettings = store.config->getLocalSettings();
60+
const LocalSettings & localSettings = store->getLocalSettings();
6161

6262
#ifndef _WIN32
6363
/**
@@ -97,25 +97,27 @@ protected:
9797
*/
9898
virtual std::filesystem::path realPathInHost(const std::filesystem::path & p)
9999
{
100-
return store.toRealPath(storeDirConfig.parseStorePath(p.string()));
100+
return store->toRealPath(storeDirConfig.parseStorePath(p.string()));
101101
}
102102

103103

104104
public:
105105

106106
DerivationBuilderImpl(
107-
LocalStore & store, std::shared_ptr<DerivationBuilderCallbacks> miscMethods, DerivationBuilderParams params)
107+
std::unique_ptr<BuildingStore> store,
108+
std::shared_ptr<DerivationBuilderCallbacks> miscMethods,
109+
DerivationBuilderParams params)
108110
: DerivationBuilderParams{std::move(params)}
109-
, store{store}
110-
, storeDirConfig{*store.config}
111+
, store{std::move(store)}
112+
, storeDirConfig{*this->store}
111113
, miscMethods{std::move(miscMethods)}
112114
, derivationType{derivation::type(drv)}
113115
{
114116
}
115117

116118
public:
117119

118-
SingleDrvOutputs registerOutputs() override;
120+
SingleDrvOutputs registerOutputs(LocalStore & localStore) override;
119121
};
120122

121123
} // namespace nix

src/libstore/build/derivation-building-goal.cc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -967,13 +967,13 @@ Goal::Co DerivationBuildingGoal::buildLocally(
967967
throw UnimplementedError("external builders are not yet supported on Windows")
968968
#else
969969
makeExternalDerivationBuilder(
970-
localBuildCap.localStore,
970+
makeBuildingStoreFromLocalStore(localBuildCap.localStore),
971971
std::make_shared<DerivationBuildingGoalCallbacks>(*this, openLogFile, closeLogFile),
972972
std::move(params),
973973
*localBuildCap.externalBuilder)
974974
#endif
975975
: makeDerivationBuilder(
976-
localBuildCap.localStore,
976+
makeBuildingStoreFromLocalStore(localBuildCap.localStore),
977977
std::make_shared<DerivationBuildingGoalCallbacks>(*this, openLogFile, closeLogFile),
978978
std::move(params)
979979
#ifdef _WIN32
@@ -1051,7 +1051,9 @@ Goal::Co DerivationBuildingGoal::buildLocally(
10511051
try {
10521052
/* Compute the FS closure of the outputs and register them as
10531053
being valid. */
1054-
builtOutputs = builder->registerOutputs();
1054+
auto * localStoreP = dynamic_cast<LocalStore *>(&worker.store);
1055+
assert(localStoreP);
1056+
builtOutputs = builder->registerOutputs(*localStoreP);
10551057
builder->cleanupBuild(true);
10561058
} catch (BuilderFailureError & e) {
10571059
builder.reset();

src/libstore/build/derivation-check.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
namespace nix {
1111

1212
void checkCAOutput(
13-
StoreDirConfig & store,
13+
const StoreDirConfig & store,
1414
const StorePath & drvPath,
1515
const DerivationOutput & outputSpec,
1616
const ValidPathInfo & info,

src/libstore/build/derivation-check.hh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace nix {
1313
* Do nothing if outputSpec is not a CAFixed or CAFloating output.
1414
*/
1515
void checkCAOutput(
16-
StoreDirConfig & store,
16+
const StoreDirConfig & store,
1717
const StorePath & drvPath,
1818
const DerivationOutput & outputSpec,
1919
const ValidPathInfo & info,

src/libstore/darwin/build/darwin-derivation-builder.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ void DarwinDerivationBuilder::setUser()
7777

7878
/* Violations will go to the syslog if you set this. Unfortunately the destination does not appear to be
7979
* configurable */
80-
if (store.config->getLocalSettings().darwinLogSandboxViolations) {
80+
if (store->getLocalSettings().darwinLogSandboxViolations) {
8181
sandboxProfile += "(deny default)\n";
8282
} else {
8383
sandboxProfile += "(deny default (with no-log))\n";

src/libstore/darwin/build/darwin-derivation-builder.hh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ struct DarwinDerivationBuilder : UnixDerivationBuilderImpl
1515
bool useSandbox;
1616

1717
DarwinDerivationBuilder(
18-
LocalStore & store,
18+
std::unique_ptr<BuildingStore> store,
1919
std::shared_ptr<DerivationBuilderCallbacks> miscMethods,
2020
DerivationBuilderParams params,
2121
bool useSandbox)
22-
: UnixDerivationBuilderImpl(store, miscMethods, std::move(params))
22+
: UnixDerivationBuilderImpl(std::move(store), std::move(miscMethods), std::move(params))
2323
, useSandbox(useSandbox)
2424
{
2525
}

0 commit comments

Comments
 (0)