aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2015-05-21 16:26:03 +0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2015-05-21 16:28:30 +0200
commit4ca5a9dcfd577487f8a5b192e8ec525c5baad8cb (patch)
treed3686237252fae1cf7e719a4f4116cabfd467a18
parent22b1a8d43f0dea4f85bce2e79b1b986ecd8ba7f6 (diff)
nix-collect-garbage: Don't call nix-env
Also, make sure --delete-older-than doesn't delete the current generation.
-rw-r--r--src/libstore/profiles.cc82
-rw-r--r--src/libstore/profiles.hh10
-rw-r--r--src/nix-collect-garbage/nix-collect-garbage.cc14
-rw-r--r--src/nix-env/nix-env.cc73
4 files changed, 110 insertions, 69 deletions
diff --git a/src/libstore/profiles.cc b/src/libstore/profiles.cc
index 5b7a533df..da3f7da9d 100644
--- a/src/libstore/profiles.cc
+++ b/src/libstore/profiles.cc
@@ -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. */
diff --git a/src/libstore/profiles.hh b/src/libstore/profiles.hh
index 30d2376d9..e99bbf398 100644
--- a/src/libstore/profiles.hh
+++ b/src/libstore/profiles.hh
@@ -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
diff --git a/src/nix-collect-garbage/nix-collect-garbage.cc b/src/nix-collect-garbage/nix-collect-garbage.cc
index 740ef88f5..b671e6cb8 100644
--- a/src/nix-collect-garbage/nix-collect-garbage.cc
+++ b/src/nix-collect-garbage/nix-collect-garbage.cc
@@ -1,5 +1,5 @@
#include "store-api.hh"
-#include "hash.hh"
+#include "profiles.hh"
#include "shared.hh"
#include "globals.hh"
@@ -7,7 +7,7 @@
using namespace nix;
-std::string gen = "old";
+std::string deleteOlderThan;
bool dryRun = false;
void runProgramSimple(Path program, const Strings & args)
@@ -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);
@@ -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
diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc
index 5cf41e844..3f82345ce 100644
--- a/src/nix-env/nix-env.cc
+++ b/src/nix-env/nix-env.cc
@@ -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);
}
}