2ef1060361
Plugins seem to not really be used anywhere (I can find one plugin that's actually defined, and it doesn't seem very useful, especially since we got rid of builtins.exec) and their presence is adding additional complexity and potential sources of bugs to an already unsteady refactor. At some point we may want to bring back something *like* plugins, but their design will likely be different and it will definitely be after we have a functioning Nix again. Change-Id: I3bc40e55917f70bf260fbc208c1705e2e6a7c626 Reviewed-on: https://cl.tvl.fyi/c/depot/+/1291 Tested-by: BuildkiteCI Reviewed-by: Alyssa Ross <hi@alyssa.is> Reviewed-by: isomer <isomer@tvl.fyi>
103 lines
2.9 KiB
C++
103 lines
2.9 KiB
C++
#include <cerrno>
|
|
#include <iostream>
|
|
|
|
#include <glog/logging.h>
|
|
|
|
#include "libmain/shared.hh"
|
|
#include "libstore/globals.hh"
|
|
#include "libstore/profiles.hh"
|
|
#include "libstore/store-api.hh"
|
|
#include "nix/legacy.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") != std::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;
|
|
});
|
|
|
|
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);
|