diff options
Diffstat (limited to 'perl/lib/Nix/CopyClosure.pm')
-rw-r--r-- | perl/lib/Nix/CopyClosure.pm | 96 |
1 files changed, 36 insertions, 60 deletions
diff --git a/perl/lib/Nix/CopyClosure.pm b/perl/lib/Nix/CopyClosure.pm index 131f0b5a4557..f701a7c8a0d5 100644 --- a/perl/lib/Nix/CopyClosure.pm +++ b/perl/lib/Nix/CopyClosure.pm @@ -3,76 +3,27 @@ package Nix::CopyClosure; use strict; use Nix::Config; use Nix::Store; +use Nix::SSH; use List::Util qw(sum); use IPC::Open2; -sub readN { - my ($bytes, $from) = @_; - my $res = ""; - while ($bytes > 0) { - my $s; - my $n = sysread($from, $s, $bytes); - die "I/O error reading from remote side\n" if !defined $n; - die "got EOF while expecting $bytes bytes from remote side\n" if !$n; - $bytes -= $n; - $res .= $s; - } - return $res; -} - - -sub readInt { - my ($from) = @_; - return unpack("L<x4", readN(8, $from)); -} - - -sub writeString { - my ($s, $to) = @_; - my $len = length $s; - my $req .= pack("L<x4", $len); - $req .= $s; - $req .= "\000" x (8 - $len % 8) if $len % 8; - syswrite($to, $req) or die; -} - - -sub copyTo { - my ($sshHost, $sshOpts, $storePaths, $compressor, $decompressor, +sub copyToOpen { + my ($from, $to, $sshHost, $storePaths, $compressor, $decompressor, $includeOutputs, $dryRun, $sign, $progressViewer, $useSubstitutes) = @_; - $useSubstitutes = 0 if $dryRun; + $useSubstitutes = 0 if $dryRun || !defined $useSubstitutes; # Get the closure of this path. my @closure = reverse(topoSortPaths(computeFSClosure(0, $includeOutputs, map { followLinksToStorePath $_ } @{$storePaths}))); - # Start ‘nix-store --serve’ on the remote host. - my ($from, $to); - my $pid = open2($from, $to, "ssh $sshHost @{$sshOpts} nix-store --serve --write"); - - # Do the handshake. - eval { - my $SERVE_MAGIC_1 = 0x390c9deb; # FIXME - my $clientVersion = 0x200; - syswrite($to, pack("L<x4L<x4", $SERVE_MAGIC_1, $clientVersion)) or die; - die "did not get valid handshake from remote host\n" if readInt($from) != 0x5452eecb; - my $serverVersion = readInt($from); - die "unsupported server version\n" if $serverVersion < 0x200 || $serverVersion >= 0x300; - }; - if ($@) { - chomp $@; - warn "$@; falling back to old closure copying method\n"; - return oldCopyTo(\@closure, @_); - } - # Send the "query valid paths" command with the "lock" option # enabled. This prevents a race where the remote host # garbage-collect paths that are already there. Optionally, ask # the remote host to substitute missing paths. - syswrite($to, pack("L<x4L<x4L<x4L<x4", 1, 1, $useSubstitutes, scalar @closure)) or die; - writeString($_, $to) foreach @closure; + syswrite($to, pack("L<x4L<x4L<x4", 1, 1, $useSubstitutes)) or die; + writeStrings(\@closure, $to); # Get back the set of paths that are already valid on the remote host. my %present; @@ -115,22 +66,47 @@ sub copyTo { } else { exportPaths(fileno($to), $sign, @missing); - close $to; } readInt($from) == 1 or die "remote machine \`$sshHost' failed to import closure\n"; } +sub copyTo { + my ($sshHost, $sshOpts, $storePaths, $compressor, $decompressor, + $includeOutputs, $dryRun, $sign, $progressViewer, $useSubstitutes) = @_; + + # Connect to the remote host. + my ($from, $to); + eval { + ($from, $to) = connectToRemoteNix($sshHost, $sshOpts); + }; + if ($@) { + chomp $@; + warn "$@; falling back to old closure copying method\n"; + return oldCopyTo(@_); + } + + copyToOpen($from, $to, $sshHost, $storePaths, $compressor, $decompressor, + $includeOutputs, $dryRun, $sign, $progressViewer, $useSubstitutes); + + close $to; +} + + # For backwards compatibility with Nix <= 1.7. Will be removed # eventually. sub oldCopyTo { - my ($closure, $sshHost, $sshOpts, $storePaths, $compressor, $decompressor, + my ($sshHost, $sshOpts, $storePaths, $compressor, $decompressor, $includeOutputs, $dryRun, $sign, $progressViewer, $useSubstitutes) = @_; + # Get the closure of this path. + my @closure = reverse(topoSortPaths(computeFSClosure(0, $includeOutputs, + map { followLinksToStorePath $_ } @{$storePaths}))); + # Optionally use substitutes on the remote host. if (!$dryRun && $useSubstitutes) { - system "ssh $sshHost @{$sshOpts} nix-store -r --ignore-unknown @$closure"; + system "ssh $sshHost @{$sshOpts} nix-store -r --ignore-unknown @closure"; # Ignore exit status because this is just an optimisation. } @@ -140,8 +116,8 @@ sub oldCopyTo { # target having this option yet. my @missing; my $missingSize = 0; - while (scalar(@$closure) > 0) { - my @ps = splice(@$closure, 0, 1500); + while (scalar(@closure) > 0) { + my @ps = splice(@closure, 0, 1500); open(READ, "set -f; ssh $sshHost @{$sshOpts} nix-store --check-validity --print-invalid @ps|"); while (<READ>) { chomp; |