[Nix-dev] User environment hooks - proposal - review this patch, please

Marc Weber marco-oweber at gmx.de
Thu May 21 10:44:39 CEST 2009


I finally got around implementing a proposal.
Sorry for the bad perl style. I don't know the language very well. :-)

Maybe you can give me some hints how to improve the code?

So what does it do?

  The builder.pl (which can be found in the nix repo) gets passed a list of store
  paths to form a profile (user env) you install by using nix-env ..
  Till now it created all the symlinks. This patch adds additional code which 
  is run at the end of the original builder scanning all paths for
  nix-support/post-profile-hook.  If such a script is found its run and passed
  the profile directory and the list of package paths to be installed.

Very simple example:

    packageList = pkgs.writeTextFile {
      name = "pkgsList";
      executable = true;
      destination = "/nix-support/post-profile-hook";
      text=''
        #!/bin/sh
        profile=$1
        paths=$2
        echo "$paths" > "$profile/all-paths"
      '';
    };

Use cases:
  Create some hooks creating or ammending to
  ~/.nix-prfile/env which you can source in your .bashrc / .zshrc
  exporting stuff like includes, libs, INFOPATH, pkg-config information etc.

  Another use case is create some scripts based on installed packages adding the
  dependencies to various build systems (eg vim, emacs, eclipse-cdt, ..)

Marc Weber

diff --git a/corepkgs/buildenv/builder.pl.in b/corepkgs/buildenv/builder.pl.in
index 9932ea5..78acf18 100755
--- a/corepkgs/buildenv/builder.pl.in
+++ b/corepkgs/buildenv/builder.pl.in
@@ -147,17 +147,45 @@ foreach my $pkg (sort (keys %pkgs)) {
 # installed by the user (i.e., package X declares that it want Y
 # installed as well).  We do these later because they have a lower
 # priority in case of collisions.
+my @allPostponed = ();
 my $priorityCounter = 1000; # don't care about collisions
 while (scalar(keys %postponed) > 0) {
     my @pkgDirs = keys %postponed;
+    @allPostponed = (@allPostponed, @pkgDirs);
     %postponed = ();
     foreach my $pkgDir (sort @pkgDirs) {
         addPkg($pkgDir, $priorityCounter++);
     }
 }
 
+# run post hooks. A post hook is a script 
+# $out/nix-support/post-profile-hook out allUniq
+#   out    : profile dir
+#   allUniq: list of all paths which have already been installed to
+#            the profile
+#
+# post hooks should be unobtrusive. This means: Don't add post-profile hooks
+# to normal derivations. Make them optional so that they must be installed
+# explicitely
+# TODO: think about security
+my @allPkgDirs = (keys %pkgs, @allPostponed);
+
+# get uniq list, is there an easier way?
+my %seen = ();
+my @allUniq = ();
+foreach my $item (@allPkgDirs) {
+    push(@allUniq, $item) unless $seen{$item}++;
+}
 
-print STDERR "created $symlinks symlinks in user environment\n";
+my $numHooks = 0;
+foreach my $path (@allUniq) {
+    my $hook = "$path/nix-support/post-profile-hook";
+    if (-x $hook){
+        system(($hook, $out, "@allUniq")) == 0 or die "profile-post-hook $hook failed with $? ";
+        $numHooks ++;
+    }
+}
 
+print STDERR "created $symlinks symlinks in user environment, $numHooks run\n";
 
 symlink($ENV{"manifest"}, "$out/manifest") or die "cannot create manifest";




More information about the nix-dev mailing list