1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-12-02 23:20:59 +01:00
nix/corepkgs/buildenv/builder.pl.in
2007-08-27 13:09:24 +00:00

229 lines
6.9 KiB
Perl
Executable file

#! @perl@ -w
use strict;
use Cwd;
use IO::Handle;
use Fcntl;
STDOUT->autoflush(1);
my $out = $ENV{"out"};
mkdir "$out", 0755 || die "error creating $out";
sub readlink_or_StateWrapper;
my $symlinks = 0;
my %path_state_identifier;
my %path_runtimeArgs;
my $nixBinDir = $ENV{"nixBinDir"};
my $nixStore = $ENV{"nixStore"};
# For each activated package, create symlinks.
sub createLinks {
my $srcDir = shift;
#Lookup each $stateIdentifiers in $path_state_identifier
#we strip $srcDir to its rootdir e.g. /nix/store/......./
my @srcDirParts = split /\// , substr($srcDir, length ($nixStore), length ($srcDir));
my $srcDirRoot = $nixStore . "/" . $srcDirParts[1];
# print "srcDirRoot $srcDirRoot \n";
my $pkgStateIdentifier = $path_state_identifier{$srcDirRoot};
my $pkgRuntimeStateArgs = $path_runtimeArgs{$srcDirRoot};
my $dstDir = shift;
my $ignoreCollisions = shift;
# print "createLinks $srcDir to $dstDir with iden $pkgStateIdentifier \n";
my @srcFiles = glob("$srcDir/*");
foreach my $srcFile (@srcFiles) {
my $baseName = $srcFile;
$baseName =~ s/^.*\///g; # strip directory
my $dstFile = "$dstDir/$baseName";
# Urgh, hacky...
if ($srcFile =~ /\/propagated-build-inputs$/ ||
$srcFile =~ /\/nix-support$/ ||
$srcFile =~ /\/perllocal.pod$/ ||
$srcFile =~ /\/info\/dir$/ ||
$srcFile =~ /\/log$/)
{
# Do nothing.
}
elsif (-d $srcFile) {
lstat $dstFile;
#go recursive on directorys
if (-d _) {
createLinks($srcFile, $dstFile, $ignoreCollisions);
}
elsif (-l _) {
my $target = readlink $dstFile or die;
if (!-d $target) {
die "collission between directory `$srcFile' and non-directory `$target'";
}
unlink $dstFile or die "error unlinking `$dstFile': $!";
mkdir $dstFile, 0755 || die "error creating directory `$dstFile': $!";
createLinks($target, $dstFile, $ignoreCollisions);
createLinks($srcFile, $dstFile, $ignoreCollisions);
}
else {
# print "1STLINK $srcFile to $dstFile with iden $pkgStateIdentifier \n";
symlink($srcFile, $dstFile) ||
die "error creating link `$dstFile': $!";
$symlinks++;
}
}
else {
# print "ELSE LINK $srcFile to $dstFile with iden $pkgStateIdentifier \n";
# if we have .....
if($pkgStateIdentifier ne "__NOSTATE__" && $pkgStateIdentifier ne ""){
my @pathparts = split /\// , $srcFile;
my $parentDir = $pathparts[scalar(@pathparts) - 2];
if( $parentDir eq "bin" || $parentDir eq "sbin"){ #hacky....
print "STATELINK $srcFile to $dstFile - $pkgStateIdentifier \n";
my $new_dstFile;
my $new_stateIdentifier;
if($pkgStateIdentifier eq "__EMTPY__"){
$new_dstFile = $dstFile;
$new_stateIdentifier = "";
}
else{
$new_dstFile = "$dstFile-$pkgStateIdentifier";
$new_stateIdentifier = $pkgStateIdentifier;
}
# We also check with -e if the wrapperscript-file exists, and if is it a symlink (with -l)
if (-l $new_dstFile || -e $new_dstFile) {
if (!$ignoreCollisions) {
my $target = readlink_or_StateWrapper $new_dstFile;
die "(state) collission between `$srcFile' and `$target' (over $new_dstFile)";
}
}
sysopen (DSTFILEHANDLE, $new_dstFile, O_RDWR|O_EXCL|O_CREAT, 0755);
printf DSTFILEHANDLE "#! @shell@ \n";
if($pkgRuntimeStateArgs eq "__NOARGS__"){
printf DSTFILEHANDLE "$nixBinDir/nix-state --run --identifier=$new_stateIdentifier $srcFile \"\$@\" \n";
}
else{
printf DSTFILEHANDLE "$nixBinDir/nix-state --run --identifier=$new_stateIdentifier $srcFile \"\$@\" $pkgRuntimeStateArgs \n";
} # TODO, maybe first R.T.A. then other args ?
close (DSTFILEHANDLE);
}
}
else{
if (-l $dstFile || -e $dstFile) {
if (!$ignoreCollisions) {
my $target = readlink_or_StateWrapper $dstFile;
die "collission between `$srcFile' and `$target'";
}
}
symlink($srcFile, $dstFile) ||
die "error creating link `$dstFile': $!";
$symlinks++;
}
}
}
}
my %done;
my %postponed;
sub addPkg;
sub addPkg {
my $pkgDir = shift;
my $ignoreCollisions = shift;
return if (defined $done{$pkgDir});
$done{$pkgDir} = 1;
# print "symlinking $pkgDir\n";
createLinks("$pkgDir", "$out", $ignoreCollisions);
my $propagatedFN = "$pkgDir/nix-support/propagated-user-env-packages";
if (-e $propagatedFN) {
open PROP, "<$propagatedFN" or die;
my $propagated = <PROP>;
close PROP;
my @propagated = split ' ', $propagated;
foreach my $p (@propagated) {
$postponed{$p} = 1 unless defined $done{$p};
}
}
}
sub readlink_or_StateWrapper {
my $src = shift;
my $target;
if (-l $src)
{ $target = readlink $src; }
else{
open(DAT, $src) || die("Could not open file!");
my @raw_data=<DAT>;
close(DAT);
$target = $raw_data[1];
}
return $target
}
# Symlink to the packages that have been installed explicitly by the user.
my @storePaths = split ' ', $ENV{"derivations"};
my @stateIdentifiers = split ' ', $ENV{"stateIdentifiers"};
my @runtimeStateArgs = split ' ', $ENV{"runtimeStateArgs_arg"};
my $si_counter = 0;
foreach my $pkgDir (@storePaths) { #Commented the sort out
#Link each $pkgDir to a $stateIdentifiers in $path_state_identifier
$path_state_identifier{$pkgDir} = $stateIdentifiers[$si_counter];
$path_runtimeArgs{$pkgDir} = $runtimeStateArgs[$si_counter];
# print "SP: $pkgDir \n";
# print "SI: $path_state_identifier{$pkgDir} \n";
# print "RT: $path_runtimeArgs{$pkgDir} \n";
addPkg($pkgDir, 0);
$si_counter++;
}
# Symlink to the packages that have been "propagated" by packages
# 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.
while (scalar(keys %postponed) > 0) {
my @pkgDirs = keys %postponed;
%postponed = ();
foreach my $pkgDir (sort @pkgDirs) {
addPkg($pkgDir, 1);
}
}
print STDERR "created $symlinks symlinks in user environment\n";
symlink($ENV{"manifest"}, "$out/manifest") or die "cannot create manifest";