diff options
author | Eelco Dolstra <edolstra@gmail.com> | 2022-03-02 20:37:46 +0100 |
---|---|---|
committer | Eelco Dolstra <edolstra@gmail.com> | 2022-03-02 20:38:51 +0100 |
commit | 161f798aa13b56c5f71120a8cb5788409d9ab815 (patch) | |
tree | 5c3d00d365962c836ebd43595daa9b08ba0ab11b | |
parent | 54888b92ded6c242ce4914628553d8b2c9c55d10 (diff) |
nix profile: Support CA derivations
-rw-r--r-- | src/libcmd/installables.cc | 4 | ||||
-rw-r--r-- | src/libcmd/installables.hh | 1 | ||||
-rw-r--r-- | src/nix/profile.cc | 91 | ||||
-rw-r--r-- | tests/nix-profile.sh | 19 |
4 files changed, 64 insertions, 51 deletions
diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index b9afe5105..f18be5287 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -470,7 +470,6 @@ std::vector<InstallableValue::DerivationInfo> InstallableAttrPath::toDerivations for (auto & drvInfo : drvInfos) { res.push_back({ state->store->parseStorePath(drvInfo.queryDrvPath()), - state->store->maybeParseStorePath(drvInfo.queryOutPath()), drvInfo.queryOutputName() }); } @@ -584,9 +583,8 @@ std::tuple<std::string, FlakeRef, InstallableValue::DerivationInfo> InstallableF auto drvPath = attr->forceDerivation(); - auto drvInfo = DerivationInfo{ + auto drvInfo = DerivationInfo { std::move(drvPath), - state->store->maybeParseStorePath(attr->getAttr(state->sOutPath)->getString()), attr->getAttr(state->sOutputName)->getString() }; diff --git a/src/libcmd/installables.hh b/src/libcmd/installables.hh index f296434c5..e172b71b0 100644 --- a/src/libcmd/installables.hh +++ b/src/libcmd/installables.hh @@ -134,7 +134,6 @@ struct InstallableValue : Installable struct DerivationInfo { StorePath drvPath; - std::optional<StorePath> outPath; std::string outputName; }; diff --git a/src/nix/profile.cc b/src/nix/profile.cc index c1bf62357..48834d15b 100644 --- a/src/nix/profile.cc +++ b/src/nix/profile.cc @@ -61,6 +61,27 @@ struct ProfileElement { return std::tuple(describe(), storePaths) < std::tuple(other.describe(), other.storePaths); } + + void updateStorePaths(ref<Store> evalStore, ref<Store> store, Installable & installable) + { + // FIXME: respect meta.outputsToInstall + storePaths.clear(); + for (auto & buildable : getBuiltPaths(evalStore, store, installable.toDerivedPaths())) { + std::visit(overloaded { + [&](const BuiltPath::Opaque & bo) { + storePaths.insert(bo.path); + }, + [&](const BuiltPath::Built & bfd) { + // TODO: Why are we querying if we know the output + // names already? Is it just to figure out what the + // default one is? + for (auto & output : store->queryDerivationOutputMap(bfd.drvPath)) { + storePaths.insert(output.second); + } + }, + }, buildable.raw()); + } + } }; struct ProfileManifest @@ -232,54 +253,26 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile { ProfileManifest manifest(*getEvalState(), *profile); - std::vector<DerivedPath> pathsToBuild; + auto builtPaths = Installable::build(getEvalStore(), store, Realise::Outputs, installables, bmNormal); for (auto & installable : installables) { + ProfileElement element; + if (auto installable2 = std::dynamic_pointer_cast<InstallableFlake>(installable)) { + // FIXME: make build() return this? auto [attrPath, resolvedRef, drv] = installable2->toDerivation(); - - ProfileElement element; - if (!drv.outPath) - throw UnimplementedError("CA derivations are not yet supported by 'nix profile'"); - element.storePaths = {*drv.outPath}; // FIXME element.source = ProfileElementSource{ installable2->flakeRef, resolvedRef, attrPath, }; + } - pathsToBuild.push_back(DerivedPath::Built{drv.drvPath, StringSet{drv.outputName}}); + element.updateStorePaths(getEvalStore(), store, *installable); - manifest.elements.emplace_back(std::move(element)); - } else { - auto buildables = Installable::build(getEvalStore(), store, Realise::Outputs, {installable}, bmNormal); - - for (auto & buildable : buildables) { - ProfileElement element; - - std::visit(overloaded { - [&](const BuiltPath::Opaque & bo) { - pathsToBuild.push_back(bo); - element.storePaths.insert(bo.path); - }, - [&](const BuiltPath::Built & bfd) { - // TODO: Why are we querying if we know the output - // names already? Is it just to figure out what the - // default one is? - for (auto & output : store->queryDerivationOutputMap(bfd.drvPath)) { - pathsToBuild.push_back(DerivedPath::Built{bfd.drvPath, {output.first}}); - element.storePaths.insert(output.second); - } - }, - }, buildable.raw()); - - manifest.elements.emplace_back(std::move(element)); - } - } + manifest.elements.push_back(std::move(element)); } - store->buildPaths(pathsToBuild); - updateProfile(manifest.build(store)); } }; @@ -407,8 +400,8 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf auto matchers = getMatchers(store); - // FIXME: code duplication - std::vector<DerivedPath> pathsToBuild; + std::vector<std::shared_ptr<Installable>> installables; + std::vector<size_t> indices; auto upgradedCount = 0; @@ -423,32 +416,30 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf Activity act(*logger, lvlChatty, actUnknown, fmt("checking '%s' for updates", element.source->attrPath)); - InstallableFlake installable( + auto installable = std::make_shared<InstallableFlake>( this, getEvalState(), FlakeRef(element.source->originalRef), "", - {element.source->attrPath}, - {}, + Strings{element.source->attrPath}, + Strings{}, lockFlags); - auto [attrPath, resolvedRef, drv] = installable.toDerivation(); + auto [attrPath, resolvedRef, drv] = installable->toDerivation(); if (element.source->resolvedRef == resolvedRef) continue; printInfo("upgrading '%s' from flake '%s' to '%s'", element.source->attrPath, element.source->resolvedRef, resolvedRef); - if (!drv.outPath) - throw UnimplementedError("CA derivations are not yet supported by 'nix profile'"); - element.storePaths = {*drv.outPath}; // FIXME element.source = ProfileElementSource{ - installable.flakeRef, + installable->flakeRef, resolvedRef, attrPath, }; - pathsToBuild.push_back(DerivedPath::Built{drv.drvPath, {drv.outputName}}); + installables.push_back(installable); + indices.push_back(i); } } @@ -465,7 +456,13 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf warn ("Use 'nix profile list' to see the current profile."); } - store->buildPaths(pathsToBuild); + auto builtPaths = Installable::build(getEvalStore(), store, Realise::Outputs, installables, bmNormal); + + for (size_t i = 0; i < installables.size(); ++i) { + auto & installable = installables.at(i); + auto & element = manifest.elements[indices.at(i)]; + element.updateStorePaths(getEvalStore(), store, *installable); + } updateProfile(manifest.build(store)); } diff --git a/tests/nix-profile.sh b/tests/nix-profile.sh index f134d70a4..0ab69db22 100644 --- a/tests/nix-profile.sh +++ b/tests/nix-profile.sh @@ -22,7 +22,11 @@ cat > $flake1Dir/flake.nix <<EOF echo Hello \${builtins.readFile ./who} EOF chmod +x \$out/bin/hello + echo DONE ''; + __contentAddressed = import ./ca.nix; + outputHashMode = "recursive"; + outputHashAlgo = "sha256"; }; }; } @@ -30,6 +34,7 @@ EOF printf World > $flake1Dir/who printf 1.0 > $flake1Dir/version +printf false > $flake1Dir/ca.nix cp ./config.nix $flake1Dir/ @@ -66,3 +71,17 @@ nix profile diff-closures | grep 'Version 3 -> 4' # Test wipe-history. nix profile wipe-history [[ $(nix profile history | grep Version | wc -l) -eq 1 ]] + +# Test upgrade to CA package. +printf true > $flake1Dir/ca.nix +printf 3.0 > $flake1Dir/version +nix profile upgrade --extra-experimental-features ca-derivations 0 +nix profile history | grep "packages.$system.default: 1.0 -> 3.0" + +# Test new install of CA package. +nix profile remove 0 +printf 4.0 > $flake1Dir/version +printf Utrecht > $flake1Dir/who +nix profile install --extra-experimental-features ca-derivations $flake1Dir +[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello Utrecht" ]] +[[ $(nix path-info --json $(realpath $TEST_HOME/.nix-profile/bin/hello) | jq -r .[].ca) =~ fixed:r:sha256: ]] |