aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--scripts/local.mk1
-rwxr-xr-xscripts/nix-collect-garbage.in65
-rw-r--r--src/nix-collect-garbage/local.mk7
-rw-r--r--src/nix-collect-garbage/nix-collect-garbage.cc87
5 files changed, 95 insertions, 66 deletions
diff --git a/Makefile b/Makefile
index d8d4a7cc5..fe2e88a99 100644
--- a/Makefile
+++ b/Makefile
@@ -10,6 +10,7 @@ makefiles = \
src/nix-instantiate/local.mk \
src/nix-env/local.mk \
src/nix-daemon/local.mk \
+ src/nix-collect-garbage/local.mk \
src/download-via-ssh/local.mk \
src/nix-log2xml/local.mk \
src/bsdiff-4.3/local.mk \
diff --git a/scripts/local.mk b/scripts/local.mk
index f4c5e8097..39e1df611 100644
--- a/scripts/local.mk
+++ b/scripts/local.mk
@@ -1,7 +1,6 @@
nix_bin_scripts := \
$(d)/nix-build \
$(d)/nix-channel \
- $(d)/nix-collect-garbage \
$(d)/nix-copy-closure \
$(d)/nix-generate-patches \
$(d)/nix-install-package \
diff --git a/scripts/nix-collect-garbage.in b/scripts/nix-collect-garbage.in
deleted file mode 100755
index 55e0ba7a6..000000000
--- a/scripts/nix-collect-garbage.in
+++ /dev/null
@@ -1,65 +0,0 @@
-#! @perl@ -w @perlFlags@
-
-use strict;
-use Nix::Config;
-
-my $profilesDir = "@localstatedir@/nix/profiles";
-
-
-# Process the command line arguments.
-my @args = ();
-my $arg;
-
-my $removeOld = 0;
-my $gen;
-my $dryRun = 0;
-
-while ($arg = shift) {
- if ($arg eq "--delete-old" || $arg eq "-d") {
- $removeOld = 1;
- $gen = "old";
- } elsif ($arg eq "--delete-older-than") {
- $removeOld = 1;
- $gen = shift;
- } elsif ($arg eq "--dry-run") {
- $dryRun = 1;
- } elsif ($arg eq "--help") {
- exec "man nix-collect-garbage" or die;
- } else {
- push @args, $arg;
- }
-}
-
-
-# If `-d' was specified, remove all old generations of all profiles.
-# Of course, this makes rollbacks to before this point in time
-# impossible.
-
-sub removeOldGenerations;
-sub removeOldGenerations {
- my $dir = shift;
-
- my $dh;
- opendir $dh, $dir or die;
-
- foreach my $name (sort (readdir $dh)) {
- next if $name eq "." || $name eq "..";
- $name = $dir . "/" . $name;
- if (-l $name && (readlink($name) =~ /link/)) {
- print STDERR "removing old generations of profile $name\n";
-
- system("$Nix::Config::binDir/nix-env", "-p", $name, "--delete-generations", $gen, $dryRun ? "--dry-run" : ());
- }
- elsif (! -l $name && -d $name) {
- removeOldGenerations $name;
- }
- }
-
- closedir $dh or die;
-}
-
-removeOldGenerations $profilesDir if $removeOld;
-
-
-# Run the actual garbage collector.
-exec "$Nix::Config::binDir/nix-store", "--gc", @args unless $dryRun;
diff --git a/src/nix-collect-garbage/local.mk b/src/nix-collect-garbage/local.mk
new file mode 100644
index 000000000..02d14cf62
--- /dev/null
+++ b/src/nix-collect-garbage/local.mk
@@ -0,0 +1,7 @@
+programs += nix-collect-garbage
+
+nix-collect-garbage_DIR := $(d)
+
+nix-collect-garbage_SOURCES := $(d)/nix-collect-garbage.cc
+
+nix-collect-garbage_LIBS = libmain libstore libutil libformat
diff --git a/src/nix-collect-garbage/nix-collect-garbage.cc b/src/nix-collect-garbage/nix-collect-garbage.cc
new file mode 100644
index 000000000..568a1fa7d
--- /dev/null
+++ b/src/nix-collect-garbage/nix-collect-garbage.cc
@@ -0,0 +1,87 @@
+#include "hash.hh"
+#include "shared.hh"
+#include "globals.hh"
+
+#include <iostream>
+
+using namespace nix;
+
+std::string gen = "";
+bool dryRun = false;
+
+void runProgramSimple(Path program, const Strings & args)
+{
+ checkInterrupt();
+
+ /* Fork. */
+ Pid pid = startProcess([&]() {
+ Strings args_(args);
+ args_.push_front(program);
+ auto cargs = stringsToCharPtrs(args_);
+
+ execv(program.c_str(), (char * *) &cargs[0]);
+
+ throw SysError(format("executing ‘%1%’") % program);
+ });
+
+ pid.wait(true);
+}
+
+
+/* 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)
+{
+ for (auto & i : readDirectory(dir)) {
+ checkInterrupt();
+
+ auto path = dir + "/" + i.name;
+ auto type = getFileType(path);
+
+ if (type == DT_LNK) {
+ auto link = readLink(path);
+ if (link.find("link") != string::npos) {
+ printMsg(lvlInfo, format("removing old generations of profile %1%") % path);
+
+ runProgramSimple(settings.nixBinDir + "/nix-env", Strings{"-p", path, "--delete-generations", gen, dryRun ? "--dry-run" : ""});
+ }
+ } else if (type == DT_DIR) {
+ removeOldGenerations(path);
+ }
+ }
+}
+
+int main(int argc, char * * argv)
+{
+ bool removeOld = false;
+ Strings extraArgs;
+
+ return handleExceptions(argv[0], [&]() {
+ initNix();
+
+ 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;
+ gen = getArg(*arg, arg, end);
+ }
+ else if (*arg == "--dry-run") dryRun = true;
+ else
+ extraArgs.push_back(*arg);
+ return true;
+ });
+
+ auto profilesDir = settings.nixStateDir + "/profiles";
+ if (removeOld) removeOldGenerations(profilesDir);
+
+ // Run the actual garbage collector.
+ if (!dryRun) runProgramSimple(settings.nixBinDir + "/nix-store", Strings{"--gc"});
+ });
+}
+