Remove trailing whitespace / tabs
This commit is contained in:
		
							parent
							
								
									7f8e805c8e
								
							
						
					
					
						commit
						b4ea83249b
					
				
					 2 changed files with 147 additions and 147 deletions
				
			
		| 
						 | 
					@ -35,7 +35,7 @@ my $caBundle = $ENV{"CURL_CA_BUNDLE"} // $ENV{"OPENSSL_X509_CERT_FILE"};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub addRequest {
 | 
					sub addRequest {
 | 
				
			||||||
    my ($storePath, $url, $head) = @_;
 | 
					    my ($storePath, $url, $head) = @_;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    my $curl = WWW::Curl::Easy->new;
 | 
					    my $curl = WWW::Curl::Easy->new;
 | 
				
			||||||
    my $curlId = $curlIdCount++;
 | 
					    my $curlId = $curlIdCount++;
 | 
				
			||||||
    $requests{$curlId} = { storePath => $storePath, url => $url, handle => $curl, content => "", type => $head ? "HEAD" : "GET" };
 | 
					    $requests{$curlId} = { storePath => $storePath, url => $url, handle => $curl, content => "", type => $head ? "HEAD" : "GET" };
 | 
				
			||||||
| 
						 | 
					@ -69,7 +69,7 @@ sub processRequests {
 | 
				
			||||||
        if (scalar @{$rfds} + scalar @{$wfds} + scalar @{$efds} > 0) {
 | 
					        if (scalar @{$rfds} + scalar @{$wfds} + scalar @{$efds} > 0) {
 | 
				
			||||||
            IO::Select->select(IO::Select->new(@{$rfds}), IO::Select->new(@{$wfds}), IO::Select->new(@{$efds}), 0.1);
 | 
					            IO::Select->select(IO::Select->new(@{$rfds}), IO::Select->new(@{$wfds}), IO::Select->new(@{$efds}), 0.1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        if ($curlm->perform() != $activeRequests) {
 | 
					        if ($curlm->perform() != $activeRequests) {
 | 
				
			||||||
            while (my ($id, $result) = $curlm->info_read) {
 | 
					            while (my ($id, $result) = $curlm->info_read) {
 | 
				
			||||||
                if ($id) {
 | 
					                if ($id) {
 | 
				
			||||||
| 
						 | 
					@ -77,9 +77,9 @@ sub processRequests {
 | 
				
			||||||
                    my $handle = $request->{handle};
 | 
					                    my $handle = $request->{handle};
 | 
				
			||||||
                    $request->{result} = $result;
 | 
					                    $request->{result} = $result;
 | 
				
			||||||
                    $request->{httpStatus} = $handle->getinfo(CURLINFO_RESPONSE_CODE);
 | 
					                    $request->{httpStatus} = $handle->getinfo(CURLINFO_RESPONSE_CODE);
 | 
				
			||||||
                    
 | 
					
 | 
				
			||||||
                    print STDERR "$request->{type} on $request->{url} [$request->{result}, $request->{httpStatus}]\n" if $debug;
 | 
					                    print STDERR "$request->{type} on $request->{url} [$request->{result}, $request->{httpStatus}]\n" if $debug;
 | 
				
			||||||
                    
 | 
					
 | 
				
			||||||
                    $activeRequests--;
 | 
					                    $activeRequests--;
 | 
				
			||||||
                    delete $request->{handle};
 | 
					                    delete $request->{handle};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -115,7 +115,7 @@ sub initCache {
 | 
				
			||||||
            url       text unique not null
 | 
					            url       text unique not null
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
EOF
 | 
					EOF
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    $dbh->do(<<EOF);
 | 
					    $dbh->do(<<EOF);
 | 
				
			||||||
        create table if not exists NARs (
 | 
					        create table if not exists NARs (
 | 
				
			||||||
            cache            integer not null,
 | 
					            cache            integer not null,
 | 
				
			||||||
| 
						 | 
					@ -179,7 +179,7 @@ sub positiveHit {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub processNARInfo {
 | 
					sub processNARInfo {
 | 
				
			||||||
    my ($storePath, $binaryCacheUrl, $request) = @_;
 | 
					    my ($storePath, $binaryCacheUrl, $request) = @_;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    my $cacheId = getCacheId($binaryCacheUrl);
 | 
					    my $cacheId = getCacheId($binaryCacheUrl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ($request->{result} != 0) {
 | 
					    if ($request->{result} != 0) {
 | 
				
			||||||
| 
						 | 
					@ -192,7 +192,7 @@ sub processNARInfo {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return undef;
 | 
					        return undef;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    my ($storePath2, $url, $fileHash, $fileSize, $narHash, $narSize, $deriver, $system);
 | 
					    my ($storePath2, $url, $fileHash, $fileSize, $narHash, $narSize, $deriver, $system);
 | 
				
			||||||
    my $compression = "bzip2";
 | 
					    my $compression = "bzip2";
 | 
				
			||||||
    my @refs;
 | 
					    my @refs;
 | 
				
			||||||
| 
						 | 
					@ -219,13 +219,13 @@ sub processNARInfo {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # FIXME: validate $url etc. for security.
 | 
					    # FIXME: validate $url etc. for security.
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    # Cache the result.
 | 
					    # Cache the result.
 | 
				
			||||||
    $insertNAR->execute(
 | 
					    $insertNAR->execute(
 | 
				
			||||||
        $cacheId, basename($storePath), $url, $compression, $fileHash, $fileSize,
 | 
					        $cacheId, basename($storePath), $url, $compression, $fileHash, $fileSize,
 | 
				
			||||||
        $narHash, $narSize, join(" ", @refs), $deriver, $system, time())
 | 
					        $narHash, $narSize, join(" ", @refs), $deriver, $system, time())
 | 
				
			||||||
        unless $request->{url} =~ /^file:/;
 | 
					        unless $request->{url} =~ /^file:/;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    return
 | 
					    return
 | 
				
			||||||
        { url => $url
 | 
					        { url => $url
 | 
				
			||||||
        , compression => $compression
 | 
					        , compression => $compression
 | 
				
			||||||
| 
						 | 
					@ -242,10 +242,10 @@ sub processNARInfo {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub getCacheId {
 | 
					sub getCacheId {
 | 
				
			||||||
    my ($binaryCacheUrl) = @_;
 | 
					    my ($binaryCacheUrl) = @_;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    my $cacheId = $cacheIds{$binaryCacheUrl};
 | 
					    my $cacheId = $cacheIds{$binaryCacheUrl};
 | 
				
			||||||
    return $cacheId if defined $cacheId;
 | 
					    return $cacheId if defined $cacheId;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    # FIXME: not atomic.
 | 
					    # FIXME: not atomic.
 | 
				
			||||||
    my @res = @{$dbh->selectcol_arrayref("select id from BinaryCaches where url = ?", {}, $binaryCacheUrl)};
 | 
					    my @res = @{$dbh->selectcol_arrayref("select id from BinaryCaches where url = ?", {}, $binaryCacheUrl)};
 | 
				
			||||||
    if (scalar @res == 1) {
 | 
					    if (scalar @res == 1) {
 | 
				
			||||||
| 
						 | 
					@ -267,8 +267,8 @@ sub getCachedInfoFrom {
 | 
				
			||||||
    $queryNAR->execute(getCacheId($binaryCacheUrl), basename($storePath));
 | 
					    $queryNAR->execute(getCacheId($binaryCacheUrl), basename($storePath));
 | 
				
			||||||
    my $res = $queryNAR->fetchrow_hashref();
 | 
					    my $res = $queryNAR->fetchrow_hashref();
 | 
				
			||||||
    return undef unless defined $res;
 | 
					    return undef unless defined $res;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    return 
 | 
					    return
 | 
				
			||||||
        { url => $res->{url}
 | 
					        { url => $res->{url}
 | 
				
			||||||
        , compression => $res->{compression}
 | 
					        , compression => $res->{compression}
 | 
				
			||||||
        , fileHash => $res->{fileHash}
 | 
					        , fileHash => $res->{fileHash}
 | 
				
			||||||
| 
						 | 
					@ -379,7 +379,7 @@ sub printSubstitutablePaths {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            addRequest($storePath, infoUrl($binaryCacheUrl, $storePath), 1);
 | 
					            addRequest($storePath, infoUrl($binaryCacheUrl, $storePath), 1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        processRequests;
 | 
					        processRequests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach my $request (values %requests) {
 | 
					        foreach my $request (values %requests) {
 | 
				
			||||||
| 
						 | 
					@ -406,7 +406,7 @@ sub printSubstitutablePaths {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub downloadBinary {
 | 
					sub downloadBinary {
 | 
				
			||||||
    my ($storePath) = @_;
 | 
					    my ($storePath) = @_;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    foreach my $binaryCacheUrl (@binaryCacheUrls) {
 | 
					    foreach my $binaryCacheUrl (@binaryCacheUrls) {
 | 
				
			||||||
        my $info = getCachedInfoFrom($storePath, $binaryCacheUrl);
 | 
					        my $info = getCachedInfoFrom($storePath, $binaryCacheUrl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -418,7 +418,7 @@ sub downloadBinary {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        next unless defined $info;
 | 
					        next unless defined $info;
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        my $decompressor;
 | 
					        my $decompressor;
 | 
				
			||||||
        if ($info->{compression} eq "bzip2") { $decompressor = "$Nix::Config::bzip2 -d"; }
 | 
					        if ($info->{compression} eq "bzip2") { $decompressor = "$Nix::Config::bzip2 -d"; }
 | 
				
			||||||
        elsif ($info->{compression} eq "xz") { $decompressor = "$Nix::Config::xz -d"; }
 | 
					        elsif ($info->{compression} eq "xz") { $decompressor = "$Nix::Config::xz -d"; }
 | 
				
			||||||
| 
						 | 
					@ -455,7 +455,7 @@ if ($ARGV[0] eq "--query") {
 | 
				
			||||||
    while (<STDIN>) {
 | 
					    while (<STDIN>) {
 | 
				
			||||||
        chomp;
 | 
					        chomp;
 | 
				
			||||||
        my ($cmd, @args) = split " ", $_;
 | 
					        my ($cmd, @args) = split " ", $_;
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        if ($cmd eq "have") {
 | 
					        if ($cmd eq "have") {
 | 
				
			||||||
            printSubstitutablePaths(@args);
 | 
					            printSubstitutablePaths(@args);
 | 
				
			||||||
            print "\n";
 | 
					            print "\n";
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,7 +64,7 @@
 | 
				
			||||||
namespace nix {
 | 
					namespace nix {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using std::map;
 | 
					using std::map;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static string pathNullDevice = "/dev/null";
 | 
					static string pathNullDevice = "/dev/null";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -95,9 +95,9 @@ class Goal : public boost::enable_shared_from_this<Goal>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    typedef enum {ecBusy, ecSuccess, ecFailed, ecNoSubstituters} ExitCode;
 | 
					    typedef enum {ecBusy, ecSuccess, ecFailed, ecNoSubstituters} ExitCode;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* Backlink to the worker. */
 | 
					    /* Backlink to the worker. */
 | 
				
			||||||
    Worker & worker;
 | 
					    Worker & worker;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -155,7 +155,7 @@ public:
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return name;
 | 
					        return name;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    ExitCode getExitCode()
 | 
					    ExitCode getExitCode()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return exitCode;
 | 
					        return exitCode;
 | 
				
			||||||
| 
						 | 
					@ -217,7 +217,7 @@ private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Goals waiting for busy paths to be unlocked. */
 | 
					    /* Goals waiting for busy paths to be unlocked. */
 | 
				
			||||||
    WeakGoals waitingForAnyGoal;
 | 
					    WeakGoals waitingForAnyGoal;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* Goals sleeping for a few seconds (polling a lock). */
 | 
					    /* Goals sleeping for a few seconds (polling a lock). */
 | 
				
			||||||
    WeakGoals waitingForAWhile;
 | 
					    WeakGoals waitingForAWhile;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -238,7 +238,7 @@ public:
 | 
				
			||||||
    LocalStore & store;
 | 
					    LocalStore & store;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    boost::shared_ptr<HookInstance> hook;
 | 
					    boost::shared_ptr<HookInstance> hook;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    Worker(LocalStore & store);
 | 
					    Worker(LocalStore & store);
 | 
				
			||||||
    ~Worker();
 | 
					    ~Worker();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -275,13 +275,13 @@ public:
 | 
				
			||||||
    /* Wait for any goal to finish.  Pretty indiscriminate way to
 | 
					    /* Wait for any goal to finish.  Pretty indiscriminate way to
 | 
				
			||||||
       wait for some resource that some other goal is holding. */
 | 
					       wait for some resource that some other goal is holding. */
 | 
				
			||||||
    void waitForAnyGoal(GoalPtr goal);
 | 
					    void waitForAnyGoal(GoalPtr goal);
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* Wait for a few seconds and then retry this goal.  Used when
 | 
					    /* Wait for a few seconds and then retry this goal.  Used when
 | 
				
			||||||
       waiting for a lock held by another process.  This kind of
 | 
					       waiting for a lock held by another process.  This kind of
 | 
				
			||||||
       polling is inefficient, but POSIX doesn't really provide a way
 | 
					       polling is inefficient, but POSIX doesn't really provide a way
 | 
				
			||||||
       to wait for multiple locks in the main select() loop. */
 | 
					       to wait for multiple locks in the main select() loop. */
 | 
				
			||||||
    void waitForAWhile(GoalPtr goal);
 | 
					    void waitForAWhile(GoalPtr goal);
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* Loop until the specified top-level goals have finished. */
 | 
					    /* Loop until the specified top-level goals have finished. */
 | 
				
			||||||
    void run(const Goals & topGoals);
 | 
					    void run(const Goals & topGoals);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -309,11 +309,11 @@ void Goal::waiteeDone(GoalPtr waitee, ExitCode result)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    trace(format("waitee `%1%' done; %2% left") %
 | 
					    trace(format("waitee `%1%' done; %2% left") %
 | 
				
			||||||
        waitee->name % waitees.size());
 | 
					        waitee->name % waitees.size());
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    if (result == ecFailed || result == ecNoSubstituters) ++nrFailed;
 | 
					    if (result == ecFailed || result == ecNoSubstituters) ++nrFailed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (result == ecNoSubstituters) ++nrNoSubstituters;
 | 
					    if (result == ecNoSubstituters) ++nrNoSubstituters;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    if (waitees.empty() || (result == ecFailed && !keepGoing)) {
 | 
					    if (waitees.empty() || (result == ecFailed && !keepGoing)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* If we failed and keepGoing is not set, we remove all
 | 
					        /* If we failed and keepGoing is not set, we remove all
 | 
				
			||||||
| 
						 | 
					@ -366,12 +366,12 @@ void commonChildInit(Pipe & logPipe)
 | 
				
			||||||
       terminal signals. */
 | 
					       terminal signals. */
 | 
				
			||||||
    if (setsid() == -1)
 | 
					    if (setsid() == -1)
 | 
				
			||||||
        throw SysError(format("creating a new session"));
 | 
					        throw SysError(format("creating a new session"));
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* Dup the write side of the logger pipe into stderr. */
 | 
					    /* Dup the write side of the logger pipe into stderr. */
 | 
				
			||||||
    if (dup2(logPipe.writeSide, STDERR_FILENO) == -1)
 | 
					    if (dup2(logPipe.writeSide, STDERR_FILENO) == -1)
 | 
				
			||||||
        throw SysError("cannot pipe standard error into log file");
 | 
					        throw SysError("cannot pipe standard error into log file");
 | 
				
			||||||
    logPipe.readSide.close();
 | 
					    logPipe.readSide.close();
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
    /* Dup stderr to stdout. */
 | 
					    /* Dup stderr to stdout. */
 | 
				
			||||||
    if (dup2(STDERR_FILENO, STDOUT_FILENO) == -1)
 | 
					    if (dup2(STDERR_FILENO, STDOUT_FILENO) == -1)
 | 
				
			||||||
        throw SysError("cannot dup stderr into stdout");
 | 
					        throw SysError("cannot dup stderr into stdout");
 | 
				
			||||||
| 
						 | 
					@ -400,7 +400,7 @@ const char * * strings2CharPtrs(const Strings & ss)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Restore default handling of SIGPIPE, otherwise some programs will
 | 
					/* Restore default handling of SIGPIPE, otherwise some programs will
 | 
				
			||||||
   randomly say "Broken pipe". */
 | 
					   randomly say "Broken pipe". */
 | 
				
			||||||
static void restoreSIGPIPE() 
 | 
					static void restoreSIGPIPE()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    struct sigaction act, oact;
 | 
					    struct sigaction act, oact;
 | 
				
			||||||
    act.sa_handler = SIG_DFL;
 | 
					    act.sa_handler = SIG_DFL;
 | 
				
			||||||
| 
						 | 
					@ -427,7 +427,7 @@ private:
 | 
				
			||||||
    string user;
 | 
					    string user;
 | 
				
			||||||
    uid_t uid;
 | 
					    uid_t uid;
 | 
				
			||||||
    gid_t gid;
 | 
					    gid_t gid;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    UserLock();
 | 
					    UserLock();
 | 
				
			||||||
    ~UserLock();
 | 
					    ~UserLock();
 | 
				
			||||||
| 
						 | 
					@ -442,7 +442,7 @@ public:
 | 
				
			||||||
    uid_t getGID() { return gid; }
 | 
					    uid_t getGID() { return gid; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool enabled() { return uid != 0; }
 | 
					    bool enabled() { return uid != 0; }
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -497,13 +497,13 @@ void UserLock::acquire()
 | 
				
			||||||
                % *i % buildUsersGroup);
 | 
					                % *i % buildUsersGroup);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        createDirs(nixStateDir + "/userpool");
 | 
					        createDirs(nixStateDir + "/userpool");
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        fnUserLock = (format("%1%/userpool/%2%") % nixStateDir % pw->pw_uid).str();
 | 
					        fnUserLock = (format("%1%/userpool/%2%") % nixStateDir % pw->pw_uid).str();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (lockedPaths.find(fnUserLock) != lockedPaths.end())
 | 
					        if (lockedPaths.find(fnUserLock) != lockedPaths.end())
 | 
				
			||||||
            /* We already have a lock on this one. */
 | 
					            /* We already have a lock on this one. */
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        AutoCloseFD fd = open(fnUserLock.c_str(), O_RDWR | O_CREAT, 0600);
 | 
					        AutoCloseFD fd = open(fnUserLock.c_str(), O_RDWR | O_CREAT, 0600);
 | 
				
			||||||
        if (fd == -1)
 | 
					        if (fd == -1)
 | 
				
			||||||
            throw SysError(format("opening user lock `%1%'") % fnUserLock);
 | 
					            throw SysError(format("opening user lock `%1%'") % fnUserLock);
 | 
				
			||||||
| 
						 | 
					@ -519,7 +519,7 @@ void UserLock::acquire()
 | 
				
			||||||
            if (uid == getuid() || uid == geteuid())
 | 
					            if (uid == getuid() || uid == geteuid())
 | 
				
			||||||
                throw Error(format("the Nix user should not be a member of `%1%'")
 | 
					                throw Error(format("the Nix user should not be a member of `%1%'")
 | 
				
			||||||
                    % buildUsersGroup);
 | 
					                    % buildUsersGroup);
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -546,7 +546,7 @@ static void runSetuidHelper(const string & command,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Path program = getEnv("NIX_SETUID_HELPER",
 | 
					    Path program = getEnv("NIX_SETUID_HELPER",
 | 
				
			||||||
        nixLibexecDir + "/nix-setuid-helper");
 | 
					        nixLibexecDir + "/nix-setuid-helper");
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
    /* Fork. */
 | 
					    /* Fork. */
 | 
				
			||||||
    Pid pid;
 | 
					    Pid pid;
 | 
				
			||||||
    pid = fork();
 | 
					    pid = fork();
 | 
				
			||||||
| 
						 | 
					@ -564,7 +564,7 @@ static void runSetuidHelper(const string & command,
 | 
				
			||||||
            args.push_back(0);
 | 
					            args.push_back(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            restoreSIGPIPE();
 | 
					            restoreSIGPIPE();
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
            execve(program.c_str(), (char * *) &args[0], 0);
 | 
					            execve(program.c_str(), (char * *) &args[0], 0);
 | 
				
			||||||
            throw SysError(format("executing `%1%'") % program);
 | 
					            throw SysError(format("executing `%1%'") % program);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -650,7 +650,7 @@ struct HookInstance
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Pipe for the builder's standard output/error. */
 | 
					    /* Pipe for the builder's standard output/error. */
 | 
				
			||||||
    Pipe builderOut;
 | 
					    Pipe builderOut;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* The process ID of the hook. */
 | 
					    /* The process ID of the hook. */
 | 
				
			||||||
    Pid pid;
 | 
					    Pid pid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -663,12 +663,12 @@ struct HookInstance
 | 
				
			||||||
HookInstance::HookInstance()
 | 
					HookInstance::HookInstance()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    debug("starting build hook");
 | 
					    debug("starting build hook");
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    Path buildHook = absPath(getEnv("NIX_BUILD_HOOK"));
 | 
					    Path buildHook = absPath(getEnv("NIX_BUILD_HOOK"));
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* Create a pipe to get the output of the child. */
 | 
					    /* Create a pipe to get the output of the child. */
 | 
				
			||||||
    fromHook.create();
 | 
					    fromHook.create();
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* Create the communication pipes. */
 | 
					    /* Create the communication pipes. */
 | 
				
			||||||
    toHook.create();
 | 
					    toHook.create();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -678,7 +678,7 @@ HookInstance::HookInstance()
 | 
				
			||||||
    /* Fork the hook. */
 | 
					    /* Fork the hook. */
 | 
				
			||||||
    pid = fork();
 | 
					    pid = fork();
 | 
				
			||||||
    switch (pid) {
 | 
					    switch (pid) {
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
    case -1:
 | 
					    case -1:
 | 
				
			||||||
        throw SysError("unable to fork");
 | 
					        throw SysError("unable to fork");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -688,7 +688,7 @@ HookInstance::HookInstance()
 | 
				
			||||||
            commonChildInit(fromHook);
 | 
					            commonChildInit(fromHook);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (chdir("/") == -1) throw SysError("changing into `/");
 | 
					            if (chdir("/") == -1) throw SysError("changing into `/");
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
            /* Dup the communication pipes. */
 | 
					            /* Dup the communication pipes. */
 | 
				
			||||||
            toHook.writeSide.close();
 | 
					            toHook.writeSide.close();
 | 
				
			||||||
            if (dup2(toHook.readSide, STDIN_FILENO) == -1)
 | 
					            if (dup2(toHook.readSide, STDIN_FILENO) == -1)
 | 
				
			||||||
| 
						 | 
					@ -699,20 +699,20 @@ HookInstance::HookInstance()
 | 
				
			||||||
            if (dup2(builderOut.writeSide, 4) == -1)
 | 
					            if (dup2(builderOut.writeSide, 4) == -1)
 | 
				
			||||||
                throw SysError("dupping builder's stdout/stderr");
 | 
					                throw SysError("dupping builder's stdout/stderr");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    /* XXX: Pass `buildTimeout' to the hook?  */
 | 
					            /* XXX: Pass `buildTimeout' to the hook?  */
 | 
				
			||||||
            execl(buildHook.c_str(), buildHook.c_str(), thisSystem.c_str(),
 | 
					            execl(buildHook.c_str(), buildHook.c_str(), thisSystem.c_str(),
 | 
				
			||||||
                (format("%1%") % maxSilentTime).str().c_str(),
 | 
					                (format("%1%") % maxSilentTime).str().c_str(),
 | 
				
			||||||
                (format("%1%") % printBuildTrace).str().c_str(),
 | 
					                (format("%1%") % printBuildTrace).str().c_str(),
 | 
				
			||||||
                NULL);
 | 
					                NULL);
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
            throw SysError(format("executing `%1%'") % buildHook);
 | 
					            throw SysError(format("executing `%1%'") % buildHook);
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
        } catch (std::exception & e) {
 | 
					        } catch (std::exception & e) {
 | 
				
			||||||
            std::cerr << format("build hook error: %1%") % e.what() << std::endl;
 | 
					            std::cerr << format("build hook error: %1%") % e.what() << std::endl;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        quickExit(1);
 | 
					        quickExit(1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* parent */
 | 
					    /* parent */
 | 
				
			||||||
    pid.setSeparatePG(true);
 | 
					    pid.setSeparatePG(true);
 | 
				
			||||||
    pid.setKillSignal(SIGTERM);
 | 
					    pid.setKillSignal(SIGTERM);
 | 
				
			||||||
| 
						 | 
					@ -752,7 +752,7 @@ private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* The derivation stored at drvPath. */
 | 
					    /* The derivation stored at drvPath. */
 | 
				
			||||||
    Derivation drv;
 | 
					    Derivation drv;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* The remainder is state held during the build. */
 | 
					    /* The remainder is state held during the build. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Locks on the output paths. */
 | 
					    /* Locks on the output paths. */
 | 
				
			||||||
| 
						 | 
					@ -760,7 +760,7 @@ private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* All input paths (that is, the union of FS closures of the
 | 
					    /* All input paths (that is, the union of FS closures of the
 | 
				
			||||||
       immediate input paths). */
 | 
					       immediate input paths). */
 | 
				
			||||||
    PathSet inputPaths; 
 | 
					    PathSet inputPaths;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Referenceable paths (i.e., input and output paths). */
 | 
					    /* Referenceable paths (i.e., input and output paths). */
 | 
				
			||||||
    PathSet allPaths;
 | 
					    PathSet allPaths;
 | 
				
			||||||
| 
						 | 
					@ -784,10 +784,10 @@ private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* The build hook. */
 | 
					    /* The build hook. */
 | 
				
			||||||
    boost::shared_ptr<HookInstance> hook;
 | 
					    boost::shared_ptr<HookInstance> hook;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* Whether we're currently doing a chroot build. */
 | 
					    /* Whether we're currently doing a chroot build. */
 | 
				
			||||||
    bool useChroot;
 | 
					    bool useChroot;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    Path chrootRootDir;
 | 
					    Path chrootRootDir;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* RAII object to delete the chroot directory. */
 | 
					    /* RAII object to delete the chroot directory. */
 | 
				
			||||||
| 
						 | 
					@ -798,10 +798,10 @@ private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Whether this is a fixed-output derivation. */
 | 
					    /* Whether this is a fixed-output derivation. */
 | 
				
			||||||
    bool fixedOutput;
 | 
					    bool fixedOutput;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    typedef void (DerivationGoal::*GoalState)();
 | 
					    typedef void (DerivationGoal::*GoalState)();
 | 
				
			||||||
    GoalState state;
 | 
					    GoalState state;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* Stuff we need to pass to initChild(). */
 | 
					    /* Stuff we need to pass to initChild(). */
 | 
				
			||||||
    PathSet dirsInChroot;
 | 
					    PathSet dirsInChroot;
 | 
				
			||||||
    typedef map<string, string> Environment;
 | 
					    typedef map<string, string> Environment;
 | 
				
			||||||
| 
						 | 
					@ -812,7 +812,7 @@ public:
 | 
				
			||||||
    ~DerivationGoal();
 | 
					    ~DerivationGoal();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void cancel();
 | 
					    void cancel();
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    void work();
 | 
					    void work();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Path getDrvPath()
 | 
					    Path getDrvPath()
 | 
				
			||||||
| 
						 | 
					@ -917,7 +917,7 @@ void DerivationGoal::killChild()
 | 
				
			||||||
            pid.wait(true);
 | 
					            pid.wait(true);
 | 
				
			||||||
        } else
 | 
					        } else
 | 
				
			||||||
            pid.kill();
 | 
					            pid.kill();
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        assert(pid == -1);
 | 
					        assert(pid == -1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -968,7 +968,7 @@ void DerivationGoal::haveDerivation()
 | 
				
			||||||
       side: if the user forgot to make it a root, we wouldn't want
 | 
					       side: if the user forgot to make it a root, we wouldn't want
 | 
				
			||||||
       things being garbage collected while we're busy. */
 | 
					       things being garbage collected while we're busy. */
 | 
				
			||||||
    worker.store.addTempRoot(drvPath);
 | 
					    worker.store.addTempRoot(drvPath);
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    assert(worker.store.isValidPath(drvPath));
 | 
					    assert(worker.store.isValidPath(drvPath));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Get the derivation. */
 | 
					    /* Get the derivation. */
 | 
				
			||||||
| 
						 | 
					@ -990,14 +990,14 @@ void DerivationGoal::haveDerivation()
 | 
				
			||||||
       don't bother. */
 | 
					       don't bother. */
 | 
				
			||||||
    foreach (PathSet::iterator, i, invalidOutputs)
 | 
					    foreach (PathSet::iterator, i, invalidOutputs)
 | 
				
			||||||
        if (pathFailed(*i)) return;
 | 
					        if (pathFailed(*i)) return;
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
    /* We are first going to try to create the invalid output paths
 | 
					    /* We are first going to try to create the invalid output paths
 | 
				
			||||||
       through substitutes.  If that doesn't work, we'll build
 | 
					       through substitutes.  If that doesn't work, we'll build
 | 
				
			||||||
       them. */
 | 
					       them. */
 | 
				
			||||||
    if (queryBoolSetting("build-use-substitutes", true))
 | 
					    if (queryBoolSetting("build-use-substitutes", true))
 | 
				
			||||||
        foreach (PathSet::iterator, i, invalidOutputs)
 | 
					        foreach (PathSet::iterator, i, invalidOutputs)
 | 
				
			||||||
            addWaitee(worker.makeSubstitutionGoal(*i));
 | 
					            addWaitee(worker.makeSubstitutionGoal(*i));
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    if (waitees.empty()) /* to prevent hang (no wake-up event) */
 | 
					    if (waitees.empty()) /* to prevent hang (no wake-up event) */
 | 
				
			||||||
        outputsSubstituted();
 | 
					        outputsSubstituted();
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
| 
						 | 
					@ -1051,7 +1051,7 @@ void DerivationGoal::inputsRealised()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Gather information necessary for computing the closure and/or
 | 
					    /* Gather information necessary for computing the closure and/or
 | 
				
			||||||
       running the build hook. */
 | 
					       running the build hook. */
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* The outputs are referenceable paths. */
 | 
					    /* The outputs are referenceable paths. */
 | 
				
			||||||
    foreach (DerivationOutputs::iterator, i, drv.outputs) {
 | 
					    foreach (DerivationOutputs::iterator, i, drv.outputs) {
 | 
				
			||||||
        debug(format("building path `%1%'") % i->second.path);
 | 
					        debug(format("building path `%1%'") % i->second.path);
 | 
				
			||||||
| 
						 | 
					@ -1088,7 +1088,7 @@ void DerivationGoal::inputsRealised()
 | 
				
			||||||
    fixedOutput = true;
 | 
					    fixedOutput = true;
 | 
				
			||||||
    foreach (DerivationOutputs::iterator, i, drv.outputs)
 | 
					    foreach (DerivationOutputs::iterator, i, drv.outputs)
 | 
				
			||||||
        if (i->second.hash == "") fixedOutput = false;
 | 
					        if (i->second.hash == "") fixedOutput = false;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* Okay, try to build.  Note that here we don't wait for a build
 | 
					    /* Okay, try to build.  Note that here we don't wait for a build
 | 
				
			||||||
       slot to become available, since we don't need one if there is a
 | 
					       slot to become available, since we don't need one if there is a
 | 
				
			||||||
       build hook. */
 | 
					       build hook. */
 | 
				
			||||||
| 
						 | 
					@ -1108,7 +1108,7 @@ PathSet outputPaths(const DerivationOutputs & outputs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool canBuildLocally(const string & platform)
 | 
					static bool canBuildLocally(const string & platform)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return platform == thisSystem 
 | 
					    return platform == thisSystem
 | 
				
			||||||
#ifdef CAN_DO_LINUX32_BUILDS
 | 
					#ifdef CAN_DO_LINUX32_BUILDS
 | 
				
			||||||
        || (platform == "i686-linux" && thisSystem == "x86_64-linux")
 | 
					        || (platform == "i686-linux" && thisSystem == "x86_64-linux")
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -1132,7 +1132,7 @@ void DerivationGoal::tryToBuild()
 | 
				
			||||||
            worker.waitForAnyGoal(shared_from_this());
 | 
					            worker.waitForAnyGoal(shared_from_this());
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* Obtain locks on all output paths.  The locks are automatically
 | 
					    /* Obtain locks on all output paths.  The locks are automatically
 | 
				
			||||||
       released when we exit this function or Nix crashes.  If we
 | 
					       released when we exit this function or Nix crashes.  If we
 | 
				
			||||||
       can't acquire the lock, then continue; hopefully some other
 | 
					       can't acquire the lock, then continue; hopefully some other
 | 
				
			||||||
| 
						 | 
					@ -1207,7 +1207,7 @@ void DerivationGoal::tryToBuild()
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* Make sure that we are allowed to start a build.  If this
 | 
					    /* Make sure that we are allowed to start a build.  If this
 | 
				
			||||||
       derivation prefers to be done locally, do it even if
 | 
					       derivation prefers to be done locally, do it even if
 | 
				
			||||||
       maxBuildJobs is 0. */
 | 
					       maxBuildJobs is 0. */
 | 
				
			||||||
| 
						 | 
					@ -1217,7 +1217,7 @@ void DerivationGoal::tryToBuild()
 | 
				
			||||||
        outputLocks.unlock();
 | 
					        outputLocks.unlock();
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Okay, we have to build. */
 | 
					        /* Okay, we have to build. */
 | 
				
			||||||
| 
						 | 
					@ -1265,7 +1265,7 @@ void DerivationGoal::buildDone()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* So the child is gone now. */
 | 
					    /* So the child is gone now. */
 | 
				
			||||||
    worker.childTerminated(savedPid);
 | 
					    worker.childTerminated(savedPid);
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* Close the read side of the logger pipe. */
 | 
					    /* Close the read side of the logger pipe. */
 | 
				
			||||||
    if (hook) {
 | 
					    if (hook) {
 | 
				
			||||||
        hook->builderOut.readSide.close();
 | 
					        hook->builderOut.readSide.close();
 | 
				
			||||||
| 
						 | 
					@ -1295,13 +1295,13 @@ void DerivationGoal::buildDone()
 | 
				
			||||||
                if (rename((chrootRootDir + path).c_str(), path.c_str()) == -1)
 | 
					                if (rename((chrootRootDir + path).c_str(), path.c_str()) == -1)
 | 
				
			||||||
                    throw SysError(format("moving build output `%1%' from the chroot to the Nix store") % path);
 | 
					                    throw SysError(format("moving build output `%1%' from the chroot to the Nix store") % path);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
            if (!pathExists(path)) continue;
 | 
					            if (!pathExists(path)) continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            struct stat st;
 | 
					            struct stat st;
 | 
				
			||||||
            if (lstat(path.c_str(), &st) == -1)
 | 
					            if (lstat(path.c_str(), &st) == -1)
 | 
				
			||||||
                throw SysError(format("getting attributes of path `%1%'") % path);
 | 
					                throw SysError(format("getting attributes of path `%1%'") % path);
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
#ifndef __CYGWIN__
 | 
					#ifndef __CYGWIN__
 | 
				
			||||||
            /* Check that the output is not group or world writable,
 | 
					            /* Check that the output is not group or world writable,
 | 
				
			||||||
               as that means that someone else can have interfered
 | 
					               as that means that someone else can have interfered
 | 
				
			||||||
| 
						 | 
					@ -1319,14 +1319,14 @@ void DerivationGoal::buildDone()
 | 
				
			||||||
            if (buildUser.enabled() && !amPrivileged())
 | 
					            if (buildUser.enabled() && !amPrivileged())
 | 
				
			||||||
                getOwnership(path);
 | 
					                getOwnership(path);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
        /* Check the exit status. */
 | 
					        /* Check the exit status. */
 | 
				
			||||||
        if (!statusOk(status)) {
 | 
					        if (!statusOk(status)) {
 | 
				
			||||||
            deleteTmpDir(false);
 | 
					            deleteTmpDir(false);
 | 
				
			||||||
            throw BuildError(format("builder for `%1%' %2%")
 | 
					            throw BuildError(format("builder for `%1%' %2%")
 | 
				
			||||||
                % drvPath % statusToString(status));
 | 
					                % drvPath % statusToString(status));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
        deleteTmpDir(true);
 | 
					        deleteTmpDir(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Delete the chroot (if we were using one). */
 | 
					        /* Delete the chroot (if we were using one). */
 | 
				
			||||||
| 
						 | 
					@ -1336,7 +1336,7 @@ void DerivationGoal::buildDone()
 | 
				
			||||||
           hard-linked inputs to be cleared.  So set them again. */
 | 
					           hard-linked inputs to be cleared.  So set them again. */
 | 
				
			||||||
        foreach (PathSet::iterator, i, regularInputPaths)
 | 
					        foreach (PathSet::iterator, i, regularInputPaths)
 | 
				
			||||||
            makeImmutable(*i);
 | 
					            makeImmutable(*i);
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        /* Compute the FS closure of the outputs and register them as
 | 
					        /* Compute the FS closure of the outputs and register them as
 | 
				
			||||||
           being valid. */
 | 
					           being valid. */
 | 
				
			||||||
        computeClosure();
 | 
					        computeClosure();
 | 
				
			||||||
| 
						 | 
					@ -1358,7 +1358,7 @@ void DerivationGoal::buildDone()
 | 
				
			||||||
           problem. */
 | 
					           problem. */
 | 
				
			||||||
        bool hookError = hook &&
 | 
					        bool hookError = hook &&
 | 
				
			||||||
            (!WIFEXITED(status) || WEXITSTATUS(status) != 100);
 | 
					            (!WIFEXITED(status) || WEXITSTATUS(status) != 100);
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        if (printBuildTrace) {
 | 
					        if (printBuildTrace) {
 | 
				
			||||||
            if (hook && hookError)
 | 
					            if (hook && hookError)
 | 
				
			||||||
                printMsg(lvlError, format("@ hook-failed %1% %2% %3% %4%")
 | 
					                printMsg(lvlError, format("@ hook-failed %1% %2% %3% %4%")
 | 
				
			||||||
| 
						 | 
					@ -1378,7 +1378,7 @@ void DerivationGoal::buildDone()
 | 
				
			||||||
        if (worker.cacheFailure && !hookError && !fixedOutput)
 | 
					        if (worker.cacheFailure && !hookError && !fixedOutput)
 | 
				
			||||||
            foreach (DerivationOutputs::iterator, i, drv.outputs)
 | 
					            foreach (DerivationOutputs::iterator, i, drv.outputs)
 | 
				
			||||||
                worker.store.registerFailedPath(i->second.path);
 | 
					                worker.store.registerFailedPath(i->second.path);
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        worker.permanentFailure = !hookError && !fixedOutput;
 | 
					        worker.permanentFailure = !hookError && !fixedOutput;
 | 
				
			||||||
        amDone(ecFailed);
 | 
					        amDone(ecFailed);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
| 
						 | 
					@ -1391,7 +1391,7 @@ void DerivationGoal::buildDone()
 | 
				
			||||||
        printMsg(lvlError, format("@ build-succeeded %1% %2%")
 | 
					        printMsg(lvlError, format("@ build-succeeded %1% %2%")
 | 
				
			||||||
            % drvPath % drv.outputs["out"].path);
 | 
					            % drvPath % drv.outputs["out"].path);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    amDone(ecSuccess);
 | 
					    amDone(ecSuccess);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1439,7 +1439,7 @@ HookReply DerivationGoal::tryBuildHook()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    hook = worker.hook;
 | 
					    hook = worker.hook;
 | 
				
			||||||
    worker.hook.reset();
 | 
					    worker.hook.reset();
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
    /* Tell the hook all the inputs that have to be copied to the
 | 
					    /* Tell the hook all the inputs that have to be copied to the
 | 
				
			||||||
       remote system.  This unfortunately has to contain the entire
 | 
					       remote system.  This unfortunately has to contain the entire
 | 
				
			||||||
       derivation closure to ensure that the validity invariant holds
 | 
					       derivation closure to ensure that the validity invariant holds
 | 
				
			||||||
| 
						 | 
					@ -1448,18 +1448,18 @@ HookReply DerivationGoal::tryBuildHook()
 | 
				
			||||||
    PathSet allInputs;
 | 
					    PathSet allInputs;
 | 
				
			||||||
    allInputs.insert(inputPaths.begin(), inputPaths.end());
 | 
					    allInputs.insert(inputPaths.begin(), inputPaths.end());
 | 
				
			||||||
    computeFSClosure(worker.store, drvPath, allInputs);
 | 
					    computeFSClosure(worker.store, drvPath, allInputs);
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
    string s;
 | 
					    string s;
 | 
				
			||||||
    foreach (PathSet::iterator, i, allInputs) s += *i + " ";
 | 
					    foreach (PathSet::iterator, i, allInputs) s += *i + " ";
 | 
				
			||||||
    writeLine(hook->toHook.writeSide, s);
 | 
					    writeLine(hook->toHook.writeSide, s);
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
    /* Tell the hooks the outputs that have to be copied back from the
 | 
					    /* Tell the hooks the outputs that have to be copied back from the
 | 
				
			||||||
       remote system. */
 | 
					       remote system. */
 | 
				
			||||||
    s = "";
 | 
					    s = "";
 | 
				
			||||||
    foreach (DerivationOutputs::iterator, i, drv.outputs)
 | 
					    foreach (DerivationOutputs::iterator, i, drv.outputs)
 | 
				
			||||||
        s += i->second.path + " ";
 | 
					        s += i->second.path + " ";
 | 
				
			||||||
    writeLine(hook->toHook.writeSide, s);
 | 
					    writeLine(hook->toHook.writeSide, s);
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    hook->toHook.writeSide.close();
 | 
					    hook->toHook.writeSide.close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Create the log file and pipe. */
 | 
					    /* Create the log file and pipe. */
 | 
				
			||||||
| 
						 | 
					@ -1469,12 +1469,12 @@ HookReply DerivationGoal::tryBuildHook()
 | 
				
			||||||
    fds.insert(hook->fromHook.readSide);
 | 
					    fds.insert(hook->fromHook.readSide);
 | 
				
			||||||
    fds.insert(hook->builderOut.readSide);
 | 
					    fds.insert(hook->builderOut.readSide);
 | 
				
			||||||
    worker.childStarted(shared_from_this(), hook->pid, fds, false, false);
 | 
					    worker.childStarted(shared_from_this(), hook->pid, fds, false, false);
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    if (printBuildTrace)
 | 
					    if (printBuildTrace)
 | 
				
			||||||
        printMsg(lvlError, format("@ build-started %1% %2% %3% %4%")
 | 
					        printMsg(lvlError, format("@ build-started %1% %2% %3% %4%")
 | 
				
			||||||
            % drvPath % drv.outputs["out"].path % drv.platform % logFile);
 | 
					            % drvPath % drv.outputs["out"].path % drv.platform % logFile);
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
    return rpAccept;    
 | 
					    return rpAccept;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1496,7 +1496,7 @@ void DerivationGoal::startBuilder()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    startNest(nest, lvlInfo,
 | 
					    startNest(nest, lvlInfo,
 | 
				
			||||||
        format("building path(s) %1%") % showPaths(outputPaths(drv.outputs)))
 | 
					        format("building path(s) %1%") % showPaths(outputPaths(drv.outputs)))
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* Right platform? */
 | 
					    /* Right platform? */
 | 
				
			||||||
    if (!canBuildLocally(drv.platform))
 | 
					    if (!canBuildLocally(drv.platform))
 | 
				
			||||||
        throw Error(
 | 
					        throw Error(
 | 
				
			||||||
| 
						 | 
					@ -1504,7 +1504,7 @@ void DerivationGoal::startBuilder()
 | 
				
			||||||
            % drv.platform % thisSystem % drvPath);
 | 
					            % drv.platform % thisSystem % drvPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Construct the environment passed to the builder. */
 | 
					    /* Construct the environment passed to the builder. */
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* Most shells initialise PATH to some default (/bin:/usr/bin:...) when
 | 
					    /* Most shells initialise PATH to some default (/bin:/usr/bin:...) when
 | 
				
			||||||
       PATH is not set.  We don't want this, so we fill it in with some dummy
 | 
					       PATH is not set.  We don't want this, so we fill it in with some dummy
 | 
				
			||||||
       value. */
 | 
					       value. */
 | 
				
			||||||
| 
						 | 
					@ -1614,7 +1614,7 @@ void DerivationGoal::startBuilder()
 | 
				
			||||||
            worker.store.makeValidityRegistration(paths, false, false));
 | 
					            worker.store.makeValidityRegistration(paths, false, false));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* If `build-users-group' is not empty, then we have to build as
 | 
					    /* If `build-users-group' is not empty, then we have to build as
 | 
				
			||||||
       one of the members of that group. */
 | 
					       one of the members of that group. */
 | 
				
			||||||
    if (haveBuildUsers()) {
 | 
					    if (haveBuildUsers()) {
 | 
				
			||||||
| 
						 | 
					@ -1625,7 +1625,7 @@ void DerivationGoal::startBuilder()
 | 
				
			||||||
        /* Make sure that no other processes are executing under this
 | 
					        /* Make sure that no other processes are executing under this
 | 
				
			||||||
           uid. */
 | 
					           uid. */
 | 
				
			||||||
        buildUser.kill();
 | 
					        buildUser.kill();
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        /* Change ownership of the temporary build directory, if we're
 | 
					        /* Change ownership of the temporary build directory, if we're
 | 
				
			||||||
           root.  If we're not root, then the setuid helper will do it
 | 
					           root.  If we're not root, then the setuid helper will do it
 | 
				
			||||||
           just before it starts the builder. */
 | 
					           just before it starts the builder. */
 | 
				
			||||||
| 
						 | 
					@ -1674,7 +1674,7 @@ void DerivationGoal::startBuilder()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Clean up the chroot directory automatically. */
 | 
					        /* Clean up the chroot directory automatically. */
 | 
				
			||||||
        autoDelChroot = boost::shared_ptr<AutoDelete>(new AutoDelete(chrootRootDir));
 | 
					        autoDelChroot = boost::shared_ptr<AutoDelete>(new AutoDelete(chrootRootDir));
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        printMsg(lvlChatty, format("setting up chroot environment in `%1%'") % chrootRootDir);
 | 
					        printMsg(lvlChatty, format("setting up chroot environment in `%1%'") % chrootRootDir);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Create a writable /tmp in the chroot.  Many builders need
 | 
					        /* Create a writable /tmp in the chroot.  Many builders need
 | 
				
			||||||
| 
						 | 
					@ -1696,8 +1696,8 @@ void DerivationGoal::startBuilder()
 | 
				
			||||||
                % (buildUser.enabled() ? buildUser.getUID() : getuid())
 | 
					                % (buildUser.enabled() ? buildUser.getUID() : getuid())
 | 
				
			||||||
                % (buildUser.enabled() ? buildUser.getGID() : getgid())).str());
 | 
					                % (buildUser.enabled() ? buildUser.getGID() : getgid())).str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Declare the build user's group so that programs get a consistent
 | 
					        /* Declare the build user's group so that programs get a consistent
 | 
				
			||||||
	   view of the system (e.g., "id -gn"). */
 | 
					           view of the system (e.g., "id -gn"). */
 | 
				
			||||||
        writeFile(chrootRootDir + "/etc/group",
 | 
					        writeFile(chrootRootDir + "/etc/group",
 | 
				
			||||||
            (format("nixbld:!:%1%:\n")
 | 
					            (format("nixbld:!:%1%:\n")
 | 
				
			||||||
                % (buildUser.enabled() ? buildUser.getGID() : getgid())).str());
 | 
					                % (buildUser.enabled() ? buildUser.getGID() : getgid())).str());
 | 
				
			||||||
| 
						 | 
					@ -1738,7 +1738,7 @@ void DerivationGoal::startBuilder()
 | 
				
			||||||
                /* Creating a hard link to *i is impossible if its
 | 
					                /* Creating a hard link to *i is impossible if its
 | 
				
			||||||
                   immutable bit is set.  So clear it first. */
 | 
					                   immutable bit is set.  So clear it first. */
 | 
				
			||||||
                makeMutable(*i);
 | 
					                makeMutable(*i);
 | 
				
			||||||
                
 | 
					
 | 
				
			||||||
                Path p = chrootRootDir + *i;
 | 
					                Path p = chrootRootDir + *i;
 | 
				
			||||||
                if (link(i->c_str(), p.c_str()) == -1) {
 | 
					                if (link(i->c_str(), p.c_str()) == -1) {
 | 
				
			||||||
                    /* Hard-linking fails if we exceed the maximum
 | 
					                    /* Hard-linking fails if we exceed the maximum
 | 
				
			||||||
| 
						 | 
					@ -1755,25 +1755,25 @@ void DerivationGoal::startBuilder()
 | 
				
			||||||
                    StringSource source(sink.s);
 | 
					                    StringSource source(sink.s);
 | 
				
			||||||
                    restorePath(p, source);
 | 
					                    restorePath(p, source);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                
 | 
					
 | 
				
			||||||
                makeImmutable(*i);
 | 
					                makeImmutable(*i);
 | 
				
			||||||
                regularInputPaths.insert(*i);
 | 
					                regularInputPaths.insert(*i);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
        throw Error("chroot builds are not supported on this platform");
 | 
					        throw Error("chroot builds are not supported on this platform");
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* Run the builder. */
 | 
					    /* Run the builder. */
 | 
				
			||||||
    printMsg(lvlChatty, format("executing builder `%1%'") %
 | 
					    printMsg(lvlChatty, format("executing builder `%1%'") %
 | 
				
			||||||
        drv.builder);
 | 
					        drv.builder);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Create the log file. */
 | 
					    /* Create the log file. */
 | 
				
			||||||
    Path logFile = openLogFile();
 | 
					    Path logFile = openLogFile();
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* Create a pipe to get the output of the builder. */
 | 
					    /* Create a pipe to get the output of the builder. */
 | 
				
			||||||
    builderOut.create();
 | 
					    builderOut.create();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1793,7 +1793,7 @@ void DerivationGoal::startBuilder()
 | 
				
			||||||
       - The private mount namespace ensures that all the bind mounts
 | 
					       - The private mount namespace ensures that all the bind mounts
 | 
				
			||||||
         we do will only show up in this process and its children, and
 | 
					         we do will only show up in this process and its children, and
 | 
				
			||||||
         will disappear automatically when we're done.
 | 
					         will disappear automatically when we're done.
 | 
				
			||||||
         
 | 
					
 | 
				
			||||||
       - The private network namespace ensures that the builder cannot
 | 
					       - The private network namespace ensures that the builder cannot
 | 
				
			||||||
         talk to the outside world (or vice versa).  It only has a
 | 
					         talk to the outside world (or vice versa).  It only has a
 | 
				
			||||||
         private loopback interface.
 | 
					         private loopback interface.
 | 
				
			||||||
| 
						 | 
					@ -1845,7 +1845,7 @@ void DerivationGoal::initChild()
 | 
				
			||||||
            /* Initialise the loopback interface. */
 | 
					            /* Initialise the loopback interface. */
 | 
				
			||||||
            AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP));
 | 
					            AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP));
 | 
				
			||||||
            if (fd == -1) throw SysError("cannot open IP socket");
 | 
					            if (fd == -1) throw SysError("cannot open IP socket");
 | 
				
			||||||
                
 | 
					
 | 
				
			||||||
            struct ifreq ifr;
 | 
					            struct ifreq ifr;
 | 
				
			||||||
            strcpy(ifr.ifr_name, "lo");
 | 
					            strcpy(ifr.ifr_name, "lo");
 | 
				
			||||||
            ifr.ifr_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING;
 | 
					            ifr.ifr_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING;
 | 
				
			||||||
| 
						 | 
					@ -1867,9 +1867,9 @@ void DerivationGoal::initChild()
 | 
				
			||||||
                Path source = *i;
 | 
					                Path source = *i;
 | 
				
			||||||
                Path target = chrootRootDir + source;
 | 
					                Path target = chrootRootDir + source;
 | 
				
			||||||
                debug(format("bind mounting `%1%' to `%2%'") % source % target);
 | 
					                debug(format("bind mounting `%1%' to `%2%'") % source % target);
 | 
				
			||||||
                
 | 
					
 | 
				
			||||||
                createDirs(target);
 | 
					                createDirs(target);
 | 
				
			||||||
                
 | 
					
 | 
				
			||||||
                if (mount(source.c_str(), target.c_str(), "", MS_BIND, 0) == -1)
 | 
					                if (mount(source.c_str(), target.c_str(), "", MS_BIND, 0) == -1)
 | 
				
			||||||
                    throw SysError(format("bind mount from `%1%' to `%2%' failed") % source % target);
 | 
					                    throw SysError(format("bind mount from `%1%' to `%2%' failed") % source % target);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -1884,7 +1884,7 @@ void DerivationGoal::initChild()
 | 
				
			||||||
            if (pathExists("/dev/shm"))
 | 
					            if (pathExists("/dev/shm"))
 | 
				
			||||||
                if (mount("none", (chrootRootDir + "/dev/shm").c_str(), "tmpfs", 0, 0) == -1)
 | 
					                if (mount("none", (chrootRootDir + "/dev/shm").c_str(), "tmpfs", 0, 0) == -1)
 | 
				
			||||||
                    throw SysError("mounting /dev/shm");
 | 
					                    throw SysError("mounting /dev/shm");
 | 
				
			||||||
                    
 | 
					
 | 
				
			||||||
            /* Do the chroot().  Below we do a chdir() to the
 | 
					            /* Do the chroot().  Below we do a chdir() to the
 | 
				
			||||||
               temporary build directory to make sure the current
 | 
					               temporary build directory to make sure the current
 | 
				
			||||||
               directory is in the chroot.  (Actually the order
 | 
					               directory is in the chroot.  (Actually the order
 | 
				
			||||||
| 
						 | 
					@ -1894,9 +1894,9 @@ void DerivationGoal::initChild()
 | 
				
			||||||
                throw SysError(format("cannot change root directory to `%1%'") % chrootRootDir);
 | 
					                throw SysError(format("cannot change root directory to `%1%'") % chrootRootDir);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
        commonChildInit(builderOut);
 | 
					        commonChildInit(builderOut);
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
        if (chdir(tmpDir.c_str()) == -1)
 | 
					        if (chdir(tmpDir.c_str()) == -1)
 | 
				
			||||||
            throw SysError(format("changing into `%1%'") % tmpDir);
 | 
					            throw SysError(format("changing into `%1%'") % tmpDir);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1930,7 +1930,7 @@ void DerivationGoal::initChild()
 | 
				
			||||||
        Path program = drv.builder.c_str();
 | 
					        Path program = drv.builder.c_str();
 | 
				
			||||||
        std::vector<const char *> args; /* careful with c_str()! */
 | 
					        std::vector<const char *> args; /* careful with c_str()! */
 | 
				
			||||||
        string user; /* must be here for its c_str()! */
 | 
					        string user; /* must be here for its c_str()! */
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
        /* If we are running in `build-users' mode, then switch to the
 | 
					        /* If we are running in `build-users' mode, then switch to the
 | 
				
			||||||
           user we allocated above.  Make sure that we drop all root
 | 
					           user we allocated above.  Make sure that we drop all root
 | 
				
			||||||
           privileges.  Note that above we have closed all file
 | 
					           privileges.  Note that above we have closed all file
 | 
				
			||||||
| 
						 | 
					@ -1941,10 +1941,10 @@ void DerivationGoal::initChild()
 | 
				
			||||||
            printMsg(lvlChatty, format("switching to user `%1%'") % buildUser.getUser());
 | 
					            printMsg(lvlChatty, format("switching to user `%1%'") % buildUser.getUser());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (amPrivileged()) {
 | 
					            if (amPrivileged()) {
 | 
				
			||||||
                    
 | 
					
 | 
				
			||||||
                if (setgroups(0, 0) == -1)
 | 
					                if (setgroups(0, 0) == -1)
 | 
				
			||||||
                    throw SysError("cannot clear the set of supplementary groups");
 | 
					                    throw SysError("cannot clear the set of supplementary groups");
 | 
				
			||||||
                
 | 
					
 | 
				
			||||||
                if (setgid(buildUser.getGID()) == -1 ||
 | 
					                if (setgid(buildUser.getGID()) == -1 ||
 | 
				
			||||||
                    getgid() != buildUser.getGID() ||
 | 
					                    getgid() != buildUser.getGID() ||
 | 
				
			||||||
                    getegid() != buildUser.getGID())
 | 
					                    getegid() != buildUser.getGID())
 | 
				
			||||||
| 
						 | 
					@ -1954,7 +1954,7 @@ void DerivationGoal::initChild()
 | 
				
			||||||
                    getuid() != buildUser.getUID() ||
 | 
					                    getuid() != buildUser.getUID() ||
 | 
				
			||||||
                    geteuid() != buildUser.getUID())
 | 
					                    geteuid() != buildUser.getUID())
 | 
				
			||||||
                    throw SysError("setuid failed");
 | 
					                    throw SysError("setuid failed");
 | 
				
			||||||
                    
 | 
					
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                /* Let the setuid helper take care of it. */
 | 
					                /* Let the setuid helper take care of it. */
 | 
				
			||||||
                program = nixLibexecDir + "/nix-setuid-helper";
 | 
					                program = nixLibexecDir + "/nix-setuid-helper";
 | 
				
			||||||
| 
						 | 
					@ -1965,7 +1965,7 @@ void DerivationGoal::initChild()
 | 
				
			||||||
                args.push_back(drv.builder.c_str());
 | 
					                args.push_back(drv.builder.c_str());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
        /* Fill in the arguments. */
 | 
					        /* Fill in the arguments. */
 | 
				
			||||||
        string builderBasename = baseNameOf(drv.builder);
 | 
					        string builderBasename = baseNameOf(drv.builder);
 | 
				
			||||||
        args.push_back(builderBasename.c_str());
 | 
					        args.push_back(builderBasename.c_str());
 | 
				
			||||||
| 
						 | 
					@ -1980,7 +1980,7 @@ void DerivationGoal::initChild()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        throw SysError(format("executing `%1%'")
 | 
					        throw SysError(format("executing `%1%'")
 | 
				
			||||||
            % drv.builder);
 | 
					            % drv.builder);
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
    } catch (std::exception & e) {
 | 
					    } catch (std::exception & e) {
 | 
				
			||||||
        std::cerr << format("build error: %1%") % e.what() << std::endl;
 | 
					        std::cerr << format("build error: %1%") % e.what() << std::endl;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -2022,7 +2022,7 @@ void DerivationGoal::computeClosure()
 | 
				
			||||||
            if (!worker.store.isValidPath(i->second.path)) allValid = false;
 | 
					            if (!worker.store.isValidPath(i->second.path)) allValid = false;
 | 
				
			||||||
        if (allValid) return;
 | 
					        if (allValid) return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
    /* Check whether the output paths were created, and grep each
 | 
					    /* Check whether the output paths were created, and grep each
 | 
				
			||||||
       output path to determine what other paths it references.  Also make all
 | 
					       output path to determine what other paths it references.  Also make all
 | 
				
			||||||
       output paths read-only. */
 | 
					       output paths read-only. */
 | 
				
			||||||
| 
						 | 
					@ -2037,18 +2037,18 @@ void DerivationGoal::computeClosure()
 | 
				
			||||||
        struct stat st;
 | 
					        struct stat st;
 | 
				
			||||||
        if (lstat(path.c_str(), &st) == -1)
 | 
					        if (lstat(path.c_str(), &st) == -1)
 | 
				
			||||||
            throw SysError(format("getting attributes of path `%1%'") % path);
 | 
					            throw SysError(format("getting attributes of path `%1%'") % path);
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
        startNest(nest, lvlTalkative,
 | 
					        startNest(nest, lvlTalkative,
 | 
				
			||||||
            format("scanning for references inside `%1%'") % path);
 | 
					            format("scanning for references inside `%1%'") % path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Check that fixed-output derivations produced the right
 | 
					        /* Check that fixed-output derivations produced the right
 | 
				
			||||||
           outputs (i.e., the content hash should match the specified
 | 
					           outputs (i.e., the content hash should match the specified
 | 
				
			||||||
           hash). */ 
 | 
					           hash). */
 | 
				
			||||||
        if (i->second.hash != "") {
 | 
					        if (i->second.hash != "") {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            bool recursive; HashType ht; Hash h;
 | 
					            bool recursive; HashType ht; Hash h;
 | 
				
			||||||
            i->second.parseHashInfo(recursive, ht, h);
 | 
					            i->second.parseHashInfo(recursive, ht, h);
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
            if (!recursive) {
 | 
					            if (!recursive) {
 | 
				
			||||||
                /* The output path should be a regular file without
 | 
					                /* The output path should be a regular file without
 | 
				
			||||||
                   execute permission. */
 | 
					                   execute permission. */
 | 
				
			||||||
| 
						 | 
					@ -2067,12 +2067,12 @@ void DerivationGoal::computeClosure()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Get rid of all weird permissions. */
 | 
					        /* Get rid of all weird permissions. */
 | 
				
			||||||
	canonicalisePathMetaData(path);
 | 
					        canonicalisePathMetaData(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* For this output path, find the references to other paths
 | 
					        /* For this output path, find the references to other paths
 | 
				
			||||||
	   contained in it.  Compute the SHA-256 NAR hash at the same
 | 
					           contained in it.  Compute the SHA-256 NAR hash at the same
 | 
				
			||||||
	   time.  The hash is stored in the database so that we can
 | 
					           time.  The hash is stored in the database so that we can
 | 
				
			||||||
	   verify later on whether nobody has messed with the store. */
 | 
					           verify later on whether nobody has messed with the store. */
 | 
				
			||||||
        HashResult hash;
 | 
					        HashResult hash;
 | 
				
			||||||
        PathSet references = scanForReferences(path, allPaths, hash);
 | 
					        PathSet references = scanForReferences(path, allPaths, hash);
 | 
				
			||||||
        contentHashes[path] = hash;
 | 
					        contentHashes[path] = hash;
 | 
				
			||||||
| 
						 | 
					@ -2126,7 +2126,7 @@ string drvsLogDir = "drvs";
 | 
				
			||||||
Path DerivationGoal::openLogFile()
 | 
					Path DerivationGoal::openLogFile()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (!queryBoolSetting("build-keep-log", true)) return "";
 | 
					    if (!queryBoolSetting("build-keep-log", true)) return "";
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* Create a log file. */
 | 
					    /* Create a log file. */
 | 
				
			||||||
    Path dir = (format("%1%/%2%") % nixLogDir % drvsLogDir).str();
 | 
					    Path dir = (format("%1%/%2%") % nixLogDir % drvsLogDir).str();
 | 
				
			||||||
    createDirs(dir);
 | 
					    createDirs(dir);
 | 
				
			||||||
| 
						 | 
					@ -2179,7 +2179,7 @@ void DerivationGoal::deleteTmpDir(bool force)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (tmpDir != "") {
 | 
					    if (tmpDir != "") {
 | 
				
			||||||
        if (keepFailed && !force) {
 | 
					        if (keepFailed && !force) {
 | 
				
			||||||
	    printMsg(lvlError, 
 | 
						    printMsg(lvlError,
 | 
				
			||||||
		format("builder for `%1%' failed; keeping build directory `%2%'")
 | 
							format("builder for `%1%' failed; keeping build directory `%2%'")
 | 
				
			||||||
                % drvPath % tmpDir);
 | 
					                % drvPath % tmpDir);
 | 
				
			||||||
            if (buildUser.enabled() && !amPrivileged())
 | 
					            if (buildUser.enabled() && !amPrivileged())
 | 
				
			||||||
| 
						 | 
					@ -2235,14 +2235,14 @@ PathSet DerivationGoal::checkPathValidity(bool returnValid)
 | 
				
			||||||
bool DerivationGoal::pathFailed(const Path & path)
 | 
					bool DerivationGoal::pathFailed(const Path & path)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (!worker.cacheFailure) return false;
 | 
					    if (!worker.cacheFailure) return false;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    if (!worker.store.hasPathFailed(path)) return false;
 | 
					    if (!worker.store.hasPathFailed(path)) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printMsg(lvlError, format("builder for `%1%' failed previously (cached)") % path);
 | 
					    printMsg(lvlError, format("builder for `%1%' failed previously (cached)") % path);
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    if (printBuildTrace)
 | 
					    if (printBuildTrace)
 | 
				
			||||||
        printMsg(lvlError, format("@ build-failed %1% %2% cached") % drvPath % path);
 | 
					        printMsg(lvlError, format("@ build-failed %1% %2% cached") % drvPath % path);
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    worker.permanentFailure = true;
 | 
					    worker.permanentFailure = true;
 | 
				
			||||||
    amDone(ecFailed);
 | 
					    amDone(ecFailed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2256,7 +2256,7 @@ bool DerivationGoal::pathFailed(const Path & path)
 | 
				
			||||||
class SubstitutionGoal : public Goal
 | 
					class SubstitutionGoal : public Goal
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    friend class Worker;
 | 
					    friend class Worker;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    /* The store path that should be realised through a substitute. */
 | 
					    /* The store path that should be realised through a substitute. */
 | 
				
			||||||
    Path storePath;
 | 
					    Path storePath;
 | 
				
			||||||
| 
						 | 
					@ -2281,7 +2281,7 @@ private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Lock on the store path. */
 | 
					    /* Lock on the store path. */
 | 
				
			||||||
    boost::shared_ptr<PathLocks> outputLock;
 | 
					    boost::shared_ptr<PathLocks> outputLock;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    typedef void (SubstitutionGoal::*GoalState)();
 | 
					    typedef void (SubstitutionGoal::*GoalState)();
 | 
				
			||||||
    GoalState state;
 | 
					    GoalState state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2290,7 +2290,7 @@ public:
 | 
				
			||||||
    ~SubstitutionGoal();
 | 
					    ~SubstitutionGoal();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void cancel();
 | 
					    void cancel();
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    void work();
 | 
					    void work();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* The states. */
 | 
					    /* The states. */
 | 
				
			||||||
| 
						 | 
					@ -2351,7 +2351,7 @@ void SubstitutionGoal::init()
 | 
				
			||||||
    trace("init");
 | 
					    trace("init");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    worker.store.addTempRoot(storePath);
 | 
					    worker.store.addTempRoot(storePath);
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* If the path already exists we're done. */
 | 
					    /* If the path already exists we're done. */
 | 
				
			||||||
    if (worker.store.isValidPath(storePath)) {
 | 
					    if (worker.store.isValidPath(storePath)) {
 | 
				
			||||||
        amDone(ecSuccess);
 | 
					        amDone(ecSuccess);
 | 
				
			||||||
| 
						 | 
					@ -2362,7 +2362,7 @@ void SubstitutionGoal::init()
 | 
				
			||||||
        throw Error(format("cannot substitute path `%1%' - no write access to the Nix store") % storePath);
 | 
					        throw Error(format("cannot substitute path `%1%' - no write access to the Nix store") % storePath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    subs = substituters;
 | 
					    subs = substituters;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    tryNext();
 | 
					    tryNext();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2448,7 +2448,7 @@ void SubstitutionGoal::tryToRun()
 | 
				
			||||||
        worker.waitForAnyGoal(shared_from_this());
 | 
					        worker.waitForAnyGoal(shared_from_this());
 | 
				
			||||||
        return; /* restart in the tryToRun() state when another goal finishes */
 | 
					        return; /* restart in the tryToRun() state when another goal finishes */
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* Acquire a lock on the output path. */
 | 
					    /* Acquire a lock on the output path. */
 | 
				
			||||||
    outputLock = boost::shared_ptr<PathLocks>(new PathLocks);
 | 
					    outputLock = boost::shared_ptr<PathLocks>(new PathLocks);
 | 
				
			||||||
    if (!outputLock->lockPaths(singleton<PathSet>(storePath), "", false)) {
 | 
					    if (!outputLock->lockPaths(singleton<PathSet>(storePath), "", false)) {
 | 
				
			||||||
| 
						 | 
					@ -2465,7 +2465,7 @@ void SubstitutionGoal::tryToRun()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printMsg(lvlInfo, format("fetching path `%1%'...") % storePath);
 | 
					    printMsg(lvlInfo, format("fetching path `%1%'...") % storePath);
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    logPipe.create();
 | 
					    logPipe.create();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Remove the (stale) output path if it exists. */
 | 
					    /* Remove the (stale) output path if it exists. */
 | 
				
			||||||
| 
						 | 
					@ -2475,7 +2475,7 @@ void SubstitutionGoal::tryToRun()
 | 
				
			||||||
    /* Fork the substitute program. */
 | 
					    /* Fork the substitute program. */
 | 
				
			||||||
    pid = fork();
 | 
					    pid = fork();
 | 
				
			||||||
    switch (pid) {
 | 
					    switch (pid) {
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
    case -1:
 | 
					    case -1:
 | 
				
			||||||
        throw SysError("unable to fork");
 | 
					        throw SysError("unable to fork");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2494,15 +2494,15 @@ void SubstitutionGoal::tryToRun()
 | 
				
			||||||
            const char * * argArr = strings2CharPtrs(args);
 | 
					            const char * * argArr = strings2CharPtrs(args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            execv(sub.c_str(), (char * *) argArr);
 | 
					            execv(sub.c_str(), (char * *) argArr);
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
            throw SysError(format("executing `%1%'") % sub);
 | 
					            throw SysError(format("executing `%1%'") % sub);
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
        } catch (std::exception & e) {
 | 
					        } catch (std::exception & e) {
 | 
				
			||||||
            std::cerr << format("substitute error: %1%") % e.what() << std::endl;
 | 
					            std::cerr << format("substitute error: %1%") % e.what() << std::endl;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        quickExit(1);
 | 
					        quickExit(1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /* parent */
 | 
					    /* parent */
 | 
				
			||||||
    pid.setSeparatePG(true);
 | 
					    pid.setSeparatePG(true);
 | 
				
			||||||
    pid.setKillSignal(SIGTERM);
 | 
					    pid.setKillSignal(SIGTERM);
 | 
				
			||||||
| 
						 | 
					@ -2538,23 +2538,23 @@ void SubstitutionGoal::finished()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Check the exit status and the build result. */
 | 
					    /* Check the exit status and the build result. */
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        if (!statusOk(status))
 | 
					        if (!statusOk(status))
 | 
				
			||||||
            throw SubstError(format("fetching path `%1%' %2%")
 | 
					            throw SubstError(format("fetching path `%1%' %2%")
 | 
				
			||||||
                % storePath % statusToString(status));
 | 
					                % storePath % statusToString(status));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!pathExists(storePath))
 | 
					        if (!pathExists(storePath))
 | 
				
			||||||
            throw SubstError(format("substitute did not produce path `%1%'") % storePath);
 | 
					            throw SubstError(format("substitute did not produce path `%1%'") % storePath);
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
    } catch (SubstError & e) {
 | 
					    } catch (SubstError & e) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        printMsg(lvlInfo, e.msg());
 | 
					        printMsg(lvlInfo, e.msg());
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        if (printBuildTrace) {
 | 
					        if (printBuildTrace) {
 | 
				
			||||||
            printMsg(lvlError, format("@ substituter-failed %1% %2% %3%")
 | 
					            printMsg(lvlError, format("@ substituter-failed %1% %2% %3%")
 | 
				
			||||||
                % storePath % status % e.msg());
 | 
					                % storePath % status % e.msg());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        /* Try the next substitute. */
 | 
					        /* Try the next substitute. */
 | 
				
			||||||
        state = &SubstitutionGoal::tryNext;
 | 
					        state = &SubstitutionGoal::tryNext;
 | 
				
			||||||
        worker.wakeUp(shared_from_this());
 | 
					        worker.wakeUp(shared_from_this());
 | 
				
			||||||
| 
						 | 
					@ -2564,9 +2564,9 @@ void SubstitutionGoal::finished()
 | 
				
			||||||
    canonicalisePathMetaData(storePath);
 | 
					    canonicalisePathMetaData(storePath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    HashResult hash = hashPath(htSHA256, storePath);
 | 
					    HashResult hash = hashPath(htSHA256, storePath);
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    worker.store.optimisePath(storePath); // FIXME: combine with hashPath()
 | 
					    worker.store.optimisePath(storePath); // FIXME: combine with hashPath()
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    ValidPathInfo info2;
 | 
					    ValidPathInfo info2;
 | 
				
			||||||
    info2.path = storePath;
 | 
					    info2.path = storePath;
 | 
				
			||||||
    info2.hash = hash.first;
 | 
					    info2.hash = hash.first;
 | 
				
			||||||
| 
						 | 
					@ -2576,14 +2576,14 @@ void SubstitutionGoal::finished()
 | 
				
			||||||
    worker.store.registerValidPath(info2);
 | 
					    worker.store.registerValidPath(info2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    outputLock->setDeletion(true);
 | 
					    outputLock->setDeletion(true);
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    printMsg(lvlChatty,
 | 
					    printMsg(lvlChatty,
 | 
				
			||||||
        format("substitution of path `%1%' succeeded") % storePath);
 | 
					        format("substitution of path `%1%' succeeded") % storePath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (printBuildTrace) {
 | 
					    if (printBuildTrace) {
 | 
				
			||||||
        printMsg(lvlError, format("@ substituter-succeeded %1%") % storePath);
 | 
					        printMsg(lvlError, format("@ substituter-succeeded %1%") % storePath);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    amDone(ecSuccess);
 | 
					    amDone(ecSuccess);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2614,7 +2614,7 @@ static bool working = false;
 | 
				
			||||||
Worker::Worker(LocalStore & store)
 | 
					Worker::Worker(LocalStore & store)
 | 
				
			||||||
    : store(store)
 | 
					    : store(store)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /* Debugging: prevent recursive workers. */ 
 | 
					    /* Debugging: prevent recursive workers. */
 | 
				
			||||||
    if (working) abort();
 | 
					    if (working) abort();
 | 
				
			||||||
    working = true;
 | 
					    working = true;
 | 
				
			||||||
    nrLocalBuilds = 0;
 | 
					    nrLocalBuilds = 0;
 | 
				
			||||||
| 
						 | 
					@ -2729,7 +2729,7 @@ void Worker::childStarted(GoalPtr goal,
 | 
				
			||||||
void Worker::childTerminated(pid_t pid, bool wakeSleepers)
 | 
					void Worker::childTerminated(pid_t pid, bool wakeSleepers)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    assert(pid != -1); /* common mistake */
 | 
					    assert(pid != -1); /* common mistake */
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    Children::iterator i = children.find(pid);
 | 
					    Children::iterator i = children.find(pid);
 | 
				
			||||||
    assert(i != children.end());
 | 
					    assert(i != children.end());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2741,7 +2741,7 @@ void Worker::childTerminated(pid_t pid, bool wakeSleepers)
 | 
				
			||||||
    children.erase(pid);
 | 
					    children.erase(pid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (wakeSleepers) {
 | 
					    if (wakeSleepers) {
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        /* Wake up goals waiting for a build slot. */
 | 
					        /* Wake up goals waiting for a build slot. */
 | 
				
			||||||
        foreach (WeakGoals::iterator, i, wantingToBuild) {
 | 
					        foreach (WeakGoals::iterator, i, wantingToBuild) {
 | 
				
			||||||
            GoalPtr goal = i->lock();
 | 
					            GoalPtr goal = i->lock();
 | 
				
			||||||
| 
						 | 
					@ -2780,7 +2780,7 @@ void Worker::waitForAWhile(GoalPtr goal)
 | 
				
			||||||
void Worker::run(const Goals & _topGoals)
 | 
					void Worker::run(const Goals & _topGoals)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    foreach (Goals::iterator, i,  _topGoals) topGoals.insert(*i);
 | 
					    foreach (Goals::iterator, i,  _topGoals) topGoals.insert(*i);
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    startNest(nest, lvlDebug, format("entered goal loop"));
 | 
					    startNest(nest, lvlDebug, format("entered goal loop"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while (1) {
 | 
					    while (1) {
 | 
				
			||||||
| 
						 | 
					@ -2866,7 +2866,7 @@ void Worker::waitForInput()
 | 
				
			||||||
    /* If we are polling goals that are waiting for a lock, then wake
 | 
					    /* If we are polling goals that are waiting for a lock, then wake
 | 
				
			||||||
       up after a few seconds at most. */
 | 
					       up after a few seconds at most. */
 | 
				
			||||||
    int wakeUpInterval = queryIntSetting("build-poll-interval", 5);
 | 
					    int wakeUpInterval = queryIntSetting("build-poll-interval", 5);
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
    if (!waitingForAWhile.empty()) {
 | 
					    if (!waitingForAWhile.empty()) {
 | 
				
			||||||
        useTimeout = true;
 | 
					        useTimeout = true;
 | 
				
			||||||
        if (lastWokenUp == 0)
 | 
					        if (lastWokenUp == 0)
 | 
				
			||||||
| 
						 | 
					@ -2907,7 +2907,7 @@ void Worker::waitForInput()
 | 
				
			||||||
       cancel(). */
 | 
					       cancel(). */
 | 
				
			||||||
    set<pid_t> pids;
 | 
					    set<pid_t> pids;
 | 
				
			||||||
    foreach (Children::iterator, i, children) pids.insert(i->first);
 | 
					    foreach (Children::iterator, i, children) pids.insert(i->first);
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
    foreach (set<pid_t>::iterator, i, pids) {
 | 
					    foreach (set<pid_t>::iterator, i, pids) {
 | 
				
			||||||
        checkInterrupt();
 | 
					        checkInterrupt();
 | 
				
			||||||
        Children::iterator j = children.find(*i);
 | 
					        Children::iterator j = children.find(*i);
 | 
				
			||||||
| 
						 | 
					@ -3001,7 +3001,7 @@ void LocalStore::buildPaths(const PathSet & drvPaths)
 | 
				
			||||||
            if (i2) failed.insert(i2->getDrvPath());
 | 
					            if (i2) failed.insert(i2->getDrvPath());
 | 
				
			||||||
            else failed.insert(dynamic_cast<SubstitutionGoal *>(i->get())->getStorePath());
 | 
					            else failed.insert(dynamic_cast<SubstitutionGoal *>(i->get())->getStorePath());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
    if (!failed.empty())
 | 
					    if (!failed.empty())
 | 
				
			||||||
        throw Error(format("build of %1% failed") % showPaths(failed), worker.exitStatus());
 | 
					        throw Error(format("build of %1% failed") % showPaths(failed), worker.exitStatus());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -3022,5 +3022,5 @@ void LocalStore::ensurePath(const Path & path)
 | 
				
			||||||
        throw Error(format("path `%1%' does not exist and cannot be created") % path, worker.exitStatus());
 | 
					        throw Error(format("path `%1%' does not exist and cannot be created") % path, worker.exitStatus());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue