forked from lix-project/lix
* New tools nix-pack-closure and nix-unpack-closure. These provide a
useful way to transfer the closure of a store path to another machine. These commands provide functionality previously possible through `nix-push --copy'. However, they are much more convenient in many situations (though possibly less efficient). Example: $ nix-pack-closure /nix/store/hj232g1r...-subversion-1.3.0 > svn.closure (on another machine:) $ nix-unpack-closure < svn.closure Note that Subversion is added to the store, but not installed into a user environment. One should do `nix-env -i /nix/store/hj232g1r...-subversion-1.3.0' for that. Another example: copy the application Azureus to the machine `scratchy' through ssh: $ nix-pack-closure $(which azureus) | ssh scratchy nix-unpack-closure
This commit is contained in:
parent
5b527901ae
commit
e4d4969ae9
|
@ -1,6 +1,7 @@
|
||||||
bin_SCRIPTS = nix-collect-garbage \
|
bin_SCRIPTS = nix-collect-garbage \
|
||||||
nix-pull nix-push nix-prefetch-url \
|
nix-pull nix-push nix-prefetch-url \
|
||||||
nix-install-package nix-channel nix-build
|
nix-install-package nix-channel nix-build \
|
||||||
|
nix-pack-closure nix-unpack-closure
|
||||||
|
|
||||||
noinst_SCRIPTS = nix-profile.sh generate-patches.pl
|
noinst_SCRIPTS = nix-profile.sh generate-patches.pl
|
||||||
|
|
||||||
|
@ -23,4 +24,5 @@ EXTRA_DIST = nix-collect-garbage.in \
|
||||||
readmanifest.pm.in \
|
readmanifest.pm.in \
|
||||||
nix-build.in \
|
nix-build.in \
|
||||||
download-using-manifests.pl.in \
|
download-using-manifests.pl.in \
|
||||||
generate-patches.pl.in
|
generate-patches.pl.in \
|
||||||
|
nix-pack-closure.in nix-unpack-closure.in
|
||||||
|
|
67
scripts/nix-pack-closure.in
Normal file
67
scripts/nix-pack-closure.in
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
#! @perl@ -w
|
||||||
|
|
||||||
|
# This tool computes the closure of a path (using "nix-store --query
|
||||||
|
# --requisites") and puts the contents of each path in the closure in
|
||||||
|
# a big NAR archive that can be installed on another Nix installation
|
||||||
|
# using "nix-unpack-closure".
|
||||||
|
|
||||||
|
# TODO: make this program "streamy", i.e., don't use a temporary
|
||||||
|
# directory.
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use POSIX qw(tmpnam);
|
||||||
|
|
||||||
|
my $binDir = $ENV{"NIX_BIN_DIR"};
|
||||||
|
$binDir = "@bindir@" unless defined $binDir;
|
||||||
|
|
||||||
|
my $tmpDir;
|
||||||
|
do { $tmpDir = tmpnam(); }
|
||||||
|
until mkdir $tmpDir, 0777;
|
||||||
|
END { system "rm -rf '$tmpDir'"; }
|
||||||
|
mkdir "$tmpDir/contents", 0777 or die;
|
||||||
|
mkdir "$tmpDir/references", 0777 or die;
|
||||||
|
mkdir "$tmpDir/derivers", 0777 or die;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
my %storePaths;
|
||||||
|
|
||||||
|
|
||||||
|
while (@ARGV) {
|
||||||
|
my $storePath = shift @ARGV;
|
||||||
|
|
||||||
|
# Get the closure of this path.
|
||||||
|
my $pid = open(READ,
|
||||||
|
"$binDir/nix-store --query --requisites " .
|
||||||
|
"--force-realise '$storePath'|") or die;
|
||||||
|
|
||||||
|
while (<READ>) {
|
||||||
|
chomp;
|
||||||
|
die "bad: $_" unless /^\//;
|
||||||
|
$storePaths{$_} = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
close READ or die "nix-store failed: $?";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
foreach my $storePath (sort(keys %storePaths)) {
|
||||||
|
print STDERR "packing `$storePath'...\n";
|
||||||
|
|
||||||
|
$storePath =~ /\/([^\/]+)$/;
|
||||||
|
my $name = $1;
|
||||||
|
|
||||||
|
system("$binDir/nix-store --dump '$storePath' > $tmpDir/contents/$name") == 0
|
||||||
|
or die "nix-store --dump failed on `$storePath': $?";
|
||||||
|
|
||||||
|
system("$binDir/nix-store --query --references '$storePath' > $tmpDir/references/$name") == 0
|
||||||
|
or die "nix-store --query --references failed on `$storePath': $?";
|
||||||
|
|
||||||
|
system("$binDir/nix-store --query --deriver '$storePath' > $tmpDir/derivers/$name") == 0
|
||||||
|
or die "nix-store --query --deriver failed on `$storePath': $?";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Write a NAR archive of everything to standard output.
|
||||||
|
system("nix-store --dump '$tmpDir'") == 0
|
||||||
|
or die "nix-store --dump failed";
|
81
scripts/nix-unpack-closure.in
Normal file
81
scripts/nix-unpack-closure.in
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
#! @perl@ -w
|
||||||
|
|
||||||
|
# This tool unpacks the closures created by "nix-pack-closure" and
|
||||||
|
# adds them to the Nix store.
|
||||||
|
|
||||||
|
# TODO: make this program "streamy", i.e., don't use a temporary
|
||||||
|
# directory.
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use POSIX qw(tmpnam);
|
||||||
|
|
||||||
|
my $binDir = $ENV{"NIX_BIN_DIR"};
|
||||||
|
$binDir = "@bindir@" unless defined $binDir;
|
||||||
|
|
||||||
|
my $tmpDir;
|
||||||
|
do { $tmpDir = tmpnam(); }
|
||||||
|
until mkdir $tmpDir, 0777;
|
||||||
|
END { system "rm -rf '$tmpDir'"; }
|
||||||
|
|
||||||
|
|
||||||
|
# Unpack the NAR archive on standard input.
|
||||||
|
system("nix-store --restore '$tmpDir/unpacked'") == 0
|
||||||
|
or die "nix-store --restore failed";
|
||||||
|
|
||||||
|
|
||||||
|
open VALID, ">$tmpDir/validity" or die;
|
||||||
|
|
||||||
|
|
||||||
|
# For each path in the closure that is not yet valid, add it to the
|
||||||
|
# store. TODO: use proper locking. Or even better, let nix-store do
|
||||||
|
# this.
|
||||||
|
opendir(DIR, "$tmpDir/unpacked/contents") or die "cannot open directory: $!";
|
||||||
|
|
||||||
|
foreach my $name (sort(readdir DIR)) {
|
||||||
|
next if $name eq "." or $name eq "..";
|
||||||
|
|
||||||
|
my $storePath = "/nix/store/$name"; # !!!
|
||||||
|
|
||||||
|
# !!! this really isn't a good validity check!
|
||||||
|
system "/nix/bin/nix-store --check-validity '$storePath' 2> /dev/null";
|
||||||
|
if ($? != 0) {
|
||||||
|
print STDERR "unpacking `$storePath'...\n";
|
||||||
|
|
||||||
|
# !!! race
|
||||||
|
system("rm -rf '$storePath'") == 0
|
||||||
|
or die "cannot remove `$storePath': $?";
|
||||||
|
|
||||||
|
system("$binDir/nix-store --restore '$storePath' < '$tmpDir/unpacked/contents/$name'") == 0
|
||||||
|
or die "nix-store --dump failed on `$storePath': $?";
|
||||||
|
|
||||||
|
print VALID "$storePath\n";
|
||||||
|
|
||||||
|
open DRV, "<$tmpDir/unpacked/derivers/$name" or die;
|
||||||
|
my $deriver = <DRV>;
|
||||||
|
chomp $deriver;
|
||||||
|
$deriver = "" if $deriver eq "unknown-deriver";
|
||||||
|
close DRV;
|
||||||
|
|
||||||
|
my @refs;
|
||||||
|
open REFS, "<$tmpDir/unpacked/references/$name" or die;
|
||||||
|
while (<REFS>) {
|
||||||
|
chomp;
|
||||||
|
push @refs, $_;
|
||||||
|
}
|
||||||
|
close REFS;
|
||||||
|
|
||||||
|
print VALID "$deriver\n";
|
||||||
|
|
||||||
|
print VALID (scalar @refs), "\n";
|
||||||
|
foreach my $ref (@refs) {
|
||||||
|
print VALID "$ref\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(DIR) or die;
|
||||||
|
|
||||||
|
|
||||||
|
# Register the invalid paths as valid.
|
||||||
|
system("nix-store --register-validity <'$tmpDir/validity'") == 0
|
||||||
|
or die "nix-store --register-validity failed";
|
Loading…
Reference in a new issue