* Operation `--delete-generations' to delete generations of a

profile.  Arguments are either generation number, or `old' to delete
  all non-current generations.  Typical use:

  $ nix-env --delete-generations old
  $ nix-collect-garbage

* istringstream -> string2Int.
This commit is contained in:
Eelco Dolstra 2004-09-10 13:32:08 +00:00
parent c16be6ac92
commit dcc433de47
8 changed files with 100 additions and 33 deletions

View file

@ -643,10 +643,8 @@ static void opSwitchGeneration(Globals & globals,
if (opArgs.size() != 1)
throw UsageError(format("exactly one argument expected"));
istringstream str(opArgs.front());
int dstGen;
str >> dstGen;
if (!str || !str.eof())
if (!string2Int(opArgs.front(), dstGen))
throw UsageError(format("expected a generation number"));
switchGeneration(globals, dstGen);
@ -688,6 +686,49 @@ static void opListGenerations(Globals & globals,
}
static void deleteGeneration2(const Path & profile, unsigned int gen)
{
printMsg(lvlInfo, format("removing generation %1%") % gen);
deleteGeneration(profile, gen);
}
static void opDeleteGenerations(Globals & globals,
Strings opFlags, Strings opArgs)
{
if (opFlags.size() > 0)
throw UsageError(format("unknown flag `%1%'") % opFlags.front());
int curGen;
Generations gens = findGenerations(globals.profile, curGen);
for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); ++i) {
if (*i == "old") {
for (Generations::iterator j = gens.begin(); j != gens.end(); ++j)
if (j->number != curGen)
deleteGeneration2(globals.profile, j->number);
}
else {
int n;
if (!string2Int(*i, n) || n < 0)
throw UsageError(format("invalid generation specifier `%1%'") % *i);
bool found = false;
for (Generations::iterator j = gens.begin(); j != gens.end(); ++j) {
if (j->number == n) {
deleteGeneration2(globals.profile, j->number);
found = true;
break;
}
}
if (!found)
printMsg(lvlError, format("generation %1% does not exist") % n);
}
}
}
static void opDefaultExpr(Globals & globals,
Strings opFlags, Strings opArgs)
{
@ -750,6 +791,8 @@ void run(Strings args)
op = opRollback;
else if (arg == "--list-generations")
op = opListGenerations;
else if (arg == "--delete-generations")
op = opDeleteGenerations;
else if (arg == "--dry-run") {
printMsg(lvlInfo, "(dry run; not doing anything)");
globals.dryRun = true;

View file

@ -56,20 +56,10 @@ static string nextComponent(string::const_iterator & p,
}
#include <fstream>
static bool parseInt(const string & s, int & n)
{
istringstream st(s);
st >> n;
return !st.fail();
}
static bool componentsLT(const string & c1, const string & c2)
{
int n1, n2;
bool c1Num = parseInt(c1, n1), c2Num = parseInt(c2, n2);
bool c1Num = string2Int(c1, n1), c2Num = string2Int(c2, n2);
if (c1Num && c2Num) return n1 < n2;
else if (c1 == "" && c2Num) return true;

View file

@ -20,9 +20,11 @@ static int parseName(const string & profileName, const string & name)
string s = string(name, profileName.size() + 1);
int p = s.find("-link");
if (p == string::npos) return -1;
istringstream str(string(s, 0, p));
unsigned int n;
if (str >> n && str.eof()) return n; else return -1;
int n;
if (string2Int(string(s, 0, p), n) && n >= 0)
return n;
else
return -1;
}
@ -59,6 +61,16 @@ Generations findGenerations(Path profile, int & curGen)
}
static void makeNames(const Path & profile, unsigned int num,
Path & generation, Path & gcrootDrv, Path & gcrootClr)
{
Path prefix = (format("%1%-%2%") % profile % num).str();
generation = prefix + "-link";
gcrootDrv = prefix + "-drv.gcroot";
gcrootClr = prefix + "-clr.gcroot";
}
Path createGeneration(Path profile, Path outPath,
Path drvPath, Path clrPath)
{
@ -72,10 +84,7 @@ Path createGeneration(Path profile, Path outPath,
Path generation, gcrootDrv, gcrootClr;
while (1) {
Path prefix = (format("%1%-%2%") % profile % num).str();
generation = prefix + "-link";
gcrootDrv = prefix + "-drv.gcroot";
gcrootClr = prefix + "-clr.gcroot";
makeNames(profile, num, generation, gcrootDrv, gcrootClr);
if (symlink(outPath.c_str(), generation.c_str()) == 0) break;
if (errno != EEXIST)
throw SysError(format("creating symlink `%1%'") % generation);
@ -90,6 +99,23 @@ Path createGeneration(Path profile, Path outPath,
}
static void removeFile(const Path & path)
{
if (remove(path.c_str()) == -1)
throw SysError(format("cannot unlink `%1%'") % path);
}
void deleteGeneration(const Path & profile, unsigned int gen)
{
Path generation, gcrootDrv, gcrootClr;
makeNames(profile, gen, generation, gcrootDrv, gcrootClr);
removeFile(generation);
if (pathExists(gcrootClr)) removeFile(gcrootClr);
if (pathExists(gcrootDrv)) removeFile(gcrootDrv);
}
void switchLink(Path link, Path target)
{
/* Hacky. */

View file

@ -31,6 +31,8 @@ Generations findGenerations(Path profile, int & curGen);
Path createGeneration(Path profile, Path outPath,
Path drvPath, Path clrPath);
void deleteGeneration(const Path & profile, unsigned int gen);
void switchLink(Path link, Path target);