diff options
Diffstat (limited to 'src/legacy/nix-collect-garbage.cc')
-rw-r--r-- | src/legacy/nix-collect-garbage.cc | 118 |
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); +} + +} |