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) | ||||
| { | ||||
|     /* Hacky. */ | ||||
|  |  | |||
|  | @ -30,11 +30,19 @@ typedef list<Generation> Generations; | |||
| /* Returns the list of currently present generations for the specified
 | ||||
|    profile, sorted by generation number. */ | ||||
| Generations findGenerations(Path profile, int & curGen); | ||||
|      | ||||
| 
 | ||||
| Path createGeneration(Path profile, Path outPath); | ||||
| 
 | ||||
| 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); | ||||
| 
 | ||||
| /* Ensure exclusive access to a profile.  Any command that modifies
 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| #include "store-api.hh" | ||||
| #include "hash.hh" | ||||
| #include "profiles.hh" | ||||
| #include "shared.hh" | ||||
| #include "globals.hh" | ||||
| 
 | ||||
|  | @ -7,7 +7,7 @@ | |||
| 
 | ||||
| using namespace nix; | ||||
| 
 | ||||
| std::string gen = "old"; | ||||
| std::string deleteOlderThan; | ||||
| bool dryRun = false; | ||||
| 
 | ||||
| void runProgramSimple(Path program, const Strings & args) | ||||
|  | @ -49,10 +49,10 @@ void removeOldGenerations(std::string dir) | |||
|             auto link = readLink(path); | ||||
|             if (link.find("link") != string::npos) { | ||||
|                 printMsg(lvlInfo, format("removing old generations of profile %1%") % path); | ||||
| 
 | ||||
|                 auto args = Strings{"-p", path, "--delete-generations", gen}; | ||||
|                 if (dryRun) args.push_back("--dry-run"); | ||||
|                 runProgramSimple(settings.nixBinDir + "/nix-env", args); | ||||
|                 if (deleteOlderThan != "") | ||||
|                     deleteGenerationsOlderThan(path, deleteOlderThan, dryRun); | ||||
|                 else | ||||
|                     deleteOldGenerations(path, dryRun); | ||||
|             } | ||||
|         } else if (type == DT_DIR) { | ||||
|             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-older-than") { | ||||
|                 removeOld = true; | ||||
|                 gen = getArg(*arg, arg, end); | ||||
|                 deleteOlderThan = getArg(*arg, arg, end); | ||||
|             } | ||||
|             else if (*arg == "--dry-run") dryRun = true; | ||||
|             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) | ||||
| { | ||||
|     if (opFlags.size() > 0) | ||||
|         throw UsageError(format("unknown flag ‘%1%’") % opFlags.front()); | ||||
| 
 | ||||
|     PathLocks lock; | ||||
|     lockProfile(lock, globals.profile); | ||||
| 
 | ||||
|     int curGen; | ||||
|     Generations gens = findGenerations(globals.profile, curGen); | ||||
| 
 | ||||
|     for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); ++i) { | ||||
| 
 | ||||
|         if (*i == "old") { | ||||
|             for (Generations::iterator j = gens.begin(); j != gens.end(); ++j) | ||||
|                 if (j->number != curGen) | ||||
|                     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); | ||||
|     if (opArgs.size() == 1 && opArgs.front() == "old") { | ||||
|         deleteOldGenerations(globals.profile, globals.dryRun); | ||||
|     } else if (opArgs.size() == 1 && opArgs.front().find('d') != string::npos) { | ||||
|         deleteGenerationsOlderThan(globals.profile, opArgs.front(), globals.dryRun); | ||||
|     } else { | ||||
|         std::set<unsigned int> gens; | ||||
|         for (auto & i : opArgs) { | ||||
|             unsigned int n; | ||||
|             if (!string2Int(i, n) || n < 0) | ||||
|                 throw UsageError(format("invalid generation number ‘%1%’") % i); | ||||
|             gens.insert(n); | ||||
|         } | ||||
|         deleteGenerations(globals.profile, gens, globals.dryRun); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue