* A command `--switch-generation' to switch to a specific generation

of the current profile, e.g.,

    $ nix-env --list-generations
    ...
    39   2004-02-02 17:53:53
    40   2004-02-02 17:55:18
    41   2004-02-02 17:55:41
    42   2004-02-02 17:55:50   (current)

    $ nix-env --switch-generation 39

    $ ls -l /nix/var/nix/profiles/default
    ... default -> default-39-link

* Also a command `--rollback' which is just a convenience operation to
  rollback to the oldest generation younger than the current one.

  Note that generations properly form a tree.  E.g., if after
  switching to generation 39, we perform an installation action,
  a generation 43 is created which is a descendant of 39, not 42.  So
  a rollback from 43 ought to go back to 39.  This is not currently
  implemented; generations form a linear sequence.
This commit is contained in:
Eelco Dolstra 2004-02-08 14:07:43 +00:00
parent b8675aee54
commit 06a75a7e0c
3 changed files with 71 additions and 0 deletions

View File

@ -13,6 +13,10 @@ The previous operations take a list of derivation names. The special
name `*' may be used to indicate all derivations. name `*' may be used to indicate all derivations.
--switch-profile / -S [FILE]: switch to specified profile --switch-profile / -S [FILE]: switch to specified profile
--switch-generation / -G NUMBER: switch to specified generation of profile
--rollback: switch to the previous generation
--list-generations: list available generations of a profile
--import / -I FILE: set default Nix expression --import / -I FILE: set default Nix expression
--version: output version information --version: output version information

View File

@ -472,6 +472,61 @@ static void opSwitchProfile(Globals & globals,
} }
static const int prevGen = -2;
static void switchGeneration(Globals & globals, int dstGen)
{
int curGen;
Generations gens = findGenerations(globals.profile, curGen);
Generation dst;
for (Generations::iterator i = gens.begin(); i != gens.end(); ++i)
if ((dstGen == prevGen && i->number < curGen) ||
(dstGen >= 0 && i->number == dstGen))
dst = *i;
if (!dst)
if (dstGen == prevGen)
throw Error(format("no generation older than the current (%1%) exists")
% curGen);
else
throw Error(format("generation %1% does not exist") % dstGen);
switchLink(globals.profile, dst.path);
}
static void opSwitchGeneration(Globals & globals,
Strings opFlags, Strings opArgs)
{
if (opFlags.size() > 0)
throw UsageError(format("unknown flag `%1%'") % opFlags.front());
if (opArgs.size() != 1)
throw UsageError(format("exactly one argument expected"));
istringstream str(opArgs.front());
int dstGen;
str >> dstGen;
if (!str || !str.eof())
throw UsageError(format("expected a generation number"));
switchGeneration(globals, dstGen);
}
static void opRollback(Globals & globals,
Strings opFlags, Strings opArgs)
{
if (opFlags.size() > 0)
throw UsageError(format("unknown flag `%1%'") % opFlags.front());
if (opArgs.size() != 0)
throw UsageError(format("no arguments expected"));
switchGeneration(globals, prevGen);
}
static void opListGenerations(Globals & globals, static void opListGenerations(Globals & globals,
Strings opFlags, Strings opArgs) Strings opFlags, Strings opArgs)
{ {
@ -550,6 +605,10 @@ void run(Strings args)
} }
else if (arg == "--switch-profile" || arg == "-S") else if (arg == "--switch-profile" || arg == "-S")
op = opSwitchProfile; op = opSwitchProfile;
else if (arg == "--switch-generation" || arg == "-G")
op = opSwitchGeneration;
else if (arg == "--rollback")
op = opRollback;
else if (arg == "--list-generations") else if (arg == "--list-generations")
op = opListGenerations; op = opListGenerations;
else if (arg[0] == '-') else if (arg[0] == '-')

View File

@ -11,6 +11,14 @@ struct Generation
int number; int number;
Path path; Path path;
time_t creationTime; time_t creationTime;
Generation()
{
number = -1;
}
operator bool() const
{
return number != -1;
}
}; };
typedef list<Generation> Generations; typedef list<Generation> Generations;