* Revived the old "nix-store --delete" operation that deletes the
specified paths from the Nix store. However, this operation is safe: it refuses to delete anything that the garbage collector wouldn't delete.
This commit is contained in:
		
							parent
							
								
									3c5619c7e4
								
							
						
					
					
						commit
						4b9e7f59ca
					
				
					 4 changed files with 45 additions and 11 deletions
				
			
		|  | @ -303,8 +303,8 @@ static Paths topoSort(const PathSet & paths) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| void collectGarbage(GCAction action, PathSet & result, | ||||
|     unsigned long long & bytesFreed) | ||||
| void collectGarbage(GCAction action, const PathSet & pathsToDelete, | ||||
|     PathSet & result, unsigned long long & bytesFreed) | ||||
| { | ||||
|     result.clear(); | ||||
|     bytesFreed = 0; | ||||
|  | @ -398,17 +398,26 @@ void collectGarbage(GCAction action, PathSet & result, | |||
|      | ||||
|     /* Read the Nix store directory to find all currently existing
 | ||||
|        paths. */ | ||||
|     Paths storePaths = readDirectory(nixStore); | ||||
|     PathSet storePaths2; | ||||
|     for (Paths::iterator i = storePaths.begin(); i != storePaths.end(); ++i) | ||||
|         storePaths2.insert(canonPath(nixStore + "/" + *i)); | ||||
|     PathSet storePathSet; | ||||
|     if (action != gcDeleteSpecific) { | ||||
|         Paths entries = readDirectory(nixStore); | ||||
|         for (Paths::iterator i = entries.begin(); i != entries.end(); ++i) | ||||
|             storePathSet.insert(canonPath(nixStore + "/" + *i)); | ||||
|     } else { | ||||
|         for (PathSet::iterator i = pathsToDelete.begin(); | ||||
|              i != pathsToDelete.end(); ++i) | ||||
|         { | ||||
|             assertStorePath(*i); | ||||
|             storePathSet.insert(*i); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /* Topologically sort them under the `referrers' relation.  That
 | ||||
|        is, a < b iff a is in referrers(b).  This gives us the order in | ||||
|        which things can be deleted safely. */ | ||||
|     /* !!! when we have multiple output paths per derivation, this
 | ||||
|        will not work anymore because we get cycles. */ | ||||
|     storePaths = topoSort(storePaths2); | ||||
|     Paths storePaths = topoSort(storePathSet); | ||||
| 
 | ||||
|     /* Try to delete store paths in the topologically sorted order. */ | ||||
|     for (Paths::iterator i = storePaths.begin(); i != storePaths.end(); ++i) { | ||||
|  | @ -416,6 +425,8 @@ void collectGarbage(GCAction action, PathSet & result, | |||
|         debug(format("considering deletion of `%1%'") % *i); | ||||
|          | ||||
|         if (livePaths.find(*i) != livePaths.end()) { | ||||
|             if (action == gcDeleteSpecific) | ||||
|                 throw Error(format("cannot delete path `%1%' since it is still alive") % *i); | ||||
|             debug(format("live path `%1%'") % *i); | ||||
|             continue; | ||||
|         } | ||||
|  | @ -430,7 +441,7 @@ void collectGarbage(GCAction action, PathSet & result, | |||
| 
 | ||||
|         AutoCloseFD fdLock; | ||||
| 
 | ||||
|         if (action == gcDeleteDead) { | ||||
|         if (action == gcDeleteDead || action == gcDeleteSpecific) { | ||||
| 
 | ||||
|             /* Only delete a lock file if we can acquire a write lock
 | ||||
|                on it.  That means that it's either stale, or the | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ typedef enum { | |||
|     gcReturnLive, | ||||
|     gcReturnDead, | ||||
|     gcDeleteDead, | ||||
|     gcDeleteSpecific, | ||||
| } GCAction; | ||||
| 
 | ||||
| /* If `action' is set to `gcReturnRoots', find and return the set of
 | ||||
|  | @ -19,8 +20,8 @@ typedef enum { | |||
|    closure of) the roots.  If `action' is `gcReturnDead', return the | ||||
|    set of paths not reachable from the roots.  If `action' is | ||||
|    `gcDeleteDead', actually delete the latter set. */ | ||||
| void collectGarbage(GCAction action, PathSet & result, | ||||
|     unsigned long long & bytesFreed); | ||||
| void collectGarbage(GCAction action, const PathSet & pathsToDelete, | ||||
|     PathSet & result, unsigned long long & bytesFreed); | ||||
| 
 | ||||
| /* Register a temporary GC root.  This root will automatically
 | ||||
|    disappear when this process exits.  WARNING: this function should | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ Operations: | |||
|   --realise / -r: ensure path validity; if a derivation, ensure that | ||||
|       validity of the outputs | ||||
|   --add / -A: copy a path to the Nix store | ||||
|   --delete: safely delete paths from the Nix store | ||||
|   --query / -q: query information | ||||
| 
 | ||||
|   --register-substitutes: register a substitute expression (dangerous!) | ||||
|  |  | |||
|  | @ -518,7 +518,7 @@ static void opGC(Strings opFlags, Strings opArgs) | |||
| 
 | ||||
|     PathSet result; | ||||
|     PrintFreed freed(action == gcDeleteDead); | ||||
|     collectGarbage(action, result, freed.bytesFreed); | ||||
|     collectGarbage(action, PathSet(), result, freed.bytesFreed); | ||||
| 
 | ||||
|     if (action != gcDeleteDead) { | ||||
|         for (PathSet::iterator i = result.begin(); i != result.end(); ++i) | ||||
|  | @ -527,6 +527,25 @@ static void opGC(Strings opFlags, Strings opArgs) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Remove paths from the Nix store if possible (i.e., if they do not
 | ||||
|    have any remaining referrers and are not reachable from any GC | ||||
|    roots). */ | ||||
| static void opDelete(Strings opFlags, Strings opArgs) | ||||
| { | ||||
|     if (!opFlags.empty()) throw UsageError("unknown flag"); | ||||
| 
 | ||||
|     PathSet pathsToDelete; | ||||
|     for (Strings::iterator i = opArgs.begin(); | ||||
|          i != opArgs.end(); ++i) | ||||
|         pathsToDelete.insert(fixPath(*i)); | ||||
|      | ||||
|     PathSet dummy; | ||||
|     PrintFreed freed(true); | ||||
|     collectGarbage(gcDeleteSpecific, pathsToDelete, | ||||
|         dummy, freed.bytesFreed); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* A sink that writes dump output to stdout. */ | ||||
| struct StdoutSink : DumpSink | ||||
| { | ||||
|  | @ -621,6 +640,8 @@ void run(Strings args) | |||
|             op = opAddFixed; | ||||
|         else if (arg == "--print-fixed-path") | ||||
|             op = opPrintFixedPath; | ||||
|         else if (arg == "--delete") | ||||
|             op = opDelete; | ||||
|         else if (arg == "--query" || arg == "-q") | ||||
|             op = opQuery; | ||||
|         else if (arg == "--register-substitutes") | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue