forked from lix-project/lix
nix-collect-garbage: Don't call nix-env
Also, make sure --delete-older-than doesn't delete the current generation.
This commit is contained in:
parent
22b1a8d43f
commit
4ca5a9dcfd
|
@ -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)
|
void switchLink(Path link, Path target)
|
||||||
{
|
{
|
||||||
/* Hacky. */
|
/* Hacky. */
|
||||||
|
|
|
@ -35,6 +35,14 @@ Path createGeneration(Path profile, Path outPath);
|
||||||
|
|
||||||
void deleteGeneration(const Path & profile, unsigned int gen);
|
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);
|
void switchLink(Path link, Path target);
|
||||||
|
|
||||||
/* Ensure exclusive access to a profile. Any command that modifies
|
/* Ensure exclusive access to a profile. Any command that modifies
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
#include "hash.hh"
|
#include "profiles.hh"
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
|
||||||
std::string gen = "old";
|
std::string deleteOlderThan;
|
||||||
bool dryRun = false;
|
bool dryRun = false;
|
||||||
|
|
||||||
void runProgramSimple(Path program, const Strings & args)
|
void runProgramSimple(Path program, const Strings & args)
|
||||||
|
@ -49,10 +49,10 @@ void removeOldGenerations(std::string dir)
|
||||||
auto link = readLink(path);
|
auto link = readLink(path);
|
||||||
if (link.find("link") != string::npos) {
|
if (link.find("link") != string::npos) {
|
||||||
printMsg(lvlInfo, format("removing old generations of profile %1%") % path);
|
printMsg(lvlInfo, format("removing old generations of profile %1%") % path);
|
||||||
|
if (deleteOlderThan != "")
|
||||||
auto args = Strings{"-p", path, "--delete-generations", gen};
|
deleteGenerationsOlderThan(path, deleteOlderThan, dryRun);
|
||||||
if (dryRun) args.push_back("--dry-run");
|
else
|
||||||
runProgramSimple(settings.nixBinDir + "/nix-env", args);
|
deleteOldGenerations(path, dryRun);
|
||||||
}
|
}
|
||||||
} else if (type == DT_DIR) {
|
} else if (type == DT_DIR) {
|
||||||
removeOldGenerations(path);
|
removeOldGenerations(path);
|
||||||
|
@ -76,7 +76,7 @@ int main(int argc, char * * argv)
|
||||||
else if (*arg == "--delete-old" || *arg == "-d") removeOld = true;
|
else if (*arg == "--delete-old" || *arg == "-d") removeOld = true;
|
||||||
else if (*arg == "--delete-older-than") {
|
else if (*arg == "--delete-older-than") {
|
||||||
removeOld = true;
|
removeOld = true;
|
||||||
gen = getArg(*arg, arg, end);
|
deleteOlderThan = getArg(*arg, arg, end);
|
||||||
}
|
}
|
||||||
else if (*arg == "--dry-run") dryRun = true;
|
else if (*arg == "--dry-run") dryRun = true;
|
||||||
else
|
else
|
||||||
|
|
|
@ -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)
|
static void opDeleteGenerations(Globals & globals, Strings opFlags, Strings opArgs)
|
||||||
{
|
{
|
||||||
if (opFlags.size() > 0)
|
if (opFlags.size() > 0)
|
||||||
throw UsageError(format("unknown flag ‘%1%’") % opFlags.front());
|
throw UsageError(format("unknown flag ‘%1%’") % opFlags.front());
|
||||||
|
|
||||||
PathLocks lock;
|
if (opArgs.size() == 1 && opArgs.front() == "old") {
|
||||||
lockProfile(lock, globals.profile);
|
deleteOldGenerations(globals.profile, globals.dryRun);
|
||||||
|
} else if (opArgs.size() == 1 && opArgs.front().find('d') != string::npos) {
|
||||||
int curGen;
|
deleteGenerationsOlderThan(globals.profile, opArgs.front(), globals.dryRun);
|
||||||
Generations gens = findGenerations(globals.profile, curGen);
|
} else {
|
||||||
|
std::set<unsigned int> gens;
|
||||||
for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); ++i) {
|
for (auto & i : opArgs) {
|
||||||
|
unsigned int n;
|
||||||
if (*i == "old") {
|
if (!string2Int(i, n) || n < 0)
|
||||||
for (Generations::iterator j = gens.begin(); j != gens.end(); ++j)
|
throw UsageError(format("invalid generation number ‘%1%’") % i);
|
||||||
if (j->number != curGen)
|
gens.insert(n);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
deleteGenerations(globals.profile, gens, globals.dryRun);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue