aboutsummaryrefslogtreecommitdiff
path: root/src/libstore
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2021-09-14 19:05:28 +0200
committerEelco Dolstra <edolstra@gmail.com>2021-09-14 19:32:33 +0200
commit817562e6946fa44c253beb76a36d85b55fd9c14d (patch)
tree9259231b8a4eebd81344a8f323d8737ef2c7f0f9 /src/libstore
parent1fbaf367292a8eb57a120f74daacabccce622f2f (diff)
Add "nix profile rollback" command
Diffstat (limited to 'src/libstore')
-rw-r--r--src/libstore/profiles.cc31
-rw-r--r--src/libstore/profiles.hh9
2 files changed, 39 insertions, 1 deletions
diff --git a/src/libstore/profiles.cc b/src/libstore/profiles.cc
index 84a21c0ba..9959da535 100644
--- a/src/libstore/profiles.cc
+++ b/src/libstore/profiles.cc
@@ -236,6 +236,37 @@ void switchLink(Path link, Path target)
}
+void switchGeneration(
+ const Path & profile,
+ std::optional<GenerationNumber> dstGen,
+ bool dryRun)
+{
+ PathLocks lock;
+ lockProfile(lock, profile);
+
+ auto [gens, curGen] = findGenerations(profile);
+
+ std::optional<Generation> dst;
+ for (auto & i : gens)
+ if ((!dstGen && i.number < curGen) ||
+ (dstGen && i.number == *dstGen))
+ dst = i;
+
+ if (!dst) {
+ if (dstGen)
+ throw Error("generation %1% does not exist", *dstGen);
+ else
+ throw Error("no generation older than the current (%1%) exists", curGen.value_or(0));
+ }
+
+ notice("switching from generation %d to %d", curGen.value_or(0), dst->number);
+
+ if (dryRun) return;
+
+ switchLink(profile, dst->path);
+}
+
+
void lockProfile(PathLocks & lock, const Path & profile)
{
lock.lockPaths({profile}, (format("waiting for lock on profile '%1%'") % profile).str());
diff --git a/src/libstore/profiles.hh b/src/libstore/profiles.hh
index be55a65d4..d100c970c 100644
--- a/src/libstore/profiles.hh
+++ b/src/libstore/profiles.hh
@@ -11,7 +11,7 @@ namespace nix {
class StorePath;
-typedef unsigned int GenerationNumber;
+typedef uint64_t GenerationNumber;
struct Generation
{
@@ -46,6 +46,13 @@ void deleteGenerationsOlderThan(const Path & profile, const string & timeSpec, b
void switchLink(Path link, Path target);
+/* Roll back a profile to the specified generation, or to the most
+ recent one older than the current. */
+void switchGeneration(
+ const Path & profile,
+ std::optional<GenerationNumber> dstGen,
+ bool dryRun);
+
/* Ensure exclusive access to a profile. Any command that modifies
the profile first acquires this lock. */
void lockProfile(PathLocks & lock, const Path & profile);