1 #include "store-api.hh"
2 #include "profiles.hh"
3 #include "shared.hh"
4 #include "globals.hh"
5 #include "legacy.hh"
6
7 #include <iostream>
8 #include <cerrno>
9
10 using namespace nix;
11
12 std::string deleteOlderThan;
13 bool dryRun = false;
14
15
16 /* If `-d' was specified, remove all old generations of all profiles.
17 * Of course, this makes rollbacks to before this point in time
18 * impossible. */
19
removeOldGenerations(std::string dir)20 void removeOldGenerations(std::string dir)
21 {
22 if (access(dir.c_str(), R_OK) != 0) return;
23
24 bool canWrite = access(dir.c_str(), W_OK) == 0;
25
26 for (auto & i : readDirectory(dir)) {
27 checkInterrupt();
28
29 auto path = dir + "/" + i.name;
30 auto type = i.type == DT_UNKNOWN ? getFileType(path) : i.type;
31
32 if (type == DT_LNK && canWrite) {
33 std::string link;
34 try {
35 link = readLink(path);
36 } catch (SysError & e) {
37 if (e.errNo == ENOENT) continue;
38 }
39 if (link.find("link") != string::npos) {
40 printInfo(format("removing old generations of profile %1%") % path);
41 if (deleteOlderThan != "")
42 deleteGenerationsOlderThan(path, deleteOlderThan, dryRun);
43 else
44 deleteOldGenerations(path, dryRun);
45 }
46 } else if (type == DT_DIR) {
47 removeOldGenerations(path);
48 }
49 }
50 }
51
_main(int argc,char ** argv)52 static int _main(int argc, char * * argv)
53 {
54 {
55 bool removeOld = false;
56
57 GCOptions options;
58
59 parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) {
60 if (*arg == "--help")
61 showManPage("nix-collect-garbage");
62 else if (*arg == "--version")
63 printVersion("nix-collect-garbage");
64 else if (*arg == "--delete-old" || *arg == "-d") removeOld = true;
65 else if (*arg == "--delete-older-than") {
66 removeOld = true;
67 deleteOlderThan = getArg(*arg, arg, end);
68 }
69 else if (*arg == "--dry-run") dryRun = true;
70 else if (*arg == "--max-freed") {
71 long long maxFreed = getIntArg<long long>(*arg, arg, end, true);
72 options.maxFreed = maxFreed >= 0 ? maxFreed : 0;
73 }
74 else
75 return false;
76 return true;
77 });
78
79 initPlugins();
80
81 auto profilesDir = settings.nixStateDir + "/profiles";
82 if (removeOld) removeOldGenerations(profilesDir);
83
84 // Run the actual garbage collector.
85 if (!dryRun) {
86 auto store = openStore();
87 options.action = GCOptions::gcDeleteDead;
88 GCResults results;
89 PrintFreed freed(true, results);
90 store->collectGarbage(options, results);
91 }
92
93 return 0;
94 }
95 }
96
97 static RegisterLegacyCommand s1("nix-collect-garbage", _main);
98