Skip to content

Commit

Permalink
nix-collect-garbage: Don't call nix-env
Browse files Browse the repository at this point in the history
Also, make sure --delete-older-than doesn't delete the current
generation.
  • Loading branch information
edolstra committed May 21, 2015
1 parent 22b1a8d commit 4ca5a9d
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 69 deletions.
82 changes: 82 additions & 0 deletions src/libstore/profiles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,88 @@ void deleteGeneration(const Path & profile, unsigned int gen)
}


static void deleteGeneration2(const Path & profile, unsigned int gen, bool dryRun)
{
if (dryRun)
printMsg(lvlInfo, format("would remove generation %1%") % gen);
else {
printMsg(lvlInfo, format("removing generation %1%") % gen);
deleteGeneration(profile, gen);
}
}


void deleteGenerations(const Path & profile, const std::set<unsigned int> & gensToDelete, bool dryRun)
{
PathLocks lock;
lockProfile(lock, profile);

int curGen;
Generations gens = findGenerations(profile, curGen);

if (gensToDelete.find(curGen) != gensToDelete.end())
throw Error(format("cannot delete current generation of profile %1%’") % profile);

for (auto & i : gens) {
if (gensToDelete.find(i.number) == gensToDelete.end()) continue;
deleteGeneration2(profile, i.number, dryRun);
}
}


void deleteOldGenerations(const Path & profile, bool dryRun)
{
PathLocks lock;
lockProfile(lock, profile);

int curGen;
Generations gens = findGenerations(profile, curGen);

for (auto & i : gens)
if (i.number != curGen)
deleteGeneration2(profile, i.number, dryRun);
}


void deleteGenerationsOlderThan(const Path & profile, time_t t, bool dryRun)
{
PathLocks lock;
lockProfile(lock, profile);

int curGen;
Generations gens = findGenerations(profile, curGen);

bool canDelete = false;
for (auto i = gens.rbegin(); i != gens.rend(); ++i)
if (canDelete) {
assert(i->creationTime < t);
if (i->number != curGen)
deleteGeneration2(profile, i->number, dryRun);
} else if (i->creationTime < t) {
/* We may now start deleting generations, but we don't
delete this generation yet, because this generation was
still the one that was active at the requested point in
time. */
canDelete = true;
}
}


void deleteGenerationsOlderThan(const Path & profile, const string & timeSpec, bool dryRun)
{
time_t curTime = time(0);
string strDays = string(timeSpec, 0, timeSpec.size() - 1);
int days;

if (!string2Int(strDays, days) || days < 1)
throw Error(format("invalid number of days specifier ‘%1%’") % timeSpec);

time_t oldTime = curTime - days * 24 * 3600;

deleteGenerationsOlderThan(profile, oldTime, dryRun);
}


void switchLink(Path link, Path target)
{
/* Hacky. */
Expand Down
10 changes: 9 additions & 1 deletion src/libstore/profiles.hh
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,19 @@ typedef list<Generation> Generations;
/* Returns the list of currently present generations for the specified
profile, sorted by generation number. */
Generations findGenerations(Path profile, int & curGen);

Path createGeneration(Path profile, Path outPath);

void deleteGeneration(const Path & profile, unsigned int gen);

void deleteGenerations(const Path & profile, const std::set<unsigned int> & gensToDelete, bool dryRun);

void deleteOldGenerations(const Path & profile, bool dryRun);

void deleteGenerationsOlderThan(const Path & profile, time_t t, bool dryRun);

void deleteGenerationsOlderThan(const Path & profile, const string & timeSpec, bool dryRun);

void switchLink(Path link, Path target);

/* Ensure exclusive access to a profile. Any command that modifies
Expand Down
14 changes: 7 additions & 7 deletions src/nix-collect-garbage/nix-collect-garbage.cc
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
#include "store-api.hh"
#include "hash.hh"
#include "profiles.hh"
#include "shared.hh"
#include "globals.hh"

#include <iostream>

using namespace nix;

std::string gen = "old";
std::string deleteOlderThan;
bool dryRun = false;

void runProgramSimple(Path program, const Strings & args)
Expand Down Expand Up @@ -49,10 +49,10 @@ void removeOldGenerations(std::string dir)
auto link = readLink(path);
if (link.find("link") != string::npos) {
printMsg(lvlInfo, format("removing old generations of profile %1%") % path);

auto args = Strings{"-p", path, "--delete-generations", gen};
if (dryRun) args.push_back("--dry-run");
runProgramSimple(settings.nixBinDir + "/nix-env", args);
if (deleteOlderThan != "")
deleteGenerationsOlderThan(path, deleteOlderThan, dryRun);
else
deleteOldGenerations(path, dryRun);
}
} else if (type == DT_DIR) {
removeOldGenerations(path);
Expand All @@ -76,7 +76,7 @@ int main(int argc, char * * argv)
else if (*arg == "--delete-old" || *arg == "-d") removeOld = true;
else if (*arg == "--delete-older-than") {
removeOld = true;
gen = getArg(*arg, arg, end);
deleteOlderThan = getArg(*arg, arg, end);
}
else if (*arg == "--dry-run") dryRun = true;
else
Expand Down
73 changes: 12 additions & 61 deletions src/nix-env/nix-env.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1262,73 +1262,24 @@ static void opListGenerations(Globals & globals, Strings opFlags, Strings opArgs
}


static void deleteGeneration2(Globals & globals, unsigned int gen)
{
if (globals.dryRun)
printMsg(lvlInfo, format("would remove generation %1%") % gen);
else {
printMsg(lvlInfo, format("removing generation %1%") % gen);
deleteGeneration(globals.profile, gen);
}

}


static void opDeleteGenerations(Globals & globals, Strings opFlags, Strings opArgs)
{
if (opFlags.size() > 0)
throw UsageError(format("unknown flag ‘%1%’") % opFlags.front());

PathLocks lock;
lockProfile(lock, globals.profile);

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, j->number);
} else if (i->size() >= 2 && tolower(*i->rbegin()) == 'd') {
time_t curTime = time(NULL);
time_t oldTime;
string strDays = string(*i, 0, i->size() - 1);
int days;

if (!string2Int(strDays, days) || days < 1)
throw UsageError(format("invalid number of days specifier ‘%1%’") % *i);

oldTime = curTime - days * 24 * 3600;

bool canDelete = false;
for (Generations::reverse_iterator j = gens.rbegin(); j != gens.rend(); ++j) {
if (canDelete) {
assert(j->creationTime < oldTime);
deleteGeneration2(globals, j->number);
} else if (j->creationTime < oldTime) {
/* We may now start deleting generations, but we don't delete
this generation yet, because this generation was still the
one that was active at the requested point in time. */
canDelete = true;
}
}
} 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, j->number);
found = true;
break;
}
}
if (!found)
printMsg(lvlError, format("generation %1% does not exist") % n);
if (opArgs.size() == 1 && opArgs.front() == "old") {
deleteOldGenerations(globals.profile, globals.dryRun);
} else if (opArgs.size() == 1 && opArgs.front().find('d') != string::npos) {
deleteGenerationsOlderThan(globals.profile, opArgs.front(), globals.dryRun);
} else {
std::set<unsigned int> gens;
for (auto & i : opArgs) {
unsigned int n;
if (!string2Int(i, n) || n < 0)
throw UsageError(format("invalid generation number ‘%1%’") % i);
gens.insert(n);
}
deleteGenerations(globals.profile, gens, globals.dryRun);
}
}

Expand Down

0 comments on commit 4ca5a9d

Please sign in to comment.