aboutsummaryrefslogtreecommitdiff
path: root/src/legacy/nix-collect-garbage.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/legacy/nix-collect-garbage.cc')
-rw-r--r--src/legacy/nix-collect-garbage.cc118
1 files changed, 118 insertions, 0 deletions
diff --git a/src/legacy/nix-collect-garbage.cc b/src/legacy/nix-collect-garbage.cc
new file mode 100644
index 000000000..7640100a0
--- /dev/null
+++ b/src/legacy/nix-collect-garbage.cc
@@ -0,0 +1,118 @@
+#include "file-system.hh"
+#include "store-api.hh"
+#include "store-cast.hh"
+#include "gc-store.hh"
+#include "profiles.hh"
+#include "shared.hh"
+#include "globals.hh"
+#include "legacy.hh"
+#include "signals.hh"
+#include "nix-collect-garbage.hh"
+
+#include <iostream>
+#include <cerrno>
+
+namespace nix {
+
+std::string deleteOlderThan;
+bool dryRun = false;
+
+
+/* If `-d' was specified, remove all old generations of all profiles.
+ * Of course, this makes rollbacks to before this point in time
+ * impossible. */
+
+void removeOldGenerations(std::string dir)
+{
+ if (access(dir.c_str(), R_OK) != 0) return;
+
+ bool canWrite = access(dir.c_str(), W_OK) == 0;
+
+ for (auto & i : readDirectory(dir)) {
+ checkInterrupt();
+
+ auto path = dir + "/" + i.name;
+ auto type = i.type == DT_UNKNOWN ? getFileType(path) : i.type;
+
+ if (type == DT_LNK && canWrite) {
+ std::string link;
+ try {
+ link = readLink(path);
+ } catch (SysError & e) {
+ if (e.errNo == ENOENT) continue;
+ throw;
+ }
+ if (link.find("link") != std::string::npos) {
+ printInfo("removing old generations of profile %s", path);
+ if (deleteOlderThan != "") {
+ auto t = parseOlderThanTimeSpec(deleteOlderThan);
+ deleteGenerationsOlderThan(path, t, dryRun);
+ } else
+ deleteOldGenerations(path, dryRun);
+ }
+ } else if (type == DT_DIR) {
+ removeOldGenerations(path);
+ }
+ }
+}
+
+static int main_nix_collect_garbage(int argc, char * * argv)
+{
+ {
+ bool removeOld = false;
+
+ GCOptions options;
+
+ parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) {
+ if (*arg == "--help")
+ showManPage("nix-collect-garbage");
+ else if (*arg == "--version")
+ printVersion("nix-collect-garbage");
+ else if (*arg == "--delete-old" || *arg == "-d") removeOld = true;
+ else if (*arg == "--delete-older-than") {
+ removeOld = true;
+ deleteOlderThan = getArg(*arg, arg, end);
+ }
+ else if (*arg == "--dry-run") dryRun = true;
+ else if (*arg == "--max-freed")
+ options.maxFreed = std::max(getIntArg<int64_t>(*arg, arg, end, true), (int64_t) 0);
+ else
+ return false;
+ return true;
+ });
+
+ if (removeOld) {
+ std::set<Path> dirsToClean = {
+ profilesDir(), settings.nixStateDir + "/profiles", dirOf(getDefaultProfile())};
+ for (auto & dir : dirsToClean)
+ removeOldGenerations(dir);
+ }
+
+ // Run the actual garbage collector.
+ if (!dryRun) {
+ options.action = GCOptions::gcDeleteDead;
+ } else {
+ options.action = GCOptions::gcReturnDead;
+ }
+ auto store = openStore();
+ auto & gcStore = require<GcStore>(*store);
+ GCResults results;
+ PrintFreed freed(true, results);
+ gcStore.collectGarbage(options, results);
+
+ if (dryRun) {
+ // Only print results for dry run; when !dryRun, paths will be printed as they're deleted.
+ for (auto & i : results.paths) {
+ printInfo("%s", i);
+ }
+ }
+
+ return 0;
+ }
+}
+
+void registerNixCollectGarbage() {
+ LegacyCommands::add("nix-collect-garbage", main_nix_collect_garbage);
+}
+
+}