aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2022-03-02 20:37:46 +0100
committerEelco Dolstra <edolstra@gmail.com>2022-03-02 20:38:51 +0100
commit161f798aa13b56c5f71120a8cb5788409d9ab815 (patch)
tree5c3d00d365962c836ebd43595daa9b08ba0ab11b
parent54888b92ded6c242ce4914628553d8b2c9c55d10 (diff)
nix profile: Support CA derivations
-rw-r--r--src/libcmd/installables.cc4
-rw-r--r--src/libcmd/installables.hh1
-rw-r--r--src/nix/profile.cc91
-rw-r--r--tests/nix-profile.sh19
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: ]]