nix-collect-garbage: Don't call nix-env
Also, make sure --delete-older-than doesn't delete the current generation.
This commit is contained in:
		
							parent
							
								
									22b1a8d43f
								
							
						
					
					
						commit
						4ca5a9dcfd
					
				
					 4 changed files with 110 additions and 69 deletions
				
			
		|  | @ -129,6 +129,88 @@ void deleteGeneration(const Path & profile, unsigned int gen) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | static void deleteGeneration2(const Path & profile, unsigned int gen, bool dryRun) | ||||||
|  | { | ||||||
|  |     if (dryRun) | ||||||
|  |         printMsg(lvlInfo, format("would remove generation %1%") % gen); | ||||||
|  |     else { | ||||||
|  |         printMsg(lvlInfo, format("removing generation %1%") % gen); | ||||||
|  |         deleteGeneration(profile, gen); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | void deleteGenerations(const Path & profile, const std::set<unsigned int> & gensToDelete, bool dryRun) | ||||||
|  | { | ||||||
|  |     PathLocks lock; | ||||||
|  |     lockProfile(lock, profile); | ||||||
|  | 
 | ||||||
|  |     int curGen; | ||||||
|  |     Generations gens = findGenerations(profile, curGen); | ||||||
|  | 
 | ||||||
|  |     if (gensToDelete.find(curGen) != gensToDelete.end()) | ||||||
|  |         throw Error(format("cannot delete current generation of profile %1%’") % profile); | ||||||
|  | 
 | ||||||
|  |     for (auto & i : gens) { | ||||||
|  |         if (gensToDelete.find(i.number) == gensToDelete.end()) continue; | ||||||
|  |         deleteGeneration2(profile, i.number, dryRun); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | void deleteOldGenerations(const Path & profile, bool dryRun) | ||||||
|  | { | ||||||
|  |     PathLocks lock; | ||||||
|  |     lockProfile(lock, profile); | ||||||
|  | 
 | ||||||
|  |     int curGen; | ||||||
|  |     Generations gens = findGenerations(profile, curGen); | ||||||
|  | 
 | ||||||
|  |     for (auto & i : gens) | ||||||
|  |         if (i.number != curGen) | ||||||
|  |             deleteGeneration2(profile, i.number, dryRun); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | void deleteGenerationsOlderThan(const Path & profile, time_t t, bool dryRun) | ||||||
|  | { | ||||||
|  |     PathLocks lock; | ||||||
|  |     lockProfile(lock, profile); | ||||||
|  | 
 | ||||||
|  |     int curGen; | ||||||
|  |     Generations gens = findGenerations(profile, curGen); | ||||||
|  | 
 | ||||||
|  |     bool canDelete = false; | ||||||
|  |     for (auto i = gens.rbegin(); i != gens.rend(); ++i) | ||||||
|  |         if (canDelete) { | ||||||
|  |             assert(i->creationTime < t); | ||||||
|  |             if (i->number != curGen) | ||||||
|  |                 deleteGeneration2(profile, i->number, dryRun); | ||||||
|  |         } else if (i->creationTime < t) { | ||||||
|  |             /* We may now start deleting generations, but we don't
 | ||||||
|  |                delete this generation yet, because this generation was | ||||||
|  |                still the one that was active at the requested point in | ||||||
|  |                time. */ | ||||||
|  |             canDelete = true; | ||||||
|  |         } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | void deleteGenerationsOlderThan(const Path & profile, const string & timeSpec, bool dryRun) | ||||||
|  | { | ||||||
|  |     time_t curTime = time(0); | ||||||
|  |     string strDays = string(timeSpec, 0, timeSpec.size() - 1); | ||||||
|  |     int days; | ||||||
|  | 
 | ||||||
|  |     if (!string2Int(strDays, days) || days < 1) | ||||||
|  |         throw Error(format("invalid number of days specifier ‘%1%’") % timeSpec); | ||||||
|  | 
 | ||||||
|  |     time_t oldTime = curTime - days * 24 * 3600; | ||||||
|  | 
 | ||||||
|  |     deleteGenerationsOlderThan(profile, oldTime, dryRun); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| void switchLink(Path link, Path target) | void switchLink(Path link, Path target) | ||||||
| { | { | ||||||
|     /* Hacky. */ |     /* Hacky. */ | ||||||
|  |  | ||||||
|  | @ -30,11 +30,19 @@ typedef list<Generation> Generations; | ||||||
| /* Returns the list of currently present generations for the specified
 | /* Returns the list of currently present generations for the specified
 | ||||||
|    profile, sorted by generation number. */ |    profile, sorted by generation number. */ | ||||||
| Generations findGenerations(Path profile, int & curGen); | Generations findGenerations(Path profile, int & curGen); | ||||||
|      | 
 | ||||||
| Path createGeneration(Path profile, Path outPath); | Path createGeneration(Path profile, Path outPath); | ||||||
| 
 | 
 | ||||||
| void deleteGeneration(const Path & profile, unsigned int gen); | void deleteGeneration(const Path & profile, unsigned int gen); | ||||||
| 
 | 
 | ||||||
|  | void deleteGenerations(const Path & profile, const std::set<unsigned int> & gensToDelete, bool dryRun); | ||||||
|  | 
 | ||||||
|  | void deleteOldGenerations(const Path & profile, bool dryRun); | ||||||
|  | 
 | ||||||
|  | void deleteGenerationsOlderThan(const Path & profile, time_t t, bool dryRun); | ||||||
|  | 
 | ||||||
|  | void deleteGenerationsOlderThan(const Path & profile, const string & timeSpec, bool dryRun); | ||||||
|  | 
 | ||||||
| void switchLink(Path link, Path target); | void switchLink(Path link, Path target); | ||||||
| 
 | 
 | ||||||
| /* Ensure exclusive access to a profile.  Any command that modifies
 | /* Ensure exclusive access to a profile.  Any command that modifies
 | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| #include "store-api.hh" | #include "store-api.hh" | ||||||
| #include "hash.hh" | #include "profiles.hh" | ||||||
| #include "shared.hh" | #include "shared.hh" | ||||||
| #include "globals.hh" | #include "globals.hh" | ||||||
| 
 | 
 | ||||||
|  | @ -7,7 +7,7 @@ | ||||||
| 
 | 
 | ||||||
| using namespace nix; | using namespace nix; | ||||||
| 
 | 
 | ||||||
| std::string gen = "old"; | std::string deleteOlderThan; | ||||||
| bool dryRun = false; | bool dryRun = false; | ||||||
| 
 | 
 | ||||||
| void runProgramSimple(Path program, const Strings & args) | void runProgramSimple(Path program, const Strings & args) | ||||||
|  | @ -49,10 +49,10 @@ void removeOldGenerations(std::string dir) | ||||||
|             auto link = readLink(path); |             auto link = readLink(path); | ||||||
|             if (link.find("link") != string::npos) { |             if (link.find("link") != string::npos) { | ||||||
|                 printMsg(lvlInfo, format("removing old generations of profile %1%") % path); |                 printMsg(lvlInfo, format("removing old generations of profile %1%") % path); | ||||||
| 
 |                 if (deleteOlderThan != "") | ||||||
|                 auto args = Strings{"-p", path, "--delete-generations", gen}; |                     deleteGenerationsOlderThan(path, deleteOlderThan, dryRun); | ||||||
|                 if (dryRun) args.push_back("--dry-run"); |                 else | ||||||
|                 runProgramSimple(settings.nixBinDir + "/nix-env", args); |                     deleteOldGenerations(path, dryRun); | ||||||
|             } |             } | ||||||
|         } else if (type == DT_DIR) { |         } else if (type == DT_DIR) { | ||||||
|             removeOldGenerations(path); |             removeOldGenerations(path); | ||||||
|  | @ -76,7 +76,7 @@ int main(int argc, char * * argv) | ||||||
|             else if (*arg == "--delete-old" || *arg == "-d") removeOld = true; |             else if (*arg == "--delete-old" || *arg == "-d") removeOld = true; | ||||||
|             else if (*arg == "--delete-older-than") { |             else if (*arg == "--delete-older-than") { | ||||||
|                 removeOld = true; |                 removeOld = true; | ||||||
|                 gen = getArg(*arg, arg, end); |                 deleteOlderThan = getArg(*arg, arg, end); | ||||||
|             } |             } | ||||||
|             else if (*arg == "--dry-run") dryRun = true; |             else if (*arg == "--dry-run") dryRun = true; | ||||||
|             else |             else | ||||||
|  |  | ||||||
|  | @ -1262,73 +1262,24 @@ static void opListGenerations(Globals & globals, Strings opFlags, Strings opArgs | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static void deleteGeneration2(Globals & globals, unsigned int gen) |  | ||||||
| { |  | ||||||
|     if (globals.dryRun) |  | ||||||
|         printMsg(lvlInfo, format("would remove generation %1%") % gen); |  | ||||||
|     else { |  | ||||||
|         printMsg(lvlInfo, format("removing generation %1%") % gen); |  | ||||||
|         deleteGeneration(globals.profile, gen); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| static void opDeleteGenerations(Globals & globals, Strings opFlags, Strings opArgs) | static void opDeleteGenerations(Globals & globals, Strings opFlags, Strings opArgs) | ||||||
| { | { | ||||||
|     if (opFlags.size() > 0) |     if (opFlags.size() > 0) | ||||||
|         throw UsageError(format("unknown flag ‘%1%’") % opFlags.front()); |         throw UsageError(format("unknown flag ‘%1%’") % opFlags.front()); | ||||||
| 
 | 
 | ||||||
|     PathLocks lock; |     if (opArgs.size() == 1 && opArgs.front() == "old") { | ||||||
|     lockProfile(lock, globals.profile); |         deleteOldGenerations(globals.profile, globals.dryRun); | ||||||
| 
 |     } else if (opArgs.size() == 1 && opArgs.front().find('d') != string::npos) { | ||||||
|     int curGen; |         deleteGenerationsOlderThan(globals.profile, opArgs.front(), globals.dryRun); | ||||||
|     Generations gens = findGenerations(globals.profile, curGen); |     } else { | ||||||
| 
 |         std::set<unsigned int> gens; | ||||||
|     for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); ++i) { |         for (auto & i : opArgs) { | ||||||
| 
 |             unsigned int n; | ||||||
|         if (*i == "old") { |             if (!string2Int(i, n) || n < 0) | ||||||
|             for (Generations::iterator j = gens.begin(); j != gens.end(); ++j) |                 throw UsageError(format("invalid generation number ‘%1%’") % i); | ||||||
|                 if (j->number != curGen) |             gens.insert(n); | ||||||
|                     deleteGeneration2(globals, j->number); |  | ||||||
|         } else if (i->size() >= 2 && tolower(*i->rbegin()) == 'd') { |  | ||||||
|             time_t curTime = time(NULL); |  | ||||||
|             time_t oldTime; |  | ||||||
|             string strDays = string(*i, 0, i->size() - 1); |  | ||||||
|             int days; |  | ||||||
| 
 |  | ||||||
|             if (!string2Int(strDays, days) || days < 1) |  | ||||||
|                 throw UsageError(format("invalid number of days specifier ‘%1%’") % *i); |  | ||||||
| 
 |  | ||||||
|             oldTime = curTime - days * 24 * 3600; |  | ||||||
| 
 |  | ||||||
|             bool canDelete = false; |  | ||||||
|             for (Generations::reverse_iterator j = gens.rbegin(); j != gens.rend(); ++j) { |  | ||||||
|                 if (canDelete) { |  | ||||||
|                     assert(j->creationTime < oldTime); |  | ||||||
|                     deleteGeneration2(globals, j->number); |  | ||||||
|                 } else if (j->creationTime < oldTime) { |  | ||||||
|                     /* We may now start deleting generations, but we don't delete
 |  | ||||||
|                        this generation yet, because this generation was still the |  | ||||||
|                        one that was active at the requested point in time. */ |  | ||||||
|                     canDelete = true; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             int n; |  | ||||||
|             if (!string2Int(*i, n) || n < 0) |  | ||||||
|                 throw UsageError(format("invalid generation specifier ‘%1%’")  % *i); |  | ||||||
|             bool found = false; |  | ||||||
|             for (Generations::iterator j = gens.begin(); j != gens.end(); ++j) { |  | ||||||
|                 if (j->number == n) { |  | ||||||
|                     deleteGeneration2(globals, j->number); |  | ||||||
|                     found = true; |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             if (!found) |  | ||||||
|                 printMsg(lvlError, format("generation %1% does not exist") % n); |  | ||||||
|         } |         } | ||||||
|  |         deleteGenerations(globals.profile, gens, globals.dryRun); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue