aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libstore/build.cc1
-rw-r--r--src/libstore/builtins.hh1
-rw-r--r--src/libstore/builtins/buildenv.cc120
-rw-r--r--src/libstore/builtins/buildenv.hh21
4 files changed, 77 insertions, 66 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index cdf848c98..1b27d7af0 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -6,6 +6,7 @@
#include "archive.hh"
#include "affinity.hh"
#include "builtins.hh"
+#include "builtins/buildenv.hh"
#include "download.hh"
#include "finally.hh"
#include "compression.hh"
diff --git a/src/libstore/builtins.hh b/src/libstore/builtins.hh
index 0d2da873e..f9b5f7900 100644
--- a/src/libstore/builtins.hh
+++ b/src/libstore/builtins.hh
@@ -6,6 +6,5 @@ namespace nix {
// TODO: make pluggable.
void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData);
-void builtinBuildenv(const BasicDerivation & drv);
}
diff --git a/src/libstore/builtins/buildenv.cc b/src/libstore/builtins/buildenv.cc
index 096593886..c1c85d0bf 100644
--- a/src/libstore/builtins/buildenv.cc
+++ b/src/libstore/builtins/buildenv.cc
@@ -1,4 +1,4 @@
-#include "builtins.hh"
+#include "buildenv.hh"
#include <sys/stat.h>
#include <sys/types.h>
@@ -7,16 +7,14 @@
namespace nix {
-typedef std::map<Path,int> Priorities;
-
-// FIXME: change into local variables.
-
-static Priorities priorities;
-
-static unsigned long symlinks;
+struct State
+{
+ std::map<Path, int> priorities;
+ unsigned long symlinks = 0;
+};
/* For each activated package, create symlinks */
-static void createLinks(const Path & srcDir, const Path & dstDir, int priority)
+static void createLinks(State & state, const Path & srcDir, const Path & dstDir, int priority)
{
DirEntries srcFiles;
@@ -67,7 +65,7 @@ static void createLinks(const Path & srcDir, const Path & dstDir, int priority)
auto res = lstat(dstFile.c_str(), &dstSt);
if (res == 0) {
if (S_ISDIR(dstSt.st_mode)) {
- createLinks(srcFile, dstFile, priority);
+ createLinks(state, srcFile, dstFile, priority);
continue;
} else if (S_ISLNK(dstSt.st_mode)) {
auto target = canonPath(dstFile, true);
@@ -77,8 +75,8 @@ static void createLinks(const Path & srcDir, const Path & dstDir, int priority)
throw SysError(format("unlinking '%1%'") % dstFile);
if (mkdir(dstFile.c_str(), 0755) == -1)
throw SysError(format("creating directory '%1%'"));
- createLinks(target, dstFile, priorities[dstFile]);
- createLinks(srcFile, dstFile, priority);
+ createLinks(state, target, dstFile, state.priorities[dstFile]);
+ createLinks(state, srcFile, dstFile, priority);
continue;
}
} else if (errno != ENOENT)
@@ -90,7 +88,7 @@ static void createLinks(const Path & srcDir, const Path & dstDir, int priority)
auto res = lstat(dstFile.c_str(), &dstSt);
if (res == 0) {
if (S_ISLNK(dstSt.st_mode)) {
- auto prevPriority = priorities[dstFile];
+ auto prevPriority = state.priorities[dstFile];
if (prevPriority == priority)
throw Error(
"packages '%1%' and '%2%' have the same priority %3%; "
@@ -109,41 +107,57 @@ static void createLinks(const Path & srcDir, const Path & dstDir, int priority)
}
createSymlink(srcFile, dstFile);
- priorities[dstFile] = priority;
- symlinks++;
+ state.priorities[dstFile] = priority;
+ state.symlinks++;
}
}
-typedef std::set<Path> FileProp;
+void buildProfile(const Path & out, Packages && pkgs)
+{
+ State state;
-static FileProp done;
-static FileProp postponed = FileProp{};
+ std::set<Path> done, postponed;
-static Path out;
+ auto addPkg = [&](const Path & pkgDir, int priority) {
+ if (!done.insert(pkgDir).second) return;
+ createLinks(state, pkgDir, out, priority);
-static void addPkg(const Path & pkgDir, int priority)
-{
- if (!done.insert(pkgDir).second) return;
- createLinks(pkgDir, out, priority);
+ try {
+ for (const auto & p : tokenizeString<std::vector<string>>(
+ readFile(pkgDir + "/nix-support/propagated-user-env-packages"), " \n"))
+ if (!done.count(p))
+ postponed.insert(p);
+ } catch (SysError & e) {
+ if (e.errNo != ENOENT && e.errNo != ENOTDIR) throw;
+ }
+ };
- try {
- for (const auto & p : tokenizeString<std::vector<string>>(
- readFile(pkgDir + "/nix-support/propagated-user-env-packages"), " \n"))
- if (!done.count(p))
- postponed.insert(p);
- } catch (SysError & e) {
- if (e.errNo != ENOENT && e.errNo != ENOTDIR) throw;
- }
-}
+ /* Symlink to the packages that have been installed explicitly by the
+ * user. Process in priority order to reduce unnecessary
+ * symlink/unlink steps.
+ */
+ std::sort(pkgs.begin(), pkgs.end(), [](const Package & a, const Package & b) {
+ return a.priority < b.priority || (a.priority == b.priority && a.path < b.path);
+ });
+ for (const auto & pkg : pkgs)
+ if (pkg.active)
+ addPkg(pkg.path, pkg.priority);
-struct Package {
- Path path;
- bool active;
- int priority;
- Package(Path path, bool active, int priority) : path{path}, active{active}, priority{priority} {}
-};
+ /* Symlink to the packages that have been "propagated" by packages
+ * installed by the user (i.e., package X declares that it wants Y
+ * installed as well). We do these later because they have a lower
+ * priority in case of collisions.
+ */
+ auto priorityCounter = 1000;
+ while (!postponed.empty()) {
+ std::set<Path> pkgDirs;
+ postponed.swap(pkgDirs);
+ for (const auto & pkgDir : pkgDirs)
+ addPkg(pkgDir, priorityCounter++);
+ }
-typedef std::vector<Package> Packages;
+ printError("created %d symlinks in user environment", state.symlinks);
+}
void builtinBuildenv(const BasicDerivation & drv)
{
@@ -153,7 +167,7 @@ void builtinBuildenv(const BasicDerivation & drv)
return i->second;
};
- out = getAttr("out");
+ Path out = getAttr("out");
createDirs(out);
/* Convert the stuff we get from the environment back into a
@@ -171,31 +185,7 @@ void builtinBuildenv(const BasicDerivation & drv)
}
}
- /* Symlink to the packages that have been installed explicitly by the
- * user. Process in priority order to reduce unnecessary
- * symlink/unlink steps.
- */
- std::sort(pkgs.begin(), pkgs.end(), [](const Package & a, const Package & b) {
- return a.priority < b.priority || (a.priority == b.priority && a.path < b.path);
- });
- for (const auto & pkg : pkgs)
- if (pkg.active)
- addPkg(pkg.path, pkg.priority);
-
- /* Symlink to the packages that have been "propagated" by packages
- * installed by the user (i.e., package X declares that it wants Y
- * installed as well). We do these later because they have a lower
- * priority in case of collisions.
- */
- auto priorityCounter = 1000;
- while (!postponed.empty()) {
- auto pkgDirs = postponed;
- postponed = FileProp{};
- for (const auto & pkgDir : pkgDirs)
- addPkg(pkgDir, priorityCounter++);
- }
-
- printError("created %d symlinks in user environment", symlinks);
+ buildProfile(out, std::move(pkgs));
createSymlink(getAttr("manifest"), out + "/manifest.nix");
}
diff --git a/src/libstore/builtins/buildenv.hh b/src/libstore/builtins/buildenv.hh
new file mode 100644
index 000000000..0a37459b0
--- /dev/null
+++ b/src/libstore/builtins/buildenv.hh
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "derivations.hh"
+#include "store-api.hh"
+
+namespace nix {
+
+struct Package {
+ Path path;
+ bool active;
+ int priority;
+ Package(Path path, bool active, int priority) : path{path}, active{active}, priority{priority} {}
+};
+
+typedef std::vector<Package> Packages;
+
+void buildProfile(const Path & out, Packages && pkgs);
+
+void builtinBuildenv(const BasicDerivation & drv);
+
+}