1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-30 19:57:59 +02:00
nix/src/nix-collect-garbage/nix-collect-garbage.cc
John Ericson ac89bb064a Split up util.{hh,cc}
All OS and IO operations should be moved out, leaving only some misc
portable pure functions.

This is useful to avoid copious CPP when doing things like Windows and
Emscripten ports.

Newly exposed functions to break cycles:

 - `restoreSignals`
 - `updateWindowSize`
2023-11-05 12:20:02 -05:00

104 lines
3.2 KiB
C++

#include "file-system.hh"
#include "signals.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 <iostream>
#include <cerrno>
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(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) {
auto store = openStore();
auto & gcStore = require<GcStore>(*store);
options.action = GCOptions::gcDeleteDead;
GCResults results;
PrintFreed freed(true, results);
gcStore.collectGarbage(options, results);
}
return 0;
}
}
static RegisterLegacyCommand r_nix_collect_garbage("nix-collect-garbage", main_nix_collect_garbage);