mirror of
https://github.com/NixOS/nix
synced 2025-06-30 19:57:59 +02:00
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`
104 lines
3.2 KiB
C++
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);
|