mirror of
https://github.com/NixOS/nix
synced 2025-07-06 21:41:48 +02:00
* nix-build: use an indirection scheme to make it easier for users to
get rid of GC roots. Nix-build places a symlink `result' in the current directory. Previously, removing that symlink would not remove the store path being linked to as a GC root. Now, the GC root created by nix-build is actually a symlink in `/nix/var/nix/gcroots/auto' to `result'. So if that symlink is removed the GC root automatically becomes invalid (since it can no longer be resolved). The root itself is not automatically removed - the garbage collector should delete dangling roots.
This commit is contained in:
parent
dcc37c236c
commit
630ae0c9d7
7 changed files with 101 additions and 50 deletions
|
@ -13,6 +13,8 @@
|
|||
|
||||
|
||||
static string gcLockName = "gc.lock";
|
||||
static string tempRootsDir = "temproots";
|
||||
static string gcRootsDir = "gcroots";
|
||||
|
||||
|
||||
/* Acquire the global GC lock. This is used to prevent new Nix
|
||||
|
@ -49,40 +51,61 @@ static void createDirs(const Path & path)
|
|||
}
|
||||
|
||||
|
||||
Path addPermRoot(const Path & _storePath, const Path & _gcRoot)
|
||||
void createSymlink(const Path & link, const Path & target, bool careful)
|
||||
{
|
||||
/* Create directories up to `gcRoot'. */
|
||||
createDirs(dirOf(link));
|
||||
|
||||
/* Remove the old symlink. */
|
||||
if (pathExists(link)) {
|
||||
if (careful && (!isLink(link) || !isStorePath(readLink(link))))
|
||||
throw Error(format("cannot create symlink `%1%'; already exists") % link);
|
||||
unlink(link.c_str());
|
||||
}
|
||||
|
||||
/* And create the new own. */
|
||||
if (symlink(target.c_str(), link.c_str()) == -1)
|
||||
throw SysError(format("symlinking `%1%' to `%2%'")
|
||||
% link % target);
|
||||
}
|
||||
|
||||
|
||||
Path addPermRoot(const Path & _storePath, const Path & _gcRoot,
|
||||
bool indirect)
|
||||
{
|
||||
Path storePath(canonPath(_storePath));
|
||||
Path gcRoot(canonPath(_gcRoot));
|
||||
|
||||
Path rootsDir = canonPath((format("%1%/%2%") % nixStateDir % "gcroots").str());
|
||||
|
||||
if (string(gcRoot, 0, rootsDir.size() + 1) != rootsDir + "/")
|
||||
throw Error(format(
|
||||
"path `%1%' is not a valid garbage collector root; "
|
||||
"it's not in the `%1%' directory")
|
||||
% gcRoot % rootsDir);
|
||||
assertStorePath(storePath);
|
||||
|
||||
/* Grab the global GC root. This prevents the set of permanent
|
||||
roots from increasing while a GC is in progress. */
|
||||
AutoCloseFD fdGCLock = openGCLock(ltRead);
|
||||
|
||||
/* Create directories up to `gcRoot'. */
|
||||
createDirs(dirOf(gcRoot));
|
||||
if (indirect) {
|
||||
string hash = printHash32(hashString(htSHA1, gcRoot));
|
||||
Path realRoot = canonPath((format("%1%/%2%/auto/%3%")
|
||||
% nixStateDir % gcRootsDir % hash).str());
|
||||
|
||||
/* Remove the old symlink. */
|
||||
unlink(gcRoot.c_str());
|
||||
createSymlink(gcRoot, storePath, true);
|
||||
createSymlink(realRoot, gcRoot, false);
|
||||
}
|
||||
|
||||
/* And create the new own. */
|
||||
if (symlink(storePath.c_str(), gcRoot.c_str()) == -1)
|
||||
throw SysError(format("symlinking `%1%' to `%2%'")
|
||||
% gcRoot % storePath);
|
||||
else {
|
||||
Path rootsDir = canonPath((format("%1%/%2%") % nixStateDir % gcRootsDir).str());
|
||||
|
||||
if (string(gcRoot, 0, rootsDir.size() + 1) != rootsDir + "/")
|
||||
throw Error(format(
|
||||
"path `%1%' is not a valid garbage collector root; "
|
||||
"it's not in the directory `%2%'")
|
||||
% gcRoot % rootsDir);
|
||||
|
||||
createSymlink(gcRoot, storePath, false);
|
||||
}
|
||||
|
||||
return gcRoot;
|
||||
}
|
||||
|
||||
|
||||
static string tempRootsDir = "temproots";
|
||||
|
||||
/* The file to which we write our temporary roots. */
|
||||
static Path fnTempRoots;
|
||||
static AutoCloseFD fdTempRoots;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue