diff options
Diffstat (limited to 'third_party/nix/src/nix-collect-garbage/nix-collect-garbage.cc')
-rw-r--r-- | third_party/nix/src/nix-collect-garbage/nix-collect-garbage.cc | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/third_party/nix/src/nix-collect-garbage/nix-collect-garbage.cc b/third_party/nix/src/nix-collect-garbage/nix-collect-garbage.cc new file mode 100644 index 000000000000..0050bdda15fb --- /dev/null +++ b/third_party/nix/src/nix-collect-garbage/nix-collect-garbage.cc @@ -0,0 +1,105 @@ +#include <cerrno> +#include <iostream> + +#include <glog/logging.h> + +#include "globals.hh" +#include "legacy.hh" +#include "profiles.hh" +#include "shared.hh" +#include "store-api.hh" + +using 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(const 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; + } + } + if (link.find("link") != string::npos) { + LOG(INFO) << "removing old generations of profile " << path; + if (!deleteOlderThan.empty()) { + deleteGenerationsOlderThan(path, deleteOlderThan, dryRun); + } else { + deleteOldGenerations(path, dryRun); + } + } + } else if (type == DT_DIR) { + removeOldGenerations(path); + } + } +} + +static int _main(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") { + auto maxFreed = getIntArg<long long>(*arg, arg, end, true); + options.maxFreed = maxFreed >= 0 ? maxFreed : 0; + } else { + return false; + } + return true; + }); + + initPlugins(); + + auto profilesDir = settings.nixStateDir + "/profiles"; + if (removeOld) { + removeOldGenerations(profilesDir); + } + + // Run the actual garbage collector. + if (!dryRun) { + auto store = openStore(); + options.action = GCOptions::gcDeleteDead; + GCResults results; + PrintFreed freed(true, results); + store->collectGarbage(options, results); + } + + return 0; + } +} + +static RegisterLegacyCommand s1("nix-collect-garbage", _main); |