aboutsummaryrefslogtreecommitdiff
path: root/src/nix/profile.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/nix/profile.cc')
-rw-r--r--src/nix/profile.cc111
1 files changed, 93 insertions, 18 deletions
diff --git a/src/nix/profile.cc b/src/nix/profile.cc
index 4d275f577..96a20f673 100644
--- a/src/nix/profile.cc
+++ b/src/nix/profile.cc
@@ -12,6 +12,7 @@
#include <nlohmann/json.hpp>
#include <regex>
+#include <iomanip>
using namespace nix;
@@ -97,10 +98,8 @@ struct ProfileManifest
else if (pathExists(profile + "/manifest.nix")) {
// FIXME: needed because of pure mode; ugly.
- if (state.allowedPaths) {
- state.allowedPaths->insert(state.store->followLinksToStore(profile));
- state.allowedPaths->insert(state.store->followLinksToStore(profile + "/manifest.nix"));
- }
+ state.allowPath(state.store->followLinksToStore(profile));
+ state.allowPath(state.store->followLinksToStore(profile + "/manifest.nix"));
auto drvInfos = queryInstalled(state, state.store->followLinksToStore(profile));
@@ -233,7 +232,7 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
{
ProfileManifest manifest(*getEvalState(), *profile);
- std::vector<StorePathWithOutputs> pathsToBuild;
+ std::vector<DerivedPath> pathsToBuild;
for (auto & installable : installables) {
if (auto installable2 = std::dynamic_pointer_cast<InstallableFlake>(installable)) {
@@ -249,27 +248,30 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
attrPath,
};
- pathsToBuild.push_back({drv.drvPath, StringSet{drv.outputName}});
+ pathsToBuild.push_back(DerivedPath::Built{drv.drvPath, StringSet{drv.outputName}});
manifest.elements.emplace_back(std::move(element));
} else {
- auto buildables = build(store, Realise::Outputs, {installable}, bmNormal);
+ auto buildables = build(getEvalStore(), store, Realise::Outputs, {installable}, bmNormal);
for (auto & buildable : buildables) {
ProfileElement element;
std::visit(overloaded {
- [&](BuildableOpaque bo) {
- pathsToBuild.push_back({bo.path, {}});
+ [&](const BuiltPath::Opaque & bo) {
+ pathsToBuild.push_back(bo);
element.storePaths.insert(bo.path);
},
- [&](BuildableFromDrv bfd) {
+ [&](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({bfd.drvPath, {output.first}});
+ pathsToBuild.push_back(DerivedPath::Built{bfd.drvPath, {output.first}});
element.storePaths.insert(output.second);
}
},
- }, buildable);
+ }, buildable.raw());
manifest.elements.emplace_back(std::move(element));
}
@@ -388,7 +390,7 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf
auto matchers = getMatchers(store);
// FIXME: code duplication
- std::vector<StorePathWithOutputs> pathsToBuild;
+ std::vector<DerivedPath> pathsToBuild;
for (size_t i = 0; i < manifest.elements.size(); ++i) {
auto & element(manifest.elements[i]);
@@ -423,7 +425,7 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf
attrPath,
};
- pathsToBuild.push_back({drv.drvPath, StringSet{"out"}}); // FIXME
+ pathsToBuild.push_back(DerivedPath::Built{drv.drvPath, {drv.outputName}});
}
}
@@ -525,10 +527,11 @@ struct CmdProfileHistory : virtual StoreCommand, EvalCommand, MixDefaultProfile
if (!first) std::cout << "\n";
first = false;
- if (prevGen)
- std::cout << fmt("Version %d -> %d:\n", prevGen->first.number, gen.number);
- else
- std::cout << fmt("Version %d:\n", gen.number);
+ std::cout << fmt("Version %s%d" ANSI_NORMAL " (%s)%s:\n",
+ gen.number == curGen ? ANSI_GREEN : ANSI_BOLD,
+ gen.number,
+ std::put_time(std::gmtime(&gen.creationTime), "%Y-%m-%d"),
+ prevGen ? fmt(" <- %d", prevGen->first.number) : "");
ProfileManifest::printDiff(
prevGen ? prevGen->second : ProfileManifest(),
@@ -540,6 +543,76 @@ struct CmdProfileHistory : virtual StoreCommand, EvalCommand, MixDefaultProfile
}
};
+struct CmdProfileRollback : virtual StoreCommand, MixDefaultProfile, MixDryRun
+{
+ std::optional<GenerationNumber> version;
+
+ CmdProfileRollback()
+ {
+ addFlag({
+ .longName = "to",
+ .description = "The profile version to roll back to.",
+ .labels = {"version"},
+ .handler = {&version},
+ });
+ }
+
+ std::string description() override
+ {
+ return "roll back to the previous version or a specified version of a profile";
+ }
+
+ std::string doc() override
+ {
+ return
+ #include "profile-rollback.md"
+ ;
+ }
+
+ void run(ref<Store> store) override
+ {
+ switchGeneration(*profile, version, dryRun);
+ }
+};
+
+struct CmdProfileWipeHistory : virtual StoreCommand, MixDefaultProfile, MixDryRun
+{
+ std::optional<std::string> minAge;
+
+ CmdProfileWipeHistory()
+ {
+ addFlag({
+ .longName = "older-than",
+ .description =
+ "Delete versions older than the specified age. *age* "
+ "must be in the format *N*`d`, where *N* denotes a number "
+ "of days.",
+ .labels = {"age"},
+ .handler = {&minAge},
+ });
+ }
+
+ std::string description() override
+ {
+ return "delete non-current versions of a profile";
+ }
+
+ std::string doc() override
+ {
+ return
+ #include "profile-wipe-history.md"
+ ;
+ }
+
+ void run(ref<Store> store) override
+ {
+ if (minAge)
+ deleteGenerationsOlderThan(*profile, *minAge, dryRun);
+ else
+ deleteOldGenerations(*profile, dryRun);
+ }
+};
+
struct CmdProfile : NixMultiCommand
{
CmdProfile()
@@ -550,6 +623,8 @@ struct CmdProfile : NixMultiCommand
{"list", []() { return make_ref<CmdProfileList>(); }},
{"diff-closures", []() { return make_ref<CmdProfileDiffClosures>(); }},
{"history", []() { return make_ref<CmdProfileHistory>(); }},
+ {"rollback", []() { return make_ref<CmdProfileRollback>(); }},
+ {"wipe-history", []() { return make_ref<CmdProfileWipeHistory>(); }},
})
{ }