diff options
Diffstat (limited to 'scripts/nix-copy-closure.in')
-rwxr-xr-x | scripts/nix-copy-closure.in | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/scripts/nix-copy-closure.in b/scripts/nix-copy-closure.in new file mode 100755 index 000000000000..23d5619519a4 --- /dev/null +++ b/scripts/nix-copy-closure.in @@ -0,0 +1,131 @@ +#! @perl@ -w @perlFlags@ + +use Nix::SSH; +use Nix::Config; +use Nix::Store; +use Nix::CopyClosure; +use List::Util qw(sum); + + +if (scalar @ARGV < 1) { + print STDERR <<EOF +Usage: nix-copy-closure [--from | --to] HOSTNAME [--sign] [--gzip] [--bzip2] [--xz] PATHS... +EOF + ; + exit 1; +} + + +# Get the target host. +my $sshHost; +my $sign = 0; +my $compressor = ""; +my $decompressor = ""; +my $progressViewer = ""; +my $toMode = 1; +my $includeOutputs = 0; +my $dryRun = 0; +my $useSubstitutes = 0; + + +# !!! Copied from nix-pack-closure, should put this in a module. +my @storePaths = (); + +while (@ARGV) { + my $arg = shift @ARGV; + + if ($arg eq "--help") { + exec "man nix-copy-closure" or die; + } + elsif ($arg eq "--sign") { + $sign = 1; + } + elsif ($arg eq "--gzip") { + $compressor = "gzip"; + $decompressor = "gunzip"; + } + elsif ($arg eq "--bzip2") { + $compressor = "bzip2"; + $decompressor = "bunzip2"; + } + elsif ($arg eq "--xz") { + $compressor = "xz"; + $decompressor = "xz -d"; + } + elsif ($arg eq "--from") { + $toMode = 0; + } + elsif ($arg eq "--to") { + $toMode = 1; + } + elsif ($arg eq "--include-outputs") { + $includeOutputs = 1; + } + elsif ($arg eq "--show-progress") { + $progressViewer = "@pv@"; + } + elsif ($arg eq "--dry-run") { + $dryRun = 1; + } + elsif ($arg eq "--use-substitutes" || $arg eq "-s") { + $useSubstitutes = 1; + } + elsif (!defined $sshHost) { + $sshHost = $arg; + } + else { + push @storePaths, $arg; + } +} + +die "$0: you did not specify a host name\n" unless defined $sshHost; + + +openSSHConnection $sshHost or die "$0: unable to start SSH\n"; + + +if ($toMode) { # Copy TO the remote machine. + Nix::CopyClosure::copyTo( + $sshHost, [ @sshOpts ], [ @storePaths ], $compressor, $decompressor, + $includeOutputs, $dryRun, $sign, $progressViewer, $useSubstitutes); +} + +else { # Copy FROM the remote machine. + + # Query the closure of the given store paths on the remote + # machine. Paths are assumed to be store paths; there is no + # resolution (following of symlinks). + my $extraOpts = $includeOutputs ? "--include-outputs" : ""; + my $pid = open(READ, + "set -f; ssh @sshOpts $sshHost nix-store --query --requisites $extraOpts @storePaths|") or die; + + while (<READ>) { + chomp; + die "bad: $_" unless /^\//; + push @missing, $_ unless isValidPath($_); + } + + close READ or die "nix-store on remote machine `$sshHost' failed: $?"; + + my $missingSize = 0; + if ($progressViewer ne "") { + $missingSize = sum (split ' ', `set -f; ssh @sshOpts $sshHost nix-store -q --size @missing`) or die; + } + + # Export the store paths on the remote machine and import them locally. + if (scalar @missing > 0) { + print STDERR "copying ", scalar @missing, " missing paths from ‘$sshHost’...\n"; + unless ($dryRun) { + if ($useSubstitutes) { + system "$Nix::Config::binDir/nix-store -r --ignore-unknown @missing"; + } + $compressor = "| $compressor" if $compressor ne ""; + $decompressor = "$decompressor |" if $decompressor ne ""; + $progressViewer = "$progressViewer -s $missingSize |" if $progressViewer ne ""; + my $extraOpts = $sign ? "--sign" : ""; + system("set -f; ssh $sshHost @sshOpts 'nix-store --export $extraOpts @missing $compressor' | $decompressor $progressViewer $Nix::Config::binDir/nix-store --import > /dev/null") == 0 + or die "copying store paths from remote machine `$sshHost' failed: $?"; + } + } + +} |