Compare commits
195 Commits
sqlite
...
multiple-o
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9936da6b54 | ||
|
|
9d43a02382 | ||
|
|
a0477a458f | ||
|
|
b79b85ad76 | ||
|
|
83647f4ef1 | ||
|
|
71f3c46cf6 | ||
|
|
921111d197 | ||
|
|
6c31232e14 | ||
|
|
502d94048a | ||
|
|
63227d434c | ||
|
|
9b7df1ef00 | ||
|
|
39d45a6b09 | ||
|
|
dadbb51d96 | ||
|
|
48cea0d01e | ||
|
|
93e71e6ab6 | ||
|
|
f2d65c9c80 | ||
|
|
93b56acb2d | ||
|
|
a71d02440b | ||
|
|
6f5e3326ce | ||
|
|
b1004f40f7 | ||
|
|
ed11b17b2e | ||
|
|
254b3399ba | ||
|
|
8c42a8c8ff | ||
|
|
524fa8a4f1 | ||
|
|
b33da599c5 | ||
|
|
58d974336c | ||
|
|
66c99b0cf5 | ||
|
|
2aac7cd021 | ||
|
|
4d728bc3e6 | ||
|
|
69d6f0936a | ||
|
|
5679041132 | ||
|
|
f8e54b7874 | ||
|
|
b4cee3f816 | ||
|
|
f3c88f297d | ||
|
|
b19a0f63db | ||
|
|
4be5a2c096 | ||
|
|
179409b911 | ||
|
|
3877619888 | ||
|
|
edd9359beb | ||
|
|
1f3b0ede7d | ||
|
|
46e42c92c1 | ||
|
|
b5363810bb | ||
|
|
194d21f9f6 | ||
|
|
273b288a7e | ||
|
|
8d3dfa2c17 | ||
|
|
e0bd307802 | ||
|
|
78598d06f0 | ||
|
|
5a1b9ed0aa | ||
|
|
a67b8ae224 | ||
|
|
a3e0656cbb | ||
|
|
3a48282b06 | ||
|
|
893cac1402 | ||
|
|
23bf700196 | ||
|
|
c8c0380744 | ||
|
|
000160f5b9 | ||
|
|
3964d95abf | ||
|
|
92d6a5ed73 | ||
|
|
49f59dceca | ||
|
|
b12b21825c | ||
|
|
23c38a04cc | ||
|
|
24f863d86b | ||
|
|
be9be4c147 | ||
|
|
3c7ec8fc1b | ||
|
|
f35c4351e5 | ||
|
|
4d0407ba08 | ||
|
|
1749a7b0ae | ||
|
|
b1eb8f4249 | ||
|
|
216440b3ff | ||
|
|
1df120cb05 | ||
|
|
784083176a | ||
|
|
f3bc98b001 | ||
|
|
10e2b2b79e | ||
|
|
d5ac78e0d6 | ||
|
|
5bbd693cae | ||
|
|
ab20af3e6f | ||
|
|
993fa94fb4 | ||
|
|
4e1ea17052 | ||
|
|
4de3e2a0db | ||
|
|
23e933b3b3 | ||
|
|
a6abade8e8 | ||
|
|
964399c079 | ||
|
|
b92f76374f | ||
|
|
42164d6de4 | ||
|
|
45ec69cbdf | ||
|
|
f8e609c341 | ||
|
|
d7d7910ba4 | ||
|
|
63ee5e4d2a | ||
|
|
a5952405d2 | ||
|
|
c0b706213d | ||
|
|
3c3107da86 | ||
|
|
2ab29be70c | ||
|
|
ca0d47a70c | ||
|
|
24b65937e1 | ||
|
|
3522730316 | ||
|
|
46876ff203 | ||
|
|
af2e53fd48 | ||
|
|
981edeab7b | ||
|
|
f883afa1a1 | ||
|
|
2721e9f56f | ||
|
|
a6a3f3a8c2 | ||
|
|
fa69ff5726 | ||
|
|
daed9aeac5 | ||
|
|
d7b87bebe3 | ||
|
|
325b5a8aee | ||
|
|
a12095d3be | ||
|
|
00b41e46ed | ||
|
|
f186a9141e | ||
|
|
6761757428 | ||
|
|
d43a148204 | ||
|
|
2492914fbc | ||
|
|
c362e4d718 | ||
|
|
7d314b8c95 | ||
|
|
5193db048e | ||
|
|
a2a317eb0b | ||
|
|
5090c34ee1 | ||
|
|
8af7d766f0 | ||
|
|
cd6d02c366 | ||
|
|
6fcdbcac20 | ||
|
|
659c427caa | ||
|
|
73fe6871c4 | ||
|
|
bffe35aced | ||
|
|
6c38cc9025 | ||
|
|
55481c44d4 | ||
|
|
e81c09edbf | ||
|
|
bf50d6ad32 | ||
|
|
ffa038f66d | ||
|
|
f3e410d4bf | ||
|
|
8f28a3ba25 | ||
|
|
c172d16b00 | ||
|
|
0b34e57eb8 | ||
|
|
13114daa3e | ||
|
|
281e3ed059 | ||
|
|
e6cb3d0a0d | ||
|
|
82710f96f7 | ||
|
|
93227ff65c | ||
|
|
5bcdc7e351 | ||
|
|
a95ba4cdd9 | ||
|
|
da18b11b05 | ||
|
|
76e0029f7a | ||
|
|
d374be551d | ||
|
|
2d663b502d | ||
|
|
510033e783 | ||
|
|
9d091ee99a | ||
|
|
00a724ebc6 | ||
|
|
07340b8be7 | ||
|
|
c7101dac0b | ||
|
|
1578b2261d | ||
|
|
1ecc97b6bd | ||
|
|
54945a2950 | ||
|
|
c8606664ab | ||
|
|
b2027f70d9 | ||
|
|
d2bfe1b071 | ||
|
|
4bdb51e621 | ||
|
|
0243eea4b9 | ||
|
|
d329c3ea9d | ||
|
|
d9a5959139 | ||
|
|
d5d4dcd4c9 | ||
|
|
e649f3168b | ||
|
|
0a623a10c7 | ||
|
|
2b9e29b1c8 | ||
|
|
5580f3817c | ||
|
|
5637037802 | ||
|
|
34f4b91820 | ||
|
|
1ea6e06445 | ||
|
|
5c9e9f732d | ||
|
|
9c99aa2620 | ||
|
|
e4d8148585 | ||
|
|
4891b21f34 | ||
|
|
d94cb02bfe | ||
|
|
8c69dac8a1 | ||
|
|
4ba6afaf48 | ||
|
|
412914d004 | ||
|
|
08c8971498 | ||
|
|
b2c11b9ed0 | ||
|
|
3cbf680f5d | ||
|
|
83252b4ca9 | ||
|
|
b1882c3ef7 | ||
|
|
5591fcc529 | ||
|
|
1e7e4f21ba | ||
|
|
0423d0692a | ||
|
|
48bdbbf070 | ||
|
|
802c2651c8 | ||
|
|
e945b52a31 | ||
|
|
c3cee5395b | ||
|
|
8fcaf3e9c6 | ||
|
|
538b7caab0 | ||
|
|
5a6b039802 | ||
|
|
f1462c208b | ||
|
|
1876ab764f | ||
|
|
dfc4117e90 | ||
|
|
d159ea1b7e | ||
|
|
3087b3f751 | ||
|
|
eb94581d39 | ||
|
|
7bba67c401 | ||
|
|
d0eda1f3e9 |
27
.gitignore
vendored
27
.gitignore
vendored
@@ -61,23 +61,11 @@
|
||||
# /externals/
|
||||
/externals/Makefile
|
||||
/externals/Makefile.in
|
||||
/externals/aterm-*
|
||||
/externals/have-aterm
|
||||
/externals/build-aterm
|
||||
/externals/inst-aterm
|
||||
/externals/bzip2-*
|
||||
/externals/have-bzip2
|
||||
/externals/build-bzip2
|
||||
/externals/inst-bzip2
|
||||
|
||||
# /make/examples/aterm/
|
||||
/make/examples/aterm/result*
|
||||
|
||||
# /make/examples/aterm/aterm/
|
||||
/make/examples/aterm/aterm/*
|
||||
|
||||
# /make/examples/aterm/test/
|
||||
/make/examples/aterm/test/*
|
||||
/externals/sqlite-*
|
||||
/externals/build-sqlite
|
||||
|
||||
# /misc/
|
||||
/misc/Makefile.in
|
||||
@@ -100,13 +88,16 @@
|
||||
/scripts/nix-channel
|
||||
/scripts/nix-build
|
||||
/scripts/nix-copy-closure
|
||||
/scripts/readmanifest.pm
|
||||
/scripts/readconfig.pm
|
||||
/scripts/nix-generate-patches
|
||||
/scripts/NixConfig.pm
|
||||
/scripts/NixManifest.pm
|
||||
/scripts/GeneratePatches.pm
|
||||
/scripts/download-using-manifests.pl
|
||||
/scripts/copy-from-other-stores.pl
|
||||
/scripts/generate-patches.pl
|
||||
/scripts/find-runtime-roots.pl
|
||||
/scripts/build-remote.pl
|
||||
/scripts/nix-reduce-build
|
||||
/scripts/nix-http-export.cgi
|
||||
|
||||
# /src/
|
||||
/src/Makefile
|
||||
@@ -168,6 +159,7 @@
|
||||
/src/libstore/derivations-ast.cc
|
||||
/src/libstore/derivations-ast.hh
|
||||
/src/libstore/.libs
|
||||
/src/libstore/schema.sql.hh
|
||||
|
||||
# /src/libutil/
|
||||
/src/libutil/Makefile
|
||||
@@ -242,6 +234,7 @@
|
||||
/tests/config.nix
|
||||
/tests/common.sh
|
||||
/tests/dummy
|
||||
/tests/result*
|
||||
|
||||
# /tests/lang/
|
||||
/tests/lang/*.out
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SUBDIRS = externals src scripts corepkgs doc misc tests
|
||||
SUBDIRS = externals src perl scripts corepkgs doc misc tests
|
||||
EXTRA_DIST = substitute.mk nix.spec nix.spec.in bootstrap.sh \
|
||||
nix.conf.example NEWS version
|
||||
|
||||
@@ -33,7 +33,7 @@ init-state:
|
||||
$(INSTALL) $(INIT_FLAGS) -d $(DESTDIR)$(localstatedir)/nix/temproots
|
||||
ln -sfn $(localstatedir)/nix/profiles $(DESTDIR)$(localstatedir)/nix/gcroots/profiles
|
||||
$(INSTALL) $(INIT_FLAGS) -d $(DESTDIR)$(localstatedir)/nix/userpool
|
||||
-$(INSTALL) $(INIT_FLAGS) -m 1777 -d $(DESTDIR)$(storedir)
|
||||
-$(INSTALL) $(INIT_FLAGS) -d $(DESTDIR)$(storedir)
|
||||
$(INSTALL) $(INIT_FLAGS) $(GROUP_WRITABLE) -d $(DESTDIR)$(localstatedir)/nix/manifests
|
||||
ln -sfn $(localstatedir)/nix/manifests $(DESTDIR)$(localstatedir)/nix/gcroots/manifests
|
||||
|
||||
|
||||
149
aterm-gc.supp
149
aterm-gc.supp
@@ -1,149 +0,0 @@
|
||||
{
|
||||
ATerm library conservatively scans for GC roots
|
||||
Memcheck:Cond
|
||||
fun:*
|
||||
fun:AT_collect_minor
|
||||
}
|
||||
|
||||
{
|
||||
ATerm library conservatively scans for GC roots
|
||||
Memcheck:Cond
|
||||
fun:*
|
||||
fun:*
|
||||
fun:AT_collect_minor
|
||||
}
|
||||
|
||||
{
|
||||
ATerm library conservatively scans for GC roots
|
||||
Memcheck:Value4
|
||||
fun:*
|
||||
fun:AT_collect_minor
|
||||
}
|
||||
|
||||
{
|
||||
ATerm library conservatively scans for GC roots
|
||||
Memcheck:Value8
|
||||
fun:*
|
||||
fun:AT_collect_minor
|
||||
}
|
||||
|
||||
{
|
||||
ATerm library conservatively scans for GC roots
|
||||
Memcheck:Value4
|
||||
fun:*
|
||||
fun:*
|
||||
fun:AT_collect_minor
|
||||
}
|
||||
|
||||
{
|
||||
ATerm library conservatively scans for GC roots
|
||||
Memcheck:Value8
|
||||
fun:*
|
||||
fun:*
|
||||
fun:AT_collect_minor
|
||||
}
|
||||
|
||||
{
|
||||
ATerm library conservatively scans for GC roots
|
||||
Memcheck:Addr4
|
||||
fun:*
|
||||
fun:AT_collect_minor
|
||||
}
|
||||
|
||||
{
|
||||
ATerm library conservatively scans for GC roots
|
||||
Memcheck:Addr8
|
||||
fun:*
|
||||
fun:AT_collect_minor
|
||||
}
|
||||
|
||||
{
|
||||
ATerm library conservatively scans for GC roots
|
||||
Memcheck:Cond
|
||||
fun:*
|
||||
fun:AT_collect
|
||||
}
|
||||
|
||||
{
|
||||
ATerm library conservatively scans for GC roots
|
||||
Memcheck:Value4
|
||||
fun:*
|
||||
fun:AT_collect
|
||||
}
|
||||
|
||||
{
|
||||
ATerm library conservatively scans for GC roots
|
||||
Memcheck:Value8
|
||||
fun:*
|
||||
fun:AT_collect
|
||||
}
|
||||
|
||||
{
|
||||
ATerm library conservatively scans for GC roots
|
||||
Memcheck:Addr4
|
||||
fun:*
|
||||
fun:AT_collect
|
||||
}
|
||||
|
||||
{
|
||||
ATerm library conservatively scans for GC roots
|
||||
Memcheck:Addr8
|
||||
fun:*
|
||||
fun:AT_collect
|
||||
}
|
||||
|
||||
{
|
||||
ATerm library conservatively scans for GC roots
|
||||
Memcheck:Value4
|
||||
fun:*
|
||||
fun:*
|
||||
fun:AT_collect
|
||||
}
|
||||
|
||||
{
|
||||
ATerm library conservatively scans for GC roots
|
||||
Memcheck:Value8
|
||||
fun:*
|
||||
fun:*
|
||||
fun:AT_collect
|
||||
}
|
||||
|
||||
{
|
||||
ATerm library conservatively scans for GC roots
|
||||
Memcheck:Cond
|
||||
fun:*
|
||||
fun:*
|
||||
fun:AT_collect
|
||||
}
|
||||
|
||||
{
|
||||
ATerm library conservatively scans for GC roots
|
||||
Memcheck:Value4
|
||||
fun:*
|
||||
fun:*
|
||||
fun:mark_phase
|
||||
}
|
||||
|
||||
{
|
||||
ATerm library conservatively scans for GC roots
|
||||
Memcheck:Cond
|
||||
fun:*
|
||||
fun:*
|
||||
fun:mark_phase
|
||||
}
|
||||
|
||||
{
|
||||
ATerm library conservatively scans for GC roots
|
||||
Memcheck:Value4
|
||||
fun:*
|
||||
fun:*
|
||||
fun:mark_phase_young
|
||||
}
|
||||
|
||||
{
|
||||
ATerm library conservatively scans for GC roots
|
||||
Memcheck:Cond
|
||||
fun:*
|
||||
fun:*
|
||||
fun:mark_phase_young
|
||||
}
|
||||
@@ -1,252 +0,0 @@
|
||||
#! /usr/bin/perl -w -I /home/eelco/.nix-profile/lib/site_perl
|
||||
|
||||
use strict;
|
||||
use XML::LibXML;
|
||||
#use XML::Simple;
|
||||
|
||||
my $blacklistFN = shift @ARGV;
|
||||
die unless defined $blacklistFN;
|
||||
my $userEnv = shift @ARGV;
|
||||
die unless defined $userEnv;
|
||||
|
||||
|
||||
# Read the blacklist.
|
||||
my $parser = XML::LibXML->new();
|
||||
my $blacklist = $parser->parse_file($blacklistFN)->getDocumentElement;
|
||||
|
||||
#print $blacklist->toString() , "\n";
|
||||
|
||||
|
||||
# Get all the elements of the user environment.
|
||||
my $userEnvElems = `nix-store --query --references '$userEnv'`;
|
||||
die "cannot query user environment elements" if $? != 0;
|
||||
my @userEnvElems = split ' ', $userEnvElems;
|
||||
|
||||
|
||||
my %storePathHashes;
|
||||
|
||||
|
||||
sub getElemNodes {
|
||||
my $node = shift;
|
||||
my @elems = ();
|
||||
foreach my $node ($node->getChildNodes) {
|
||||
push @elems, $node if $node->nodeType == XML_ELEMENT_NODE;
|
||||
}
|
||||
return @elems;
|
||||
}
|
||||
|
||||
|
||||
my %referencesCache;
|
||||
sub getReferences {
|
||||
my $path = shift;
|
||||
return $referencesCache{$path} if defined $referencesCache{$path};
|
||||
|
||||
my $references = `nix-store --query --references '$path'`;
|
||||
die "cannot query references" if $? != 0;
|
||||
$referencesCache{$path} = [split ' ', $references];
|
||||
|
||||
return $referencesCache{$path};
|
||||
}
|
||||
|
||||
|
||||
my %attrsCache;
|
||||
sub getAttr {
|
||||
my $path = shift;
|
||||
my $name = shift;
|
||||
my $key = "$path/$name";
|
||||
return $referencesCache{$key} if defined $referencesCache{$key};
|
||||
|
||||
my $value = `nix-store --query --binding '$name' '$path' 2> /dev/null`;
|
||||
$value = "" if $? != 0; # !!!
|
||||
chomp $value;
|
||||
$referencesCache{$key} = $value;
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
sub evalCondition;
|
||||
|
||||
|
||||
sub traverse {
|
||||
my $done = shift;
|
||||
my $set = shift;
|
||||
my $path = shift;
|
||||
my $stopCondition = shift;
|
||||
|
||||
return if defined $done->{$path};
|
||||
$done->{$path} = 1;
|
||||
$set->{$path} = 1;
|
||||
|
||||
# print " in $path\n";
|
||||
|
||||
if (!evalCondition({$path => 1}, $stopCondition)) {
|
||||
# print " STOPPING in $path\n";
|
||||
return;
|
||||
}
|
||||
|
||||
# Get the requisites of the deriver.
|
||||
|
||||
foreach my $reference (@{getReferences $path}) {
|
||||
traverse($done, $set, $reference, $stopCondition);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub evalSet {
|
||||
my $inSet = shift;
|
||||
my $expr = shift;
|
||||
my $name = $expr->getName;
|
||||
|
||||
if ($name eq "traverse") {
|
||||
my $stopCondition = (getElemNodes $expr)[0];
|
||||
my $done = { };
|
||||
my $set = { };
|
||||
foreach my $path (keys %{$inSet}) {
|
||||
traverse($done, $set, $path, $stopCondition);
|
||||
}
|
||||
return $set;
|
||||
}
|
||||
|
||||
else {
|
||||
die "unknown element `$name'";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Function for evaluating conditions.
|
||||
sub evalCondition {
|
||||
my $storePaths = shift;
|
||||
my $condition = shift;
|
||||
my $elemName = $condition->getName;
|
||||
|
||||
if ($elemName eq "containsSource") {
|
||||
my $hash = $condition->attributes->getNamedItem("hash")->getValue;
|
||||
foreach my $path (keys %{$storePathHashes{$hash}}) {
|
||||
return 1 if defined $storePaths->{$path};
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
elsif ($elemName eq "hasName") {
|
||||
my $nameRE = $condition->attributes->getNamedItem("name")->getValue;
|
||||
foreach my $path (keys %{$storePaths}) {
|
||||
return 1 if $path =~ /$nameRE/;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
elsif ($elemName eq "hasAttr") {
|
||||
my $name = $condition->attributes->getNamedItem("name")->getValue;
|
||||
my $valueRE = $condition->attributes->getNamedItem("value")->getValue;
|
||||
foreach my $path (keys %{$storePaths}) {
|
||||
if ($path =~ /\.drv$/) {
|
||||
my $value = getAttr($path, $name);
|
||||
# print " $path $name $value\n";
|
||||
return 1 if $value =~ /$valueRE/;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
elsif ($elemName eq "and") {
|
||||
my $result = 1;
|
||||
foreach my $node (getElemNodes $condition) {
|
||||
$result &= evalCondition($storePaths, $node);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
elsif ($elemName eq "not") {
|
||||
return !evalCondition($storePaths, (getElemNodes $condition)[0]);
|
||||
}
|
||||
|
||||
elsif ($elemName eq "within") {
|
||||
my @elems = getElemNodes $condition;
|
||||
my $set = evalSet($storePaths, $elems[0]);
|
||||
return evalCondition($set, $elems[1]);
|
||||
}
|
||||
|
||||
elsif ($elemName eq "true") {
|
||||
return 1;
|
||||
}
|
||||
|
||||
elsif ($elemName eq "false") {
|
||||
return 0;
|
||||
}
|
||||
|
||||
else {
|
||||
die "unknown element `$elemName'";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub evalOr {
|
||||
my $storePaths = shift;
|
||||
my $nodes = shift;
|
||||
|
||||
my $result = 0;
|
||||
foreach my $node (@{$nodes}) {
|
||||
$result |= evalCondition($storePaths, $node);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
# Iterate over all elements, check them.
|
||||
foreach my $userEnvElem (@userEnvElems) {
|
||||
|
||||
# Get the deriver of this path.
|
||||
my $deriver = `nix-store --query --deriver '$userEnvElem'`;
|
||||
die "cannot query deriver" if $? != 0;
|
||||
chomp $deriver;
|
||||
|
||||
if ($deriver eq "unknown-deriver") {
|
||||
# print " deriver unknown, cannot check sources\n";
|
||||
next;
|
||||
}
|
||||
|
||||
print "CHECKING $userEnvElem\n";
|
||||
|
||||
|
||||
# Get the requisites of the deriver.
|
||||
# my $requisites = `nix-store --query --requisites --include-outputs '$deriver'`;
|
||||
# die "cannot query requisites" if $? != 0;
|
||||
# my @requisites = split ' ', $requisites;
|
||||
|
||||
|
||||
# Get the hashes of the requisites.
|
||||
# my $hashes = `nix-store --query --hash @requisites`;
|
||||
# die "cannot query hashes" if $? != 0;
|
||||
# my @hashes = split ' ', $hashes;
|
||||
# for (my $i = 0; $i < scalar @requisites; $i++) {
|
||||
# die unless $i < scalar @hashes;
|
||||
# my $hash = $hashes[$i];
|
||||
# $storePathHashes{$hash} = {} unless defined $storePathHashes{$hash};
|
||||
# my $r = $storePathHashes{$hash}; # !!! fix
|
||||
# $$r{$requisites[$i]} = 1;
|
||||
# }
|
||||
|
||||
|
||||
# Evaluate each blacklist item.
|
||||
foreach my $item ($blacklist->getChildrenByTagName("item")) {
|
||||
my $itemId = $item->getAttributeNode("id")->getValue;
|
||||
# print " CHECKING FOR $itemId\n";
|
||||
|
||||
my $condition = ($item->getChildrenByTagName("condition"))[0];
|
||||
die unless $condition;
|
||||
|
||||
# Evaluate the condition.
|
||||
my @elems = getElemNodes $condition;
|
||||
if (evalOr({$deriver => 1}, \@elems)) {
|
||||
# Oops, condition triggered.
|
||||
my $reason = ($item->getChildrenByTagName("reason"))[0]->getChildNodes->to_literal;
|
||||
$reason =~ s/\s+/ /g;
|
||||
$reason =~ s/^\s+//g;
|
||||
|
||||
print " VULNERABLE TO `$itemId': $reason\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
#! /bin/sh -e
|
||||
rm -f aclocal.m4
|
||||
mkdir -p config
|
||||
libtoolize --copy
|
||||
aclocal
|
||||
autoheader
|
||||
automake --add-missing --copy
|
||||
autoconf
|
||||
exec autoreconf -vfi
|
||||
|
||||
98
configure.ac
98
configure.ac
@@ -5,42 +5,42 @@ AM_INIT_AUTOMAKE([dist-bzip2 foreign])
|
||||
|
||||
AC_DEFINE_UNQUOTED(NIX_VERSION, ["$VERSION"], [Nix version.])
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
AC_PROG_SED
|
||||
|
||||
# Construct a Nix system name (like "i686-linux").
|
||||
AC_CANONICAL_HOST
|
||||
AC_MSG_CHECKING([for the canonical Nix system name])
|
||||
cpu_name=$(uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ' 'abcdefghijklmnopqrstuvwxyz_')
|
||||
machine_name=$(uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ' 'abcdefghijklmnopqrstuvwxyz_')
|
||||
|
||||
case $machine_name in
|
||||
i*86)
|
||||
machine_name=i686
|
||||
;;
|
||||
x86_64)
|
||||
machine_name=x86_64
|
||||
;;
|
||||
ppc)
|
||||
machine_name=powerpc
|
||||
;;
|
||||
*)
|
||||
if test "$cpu_name" != "unknown"; then
|
||||
machine_name=$cpu_name
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
AC_ARG_WITH(system, AC_HELP_STRING([--with-system=SYSTEM],
|
||||
[Platform identifier (e.g., `i686-linux').]),
|
||||
[system=$withval],
|
||||
[case "$host_cpu" in
|
||||
i*86)
|
||||
machine_name="i686";;
|
||||
amd64)
|
||||
machine_name="x86_64";;
|
||||
*)
|
||||
machine_name="$host_cpu";;
|
||||
esac
|
||||
|
||||
sys_name=$(uname -s | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ' 'abcdefghijklmnopqrstuvwxyz_')
|
||||
case "$host_os" in
|
||||
linux-gnu*)
|
||||
# For backward compatibility, strip the `-gnu' part.
|
||||
system="$machine_name-linux";;
|
||||
*)
|
||||
# Strip the version number from names such as `gnu0.3',
|
||||
# `darwin10.2.0', etc.
|
||||
system="$machine_name-`echo $host_os | "$SED" -e's/@<:@0-9.@:>@*$//g'`";;
|
||||
esac])
|
||||
|
||||
sys_name=$(uname -s | tr 'A-Z ' 'a-z_')
|
||||
|
||||
case $sys_name in
|
||||
cygwin*)
|
||||
sys_name=cygwin
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_WITH(system, AC_HELP_STRING([--with-system=SYSTEM],
|
||||
[Platform identifier (e.g., `i686-linux').]),
|
||||
system=$withval, system="${machine_name}-${sys_name}")
|
||||
|
||||
AC_MSG_RESULT($system)
|
||||
AC_SUBST(system)
|
||||
AC_DEFINE_UNQUOTED(SYSTEM, ["$system"], [platform identifier (`cpu-os')])
|
||||
@@ -62,7 +62,7 @@ fi
|
||||
|
||||
|
||||
# Solaris-specific stuff.
|
||||
if test "$sys_name" = "sunos"; then
|
||||
if test "$sys_name" = sunos; then
|
||||
# Solaris requires -lsocket -lnsl for network functions
|
||||
LIBS="-lsocket -lnsl $LIBS"
|
||||
fi
|
||||
@@ -171,6 +171,7 @@ AC_PATH_PROG(openssl_prog, openssl, openssl) # if not found, call openssl in $PA
|
||||
AC_SUBST(openssl_prog)
|
||||
AC_DEFINE_UNQUOTED(OPENSSL_PATH, ["$openssl_prog"], [Path of the OpenSSL binary])
|
||||
|
||||
|
||||
# Test that Perl has the open/fork feature (Perl 5.8.0 and beyond).
|
||||
AC_MSG_CHECKING([whether Perl is recent enough])
|
||||
if ! $perl -e 'open(FOO, "-|", "true"); while (<FOO>) { print; }; close FOO or die;'; then
|
||||
@@ -179,6 +180,7 @@ if ! $perl -e 'open(FOO, "-|", "true"); while (<FOO>) { print; }; close FOO or d
|
||||
fi
|
||||
AC_MSG_RESULT(yes)
|
||||
|
||||
|
||||
NEED_PROG(cat, cat)
|
||||
NEED_PROG(tr, tr)
|
||||
AC_ARG_WITH(coreutils-bin, AC_HELP_STRING([--with-coreutils-bin=PATH],
|
||||
@@ -186,6 +188,7 @@ AC_ARG_WITH(coreutils-bin, AC_HELP_STRING([--with-coreutils-bin=PATH],
|
||||
coreutils=$withval, coreutils=$(dirname $cat))
|
||||
AC_SUBST(coreutils)
|
||||
|
||||
|
||||
AC_ARG_WITH(docbook-rng, AC_HELP_STRING([--with-docbook-rng=PATH],
|
||||
[path of the DocBook RelaxNG schema]),
|
||||
docbookrng=$withval, docbookrng=/docbook-rng-missing)
|
||||
@@ -196,16 +199,19 @@ AC_ARG_WITH(docbook-xsl, AC_HELP_STRING([--with-docbook-xsl=PATH],
|
||||
docbookxsl=$withval, docbookxsl=/docbook-xsl-missing)
|
||||
AC_SUBST(docbookxsl)
|
||||
|
||||
|
||||
AC_ARG_WITH(xml-flags, AC_HELP_STRING([--with-xml-flags=FLAGS],
|
||||
[extra flags to be passed to xmllint and xsltproc]),
|
||||
xmlflags=$withval, xmlflags=)
|
||||
AC_SUBST(xmlflags)
|
||||
|
||||
|
||||
AC_ARG_WITH(store-dir, AC_HELP_STRING([--with-store-dir=PATH],
|
||||
[path of the Nix store]),
|
||||
[path of the Nix store (defaults to /nix/store)]),
|
||||
storedir=$withval, storedir='/nix/store')
|
||||
AC_SUBST(storedir)
|
||||
|
||||
|
||||
AC_ARG_WITH(openssl, AC_HELP_STRING([--with-openssl=PATH],
|
||||
[prefix of the OpenSSL library]),
|
||||
openssl=$withval, openssl=)
|
||||
@@ -217,6 +223,7 @@ if test -n "$openssl"; then
|
||||
AC_DEFINE(HAVE_OPENSSL, 1, [Whether to use OpenSSL.])
|
||||
fi
|
||||
|
||||
|
||||
AC_ARG_WITH(bzip2, AC_HELP_STRING([--with-bzip2=PATH],
|
||||
[prefix of bzip2]),
|
||||
bzip2=$withval, bzip2=)
|
||||
@@ -243,11 +250,12 @@ AC_SUBST(bzip2_include)
|
||||
AC_SUBST(bzip2_bin)
|
||||
AC_SUBST(bzip2_bin_test)
|
||||
|
||||
|
||||
AC_ARG_WITH(sqlite, AC_HELP_STRING([--with-sqlite=PATH],
|
||||
[prefix of SQLite]),
|
||||
sqlite=$withval, sqlite=)
|
||||
AM_CONDITIONAL(HAVE_SQLITE, test -n "$sqlite")
|
||||
SQLITE_VERSION=3070500
|
||||
SQLITE_VERSION=3070900
|
||||
AC_SUBST(SQLITE_VERSION)
|
||||
if test -z "$sqlite"; then
|
||||
sqlite_lib='${top_builddir}/externals/sqlite-autoconf-$(SQLITE_VERSION)/libsqlite3.la'
|
||||
@@ -262,17 +270,37 @@ AC_SUBST(sqlite_lib)
|
||||
AC_SUBST(sqlite_include)
|
||||
AC_SUBST(sqlite_bin)
|
||||
|
||||
|
||||
# Whether to use the Boehm garbage collector.
|
||||
AC_ARG_ENABLE(gc, AC_HELP_STRING([--enable-gc],
|
||||
[enable garbage collection in the Nix expression evaluator (requires Boehm GC)]),
|
||||
gc=$enableval, gc=)
|
||||
if test -n "$gc"; then
|
||||
gc=$enableval, gc=no)
|
||||
if test "$gc" = yes; then
|
||||
PKG_CHECK_MODULES([BDW_GC], [bdw-gc])
|
||||
boehmgc_lib="-L$boehmgc/lib -lgc"
|
||||
CXXFLAGS="$BDW_GC_CFLAGS $CXXFLAGS"
|
||||
AC_DEFINE(HAVE_BOEHMGC, 1, [Whether to use the Boehm garbage collector.])
|
||||
fi
|
||||
AC_SUBST(boehmgc_lib)
|
||||
|
||||
|
||||
# Check for the required Perl dependencies (DBI and DBD::SQLite).
|
||||
perlFlags="-I${libdir}/perl5/site_perl"
|
||||
|
||||
AC_ARG_WITH(dbi, AC_HELP_STRING([--with-dbi=PATH],
|
||||
[prefix of the Perl DBI library]),
|
||||
perlFlags="$perlFlags -I$withval")
|
||||
|
||||
AC_ARG_WITH(dbd-sqlite, AC_HELP_STRING([--with-dbd-sqlite=PATH],
|
||||
[prefix of the Perl DBD::SQLite library]),
|
||||
perlFlags="$perlFlags -I$withval")
|
||||
|
||||
AC_MSG_CHECKING([whether DBD::SQLite works])
|
||||
if ! $perl $perlFlags -e 'use DBI; use DBD::SQLite;' 2>&5; then
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_FAILURE([The Perl modules DBI and/or DBD::SQLite are missing.])
|
||||
fi
|
||||
AC_MSG_RESULT(yes)
|
||||
|
||||
AC_SUBST(perlFlags)
|
||||
|
||||
|
||||
AC_ARG_ENABLE(init-state, AC_HELP_STRING([--disable-init-state],
|
||||
@@ -286,7 +314,7 @@ AC_CHECK_FUNCS([setresuid setreuid lchown])
|
||||
|
||||
|
||||
# Nice to have, but not essential.
|
||||
AC_CHECK_FUNCS([strsignal posix_fallocate nanosleep])
|
||||
AC_CHECK_FUNCS([strsignal posix_fallocate nanosleep sysconf])
|
||||
|
||||
|
||||
# This is needed if ATerm or bzip2 are static libraries,
|
||||
@@ -315,11 +343,9 @@ AC_CONFIG_FILES([Makefile
|
||||
src/nix-setuid-helper/Makefile
|
||||
src/nix-log2xml/Makefile
|
||||
src/bsdiff-4.3/Makefile
|
||||
perl/Makefile
|
||||
scripts/Makefile
|
||||
corepkgs/Makefile
|
||||
corepkgs/nar/Makefile
|
||||
corepkgs/buildenv/Makefile
|
||||
corepkgs/channels/Makefile
|
||||
doc/Makefile
|
||||
doc/manual/Makefile
|
||||
misc/Makefile
|
||||
|
||||
@@ -1 +1,11 @@
|
||||
SUBDIRS = nar buildenv channels
|
||||
all-local: config.nix
|
||||
|
||||
files = nar.nix buildenv.nix buildenv.pl unpack-channel.nix unpack-channel.sh derivation.nix
|
||||
|
||||
install-exec-local:
|
||||
$(INSTALL) -d $(DESTDIR)$(datadir)/nix/corepkgs
|
||||
$(INSTALL_DATA) config.nix $(files) $(DESTDIR)$(datadir)/nix/corepkgs
|
||||
|
||||
include ../substitute.mk
|
||||
|
||||
EXTRA_DIST = config.nix.in $(files)
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
{system, derivations, manifest}:
|
||||
with import <nix/config.nix>;
|
||||
|
||||
{ system, derivations, manifest }:
|
||||
|
||||
derivation {
|
||||
name = "user-environment";
|
||||
system = system;
|
||||
builder = ./builder.pl;
|
||||
builder = perl;
|
||||
args = [ "-w" ./buildenv.pl ];
|
||||
|
||||
manifest = manifest;
|
||||
|
||||
2
corepkgs/buildenv/builder.pl.in → corepkgs/buildenv.pl
Executable file → Normal file
2
corepkgs/buildenv/builder.pl.in → corepkgs/buildenv.pl
Executable file → Normal file
@@ -1,5 +1,3 @@
|
||||
#! @perl@ -w
|
||||
|
||||
use strict;
|
||||
use Cwd;
|
||||
use IO::Handle;
|
||||
@@ -1,11 +0,0 @@
|
||||
all-local: builder.pl
|
||||
|
||||
install-exec-local:
|
||||
$(INSTALL) -d $(DESTDIR)$(datadir)/nix/corepkgs
|
||||
$(INSTALL) -d $(DESTDIR)$(datadir)/nix/corepkgs/buildenv
|
||||
$(INSTALL_DATA) $(srcdir)/default.nix $(DESTDIR)$(datadir)/nix/corepkgs/buildenv
|
||||
$(INSTALL_PROGRAM) builder.pl $(DESTDIR)$(datadir)/nix/corepkgs/buildenv
|
||||
|
||||
include ../../substitute.mk
|
||||
|
||||
EXTRA_DIST = default.nix builder.pl.in
|
||||
@@ -1,11 +0,0 @@
|
||||
all-local: unpack.sh
|
||||
|
||||
install-exec-local:
|
||||
$(INSTALL) -d $(DESTDIR)$(datadir)/nix/corepkgs
|
||||
$(INSTALL) -d $(DESTDIR)$(datadir)/nix/corepkgs/channels
|
||||
$(INSTALL_DATA) $(srcdir)/unpack.nix $(DESTDIR)$(datadir)/nix/corepkgs/channels
|
||||
$(INSTALL_PROGRAM) unpack.sh $(DESTDIR)$(datadir)/nix/corepkgs/channels
|
||||
|
||||
include ../../substitute.mk
|
||||
|
||||
EXTRA_DIST = unpack.nix unpack.sh.in
|
||||
@@ -1,7 +0,0 @@
|
||||
{system, inputs}:
|
||||
|
||||
derivation {
|
||||
name = "channels";
|
||||
builder = ./unpack.sh;
|
||||
inherit system inputs;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
#! @shell@ -e
|
||||
|
||||
# Cygwin compatibility hack: bunzip2 expects cygwin.dll in $PATH.
|
||||
export PATH=@coreutils@
|
||||
|
||||
@coreutils@/mkdir $out
|
||||
@coreutils@/mkdir $out/tmp
|
||||
cd $out/tmp
|
||||
|
||||
inputs=($inputs)
|
||||
for ((n = 0; n < ${#inputs[*]}; n += 2)); do
|
||||
channelName=${inputs[n]}
|
||||
channelTarball=${inputs[n+1]}
|
||||
|
||||
echo "unpacking channel $channelName"
|
||||
|
||||
@bunzip2@ < $channelTarball | @tar@ xf -
|
||||
|
||||
if test -e */channel-name; then
|
||||
channelName="$(@coreutils@/cat */channel-name)"
|
||||
fi
|
||||
|
||||
nr=1
|
||||
attrName=$(echo $channelName | @tr@ -- '- ' '__')
|
||||
dirName=$attrName
|
||||
while test -e ../$dirName; do
|
||||
nr=$((nr+1))
|
||||
dirName=$attrName-$nr
|
||||
done
|
||||
|
||||
@coreutils@/mv * ../$dirName # !!! hacky
|
||||
done
|
||||
|
||||
cd ..
|
||||
@coreutils@/rmdir tmp
|
||||
13
corepkgs/config.nix.in
Normal file
13
corepkgs/config.nix.in
Normal file
@@ -0,0 +1,13 @@
|
||||
let
|
||||
fromEnv = var: def:
|
||||
let val = builtins.getEnv var; in
|
||||
if val != "" then val else def;
|
||||
in {
|
||||
perl = "@perl@";
|
||||
shell = "@shell@";
|
||||
coreutils = "@coreutils@";
|
||||
bzip2 = fromEnv "NIX_BZIP2" "@bzip2@";
|
||||
tar = "@tar@";
|
||||
tr = "@tr@";
|
||||
nixBinDir = fromEnv "NIX_BIN_DIR" "@bindir@";
|
||||
}
|
||||
27
corepkgs/derivation.nix
Normal file
27
corepkgs/derivation.nix
Normal file
@@ -0,0 +1,27 @@
|
||||
/* This is the implementation of the ‘derivation’ builtin function.
|
||||
It's actually a wrapper around the ‘derivationStrict’ primop. */
|
||||
|
||||
drvAttrs @ { outputs ? [ "out" ], ... }:
|
||||
|
||||
let
|
||||
|
||||
strict = derivationStrict drvAttrs;
|
||||
|
||||
commonAttrs = drvAttrs // (builtins.listToAttrs outputsList) //
|
||||
{ all = map (x: x.value) outputsList;
|
||||
inherit drvAttrs;
|
||||
};
|
||||
|
||||
outputToAttrListElement = outputName:
|
||||
{ name = outputName;
|
||||
value = commonAttrs // {
|
||||
outPath = builtins.getAttr outputName strict;
|
||||
drvPath = strict.drvPath;
|
||||
type = "derivation";
|
||||
inherit outputName;
|
||||
};
|
||||
};
|
||||
|
||||
outputsList = map outputToAttrListElement outputs;
|
||||
|
||||
in (builtins.head outputsList).value
|
||||
30
corepkgs/nar.nix
Normal file
30
corepkgs/nar.nix
Normal file
@@ -0,0 +1,30 @@
|
||||
with import <nix/config.nix>;
|
||||
|
||||
let
|
||||
|
||||
builder = builtins.toFile "nar.sh"
|
||||
''
|
||||
export PATH=${nixBinDir}:${coreutils}
|
||||
|
||||
echo "packing ‘$storePath’..."
|
||||
mkdir $out
|
||||
dst=$out/tmp.nar.bz2
|
||||
|
||||
set -o pipefail
|
||||
nix-store --dump "$storePath" | ${bzip2} > $dst
|
||||
|
||||
nix-hash --flat --type $hashAlgo --base32 $dst > $out/narbz2-hash
|
||||
|
||||
mv $out/tmp.nar.bz2 $out/$(cat $out/narbz2-hash).nar.bz2
|
||||
'';
|
||||
|
||||
in
|
||||
|
||||
{ system, storePath, hashAlgo }:
|
||||
|
||||
derivation {
|
||||
name = "nar";
|
||||
builder = shell;
|
||||
args = [ "-e" builder ];
|
||||
inherit system storePath hashAlgo;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
all-local: nar.sh
|
||||
|
||||
install-exec-local:
|
||||
$(INSTALL) -d $(DESTDIR)$(datadir)/nix/corepkgs
|
||||
$(INSTALL) -d $(DESTDIR)$(datadir)/nix/corepkgs/nar
|
||||
$(INSTALL_DATA) $(srcdir)/nar.nix $(DESTDIR)$(datadir)/nix/corepkgs/nar
|
||||
$(INSTALL_PROGRAM) nar.sh $(DESTDIR)$(datadir)/nix/corepkgs/nar
|
||||
|
||||
include ../../substitute.mk
|
||||
|
||||
EXTRA_DIST = nar.nix nar.sh.in
|
||||
@@ -1,7 +0,0 @@
|
||||
{system, storePath, hashAlgo}:
|
||||
|
||||
derivation {
|
||||
name = "nar";
|
||||
builder = ./nar.sh;
|
||||
inherit system storePath hashAlgo;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
#! @shell@ -e
|
||||
|
||||
echo "packing $storePath into $out..."
|
||||
@coreutils@/mkdir $out
|
||||
dst=$out/tmp.nar.bz2
|
||||
@bindir@/nix-store --dump "$storePath" > tmp
|
||||
|
||||
@bzip2@ < tmp > $dst
|
||||
|
||||
@bindir@/nix-hash --flat --type $hashAlgo --base32 $dst > $out/narbz2-hash
|
||||
|
||||
@coreutils@/mv $out/tmp.nar.bz2 $out/$(@coreutils@/cat $out/narbz2-hash).nar.bz2
|
||||
11
corepkgs/unpack-channel.nix
Normal file
11
corepkgs/unpack-channel.nix
Normal file
@@ -0,0 +1,11 @@
|
||||
with import <nix/config.nix>;
|
||||
|
||||
{ system, inputs }:
|
||||
|
||||
derivation {
|
||||
name = "channels";
|
||||
builder = shell;
|
||||
args = [ "-e" ./unpack-channel.sh ];
|
||||
inherit system inputs bzip2 tar tr;
|
||||
PATH = "${nixBinDir}:${coreutils}";
|
||||
}
|
||||
30
corepkgs/unpack-channel.sh
Normal file
30
corepkgs/unpack-channel.sh
Normal file
@@ -0,0 +1,30 @@
|
||||
mkdir $out
|
||||
mkdir $out/tmp
|
||||
cd $out/tmp
|
||||
|
||||
inputs=($inputs)
|
||||
for ((n = 0; n < ${#inputs[*]}; n += 2)); do
|
||||
channelName=${inputs[n]}
|
||||
channelTarball=${inputs[n+1]}
|
||||
|
||||
echo "unpacking channel $channelName"
|
||||
|
||||
$bzip2 -d < $channelTarball | $tar xf -
|
||||
|
||||
if test -e */channel-name; then
|
||||
channelName="$(cat */channel-name)"
|
||||
fi
|
||||
|
||||
nr=1
|
||||
attrName=$(echo $channelName | $tr -- '- ' '__')
|
||||
dirName=$attrName
|
||||
while test -e ../$dirName; do
|
||||
nr=$((nr+1))
|
||||
dirName=$attrName-$nr
|
||||
done
|
||||
|
||||
mv * ../$dirName # !!! hacky
|
||||
done
|
||||
|
||||
cd ..
|
||||
rmdir tmp
|
||||
@@ -43,10 +43,10 @@ is also available as <function>builtins.derivation</function>.</para>
|
||||
|
||||
<listitem><para>Return the names of the attributes in the
|
||||
attribute set <replaceable>attrs</replaceable> in a sorted list.
|
||||
For instance, <literal>builtins.attrNames {y = 1; x =
|
||||
"foo";}</literal> evaluates to <literal>["x" "y"]</literal>.
|
||||
There is no built-in function <function>attrValues</function>, but
|
||||
you can easily define it yourself:
|
||||
For instance, <literal>builtins.attrNames { y = 1; x = "foo";
|
||||
}</literal> evaluates to <literal>[ "x" "y" ]</literal>. There is
|
||||
no built-in function <function>attrValues</function>, but you can
|
||||
easily define it yourself:
|
||||
|
||||
<programlisting>
|
||||
attrValues = attrs: map (name: builtins.getAttr name attrs) (builtins.attrNames attrs);</programlisting>
|
||||
@@ -442,10 +442,10 @@ x: x + 456</programlisting>
|
||||
Example:
|
||||
|
||||
<programlisting>
|
||||
builtins.listToAttrs [
|
||||
{name = "foo"; value = 123;}
|
||||
{name = "bar"; value = 456;}
|
||||
]
|
||||
builtins.listToAttrs
|
||||
[ { name = "foo"; value = 123; }
|
||||
{ name = "bar"; value = 456; }
|
||||
]
|
||||
</programlisting>
|
||||
|
||||
evaluates to
|
||||
@@ -466,10 +466,10 @@ builtins.listToAttrs [
|
||||
example,
|
||||
|
||||
<programlisting>
|
||||
map (x: "foo" + x) ["bar" "bla" "abc"]</programlisting>
|
||||
map (x: "foo" + x) [ "bar" "bla" "abc" ]</programlisting>
|
||||
|
||||
evaluates to <literal>["foobar" "foobla"
|
||||
"fooabc"]</literal>.</para></listitem>
|
||||
evaluates to <literal>[ "foobar" "foobla" "fooabc"
|
||||
]</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
@@ -491,10 +491,10 @@ map (x: "foo" + x) ["bar" "bla" "abc"]</programlisting>
|
||||
a package name and version. The package name is everything up to
|
||||
but not including the first dash followed by a digit, and the
|
||||
version is everything following that dash. The result is returned
|
||||
in an attribute set <literal>{name, version}</literal>. Thus,
|
||||
in an attribute set <literal>{ name, version }</literal>. Thus,
|
||||
<literal>builtins.parseDrvName "nix-0.12pre12876"</literal>
|
||||
returns <literal>{name = "nix"; version =
|
||||
"0.12pre12876";}</literal>.</para></listitem>
|
||||
returns <literal>{ name = "nix"; version = "0.12pre12876";
|
||||
}</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
@@ -550,9 +550,9 @@ in config.someSetting</programlisting>
|
||||
exist in <replaceable>attrs</replaceable>. For instance,
|
||||
|
||||
<screen>
|
||||
removeAttrs { x = 1; y = 2; z = 3; } ["a" "x" "z"]</screen>
|
||||
removeAttrs { x = 1; y = 2; z = 3; } [ "a" "x" "z" ]</screen>
|
||||
|
||||
evaluates to <literal>{y = 2;}</literal>.</para></listitem>
|
||||
evaluates to <literal>{ y = 2; }</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
@@ -632,7 +632,7 @@ removeAttrs { x = 1; y = 2; z = 3; } ["a" "x" "z"]</screen>
|
||||
linkend='ex-hello-builder' /> into one file:
|
||||
|
||||
<programlisting>
|
||||
{stdenv, fetchurl, perl}:
|
||||
{ stdenv, fetchurl, perl }:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "hello-2.1.1";
|
||||
@@ -765,12 +765,12 @@ in foo</programlisting>
|
||||
using <function>toXML</function></title>
|
||||
|
||||
<programlisting><![CDATA[
|
||||
{stdenv, fetchurl, libxslt, jira, uberwiki}:
|
||||
{ stdenv, fetchurl, libxslt, jira, uberwiki }:
|
||||
|
||||
stdenv.mkDerivation (rec {
|
||||
name = "web-server";
|
||||
|
||||
buildInputs = [libxslt];
|
||||
buildInputs = [ libxslt ];
|
||||
|
||||
builder = builtins.toFile "builder.sh" "
|
||||
source $stdenv/setup
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
|
||||
<para>A number of persistent settings of Nix are stored in the file
|
||||
<filename><replaceable>prefix</replaceable>/etc/nix/nix.conf</filename>.
|
||||
<filename><replaceable>sysconfdir</replaceable>/nix/nix.conf</filename>.
|
||||
This file is a list of <literal><replaceable>name</replaceable> =
|
||||
<replaceable>value</replaceable></literal> pairs, one per line.
|
||||
Comments start with a <literal>#</literal> character. An example
|
||||
@@ -136,6 +136,25 @@ env-keep-derivations = false
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-build-timeout"><term><literal>build-timeout</literal></term>
|
||||
|
||||
<listitem>
|
||||
|
||||
<para>This option defines the maximum number of seconds that a
|
||||
builder can run. This is useful (for instance in a automated
|
||||
build system) to catch builds that are stuck in an infinite loop
|
||||
but keep writing to their standard output or standard error. It
|
||||
can be overriden using the <option
|
||||
linkend="opt-timeout">--timeout</option> command line
|
||||
switch.</para>
|
||||
|
||||
<para>The value <literal>0</literal> means that there is no
|
||||
timeout. This is also the default.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-build-users-group"><term><literal>build-users-group</literal></term>
|
||||
|
||||
|
||||
@@ -314,7 +314,7 @@ bit turned on (like <filename>/tmp</filename>):
|
||||
|
||||
<screen>
|
||||
$ chgrp nixbld /nix/store
|
||||
$ chmod 1777 /nix/store
|
||||
$ chmod 1775 /nix/store
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
@@ -323,7 +323,7 @@ $ chmod 1777 /nix/store
|
||||
specifying the build users group in the <link
|
||||
linkend="conf-build-users-group"><literal>build-users-group</literal>
|
||||
option</link> in the <link linkend="sec-conf-file">Nix configuration
|
||||
file</link> (<literal>/nix/etc/nix/nix.conf</literal>):
|
||||
file</link> (usually <literal>/etc/nix/nix.conf</literal>):
|
||||
|
||||
<programlisting>
|
||||
build-users-group = nixbld
|
||||
@@ -380,7 +380,7 @@ is a special account called <literal>nix</literal>, but it can be
|
||||
named anything. It should own the Nix store and database:
|
||||
|
||||
<screen>
|
||||
$ chown -R root /nix/store /nix/var/nix</screen>
|
||||
$ chown -R nix /nix/store /nix/var/nix</screen>
|
||||
|
||||
and of course <command>nix-worker --daemon</command> should be started
|
||||
under that user, e.g.,
|
||||
|
||||
@@ -24,8 +24,11 @@
|
||||
</group>
|
||||
<arg><option>--sign</option></arg>
|
||||
<arg><option>--gzip</option></arg>
|
||||
<arg><option>--bzip2</option></arg>
|
||||
<arg><option>--xz</option></arg>
|
||||
<arg><option>--include-outputs</option></arg>
|
||||
<arg choice='plain'>
|
||||
<arg><replaceable>user@</replaceable></arg><replaceable>machine</replaceable>
|
||||
<replaceable>user@</replaceable><replaceable>machine</replaceable>
|
||||
</arg>
|
||||
<arg choice='plain'><replaceable>paths</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
@@ -84,25 +87,36 @@ those paths. If this bothers you, use
|
||||
|
||||
<listitem><para>Let the sending machine cryptographically sign the
|
||||
dump of each path with the key in
|
||||
<filename>/nix/etc/nix/signing-key.sec</filename>. If the user on
|
||||
the target machine does not have direct access to the Nix store
|
||||
(i.e., if the target machine has a multi-user Nix installation),
|
||||
then the target machine will check the dump against
|
||||
<filename>/nix/etc/nix/signing-key.pub</filename> before unpacking
|
||||
it in its Nix store. This allows secure sharing of store paths
|
||||
between untrusted users on two machines, provided that there is a
|
||||
trust relation between the Nix installations on both machines
|
||||
(namely, they have matching public/secret keys).</para></listitem>
|
||||
<filename><replaceable>sysconfdir</replaceable>/nix/signing-key.sec</filename>.
|
||||
If the user on the target machine does not have direct access to
|
||||
the Nix store (i.e., if the target machine has a multi-user Nix
|
||||
installation), then the target machine will check the dump against
|
||||
<filename><replaceable>sysconfdir</replaceable>/nix/signing-key.pub</filename>
|
||||
before unpacking it in its Nix store. This allows secure sharing
|
||||
of store paths between untrusted users on two machines, provided
|
||||
that there is a trust relation between the Nix installations on
|
||||
both machines (namely, they have matching public/secret
|
||||
keys).</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--gzip</option></term>
|
||||
<varlistentry><term><option>--gzip</option> / <option>--bzip2</option> / <option>--xz</option></term>
|
||||
|
||||
<listitem><para>Compress the dump of each path with
|
||||
<command>gzip</command> before sending it.</para></listitem>
|
||||
<listitem><para>Compress the dump of each path with respectively
|
||||
<command>gzip</command>, <command>bzip2</command> or
|
||||
<command>xz</command> before sending it. The corresponding
|
||||
decompression program must be installed on the target
|
||||
machine.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--include-outputs</option></term>
|
||||
|
||||
<listitem><para>Also copy the outputs of store derivations included
|
||||
in the closure.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</refsection>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xml:id="sec-nix-env">
|
||||
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>nix-env</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
@@ -60,7 +60,7 @@ environments.</para>
|
||||
<para><command>nix-env</command> takes exactly one
|
||||
<emphasis>operation</emphasis> flag which indicates the subcommand to
|
||||
be performed. These are documented below.</para>
|
||||
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
@@ -78,19 +78,19 @@ linkend="sec-common-options" />.</para>
|
||||
|
||||
<varlistentry><term><option>--file</option></term>
|
||||
<term><option>-f</option></term>
|
||||
|
||||
|
||||
<listitem><para>Specifies the Nix expression (designated below as
|
||||
the <emphasis>active Nix expression</emphasis>) used by the
|
||||
<option>--install</option>, <option>--upgrade</option>, and
|
||||
<option>--query --available</option> operations to obtain
|
||||
derivations. The default is
|
||||
<filename>~/.nix-defexpr</filename>.</para></listitem>
|
||||
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><option>--profile</option></term>
|
||||
<term><option>-p</option></term>
|
||||
|
||||
|
||||
<listitem><para>Specifies the profile to be used by those
|
||||
operations that operate on a profile (designated below as the
|
||||
<emphasis>active profile</emphasis>). A profile is sequence of
|
||||
@@ -98,11 +98,11 @@ linkend="sec-common-options" />.</para>
|
||||
which is the <emphasis>current generation</emphasis>. The default
|
||||
profile is the target of the symbolic link
|
||||
<filename>~/.nix-profile</filename> (see below).</para></listitem>
|
||||
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><option>--dry-run</option></term>
|
||||
|
||||
|
||||
<listitem><para>For the <option>--install</option>,
|
||||
<option>--upgrade</option>, <option>--uninstall</option>,
|
||||
<option>--switch-generation</option> and
|
||||
@@ -117,23 +117,23 @@ linkend="sec-common-options" />.</para>
|
||||
substitute is available).</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><option>--system-filter</option> <replaceable>system</replaceable></term>
|
||||
|
||||
|
||||
<listitem><para>By default, operations such as <option>--query
|
||||
--available</option> only include derivations matching the current
|
||||
platform. This option allows you to use derivations for the
|
||||
specified platform <replaceable>system</replaceable>. The special
|
||||
value <literal>*</literal> causes derivations for any platform to
|
||||
be included.</para></listitem>
|
||||
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
|
||||
|
||||
<!--######################################################################-->
|
||||
|
||||
@@ -170,25 +170,25 @@ linkend="sec-common-options" />.</para>
|
||||
this directory.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><filename>~/.nix-profile</filename></term>
|
||||
|
||||
|
||||
<listitem><para>A symbolic link to the user's current profile. By
|
||||
default, this symlink points to
|
||||
<filename><replaceable>prefix</replaceable>/var/nix/profiles/default</filename>.
|
||||
The <envar>PATH</envar> environment variable should include
|
||||
<filename>~/.nix-profile/bin</filename> for the user environment
|
||||
to be visible to the user.</para></listitem>
|
||||
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
|
||||
|
||||
<!--######################################################################-->
|
||||
|
||||
@@ -214,7 +214,7 @@ linkend="sec-common-options" />.</para>
|
||||
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
|
||||
<para>The install operation creates a new user environment, based on
|
||||
the current generation of the active profile, to which a set of store
|
||||
paths described by <replaceable>args</replaceable> is added. The
|
||||
@@ -256,7 +256,7 @@ number of possible ways:
|
||||
<emphasis>attribute paths</emphasis> that select attributes from the
|
||||
top-level Nix expression. This is faster than using derivation
|
||||
names and unambiguous. To find out the attribute paths of available
|
||||
packages, use <literal>nix-env -qaA '*'</literal>.</para></listitem>
|
||||
packages, use <literal>nix-env -qaP '*'</literal>.</para></listitem>
|
||||
|
||||
<listitem><para>If <option>--from-profile</option>
|
||||
<replaceable>path</replaceable> is given,
|
||||
@@ -306,20 +306,20 @@ number of possible ways:
|
||||
|
||||
<varlistentry><term><option>--preserve-installed</option></term>
|
||||
<term><option>-P</option></term>
|
||||
|
||||
|
||||
<listitem><para>Do not remove derivations with a name matching one
|
||||
of the derivations being installed. Usually, trying to have two
|
||||
versions of the same package installed in the same generation of a
|
||||
profile will lead to an error in building the generation, due to
|
||||
file name clashes between the two versions. However, this is not
|
||||
the case for all packages.</para></listitem>
|
||||
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
|
||||
<refsection xml:id='refsec-nix-env-install-examples'><title>Examples</title>
|
||||
|
||||
@@ -327,7 +327,7 @@ number of possible ways:
|
||||
active Nix expression:
|
||||
|
||||
<screen>
|
||||
$ nix-env --install gcc-3.3.2
|
||||
$ nix-env --install gcc-3.3.2
|
||||
installing `gcc-3.3.2'
|
||||
uninstalling `gcc-3.1'</screen>
|
||||
|
||||
@@ -408,15 +408,15 @@ the following paths will be substituted:
|
||||
/nix/store/8zbipvm4gp9jfqh9nnk1n3bary1a37gs-perl-XML-Parser-2.34
|
||||
/nix/store/b8a2bg7gnyvvvjjibp4axg9x1hzkw36c-mono-1.1.4
|
||||
<replaceable>...</replaceable></screen>
|
||||
|
||||
|
||||
</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
|
||||
|
||||
<!--######################################################################-->
|
||||
|
||||
<refsection xml:id="rsec-nix-env-upgrade"><title>Operation <option>--upgrade</option></title>
|
||||
@@ -442,7 +442,7 @@ the following paths will be substituted:
|
||||
</refsection>
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
|
||||
<para>The upgrade operation creates a new user environment, based on
|
||||
the current generation of the active profile, in which all store paths
|
||||
are replaced for which there are newer versions in the set of paths
|
||||
@@ -459,47 +459,47 @@ the same symbolic name, only the one with the highest version is
|
||||
installed.</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Flags</title>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><option>--lt</option></term>
|
||||
|
||||
|
||||
<listitem><para>Only upgrade a derivation to newer versions. This
|
||||
is the default.</para></listitem>
|
||||
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--leq</option></term>
|
||||
|
||||
|
||||
<listitem><para>In addition to upgrading to newer versions, also
|
||||
“upgrade” to derivations that have the same version. Version are
|
||||
not a unique identification of a derivation, so there may be many
|
||||
derivations that have the same version. This flag may be useful
|
||||
to force “synchronisation” between the installed and available
|
||||
derivations.</para></listitem>
|
||||
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--eq</option></term>
|
||||
|
||||
|
||||
<listitem><para><emphasis>Only</emphasis> “upgrade” to derivations
|
||||
that have the same version. This may not seem very useful, but it
|
||||
actually is, e.g., when there is a new release of Nixpkgs and you
|
||||
want to replace installed applications with the same versions
|
||||
built against newer dependencies (to reduce the number of
|
||||
dependencies floating around on your system).</para></listitem>
|
||||
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--always</option></term>
|
||||
|
||||
|
||||
<listitem><para>In addition to upgrading to newer versions, also
|
||||
“upgrade” to derivations that have the same or a lower version.
|
||||
I.e., derivations may actually be downgraded depending on what is
|
||||
available in the active Nix expression.</para></listitem>
|
||||
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
@@ -523,10 +523,10 @@ $ nix-env --upgrade pan
|
||||
|
||||
$ nix-env -u '*' <lineannotation>(try to upgrade everything)</lineannotation>
|
||||
upgrading `hello-2.1.2' to `hello-2.1.3'
|
||||
upgrading `mozilla-1.2' to `mozilla-1.4'</screen>
|
||||
upgrading `mozilla-1.2' to `mozilla-1.4'</screen>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection xml:id="ssec-version-comparisons"><title>Versions</title>
|
||||
|
||||
<para>The upgrade operation determines whether a derivation
|
||||
@@ -570,14 +570,14 @@ lexicographically (i.e., using case-sensitive string comparison).</para>
|
||||
2.3a < 2.3c
|
||||
2.3pre1 < 2.3c
|
||||
2.3pre1 < 2.3q</screen>
|
||||
|
||||
|
||||
</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
|
||||
|
||||
<!--######################################################################-->
|
||||
|
||||
@@ -596,14 +596,14 @@ lexicographically (i.e., using case-sensitive string comparison).</para>
|
||||
</refsection>
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
|
||||
<para>The uninstall operation creates a new user environment, based on
|
||||
the current generation of the active profile, from which the store
|
||||
paths designated by the symbolic names
|
||||
<replaceable>names</replaceable> are removed.</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Examples</title>
|
||||
|
||||
<screen>
|
||||
@@ -611,11 +611,11 @@ $ nix-env --uninstall gcc
|
||||
$ nix-env -e '*' <lineannotation>(remove everything)</lineannotation></screen>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
|
||||
|
||||
<!--######################################################################-->
|
||||
|
||||
<refsection xml:id="rsec-nix-env-set-flag"><title>Operation <option>--set-flag</option></title>
|
||||
@@ -632,7 +632,7 @@ $ nix-env -e '*' <lineannotation>(remove everything)</lineannotation></screen>
|
||||
</refsection>
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
|
||||
<para>The <option>--set-flag</option> operation allows meta attributes
|
||||
of installed packages to be modified. There are several attributes
|
||||
that can be usefully modified, because they affect the behaviour of
|
||||
@@ -670,7 +670,7 @@ script:
|
||||
</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Examples</title>
|
||||
|
||||
<para>To prevent the currently installed Firefox from being upgraded:
|
||||
@@ -716,13 +716,13 @@ $ nix-env --set-flag priority 10 gcc</screen>
|
||||
</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
|
||||
|
||||
<!--######################################################################-->
|
||||
|
||||
|
||||
<refsection><title>Operation <option>--query</option></title>
|
||||
|
||||
<refsection><title>Synopsis</title>
|
||||
@@ -738,9 +738,9 @@ $ nix-env --set-flag priority 10 gcc</screen>
|
||||
<arg choice='plain'><option>--available</option></arg>
|
||||
<arg choice='plain'><option>-a</option></arg>
|
||||
</group>
|
||||
|
||||
|
||||
<sbr />
|
||||
|
||||
|
||||
<arg>
|
||||
<group choice='req'>
|
||||
<arg choice='plain'><option>--status</option></arg>
|
||||
@@ -785,7 +785,7 @@ $ nix-env --set-flag priority 10 gcc</screen>
|
||||
</arg>
|
||||
|
||||
<sbr />
|
||||
|
||||
|
||||
<arg choice='plain' rep='repeat'><replaceable>names</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
|
||||
@@ -793,7 +793,7 @@ $ nix-env --set-flag priority 10 gcc</screen>
|
||||
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
|
||||
<para>The query operation displays information about either the store
|
||||
paths that are installed in the current generation of the active
|
||||
profile (<option>--installed</option>), or the derivations that are
|
||||
@@ -817,23 +817,23 @@ operates.</para>
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><option>--installed</option></term>
|
||||
|
||||
|
||||
<listitem><para>The query operates on the store paths that are
|
||||
installed in the current generation of the active profile. This
|
||||
is the default.</para></listitem>
|
||||
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--available</option></term>
|
||||
<term><option>-a</option></term>
|
||||
|
||||
|
||||
<listitem><para>The query operates on the derivations that are
|
||||
available in the active Nix expression.</para></listitem>
|
||||
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
@@ -874,7 +874,7 @@ user environment elements, etc. -->
|
||||
|
||||
<varlistentry><term><option>--status</option></term>
|
||||
<term><option>-s</option></term>
|
||||
|
||||
|
||||
<listitem><para>Print the <emphasis>status</emphasis> of the
|
||||
derivation. The status consists of three characters. The first
|
||||
is <literal>I</literal> or <literal>-</literal>, indicating
|
||||
@@ -888,7 +888,7 @@ user environment elements, etc. -->
|
||||
third is <literal>S</literal> or <literal>-</literal>, indicating
|
||||
whether a substitute is available for the
|
||||
derivation.</para></listitem>
|
||||
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--attr-path</option></term>
|
||||
@@ -901,17 +901,17 @@ user environment elements, etc. -->
|
||||
<literal>nix-env --install</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><option>--no-name</option></term>
|
||||
|
||||
|
||||
<listitem><para>Suppress printing of the <literal>name</literal>
|
||||
attribute of each derivation.</para></listitem>
|
||||
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--compare-versions</option> /
|
||||
<option>-c</option></term>
|
||||
|
||||
|
||||
<listitem><para>Compare installed versions to available versions,
|
||||
or vice versa (if <option>--available</option> is given). This is
|
||||
useful for quickly seeing whether upgrades for installed
|
||||
@@ -926,21 +926,21 @@ user environment elements, etc. -->
|
||||
or installed.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>=</literal> <replaceable>version</replaceable></term>
|
||||
|
||||
<listitem><para>At most the same version of the package is
|
||||
available or installed.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>></literal> <replaceable>version</replaceable></term>
|
||||
|
||||
<listitem><para>Only older versions of the package are
|
||||
available or installed.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>- ?</literal></term>
|
||||
|
||||
<listitem><para>No version of the package is available or
|
||||
@@ -951,45 +951,45 @@ user environment elements, etc. -->
|
||||
</variablelist>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--system</option></term>
|
||||
|
||||
|
||||
<listitem><para>Print the <literal>system</literal> attribute of
|
||||
the derivation.</para></listitem>
|
||||
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--drv-path</option></term>
|
||||
|
||||
|
||||
<listitem><para>Print the path of the store
|
||||
derivation.</para></listitem>
|
||||
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--out-path</option></term>
|
||||
|
||||
|
||||
<listitem><para>Print the output path of the
|
||||
derivation.</para></listitem>
|
||||
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--description</option></term>
|
||||
|
||||
|
||||
<listitem><para>Print a short (one-line) description of the
|
||||
derivation, if available. The description is taken from the
|
||||
<literal>meta.description</literal> attribute of the
|
||||
derivation.</para></listitem>
|
||||
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--meta</option></term>
|
||||
|
||||
|
||||
<listitem><para>Print all of the meta-attributes of the
|
||||
derivation. This option is only available with
|
||||
<option>--xml</option>.</para></listitem>
|
||||
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
@@ -1023,7 +1023,7 @@ IP- ORBit2-2.8.3 <lineannotation>(installed and by definition present)</linea
|
||||
...
|
||||
|
||||
<lineannotation>(show available derivations in the Nix expression <!-- !!! <filename>-->foo.nix<!-- </filename> -->)</lineannotation>
|
||||
$ nix-env -f ./foo.nix -qa '*'
|
||||
$ nix-env -f ./foo.nix -qa '*'
|
||||
foo-1.2.3
|
||||
|
||||
$ nix-env -qc '*' <lineannotation>(compare installed versions to what’s available)</lineannotation>
|
||||
@@ -1034,7 +1034,7 @@ firefox-1.0.4 < 1.0.7 <lineannotation>(a more recent version is availab
|
||||
<replaceable>...</replaceable>
|
||||
|
||||
<lineannotation>(show info about a specific package, in XML)</lineannotation>
|
||||
$ nix-env -qa --xml --description firefox
|
||||
$ nix-env -qa --xml --description firefox
|
||||
<![CDATA[<?xml version='1.0' encoding='utf-8'?>
|
||||
<items>
|
||||
<item attrPath="0.0.firefoxWrapper"
|
||||
@@ -1045,8 +1045,8 @@ $ nix-env -qa --xml --description firefox
|
||||
</refsection>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--######################################################################-->
|
||||
|
||||
@@ -1067,25 +1067,25 @@ $ nix-env -qa --xml --description firefox
|
||||
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
|
||||
<para>This operation makes <replaceable>path</replaceable> the current
|
||||
profile for the user. That is, the symlink
|
||||
<filename>~/.nix-profile</filename> is made to point to
|
||||
<replaceable>path</replaceable>.</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Examples</title>
|
||||
|
||||
<screen>
|
||||
$ nix-env -S ~/my-profile</screen>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
|
||||
|
||||
<!--######################################################################-->
|
||||
|
||||
<refsection><title>Operation <option>--list-generations</option></title>
|
||||
@@ -1101,7 +1101,7 @@ $ nix-env -S ~/my-profile</screen>
|
||||
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
|
||||
<para>This operation print a list of all the currently existing
|
||||
generations for the active profile. These may be switched to using
|
||||
the <option>--switch-generation</option> operation. It also prints
|
||||
@@ -1121,11 +1121,11 @@ $ nix-env --list-generations
|
||||
98 2004-02-06 16:24:33 (current)</screen>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
|
||||
|
||||
<!--######################################################################-->
|
||||
|
||||
<refsection><title>Operation <option>--delete-generations</option></title>
|
||||
@@ -1142,7 +1142,7 @@ $ nix-env --list-generations
|
||||
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
|
||||
<para>This operation deletes the specified generations of the current
|
||||
profile. The generations can be a list of generation numbers, or the
|
||||
special value <literal>old</literal> to delete all non-current
|
||||
@@ -1150,7 +1150,7 @@ generations. Periodically deleting old generations is important to
|
||||
make garbage collection effective.</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Examples</title>
|
||||
|
||||
<screen>
|
||||
@@ -1159,11 +1159,11 @@ $ nix-env --delete-generations 3 4 8
|
||||
$ nix-env -p other_profile --delete-generations old</screen>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
|
||||
|
||||
<!--######################################################################-->
|
||||
|
||||
<refsection><title>Operation <option>--switch-generation</option></title>
|
||||
@@ -1183,7 +1183,7 @@ $ nix-env -p other_profile --delete-generations old</screen>
|
||||
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
|
||||
<para>This operation makes generation number
|
||||
<replaceable>generation</replaceable> the current generation of the
|
||||
active profile. That is, if the
|
||||
@@ -1207,11 +1207,11 @@ $ nix-env -G 42
|
||||
switching from generation 50 to 42</screen>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
|
||||
|
||||
<!--######################################################################-->
|
||||
|
||||
<refsection><title>Operation <option>--rollback</option></title>
|
||||
@@ -1226,7 +1226,7 @@ switching from generation 50 to 42</screen>
|
||||
</refsection>
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
|
||||
<para>This operation switches to the “previous” generation of the
|
||||
active profile, that is, the highest numbered generation lower than
|
||||
the current generation, if it exists. It is just a convenience
|
||||
@@ -1246,9 +1246,9 @@ $ nix-env --rolback
|
||||
error: no generation older than the current (91) exists</screen>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
|
||||
|
||||
</refentry>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
<refnamediv>
|
||||
<refname>nix-prefetch-url</refname>
|
||||
<refpurpose>copy a file from a URL into the store and print its MD5 hash</refpurpose>
|
||||
<refpurpose>copy a file from a URL into the store and print its hash</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
<arg><option>--max-silent-time</option></arg>
|
||||
<replaceable>number</replaceable>
|
||||
</arg>
|
||||
<arg>
|
||||
<arg><option>--timeout</option></arg>
|
||||
<replaceable>number</replaceable>
|
||||
</arg>
|
||||
<arg><option>--keep-going</option></arg>
|
||||
<arg><option>-k</option></arg>
|
||||
<arg><option>--keep-failed</option></arg>
|
||||
|
||||
@@ -132,6 +132,16 @@
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="opt-timeout"><term><option>--timeout</option></term>
|
||||
|
||||
<listitem><para>Sets the maximum number of seconds that a builder
|
||||
can run. The default is specified by the <link
|
||||
linkend='conf-build-timeout'><literal>build-timeout</literal></link>
|
||||
configuration setting. <literal>0</literal> means no
|
||||
timeout.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--keep-going</option></term>
|
||||
<term><option>-k</option></term>
|
||||
|
||||
@@ -254,8 +264,8 @@
|
||||
expression evaluator will automatically try to call functions that
|
||||
it encounters. It can automatically call functions for which every
|
||||
argument has a <link linkend='ss-functions'>default value</link>
|
||||
(e.g., <literal>{<replaceable>argName</replaceable> ?
|
||||
<replaceable>defaultValue</replaceable>}:
|
||||
(e.g., <literal>{ <replaceable>argName</replaceable> ?
|
||||
<replaceable>defaultValue</replaceable> }:
|
||||
<replaceable>...</replaceable></literal>). With
|
||||
<option>--arg</option>, you can also call functions that have
|
||||
arguments without a default value (or override a default value).
|
||||
|
||||
@@ -22,6 +22,28 @@
|
||||
option.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>The option <option>--timeout</option> (corresponding to the
|
||||
configuration setting <literal>build-timeout</literal>) allows you
|
||||
to set an absolute timeout on builds — if a build runs for more than
|
||||
the given number of seconds, it is terminated. This is useful for
|
||||
recovering automatically from builds that are stuck in an infinite
|
||||
loop but keep producing output, and for which
|
||||
<literal>--max-silent-time</literal> is ineffective.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>TODO: “or” keyword.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>TODO: Nix expression search path (<literal>import <foo/bar.nix></literal>).</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>TODO: <command>nix-store --verify-path</command> command.</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
|
||||
@@ -52,7 +52,7 @@ need to do three things:
|
||||
<example xml:id='ex-hello-nix'><title>Nix expression for GNU Hello
|
||||
(<filename>default.nix</filename>)</title>
|
||||
<programlisting>
|
||||
{stdenv, fetchurl, perl}: <co xml:id='ex-hello-nix-co-1' />
|
||||
{ stdenv, fetchurl, perl }: <co xml:id='ex-hello-nix-co-1' />
|
||||
|
||||
stdenv.mkDerivation { <co xml:id='ex-hello-nix-co-2' />
|
||||
name = "hello-2.1.1"; <co xml:id='ex-hello-nix-co-3' />
|
||||
@@ -92,8 +92,8 @@ the single Nix expression in that directory
|
||||
function that downloads files. <varname>perl</varname> is the
|
||||
Perl interpreter.</para>
|
||||
|
||||
<para>Nix functions generally have the form <literal>{x, y, ...,
|
||||
z}: e</literal> where <varname>x</varname>, <varname>y</varname>,
|
||||
<para>Nix functions generally have the form <literal>{ x, y, ...,
|
||||
z }: e</literal> where <varname>x</varname>, <varname>y</varname>,
|
||||
etc. are the names of the expected arguments, and where
|
||||
<replaceable>e</replaceable> is the body of the function. So
|
||||
here, the entire remainder of the file is the body of the
|
||||
@@ -114,10 +114,10 @@ the single Nix expression in that directory
|
||||
<emphasis>attributes</emphasis>. An attribute set is just a list
|
||||
of key/value pairs where each value is an arbitrary Nix
|
||||
expression. They take the general form
|
||||
<literal>{<replaceable>name1</replaceable> =
|
||||
<literal>{ <replaceable>name1</replaceable> =
|
||||
<replaceable>expr1</replaceable>; <replaceable>...</replaceable>
|
||||
<replaceable>nameN</replaceable> =
|
||||
<replaceable>exprN</replaceable>;}</literal>.</para>
|
||||
<replaceable>exprN</replaceable>; }</literal>.</para>
|
||||
|
||||
</callout>
|
||||
|
||||
@@ -564,7 +564,7 @@ genericBuild <co xml:id='ex-hello-builder2-co-3' /></programlisting>
|
||||
expression, like this:
|
||||
|
||||
<programlisting>
|
||||
buildInputs = [perl];</programlisting>
|
||||
buildInputs = [ perl ];</programlisting>
|
||||
|
||||
The <varname>perl</varname> attribute can then be removed, and the
|
||||
builder becomes even shorter:
|
||||
@@ -771,14 +771,14 @@ stdenv.mkDerivation {
|
||||
values between square brackets. For example,
|
||||
|
||||
<programlisting>
|
||||
[ 123 ./foo.nix "abc" (f {x=y;}) ]</programlisting>
|
||||
[ 123 ./foo.nix "abc" (f { x = y; }) ]</programlisting>
|
||||
|
||||
defines a list of four elements, the last being the result of a call
|
||||
to the function <varname>f</varname>. Note that function calls have
|
||||
to be enclosed in parentheses. If they had been omitted, e.g.,
|
||||
|
||||
<programlisting>
|
||||
[ 123 ./foo.nix "abc" f {x=y;} ]</programlisting>
|
||||
[ 123 ./foo.nix "abc" f { x = y; } ]</programlisting>
|
||||
|
||||
the result would be a list of five elements, the fourth one being a
|
||||
function and the fifth being an attribute set.</para>
|
||||
@@ -891,15 +891,12 @@ propagate attributes). This can be shortened using the
|
||||
<literal>inherit</literal> keyword. For instance,
|
||||
|
||||
<programlisting>
|
||||
let
|
||||
x = 123;
|
||||
in
|
||||
{
|
||||
inherit x;
|
||||
y = 456;
|
||||
}</programlisting>
|
||||
let x = 123; in
|
||||
{ inherit x;
|
||||
y = 456;
|
||||
}</programlisting>
|
||||
|
||||
evaluates to <literal>{x = 123; y = 456;}</literal>. (Note that this
|
||||
evaluates to <literal>{ x = 123; y = 456; }</literal>. (Note that this
|
||||
works because <varname>x</varname> is added to the lexical scope by
|
||||
the <literal>let</literal> construct.) It is also possible to inherit
|
||||
attributes from another attribute set. For instance, in this fragment
|
||||
@@ -960,20 +957,20 @@ in if negate true then concat "foo" "bar" else ""</programlisting>
|
||||
arguments of a function); e.g.,
|
||||
|
||||
<programlisting>
|
||||
map (concat "foo") ["bar" "bla" "abc"]</programlisting>
|
||||
map (concat "foo") [ "bar" "bla" "abc" ]</programlisting>
|
||||
|
||||
evaluates to <literal>["foobar" "foobla"
|
||||
"fooabc"]</literal>.</para></listitem>
|
||||
evaluates to <literal>[ "foobar" "foobla"
|
||||
"fooabc" ]</literal>.</para></listitem>
|
||||
|
||||
|
||||
<listitem><para>An <emphasis>attribute set pattern</emphasis> of the
|
||||
form <literal>{name1, name2, …, nameN}</literal>
|
||||
form <literal>{ name1, name2, …, nameN }</literal>
|
||||
matches an attribute set containing the listed attributes, and binds
|
||||
the values of those attributes to variables in the function body.
|
||||
For example, the function
|
||||
|
||||
<programlisting>
|
||||
{x, y, z}: z + y + x</programlisting>
|
||||
{ x, y, z }: z + y + x</programlisting>
|
||||
|
||||
can only be called with a set containing exactly the attributes
|
||||
<varname>x</varname>, <varname>y</varname> and
|
||||
@@ -982,7 +979,7 @@ map (concat "foo") ["bar" "bla" "abc"]</programlisting>
|
||||
(<literal>...</literal>):
|
||||
|
||||
<programlisting>
|
||||
{x, y, z, ....}: z + y + x</programlisting>
|
||||
{ x, y, z, ... }: z + y + x</programlisting>
|
||||
|
||||
This works on any set that contains at least the three named
|
||||
attributes.</para>
|
||||
@@ -995,7 +992,7 @@ map (concat "foo") ["bar" "bla" "abc"]</programlisting>
|
||||
<replaceable>e</replaceable> is an arbitrary expression. For example,
|
||||
|
||||
<programlisting>
|
||||
{x, y ? "foo", z ? "bar"}: z + y + x</programlisting>
|
||||
{ x, y ? "foo", z ? "bar" }: z + y + x</programlisting>
|
||||
|
||||
specifies a function that only requires an attribute named
|
||||
<varname>x</varname>, but optionally accepts <varname>y</varname>
|
||||
@@ -1007,11 +1004,11 @@ map (concat "foo") ["bar" "bla" "abc"]</programlisting>
|
||||
of the <literal>@</literal>-sign. For example:
|
||||
|
||||
<programlisting>
|
||||
args@{x, y, z, ...}: z + y + x + args.a</programlisting>
|
||||
args@{ x, y, z, ... }: z + y + x + args.a</programlisting>
|
||||
|
||||
Here <varname>args</varname> is bound to the entire argument, which
|
||||
is further matches against the pattern <literal>{x, y, z,
|
||||
...}</literal>.</para></listitem>
|
||||
is further matches against the pattern <literal>{ x, y, z,
|
||||
... }</literal>.</para></listitem>
|
||||
|
||||
|
||||
</itemizedlist>
|
||||
@@ -1020,8 +1017,8 @@ args@{x, y, z, ...}: z + y + x + args.a</programlisting>
|
||||
a name, you can bind them to an attribute, e.g.,
|
||||
|
||||
<programlisting>
|
||||
let concat = {x, y}: x + y;
|
||||
in concat {x = "foo"; y = "bar";}</programlisting>
|
||||
let concat = { x, y }: x + y;
|
||||
in concat { x = "foo"; y = "bar"; }</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
@@ -1142,7 +1139,7 @@ lexical scope of the expression <replaceable>e2</replaceable>. For
|
||||
instance,
|
||||
|
||||
<programlisting>
|
||||
let as = {x = "foo"; y = "bar";};
|
||||
let as = { x = "foo"; y = "bar"; };
|
||||
in with as; x + y</programlisting>
|
||||
|
||||
evaluates to <literal>"foobar"</literal> since the
|
||||
@@ -1480,21 +1477,20 @@ allowedReferences = [];
|
||||
references graph of their inputs. The attribute is a list of
|
||||
inputs in the Nix store whose references graph the builder needs
|
||||
to know. The value of this attribute should be a list of pairs
|
||||
<literal>[<replaceable>name1</replaceable>
|
||||
<literal>[ <replaceable>name1</replaceable>
|
||||
<replaceable>path1</replaceable> <replaceable>name2</replaceable>
|
||||
<replaceable>path2</replaceable>
|
||||
<replaceable>...</replaceable>]</literal>. The references graph
|
||||
of each <replaceable>pathN</replaceable> will be stored in a text
|
||||
file <replaceable>nameN</replaceable> in the temporary build
|
||||
directory. The text files have the format used by
|
||||
<command>nix-store --register-validity</command> (with the deriver
|
||||
fields left empty). For example, when the following derivation is
|
||||
built:
|
||||
<replaceable>path2</replaceable> <replaceable>...</replaceable>
|
||||
]</literal>. The references graph of each
|
||||
<replaceable>pathN</replaceable> will be stored in a text file
|
||||
<replaceable>nameN</replaceable> in the temporary build directory.
|
||||
The text files have the format used by <command>nix-store
|
||||
--register-validity</command> (with the deriver fields left
|
||||
empty). For example, when the following derivation is built:
|
||||
|
||||
<programlisting>
|
||||
derivation {
|
||||
...
|
||||
exportReferencesGraph = ["libfoo-graph" libfoo];
|
||||
exportReferencesGraph = [ "libfoo-graph" libfoo ];
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
@@ -1571,14 +1567,14 @@ fetchurl {
|
||||
<varname>fetchurl</varname>:
|
||||
|
||||
<programlisting>
|
||||
{stdenv, curl}: # The <command>curl</command> program is used for downloading.
|
||||
{ stdenv, curl }: # The <command>curl</command> program is used for downloading.
|
||||
|
||||
{url, md5}:
|
||||
{ url, md5 }:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = baseNameOf (toString url);
|
||||
builder = ./builder.sh;
|
||||
buildInputs = [curl];
|
||||
buildInputs = [ curl ];
|
||||
|
||||
# This is a fixed-output derivation; the output must be a regular
|
||||
# file with MD5 hash <varname>md5</varname>.
|
||||
@@ -1650,7 +1646,7 @@ stdenv.mkDerivation {
|
||||
Nixpkgs has the line
|
||||
|
||||
<programlisting>
|
||||
impureEnvVars = ["http_proxy" "https_proxy" <replaceable>...</replaceable>];
|
||||
impureEnvVars = [ "http_proxy" "https_proxy" <replaceable>...</replaceable> ];
|
||||
</programlisting>
|
||||
|
||||
to make it use the proxy server configuration specified by the
|
||||
|
||||
2
externals/Makefile.am
vendored
2
externals/Makefile.am
vendored
@@ -23,7 +23,7 @@ build-bzip2: $(BZIP2)
|
||||
|
||||
install-exec-local:: build-bzip2
|
||||
mkdir -p $(DESTDIR)${bzip2_bin}
|
||||
$(INSTALL_PROGRAM) $(bzip2_bin_test)/bzip2 $(bzip2_bin_test)/bunzip2 $(DESTDIR)${bzip2_bin}
|
||||
$(INSTALL_PROGRAM) $(bzip2_bin_test)/bzip2 $(DESTDIR)${bzip2_bin}
|
||||
endif
|
||||
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
{sharedLib ? true}:
|
||||
|
||||
rec {
|
||||
|
||||
inherit (import ../../../lib) compileC makeLibrary;
|
||||
|
||||
sources = [
|
||||
./afun.c
|
||||
./aterm.c
|
||||
./bafio.c
|
||||
./byteio.c
|
||||
./gc.c
|
||||
./hash.c
|
||||
./list.c
|
||||
./make.c
|
||||
./md5c.c
|
||||
./memory.c
|
||||
./tafio.c
|
||||
./version.c
|
||||
];
|
||||
|
||||
compile = main: compileC {inherit main sharedLib;};
|
||||
|
||||
libATerm = makeLibrary {
|
||||
libraryName = "ATerm";
|
||||
objects = map compile sources;
|
||||
inherit sharedLib;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
import test/default.nix
|
||||
@@ -1,15 +0,0 @@
|
||||
with (import ../../../lib);
|
||||
|
||||
let {
|
||||
inherit (import ../aterm {}) libATerm;
|
||||
|
||||
compileTest = main: link {
|
||||
objects = [(compileC {inherit main; localIncludePath = [ ../aterm ];})];
|
||||
libraries = libATerm;
|
||||
};
|
||||
|
||||
body = [
|
||||
(compileTest ./fib.c)
|
||||
(compileTest ./primes.c)
|
||||
];
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
[ (import ./trivial)
|
||||
(import ./simple-header)
|
||||
(import ./not-so-simple-header)
|
||||
(import ./not-so-simple-header-auto)
|
||||
(import ./aterm)
|
||||
]
|
||||
@@ -1 +0,0 @@
|
||||
#define WHAT "World"
|
||||
@@ -1,13 +0,0 @@
|
||||
with import ../../lib;
|
||||
|
||||
let {
|
||||
|
||||
hello = link {programName = "hello"; objects = compileC {
|
||||
main = ./foo/hello.c;
|
||||
localIncludes = "auto";
|
||||
};};
|
||||
|
||||
# body = findIncludes {main = ./foo/hello.c;};
|
||||
|
||||
body = [hello];
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
#define HELLO "Hello"
|
||||
|
||||
#include "../../bar/hello.h"
|
||||
@@ -1,9 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "fnord/indirect.h"
|
||||
|
||||
int main(int argc, char * * argv)
|
||||
{
|
||||
printf(HELLO " " WHAT "\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
#define WHAT "World"
|
||||
@@ -1,14 +0,0 @@
|
||||
let {
|
||||
|
||||
inherit (import ../../lib) compileC link;
|
||||
|
||||
hello = link {programName = "hello"; objects = compileC {
|
||||
main = ./foo/hello.c;
|
||||
localIncludes = [
|
||||
[./foo/fnord/indirect.h "fnord/indirect.h"]
|
||||
[./bar/hello.h "fnord/../../bar/hello.h"]
|
||||
];
|
||||
};};
|
||||
|
||||
body = [hello];
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
#define HELLO "Hello"
|
||||
|
||||
#include "../../bar/hello.h"
|
||||
@@ -1,9 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "fnord/indirect.h"
|
||||
|
||||
int main(int argc, char * * argv)
|
||||
{
|
||||
printf(HELLO " " WHAT "\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
let {
|
||||
|
||||
inherit (import ../../lib) compileC link;
|
||||
|
||||
hello = link {objects = compileC {
|
||||
main = ./hello.c;
|
||||
localIncludes = [ [./hello.h "hello.h"] ];
|
||||
};};
|
||||
|
||||
body = [hello];
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "hello.h"
|
||||
|
||||
int main(int argc, char * * argv)
|
||||
{
|
||||
printf("Hello " WHAT "\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
#define WHAT "World"
|
||||
@@ -1,8 +0,0 @@
|
||||
let {
|
||||
|
||||
inherit (import ../../lib) compileC link;
|
||||
|
||||
hello = link {objects = compileC {main = ./hello.c;};};
|
||||
|
||||
body = [hello];
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char * * argv)
|
||||
{
|
||||
printf("Hello World\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
. $stdenv/setup
|
||||
|
||||
mainName=$(basename $main | cut -c34-)
|
||||
|
||||
echo "compiling \`$mainName'..."
|
||||
|
||||
# Turn $localIncludes into an array.
|
||||
localIncludes=($localIncludes)
|
||||
|
||||
# Determine how many `..' levels appear in the header file references.
|
||||
# E.g., if there is some reference `../../foo.h', then we have to
|
||||
# insert two extra levels in the directory structure, so that `a.c' is
|
||||
# stored at `dotdot/dotdot/a.c', and a reference from it to
|
||||
# `../../foo.h' resolves to `dotdot/dotdot/../../foo.h' == `foo.h'.
|
||||
n=0
|
||||
maxDepth=0
|
||||
for ((n = 0; n < ${#localIncludes[*]}; n += 2)); do
|
||||
target=${localIncludes[$((n + 1))]}
|
||||
|
||||
# Split the target name into path components using some IFS magic.
|
||||
savedIFS="$IFS"
|
||||
IFS=/
|
||||
components=($target)
|
||||
depth=0
|
||||
for ((m = 0; m < ${#components[*]}; m++)); do
|
||||
c=${components[m]}
|
||||
if test "$c" = ".."; then
|
||||
depth=$((depth + 1))
|
||||
fi
|
||||
done
|
||||
IFS="$savedIFS"
|
||||
|
||||
if test $depth -gt $maxDepth; then
|
||||
maxDepth=$depth;
|
||||
fi
|
||||
done
|
||||
|
||||
# Create the extra levels in the directory hierarchy.
|
||||
prefix=
|
||||
for ((n = 0; n < maxDepth; n++)); do
|
||||
prefix="dotdot/$prefix"
|
||||
done
|
||||
|
||||
# Create symlinks to the header files.
|
||||
for ((n = 0; n < ${#localIncludes[*]}; n += 2)); do
|
||||
source=${localIncludes[n]}
|
||||
target=${localIncludes[$((n + 1))]}
|
||||
|
||||
# Create missing directories. We use IFS magic to split the path
|
||||
# into path components.
|
||||
savedIFS="$IFS"
|
||||
IFS=/
|
||||
components=($prefix$target)
|
||||
fullPath=(.)
|
||||
for ((m = 0; m < ${#components[*]} - 1; m++)); do
|
||||
fullPath=("${fullPath[@]}" ${components[m]})
|
||||
if ! test -d "${fullPath[*]}"; then
|
||||
mkdir "${fullPath[*]}"
|
||||
fi
|
||||
done
|
||||
IFS="$savedIFS"
|
||||
|
||||
ln -sf $source $prefix$target
|
||||
done
|
||||
|
||||
# Create a symlink to the main file.
|
||||
if ! test "$(readlink $prefix$mainName)" = $main; then
|
||||
ln -s $main $prefix$mainName
|
||||
fi
|
||||
|
||||
mkdir $out
|
||||
test "$prefix" && cd $prefix
|
||||
gcc -Wall $cFlags -c $mainName -o $out/$mainName.o
|
||||
@@ -1,69 +0,0 @@
|
||||
rec {
|
||||
|
||||
# Should point at your Nixpkgs installation.
|
||||
pkgPath = ./pkgs;
|
||||
|
||||
pkgs = import (pkgPath + /system/all-packages.nix) {};
|
||||
|
||||
stdenv = pkgs.stdenv;
|
||||
|
||||
|
||||
compileC =
|
||||
{ main
|
||||
, localIncludes ? "auto"
|
||||
, localIncludePath ? []
|
||||
, cFlags ? ""
|
||||
, sharedLib ? false
|
||||
}:
|
||||
stdenv.mkDerivation {
|
||||
name = "compile-c";
|
||||
builder = ./compile-c.sh;
|
||||
|
||||
localIncludes =
|
||||
if localIncludes == "auto" then
|
||||
dependencyClosure {
|
||||
scanner = main:
|
||||
import (findIncludes {
|
||||
inherit main;
|
||||
});
|
||||
searchPath = localIncludePath;
|
||||
startSet = [main];
|
||||
}
|
||||
else
|
||||
localIncludes;
|
||||
|
||||
inherit main;
|
||||
|
||||
cFlags = [
|
||||
cFlags
|
||||
(if sharedLib then ["-fpic"] else [])
|
||||
(map (p: "-I" + (relativise (dirOf main) p)) localIncludePath)
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
findIncludes = {main}: stdenv.mkDerivation {
|
||||
name = "find-includes";
|
||||
realBuilder = pkgs.perl ~ "bin/perl";
|
||||
args = [ ./find-includes.pl ];
|
||||
inherit main;
|
||||
};
|
||||
|
||||
|
||||
link = {objects, programName ? "program", libraries ? []}: stdenv.mkDerivation {
|
||||
name = "link";
|
||||
builder = ./link.sh;
|
||||
inherit objects programName libraries;
|
||||
};
|
||||
|
||||
|
||||
makeLibrary = {objects, libraryName ? [], sharedLib ? false}:
|
||||
# assert sharedLib -> fold (obj: x: assert obj.sharedLib && x) false objects
|
||||
stdenv.mkDerivation {
|
||||
name = "library";
|
||||
builder = ./make-library.sh;
|
||||
inherit objects libraryName sharedLib;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
use strict;
|
||||
|
||||
my $root = $ENV{"main"};
|
||||
my $out = $ENV{"out"};
|
||||
|
||||
open OUT, ">$out" or die "$!";
|
||||
print OUT "[\n";
|
||||
|
||||
open IN, "<$root" or die "$!";
|
||||
while (<IN>) {
|
||||
if (/^\#include\s+\"(.*)\"/) {
|
||||
print OUT "\"$1\"\n";
|
||||
}
|
||||
if (/^\#include\s+\<(.*)\>/) {
|
||||
print OUT "\"$1\"\n";
|
||||
}
|
||||
}
|
||||
close IN;
|
||||
|
||||
print OUT "]\n";
|
||||
close OUT;
|
||||
@@ -1,21 +0,0 @@
|
||||
. $stdenv/setup
|
||||
|
||||
shopt -s nullglob
|
||||
|
||||
objs=
|
||||
for i in $objects; do
|
||||
obj=$(echo $i/*.o)
|
||||
objs="$objs $obj"
|
||||
done
|
||||
|
||||
libs=
|
||||
for i in $libraries; do
|
||||
lib=$(echo $i/*.a; echo $i/*.so)
|
||||
name=$(echo $(basename $lib) | sed -e 's/^lib//' -e 's/.a$//' -e 's/.so$//')
|
||||
libs="$libs -L$(dirname $lib) -l$name"
|
||||
done
|
||||
|
||||
echo "linking object files into \`$programName'..."
|
||||
|
||||
mkdir $out
|
||||
gcc -o $out/$programName $objs $libs
|
||||
@@ -1,28 +0,0 @@
|
||||
. $stdenv/setup
|
||||
|
||||
objs=
|
||||
for i in $objects; do
|
||||
obj=$(echo $i/*.o)
|
||||
objs="$objs $obj"
|
||||
done
|
||||
|
||||
echo "archiving object files into library \`$libraryName'..."
|
||||
|
||||
ensureDir $out
|
||||
|
||||
if test -z "$sharedLib"; then
|
||||
|
||||
outPath=$out/lib${libraryName}.a
|
||||
|
||||
ar crs $outPath $objs
|
||||
ranlib $outPath
|
||||
|
||||
else
|
||||
|
||||
outPath=$out/lib${libraryName}.so
|
||||
|
||||
gcc -shared -o $outPath $objs
|
||||
|
||||
fi
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ The hook `nix-mode-hook' is run when Nix mode is started.
|
||||
|
||||
(defvar nix-keywords
|
||||
'("\\<if\\>" "\\<then\\>" "\\<else\\>" "\\<assert\\>" "\\<with\\>"
|
||||
"\\<let\\>" "\\<in\\>" "\\<rec\\>" "\\<inherit\\>"
|
||||
"\\<let\\>" "\\<in\\>" "\\<rec\\>" "\\<inherit\\>" "\\<or\\>"
|
||||
("\\<true\\>" . font-lock-builtin-face)
|
||||
("\\<false\\>" . font-lock-builtin-face)
|
||||
("\\<null\\>" . font-lock-builtin-face)
|
||||
@@ -80,6 +80,8 @@ The hook `nix-mode-hook' is run when Nix mode is started.
|
||||
. font-lock-constant-face)
|
||||
("\\<\\([a-zA-Z_][a-zA-Z0-9_'\.]*\\)[ \t]*="
|
||||
(1 font-lock-variable-name-face nil nil))
|
||||
("<[a-zA-Z0-9._\\+-]+\\(/[a-zA-Z0-9._\\+-]+\\)*>"
|
||||
. font-lock-constant-face)
|
||||
("[a-zA-Z0-9._\\+-]*\\(/[a-zA-Z0-9._\\+-]+\\)+"
|
||||
. font-lock-constant-face)
|
||||
))
|
||||
@@ -107,3 +109,5 @@ The hook `nix-mode-hook' is run when Nix mode is started.
|
||||
|
||||
(setq auto-mode-alist (cons '("\\.nix\\'" . nix-mode) auto-mode-alist))
|
||||
(setq auto-mode-alist (cons '("\\.nix.in\\'" . nix-mode) auto-mode-alist))
|
||||
|
||||
(provide 'nix-mode)
|
||||
|
||||
@@ -19,6 +19,8 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot
|
||||
Prefix: /usr
|
||||
Requires: /usr/bin/perl
|
||||
Requires: curl
|
||||
Requires: perl-DBD-SQLite
|
||||
Requires: perl-devel
|
||||
|
||||
# Hack to make that shitty RPM scanning hack shut up.
|
||||
Provides: perl(readmanifest)
|
||||
|
||||
7
perl/MANIFEST
Normal file
7
perl/MANIFEST
Normal file
@@ -0,0 +1,7 @@
|
||||
Changes
|
||||
Makefile.PL
|
||||
MANIFEST
|
||||
Nix.xs
|
||||
README
|
||||
t/Nix.t
|
||||
lib/Nix.pm
|
||||
34
perl/Makefile.am
Normal file
34
perl/Makefile.am
Normal file
@@ -0,0 +1,34 @@
|
||||
perlversion := $(shell perl -e 'use Config; print $$Config{version};')
|
||||
perlarchname := $(shell perl -e 'use Config; print $$Config{archname};')
|
||||
perllibdir = $(libdir)/perl5/site_perl/$(perlversion)/$(perlarchname)
|
||||
|
||||
PERL_MODULES = lib/Nix/Store.pm lib/Nix/Manifest.pm lib/Nix/GeneratePatches.pm lib/Nix/SSH.pm lib/Nix/CopyClosure.pm lib/Nix/Config.pm.in
|
||||
|
||||
# Hack required by "make check".
|
||||
all: $(PERL_MODULES:.in=)
|
||||
mkdir -p lib/auto/Nix/Store
|
||||
ln -sfn $(abs_builddir)/.libs/libNixStore.so lib/auto/Nix/Store/Store.so
|
||||
|
||||
install-exec-local: $(PERL_MODULES:.in=)
|
||||
$(INSTALL) -d $(DESTDIR)$(perllibdir)/Nix
|
||||
$(INSTALL_DATA) $(PERL_MODULES:.in=) $(DESTDIR)$(perllibdir)/Nix
|
||||
$(INSTALL) -d $(DESTDIR)$(perllibdir)/auto/Nix/Store
|
||||
ln -sfn $(pkglibdir)/libNixStore.so $(DESTDIR)$(perllibdir)/auto/Nix/Store/Store.so
|
||||
|
||||
# Awful hackery to get libtool to build Perl XS bindings.
|
||||
pkglib_LTLIBRARIES = libNixStore.la
|
||||
|
||||
libNixStore_la_SOURCES = lib/Nix/Store.cc
|
||||
|
||||
libNixStore_la_LIBADD = $(top_srcdir)/src/libstore/libstore.la
|
||||
|
||||
AM_CXXFLAGS = \
|
||||
-I$(top_srcdir)/src -I$(top_srcdir)/src/libutil -I$(top_srcdir)/src/libstore \
|
||||
-I$(shell perl -e 'use Config; print $$Config{archlibexp};')/CORE
|
||||
|
||||
lib/Nix/Store.cc: lib/Nix/Store.xs
|
||||
xsubpp $^ -output $@
|
||||
|
||||
EXTRA_DIST = $(PERL_MODULES) lib/Nix/Store.xs
|
||||
|
||||
include ../substitute.mk
|
||||
27
perl/lib/Nix/Config.pm.in
Normal file
27
perl/lib/Nix/Config.pm.in
Normal file
@@ -0,0 +1,27 @@
|
||||
package Nix::Config;
|
||||
|
||||
$binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
|
||||
$libexecDir = $ENV{"NIX_LIBEXEC_DIR"} || "@libexecdir@";
|
||||
$stateDir = $ENV{"NIX_STATE_DIR"} || "@localstatedir@/nix";
|
||||
$manifestDir = $ENV{"NIX_MANIFESTS_DIR"} || "@localstatedir@/nix/manifests";
|
||||
$logDir = $ENV{"NIX_LOG_DIR"} || "@localstatedir@/log/nix";
|
||||
$confDir = $ENV{"NIX_CONF_DIR"} || "@sysconfdir@/nix";
|
||||
|
||||
$bzip2 = $ENV{"NIX_BZIP2"} || "@bzip2@";
|
||||
$curl = "@curl@";
|
||||
|
||||
sub readConfig {
|
||||
my %config;
|
||||
my $config = "@sysconfdir@/nix/nix.conf";
|
||||
return unless -f $config;
|
||||
|
||||
open CONFIG, "<$config" or die "cannot open `$config'";
|
||||
while (<CONFIG>) {
|
||||
/^\s*([\w|-]+)\s*=\s*(.*)$/ or next;
|
||||
$config{$1} = $2;
|
||||
print "|$1| -> |$2|\n";
|
||||
}
|
||||
close CONFIG;
|
||||
}
|
||||
|
||||
return 1;
|
||||
46
perl/lib/Nix/CopyClosure.pm
Normal file
46
perl/lib/Nix/CopyClosure.pm
Normal file
@@ -0,0 +1,46 @@
|
||||
package Nix::CopyClosure;
|
||||
|
||||
use strict;
|
||||
use Nix::Config;
|
||||
use Nix::Store;
|
||||
|
||||
|
||||
sub copyTo {
|
||||
my ($sshHost, $sshOpts, $storePaths, $compressor, $decompressor, $includeOutputs, $dryRun, $sign) = @_;
|
||||
|
||||
$compressor = "$compressor |" if $compressor ne "";
|
||||
$decompressor = "$decompressor |" if $decompressor ne "";
|
||||
|
||||
# Get the closure of this path.
|
||||
my @closure = reverse(topoSortPaths(computeFSClosure(0, $includeOutputs,
|
||||
map { followLinksToStorePath $_ } @{$storePaths})));
|
||||
|
||||
# Ask the remote host which paths are invalid. Because of limits
|
||||
# to the command line length, do this in chunks. Eventually,
|
||||
# we'll want to use ‘--from-stdin’, but we can't rely on the
|
||||
# target having this option yet.
|
||||
my @missing = ();
|
||||
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;
|
||||
push @missing, $_;
|
||||
}
|
||||
close READ or die;
|
||||
}
|
||||
|
||||
# Export the store paths and import them on the remote machine.
|
||||
if (scalar @missing > 0) {
|
||||
print STDERR "copying ", scalar @missing, " missing paths to ‘$sshHost’...\n";
|
||||
#print STDERR " $_\n" foreach @missing;
|
||||
unless ($dryRun) {
|
||||
open SSH, "| $compressor ssh $sshHost @{$sshOpts} '$decompressor nix-store --import'" or die;
|
||||
exportPaths(fileno(SSH), $sign, @missing);
|
||||
close SSH or die "copying store paths to remote machine `$sshHost' failed: $?";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
28
scripts/GeneratePatches.pm.in → perl/lib/Nix/GeneratePatches.pm
Executable file → Normal file
28
scripts/GeneratePatches.pm.in → perl/lib/Nix/GeneratePatches.pm
Executable file → Normal file
@@ -1,7 +1,13 @@
|
||||
#! @perl@ -w -I@libexecdir@/nix
|
||||
package Nix::GeneratePatches;
|
||||
|
||||
use strict;
|
||||
use File::Temp qw(tempdir);
|
||||
use File::stat;
|
||||
use Nix::Config;
|
||||
use Nix::Manifest;
|
||||
|
||||
our @ISA = qw(Exporter);
|
||||
our @EXPORT = qw(generatePatches propagatePatches copyPatches);
|
||||
|
||||
|
||||
# Some patch generations options.
|
||||
@@ -202,41 +208,41 @@ sub generatePatches {
|
||||
next;
|
||||
}
|
||||
|
||||
system("@bunzip2@ < $srcNarBz2 > $tmpDir/A") == 0
|
||||
system("$Nix::Config::bzip2 -d < $srcNarBz2 > $tmpDir/A") == 0
|
||||
or die "cannot unpack $srcNarBz2";
|
||||
|
||||
if ((stat "$tmpDir/A")[7] >= $maxNarSize) {
|
||||
if (stat("$tmpDir/A")->size >= $maxNarSize) {
|
||||
print " skipping, source is too large\n";
|
||||
next;
|
||||
}
|
||||
|
||||
system("@bunzip2@ < $dstNarBz2 > $tmpDir/B") == 0
|
||||
system("$Nix::Config::bzip2 -d < $dstNarBz2 > $tmpDir/B") == 0
|
||||
or die "cannot unpack $dstNarBz2";
|
||||
|
||||
if ((stat "$tmpDir/B")[7] >= $maxNarSize) {
|
||||
if (stat("$tmpDir/B")->size >= $maxNarSize) {
|
||||
print " skipping, destination is too large\n";
|
||||
next;
|
||||
}
|
||||
|
||||
my $time1 = time();
|
||||
my $res = system("ulimit -t $timeLimit; @libexecdir@/bsdiff $tmpDir/A $tmpDir/B $tmpDir/DIFF");
|
||||
my $res = system("ulimit -t $timeLimit; $Nix::Config::libexecDir/bsdiff $tmpDir/A $tmpDir/B $tmpDir/DIFF");
|
||||
my $time2 = time();
|
||||
if ($res) {
|
||||
warn "binary diff computation aborted after ", $time2 - $time1, " seconds\n";
|
||||
next;
|
||||
}
|
||||
|
||||
my $baseHash = `@bindir@/nix-hash --flat --type $hashAlgo --base32 $tmpDir/A` or die;
|
||||
my $baseHash = `$Nix::Config::binDir/nix-hash --flat --type $hashAlgo --base32 $tmpDir/A` or die;
|
||||
chomp $baseHash;
|
||||
|
||||
my $narHash = `@bindir@/nix-hash --flat --type $hashAlgo --base32 $tmpDir/B` or die;
|
||||
my $narHash = `$Nix::Config::binDir/nix-hash --flat --type $hashAlgo --base32 $tmpDir/B` or die;
|
||||
chomp $narHash;
|
||||
|
||||
my $narDiffHash = `@bindir@/nix-hash --flat --type $hashAlgo --base32 $tmpDir/DIFF` or die;
|
||||
my $narDiffHash = `$Nix::Config::binDir/nix-hash --flat --type $hashAlgo --base32 $tmpDir/DIFF` or die;
|
||||
chomp $narDiffHash;
|
||||
|
||||
my $narDiffSize = (stat "$tmpDir/DIFF")[7];
|
||||
my $dstNarBz2Size = (stat $dstNarBz2)[7];
|
||||
my $narDiffSize = stat("$tmpDir/DIFF")->size;
|
||||
my $dstNarBz2Size = stat($dstNarBz2)->size;
|
||||
|
||||
print " size $narDiffSize; full size $dstNarBz2Size; ", $time2 - $time1, " seconds\n";
|
||||
|
||||
367
perl/lib/Nix/Manifest.pm
Normal file
367
perl/lib/Nix/Manifest.pm
Normal file
@@ -0,0 +1,367 @@
|
||||
package Nix::Manifest;
|
||||
|
||||
use strict;
|
||||
use DBI;
|
||||
use Cwd;
|
||||
use File::stat;
|
||||
use File::Path;
|
||||
use Fcntl ':flock';
|
||||
use Nix::Config;
|
||||
|
||||
our @ISA = qw(Exporter);
|
||||
our @EXPORT = qw(readManifest writeManifest updateManifestDB addPatch);
|
||||
|
||||
|
||||
sub addNAR {
|
||||
my ($narFiles, $storePath, $info) = @_;
|
||||
|
||||
$$narFiles{$storePath} = []
|
||||
unless defined $$narFiles{$storePath};
|
||||
|
||||
my $narFileList = $$narFiles{$storePath};
|
||||
|
||||
my $found = 0;
|
||||
foreach my $narFile (@{$narFileList}) {
|
||||
$found = 1 if $narFile->{url} eq $info->{url};
|
||||
}
|
||||
|
||||
push @{$narFileList}, $info if !$found;
|
||||
}
|
||||
|
||||
|
||||
sub addPatch {
|
||||
my ($patches, $storePath, $patch) = @_;
|
||||
|
||||
$$patches{$storePath} = []
|
||||
unless defined $$patches{$storePath};
|
||||
|
||||
my $patchList = $$patches{$storePath};
|
||||
|
||||
my $found = 0;
|
||||
foreach my $patch2 (@{$patchList}) {
|
||||
$found = 1 if
|
||||
$patch2->{url} eq $patch->{url} &&
|
||||
$patch2->{basePath} eq $patch->{basePath};
|
||||
}
|
||||
|
||||
push @{$patchList}, $patch if !$found;
|
||||
|
||||
return !$found;
|
||||
}
|
||||
|
||||
|
||||
sub readManifest_ {
|
||||
my ($manifest, $addNAR, $addPatch) = @_;
|
||||
|
||||
# Decompress the manifest if necessary.
|
||||
if ($manifest =~ /\.bz2$/) {
|
||||
open MANIFEST, "$Nix::Config::bzip2 -d < $manifest |"
|
||||
or die "cannot decompress `$manifest': $!";
|
||||
} else {
|
||||
open MANIFEST, "<$manifest"
|
||||
or die "cannot open `$manifest': $!";
|
||||
}
|
||||
|
||||
my $inside = 0;
|
||||
my $type;
|
||||
|
||||
my $manifestVersion = 2;
|
||||
|
||||
my ($storePath, $url, $hash, $size, $basePath, $baseHash, $patchType);
|
||||
my ($narHash, $narSize, $references, $deriver, $copyFrom, $system);
|
||||
|
||||
while (<MANIFEST>) {
|
||||
chomp;
|
||||
s/\#.*$//g;
|
||||
next if (/^$/);
|
||||
|
||||
if (!$inside) {
|
||||
|
||||
if (/^\s*(\w*)\s*\{$/) {
|
||||
$type = $1;
|
||||
$type = "narfile" if $type eq "";
|
||||
$inside = 1;
|
||||
undef $storePath;
|
||||
undef $url;
|
||||
undef $hash;
|
||||
undef $size;
|
||||
undef $narHash;
|
||||
undef $narSize;
|
||||
undef $basePath;
|
||||
undef $baseHash;
|
||||
undef $patchType;
|
||||
undef $system;
|
||||
$references = "";
|
||||
$deriver = "";
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (/^\}$/) {
|
||||
$inside = 0;
|
||||
|
||||
if ($type eq "narfile") {
|
||||
&$addNAR($storePath,
|
||||
{ url => $url, hash => $hash, size => $size
|
||||
, narHash => $narHash, narSize => $narSize
|
||||
, references => $references
|
||||
, deriver => $deriver
|
||||
, system => $system
|
||||
});
|
||||
}
|
||||
|
||||
elsif ($type eq "patch") {
|
||||
&$addPatch($storePath,
|
||||
{ url => $url, hash => $hash, size => $size
|
||||
, basePath => $basePath, baseHash => $baseHash
|
||||
, narHash => $narHash, narSize => $narSize
|
||||
, patchType => $patchType
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
elsif (/^\s*StorePath:\s*(\/\S+)\s*$/) { $storePath = $1; }
|
||||
elsif (/^\s*CopyFrom:\s*(\/\S+)\s*$/) { $copyFrom = $1; }
|
||||
elsif (/^\s*Hash:\s*(\S+)\s*$/) { $hash = $1; }
|
||||
elsif (/^\s*URL:\s*(\S+)\s*$/) { $url = $1; }
|
||||
elsif (/^\s*Size:\s*(\d+)\s*$/) { $size = $1; }
|
||||
elsif (/^\s*BasePath:\s*(\/\S+)\s*$/) { $basePath = $1; }
|
||||
elsif (/^\s*BaseHash:\s*(\S+)\s*$/) { $baseHash = $1; }
|
||||
elsif (/^\s*Type:\s*(\S+)\s*$/) { $patchType = $1; }
|
||||
elsif (/^\s*NarHash:\s*(\S+)\s*$/) { $narHash = $1; }
|
||||
elsif (/^\s*NarSize:\s*(\d+)\s*$/) { $narSize = $1; }
|
||||
elsif (/^\s*References:\s*(.*)\s*$/) { $references = $1; }
|
||||
elsif (/^\s*Deriver:\s*(\S+)\s*$/) { $deriver = $1; }
|
||||
elsif (/^\s*ManifestVersion:\s*(\d+)\s*$/) { $manifestVersion = $1; }
|
||||
elsif (/^\s*System:\s*(\S+)\s*$/) { $system = $1; }
|
||||
|
||||
# Compatibility;
|
||||
elsif (/^\s*NarURL:\s*(\S+)\s*$/) { $url = $1; }
|
||||
elsif (/^\s*MD5:\s*(\S+)\s*$/) { $hash = "md5:$1"; }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
close MANIFEST;
|
||||
|
||||
return $manifestVersion;
|
||||
}
|
||||
|
||||
|
||||
sub readManifest {
|
||||
my ($manifest, $narFiles, $patches) = @_;
|
||||
readManifest_($manifest,
|
||||
sub { addNAR($narFiles, @_); },
|
||||
sub { addPatch($patches, @_); } );
|
||||
}
|
||||
|
||||
|
||||
sub writeManifest {
|
||||
my ($manifest, $narFiles, $patches, $noCompress) = @_;
|
||||
|
||||
open MANIFEST, ">$manifest.tmp"; # !!! check exclusive
|
||||
|
||||
print MANIFEST "version {\n";
|
||||
print MANIFEST " ManifestVersion: 3\n";
|
||||
print MANIFEST "}\n";
|
||||
|
||||
foreach my $storePath (sort (keys %{$narFiles})) {
|
||||
my $narFileList = $$narFiles{$storePath};
|
||||
foreach my $narFile (@{$narFileList}) {
|
||||
print MANIFEST "{\n";
|
||||
print MANIFEST " StorePath: $storePath\n";
|
||||
print MANIFEST " NarURL: $narFile->{url}\n";
|
||||
print MANIFEST " Hash: $narFile->{hash}\n" if defined $narFile->{hash};
|
||||
print MANIFEST " Size: $narFile->{size}\n" if defined $narFile->{size};
|
||||
print MANIFEST " NarHash: $narFile->{narHash}\n";
|
||||
print MANIFEST " NarSize: $narFile->{narSize}\n" if $narFile->{narSize};
|
||||
print MANIFEST " References: $narFile->{references}\n"
|
||||
if defined $narFile->{references} && $narFile->{references} ne "";
|
||||
print MANIFEST " Deriver: $narFile->{deriver}\n"
|
||||
if defined $narFile->{deriver} && $narFile->{deriver} ne "";
|
||||
print MANIFEST " System: $narFile->{system}\n" if defined $narFile->{system};
|
||||
print MANIFEST "}\n";
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $storePath (sort (keys %{$patches})) {
|
||||
my $patchList = $$patches{$storePath};
|
||||
foreach my $patch (@{$patchList}) {
|
||||
print MANIFEST "patch {\n";
|
||||
print MANIFEST " StorePath: $storePath\n";
|
||||
print MANIFEST " NarURL: $patch->{url}\n";
|
||||
print MANIFEST " Hash: $patch->{hash}\n";
|
||||
print MANIFEST " Size: $patch->{size}\n";
|
||||
print MANIFEST " NarHash: $patch->{narHash}\n";
|
||||
print MANIFEST " NarSize: $patch->{narSize}\n" if $patch->{narSize};
|
||||
print MANIFEST " BasePath: $patch->{basePath}\n";
|
||||
print MANIFEST " BaseHash: $patch->{baseHash}\n";
|
||||
print MANIFEST " Type: $patch->{patchType}\n";
|
||||
print MANIFEST "}\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
close MANIFEST;
|
||||
|
||||
rename("$manifest.tmp", $manifest)
|
||||
or die "cannot rename $manifest.tmp: $!";
|
||||
|
||||
|
||||
# Create a bzipped manifest.
|
||||
unless (defined $noCompress) {
|
||||
system("$Nix::Config::bzip2 < $manifest > $manifest.bz2.tmp") == 0
|
||||
or die "cannot compress manifest";
|
||||
|
||||
rename("$manifest.bz2.tmp", "$manifest.bz2")
|
||||
or die "cannot rename $manifest.bz2.tmp: $!";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub updateManifestDB {
|
||||
my $manifestDir = $Nix::Config::manifestDir;
|
||||
|
||||
mkpath($manifestDir);
|
||||
|
||||
my $dbPath = "$manifestDir/cache.sqlite";
|
||||
|
||||
# Open/create the database.
|
||||
our $dbh = DBI->connect("dbi:SQLite:dbname=$dbPath", "", "")
|
||||
or die "cannot open database `$dbPath'";
|
||||
$dbh->{RaiseError} = 1;
|
||||
$dbh->{PrintError} = 0;
|
||||
|
||||
$dbh->do("pragma foreign_keys = on");
|
||||
$dbh->do("pragma synchronous = off"); # we can always reproduce the cache
|
||||
$dbh->do("pragma journal_mode = truncate");
|
||||
|
||||
# Initialise the database schema, if necessary.
|
||||
$dbh->do(<<EOF);
|
||||
create table if not exists Manifests (
|
||||
id integer primary key autoincrement not null,
|
||||
path text unique not null,
|
||||
timestamp integer not null
|
||||
);
|
||||
EOF
|
||||
|
||||
$dbh->do(<<EOF);
|
||||
create table if not exists NARs (
|
||||
id integer primary key autoincrement not null,
|
||||
manifest integer not null,
|
||||
storePath text not null,
|
||||
url text not null,
|
||||
hash text,
|
||||
size integer,
|
||||
narHash text,
|
||||
narSize integer,
|
||||
refs text,
|
||||
deriver text,
|
||||
system text,
|
||||
foreign key (manifest) references Manifests(id) on delete cascade
|
||||
);
|
||||
EOF
|
||||
|
||||
$dbh->do("create index if not exists NARs_storePath on NARs(storePath)");
|
||||
|
||||
$dbh->do(<<EOF);
|
||||
create table if not exists Patches (
|
||||
id integer primary key autoincrement not null,
|
||||
manifest integer not null,
|
||||
storePath text not null,
|
||||
basePath text not null,
|
||||
baseHash text not null,
|
||||
url text not null,
|
||||
hash text,
|
||||
size integer,
|
||||
narHash text,
|
||||
narSize integer,
|
||||
patchType text not null,
|
||||
foreign key (manifest) references Manifests(id) on delete cascade
|
||||
);
|
||||
EOF
|
||||
|
||||
$dbh->do("create index if not exists Patches_storePath on Patches(storePath)");
|
||||
|
||||
# Acquire an exclusive lock to ensure that only one process
|
||||
# updates the DB at the same time. This isn't really necessary,
|
||||
# but it prevents work duplication and lock contention in SQLite.
|
||||
my $lockFile = "$manifestDir/cache.lock";
|
||||
open MAINLOCK, ">>$lockFile" or die "unable to acquire lock ‘$lockFile’: $!\n";
|
||||
flock(MAINLOCK, LOCK_EX) or die;
|
||||
|
||||
our $insertNAR = $dbh->prepare(
|
||||
"insert into NARs(manifest, storePath, url, hash, size, narHash, " .
|
||||
"narSize, refs, deriver, system) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") or die;
|
||||
|
||||
our $insertPatch = $dbh->prepare(
|
||||
"insert into Patches(manifest, storePath, basePath, baseHash, url, hash, " .
|
||||
"size, narHash, narSize, patchType) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
|
||||
$dbh->begin_work;
|
||||
|
||||
# Read each manifest in $manifestDir and add it to the database,
|
||||
# unless we've already done so on a previous run.
|
||||
my %seen;
|
||||
|
||||
for my $manifestLink (glob "$manifestDir/*.nixmanifest") {
|
||||
my $manifest = Cwd::abs_path($manifestLink);
|
||||
next unless -f $manifest;
|
||||
my $timestamp = lstat($manifest)->mtime;
|
||||
$seen{$manifest} = 1;
|
||||
|
||||
next if scalar @{$dbh->selectcol_arrayref(
|
||||
"select 1 from Manifests where path = ? and timestamp = ?",
|
||||
{}, $manifest, $timestamp)} == 1;
|
||||
|
||||
print STDERR "caching $manifest...\n";
|
||||
|
||||
$dbh->do("delete from Manifests where path = ?", {}, $manifest);
|
||||
|
||||
$dbh->do("insert into Manifests(path, timestamp) values (?, ?)",
|
||||
{}, $manifest, $timestamp);
|
||||
|
||||
our $id = $dbh->last_insert_id("", "", "", "");
|
||||
|
||||
sub addNARToDB {
|
||||
my ($storePath, $narFile) = @_;
|
||||
$insertNAR->execute(
|
||||
$id, $storePath, $narFile->{url}, $narFile->{hash}, $narFile->{size},
|
||||
$narFile->{narHash}, $narFile->{narSize}, $narFile->{references},
|
||||
$narFile->{deriver}, $narFile->{system});
|
||||
};
|
||||
|
||||
sub addPatchToDB {
|
||||
my ($storePath, $patch) = @_;
|
||||
$insertPatch->execute(
|
||||
$id, $storePath, $patch->{basePath}, $patch->{baseHash}, $patch->{url},
|
||||
$patch->{hash}, $patch->{size}, $patch->{narHash}, $patch->{narSize},
|
||||
$patch->{patchType});
|
||||
};
|
||||
|
||||
my $version = readManifest_($manifest, \&addNARToDB, \&addPatchToDB);
|
||||
|
||||
if ($version < 3) {
|
||||
die "you have an old-style or corrupt manifest `$manifestLink'; please delete it";
|
||||
}
|
||||
if ($version >= 10) {
|
||||
die "manifest `$manifestLink' is too new; please delete it or upgrade Nix";
|
||||
}
|
||||
}
|
||||
|
||||
# Removed cached information for removed manifests from the DB.
|
||||
foreach my $manifest (@{$dbh->selectcol_arrayref("select path from Manifests")}) {
|
||||
next if defined $seen{$manifest};
|
||||
$dbh->do("delete from Manifests where path = ?", {}, $manifest);
|
||||
}
|
||||
|
||||
$dbh->commit;
|
||||
|
||||
close MAINLOCK;
|
||||
|
||||
return $dbh;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
27
perl/lib/Nix/Store.pm
Normal file
27
perl/lib/Nix/Store.pm
Normal file
@@ -0,0 +1,27 @@
|
||||
package Nix::Store;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
require Exporter;
|
||||
|
||||
our @ISA = qw(Exporter);
|
||||
|
||||
our %EXPORT_TAGS = ( 'all' => [ qw( ) ] );
|
||||
|
||||
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
|
||||
|
||||
our @EXPORT = qw(
|
||||
isValidPath queryReferences queryPathInfo queryDeriver queryPathHash
|
||||
topoSortPaths computeFSClosure followLinksToStorePath exportPaths
|
||||
hashPath hashFile hashString
|
||||
addToStore makeFixedOutputPath
|
||||
);
|
||||
|
||||
our $VERSION = '0.15';
|
||||
|
||||
require XSLoader;
|
||||
XSLoader::load('Nix::Store', $VERSION);
|
||||
|
||||
1;
|
||||
__END__
|
||||
218
perl/lib/Nix/Store.xs
Normal file
218
perl/lib/Nix/Store.xs
Normal file
@@ -0,0 +1,218 @@
|
||||
#include "EXTERN.h"
|
||||
#include "perl.h"
|
||||
#include "XSUB.h"
|
||||
|
||||
/* Prevent a clash between some Perl and libstdc++ macros. */
|
||||
#undef do_open
|
||||
#undef do_close
|
||||
|
||||
#include <store-api.hh>
|
||||
#include <globals.hh>
|
||||
#include <misc.hh>
|
||||
#include <util.hh>
|
||||
|
||||
|
||||
using namespace nix;
|
||||
|
||||
|
||||
void doInit()
|
||||
{
|
||||
if (!store) {
|
||||
try {
|
||||
setDefaultsFromEnvironment();
|
||||
store = openStore();
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MODULE = Nix::Store PACKAGE = Nix::Store
|
||||
PROTOTYPES: ENABLE
|
||||
|
||||
|
||||
void init()
|
||||
CODE:
|
||||
doInit();
|
||||
|
||||
|
||||
int isValidPath(char * path)
|
||||
CODE:
|
||||
try {
|
||||
doInit();
|
||||
RETVAL = store->isValidPath(path);
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
}
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
|
||||
SV * queryReferences(char * path)
|
||||
PPCODE:
|
||||
try {
|
||||
doInit();
|
||||
PathSet paths;
|
||||
store->queryReferences(path, paths);
|
||||
for (PathSet::iterator i = paths.begin(); i != paths.end(); ++i)
|
||||
XPUSHs(sv_2mortal(newSVpv(i->c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
}
|
||||
|
||||
|
||||
SV * queryPathHash(char * path)
|
||||
PPCODE:
|
||||
try {
|
||||
doInit();
|
||||
Hash hash = store->queryPathHash(path);
|
||||
string s = "sha256:" + printHash32(hash);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
}
|
||||
|
||||
|
||||
SV * queryDeriver(char * path)
|
||||
PPCODE:
|
||||
try {
|
||||
doInit();
|
||||
Path deriver = store->queryDeriver(path);
|
||||
if (deriver == "") XSRETURN_UNDEF;
|
||||
XPUSHs(sv_2mortal(newSVpv(deriver.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
}
|
||||
|
||||
|
||||
SV * queryPathInfo(char * path)
|
||||
PPCODE:
|
||||
try {
|
||||
doInit();
|
||||
ValidPathInfo info = store->queryPathInfo(path);
|
||||
if (info.deriver == "")
|
||||
XPUSHs(&PL_sv_undef);
|
||||
else
|
||||
XPUSHs(sv_2mortal(newSVpv(info.deriver.c_str(), 0)));
|
||||
string s = "sha256:" + printHash(info.hash);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
mXPUSHi(info.registrationTime);
|
||||
mXPUSHi(info.narSize);
|
||||
AV * arr = newAV();
|
||||
for (PathSet::iterator i = info.references.begin(); i != info.references.end(); ++i)
|
||||
av_push(arr, newSVpv(i->c_str(), 0));
|
||||
XPUSHs(sv_2mortal(newRV((SV *) arr)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
}
|
||||
|
||||
|
||||
SV * computeFSClosure(int flipDirection, int includeOutputs, ...)
|
||||
PPCODE:
|
||||
try {
|
||||
doInit();
|
||||
PathSet paths;
|
||||
for (int n = 2; n < items; ++n)
|
||||
computeFSClosure(*store, SvPV_nolen(ST(n)), paths, flipDirection, includeOutputs);
|
||||
for (PathSet::iterator i = paths.begin(); i != paths.end(); ++i)
|
||||
XPUSHs(sv_2mortal(newSVpv(i->c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
}
|
||||
|
||||
|
||||
SV * topoSortPaths(...)
|
||||
PPCODE:
|
||||
try {
|
||||
doInit();
|
||||
PathSet paths;
|
||||
for (int n = 0; n < items; ++n) paths.insert(SvPV_nolen(ST(n)));
|
||||
Paths sorted = topoSortPaths(*store, paths);
|
||||
for (Paths::iterator i = sorted.begin(); i != sorted.end(); ++i)
|
||||
XPUSHs(sv_2mortal(newSVpv(i->c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
}
|
||||
|
||||
|
||||
SV * followLinksToStorePath(char * path)
|
||||
CODE:
|
||||
try {
|
||||
doInit();
|
||||
RETVAL = newSVpv(followLinksToStorePath(path).c_str(), 0);
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
}
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
|
||||
void exportPaths(int fd, int sign, ...)
|
||||
PPCODE:
|
||||
try {
|
||||
doInit();
|
||||
Paths paths;
|
||||
for (int n = 2; n < items; ++n) paths.push_back(SvPV_nolen(ST(n)));
|
||||
FdSink sink(fd);
|
||||
exportPaths(*store, paths, sign, sink);
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
}
|
||||
|
||||
|
||||
SV * hashPath(char * algo, int base32, char * path)
|
||||
PPCODE:
|
||||
try {
|
||||
Hash h = hashPath(parseHashType(algo), path).first;
|
||||
string s = base32 ? printHash32(h) : printHash(h);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
}
|
||||
|
||||
|
||||
SV * hashFile(char * algo, int base32, char * path)
|
||||
PPCODE:
|
||||
try {
|
||||
Hash h = hashFile(parseHashType(algo), path);
|
||||
string s = base32 ? printHash32(h) : printHash(h);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
}
|
||||
|
||||
|
||||
SV * hashString(char * algo, int base32, char * s)
|
||||
PPCODE:
|
||||
try {
|
||||
Hash h = hashString(parseHashType(algo), s);
|
||||
string s = base32 ? printHash32(h) : printHash(h);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
}
|
||||
|
||||
|
||||
SV * addToStore(char * srcPath, int recursive, char * algo)
|
||||
PPCODE:
|
||||
try {
|
||||
doInit();
|
||||
Path path = store->addToStore(srcPath, recursive, parseHashType(algo));
|
||||
XPUSHs(sv_2mortal(newSVpv(path.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
}
|
||||
|
||||
|
||||
SV * makeFixedOutputPath(int recursive, char * algo, char * hash, char * name)
|
||||
PPCODE:
|
||||
try {
|
||||
doInit();
|
||||
HashType ht = parseHashType(algo);
|
||||
Path path = makeFixedOutputPath(recursive, ht,
|
||||
parseHash16or32(ht, hash), name);
|
||||
XPUSHs(sv_2mortal(newSVpv(path.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
}
|
||||
74
release.nix
74
release.nix
@@ -1,4 +1,4 @@
|
||||
{ nixpkgs ? ../nixpkgs
|
||||
{ nixpkgs ? <nixpkgs>, nixos ? <nixos>
|
||||
, nix ? { outPath = ./.; rev = 1234; }
|
||||
, officialRelease ? false
|
||||
}:
|
||||
@@ -26,6 +26,8 @@ let
|
||||
--with-docbook-rng=${docbook5}/xml/rng/docbook
|
||||
--with-docbook-xsl=${docbook5_xsl}/xml/xsl/docbook
|
||||
--with-xml-flags=--nonet
|
||||
--with-dbi=${perlPackages.DBI}/lib/perl5/site_perl
|
||||
--with-dbd-sqlite=${perlPackages.DBDSQLite}/lib/perl5/site_perl
|
||||
'';
|
||||
|
||||
# Include the Bzip2 tarball in the distribution.
|
||||
@@ -75,6 +77,8 @@ let
|
||||
configureFlags = ''
|
||||
--disable-init-state
|
||||
--with-bzip2=${bzip2} --with-sqlite=${sqlite}
|
||||
--with-dbi=${perlPackages.DBI}/lib/perl5/site_perl
|
||||
--with-dbd-sqlite=${perlPackages.DBDSQLite}/lib/perl5/site_perl
|
||||
--enable-gc
|
||||
'';
|
||||
};
|
||||
@@ -94,8 +98,10 @@ let
|
||||
];
|
||||
|
||||
configureFlags = ''
|
||||
--disable-init-state --disable-shared
|
||||
--disable-init-state
|
||||
--with-bzip2=${bzip2} --with-sqlite=${sqlite}
|
||||
--with-dbi=${perlPackages.DBI}/lib/perl5/site_perl
|
||||
--with-dbd-sqlite=${perlPackages.DBDSQLite}/lib/perl5/site_perl
|
||||
'';
|
||||
|
||||
lcovFilter = [ "*/boost/*" "*-tab.*" ];
|
||||
@@ -107,34 +113,42 @@ let
|
||||
};
|
||||
|
||||
|
||||
rpm_fedora5i386 = makeRPM_i686 (diskImages: diskImages.fedora5i386) 10;
|
||||
rpm_fedora9i386 = makeRPM_i686 (diskImages: diskImages.fedora9i386) 20;
|
||||
rpm_fedora9x86_64 = makeRPM_x86_64 (diskImages: diskImages.fedora9x86_64) 20;
|
||||
rpm_fedora10i386 = makeRPM_i686 (diskImages: diskImages.fedora10i386) 30;
|
||||
rpm_fedora10x86_64 = makeRPM_x86_64 (diskImages: diskImages.fedora10x86_64) 30;
|
||||
rpm_fedora11i386 = makeRPM_i686 (diskImages: diskImages.fedora11i386) 40;
|
||||
rpm_fedora11x86_64 = makeRPM_x86_64 (diskImages: diskImages.fedora11x86_64) 40;
|
||||
rpm_fedora12i386 = makeRPM_i686 (diskImages: diskImages.fedora12i386) 50;
|
||||
rpm_fedora12x86_64 = makeRPM_x86_64 (diskImages: diskImages.fedora12x86_64) 50;
|
||||
rpm_opensuse103i386 = makeRPM_i686 (diskImages: diskImages.opensuse103i386) 40;
|
||||
rpm_opensuse110i386 = makeRPM_i686 (diskImages: diskImages.opensuse110i386) 50;
|
||||
rpm_opensuse110x86_64 = makeRPM_x86_64 (diskImages: diskImages.opensuse110x86_64) 50;
|
||||
rpm_fedora10i386 = makeRPM_i686 (diskImageFuns: diskImageFuns.fedora10i386) 20;
|
||||
rpm_fedora10x86_64 = makeRPM_x86_64 (diskImageFuns: diskImageFuns.fedora10x86_64) 20;
|
||||
rpm_fedora11i386 = makeRPM_i686 (diskImageFuns: diskImageFuns.fedora11i386) 30;
|
||||
rpm_fedora11x86_64 = makeRPM_x86_64 (diskImageFuns: diskImageFuns.fedora11x86_64) 30;
|
||||
rpm_fedora12i386 = makeRPM_i686 (diskImageFuns: diskImageFuns.fedora12i386) 40;
|
||||
rpm_fedora12x86_64 = makeRPM_x86_64 (diskImageFuns: diskImageFuns.fedora12x86_64) 40;
|
||||
rpm_fedora13i386 = makeRPM_i686 (diskImageFuns: diskImageFuns.fedora13i386) 50;
|
||||
rpm_fedora13x86_64 = makeRPM_x86_64 (diskImageFunsFun: diskImageFunsFun.fedora13x86_64) 50;
|
||||
rpm_opensuse103i386 = makeRPM_i686 (diskImageFuns: diskImageFuns.opensuse103i386) 40;
|
||||
rpm_opensuse110i386 = makeRPM_i686 (diskImageFuns: diskImageFuns.opensuse110i386) 50;
|
||||
rpm_opensuse110x86_64 = makeRPM_x86_64 (diskImageFuns: diskImageFuns.opensuse110x86_64) 50;
|
||||
|
||||
|
||||
deb_debian40i386 = makeDeb_i686 (diskImages: diskImages.debian40i386) 40;
|
||||
deb_debian40x86_64 = makeDeb_x86_64 (diskImages: diskImages.debian40x86_64) 40;
|
||||
deb_debian50i386 = makeDeb_i686 (diskImages: diskImages.debian50i386) 50;
|
||||
deb_debian50x86_64 = makeDeb_x86_64 (diskImages: diskImages.debian50x86_64) 50;
|
||||
deb_ubuntu804i386 = makeDeb_i686 (diskImages: diskImages.ubuntu804i386) 20;
|
||||
deb_ubuntu804x86_64 = makeDeb_x86_64 (diskImages: diskImages.ubuntu804x86_64) 20;
|
||||
deb_ubuntu810i386 = makeDeb_i686 (diskImages: diskImages.ubuntu810i386) 30;
|
||||
deb_ubuntu810x86_64 = makeDeb_x86_64 (diskImages: diskImages.ubuntu810x86_64) 30;
|
||||
deb_ubuntu904i386 = makeDeb_i686 (diskImages: diskImages.ubuntu904i386) 40;
|
||||
deb_ubuntu904x86_64 = makeDeb_x86_64 (diskImages: diskImages.ubuntu904x86_64) 40;
|
||||
deb_ubuntu910i386 = makeDeb_i686 (diskImages: diskImages.ubuntu910i386) 50;
|
||||
deb_ubuntu910x86_64 = makeDeb_x86_64 (diskImages: diskImages.ubuntu910x86_64) 50;
|
||||
deb_debian50i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.debian50i386) 50;
|
||||
deb_debian50x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.debian50x86_64) 50;
|
||||
deb_debian60i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.debian60i386) 50;
|
||||
deb_debian60x86_64 = makeDeb_x86_64 (diskImageFunsFun: diskImageFunsFun.debian60x86_64) 50;
|
||||
deb_ubuntu904i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu904i386) 40;
|
||||
deb_ubuntu904x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu904x86_64) 40;
|
||||
deb_ubuntu910i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu910i386) 50;
|
||||
deb_ubuntu910x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu910x86_64) 50;
|
||||
deb_ubuntu1004i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1004i386) 50;
|
||||
deb_ubuntu1004x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1004x86_64) 50;
|
||||
deb_ubuntu1010i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1010i386) 50;
|
||||
deb_ubuntu1010x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1010x86_64) 50;
|
||||
|
||||
|
||||
# System tests.
|
||||
tests.remote_builds = (import ./tests/remote-builds.nix rec {
|
||||
inherit nixpkgs nixos; nix = build { inherit system; }; system = "x86_64-linux";
|
||||
}).test;
|
||||
|
||||
tests.nix_copy_closure = (import ./tests/nix-copy-closure.nix rec {
|
||||
inherit nixpkgs nixos; nix = build { inherit system; }; system = "x86_64-linux";
|
||||
}).test;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -149,7 +163,8 @@ let
|
||||
releaseTools.rpmBuild rec {
|
||||
name = "nix-rpm-${diskImage.name}";
|
||||
src = jobs.tarball;
|
||||
diskImage = diskImageFun vmTools.diskImages;
|
||||
diskImage = (diskImageFun vmTools.diskImageFuns)
|
||||
{ extraPackages = [ "perl-DBD-SQLite" "perl-devel" ]; };
|
||||
memSize = 1024;
|
||||
meta.schedulingPriority = prio;
|
||||
};
|
||||
@@ -166,11 +181,12 @@ let
|
||||
releaseTools.debBuild {
|
||||
name = "nix-deb";
|
||||
src = jobs.tarball;
|
||||
diskImage = diskImageFun vmTools.diskImages;
|
||||
diskImage = (diskImageFun vmTools.diskImageFuns)
|
||||
{ extraPackages = [ "libdbd-sqlite3-perl" ]; };
|
||||
memSize = 1024;
|
||||
meta.schedulingPriority = prio;
|
||||
configureFlags = "--sysconfdir=/etc";
|
||||
debRequires = [ "curl" ];
|
||||
debRequires = [ "curl" "libdbd-sqlite3-perl" ];
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -3,20 +3,16 @@ bin_SCRIPTS = nix-collect-garbage \
|
||||
nix-install-package nix-channel nix-build \
|
||||
nix-copy-closure nix-generate-patches
|
||||
|
||||
noinst_SCRIPTS = nix-profile.sh GeneratePatches.pm \
|
||||
noinst_SCRIPTS = nix-profile.sh \
|
||||
find-runtime-roots.pl build-remote.pl nix-reduce-build \
|
||||
copy-from-other-stores.pl nix-http-export.cgi
|
||||
|
||||
nix-pull nix-push: NixManifest.pm NixConfig.pm download-using-manifests.pl
|
||||
nix-pull nix-push: download-using-manifests.pl
|
||||
|
||||
install-exec-local: NixManifest.pm GeneratePatches.pm download-using-manifests.pl copy-from-other-stores.pl find-runtime-roots.pl
|
||||
install-exec-local: download-using-manifests.pl copy-from-other-stores.pl find-runtime-roots.pl
|
||||
$(INSTALL) -d $(DESTDIR)$(sysconfdir)/profile.d
|
||||
$(INSTALL_PROGRAM) nix-profile.sh $(DESTDIR)$(sysconfdir)/profile.d/nix.sh
|
||||
$(INSTALL) -d $(DESTDIR)$(libexecdir)/nix
|
||||
$(INSTALL_DATA) NixManifest.pm $(DESTDIR)$(libexecdir)/nix
|
||||
$(INSTALL_DATA) NixConfig.pm $(DESTDIR)$(libexecdir)/nix
|
||||
$(INSTALL_DATA) SSH.pm $(DESTDIR)$(libexecdir)/nix
|
||||
$(INSTALL_DATA) GeneratePatches.pm $(DESTDIR)$(libexecdir)/nix
|
||||
$(INSTALL_PROGRAM) find-runtime-roots.pl $(DESTDIR)$(libexecdir)/nix
|
||||
$(INSTALL_PROGRAM) build-remote.pl $(DESTDIR)$(libexecdir)/nix
|
||||
$(INSTALL) -d $(DESTDIR)$(libexecdir)/nix/substituters
|
||||
@@ -30,10 +26,6 @@ EXTRA_DIST = nix-collect-garbage.in \
|
||||
nix-pull.in nix-push.in nix-profile.sh.in \
|
||||
nix-prefetch-url.in nix-install-package.in \
|
||||
nix-channel.in \
|
||||
NixManifest.pm.in \
|
||||
NixConfig.pm.in \
|
||||
SSH.pm \
|
||||
GeneratePatches.pm.in \
|
||||
nix-build.in \
|
||||
download-using-manifests.pl.in \
|
||||
copy-from-other-stores.pl.in \
|
||||
@@ -43,3 +35,6 @@ EXTRA_DIST = nix-collect-garbage.in \
|
||||
nix-reduce-build.in \
|
||||
nix-http-export.cgi.in \
|
||||
nix-generate-patches.in
|
||||
|
||||
clean:
|
||||
rm -f $(bin_SCRIPTS) $(noinst_SCRIPTS)
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
use strict;
|
||||
|
||||
sub readConfig {
|
||||
my %config;
|
||||
my $config = "@sysconfdir@/nix/nix.conf";
|
||||
return unless -f $config;
|
||||
|
||||
open CONFIG, "<$config" or die "cannot open `$config'";
|
||||
while (<CONFIG>) {
|
||||
/^\s*([\w|-]+)\s*=\s*(.*)$/ or next;
|
||||
$config{$1} = $2;
|
||||
print "|$1| -> |$2|\n";
|
||||
}
|
||||
close CONFIG;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -1,211 +0,0 @@
|
||||
use strict;
|
||||
|
||||
|
||||
sub addPatch {
|
||||
my ($patches, $storePath, $patch) = @_;
|
||||
|
||||
$$patches{$storePath} = []
|
||||
unless defined $$patches{$storePath};
|
||||
|
||||
my $patchList = $$patches{$storePath};
|
||||
|
||||
my $found = 0;
|
||||
foreach my $patch2 (@{$patchList}) {
|
||||
$found = 1 if
|
||||
$patch2->{url} eq $patch->{url} &&
|
||||
$patch2->{basePath} eq $patch->{basePath};
|
||||
}
|
||||
|
||||
push @{$patchList}, $patch if !$found;
|
||||
|
||||
return !$found;
|
||||
}
|
||||
|
||||
|
||||
sub readManifest {
|
||||
my ($manifest, $narFiles, $localPaths, $patches) = @_;
|
||||
|
||||
open MANIFEST, "<$manifest"
|
||||
or die "cannot open `$manifest': $!";
|
||||
|
||||
my $inside = 0;
|
||||
my $type;
|
||||
|
||||
my $manifestVersion = 2;
|
||||
|
||||
my ($storePath, $url, $hash, $size, $basePath, $baseHash, $patchType);
|
||||
my ($narHash, $narSize, $references, $deriver, $hashAlgo, $copyFrom, $system);
|
||||
|
||||
while (<MANIFEST>) {
|
||||
chomp;
|
||||
s/\#.*$//g;
|
||||
next if (/^$/);
|
||||
|
||||
if (!$inside) {
|
||||
|
||||
if (/^\s*(\w*)\s*\{$/) {
|
||||
$type = $1;
|
||||
$type = "narfile" if $type eq "";
|
||||
$inside = 1;
|
||||
undef $storePath;
|
||||
undef $url;
|
||||
undef $hash;
|
||||
undef $size;
|
||||
undef $narHash;
|
||||
undef $narSize;
|
||||
undef $basePath;
|
||||
undef $baseHash;
|
||||
undef $patchType;
|
||||
undef $system;
|
||||
$references = "";
|
||||
$deriver = "";
|
||||
$hashAlgo = "md5";
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (/^\}$/) {
|
||||
$inside = 0;
|
||||
|
||||
if ($type eq "narfile") {
|
||||
|
||||
$$narFiles{$storePath} = []
|
||||
unless defined $$narFiles{$storePath};
|
||||
|
||||
my $narFileList = $$narFiles{$storePath};
|
||||
|
||||
my $found = 0;
|
||||
foreach my $narFile (@{$narFileList}) {
|
||||
$found = 1 if $narFile->{url} eq $url;
|
||||
}
|
||||
if (!$found) {
|
||||
push @{$narFileList},
|
||||
{ url => $url, hash => $hash, size => $size
|
||||
, narHash => $narHash, narSize => $narSize
|
||||
, references => $references
|
||||
, deriver => $deriver, hashAlgo => $hashAlgo
|
||||
, system => $system
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
elsif ($type eq "patch") {
|
||||
addPatch $patches, $storePath,
|
||||
{ url => $url, hash => $hash, size => $size
|
||||
, basePath => $basePath, baseHash => $baseHash
|
||||
, narHash => $narHash, narSize => $narSize
|
||||
, patchType => $patchType, hashAlgo => $hashAlgo
|
||||
};
|
||||
}
|
||||
|
||||
elsif ($type eq "localPath") {
|
||||
|
||||
$$localPaths{$storePath} = []
|
||||
unless defined $$localPaths{$storePath};
|
||||
|
||||
my $localPathsList = $$localPaths{$storePath};
|
||||
|
||||
# !!! remove duplicates
|
||||
|
||||
push @{$localPathsList},
|
||||
{ copyFrom => $copyFrom, references => $references
|
||||
, deriver => ""
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
elsif (/^\s*StorePath:\s*(\/\S+)\s*$/) { $storePath = $1; }
|
||||
elsif (/^\s*CopyFrom:\s*(\/\S+)\s*$/) { $copyFrom = $1; }
|
||||
elsif (/^\s*Hash:\s*(\S+)\s*$/) { $hash = $1; }
|
||||
elsif (/^\s*URL:\s*(\S+)\s*$/) { $url = $1; }
|
||||
elsif (/^\s*Size:\s*(\d+)\s*$/) { $size = $1; }
|
||||
elsif (/^\s*SuccOf:\s*(\/\S+)\s*$/) { } # obsolete
|
||||
elsif (/^\s*BasePath:\s*(\/\S+)\s*$/) { $basePath = $1; }
|
||||
elsif (/^\s*BaseHash:\s*(\S+)\s*$/) { $baseHash = $1; }
|
||||
elsif (/^\s*Type:\s*(\S+)\s*$/) { $patchType = $1; }
|
||||
elsif (/^\s*NarHash:\s*(\S+)\s*$/) { $narHash = $1; }
|
||||
elsif (/^\s*NarSize:\s*(\d+)\s*$/) { $narSize = $1; }
|
||||
elsif (/^\s*References:\s*(.*)\s*$/) { $references = $1; }
|
||||
elsif (/^\s*Deriver:\s*(\S+)\s*$/) { $deriver = $1; }
|
||||
elsif (/^\s*ManifestVersion:\s*(\d+)\s*$/) { $manifestVersion = $1; }
|
||||
elsif (/^\s*System:\s*(\S+)\s*$/) { $system = $1; }
|
||||
|
||||
# Compatibility;
|
||||
elsif (/^\s*NarURL:\s*(\S+)\s*$/) { $url = $1; }
|
||||
elsif (/^\s*MD5:\s*(\S+)\s*$/) { $hash = "md5:$1"; }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
close MANIFEST;
|
||||
|
||||
return $manifestVersion;
|
||||
}
|
||||
|
||||
|
||||
sub writeManifest {
|
||||
my ($manifest, $narFiles, $patches, $noCompress) = @_;
|
||||
|
||||
open MANIFEST, ">$manifest.tmp"; # !!! check exclusive
|
||||
|
||||
print MANIFEST "version {\n";
|
||||
print MANIFEST " ManifestVersion: 3\n";
|
||||
print MANIFEST "}\n";
|
||||
|
||||
foreach my $storePath (sort (keys %{$narFiles})) {
|
||||
my $narFileList = $$narFiles{$storePath};
|
||||
foreach my $narFile (@{$narFileList}) {
|
||||
print MANIFEST "{\n";
|
||||
print MANIFEST " StorePath: $storePath\n";
|
||||
print MANIFEST " NarURL: $narFile->{url}\n";
|
||||
print MANIFEST " Hash: $narFile->{hash}\n" if defined $narFile->{hash};
|
||||
print MANIFEST " Size: $narFile->{size}\n" if defined $narFile->{size};
|
||||
print MANIFEST " NarHash: $narFile->{narHash}\n";
|
||||
print MANIFEST " NarSize: $narFile->{narSize}\n" if $narFile->{narSize};
|
||||
print MANIFEST " References: $narFile->{references}\n"
|
||||
if defined $narFile->{references} && $narFile->{references} ne "";
|
||||
print MANIFEST " Deriver: $narFile->{deriver}\n"
|
||||
if defined $narFile->{deriver} && $narFile->{deriver} ne "";
|
||||
print MANIFEST " System: $narFile->{system}\n" if defined $narFile->{system};
|
||||
print MANIFEST "}\n";
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $storePath (sort (keys %{$patches})) {
|
||||
my $patchList = $$patches{$storePath};
|
||||
foreach my $patch (@{$patchList}) {
|
||||
print MANIFEST "patch {\n";
|
||||
print MANIFEST " StorePath: $storePath\n";
|
||||
print MANIFEST " NarURL: $patch->{url}\n";
|
||||
print MANIFEST " Hash: $patch->{hash}\n";
|
||||
print MANIFEST " Size: $patch->{size}\n";
|
||||
print MANIFEST " NarHash: $patch->{narHash}\n";
|
||||
print MANIFEST " NarSize: $patch->{narSize}\n" if $patch->{narSize};
|
||||
print MANIFEST " BasePath: $patch->{basePath}\n";
|
||||
print MANIFEST " BaseHash: $patch->{baseHash}\n";
|
||||
print MANIFEST " Type: $patch->{patchType}\n";
|
||||
print MANIFEST "}\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
close MANIFEST;
|
||||
|
||||
rename("$manifest.tmp", $manifest)
|
||||
or die "cannot rename $manifest.tmp: $!";
|
||||
|
||||
|
||||
# Create a bzipped manifest.
|
||||
unless (defined $noCompress) {
|
||||
system("@bzip2@ < $manifest > $manifest.bz2.tmp") == 0
|
||||
or die "cannot compress manifest";
|
||||
|
||||
rename("$manifest.bz2.tmp", "$manifest.bz2")
|
||||
or die "cannot rename $manifest.bz2.tmp: $!";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
@@ -1,9 +1,11 @@
|
||||
#! @perl@ -w -I@libexecdir@/nix
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use Fcntl ':flock';
|
||||
use Fcntl qw(:DEFAULT :flock);
|
||||
use English '-no_match_vars';
|
||||
use IO::Handle;
|
||||
use SSH qw/sshOpts openSSHConnection/;
|
||||
use Nix::Config;
|
||||
use Nix::SSH qw/sshOpts openSSHConnection/;
|
||||
use Nix::CopyClosure;
|
||||
no warnings('once');
|
||||
|
||||
|
||||
@@ -54,7 +56,7 @@ sub openSlotLock {
|
||||
my ($machine, $slot) = @_;
|
||||
my $slotLockFn = "$currentLoad/" . (join '+', @{$machine->{systemTypes}}) . "-" . $machine->{hostName} . "-$slot";
|
||||
my $slotLock = new IO::Handle;
|
||||
open $slotLock, ">>$slotLockFn" or die;
|
||||
sysopen $slotLock, "$slotLockFn", O_RDWR|O_CREAT, 0600 or die;
|
||||
return $slotLock;
|
||||
}
|
||||
|
||||
@@ -62,7 +64,7 @@ sub openSlotLock {
|
||||
# Read the list of machines.
|
||||
my @machines;
|
||||
if (defined $conf && -e $conf) {
|
||||
open CONF, "< $conf" or die;
|
||||
open CONF, "<$conf" or die;
|
||||
while (<CONF>) {
|
||||
chomp;
|
||||
s/\#.*$//g;
|
||||
@@ -102,7 +104,7 @@ REQ: while (1) {
|
||||
# Acquire the exclusive lock on $currentLoad/main-lock.
|
||||
mkdir $currentLoad, 0777 or die unless -d $currentLoad;
|
||||
my $mainLock = "$currentLoad/main-lock";
|
||||
open MAINLOCK, ">>$mainLock" or die;
|
||||
sysopen MAINLOCK, "$mainLock", O_RDWR|O_CREAT, 0600 or die;
|
||||
flock(MAINLOCK, LOCK_EX) or die;
|
||||
|
||||
|
||||
@@ -208,7 +210,7 @@ print STDERR "@ build-remote $drvPath $hostName\n" if $printBuildTrace;
|
||||
|
||||
|
||||
my $maybeSign = "";
|
||||
$maybeSign = "--sign" if -e "/nix/etc/nix/signing-key.sec";
|
||||
$maybeSign = "--sign" if -e "$Nix::Config::confDir/signing-key.sec";
|
||||
|
||||
|
||||
# Register the derivation as a temporary GC root. Note that $PPID is
|
||||
@@ -223,9 +225,17 @@ sub removeRoots {
|
||||
}
|
||||
|
||||
|
||||
# Copy the derivation and its dependencies to the build machine.
|
||||
system("NIX_SSHOPTS=\"@sshOpts\" @bindir@/nix-copy-closure $hostName $maybeSign $drvPath @inputs") == 0
|
||||
or die "cannot copy inputs to $hostName: $?";
|
||||
# Copy the derivation and its dependencies to the build machine. This
|
||||
# is guarded by an exclusive lock per machine to prevent multiple
|
||||
# build-remote instances from copying to a machine simultaneously.
|
||||
# That's undesirable because we may end up with N instances uploading
|
||||
# the same missing path simultaneously, causing the effective network
|
||||
# bandwidth and target disk speed to be divided by N.
|
||||
my $uploadLock = "$currentLoad/$hostName.upload-lock";
|
||||
sysopen MAINLOCK, "$uploadLock", O_RDWR|O_CREAT, 0600 or die;
|
||||
flock(MAINLOCK, LOCK_EX) or die;
|
||||
Nix::CopyClosure::copyTo($hostName, [ @sshOpts ], [ $drvPath, @inputs ], "", "", 0, 0, $maybeSign ne "");
|
||||
close MAINLOCK;
|
||||
|
||||
|
||||
# Perform the build.
|
||||
@@ -239,7 +249,7 @@ my $buildFlags = "--max-silent-time $maxSilentTime --fallback --add-root $rootsD
|
||||
# in which case every child receives SIGHUP; however, `-tt' doesn't
|
||||
# work on some platforms when connection sharing is used.)
|
||||
pipe STDIN, DUMMY; # make sure we have a readable STDIN
|
||||
if (system("ssh $hostName @sshOpts '(read; kill -INT -\$\$) <&0 & nix-store -r $drvPath $buildFlags > /dev/null' 2>&4") != 0) {
|
||||
if (system("exec ssh $hostName @sshOpts '(read; kill -INT -\$\$) <&0 & nix-store -r $drvPath $buildFlags > /dev/null' 2>&4") != 0) {
|
||||
# Note that if we get exit code 100 from `nix-store -r', it
|
||||
# denotes a permanent build failure (as opposed to an SSH problem
|
||||
# or a temporary Nix problem). We propagate this to the caller to
|
||||
@@ -259,7 +269,7 @@ foreach my $output (@outputs) {
|
||||
my $maybeSignRemote = "";
|
||||
$maybeSignRemote = "--sign" if $UID != 0;
|
||||
|
||||
system("ssh $hostName @sshOpts 'nix-store --export $maybeSignRemote $output'" .
|
||||
system("exec ssh $hostName @sshOpts 'nix-store --export $maybeSignRemote $output'" .
|
||||
"| NIX_HELD_LOCKS=$output @bindir@/nix-store --import > /dev/null") == 0
|
||||
or die "cannot copy $output from $hostName: $?";
|
||||
}
|
||||
|
||||
0
scripts/copy-from-other-stores.pl.in
Normal file → Executable file
0
scripts/copy-from-other-stores.pl.in
Normal file → Executable file
162
scripts/download-using-manifests.pl.in
Normal file → Executable file
162
scripts/download-using-manifests.pl.in
Normal file → Executable file
@@ -1,48 +1,27 @@
|
||||
#! @perl@ -w -I@libexecdir@/nix
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use strict;
|
||||
use NixManifest;
|
||||
use Nix::Config;
|
||||
use Nix::Manifest;
|
||||
use Nix::Store;
|
||||
use POSIX qw(strftime);
|
||||
use File::Temp qw(tempdir);
|
||||
|
||||
my $binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
|
||||
|
||||
STDOUT->autoflush(1);
|
||||
|
||||
my $manifestDir = ($ENV{"NIX_MANIFESTS_DIR"} or "@localstatedir@/nix/manifests");
|
||||
my $logFile = "@localstatedir@/log/nix/downloads";
|
||||
my $logFile = "$Nix::Config::logDir/downloads";
|
||||
|
||||
# For queries, skip expensive calls to nix-hash etc. We're just
|
||||
# estimating the expected download size.
|
||||
my $fast = 1;
|
||||
|
||||
|
||||
# Load all manifests.
|
||||
my %narFiles;
|
||||
my %localPaths;
|
||||
my %patches;
|
||||
|
||||
for my $manifest (glob "$manifestDir/*.nixmanifest") {
|
||||
my $version = readManifest($manifest, \%narFiles, \%localPaths, \%patches);
|
||||
if ($version < 3) {
|
||||
print STDERR "you have an old-style manifest `$manifest'; please delete it\n";
|
||||
exit 1;
|
||||
}
|
||||
if ($version >= 10) {
|
||||
print STDERR "manifest `$manifest' is too new; please delete it or upgrade Nix\n";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
# Open the manifest cache and update it if necessary.
|
||||
my $dbh = updateManifestDB();
|
||||
|
||||
|
||||
sub isValidPath {
|
||||
my $p = shift;
|
||||
if ($fast) {
|
||||
return -e $p;
|
||||
} else {
|
||||
return system("$binDir/nix-store --check-validity '$p' 2> /dev/null") == 0;
|
||||
}
|
||||
}
|
||||
# $hashCache->{$algo}->{$path} yields the $algo-hash of $path.
|
||||
my $hashCache;
|
||||
|
||||
|
||||
sub parseHash {
|
||||
@@ -111,18 +90,23 @@ sub computeSmallestDownload {
|
||||
else {
|
||||
|
||||
# Add patch edges.
|
||||
my $patchList = $patches{$u};
|
||||
my $patchList = $dbh->selectall_arrayref(
|
||||
"select * from Patches where storePath = ?",
|
||||
{ Slice => {} }, $u);
|
||||
|
||||
foreach my $patch (@{$patchList}) {
|
||||
if (isValidPath($patch->{basePath})) {
|
||||
# !!! this should be cached
|
||||
my ($baseHashAlgo, $baseHash) = parseHash $patch->{baseHash};
|
||||
my $format = "--base32";
|
||||
$format = "" if $baseHashAlgo eq "md5";
|
||||
my $hash = $fast && $baseHashAlgo eq "sha256"
|
||||
? `$binDir/nix-store -q --hash "$patch->{basePath}"`
|
||||
: `$binDir/nix-hash --type '$baseHashAlgo' $format "$patch->{basePath}"`;
|
||||
chomp $hash;
|
||||
$hash =~ s/.*://;
|
||||
|
||||
my $hash = $hashCache->{$baseHashAlgo}->{$patch->{basePath}};
|
||||
if (!defined $hash) {
|
||||
$hash = $fast && $baseHashAlgo eq "sha256"
|
||||
? queryPathHash($patch->{basePath})
|
||||
: hashPath($baseHashAlgo, $baseHashAlgo ne "md5", $patch->{basePath});
|
||||
$hash =~ s/.*://;
|
||||
$hashCache->{$baseHashAlgo}->{$patch->{basePath}} = $hash;
|
||||
}
|
||||
|
||||
next if $hash ne $baseHash;
|
||||
}
|
||||
push @queue, $patch->{basePath};
|
||||
@@ -130,11 +114,15 @@ sub computeSmallestDownload {
|
||||
}
|
||||
|
||||
# Add NAR file edges to the start node.
|
||||
my $narFileList = $narFiles{$u};
|
||||
my $narFileList = $dbh->selectall_arrayref(
|
||||
"select * from NARs where storePath = ?",
|
||||
{ Slice => {} }, $u);
|
||||
|
||||
foreach my $narFile (@{$narFileList}) {
|
||||
# !!! how to handle files whose size is not known in advance?
|
||||
# For now, assume some arbitrary size (1 MB).
|
||||
addEdge \%graph, "start", $u, ($narFile->{size} || 1000000), "narfile", $narFile;
|
||||
# For now, assume some arbitrary size (1 GB).
|
||||
# This has the side-effect of preferring non-Hydra downloads.
|
||||
addEdge \%graph, "start", $u, ($narFile->{size} || 1000000000), "narfile", $narFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -161,7 +149,7 @@ sub computeSmallestDownload {
|
||||
$v_->{d} = $u_->{d} + $edge->{weight};
|
||||
# Store the edge; to edge->start is actually the
|
||||
# predecessor.
|
||||
$v_->{pred} = $edge;
|
||||
$v_->{pred} = $edge;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -189,19 +177,21 @@ if ($ARGV[0] eq "--query") {
|
||||
|
||||
if ($cmd eq "have") {
|
||||
my $storePath = <STDIN>; chomp $storePath;
|
||||
print STDOUT ((defined $narFiles{$storePath} or defined $localPaths{$storePath})
|
||||
print STDOUT (
|
||||
scalar @{$dbh->selectcol_arrayref("select 1 from NARs where storePath = ?", {}, $storePath)} > 0
|
||||
? "1\n" : "0\n");
|
||||
}
|
||||
|
||||
elsif ($cmd eq "info") {
|
||||
my $storePath = <STDIN>; chomp $storePath;
|
||||
|
||||
my $infos = $dbh->selectall_arrayref(
|
||||
"select * from NARs where storePath = ?",
|
||||
{ Slice => {} }, $storePath);
|
||||
|
||||
my $info;
|
||||
if (defined $narFiles{$storePath}) {
|
||||
$info = @{$narFiles{$storePath}}[0];
|
||||
}
|
||||
elsif (defined $localPaths{$storePath}) {
|
||||
$info = @{$localPaths{$storePath}}[0];
|
||||
if (scalar @{$infos} > 0) {
|
||||
$info = @{$infos}[0];
|
||||
}
|
||||
else {
|
||||
print "0\n";
|
||||
@@ -210,12 +200,12 @@ if ($ARGV[0] eq "--query") {
|
||||
|
||||
print "1\n";
|
||||
print "$info->{deriver}\n";
|
||||
my @references = split " ", $info->{references};
|
||||
my @references = split " ", $info->{refs};
|
||||
print scalar @references, "\n";
|
||||
print "$_\n" foreach @references;
|
||||
|
||||
my @path = computeSmallestDownload $storePath;
|
||||
|
||||
|
||||
my $downloadSize = 0;
|
||||
while (scalar @path > 0) {
|
||||
my $edge = pop @path;
|
||||
@@ -228,7 +218,7 @@ if ($ARGV[0] eq "--query") {
|
||||
$downloadSize += $edge->{info}->{size} || 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
print "$downloadSize\n";
|
||||
|
||||
my $narSize = $info->{narSize} || 0;
|
||||
@@ -264,20 +254,7 @@ open LOGFILE, ">>$logFile" or die "cannot open log file $logFile";
|
||||
my $date = strftime ("%F %H:%M:%S UTC", gmtime (time));
|
||||
print LOGFILE "$$ get $targetPath $date\n";
|
||||
|
||||
print "\n*** Trying to download/patch `$targetPath'\n";
|
||||
|
||||
|
||||
# If we can copy from a local path, do that.
|
||||
my $localPathList = $localPaths{$targetPath};
|
||||
foreach my $localPath (@{$localPathList}) {
|
||||
my $sourcePath = $localPath->{copyFrom};
|
||||
if (-e $sourcePath) {
|
||||
print "\n*** Step 1/1: copying from $sourcePath\n";
|
||||
system("$binDir/nix-store --dump $sourcePath | $binDir/nix-store --restore $targetPath") == 0
|
||||
or die "cannot copy `$sourcePath' to `$targetPath'";
|
||||
exit 0;
|
||||
}
|
||||
}
|
||||
print STDERR "\n*** Trying to download/patch `$targetPath'\n";
|
||||
|
||||
|
||||
# Compute the shortest path.
|
||||
@@ -285,6 +262,12 @@ my @path = computeSmallestDownload $targetPath;
|
||||
die "don't know how to produce $targetPath\n" if scalar @path == 0;
|
||||
|
||||
|
||||
# We don't need the manifest anymore, so close it as an optimisation:
|
||||
# if we still have SQLite locks blocking other processes (we
|
||||
# shouldn't), this gets rid of them.
|
||||
$dbh->disconnect;
|
||||
|
||||
|
||||
# Traverse the shortest path, perform the actions described by the
|
||||
# edges.
|
||||
my $curStep = 1;
|
||||
@@ -294,8 +277,8 @@ sub downloadFile {
|
||||
my $url = shift;
|
||||
$ENV{"PRINT_PATH"} = 1;
|
||||
$ENV{"QUIET"} = 1;
|
||||
my ($hash, $path) = `$binDir/nix-prefetch-url '$url'`;
|
||||
die "download of `$url' failed" unless $? == 0;
|
||||
my ($hash, $path) = `$Nix::Config::binDir/nix-prefetch-url '$url'`;
|
||||
die "download of `$url' failed" . ($! ? ": $!" : "") . "\n" unless $? == 0;
|
||||
chomp $path;
|
||||
return $path;
|
||||
}
|
||||
@@ -307,36 +290,36 @@ while (scalar @path > 0) {
|
||||
my $u = $edge->{start};
|
||||
my $v = $edge->{end};
|
||||
|
||||
print "\n*** Step $curStep/$maxStep: ";
|
||||
print STDERR "\n*** Step $curStep/$maxStep: ";
|
||||
|
||||
if ($edge->{type} eq "present") {
|
||||
print "using already present path `$v'\n";
|
||||
print STDERR "using already present path `$v'\n";
|
||||
print LOGFILE "$$ present $v\n";
|
||||
|
||||
if ($curStep < $maxStep) {
|
||||
# Since this is not the last step, the path will be used
|
||||
# as a base to one or more patches. So turn the base path
|
||||
# into a NAR archive, to which we can apply the patch.
|
||||
print " packing base path...\n";
|
||||
system("$binDir/nix-store --dump $v > $tmpNar") == 0
|
||||
print STDERR " packing base path...\n";
|
||||
system("$Nix::Config::binDir/nix-store --dump $v > $tmpNar") == 0
|
||||
or die "cannot dump `$v'";
|
||||
}
|
||||
}
|
||||
|
||||
elsif ($edge->{type} eq "patch") {
|
||||
my $patch = $edge->{info};
|
||||
print "applying patch `$patch->{url}' to `$u' to create `$v'\n";
|
||||
print STDERR "applying patch `$patch->{url}' to `$u' to create `$v'\n";
|
||||
|
||||
print LOGFILE "$$ patch $patch->{url} $patch->{size} $patch->{baseHash} $u $v\n";
|
||||
|
||||
# Download the patch.
|
||||
print " downloading patch...\n";
|
||||
print STDERR " downloading patch...\n";
|
||||
my $patchPath = downloadFile "$patch->{url}";
|
||||
|
||||
# Apply the patch to the NAR archive produced in step 1 (for
|
||||
# the already present path) or a later step (for patch sequences).
|
||||
print " applying patch...\n";
|
||||
system("@libexecdir@/bspatch $tmpNar $tmpNar2 $patchPath") == 0
|
||||
print STDERR " applying patch...\n";
|
||||
system("$Nix::Config::libexecDir/bspatch $tmpNar $tmpNar2 $patchPath") == 0
|
||||
or die "cannot apply patch `$patchPath' to $tmpNar";
|
||||
|
||||
if ($curStep < $maxStep) {
|
||||
@@ -345,8 +328,8 @@ while (scalar @path > 0) {
|
||||
} else {
|
||||
# This was the last patch. Unpack the final NAR archive
|
||||
# into the target path.
|
||||
print " unpacking patched archive...\n";
|
||||
system("$binDir/nix-store --restore $v < $tmpNar2") == 0
|
||||
print STDERR " unpacking patched archive...\n";
|
||||
system("$Nix::Config::binDir/nix-store --restore $v < $tmpNar2") == 0
|
||||
or die "cannot unpack $tmpNar2 into `$v'";
|
||||
}
|
||||
|
||||
@@ -355,23 +338,23 @@ while (scalar @path > 0) {
|
||||
|
||||
elsif ($edge->{type} eq "narfile") {
|
||||
my $narFile = $edge->{info};
|
||||
print "downloading `$narFile->{url}' into `$v'\n";
|
||||
print STDERR "downloading `$narFile->{url}' into `$v'\n";
|
||||
|
||||
my $size = $narFile->{size} || -1;
|
||||
print LOGFILE "$$ narfile $narFile->{url} $size $v\n";
|
||||
|
||||
# Download the archive.
|
||||
print " downloading archive...\n";
|
||||
print STDERR " downloading archive...\n";
|
||||
my $narFilePath = downloadFile "$narFile->{url}";
|
||||
|
||||
if ($curStep < $maxStep) {
|
||||
# The archive will be used a base to a patch.
|
||||
system("@bunzip2@ < '$narFilePath' > $tmpNar") == 0
|
||||
system("$Nix::Config::bzip2 -d < '$narFilePath' > $tmpNar") == 0
|
||||
or die "cannot unpack `$narFilePath' into `$v'";
|
||||
} else {
|
||||
# Unpack the archive into the target path.
|
||||
print " unpacking archive...\n";
|
||||
system("@bunzip2@ < '$narFilePath' | $binDir/nix-store --restore '$v'") == 0
|
||||
print STDERR " unpacking archive...\n";
|
||||
system("$Nix::Config::bzip2 -d < '$narFilePath' | $Nix::Config::binDir/nix-store --restore '$v'") == 0
|
||||
or die "cannot unpack `$narFilePath' into `$v'";
|
||||
}
|
||||
|
||||
@@ -390,20 +373,15 @@ if (defined $finalNarHash) {
|
||||
|
||||
# The hash in the manifest can be either in base-16 or base-32.
|
||||
# Handle both.
|
||||
my $extraFlag =
|
||||
($hashAlgo eq "sha256" && length($hash) != 64)
|
||||
? "--base32" : "";
|
||||
my $hash2 = hashPath($hashAlgo, $hashAlgo eq "sha256" && length($hash) != 64, $targetPath);
|
||||
|
||||
my $hash2 = `@bindir@/nix-hash --type $hashAlgo $extraFlag $targetPath`
|
||||
or die "cannot compute hash of path `$targetPath'";
|
||||
chomp $hash2;
|
||||
|
||||
die "hash mismatch in downloaded path $targetPath; expected $hash, got $hash2"
|
||||
die "hash mismatch in downloaded path $targetPath; expected $hash, got $hash2\n"
|
||||
if $hash ne $hash2;
|
||||
} else {
|
||||
die "cannot check integrity of the downloaded path since its hash is not known";
|
||||
die "cannot check integrity of the downloaded path since its hash is not known\n";
|
||||
}
|
||||
|
||||
|
||||
print STDERR "\n";
|
||||
print LOGFILE "$$ success\n";
|
||||
close LOGFILE;
|
||||
|
||||
0
scripts/find-runtime-roots.pl.in
Normal file → Executable file
0
scripts/find-runtime-roots.pl.in
Normal file → Executable file
@@ -1,2 +1,2 @@
|
||||
./gc-releases.pl /data/webserver/dist/*/*/MANIFEST > dead
|
||||
cat dead | xargs mv --target-directory=/data/webserver/trash/
|
||||
./gc-releases.pl /data/releases/patches/all-patches $(find /data/releases -name MANIFEST) | sort > dead
|
||||
cat dead | xargs -d '\n' sh -c 'find "$@" -mtime +100 -print' | xargs -d '\n' mv -v --target-directory=/data/releases/trash/
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#! /usr/bin/perl -w -I. -I..
|
||||
#! /var/run/current-system/sw/bin/perl -w -I. -I..
|
||||
|
||||
use strict;
|
||||
use readmanifest;
|
||||
use NixManifest;
|
||||
use readcache;
|
||||
use File::Basename;
|
||||
|
||||
|
||||
# Read the manifests.
|
||||
my %narFiles;
|
||||
my %localPaths;
|
||||
my %patches;
|
||||
|
||||
foreach my $manifest (@ARGV) {
|
||||
print STDERR "loading $manifest\n";
|
||||
if (readManifest($manifest, \%narFiles, \%localPaths, \%patches, 1) < 3) {
|
||||
if (readManifest($manifest, \%narFiles, \%patches, 1) < 3) {
|
||||
# die "manifest `$manifest' is too old (i.e., for Nix <= 0.7)\n";
|
||||
}
|
||||
}
|
||||
@@ -50,6 +50,9 @@ foreach my $patch (keys %patches) {
|
||||
foreach my $archive (keys %readcache::archives) {
|
||||
next if $archive eq "." || $archive eq "..";
|
||||
if (!defined $usedFiles{$archive}) {
|
||||
print $readcache::archives{$archive}, "\n";
|
||||
my $file = $readcache::archives{$archive};
|
||||
print "$file\n";
|
||||
my $hashFile = dirname($file) . "/.hash." . basename($file);
|
||||
print "$hashFile\n" if -e $hashFile;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,13 +9,13 @@ sub readDir {
|
||||
opendir(DIR, "$dir") or die "cannot open `$dir': $!";
|
||||
my @as = readdir DIR;
|
||||
foreach my $archive (@as) {
|
||||
next unless $archive =~ /^sha256_/ || $archive =~ /\.nar-bsdiff$/ || $archive =~ /\.nar\.bz2$/;
|
||||
$archives{$archive} = "$dir/$archive";
|
||||
}
|
||||
closedir DIR;
|
||||
}
|
||||
|
||||
readDir "/data/webserver/dist/nix-cache";
|
||||
readDir "/data/webserver/dist/test-cache";
|
||||
readDir "/data/webserver/dist/patches";
|
||||
readDir "/data/releases/nars";
|
||||
readDir "/data/releases/patches";
|
||||
|
||||
print STDERR scalar (keys %archives), "\n";
|
||||
|
||||
11
scripts/nix-build.in
Normal file → Executable file
11
scripts/nix-build.in
Normal file → Executable file
@@ -1,8 +1,7 @@
|
||||
#! @perl@ -w -I@libexecdir@/nix
|
||||
|
||||
use strict;
|
||||
|
||||
my $binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
|
||||
use Nix::Config;
|
||||
|
||||
|
||||
my $addDrvLink = 0;
|
||||
@@ -76,10 +75,10 @@ EOF
|
||||
$outLink = $ARGV[$n];
|
||||
}
|
||||
|
||||
elsif ($arg eq "--attr" or $arg eq "-A") {
|
||||
elsif ($arg eq "--attr" or $arg eq "-A" or $arg eq "-I") {
|
||||
$n++;
|
||||
die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV;
|
||||
push @instArgs, ("--attr", $ARGV[$n]);
|
||||
push @instArgs, ($arg, $ARGV[$n]);
|
||||
}
|
||||
|
||||
elsif ($arg eq "--arg" || $arg eq "--argstr") {
|
||||
@@ -156,7 +155,7 @@ foreach my $expr (@exprs) {
|
||||
# Instantiate.
|
||||
my @drvPaths;
|
||||
# !!! would prefer the perl 5.8.0 pipe open feature here.
|
||||
my $pid = open(DRVPATHS, "-|") || exec "$binDir/nix-instantiate", "--add-root", $drvLink, "--indirect", @instArgs, $expr;
|
||||
my $pid = open(DRVPATHS, "-|") || exec "$Nix::Config::binDir/nix-instantiate", "--add-root", $drvLink, "--indirect", @instArgs, $expr;
|
||||
while (<DRVPATHS>) {chomp; push @drvPaths, $_;}
|
||||
if (!close DRVPATHS) {
|
||||
die "nix-instantiate killed by signal " . ($? & 127) . "\n" if ($? & 127);
|
||||
@@ -170,7 +169,7 @@ foreach my $expr (@exprs) {
|
||||
|
||||
# Build.
|
||||
my @outPaths;
|
||||
$pid = open(OUTPATHS, "-|") || exec "$binDir/nix-store", "--add-root", $outLink, "--indirect", "-r",
|
||||
$pid = open(OUTPATHS, "-|") || exec "$Nix::Config::binDir/nix-store", "--add-root", $outLink, "--indirect", "-r",
|
||||
@buildArgs, @drvPaths;
|
||||
while (<OUTPATHS>) {chomp; push @outPaths, $_;}
|
||||
if (!close OUTPATHS) {
|
||||
|
||||
22
scripts/nix-channel.in
Normal file → Executable file
22
scripts/nix-channel.in
Normal file → Executable file
@@ -1,15 +1,13 @@
|
||||
#! @perl@ -w
|
||||
|
||||
use strict;
|
||||
use Nix::Config;
|
||||
|
||||
my $rootsDir = "@localstatedir@/nix/gcroots";
|
||||
|
||||
my $stateDir = $ENV{"NIX_STATE_DIR"};
|
||||
$stateDir = "@localstatedir@/nix" unless defined $stateDir;
|
||||
my $manifestDir = $Nix::Config::manifestDir;
|
||||
|
||||
|
||||
# Turn on caching in nix-prefetch-url.
|
||||
my $channelCache = "$stateDir/channel-cache";
|
||||
my $channelCache = "$Nix::Config::stateDir/channel-cache";
|
||||
mkdir $channelCache, 0755 unless -e $channelCache;
|
||||
$ENV{'NIX_DOWNLOAD_CACHE'} = $channelCache if -W $channelCache;
|
||||
|
||||
@@ -79,19 +77,19 @@ sub update {
|
||||
readChannels;
|
||||
|
||||
# Create the manifests directory if it doesn't exist.
|
||||
mkdir "$stateDir/manifests", 0755 unless -e "$stateDir/manifests";
|
||||
mkdir $manifestDir, 0755 unless -e $manifestDir;
|
||||
|
||||
# Do we have write permission to the manifests directory? If not,
|
||||
# then just skip pulling the manifest and just download the Nix
|
||||
# expressions. If the user is a non-privileged user in a
|
||||
# multi-user Nix installation, he at least gets installation from
|
||||
# source.
|
||||
if (-W "$stateDir/manifests") {
|
||||
if (-W $manifestDir) {
|
||||
|
||||
# Pull cache manifests.
|
||||
foreach my $url (@channels) {
|
||||
#print "pulling cache manifest from `$url'\n";
|
||||
system("@bindir@/nix-pull", "--skip-wrong-store", "$url/MANIFEST") == 0
|
||||
system("$Nix::Config::binDir/nix-pull", "--skip-wrong-store", "$url/MANIFEST") == 0
|
||||
or die "cannot pull cache manifest from `$url'";
|
||||
}
|
||||
|
||||
@@ -110,7 +108,7 @@ sub update {
|
||||
print "downloading Nix expressions from `$fullURL'...\n";
|
||||
$ENV{"PRINT_PATH"} = 1;
|
||||
$ENV{"QUIET"} = 1;
|
||||
my ($hash, $path) = `@bindir@/nix-prefetch-url '$fullURL'`;
|
||||
my ($hash, $path) = `$Nix::Config::binDir/nix-prefetch-url '$fullURL'`;
|
||||
die "cannot fetch `$fullURL'" if $? != 0;
|
||||
chomp $path;
|
||||
$inputs .= '"' . $channelName . '"' . " " . $path . " ";
|
||||
@@ -121,13 +119,13 @@ sub update {
|
||||
my $userName = getpwuid($<);
|
||||
die "who ARE you? go away" unless defined $userName;
|
||||
|
||||
my $rootFile = "$rootsDir/per-user/$userName/channels";
|
||||
my $rootFile = "$Nix::Config::stateDir/gcroots/per-user/$userName/channels";
|
||||
|
||||
# Build the Nix expression.
|
||||
print "unpacking channel Nix expressions...\n";
|
||||
my $outPath = `\\
|
||||
@bindir@/nix-build --out-link '$rootFile' --drv-link '$rootFile'.tmp \\
|
||||
@datadir@/nix/corepkgs/channels/unpack.nix \\
|
||||
$Nix::Config::binDir/nix-build --out-link '$rootFile' --drv-link '$rootFile'.tmp \\
|
||||
'<nix/unpack-channel.nix>' \\
|
||||
--argstr system @system@ --arg inputs '$inputs'`
|
||||
or die "cannot unpack the channels";
|
||||
chomp $outPath;
|
||||
|
||||
7
scripts/nix-collect-garbage.in
Normal file → Executable file
7
scripts/nix-collect-garbage.in
Normal file → Executable file
@@ -1,11 +1,10 @@
|
||||
#! @perl@ -w
|
||||
|
||||
use strict;
|
||||
use Nix::Config;
|
||||
|
||||
my $profilesDir = "@localstatedir@/nix/profiles";
|
||||
|
||||
my $binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
|
||||
|
||||
|
||||
# Process the command line arguments.
|
||||
my @args = ();
|
||||
@@ -36,7 +35,7 @@ sub removeOldGenerations {
|
||||
$name = $dir . "/" . $name;
|
||||
if (-l $name && (readlink($name) =~ /link/)) {
|
||||
print STDERR "removing old generations of profile $name\n";
|
||||
system("$binDir/nix-env", "-p", $name, "--delete-generations", "old");
|
||||
system("$Nix::Config::binDir/nix-env", "-p", $name, "--delete-generations", "old");
|
||||
}
|
||||
elsif (! -l $name && -d $name) {
|
||||
removeOldGenerations $name;
|
||||
@@ -50,4 +49,4 @@ removeOldGenerations $profilesDir if $removeOld;
|
||||
|
||||
|
||||
# Run the actual garbage collector.
|
||||
exec "$binDir/nix-store", "--gc", @args;
|
||||
exec "$Nix::Config::binDir/nix-store", "--gc", @args;
|
||||
|
||||
105
scripts/nix-copy-closure.in
Normal file → Executable file
105
scripts/nix-copy-closure.in
Normal file → Executable file
@@ -1,13 +1,14 @@
|
||||
#! @perl@ -w -I@libexecdir@/nix
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use SSH;
|
||||
|
||||
my $binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
|
||||
use Nix::SSH;
|
||||
use Nix::Config;
|
||||
use Nix::Store;
|
||||
use Nix::CopyClosure;
|
||||
|
||||
|
||||
if (scalar @ARGV < 1) {
|
||||
print STDERR <<EOF
|
||||
Usage: nix-copy-closure [--from | --to] HOSTNAME [--sign] [--gzip] PATHS...
|
||||
Usage: nix-copy-closure [--from | --to] HOSTNAME [--sign] [--gzip] [--bzip2] [--xz] PATHS...
|
||||
EOF
|
||||
;
|
||||
exit 1;
|
||||
@@ -24,6 +25,10 @@ my $decompressor = "";
|
||||
|
||||
my $toMode = 1;
|
||||
|
||||
my $includeOutputs = 0;
|
||||
|
||||
my $dryRun = 0;
|
||||
|
||||
|
||||
# !!! Copied from nix-pack-closure, should put this in a module.
|
||||
my @storePaths = ();
|
||||
@@ -35,8 +40,16 @@ while (@ARGV) {
|
||||
$sign = 1;
|
||||
}
|
||||
elsif ($arg eq "--gzip") {
|
||||
$compressor = "| gzip";
|
||||
$decompressor = "gunzip |";
|
||||
$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;
|
||||
@@ -44,6 +57,12 @@ while (@ARGV) {
|
||||
elsif ($arg eq "--to") {
|
||||
$toMode = 1;
|
||||
}
|
||||
elsif ($arg eq "--include-outputs") {
|
||||
$includeOutputs = 1;
|
||||
}
|
||||
elsif ($arg eq "--dry-run") {
|
||||
$dryRun = 1;
|
||||
}
|
||||
elsif (!defined $sshHost) {
|
||||
$sshHost = $arg;
|
||||
}
|
||||
@@ -57,81 +76,37 @@ openSSHConnection $sshHost or die "$0: unable to start SSH\n";
|
||||
|
||||
|
||||
if ($toMode) { # Copy TO the remote machine.
|
||||
|
||||
my @allStorePaths;
|
||||
|
||||
# Get the closure of this path.
|
||||
my $pid = open(READ, "set -f; $binDir/nix-store --query --requisites @storePaths|") or die;
|
||||
|
||||
while (<READ>) {
|
||||
chomp;
|
||||
die "bad: $_" unless /^\//;
|
||||
push @allStorePaths, $_;
|
||||
}
|
||||
|
||||
close READ or die "nix-store failed: $?";
|
||||
|
||||
|
||||
# Ask the remote host which paths are invalid.
|
||||
open(READ, "set -f; ssh $sshHost @sshOpts nix-store --check-validity --print-invalid @allStorePaths|");
|
||||
my @missing = ();
|
||||
while (<READ>) {
|
||||
chomp;
|
||||
push @missing, $_;
|
||||
}
|
||||
close READ or die;
|
||||
|
||||
|
||||
# Export the store paths and import them on the remote machine.
|
||||
if (scalar @missing > 0) {
|
||||
print STDERR "copying these missing paths:\n";
|
||||
print STDERR " $_\n" foreach @missing;
|
||||
my $extraOpts = "";
|
||||
$extraOpts .= "--sign" if $sign == 1;
|
||||
system("set -f; nix-store --export $extraOpts @missing $compressor | ssh $sshHost @sshOpts '$decompressor nix-store --import'") == 0
|
||||
or die "copying store paths to remote machine `$sshHost' failed: $?";
|
||||
}
|
||||
|
||||
Nix::CopyClosure::copyTo($sshHost, [ @sshOpts ], [ @storePaths ], $compressor, $decompressor, $includeOutputs, $dryRun, $sign);
|
||||
}
|
||||
|
||||
|
||||
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 @storePaths|") or die;
|
||||
"set -f; ssh @sshOpts $sshHost nix-store --query --requisites $extraOpts @storePaths|") or die;
|
||||
|
||||
my @allStorePaths;
|
||||
|
||||
while (<READ>) {
|
||||
chomp;
|
||||
die "bad: $_" unless /^\//;
|
||||
push @allStorePaths, $_;
|
||||
push @missing, $_ unless isValidPath($_);
|
||||
}
|
||||
|
||||
close READ or die "nix-store on remote machine `$sshHost' failed: $?";
|
||||
|
||||
|
||||
# What paths are already valid locally?
|
||||
open(READ, "set -f; @bindir@/nix-store --check-validity --print-invalid @allStorePaths|");
|
||||
my @missing = ();
|
||||
while (<READ>) {
|
||||
chomp;
|
||||
push @missing, $_;
|
||||
}
|
||||
close READ or die;
|
||||
|
||||
|
||||
# Export the store paths on the remote machine and import them on locally.
|
||||
# Export the store paths on the remote machine and import them locally.
|
||||
if (scalar @missing > 0) {
|
||||
print STDERR "copying these missing paths:\n";
|
||||
print STDERR " $_\n" foreach @missing;
|
||||
my $extraOpts = "";
|
||||
$extraOpts .= "--sign" if $sign == 1;
|
||||
system("set -f; ssh $sshHost @sshOpts 'nix-store --export $extraOpts @missing $compressor' | $decompressor @bindir@/nix-store --import") == 0
|
||||
or die "copying store paths from remote machine `$sshHost' failed: $?";
|
||||
print STDERR "copying ", scalar @missing, " missing paths from ‘$sshHost’...\n";
|
||||
#print STDERR " $_\n" foreach @missing;
|
||||
$compressor = "| $compressor" if $compressor ne "";
|
||||
$decompressor = "$decompressor |" if $decompressor ne "";
|
||||
unless ($dryRun) {
|
||||
my $extraOpts = $sign ? "--sign" : "";
|
||||
system("set -f; ssh $sshHost @sshOpts 'nix-store --export $extraOpts @missing $compressor' | $decompressor $Nix::Config::binDir/nix-store --import") == 0
|
||||
or die "copying store paths from remote machine `$sshHost' failed: $?";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
10
scripts/nix-generate-patches.in
Normal file → Executable file
10
scripts/nix-generate-patches.in
Normal file → Executable file
@@ -1,9 +1,9 @@
|
||||
#! @perl@ -w -I@libexecdir@/nix
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use strict;
|
||||
use File::Temp qw(tempdir);
|
||||
use NixManifest;
|
||||
use GeneratePatches;
|
||||
use Nix::Manifest;
|
||||
use Nix::GeneratePatches;
|
||||
|
||||
if (scalar @ARGV != 5) {
|
||||
print STDERR <<EOF;
|
||||
@@ -26,10 +26,10 @@ my $srcManifest = $ARGV[3];
|
||||
my $dstManifest = $ARGV[4];
|
||||
|
||||
my (%srcNarFiles, %srcLocalPaths, %srcPatches);
|
||||
readManifest $srcManifest, \%srcNarFiles, \%srcLocalPaths, \%srcPatches;
|
||||
readManifest $srcManifest, \%srcNarFiles, \%srcPatches;
|
||||
|
||||
my (%dstNarFiles, %dstLocalPaths, %dstPatches);
|
||||
readManifest $dstManifest, \%dstNarFiles, \%dstLocalPaths, \%dstPatches;
|
||||
readManifest $dstManifest, \%dstNarFiles, \%dstPatches;
|
||||
|
||||
my $tmpDir = tempdir("nix-generate-patches.XXXXXX", CLEANUP => 1, TMPDIR => 1)
|
||||
or die "cannot create a temporary directory";
|
||||
|
||||
14
scripts/nix-install-package.in
Normal file → Executable file
14
scripts/nix-install-package.in
Normal file → Executable file
@@ -2,8 +2,7 @@
|
||||
|
||||
use strict;
|
||||
use File::Temp qw(tempdir);
|
||||
|
||||
my $binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
|
||||
use Nix::Config;
|
||||
|
||||
|
||||
sub usageError {
|
||||
@@ -61,7 +60,7 @@ if ($interactive && !defined $ENV{"NIX_HAVE_TERMINAL"}) {
|
||||
$ENV{"NIX_HAVE_TERMINAL"} = "1";
|
||||
$ENV{"LD_LIBRARY_PATH"} = "";
|
||||
foreach my $term ("xterm", "konsole", "gnome-terminal", "xterm") {
|
||||
exec($term, "-e", "$binDir/nix-install-package", @ARGV);
|
||||
exec($term, "-e", "$Nix::Config::binDir/nix-install-package", @ARGV);
|
||||
}
|
||||
die "cannot execute `xterm'";
|
||||
}
|
||||
@@ -124,17 +123,20 @@ if ($interactive) {
|
||||
|
||||
|
||||
# Store the manifest in the temporary directory so that we don't
|
||||
# pollute /nix/var/nix/manifests.
|
||||
# pollute /nix/var/nix/manifests. This also requires that we don't
|
||||
# use the Nix daemon (because otherwise download-using-manifests won't
|
||||
# see our NIX_MANIFESTS_DIRS environment variable).
|
||||
$ENV{NIX_MANIFESTS_DIR} = $tmpDir;
|
||||
$ENV{NIX_REMOTE} = "";
|
||||
|
||||
|
||||
print "\nPulling manifests...\n";
|
||||
system("$binDir/nix-pull", $manifestURL) == 0
|
||||
system("$Nix::Config::binDir/nix-pull", $manifestURL) == 0
|
||||
or barf "nix-pull failed: $?";
|
||||
|
||||
|
||||
print "\nInstalling package...\n";
|
||||
system("$binDir/nix-env", "--install", $outPath, "--force-name", $drvName, @extraNixEnvArgs) == 0
|
||||
system("$Nix::Config::binDir/nix-env", "--install", $outPath, "--force-name", $drvName, @extraNixEnvArgs) == 0
|
||||
or barf "nix-env failed: $?";
|
||||
|
||||
|
||||
|
||||
226
scripts/nix-prefetch-url.in
Normal file → Executable file
226
scripts/nix-prefetch-url.in
Normal file → Executable file
@@ -1,162 +1,128 @@
|
||||
#! @shell@ -e
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
url=$1
|
||||
expHash=$2
|
||||
use strict;
|
||||
use File::Basename;
|
||||
use File::Temp qw(tempdir);
|
||||
use File::stat;
|
||||
use Nix::Store;
|
||||
use Nix::Config;
|
||||
|
||||
# needed to make it work on NixOS
|
||||
export PATH=$PATH:@coreutils@
|
||||
my $url = shift;
|
||||
my $expHash = shift;
|
||||
my $hashType = $ENV{'NIX_HASH_ALGO'} || "sha256";
|
||||
my $cacheDir = $ENV{'NIX_DOWNLOAD_CACHE'};
|
||||
|
||||
hashType=$NIX_HASH_ALGO
|
||||
if test -z "$hashType"; then
|
||||
hashType=sha256
|
||||
fi
|
||||
if (!defined $url || $url eq "") {
|
||||
print STDERR <<EOF
|
||||
Usage: nix-prefetch-url URL [EXPECTED-HASH]
|
||||
EOF
|
||||
;
|
||||
exit 1;
|
||||
}
|
||||
|
||||
hashFormat=
|
||||
if test "$hashType" != "md5"; then
|
||||
hashFormat=--base32
|
||||
fi
|
||||
sub writeFile {
|
||||
my ($fn, $s) = @_;
|
||||
open TMP, ">$fn" or die;
|
||||
print TMP "$s" or die;
|
||||
close TMP or die;
|
||||
}
|
||||
|
||||
if test -z "$url"; then
|
||||
echo "syntax: nix-prefetch-url URL [EXPECTED-HASH]" >&2
|
||||
exit 1
|
||||
fi
|
||||
sub readFile {
|
||||
local $/ = undef;
|
||||
my ($fn) = @_;
|
||||
open TMP, "<$fn" or die;
|
||||
my $s = <TMP>;
|
||||
close TMP or die;
|
||||
return $s;
|
||||
}
|
||||
|
||||
my $tmpDir = tempdir("nix-prefetch-url.XXXXXX", CLEANUP => 1, TMPDIR => 1)
|
||||
or die "cannot create a temporary directory";
|
||||
|
||||
# Hack to support the mirror:// scheme from Nixpkgs.
|
||||
if ($url =~ /^mirror:\/\//) {
|
||||
system("$Nix::Config::binDir/nix-build '<nixpkgs>' -A resolveMirrorURLs --argstr url '$url' -o $tmpDir/urls > /dev/null") == 0
|
||||
or die "$0: nix-build failed; maybe \$NIX_PATH is not set properly\n";
|
||||
my @expanded = split ' ', readFile("$tmpDir/urls");
|
||||
die "$0: cannot resolve ‘$url’" unless scalar @expanded > 0;
|
||||
print STDERR "$url expands to $expanded[0]\n";
|
||||
$url = $expanded[0];
|
||||
}
|
||||
|
||||
# Handle escaped characters in the URI. `+', `=' and `?' are the only
|
||||
# characters that are valid in Nix store path names but have a special
|
||||
# meaning in URIs.
|
||||
name=$(basename "$url" | @sed@ -e 's/%2b/+/g' -e 's/%3d/=/g' -e 's/%3f/\?/g')
|
||||
if test -z "$name"; then echo "invalid url"; exit 1; fi
|
||||
my $name = basename $url;
|
||||
die "cannot figure out file name for ‘$url’\n" if $name eq "";
|
||||
$name =~ s/%2b/+/g;
|
||||
$name =~ s/%3d/=/g;
|
||||
$name =~ s/%3f/?/g;
|
||||
|
||||
my $finalPath;
|
||||
my $hash;
|
||||
|
||||
# If the hash was given, a file with that hash may already be in the
|
||||
# store.
|
||||
if test -n "$expHash"; then
|
||||
finalPath=$(@bindir@/nix-store --print-fixed-path "$hashType" "$expHash" "$name")
|
||||
if ! @bindir@/nix-store --check-validity "$finalPath" 2> /dev/null; then
|
||||
finalPath=
|
||||
fi
|
||||
hash=$expHash
|
||||
fi
|
||||
|
||||
|
||||
mkTempDir() {
|
||||
if test -n "$tmpPath"; then return; fi
|
||||
local i=0
|
||||
while true; do
|
||||
if test -z "$TMPDIR"; then TMPDIR=/tmp; fi
|
||||
tmpPath=$TMPDIR/nix-prefetch-url-$$-$i
|
||||
if mkdir "$tmpPath"; then break; fi
|
||||
# !!! to bad we can't check for ENOENT in mkdir, so this check
|
||||
# is slightly racy (it bombs out if somebody just removed
|
||||
# $tmpPath...).
|
||||
if ! test -e "$tmpPath"; then exit 1; fi
|
||||
i=$((i + 1))
|
||||
done
|
||||
trap removeTempDir EXIT SIGINT SIGQUIT
|
||||
if (defined $expHash) {
|
||||
$finalPath = makeFixedOutputPath(0, $hashType, $expHash, $name);
|
||||
if (isValidPath($finalPath)) { $hash = $expHash; } else { $finalPath = undef; }
|
||||
}
|
||||
|
||||
removeTempDir() {
|
||||
if test -n "$tmpPath"; then
|
||||
rm -rf "$tmpPath" || true
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
doDownload() {
|
||||
@curl@ $cacheFlags --fail --location --max-redirs 20 --disable-epsv \
|
||||
--cookie-jar $tmpPath/cookies "$url" -o $tmpFile
|
||||
}
|
||||
|
||||
|
||||
# Hack to support the mirror:// scheme from Nixpkgs.
|
||||
if test "${url:0:9}" = "mirror://"; then
|
||||
if test -z "$NIXPKGS_ALL"; then
|
||||
echo "Resolving mirror:// URLs requires Nixpkgs. Please point \$NIXPKGS_ALL at a Nixpkgs tree." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkTempDir
|
||||
nix-build "$NIXPKGS_ALL" -A resolveMirrorURLs --argstr url "$url" -o $tmpPath/urls > /dev/null
|
||||
|
||||
expanded=($(cat $tmpPath/urls))
|
||||
if test "${#expanded[*]}" = 0; then
|
||||
echo "$0: cannot resolve $url." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "$url expands to ${expanded[*]} (using ${expanded[0]})" >&2
|
||||
url="${expanded[0]}"
|
||||
fi
|
||||
|
||||
|
||||
# If we don't know the hash or a file with that hash doesn't exist,
|
||||
# download the file and add it to the store.
|
||||
if test -z "$finalPath"; then
|
||||
|
||||
mkTempDir
|
||||
tmpFile=$tmpPath/$name
|
||||
if (!defined $finalPath) {
|
||||
|
||||
my $tmpFile = "$tmpDir/$name";
|
||||
|
||||
# Optionally do timestamp-based caching of the download.
|
||||
# Actually, the only thing that we cache in $NIX_DOWNLOAD_CACHE is
|
||||
# the hash and the timestamp of the file at $url. The caching of
|
||||
# the file *contents* is done in Nix store, where it can be
|
||||
# garbage-collected independently.
|
||||
if test -n "$NIX_DOWNLOAD_CACHE"; then
|
||||
echo -n "$url" > $tmpPath/url
|
||||
urlHash=$(@bindir@/nix-hash --type sha256 --base32 --flat $tmpPath/url)
|
||||
echo "$url" > "$NIX_DOWNLOAD_CACHE/$urlHash.url"
|
||||
cachedHashFN="$NIX_DOWNLOAD_CACHE/$urlHash.$hashType"
|
||||
cachedTimestampFN="$NIX_DOWNLOAD_CACHE/$urlHash.stamp"
|
||||
cacheFlags="--remote-time"
|
||||
if test -e "$cachedTimestampFN" -a -e "$cachedHashFN"; then
|
||||
# Only download the file if it is newer than the cached version.
|
||||
cacheFlags="$cacheFlags --time-cond $cachedTimestampFN"
|
||||
fi
|
||||
fi
|
||||
|
||||
my ($cachedTimestampFN, $cachedHashFN, @cacheFlags);
|
||||
if (defined $cacheDir) {
|
||||
my $urlHash = hashString("sha256", 1, $url);
|
||||
writeFile "$cacheDir/$urlHash.url", $url;
|
||||
$cachedHashFN = "$cacheDir/$urlHash.$hashType";
|
||||
$cachedTimestampFN = "$cacheDir/$urlHash.stamp";
|
||||
@cacheFlags = ("--time-cond", $cachedTimestampFN) if -f $cachedHashFN && -f $cachedTimestampFN;
|
||||
}
|
||||
|
||||
# Perform the download.
|
||||
doDownload
|
||||
my @curlFlags = ("curl", $url, "-o", $tmpFile, "--fail", "--location", "--max-redirs", "20", "--disable-epsv", "--cookie-jar", "$tmpDir/cookies", "--remote-time", (split " ", ($ENV{NIX_CURL_FLAGS} || "")));
|
||||
(system $Nix::Config::curl @curlFlags, @cacheFlags) == 0 or die "$0: download of ‘$url’ failed\n";
|
||||
|
||||
if test -n "$NIX_DOWNLOAD_CACHE" -a ! -e $tmpFile; then
|
||||
if (defined $cacheDir && ! -e $tmpFile) {
|
||||
# Curl didn't create $tmpFile, so apparently there's no newer
|
||||
# file on the server.
|
||||
hash=$(cat $cachedHashFN)
|
||||
finalPath=$(@bindir@/nix-store --print-fixed-path "$hashType" "$hash" "$name")
|
||||
if ! @bindir@/nix-store --check-validity "$finalPath" 2> /dev/null; then
|
||||
echo "cached contents of \`$url' disappeared, redownloading..." >&2
|
||||
finalPath=
|
||||
cacheFlags="--remote-time"
|
||||
doDownload
|
||||
fi
|
||||
fi
|
||||
$hash = readFile $cachedHashFN or die;
|
||||
$finalPath = makeFixedOutputPath(0, $hashType, $hash, $name);
|
||||
unless (isValidPath $finalPath) {
|
||||
print STDERR "cached contents of ‘$url’ disappeared, redownloading...\n";
|
||||
$finalPath = undef;
|
||||
(system $Nix::Config::curl @curlFlags) == 0 or die "$0: download of ‘$url’ failed\n";
|
||||
}
|
||||
}
|
||||
|
||||
if test -z "$finalPath"; then
|
||||
|
||||
# Compute the hash.
|
||||
hash=$(@bindir@/nix-hash --type "$hashType" $hashFormat --flat $tmpFile)
|
||||
if ! test -n "$QUIET"; then echo "hash is $hash" >&2; fi
|
||||
|
||||
if test -n "$NIX_DOWNLOAD_CACHE"; then
|
||||
echo $hash > $cachedHashFN
|
||||
touch -r $tmpFile $cachedTimestampFN
|
||||
fi
|
||||
|
||||
# Add the downloaded file to the Nix store.
|
||||
finalPath=$(@bindir@/nix-store --add-fixed "$hashType" $tmpFile)
|
||||
|
||||
if test -n "$expHash" -a "$expHash" != "$hash"; then
|
||||
echo "hash mismatch for URL \`$url'" >&2
|
||||
exit 1
|
||||
fi
|
||||
if (!defined $finalPath) {
|
||||
|
||||
fi
|
||||
fi
|
||||
# Compute the hash.
|
||||
$hash = hashFile($hashType, $hashType ne "md5", $tmpFile);
|
||||
|
||||
if (defined $cacheDir) {
|
||||
writeFile $cachedHashFN, $hash;
|
||||
my $st = stat($tmpFile) or die;
|
||||
open STAMP, ">$cachedTimestampFN" or die; close STAMP;
|
||||
utime($st->atime, $st->mtime, $cachedTimestampFN) or die;
|
||||
}
|
||||
|
||||
# Add the downloaded file to the Nix store.
|
||||
$finalPath = addToStore($tmpFile, 0, $hashType);
|
||||
}
|
||||
|
||||
if ! test -n "$QUIET"; then echo "path is $finalPath" >&2; fi
|
||||
die "$0: hash mismatch for ‘$url’\n" if defined $expHash && $expHash ne $hash;
|
||||
}
|
||||
|
||||
echo $hash
|
||||
|
||||
if test -n "$PRINT_PATH"; then
|
||||
echo $finalPath
|
||||
fi
|
||||
print STDERR "path is ‘$finalPath’\n" unless $ENV{'QUIET'};
|
||||
print "$hash\n";
|
||||
print "$finalPath\n" if $ENV{'PRINT_PATH'};
|
||||
|
||||
63
scripts/nix-pull.in
Normal file → Executable file
63
scripts/nix-pull.in
Normal file → Executable file
@@ -1,17 +1,14 @@
|
||||
#! @perl@ -w -I@libexecdir@/nix
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use strict;
|
||||
use File::Temp qw(tempdir);
|
||||
use NixManifest;
|
||||
use Nix::Config;
|
||||
use Nix::Manifest;
|
||||
|
||||
my $tmpDir = tempdir("nix-pull.XXXXXX", CLEANUP => 1, TMPDIR => 1)
|
||||
or die "cannot create a temporary directory";
|
||||
|
||||
my $binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
|
||||
my $libexecDir = ($ENV{"NIX_LIBEXEC_DIR"} or "@libexecdir@");
|
||||
my $storeDir = ($ENV{"NIX_STORE_DIR"} or "@storedir@");
|
||||
my $stateDir = ($ENV{"NIX_STATE_DIR"} or "@localstatedir@/nix");
|
||||
my $manifestDir = ($ENV{"NIX_MANIFESTS_DIR"} or "$stateDir/manifests");
|
||||
my $manifestDir = $Nix::Config::manifestDir;
|
||||
|
||||
|
||||
# Prevent access problems in shared-stored installations.
|
||||
@@ -24,18 +21,21 @@ if (! -e $manifestDir) {
|
||||
}
|
||||
|
||||
|
||||
# Process the URLs specified on the command line.
|
||||
my %narFiles;
|
||||
my %localPaths;
|
||||
my %patches;
|
||||
# Make sure that the manifests directory is scanned for GC roots.
|
||||
my $gcRootsDir = "$Nix::Config::stateDir/gcroots";
|
||||
my $manifestDirLink = "$gcRootsDir/manifests";
|
||||
if (! -l $manifestDirLink) {
|
||||
symlink($manifestDir, $manifestDirLink) or die "cannot create symlink `$manifestDirLink'";
|
||||
}
|
||||
|
||||
my $skipWrongStore = 0;
|
||||
|
||||
# Process the URLs specified on the command line.
|
||||
|
||||
sub downloadFile {
|
||||
my $url = shift;
|
||||
$ENV{"PRINT_PATH"} = 1;
|
||||
$ENV{"QUIET"} = 1;
|
||||
my ($dummy, $path) = `$binDir/nix-prefetch-url '$url'`;
|
||||
my ($dummy, $path) = `$Nix::Config::binDir/nix-prefetch-url '$url'`;
|
||||
die "cannot fetch `$url'" if $? != 0;
|
||||
die "nix-prefetch-url did not return a path" unless defined $path;
|
||||
chomp $path;
|
||||
@@ -50,46 +50,23 @@ sub processURL {
|
||||
my $manifest;
|
||||
|
||||
# First see if a bzipped manifest is available.
|
||||
if (system("@curl@ --fail --silent --head '$url'.bz2 > /dev/null") == 0) {
|
||||
if (system("$Nix::Config::curl --fail --silent --head '$url'.bz2 > /dev/null") == 0) {
|
||||
print "fetching list of Nix archives at `$url.bz2'...\n";
|
||||
my $bzipped = downloadFile "$url.bz2";
|
||||
|
||||
$manifest = "$tmpDir/MANIFEST";
|
||||
|
||||
system("@bunzip2@ < $bzipped > $manifest") == 0
|
||||
or die "cannot decompress manifest";
|
||||
|
||||
$manifest = (`$binDir/nix-store --add $manifest`
|
||||
or die "cannot copy $manifest to the store");
|
||||
chomp $manifest;
|
||||
$manifest = downloadFile "$url.bz2";
|
||||
}
|
||||
|
||||
# Otherwise, just get the uncompressed manifest.
|
||||
else {
|
||||
print "obtaining list of Nix archives at `$url'...\n";
|
||||
print "fetching list of Nix archives at `$url'...\n";
|
||||
$manifest = downloadFile $url;
|
||||
}
|
||||
|
||||
my $version = readManifest($manifest, \%narFiles, \%localPaths, \%patches);
|
||||
|
||||
die "`$url' is not a manifest or it is too old (i.e., for Nix <= 0.7)\n" if $version < 3;
|
||||
die "manifest `$url' is too new\n" if $version >= 5;
|
||||
|
||||
if ($skipWrongStore) {
|
||||
foreach my $path (keys %narFiles) {
|
||||
if (substr($path, 0, length($storeDir) + 1) ne "$storeDir/") {
|
||||
print STDERR "warning: manifest `$url' assumes a Nix store at a different location than $storeDir, skipping...\n";
|
||||
exit 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my $baseName = "unnamed";
|
||||
if ($url =~ /\/([^\/]+)\/[^\/]+$/) { # get the forelast component
|
||||
$baseName = $1;
|
||||
}
|
||||
|
||||
my $hash = `$binDir/nix-hash --flat '$manifest'`
|
||||
my $hash = `$Nix::Config::binDir/nix-hash --flat '$manifest'`
|
||||
or die "cannot hash `$manifest'";
|
||||
chomp $hash;
|
||||
|
||||
@@ -122,12 +99,12 @@ sub processURL {
|
||||
while (@ARGV) {
|
||||
my $url = shift @ARGV;
|
||||
if ($url eq "--skip-wrong-store") {
|
||||
$skipWrongStore = 1;
|
||||
# No-op, no longer supported.
|
||||
} else {
|
||||
processURL $url;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
my $size = scalar (keys %narFiles) + scalar (keys %localPaths);
|
||||
print "$size store paths in manifest\n";
|
||||
# Update the cache.
|
||||
updateManifestDB();
|
||||
|
||||
43
scripts/nix-push.in
Normal file → Executable file
43
scripts/nix-push.in
Normal file → Executable file
@@ -1,8 +1,10 @@
|
||||
#! @perl@ -w -I@libexecdir@/nix
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use strict;
|
||||
use File::Temp qw(tempdir);
|
||||
use NixManifest;
|
||||
use File::stat;
|
||||
use Nix::Config;
|
||||
use Nix::Manifest;
|
||||
|
||||
my $hashAlgo = "sha256";
|
||||
|
||||
@@ -12,15 +14,10 @@ my $tmpDir = tempdir("nix-push.XXXXXX", CLEANUP => 1, TMPDIR => 1)
|
||||
my $nixExpr = "$tmpDir/create-nars.nix";
|
||||
my $manifest = "$tmpDir/MANIFEST";
|
||||
|
||||
my $curl = "@curl@ --fail --silent";
|
||||
my $curl = "$Nix::Config::curl --fail --silent";
|
||||
my $extraCurlFlags = ${ENV{'CURL_FLAGS'}};
|
||||
$curl = "$curl $extraCurlFlags" if defined $extraCurlFlags;
|
||||
|
||||
my $binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
|
||||
|
||||
my $dataDir = $ENV{"NIX_DATA_DIR"};
|
||||
$dataDir = "@datadir@" unless defined $dataDir;
|
||||
|
||||
|
||||
# Parse the command line.
|
||||
my $localCopy;
|
||||
@@ -80,7 +77,7 @@ foreach my $path (@ARGV) {
|
||||
# Get all paths referenced by the normalisation of the given
|
||||
# Nix expression.
|
||||
my $pid = open(READ,
|
||||
"$binDir/nix-store --query --requisites --force-realise " .
|
||||
"$Nix::Config::binDir/nix-store --query --requisites --force-realise " .
|
||||
"--include-outputs '$path'|") or die;
|
||||
|
||||
while (<READ>) {
|
||||
@@ -105,8 +102,8 @@ foreach my $storePath (@storePaths) {
|
||||
|
||||
# Construct a Nix expression that creates a Nix archive.
|
||||
my $nixexpr =
|
||||
"((import $dataDir/nix/corepkgs/nar/nar.nix) " .
|
||||
"{storePath = builtins.storePath \"$storePath\"; system = \"@system@\"; hashAlgo = \"$hashAlgo\";}) ";
|
||||
"(import <nix/nar.nix> " .
|
||||
"{ storePath = builtins.storePath \"$storePath\"; system = \"@system@\"; hashAlgo = \"$hashAlgo\"; }) ";
|
||||
|
||||
print NIX $nixexpr;
|
||||
}
|
||||
@@ -118,7 +115,7 @@ close NIX;
|
||||
# Instantiate store derivations from the Nix expression.
|
||||
my @storeExprs;
|
||||
print STDERR "instantiating store derivations...\n";
|
||||
my $pid = open(READ, "$binDir/nix-instantiate $nixExpr|")
|
||||
my $pid = open(READ, "$Nix::Config::binDir/nix-instantiate $nixExpr|")
|
||||
or die "cannot run nix-instantiate";
|
||||
while (<READ>) {
|
||||
chomp;
|
||||
@@ -140,7 +137,7 @@ while (scalar @tmp > 0) {
|
||||
my @tmp2 = @tmp[0..$n - 1];
|
||||
@tmp = @tmp[$n..scalar @tmp - 1];
|
||||
|
||||
my $pid = open(READ, "$binDir/nix-store --realise @tmp2|")
|
||||
my $pid = open(READ, "$Nix::Config::binDir/nix-store --realise @tmp2|")
|
||||
or die "cannot run nix-store";
|
||||
while (<READ>) {
|
||||
chomp;
|
||||
@@ -178,22 +175,32 @@ for (my $n = 0; $n < scalar @storePaths; $n++) {
|
||||
(-f $narFile) or die "narfile for $storePath not found";
|
||||
push @narArchives, $narFile;
|
||||
|
||||
my $narbz2Size = (stat $narFile)[7];
|
||||
my $narbz2Size = stat($narFile)->size;
|
||||
|
||||
my $references = `$binDir/nix-store --query --references '$storePath'`;
|
||||
my $references = `$Nix::Config::binDir/nix-store --query --references '$storePath'`;
|
||||
die "cannot query references for `$storePath'" if $? != 0;
|
||||
$references = join(" ", split(" ", $references));
|
||||
|
||||
my $deriver = `$binDir/nix-store --query --deriver '$storePath'`;
|
||||
my $deriver = `$Nix::Config::binDir/nix-store --query --deriver '$storePath'`;
|
||||
die "cannot query deriver for `$storePath'" if $? != 0;
|
||||
chomp $deriver;
|
||||
$deriver = "" if $deriver eq "unknown-deriver";
|
||||
|
||||
my $narHash = `$binDir/nix-store --query --hash '$storePath'`;
|
||||
my $narHash = `$Nix::Config::binDir/nix-store --query --hash '$storePath'`;
|
||||
die "cannot query hash for `$storePath'" if $? != 0;
|
||||
chomp $narHash;
|
||||
|
||||
my $narSize = `$binDir/nix-store --query --size '$storePath'`;
|
||||
# In some exceptional cases (such as VM tests that use the Nix
|
||||
# store of the host), the database doesn't contain the hash. So
|
||||
# compute it.
|
||||
if ($narHash =~ /^sha256:0*$/) {
|
||||
$narHash = `$Nix::Config::binDir/nix-hash --type sha256 --base32 '$storePath'`;
|
||||
die "cannot hash `$storePath'" if $? != 0;
|
||||
chomp $narHash;
|
||||
$narHash = "sha256:$narHash";
|
||||
}
|
||||
|
||||
my $narSize = `$Nix::Config::binDir/nix-store --query --size '$storePath'`;
|
||||
die "cannot query size for `$storePath'" if $? != 0;
|
||||
chomp $narSize;
|
||||
|
||||
|
||||
0
scripts/nix-reduce-build.in
Normal file → Executable file
0
scripts/nix-reduce-build.in
Normal file → Executable file
@@ -6,10 +6,9 @@ use readmanifest;
|
||||
for my $p (@ARGV) {
|
||||
|
||||
my %narFiles;
|
||||
my %localPaths;
|
||||
my %patches;
|
||||
|
||||
readManifest $p, \%narFiles, \%localPaths, \%patches;
|
||||
readManifest $p, \%narFiles, \%patches;
|
||||
|
||||
%patches = ();
|
||||
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
#! /usr/bin/perl -w -I.
|
||||
|
||||
use strict;
|
||||
use readmanifest;
|
||||
|
||||
die unless scalar @ARGV == 2;
|
||||
|
||||
my $cache = $ARGV[0];
|
||||
my $manifest = $ARGV[1];
|
||||
my %narFiles;
|
||||
my %localPaths;
|
||||
my %patches;
|
||||
|
||||
readManifest $manifest, \%narFiles, \%localPaths, \%patches;
|
||||
|
||||
foreach my $storePath (keys %narFiles) {
|
||||
my $narFileList = $narFiles{$storePath};
|
||||
|
||||
foreach my $narFile (@{$narFileList}) {
|
||||
if (!defined $narFile->{size} or
|
||||
!defined $narFile->{narHash})
|
||||
{
|
||||
$narFile->{url} =~ /\/([^\/]+)$/;
|
||||
die unless defined $1;
|
||||
my $fn = "$cache/$1";
|
||||
|
||||
my @info = stat $fn or die;
|
||||
$narFile->{size} = $info[7];
|
||||
|
||||
my $narHash;
|
||||
my $hashFile = "$fn.NARHASH";
|
||||
if (-e $hashFile) {
|
||||
open HASH, "<$hashFile" or die;
|
||||
$narHash = <HASH>;
|
||||
close HASH;
|
||||
} else {
|
||||
print "$fn\n";
|
||||
$narHash = `bunzip2 < '$fn' | nix-hash --flat /dev/stdin` or die;
|
||||
open HASH, ">$hashFile" or die;
|
||||
print HASH $narHash;
|
||||
close HASH;
|
||||
}
|
||||
chomp $narHash;
|
||||
$narFile->{narHash} = $narHash;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! -e "$manifest.backup") {
|
||||
system "mv --reply=no '$manifest' '$manifest.backup'";
|
||||
}
|
||||
|
||||
writeManifest $manifest, \%narFiles, \%patches;
|
||||
@@ -6,12 +6,12 @@ libexpr_la_SOURCES = \
|
||||
names.cc
|
||||
|
||||
pkginclude_HEADERS = \
|
||||
nixexpr.hh eval.hh parser.hh lexer-tab.hh parser-tab.hh \
|
||||
nixexpr.hh eval.hh lexer-tab.hh parser-tab.hh \
|
||||
get-drvs.hh attr-path.hh value-to-xml.hh common-opts.hh \
|
||||
names.hh symbol-table.hh
|
||||
|
||||
libexpr_la_LIBADD = ../libutil/libutil.la ../libstore/libstore.la \
|
||||
../boost/format/libformat.la @boehmgc_lib@
|
||||
../boost/format/libformat.la @BDW_GC_LIBS@
|
||||
|
||||
BUILT_SOURCES = \
|
||||
parser-tab.hh lexer-tab.hh parser-tab.cc lexer-tab.cc
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "common-opts.hh"
|
||||
#include "../libmain/shared.hh"
|
||||
#include "util.hh"
|
||||
#include "parser.hh"
|
||||
|
||||
|
||||
namespace nix {
|
||||
@@ -25,7 +24,7 @@ bool parseOptionArg(const string & arg, Strings::iterator & i,
|
||||
autoArgs.push_back(Attr(state.symbols.create(name), v));
|
||||
|
||||
if (arg == "--arg")
|
||||
state.mkThunk_(*v, parseExprFromString(state, value, absPath(".")));
|
||||
state.mkThunk_(*v, state.parseExprFromString(value, absPath(".")));
|
||||
else
|
||||
mkString(*v, value);
|
||||
|
||||
@@ -34,5 +33,26 @@ bool parseOptionArg(const string & arg, Strings::iterator & i,
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool parseSearchPathArg(const string & arg, Strings::iterator & i,
|
||||
const Strings::iterator & argsEnd, EvalState & state)
|
||||
{
|
||||
if (arg != "-I") return false;
|
||||
if (i == argsEnd) throw UsageError(format("`%1%' requires an argument") % arg);;
|
||||
state.addToSearchPath(*i++);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Path lookupFileArg(EvalState & state, string s)
|
||||
{
|
||||
if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {
|
||||
Path p = state.findFile(s.substr(1, s.size() - 2));
|
||||
if (p == "") throw Error(format("file `%1%' was not found in the Nix search path (add it using $NIX_PATH or -I)") % p);
|
||||
return p;
|
||||
} else
|
||||
return absPath(s);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,11 @@ bool parseOptionArg(const string & arg, Strings::iterator & i,
|
||||
const Strings::iterator & argsEnd, EvalState & state,
|
||||
Bindings & autoArgs);
|
||||
|
||||
bool parseSearchPathArg(const string & arg, Strings::iterator & i,
|
||||
const Strings::iterator & argsEnd, EvalState & state);
|
||||
|
||||
Path lookupFileArg(EvalState & state, string s);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "eval.hh"
|
||||
#include "parser.hh"
|
||||
#include "hash.hh"
|
||||
#include "util.hh"
|
||||
#include "store-api.hh"
|
||||
@@ -7,6 +6,7 @@
|
||||
#include "globals.hh"
|
||||
|
||||
#include <cstring>
|
||||
#include <unistd.h>
|
||||
|
||||
#if HAVE_BOEHMGC
|
||||
|
||||
@@ -148,9 +148,46 @@ EvalState::EvalState()
|
||||
nrAttrsets = nrOpUpdates = nrOpUpdateValuesCopied = 0;
|
||||
deepestStack = (char *) -1;
|
||||
|
||||
createBaseEnv();
|
||||
|
||||
allowUnsafeEquality = getEnv("NIX_NO_UNSAFE_EQ", "") == "";
|
||||
|
||||
#if HAVE_BOEHMGC
|
||||
static bool gcInitialised = true;
|
||||
if (gcInitialised) {
|
||||
/* Set the initial heap size to something fairly big (25% of
|
||||
physical RAM, up to a maximum of 384 MiB) so that in most
|
||||
cases we don't need to garbage collect at all. (Collection
|
||||
has a fairly significant overhead.) The heap size can be
|
||||
overriden through libgc's GC_INITIAL_HEAP_SIZE environment
|
||||
variable. We should probably also provide a nix.conf
|
||||
setting for this. Note that GC_expand_hp() causes a lot of
|
||||
virtual, but not physical (resident) memory to be
|
||||
allocated. This might be a problem on systems that don't
|
||||
overcommit. */
|
||||
if (!getenv("GC_INITIAL_HEAP_SIZE")) {
|
||||
size_t maxSize = 384 * 1024 * 1024;
|
||||
size_t size = 32 * 1024 * 1024;
|
||||
#if HAVE_SYSCONF && defined(_SC_PAGESIZE) && defined(_SC_PHYS_PAGES)
|
||||
long pageSize = sysconf(_SC_PAGESIZE);
|
||||
long pages = sysconf(_SC_PHYS_PAGES);
|
||||
if (pageSize != -1)
|
||||
size = (pageSize * pages) / 4; // 25% of RAM
|
||||
if (size > maxSize) size = maxSize;
|
||||
#endif
|
||||
debug(format("setting initial heap size to %1% bytes") % size);
|
||||
GC_expand_hp(size);
|
||||
}
|
||||
gcInitialised = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialise the Nix expression search path. */
|
||||
searchPathInsertionPoint = searchPath.end();
|
||||
Strings paths = tokenizeString(getEnv("NIX_PATH", ""), ":");
|
||||
foreach (Strings::iterator, i, paths) addToSearchPath(*i);
|
||||
addToSearchPath("nix=" + nixDataDir + "/nix/corepkgs");
|
||||
searchPathInsertionPoint = searchPath.begin();
|
||||
|
||||
createBaseEnv();
|
||||
}
|
||||
|
||||
|
||||
@@ -394,21 +431,19 @@ Value * EvalState::maybeThunk(Env & env, Expr * expr)
|
||||
|
||||
void EvalState::evalFile(const Path & path, Value & v)
|
||||
{
|
||||
startNest(nest, lvlTalkative, format("evaluating file `%1%'") % path);
|
||||
|
||||
Expr * e = parseTrees[path];
|
||||
|
||||
if (!e) {
|
||||
e = parseExprFromFile(*this, path);
|
||||
parseTrees[path] = e;
|
||||
}
|
||||
|
||||
try {
|
||||
eval(e, v);
|
||||
} catch (Error & e) {
|
||||
addErrorPrefix(e, "while evaluating the file `%1%':\n", path);
|
||||
throw;
|
||||
}
|
||||
FileEvalCache::iterator i = fileEvalCache.find(path);
|
||||
if (i == fileEvalCache.end()) {
|
||||
startNest(nest, lvlTalkative, format("evaluating file `%1%'") % path);
|
||||
Expr * e = parseExprFromFile(path);
|
||||
try {
|
||||
eval(e, v);
|
||||
} catch (Error & e) {
|
||||
addErrorPrefix(e, "while evaluating the file `%1%':\n", path);
|
||||
throw;
|
||||
}
|
||||
fileEvalCache[path] = v;
|
||||
} else
|
||||
v = i->second;
|
||||
}
|
||||
|
||||
|
||||
@@ -601,33 +636,71 @@ void ExprVar::eval(EvalState & state, Env & env, Value & v)
|
||||
|
||||
|
||||
unsigned long nrLookups = 0;
|
||||
unsigned long nrLookupSize = 0;
|
||||
|
||||
void ExprSelect::eval(EvalState & state, Env & env, Value & v)
|
||||
{
|
||||
nrLookups++;
|
||||
Value v2;
|
||||
state.evalAttrs(env, e, v2);
|
||||
nrLookupSize += v2.attrs->size();
|
||||
Bindings::iterator i = v2.attrs->find(name);
|
||||
if (i == v2.attrs->end())
|
||||
throwEvalError("attribute `%1%' missing", name);
|
||||
try {
|
||||
state.forceValue(*i->value);
|
||||
Value vTmp;
|
||||
Pos * pos = 0;
|
||||
Value * vAttrs = &vTmp;
|
||||
|
||||
state.eval(env, e, vTmp);
|
||||
|
||||
try {
|
||||
|
||||
foreach (AttrPath::const_iterator, i, attrPath) {
|
||||
nrLookups++;
|
||||
Bindings::iterator j;
|
||||
if (def) {
|
||||
state.forceValue(*vAttrs);
|
||||
if (vAttrs->type != tAttrs ||
|
||||
(j = vAttrs->attrs->find(*i)) == vAttrs->attrs->end())
|
||||
{
|
||||
state.eval(env, def, v);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
state.forceAttrs(*vAttrs);
|
||||
if ((j = vAttrs->attrs->find(*i)) == vAttrs->attrs->end())
|
||||
throwEvalError("attribute `%1%' missing", showAttrPath(attrPath));
|
||||
}
|
||||
vAttrs = j->value;
|
||||
pos = j->pos;
|
||||
}
|
||||
|
||||
state.forceValue(*vAttrs);
|
||||
|
||||
} catch (Error & e) {
|
||||
addErrorPrefix(e, "while evaluating the attribute `%1%' at %2%:\n",
|
||||
name, *i->pos);
|
||||
if (pos)
|
||||
addErrorPrefix(e, "while evaluating the attribute `%1%' at %2%:\n",
|
||||
showAttrPath(attrPath), *pos);
|
||||
throw;
|
||||
}
|
||||
v = *i->value;
|
||||
|
||||
v = *vAttrs;
|
||||
}
|
||||
|
||||
|
||||
void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v)
|
||||
{
|
||||
Value vAttrs;
|
||||
state.evalAttrs(env, e, vAttrs);
|
||||
mkBool(v, vAttrs.attrs->find(name) != vAttrs.attrs->end());
|
||||
Value vTmp;
|
||||
Value * vAttrs = &vTmp;
|
||||
|
||||
state.eval(env, e, vTmp);
|
||||
|
||||
foreach (AttrPath::const_iterator, i, attrPath) {
|
||||
state.forceValue(*vAttrs);
|
||||
Bindings::iterator j;
|
||||
if (vAttrs->type != tAttrs ||
|
||||
(j = vAttrs->attrs->find(*i)) == vAttrs->attrs->end())
|
||||
{
|
||||
mkBool(v, false);
|
||||
return;
|
||||
} else {
|
||||
vAttrs = j->value;
|
||||
}
|
||||
}
|
||||
|
||||
mkBool(v, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -1035,7 +1108,10 @@ bool EvalState::isDerivation(Value & v)
|
||||
{
|
||||
if (v.type != tAttrs) return false;
|
||||
Bindings::iterator i = v.attrs->find(sType);
|
||||
return i != v.attrs->end() && forceStringNoCtx(*i->value) == "derivation";
|
||||
if (i == v.attrs->end()) return false;
|
||||
forceValue(*i->value);
|
||||
if (i->value->type != tString) return false;
|
||||
return forceStringNoCtx(*i->value) == "derivation";
|
||||
}
|
||||
|
||||
|
||||
@@ -1209,7 +1285,6 @@ void EvalState::printStats()
|
||||
printMsg(v, format(" number of thunks: %1%") % nrThunks);
|
||||
printMsg(v, format(" number of thunks avoided: %1%") % nrAvoided);
|
||||
printMsg(v, format(" number of attr lookups: %1%") % nrLookups);
|
||||
printMsg(v, format(" attr lookup size: %1%") % nrLookupSize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -188,8 +188,6 @@ void mkPath(Value & v, const char * s);
|
||||
void copyContext(const Value & v, PathSet & context);
|
||||
|
||||
|
||||
typedef std::map<Path, Hash> DrvHashes;
|
||||
|
||||
/* Cache for calls to addToStore(); maps source paths to the store
|
||||
paths. */
|
||||
typedef std::map<Path, Path> SrcToStore;
|
||||
@@ -203,8 +201,6 @@ std::ostream & operator << (std::ostream & str, const Value & v);
|
||||
class EvalState
|
||||
{
|
||||
public:
|
||||
DrvHashes drvHashes; /* normalised derivation hashes */
|
||||
|
||||
SymbolTable symbols;
|
||||
|
||||
const Symbol sWith, sOutPath, sDrvPath, sType, sMeta, sName,
|
||||
@@ -215,17 +211,42 @@ private:
|
||||
|
||||
bool allowUnsafeEquality;
|
||||
|
||||
/* A cache from path names to parse trees. */
|
||||
std::map<Path, Expr *> parseTrees;
|
||||
|
||||
/* A cache from path names to values. */
|
||||
#if HAVE_BOEHMGC
|
||||
typedef std::map<Path, Value, std::less<Path>, gc_allocator<std::pair<const Path, Value> > > FileEvalCache;
|
||||
#else
|
||||
typedef std::map<Path, Value> FileEvalCache;
|
||||
#endif
|
||||
FileEvalCache fileEvalCache;
|
||||
|
||||
typedef list<std::pair<string, Path> > SearchPath;
|
||||
SearchPath searchPath;
|
||||
SearchPath::iterator searchPathInsertionPoint;
|
||||
|
||||
public:
|
||||
|
||||
EvalState();
|
||||
~EvalState();
|
||||
|
||||
void addToSearchPath(const string & s);
|
||||
|
||||
/* Parse a Nix expression from the specified file. If `path'
|
||||
refers to a directory, then "/default.nix" is appended. */
|
||||
Expr * parseExprFromFile(Path path);
|
||||
|
||||
/* Parse a Nix expression from the specified string. */
|
||||
Expr * parseExprFromString(const string & s, const Path & basePath);
|
||||
|
||||
/* Evaluate an expression read from the given file to normal
|
||||
form. */
|
||||
void evalFile(const Path & path, Value & v);
|
||||
|
||||
/* Look up a file in the search path. */
|
||||
Path findFile(const string & path);
|
||||
|
||||
/* Evaluate an expression to normal form, storing the result in
|
||||
value `v'. */
|
||||
void eval(Expr * e, Value & v);
|
||||
@@ -300,6 +321,9 @@ private:
|
||||
friend class ExprAttrs;
|
||||
friend class ExprLet;
|
||||
|
||||
Expr * parse(const char * text,
|
||||
const Path & path, const Path & basePath);
|
||||
|
||||
public:
|
||||
|
||||
/* Do a deep equality test between two values. That is, list
|
||||
|
||||
@@ -81,6 +81,7 @@ static Expr * unescapeStr(SymbolTable & symbols, const char * s)
|
||||
ID [a-zA-Z\_][a-zA-Z0-9\_\']*
|
||||
INT [0-9]+
|
||||
PATH [a-zA-Z0-9\.\_\-\+]*(\/[a-zA-Z0-9\.\_\-\+]+)+
|
||||
SPATH \<[a-zA-Z0-9\.\_\-\+]+(\/[a-zA-Z0-9\.\_\-\+]+)*\>
|
||||
URI [a-zA-Z][a-zA-Z0-9\+\-\.]*\:[a-zA-Z0-9\%\/\?\:\@\&\=\+\$\,\-\_\.\!\~\*\']+
|
||||
|
||||
|
||||
@@ -96,6 +97,7 @@ let { return LET; }
|
||||
in { return IN; }
|
||||
rec { return REC; }
|
||||
inherit { return INHERIT; }
|
||||
or { return OR_KW; }
|
||||
\.\.\. { return ELLIPSIS; }
|
||||
|
||||
\=\= { return EQ; }
|
||||
@@ -152,6 +154,7 @@ inherit { return INHERIT; }
|
||||
<IND_STRING>. return yytext[0]; /* just in case: shouldn't be reached */
|
||||
|
||||
{PATH} { yylval->path = strdup(yytext); return PATH; }
|
||||
{SPATH} { yylval->path = strdup(yytext); return SPATH; }
|
||||
{URI} { yylval->uri = strdup(yytext); return URI; }
|
||||
|
||||
[ \t\r\n]+ /* eat up whitespace */
|
||||
|
||||
@@ -43,12 +43,13 @@ void ExprVar::show(std::ostream & str)
|
||||
|
||||
void ExprSelect::show(std::ostream & str)
|
||||
{
|
||||
str << "(" << *e << ")." << name;
|
||||
str << "(" << *e << ")." << showAttrPath(attrPath);
|
||||
if (def) str << " or " << *def;
|
||||
}
|
||||
|
||||
void ExprOpHasAttr::show(std::ostream & str)
|
||||
{
|
||||
str << "(" << *e << ") ? " << name;
|
||||
str << "(" << *e << ") ? " << showAttrPath(attrPath);
|
||||
}
|
||||
|
||||
void ExprAttrs::show(std::ostream & str)
|
||||
@@ -140,6 +141,17 @@ std::ostream & operator << (std::ostream & str, const Pos & pos)
|
||||
}
|
||||
|
||||
|
||||
string showAttrPath(const AttrPath & attrPath)
|
||||
{
|
||||
string s;
|
||||
foreach (AttrPath::const_iterator, i, attrPath) {
|
||||
if (!s.empty()) s += '.';
|
||||
s += *i;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
Pos noPos;
|
||||
|
||||
|
||||
@@ -200,6 +212,7 @@ void ExprVar::bindVars(const StaticEnv & env)
|
||||
void ExprSelect::bindVars(const StaticEnv & env)
|
||||
{
|
||||
e->bindVars(env);
|
||||
if (def) def->bindVars(env);
|
||||
}
|
||||
|
||||
void ExprOpHasAttr::bindVars(const StaticEnv & env)
|
||||
|
||||
@@ -40,6 +40,12 @@ struct EvalState;
|
||||
struct StaticEnv;
|
||||
|
||||
|
||||
/* An attribute path is a sequence of attribute names. */
|
||||
typedef vector<Symbol> AttrPath;
|
||||
|
||||
string showAttrPath(const AttrPath & attrPath);
|
||||
|
||||
|
||||
/* Abstract syntax of Nix expressions. */
|
||||
|
||||
struct Expr
|
||||
@@ -115,17 +121,18 @@ struct ExprVar : Expr
|
||||
|
||||
struct ExprSelect : Expr
|
||||
{
|
||||
Expr * e;
|
||||
Symbol name;
|
||||
ExprSelect(Expr * e, const Symbol & name) : e(e), name(name) { };
|
||||
Expr * e, * def;
|
||||
AttrPath attrPath;
|
||||
ExprSelect(Expr * e, const AttrPath & attrPath, Expr * def) : e(e), def(def), attrPath(attrPath) { };
|
||||
ExprSelect(Expr * e, const Symbol & name) : e(e), def(0) { attrPath.push_back(name); };
|
||||
COMMON_METHODS
|
||||
};
|
||||
|
||||
struct ExprOpHasAttr : Expr
|
||||
{
|
||||
Expr * e;
|
||||
Symbol name;
|
||||
ExprOpHasAttr(Expr * e, const Symbol & name) : e(e), name(name) { };
|
||||
AttrPath attrPath;
|
||||
ExprOpHasAttr(Expr * e, const AttrPath & attrPath) : e(e), attrPath(attrPath) { };
|
||||
COMMON_METHODS
|
||||
};
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#ifndef __PARSER_H
|
||||
#define __PARSER_H
|
||||
|
||||
#include "eval.hh"
|
||||
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
||||
/* Parse a Nix expression from the specified file. If `path' refers
|
||||
to a directory, then "/default.nix" is appended. */
|
||||
Expr * parseExprFromFile(EvalState & state, Path path);
|
||||
|
||||
/* Parse a Nix expression from the specified string. */
|
||||
Expr * parseExprFromString(EvalState & state, const string & s, const Path & basePath);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif /* !__PARSER_H */
|
||||
@@ -17,19 +17,22 @@
|
||||
#include "util.hh"
|
||||
|
||||
#include "nixexpr.hh"
|
||||
#include "eval.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
struct ParseData
|
||||
{
|
||||
EvalState & state;
|
||||
SymbolTable & symbols;
|
||||
Expr * result;
|
||||
Path basePath;
|
||||
Path path;
|
||||
string error;
|
||||
Symbol sLetBody;
|
||||
ParseData(SymbolTable & symbols)
|
||||
: symbols(symbols)
|
||||
ParseData(EvalState & state)
|
||||
: state(state)
|
||||
, symbols(state.symbols)
|
||||
, sLetBody(symbols.create("<let-body>"))
|
||||
{ };
|
||||
};
|
||||
@@ -61,18 +64,7 @@ using namespace nix;
|
||||
namespace nix {
|
||||
|
||||
|
||||
static string showAttrPath(const vector<Symbol> & attrPath)
|
||||
{
|
||||
string s;
|
||||
foreach (vector<Symbol>::const_iterator, i, attrPath) {
|
||||
if (!s.empty()) s += '.';
|
||||
s += *i;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
static void dupAttr(const vector<Symbol> & attrPath, const Pos & pos, const Pos & prevPos)
|
||||
static void dupAttr(const AttrPath & attrPath, const Pos & pos, const Pos & prevPos)
|
||||
{
|
||||
throw ParseError(format("attribute `%1%' at %2% already defined at %3%")
|
||||
% showAttrPath(attrPath) % pos % prevPos);
|
||||
@@ -81,17 +73,17 @@ static void dupAttr(const vector<Symbol> & attrPath, const Pos & pos, const Pos
|
||||
|
||||
static void dupAttr(Symbol attr, const Pos & pos, const Pos & prevPos)
|
||||
{
|
||||
vector<Symbol> attrPath; attrPath.push_back(attr);
|
||||
AttrPath attrPath; attrPath.push_back(attr);
|
||||
throw ParseError(format("attribute `%1%' at %2% already defined at %3%")
|
||||
% showAttrPath(attrPath) % pos % prevPos);
|
||||
}
|
||||
|
||||
|
||||
static void addAttr(ExprAttrs * attrs, const vector<Symbol> & attrPath,
|
||||
static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
|
||||
Expr * e, const Pos & pos)
|
||||
{
|
||||
unsigned int n = 0;
|
||||
foreach (vector<Symbol>::const_iterator, i, attrPath) {
|
||||
foreach (AttrPath::const_iterator, i, attrPath) {
|
||||
n++;
|
||||
ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(*i);
|
||||
if (j != attrs->attrs.end()) {
|
||||
@@ -238,6 +230,7 @@ void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * err
|
||||
%}
|
||||
|
||||
%union {
|
||||
// !!! We're probably leaking stuff here.
|
||||
nix::Expr * e;
|
||||
nix::ExprList * list;
|
||||
nix::ExprAttrs * attrs;
|
||||
@@ -247,7 +240,7 @@ void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * err
|
||||
char * id; // !!! -> Symbol
|
||||
char * path;
|
||||
char * uri;
|
||||
std::vector<nix::Symbol> * ids;
|
||||
std::vector<nix::Symbol> * attrNames;
|
||||
std::vector<nix::Expr *> * string_parts;
|
||||
}
|
||||
|
||||
@@ -257,14 +250,15 @@ void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * err
|
||||
%type <attrs> binds
|
||||
%type <formals> formals
|
||||
%type <formal> formal
|
||||
%type <ids> ids attrpath
|
||||
%type <attrNames> attrs attrpath
|
||||
%type <string_parts> string_parts ind_string_parts
|
||||
%type <id> attr
|
||||
%token <id> ID ATTRPATH
|
||||
%token <e> STR IND_STR
|
||||
%token <n> INT
|
||||
%token <path> PATH
|
||||
%token <path> PATH SPATH
|
||||
%token <uri> URI
|
||||
%token IF THEN ELSE ASSERT WITH LET IN REC INHERIT EQ NEQ AND OR IMPL
|
||||
%token IF THEN ELSE ASSERT WITH LET IN REC INHERIT EQ NEQ AND OR IMPL OR_KW
|
||||
%token DOLLAR_CURLY /* == ${ */
|
||||
%token IND_STRING_OPEN IND_STRING_CLOSE
|
||||
%token ELLIPSIS
|
||||
@@ -317,7 +311,7 @@ expr_op
|
||||
| expr_op OR expr_op { $$ = new ExprOpOr($1, $3); }
|
||||
| expr_op IMPL expr_op { $$ = new ExprOpImpl($1, $3); }
|
||||
| expr_op UPDATE expr_op { $$ = new ExprOpUpdate($1, $3); }
|
||||
| expr_op '?' ID { $$ = new ExprOpHasAttr($1, data->symbols.create($3)); }
|
||||
| expr_op '?' attrpath { $$ = new ExprOpHasAttr($1, *$3); }
|
||||
| expr_op '+' expr_op
|
||||
{ vector<Expr *> * l = new vector<Expr *>;
|
||||
l->push_back($1);
|
||||
@@ -335,8 +329,14 @@ expr_app
|
||||
;
|
||||
|
||||
expr_select
|
||||
: expr_select '.' ID
|
||||
{ $$ = new ExprSelect($1, data->symbols.create($3)); }
|
||||
: expr_simple '.' attrpath
|
||||
{ $$ = new ExprSelect($1, *$3, 0); }
|
||||
| expr_simple '.' attrpath OR_KW expr_select
|
||||
{ $$ = new ExprSelect($1, *$3, $5); }
|
||||
| /* Backwards compatibility: because Nixpkgs has a rarely used
|
||||
function named ‘or’, allow stuff like ‘map or [...]’. */
|
||||
expr_simple OR_KW
|
||||
{ $$ = new ExprApp($1, new ExprVar(data->symbols.create("or"))); }
|
||||
| expr_simple { $$ = $1; }
|
||||
;
|
||||
|
||||
@@ -353,6 +353,20 @@ expr_simple
|
||||
$$ = stripIndentation(data->symbols, *$2);
|
||||
}
|
||||
| PATH { $$ = new ExprPath(absPath($1, data->basePath)); }
|
||||
| SPATH {
|
||||
string path($1 + 1, strlen($1) - 2);
|
||||
Path path2 = data->state.findFile(path);
|
||||
/* The file wasn't found in the search path. However, we can't
|
||||
throw an error here, because the expression might never be
|
||||
evaluated. So return an expression that lazily calls
|
||||
‘abort’. */
|
||||
$$ = path2 == ""
|
||||
? (Expr * ) new ExprApp(
|
||||
new ExprVar(data->symbols.create("throw")),
|
||||
new ExprString(data->symbols.create(
|
||||
(format("file `%1%' was not found in the Nix search path (add it using $NIX_PATH or -I)") % path).str())))
|
||||
: (Expr * ) new ExprPath(path2);
|
||||
}
|
||||
| URI { $$ = new ExprString(data->symbols.create($1)); }
|
||||
| '(' expr ')' { $$ = $2; }
|
||||
/* Let expressions `let {..., body = ...}' are just desugared
|
||||
@@ -380,35 +394,42 @@ ind_string_parts
|
||||
|
||||
binds
|
||||
: binds attrpath '=' expr ';' { $$ = $1; addAttr($$, *$2, $4, makeCurPos(@2, data)); }
|
||||
| binds INHERIT ids ';'
|
||||
| binds INHERIT attrs ';'
|
||||
{ $$ = $1;
|
||||
foreach (vector<Symbol>::iterator, i, *$3) {
|
||||
foreach (AttrPath::iterator, i, *$3) {
|
||||
if ($$->attrs.find(*i) != $$->attrs.end())
|
||||
dupAttr(*i, makeCurPos(@3, data), $$->attrs[*i].pos);
|
||||
Pos pos = makeCurPos(@3, data);
|
||||
$$->attrs[*i] = ExprAttrs::AttrDef(*i, pos);
|
||||
}
|
||||
}
|
||||
| binds INHERIT '(' expr ')' ids ';'
|
||||
| binds INHERIT '(' expr ')' attrs ';'
|
||||
{ $$ = $1;
|
||||
/* !!! Should ensure sharing of the expression in $4. */
|
||||
foreach (vector<Symbol>::iterator, i, *$6) {
|
||||
if ($$->attrs.find(*i) != $$->attrs.end())
|
||||
dupAttr(*i, makeCurPos(@6, data), $$->attrs[*i].pos);
|
||||
$$->attrs[*i] = ExprAttrs::AttrDef(new ExprSelect($4, *i), makeCurPos(@6, data));
|
||||
}}
|
||||
|
||||
}
|
||||
}
|
||||
| { $$ = new ExprAttrs; }
|
||||
;
|
||||
|
||||
ids
|
||||
: ids ID { $$ = $1; $1->push_back(data->symbols.create($2)); /* !!! dangerous */ }
|
||||
attrs
|
||||
: attrs attr { $$ = $1; $1->push_back(data->symbols.create($2)); /* !!! dangerous */ }
|
||||
| { $$ = new vector<Symbol>; }
|
||||
;
|
||||
|
||||
attrpath
|
||||
: attrpath '.' ID { $$ = $1; $1->push_back(data->symbols.create($3)); }
|
||||
| ID { $$ = new vector<Symbol>; $$->push_back(data->symbols.create($1)); }
|
||||
: attrpath '.' attr { $$ = $1; $1->push_back(data->symbols.create($3)); }
|
||||
| attr { $$ = new vector<Symbol>; $$->push_back(data->symbols.create($1)); }
|
||||
;
|
||||
|
||||
attr
|
||||
: ID { $$ = $1; }
|
||||
| OR_KW { $$ = "or"; }
|
||||
| '"' STR '"'
|
||||
{ $$ = strdup(((string) ((ExprString *) $2)->s).c_str()); delete $2; }
|
||||
;
|
||||
|
||||
expr_list
|
||||
@@ -446,11 +467,11 @@ formal
|
||||
namespace nix {
|
||||
|
||||
|
||||
static Expr * parse(EvalState & state, const char * text,
|
||||
Expr * EvalState::parse(const char * text,
|
||||
const Path & path, const Path & basePath)
|
||||
{
|
||||
yyscan_t scanner;
|
||||
ParseData data(state.symbols);
|
||||
ParseData data(*this);
|
||||
data.basePath = basePath;
|
||||
data.path = path;
|
||||
|
||||
@@ -462,7 +483,7 @@ static Expr * parse(EvalState & state, const char * text,
|
||||
if (res) throw ParseError(data.error);
|
||||
|
||||
try {
|
||||
data.result->bindVars(state.staticBaseEnv);
|
||||
data.result->bindVars(staticBaseEnv);
|
||||
} catch (Error & e) {
|
||||
throw ParseError(format("%1%, in `%2%'") % e.msg() % path);
|
||||
}
|
||||
@@ -471,7 +492,7 @@ static Expr * parse(EvalState & state, const char * text,
|
||||
}
|
||||
|
||||
|
||||
Expr * parseExprFromFile(EvalState & state, Path path)
|
||||
Expr * EvalState::parseExprFromFile(Path path)
|
||||
{
|
||||
assert(path[0] == '/');
|
||||
|
||||
@@ -489,16 +510,61 @@ Expr * parseExprFromFile(EvalState & state, Path path)
|
||||
if (S_ISDIR(st.st_mode))
|
||||
path = canonPath(path + "/default.nix");
|
||||
|
||||
/* Read and parse the input file. */
|
||||
return parse(state, readFile(path).c_str(), path, dirOf(path));
|
||||
/* Read and parse the input file, unless it's already in the parse
|
||||
tree cache. */
|
||||
Expr * e = parseTrees[path];
|
||||
if (!e) {
|
||||
e = parse(readFile(path).c_str(), path, dirOf(path));
|
||||
parseTrees[path] = e;
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
Expr * parseExprFromString(EvalState & state,
|
||||
const string & s, const Path & basePath)
|
||||
Expr * EvalState::parseExprFromString(const string & s, const Path & basePath)
|
||||
{
|
||||
return parse(state, s.c_str(), "(string)", basePath);
|
||||
return parse(s.c_str(), "(string)", basePath);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void EvalState::addToSearchPath(const string & s)
|
||||
{
|
||||
size_t pos = s.find('=');
|
||||
string prefix;
|
||||
Path path;
|
||||
if (pos == string::npos) {
|
||||
path = s;
|
||||
} else {
|
||||
prefix = string(s, 0, pos);
|
||||
path = string(s, pos + 1);
|
||||
}
|
||||
|
||||
path = absPath(path);
|
||||
if (pathExists(path)) {
|
||||
debug(format("adding path `%1%' to the search path") % path);
|
||||
searchPath.insert(searchPathInsertionPoint, std::pair<string, Path>(prefix, path));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Path EvalState::findFile(const string & path)
|
||||
{
|
||||
foreach (SearchPath::iterator, i, searchPath) {
|
||||
Path res;
|
||||
if (i->first.empty())
|
||||
res = i->second + "/" + path;
|
||||
else {
|
||||
if (path.compare(0, i->first.size(), i->first) != 0 ||
|
||||
(path.size() > i->first.size() && path[i->first.size()] != '/'))
|
||||
continue;
|
||||
res = i->second +
|
||||
(path.size() == i->first.size() ? "" : "/" + string(path, i->first.size()));
|
||||
}
|
||||
if (pathExists(res)) return canonPath(res);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "util.hh"
|
||||
#include "archive.hh"
|
||||
#include "value-to-xml.hh"
|
||||
#include "parser.hh"
|
||||
#include "names.hh"
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -246,63 +245,6 @@ static void prim_trace(EvalState & state, Value * * args, Value & v)
|
||||
*************************************************************/
|
||||
|
||||
|
||||
static bool isFixedOutput(const Derivation & drv)
|
||||
{
|
||||
return drv.outputs.size() == 1 &&
|
||||
drv.outputs.begin()->first == "out" &&
|
||||
drv.outputs.begin()->second.hash != "";
|
||||
}
|
||||
|
||||
|
||||
/* Returns the hash of a derivation modulo fixed-output
|
||||
subderivations. A fixed-output derivation is a derivation with one
|
||||
output (`out') for which an expected hash and hash algorithm are
|
||||
specified (using the `outputHash' and `outputHashAlgo'
|
||||
attributes). We don't want changes to such derivations to
|
||||
propagate upwards through the dependency graph, changing output
|
||||
paths everywhere.
|
||||
|
||||
For instance, if we change the url in a call to the `fetchurl'
|
||||
function, we do not want to rebuild everything depending on it
|
||||
(after all, (the hash of) the file being downloaded is unchanged).
|
||||
So the *output paths* should not change. On the other hand, the
|
||||
*derivation paths* should change to reflect the new dependency
|
||||
graph.
|
||||
|
||||
That's what this function does: it returns a hash which is just the
|
||||
hash of the derivation ATerm, except that any input derivation
|
||||
paths have been replaced by the result of a recursive call to this
|
||||
function, and that for fixed-output derivations we return a hash of
|
||||
its output path. */
|
||||
static Hash hashDerivationModulo(EvalState & state, Derivation drv)
|
||||
{
|
||||
/* Return a fixed hash for fixed-output derivations. */
|
||||
if (isFixedOutput(drv)) {
|
||||
DerivationOutputs::const_iterator i = drv.outputs.begin();
|
||||
return hashString(htSHA256, "fixed:out:"
|
||||
+ i->second.hashAlgo + ":"
|
||||
+ i->second.hash + ":"
|
||||
+ i->second.path);
|
||||
}
|
||||
|
||||
/* For other derivations, replace the inputs paths with recursive
|
||||
calls to this function.*/
|
||||
DerivationInputs inputs2;
|
||||
foreach (DerivationInputs::const_iterator, i, drv.inputDrvs) {
|
||||
Hash h = state.drvHashes[i->first];
|
||||
if (h.type == htUnknown) {
|
||||
Derivation drv2 = derivationFromPath(i->first);
|
||||
h = hashDerivationModulo(state, drv2);
|
||||
state.drvHashes[i->first] = h;
|
||||
}
|
||||
inputs2[printHash(h)] = i->second;
|
||||
}
|
||||
drv.inputDrvs = inputs2;
|
||||
|
||||
return hashString(htSHA256, unparseDerivation(drv));
|
||||
}
|
||||
|
||||
|
||||
/* Construct (as a unobservable side effect) a Nix derivation
|
||||
expression that performs the derivation described by the argument
|
||||
set. Returns the original set extended with the following
|
||||
@@ -337,6 +279,9 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v)
|
||||
string outputHash, outputHashAlgo;
|
||||
bool outputHashRecursive = false;
|
||||
|
||||
StringSet outputs;
|
||||
outputs.insert("out");
|
||||
|
||||
foreach (Bindings::iterator, i, *args[0]->attrs) {
|
||||
string key = i->name;
|
||||
startNest(nest, lvlVomit, format("processing attribute `%1%'") % key);
|
||||
@@ -368,6 +313,24 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v)
|
||||
else if (s == "flat") outputHashRecursive = false;
|
||||
else throw EvalError(format("invalid value `%1%' for `outputHashMode' attribute") % s);
|
||||
}
|
||||
else if (key == "outputs") {
|
||||
Strings tmp = tokenizeString(s);
|
||||
outputs.clear();
|
||||
foreach (Strings::iterator, j, tmp) {
|
||||
if (outputs.find(*j) != outputs.end())
|
||||
throw EvalError(format("duplicate derivation output `%1%'") % *j);
|
||||
/* !!! Check whether *j is a valid attribute
|
||||
name. */
|
||||
/* Derivations cannot be named ‘drv’, because
|
||||
then we'd have an attribute ‘drvPath’ in
|
||||
the resulting set. */
|
||||
if (*j == "drv")
|
||||
throw EvalError(format("invalid derivation output name `drv'") % *j);
|
||||
outputs.insert(*j);
|
||||
}
|
||||
if (outputs.empty())
|
||||
throw EvalError("derivation cannot have an empty set of outputs");
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Error & e) {
|
||||
@@ -393,27 +356,31 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v)
|
||||
inputs to ensure that they are available when the builder
|
||||
runs. */
|
||||
if (path.at(0) == '=') {
|
||||
path = string(path, 1);
|
||||
PathSet refs; computeFSClosure(path, refs);
|
||||
/* !!! This doesn't work if readOnlyMode is set. */
|
||||
PathSet refs; computeFSClosure(*store, string(path, 1), refs);
|
||||
foreach (PathSet::iterator, j, refs) {
|
||||
drv.inputSrcs.insert(*j);
|
||||
if (isDerivation(*j))
|
||||
drv.inputDrvs[*j] = singleton<StringSet>("out");
|
||||
drv.inputDrvs[*j] = store->queryDerivationOutputNames(*j);
|
||||
}
|
||||
}
|
||||
|
||||
/* See prim_unsafeDiscardOutputDependency. */
|
||||
bool useDrvAsSrc = false;
|
||||
if (path.at(0) == '~') {
|
||||
path = string(path, 1);
|
||||
useDrvAsSrc = true;
|
||||
else if (path.at(0) == '~')
|
||||
drv.inputSrcs.insert(string(path, 1));
|
||||
|
||||
/* Handle derivation outputs of the form ‘!<name>!<path>’. */
|
||||
else if (path.at(0) == '!') {
|
||||
size_t index = path.find("!", 1);
|
||||
drv.inputDrvs[string(path, index + 1)].insert(string(path, 1, index - 1));
|
||||
}
|
||||
|
||||
assert(isStorePath(path));
|
||||
/* Handle derivation contexts returned by
|
||||
‘builtins.storePath’. */
|
||||
else if (isDerivation(path))
|
||||
drv.inputDrvs[path] = store->queryDerivationOutputNames(path);
|
||||
|
||||
debug(format("derivation uses `%1%'") % path);
|
||||
if (!useDrvAsSrc && isDerivation(path))
|
||||
drv.inputDrvs[path] = singleton<StringSet>("out");
|
||||
/* Otherwise it's a source file. */
|
||||
else
|
||||
drv.inputSrcs.insert(path);
|
||||
}
|
||||
@@ -424,69 +391,69 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v)
|
||||
if (drv.platform == "")
|
||||
throw EvalError("required attribute `system' missing");
|
||||
|
||||
/* If an output hash was given, check it. */
|
||||
Path outPath;
|
||||
if (outputHash == "")
|
||||
outputHashAlgo = "";
|
||||
else {
|
||||
HashType ht = parseHashType(outputHashAlgo);
|
||||
if (ht == htUnknown)
|
||||
throw EvalError(format("unknown hash algorithm `%1%'") % outputHashAlgo);
|
||||
Hash h(ht);
|
||||
if (outputHash.size() == h.hashSize * 2)
|
||||
/* hexadecimal representation */
|
||||
h = parseHash(ht, outputHash);
|
||||
else if (outputHash.size() == hashLength32(h))
|
||||
/* base-32 representation */
|
||||
h = parseHash32(ht, outputHash);
|
||||
else
|
||||
throw Error(format("hash `%1%' has wrong length for hash type `%2%'")
|
||||
% outputHash % outputHashAlgo);
|
||||
string s = outputHash;
|
||||
outputHash = printHash(h);
|
||||
outPath = makeFixedOutputPath(outputHashRecursive, ht, h, drvName);
|
||||
if (outputHashRecursive) outputHashAlgo = "r:" + outputHashAlgo;
|
||||
}
|
||||
|
||||
/* Check whether the derivation name is valid. */
|
||||
checkStoreName(drvName);
|
||||
if (isDerivation(drvName))
|
||||
throw EvalError(format("derivation names are not allowed to end in `%1%'")
|
||||
% drvExtension);
|
||||
|
||||
/* Construct the "masked" derivation store expression, which is
|
||||
the final one except that in the list of outputs, the output
|
||||
paths are empty, and the corresponding environment variables
|
||||
have an empty value. This ensures that changes in the set of
|
||||
output names do get reflected in the hash. */
|
||||
drv.env["out"] = "";
|
||||
drv.outputs["out"] = DerivationOutput("", outputHashAlgo, outputHash);
|
||||
if (outputHash != "") {
|
||||
/* Handle fixed-output derivations. */
|
||||
if (outputs.size() != 1 || *(outputs.begin()) != "out")
|
||||
throw Error("multiple outputs are not supported in fixed-output derivations");
|
||||
|
||||
/* Use the masked derivation expression to compute the output
|
||||
path. */
|
||||
if (outPath == "")
|
||||
outPath = makeStorePath("output:out", hashDerivationModulo(state, drv), drvName);
|
||||
HashType ht = parseHashType(outputHashAlgo);
|
||||
if (ht == htUnknown)
|
||||
throw EvalError(format("unknown hash algorithm `%1%'") % outputHashAlgo);
|
||||
Hash h = parseHash16or32(ht, outputHash);
|
||||
outputHash = printHash(h);
|
||||
if (outputHashRecursive) outputHashAlgo = "r:" + outputHashAlgo;
|
||||
|
||||
Path outPath = makeFixedOutputPath(outputHashRecursive, ht, h, drvName);
|
||||
drv.env["out"] = outPath;
|
||||
drv.outputs["out"] = DerivationOutput(outPath, outputHashAlgo, outputHash);
|
||||
}
|
||||
|
||||
/* Construct the final derivation store expression. */
|
||||
drv.env["out"] = outPath;
|
||||
drv.outputs["out"] =
|
||||
DerivationOutput(outPath, outputHashAlgo, outputHash);
|
||||
else {
|
||||
/* Construct the "masked" store derivation, which is the final
|
||||
one except that in the list of outputs, the output paths
|
||||
are empty, and the corresponding environment variables have
|
||||
an empty value. This ensures that changes in the set of
|
||||
output names do get reflected in the hash. */
|
||||
foreach (StringSet::iterator, i, outputs) {
|
||||
drv.env[*i] = "";
|
||||
drv.outputs[*i] = DerivationOutput("", "", "");
|
||||
}
|
||||
|
||||
/* Use the masked derivation expression to compute the output
|
||||
path. */
|
||||
Hash h = hashDerivationModulo(*store, drv);
|
||||
|
||||
foreach (DerivationOutputs::iterator, i, drv.outputs)
|
||||
if (i->second.path == "") {
|
||||
Path outPath = makeOutputPath(i->first, h, drvName);
|
||||
drv.env[i->first] = outPath;
|
||||
i->second.path = outPath;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the resulting term into the Nix store directory. */
|
||||
Path drvPath = writeDerivation(drv, drvName);
|
||||
Path drvPath = writeDerivation(*store, drv, drvName);
|
||||
|
||||
printMsg(lvlChatty, format("instantiated `%1%' -> `%2%'")
|
||||
% drvName % drvPath);
|
||||
|
||||
/* Optimisation, but required in read-only mode! because in that
|
||||
case we don't actually write store expressions, so we can't
|
||||
case we don't actually write store derivations, so we can't
|
||||
read them later. */
|
||||
state.drvHashes[drvPath] = hashDerivationModulo(state, drv);
|
||||
drvHashes[drvPath] = hashDerivationModulo(*store, drv);
|
||||
|
||||
/* !!! assumes a single output */
|
||||
state.mkAttrs(v, 2);
|
||||
mkString(*state.allocAttr(v, state.sOutPath), outPath, singleton<PathSet>(drvPath));
|
||||
state.mkAttrs(v, 1 + drv.outputs.size());
|
||||
mkString(*state.allocAttr(v, state.sDrvPath), drvPath, singleton<PathSet>("=" + drvPath));
|
||||
foreach (DerivationOutputs::iterator, i, drv.outputs) {
|
||||
mkString(*state.allocAttr(v, state.symbols.create(i->first)),
|
||||
i->second.path, singleton<PathSet>("!" + i->first + "!" + drvPath));
|
||||
}
|
||||
v.attrs->sort();
|
||||
}
|
||||
|
||||
@@ -1077,15 +1044,6 @@ void EvalState::createBaseEnv()
|
||||
addPrimOp("__getEnv", 1, prim_getEnv);
|
||||
addPrimOp("__trace", 2, prim_trace);
|
||||
|
||||
// Derivations
|
||||
addPrimOp("derivationStrict", 1, prim_derivationStrict);
|
||||
|
||||
/* Add a wrapper around the derivation primop that computes the
|
||||
`drvPath' and `outPath' attributes lazily. */
|
||||
string s = "attrs: let res = derivationStrict attrs; in attrs // { drvPath = res.drvPath; outPath = res.outPath; type = \"derivation\"; }";
|
||||
mkThunk_(v, parseExprFromString(*this, s, "/"));
|
||||
addConstant("derivation", v);
|
||||
|
||||
// Paths
|
||||
addPrimOp("__toPath", 1, prim_toPath);
|
||||
addPrimOp("__storePath", 1, prim_storePath);
|
||||
@@ -1134,6 +1092,14 @@ void EvalState::createBaseEnv()
|
||||
addPrimOp("__parseDrvName", 1, prim_parseDrvName);
|
||||
addPrimOp("__compareVersions", 2, prim_compareVersions);
|
||||
|
||||
// Derivations
|
||||
addPrimOp("derivationStrict", 1, prim_derivationStrict);
|
||||
|
||||
/* Add a wrapper around the derivation primop that computes the
|
||||
`drvPath' and `outPath' attributes lazily. */
|
||||
mkThunk_(v, parseExprFromFile(findFile("nix/derivation.nix")));
|
||||
addConstant("derivation", v);
|
||||
|
||||
/* Now that we've added all primops, sort the `builtins' attribute
|
||||
set, because attribute lookups expect it to be sorted. */
|
||||
baseEnv.values[0]->attrs->sort();
|
||||
|
||||
@@ -2,18 +2,11 @@ pkglib_LTLIBRARIES = libmain.la
|
||||
|
||||
libmain_la_SOURCES = shared.cc
|
||||
|
||||
libmain_la_LIBADD = ../libstore/libstore.la @boehmgc_lib@
|
||||
libmain_la_LIBADD = ../libstore/libstore.la @BDW_GC_LIBS@
|
||||
|
||||
pkginclude_HEADERS = shared.hh
|
||||
|
||||
AM_CXXFLAGS = \
|
||||
-DNIX_STORE_DIR=\"$(storedir)\" \
|
||||
-DNIX_DATA_DIR=\"$(datadir)\" \
|
||||
-DNIX_STATE_DIR=\"$(localstatedir)/nix\" \
|
||||
-DNIX_LOG_DIR=\"$(localstatedir)/log/nix\" \
|
||||
-DNIX_CONF_DIR=\"$(sysconfdir)/nix\" \
|
||||
-DNIX_LIBEXEC_DIR=\"$(libexecdir)\" \
|
||||
-DNIX_BIN_DIR=\"$(bindir)\" \
|
||||
-DNIX_VERSION=\"$(VERSION)\" \
|
||||
-I$(srcdir)/.. -I$(srcdir)/../libutil \
|
||||
-I$(srcdir)/../libstore
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user