Compare commits
2945 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a6ce6d9e7c | ||
|
|
8cc19ed089 | ||
|
|
52edef3495 | ||
|
|
8d100dbef1 | ||
|
|
5c487761c4 | ||
|
|
3631dc6b2f | ||
|
|
aa61bc7472 | ||
|
|
0f96966a44 | ||
|
|
566afa1e9c | ||
|
|
444b03a36f | ||
|
|
d5a01d0f9d | ||
|
|
a7b4aaa2c3 | ||
|
|
3100b29fc5 | ||
|
|
094a08f839 | ||
|
|
4387d19359 | ||
|
|
24d5875514 | ||
|
|
b215b23e9e | ||
|
|
56d29dcd62 | ||
|
|
2d5e8e267b | ||
|
|
5ad89398d1 | ||
|
|
21c2d8d102 | ||
|
|
d62fc71b85 | ||
|
|
4bb4d5479a | ||
|
|
8eed07cda4 | ||
|
|
6c98e6a5de | ||
|
|
8b8ee53bc7 | ||
|
|
5943f41b8b | ||
|
|
08964d7328 | ||
|
|
69c88f5028 | ||
|
|
408a7bfac1 | ||
|
|
8d8d47abd2 | ||
|
|
46a369ad95 | ||
|
|
a3d6585c5a | ||
|
|
9de6bc5d05 | ||
|
|
bf3725da2a | ||
|
|
17dc306aa3 | ||
|
|
f794465ca8 | ||
|
|
8541d27fce | ||
|
|
3acc8adcad | ||
|
|
ea89df2b76 | ||
|
|
48c19c4633 | ||
|
|
198dbe7fa1 | ||
|
|
10dcee99ed | ||
|
|
4c9e3fa641 | ||
|
|
182e15b661 | ||
|
|
88164325fa | ||
|
|
f581ce0b0c | ||
|
|
91ef4d9a81 | ||
|
|
a9a8baaccb | ||
|
|
c31ebc50aa | ||
|
|
e28b683324 | ||
|
|
bbc107ef1e | ||
|
|
3a95e1a17c | ||
|
|
82951e5582 | ||
|
|
620e92e880 | ||
|
|
df27db712d | ||
|
|
d0fc615af6 | ||
|
|
4c34d384e6 | ||
|
|
a28b4445a4 | ||
|
|
2980d1fba9 | ||
|
|
dde6486eab | ||
|
|
c8daeba303 | ||
|
|
167e36a5c3 | ||
|
|
ac238d619c | ||
|
|
600daf972f | ||
|
|
e345182055 | ||
|
|
ecedd9c50c | ||
|
|
70f75be199 | ||
|
|
ad328bea15 | ||
|
|
bfaa5635de | ||
|
|
904f50412c | ||
|
|
90b8a34f82 | ||
|
|
d1de836938 | ||
|
|
f766e146f4 | ||
|
|
e35d6f78dc | ||
|
|
522ecab9b8 | ||
|
|
7586095504 | ||
|
|
a562d544d8 | ||
|
|
9c41c66c5b | ||
|
|
2bbc4a214e | ||
|
|
2e90a5a2a7 | ||
|
|
0a7084567f | ||
|
|
a807edfae8 | ||
|
|
a3f205b249 | ||
|
|
2001895f3d | ||
|
|
cf46f19444 | ||
|
|
8e3a7bd712 | ||
|
|
9958bd6992 | ||
|
|
e666e1156f | ||
|
|
f406288cc7 | ||
|
|
95c74eae26 | ||
|
|
f46612be96 | ||
|
|
d534f137f0 | ||
|
|
0f358ca5b6 | ||
|
|
cb6651e878 | ||
|
|
e464b0247d | ||
|
|
28bf183d2d | ||
|
|
c1f91570b3 | ||
|
|
20582e9ae3 | ||
|
|
b9c2b4d5b4 | ||
|
|
b9124a5c33 | ||
|
|
76e88871b2 | ||
|
|
00092b2d35 | ||
|
|
b674665765 | ||
|
|
09eb230900 | ||
|
|
983220bcd4 | ||
|
|
9fd9dedf12 | ||
|
|
1bda006b74 | ||
|
|
aac14222f5 | ||
|
|
54fe8e0773 | ||
|
|
47ae3ce2ca | ||
|
|
e03a8a1c92 | ||
|
|
8fbe96cb31 | ||
|
|
e6e495649c | ||
|
|
2923b55f9d | ||
|
|
31114ec3a5 | ||
|
|
c845c0ccad | ||
|
|
b14717ab90 | ||
|
|
6c4ac29917 | ||
|
|
e56f71edaf | ||
|
|
4fca02077c | ||
|
|
479e9172b3 | ||
|
|
4ba47205c6 | ||
|
|
6762424e24 | ||
|
|
d4c3b6327f | ||
|
|
1f7901ec3b | ||
|
|
5e2ffd0b8a | ||
|
|
8cf672091e | ||
|
|
9dbda2b3fe | ||
|
|
a2785b7391 | ||
|
|
295027f533 | ||
|
|
d3004c78d9 | ||
|
|
360056e174 | ||
|
|
f7b650d234 | ||
|
|
15e1b2c223 | ||
|
|
9e2fc6951c | ||
|
|
cfd968dd94 | ||
|
|
f3077fd88d | ||
|
|
cc8641815b | ||
|
|
2688fb73f1 | ||
|
|
8207359227 | ||
|
|
8b8fe6139e | ||
|
|
babe54bf97 | ||
|
|
e94806d030 | ||
|
|
a9e6752bbd | ||
|
|
4aa1e5c554 | ||
|
|
d950cfe70b | ||
|
|
56e30e161c | ||
|
|
f0eab0636b | ||
|
|
862c4c5ec5 | ||
|
|
767101824a | ||
|
|
e5c589d271 | ||
|
|
3e89ef597c | ||
|
|
9c2d63084b | ||
|
|
198d0338be | ||
|
|
b9e5b908ed | ||
|
|
4ccd48ce24 | ||
|
|
62f72eb9e1 | ||
|
|
e82767910c | ||
|
|
325d1cfebf | ||
|
|
d025142f52 | ||
|
|
b6c989b801 | ||
|
|
108e14bb18 | ||
|
|
6763084ae5 | ||
|
|
01d56c1eec | ||
|
|
967d066d8e | ||
|
|
1df702d347 | ||
|
|
9c2decaa19 | ||
|
|
5170c5691a | ||
|
|
79bba3782c | ||
|
|
ca94b38371 | ||
|
|
46f852cda0 | ||
|
|
afa7e01878 | ||
|
|
234ce610e0 | ||
|
|
7b10562370 | ||
|
|
8a25d787d7 | ||
|
|
c770a2422a | ||
|
|
4d1b64f118 | ||
|
|
eb7849e3a2 | ||
|
|
90d9c58d4d | ||
|
|
89a8207029 | ||
|
|
157170059d | ||
|
|
97421eb5ec | ||
|
|
d50d7a2874 | ||
|
|
9cd63d2244 | ||
|
|
f3eb29c653 | ||
|
|
9de6d10d11 | ||
|
|
ab42bf1dab | ||
|
|
d059bf48e4 | ||
|
|
f9613da180 | ||
|
|
6183cf2f19 | ||
|
|
f15083c10a | ||
|
|
66a3ac6a56 | ||
|
|
6ecf4f13f6 | ||
|
|
e6ab52cdd1 | ||
|
|
73acb8b836 | ||
|
|
fbf59d95f6 | ||
|
|
3a8f841612 | ||
|
|
b4ea83249b | ||
|
|
7f8e805c8e | ||
|
|
67c6f3eded | ||
|
|
50395b71a9 | ||
|
|
e3ce54ccee | ||
|
|
609586a16d | ||
|
|
7861260a5f | ||
|
|
7892ad15ab | ||
|
|
dbce685e91 | ||
|
|
8c79100839 | ||
|
|
3a4623afbb | ||
|
|
2605f4f4e6 | ||
|
|
477b0fbeca | ||
|
|
f5954e2d94 | ||
|
|
1ef2d5765b | ||
|
|
b1112bbef1 | ||
|
|
566a30c007 | ||
|
|
e98c029717 | ||
|
|
fd63c8bfcd | ||
|
|
0f65793f94 | ||
|
|
680ab6f83d | ||
|
|
6193105710 | ||
|
|
564fb7d9fa | ||
|
|
ed59bf7a18 | ||
|
|
6852289c46 | ||
|
|
1832ab71db | ||
|
|
98193bb440 | ||
|
|
b7fd2c2822 | ||
|
|
58337e0e61 | ||
|
|
aa115e22df | ||
|
|
fe241ece29 | ||
|
|
ccc52adfb2 | ||
|
|
220818f758 | ||
|
|
a6f348599c | ||
|
|
3a9fdf2747 | ||
|
|
1217204c81 | ||
|
|
51d71ad3d7 | ||
|
|
6c01fb4d68 | ||
|
|
53b24f3518 | ||
|
|
a7a43adb79 | ||
|
|
04559a0d45 | ||
|
|
e4d6bcb6cd | ||
|
|
f2bdc87595 | ||
|
|
15c15da482 | ||
|
|
d287b62b64 | ||
|
|
b74d92755d | ||
|
|
09a6321aeb | ||
|
|
58ef4d9a95 | ||
|
|
667d5f1936 | ||
|
|
eb3036da87 | ||
|
|
6586414bc7 | ||
|
|
5ee8944155 | ||
|
|
eae802459d | ||
|
|
2dd3117c27 | ||
|
|
51f9f9924b | ||
|
|
035aa11403 | ||
|
|
a2865f6b3d | ||
|
|
53f52c2111 | ||
|
|
543bf742c9 | ||
|
|
f863673a90 | ||
|
|
a994eb92a4 | ||
|
|
9d94a28bed | ||
|
|
fd2630e1f7 | ||
|
|
6450f5699f | ||
|
|
40c01ec467 | ||
|
|
c4df747267 | ||
|
|
27f0c34390 | ||
|
|
ae72be1b8b | ||
|
|
a560124cdf | ||
|
|
087dee6e1b | ||
|
|
5755a5c354 | ||
|
|
099125435f | ||
|
|
98a423b75a | ||
|
|
425cc612ad | ||
|
|
400e556b34 | ||
|
|
11800e6198 | ||
|
|
cd94665f38 | ||
|
|
ae60643c15 | ||
|
|
89380c03e9 | ||
|
|
2a8e5c8b11 | ||
|
|
d694c599e2 | ||
|
|
8319b1ab9f | ||
|
|
cf49472d60 | ||
|
|
6ec7460af1 | ||
|
|
6b1e671ac6 | ||
|
|
440adfbdd1 | ||
|
|
f4190c38ba | ||
|
|
000132cbd1 | ||
|
|
37f7098464 | ||
|
|
91b8814f0d | ||
|
|
4911a10a4e | ||
|
|
49cd7387ad | ||
|
|
1aba0bf0fa | ||
|
|
42f5a2fc29 | ||
|
|
3ee208516f | ||
|
|
1db38ae81b | ||
|
|
5489086456 | ||
|
|
8da6772ed4 | ||
|
|
723a68c826 | ||
|
|
7ffa523fd1 | ||
|
|
df716c98d2 | ||
|
|
2f3f413e91 | ||
|
|
02fb6323e0 | ||
|
|
221626e715 | ||
|
|
a7ed1f67ee | ||
|
|
8922346305 | ||
|
|
6a214f3e06 | ||
|
|
d0308073c3 | ||
|
|
e545a7f9a8 | ||
|
|
f5398d374b | ||
|
|
881beb170d | ||
|
|
4bc4da331a | ||
|
|
2c26985835 | ||
|
|
8058dab26e | ||
|
|
0301525e6c | ||
|
|
6814b1dfa1 | ||
|
|
591aab7e21 | ||
|
|
e071f87dc5 | ||
|
|
cac9eb39fe | ||
|
|
dfc6a43b72 | ||
|
|
587b408210 | ||
|
|
8a08813d6c | ||
|
|
2b00e6990c | ||
|
|
58d1de08d9 | ||
|
|
37fa47908b | ||
|
|
4d383f57f4 | ||
|
|
4f7bab7db1 | ||
|
|
6a7b24a3f2 | ||
|
|
cda1fd8ec8 | ||
|
|
663c06e8cd | ||
|
|
cb1248d208 | ||
|
|
7a213ffc69 | ||
|
|
a58efdb69b | ||
|
|
0c4c8f7a9d | ||
|
|
afa7b8a479 | ||
|
|
147f10157f | ||
|
|
464089365e | ||
|
|
c6acb219f9 | ||
|
|
56c82f3d9d | ||
|
|
373e875ac2 | ||
|
|
d03a295192 | ||
|
|
e060c99447 | ||
|
|
e19fb7ebed | ||
|
|
e145ac30e3 | ||
|
|
db5b86ef13 | ||
|
|
59a26360c7 | ||
|
|
82ae0e688c | ||
|
|
46cdc6ad51 | ||
|
|
c722193a91 | ||
|
|
6de5d53416 | ||
|
|
6387830c3b | ||
|
|
259c6d3fbb | ||
|
|
9cd3ff1059 | ||
|
|
8745fade03 | ||
|
|
8cf1719e3e | ||
|
|
1132dd27ea | ||
|
|
154aa7f71a | ||
|
|
31e34fcf93 | ||
|
|
0b5107c016 | ||
|
|
1d0bafb74d | ||
|
|
ca3d9f8b31 | ||
|
|
ef902274fd | ||
|
|
e855c7e2c9 | ||
|
|
969a14599d | ||
|
|
34a85c5405 | ||
|
|
055e803851 | ||
|
|
00c98a6bef | ||
|
|
209927bb27 | ||
|
|
1fb30e6d50 | ||
|
|
8f6146a7bc | ||
|
|
242a99c95a | ||
|
|
533250a4a3 | ||
|
|
831c7aa410 | ||
|
|
5863987bba | ||
|
|
998b977ede | ||
|
|
d49ef039dd | ||
|
|
5a6d50998d | ||
|
|
f2467eb6a0 | ||
|
|
3b859ead37 | ||
|
|
34ea91b259 | ||
|
|
0837348049 | ||
|
|
b8fb0ce563 | ||
|
|
5144abe5b6 | ||
|
|
3e94ffffd6 | ||
|
|
446b827bae | ||
|
|
480dda0e42 | ||
|
|
117670be57 | ||
|
|
8be1979f1a | ||
|
|
85799bf89e | ||
|
|
25de80e2b6 | ||
|
|
19d9762ad5 | ||
|
|
cb79e91ec3 | ||
|
|
457dd55962 | ||
|
|
4b83483142 | ||
|
|
7f38087f35 | ||
|
|
ea402a255f | ||
|
|
4b23900ff1 | ||
|
|
b006a31d52 | ||
|
|
2e0322efd1 | ||
|
|
bd50c01972 | ||
|
|
b461721f17 | ||
|
|
005d1e4ccb | ||
|
|
605b16cd7b | ||
|
|
d645633643 | ||
|
|
35355fc1fc | ||
|
|
7b22bec252 | ||
|
|
1d487dc6a6 | ||
|
|
2b4964f319 | ||
|
|
56042a120a | ||
|
|
8afd28a922 | ||
|
|
1c94524458 | ||
|
|
6fe13e6aba | ||
|
|
bd013b6f98 | ||
|
|
5e57047d87 | ||
|
|
58ac7a17a4 | ||
|
|
e9fc91df45 | ||
|
|
d5a5a83ad4 | ||
|
|
ec2827f5fc | ||
|
|
4055a3b19c | ||
|
|
fb95455c02 | ||
|
|
67444f5e54 | ||
|
|
f491ae97d4 | ||
|
|
2bda12ef3b | ||
|
|
ce86a9a0ae | ||
|
|
baa0501cc1 | ||
|
|
4c9fdd2cd6 | ||
|
|
330df4b4db | ||
|
|
18047d4625 | ||
|
|
126c7317bc | ||
|
|
ddd0ce534a | ||
|
|
02f1363e19 | ||
|
|
4e624849b6 | ||
|
|
2a3f4110c5 | ||
|
|
7ae763e16b | ||
|
|
6245f0d529 | ||
|
|
c5d9ccd810 | ||
|
|
f86fca9b70 | ||
|
|
9fe24c5a0d | ||
|
|
d4e6b9f2d6 | ||
|
|
a7366a764a | ||
|
|
b52966e821 | ||
|
|
35f2a6ba82 | ||
|
|
adaf64a99b | ||
|
|
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 | ||
|
|
543988572e | ||
|
|
c0340eec5a | ||
|
|
0304fda3cf | ||
|
|
aeae0beba4 | ||
|
|
3854fc9b42 | ||
|
|
9db190eb31 | ||
|
|
d6c8b995c5 | ||
|
|
c931a7aec5 | ||
|
|
b1eb252172 | ||
|
|
eac93d6efe | ||
|
|
a0be433fec | ||
|
|
f1a6b97639 | ||
|
|
3dd02580e3 | ||
|
|
d787285af9 | ||
|
|
5833243c92 | ||
|
|
100becf8d1 | ||
|
|
d7ca6f44eb | ||
|
|
542fc69062 | ||
|
|
4d57776813 | ||
|
|
e4720b1a79 | ||
|
|
7d0444e244 | ||
|
|
8062d3af30 | ||
|
|
de79d23f76 | ||
|
|
365f3028dd | ||
|
|
f42a505ab7 | ||
|
|
77f7a6d591 | ||
|
|
d3bba0c2d8 | ||
|
|
9737a7eba0 | ||
|
|
bd48fd97f6 | ||
|
|
703e5a2ce2 | ||
|
|
812fae424e | ||
|
|
d92ccbf1ac | ||
|
|
1a211d812f | ||
|
|
a4f0365b2d | ||
|
|
3d38a49840 | ||
|
|
f69626ed3e | ||
|
|
a07c68f05e | ||
|
|
bf658f016f | ||
|
|
1e24cbaba3 | ||
|
|
bdf089f463 | ||
|
|
06699d4219 | ||
|
|
5693b8a7e2 | ||
|
|
e60c962fb8 | ||
|
|
1db6259076 | ||
|
|
a3883cbd28 | ||
|
|
fb9368b5a0 | ||
|
|
4aced7f8d0 | ||
|
|
26def5392f | ||
|
|
3d71c8013e | ||
|
|
14fbf85380 | ||
|
|
0c4828ea05 | ||
|
|
e11e6fb1c6 | ||
|
|
8a788e38ac | ||
|
|
11ccd44e95 | ||
|
|
43535499f3 | ||
|
|
e0b7fb8f27 | ||
|
|
2dc6d50941 | ||
|
|
0b305c534f | ||
|
|
a247d20604 | ||
|
|
02934b1200 | ||
|
|
b2ba62170c | ||
|
|
8ac06726b9 | ||
|
|
3f66cfb96b | ||
|
|
4dee289550 | ||
|
|
cf7e645a48 | ||
|
|
41c45a9b31 | ||
|
|
64c3325b0b | ||
|
|
76feaf016a | ||
|
|
e879a0371b | ||
|
|
b0c11cda7e | ||
|
|
64fd29855a | ||
|
|
8dadcede65 | ||
|
|
7119d38287 | ||
|
|
705868a8a9 | ||
|
|
95f4f2cf61 | ||
|
|
36a23e86b6 | ||
|
|
bfa6ee7d91 | ||
|
|
71dfe4b90b | ||
|
|
450837bcc8 | ||
|
|
4aa9245083 | ||
|
|
923736df38 | ||
|
|
e4907411c2 | ||
|
|
bf0dde9597 | ||
|
|
e2e168f7c2 | ||
|
|
80e722278c | ||
|
|
20acd43c25 | ||
|
|
766f708418 | ||
|
|
df50916e46 | ||
|
|
e41ecbf730 | ||
|
|
e437b08250 | ||
|
|
1a396f3789 | ||
|
|
95deba581d | ||
|
|
1e5f5ea2e9 | ||
|
|
034f608e00 | ||
|
|
f58f51f380 | ||
|
|
955d11aae7 | ||
|
|
c67eccc26d | ||
|
|
2c8e070e5d | ||
|
|
ed133e6e64 | ||
|
|
2de17f4edc | ||
|
|
86f65edf4e | ||
|
|
b75e1043a3 | ||
|
|
8ec6594d6d | ||
|
|
12721a3a9a | ||
|
|
5fb824e896 | ||
|
|
5c5ab2bc12 | ||
|
|
6846ed8b44 | ||
|
|
5f9aad44ca | ||
|
|
d7875d1648 | ||
|
|
587dc8aa00 | ||
|
|
fd9c77dfc7 | ||
|
|
750be19ae8 | ||
|
|
7f893b7a43 | ||
|
|
315d8fbd75 | ||
|
|
6d6200f37a | ||
|
|
7af6a2fd71 | ||
|
|
532d766c27 | ||
|
|
7e043d28a6 | ||
|
|
60b632b173 | ||
|
|
a0d29040f7 | ||
|
|
af09fe12dd | ||
|
|
d63375d529 | ||
|
|
4c21c016c5 | ||
|
|
bcec46057c | ||
|
|
a17071fef1 | ||
|
|
560ab22f7d | ||
|
|
8b7f8b56f1 | ||
|
|
87ef5907e9 | ||
|
|
819548d92f | ||
|
|
3e5e0faf9c | ||
|
|
bf87cc44b4 | ||
|
|
b57189174f | ||
|
|
f16fe2af8d | ||
|
|
d1f6c0cbe3 | ||
|
|
07ca66cf24 | ||
|
|
1ab67cf437 | ||
|
|
89865da76d | ||
|
|
a443c7573b | ||
|
|
8bcdd36f10 | ||
|
|
da52f8bea0 | ||
|
|
7343e6c8ae | ||
|
|
b92a2e5cc2 | ||
|
|
93cd5a4a13 | ||
|
|
32539e41d5 | ||
|
|
b2235d81d1 | ||
|
|
aa45027818 | ||
|
|
8032f26ca0 | ||
|
|
bd25ac2260 | ||
|
|
81a4b4e49b | ||
|
|
1a8eb6e3ec | ||
|
|
83dfa89870 | ||
|
|
01e58adce0 | ||
|
|
83d7b89660 | ||
|
|
e2d5e40f4f | ||
|
|
84ce7ac76f | ||
|
|
4750065ada | ||
|
|
a0e3b84fac | ||
|
|
f92c9a0ac5 | ||
|
|
4bab25a28d | ||
|
|
7fa338f4ba | ||
|
|
c82782f9a5 | ||
|
|
c778ed1768 | ||
|
|
ef337f7089 | ||
|
|
6199f9b93e | ||
|
|
2398af13c5 | ||
|
|
d77331d32f | ||
|
|
2be6118f4c | ||
|
|
0bc468f195 | ||
|
|
ee0384fb96 | ||
|
|
ebade9ff8b | ||
|
|
2d7636529f | ||
|
|
6bbfe95e30 | ||
|
|
7148df7971 | ||
|
|
6f0f16497a | ||
|
|
cae4efdca3 | ||
|
|
0777448ca6 | ||
|
|
fe2d869e04 | ||
|
|
d66ea83a76 | ||
|
|
f3b8833a48 | ||
|
|
efc7a579e8 | ||
|
|
55b5ddd3ca | ||
|
|
b7ff69eb7c | ||
|
|
5c31995bb8 | ||
|
|
8bb0210fea | ||
|
|
8ca4a001cb | ||
|
|
497e4ad126 | ||
|
|
02c1dac909 | ||
|
|
04c4bd3624 | ||
|
|
e41b5828db | ||
|
|
d39d3c6264 | ||
|
|
267dc693d2 | ||
|
|
81de12bc8f | ||
|
|
110d155778 | ||
|
|
9985230c00 | ||
|
|
816dd3f061 | ||
|
|
011b5da0f4 | ||
|
|
85d13c8f93 | ||
|
|
816f9c0f6f | ||
|
|
7d47498b5e | ||
|
|
ac1e8f40d4 | ||
|
|
10e8b1fd15 | ||
|
|
0d272fca79 | ||
|
|
d4f0b0fc6c | ||
|
|
a60317f20f | ||
|
|
4d6ad5be17 | ||
|
|
ed711f73bc | ||
|
|
db90b88e65 | ||
|
|
4e49002576 | ||
|
|
c3f228f296 | ||
|
|
aac5fcfbb5 | ||
|
|
f3dc7ab877 | ||
|
|
b7b3dd55f9 | ||
|
|
7e048eddf5 | ||
|
|
af2a372bb0 | ||
|
|
9a64454faa | ||
|
|
fc92244ba8 | ||
|
|
a353aef0b1 | ||
|
|
a5ece7d016 | ||
|
|
c172274e17 | ||
|
|
7b851915bf | ||
|
|
95cc417d76 | ||
|
|
71f026292b | ||
|
|
dc31305b38 | ||
|
|
979f163615 | ||
|
|
d8cd3115d8 | ||
|
|
55e207b2dc | ||
|
|
3d94be61ea | ||
|
|
5187678913 | ||
|
|
f061086a93 | ||
|
|
09381cccff | ||
|
|
13c2adc897 | ||
|
|
4c53ca2692 | ||
|
|
471419d1fa | ||
|
|
eb07a4f1ee | ||
|
|
7f19e03c65 | ||
|
|
47df476daa | ||
|
|
c9170be2bd | ||
|
|
c3aa615a5f | ||
|
|
5b72d8a749 | ||
|
|
d78a05ab40 | ||
|
|
31428c3a06 | ||
|
|
52090d2418 | ||
|
|
e3f32ac5af | ||
|
|
807a67bc74 | ||
|
|
392811eb8f | ||
|
|
d96cdcea6b | ||
|
|
3d2b835f30 | ||
|
|
45d822f29c | ||
|
|
cad8726b2c | ||
|
|
8da118e4d0 | ||
|
|
c2ba4313fb | ||
|
|
25eedf085d | ||
|
|
3c9f8fc9b6 | ||
|
|
f450384ded | ||
|
|
ef8bd919fc | ||
|
|
8a10360c91 | ||
|
|
7482349fe8 | ||
|
|
0fd3648d34 | ||
|
|
b70bd8fe56 | ||
|
|
d31c59eb17 | ||
|
|
e8f7978274 | ||
|
|
0910ae9568 | ||
|
|
90039e0863 | ||
|
|
71be50cc25 | ||
|
|
3bfd3a4e95 | ||
|
|
f71ea9c911 | ||
|
|
141294ff38 | ||
|
|
74299c1cfb | ||
|
|
c4cfb392d3 | ||
|
|
8e3d98eb41 | ||
|
|
f0c473c5f7 | ||
|
|
fe1b8781ae | ||
|
|
741b7577c1 | ||
|
|
2fb0df83e9 | ||
|
|
13cce8ec45 | ||
|
|
e020d80e4e | ||
|
|
05e15049a5 | ||
|
|
070057c1b9 | ||
|
|
c752c9f41a | ||
|
|
2e8eaca573 | ||
|
|
03afc34805 | ||
|
|
1a65142ec4 | ||
|
|
4c356acd04 | ||
|
|
44f6e6de77 | ||
|
|
2e4ef03aa3 | ||
|
|
05fbf61f0e | ||
|
|
04791840f4 | ||
|
|
bc6f7fc139 | ||
|
|
fb6e223ddc | ||
|
|
5ff87c982e | ||
|
|
e14e2399ed | ||
|
|
158aa89317 | ||
|
|
56af8e86e3 | ||
|
|
3f9e647ae8 | ||
|
|
d8c5745c41 | ||
|
|
e07d7284a2 | ||
|
|
5414b3b2db | ||
|
|
594eaddd11 | ||
|
|
966ffb29a7 | ||
|
|
24035b98b1 | ||
|
|
e42401ee7b | ||
|
|
af565c348a | ||
|
|
e33f67ff0b | ||
|
|
84a4dd5ff0 | ||
|
|
cfe742cfc5 | ||
|
|
6baa2a2f5e | ||
|
|
9fd85c94de | ||
|
|
fefd467539 | ||
|
|
21b134b4e5 | ||
|
|
a3c63d0d6c | ||
|
|
90b6352d0a | ||
|
|
fae0427324 | ||
|
|
fa6a4fcb11 | ||
|
|
5954eadf67 | ||
|
|
bb82310dba | ||
|
|
69d9df7fe6 | ||
|
|
462bd50aef | ||
|
|
8520de4720 | ||
|
|
dc6d1ec67e | ||
|
|
63b09c5e41 | ||
|
|
0efc986ba1 | ||
|
|
b4e6d98fc3 | ||
|
|
7db2831d3a | ||
|
|
5ccb6f64f4 | ||
|
|
2b20318b0e | ||
|
|
9cda616949 | ||
|
|
c4d388add4 | ||
|
|
103cfee056 | ||
|
|
299ff64812 | ||
|
|
1930570ad9 | ||
|
|
9c9a88e9e2 | ||
|
|
762cee72cc | ||
|
|
268f9aaf28 | ||
|
|
836e5b6f57 | ||
|
|
77cb9e3fb1 | ||
|
|
885e22b16e | ||
|
|
cfb09e0fad | ||
|
|
e0305bb7a8 | ||
|
|
a053d2d8e5 | ||
|
|
dbddac0fe9 | ||
|
|
c1a07f9445 | ||
|
|
eaaa13ce47 | ||
|
|
68e55cd9da | ||
|
|
3b3e1025c3 | ||
|
|
20186a4079 | ||
|
|
d0bf4adb1f | ||
|
|
e08dbff9a8 | ||
|
|
e1e91a3731 | ||
|
|
817f4f7908 | ||
|
|
f36b7e7579 | ||
|
|
719cebcac2 | ||
|
|
443673620d | ||
|
|
7ec5a65925 | ||
|
|
c9b2d80bcd | ||
|
|
3cfe65e516 | ||
|
|
e51a276907 | ||
|
|
408913bbaf | ||
|
|
4e17be7981 | ||
|
|
f859a8d3c3 | ||
|
|
c45de33c67 | ||
|
|
d0c32dc135 | ||
|
|
f56a039775 | ||
|
|
bc1e478db1 | ||
|
|
4d8a85b8f5 | ||
|
|
3ce5f07793 | ||
|
|
e839802720 | ||
|
|
4bbbe25802 | ||
|
|
2723d9b56e | ||
|
|
07ffdc2862 | ||
|
|
ad529fb89f | ||
|
|
fdcaf37361 | ||
|
|
50e34891f0 | ||
|
|
5388944e8d | ||
|
|
f0c0277970 | ||
|
|
ef92a14bfe | ||
|
|
945d8218fb | ||
|
|
d8a5dc02fc | ||
|
|
3a78af1e24 | ||
|
|
7ca9972636 | ||
|
|
c4c84d1edb | ||
|
|
bcd6cdf0d8 | ||
|
|
13618b191e | ||
|
|
aa5a768720 | ||
|
|
9b8fda796b | ||
|
|
8022015552 | ||
|
|
f9e766db98 | ||
|
|
ca50c83fbb | ||
|
|
3d55f1eb57 | ||
|
|
ae6bf87273 | ||
|
|
c364d5d1e3 | ||
|
|
4f7e5f5810 | ||
|
|
8824d60fe5 | ||
|
|
997db91e07 | ||
|
|
3392d32e8b | ||
|
|
327a232c85 | ||
|
|
c60d796f04 | ||
|
|
e8bad77c7c | ||
|
|
7680904839 | ||
|
|
58f3338bfa | ||
|
|
268d90a03e | ||
|
|
1ff8758f76 | ||
|
|
8520542071 | ||
|
|
6b9f6b0222 | ||
|
|
deb342fb08 | ||
|
|
437077c39d | ||
|
|
6f7d7bc1de | ||
|
|
53a4981fa2 | ||
|
|
18f0ff003d | ||
|
|
96f1517831 | ||
|
|
1a8f8fd86f | ||
|
|
0f79ad47c5 | ||
|
|
c7057fc1f2 | ||
|
|
193f59e077 | ||
|
|
0ae2be5692 | ||
|
|
1332dd1ed3 | ||
|
|
63a17d4bd5 | ||
|
|
676e07902e | ||
|
|
64e89980e8 | ||
|
|
48b58617e9 | ||
|
|
51ad64cc07 | ||
|
|
df05a759e4 | ||
|
|
d3de71efc9 | ||
|
|
e1df4ef73c | ||
|
|
86408b3f47 | ||
|
|
57e0d73c77 | ||
|
|
0dbd4638e0 | ||
|
|
3bca8931e8 | ||
|
|
5e9a4e5101 | ||
|
|
9b46d1ae6f | ||
|
|
20b6f94b65 | ||
|
|
d413612029 | ||
|
|
1f169f43b3 | ||
|
|
5e2e2f10ef | ||
|
|
c6890d6b5c | ||
|
|
749dd97a54 | ||
|
|
f2c3fc5191 | ||
|
|
a2fc3a53ba | ||
|
|
d53603c928 | ||
|
|
14bc3ce3d6 | ||
|
|
f24cf5d303 | ||
|
|
c6cb792d48 | ||
|
|
a64bbe049e | ||
|
|
d407d572fd | ||
|
|
e42975490f | ||
|
|
50d11b90ca | ||
|
|
c34e6d71bc | ||
|
|
9536ba19d4 | ||
|
|
83bd320b39 | ||
|
|
f751c2966b | ||
|
|
404996ca1f | ||
|
|
7660e2a068 | ||
|
|
52a9ba96f5 | ||
|
|
6a5599fd01 | ||
|
|
098cb9d233 | ||
|
|
c710fe540e | ||
|
|
d5eab2fc82 | ||
|
|
8f1bf28505 | ||
|
|
4e646b0ddb | ||
|
|
0460ea4c39 | ||
|
|
dfb863f333 | ||
|
|
435a93b5d8 | ||
|
|
8b2a01a8c2 | ||
|
|
50cb6f9782 | ||
|
|
351bf658f9 | ||
|
|
cff2b2a13a | ||
|
|
160a60d663 | ||
|
|
805144b705 | ||
|
|
096affb55b | ||
|
|
cbc1f57b48 | ||
|
|
7377195297 | ||
|
|
737423a89c | ||
|
|
47706e3924 | ||
|
|
6e946c8e72 | ||
|
|
c7152c8f97 | ||
|
|
3a2bbe7f8a | ||
|
|
7fb548aa26 | ||
|
|
f54e800366 | ||
|
|
38f98b3282 | ||
|
|
e23a7a8b7b | ||
|
|
cb85bc396e | ||
|
|
61686926d1 | ||
|
|
9856efc7b0 | ||
|
|
5dd8fb2069 | ||
|
|
92f525ecf4 | ||
|
|
7024a1ef07 | ||
|
|
8146a0c731 | ||
|
|
a046858a22 | ||
|
|
12c8c64efa | ||
|
|
7aedcf9460 | ||
|
|
3a87163b24 | ||
|
|
cacff1be88 | ||
|
|
58969fa2bf | ||
|
|
d7b2d11255 | ||
|
|
7a57b2920b | ||
|
|
77d272623f | ||
|
|
7e05b8b75e | ||
|
|
b88460bcbc | ||
|
|
2897286487 | ||
|
|
e530e0a350 | ||
|
|
9485ec31ea | ||
|
|
13df3915ef | ||
|
|
c183ee5c79 | ||
|
|
1dcf208f56 | ||
|
|
93b6926054 | ||
|
|
51e7e32c3b | ||
|
|
2d5114452d | ||
|
|
33ecb42991 | ||
|
|
be88248add | ||
|
|
a96cac0d18 | ||
|
|
d4753c944f | ||
|
|
0e6f604178 | ||
|
|
7f254706b0 | ||
|
|
1273d355ac | ||
|
|
d4ca5c3952 | ||
|
|
fd2e14b3c8 | ||
|
|
60cb7de336 | ||
|
|
8ab6bc5a49 | ||
|
|
f052c10eed | ||
|
|
a7cee528c5 | ||
|
|
041717eda3 | ||
|
|
621093cb1c | ||
|
|
824b154ce8 | ||
|
|
2ef579d1aa | ||
|
|
1407a1ec99 | ||
|
|
1bb0f1e84b | ||
|
|
b682fae9d9 | ||
|
|
6f8c96d123 | ||
|
|
110606d470 | ||
|
|
061141e632 | ||
|
|
019176137f | ||
|
|
4ce692df88 | ||
|
|
c504d90c11 | ||
|
|
8e39d9bdb3 | ||
|
|
28355dafcf | ||
|
|
8fce03e0ad | ||
|
|
60ec75048a | ||
|
|
6f6bb1fdea | ||
|
|
92cb7c4dfe | ||
|
|
0008b0006d | ||
|
|
ac36c6cd44 | ||
|
|
2b70a8e7c9 | ||
|
|
9122dcecbb | ||
|
|
6776a52bb3 | ||
|
|
d86bd22d24 | ||
|
|
ac5478eb52 | ||
|
|
652817046b | ||
|
|
5a569509b4 | ||
|
|
7c54f1603f | ||
|
|
07cdfb09fb | ||
|
|
a0766eca27 | ||
|
|
cd16d5dc3d | ||
|
|
5b949241a5 | ||
|
|
67958f21df | ||
|
|
d91dc086bb | ||
|
|
9ac3f5df9c | ||
|
|
bcfe98acff | ||
|
|
9850262a72 | ||
|
|
909fbb9de1 | ||
|
|
5dfba0b4db | ||
|
|
9ccdb80de3 | ||
|
|
9fd9c4c635 | ||
|
|
63b8f09d8d | ||
|
|
f8713e1287 | ||
|
|
82ae85de27 | ||
|
|
5eaf644c99 | ||
|
|
cdee317419 | ||
|
|
d95b68fde3 | ||
|
|
ff762fb499 | ||
|
|
1307b22223 | ||
|
|
64519cfd65 | ||
|
|
09bc0c502c | ||
|
|
5d4eb9dd07 | ||
|
|
0c478d2f4d | ||
|
|
5024bde8f4 | ||
|
|
2ab09a55cf | ||
|
|
6bbff48079 | ||
|
|
b8eb32f4d2 | ||
|
|
bba87589cc | ||
|
|
f3e2e6076a | ||
|
|
53cca4a445 | ||
|
|
4213b8d8ec | ||
|
|
eb86b6f5a5 | ||
|
|
3d2035ea86 | ||
|
|
285d26374a | ||
|
|
a55113411f | ||
|
|
c202523e53 | ||
|
|
aab530e971 | ||
|
|
60564410ef | ||
|
|
2668a43388 | ||
|
|
63ccd72496 | ||
|
|
e13da525a7 | ||
|
|
5d250ad1ea | ||
|
|
7509d70f9d | ||
|
|
2369b122d1 | ||
|
|
6c2c771af7 | ||
|
|
07d3a38726 | ||
|
|
f5325d292d | ||
|
|
fa791116a3 | ||
|
|
3f4ed681c2 | ||
|
|
6fedb7aa0f | ||
|
|
a519bb0635 | ||
|
|
96598e7b06 | ||
|
|
4166b11a53 | ||
|
|
2b7c839b4e | ||
|
|
709b55ee02 | ||
|
|
c98ea254dc | ||
|
|
9d6d50269b | ||
|
|
fa61ee70ee | ||
|
|
f32fef1b07 | ||
|
|
4af2fdba6d | ||
|
|
c987061aa4 | ||
|
|
77afd97a99 | ||
|
|
7ab68961e4 | ||
|
|
2b2aa8a820 | ||
|
|
7933cdc6dc | ||
|
|
0f0dbe8c0c | ||
|
|
311c222f47 | ||
|
|
2a01d06da6 | ||
|
|
7718b19389 | ||
|
|
9cc0da8453 | ||
|
|
99dc3e613a | ||
|
|
d06be428f6 | ||
|
|
abec1c0004 | ||
|
|
c4f1c2114b | ||
|
|
49829da8b4 | ||
|
|
b428adc267 | ||
|
|
cc826dc03e | ||
|
|
51e2dda58c | ||
|
|
b7ff182b6e | ||
|
|
ca07f3e370 | ||
|
|
9279174dde | ||
|
|
db4f4a8425 | ||
|
|
1b962fc720 | ||
|
|
e818838412 | ||
|
|
efe4b690ae | ||
|
|
c03b729319 | ||
|
|
5664b6d7ba | ||
|
|
b455c4c45c | ||
|
|
72f3ea7358 | ||
|
|
98b07466fb | ||
|
|
339c142009 | ||
|
|
a87b5256e2 | ||
|
|
001b3f06ec | ||
|
|
7592f48c83 | ||
|
|
a1d310b6b5 | ||
|
|
42043953c3 | ||
|
|
5adbb0aabe | ||
|
|
5b1052663a | ||
|
|
c4f98941ed | ||
|
|
03427e76f1 | ||
|
|
b3c26180e3 | ||
|
|
3c92ea399d | ||
|
|
fc691e1cbd | ||
|
|
096198d11f | ||
|
|
660244f65f | ||
|
|
e139d7fc68 | ||
|
|
989176c56e | ||
|
|
8bc591a6f0 | ||
|
|
15f39aba8c | ||
|
|
7cd88b1dec | ||
|
|
d567baabbd | ||
|
|
b3b0b2a29e | ||
|
|
6c8641a542 | ||
|
|
5af84139a8 | ||
|
|
d3aa183beb | ||
|
|
a8f3b02092 | ||
|
|
a72709afd8 | ||
|
|
934c58aa38 | ||
|
|
ee8f15930d | ||
|
|
f351834f77 | ||
|
|
94fd46fa1c | ||
|
|
955b8841cd | ||
|
|
18e27629d3 | ||
|
|
826b271d9a | ||
|
|
30c9f909b2 | ||
|
|
194c66eeeb | ||
|
|
f903d86740 | ||
|
|
ce85b55cf0 | ||
|
|
4532e4b90d | ||
|
|
2818b7cee6 | ||
|
|
997b95a4af | ||
|
|
b0e92f6d47 | ||
|
|
4ed01ed791 | ||
|
|
c41a3ec3a9 | ||
|
|
bd955e15e1 | ||
|
|
9819bb20da | ||
|
|
b4bc8b7616 | ||
|
|
b1e321d6ce | ||
|
|
658816ddc9 | ||
|
|
72034ab35d | ||
|
|
f8985d195e | ||
|
|
329025253d | ||
|
|
5bb08db55b | ||
|
|
98968fbb63 | ||
|
|
2f1e2cf632 | ||
|
|
f106868110 | ||
|
|
f789ea1d09 | ||
|
|
d7caac3e81 | ||
|
|
11d512e7a8 | ||
|
|
0a84137c45 | ||
|
|
0ed89c569f | ||
|
|
4066f450c2 | ||
|
|
e7bdde981f | ||
|
|
66c51dc215 | ||
|
|
5b5a3af983 | ||
|
|
5eb5c23447 | ||
|
|
7d0f6aed59 | ||
|
|
895c953817 | ||
|
|
d4117859d6 | ||
|
|
e0ca671491 | ||
|
|
6bdecfacbb | ||
|
|
454f571f87 | ||
|
|
4c82983010 | ||
|
|
f60aa2aa21 | ||
|
|
dedd62dd0c | ||
|
|
b5ddcf58ad | ||
|
|
59707975a3 | ||
|
|
de012e76e2 | ||
|
|
2196cb67c5 | ||
|
|
df303666bc | ||
|
|
1e90b4189d | ||
|
|
485d71c54a | ||
|
|
30e4653783 | ||
|
|
4ff1335b2e | ||
|
|
3a2833daff | ||
|
|
764b0115d5 | ||
|
|
b42ef9c054 | ||
|
|
d4950f207f | ||
|
|
6d6c68c0d2 | ||
|
|
633518628f | ||
|
|
12d0a1eb75 | ||
|
|
06f95dd07c | ||
|
|
c370755583 | ||
|
|
c05783ad67 | ||
|
|
6784b14241 | ||
|
|
ca210d2a58 | ||
|
|
149e273023 | ||
|
|
bfec245efa | ||
|
|
6fc60e2060 | ||
|
|
5b74a59570 | ||
|
|
5f8a203b55 | ||
|
|
1511aa11ce | ||
|
|
fa44e401a8 | ||
|
|
e007b50eb7 | ||
|
|
bfea7b1f35 | ||
|
|
0b95603595 | ||
|
|
42d80d1170 | ||
|
|
d91cd30563 | ||
|
|
dc6f373842 | ||
|
|
9397cd30c8 | ||
|
|
0b4ed64d29 | ||
|
|
cd08fb3fde | ||
|
|
d423968ba1 | ||
|
|
612b3e8fa3 | ||
|
|
35ac16e75e | ||
|
|
1db187ff69 | ||
|
|
f90d85107e | ||
|
|
f8ed2e64a5 | ||
|
|
f529a3be8a | ||
|
|
14e47e9c2c | ||
|
|
d04291cfab | ||
|
|
315183f194 | ||
|
|
a8629de827 | ||
|
|
27a0662828 | ||
|
|
8a9fe6c11c | ||
|
|
27f57c9018 | ||
|
|
f3441e6122 | ||
|
|
26f981c2e5 | ||
|
|
c8ea8a09b8 | ||
|
|
055608227f | ||
|
|
3339f85447 | ||
|
|
9441550acb | ||
|
|
7b20c0ed4b | ||
|
|
0d65fc08e2 | ||
|
|
cb1c1004cd | ||
|
|
c970b28ba0 | ||
|
|
bc0429b1cd | ||
|
|
e0d7e47862 | ||
|
|
455a7b9577 | ||
|
|
7d5836b34d | ||
|
|
2629998e91 | ||
|
|
dbc0170ed9 | ||
|
|
5c793ad03e | ||
|
|
ffa1c61cd5 | ||
|
|
a7e1a51fdf | ||
|
|
550ba9ebb4 | ||
|
|
3757ee589f | ||
|
|
59afc1a15c | ||
|
|
9e975458b4 | ||
|
|
4695f4edd6 | ||
|
|
911bc01454 | ||
|
|
5e52df18fe | ||
|
|
c5e934dcc9 | ||
|
|
f881f7a017 | ||
|
|
ef240bc0d5 | ||
|
|
d71cc503a6 | ||
|
|
4cad125e08 | ||
|
|
6da6fbfbe9 | ||
|
|
6d1a1191b0 | ||
|
|
9d9e1c5c41 | ||
|
|
9bff7ad728 | ||
|
|
f3ebd03bb1 | ||
|
|
40b6f06f09 | ||
|
|
b47da5ea21 | ||
|
|
bddc83a148 | ||
|
|
ca00aa1171 | ||
|
|
7046c35843 | ||
|
|
e5da9c8803 | ||
|
|
30beeb27a9 | ||
|
|
34d4c9388b | ||
|
|
93aefd9fc0 | ||
|
|
a9d15d4f43 | ||
|
|
cbfac2fdcc | ||
|
|
644946feed | ||
|
|
bd1f66453a | ||
|
|
e20f0da22c | ||
|
|
89c1d2b202 | ||
|
|
a46db5d013 | ||
|
|
3d05166086 | ||
|
|
b7f0f65c19 | ||
|
|
5dc05b76ab | ||
|
|
5f2492eaec | ||
|
|
0a8eeea9d8 | ||
|
|
2716f9bc5f | ||
|
|
ae7990cc88 | ||
|
|
4caca58ff7 | ||
|
|
17b506c0c7 | ||
|
|
efd31139df | ||
|
|
d303b389a9 | ||
|
|
7edd2e2cd2 | ||
|
|
f3584ff535 | ||
|
|
803cb6e3b9 | ||
|
|
a8ea4cbcc8 | ||
|
|
8ab229ddf2 | ||
|
|
b2b6cf3fc8 | ||
|
|
eb2dd4815c | ||
|
|
917e06bf63 | ||
|
|
df0283ae86 | ||
|
|
30394a4f3f | ||
|
|
db1973d012 | ||
|
|
b4a040e52b | ||
|
|
2ea3bebc23 | ||
|
|
044b6482c1 | ||
|
|
adce01a8d0 | ||
|
|
363e307fd3 | ||
|
|
ddde8e2f32 | ||
|
|
27bb0ac7d2 | ||
|
|
fa2be32034 | ||
|
|
4c5e6d1a2f | ||
|
|
024a8ed382 | ||
|
|
7f6161ab3a | ||
|
|
0db450024d | ||
|
|
9da367b7d5 | ||
|
|
881feb9698 | ||
|
|
65f195f4c7 | ||
|
|
bdadb98de8 | ||
|
|
0f5da8a83c | ||
|
|
dc7d594776 | ||
|
|
43c4d18c6a | ||
|
|
46e0919ced | ||
|
|
6c9fdb17fb | ||
|
|
b824a1daee | ||
|
|
3390c1be76 | ||
|
|
8181a1c3bb | ||
|
|
46605fb4f5 | ||
|
|
52d03276dd | ||
|
|
451dbf687f | ||
|
|
f52de527c7 | ||
|
|
b618fa6eb6 | ||
|
|
c558b1583c | ||
|
|
18e6096105 | ||
|
|
7349bd0176 | ||
|
|
7dedbd896a | ||
|
|
84a84afb0e | ||
|
|
fac63d6416 | ||
|
|
bae75ca5a1 | ||
|
|
36d9258c0d | ||
|
|
7bc30e1ca8 | ||
|
|
71ceb1c161 | ||
|
|
e4b0666f8e | ||
|
|
63f3ce6d9a | ||
|
|
8f67b35886 | ||
|
|
8659edc098 | ||
|
|
e418976107 | ||
|
|
4e329f173f | ||
|
|
afe23b5f38 | ||
|
|
f25f900045 | ||
|
|
215505bb46 | ||
|
|
f23dcdd603 | ||
|
|
05879db628 | ||
|
|
5011588459 | ||
|
|
792878af91 | ||
|
|
11158028be | ||
|
|
1b7840b949 | ||
|
|
69c8b5b8a7 | ||
|
|
1f3722bd4a | ||
|
|
50bdec410a | ||
|
|
4c63f9fe04 | ||
|
|
57969b95b3 | ||
|
|
cafaceb707 | ||
|
|
1073b1780a | ||
|
|
a3e6415ba8 | ||
|
|
b438d37558 | ||
|
|
3130f1f0fa | ||
|
|
7ace29dae7 | ||
|
|
1a7e88bbd9 | ||
|
|
5e6699188f | ||
|
|
b17677462c | ||
|
|
5f681988f2 | ||
|
|
fa33303146 | ||
|
|
06c4929958 | ||
|
|
9dbfe242e3 | ||
|
|
d3fe6ab024 | ||
|
|
096194ab29 | ||
|
|
6833e8bbe8 | ||
|
|
e24d0201c2 | ||
|
|
2819eb36a4 | ||
|
|
4ca01065c3 | ||
|
|
d03f0d4117 | ||
|
|
c3286ec020 | ||
|
|
a82d80ddeb | ||
|
|
f76fdb6d42 | ||
|
|
ec23ecc64d | ||
|
|
a0a43c3206 | ||
|
|
6a07ff1ec0 | ||
|
|
7d8cf316ee | ||
|
|
a45c498e4e | ||
|
|
813a7c65c9 | ||
|
|
6a8e60913a | ||
|
|
79875c5e42 | ||
|
|
62ab131412 | ||
|
|
f07ac41656 | ||
|
|
173d328351 | ||
|
|
ef281b93c2 | ||
|
|
a14d491f09 | ||
|
|
6e5ec1029a | ||
|
|
751f6d2157 | ||
|
|
9f0efa6611 | ||
|
|
2b558843a2 | ||
|
|
44cad9630f | ||
|
|
6f0d050324 | ||
|
|
4c1c37d0b6 | ||
|
|
8d1854c3f1 | ||
|
|
99655245ae | ||
|
|
62b0497c0f | ||
|
|
c808e6252f | ||
|
|
fd4a9db91f | ||
|
|
fc1c20d11b | ||
|
|
a9c4f66cfb | ||
|
|
29cf434a35 | ||
|
|
8623256f48 | ||
|
|
d27a73b1a9 | ||
|
|
74033a844f | ||
|
|
0d40f6d7bb | ||
|
|
7751160e9f | ||
|
|
40c3529909 | ||
|
|
0130ef88ea | ||
|
|
4740baf3a6 | ||
|
|
f5f0cf423f | ||
|
|
052b6fb149 | ||
|
|
1e16d20655 | ||
|
|
9322b399f3 | ||
|
|
f4279bcde0 | ||
|
|
35247c4c9f | ||
|
|
84d6459bd5 | ||
|
|
a9f9241054 | ||
|
|
3ed9e4ad9b | ||
|
|
4251f94b32 | ||
|
|
8c76df93e6 | ||
|
|
363f40022f | ||
|
|
7951c3c546 | ||
|
|
714fa24cfb | ||
|
|
e25fad691a | ||
|
|
30bf547f4f | ||
|
|
536595b072 | ||
|
|
9c9cdb06d0 | ||
|
|
626f8ee42f | ||
|
|
8ba5d32769 | ||
|
|
fcd9900d74 | ||
|
|
a824d58b56 | ||
|
|
ceb982a1be | ||
|
|
b0d8e05be1 | ||
|
|
0565b5f2b3 | ||
|
|
aac547a8b3 | ||
|
|
0263279071 | ||
|
|
a711689368 | ||
|
|
765bdfe542 | ||
|
|
40b3f64b55 | ||
|
|
9adc074dc3 | ||
|
|
9cf1948993 | ||
|
|
6ecb840fd1 | ||
|
|
e2ef5e07fd | ||
|
|
5f0b9de6d8 | ||
|
|
fe15f991e3 | ||
|
|
80b742dd52 | ||
|
|
92417600a1 | ||
|
|
71e867c5f5 | ||
|
|
c6a97e3b74 | ||
|
|
a76efaeb3f | ||
|
|
d941186289 | ||
|
|
0541ddc7e3 | ||
|
|
471749ca7e | ||
|
|
17d18b1a9c | ||
|
|
0ddaee756e | ||
|
|
bce9ff7ece | ||
|
|
745e354b19 | ||
|
|
f459a5bb3a | ||
|
|
e2a70b7ec0 | ||
|
|
e40d4a5604 | ||
|
|
e790404318 | ||
|
|
983c5e3fce | ||
|
|
7e85a2af5f | ||
|
|
b3f916995a | ||
|
|
005eecfc4d | ||
|
|
8478cd260f | ||
|
|
8d17265ac4 | ||
|
|
ae6fb27f18 | ||
|
|
99b0ea7c67 | ||
|
|
dd300fb48d | ||
|
|
1d694eef4c | ||
|
|
7a4497d98c | ||
|
|
17f4883bfe | ||
|
|
9bd93f7606 | ||
|
|
b3d3700e11 | ||
|
|
6a67556f71 | ||
|
|
daa8f85fcd | ||
|
|
24737f279e | ||
|
|
4bd5cdb90b | ||
|
|
58ff6939f4 | ||
|
|
3059df0f1e | ||
|
|
822dba2210 | ||
|
|
dfc042a0c1 | ||
|
|
9e30694f98 | ||
|
|
be1961c9f8 | ||
|
|
cba913c521 | ||
|
|
cf705eaf78 | ||
|
|
7de5fe2fc2 | ||
|
|
46b631b6c4 | ||
|
|
d7efd76394 | ||
|
|
4c9aa821b9 | ||
|
|
142863a89d | ||
|
|
37c8a664f3 | ||
|
|
e4af398681 | ||
|
|
2a535689fe | ||
|
|
7d4567f2cc | ||
|
|
b4e012ab4d | ||
|
|
0c4c5c2020 | ||
|
|
bd0c40e1e9 | ||
|
|
7bada48b36 | ||
|
|
e1cc84259c | ||
|
|
b3fc016061 | ||
|
|
3815d2d463 | ||
|
|
beee18de88 | ||
|
|
eff573f563 | ||
|
|
9e08f5efe1 | ||
|
|
8791ffbc88 | ||
|
|
99ef620c8c | ||
|
|
8396b59286 | ||
|
|
5d769de8a3 | ||
|
|
6f2bfd92b6 | ||
|
|
d98f750fd8 | ||
|
|
34427a7b43 | ||
|
|
a3fd53b9eb | ||
|
|
59ef0aaf3f | ||
|
|
407c9fd520 | ||
|
|
0ef3bd3c37 | ||
|
|
4a7ece698b | ||
|
|
bd4f1b4bb8 | ||
|
|
96fa456a0a | ||
|
|
5fd44654db | ||
|
|
3837fb233c | ||
|
|
d20c3011a0 | ||
|
|
84e6c43e85 | ||
|
|
cfe35ca0e0 | ||
|
|
853252ac66 | ||
|
|
ac19b333b3 | ||
|
|
7581cfdee4 | ||
|
|
f316b6c1a9 | ||
|
|
91a01e6fcf | ||
|
|
88d422567e | ||
|
|
0212feeed6 | ||
|
|
070e07ed5a | ||
|
|
30c7db85d8 | ||
|
|
e2eed05224 | ||
|
|
4ad6fb7ea3 | ||
|
|
015ac7c7da | ||
|
|
a9a6356ffc | ||
|
|
e47d42536f | ||
|
|
5ca45d085e | ||
|
|
02f2335712 | ||
|
|
3632019b73 | ||
|
|
d43565c3e8 | ||
|
|
68ae953d8a | ||
|
|
76c9710091 | ||
|
|
e347033f71 | ||
|
|
0e705391db | ||
|
|
e47e0c2dbe | ||
|
|
df8873e14a | ||
|
|
2ab4bc44c7 | ||
|
|
d315210612 | ||
|
|
c02a44183f | ||
|
|
8a1ab709a4 | ||
|
|
666babbbfa | ||
|
|
385c6f8737 | ||
|
|
d22d7565f3 | ||
|
|
b43aeadbc9 | ||
|
|
4cab35d1a6 | ||
|
|
25df501704 | ||
|
|
0bd5eb71a0 | ||
|
|
4e91d8621f | ||
|
|
ee5040421f | ||
|
|
1bdc152931 | ||
|
|
1b804f88e4 | ||
|
|
0623359fbc | ||
|
|
22d13d6ec2 | ||
|
|
947e645789 | ||
|
|
a060adf165 | ||
|
|
7dd342e482 | ||
|
|
ee6cf99660 | ||
|
|
6dbed1bf38 | ||
|
|
07cec27848 | ||
|
|
9488ae7357 | ||
|
|
e0afaf1857 | ||
|
|
86cbd93ec1 | ||
|
|
5c38c863bd | ||
|
|
f00bc4c94c | ||
|
|
01d169f817 | ||
|
|
feb63da431 | ||
|
|
a04a65d7a5 | ||
|
|
2e210b2387 | ||
|
|
89ac8db74f | ||
|
|
a89a201598 | ||
|
|
fc195519b5 | ||
|
|
bafc1690fc | ||
|
|
e5a6c09b12 | ||
|
|
4be5443882 | ||
|
|
2382a729e0 | ||
|
|
e3ce954582 | ||
|
|
75068e7d75 | ||
|
|
aab8812732 | ||
|
|
7974aae81c | ||
|
|
de90fdf908 | ||
|
|
c9586b6c3f | ||
|
|
c25f688e23 | ||
|
|
354d58b3d7 | ||
|
|
f93f7b75be | ||
|
|
dce1afdc67 | ||
|
|
3151bdea55 | ||
|
|
547b119f25 | ||
|
|
2132d9ddeb | ||
|
|
1f6616dabf | ||
|
|
1ec9f55741 | ||
|
|
1fca76870b | ||
|
|
8a6080eb14 | ||
|
|
4b66cebe7b | ||
|
|
e5678b3435 | ||
|
|
e64c4f5742 | ||
|
|
bf738f0070 | ||
|
|
3e8dccf6ab | ||
|
|
215ec2ddc6 | ||
|
|
f793caf936 | ||
|
|
da25d80152 | ||
|
|
943ab38a0d | ||
|
|
f41297fdce | ||
|
|
9638f3f393 | ||
|
|
b19cebc513 | ||
|
|
38f18aa6d4 | ||
|
|
4a053bfdfd | ||
|
|
68515b5a96 | ||
|
|
561a07f51d | ||
|
|
93d9797eda | ||
|
|
1a9a1f2768 | ||
|
|
cc0505f033 | ||
|
|
4874fd2d9a | ||
|
|
24e234a2fa | ||
|
|
22ba63df16 | ||
|
|
18e4ac0fc6 | ||
|
|
fe101fa785 | ||
|
|
2670642733 | ||
|
|
bfe19b3c37 | ||
|
|
3e5b68068b | ||
|
|
7455fd8835 | ||
|
|
4250b641d8 | ||
|
|
92f7dfa5b7 | ||
|
|
d19b6521fc | ||
|
|
3e239a37ff | ||
|
|
f1aa71a92f | ||
|
|
a18d02e0b0 | ||
|
|
c0bfcbdd45 | ||
|
|
a0607be7f4 | ||
|
|
5a6b45e252 | ||
|
|
a61129c48c | ||
|
|
f1947cce93 | ||
|
|
1854f84e83 | ||
|
|
dcff8cdb76 | ||
|
|
f4a502a09a | ||
|
|
981eff065b | ||
|
|
339e6f0e1d | ||
|
|
0e267e2625 | ||
|
|
4750f6c5ed | ||
|
|
fcb784051f | ||
|
|
a29b64a231 | ||
|
|
4fde308ec0 | ||
|
|
601a8eab79 | ||
|
|
6ac237e242 | ||
|
|
4661282fde | ||
|
|
c11839d7b2 | ||
|
|
ca2238cf81 | ||
|
|
2317d8f671 | ||
|
|
0e6dc72a7a | ||
|
|
b11aeb2c4b | ||
|
|
5744dd5480 | ||
|
|
7a3a5d1608 | ||
|
|
f4c5531d92 | ||
|
|
88acffa20a | ||
|
|
b545c669a0 | ||
|
|
57751fdb55 | ||
|
|
9c3099d328 | ||
|
|
7adaa6d446 | ||
|
|
dcded7da47 | ||
|
|
a4273156c4 | ||
|
|
410760c5ab | ||
|
|
ee2cf45d76 | ||
|
|
eca30e12e1 | ||
|
|
c15f544356 | ||
|
|
ebcccbd358 | ||
|
|
88e54153dc | ||
|
|
4f3725b167 | ||
|
|
e10b830251 | ||
|
|
2b4b0658fa | ||
|
|
d51aede4af | ||
|
|
a945fb7905 | ||
|
|
f4a3a280db | ||
|
|
dbf6d7e783 | ||
|
|
cc51f9c539 | ||
|
|
5bb3444032 | ||
|
|
b35735d8b2 | ||
|
|
0e783e5579 | ||
|
|
d7f40357e3 | ||
|
|
c937b73622 | ||
|
|
588cb0eade | ||
|
|
49de87132f | ||
|
|
48e4a3231b | ||
|
|
b454977909 | ||
|
|
3a68622dda | ||
|
|
370af25eff | ||
|
|
23960e92df | ||
|
|
2d456fc35a | ||
|
|
bb84984f3f | ||
|
|
50fe85f016 | ||
|
|
04cf72287b | ||
|
|
1390ce4142 | ||
|
|
b1c63dc362 | ||
|
|
c7d9397fc9 | ||
|
|
58b4198ed8 | ||
|
|
d764409d97 | ||
|
|
b5988004d6 | ||
|
|
9d72bf8835 | ||
|
|
e3c07782d1 | ||
|
|
c54287eafe | ||
|
|
8b5aa91aa7 | ||
|
|
5cabd47394 | ||
|
|
310e605995 | ||
|
|
0832956089 | ||
|
|
9840368cad | ||
|
|
6980544467 | ||
|
|
b803fb95cb | ||
|
|
db0d865ec4 | ||
|
|
052cefe1bd | ||
|
|
d300b4383d | ||
|
|
68174bdc7d | ||
|
|
c791e94aee | ||
|
|
b52e711910 | ||
|
|
11ae2d1e7a | ||
|
|
dc719e6ba5 | ||
|
|
ae55e79541 | ||
|
|
dca43ef795 | ||
|
|
7276e194ee | ||
|
|
0064599a27 | ||
|
|
6cecad2be0 | ||
|
|
cce31b739c | ||
|
|
6fca1b82ae | ||
|
|
de8f2d061c | ||
|
|
e18c93169c | ||
|
|
0748331b70 | ||
|
|
03162f8f47 | ||
|
|
ef2d4a2da9 | ||
|
|
b69e469328 | ||
|
|
49ce8b57dd | ||
|
|
20675feeab | ||
|
|
05bb644890 | ||
|
|
fdea084c36 | ||
|
|
37d1b1cafd | ||
|
|
a33fb2d287 | ||
|
|
2b3b6c9b34 | ||
|
|
4ada6db1fc | ||
|
|
9811815429 | ||
|
|
18c321308d | ||
|
|
b90c00e63f | ||
|
|
922697c8b2 | ||
|
|
6dca5c9099 | ||
|
|
9088dee9e2 | ||
|
|
fa72ae1e9c | ||
|
|
c8bfb11b34 | ||
|
|
7ba1fd2029 | ||
|
|
120f00c04f | ||
|
|
2d54312f87 | ||
|
|
78d84f5631 | ||
|
|
2167bf6b72 | ||
|
|
70dee0f8ca | ||
|
|
e136532800 | ||
|
|
74166f2f44 | ||
|
|
1bdceb421f | ||
|
|
d822bf32e4 | ||
|
|
fa95f4be3f | ||
|
|
80b5c71684 | ||
|
|
e3daee919d | ||
|
|
ea9c35d3cc | ||
|
|
30d051ff14 | ||
|
|
b6780b9e10 | ||
|
|
b602d2dfdf | ||
|
|
b90787290d | ||
|
|
089c41a0c2 | ||
|
|
ca0b23c831 | ||
|
|
5cb6c42088 | ||
|
|
8cd646b6af | ||
|
|
e48bd8c8b5 | ||
|
|
458820df6c | ||
|
|
6b8bb8d74a | ||
|
|
84c4631221 | ||
|
|
a4c63c6e8e | ||
|
|
85793fa438 | ||
|
|
e2f16b9cae | ||
|
|
5168f9bb00 | ||
|
|
9d3bee50ad | ||
|
|
17f39049cf | ||
|
|
43fa1c20e7 | ||
|
|
928cce5922 | ||
|
|
fcec32a2c5 | ||
|
|
f0d6318dd1 | ||
|
|
ddb78dfc3d | ||
|
|
46f0cb0869 | ||
|
|
7a3e715980 | ||
|
|
58fc420b36 | ||
|
|
4ddd5ff39c | ||
|
|
889ef564fd | ||
|
|
345a95afe9 | ||
|
|
651ab439cf | ||
|
|
d6f586d0ea | ||
|
|
e8475bbd5b | ||
|
|
2d2e28d02c | ||
|
|
0ca0a4da9f | ||
|
|
da0a6b6499 | ||
|
|
982399bb14 | ||
|
|
c6120352b3 | ||
|
|
b505f9eaf5 | ||
|
|
9e51abc7dc | ||
|
|
f848a45739 | ||
|
|
4eb637c799 | ||
|
|
8688e83194 | ||
|
|
f8aadf14c3 | ||
|
|
287d0ef41c | ||
|
|
e771e59178 | ||
|
|
39f50db731 | ||
|
|
4db4b61380 | ||
|
|
81de538e46 | ||
|
|
b90daaaf6c | ||
|
|
6e2eaaec96 | ||
|
|
d9d6ff9f8e | ||
|
|
8291f6d968 | ||
|
|
9e4ffc43a2 | ||
|
|
3eba483692 | ||
|
|
151f10dbc7 | ||
|
|
83424eb71b | ||
|
|
db2275cb99 | ||
|
|
1029716a8a | ||
|
|
e4d4969ae9 | ||
|
|
5b527901ae | ||
|
|
04be39734f | ||
|
|
0f8d3c871b | ||
|
|
52d20ef124 | ||
|
|
1440419b45 | ||
|
|
1d2460ee5d | ||
|
|
f96d2dea26 | ||
|
|
4b9e7f59ca | ||
|
|
3c5619c7e4 | ||
|
|
530b27df1e | ||
|
|
5144f750c4 | ||
|
|
b1eed6b586 | ||
|
|
11a8dc76d6 | ||
|
|
ab5c6bb3a3 | ||
|
|
d87549c1c7 | ||
|
|
8463f27d8c | ||
|
|
18bbcb1214 | ||
|
|
a33b561a6b | ||
|
|
eb268a7f95 | ||
|
|
dfffd92568 | ||
|
|
760264bffe | ||
|
|
dc528128cc | ||
|
|
44409f52c1 | ||
|
|
b7f008fc35 | ||
|
|
9311ab76a5 | ||
|
|
5bf939885a | ||
|
|
1f285cf556 | ||
|
|
221c79013f | ||
|
|
f0856fd905 | ||
|
|
92d599c6a7 | ||
|
|
e932c40f8e | ||
|
|
1b43fbd8e4 | ||
|
|
13b089c890 | ||
|
|
f1b3a418fa | ||
|
|
439823ae80 | ||
|
|
7ef574e5d0 | ||
|
|
32282abcea | ||
|
|
15ff877438 | ||
|
|
0f133ae8d2 | ||
|
|
dfbf520ec2 | ||
|
|
62412c5874 | ||
|
|
cec2be64f3 | ||
|
|
b87b9c0d1f | ||
|
|
0e0041b2b6 | ||
|
|
0e38578433 | ||
|
|
d47e03fccd | ||
|
|
ed4de220d2 | ||
|
|
ebfe57166d | ||
|
|
4578a490ce | ||
|
|
fbedf6056e | ||
|
|
607a2f01e6 | ||
|
|
95304172a5 | ||
|
|
a864aca44c | ||
|
|
8d06842a76 | ||
|
|
89cd0f57b1 | ||
|
|
ef9e2c8e73 | ||
|
|
25d217684b | ||
|
|
f4fe3bd5b1 | ||
|
|
db1a4227a3 | ||
|
|
c28b8eb699 | ||
|
|
6f044ab39c | ||
|
|
d34fa9a6cc | ||
|
|
846b53bde4 | ||
|
|
5c0770ac84 | ||
|
|
1b62c2eba3 | ||
|
|
d1d0271996 | ||
|
|
7f384d9c1b | ||
|
|
896c0b92f3 | ||
|
|
5818e8eeaf | ||
|
|
025086edea | ||
|
|
ed1db42915 | ||
|
|
deb75bb414 | ||
|
|
116e939d57 | ||
|
|
55b84357a1 | ||
|
|
cf2bb91ec8 | ||
|
|
699073c337 | ||
|
|
cb44aa03b8 | ||
|
|
2bcd65ecf6 | ||
|
|
e1a6fb7870 | ||
|
|
08c53923db | ||
|
|
714b7256cd | ||
|
|
0399365675 | ||
|
|
2fd22c6360 | ||
|
|
c680f835c9 | ||
|
|
f450c8ea2f | ||
|
|
800a6ff845 | ||
|
|
78c72bf10e | ||
|
|
991a130b1e | ||
|
|
e6899794ae | ||
|
|
33efb52e02 | ||
|
|
3fae65d4cc | ||
|
|
4c20a08293 | ||
|
|
1a67154d41 | ||
|
|
0f827cc607 | ||
|
|
2135e7c041 | ||
|
|
6f82a78de7 | ||
|
|
6f91f02f75 | ||
|
|
9590009a74 | ||
|
|
f797cb5855 | ||
|
|
a5ceb5bc0b | ||
|
|
d4879b4dfe | ||
|
|
22d3587f3b | ||
|
|
928a7c06dc | ||
|
|
040140dd1c | ||
|
|
109cde6706 | ||
|
|
c09e47c68f | ||
|
|
8be1db899e | ||
|
|
cbc8d083ac | ||
|
|
456f3251d2 | ||
|
|
9ec7e58aa4 | ||
|
|
bfe4875a5e | ||
|
|
8f57634c14 | ||
|
|
88dea78cdf | ||
|
|
edd145d2fb | ||
|
|
426593162e | ||
|
|
77557a6f06 | ||
|
|
6057b51835 | ||
|
|
6c88d67780 | ||
|
|
d8cda7c3dc | ||
|
|
52a2f41320 | ||
|
|
26fd28432d | ||
|
|
5dea0622d1 | ||
|
|
4a266e35d4 | ||
|
|
d7b3cdbd91 | ||
|
|
ae6d9033a1 | ||
|
|
d8a31da1ea | ||
|
|
36fb29f8f0 | ||
|
|
02f2da0142 | ||
|
|
6842bc9ac4 | ||
|
|
f913283570 | ||
|
|
9f3601a36c | ||
|
|
f3660b1c8c | ||
|
|
d5219a351a | ||
|
|
1d86790910 | ||
|
|
bc5e26dcda | ||
|
|
cab7816b56 | ||
|
|
82d771f6e6 | ||
|
|
c9c58dba55 | ||
|
|
b4b51c9f93 | ||
|
|
fb45b0f548 | ||
|
|
c702dfca3f | ||
|
|
8b70f138e0 | ||
|
|
4271385a73 | ||
|
|
90905634ed | ||
|
|
b9d8ecbc6a | ||
|
|
7d876f8fa7 | ||
|
|
10c429c757 | ||
|
|
f9848d4f31 | ||
|
|
c815aff21b | ||
|
|
57d023a184 | ||
|
|
f1ae10b992 | ||
|
|
806b91f104 | ||
|
|
128c174295 | ||
|
|
229252941a | ||
|
|
6c8cf567b8 | ||
|
|
31e140d70b | ||
|
|
4a83c12c5d | ||
|
|
6f788880b6 | ||
|
|
298dd487bb | ||
|
|
ebe342c9c1 | ||
|
|
7eaf038763 | ||
|
|
c6178f0b03 | ||
|
|
d1487d9015 | ||
|
|
009752ca70 | ||
|
|
cff6bc06df | ||
|
|
590e5a0d65 | ||
|
|
0df9f08078 | ||
|
|
3f236f01ae | ||
|
|
a04c62e0c4 | ||
|
|
f20f081560 | ||
|
|
a1e00bf6aa | ||
|
|
ab75a50ba4 | ||
|
|
7272c3f817 | ||
|
|
67eff20906 | ||
|
|
ad3121a52d | ||
|
|
f982df3cd7 | ||
|
|
afc3a7b79b | ||
|
|
693ff4f6bf | ||
|
|
62dbfbc45b | ||
|
|
e301334696 | ||
|
|
b376565b86 | ||
|
|
bacd3a6cfa | ||
|
|
e52ae1c0ff | ||
|
|
155c91b335 | ||
|
|
5675d5f488 | ||
|
|
6fb5f7e532 | ||
|
|
c757d16c8c | ||
|
|
bb2e53699f | ||
|
|
5863f24722 | ||
|
|
bd333b939c | ||
|
|
8eff18cd43 | ||
|
|
1562dfe9ba | ||
|
|
012b812698 | ||
|
|
536f324177 | ||
|
|
08df443618 | ||
|
|
97c93526da | ||
|
|
bfbc55cbc6 | ||
|
|
543d7a41dc | ||
|
|
9a7f95882c | ||
|
|
4bbdcfbb45 | ||
|
|
9e6bca8765 | ||
|
|
86cb3cc554 | ||
|
|
0107fba48e | ||
|
|
07b4399fb6 | ||
|
|
9e50e648a4 | ||
|
|
8d364e5baa | ||
|
|
db322a47ff | ||
|
|
2c4302dd7a | ||
|
|
8376fff151 | ||
|
|
8d3c346559 | ||
|
|
6bafeafb88 | ||
|
|
3259ae5811 | ||
|
|
95e870a113 | ||
|
|
bfaf83a0fd | ||
|
|
3a2c3f0cf2 | ||
|
|
eda2c3c253 | ||
|
|
3c1630131e | ||
|
|
398463a72a | ||
|
|
e0181f56be | ||
|
|
74ab0695b5 | ||
|
|
8a3a96dd5b | ||
|
|
88273f9574 | ||
|
|
fb5dae8694 | ||
|
|
202d5bbda5 | ||
|
|
e17910cfb5 | ||
|
|
0083562f75 | ||
|
|
8992fce3da | ||
|
|
e446d342b7 | ||
|
|
0cb016c209 | ||
|
|
a04a5de8f7 | ||
|
|
6a8ef36fe6 | ||
|
|
b0aba6ec2a | ||
|
|
32429142cd | ||
|
|
20ce2642fc | ||
|
|
80870d9291 | ||
|
|
3a99616968 | ||
|
|
98df735b51 | ||
|
|
582e01c06f | ||
|
|
c547439843 | ||
|
|
3d74274b37 | ||
|
|
60feff82cf | ||
|
|
48ebe4527e | ||
|
|
fbc434ee4c | ||
|
|
450c358e20 | ||
|
|
a37338815d | ||
|
|
2e6bf723e4 | ||
|
|
9f6835c282 | ||
|
|
c3981d81f6 | ||
|
|
65b6c8ab4c | ||
|
|
630ae0c9d7 | ||
|
|
dcc37c236c | ||
|
|
a6b65fd5e1 | ||
|
|
06b4424286 | ||
|
|
32fa82a56a | ||
|
|
89c9bc11ab | ||
|
|
207bdcbe86 | ||
|
|
252c9c91ab | ||
|
|
33c5d23b81 | ||
|
|
1328aa3307 | ||
|
|
a7668411a1 | ||
|
|
22cfdfa246 | ||
|
|
9ab0bc9395 | ||
|
|
0ea8b6993a | ||
|
|
ac2f665853 | ||
|
|
a85d1849af | ||
|
|
e5c16c9582 | ||
|
|
8a3eef22e3 | ||
|
|
c60a4943ba | ||
|
|
4e37548a1e | ||
|
|
c505702265 | ||
|
|
59682e6188 | ||
|
|
a24b78e9f1 | ||
|
|
2a2756b856 | ||
|
|
a9340fa672 | ||
|
|
498f4915cc | ||
|
|
066da4ab85 | ||
|
|
c6290e42bc | ||
|
|
581fc47783 | ||
|
|
52bf9b86bb | ||
|
|
80faa2f98a | ||
|
|
6a0a2d5593 | ||
|
|
6bb5efadec | ||
|
|
05f0430de1 | ||
|
|
6ff48e77f6 | ||
|
|
e0f4e587c3 | ||
|
|
96de272b48 | ||
|
|
ef5f254a55 | ||
|
|
06c77bf7a8 | ||
|
|
863dcff6c5 | ||
|
|
e9762e2d10 | ||
|
|
6d493751c3 | ||
|
|
32aac8748a | ||
|
|
f3dc231250 | ||
|
|
d58a11e019 | ||
|
|
9530cc3170 | ||
|
|
a7b94e87d7 | ||
|
|
9ee88bb2f2 | ||
|
|
63791eb05b | ||
|
|
37b51a9aa6 | ||
|
|
7e8961f720 | ||
|
|
73992371a3 | ||
|
|
d46b4262dc | ||
|
|
b17e7cf979 | ||
|
|
0bc41f632b | ||
|
|
7d75616f2c | ||
|
|
6af4a5a71f | ||
|
|
a03397be4c | ||
|
|
f28ea27d83 | ||
|
|
c53898cb65 | ||
|
|
35b76a81c4 | ||
|
|
3745cecc6a | ||
|
|
581bcb986f | ||
|
|
6270aa727d | ||
|
|
4f07ebc67e | ||
|
|
54d8f08588 | ||
|
|
2fdb27e7f2 | ||
|
|
e1e9c036f9 | ||
|
|
77fc1c6c5c | ||
|
|
9022cf9adf | ||
|
|
4bf58d5379 | ||
|
|
3d1b2101cc | ||
|
|
7eed57e784 | ||
|
|
96c3d8a615 | ||
|
|
8b9697e575 | ||
|
|
fa9259f5f5 | ||
|
|
015beb7cd0 | ||
|
|
4d25b0b0bb | ||
|
|
f4041cc175 | ||
|
|
77970f8daf | ||
|
|
e3b051aeeb | ||
|
|
862f4c154e | ||
|
|
dca48aed34 | ||
|
|
71926ee188 | ||
|
|
13f77276d1 | ||
|
|
eee6fe478e | ||
|
|
f17553a212 | ||
|
|
4115d8d8ce | ||
|
|
5d5318c2ff | ||
|
|
9f8964a062 | ||
|
|
0b79a12082 | ||
|
|
54c7a870d5 | ||
|
|
c2b0d6b02f | ||
|
|
32c7326850 | ||
|
|
92ee003dc9 | ||
|
|
d6db574ec1 | ||
|
|
b8aaef5e4e | ||
|
|
2c3b29c5ca | ||
|
|
ea6581b691 | ||
|
|
09e7f06818 | ||
|
|
1bac7a10e6 | ||
|
|
55b35d6d77 | ||
|
|
0b1ee4802b | ||
|
|
5f0300d18c | ||
|
|
3e9d2038b4 | ||
|
|
6ca9c7f0a9 | ||
|
|
8b934694f2 | ||
|
|
feb3ceaee0 | ||
|
|
cb7ccb528b | ||
|
|
4cbd845aa4 | ||
|
|
5f2c5a306c | ||
|
|
0913f5a615 | ||
|
|
ee5dcfade2 | ||
|
|
cbe8de592d | ||
|
|
b05a596d61 | ||
|
|
0d80d237c5 | ||
|
|
2aa1f4717b | ||
|
|
f8ac8d1ec8 | ||
|
|
a69534fc21 | ||
|
|
ed09821859 | ||
|
|
3277c9432a | ||
|
|
463e2817c5 | ||
|
|
f09618b63a | ||
|
|
c7bea941b0 | ||
|
|
210ab0296d | ||
|
|
c52dda95a6 | ||
|
|
5fe9222b36 | ||
|
|
eb8284ddaa | ||
|
|
033d7c6593 | ||
|
|
9fa07b376d | ||
|
|
ee401afad8 | ||
|
|
37d7abd694 | ||
|
|
f4d44a0026 | ||
|
|
3ade3e7721 | ||
|
|
2248becfd3 | ||
|
|
50b9caac14 | ||
|
|
2155c0a673 | ||
|
|
88888160d2 | ||
|
|
99da51d4de | ||
|
|
2cd590d96c | ||
|
|
692204e0c5 | ||
|
|
d830b2c1df | ||
|
|
febd8bed1b | ||
|
|
98c69e5172 | ||
|
|
371c57d8a7 | ||
|
|
2b20701f78 | ||
|
|
1317242780 | ||
|
|
995d08208e | ||
|
|
b357284a32 | ||
|
|
dcc433de47 | ||
|
|
c16be6ac92 | ||
|
|
47f87072ad | ||
|
|
5396304c73 | ||
|
|
e043fc7d0b | ||
|
|
550d960586 | ||
|
|
17c8252fc9 | ||
|
|
fb28cfc86d | ||
|
|
5c443b6550 | ||
|
|
c25f2883b1 | ||
|
|
fe122c5a15 | ||
|
|
eb233e728f | ||
|
|
fdec72c6cc | ||
|
|
818047881e | ||
|
|
9994c1dd9f | ||
|
|
8f58733ef1 | ||
|
|
1c90fabccc | ||
|
|
e77fbe0fa2 | ||
|
|
2d35116c13 | ||
|
|
8f1dcdfc0a | ||
|
|
1eddee59f2 | ||
|
|
937ce0cd21 | ||
|
|
966bd9d19f | ||
|
|
62fe5c4a22 | ||
|
|
ae1a1efa41 | ||
|
|
d8989b1fb4 | ||
|
|
bbfdd64741 | ||
|
|
e3a50f7e25 | ||
|
|
18ebd7b030 | ||
|
|
5373aed1a8 | ||
|
|
16c8b4c8e5 | ||
|
|
e8a95108c0 | ||
|
|
9bf7a5f516 | ||
|
|
39eaecbc98 | ||
|
|
064a36cb54 | ||
|
|
c1a18f543e | ||
|
|
056cd1d3b7 | ||
|
|
638ce339a5 | ||
|
|
292d6468ec | ||
|
|
8f6254e823 | ||
|
|
593bc23d8b | ||
|
|
b584253af4 | ||
|
|
f5d5ffe536 | ||
|
|
00aadf478b | ||
|
|
151e61fa5a | ||
|
|
4d2946c516 | ||
|
|
24286e15c9 | ||
|
|
2746a879e2 | ||
|
|
91dc023665 | ||
|
|
b113edeab7 | ||
|
|
e4883211f9 | ||
|
|
795d9f8b08 | ||
|
|
a29c8ac51c | ||
|
|
ec32627621 | ||
|
|
8052aef486 | ||
|
|
66c7f34759 | ||
|
|
05a5362d63 | ||
|
|
d051cd40e1 | ||
|
|
3093af58a7 | ||
|
|
b302e5f63b | ||
|
|
83ae1723da | ||
|
|
72bc9a522f | ||
|
|
5e2cf44a4d | ||
|
|
84007a0958 | ||
|
|
c9fbd2dfd5 | ||
|
|
155d7c8dfa | ||
|
|
c4cb6ea2bc | ||
|
|
88fb4f6e53 | ||
|
|
2db9748221 | ||
|
|
37ee6cef99 | ||
|
|
3f3a3ae87b | ||
|
|
72c857f0eb | ||
|
|
be1a917beb | ||
|
|
daf0a923c7 | ||
|
|
15c60ca1b6 | ||
|
|
112ee89501 | ||
|
|
bafb2357d1 | ||
|
|
85ae781765 | ||
|
|
23bb902d1f | ||
|
|
41ec982f31 | ||
|
|
3454c685ee | ||
|
|
6ba26f27c3 | ||
|
|
0b70231b9d | ||
|
|
1bc6afefac | ||
|
|
e8411948ff | ||
|
|
5e4a2272bf | ||
|
|
19479899fb | ||
|
|
1d08093b48 | ||
|
|
8e9fd57ef9 | ||
|
|
ace8872706 | ||
|
|
4fc00cbec1 | ||
|
|
2fa3304933 | ||
|
|
25db622454 | ||
|
|
3426d19547 | ||
|
|
a8306cb98f | ||
|
|
5087c8f645 | ||
|
|
efa5fa1a91 | ||
|
|
1f48aa0be7 | ||
|
|
aa5a5084e4 | ||
|
|
8c0b42f857 | ||
|
|
c8d3882cdc | ||
|
|
aea436503e | ||
|
|
a9858c9f26 | ||
|
|
f044ccf702 | ||
|
|
a7bbe73971 | ||
|
|
ef093aac8f | ||
|
|
256eeab711 | ||
|
|
fd927c5d25 | ||
|
|
22371cbd3f | ||
|
|
bcce9c1ff5 | ||
|
|
d4779abc04 | ||
|
|
759c953196 | ||
|
|
d7238bc84e | ||
|
|
b6df68c942 | ||
|
|
21655a70f5 | ||
|
|
f79e9c2d22 | ||
|
|
8e459d919d | ||
|
|
7cce0c34e1 | ||
|
|
2c5a8bf49f | ||
|
|
b275f2ed3b | ||
|
|
a4d2b22c8c | ||
|
|
87bf541f23 | ||
|
|
b0c9baf1b5 | ||
|
|
153429520a | ||
|
|
2be8ac48bb | ||
|
|
bf3863b546 | ||
|
|
03f1d1ecb5 | ||
|
|
59b94ee18a | ||
|
|
a520b1cbc3 | ||
|
|
c4ac2a164a | ||
|
|
df101d6fca | ||
|
|
ac4d39f9db | ||
|
|
f958bcdf1f | ||
|
|
db3e644c1c | ||
|
|
f8cd904e05 | ||
|
|
f0f7a9f299 | ||
|
|
7823db2137 | ||
|
|
777e13b94b | ||
|
|
79bb0008ec | ||
|
|
e6253b58cd | ||
|
|
3f3c4cce5a | ||
|
|
84c617966b | ||
|
|
c2fc2c13c9 | ||
|
|
a784fd5792 | ||
|
|
8ce3dd4887 | ||
|
|
8330c8202a | ||
|
|
b5539e7a30 | ||
|
|
9d2669d218 | ||
|
|
beda10f5a2 | ||
|
|
a5619f1dff | ||
|
|
7f0ed370da | ||
|
|
dbf547645d | ||
|
|
86b7efbdbe | ||
|
|
0dfdafdf6d | ||
|
|
f34de12140 | ||
|
|
fbc48a469c | ||
|
|
76c0e85929 | ||
|
|
6f5a5ea5ea | ||
|
|
1ad9d11247 | ||
|
|
00fe1a506f | ||
|
|
92e832348d | ||
|
|
6551b36790 | ||
|
|
0616b7feea | ||
|
|
618aa69b01 | ||
|
|
06a75a7e0c | ||
|
|
b8675aee54 | ||
|
|
73ab2ed4fd | ||
|
|
7c0fa4474f | ||
|
|
7abf9911d9 | ||
|
|
49bafe1faf | ||
|
|
66e94d3275 | ||
|
|
d445da7a7b | ||
|
|
9d25466b34 | ||
|
|
6d46e647ba | ||
|
|
9b44480612 | ||
|
|
c4f7ae4aa5 | ||
|
|
1c9c0a5a46 | ||
|
|
d9f30fe7c7 | ||
|
|
47c003cb59 | ||
|
|
619f20775d | ||
|
|
c625718513 | ||
|
|
c5baaafae6 | ||
|
|
abd1878b26 | ||
|
|
3648d1c732 | ||
|
|
cdb50886f4 | ||
|
|
3c4bc7276a | ||
|
|
4f72b408a5 | ||
|
|
840551ebdb | ||
|
|
1109ea0680 | ||
|
|
47f19b6293 | ||
|
|
4db7ef3fcc | ||
|
|
3778586b2a | ||
|
|
8baf50f108 | ||
|
|
699989b216 | ||
|
|
3a4a4aaa88 | ||
|
|
f899e8ce4d | ||
|
|
b1c5f3c10d | ||
|
|
291030b900 | ||
|
|
447089a5f6 | ||
|
|
08719c6c97 | ||
|
|
55e11bc0d3 | ||
|
|
9a404e45c9 | ||
|
|
16f9b133ec | ||
|
|
ff9af107d3 | ||
|
|
3495d153b3 | ||
|
|
698e880c9f | ||
|
|
23fbc72f5d | ||
|
|
4c4fe7a114 | ||
|
|
46a71c857c | ||
|
|
30b31a8f61 | ||
|
|
b594215531 | ||
|
|
5346536b62 | ||
|
|
7959354379 | ||
|
|
abe8c8c2aa | ||
|
|
1ff986d51a | ||
|
|
2f0b93904b | ||
|
|
4a373a3e9a | ||
|
|
f83c5e3e5f | ||
|
|
0e68af0ce3 | ||
|
|
9ff3657095 | ||
|
|
0e09cc12c0 | ||
|
|
94175e978a | ||
|
|
68f2fadb78 | ||
|
|
392b7e0f8e | ||
|
|
833f2fc92d | ||
|
|
cf0287c09e | ||
|
|
f3c9783846 | ||
|
|
a81b621202 | ||
|
|
0a753e182a | ||
|
|
df7a718786 | ||
|
|
397c8ba898 | ||
|
|
528f1d1867 | ||
|
|
06c5a7075d | ||
|
|
cff6fd22eb | ||
|
|
feaab52203 | ||
|
|
00d4f907e1 | ||
|
|
31fd72ee17 | ||
|
|
16d971bce7 | ||
|
|
0d3a1a8582 | ||
|
|
0c804c6775 | ||
|
|
a3ca74a1c3 | ||
|
|
078e20885e | ||
|
|
905d5b91fa | ||
|
|
83ffd4f282 | ||
|
|
5d2b424804 | ||
|
|
dc05f29cf6 | ||
|
|
7b0e29b4dc | ||
|
|
62d9b31d0a | ||
|
|
f6a30ab264 | ||
|
|
2a4bac5459 | ||
|
|
bd0ce1a4be | ||
|
|
80f8c38384 | ||
|
|
c38ba181ed | ||
|
|
4da9316c8f | ||
|
|
6d5877ea12 | ||
|
|
12e805cfb0 | ||
|
|
ba73f94b3b | ||
|
|
66c115ef5f | ||
|
|
c3ee8c9166 | ||
|
|
6e8c19714a | ||
|
|
d1d87badf6 | ||
|
|
604c45e960 | ||
|
|
e7ea52d3b3 | ||
|
|
b857267893 | ||
|
|
496934a99c | ||
|
|
c9cb1fa21f | ||
|
|
60e86b124f | ||
|
|
af7e6fe22e | ||
|
|
9486dda115 | ||
|
|
ab0bc4999a | ||
|
|
40d9eb14df | ||
|
|
7a02d95418 | ||
|
|
06208d1d86 | ||
|
|
2e9042bd1e | ||
|
|
e0b5a492f5 | ||
|
|
9898746ef3 | ||
|
|
fd7ac09f10 | ||
|
|
ac68840e79 | ||
|
|
2be8b5917a | ||
|
|
38946e1378 | ||
|
|
dfc9c64ead | ||
|
|
b1117ef29d | ||
|
|
ce92d1bf14 | ||
|
|
9f0f020929 | ||
|
|
8798fae304 | ||
|
|
45610ae675 | ||
|
|
3e5a019a07 | ||
|
|
06ae269c7c | ||
|
|
15801c88fa | ||
|
|
d2e3a132fe | ||
|
|
90e26d392c | ||
|
|
cfaea07444 | ||
|
|
569e7940f8 | ||
|
|
fa18f1f184 | ||
|
|
e17e95a828 | ||
|
|
80bb477cc4 | ||
|
|
0690c1c9c0 | ||
|
|
ff31324278 | ||
|
|
e2655aa332 | ||
|
|
ad0976f8d5 | ||
|
|
40986312bb | ||
|
|
adf9a45469 | ||
|
|
c8268ca991 | ||
|
|
7de1b2a698 | ||
|
|
1610444671 | ||
|
|
1b4184ccbb | ||
|
|
a2a9bacd82 | ||
|
|
449411e511 | ||
|
|
9210d4d530 | ||
|
|
f1c1a3c97f | ||
|
|
7db08cc924 | ||
|
|
403cb9327f | ||
|
|
9f8f39aa3c | ||
|
|
e537844f4e | ||
|
|
442b09ea33 | ||
|
|
933b3f677d | ||
|
|
b95a3dc45b | ||
|
|
4d728f6a36 | ||
|
|
f31661a3b5 | ||
|
|
7102455cba | ||
|
|
92eea8fc4e | ||
|
|
c4e7d324b8 | ||
|
|
9d95aafe8c | ||
|
|
143427f90b | ||
|
|
4a8948b7a6 | ||
|
|
c62433751d | ||
|
|
53e376d836 | ||
|
|
0eab306466 | ||
|
|
a0a7a4e087 | ||
|
|
0791282b2f | ||
|
|
ab5e8767fa | ||
|
|
c78bf11524 | ||
|
|
f7c7aad135 | ||
|
|
181aa3dc41 | ||
|
|
ebff82222c | ||
|
|
5fc7127643 | ||
|
|
c190f051ac | ||
|
|
1d61e473c8 | ||
|
|
0abe185688 | ||
|
|
d3d5e77810 | ||
|
|
1eb4da156c | ||
|
|
08b7319f5b | ||
|
|
6409c215e5 | ||
|
|
6baa2c4420 | ||
|
|
b9f4942bd2 | ||
|
|
5d4171f7fb | ||
|
|
563afb7fcc | ||
|
|
e78f753aa8 | ||
|
|
4193d62e08 | ||
|
|
6d478597c7 | ||
|
|
9fb94f4f2f | ||
|
|
9ba2397ea9 | ||
|
|
41730f5779 | ||
|
|
1c7d6bf5fc | ||
|
|
d930a9bc5a | ||
|
|
803a924b77 | ||
|
|
c0bbed0959 | ||
|
|
0d2bc68681 | ||
|
|
25304af72e | ||
|
|
b018517314 | ||
|
|
c4f1f49574 | ||
|
|
31be53cd0a | ||
|
|
920193beb1 | ||
|
|
a88144215c | ||
|
|
56b98c3857 | ||
|
|
956801fcc2 | ||
|
|
624c48260f | ||
|
|
710175e6a0 | ||
|
|
ed0db2e0d8 | ||
|
|
1472cc4825 | ||
|
|
2de8504791 | ||
|
|
31e4aa6439 | ||
|
|
ebbb6ce578 | ||
|
|
c32e01eab2 | ||
|
|
08f9cfe267 | ||
|
|
96c7b98bf0 | ||
|
|
555347744d | ||
|
|
e374dbf89b | ||
|
|
01e30360d4 | ||
|
|
163db7367f | ||
|
|
161aab582b | ||
|
|
a24cb19361 | ||
|
|
9ee3b7a37a | ||
|
|
dc0ef2ca98 | ||
|
|
2e16ff22ac | ||
|
|
5cde23f869 | ||
|
|
0a2de7f543 | ||
|
|
95b49f8044 | ||
|
|
68022552d2 | ||
|
|
c34a153ae5 | ||
|
|
b4f88d0ec3 | ||
|
|
469f1eba56 | ||
|
|
e405ca506e | ||
|
|
c602930e08 | ||
|
|
4b7b0bd12c | ||
|
|
74867e72f2 | ||
|
|
f8035d06f2 | ||
|
|
9ad39df282 | ||
|
|
d551062ec4 | ||
|
|
236eb59293 | ||
|
|
720f06e3b0 | ||
|
|
37483672d4 | ||
|
|
d34b4d4f28 | ||
|
|
b9c9b461ea | ||
|
|
4ce652640b | ||
|
|
fd30f52cfc | ||
|
|
17f05dba77 | ||
|
|
d6b6b2d3a8 | ||
|
|
d2e963f7a3 | ||
|
|
c95b4ad290 | ||
|
|
d99d04e644 | ||
|
|
545145cd58 | ||
|
|
9df93f30bd | ||
|
|
06434072e7 | ||
|
|
06d3d7355d | ||
|
|
177a7782ae | ||
|
|
4a013962bd | ||
|
|
758bd4673a | ||
|
|
9f4c19276d | ||
|
|
26ff1cdf89 | ||
|
|
64c617e984 | ||
|
|
2ac02440dc | ||
|
|
aaee69cfde | ||
|
|
83075304e5 | ||
|
|
1cb030736e | ||
|
|
a01629894d | ||
|
|
40f32ae00a | ||
|
|
8846465934 | ||
|
|
dc14a3de46 | ||
|
|
79ba0431db | ||
|
|
5acb45446e | ||
|
|
ce5fd1cc12 | ||
|
|
dec8fbc52b | ||
|
|
949c4fa1a8 | ||
|
|
f21b341957 | ||
|
|
5d7a20dac3 | ||
|
|
0a0c1fcb4d | ||
|
|
3b521bb1bd | ||
|
|
1a7468a57a | ||
|
|
b75719b984 | ||
|
|
39ce70025b | ||
|
|
9202570f8c | ||
|
|
e877c69d78 | ||
|
|
df648c4967 | ||
|
|
d84931ee56 | ||
|
|
c7bdb76fe4 | ||
|
|
d5ee6f8700 | ||
|
|
2616e6a6f3 | ||
|
|
9f4ad99e92 | ||
|
|
249988a787 | ||
|
|
49231fbe41 | ||
|
|
401452e57a | ||
|
|
7984cfc7c1 | ||
|
|
667a6afb9d | ||
|
|
6f1a0f948d | ||
|
|
ab350eafd2 | ||
|
|
b3fc38bf6a | ||
|
|
71cc3ceae5 | ||
|
|
54664b6fb7 | ||
|
|
335aa1c35d | ||
|
|
6822fd7bf4 | ||
|
|
9d56ca219f | ||
|
|
b9ecadee6e | ||
|
|
c11bbcfd26 | ||
|
|
d41d085b77 | ||
|
|
7b3f44e05b | ||
|
|
f5b6fa5256 | ||
|
|
8898e86b4f | ||
|
|
3509299aca | ||
|
|
135b7d54db | ||
|
|
e6363b05ae | ||
|
|
9c620e4afa | ||
|
|
5304a1eb3a | ||
|
|
73b163c1a1 | ||
|
|
c834a5c597 | ||
|
|
822c072cfa | ||
|
|
9bcc31c941 | ||
|
|
81304a6bb5 | ||
|
|
e5fbf58041 | ||
|
|
8511571f65 | ||
|
|
1d1c3691d2 | ||
|
|
d072485d28 | ||
|
|
5d4b90b689 | ||
|
|
089b436175 | ||
|
|
b96239c657 | ||
|
|
9ebd78144a | ||
|
|
6011bd0da2 | ||
|
|
2b95a9dc05 | ||
|
|
9a99dc736d | ||
|
|
cab3f4977a | ||
|
|
333f4963de | ||
|
|
40274c1f4f | ||
|
|
a279137327 | ||
|
|
85a913a3e7 | ||
|
|
0b38b43bab | ||
|
|
ab644ad10b | ||
|
|
a5a90f501e | ||
|
|
be96c2189c | ||
|
|
5895c160c4 | ||
|
|
609a224848 | ||
|
|
224c585aba | ||
|
|
7952a8053c | ||
|
|
bfa5d77211 | ||
|
|
82e3d8fafe | ||
|
|
f826e432aa | ||
|
|
01b34fe584 | ||
|
|
207ff2caf0 | ||
|
|
40b5936691 | ||
|
|
3da9687854 | ||
|
|
bb03c45ca0 | ||
|
|
d4c3edfaba | ||
|
|
3ec5252582 | ||
|
|
2b07b0e7eb | ||
|
|
692b562342 | ||
|
|
c0cbaef4be | ||
|
|
5f5cab0ac7 | ||
|
|
85effedca3 | ||
|
|
5079ccb455 | ||
|
|
1849aa2a72 | ||
|
|
38e12df631 | ||
|
|
aeaffec785 | ||
|
|
94cf1f86bb | ||
|
|
bc57eb3c8a | ||
|
|
fab7b128b9 | ||
|
|
34fcf5fa0c | ||
|
|
7a96da3627 | ||
|
|
6656993f83 | ||
|
|
a7ab242fb4 | ||
|
|
c739e20585 | ||
|
|
727beb798a | ||
|
|
2f04e7102e | ||
|
|
a09e66da5a | ||
|
|
822794001c | ||
|
|
b9f09b3268 |
140
.gitignore
vendored
Normal file
140
.gitignore
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
|
||||
# /
|
||||
/aclocal.m4
|
||||
/autom4te.cache
|
||||
/config.*
|
||||
/configure
|
||||
/nix.spec
|
||||
/stamp-h1
|
||||
/svn-revision
|
||||
/NEWS
|
||||
/libtool
|
||||
|
||||
# /config/
|
||||
/config/config.guess
|
||||
/config/config.sub
|
||||
/config/depcomp
|
||||
/config/install-sh
|
||||
/config/missing
|
||||
/config/mkinstalldirs
|
||||
/config/ltmain.sh
|
||||
|
||||
/corepkgs/config.nix
|
||||
|
||||
# /corepkgs/buildenv/
|
||||
/corepkgs/buildenv/builder.pl
|
||||
|
||||
# /corepkgs/channels/
|
||||
/corepkgs/channels/unpack.sh
|
||||
|
||||
# /corepkgs/nar/
|
||||
/corepkgs/nar/nar.sh
|
||||
/corepkgs/nar/unnar.sh
|
||||
|
||||
# /doc/manual/
|
||||
/doc/manual/manual.html
|
||||
/doc/manual/manual.xmli
|
||||
/doc/manual/manual.pdf
|
||||
/doc/manual/manual.is-valid
|
||||
/doc/manual/*.1
|
||||
/doc/manual/*.5
|
||||
/doc/manual/*.8
|
||||
/doc/manual/images
|
||||
/doc/manual/version.txt
|
||||
/doc/manual/NEWS.html
|
||||
/doc/manual/NEWS.txt
|
||||
|
||||
# /scripts/
|
||||
/scripts/nix-profile.sh
|
||||
/scripts/nix-pull
|
||||
/scripts/nix-push
|
||||
/scripts/nix-switch
|
||||
/scripts/nix-collect-garbage
|
||||
/scripts/nix-prefetch-url
|
||||
/scripts/nix-install-package
|
||||
/scripts/nix-channel
|
||||
/scripts/nix-build
|
||||
/scripts/nix-copy-closure
|
||||
/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/download-from-binary-cache.pl
|
||||
/scripts/find-runtime-roots.pl
|
||||
/scripts/build-remote.pl
|
||||
/scripts/nix-reduce-build
|
||||
/scripts/nix-http-export.cgi
|
||||
|
||||
# /src/bsdiff-4.3/
|
||||
/src/bsdiff-4.3/bsdiff
|
||||
/src/bsdiff-4.3/bspatch
|
||||
|
||||
# /src/libexpr/
|
||||
/src/libexpr/lexer-tab.cc
|
||||
/src/libexpr/lexer-tab.hh
|
||||
/src/libexpr/parser-tab.cc
|
||||
/src/libexpr/parser-tab.hh
|
||||
/src/libexpr/parser-tab.output
|
||||
/src/libexpr/nix.tbl
|
||||
|
||||
# /src/libstore/
|
||||
/src/libstore/schema.sql.hh
|
||||
|
||||
# /src/nix-env/
|
||||
/src/nix-env/nix-env
|
||||
|
||||
# /src/nix-hash/
|
||||
/src/nix-hash/nix-hash
|
||||
|
||||
# /src/nix-instantiate/
|
||||
/src/nix-instantiate/nix-instantiate
|
||||
|
||||
# /src/nix-log2xml/
|
||||
/src/nix-log2xml/nix-log2xml
|
||||
/src/nix-log2xml/test*.*
|
||||
/src/nix-log2xml/*.log
|
||||
/src/nix-log2xml/*.xml
|
||||
/src/nix-log2xml/*.html
|
||||
|
||||
# /src/nix-setuid-helper/
|
||||
/src/nix-setuid-helper/nix-setuid-helper
|
||||
|
||||
# /src/nix-store/
|
||||
/src/nix-store/nix-store
|
||||
|
||||
# /src/nix-daemon/
|
||||
/src/nix-daemon/nix-daemon
|
||||
|
||||
# /tests/
|
||||
/tests/test-tmp
|
||||
/tests/config.nix
|
||||
/tests/common.sh
|
||||
/tests/dummy
|
||||
/tests/result*
|
||||
|
||||
# /tests/lang/
|
||||
/tests/lang/*.out
|
||||
/tests/lang/*.out.xml
|
||||
/tests/lang/*.ast
|
||||
|
||||
/perl/lib/Nix/Config.pm
|
||||
/perl/lib/Nix/Store.cc
|
||||
|
||||
.deps
|
||||
.libs
|
||||
*.a
|
||||
*.lo
|
||||
*.la
|
||||
*.o
|
||||
*.so
|
||||
*~
|
||||
|
||||
# GNU Global
|
||||
GPATH
|
||||
GRTAGS
|
||||
GSYMS
|
||||
GTAGS
|
||||
8
AUTHORS
8
AUTHORS
@@ -0,0 +1,8 @@
|
||||
The following people contributed to Nix, in alphabetical order:
|
||||
|
||||
Martin Bravenboer
|
||||
Eelco Dolstra
|
||||
Niels Janssen
|
||||
Armijn Hemel
|
||||
Rob Vermaas
|
||||
Eelco Visser
|
||||
|
||||
644
COPYING
644
COPYING
@@ -1,221 +1,397 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
the Library or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
@@ -225,116 +401,104 @@ impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
That's all there is to it!
|
||||
|
||||
|
||||
|
||||
45
Makefile.am
45
Makefile.am
@@ -1 +1,44 @@
|
||||
SUBDIRS = src scripts
|
||||
SUBDIRS = src perl scripts corepkgs doc misc tests
|
||||
EXTRA_DIST = substitute.mk nix.spec nix.spec.in bootstrap.sh \
|
||||
NEWS version misc/systemd/nix-daemon.service
|
||||
|
||||
pkginclude_HEADERS = config.h
|
||||
|
||||
include ./substitute.mk
|
||||
|
||||
nix.spec: nix.spec.in
|
||||
|
||||
install-data-local: init-state
|
||||
$(INSTALL) -d $(DESTDIR)$(sysconfdir)/nix
|
||||
$(INSTALL) -d $(DESTDIR)$(docdir)
|
||||
$(INSTALL_DATA) README $(DESTDIR)$(docdir)/
|
||||
|
||||
if INIT_STATE
|
||||
|
||||
# For setuid operation, you can enable the following:
|
||||
# INIT_FLAGS = -g @NIX_GROUP@ -o @NIX_USER@
|
||||
# GROUP_WRITABLE = -m 775
|
||||
|
||||
init-state:
|
||||
$(INSTALL) $(INIT_FLAGS) -d $(DESTDIR)$(localstatedir)/nix
|
||||
$(INSTALL) $(INIT_FLAGS) -d $(DESTDIR)$(localstatedir)/nix/db
|
||||
$(INSTALL) $(INIT_FLAGS) -d $(DESTDIR)$(localstatedir)/log/nix
|
||||
$(INSTALL) $(INIT_FLAGS) -d $(DESTDIR)$(localstatedir)/log/nix/drvs
|
||||
$(INSTALL) $(INIT_FLAGS) -d $(DESTDIR)$(localstatedir)/nix/profiles
|
||||
$(INSTALL) $(INIT_FLAGS) -d $(DESTDIR)$(localstatedir)/nix/gcroots
|
||||
$(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) -d $(DESTDIR)$(storedir)
|
||||
$(INSTALL) $(INIT_FLAGS) $(GROUP_WRITABLE) -d $(DESTDIR)$(localstatedir)/nix/manifests
|
||||
ln -sfn $(localstatedir)/nix/manifests $(DESTDIR)$(localstatedir)/nix/gcroots/manifests
|
||||
|
||||
else
|
||||
|
||||
init-state:
|
||||
|
||||
endif
|
||||
|
||||
NEWS:
|
||||
$(MAKE) -C doc/manual NEWS.txt
|
||||
cp $(srcdir)/doc/manual/NEWS.txt NEWS
|
||||
|
||||
40
README
40
README
@@ -1,36 +1,10 @@
|
||||
Overview
|
||||
========
|
||||
|
||||
Nix is a package manager, deployment system, and component glue
|
||||
mechanism.
|
||||
Nix is a purely functional package manager. For installation and
|
||||
usage instructions, please read the manual, which can be found in
|
||||
`docs/manual/manual.html', and additionally at the Nix website at
|
||||
<http://nixos.org/>.
|
||||
|
||||
|
||||
Prerequisites
|
||||
=============
|
||||
Acknowledgments
|
||||
|
||||
* Berkeley DB 4.0.14
|
||||
* CWI ATerm 2.0
|
||||
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
* When building from the Subversion repository, first do:
|
||||
|
||||
autoreconf -i
|
||||
|
||||
* To build, do:
|
||||
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
|
||||
Note that this will install to /nix, which is the default prefix.
|
||||
You can specify another prefix, but this is not recommended if you
|
||||
want to use prebuilt packages from other sources.
|
||||
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
TODO
|
||||
This product includes software developed by the OpenSSL Project for
|
||||
use in the OpenSSL Toolkit (http://www.OpenSSL.org/).
|
||||
|
||||
4
bootstrap.sh
Executable file
4
bootstrap.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
#! /bin/sh -e
|
||||
rm -f aclocal.m4
|
||||
mkdir -p config
|
||||
exec autoreconf -vfi
|
||||
169
build.nix
Normal file
169
build.nix
Normal file
@@ -0,0 +1,169 @@
|
||||
with import <nix-make/lib>;
|
||||
with pkgs;
|
||||
|
||||
rec {
|
||||
|
||||
bin2c = link {
|
||||
objects = [ (compileC { main = ./src/bin2c/bin2c.c; }) ];
|
||||
programName = "bin2c";
|
||||
};
|
||||
|
||||
bsdiff = link {
|
||||
objects = [ (compileC { main = ./src/bsdiff-4.3/bsdiff.c; buildInputs = [ pkgs.bzip2 ]; }) ];
|
||||
programName = "bsdiff";
|
||||
buildInputs = [ pkgs.bzip2 ];
|
||||
flags = "-lbz2";
|
||||
};
|
||||
|
||||
bspatch = link {
|
||||
objects = [ (compileC { main = ./src/bsdiff-4.3/bspatch.c; buildInputs = [ pkgs.bzip2 ]; }) ];
|
||||
programName = "bspatch";
|
||||
buildInputs = [ pkgs.bzip2 ];
|
||||
flags = "-lbz2";
|
||||
};
|
||||
|
||||
libformat = makeLibrary {
|
||||
objects =
|
||||
map (fn: compileC {
|
||||
main = fn;
|
||||
localIncludePath = [ ./src ];
|
||||
})
|
||||
[ ./src/boost/format/format_implementation.cc
|
||||
./src/boost/format/free_funcs.cc
|
||||
./src/boost/format/parsing.cc
|
||||
];
|
||||
libraryName = "format";
|
||||
};
|
||||
|
||||
libutil = makeLibrary {
|
||||
objects =
|
||||
map (fn: compileC {
|
||||
main = fn;
|
||||
localIncludePath = [ ./src/libutil ./src ./. ];
|
||||
buildInputs = [ pkgs.openssl ];
|
||||
})
|
||||
[ ./src/libutil/util.cc
|
||||
./src/libutil/hash.cc
|
||||
./src/libutil/serialise.cc
|
||||
./src/libutil/archive.cc
|
||||
./src/libutil/xml-writer.cc
|
||||
./src/libutil/immutable.cc
|
||||
];
|
||||
libraryName = "util";
|
||||
};
|
||||
|
||||
libstore = makeLibrary {
|
||||
objects =
|
||||
map (fn: compileC {
|
||||
main = fn;
|
||||
localIncludePath = [ ./src/libstore ./src/libutil ./src ./. ];
|
||||
buildInputs = [ pkgs.sqlite ];
|
||||
cFlags = "-DNIX_STORE_DIR=\"/nix/store\" -DNIX_DATA_DIR=\"/home/eelco/Dev/nix/inst/share\" -DNIX_STATE_DIR=\"/nix/var/nix\" -DNIX_LOG_DIR=\"/foo\" -DNIX_CONF_DIR=\"/foo\" -DNIX_LIBEXEC_DIR=\"/foo\" -DNIX_BIN_DIR=\"/home/eelco/Dev/nix/inst/bin\"";
|
||||
})
|
||||
[ ./src/libstore/store-api.cc
|
||||
./src/libstore/local-store.cc
|
||||
./src/libstore/remote-store.cc
|
||||
./src/libstore/derivations.cc
|
||||
./src/libstore/build.cc
|
||||
./src/libstore/misc.cc
|
||||
./src/libstore/globals.cc
|
||||
./src/libstore/references.cc
|
||||
./src/libstore/pathlocks.cc
|
||||
./src/libstore/gc.cc
|
||||
./src/libstore/optimise-store.cc
|
||||
];
|
||||
libraryName = "store";
|
||||
};
|
||||
|
||||
libmain = makeLibrary {
|
||||
objects =
|
||||
map (fn: compileC {
|
||||
main = fn;
|
||||
localIncludePath = [ ./src/libmain ./src/libstore ./src/libutil ./src ./. ];
|
||||
})
|
||||
[ ./src/libmain/shared.cc ];
|
||||
libraryName = "main";
|
||||
};
|
||||
|
||||
nix_hash = link {
|
||||
objects =
|
||||
map (fn: compileC {
|
||||
main = fn;
|
||||
localIncludePath = [ ./src/nix-hash ./src/libmain ./src/libstore ./src/libutil ./src ./. ];
|
||||
})
|
||||
[ ./src/nix-hash/nix-hash.cc
|
||||
];
|
||||
libraries = [ libformat libutil libstore libmain ];
|
||||
buildInputs = [ pkgs.openssl pkgs.sqlite ];
|
||||
flags = "-lssl -lsqlite3 -lstdc++";
|
||||
programName = "nix-hash";
|
||||
};
|
||||
|
||||
nix_store = link {
|
||||
objects =
|
||||
map (fn: compileC {
|
||||
main = fn;
|
||||
localIncludePath = [ ./src/nix-store ./src/libmain ./src/libstore ./src/libutil ./src ./. ];
|
||||
})
|
||||
[ ./src/nix-store/nix-store.cc
|
||||
./src/nix-store/dotgraph.cc
|
||||
./src/nix-store/xmlgraph.cc
|
||||
];
|
||||
libraries = [ libformat libutil libstore libmain ];
|
||||
buildInputs = [ pkgs.openssl pkgs.sqlite ];
|
||||
flags = "-lssl -lsqlite3 -lstdc++";
|
||||
programName = "nix-store";
|
||||
};
|
||||
|
||||
libexpr = makeLibrary {
|
||||
objects =
|
||||
map (fn: compileC {
|
||||
main = fn;
|
||||
localIncludePath = [ ./src/libexpr ./src/libstore ./src/libutil ./src ./. ];
|
||||
})
|
||||
[ ./src/libexpr/nixexpr.cc
|
||||
./src/libexpr/eval.cc
|
||||
./src/libexpr/primops.cc
|
||||
./src/libexpr/lexer-tab.cc
|
||||
./src/libexpr/parser-tab.cc
|
||||
./src/libexpr/get-drvs.cc
|
||||
./src/libexpr/attr-path.cc
|
||||
./src/libexpr/value-to-xml.cc
|
||||
./src/libexpr/common-opts.cc
|
||||
./src/libexpr/names.cc
|
||||
];
|
||||
libraryName = "expr";
|
||||
};
|
||||
|
||||
nix_instantiate = link {
|
||||
objects =
|
||||
map (fn: compileC {
|
||||
main = fn;
|
||||
localIncludePath = [ ./src/nix-instantiate ./src/libexpr ./src/libmain ./src/libstore ./src/libutil ./src ./. ];
|
||||
})
|
||||
[ ./src/nix-instantiate/nix-instantiate.cc ];
|
||||
libraries = [ libformat libutil libstore libmain libexpr ];
|
||||
buildInputs = [ pkgs.openssl pkgs.sqlite ];
|
||||
flags = "-lssl -lsqlite3 -lstdc++";
|
||||
programName = "nix-instantiate";
|
||||
};
|
||||
|
||||
nix_env = link {
|
||||
objects =
|
||||
map (fn: compileC {
|
||||
main = fn;
|
||||
localIncludePath = [ ./src/nix-env ./src/libexpr ./src/libmain ./src/libstore ./src/libutil ./src ./. ];
|
||||
})
|
||||
[ ./src/nix-env/nix-env.cc
|
||||
./src/nix-env/profiles.cc
|
||||
./src/nix-env/user-env.cc
|
||||
];
|
||||
libraries = [ libformat libutil libstore libmain libexpr ];
|
||||
buildInputs = [ pkgs.openssl pkgs.sqlite ];
|
||||
flags = "-lssl -lsqlite3 -lstdc++";
|
||||
programName = "nix-env";
|
||||
};
|
||||
|
||||
all = [ bsdiff bspatch nix_hash nix_store nix_instantiate nix_env ];
|
||||
|
||||
}
|
||||
380
configure.ac
380
configure.ac
@@ -1,14 +1,384 @@
|
||||
AC_INIT(nix, 0.1)
|
||||
AC_CONFIG_SRCDIR(src/nix.cc)
|
||||
AC_INIT(nix, m4_esyscmd([echo -n $(cat ./version)$VERSION_SUFFIX]))
|
||||
AC_CONFIG_SRCDIR(README)
|
||||
AC_CONFIG_AUX_DIR(config)
|
||||
AM_INIT_AUTOMAKE
|
||||
AM_INIT_AUTOMAKE([dist-bzip2 foreign])
|
||||
|
||||
AC_PREFIX_DEFAULT(/nix)
|
||||
AC_DEFINE_UNQUOTED(NIX_VERSION, ["$VERSION"], [Nix version.])
|
||||
|
||||
AC_PROG_SED
|
||||
|
||||
# Construct a Nix system name (like "i686-linux").
|
||||
AC_CANONICAL_HOST
|
||||
AC_MSG_CHECKING([for the canonical Nix system name])
|
||||
|
||||
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
|
||||
|
||||
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_MSG_RESULT($system)
|
||||
AC_SUBST(system)
|
||||
AC_DEFINE_UNQUOTED(SYSTEM, ["$system"], [platform identifier (`cpu-os')])
|
||||
|
||||
|
||||
# State should be stored in /nix/var, unless the user overrides it explicitly.
|
||||
test "$localstatedir" = '${prefix}/var' && localstatedir=/nix/var
|
||||
|
||||
|
||||
# Windows-specific stuff. On Cygwin, dynamically linking against the
|
||||
# ATerm DLL works, except that it requires the ATerm "lib" directory
|
||||
# to be in $PATH, as Windows doesn't have anything like an RPATH
|
||||
# embedded in executable. Since this is kind of annoying, we use
|
||||
# static libraries for now.
|
||||
if test "$sys_name" = "cygwin"; then
|
||||
AC_DISABLE_SHARED
|
||||
AC_ENABLE_STATIC
|
||||
fi
|
||||
|
||||
|
||||
# Solaris-specific stuff.
|
||||
if test "$sys_name" = sunos; then
|
||||
# Solaris requires -lsocket -lnsl for network functions
|
||||
LIBS="-lsocket -lnsl $LIBS"
|
||||
fi
|
||||
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
|
||||
AC_CONFIG_FILES([Makefile src/Makefile scripts/Makefile])
|
||||
# To build programs to be run in the build machine.
|
||||
if test "$CC_FOR_BUILD" = ""; then
|
||||
if test "$cross_compiling" = "yes"; then
|
||||
AC_CHECK_PROGS(CC_FOR_BUILD, gcc cc)
|
||||
else
|
||||
CC_FOR_BUILD="$CC"
|
||||
fi
|
||||
fi
|
||||
AC_SUBST([CC_FOR_BUILD])
|
||||
|
||||
# We are going to use libtool.
|
||||
AC_DISABLE_STATIC
|
||||
AC_ENABLE_SHARED
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
|
||||
# Use 64-bit file system calls so that we can support files > 2 GiB.
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
|
||||
# Check for pubsetbuf.
|
||||
AC_MSG_CHECKING([for pubsetbuf])
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <iostream>
|
||||
using namespace std;
|
||||
static char buf[1024];]],
|
||||
[[cerr.rdbuf()->pubsetbuf(buf, sizeof(buf));]])],
|
||||
[AC_MSG_RESULT(yes) AC_DEFINE(HAVE_PUBSETBUF, 1, [Whether pubsetbuf is available.])],
|
||||
AC_MSG_RESULT(no))
|
||||
AC_LANG_POP(C++)
|
||||
|
||||
|
||||
# Check for chroot support (requires chroot() and bind mounts).
|
||||
AC_CHECK_FUNCS([chroot])
|
||||
AC_CHECK_FUNCS([unshare])
|
||||
AC_CHECK_HEADERS([sched.h])
|
||||
AC_CHECK_HEADERS([sys/param.h])
|
||||
AC_CHECK_HEADERS([sys/mount.h], [], [],
|
||||
[#ifdef HAVE_SYS_PARAM_H
|
||||
# include <sys/param.h>
|
||||
# endif
|
||||
])
|
||||
|
||||
|
||||
# Check for vfork.
|
||||
#AC_FUNC_FORK()
|
||||
|
||||
|
||||
# Check for lutimes, optionally used for changing the mtime of
|
||||
# symlinks.
|
||||
AC_CHECK_FUNCS([lutimes])
|
||||
|
||||
|
||||
# Check whether the store optimiser can optimise symlinks.
|
||||
AC_MSG_CHECKING([whether it is possible to create a link to a symlink])
|
||||
ln -s bla tmp_link
|
||||
if ln tmp_link tmp_link2 2> /dev/null; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(CAN_LINK_SYMLINK, 1, [Whether link() works on symlinks.])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
rm -f tmp_link tmp_link2
|
||||
|
||||
|
||||
# Check for <locale>.
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_CHECK_HEADERS([locale])
|
||||
AC_LANG_POP(C++)
|
||||
|
||||
|
||||
# Check for <err.h>.
|
||||
AC_CHECK_HEADER([err.h], [], [bsddiff_compat_include="-Icompat-include"])
|
||||
AC_SUBST([bsddiff_compat_include])
|
||||
|
||||
|
||||
# Check whether we have the personality() syscall, which allows us to
|
||||
# do i686-linux builds on x86_64-linux machines.
|
||||
AC_CHECK_HEADERS([sys/personality.h])
|
||||
|
||||
|
||||
# Check for <linux/fs.h> (for immutable file support).
|
||||
AC_CHECK_HEADERS([linux/fs.h])
|
||||
|
||||
|
||||
# Check for tr1/unordered_set.
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_CHECK_HEADERS([tr1/unordered_set])
|
||||
AC_LANG_POP(C++)
|
||||
|
||||
|
||||
AC_DEFUN([NEED_PROG],
|
||||
[
|
||||
AC_PATH_PROG($1, $2)
|
||||
if test -z "$$1"; then
|
||||
AC_MSG_ERROR([$2 is required])
|
||||
fi
|
||||
])
|
||||
|
||||
NEED_PROG(curl, curl)
|
||||
NEED_PROG(bash, bash)
|
||||
NEED_PROG(patch, patch)
|
||||
AC_PATH_PROG(xmllint, xmllint, false)
|
||||
AC_PATH_PROG(xsltproc, xsltproc, false)
|
||||
AC_PATH_PROG(w3m, w3m, false)
|
||||
AC_PATH_PROG(flex, flex, false)
|
||||
AC_PATH_PROG(bison, bison, false)
|
||||
NEED_PROG(perl, perl)
|
||||
NEED_PROG(sed, sed)
|
||||
NEED_PROG(tar, tar)
|
||||
NEED_PROG(bzip2, bzip2)
|
||||
NEED_PROG(xz, xz)
|
||||
AC_PATH_PROG(dot, dot)
|
||||
AC_PATH_PROG(dblatex, dblatex)
|
||||
AC_PATH_PROG(gzip, gzip)
|
||||
AC_PATH_PROG(pv, pv, pv)
|
||||
|
||||
|
||||
# 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
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([Your Perl version is too old. Nix requires Perl 5.8.0 or newer.])
|
||||
fi
|
||||
AC_MSG_RESULT(yes)
|
||||
|
||||
|
||||
# Figure out where to install Perl modules.
|
||||
AC_MSG_CHECKING([for the Perl installation prefix])
|
||||
perlversion=$($perl -e 'use Config; print $Config{version};')
|
||||
perlarchname=$($perl -e 'use Config; print $Config{archname};')
|
||||
AC_SUBST(perllibdir, [$\(libdir\)/perl5/site_perl/$perlversion/$perlarchname])
|
||||
AC_MSG_RESULT($perllibdir)
|
||||
|
||||
|
||||
NEED_PROG(cat, cat)
|
||||
NEED_PROG(tr, tr)
|
||||
AC_ARG_WITH(coreutils-bin, AC_HELP_STRING([--with-coreutils-bin=PATH],
|
||||
[path of cat, mkdir, etc.]),
|
||||
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)
|
||||
AC_SUBST(docbookrng)
|
||||
|
||||
AC_ARG_WITH(docbook-xsl, AC_HELP_STRING([--with-docbook-xsl=PATH],
|
||||
[path of the DocBook XSL stylesheets]),
|
||||
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 (defaults to /nix/store)]),
|
||||
storedir=$withval, storedir='/nix/store')
|
||||
AC_SUBST(storedir)
|
||||
|
||||
|
||||
# Look for OpenSSL, an optional dependency.
|
||||
AC_PATH_PROG(openssl_prog, openssl, openssl) # if not found, call openssl in $PATH
|
||||
AC_SUBST(openssl_prog)
|
||||
AC_DEFINE_UNQUOTED(OPENSSL_PATH, ["$openssl_prog"], [Path of the OpenSSL binary])
|
||||
|
||||
PKG_CHECK_MODULES([OPENSSL], [libcrypto],
|
||||
[AC_DEFINE([HAVE_OPENSSL], [1], [Whether to use OpenSSL.])
|
||||
CXXFLAGS="$OPENSSL_CFLAGS $CXXFLAGS"
|
||||
have_openssl=1], [true])
|
||||
AM_CONDITIONAL(HAVE_OPENSSL, test "$have_openssl" = 1)
|
||||
|
||||
|
||||
# Look for libbz2, a required dependency.
|
||||
AC_CHECK_LIB([bz2], [BZ2_bzWriteOpen], [true],
|
||||
[AC_MSG_ERROR([Nix requires libbz2, which is part of bzip2. See http://www.bzip.org/.])])
|
||||
AC_CHECK_HEADERS([bzlib.h], [true],
|
||||
[AC_MSG_ERROR([Nix requires libbz2, which is part of bzip2. See http://www.bzip.org/.])])
|
||||
|
||||
|
||||
# Look for SQLite, a required dependency.
|
||||
PKG_CHECK_MODULES([SQLITE3], [sqlite3 >= 3.6.19], [CXXFLAGS="$SQLITE3_CFLAGS $CXXFLAGS"])
|
||||
|
||||
|
||||
# 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) [default=no]]),
|
||||
gc=$enableval, gc=no)
|
||||
if test "$gc" = yes; then
|
||||
PKG_CHECK_MODULES([BDW_GC], [bdw-gc])
|
||||
CXXFLAGS="$BDW_GC_CFLAGS $CXXFLAGS"
|
||||
AC_DEFINE(HAVE_BOEHMGC, 1, [Whether to use the Boehm garbage collector.])
|
||||
fi
|
||||
|
||||
|
||||
# Check for the required Perl dependencies (DBI, DBD::SQLite and WWW::Curl).
|
||||
perlFlags="-I$perllibdir"
|
||||
|
||||
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_ARG_WITH(www-curl, AC_HELP_STRING([--with-www-curl=PATH],
|
||||
[prefix of the Perl WWW::Curl 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_MSG_CHECKING([whether WWW::Curl works])
|
||||
if ! $perl $perlFlags -e 'use WWW::Curl;' 2>&5; then
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_FAILURE([The Perl module WWW::Curl is missing.])
|
||||
fi
|
||||
AC_MSG_RESULT(yes)
|
||||
|
||||
AC_SUBST(perlFlags)
|
||||
|
||||
|
||||
# Whether to build the Perl bindings
|
||||
AC_MSG_CHECKING([whether to build the Perl bindings])
|
||||
AC_ARG_ENABLE(perl-bindings, AC_HELP_STRING([--enable-perl-bindings],
|
||||
[whether to build the Perl bindings (recommended) [default=yes]]),
|
||||
perlbindings=$enableval, perlbindings=yes)
|
||||
if test "$enable_shared" = no; then
|
||||
# Perl bindings require shared libraries.
|
||||
perlbindings=no
|
||||
fi
|
||||
AM_CONDITIONAL(PERL_BINDINGS, test "$perlbindings" = "yes")
|
||||
AC_SUBST(perlbindings)
|
||||
AC_MSG_RESULT($perlbindings)
|
||||
|
||||
|
||||
AC_ARG_ENABLE(init-state, AC_HELP_STRING([--disable-init-state],
|
||||
[do not initialise DB etc. in `make install']),
|
||||
init_state=$enableval, init_state=yes)
|
||||
AM_CONDITIONAL(INIT_STATE, test "$init_state" = "yes")
|
||||
|
||||
|
||||
# Setuid installations.
|
||||
AC_CHECK_FUNCS([setresuid setreuid lchown])
|
||||
|
||||
|
||||
# Nice to have, but not essential.
|
||||
AC_CHECK_FUNCS([strsignal posix_fallocate nanosleep sysconf])
|
||||
|
||||
|
||||
# This is needed if bzip2 is a static library, and the Nix libraries
|
||||
# are dynamic.
|
||||
if test "$(uname)" = "Darwin"; then
|
||||
LDFLAGS="-all_load $LDFLAGS"
|
||||
fi
|
||||
|
||||
|
||||
# Figure out the extension of dynamic libraries.
|
||||
eval dynlib_suffix=$shrext_cmds
|
||||
AC_SUBST(dynlib_suffix)
|
||||
|
||||
|
||||
# Do we have GNU tar?
|
||||
AC_MSG_CHECKING([if you have a recent GNU tar])
|
||||
if $tar --version 2> /dev/null | grep -q GNU && tar cvf /dev/null --warning=no-timestamp ./config.log > /dev/null; then
|
||||
AC_MSG_RESULT(yes)
|
||||
tarFlags="--warning=no-timestamp"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AC_SUBST(tarFlags)
|
||||
|
||||
|
||||
|
||||
AM_CONFIG_HEADER([config.h])
|
||||
AC_CONFIG_FILES([Makefile
|
||||
src/Makefile
|
||||
src/boost/Makefile
|
||||
src/boost/format/Makefile
|
||||
src/libutil/Makefile
|
||||
src/libstore/Makefile
|
||||
src/libmain/Makefile
|
||||
src/nix-store/Makefile
|
||||
src/nix-hash/Makefile
|
||||
src/libexpr/Makefile
|
||||
src/nix-instantiate/Makefile
|
||||
src/nix-env/Makefile
|
||||
src/nix-daemon/Makefile
|
||||
src/nix-setuid-helper/Makefile
|
||||
src/nix-log2xml/Makefile
|
||||
src/bsdiff-4.3/Makefile
|
||||
perl/Makefile
|
||||
scripts/Makefile
|
||||
corepkgs/Makefile
|
||||
doc/Makefile
|
||||
doc/manual/Makefile
|
||||
misc/Makefile
|
||||
misc/emacs/Makefile
|
||||
tests/Makefile
|
||||
])
|
||||
AC_OUTPUT
|
||||
|
||||
12
corepkgs/Makefile.am
Normal file
12
corepkgs/Makefile.am
Normal file
@@ -0,0 +1,12 @@
|
||||
all-local: config.nix
|
||||
|
||||
files = nar.nix buildenv.nix buildenv.pl unpack-channel.nix derivation.nix fetchurl.nix \
|
||||
imported-drv-to-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)
|
||||
28
corepkgs/buildenv.nix
Normal file
28
corepkgs/buildenv.nix
Normal file
@@ -0,0 +1,28 @@
|
||||
with import <nix/config.nix>;
|
||||
|
||||
{ derivations, manifest }:
|
||||
|
||||
derivation {
|
||||
name = "user-environment";
|
||||
system = builtins.currentSystem;
|
||||
builder = perl;
|
||||
args = [ "-w" ./buildenv.pl ];
|
||||
|
||||
manifest = manifest;
|
||||
|
||||
# !!! grmbl, need structured data for passing this in a clean way.
|
||||
derivations =
|
||||
map (d:
|
||||
[ (d.meta.active or "true")
|
||||
(d.meta.priority or 5)
|
||||
(builtins.length d.outputs)
|
||||
] ++ map (output: builtins.getAttr output d) d.outputs)
|
||||
derivations;
|
||||
|
||||
# Building user environments remotely just causes huge amounts of
|
||||
# network traffic, so don't do that.
|
||||
preferLocalBuild = true;
|
||||
|
||||
# Don't build in a chroot because Nix's dependencies may not be there.
|
||||
__noChroot = true;
|
||||
}
|
||||
171
corepkgs/buildenv.pl
Normal file
171
corepkgs/buildenv.pl
Normal file
@@ -0,0 +1,171 @@
|
||||
use strict;
|
||||
use Cwd;
|
||||
use IO::Handle;
|
||||
|
||||
STDOUT->autoflush(1);
|
||||
|
||||
my $out = $ENV{"out"};
|
||||
mkdir "$out", 0755 || die "error creating $out";
|
||||
|
||||
|
||||
my $symlinks = 0;
|
||||
|
||||
my %priorities;
|
||||
|
||||
|
||||
# For each activated package, create symlinks.
|
||||
|
||||
sub createLinks {
|
||||
my $srcDir = shift;
|
||||
my $dstDir = shift;
|
||||
my $priority = shift;
|
||||
|
||||
my @srcFiles = glob("$srcDir/*");
|
||||
|
||||
foreach my $srcFile (@srcFiles) {
|
||||
my $baseName = $srcFile;
|
||||
$baseName =~ s/^.*\///g; # strip directory
|
||||
my $dstFile = "$dstDir/$baseName";
|
||||
|
||||
# The files below are special-cased so that they don't show up
|
||||
# in user profiles, either because they are useless, or
|
||||
# because they would cause pointless collisions (e.g., each
|
||||
# Python package brings its own
|
||||
# `$out/lib/pythonX.Y/site-packages/easy-install.pth'.)
|
||||
# Urgh, hacky...
|
||||
if ($srcFile =~ /\/propagated-build-inputs$/ ||
|
||||
$srcFile =~ /\/nix-support$/ ||
|
||||
$srcFile =~ /\/perllocal.pod$/ ||
|
||||
$srcFile =~ /\/easy-install.pth$/ ||
|
||||
$srcFile =~ /\/site.py$/ ||
|
||||
$srcFile =~ /\/site.pyc$/ ||
|
||||
$srcFile =~ /\/info\/dir$/ ||
|
||||
$srcFile =~ /\/log$/)
|
||||
{
|
||||
# Do nothing.
|
||||
}
|
||||
|
||||
elsif (-d $srcFile) {
|
||||
|
||||
lstat $dstFile;
|
||||
|
||||
if (-d _) {
|
||||
createLinks($srcFile, $dstFile, $priority);
|
||||
}
|
||||
|
||||
elsif (-l _) {
|
||||
my $target = readlink $dstFile or die;
|
||||
if (!-d $target) {
|
||||
die "collission between directory `$srcFile' and non-directory `$target'";
|
||||
}
|
||||
unlink $dstFile or die "error unlinking `$dstFile': $!";
|
||||
mkdir $dstFile, 0755 ||
|
||||
die "error creating directory `$dstFile': $!";
|
||||
createLinks($target, $dstFile, $priorities{$dstFile});
|
||||
createLinks($srcFile, $dstFile, $priority);
|
||||
}
|
||||
|
||||
else {
|
||||
symlink($srcFile, $dstFile) ||
|
||||
die "error creating link `$dstFile': $!";
|
||||
$priorities{$dstFile} = $priority;
|
||||
$symlinks++;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
if (-l $dstFile) {
|
||||
my $target = readlink $dstFile;
|
||||
my $prevPriority = $priorities{$dstFile};
|
||||
die ( "collission between `$srcFile' and `$target'; "
|
||||
. "use `nix-env --set-flag "
|
||||
. "priority NUMBER PKGNAME' to change the priority of "
|
||||
. "one of the conflicting packages\n" )
|
||||
if $prevPriority == $priority;
|
||||
next if $prevPriority < $priority;
|
||||
unlink $dstFile or die;
|
||||
}
|
||||
|
||||
symlink($srcFile, $dstFile) ||
|
||||
die "error creating link `$dstFile': $!";
|
||||
$priorities{$dstFile} = $priority;
|
||||
$symlinks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
my %done;
|
||||
my %postponed;
|
||||
|
||||
sub addPkg;
|
||||
sub addPkg {
|
||||
my $pkgDir = shift;
|
||||
my $priority = shift;
|
||||
|
||||
return if (defined $done{$pkgDir});
|
||||
$done{$pkgDir} = 1;
|
||||
|
||||
# print "symlinking $pkgDir\n";
|
||||
createLinks("$pkgDir", "$out", $priority);
|
||||
|
||||
my $propagatedFN = "$pkgDir/nix-support/propagated-user-env-packages";
|
||||
if (-e $propagatedFN) {
|
||||
open PROP, "<$propagatedFN" or die;
|
||||
my $propagated = <PROP>;
|
||||
close PROP;
|
||||
my @propagated = split ' ', $propagated;
|
||||
foreach my $p (@propagated) {
|
||||
$postponed{$p} = 1 unless defined $done{$p};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Convert the stuff we get from the environment back into a coherent
|
||||
# data type.
|
||||
my @pkgs;
|
||||
my @derivations = split ' ', $ENV{"derivations"};
|
||||
while (scalar @derivations) {
|
||||
my $active = shift @derivations;
|
||||
my $priority = shift @derivations;
|
||||
my $outputs = shift @derivations;
|
||||
for (my $n = 0; $n < $outputs; $n++) {
|
||||
my $path = shift @derivations;
|
||||
push @pkgs,
|
||||
{ path => $path
|
||||
, active => $active ne "false"
|
||||
, priority => int($priority) };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Symlink to the packages that have been installed explicitly by the
|
||||
# user. Process in priority order to reduce unnecessary
|
||||
# symlink/unlink steps.
|
||||
@pkgs = sort { $a->{priority} <=> $b->{priority} || $a->{path} cmp $b->{path} } @pkgs;
|
||||
foreach my $pkg (@pkgs) {
|
||||
#print $pkg, " ", $pkgs{$pkg}->{priority}, "\n";
|
||||
addPkg($pkg->{path}, $pkg->{priority}) if $pkg->{active};
|
||||
}
|
||||
|
||||
|
||||
# Symlink to the packages that have been "propagated" by packages
|
||||
# installed by the user (i.e., package X declares that it want Y
|
||||
# installed as well). We do these later because they have a lower
|
||||
# priority in case of collisions.
|
||||
my $priorityCounter = 1000; # don't care about collisions
|
||||
while (scalar(keys %postponed) > 0) {
|
||||
my @pkgDirs = keys %postponed;
|
||||
%postponed = ();
|
||||
foreach my $pkgDir (sort @pkgDirs) {
|
||||
addPkg($pkgDir, $priorityCounter++);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
print STDERR "created $symlinks symlinks in user environment\n";
|
||||
|
||||
|
||||
symlink($ENV{"manifest"}, "$out/manifest.nix") or die "cannot create manifest";
|
||||
16
corepkgs/config.nix.in
Normal file
16
corepkgs/config.nix.in
Normal file
@@ -0,0 +1,16 @@
|
||||
let
|
||||
fromEnv = var: def:
|
||||
let val = builtins.getEnv var; in
|
||||
if val != "" then val else def;
|
||||
in {
|
||||
perl = "@perl@";
|
||||
shell = "@shell@";
|
||||
coreutils = "@coreutils@";
|
||||
bzip2 = "@bzip2@";
|
||||
xz = "@xz@";
|
||||
tar = "@tar@";
|
||||
tarFlags = "@tarFlags@";
|
||||
tr = "@tr@";
|
||||
curl = "@curl@";
|
||||
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
|
||||
36
corepkgs/fetchurl.nix
Normal file
36
corepkgs/fetchurl.nix
Normal file
@@ -0,0 +1,36 @@
|
||||
with import <nix/config.nix>;
|
||||
|
||||
{system ? builtins.currentSystem, url, outputHash ? "", outputHashAlgo ? "", md5 ? "", sha1 ? "", sha256 ? ""}:
|
||||
|
||||
assert (outputHash != "" && outputHashAlgo != "")
|
||||
|| md5 != "" || sha1 != "" || sha256 != "";
|
||||
|
||||
let
|
||||
|
||||
builder = builtins.toFile "fetchurl.sh"
|
||||
''
|
||||
echo "downloading $url into $out"
|
||||
${curl} --fail --location --max-redirs 20 --insecure "$url" > "$out"
|
||||
'';
|
||||
|
||||
in
|
||||
|
||||
derivation {
|
||||
name = baseNameOf (toString url);
|
||||
builder = shell;
|
||||
args = [ "-e" builder ];
|
||||
|
||||
# New-style output content requirements.
|
||||
outputHashAlgo = if outputHashAlgo != "" then outputHashAlgo else
|
||||
if sha256 != "" then "sha256" else if sha1 != "" then "sha1" else "md5";
|
||||
outputHash = if outputHash != "" then outputHash else
|
||||
if sha256 != "" then sha256 else if sha1 != "" then sha1 else md5;
|
||||
|
||||
inherit system url;
|
||||
|
||||
# No need to double the amount of network traffic
|
||||
preferLocalBuild = true;
|
||||
|
||||
# Don't build in a chroot because Nix's dependencies may not be there.
|
||||
__noChroot = true;
|
||||
}
|
||||
21
corepkgs/imported-drv-to-derivation.nix
Normal file
21
corepkgs/imported-drv-to-derivation.nix
Normal file
@@ -0,0 +1,21 @@
|
||||
attrs @ { drvPath, outputs, ... }:
|
||||
|
||||
let
|
||||
|
||||
commonAttrs = (builtins.listToAttrs outputsList) //
|
||||
{ all = map (x: x.value) outputsList;
|
||||
inherit drvPath;
|
||||
type = "derivation";
|
||||
};
|
||||
|
||||
outputToAttrListElement = outputName:
|
||||
{ name = outputName;
|
||||
value = commonAttrs // {
|
||||
outPath = builtins.getAttr outputName attrs;
|
||||
inherit outputName;
|
||||
};
|
||||
};
|
||||
|
||||
outputsList = map outputToAttrListElement outputs;
|
||||
|
||||
in (builtins.head outputsList).value
|
||||
43
corepkgs/nar.nix
Normal file
43
corepkgs/nar.nix
Normal file
@@ -0,0 +1,43 @@
|
||||
with import <nix/config.nix>;
|
||||
|
||||
let
|
||||
|
||||
builder = builtins.toFile "nar.sh"
|
||||
''
|
||||
export PATH=${nixBinDir}:${coreutils}
|
||||
|
||||
if [ $compressionType = "xz" ]; then
|
||||
ext=xz
|
||||
compressor="${xz} -9"
|
||||
else
|
||||
ext=bz2
|
||||
compressor="${bzip2}"
|
||||
fi
|
||||
|
||||
echo "packing ‘$storePath’..."
|
||||
mkdir $out
|
||||
dst=$out/tmp.nar.$ext
|
||||
|
||||
set -o pipefail
|
||||
nix-store --dump "$storePath" | $compressor > $dst
|
||||
|
||||
hash=$(nix-hash --flat --type $hashAlgo --base32 $dst)
|
||||
echo -n $hash > $out/nar-compressed-hash
|
||||
|
||||
mv $dst $out/$hash.nar.$ext
|
||||
'';
|
||||
|
||||
in
|
||||
|
||||
{ storePath, hashAlgo, compressionType }:
|
||||
|
||||
derivation {
|
||||
name = "nar";
|
||||
system = builtins.currentSystem;
|
||||
builder = shell;
|
||||
args = [ "-e" builder ];
|
||||
inherit storePath hashAlgo compressionType;
|
||||
|
||||
# Don't build in a chroot because Nix's dependencies may not be there.
|
||||
__noChroot = true;
|
||||
}
|
||||
39
corepkgs/unpack-channel.nix
Normal file
39
corepkgs/unpack-channel.nix
Normal file
@@ -0,0 +1,39 @@
|
||||
with import <nix/config.nix>;
|
||||
|
||||
let
|
||||
|
||||
builder = builtins.toFile "unpack-channel.sh"
|
||||
''
|
||||
mkdir $out
|
||||
cd $out
|
||||
pat="\.xz\$"
|
||||
if [[ "$src" =~ $pat ]]; then
|
||||
${xz} -d < $src | ${tar} xf - ${tarFlags}
|
||||
else
|
||||
${bzip2} -d < $src | ${tar} xf - ${tarFlags}
|
||||
fi
|
||||
mv * $out/$channelName
|
||||
if [ -n "$binaryCacheURL" ]; then
|
||||
mkdir $out/binary-caches
|
||||
echo -n "$binaryCacheURL" > $out/binary-caches/$channelName
|
||||
fi
|
||||
'';
|
||||
|
||||
in
|
||||
|
||||
{ name, channelName, src, binaryCacheURL ? "" }:
|
||||
|
||||
derivation {
|
||||
system = builtins.currentSystem;
|
||||
builder = shell;
|
||||
args = [ "-e" builder ];
|
||||
inherit name channelName src binaryCacheURL;
|
||||
|
||||
PATH = "${nixBinDir}:${coreutils}";
|
||||
|
||||
# No point in doing this remotely.
|
||||
preferLocalBuild = true;
|
||||
|
||||
# Don't build in a chroot because Nix's dependencies may not be there.
|
||||
__noChroot = true;
|
||||
}
|
||||
1
doc/Makefile.am
Normal file
1
doc/Makefile.am
Normal file
@@ -0,0 +1 @@
|
||||
SUBDIRS = manual
|
||||
33
doc/dev/release-procedures.txt
Normal file
33
doc/dev/release-procedures.txt
Normal file
@@ -0,0 +1,33 @@
|
||||
To produce a `stable' release from the trunk:
|
||||
|
||||
-1. Update the release notes; make sure that the release date is
|
||||
correct.
|
||||
|
||||
0. Make sure that the trunk builds in the release supervisor.
|
||||
|
||||
1. Branch the trunk, e.g., `svn cp .../trunk
|
||||
.../branches/0.5-release'.
|
||||
|
||||
2. Switch to the branch, e.g., `svn switch .../branches/0.5-release'.
|
||||
|
||||
3. In `configure.ac', change `STABLE=0' into `STABLE=1' and commit.
|
||||
|
||||
4. In the release supervisor, add a one-time job to build
|
||||
`.../branches/0.5-release'.
|
||||
|
||||
5. Make sure that the release succeeds.
|
||||
|
||||
6. Move the branch to a tag, e.g., `svn mv .../branches/0.5-release
|
||||
.../tags/0.5'.
|
||||
|
||||
Note that the branch should not be used for maintenance; it should
|
||||
be deleted after the release has been created. A maintenance
|
||||
branch (e.g., `.../branches/0.5') should be created from the
|
||||
original revision of the trunk (since maintenance releases should
|
||||
also be tested first; hence, we cannot have `STABLE=1'). The same
|
||||
procedure can then be followed to produce maintenance releases;
|
||||
just substitute `.../branches/VERSION' for the trunk.
|
||||
|
||||
7. Switch back to the trunk.
|
||||
|
||||
8. Bump the version number in `configure.ac' (in AC_INIT).
|
||||
117
doc/manual/Makefile.am
Normal file
117
doc/manual/Makefile.am
Normal file
@@ -0,0 +1,117 @@
|
||||
XMLLINT = $(xmllint) --nonet $(xmlflags)
|
||||
XSLTPROC = $(xsltproc) --nonet $(xmlflags) \
|
||||
--param section.autolabel 1 \
|
||||
--param section.label.includes.component.label 1 \
|
||||
--param html.stylesheet \'style.css\' \
|
||||
--param xref.with.number.and.title 1 \
|
||||
--param toc.section.depth 3 \
|
||||
--param admon.style \'\' \
|
||||
--param callout.graphics.extension \'.gif\' \
|
||||
--param contrib.inline.enabled 0
|
||||
|
||||
dblatex_opts = \
|
||||
-P doc.collab.show=0 \
|
||||
-P latex.output.revhistory=0
|
||||
|
||||
# Note: we use GIF for now, since the PNGs shipped with Docbook aren't
|
||||
# transparent.
|
||||
|
||||
man1_MANS = nix-env.1 nix-build.1 nix-store.1 nix-instantiate.1 \
|
||||
nix-collect-garbage.1 nix-push.1 nix-pull.1 \
|
||||
nix-prefetch-url.1 nix-channel.1 \
|
||||
nix-install-package.1 nix-hash.1 nix-copy-closure.1
|
||||
|
||||
man5_MANS = nix.conf.5
|
||||
|
||||
man8_MANS = nix-daemon.8
|
||||
|
||||
FIGURES = figures/user-environments.png
|
||||
|
||||
MANUAL_SRCS = manual.xml introduction.xml installation.xml \
|
||||
package-management.xml writing-nix-expressions.xml builtins.xml \
|
||||
build-farm.xml \
|
||||
$(man1_MANS:.1=.xml) $(man8_MANS:.8=.xml) \
|
||||
troubleshooting.xml bugs.xml opt-common.xml opt-common-syn.xml opt-inst-syn.xml \
|
||||
env-common.xml quick-start.xml nix-lang-ref.xml glossary.xml \
|
||||
conf-file.xml release-notes.xml \
|
||||
style.css images
|
||||
|
||||
# Do XInclude processing.
|
||||
manual.xmli: $(MANUAL_SRCS) version.txt
|
||||
$(XMLLINT) --xinclude $< -o $@.tmp
|
||||
mv $@.tmp $@
|
||||
|
||||
# Note: RelaxNG validation requires xmllint >= 2.7.4.
|
||||
manual.is-valid: manual.xmli
|
||||
$(XSLTPROC) --novalid --stringparam profile.condition manual \
|
||||
$(docbookxsl)/profiling/profile.xsl $< 2> /dev/null | \
|
||||
$(XMLLINT) --noout --relaxng $(docbookrng)/docbook.rng -
|
||||
touch $@
|
||||
|
||||
version.txt:
|
||||
echo -n $(VERSION) > version.txt
|
||||
|
||||
man $(MANS): manual.is-valid
|
||||
$(XSLTPROC) --stringparam profile.condition manpage \
|
||||
$(docbookxsl)/profiling/profile.xsl manual.xmli 2> /dev/null | \
|
||||
$(XSLTPROC) $(docbookxsl)/manpages/docbook.xsl -
|
||||
|
||||
manual.html: $(MANUAL_SRCS) manual.is-valid images
|
||||
$(XSLTPROC) --xinclude --stringparam profile.condition manual \
|
||||
$(docbookxsl)/profiling/profile.xsl manual.xml | \
|
||||
$(XSLTPROC) --output manual.html $(docbookxsl)/html/docbook.xsl -
|
||||
|
||||
manual.pdf: $(MANUAL_SRCS) manual.is-valid images
|
||||
if test "$(dblatex)" != ""; then \
|
||||
$(XSLTPROC) --xinclude --stringparam profile.condition manual \
|
||||
$(docbookxsl)/profiling/profile.xsl manual.xml | \
|
||||
$(dblatex) -o manual.pdf $(dblatex_opts) -; \
|
||||
else \
|
||||
echo "Please install dblatex and rerun configure."; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
|
||||
NEWS_OPTS = \
|
||||
--stringparam generate.toc "article nop" \
|
||||
--stringparam section.autolabel.max.depth 0 \
|
||||
--stringparam header.rule 0
|
||||
|
||||
NEWS.html: release-notes.xml
|
||||
$(XSLTPROC) --xinclude --output $@ $(NEWS_OPTS) \
|
||||
$(docbookxsl)/html/docbook.xsl release-notes.xml
|
||||
|
||||
NEWS.txt: release-notes.xml
|
||||
$(XSLTPROC) --xinclude quote-literals.xsl release-notes.xml | \
|
||||
$(XSLTPROC) --output $@.tmp.html $(NEWS_OPTS) \
|
||||
$(docbookxsl)/html/docbook.xsl -
|
||||
LANG=en_US $(w3m) -dump $@.tmp.html > $@
|
||||
rm $@.tmp.html
|
||||
|
||||
|
||||
all-local: manual.html NEWS.html NEWS.txt
|
||||
|
||||
install-data-local: manual.html
|
||||
$(INSTALL) -d $(DESTDIR)$(docdir)/manual
|
||||
$(INSTALL_DATA) manual.html $(DESTDIR)$(docdir)/manual
|
||||
ln -sf manual.html $(DESTDIR)$(docdir)/manual/index.html
|
||||
$(INSTALL_DATA) style.css $(DESTDIR)$(docdir)/manual
|
||||
cp -r images $(DESTDIR)$(docdir)/manual/images
|
||||
$(INSTALL) -d $(DESTDIR)$(docdir)/manual/figures
|
||||
$(INSTALL_DATA) $(FIGURES) $(DESTDIR)$(docdir)/manual/figures
|
||||
$(INSTALL) -d $(DESTDIR)$(docdir)/release-notes
|
||||
$(INSTALL_DATA) NEWS.html $(DESTDIR)$(docdir)/release-notes/index.html
|
||||
$(INSTALL_DATA) style.css $(DESTDIR)$(docdir)/release-notes/
|
||||
|
||||
images:
|
||||
mkdir images
|
||||
# cp $(docbookxsl)/images/*.gif images
|
||||
mkdir images/callouts
|
||||
cp $(docbookxsl)/images/callouts/*.gif images/callouts
|
||||
chmod -R +w images
|
||||
|
||||
KEEP = manual.html manual.xmli manual.is-valid version.txt $(MANS) NEWS.html NEWS.txt
|
||||
|
||||
EXTRA_DIST = $(MANUAL_SRCS) $(FIGURES) $(KEEP)
|
||||
|
||||
DISTCLEANFILES = $(KEEP)
|
||||
39
doc/manual/bugs.xml
Normal file
39
doc/manual/bugs.xml
Normal file
@@ -0,0 +1,39 @@
|
||||
<appendix xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
|
||||
<title>Bugs / To-Do</title>
|
||||
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>The man-pages generated from the DocBook documentation
|
||||
are ugly.</para></listitem>
|
||||
|
||||
<listitem><para>Generations properly form a tree. E.g., if after
|
||||
switching to generation 39, we perform an installation action, a
|
||||
generation 43 is created which is a descendant of 39, not 42. So a
|
||||
rollback from 43 ought to go back to 39. This is not currently
|
||||
implemented; generations form a linear sequence.</para></listitem>
|
||||
|
||||
<listitem><para>For security, <command>nix-push</command> manifests
|
||||
should be digitally signed, and <command>nix-pull</command> should
|
||||
verify the signatures. The actual NAR archives in the cache do not
|
||||
need to be signed, since the manifest contains cryptographic hashes of
|
||||
these files (and <filename>fetchurl.nix</filename> checks
|
||||
them).</para></listitem>
|
||||
|
||||
<listitem><para>It would be useful to have an option in
|
||||
<command>nix-env --delete-generations</command> to remove non-current
|
||||
generations older than a certain age.</para></listitem>
|
||||
|
||||
<listitem><para>There should be a flexible way to change the user
|
||||
environment builder. Currently, you have to replace
|
||||
<filename><replaceable>prefix</replaceable>/share/nix/corepkgs/buildenv/builder.pl</filename>,
|
||||
which is hard-coded into <command>nix-env</command>. Also, the
|
||||
default builder should be more powerful. For instance, there should
|
||||
be some way to specify priorities to resolve
|
||||
collisions.</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</appendix>
|
||||
113
doc/manual/build-farm.xml
Normal file
113
doc/manual/build-farm.xml
Normal file
@@ -0,0 +1,113 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id='chap-distributed-builds'>
|
||||
|
||||
<title>Setting Up Distributed Builds</title>
|
||||
|
||||
<para>Nix supports distributed builds: a local Nix installation can
|
||||
forward Nix builds to other machines over the network. This allows
|
||||
multiple builds to be performed in parallel (thus improving
|
||||
performance) and allows Nix to perform multi-platform builds in a
|
||||
semi-transparent way. For instance, if you perform a build for a
|
||||
<literal>powerpc-darwin</literal> on an <literal>i686-linux</literal>
|
||||
machine, Nix can automatically forward the build to a
|
||||
<literal>powerpc-darwin</literal> machine, if available.</para>
|
||||
|
||||
<para>You can enable distributed builds by setting the environment
|
||||
variable <envar>NIX_BUILD_HOOK</envar> to point to a program that Nix
|
||||
will call whenever it wants to build a derivation. The build hook
|
||||
(typically a shell or Perl script) can decline the build, in which Nix
|
||||
will perform it in the usual way if possible, or it can accept it, in
|
||||
which case it is responsible for somehow getting the inputs of the
|
||||
build to another machine, doing the build there, and getting the
|
||||
results back. The details of the build hook protocol are described in
|
||||
the documentation of the <link
|
||||
linkend="envar-build-hook"><envar>NIX_BUILD_HOOK</envar>
|
||||
variable</link>.</para>
|
||||
|
||||
<example xml:id='ex-remote-systems'><title>Remote machine configuration:
|
||||
<filename>remote-systems.conf</filename></title>
|
||||
<programlisting>
|
||||
nix@mcflurry.labs.cs.uu.nl powerpc-darwin /home/nix/.ssh/id_quarterpounder_auto 2
|
||||
nix@scratchy.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto 8 1 kvm
|
||||
nix@itchy.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto 8 2
|
||||
nix@poochie.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto 8 2 kvm perf
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
<para>Nix ships with a build hook that should be suitable for most
|
||||
purposes. It uses <command>ssh</command> and
|
||||
<command>nix-copy-closure</command> to copy the build inputs and
|
||||
outputs and perform the remote build. To use it, you should set
|
||||
<envar>NIX_BUILD_HOOK</envar> to
|
||||
<filename><replaceable>prefix</replaceable>/libexec/nix/build-remote.pl</filename>.
|
||||
You should also define a list of available build machines and point
|
||||
the environment variable <envar>NIX_REMOTE_SYSTEMS</envar> to it. An
|
||||
example configuration is shown in <xref linkend='ex-remote-systems'
|
||||
/>. Each line in the file specifies a machine, with the following
|
||||
bits of information:
|
||||
|
||||
<orderedlist>
|
||||
|
||||
<listitem><para>The name of the remote machine, with optionally the
|
||||
user under which the remote build should be performed. This is
|
||||
actually passed as an argument to <command>ssh</command>, so it can
|
||||
be an alias defined in your
|
||||
<filename>~/.ssh/config</filename>.</para></listitem>
|
||||
|
||||
<listitem><para>A comma-separated list of Nix platform type
|
||||
identifiers, such as <literal>powerpc-darwin</literal>. It is
|
||||
possible for a machine to support multiple platform types, e.g.,
|
||||
<literal>i686-linux,x86_64-linux</literal>.</para></listitem>
|
||||
|
||||
<listitem><para>The SSH private key to be used to log in to the
|
||||
remote machine. Since builds should be non-interactive, this key
|
||||
should not have a passphrase!</para></listitem>
|
||||
|
||||
<listitem><para>The maximum number of builds that
|
||||
<filename>build-remote.pl</filename> will execute in parallel on the
|
||||
machine. Typically this should be equal to the number of CPU cores.
|
||||
For instance, the machine <literal>itchy</literal> in the example
|
||||
will execute up to 8 builds in parallel.</para></listitem>
|
||||
|
||||
<listitem><para>The “speed factor”, indicating the relative speed of
|
||||
the machine. If there are multiple machines of the right type, Nix
|
||||
will prefer the fastest, taking load into account.</para></listitem>
|
||||
|
||||
<listitem><para>A comma-separated list of <emphasis>supported
|
||||
features</emphasis>. If a derivation has the
|
||||
<varname>requiredSystemFeatures</varname> attribute, then
|
||||
<filename>build-remote.pl</filename> will only perform the
|
||||
derivation on a machine that has the specified features. For
|
||||
instance, the attribute
|
||||
|
||||
<programlisting>
|
||||
requiredSystemFeatures = [ "kvm" ];
|
||||
</programlisting>
|
||||
|
||||
will cause the build to be performed on a machine that has the
|
||||
<literal>kvm</literal> feature (i.e., <literal>scratchy</literal> in
|
||||
the example above).</para></listitem>
|
||||
|
||||
<listitem><para>A comma-separated list of <emphasis>mandatory
|
||||
features</emphasis>. A machine will only be used to build a
|
||||
derivation if all of the machine’s mandatory features appear in the
|
||||
derivation’s <varname>requiredSystemFeatures</varname> attribute.
|
||||
Thus, in the example, the machine <literal>poochie</literal> will
|
||||
only do derivations that have
|
||||
<varname>requiredSystemFeatures</varname> set to <literal>["kvm"
|
||||
"perf"]</literal> or <literal>["perf"]</literal>.</para></listitem>
|
||||
|
||||
</orderedlist>
|
||||
|
||||
You should also set up the environment variable
|
||||
<envar>NIX_CURRENT_LOAD</envar> to point at a directory (e.g.,
|
||||
<filename>/var/run/nix/current-load</filename>) that
|
||||
<filename>build-remote.pl</filename> uses to remember how many builds
|
||||
it is currently executing remotely. It doesn't look at the actual
|
||||
load on the remote machine, so if you have multiple instances of Nix
|
||||
running, they should use the same <envar>NIX_CURRENT_LOAD</envar>
|
||||
file. Maybe in the future <filename>build-remote.pl</filename> will
|
||||
look at the actual remote load.</para>
|
||||
|
||||
</chapter>
|
||||
895
doc/manual/builtins.xml
Normal file
895
doc/manual/builtins.xml
Normal file
@@ -0,0 +1,895 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id='ssec-builtins'>
|
||||
|
||||
<title>Built-in functions</title>
|
||||
|
||||
|
||||
<para>This section lists the functions and constants built into the
|
||||
Nix expression evaluator. (The built-in function
|
||||
<function>derivation</function> is discussed above.) Some built-ins,
|
||||
such as <function>derivation</function>, are always in scope of every
|
||||
Nix expression; you can just access them right away. But to prevent
|
||||
polluting the namespace too much, most built-ins are not in scope.
|
||||
Instead, you can access them through the <varname>builtins</varname>
|
||||
built-in value, which is an attribute set that contains all built-in
|
||||
functions and values. For instance, <function>derivation</function>
|
||||
is also available as <function>builtins.derivation</function>.</para>
|
||||
|
||||
|
||||
<variablelist>
|
||||
|
||||
|
||||
<varlistentry><term><function>abort</function> <replaceable>s</replaceable></term>
|
||||
|
||||
<listitem><para>Abort Nix expression evaluation, print error
|
||||
message <replaceable>s</replaceable>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.add</function>
|
||||
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
|
||||
|
||||
<listitem><para>Return the sum of the integers
|
||||
<replaceable>e1</replaceable> and
|
||||
<replaceable>e2</replaceable>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.attrNames</function>
|
||||
<replaceable>attrs</replaceable></term>
|
||||
|
||||
<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:
|
||||
|
||||
<programlisting>
|
||||
attrValues = attrs: map (name: builtins.getAttr name attrs) (builtins.attrNames attrs);</programlisting>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>baseNameOf</function> <replaceable>s</replaceable></term>
|
||||
|
||||
<listitem><para>Return the <emphasis>base name</emphasis> of the
|
||||
string <replaceable>s</replaceable>, that is, everything following
|
||||
the final slash in the string. This is similar to the GNU
|
||||
<command>basename</command> command.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><varname>builtins</varname></term>
|
||||
|
||||
<listitem><para>The attribute set <varname>builtins</varname>
|
||||
contains all the built-in functions and values. You can use
|
||||
<varname>builtins</varname> to test for the availability of
|
||||
features in the Nix installation, e.g.,
|
||||
|
||||
<programlisting>
|
||||
if builtins ? getEnv then builtins.getEnv "PATH" else ""</programlisting>
|
||||
|
||||
This allows a Nix expression to fall back gracefully on older Nix
|
||||
installations that don’t have the desired built-in
|
||||
function.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.compareVersions</function>
|
||||
<replaceable>s1</replaceable> <replaceable>s2</replaceable></term>
|
||||
|
||||
<listitem><para>Compare two strings representing versions and
|
||||
return <literal>-1</literal> if version
|
||||
<replaceable>s1</replaceable> is older than version
|
||||
<replaceable>s2</replaceable>, <literal>0</literal> if they are
|
||||
the same, and <literal>1</literal> if
|
||||
<replaceable>s1</replaceable> is newer than
|
||||
<replaceable>s2</replaceable>. The version comparison algorithm
|
||||
is the same as the one used by <link
|
||||
linkend="ssec-version-comparisons"><command>nix-env
|
||||
-u</command></link>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.concatLists</function>
|
||||
<replaceable>lists</replaceable></term>
|
||||
|
||||
<listitem><para>Concatenate a list of lists into a single
|
||||
list.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry
|
||||
xml:id='builtin-currentSystem'><term><varname>builtins.currentSystem</varname></term>
|
||||
|
||||
<listitem><para>The built-in value <varname>currentSystem</varname>
|
||||
evaluates to the Nix platform identifier for the Nix installation
|
||||
on which the expression is being evaluated, such as
|
||||
<literal>"i686-linux"</literal> or
|
||||
<literal>"powerpc-darwin"</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<!--
|
||||
<varlistentry><term><function>currentTime</function></term>
|
||||
|
||||
<listitem><para>The built-in value <varname>currentTime</varname>
|
||||
returns the current system time in seconds since 00:00:00 1/1/1970
|
||||
UTC. Due to the evaluation model of Nix expressions
|
||||
(<emphasis>maximal laziness</emphasis>), it always yields the same
|
||||
value within an execution of Nix.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
-->
|
||||
|
||||
|
||||
<!--
|
||||
<varlistentry><term><function>dependencyClosure</function></term>
|
||||
|
||||
<listitem><para>TODO</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
-->
|
||||
|
||||
|
||||
<varlistentry><term><function>derivation</function>
|
||||
<replaceable>attrs</replaceable></term>
|
||||
|
||||
<listitem><para><function>derivation</function> is described in
|
||||
<xref linkend='ssec-derivation' />.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>dirOf</function> <replaceable>s</replaceable></term>
|
||||
|
||||
<listitem><para>Return the directory part of the string
|
||||
<replaceable>s</replaceable>, that is, everything before the final
|
||||
slash in the string. This is similar to the GNU
|
||||
<command>dirname</command> command.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.div</function>
|
||||
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
|
||||
|
||||
<listitem><para>Return the quotient of the integers
|
||||
<replaceable>e1</replaceable> and
|
||||
<replaceable>e2</replaceable>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.elem</function>
|
||||
<replaceable>x</replaceable> <replaceable>xs</replaceable></term>
|
||||
|
||||
<listitem><para>Return <literal>true</literal> if a value equal to
|
||||
<replaceable>x</replaceable> occurs in the list
|
||||
<replaceable>xs</replaceable>, and <literal>false</literal>
|
||||
otherwise.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.elemAt</function>
|
||||
<replaceable>xs</replaceable> <replaceable>n</replaceable></term>
|
||||
|
||||
<listitem><para>Return element <replaceable>n</replaceable> from
|
||||
the list <replaceable>xs</replaceable>. Elements are counted
|
||||
starting from 0. A fatal error occurs in the index is out of
|
||||
bounds.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.filter</function>
|
||||
<replaceable>f</replaceable> <replaceable>xs</replaceable></term>
|
||||
|
||||
<listitem><para>Return a list consisting of the elements of
|
||||
<replaceable>xs</replaceable> for which the function
|
||||
<replaceable>f</replaceable> returns
|
||||
<literal>true</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.filterSource</function>
|
||||
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
|
||||
|
||||
<listitem>
|
||||
|
||||
<para>This function allows you to copy sources into the Nix
|
||||
store while filtering certain files. For instance, suppose that
|
||||
you want to use the directory <filename>source-dir</filename> as
|
||||
an input to a Nix expression, e.g.
|
||||
|
||||
<programlisting>
|
||||
stdenv.mkDerivation {
|
||||
...
|
||||
src = ./source-dir;
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
However, if <filename>source-dir</filename> is a Subversion
|
||||
working copy, then all those annoying <filename>.svn</filename>
|
||||
subdirectories will also be copied to the store. Worse, the
|
||||
contents of those directories may change a lot, causing lots of
|
||||
spurious rebuilds. With <function>filterSource</function> you
|
||||
can filter out the <filename>.svn</filename> directories:
|
||||
|
||||
<programlisting>
|
||||
src = builtins.filterSource
|
||||
(path: type: type != "directory" || baseNameOf path != ".svn")
|
||||
./source-dir;
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Thus, the first argument <replaceable>e1</replaceable>
|
||||
must be a predicate function that is called for each regular
|
||||
file, directory or symlink in the source tree
|
||||
<replaceable>e2</replaceable>. If the function returns
|
||||
<literal>true</literal>, the file is copied to the Nix store,
|
||||
otherwise it is omitted. The function is called with two
|
||||
arguments. The first is the full path of the file. The second
|
||||
is a string that identifies the type of the file, which is
|
||||
either <literal>"regular"</literal>,
|
||||
<literal>"directory"</literal>, <literal>"symlink"</literal> or
|
||||
<literal>"unknown"</literal> (for other kinds of files such as
|
||||
device nodes or fifos — but note that those cannot be copied to
|
||||
the Nix store, so if the predicate returns
|
||||
<literal>true</literal> for them, the copy will fail).</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.getAttr</function>
|
||||
<replaceable>s</replaceable> <replaceable>attrs</replaceable></term>
|
||||
|
||||
<listitem><para><function>getAttr</function> returns the attribute
|
||||
named <replaceable>s</replaceable> from the attribute set
|
||||
<replaceable>attrs</replaceable>. Evaluation aborts if the
|
||||
attribute doesn’t exist. This is a dynamic version of the
|
||||
<literal>.</literal> operator, since <replaceable>s</replaceable>
|
||||
is an expression rather than an identifier.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.getEnv</function>
|
||||
<replaceable>s</replaceable></term>
|
||||
|
||||
<listitem><para><function>getEnv</function> returns the value of
|
||||
the environment variable <replaceable>s</replaceable>, or an empty
|
||||
string if the variable doesn’t exist. This function should be
|
||||
used with care, as it can introduce all sorts of nasty environment
|
||||
dependencies in your Nix expression.</para>
|
||||
|
||||
<para><function>getEnv</function> is used in Nix Packages to
|
||||
locate the file <filename>~/.nixpkgs/config.nix</filename>, which
|
||||
contains user-local settings for Nix Packages. (That is, it does
|
||||
a <literal>getEnv "HOME"</literal> to locate the user’s home
|
||||
directory.)</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.hasAttr</function>
|
||||
<replaceable>s</replaceable> <replaceable>attrs</replaceable></term>
|
||||
|
||||
<listitem><para><function>hasAttr</function> returns
|
||||
<literal>true</literal> if the attribute set
|
||||
<replaceable>attrs</replaceable> has an attribute named
|
||||
<replaceable>s</replaceable>, and <literal>false</literal>
|
||||
otherwise. This is a dynamic version of the <literal>?</literal>
|
||||
operator, since <replaceable>s</replaceable> is an expression
|
||||
rather than an identifier.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.head</function>
|
||||
<replaceable>list</replaceable></term>
|
||||
|
||||
<listitem><para>Return the first element of a list; abort
|
||||
evaluation if the argument isn’t a list or is an empty list. You
|
||||
can test whether a list is empty by comparing it with
|
||||
<literal>[]</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>import</function>
|
||||
<replaceable>path</replaceable></term>
|
||||
|
||||
<listitem><para>Load, parse and return the Nix expression in the
|
||||
file <replaceable>path</replaceable>. If <replaceable>path
|
||||
</replaceable> is a directory, the file <filename>default.nix
|
||||
</filename> in that directory is loaded. Evaluation aborts if
|
||||
the file doesn’t exist or contains an incorrect Nix
|
||||
expression. <function>import</function> implements Nix’s module
|
||||
system: you can put any Nix expression (such as an attribute set
|
||||
or a function) in a separate file, and use it from Nix expressions
|
||||
in other files.</para>
|
||||
|
||||
<para>A Nix expression loaded by <function>import</function> must
|
||||
not contain any <emphasis>free variables</emphasis> (identifiers
|
||||
that are not defined in the Nix expression itself and are not
|
||||
built-in). Therefore, it cannot refer to variables that are in
|
||||
scope at the call site. For instance, if you have a calling
|
||||
expression
|
||||
|
||||
<programlisting>
|
||||
rec {
|
||||
x = 123;
|
||||
y = import ./foo.nix;
|
||||
}</programlisting>
|
||||
|
||||
then the following <filename>foo.nix</filename> will give an
|
||||
error:
|
||||
|
||||
<programlisting>
|
||||
x + 456</programlisting>
|
||||
|
||||
since <varname>x</varname> is not in scope in
|
||||
<filename>foo.nix</filename>. If you want <varname>x</varname>
|
||||
to be available in <filename>foo.nix</filename>, you should pass
|
||||
it as a function argument:
|
||||
|
||||
<programlisting>
|
||||
rec {
|
||||
x = 123;
|
||||
y = import ./foo.nix x;
|
||||
}</programlisting>
|
||||
|
||||
and
|
||||
|
||||
<programlisting>
|
||||
x: x + 456</programlisting>
|
||||
|
||||
(The function argument doesn’t have to be called
|
||||
<varname>x</varname> in <filename>foo.nix</filename>; any name
|
||||
would work.)</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.intersectAttrs</function>
|
||||
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
|
||||
|
||||
<listitem><para>Return an attribute set consisting of the
|
||||
attributes in the set <replaceable>e2</replaceable> that also
|
||||
exist in the set <replaceable>e1</replaceable>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.isAttrs</function>
|
||||
<replaceable>e</replaceable></term>
|
||||
|
||||
<listitem><para>Return <literal>true</literal> if
|
||||
<replaceable>e</replaceable> evaluates to an attribute set, and
|
||||
<literal>false</literal> otherwise.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.isList</function>
|
||||
<replaceable>e</replaceable></term>
|
||||
|
||||
<listitem><para>Return <literal>true</literal> if
|
||||
<replaceable>e</replaceable> evaluates to a list, and
|
||||
<literal>false</literal> otherwise.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.isFunction</function>
|
||||
<replaceable>e</replaceable></term>
|
||||
|
||||
<listitem><para>Return <literal>true</literal> if
|
||||
<replaceable>e</replaceable> evaluates to a function, and
|
||||
<literal>false</literal> otherwise.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.isString</function>
|
||||
<replaceable>e</replaceable></term>
|
||||
|
||||
<listitem><para>Return <literal>true</literal> if
|
||||
<replaceable>e</replaceable> evaluates to a string, and
|
||||
<literal>false</literal> otherwise.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.isInt</function>
|
||||
<replaceable>e</replaceable></term>
|
||||
|
||||
<listitem><para>Return <literal>true</literal> if
|
||||
<replaceable>e</replaceable> evaluates to a int, and
|
||||
<literal>false</literal> otherwise.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.isBool</function>
|
||||
<replaceable>e</replaceable></term>
|
||||
|
||||
<listitem><para>Return <literal>true</literal> if
|
||||
<replaceable>e</replaceable> evaluates to a bool, and
|
||||
<literal>false</literal> otherwise.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>isNull</function>
|
||||
<replaceable>e</replaceable></term>
|
||||
|
||||
<listitem><para>Return <literal>true</literal> if
|
||||
<replaceable>e</replaceable> evaluates to <literal>null</literal>,
|
||||
and <literal>false</literal> otherwise.</para>
|
||||
|
||||
<warning><para>This function is <emphasis>deprecated</emphasis>;
|
||||
just write <literal>e == null</literal> instead.</para></warning>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.length</function>
|
||||
<replaceable>e</replaceable></term>
|
||||
|
||||
<listitem><para>Return the length of the list
|
||||
<replaceable>e</replaceable>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.lessThan</function>
|
||||
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
|
||||
|
||||
<listitem><para>Return <literal>true</literal> if the integer
|
||||
<replaceable>e1</replaceable> is less than the integer
|
||||
<replaceable>e2</replaceable>, and <literal>false</literal>
|
||||
otherwise. Evaluation aborts if either
|
||||
<replaceable>e1</replaceable> or <replaceable>e2</replaceable>
|
||||
does not evaluate to an integer.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.listToAttrs</function>
|
||||
<replaceable>e</replaceable></term>
|
||||
|
||||
<listitem><para>Construct an attribute set from a list specifying
|
||||
the names and values of each attribute. Each element of the list
|
||||
should be an attribute set consisting of a string-valued attribute
|
||||
<varname>name</varname> specifying the name of the attribute, and
|
||||
an attribute <varname>value</varname> specifying its value.
|
||||
Example:
|
||||
|
||||
<programlisting>
|
||||
builtins.listToAttrs
|
||||
[ { name = "foo"; value = 123; }
|
||||
{ name = "bar"; value = 456; }
|
||||
]
|
||||
</programlisting>
|
||||
|
||||
evaluates to
|
||||
|
||||
<programlisting>
|
||||
{ foo = 123; bar = 456; }
|
||||
</programlisting>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><function>map</function>
|
||||
<replaceable>f</replaceable> <replaceable>list</replaceable></term>
|
||||
|
||||
<listitem><para>Apply the function <replaceable>f</replaceable> to
|
||||
each element in the list <replaceable>list</replaceable>. For
|
||||
example,
|
||||
|
||||
<programlisting>
|
||||
map (x: "foo" + x) [ "bar" "bla" "abc" ]</programlisting>
|
||||
|
||||
evaluates to <literal>[ "foobar" "foobla" "fooabc"
|
||||
]</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.mul</function>
|
||||
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
|
||||
|
||||
<listitem><para>Return the product of the integers
|
||||
<replaceable>e1</replaceable> and
|
||||
<replaceable>e2</replaceable>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.parseDrvName</function>
|
||||
<replaceable>s</replaceable></term>
|
||||
|
||||
<listitem><para>Split the string <replaceable>s</replaceable> into
|
||||
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,
|
||||
<literal>builtins.parseDrvName "nix-0.12pre12876"</literal>
|
||||
returns <literal>{ name = "nix"; version = "0.12pre12876";
|
||||
}</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.pathExists</function>
|
||||
<replaceable>path</replaceable></term>
|
||||
|
||||
<listitem><para>Return <literal>true</literal> if the path
|
||||
<replaceable>path</replaceable> exists, and
|
||||
<literal>false</literal> otherwise. One application of this
|
||||
function is to conditionally include a Nix expression containing
|
||||
user configuration:
|
||||
|
||||
<programlisting>
|
||||
let
|
||||
fileName = builtins.getEnv "CONFIG_FILE";
|
||||
config =
|
||||
if fileName != "" && builtins.pathExists (builtins.toPath fileName)
|
||||
then import (builtins.toPath fileName)
|
||||
else { someSetting = false; }; <lineannotation># default configuration</lineannotation>
|
||||
in config.someSetting</programlisting>
|
||||
|
||||
(Note that <envar>CONFIG_FILE</envar> must be an absolute path for
|
||||
this to work.)</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<!--
|
||||
<varlistentry><term><function>relativise</function></term>
|
||||
|
||||
<listitem><para>TODO</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
-->
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.readFile</function>
|
||||
<replaceable>path</replaceable></term>
|
||||
|
||||
<listitem><para>Return the contents of the file
|
||||
<replaceable>path</replaceable> as a string.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>removeAttrs</function>
|
||||
<replaceable>attrs</replaceable> <replaceable>list</replaceable></term>
|
||||
|
||||
<listitem><para>Remove the attributes listed in
|
||||
<replaceable>list</replaceable> from the attribute set
|
||||
<replaceable>attrs</replaceable>. The attributes don’t have to
|
||||
exist in <replaceable>attrs</replaceable>. For instance,
|
||||
|
||||
<screen>
|
||||
removeAttrs { x = 1; y = 2; z = 3; } [ "a" "x" "z" ]</screen>
|
||||
|
||||
evaluates to <literal>{ y = 2; }</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.stringLength</function>
|
||||
<replaceable>e</replaceable></term>
|
||||
|
||||
<listitem><para>Return the length of the string
|
||||
<replaceable>e</replaceable>. If <replaceable>e</replaceable> is
|
||||
not a string, evaluation is aborted.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.sub</function>
|
||||
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
|
||||
|
||||
<listitem><para>Return the difference between the integers
|
||||
<replaceable>e1</replaceable> and
|
||||
<replaceable>e2</replaceable>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.substring</function>
|
||||
<replaceable>start</replaceable> <replaceable>len</replaceable>
|
||||
<replaceable>s</replaceable></term>
|
||||
|
||||
<listitem><para>Return the substring of
|
||||
<replaceable>s</replaceable> from character position
|
||||
<replaceable>start</replaceable> (zero-based) up to but not
|
||||
including <replaceable>start + len</replaceable>. If
|
||||
<replaceable>start</replaceable> is greater than the length of the
|
||||
string, an empty string is returned, and if <replaceable>start +
|
||||
len</replaceable> lies beyond the end of the string, only the
|
||||
substring up to the end of the string is returned.
|
||||
<replaceable>start</replaceable> must be
|
||||
non-negative.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.tail</function>
|
||||
<replaceable>list</replaceable></term>
|
||||
|
||||
<listitem><para>Return the second to last elements of a list;
|
||||
abort evaluation if the argument isn’t a list or is an empty
|
||||
list.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>throw</function>
|
||||
<replaceable>s</replaceable></term>
|
||||
|
||||
<listitem><para>Throw an error message
|
||||
<replaceable>s</replaceable>. This usually aborts Nix expression
|
||||
evaluation, but in <command>nix-env -qa</command> and other
|
||||
commands that try to evaluate a set of derivations to get
|
||||
information about those derivations, a derivation that throws an
|
||||
error is silently skipped (which is not the case for
|
||||
<function>abort</function>).</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry
|
||||
xml:id='builtin-toFile'><term><function>builtins.toFile</function>
|
||||
<replaceable>name</replaceable> <replaceable>s</replaceable></term>
|
||||
|
||||
<listitem><para>Store the string <replaceable>s</replaceable> in a
|
||||
file in the Nix store and return its path. The file has suffix
|
||||
<replaceable>name</replaceable>. This file can be used as an
|
||||
input to derivations. One application is to write builders
|
||||
“inline”. For instance, the following Nix expression combines
|
||||
<xref linkend='ex-hello-nix' /> and <xref
|
||||
linkend='ex-hello-builder' /> into one file:
|
||||
|
||||
<programlisting>
|
||||
{ stdenv, fetchurl, perl }:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "hello-2.1.1";
|
||||
|
||||
builder = builtins.toFile "builder.sh" "
|
||||
source $stdenv/setup
|
||||
|
||||
PATH=$perl/bin:$PATH
|
||||
|
||||
tar xvfz $src
|
||||
cd hello-*
|
||||
./configure --prefix=$out
|
||||
make
|
||||
make install
|
||||
";
|
||||
|
||||
src = fetchurl {
|
||||
url = http://nix.cs.uu.nl/dist/tarballs/hello-2.1.1.tar.gz;
|
||||
md5 = "70c9ccf9fac07f762c24f2df2290784d";
|
||||
};
|
||||
inherit perl;
|
||||
}</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>It is even possible for one file to refer to another, e.g.,
|
||||
|
||||
<programlisting>
|
||||
builder = let
|
||||
configFile = builtins.toFile "foo.conf" "
|
||||
# This is some dummy configuration file.
|
||||
<replaceable>...</replaceable>
|
||||
";
|
||||
in builtins.toFile "builder.sh" "
|
||||
source $stdenv/setup
|
||||
<replaceable>...</replaceable>
|
||||
cp ${configFile} $out/etc/foo.conf
|
||||
";</programlisting>
|
||||
|
||||
Note that <literal>${configFile}</literal> is an antiquotation
|
||||
(see <xref linkend='ssec-values' />), so the result of the
|
||||
expression <literal>configFile</literal> (i.e., a path like
|
||||
<filename>/nix/store/m7p7jfny445k...-foo.conf</filename>) will be
|
||||
spliced into the resulting string.</para>
|
||||
|
||||
<para>It is however <emphasis>not</emphasis> allowed to have files
|
||||
mutually referring to each other, like so:
|
||||
|
||||
<programlisting>
|
||||
let
|
||||
foo = builtins.toFile "foo" "...${bar}...";
|
||||
bar = builtins.toFile "bar" "...${foo}...";
|
||||
in foo</programlisting>
|
||||
|
||||
This is not allowed because it would cause a cyclic dependency in
|
||||
the computation of the cryptographic hashes for
|
||||
<varname>foo</varname> and <varname>bar</varname>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.toPath</function> <replaceable>s</replaceable></term>
|
||||
|
||||
<listitem><para>Convert the string value
|
||||
<replaceable>s</replaceable> into a path value. The string
|
||||
<replaceable>s</replaceable> must represent an absolute path
|
||||
(i.e., must start with <literal>/</literal>). The path need not
|
||||
exist. The resulting path is canonicalised, e.g.,
|
||||
<literal>builtins.toPath "//foo/xyzzy/../bar/"</literal> returns
|
||||
<literal>/foo/bar</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>toString</function> <replaceable>e</replaceable></term>
|
||||
|
||||
<listitem><para>Convert the expression
|
||||
<replaceable>e</replaceable> to a string.
|
||||
<replaceable>e</replaceable> can be a string (in which case
|
||||
<function>toString</function> is a no-op) or a path (e.g.,
|
||||
<literal>toString /foo/bar</literal> yields
|
||||
<literal>"/foo/bar"</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id='builtin-toXML'><term><function>builtins.toXML</function> <replaceable>e</replaceable></term>
|
||||
|
||||
<listitem><para>Return a string containing an XML representation
|
||||
of <replaceable>e</replaceable>. The main application for
|
||||
<function>toXML</function> is to communicate information with the
|
||||
builder in a more structured format than plain environment
|
||||
variables.</para>
|
||||
|
||||
<!-- TODO: more formally describe the schema of the XML
|
||||
representation -->
|
||||
|
||||
<para><xref linkend='ex-toxml' /> shows an example where this is
|
||||
the case. The builder is supposed to generate the configuration
|
||||
file for a <link xlink:href='http://jetty.mortbay.org/'>Jetty
|
||||
servlet container</link>. A servlet container contains a number
|
||||
of servlets (<filename>*.war</filename> files) each exported under
|
||||
a specific URI prefix. So the servlet configuration is a list of
|
||||
attribute sets containing the <varname>path</varname> and
|
||||
<varname>war</varname> of the servlet (<xref
|
||||
linkend='ex-toxml-co-servlets' />). This kind of information is
|
||||
difficult to communicate with the normal method of passing
|
||||
information through an environment variable, which just
|
||||
concatenates everything together into a string (which might just
|
||||
work in this case, but wouldn’t work if fields are optional or
|
||||
contain lists themselves). Instead the Nix expression is
|
||||
converted to an XML representation with
|
||||
<function>toXML</function>, which is unambiguous and can easily be
|
||||
processed with the appropriate tools. For instance, in the
|
||||
example an XSLT stylesheet (<xref linkend='ex-toxml-co-stylesheet'
|
||||
/>) is applied to it (<xref linkend='ex-toxml-co-apply' />) to
|
||||
generate the XML configuration file for the Jetty server. The XML
|
||||
representation produced from <xref linkend='ex-toxml-co-servlets'
|
||||
/> by <function>toXML</function> is shown in <xref
|
||||
linkend='ex-toxml-result' />.</para>
|
||||
|
||||
<para>Note that <xref linkend='ex-toxml' /> uses the <function
|
||||
linkend='builtin-toFile'>toFile</function> built-in to write the
|
||||
builder and the stylesheet “inline” in the Nix expression. The
|
||||
path of the stylesheet is spliced into the builder at
|
||||
<literal>xsltproc ${stylesheet}
|
||||
<replaceable>...</replaceable></literal>.</para>
|
||||
|
||||
<example xml:id='ex-toxml'><title>Passing information to a builder
|
||||
using <function>toXML</function></title>
|
||||
|
||||
<programlisting><![CDATA[
|
||||
{ stdenv, fetchurl, libxslt, jira, uberwiki }:
|
||||
|
||||
stdenv.mkDerivation (rec {
|
||||
name = "web-server";
|
||||
|
||||
buildInputs = [ libxslt ];
|
||||
|
||||
builder = builtins.toFile "builder.sh" "
|
||||
source $stdenv/setup
|
||||
mkdir $out
|
||||
echo $servlets | xsltproc ${stylesheet} - > $out/server-conf.xml]]> <co xml:id='ex-toxml-co-apply' /> <![CDATA[
|
||||
";
|
||||
|
||||
stylesheet = builtins.toFile "stylesheet.xsl"]]> <co xml:id='ex-toxml-co-stylesheet' /> <![CDATA[
|
||||
"<?xml version='1.0' encoding='UTF-8'?>
|
||||
<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
|
||||
<xsl:template match='/'>
|
||||
<Configure>
|
||||
<xsl:for-each select='/expr/list/attrs'>
|
||||
<Call name='addWebApplication'>
|
||||
<Arg><xsl:value-of select=\"attr[@name = 'path']/string/@value\" /></Arg>
|
||||
<Arg><xsl:value-of select=\"attr[@name = 'war']/path/@value\" /></Arg>
|
||||
</Call>
|
||||
</xsl:for-each>
|
||||
</Configure>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
";
|
||||
|
||||
servlets = builtins.toXML []]> <co xml:id='ex-toxml-co-servlets' /> <![CDATA[
|
||||
{ path = "/bugtracker"; war = jira + "/lib/atlassian-jira.war"; }
|
||||
{ path = "/wiki"; war = uberwiki + "/uberwiki.war"; }
|
||||
];
|
||||
})]]></programlisting>
|
||||
|
||||
</example>
|
||||
|
||||
<example xml:id='ex-toxml-result'><title>XML representation produced by
|
||||
<function>toXML</function></title>
|
||||
|
||||
<programlisting><![CDATA[<?xml version='1.0' encoding='utf-8'?>
|
||||
<expr>
|
||||
<list>
|
||||
<attrs>
|
||||
<attr name="path">
|
||||
<string value="/bugtracker" />
|
||||
</attr>
|
||||
<attr name="war">
|
||||
<path value="/nix/store/d1jh9pasa7k2...-jira/lib/atlassian-jira.war" />
|
||||
</attr>
|
||||
</attrs>
|
||||
<attrs>
|
||||
<attr name="path">
|
||||
<string value="/wiki" />
|
||||
</attr>
|
||||
<attr name="war">
|
||||
<path value="/nix/store/y6423b1yi4sx...-uberwiki/uberwiki.war" />
|
||||
</attr>
|
||||
</attrs>
|
||||
</list>
|
||||
</expr>]]></programlisting>
|
||||
|
||||
</example>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><function>builtins.trace</function>
|
||||
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
|
||||
|
||||
<listitem><para>Evaluate <replaceable>e1</replaceable> and print its
|
||||
abstract syntax representation on standard error. Then return
|
||||
<replaceable>e2</replaceable>. This function is useful for
|
||||
debugging.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
</variablelist>
|
||||
|
||||
|
||||
</section>
|
||||
437
doc/manual/conf-file.xml
Normal file
437
doc/manual/conf-file.xml
Normal file
@@ -0,0 +1,437 @@
|
||||
<refentry xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xml:id="sec-conf-file">
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>nix.conf</refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
<refmiscinfo class="source">Nix</refmiscinfo>
|
||||
<refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>nix.conf</refname>
|
||||
<refpurpose>Nix configuration file</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
<para>A number of persistent settings of Nix are stored in the file
|
||||
<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. Here is an example
|
||||
configuration file:</para>
|
||||
|
||||
<programlisting>
|
||||
gc-keep-outputs = true # Nice for developers
|
||||
gc-keep-derivations = true # Idem
|
||||
env-keep-derivations = false
|
||||
</programlisting>
|
||||
|
||||
<para>You can override settings using the <option>--option</option>
|
||||
flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para>
|
||||
|
||||
<para>The following settings are currently available:
|
||||
|
||||
<variablelist>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-gc-keep-outputs"><term><literal>gc-keep-outputs</literal></term>
|
||||
|
||||
<listitem><para>If <literal>true</literal>, the garbage collector
|
||||
will keep the outputs of non-garbage derivations. If
|
||||
<literal>false</literal> (default), outputs will be deleted unless
|
||||
they are GC roots themselves (or reachable from other roots).</para>
|
||||
|
||||
<para>In general, outputs must be registered as roots separately.
|
||||
However, even if the output of a derivation is registered as a
|
||||
root, the collector will still delete store paths that are used
|
||||
only at build time (e.g., the C compiler, or source tarballs
|
||||
downloaded from the network). To prevent it from doing so, set
|
||||
this option to <literal>true</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-gc-keep-derivations"><term><literal>gc-keep-derivations</literal></term>
|
||||
|
||||
<listitem><para>If <literal>true</literal> (default), the garbage
|
||||
collector will keep the derivations from which non-garbage store
|
||||
paths were built. If <literal>false</literal>, they will be
|
||||
deleted unless explicitly registered as a root (or reachable from
|
||||
other roots).</para>
|
||||
|
||||
<para>Keeping derivation around is useful for querying and
|
||||
traceability (e.g., it allows you to ask with what dependencies or
|
||||
options a store path was built), so by default this option is on.
|
||||
Turn it off to safe a bit of disk space (or a lot if
|
||||
<literal>gc-keep-outputs</literal> is also turned on).</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>env-keep-derivations</literal></term>
|
||||
|
||||
<listitem><para>If <literal>false</literal> (default), derivations
|
||||
are not stored in Nix user environments. That is, the derivation
|
||||
any build-time-only dependencies may be garbage-collected.</para>
|
||||
|
||||
<para>If <literal>true</literal>, when you add a Nix derivation to
|
||||
a user environment, the path of the derivation is stored in the
|
||||
user environment. Thus, the derivation will not be
|
||||
garbage-collected until the user environment generation is deleted
|
||||
(<command>nix-env --delete-generations</command>). To prevent
|
||||
build-time-only dependencies from being collected, you should also
|
||||
turn on <literal>gc-keep-outputs</literal>.</para>
|
||||
|
||||
<para>The difference between this option and
|
||||
<literal>gc-keep-derivations</literal> is that this one is
|
||||
“sticky”: it applies to any user environment created while this
|
||||
option was enabled, while <literal>gc-keep-derivations</literal>
|
||||
only applies at the moment the garbage collector is
|
||||
run.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-build-max-jobs"><term><literal>build-max-jobs</literal></term>
|
||||
|
||||
<listitem><para>This option defines the maximum number of jobs
|
||||
that Nix will try to build in parallel. The default is
|
||||
<literal>1</literal>. You should generally set it to the number
|
||||
of CPUs in your system (e.g., <literal>2</literal> on a Athlon 64
|
||||
X2). It can be overriden using the <option
|
||||
linkend='opt-max-jobs'>--max-jobs</option> (<option>-j</option>)
|
||||
command line switch.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-build-cores"><term><literal>build-cores</literal></term>
|
||||
|
||||
<listitem><para>Sets the value of the
|
||||
<envar>NIX_BUILD_CORES</envar> environment variable in the
|
||||
invocation of builders. Builders can use this variable at their
|
||||
discretion to control the maximum amount of parallelism. For
|
||||
instance, in Nixpkgs, if the derivation attribute
|
||||
<varname>enableParallelBuilding</varname> is set to
|
||||
<literal>true</literal>, the builder passes the
|
||||
<option>-j<replaceable>N</replaceable></option> flag to GNU Make.
|
||||
It can be overriden using the <option
|
||||
linkend='opt-cores'>--cores</option> command line switch and
|
||||
defaults to <literal>1</literal>. The value <literal>0</literal>
|
||||
means that the builder should use all available CPU cores in the
|
||||
system.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-build-max-silent-time"><term><literal>build-max-silent-time</literal></term>
|
||||
|
||||
<listitem>
|
||||
|
||||
<para>This option defines the maximum number of seconds that a
|
||||
builder can go without producing any data on standard output or
|
||||
standard error. This is useful (for instance in a automated
|
||||
build system) to catch builds that are stuck in an infinite
|
||||
loop, or to catch remote builds that are hanging due to network
|
||||
problems. It can be overriden using the <option
|
||||
linkend="opt-max-silent-time">--max-silent-time</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-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>
|
||||
|
||||
<listitem><para>This options specifies the Unix group containing
|
||||
the Nix build user accounts. In multi-user Nix installations,
|
||||
builds should not be performed by the Nix account since that would
|
||||
allow users to arbitrarily modify the Nix store and database by
|
||||
supplying specially crafted builders; and they cannot be performed
|
||||
by the calling user since that would allow him/her to influence
|
||||
the build result.</para>
|
||||
|
||||
<para>Therefore, if this option is non-empty and specifies a valid
|
||||
group, builds will be performed under the user accounts that are a
|
||||
member of the group specified here (as listed in
|
||||
<filename>/etc/group</filename>). Those user accounts should not
|
||||
be used for any other purpose!</para>
|
||||
|
||||
<para>Nix will never run two builds under the same user account at
|
||||
the same time. This is to prevent an obvious security hole: a
|
||||
malicious user writing a Nix expression that modifies the build
|
||||
result of a legitimate Nix expression being built by another user.
|
||||
Therefore it is good to have as many Nix build user accounts as
|
||||
you can spare. (Remember: uids are cheap.)</para>
|
||||
|
||||
<para>The build users should have permission to create files in
|
||||
the Nix store, but not delete them. Therefore,
|
||||
<filename>/nix/store</filename> should be owned by the Nix
|
||||
account, its group should be the group specified here, and its
|
||||
mode should be <literal>1775</literal>.</para>
|
||||
|
||||
<para>If the build users group is empty, builds will be performed
|
||||
under the uid of the Nix process (that is, the uid of the caller
|
||||
if <envar>NIX_REMOTE</envar> is empty, the uid under which the Nix
|
||||
daemon runs if <envar>NIX_REMOTE</envar> is
|
||||
<literal>daemon</literal>). Obviously, this should not be used in
|
||||
multi-user settings with untrusted users.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>build-use-chroot</literal></term>
|
||||
|
||||
<listitem><para>If set to <literal>true</literal>, builds will be
|
||||
performed in a <emphasis>chroot environment</emphasis>, i.e., the
|
||||
build will be isolated from the normal file system hierarchy and
|
||||
will only see the Nix store, the temporary build directory, and
|
||||
the directories configured with the <link
|
||||
linkend='conf-build-chroot-dirs'><literal>build-chroot-dirs</literal>
|
||||
option</link> (such as <filename>/proc</filename> and
|
||||
<filename>/dev</filename>). This is useful to prevent undeclared
|
||||
dependencies on files in directories such as
|
||||
<filename>/usr/bin</filename>.</para>
|
||||
|
||||
<para>The use of a chroot requires that Nix is run as root (but
|
||||
you can still use the <link
|
||||
linkend='conf-build-users-group'>“build users” feature</link> to
|
||||
perform builds under different users than root). Currently,
|
||||
chroot builds only work on Linux because Nix uses “bind mounts” to
|
||||
make the Nix store and other directories available inside the
|
||||
chroot.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>build-use-substitutes</literal></term>
|
||||
|
||||
<listitem><para>If set to <literal>true</literal> (default), Nix
|
||||
will use binary substitutes if available. This option can be
|
||||
disabled to force building from source.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>build-fallback</literal></term>
|
||||
|
||||
<listitem><para>If set to <literal>true</literal>, Nix will fall
|
||||
back to building from source if a binary substitute fails. This
|
||||
is equivalent to the <option>--fallback</option> flag. The
|
||||
default is <literal>false</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-build-chroot-dirs"><term><literal>build-chroot-dirs</literal></term>
|
||||
|
||||
<listitem><para>When builds are performed in a chroot environment,
|
||||
Nix will mount (using <command>mount --bind</command> on Linux)
|
||||
some directories from the normal file system hierarchy inside the
|
||||
chroot. These are the Nix store, the temporary build directory
|
||||
(usually
|
||||
<filename>/tmp/nix-<replaceable>pid</replaceable>-<replaceable>number</replaceable></filename>)
|
||||
and the directories listed here. The default is <literal>dev
|
||||
/proc</literal>. Files in <filename>/dev</filename> (such as
|
||||
<filename>/dev/null</filename>) are needed by many builds, and
|
||||
some files in <filename>/proc</filename> may also be needed
|
||||
occasionally.</para>
|
||||
|
||||
<para>The value used on NixOS is
|
||||
|
||||
<programlisting>
|
||||
build-use-chroot = /dev /proc /bin</programlisting>
|
||||
|
||||
to make the <filename>/bin/sh</filename> symlink available (which
|
||||
is still needed by many builders).</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>build-cache-failures</literal></term>
|
||||
|
||||
<listitem><para>If set to <literal>true</literal>, Nix will
|
||||
“cache” build failures, meaning that it will remember (in its
|
||||
database) that a derivation previously failed. If you then try to
|
||||
build the derivation again, Nix will immediately fail rather than
|
||||
perform the build again. Failures in fixed-output derivations
|
||||
(such as <function>fetchurl</function> calls) are never cached.
|
||||
The “failed” status of a derivation can be cleared using
|
||||
<command>nix-store --clear-failed-paths</command>. By default,
|
||||
failure caching is disabled.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>build-keep-log</literal></term>
|
||||
|
||||
<listitem><para>If set to <literal>true</literal> (the default),
|
||||
Nix will write the build log of a derivation (i.e. the standard
|
||||
output and error of its builder) to the directory
|
||||
<filename>/nix/var/log/nix/drvs</filename>. The build log can be
|
||||
retrieved using the command <command>nix-store -l
|
||||
<replaceable>path</replaceable></command>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>build-compress-log</literal></term>
|
||||
|
||||
<listitem><para>If set to <literal>true</literal> (the default),
|
||||
build logs written to <filename>/nix/var/log/nix/drvs</filename>
|
||||
will be compressed on the fly using bzip2. Otherwise, they will
|
||||
not be compressed.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>use-binary-caches</literal></term>
|
||||
|
||||
<listitem><para>If set to <literal>true</literal> (the default),
|
||||
Nix will check the binary caches specified by
|
||||
<option>binary-caches</option> and related options to obtain
|
||||
binary substitutes.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>binary-caches</literal></term>
|
||||
|
||||
<listitem><para>A list of URLs of binary caches, separated by
|
||||
whitespace. The default is empty.<!-- The default is
|
||||
<literal>http://nixos.org/binary-cache</literal>. --></para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>binary-caches-files</literal></term>
|
||||
|
||||
<listitem><para>A list of names of files that will be read to
|
||||
obtain additional binary cache URLs. The default is
|
||||
<literal>/nix/var/nix/profiles/per-user/root/channels/binary-caches/*</literal>,
|
||||
which ensures that Nix will use the binary caches corresponding to
|
||||
the channels installed by root. Do not set this option to read
|
||||
files created by untrusted users!</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>trusted-binary-caches</literal></term>
|
||||
|
||||
<listitem><para>A list of URLs of binary caches, separated by
|
||||
whitespace. These are not used by default, but can be enabled by
|
||||
users of the Nix daemon by specifying <literal>--option
|
||||
binary-caches <replaceable>urls</replaceable></literal> on the
|
||||
command line. Daemon users are only allowed to pass a subset of
|
||||
the URLs listed in <literal>binary-caches</literal> and
|
||||
<literal>trusted-binary-caches</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>binary-caches-parallel-connections</literal></term>
|
||||
|
||||
<listitem><para>The maximum number of parallel HTTP connections
|
||||
used by the binary cache substituter to get NAR info files. This
|
||||
number should be high to minimise latency. It defaults to
|
||||
150.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>force-manifest</literal></term>
|
||||
|
||||
<listitem><para>If this option is set to <literal>false</literal>
|
||||
(default) and a Nix channel provides both a manifest and a binary
|
||||
cache, only the binary cache will be used. If set to
|
||||
<literal>true</literal>, the manifest will be fetched as well.
|
||||
This is useful if you want to use binary patches (which are
|
||||
currently not supported by binary caches).</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>system</literal></term>
|
||||
|
||||
<listitem><para>This option specifies the canonical Nix system
|
||||
name of the current installation, such as
|
||||
<literal>i686-linux</literal> or
|
||||
<literal>powerpc-darwin</literal>. Nix can only build derivations
|
||||
whose <literal>system</literal> attribute equals the value
|
||||
specified here. In general, it never makes sense to modify this
|
||||
value from its default, since you can use it to ‘lie’ about the
|
||||
platform you are building on (e.g., perform a Mac OS build on a
|
||||
Linux machine; the result would obviously be wrong). It only
|
||||
makes sense if the Nix binaries can run on multiple platforms,
|
||||
e.g., ‘universal binaries’ that run on <literal>powerpc-darwin</literal> and
|
||||
<literal>i686-darwin</literal>.</para>
|
||||
|
||||
<para>It defaults to the canonical Nix system name detected by
|
||||
<filename>configure</filename> at build time.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>fsync-metadata</literal></term>
|
||||
|
||||
<listitem><para>If set to <literal>true</literal>, changes to the
|
||||
Nix store metadata (in <filename>/nix/var/nix/db</filename>) are
|
||||
synchronously flushed to disk. This improves robustness in case
|
||||
of system crashes, but reduces performance. The default is
|
||||
<literal>true</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>auto-optimise-store</literal></term>
|
||||
|
||||
<listitem><para>If set to <literal>true</literal> (the default),
|
||||
Nix automatically detects files in the store that have identical
|
||||
contents, and replaces them with hard links to a single copy.
|
||||
This saves disk space. If set to <literal>false</literal>, you
|
||||
can still run <command>nix-store --optimise</command> to get rid
|
||||
of duplicate files.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
</refentry>
|
||||
329
doc/manual/env-common.xml
Normal file
329
doc/manual/env-common.xml
Normal file
@@ -0,0 +1,329 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="sec-common-env">
|
||||
|
||||
<title>Common environment variables</title>
|
||||
|
||||
|
||||
<para>Most Nix commands interpret the following environment variables:</para>
|
||||
|
||||
<variablelist xml:id="env-common">
|
||||
|
||||
|
||||
<varlistentry><term><envar>NIX_PATH</envar></term>
|
||||
|
||||
<listitem>
|
||||
|
||||
<para>A colon-separated list of directories used to look up Nix
|
||||
expressions enclosed in angle brackets (i.e.,
|
||||
<literal><<replaceable>path</replaceable>></literal>). For
|
||||
instance, the value
|
||||
|
||||
<screen>
|
||||
/home/eelco/Dev:/etc/nixos</screen>
|
||||
|
||||
will cause Nix to look for paths relative to
|
||||
<filename>/home/eelco/Dev</filename> and
|
||||
<filename>/etc/nixos</filename>, in that order. It is also
|
||||
possible to match paths against a prefix. For example, the value
|
||||
|
||||
<screen>
|
||||
nixpkgs=/home/eelco/Dev/nixpkgs-branch:/etc/nixos</screen>
|
||||
|
||||
will cause Nix to search for
|
||||
<literal><nixpkgs/<replaceable>path</replaceable>></literal> in
|
||||
<filename>/home/eelco/Dev/nixpkgs-branch/<replaceable>path</replaceable></filename>
|
||||
and
|
||||
<filename>/etc/nixos/nixpkgs/<replaceable>path</replaceable></filename>.
|
||||
</para>
|
||||
|
||||
<para>The search path can be extended using the
|
||||
<option>-I</option> option, which takes precedence over
|
||||
<envar>NIX_PATH</envar>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><envar>NIX_IGNORE_SYMLINK_STORE</envar></term>
|
||||
|
||||
<listitem>
|
||||
|
||||
<para>Normally, the Nix store directory (typically
|
||||
<filename>/nix/store</filename>) is not allowed to contain any
|
||||
symlink components. This is to prevent “impure” builds. Builders
|
||||
sometimes “canonicalise” paths by resolving all symlink components.
|
||||
Thus, builds on different machines (with
|
||||
<filename>/nix/store</filename> resolving to different locations)
|
||||
could yield different results. This is generally not a problem,
|
||||
except when builds are deployed to machines where
|
||||
<filename>/nix/store</filename> resolves differently. If you are
|
||||
sure that you’re not going to do that, you can set
|
||||
<envar>NIX_IGNORE_SYMLINK_STORE</envar> to <envar>1</envar>.</para>
|
||||
|
||||
<para>Note that if you’re symlinking the Nix store so that you can
|
||||
put it on another file system than the root file system, on Linux
|
||||
you’re better off using <literal>bind</literal> mount points, e.g.,
|
||||
|
||||
<screen>
|
||||
$ mkdir /nix
|
||||
$ mount -o bind /mnt/otherdisk/nix /nix</screen>
|
||||
|
||||
Consult the <citerefentry><refentrytitle>mount</refentrytitle>
|
||||
<manvolnum>8</manvolnum></citerefentry> manual page for details.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><envar>NIX_STORE_DIR</envar></term>
|
||||
|
||||
<listitem><para>Overrides the location of the Nix store (default
|
||||
<filename><replaceable>prefix</replaceable>/store</filename>).</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><envar>NIX_DATA_DIR</envar></term>
|
||||
|
||||
<listitem><para>Overrides the location of the Nix static data
|
||||
directory (default
|
||||
<filename><replaceable>prefix</replaceable>/share</filename>).</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><envar>NIX_LOG_DIR</envar></term>
|
||||
|
||||
<listitem><para>Overrides the location of the Nix log directory
|
||||
(default <filename><replaceable>prefix</replaceable>/log/nix</filename>).</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><envar>NIX_STATE_DIR</envar></term>
|
||||
|
||||
<listitem><para>Overrides the location of the Nix state directory
|
||||
(default <filename><replaceable>prefix</replaceable>/var/nix</filename>).</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><envar>NIX_DB_DIR</envar></term>
|
||||
|
||||
<listitem><para>Overrides the location of the Nix database (default
|
||||
<filename><replaceable>$NIX_STATE_DIR</replaceable>/db</filename>, i.e.,
|
||||
<filename><replaceable>prefix</replaceable>/var/nix/db</filename>).</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><envar>NIX_CONF_DIR</envar></term>
|
||||
|
||||
<listitem><para>Overrides the location of the Nix configuration
|
||||
directory (default
|
||||
<filename><replaceable>prefix</replaceable>/etc/nix</filename>).</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><envar>NIX_LOG_TYPE</envar></term>
|
||||
|
||||
<listitem><para>Equivalent to the <link
|
||||
linkend="opt-log-type"><option>--log-type</option>
|
||||
option</link>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><envar>TMPDIR</envar></term>
|
||||
|
||||
<listitem><para>Use the specified directory to store temporary
|
||||
files. In particular, this includes temporary build directories;
|
||||
these can take up substantial amounts of disk space. The default is
|
||||
<filename>/tmp</filename>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="envar-build-hook"><term><envar>NIX_BUILD_HOOK</envar></term>
|
||||
|
||||
<listitem>
|
||||
|
||||
<para>Specifies the location of the <emphasis>build hook</emphasis>,
|
||||
which is a program (typically some script) that Nix will call
|
||||
whenever it wants to build a derivation. This is used to implement
|
||||
distributed builds<phrase condition="manual"> (see <xref
|
||||
linkend="chap-distributed-builds" />)</phrase>.</para>
|
||||
|
||||
<!--
|
||||
The protocol by
|
||||
which the calling Nix process and the build hook communicate is as
|
||||
follows.
|
||||
|
||||
<para>The build hook is called with the following command-line
|
||||
arguments:
|
||||
|
||||
<orderedlist>
|
||||
|
||||
<listitem><para>A boolean value <literal>0</literal> or
|
||||
<literal>1</literal> specifying whether Nix can locally execute
|
||||
more builds, as per the <link
|
||||
linkend="opt-max-jobs"><option>- -max-jobs</option> option</link>.
|
||||
The purpose of this argument is to allow the hook to not have to
|
||||
maintain bookkeeping for the local machine.</para></listitem>
|
||||
|
||||
<listitem><para>The Nix platform identifier for the local machine
|
||||
(e.g., <literal>i686-linux</literal>).</para></listitem>
|
||||
|
||||
<listitem><para>The Nix platform identifier for the derivation,
|
||||
i.e., its <link linkend="attr-system"><varname>system</varname>
|
||||
attribute</link>.</para></listitem>
|
||||
|
||||
<listitem><para>The store path of the derivation.</para></listitem>
|
||||
|
||||
</orderedlist>
|
||||
|
||||
</para>
|
||||
|
||||
<para>On the basis of this information, and whatever persistent
|
||||
state the build hook keeps about other machines and their current
|
||||
load, it has to decide what to do with the build. It should print
|
||||
out on standard error one of the following responses (terminated by
|
||||
a newline, <literal>"\n"</literal>):
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><literal># decline</literal></term>
|
||||
|
||||
<listitem><para>The build hook is not willing or able to perform
|
||||
the build; the calling Nix process should do the build itself,
|
||||
if possible.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal># postpone</literal></term>
|
||||
|
||||
<listitem><para>The build hook cannot perform the build now, but
|
||||
can do so in the future (e.g., because all available build slots
|
||||
on remote machines are in use). The calling Nix process should
|
||||
postpone this build until at least one currently running build
|
||||
has terminated.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal># accept</literal></term>
|
||||
|
||||
<listitem><para>The build hook has accepted the
|
||||
build.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
|
||||
<para>After sending <literal># accept</literal>, the hook should
|
||||
read one line from standard input, which will be the string
|
||||
<literal>okay</literal>. It can then proceed with the build.
|
||||
Before sending <literal>okay</literal>, Nix will store in the hook’s
|
||||
current directory a number of text files that contain information
|
||||
about the derivation:
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><filename>inputs</filename></term>
|
||||
|
||||
<listitem><para>The set of store paths that are inputs to the
|
||||
build process (one per line). These have to be copied
|
||||
<emphasis>to</emphasis> the remote machine (in addition to the
|
||||
store derivation itself).</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><filename>outputs</filename></term>
|
||||
|
||||
<listitem><para>The set of store paths that are outputs of the
|
||||
derivation (one per line). These have to be copied
|
||||
<emphasis>from</emphasis> the remote machine if the build
|
||||
succeeds.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><filename>references</filename></term>
|
||||
|
||||
<listitem><para>The reference graph of the inputs, in the format
|
||||
accepted by the command <command>nix-store
|
||||
- -register-validity</command>. It is necessary to run this
|
||||
command on the remote machine after copying the inputs to inform
|
||||
Nix on the remote machine that the inputs are valid
|
||||
paths.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The hook should copy the inputs to the remote machine,
|
||||
register the validity of the inputs, perform the remote build, and
|
||||
copy the outputs back to the local machine. An exit code other than
|
||||
<literal>0</literal> indicates that the hook has failed. An exit
|
||||
code equal to 100 means that the remote build failed (as opposed to,
|
||||
e.g., a network error).</para>
|
||||
-->
|
||||
|
||||
</listitem>
|
||||
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="envar-remote"><term><envar>NIX_REMOTE</envar></term>
|
||||
|
||||
<listitem><para>This variable should be set to
|
||||
<literal>daemon</literal> if you want to use the Nix daemon to
|
||||
executed Nix operations, which is necessary in <link
|
||||
linkend="ssec-multi-user">multi-user Nix installations</link>.
|
||||
Otherwise, it should be left unset.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="envar-other-stores"><term><envar>NIX_OTHER_STORES</envar></term>
|
||||
|
||||
<listitem><para>This variable contains the paths of remote Nix
|
||||
installations from whichs paths can be copied, separated by colons.
|
||||
<phrase condition="manual">See <xref linkend="sec-sharing-packages"
|
||||
/> for details.</phrase> Each path should be the
|
||||
<filename>/nix</filename> directory of a remote Nix installation
|
||||
(i.e., not the <filename>/nix/store</filename> directory). The
|
||||
paths are subject to globbing, so you can set it so something like
|
||||
<literal>/var/run/nix/remote-stores/*/nix</literal> and mount
|
||||
multiple remote filesystems in
|
||||
<literal>/var/run/nix/remote-stores</literal>.</para>
|
||||
|
||||
<para>Note that if you’re building through the <link
|
||||
linkend="sec-nix-daemon">Nix daemon</link>, the only setting for
|
||||
this variable that matters is the one that the
|
||||
<command>nix-daemon</command> process uses. So if you want to
|
||||
change it, you have to restart the daemon.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><envar>GC_INITIAL_HEAP_SIZE</envar></term>
|
||||
|
||||
<listitem><para>If Nix has been configured to use the Boehm garbage
|
||||
collector, this variable sets the initial size of the heap in bytes.
|
||||
It defaults to 384 MiB. Setting it to a low value reduces memory
|
||||
consumption, but will increase runtime due to the overhead of
|
||||
garbage collection.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
</variablelist>
|
||||
|
||||
|
||||
</section>
|
||||
BIN
doc/manual/figures/user-environments.png
Normal file
BIN
doc/manual/figures/user-environments.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 83 KiB |
BIN
doc/manual/figures/user-environments.sxd
Normal file
BIN
doc/manual/figures/user-environments.sxd
Normal file
Binary file not shown.
179
doc/manual/glossary.xml
Normal file
179
doc/manual/glossary.xml
Normal file
@@ -0,0 +1,179 @@
|
||||
<appendix xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
|
||||
<title>Glossary</title>
|
||||
|
||||
|
||||
<glosslist>
|
||||
|
||||
|
||||
<glossentry xml:id="gloss-derivation"><glossterm>derivation</glossterm>
|
||||
|
||||
<glossdef><para>A description of a build action. The result of a
|
||||
derivation is a store object. Derivations are typically specified
|
||||
in Nix expressions using the <link
|
||||
linkend="ssec-derivation"><function>derivation</function>
|
||||
primitive</link>. These are translated into low-level
|
||||
<emphasis>store derivations</emphasis> (implicitly by
|
||||
<command>nix-env</command> and <command>nix-build</command>, or
|
||||
explicitly by <command>nix-instantiate</command>).</para></glossdef>
|
||||
|
||||
</glossentry>
|
||||
|
||||
|
||||
<glossentry><glossterm>store</glossterm>
|
||||
|
||||
<glossdef><para>The location in the file system where store objects
|
||||
live. Typically <filename>/nix/store</filename>.</para></glossdef>
|
||||
|
||||
</glossentry>
|
||||
|
||||
|
||||
<glossentry><glossterm>store path</glossterm>
|
||||
|
||||
<glossdef><para>The location in the file system of a store object,
|
||||
i.e., an immediate child of the Nix store
|
||||
directory.</para></glossdef>
|
||||
|
||||
</glossentry>
|
||||
|
||||
|
||||
<glossentry><glossterm>store object</glossterm>
|
||||
|
||||
<glossdef><para>A file that is an immediate child of the Nix store
|
||||
directory. These can be regular files, but also entire directory
|
||||
trees. Store objects can be sources (objects copied from outside of
|
||||
the store), derivation outputs (objects produced by running a build
|
||||
action), or derivations (files describing a build
|
||||
action).</para></glossdef>
|
||||
|
||||
</glossentry>
|
||||
|
||||
|
||||
<glossentry xml:id="gloss-substitute"><glossterm>substitute</glossterm>
|
||||
|
||||
<glossdef><para>A substitute is a command invocation stored in the
|
||||
Nix database that describes how to build a store object, bypassing
|
||||
normal the build mechanism (i.e., derivations). Typically, the
|
||||
substitute builds the store object by downloading a pre-built
|
||||
version of the store object from some server.</para></glossdef>
|
||||
|
||||
</glossentry>
|
||||
|
||||
|
||||
<glossentry><glossterm>purity</glossterm>
|
||||
|
||||
<glossdef><para>The assumption that equal Nix derivations when run
|
||||
always produce the same output. This cannot be guaranteed in
|
||||
general (e.g., a builder can rely on external inputs such as the
|
||||
network or the system time) but the Nix model assumes
|
||||
it.</para></glossdef>
|
||||
|
||||
</glossentry>
|
||||
|
||||
|
||||
<glossentry><glossterm>Nix expression</glossterm>
|
||||
|
||||
<glossdef><para>A high-level description of software packages and
|
||||
compositions thereof. Deploying software using Nix entails writing
|
||||
Nix expressions for your packages. Nix expressions are translated
|
||||
to derivations that are stored in the Nix store. These derivations
|
||||
can then be built.</para></glossdef>
|
||||
|
||||
</glossentry>
|
||||
|
||||
|
||||
<glossentry xml:id="gloss-reference"><glossterm>reference</glossterm>
|
||||
|
||||
<glossdef><para>A store path <varname>P</varname> is said to have a
|
||||
reference to a store path <varname>Q</varname> if the store object
|
||||
at <varname>P</varname> contains the path <varname>Q</varname>
|
||||
somewhere. This implies than an execution involving
|
||||
<varname>P</varname> potentially needs <varname>Q</varname> to be
|
||||
present. The <emphasis>references</emphasis> of a store path are
|
||||
the set of store paths to which it has a reference.</para></glossdef>
|
||||
|
||||
</glossentry>
|
||||
|
||||
|
||||
<glossentry xml:id="gloss-closure"><glossterm>closure</glossterm>
|
||||
|
||||
<glossdef><para>The closure of a store path is the set of store
|
||||
paths that are directly or indirectly “reachable” from that store
|
||||
path; that is, it’s the closure of the path under the <link
|
||||
linkend="gloss-reference">references</link> relation. For instance,
|
||||
if the store object at path <varname>P</varname> contains a
|
||||
reference to path <varname>Q</varname>, then <varname>Q</varname> is
|
||||
in the closure of <varname>P</varname>. For correct deployment it
|
||||
is necessary to deploy whole closures, since otherwise at runtime
|
||||
files could be missing. The command <command>nix-store
|
||||
-qR</command> prints out closures of store paths.</para></glossdef>
|
||||
|
||||
</glossentry>
|
||||
|
||||
|
||||
<glossentry xml:id="gloss-output-path"><glossterm>output path</glossterm>
|
||||
|
||||
<glossdef><para>A store path produced by a derivation.</para></glossdef>
|
||||
|
||||
</glossentry>
|
||||
|
||||
|
||||
<glossentry xml:id="gloss-deriver"><glossterm>deriver</glossterm>
|
||||
|
||||
<glossdef><para>The deriver of an <link
|
||||
linkend="gloss-output-path">output path</link> is the store
|
||||
derivation that built it.</para></glossdef>
|
||||
|
||||
</glossentry>
|
||||
|
||||
|
||||
<glossentry xml:id="gloss-validity"><glossterm>validity</glossterm>
|
||||
|
||||
<glossdef><para>A store path is considered
|
||||
<emphasis>valid</emphasis> if it exists in the file system, is
|
||||
listed in the Nix database as being valid, and if all paths in its
|
||||
closure are also valid.</para></glossdef>
|
||||
|
||||
</glossentry>
|
||||
|
||||
|
||||
<glossentry xml:id="gloss-user-env"><glossterm>user environment</glossterm>
|
||||
|
||||
<glossdef><para>An automatically generated store object that
|
||||
consists of a set of symlinks to “active” applications, i.e., other
|
||||
store paths. These are generated automatically by <link
|
||||
linkend="sec-nix-env"><command>nix-env</command></link>. See <xref
|
||||
linkend="sec-profiles" />.</para>
|
||||
|
||||
</glossdef>
|
||||
|
||||
</glossentry>
|
||||
|
||||
|
||||
<glossentry xml:id="gloss-profile"><glossterm>profile</glossterm>
|
||||
|
||||
<glossdef><para>A symlink to the current <link
|
||||
linkend="gloss-user-env">user environment</link> of a user, e.g.,
|
||||
<filename>/nix/var/nix/profiles/default</filename>.</para></glossdef>
|
||||
|
||||
</glossentry>
|
||||
|
||||
|
||||
<glossentry xml:id="gloss-nar"><glossterm>NAR</glossterm>
|
||||
|
||||
<glossdef><para>A <emphasis>N</emphasis>ix
|
||||
<emphasis>AR</emphasis>chive. This is a serialisation of a path in
|
||||
the Nix store. It can contain regular files, directories and
|
||||
symbolic links. NARs are generated and unpacked using
|
||||
<command>nix-store --dump</command> and <command>nix-store
|
||||
--restore</command>.</para></glossdef>
|
||||
|
||||
</glossentry>
|
||||
|
||||
|
||||
|
||||
</glosslist>
|
||||
|
||||
|
||||
</appendix>
|
||||
550
doc/manual/installation.xml
Normal file
550
doc/manual/installation.xml
Normal file
@@ -0,0 +1,550 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-installation">
|
||||
|
||||
<title>Installation</title>
|
||||
|
||||
|
||||
<section><title>Supported platforms</title>
|
||||
|
||||
<para>Nix is currently supported on the following platforms:
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>Linux (particularly on x86, x86_64, and
|
||||
PowerPC).</para></listitem>
|
||||
|
||||
<listitem><para>Mac OS X.</para></listitem>
|
||||
|
||||
<listitem><para>FreeBSD (only tested on Intel).</para></listitem>
|
||||
|
||||
<!--
|
||||
<listitem><para>Windows through <link
|
||||
xlink:href="http://www.cygwin.com/">Cygwin</link>.</para>
|
||||
|
||||
<warning><para>On Cygwin, Nix <emphasis>must</emphasis> be installed
|
||||
on an NTFS partition. It will not work correctly on a FAT
|
||||
partition.</para></warning>
|
||||
|
||||
</listitem>
|
||||
-->
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Nix is pretty portable, so it should work on most other Unix
|
||||
platforms as well.</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section><title>Installing a binary distribution</title>
|
||||
|
||||
<para>The easiest way to install Nix is to use a binary package.
|
||||
Binary packages of the latest stable release are available for Fedora,
|
||||
Debian, Ubuntu, Mac OS X and various other systems from the <link
|
||||
xlink:href="http://nixos.org/nix/download.html">Nix homepage</link>.
|
||||
You can also get builds of the latest development release from our
|
||||
<link
|
||||
xlink:href="http://hydra.nixos.org/view/nix/trunk/latest">continuous
|
||||
build system</link>.</para>
|
||||
|
||||
<para>For Fedora, RPM packages are available. These can be installed
|
||||
or upgraded using <command>rpm -U</command>. For example,
|
||||
|
||||
<screen>
|
||||
$ rpm -U nix-1.0-1.i386.rpm</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>For Debian and Ubuntu, you can download a Deb package and
|
||||
install it like this:
|
||||
|
||||
<screen>
|
||||
$ dpkg -i nix_1.0-1_amd64.deb</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>For other platforms, including Mac OS X (Darwin), FreeBSD and
|
||||
other Linux distributions, you can download a binary tarball. It
|
||||
contains Nix and all its dependencies. You should unpack it in the
|
||||
root directory, then run <command>nix-finish-install</command>:
|
||||
|
||||
<screen>
|
||||
$ cd /
|
||||
$ tar xfj nix-1.1-x86_64-darwin.tar.bz2
|
||||
$ nix-finish-install
|
||||
</screen>
|
||||
|
||||
After this you can delete
|
||||
<filename>/usr/bin/nix-finish-install</filename>.</para>
|
||||
|
||||
<para>If you plan to use Nix from a single non-root user account, it’s
|
||||
probably convenient to change the ownership of the entire Nix store
|
||||
and database to that user account. In that case, install as follows:
|
||||
|
||||
<screen>
|
||||
alice$ cd /
|
||||
alice$ sudo tar xfj nix-1.1-x86_64-darwin.tar.bz2
|
||||
alice$ sudo chown -R alice /nix
|
||||
alice$ nix-finish-install
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Nix can be uninstalled using <command>rpm -e nix</command> or
|
||||
<command>dpkg -r nix</command> on RPM- and Dpkg-based systems,
|
||||
respectively. After this you should manually remove the Nix store and
|
||||
other auxiliary data, if desired:
|
||||
|
||||
<screen>
|
||||
$ rm -rf /nix</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section><title>Installing Nix from source</title>
|
||||
|
||||
<para>If no binary package is available, you can download and compile
|
||||
a source distribution.</para>
|
||||
|
||||
<section><title>Prerequisites</title>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>GNU Make.</para></listitem>
|
||||
|
||||
<listitem><para>A fairly recent version of GCC/G++. Version 2.95
|
||||
and higher should work. Clang will also work.</para></listitem>
|
||||
|
||||
<listitem><para>Perl 5.8 or higher.</para></listitem>
|
||||
|
||||
<listitem><para><command>pkg-config</command> to locate
|
||||
dependencies. If your distribution does not provide it, you can get
|
||||
it from <link
|
||||
xlink:href="http://www.freedesktop.org/wiki/Software/pkg-config"
|
||||
/>.</para></listitem>
|
||||
|
||||
<listitem><para>The bzip2 compressor program and the
|
||||
<literal>libbz2</literal> library. Thus you must have bzip2
|
||||
installed, including development headers and libraries. If your
|
||||
distribution does not provide these, you can obtain bzip2 from <link
|
||||
xlink:href="http://www.bzip.org/"/>.</para></listitem>
|
||||
|
||||
<listitem><para>The SQLite embedded database library, version 3.6.19
|
||||
or higher. If your distribution does not provide it, please install
|
||||
it from <link xlink:href="http://www.sqlite.org/" />.</para></listitem>
|
||||
|
||||
<listitem><para>The Perl DBI and DBD::SQLite libraries, which are
|
||||
available from <link
|
||||
xlink:href="http://search.cpan.org/">CPAN</link> if your
|
||||
distribution does not provide them.</para></listitem>
|
||||
|
||||
<listitem><para>The <link
|
||||
xlink:href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/">Boehm
|
||||
garbage collector</link> to reduce the evaluator’s memory
|
||||
consumption (optional). To enable it, install
|
||||
<literal>pkgconfig</literal> and the Boehm garbage collector, and
|
||||
pass the flag <option>--enable-gc</option> to
|
||||
<command>configure</command>.</para></listitem>
|
||||
|
||||
<listitem><para>The <command>xmllint</command> and
|
||||
<command>xsltproc</command> programs to build this manual and the
|
||||
man-pages. These are part of the <literal>libxml2</literal> and
|
||||
<literal>libxslt</literal> packages, respectively. You also need
|
||||
the <link
|
||||
xlink:href="http://docbook.sourceforge.net/projects/xsl/">DocBook
|
||||
XSL stylesheets</link> and optionally the <link
|
||||
xlink:href="http://www.docbook.org/schemas/5x"> DocBook 5.0 RELAX NG
|
||||
schemas</link>. Note that these are only required if you modify the
|
||||
manual sources or when you are building from the Git
|
||||
repository.</para></listitem>
|
||||
|
||||
<listitem><para>Recent versions of Bison and Flex to build the
|
||||
parser. (This is because Nix needs GLR support in Bison and
|
||||
reentrancy support in Flex.) For Bison, you need version 2.3 or
|
||||
higher (1.875 does <emphasis>not</emphasis> work), which can be
|
||||
obtained from the <link
|
||||
xlink:href="ftp://alpha.gnu.org/pub/gnu/bison">GNU FTP
|
||||
server</link>. For Flex, you need version 2.5.33, which is
|
||||
available on <link
|
||||
xlink:href="http://lex.sourceforge.net/">SourceForge</link>.
|
||||
Slightly older versions may also work, but ancient versions like the
|
||||
ubiquitous 2.5.4a won't. Note that these are only required if you
|
||||
modify the parser or when you are building from the Git
|
||||
repository.</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section><title>Obtaining a source distribution</title>
|
||||
|
||||
<para>The source tarball of the most recent stable release can be
|
||||
downloaded from the <link
|
||||
xlink:href="http://nixos.org/nix/download.html">Nix homepage</link>.
|
||||
You can also grab the <link
|
||||
xlink:href="http://hydra.nixos.org/view/nix/trunk/latest/tarball/download-by-type/file/source-dist">most
|
||||
recent development release</link>.</para>
|
||||
|
||||
<para>Alternatively, the most recent sources of Nix can be obtained
|
||||
from its <link
|
||||
xlink:href="https://github.com/NixOS/nix">Git
|
||||
repository</link>. For example, the following command will check out
|
||||
the latest revision into a directory called
|
||||
<filename>nix</filename>:</para>
|
||||
|
||||
<screen>
|
||||
$ git clone https://github.com/NixOS/nix</screen>
|
||||
|
||||
<para>Likewise, specific releases can be obtained from the <link
|
||||
xlink:href="https://github.com/NixOS/nix/tags">tags</link> of the
|
||||
repository.</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section><title>Building Nix from source</title>
|
||||
|
||||
<para>After unpacking or checking out the Nix sources, issue the
|
||||
following commands:
|
||||
|
||||
<screen>
|
||||
$ ./configure <replaceable>options...</replaceable>
|
||||
$ make
|
||||
$ make install</screen>
|
||||
|
||||
Nix requires GNU Make so you may need to invoke
|
||||
<command>gmake</command> instead.</para>
|
||||
|
||||
<para>When building from the Git repository, these should be preceded
|
||||
by the command:
|
||||
|
||||
<screen>
|
||||
$ ./bootstrap.sh</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The installation path can be specified by passing the
|
||||
<option>--prefix=<replaceable>prefix</replaceable></option> to
|
||||
<command>configure</command>. The default installation directory is
|
||||
<filename>/usr/local</filename>. You can change this to any location
|
||||
you like. You must have write permission to the
|
||||
<replaceable>prefix</replaceable> path.</para>
|
||||
|
||||
<para>Nix keeps its <emphasis>store</emphasis> (the place where
|
||||
packages are stored) in <filename>/nix/store</filename> by default.
|
||||
This can be changed using
|
||||
<option>--with-store-dir=<replaceable>path</replaceable></option>.</para>
|
||||
|
||||
<warning><para>It is best <emphasis>not</emphasis> to change the Nix
|
||||
store from its default, since doing so makes it impossible to use
|
||||
pre-built binaries from the standard Nixpkgs channels — that is, all
|
||||
packages will need to be built from source.</para></warning>
|
||||
|
||||
<para>Nix keeps state (such as its database and log files) in
|
||||
<filename>/nix/var</filename> by default. This can be changed using
|
||||
<option>--localstatedir=<replaceable>path</replaceable></option>.</para>
|
||||
|
||||
<para>If you want to rebuild the documentation, pass the full path to
|
||||
the DocBook RELAX NG schemas and to the DocBook XSL stylesheets using
|
||||
the
|
||||
<option>--with-docbook-rng=<replaceable>path</replaceable></option>
|
||||
and
|
||||
<option>--with-docbook-xsl=<replaceable>path</replaceable></option>
|
||||
options.</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<!-- TODO: should be updated
|
||||
<section><title>Upgrading Nix through Nix</title>
|
||||
|
||||
<para>You can install the latest stable version of Nix through Nix
|
||||
itself by subscribing to the channel <link
|
||||
xlink:href="http://nixos.org/releases/nix/channels/nix-stable" />,
|
||||
or the latest unstable version by subscribing to the channel <link
|
||||
xlink:href="http://nixos.org/releases/nix/channels/nix-unstable" />.
|
||||
You can also do a <link linkend="sec-one-click">one-click
|
||||
installation</link> by clicking on the package links at <link
|
||||
xlink:href="http://nixos.org/releases/full-index-nix.html" />.</para>
|
||||
|
||||
</section>
|
||||
-->
|
||||
|
||||
|
||||
<section><title>Security</title>
|
||||
|
||||
<para>Nix has two basic security models. First, it can be used in
|
||||
“single-user mode”, which is similar to what most other package
|
||||
management tools do: there is a single user (typically <systemitem
|
||||
class="username">root</systemitem>) who performs all package
|
||||
management operations. All other users can then use the installed
|
||||
packages, but they cannot perform package management operations
|
||||
themselves.</para>
|
||||
|
||||
<para>Alternatively, you can configure Nix in “multi-user mode”. In
|
||||
this model, all users can perform package management operations — for
|
||||
instance, every user can install software without requiring root
|
||||
privileges. Nix ensures that this is secure. For instance, it’s not
|
||||
possible for one user to overwrite a package used by another user with
|
||||
a Trojan horse.</para>
|
||||
|
||||
|
||||
<section><title>Single-user mode</title>
|
||||
|
||||
<para>In single-user mode, all Nix operations that access the database
|
||||
in <filename><replaceable>prefix</replaceable>/var/nix/db</filename>
|
||||
or modify the Nix store in
|
||||
<filename><replaceable>prefix</replaceable>/store</filename> must be
|
||||
performed under the user ID that owns those directories. This is
|
||||
typically <systemitem class="username">root</systemitem>. (If you
|
||||
install from RPM packages, that’s in fact the default ownership.)
|
||||
However, on single-user machines, it is often convenient to
|
||||
<command>chown</command> those directories to your normal user account
|
||||
so that you don’t have to <command>su</command> to <systemitem
|
||||
class="username">root</systemitem> all the time.</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="ssec-multi-user"><title>Multi-user mode</title>
|
||||
|
||||
<para>To allow a Nix store to be shared safely among multiple users,
|
||||
it is important that users are not able to run builders that modify
|
||||
the Nix store or database in arbitrary ways, or that interfere with
|
||||
builds started by other users. If they could do so, they could
|
||||
install a Trojan horse in some package and compromise the accounts of
|
||||
other users.</para>
|
||||
|
||||
<para>To prevent this, the Nix store and database are owned by some
|
||||
privileged user (usually <literal>root</literal>) and builders are
|
||||
executed under special user accounts (usually named
|
||||
<literal>nixbld1</literal>, <literal>nixbld2</literal>, etc.). When a
|
||||
unprivileged user runs a Nix command, actions that operate on the Nix
|
||||
store (such as builds) are forwarded to a <emphasis>Nix
|
||||
daemon</emphasis> running under the owner of the Nix store/database
|
||||
that performs the operation.</para>
|
||||
|
||||
<note><para>Multi-user mode has one important limitation: only
|
||||
<systemitem class="username">root</systemitem> can run <command
|
||||
linkend="sec-nix-pull">nix-pull</command> to register the availability
|
||||
of pre-built binaries. However, those registrations are shared by all
|
||||
users, so they still get the benefit from <command>nix-pull</command>s
|
||||
done by <systemitem class="username">root</systemitem>.</para></note>
|
||||
|
||||
|
||||
<section><title>Setting up the build users</title>
|
||||
|
||||
<para>The <emphasis>build users</emphasis> are the special UIDs under
|
||||
which builds are performed. They should all be members of the
|
||||
<emphasis>build users group</emphasis> (usually called
|
||||
<literal>nixbld</literal>). This group should have no other members.
|
||||
The build users should not be members of any other group.</para>
|
||||
|
||||
<para>Here is a typical <filename>/etc/group</filename> definition of
|
||||
the build users group with 10 build users:
|
||||
|
||||
<programlisting>
|
||||
nixbld:!:30000:nixbld1,nixbld2,nixbld3,nixbld4,nixbld5,nixbld6,nixbld7,nixbld8,nixbld9,nixbld10
|
||||
</programlisting>
|
||||
|
||||
In this example the <literal>nixbld</literal> group has UID 30000, but
|
||||
of course it can be anything that doesn’t collide with an existing
|
||||
group.</para>
|
||||
|
||||
<para>Here is the corresponding part of
|
||||
<filename>/etc/passwd</filename>:
|
||||
|
||||
<programlisting>
|
||||
nixbld1:x:30001:65534:Nix build user 1:/var/empty:/noshell
|
||||
nixbld2:x:30002:65534:Nix build user 2:/var/empty:/noshell
|
||||
nixbld3:x:30003:65534:Nix build user 3:/var/empty:/noshell
|
||||
...
|
||||
nixbld10:x:30010:65534:Nix build user 10:/var/empty:/noshell
|
||||
</programlisting>
|
||||
|
||||
The home directory of the build users should not exist or should be an
|
||||
empty directory to which they do not have write access.</para>
|
||||
|
||||
<para>The build users should have write access to the Nix store, but
|
||||
they should not have the right to delete files. Thus the Nix store’s
|
||||
group should be the build users group, and it should have the sticky
|
||||
bit turned on (like <filename>/tmp</filename>):
|
||||
|
||||
<screen>
|
||||
$ chgrp nixbld /nix/store
|
||||
$ chmod 1775 /nix/store
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Finally, you should tell Nix to use the build users by
|
||||
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> (usually <literal>/etc/nix/nix.conf</literal>):
|
||||
|
||||
<programlisting>
|
||||
build-users-group = nixbld
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section><title>Nix store/database owned by root</title>
|
||||
|
||||
<para>The simplest setup is to let <literal>root</literal> own the Nix
|
||||
store and database. I.e.,
|
||||
|
||||
<screen>
|
||||
$ chown -R root /nix/store /nix/var/nix</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The <link linkend="sec-nix-daemon">Nix daemon</link> should be
|
||||
started as follows (as <literal>root</literal>):
|
||||
|
||||
<screen>
|
||||
$ nix-daemon</screen>
|
||||
|
||||
You’ll want to put that line somewhere in your system’s boot
|
||||
scripts.</para>
|
||||
|
||||
<para>To let unprivileged users use the daemon, they should set the
|
||||
<link linkend="envar-remote"><envar>NIX_REMOTE</envar> environment
|
||||
variable</link> to <literal>daemon</literal>. So you should put a
|
||||
line like
|
||||
|
||||
<programlisting>
|
||||
export NIX_REMOTE=daemon</programlisting>
|
||||
|
||||
into the users’ login scripts.</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section><title>Nix store/database not owned by root</title>
|
||||
|
||||
<para>It is also possible to let the Nix store and database be owned
|
||||
by a non-root user, which should be more secure<footnote><para>Note
|
||||
however that even when the Nix daemon runs as root, not
|
||||
<emphasis>that</emphasis> much code is executed as root: Nix
|
||||
expression evaluation is performed by the calling (unprivileged) user,
|
||||
and builds are performed under the special build user accounts. So
|
||||
only the code that accesses the database and starts builds is executed
|
||||
as <literal>root</literal>.</para></footnote>. Typically, this user
|
||||
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 nix /nix/store /nix/var/nix</screen>
|
||||
|
||||
and of course <command>nix-daemon</command> should be started under
|
||||
that user, e.g.,
|
||||
|
||||
<screen>
|
||||
$ su - nix -c "exec /nix/bin/nix-daemon"</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>There is a catch, though: non-<literal>root</literal> users
|
||||
cannot start builds under the build user accounts, since the
|
||||
<function>setuid</function> system call is obviously privileged. To
|
||||
allow a non-<literal>root</literal> Nix daemon to use the build user
|
||||
feature, it calls a setuid-root helper program,
|
||||
<command>nix-setuid-helper</command>. This program is installed in
|
||||
<filename><replaceable>prefix</replaceable>/libexec/nix-setuid-helper</filename>.
|
||||
To set the permissions properly (Nix’s <command>make install</command>
|
||||
doesn’t do this, since we don’t want to ship setuid-root programs
|
||||
out-of-the-box):
|
||||
|
||||
<screen>
|
||||
$ chown root.root /nix/libexec/nix-setuid-helper
|
||||
$ chmod 4755 /nix/libexec/nix-setuid-helper
|
||||
</screen>
|
||||
|
||||
(This example assumes that the Nix binaries are installed in
|
||||
<filename>/nix</filename>.)</para>
|
||||
|
||||
<para>Of course, the <command>nix-setuid-helper</command> command
|
||||
should not be usable by just anybody, since then anybody could run
|
||||
commands under the Nix build user accounts. For that reason there is
|
||||
a configuration file <filename>/etc/nix-setuid.conf</filename> that
|
||||
restricts the use of the helper. This file should be a text file
|
||||
containing precisely two lines, the first being the Nix daemon user
|
||||
and the second being the build users group, e.g.,
|
||||
|
||||
<programlisting>
|
||||
nix
|
||||
nixbld
|
||||
</programlisting>
|
||||
|
||||
The setuid-helper barfs if it is called by a user other than the one
|
||||
specified on the first line, or if it is asked to execute a build
|
||||
under a user who is not a member of the group specified on the second
|
||||
line. The file <filename>/etc/nix-setuid.conf</filename> must be
|
||||
owned by root, and must not be group- or world-writable. The
|
||||
setuid-helper barfs if this is not the case.</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section><title>Restricting access</title>
|
||||
|
||||
<para>To limit which users can perform Nix operations, you can use the
|
||||
permissions on the directory
|
||||
<filename>/nix/var/nix/daemon-socket</filename>. For instance, if you
|
||||
want to restrict the use of Nix to the members of a group called
|
||||
<literal>nix-users</literal>, do
|
||||
|
||||
<screen>
|
||||
$ chgrp nix-users /nix/var/nix/daemon-socket
|
||||
$ chmod ug=rwx,o= /nix/var/nix/daemon-socket
|
||||
</screen>
|
||||
|
||||
This way, users who are not in the <literal>nix-users</literal> group
|
||||
cannot connect to the Unix domain socket
|
||||
<filename>/nix/var/nix/daemon-socket/socket</filename>, so they cannot
|
||||
perform Nix operations.</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
</section> <!-- end of multi-user -->
|
||||
|
||||
|
||||
</section> <!-- end of security -->
|
||||
|
||||
|
||||
<section><title>Using Nix</title>
|
||||
|
||||
<para>To use Nix, some environment variables should be set. In
|
||||
particular, <envar>PATH</envar> should contain the directories
|
||||
<filename><replaceable>prefix</replaceable>/bin</filename> and
|
||||
<filename>~/.nix-profile/bin</filename>. The first directory contains
|
||||
the Nix tools themselves, while <filename>~/.nix-profile</filename> is
|
||||
a symbolic link to the current <emphasis>user environment</emphasis>
|
||||
(an automatically generated package consisting of symlinks to
|
||||
installed packages). The simplest way to set the required environment
|
||||
variables is to include the file
|
||||
<filename><replaceable>prefix</replaceable>/etc/profile.d/nix.sh</filename>
|
||||
in your <filename>~/.bashrc</filename> (or similar), like this:</para>
|
||||
|
||||
<screen>
|
||||
source <replaceable>prefix</replaceable>/etc/profile.d/nix.sh</screen>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
</chapter>
|
||||
337
doc/manual/introduction.xml
Normal file
337
doc/manual/introduction.xml
Normal file
@@ -0,0 +1,337 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-introduction">
|
||||
|
||||
<title>Introduction</title>
|
||||
|
||||
|
||||
<section><title>About Nix</title>
|
||||
|
||||
<para>Nix is a <emphasis>purely functional package manager</emphasis>.
|
||||
This means that it treats packages like values in purely functional
|
||||
programming languages such as Haskell — they are built by functions
|
||||
that don’t have side-effects, and they never change after they have
|
||||
been built. Nix stores packages in the <emphasis>Nix
|
||||
store</emphasis>, usually the directory
|
||||
<filename>/nix/store</filename>, where each package has its own unique
|
||||
subdirectory such as
|
||||
|
||||
<programlisting>
|
||||
/nix/store/nlc4z5y1hm8w9s8vm6m1f5hy962xjmp5-firefox-12.0
|
||||
</programlisting>
|
||||
|
||||
where <literal>nlc4z5…</literal> is a unique identifier for the
|
||||
package that captures all its dependencies (it’s a cryptographic hash
|
||||
of the package’s build dependency graph). This enables many powerful
|
||||
features.</para>
|
||||
|
||||
|
||||
<simplesect><title>Multiple versions</title>
|
||||
|
||||
<para>You can have multiple versions or variants of a package
|
||||
installed at the same time. This is especially important when
|
||||
different applications have dependencies on different versions of the
|
||||
same package — it prevents the “DLL hell”. Because of the hashing
|
||||
scheme, different versions of a package end up in different paths in
|
||||
the Nix store, so they don’t interfere with each other.</para>
|
||||
|
||||
<para>An important consequence is that operations like upgrading or
|
||||
uninstalling an application cannot break other applications, since
|
||||
these operations never “destructively” update or delete files that are
|
||||
used by other packages.</para>
|
||||
|
||||
</simplesect>
|
||||
|
||||
|
||||
<simplesect><title>Complete dependencies</title>
|
||||
|
||||
<para>Nix helps you make sure that package dependency specifications
|
||||
are complete. In general, when you’re making a package for a package
|
||||
management system like RPM, you have to specify for each package what
|
||||
its dependencies are, but there are no guarantees that this
|
||||
specification is complete. If you forget a dependency, then the
|
||||
package will build and work correctly on <emphasis>your</emphasis>
|
||||
machine if you have the dependency installed, but not on the end
|
||||
user's machine if it's not there.</para>
|
||||
|
||||
<para>Since Nix on the other hand doesn’t install packages in “global”
|
||||
locations like <filename>/usr/bin</filename> but in package-specific
|
||||
directories, the risk of incomplete dependencies is greatly reduced.
|
||||
This is because tools such as compilers don’t search in per-packages
|
||||
directories such as
|
||||
<filename>/nix/store/5lbfaxb722zp…-openssl-0.9.8d/include</filename>,
|
||||
so if a package builds correctly on your system, this is because you
|
||||
specified the dependency explicitly.</para>
|
||||
|
||||
<para>Runtime dependencies are found by scanning binaries for the hash
|
||||
parts of Nix store paths (such as <literal>r8vvq9kq…</literal>). This
|
||||
sounds risky, but it works extremely well.</para>
|
||||
|
||||
</simplesect>
|
||||
|
||||
|
||||
<simplesect><title>Multi-user support</title>
|
||||
|
||||
<para>Nix has multi-user support. This means that non-privileged
|
||||
users can securely install software. Each user can have a different
|
||||
<emphasis>profile</emphasis>, a set of packages in the Nix store that
|
||||
appear in the user’s <envar>PATH</envar>. If a user installs a
|
||||
package that another user has already installed previously, the
|
||||
package won’t be built or downloaded a second time. At the same time,
|
||||
it is not possible for one user to inject a Trojan horse into a
|
||||
package that might be used by another user.</para>
|
||||
|
||||
<!--
|
||||
<para>More details can be found in Section 3 of our <a
|
||||
href="docs/papers.html#securesharing">ASE 2005 paper</a>.</para>
|
||||
-->
|
||||
|
||||
</simplesect>
|
||||
|
||||
|
||||
<simplesect><title>Atomic upgrades and rollbacks</title>
|
||||
|
||||
<para>Since package management operations never overwrite packages in
|
||||
the Nix store but just add new versions in different paths, they are
|
||||
<emphasis>atomic</emphasis>. So during a package upgrade, there is no
|
||||
time window in which the package has some files from the old version
|
||||
and some files from the new version — which would be bad because a
|
||||
program might well crash if it’s started during that period.</para>
|
||||
|
||||
<para>And since package aren’t overwritten, the old versions are still
|
||||
there after an upgrade. This means that you can <emphasis>roll
|
||||
back</emphasis> to the old version:</para>
|
||||
|
||||
<screen>
|
||||
$ nix-env --upgrade <replaceable>some-packages</replaceable>
|
||||
$ nix-env --rollback
|
||||
</screen>
|
||||
|
||||
</simplesect>
|
||||
|
||||
|
||||
<simplesect><title>Garbage collection</title>
|
||||
|
||||
<para>When you uninstall a package like this…
|
||||
|
||||
<screen>
|
||||
$ nix-env --uninstall firefox
|
||||
</screen>
|
||||
|
||||
the package isn’t deleted from the system right away (after all, you
|
||||
might want to do a rollback, or it might be in the profiles of other
|
||||
users). Instead, unused packages can be deleted safely by running the
|
||||
<emphasis>garbage collector</emphasis>:
|
||||
|
||||
<screen>
|
||||
$ nix-collect-garbage
|
||||
</screen>
|
||||
|
||||
This deletes all packages that aren’t in use by any user profile or by
|
||||
a currently running program.</para>
|
||||
|
||||
</simplesect>
|
||||
|
||||
|
||||
<simplesect><title>Functional package language</title>
|
||||
|
||||
<para>Packages are built from <emphasis>Nix expressions</emphasis>,
|
||||
which is a simple functional language. A Nix expression describes
|
||||
everything that goes into a package build action (a “derivation”):
|
||||
other packages, sources, the build script, environment variables for
|
||||
the build script, etc. Nix tries very hard to ensure that Nix
|
||||
expressions are <emphasis>deterministic</emphasis>: building a Nix
|
||||
expression twice should yield the same result.</para>
|
||||
|
||||
<para>Because it’s a functional language, it’s easy to support
|
||||
building variants of a package: turn the Nix expression into a
|
||||
function and call it any number of times with the appropriate
|
||||
arguments. Due to the hashing scheme, variants don’t conflict with
|
||||
each other in the Nix store.</para>
|
||||
|
||||
</simplesect>
|
||||
|
||||
|
||||
<simplesect><title>Transparent source/binary deployment</title>
|
||||
|
||||
<para>Nix expressions generally describe how to build a package from
|
||||
source, so an installation action like
|
||||
|
||||
<screen>
|
||||
$ nix-env --install firefox
|
||||
</screen>
|
||||
|
||||
<emphasis>could</emphasis> cause quite a bit of build activity, as not
|
||||
only Firefox but also all its dependencies (all the way up to the C
|
||||
library and the compiler) would have to built, at least if they are
|
||||
not already in the Nix store. This is a <emphasis>source deployment
|
||||
model</emphasis>. For most users, building from source is not very
|
||||
pleasant as it takes far too long. However, Nix can automatically
|
||||
skip building from source and download a pre-built binary instead if
|
||||
it knows about it. <emphasis>Nix channels</emphasis> provide Nix
|
||||
expressions along with pre-built binaries.</para>
|
||||
|
||||
<!--
|
||||
<para>source deployment model (like <a
|
||||
href="http://www.gentoo.org/">Gentoo</a>) and a binary model (like
|
||||
RPM)</para>
|
||||
-->
|
||||
|
||||
</simplesect>
|
||||
|
||||
|
||||
<simplesect><title>Binary patching</title>
|
||||
|
||||
<para>In addition to downloading binaries automatically if they’re
|
||||
available, Nix can download binary deltas that patch an existing
|
||||
package in the Nix store into a new version. This speeds up
|
||||
upgrades.</para>
|
||||
|
||||
</simplesect>
|
||||
|
||||
|
||||
<simplesect><title>Nix Packages collection</title>
|
||||
|
||||
<para>We provide a large set of Nix expressions containing hundreds of
|
||||
existing Unix packages, the <emphasis>Nix Packages
|
||||
collection</emphasis> (Nixpkgs).</para>
|
||||
|
||||
</simplesect>
|
||||
|
||||
|
||||
<simplesect><title>Service deployment</title>
|
||||
|
||||
<para>Nix can be used not only for rolling out packages, but also
|
||||
complete <emphasis>configurations</emphasis> of services. This is
|
||||
done by treating all the static bits of a service (such as software
|
||||
packages, configuration files, control scripts, static web pages,
|
||||
etc.) as “packages” that can be built by Nix expressions. As a
|
||||
result, all the features above apply to services as well: for
|
||||
instance, you can roll back a web server configuration if a
|
||||
configuration change turns out to be undesirable, you can easily have
|
||||
multiple instances of a service (e.g., a test and production server),
|
||||
and because the whole service is built in a purely functional way from
|
||||
a Nix expression, it is repeatable so you can easily reproduce the
|
||||
service on another machine.</para>
|
||||
|
||||
<!--
|
||||
<para>You can read more about this in our <a
|
||||
href="docs/papers.html#servicecm">SCM-12 paper</a>.</para>
|
||||
-->
|
||||
|
||||
</simplesect>
|
||||
|
||||
|
||||
<simplesect><title>Portability</title>
|
||||
|
||||
<para>Nix should run on most Unix systems, including Linux, FreeBSD and
|
||||
Mac OS X.<!-- It is also supported on Windows using Cygwin.--></para>
|
||||
|
||||
</simplesect>
|
||||
|
||||
|
||||
<simplesect><title>NixOS</title>
|
||||
|
||||
<para>NixOS is a Linux distribution based on Nix. It uses Nix not
|
||||
just for package management but also to manage the system
|
||||
configuration (e.g., to build configuration files in
|
||||
<filename>/etc</filename>). This means, among other things, that it’s
|
||||
possible to easily roll back the entire configuration of the system to
|
||||
an earlier state. Also, users can install software without root
|
||||
privileges. For more information and downloads, see the <link
|
||||
xlink:href="http://nixos.org/">NixOS homepage</link>.</para>
|
||||
|
||||
</simplesect>
|
||||
|
||||
|
||||
<!-- other features:
|
||||
|
||||
- build farms
|
||||
- reproducibility (Nix expressions allows whole configuration to be rebuilt)
|
||||
|
||||
-->
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section><title>About us</title>
|
||||
|
||||
<para>Nix was originally developed at the <link
|
||||
xlink:href="http://www.cs.uu.nl/">Department of Information and
|
||||
Computing Sciences</link>, Utrecht University by the <link
|
||||
xlink:href="http://www.cs.uu.nl/wiki/Trace/WebHome">TraCE
|
||||
project</link> (2003-2008). The project was funded by the Software
|
||||
Engineering Research Program <link
|
||||
xlink:href="http://www.jacquard.nl/">Jacquard</link> to improve the
|
||||
support for variability in software systems. Further funding was
|
||||
provided by the NIRICT LaQuSo Build Farm project. Development is
|
||||
currently supported by <link
|
||||
xlink:href="http://www.logicblox.com/">LogicBlox</link>.</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section><title>About this manual</title>
|
||||
|
||||
<para>This manual tells you how to install and use Nix and how to
|
||||
write Nix expressions for software not already in the Nix Packages
|
||||
collection. It also discusses some advanced topics, such as setting
|
||||
up distributed multi-platform building.</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section><title>License</title>
|
||||
|
||||
<para>Nix is free software; you can redistribute it and/or modify it
|
||||
under the terms of the <link
|
||||
xlink:href="http://www.gnu.org/licenses/lgpl.html">GNU Lesser General
|
||||
Public License</link> as published by the <link
|
||||
xlink:href="http://www.fsf.org/">Free Software Foundation</link>;
|
||||
either version 2.1 of the License, or (at your option) any later
|
||||
version. Nix is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section><title>More information</title>
|
||||
|
||||
<para>Some background information on Nix can be found in a number of
|
||||
papers. The ICSE 2004 paper <citetitle
|
||||
xlink:href='http://www.st.ewi.tudelft.nl/~dolstra/pubs/immdsd-icse2004-final.pdf'>Imposing
|
||||
a Memory Management Discipline on Software Deployment</citetitle>
|
||||
discusses the hashing mechanism used to ensure reliable dependency
|
||||
identification and non-interference between different versions and
|
||||
variants of packages. The LISA 2004 paper <citetitle
|
||||
xlink:href='http://www.st.ewi.tudelft.nl/~dolstra/pubs/nspfssd-lisa2004-final.pdf'>Nix:
|
||||
A Safe and Policy-Free System for Software Deployment</citetitle>
|
||||
gives a more general discussion of Nix from a system-administration
|
||||
perspective. The CBSE 2005 paper <citetitle
|
||||
xlink:href='http://www.st.ewi.tudelft.nl/~dolstra/pubs/eupfcdm-cbse2005-final.pdf'>Efficient
|
||||
Upgrading in a Purely Functional Component Deployment Model
|
||||
</citetitle> is about transparent patch deployment in Nix. The SCM-12
|
||||
paper <citetitle
|
||||
xlink:href='http://www.st.ewi.tudelft.nl/~dolstra/pubs/servicecm-scm12-final.pdf'>
|
||||
Service Configuration Management</citetitle> shows how services (e.g.,
|
||||
web servers) can be deployed and managed through Nix. An overview of
|
||||
NixOS is given in the JFP article <citetitle
|
||||
xlink:href="http://www.st.ewi.tudelft.nl/~dolstra/pubs/nixos-jfp-final.pdf">NixOS:
|
||||
A Purely Functional Linux Distribution</citetitle>. The Nix homepage
|
||||
has <link xlink:href="http://nixos.org/docs/papers.html">an up-to-date
|
||||
list of Nix-related papers</link>.</para>
|
||||
|
||||
<para>Nix is the subject of Eelco Dolstra’s PhD thesis <citetitle
|
||||
xlink:href="http://igitur-archive.library.uu.nl/dissertations/2006-0118-200031/index.htm">The
|
||||
Purely Functional Software Deployment Model</citetitle>, which
|
||||
contains most of the papers listed above.</para>
|
||||
|
||||
<para>Nix has a homepage at <link
|
||||
xlink:href="http://nixos.org/"/>.</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
</chapter>
|
||||
82
doc/manual/manual.xml
Normal file
82
doc/manual/manual.xml
Normal file
@@ -0,0 +1,82 @@
|
||||
<book xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
|
||||
<info>
|
||||
|
||||
<title>Nix User's Guide</title>
|
||||
|
||||
<edition>Version <xi:include href="version.txt" parse="text" /></edition>
|
||||
|
||||
<author>
|
||||
<personname>
|
||||
<firstname>Eelco</firstname>
|
||||
<surname>Dolstra</surname>
|
||||
</personname>
|
||||
<affiliation>
|
||||
<orgname>LogicBlox</orgname>
|
||||
</affiliation>
|
||||
<contrib>Author</contrib>
|
||||
</author>
|
||||
|
||||
<copyright>
|
||||
<year>2004-2012</year>
|
||||
<holder>Eelco Dolstra</holder>
|
||||
</copyright>
|
||||
|
||||
<date>May 2012</date>
|
||||
|
||||
</info>
|
||||
|
||||
|
||||
<xi:include href="introduction.xml" />
|
||||
<xi:include href="quick-start.xml" />
|
||||
<xi:include href="installation.xml" />
|
||||
<xi:include href="package-management.xml" />
|
||||
<xi:include href="writing-nix-expressions.xml" />
|
||||
<xi:include href="build-farm.xml" />
|
||||
|
||||
|
||||
<appendix>
|
||||
<title>Command Reference</title>
|
||||
<xi:include href="opt-common.xml" />
|
||||
<xi:include href="env-common.xml" />
|
||||
|
||||
<section>
|
||||
<title>Main commands</title>
|
||||
<xi:include href="nix-env.xml" />
|
||||
<xi:include href="nix-instantiate.xml" />
|
||||
<xi:include href="nix-store.xml" />
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Utilities</title>
|
||||
<xi:include href="nix-build.xml" />
|
||||
<xi:include href="nix-channel.xml" />
|
||||
<xi:include href="nix-collect-garbage.xml" />
|
||||
<xi:include href="nix-copy-closure.xml" />
|
||||
<xi:include href="nix-hash.xml" />
|
||||
<xi:include href="nix-install-package.xml" />
|
||||
<xi:include href="nix-prefetch-url.xml" />
|
||||
<xi:include href="nix-pull.xml" />
|
||||
<xi:include href="nix-push.xml" />
|
||||
<xi:include href="nix-daemon.xml" />
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Files</title>
|
||||
<xi:include href="conf-file.xml" />
|
||||
</section>
|
||||
|
||||
</appendix>
|
||||
|
||||
<xi:include href="troubleshooting.xml" />
|
||||
<!-- <xi:include href="bugs.xml" /> -->
|
||||
<xi:include href="glossary.xml" />
|
||||
|
||||
<appendix>
|
||||
<title>Nix Release Notes</title>
|
||||
<xi:include href="release-notes.xml"
|
||||
xpointer="xmlns(x=http://docbook.org/ns/docbook)xpointer(x:article/x:section)" />
|
||||
</appendix>
|
||||
|
||||
</book>
|
||||
225
doc/manual/nix-build.xml
Normal file
225
doc/manual/nix-build.xml
Normal file
@@ -0,0 +1,225 @@
|
||||
<refentry xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xml:id="sec-nix-build">
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>nix-build</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
<refmiscinfo class="source">Nix</refmiscinfo>
|
||||
<refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>nix-build</refname>
|
||||
<refpurpose>build a Nix expression</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>nix-build</command>
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="opt-common-syn.xml#xmlns(db=http://docbook.org/ns/docbook)xpointer(/db:nop/*)" />
|
||||
<arg><option>--arg</option> <replaceable>name</replaceable> <replaceable>value</replaceable></arg>
|
||||
<arg><option>--argstr</option> <replaceable>name</replaceable> <replaceable>value</replaceable></arg>
|
||||
<arg>
|
||||
<group choice='req'>
|
||||
<arg choice='plain'><option>--attr</option></arg>
|
||||
<arg choice='plain'><option>-A</option></arg>
|
||||
</group>
|
||||
<replaceable>attrPath</replaceable>
|
||||
</arg>
|
||||
<arg><option>--drv-link</option> <replaceable>drvlink</replaceable></arg>
|
||||
<arg><option>--add-drv-link</option></arg>
|
||||
<arg><option>--no-out-link</option></arg>
|
||||
<arg>
|
||||
<group choice='req'>
|
||||
<arg choice='plain'><option>--out-link</option></arg>
|
||||
<arg choice='plain'><option>-o</option></arg>
|
||||
</group>
|
||||
<replaceable>outlink</replaceable>
|
||||
</arg>
|
||||
<arg>
|
||||
<option>--run-env</option>
|
||||
<arg><option>--command</option> <replaceable>cmd</replaceable></arg>
|
||||
<arg><option>--exclude</option> <replaceable>regexp</replaceable></arg>
|
||||
</arg>
|
||||
<arg choice='plain' rep='repeat'><replaceable>paths</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
<para>The <command>nix-build</command> command builds the derivations
|
||||
described by the Nix expressions in <replaceable>paths</replaceable>.
|
||||
If the build succeeds, it places a symlink to the result in the
|
||||
current directory. The symlink is called <filename>result</filename>.
|
||||
If there are multiple Nix expressions, or the Nix expressions evaluate
|
||||
to multiple derivations, multiple sequentially numbered symlinks are
|
||||
created (<filename>result</filename>, <filename>result-2</filename>,
|
||||
and so on).</para>
|
||||
|
||||
<para>If no <replaceable>paths</replaceable> are specified, then
|
||||
<command>nix-build</command> will use <filename>default.nix</filename>
|
||||
in the current directory, if it exists.</para>
|
||||
|
||||
<para><command>nix-build</command> is essentially a wrapper around
|
||||
<link
|
||||
linkend="sec-nix-instantiate"><command>nix-instantiate</command></link>
|
||||
(to translate a high-level Nix expression to a low-level store
|
||||
derivation) and <link
|
||||
linkend="rsec-nix-store-realise"><command>nix-store
|
||||
--realise</command></link> (to build the store derivation).</para>
|
||||
|
||||
<warning><para>The result of the build is automatically registered as
|
||||
a root of the Nix garbage collector. This root disappears
|
||||
automatically when the <filename>result</filename> symlink is deleted
|
||||
or renamed. So don’t rename the symlink.</para></warning>
|
||||
|
||||
<para>The subcommand <command>nix-build --run-env</command> will build
|
||||
the dependencies of the derivation, but not the derivation itself. It
|
||||
will then start an interactive shell in which all environment
|
||||
variables defined by the derivation have been set to their
|
||||
corresponding values. This is useful for reproducing the environment
|
||||
of a derivation for development.</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Options</title>
|
||||
|
||||
<para>All options not listed here are passed to <command>nix-store
|
||||
--realise</command>, except for <option>--arg</option> and
|
||||
<option>--attr</option> / <option>-A</option> which are passed to
|
||||
<command>nix-instantiate</command>. <phrase condition="manual">See
|
||||
also <xref linkend="sec-common-options" />.</phrase></para>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><option>--drv-link</option> <replaceable>drvlink</replaceable></term>
|
||||
|
||||
<listitem><para>Add a symlink named
|
||||
<replaceable>drvlink</replaceable> to the store derivation
|
||||
produced by <command>nix-instantiate</command>. The derivation is
|
||||
a root of the garbage collector until the symlink is deleted or
|
||||
renamed. If there are multiple derivations, numbers are suffixed
|
||||
to <replaceable>drvlink</replaceable> to distinguish between
|
||||
them.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--add-drv-link</option></term>
|
||||
|
||||
<listitem><para>Shorthand for <option>--drv-link</option>
|
||||
<filename>./derivation</filename>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--no-out-link</option></term>
|
||||
|
||||
<listitem><para>Do not create a symlink to the output path. Note
|
||||
that as a result the output does not become a root of the garbage
|
||||
collector, and so might be deleted by <command>nix-store
|
||||
--gc</command>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id='opt-out-link'><term><option>--out-link</option> /
|
||||
<option>-o</option> <replaceable>outlink</replaceable></term>
|
||||
|
||||
<listitem><para>Change the name of the symlink to the output path
|
||||
created from <filename>result</filename> to
|
||||
<replaceable>outlink</replaceable>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
<variablelist condition="manpage">
|
||||
<xi:include href="opt-common.xml#xmlns(db=http://docbook.org/ns/docbook)xpointer(//db:variablelist[@xml:id='opt-common']/*)" />
|
||||
</variablelist>
|
||||
|
||||
<para>The following options apply to <command>nix-build --run-env</command>.</para>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><option>--command</option> <replaceable>cmd</replaceable></term>
|
||||
|
||||
<listitem><para>In the environment of the derivation, executeq the
|
||||
command <replaceable>cmd</replaceable> instead of the default
|
||||
interactive shell.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--exclude</option> <replaceable>regexp</replaceable></term>
|
||||
|
||||
<listitem><para>Do not build any dependencies whose store path
|
||||
matches the regular expression <replaceable>regexp</replaceable>.
|
||||
This option may be specified multiple times.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Examples</title>
|
||||
|
||||
<screen>
|
||||
$ nix-build '<nixpkgs>' -A firefox
|
||||
store derivation is /nix/store/qybprl8sz2lc...-firefox-1.5.0.7.drv
|
||||
/nix/store/d18hyl92g30l...-firefox-1.5.0.7
|
||||
|
||||
$ ls -l result
|
||||
lrwxrwxrwx <replaceable>...</replaceable> result -> /nix/store/d18hyl92g30l...-firefox-1.5.0.7
|
||||
|
||||
$ ls ./result/bin/
|
||||
firefox firefox-config</screen>
|
||||
|
||||
<para>To build the dependencies of the package Pan, and start an
|
||||
interactive shell in which to build it:
|
||||
|
||||
<screen>
|
||||
$ nix-build '<nixpkgs>' --run-env -A pan
|
||||
$ tar xf $src
|
||||
$ cd pan-*
|
||||
$ ./configure
|
||||
$ make
|
||||
$ ./pan/gui/pan
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>If a derivation has multiple outputs,
|
||||
<command>nix-build</command> will build the default (first) output.
|
||||
You can also build all outputs:
|
||||
<screen>
|
||||
$ nix-build '<nixpkgs>' -A openssl.all
|
||||
</screen>
|
||||
This will create a symlink for each output named
|
||||
<filename>result-<replaceable>outputname</replaceable></filename>.
|
||||
The suffix is omitted if the output name is <literal>out</literal>.
|
||||
So if <literal>openssl</literal> has outputs <literal>out</literal>,
|
||||
<literal>bin</literal> and <literal>man</literal>,
|
||||
<command>nix-build</command> will create symlinks
|
||||
<literal>result</literal>, <literal>result-bin</literal> and
|
||||
<literal>result-man</literal>. It’s also possible to build a specific
|
||||
output:
|
||||
<screen>
|
||||
$ nix-build '<nixpkgs>' -A openssl.man
|
||||
</screen>
|
||||
This will create a symlink <literal>result-man</literal>.</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection condition="manpage"><title>Environment variables</title>
|
||||
|
||||
<variablelist>
|
||||
<xi:include href="env-common.xml#xmlns(db=http://docbook.org/ns/docbook)xpointer(//db:variablelist[@xml:id='env-common']/*)" />
|
||||
</variablelist>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
</refentry>
|
||||
112
doc/manual/nix-channel.xml
Normal file
112
doc/manual/nix-channel.xml
Normal file
@@ -0,0 +1,112 @@
|
||||
<refentry xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xml:id="sec-nix-channel">
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>nix-channel</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
<refmiscinfo class="source">Nix</refmiscinfo>
|
||||
<refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>nix-channel</refname>
|
||||
<refpurpose>manage Nix channels</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>nix-channel</command>
|
||||
<group choice='req'>
|
||||
<arg choice='plain'><option>--add</option> <replaceable>url</replaceable> <arg choice='opt'><replaceable>name</replaceable></arg></arg>
|
||||
<arg choice='plain'><option>--remove</option> <replaceable>url</replaceable></arg>
|
||||
<arg choice='plain'><option>--list</option></arg>
|
||||
<arg choice='plain'><option>--update</option> <arg rep='repeat'><replaceable>names</replaceable></arg></arg>
|
||||
</group>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
<para>A Nix channel is mechanism that allows you to automatically stay
|
||||
up-to-date with a set of pre-built Nix expressions. A Nix channel is
|
||||
just a URL that points to a place containing a set of Nix expressions
|
||||
and a <command>nix-push</command> manifest. <phrase
|
||||
condition="manual">See also <xref linkend="sec-channels"
|
||||
/>.</phrase></para>
|
||||
|
||||
<para>This command has the following operations:
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><option>--add</option> <replaceable>url</replaceable> [<replaceable>name</replaceable>]</term>
|
||||
|
||||
<listitem><para>Adds a channel named
|
||||
<replaceable>name</replaceable> with URL
|
||||
<replaceable>url</replaceable> to the list of subscribed channels.
|
||||
If <replaceable>name</replaceable> is omitted, it defaults to the
|
||||
last component of <replaceable>url</replaceable>, with the
|
||||
suffixes <literal>-stable</literal> or
|
||||
<literal>-unstable</literal> removed.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--remove</option> <replaceable>name</replaceable></term>
|
||||
|
||||
<listitem><para>Removes the channel named
|
||||
<replaceable>name</replaceable> from the list of subscribed
|
||||
channels.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--list</option></term>
|
||||
|
||||
<listitem><para>Prints the names and URLs of all subscribed
|
||||
channels on standard output.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--update</option> [<replaceable>names</replaceable>…]</term>
|
||||
|
||||
<listitem><para>Downloads the Nix expressions of all subscribed
|
||||
channels (or only those included in
|
||||
<replaceable>names</replaceable> if specified), makes them the
|
||||
default for <command>nix-env</command> operations (by symlinking
|
||||
them from the directory <filename>~/.nix-defexpr</filename>), and
|
||||
performs a <command>nix-pull</command> on the manifests of all
|
||||
channels to make pre-built binaries available.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Note that <option>--add</option> does not automatically perform
|
||||
an update.</para>
|
||||
|
||||
<para>The list of subscribed channels is stored in
|
||||
<filename>~/.nix-channels</filename>.</para>
|
||||
|
||||
<para>A channel consists of two elements: a bzipped Tar archive
|
||||
containing the Nix expressions, and a manifest created by
|
||||
<command>nix-push</command>. These must be stored under
|
||||
<literal><replaceable>url</replaceable>/nixexprs.tar.bz2</literal> and
|
||||
<literal><replaceable>url</replaceable>/MANIFEST</literal>,
|
||||
respectively.</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
<refsection><title>Examples</title>
|
||||
|
||||
<para>To subscribe to the Nixpkgs channel and install the GNU Hello package:</para>
|
||||
|
||||
<screen>
|
||||
$ nix-channel --add http://nixos.org/channels/nixpkgs-unstable
|
||||
$ nix-channel --update
|
||||
$ nix-env -iA nixpkgs.hello</screen>
|
||||
|
||||
</refsection>
|
||||
|
||||
</refentry>
|
||||
60
doc/manual/nix-collect-garbage.xml
Normal file
60
doc/manual/nix-collect-garbage.xml
Normal file
@@ -0,0 +1,60 @@
|
||||
<refentry xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xml:id="sec-nix-collect-garbage">
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>nix-collect-garbage</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
<refmiscinfo class="source">Nix</refmiscinfo>
|
||||
<refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>nix-collect-garbage</refname>
|
||||
<refpurpose>delete unreachable store paths</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>nix-collect-garbage</command>
|
||||
<arg><option>--delete-old</option></arg>
|
||||
<arg><option>-d</option></arg>
|
||||
<group choice='opt'>
|
||||
<arg choice='plain'><option>--print-roots</option></arg>
|
||||
<arg choice='plain'><option>--print-live</option></arg>
|
||||
<arg choice='plain'><option>--print-dead</option></arg>
|
||||
<arg choice='plain'><option>--delete</option></arg>
|
||||
</group>
|
||||
<arg><option>--dry-run</option></arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
<para>The command <command>nix-collect-garbage</command> is mostly an
|
||||
alias of <link linkend="rsec-nix-store-gc"><command>nix-store
|
||||
--gc</command></link>, that is, it deletes all unreachable paths in
|
||||
the Nix store to clean up your system. However, it provides an
|
||||
additional option <option>-d</option> (<option>--delete-old</option>)
|
||||
that deletes all old generations of all profiles in
|
||||
<filename>/nix/var/nix/profiles</filename> by invoking
|
||||
<literal>nix-env --delete-generations old</literal> on all profiles.
|
||||
Of course, this makes rollbacks to previous configurations
|
||||
impossible.</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
<refsection><title>Example</title>
|
||||
|
||||
<para>To delete from the Nix store everything that is not used by the
|
||||
current generations of each profile, do
|
||||
|
||||
<screen>
|
||||
$ nix-collect-garbage -d</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
</refentry>
|
||||
188
doc/manual/nix-copy-closure.xml
Normal file
188
doc/manual/nix-copy-closure.xml
Normal file
@@ -0,0 +1,188 @@
|
||||
<refentry xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xml:id="sec-nix-copy-closure">
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>nix-copy-closure</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
<refmiscinfo class="source">Nix</refmiscinfo>
|
||||
<refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>nix-copy-closure</refname>
|
||||
<refpurpose>copy a closure to or from a remote machine via SSH</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>nix-copy-closure</command>
|
||||
<group>
|
||||
<arg choice='plain'><option>--to</option></arg>
|
||||
<arg choice='plain'><option>--from</option></arg>
|
||||
</group>
|
||||
<arg><option>--sign</option></arg>
|
||||
<arg><option>--gzip</option></arg>
|
||||
<arg><option>--bzip2</option></arg>
|
||||
<arg><option>--xz</option></arg>
|
||||
<arg><option>--show-progress</option></arg>
|
||||
<arg><option>--include-outputs</option></arg>
|
||||
<arg><option>--use-substitutes</option></arg>
|
||||
<arg><option>-s</option></arg>
|
||||
<arg choice='plain'>
|
||||
<replaceable>user@</replaceable><replaceable>machine</replaceable>
|
||||
</arg>
|
||||
<arg choice='plain'><replaceable>paths</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
<para><command>nix-copy-closure</command> gives you an easy and
|
||||
efficient way to exchange software between machines. Given one or
|
||||
more Nix store paths <replaceable>paths</replaceable> on the local
|
||||
machine, <command>nix-copy-closure</command> computes the closure of
|
||||
those paths (i.e. all their dependencies in the Nix store), and copies
|
||||
all paths in the closure to the remote machine via the
|
||||
<command>ssh</command> (Secure Shell) command. With the
|
||||
<option>--from</option>, the direction is reversed:
|
||||
the closure of <replaceable>paths</replaceable> on a remote machine is
|
||||
copied to the Nix store on the local machine.</para>
|
||||
|
||||
<para>This command is efficient because it only sends the store paths
|
||||
that are missing on the target machine.</para>
|
||||
|
||||
<para>Since <command>nix-copy-closure</command> calls
|
||||
<command>ssh</command>, you may be asked to type in the appropriate
|
||||
password or passphrase. In fact, you may be asked
|
||||
<emphasis>twice</emphasis> because <command>nix-copy-closure</command>
|
||||
currently connects twice to the remote machine, first to get the set
|
||||
of paths missing on the target machine, and second to send the dump of
|
||||
those paths. If this bothers you, use
|
||||
<command>ssh-agent</command>.</para>
|
||||
|
||||
|
||||
<refsection><title>Options</title>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><option>--to</option></term>
|
||||
|
||||
<listitem><para>Copy the closure of
|
||||
<replaceable>paths</replaceable> from the local Nix store to the
|
||||
Nix store on <replaceable>machine</replaceable>. This is the
|
||||
default.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--from</option></term>
|
||||
|
||||
<listitem><para>Copy the closure of
|
||||
<replaceable>paths</replaceable> from the Nix store on
|
||||
<replaceable>machine</replaceable> to the local Nix
|
||||
store.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--sign</option></term>
|
||||
|
||||
<listitem><para>Let the sending machine cryptographically sign the
|
||||
dump of each path with the key in
|
||||
<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> / <option>--bzip2</option> / <option>--xz</option></term>
|
||||
|
||||
<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>--show-progress</option></term>
|
||||
|
||||
<listitem><para>Show the progress of each path's transfer as it's made.
|
||||
This requires the <command>pv</command> utility to be in <envar>PATH</envar>.</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>
|
||||
|
||||
<varlistentry><term><option>--use-substitutes</option> / <option>-s</option></term>
|
||||
|
||||
<listitem><para>Attempt to download missing paths on the target
|
||||
machine using Nix’s substitute mechanism. Any paths that cannot
|
||||
be substituted on the target are still copied normally from the
|
||||
source. This is useful, for instance, if the connection between
|
||||
the source and target machine is slow, but the connection between
|
||||
the target machine and <literal>nixos.org</literal> (the default
|
||||
binary cache server) is fast.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Environment variables</title>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><envar>NIX_SSHOPTS</envar></term>
|
||||
|
||||
<listitem><para>Additional options to be passed to
|
||||
<command>ssh</command> on the command line.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Examples</title>
|
||||
|
||||
<para>Copy Firefox with all its dependencies to a remote machine:
|
||||
|
||||
<screen>
|
||||
$ nix-copy-closure --to alice@itchy.labs $(type -tP firefox)</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Copy Subversion from a remote machine and then install it into a
|
||||
user environment:
|
||||
|
||||
<screen>
|
||||
$ nix-copy-closure --from alice@itchy.labs \
|
||||
/nix/store/0dj0503hjxy5mbwlafv1rsbdiyx1gkdy-subversion-1.4.4
|
||||
$ nix-env -i /nix/store/0dj0503hjxy5mbwlafv1rsbdiyx1gkdy-subversion-1.4.4
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
</refsection>
|
||||
|
||||
</refentry>
|
||||
34
doc/manual/nix-daemon.xml
Normal file
34
doc/manual/nix-daemon.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<refentry xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xml:id="sec-nix-daemon">
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>nix-daemon</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
<refmiscinfo class="source">Nix</refmiscinfo>
|
||||
<refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>nix-daemon</refname>
|
||||
<refpurpose>Nix multi-user support daemon</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>nix-daemon</command>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
<para>The Nix daemon is necessary in multi-user Nix installations. It
|
||||
performs build actions and other operations on the Nix store on behalf
|
||||
of unprivileged users.</para>
|
||||
|
||||
|
||||
</refsection>
|
||||
|
||||
</refentry>
|
||||
1265
doc/manual/nix-env.xml
Normal file
1265
doc/manual/nix-env.xml
Normal file
File diff suppressed because it is too large
Load Diff
164
doc/manual/nix-hash.xml
Normal file
164
doc/manual/nix-hash.xml
Normal file
@@ -0,0 +1,164 @@
|
||||
<refentry xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xml:id="sec-nix-hash">
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>nix-hash</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
<refmiscinfo class="source">Nix</refmiscinfo>
|
||||
<refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>nix-hash</refname>
|
||||
<refpurpose>compute the cryptographic hash of a path</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>nix-hash</command>
|
||||
<arg><option>--flat</option></arg>
|
||||
<arg><option>--base32</option></arg>
|
||||
<arg><option>--truncate</option></arg>
|
||||
<arg><option>--type</option> <replaceable>hashAlgo</replaceable></arg>
|
||||
<arg choice='plain' rep='repeat'><replaceable>path</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>nix-hash</command>
|
||||
<arg choice='plain'><option>--to-base16</option></arg>
|
||||
<arg choice='plain' rep='repeat'><replaceable>hash</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>nix-hash</command>
|
||||
<arg choice='plain'><option>--to-base32</option></arg>
|
||||
<arg choice='plain' rep='repeat'><replaceable>hash</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
<para>The command <command>nix-hash</command> computes the
|
||||
cryptographic hash of the contents of each
|
||||
<replaceable>path</replaceable> and prints it on standard output. By
|
||||
default, it computes an MD5 hash, but other hash algorithms are
|
||||
available as well. The hash is printed in hexadecimal.</para>
|
||||
|
||||
<para>The hash is computed over a <emphasis>serialisation</emphasis>
|
||||
of each path: a dump of the file system tree rooted at the path. This
|
||||
allows directories and symlinks to be hashed as well as regular files.
|
||||
The dump is in the <emphasis>NAR format</emphasis> produced by <link
|
||||
linkend="refsec-nix-store-dump"><command>nix-store</command>
|
||||
<option>--dump</option></link>. Thus, <literal>nix-hash
|
||||
<replaceable>path</replaceable></literal> yields the same
|
||||
cryptographic hash as <literal>nix-store --dump
|
||||
<replaceable>path</replaceable> | md5sum</literal>.</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Options</title>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><option>--flat</option></term>
|
||||
|
||||
<listitem><para>Print the cryptographic hash of the contents of
|
||||
each regular file <replaceable>path</replaceable>. That is, do
|
||||
not compute the hash over the dump of
|
||||
<replaceable>path</replaceable>. The result is identical to that
|
||||
produced by the GNU commands <command>md5sum</command> and
|
||||
<command>sha1sum</command>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--base32</option></term>
|
||||
|
||||
<listitem><para>Print the hash in a base-32 representation rather
|
||||
than hexadecimal. This base-32 representation is more compact and
|
||||
can be used in Nix expressions (such as in calls to
|
||||
<function>fetchurl</function>).</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--truncate</option></term>
|
||||
|
||||
<listitem><para>Truncate hashes longer than 160 bits (such as
|
||||
SHA-256) to 160 bits.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--type</option> <replaceable>hashAlgo</replaceable></term>
|
||||
|
||||
<listitem><para>Use the specified cryptographic hash algorithm,
|
||||
which can be one of <literal>md5</literal>,
|
||||
<literal>sha1</literal>, and
|
||||
<literal>sha256</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--to-base16</option></term>
|
||||
|
||||
<listitem><para>Don’t hash anything, but convert the base-32 hash
|
||||
representation <replaceable>hash</replaceable> to
|
||||
hexadecimal.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--to-base32</option></term>
|
||||
|
||||
<listitem><para>Don’t hash anything, but convert the hexadecimal
|
||||
hash representation <replaceable>hash</replaceable> to
|
||||
base-32.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Examples</title>
|
||||
|
||||
<para>Computing hashes:
|
||||
|
||||
<screen>
|
||||
$ mkdir test
|
||||
$ echo "hello" > test/world
|
||||
|
||||
$ nix-hash test/ <lineannotation>(MD5 hash; default)</lineannotation>
|
||||
8179d3caeff1869b5ba1744e5a245c04
|
||||
|
||||
$ nix-store --dump test/ | md5sum <lineannotation>(for comparison)</lineannotation>
|
||||
8179d3caeff1869b5ba1744e5a245c04 -
|
||||
|
||||
$ nix-hash --type sha1 test/
|
||||
e4fd8ba5f7bbeaea5ace89fe10255536cd60dab6
|
||||
|
||||
$ nix-hash --type sha1 --base32 test/
|
||||
nvd61k9nalji1zl9rrdfmsmvyyjqpzg4
|
||||
|
||||
$ nix-hash --type sha256 --flat test/
|
||||
error: reading file `test/': Is a directory
|
||||
|
||||
$ nix-hash --type sha256 --flat test/world
|
||||
5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Converting between hexadecimal and base-32:
|
||||
|
||||
<screen>
|
||||
$ nix-hash --type sha1 --to-base32 e4fd8ba5f7bbeaea5ace89fe10255536cd60dab6
|
||||
nvd61k9nalji1zl9rrdfmsmvyyjqpzg4
|
||||
|
||||
$ nix-hash --type sha1 --to-base16 nvd61k9nalji1zl9rrdfmsmvyyjqpzg4
|
||||
e4fd8ba5f7bbeaea5ace89fe10255536cd60dab6</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
</refentry>
|
||||
198
doc/manual/nix-install-package.xml
Normal file
198
doc/manual/nix-install-package.xml
Normal file
@@ -0,0 +1,198 @@
|
||||
<refentry xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xml:id="sec-nix-install-package">
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>nix-install-package</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
<refmiscinfo class="source">Nix</refmiscinfo>
|
||||
<refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>nix-install-package</refname>
|
||||
<refpurpose>install a Nix Package file</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>nix-install-package</command>
|
||||
<arg><option>--non-interactive</option></arg>
|
||||
<arg>
|
||||
<group choice='req'>
|
||||
<arg choice='plain'><option>--profile</option></arg>
|
||||
<arg choice='plain'><option>-p</option></arg>
|
||||
</group>
|
||||
<replaceable>path</replaceable>
|
||||
</arg>
|
||||
<sbr />
|
||||
<group choice='req'>
|
||||
<arg choice='req'>
|
||||
<option>--url</option>
|
||||
<arg choice='plain'><replaceable>url</replaceable></arg>
|
||||
</arg>
|
||||
<arg choice='req'>
|
||||
<arg choice='plain'><replaceable>file</replaceable></arg>
|
||||
</arg>
|
||||
</group>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
<para>The command <command>nix-install-package</command> interactively
|
||||
installs a Nix Package file (<filename>*.nixpkg</filename>), which is
|
||||
a small file that contains a store path to be installed along with the
|
||||
URL of a <link linkend="sec-nix-push"><command>nix-push</command>
|
||||
manifest</link>. The Nix Package file is either
|
||||
<replaceable>file</replaceable>, or automatically downloaded from
|
||||
<replaceable>url</replaceable> if the <option>--url</option> switch is
|
||||
used.</para>
|
||||
|
||||
<para><command>nix-install-package</command> is used in <link
|
||||
linkend="sec-one-click">one-click installs</link> to download and
|
||||
install pre-built binary packages with all necessary dependencies.
|
||||
<command>nix-install-package</command> is intended to be associated
|
||||
with the MIME type <literal>application/nix-package</literal> in a web
|
||||
browser so that it is invoked automatically when you click on
|
||||
<filename>*.nixpkg</filename> files. When invoked, it restarts itself
|
||||
in a terminal window (since otherwise it would be invisible when run
|
||||
from a browser), asks the user to confirm whether to install the
|
||||
package, and if so downloads and installs the package into the user’s
|
||||
current profile.</para>
|
||||
|
||||
<para>To obtain a window, <command>nix-install-package</command> tries
|
||||
to restart itself with <command>xterm</command>,
|
||||
<command>konsole</command> and
|
||||
<command>gnome-terminal</command>.</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Options</title>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><option>--non-interactive</option></term>
|
||||
|
||||
<listitem><para>Do not open a new terminal window and do not ask
|
||||
for confirmation.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--profile</option></term>
|
||||
<term><option>-p</option></term>
|
||||
|
||||
<listitem><para>Install the package into the specified profile
|
||||
rather than the user’s current profile.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Examples</title>
|
||||
|
||||
<para>To install <filename>subversion-1.4.0.nixpkg</filename> into the
|
||||
user’s current profile, without any prompting:
|
||||
|
||||
<screen>
|
||||
$ nix-install-package --non-interactive subversion-1.4.0.nixpkg</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>To install the same package from some URL into a different
|
||||
profile:
|
||||
|
||||
<screen>
|
||||
$ nix-install-package --non-interactive -p /nix/var/nix/profiles/eelco \
|
||||
--url http://nix.cs.uu.nl/dist/nix/nixpkgs-0.10pre6622/pkgs/subversion-1.4.0-i686-linux.nixpkg</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Format of <literal>nixpkg</literal> files</title>
|
||||
|
||||
<para>A Nix Package file consists of a single line with the following
|
||||
format:
|
||||
|
||||
<screen>
|
||||
NIXPKG1 <replaceable>manifestURL</replaceable> <replaceable>name</replaceable> <replaceable>system</replaceable> <replaceable>drvPath</replaceable> <replaceable>outPath</replaceable></screen>
|
||||
|
||||
The elemens are as follows:
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><literal>NIXPKG1</literal></term>
|
||||
|
||||
<listitem><para>The version of the Nix Package
|
||||
file.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><replaceable>manifestURL</replaceable></term>
|
||||
|
||||
<listitem><para>The manifest to be pulled by
|
||||
<command>nix-pull</command>. The manifest must contain
|
||||
<replaceable>outPath</replaceable>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><replaceable>name</replaceable></term>
|
||||
|
||||
<listitem><para>The symbolic name and version of the
|
||||
package.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><replaceable>system</replaceable></term>
|
||||
|
||||
<listitem><para>The platform identifier of the platform for which
|
||||
this binary package is intended.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><replaceable>drvPath</replaceable></term>
|
||||
|
||||
<listitem><para>The path in the Nix store of the derivation from
|
||||
which <replaceable>outPath</replaceable> was built. Not currently
|
||||
used.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><replaceable>outPath</replaceable></term>
|
||||
|
||||
<listitem><para>The path in the Nix store of the package. After
|
||||
<command>nix-install-package</command> has obtained the manifest
|
||||
from <replaceable>manifestURL</replaceable>, it performs a
|
||||
<literal>nix-env -i</literal> <replaceable>outPath</replaceable>
|
||||
to install the binary package.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
|
||||
<para>An example follows:
|
||||
|
||||
<screen>
|
||||
NIXPKG1 http://.../nixpkgs-0.10pre6622/MANIFEST subversion-1.4.0 i686-darwin \
|
||||
/nix/store/4kh60jkp...-subversion-1.4.0.drv \
|
||||
/nix/store/nkw7wpgb...-subversion-1.4.0</screen>
|
||||
|
||||
(The line breaks (<literal>\</literal>) are for presentation purposes
|
||||
and not part of the actual file.)
|
||||
|
||||
</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
</refentry>
|
||||
229
doc/manual/nix-instantiate.xml
Normal file
229
doc/manual/nix-instantiate.xml
Normal file
@@ -0,0 +1,229 @@
|
||||
<refentry xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xml:id="sec-nix-instantiate">
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>nix-instantiate</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
<refmiscinfo class="source">Nix</refmiscinfo>
|
||||
<refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>nix-instantiate</refname>
|
||||
<refpurpose>instantiate store derivations from Nix expressions</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>nix-instantiate</command>
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="opt-common-syn.xml#xmlns(db=http://docbook.org/ns/docbook)xpointer(/db:nop/*)" />
|
||||
<arg><option>--arg</option> <replaceable>name</replaceable> <replaceable>value</replaceable></arg>
|
||||
<arg>
|
||||
<group choice='req'>
|
||||
<arg choice='plain'><option>--attr</option></arg>
|
||||
<arg choice='plain'><option>-A</option></arg>
|
||||
</group>
|
||||
<replaceable>attrPath</replaceable>
|
||||
</arg>
|
||||
<arg><option>--add-root</option> <replaceable>path</replaceable></arg>
|
||||
<arg><option>--indirect</option></arg>
|
||||
<arg>
|
||||
<group choice='req'>
|
||||
<arg choice='plain'><option>--parse-only</option></arg>
|
||||
<arg choice='plain'>
|
||||
<option>--eval-only</option>
|
||||
<arg><option>--strict</option></arg>
|
||||
</arg>
|
||||
<arg choice='plain'><option>--find-file</option></arg>
|
||||
</group>
|
||||
<arg><option>--xml</option></arg>
|
||||
</arg>
|
||||
<arg choice='plain' rep='repeat'><replaceable>files</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
<para>The command <command>nix-instantiate</command> generates <link
|
||||
linkend="gloss-derivation">store derivations</link> from (high-level)
|
||||
Nix expressions. It loads and evaluates the Nix expressions in each
|
||||
of <replaceable>files</replaceable> (which defaults to
|
||||
<replaceable>./default.nix</replaceable>). Each top-level expression
|
||||
should evaluate to a derivation, a list of derivations, or a set of
|
||||
derivations. The paths of the resulting store derivations are printed
|
||||
on standard output.</para>
|
||||
|
||||
<para>If <replaceable>files</replaceable> is the character
|
||||
<literal>-</literal>, then a Nix expression will be read from standard
|
||||
input.</para>
|
||||
|
||||
<para>Most users and developers don’t need to use this command
|
||||
(<command>nix-env</command> and <command>nix-build</command> perform
|
||||
store derivation instantiation from Nix expressions automatically).
|
||||
It is most commonly used for implementing new deployment
|
||||
policies.</para>
|
||||
|
||||
<para condition="manual">See also <xref linkend="sec-common-options"
|
||||
/> for a list of common options.</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Options</title>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--add-root</option> <replaceable>path</replaceable></term>
|
||||
<term><option>--indirect</option></term>
|
||||
|
||||
<listitem><para>See the <link linkend="opt-add-root">corresponding
|
||||
options</link> in <command>nix-store</command>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><option>--parse-only</option></term>
|
||||
|
||||
<listitem><para>Just parse the input files, and print their
|
||||
abstract syntax trees on standard output in ATerm
|
||||
format.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--eval-only</option></term>
|
||||
|
||||
<listitem><para>Just parse and evaluate the input files, and print
|
||||
the resulting values on standard output. No instantiation of
|
||||
store derivations takes place.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--find-file</option></term>
|
||||
|
||||
<listitem><para>Look up the given files in Nix’s search path (as
|
||||
specified by the <envar>NIX_PATH</envar> environment variable).
|
||||
If found, print the corresponding absolute paths on standard
|
||||
output. For instance, if <envar>NIX_PATH</envar> is
|
||||
<literal>nixpkgs=/home/alice/nixpkgs</literal>, then
|
||||
<literal>nix-instantiate --find-file nixpkgs/default.nix</literal>
|
||||
will print
|
||||
<literal>/home/alice/nixpkgs/default.nix</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--xml</option></term>
|
||||
|
||||
<listitem><para>When used with <option>--parse-only</option> and
|
||||
<option>--eval-only</option>, print the resulting expression as an
|
||||
XML representation of the abstract syntax tree rather than as an
|
||||
ATerm. The schema is the same as that used by the <link
|
||||
linkend="builtin-toXML"><function>toXML</function>
|
||||
built-in</link>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--strict</option></term>
|
||||
|
||||
<listitem><para>When used with <option>--eval-only</option>,
|
||||
recursively evaluate list elements and attributes. Normally, such
|
||||
sub-expressions are left unevaluated (since the Nix expression
|
||||
language is lazy).</para>
|
||||
|
||||
<warning><para>This option can cause non-termination, because lazy
|
||||
data structures can be infinitely large.</para></warning>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
<variablelist condition="manpage">
|
||||
<xi:include href="opt-common.xml#xmlns(db=http://docbook.org/ns/docbook)xpointer(//db:variablelist[@xml:id='opt-common']/*)" />
|
||||
</variablelist>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Examples</title>
|
||||
|
||||
<para>Instantiating store derivations from a Nix expression, and
|
||||
building them using <command>nix-store</command>:
|
||||
|
||||
<screen>
|
||||
$ nix-instantiate test.nix <lineannotation>(instantiate)</lineannotation>
|
||||
/nix/store/cigxbmvy6dzix98dxxh9b6shg7ar5bvs-perl-BerkeleyDB-0.26.drv
|
||||
|
||||
$ nix-store -r $(nix-instantiate test.nix) <lineannotation>(build)</lineannotation>
|
||||
<replaceable>...</replaceable>
|
||||
/nix/store/qhqk4n8ci095g3sdp93x7rgwyh9rdvgk-perl-BerkeleyDB-0.26 <lineannotation>(output path)</lineannotation>
|
||||
|
||||
$ ls -l /nix/store/qhqk4n8ci095g3sdp93x7rgwyh9rdvgk-perl-BerkeleyDB-0.26
|
||||
dr-xr-xr-x 2 eelco users 4096 1970-01-01 01:00 lib
|
||||
...</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Parsing and evaluating Nix expressions:
|
||||
|
||||
<screen>
|
||||
$ echo '"foo" + "bar"' | nix-instantiate --parse-only -
|
||||
OpPlus(Str("foo"),Str("bar"))
|
||||
|
||||
$ echo '"foo" + "bar"' | nix-instantiate --eval-only -
|
||||
Str("foobar")
|
||||
|
||||
$ echo '"foo" + "bar"' | nix-instantiate --eval-only --xml -
|
||||
<![CDATA[<?xml version='1.0' encoding='utf-8'?>
|
||||
<expr>
|
||||
<string value="foobar" />
|
||||
</expr>]]></screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The difference between non-strict and strict evaluation:
|
||||
|
||||
<screen>
|
||||
$ echo 'rec { x = "foo"; y = x; }' | nix-instantiate --eval-only --xml -
|
||||
<replaceable>...</replaceable><![CDATA[
|
||||
<attr name="x">
|
||||
<string value="foo" />
|
||||
</attr>
|
||||
<attr name="y">
|
||||
<unevaluated />
|
||||
</attr>]]>
|
||||
<replaceable>...</replaceable></screen>
|
||||
|
||||
Note that <varname>y</varname> is left unevaluated (the XML
|
||||
representation doesn’t attempt to show non-normal forms).
|
||||
|
||||
<screen>
|
||||
$ echo 'rec { x = "foo"; y = x; }' | nix-instantiate --eval-only --xml --strict -
|
||||
<replaceable>...</replaceable><![CDATA[
|
||||
<attr name="x">
|
||||
<string value="foo" />
|
||||
</attr>
|
||||
<attr name="y">
|
||||
<string value="foo" />
|
||||
</attr>]]>
|
||||
<replaceable>...</replaceable></screen>
|
||||
|
||||
</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection condition="manpage"><title>Environment variables</title>
|
||||
|
||||
<variablelist>
|
||||
<xi:include href="env-common.xml#xmlns(db=http://docbook.org/ns/docbook)xpointer(//db:variablelist[@xml:id='env-common']/*)" />
|
||||
</variablelist>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
</refentry>
|
||||
182
doc/manual/nix-lang-ref.xml
Normal file
182
doc/manual/nix-lang-ref.xml
Normal file
@@ -0,0 +1,182 @@
|
||||
<appendix>
|
||||
<title>Nix Language Reference</title>
|
||||
|
||||
<sect1>
|
||||
<title>Grammar</title>
|
||||
|
||||
<productionset>
|
||||
<title>Expressions</title>
|
||||
|
||||
<production id="nix.expr">
|
||||
<lhs>Expr</lhs>
|
||||
<rhs>
|
||||
<nonterminal def="#nix.expr_function" />
|
||||
</rhs>
|
||||
</production>
|
||||
|
||||
<production id="nix.expr_function">
|
||||
<lhs>ExprFunction</lhs>
|
||||
<rhs>
|
||||
'{' <nonterminal def="#nix.formals" /> '}' ':' <nonterminal def="#nix.expr_function" />
|
||||
<sbr />|
|
||||
<nonterminal def="#nix.expr_assert" />
|
||||
</rhs>
|
||||
</production>
|
||||
|
||||
<production id="nix.expr_assert">
|
||||
<lhs>ExprAssert</lhs>
|
||||
<rhs>
|
||||
'assert' <nonterminal def="#nix.expr" /> ';' <nonterminal def="#nix.expr_assert" />
|
||||
<sbr />|
|
||||
<nonterminal def="#nix.expr_if" />
|
||||
</rhs>
|
||||
</production>
|
||||
|
||||
<production id="nix.expr_if">
|
||||
<lhs>ExprIf</lhs>
|
||||
<rhs>
|
||||
'if' <nonterminal def="#nix.expr" /> 'then' <nonterminal def="#nix.expr" />
|
||||
'else' <nonterminal def="#nix.expr" />
|
||||
<sbr />|
|
||||
<nonterminal def="#nix.expr_op" />
|
||||
</rhs>
|
||||
</production>
|
||||
|
||||
<production id="nix.expr_op">
|
||||
<lhs>ExprOp</lhs>
|
||||
<rhs>
|
||||
'!' <nonterminal def="#nix.expr_op" />
|
||||
<sbr />|
|
||||
<nonterminal def="#nix.expr_op" /> '==' <nonterminal def="#nix.expr_op" />
|
||||
<sbr />|
|
||||
<nonterminal def="#nix.expr_op" /> '!=' <nonterminal def="#nix.expr_op" />
|
||||
<sbr />|
|
||||
<nonterminal def="#nix.expr_op" /> '&&' <nonterminal def="#nix.expr_op" />
|
||||
<sbr />|
|
||||
<nonterminal def="#nix.expr_op" /> '||' <nonterminal def="#nix.expr_op" />
|
||||
<sbr />|
|
||||
<nonterminal def="#nix.expr_op" /> '->' <nonterminal def="#nix.expr_op" />
|
||||
<sbr />|
|
||||
<nonterminal def="#nix.expr_op" /> '//' <nonterminal def="#nix.expr_op" />
|
||||
<sbr />|
|
||||
<nonterminal def="#nix.expr_op" /> '~' <nonterminal def="#nix.expr_op" />
|
||||
<sbr />|
|
||||
<nonterminal def="#nix.expr_op" /> '?' <nonterminal def="#nix.id" />
|
||||
<sbr />|
|
||||
<nonterminal def="#nix.expr_app" />
|
||||
</rhs>
|
||||
</production>
|
||||
|
||||
<production id="nix.expr_app">
|
||||
<lhs>ExprApp</lhs>
|
||||
<rhs>
|
||||
<nonterminal def="#nix.expr_app" /> '.' <nonterminal def="#nix.expr_select" />
|
||||
<sbr />|
|
||||
<nonterminal def="#nix.expr_select" />
|
||||
</rhs>
|
||||
</production>
|
||||
|
||||
<production id="nix.expr_select">
|
||||
<lhs>ExprSelect</lhs>
|
||||
<rhs>
|
||||
<nonterminal def="#nix.expr_select" /> <nonterminal def="#nix.id" />
|
||||
<sbr />|
|
||||
<nonterminal def="#nix.expr_simple" />
|
||||
</rhs>
|
||||
</production>
|
||||
|
||||
<production id="nix.expr_simple">
|
||||
<lhs>ExprSimple</lhs>
|
||||
<rhs>
|
||||
<nonterminal def="#nix.id" /> |
|
||||
<nonterminal def="#nix.int" /> |
|
||||
<nonterminal def="#nix.str" /> |
|
||||
<nonterminal def="#nix.path" /> |
|
||||
<nonterminal def="#nix.uri" />
|
||||
<sbr />|
|
||||
'true' | 'false' | 'null'
|
||||
<sbr />|
|
||||
'(' <nonterminal def="#nix.expr" /> ')'
|
||||
<sbr />|
|
||||
'{' <nonterminal def="#nix.bind" />* '}'
|
||||
<sbr />|
|
||||
'let' '{' <nonterminal def="#nix.bind" />* '}'
|
||||
<sbr />|
|
||||
'rec' '{' <nonterminal def="#nix.bind" />* '}'
|
||||
<sbr />|
|
||||
'[' <nonterminal def="#nix.expr_select" />* ']'
|
||||
</rhs>
|
||||
</production>
|
||||
|
||||
<production id="nix.bind">
|
||||
<lhs>Bind</lhs>
|
||||
<rhs>
|
||||
<nonterminal def="#nix.id" /> '=' <nonterminal def="#nix.expr" /> ';'
|
||||
<sbr />|
|
||||
'inherit' ('(' <nonterminal def="#nix.expr" /> ')')? <nonterminal def="#nix.id" />* ';'
|
||||
</rhs>
|
||||
</production>
|
||||
|
||||
<production id="nix.formals">
|
||||
<lhs>Formals</lhs>
|
||||
<rhs>
|
||||
<nonterminal def="#nix.formal" /> ',' <nonterminal def="#nix.formals" />
|
||||
| <nonterminal def="#nix.formal" />
|
||||
</rhs>
|
||||
</production>
|
||||
|
||||
<production id="nix.formal">
|
||||
<lhs>Formal</lhs>
|
||||
<rhs>
|
||||
<nonterminal def="#nix.id" />
|
||||
<sbr />|
|
||||
<nonterminal def="#nix.id" /> '?' <nonterminal def="#nix.expr" />
|
||||
</rhs>
|
||||
</production>
|
||||
|
||||
</productionset>
|
||||
|
||||
<productionset>
|
||||
<title>Terminals</title>
|
||||
|
||||
<production id="nix.id">
|
||||
<lhs>Id</lhs>
|
||||
<rhs>[a-zA-Z\_][a-zA-Z0-9\_\']*</rhs>
|
||||
</production>
|
||||
|
||||
<production id="nix.int">
|
||||
<lhs>Int</lhs>
|
||||
<rhs>[0-9]+</rhs>
|
||||
</production>
|
||||
|
||||
<production id="nix.str">
|
||||
<lhs>Str</lhs>
|
||||
<rhs>\"[^\n\"]*\"</rhs>
|
||||
</production>
|
||||
|
||||
<production id="nix.path">
|
||||
<lhs>Path</lhs>
|
||||
<rhs>[a-zA-Z0-9\.\_\-\+]*(\/[a-zA-Z0-9\.\_\-\+]+)+</rhs>
|
||||
</production>
|
||||
|
||||
<production id="nix.uri">
|
||||
<lhs>Uri</lhs>
|
||||
<rhs>[a-zA-Z][a-zA-Z0-9\+\-\.]*\:[a-zA-Z0-9\%\/\?\:\@\&\=\+\$\,\-\_\.\!\~\*\']+</rhs>
|
||||
</production>
|
||||
|
||||
<production id="nix.ws">
|
||||
<lhs>Whitespace</lhs>
|
||||
<rhs>
|
||||
[ \t\n]+
|
||||
<sbr />|
|
||||
\#[^\n]*
|
||||
<sbr />|
|
||||
\/\*(.|\n)*\*\/
|
||||
</rhs>
|
||||
</production>
|
||||
|
||||
</productionset>
|
||||
|
||||
</sect1>
|
||||
|
||||
</appendix>
|
||||
93
doc/manual/nix-prefetch-url.xml
Normal file
93
doc/manual/nix-prefetch-url.xml
Normal file
@@ -0,0 +1,93 @@
|
||||
<refentry xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xml:id="sec-nix-prefetch-url">
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>nix-prefetch-url</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
<refmiscinfo class="source">Nix</refmiscinfo>
|
||||
<refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>nix-prefetch-url</refname>
|
||||
<refpurpose>copy a file from a URL into the store and print its hash</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>nix-prefetch-url</command>
|
||||
<arg><option>--type</option> <replaceable>hashAlgo</replaceable></arg>
|
||||
<arg choice='plain'><replaceable>url</replaceable></arg>
|
||||
<arg><replaceable>hash</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
<para>The command <command>nix-prefetch-url</command> downloads the
|
||||
file referenced by the URL <replaceable>url</replaceable>, prints its
|
||||
cryptographic hash, and copies it into the Nix store. The file name
|
||||
in the store is
|
||||
<filename><replaceable>hash</replaceable>-<replaceable>baseName</replaceable></filename>,
|
||||
where <replaceable>baseName</replaceable> is everything following the
|
||||
final slash in <replaceable>url</replaceable>.</para>
|
||||
|
||||
<para>This command is just a convenience for Nix expression writers.
|
||||
Often a Nix expression fetches some source distribution from the
|
||||
network using the <literal>fetchurl</literal> expression contained in
|
||||
Nixpkgs. However, <literal>fetchurl</literal> requires a
|
||||
cryptographic hash. If you don't know the hash, you would have to
|
||||
download the file first, and then <literal>fetchurl</literal> would
|
||||
download it again when you build your Nix expression. Since
|
||||
<literal>fetchurl</literal> uses the same name for the downloaded file
|
||||
as <command>nix-prefetch-url</command>, the redundant download can be
|
||||
avoided.</para>
|
||||
|
||||
<para>If <replaceable>hash</replaceable> is specified, then a download
|
||||
is not performed if the Nix store already contains a file with the
|
||||
same hash and base name. Otherwise, the file is downloaded, and an
|
||||
error if signaled if the actual hash of the file does not match the
|
||||
specified hash.</para>
|
||||
|
||||
<para>This command prints the hash on standard output. Additionally,
|
||||
if the environment variable <envar>PRINT_PATH</envar> is set, the path
|
||||
of the downloaded file in the Nix store is also printed.</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Options</title>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><option>--type</option> <replaceable>hashAlgo</replaceable></term>
|
||||
|
||||
<listitem><para>Use the specified cryptographic hash algorithm,
|
||||
which can be one of <literal>md5</literal>,
|
||||
<literal>sha1</literal>, and
|
||||
<literal>sha256</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Examples</title>
|
||||
|
||||
<screen>
|
||||
$ nix-prefetch-url ftp://ftp.nluug.nl/pub/gnu/make/make-3.80.tar.bz2
|
||||
0bbd1df101bc0294d440471e50feca71
|
||||
|
||||
$ PRINT_PATH=1 nix-prefetch-url ftp://ftp.nluug.nl/pub/gnu/make/make-3.80.tar.bz2
|
||||
0bbd1df101bc0294d440471e50feca71
|
||||
/nix/store/wvyz8ifdn7wyz1p3pqyn0ra45ka2l492-make-3.80.tar.bz2</screen>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
</refentry>
|
||||
50
doc/manual/nix-pull.xml
Normal file
50
doc/manual/nix-pull.xml
Normal file
@@ -0,0 +1,50 @@
|
||||
<refentry xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xml:id="sec-nix-pull">
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>nix-pull</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
<refmiscinfo class="source">Nix</refmiscinfo>
|
||||
<refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>nix-pull</refname>
|
||||
<refpurpose>pull substitutes from a network cache</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>nix-pull</command>
|
||||
<arg choice='plain'><replaceable>url</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
<para>The command <command>nix-pull</command> obtains a list of
|
||||
pre-built store paths from the URL <replaceable>url</replaceable>, and
|
||||
for each of these store paths, registers a substitute derivation that
|
||||
downloads and unpacks it into the Nix store. This is used to speed up
|
||||
installations: if you attempt to install something that has already
|
||||
been built and stored into the network cache, Nix can transparently
|
||||
re-use the pre-built store paths.</para>
|
||||
|
||||
<para>The file at <replaceable>url</replaceable> must be compatible
|
||||
with the files created by <replaceable>nix-push</replaceable>.</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Examples</title>
|
||||
|
||||
<screen>
|
||||
$ nix-pull http://nix.cs.uu.nl/dist/nix/nixpkgs-0.5pre753/MANIFEST</screen>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
</refentry>
|
||||
391
doc/manual/nix-push.xml
Normal file
391
doc/manual/nix-push.xml
Normal file
@@ -0,0 +1,391 @@
|
||||
<refentry xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xml:id="sec-nix-push">
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>nix-push</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
<refmiscinfo class="source">Nix</refmiscinfo>
|
||||
<refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>nix-push</refname>
|
||||
<refpurpose>generate a binary cache</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>nix-push</command>
|
||||
<arg choice='plain'><option>--dest</option> <replaceable>dest-dir</replaceable></arg>
|
||||
<arg><option>--bzip2</option></arg>
|
||||
<arg><option>--force</option></arg>
|
||||
<arg><option>--link</option></arg>
|
||||
<arg><option>--manifest</option></arg>
|
||||
<arg><option>--manifest-path</option> <replaceable>filename</replaceable></arg>
|
||||
<arg><option>--url-prefix</option> <replaceable>url</replaceable></arg>
|
||||
<arg choice='plain' rep='repeat'><replaceable>paths</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
<para>The command <command>nix-push</command> produces a
|
||||
<emphasis>binary cache</emphasis>, a directory containing compressed
|
||||
Nix archives (NARs) plus some metadata of the closure of the specified
|
||||
store paths. This directory can then be made available through a web
|
||||
server to other Nix installations, allowing them to skip building from
|
||||
source and instead download binaries from the cache
|
||||
automatically.</para>
|
||||
|
||||
<para><command>nix-push</command> performs the following actions.
|
||||
|
||||
<orderedlist>
|
||||
|
||||
<listitem><para>Each path in <replaceable>paths</replaceable> is
|
||||
built (using <link
|
||||
linkend='rsec-nix-store-realise'><command>nix-store
|
||||
--realise</command></link>).</para></listitem>
|
||||
|
||||
<listitem><para>All paths in the closure of
|
||||
<replaceable>paths</replaceable> are determined (using
|
||||
<command>nix-store --query --requisites
|
||||
--include-outputs</command>). Note that since the
|
||||
<option>--include-outputs</option> flag is used, if
|
||||
<replaceable>paths</replaceable> includes a store derivation, you
|
||||
get a combined source/binary distribution (e.g., source tarballs
|
||||
will be included).</para></listitem>
|
||||
|
||||
<listitem><para>All store paths determined in the previous step are
|
||||
packaged into a NAR (using <command>nix-store --dump</command>) and
|
||||
compressed using <command>xz</command> or <command>bzip2</command>.
|
||||
The resulting files have the extension <filename>.nar.xz</filename>
|
||||
or <filename>.nar.bz2</filename>. Also for each store path, Nix
|
||||
generates a file with extension <filename>.narinfo</filename>
|
||||
containing metadata such as the references, cryptographic hash and
|
||||
size of each path.</para></listitem>
|
||||
|
||||
<listitem><para>Optionally, a single <emphasis>manifest</emphasis>
|
||||
file is created that contains the same metadata as the
|
||||
<filename>.narinfo</filename> files. This is for compatibility with
|
||||
Nix versions prior to 1.2 (see <command>nix-pull</command> for
|
||||
details).</para></listitem>
|
||||
|
||||
<listitem><para>A file named <option>nix-cache-info</option> is
|
||||
placed in the destination directory. The existence of this file
|
||||
marks the directory as a binary cache.</para></listitem>
|
||||
|
||||
</orderedlist>
|
||||
|
||||
</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Options</title>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><option>--dest</option> <replaceable>dest-dir</replaceable></term>
|
||||
|
||||
<listitem><para>Set the destination directory to
|
||||
<replaceable>dir</replaceable>, which is created if it does not
|
||||
exist. This flag is required.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--bzip2</option></term>
|
||||
|
||||
<listitem><para>Compress NARs using <command>bzip2</command>
|
||||
instead of <command>xz -9</command>. The latter compresses about
|
||||
30% better on typical archives, decompresses about twice as fast,
|
||||
but compresses a lot slower and is not supported by Nix prior to
|
||||
version 1.2.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--force</option></term>
|
||||
|
||||
<listitem><para>Overwrite <filename>.narinfo</filename> files if
|
||||
they already exist.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--link</option></term>
|
||||
|
||||
<listitem><para>By default, NARs are generated in the Nix store
|
||||
and then copied to <replaceable>dest-dir</replaceable>. If this
|
||||
option is given, hard links are used instead. This only works if
|
||||
<replaceable>dest-dir</replaceable> is on the same filesystem as
|
||||
the Nix store.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--manifest</option></term>
|
||||
|
||||
<listitem><para>Force the generation of a manifest suitable for
|
||||
use by <command>nix-pull</command>. The manifest is stored as
|
||||
<filename><replaceable>dest-dir</replaceable>/MANIFEST</filename>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--manifest-path</option> <replaceable>filename</replaceable></term>
|
||||
|
||||
<listitem><para>Like <option>--manifest</option>, but store the
|
||||
manifest in <replaceable>filename</replaceable>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--url-prefix</option> <replaceable>url</replaceable></term>
|
||||
|
||||
<listitem><para>Manifests are expected to contain the absolute
|
||||
URLs of NARs. For generating these URLs, the prefix
|
||||
<replaceable>url</replaceable> is used. It defaults to
|
||||
<uri>file://<replaceable>dest-dir</replaceable></uri>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Examples</title>
|
||||
|
||||
<para>To add the closure of Thunderbird to a binary cache:
|
||||
|
||||
<screen>
|
||||
$ nix-push --dest /tmp/cache $(nix-build -A thunderbird)
|
||||
</screen>
|
||||
|
||||
Assuming that <filename>/tmp/cache</filename> is exported by a web
|
||||
server as <uri>http://example.org/cache</uri>, you can then use this
|
||||
cache on another machine to speed up the installation of Thunderbird:
|
||||
|
||||
<screen>
|
||||
$ nix-build -A thunderbird --option binary-caches http://example.org/cache
|
||||
</screen>
|
||||
|
||||
Alternatively, you could add <literal>binary-caches =
|
||||
http://example.org/cache</literal> to
|
||||
<filename>nix.conf</filename>.</para>
|
||||
|
||||
<para>To also include build-time dependencies (such as source
|
||||
tarballs):
|
||||
|
||||
<screen>
|
||||
$ nix-push --dest /tmp/cache $(nix-instantiate -A thunderbird)
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>To generate a manifest suitable for <command>nix-pull</command>:
|
||||
|
||||
<screen>
|
||||
$ nix-push --dest /tmp/cache $(nix-build -A thunderbird) --manifest
|
||||
</screen>
|
||||
|
||||
On another machine you can then do:
|
||||
|
||||
<screen>
|
||||
$ nix-pull http://example.org/cache
|
||||
</screen>
|
||||
|
||||
to cause the binaries to be used by subsequent Nix operations.</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
<refsection><title>Binary cache format and operation</title>
|
||||
|
||||
<para>A binary cache with URL <replaceable>url</replaceable> only
|
||||
denotes a valid binary cache if the file
|
||||
<uri><replaceable>url</replaceable>/nix-cache-info</uri> exists. If
|
||||
this file does not exist (or cannot be downloaded), the cache is
|
||||
ignored. If it does exist, it must be a text file containing cache
|
||||
properties. Here’s an example:
|
||||
|
||||
<screen>
|
||||
StoreDir: /nix/store
|
||||
WantMassQuery: 1
|
||||
Priority: 10
|
||||
</screen>
|
||||
|
||||
The properties that are currently supported are:
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><literal>StoreDir</literal></term>
|
||||
|
||||
<listitem><para>The path of the Nix store to which this binary
|
||||
cache applies. Binaries are not relocatable — a binary built for
|
||||
<filename>/nix/store</filename> won’t generally work in
|
||||
<filename>/home/alice/store</filename> — so to prevent binaries
|
||||
from being used in a wrong store, a binary cache is only used if
|
||||
its <literal>StoreDir</literal> matches the local Nix
|
||||
configuration. The default is
|
||||
<filename>/nix/store</filename>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>WantMassQuery</literal></term>
|
||||
|
||||
<listitem><para>Query operations such as <command>nix-env
|
||||
-qas</command> can cause thousands of cache queries, and thus
|
||||
thousands of HTTP requests, to determine which packages are
|
||||
available in binary form. While these requests are small, not
|
||||
every server may appreciate a potential onslaught of queries. If
|
||||
<literal>WantMassQuery</literal> is set to <literal>0</literal>
|
||||
(default), “mass queries” such as <command>nix-env -qas</command>
|
||||
will skip this cache. Thus a package may appear not to have a
|
||||
binary substitute. However, the binary will still be used when
|
||||
you actually install the package. If
|
||||
<literal>WantMassQuery</literal> is set to <literal>1</literal>,
|
||||
mass queries will use this cache.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>Priority</literal></term>
|
||||
|
||||
<listitem><para>Each binary cache has a priority (defaulting to
|
||||
50). Binary caches are checked for binaries in order of ascending
|
||||
priority; thus a higher number denotes a lower priority. The
|
||||
binary cache <uri>http://nixos.org/binary-cache</uri> has priority
|
||||
40.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Every time Nix needs to build some store path
|
||||
<replaceable>p</replaceable>, it will check each configured binary
|
||||
cache to see if it has a NAR file for <replaceable>p</replaceable>,
|
||||
until it finds one. If no cache has a NAR, Nix will fall back to
|
||||
building the path from source (if applicable). To see if a cache with
|
||||
URL <replaceable>url</replaceable> has a binary for
|
||||
<replaceable>p</replaceable>, Nix fetches
|
||||
<replaceable>url/h</replaceable>, where <replaceable>h</replaceable>
|
||||
is the hash part of <replaceable>p</replaceable>. Thus, if we have a
|
||||
cache <uri>http://nixos.org/binary-cache</uri> and we want to obtain
|
||||
the store path
|
||||
<screen>
|
||||
/nix/store/a8922c0h87iilxzzvwn2hmv8x210aqb9-glibc-2.7
|
||||
</screen>
|
||||
then Nix will attempt to fetch
|
||||
<screen>
|
||||
http://nixos.org/binary-cache/a8922c0h87iilxzzvwn2hmv8x210aqb9.narinfo
|
||||
</screen>
|
||||
(Commands such as <command>nix-env -qas</command> will issue an HTTP
|
||||
HEAD request, since it only needs to know if the
|
||||
<filename>.narinfo</filename> file exists.) The
|
||||
<filename>.narinfo</filename> file is a simple text file that looks
|
||||
like this:
|
||||
|
||||
<screen>
|
||||
StorePath: /nix/store/a8922c0h87iilxzzvwn2hmv8x210aqb9-glibc-2.7
|
||||
URL: nar/0zzjpdz46mdn74v09m053yczlz4am038g8r74iy8w43gx8801h70.nar.bz2
|
||||
Compression: bzip2
|
||||
FileHash: sha256:0zzjpdz46mdn74v09m053yczlz4am038g8r74iy8w43gx8801h70
|
||||
FileSize: 24473768
|
||||
NarHash: sha256:0s491y1h9hxj5ghiizlxk7ax6jwbha00zwn7lpyd5xg5bhf60vzg
|
||||
NarSize: 109521136
|
||||
References: 2ma2k0ys8knh4an48n28vigcmc2z8773-linux-headers-2.6.23.16 ...
|
||||
Deriver: 7akyyc87ka32xwmqza9dvyg5pwx3j212-glibc-2.7.drv
|
||||
</screen>
|
||||
|
||||
The fields are as follows:
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><literal>StorePath</literal></term>
|
||||
|
||||
<listitem><para>The full store path, including the name part
|
||||
(e.g., <literal>glibc-2.7</literal>). It must match the
|
||||
requested store path.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>URL</literal></term>
|
||||
|
||||
<listitem><para>The URL of the NAR, relative to the binary cache
|
||||
URL.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>Compression</literal></term>
|
||||
|
||||
<listitem><para>The compression method; either
|
||||
<literal>xz</literal> or
|
||||
<literal>bzip2</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>FileHash</literal></term>
|
||||
|
||||
<listitem><para>The SHA-256 hash of the compressed
|
||||
NAR.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>FileSize</literal></term>
|
||||
|
||||
<listitem><para>The size of the compressed NAR.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>NarHash</literal></term>
|
||||
|
||||
<listitem><para>The SHA-256 hash of the uncompressed NAR. This is
|
||||
equal to the hash of the store path as returned by
|
||||
<command>nix-store -q --hash
|
||||
<replaceable>p</replaceable></command>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>NarSize</literal></term>
|
||||
|
||||
<listitem><para>The size of the uncompressed NAR.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>References</literal></term>
|
||||
|
||||
<listitem><para>The references of the store path, without the Nix
|
||||
store prefix.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>Deriver</literal></term>
|
||||
|
||||
<listitem><para>The deriver of the store path, without the Nix
|
||||
store prefix. This field is optional.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>System</literal></term>
|
||||
|
||||
<listitem><para>The Nix platform type of this binary, if known.
|
||||
This field is optional.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Thus, in our example, after recursively ensuring that the
|
||||
references exist (e.g.,
|
||||
<filename>/nix/store/2ma2k0ys8knh4an48n28vigcmc2z8773-linux-headers-2.6.23.16</filename>),
|
||||
Nix will fetch <screen>
|
||||
http://nixos.org/binary-cache/nar/0zzjpdz46mdn74v09m053yczlz4am038g8r74iy8w43gx8801h70.nar.bz2
|
||||
</screen> and decompress and unpack it to
|
||||
<filename>/nix/store/a8922c0h87iilxzzvwn2hmv8x210aqb9-glibc-2.7</filename>.</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
</refentry>
|
||||
1342
doc/manual/nix-store.xml
Normal file
1342
doc/manual/nix-store.xml
Normal file
File diff suppressed because it is too large
Load Diff
47
doc/manual/opt-common-syn.xml
Normal file
47
doc/manual/opt-common-syn.xml
Normal file
@@ -0,0 +1,47 @@
|
||||
<nop xmlns="http://docbook.org/ns/docbook">
|
||||
|
||||
<arg><option>--help</option></arg>
|
||||
<arg><option>--version</option></arg>
|
||||
<arg rep='repeat'><option>--verbose</option></arg>
|
||||
<arg rep='repeat'><option>-v</option></arg>
|
||||
<arg><option>--no-build-output</option></arg>
|
||||
<arg><option>-Q</option></arg>
|
||||
<arg>
|
||||
<group choice='req'>
|
||||
<arg choice='plain'><option>--max-jobs</option></arg>
|
||||
<arg choice='plain'><option>-j</option></arg>
|
||||
</group>
|
||||
<replaceable>number</replaceable>
|
||||
</arg>
|
||||
<arg>
|
||||
<option>--cores</option>
|
||||
<replaceable>number</replaceable>
|
||||
</arg>
|
||||
<arg>
|
||||
<option>--max-silent-time</option>
|
||||
<replaceable>number</replaceable>
|
||||
</arg>
|
||||
<arg>
|
||||
<option>--timeout</option>
|
||||
<replaceable>number</replaceable>
|
||||
</arg>
|
||||
<arg><option>--keep-going</option></arg>
|
||||
<arg><option>-k</option></arg>
|
||||
<arg><option>--keep-failed</option></arg>
|
||||
<arg><option>-K</option></arg>
|
||||
<arg><option>--fallback</option></arg>
|
||||
<arg><option>--readonly-mode</option></arg>
|
||||
<arg><option>--log-type</option> <replaceable>type</replaceable></arg>
|
||||
<arg><option>--show-trace</option></arg>
|
||||
<arg>
|
||||
<option>-I</option>
|
||||
<replaceable>path</replaceable>
|
||||
</arg>
|
||||
<arg>
|
||||
<option>--option</option>
|
||||
<replaceable>name</replaceable>
|
||||
<replaceable>value</replaceable>
|
||||
</arg>
|
||||
<sbr />
|
||||
|
||||
</nop>
|
||||
378
doc/manual/opt-common.xml
Normal file
378
doc/manual/opt-common.xml
Normal file
@@ -0,0 +1,378 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook" xml:id="sec-common-options">
|
||||
|
||||
<title>Common options</title>
|
||||
|
||||
|
||||
<para>Most Nix commands accept the following command-line options:</para>
|
||||
|
||||
<variablelist xml:id="opt-common">
|
||||
|
||||
<varlistentry><term><option>--help</option></term>
|
||||
|
||||
<listitem><para>Prints out a summary of the command syntax and
|
||||
exits.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><option>--version</option></term>
|
||||
|
||||
<listitem><para>Prints out the Nix version number on standard output
|
||||
and exits.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><option>--verbose</option></term>
|
||||
<term><option>-v</option></term>
|
||||
|
||||
<listitem>
|
||||
|
||||
<para>Increases the level of verbosity of diagnostic messages
|
||||
printed on standard error. For each Nix operation, the information
|
||||
printed on standard output is well-defined; any diagnostic
|
||||
information is printed on standard error, never on standard
|
||||
output.</para>
|
||||
|
||||
<para>This option may be specified repeatedly. Currently, the
|
||||
following verbosity levels exist:</para>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term>0</term>
|
||||
<listitem><para>“Errors only”: only print messages
|
||||
explaining why the Nix invocation failed.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term>1</term>
|
||||
<listitem><para>“Informational”: print
|
||||
<emphasis>useful</emphasis> messages about what Nix is doing.
|
||||
This is the default.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term>2</term>
|
||||
<listitem><para>“Talkative”: print more informational
|
||||
messages.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term>3</term>
|
||||
<listitem><para>“Chatty”: print even more
|
||||
informational messages.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term>4</term>
|
||||
<listitem><para>“Debug”: print debug
|
||||
information.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term>5</term>
|
||||
<listitem><para>“Vomit”: print vast amounts of debug
|
||||
information.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><option>--no-build-output</option></term>
|
||||
<term><option>-Q</option></term>
|
||||
|
||||
<listitem><para>By default, output written by builders to standard
|
||||
output and standard error is echoed to the Nix command's standard
|
||||
error. This option suppresses this behaviour. Note that the
|
||||
builder's standard output and error are always written to a log file
|
||||
in
|
||||
<filename><replaceable>prefix</replaceable>/nix/var/log/nix</filename>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="opt-max-jobs"><term><option>--max-jobs</option></term>
|
||||
<term><option>-j</option></term>
|
||||
|
||||
<listitem><para>Sets the maximum number of build jobs that Nix will
|
||||
perform in parallel to the specified number. The default is
|
||||
specified by the <link
|
||||
linkend='conf-build-max-jobs'><literal>build-max-jobs</literal></link>
|
||||
configuration setting, which itself defaults to
|
||||
<literal>1</literal>. A higher value is useful on SMP systems or to
|
||||
exploit I/O latency.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="opt-cores"><term><option>--cores</option></term>
|
||||
|
||||
<listitem><para>Sets the value of the <envar>NIX_BUILD_CORES</envar>
|
||||
environment variable in the invocation of builders. Builders can
|
||||
use this variable at their discretion to control the maximum amount
|
||||
of parallelism. For instance, in Nixpkgs, if the derivation
|
||||
attribute <varname>enableParallelBuilding</varname> is set to
|
||||
<literal>true</literal>, the builder passes the
|
||||
<option>-j<replaceable>N</replaceable></option> flag to GNU Make.
|
||||
It defaults to the value of the <link
|
||||
linkend='conf-build-cores'><literal>build-cores</literal></link>
|
||||
configuration setting, if set, or <literal>1</literal> otherwise.
|
||||
The value <literal>0</literal> means that the builder should use all
|
||||
available CPU cores in the system.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="opt-max-silent-time"><term><option>--max-silent-time</option></term>
|
||||
|
||||
<listitem><para>Sets the maximum number of seconds that a builder
|
||||
can go without producing any data on standard output or standard
|
||||
error. The default is specified by the <link
|
||||
linkend='conf-build-max-silent-time'><literal>build-max-silent-time</literal></link>
|
||||
configuration setting. <literal>0</literal> means no
|
||||
time-out.</para></listitem>
|
||||
|
||||
</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>
|
||||
|
||||
<listitem><para>Keep going in case of failed builds, to the
|
||||
greatest extent possible. That is, if building an input of some
|
||||
derivation fails, Nix will still build the other inputs, but not the
|
||||
derivation itself. Without this option, Nix stops if any build
|
||||
fails (except for builds of substitutes), possibly killing builds in
|
||||
progress (in case of parallel or distributed builds).</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><option>--keep-failed</option></term>
|
||||
<term><option>-K</option></term>
|
||||
|
||||
<listitem><para>Specifies that in case of a build failure, the
|
||||
temporary directory (usually in <filename>/tmp</filename>) in which
|
||||
the build takes place should not be deleted. The path of the build
|
||||
directory is printed as an informational message.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><option>--fallback</option></term>
|
||||
|
||||
<listitem>
|
||||
|
||||
<para>Whenever Nix attempts to build a derivation for which
|
||||
substitutes are known for each output path, but realising the output
|
||||
paths through the substitutes fails, fall back on building the
|
||||
derivation.</para>
|
||||
|
||||
<para>The most common scenario in which this is useful is when we
|
||||
have registered substitutes in order to perform binary distribution
|
||||
from, say, a network repository. If the repository is down, the
|
||||
realisation of the derivation will fail. When this option is
|
||||
specified, Nix will build the derivation instead. Thus,
|
||||
installation from binaries falls back on nstallation from source.
|
||||
This option is not the default since it is generally not desirable
|
||||
for a transient failure in obtaining the substitutes to lead to a
|
||||
full build from source (with the related consumption of
|
||||
resources).</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><option>--readonly-mode</option></term>
|
||||
|
||||
<listitem><para>When this option is used, no attempt is made to open
|
||||
the Nix database. Most Nix operations do need database access, so
|
||||
those operations will fail.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="opt-log-type"><term><option>--log-type</option>
|
||||
<replaceable>type</replaceable></term>
|
||||
|
||||
<listitem>
|
||||
|
||||
<para>This option determines how the output written to standard
|
||||
error is formatted. Nix’s diagnostic messages are typically
|
||||
<emphasis>nested</emphasis>. For instance, when tracing Nix
|
||||
expression evaluation (<command>nix-env -vvvvv</command>, messages
|
||||
from subexpressions are nested inside their parent expressions. Nix
|
||||
builder output is also often nested. For instance, the Nix Packages
|
||||
generic builder nests the various build tasks (unpack, configure,
|
||||
compile, etc.), and the GNU Make in <literal>stdenv-linux</literal>
|
||||
has been patched to provide nesting for recursive Make
|
||||
invocations.</para>
|
||||
|
||||
<para><replaceable>type</replaceable> can be one of the
|
||||
following:
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><literal>pretty</literal></term>
|
||||
|
||||
<listitem><para>Pretty-print the output, indicating different
|
||||
nesting levels using spaces. This is the
|
||||
default.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>escapes</literal></term>
|
||||
|
||||
<listitem><para>Indicate nesting using escape codes that can be
|
||||
interpreted by the <command>nix-log2xml</command> tool in the
|
||||
Nix source distribution. The resulting XML file can be fed into
|
||||
the <command>log2html.xsl</command> stylesheet to create an HTML
|
||||
file that can be browsed interactively, using Javascript to
|
||||
expand and collapse parts of the output.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>flat</literal></term>
|
||||
|
||||
<listitem><para>Remove all nesting.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><option>--arg</option> <replaceable>name</replaceable> <replaceable>value</replaceable></term>
|
||||
|
||||
<listitem><para>This option is accepted by
|
||||
<command>nix-env</command>, <command>nix-instantiate</command> and
|
||||
<command>nix-build</command>. When evaluating Nix expressions, the
|
||||
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> }:
|
||||
<replaceable>...</replaceable></literal>). With
|
||||
<option>--arg</option>, you can also call functions that have
|
||||
arguments without a default value (or override a default value).
|
||||
That is, if the evaluator encounters a function with an argument
|
||||
named <replaceable>name</replaceable>, it will call it with value
|
||||
<replaceable>value</replaceable>.</para>
|
||||
|
||||
<para>For instance, the file
|
||||
<literal>pkgs/top-level/all-packages.nix</literal> in Nixpkgs is
|
||||
actually a function:
|
||||
|
||||
<programlisting>
|
||||
{ # The system (e.g., `i686-linux') for which to build the packages.
|
||||
system ? builtins.currentSystem
|
||||
<replaceable>...</replaceable>
|
||||
}: <replaceable>...</replaceable></programlisting>
|
||||
|
||||
So if you call this Nix expression (e.g., when you do
|
||||
<literal>nix-env -i <replaceable>pkgname</replaceable></literal>),
|
||||
the function will be called automatically using the value <link
|
||||
linkend='builtin-currentSystem'><literal>builtins.currentSystem</literal></link>
|
||||
for the <literal>system</literal> argument. You can override this
|
||||
using <option>--arg</option>, e.g., <literal>nix-env -i
|
||||
<replaceable>pkgname</replaceable> --arg system
|
||||
\"i686-freebsd\"</literal>. (Note that since the argument is a Nix
|
||||
string literal, you have to escape the quotes.)</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><option>--argstr</option> <replaceable>name</replaceable> <replaceable>value</replaceable></term>
|
||||
|
||||
<listitem><para>This option is like <option>--arg</option>, only the
|
||||
value is not a Nix expression but a string. So instead of
|
||||
<literal>--arg system \"i686-linux\"</literal> (the outer quotes are
|
||||
to keep the shell happy) you can say <literal>--argstr system
|
||||
i686-linux</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="opt-attr"><term><option>--attr</option> / <option>-A</option>
|
||||
<replaceable>attrPath</replaceable></term>
|
||||
|
||||
<listitem><para>In <command>nix-env</command>,
|
||||
<command>nix-instantiate</command> and <command>nix-build</command>,
|
||||
<option>--attr</option> allows you to select an attribute from the
|
||||
top-level Nix expression being evaluated. The <emphasis>attribute
|
||||
path</emphasis> <replaceable>attrPath</replaceable> is a sequence of
|
||||
attribute names separated by dots. For instance, given a top-level
|
||||
Nix expression <replaceable>e</replaceable>, the attribute path
|
||||
<literal>xorg.xorgserver</literal> would cause the expression
|
||||
<literal><replaceable>e</replaceable>.xorg.xorgserver</literal> to
|
||||
be used. See <link
|
||||
linkend='refsec-nix-env-install-examples'><command>nix-env
|
||||
--install</command></link> for some concrete examples.</para>
|
||||
|
||||
<para>In addition to attribute names, you can also specify array
|
||||
indices. For instance, the attribute path
|
||||
<literal>foo.3.bar</literal> selects the <literal>bar</literal>
|
||||
attribute of the fourth element of the array in the
|
||||
<literal>foo</literal> attribute of the top-level
|
||||
expression.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><option>--show-trace</option></term>
|
||||
|
||||
<listitem><para>Causes Nix to print out a stack trace in case of Nix
|
||||
expression evaluation errors.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><option>-I</option> <replaceable>path</replaceable></term>
|
||||
|
||||
<listitem><para>Add a path to the Nix expression search path. See
|
||||
the <envar>NIX_PATH</envar> environment variable for details. Paths
|
||||
added through <option>-I</option> take precedence over
|
||||
<envar>NIX_PATH</envar>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><option>--option</option> <replaceable>name</replaceable> <replaceable>value</replaceable></term>
|
||||
|
||||
<listitem><para>Set the Nix configuration option
|
||||
<replaceable>name</replaceable> to <replaceable>value</replaceable>.
|
||||
This overrides settings in the Nix configuration file (see
|
||||
<citerefentry><refentrytitle>nix.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>).</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><option>--repair</option></term>
|
||||
|
||||
<listitem><para>Fix corrupted or missing store paths by
|
||||
redownloading or rebuilding them. Note that this is slow because it
|
||||
requires computing a cryptographic hash of the contents of every
|
||||
path in the closure of the build. Also note the warning under
|
||||
<command>nix-store --repair-path</command>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
</variablelist>
|
||||
|
||||
|
||||
</section>
|
||||
22
doc/manual/opt-inst-syn.xml
Normal file
22
doc/manual/opt-inst-syn.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<nop xmlns="http://docbook.org/ns/docbook">
|
||||
|
||||
<arg>
|
||||
<group choice='req'>
|
||||
<arg choice='plain'><option>--prebuilt-only</option></arg>
|
||||
<arg choice='plain'><option>-b</option></arg>
|
||||
</group>
|
||||
</arg>
|
||||
|
||||
<arg>
|
||||
<group choice='req'>
|
||||
<arg choice='plain'><option>--attr</option></arg>
|
||||
<arg choice='plain'><option>-A</option></arg>
|
||||
</group>
|
||||
</arg>
|
||||
|
||||
<arg><option>--from-expression</option></arg>
|
||||
<arg><option>-E</option></arg>
|
||||
|
||||
<arg><option>--from-profile</option> <replaceable>path</replaceable></arg>
|
||||
|
||||
</nop>
|
||||
591
doc/manual/package-management.xml
Normal file
591
doc/manual/package-management.xml
Normal file
@@ -0,0 +1,591 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id='chap-package-management'>
|
||||
|
||||
<title>Package Management</title>
|
||||
|
||||
|
||||
<para>This chapter discusses how to do package management with Nix,
|
||||
i.e., how to obtain, install, upgrade, and erase packages. This is
|
||||
the “user’s” perspective of the Nix system — people
|
||||
who want to <emphasis>create</emphasis> packages should consult
|
||||
<xref linkend='chap-writing-nix-expressions' />.</para>
|
||||
|
||||
|
||||
<section><title>Basic package management</title>
|
||||
|
||||
<para>The main command for package management is <link
|
||||
linkend="sec-nix-env"><command>nix-env</command></link>. You can use
|
||||
it to install, upgrade, and erase packages, and to query what
|
||||
packages are installed or are available for installation.</para>
|
||||
|
||||
<para>In Nix, different users can have different “views”
|
||||
on the set of installed applications. That is, there might be lots of
|
||||
applications present on the system (possibly in many different
|
||||
versions), but users can have a specific selection of those active —
|
||||
where “active” just means that it appears in a directory
|
||||
in the user’s <envar>PATH</envar>. Such a view on the set of
|
||||
installed applications is called a <emphasis>user
|
||||
environment</emphasis>, which is just a directory tree consisting of
|
||||
symlinks to the files of the active applications. </para>
|
||||
|
||||
<para>Components are installed from a set of <emphasis>Nix
|
||||
expressions</emphasis> that tell Nix how to build those packages,
|
||||
including, if necessary, their dependencies. There is a collection of
|
||||
Nix expressions called the Nix Package collection that contains
|
||||
packages ranging from basic development stuff such as GCC and Glibc,
|
||||
to end-user applications like Mozilla Firefox. (Nix is however not
|
||||
tied to the Nix Package collection; you could write your own Nix
|
||||
expressions based on it, or completely new ones.) You can download
|
||||
the latest version from <link
|
||||
xlink:href='http://nixos.org/nixpkgs/download.html' />.</para>
|
||||
|
||||
<para>Assuming that you have downloaded and unpacked a release of Nix
|
||||
Packages, you can view the set of available packages in the release:
|
||||
|
||||
<screen>
|
||||
$ nix-env -qaf nixpkgs-<replaceable>version</replaceable> '*'
|
||||
ant-blackdown-1.4.2
|
||||
aterm-2.2
|
||||
bash-3.0
|
||||
binutils-2.15
|
||||
bison-1.875d
|
||||
blackdown-1.4.2
|
||||
bzip2-1.0.2
|
||||
...</screen>
|
||||
|
||||
where <literal>nixpkgs-<replaceable>version</replaceable></literal> is
|
||||
where you’ve unpacked the release. The flag <option>-q</option>
|
||||
specifies a query operation; <option>-a</option> means that you want
|
||||
to show the “available” (i.e., installable) packages, as opposed to
|
||||
the installed packages; and <option>-f</option>
|
||||
<filename>nixpkgs-<replaceable>version</replaceable></filename>
|
||||
specifies the source of the packages. The argument
|
||||
<literal>'*'</literal> shows all installable packages. (The quotes are
|
||||
necessary to prevent shell expansion.) You can also select specific
|
||||
packages by name:
|
||||
|
||||
<screen>
|
||||
$ nix-env -qaf nixpkgs-<replaceable>version</replaceable> gcc
|
||||
gcc-3.4.6
|
||||
gcc-4.0.3
|
||||
gcc-4.1.1</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>It is also possible to see the <emphasis>status</emphasis> of
|
||||
available packages, i.e., whether they are installed into the user
|
||||
environment and/or present in the system:
|
||||
|
||||
<screen>
|
||||
$ nix-env -qasf nixpkgs-<replaceable>version</replaceable> '*'
|
||||
...
|
||||
-PS bash-3.0
|
||||
--S binutils-2.15
|
||||
IPS bison-1.875d
|
||||
...</screen>
|
||||
|
||||
The first character (<literal>I</literal>) indicates whether the
|
||||
package is installed in your current user environment. The second
|
||||
(<literal>P</literal>) indicates whether it is present on your system
|
||||
(in which case installing it into your user environment would be a
|
||||
very quick operation). The last one (<literal>S</literal>) indicates
|
||||
whether there is a so-called <emphasis>substitute</emphasis> for the
|
||||
package, which is Nix’s mechanism for doing binary deployment. It
|
||||
just means that Nix knows that it can fetch a pre-built package from
|
||||
somewhere (typically a network server) instead of building it
|
||||
locally.</para>
|
||||
|
||||
<para>So now that we have a set of Nix expressions we can build the
|
||||
packages contained in them. This is done using <literal>nix-env
|
||||
-i</literal>. For instance,
|
||||
|
||||
<screen>
|
||||
$ nix-env -f nixpkgs-<replaceable>version</replaceable> -i subversion</screen>
|
||||
|
||||
will install the package called <literal>subversion</literal> (which
|
||||
is, of course, the <link
|
||||
xlink:href='http://subversion.tigris.org/'>Subversion version
|
||||
management system</link>).</para>
|
||||
|
||||
<para>When you do this for the first time, Nix will start building
|
||||
Subversion and all its dependencies. This will take quite a while —
|
||||
typically an hour or two on modern machines. Fortunately, there is a
|
||||
faster way (so do a Ctrl-C on that install operation!): you just need
|
||||
to tell Nix that pre-built binaries of all those packages are
|
||||
available somewhere. This is done using the
|
||||
<command>nix-pull</command> command, which must be supplied with a URL
|
||||
containing a <emphasis>manifest</emphasis> describing what binaries
|
||||
are available. This URL should correspond to the Nix Packages release
|
||||
that you’re using. For instance, if you obtained a release from <link
|
||||
xlink:href='http://nixos.org/releases/nixpkgs/nixpkgs-0.12pre11712-4lrp7j8x'
|
||||
/>, then you should do:
|
||||
|
||||
<screen>
|
||||
$ nix-pull http://nixos.org/releases/nixpkgs/nixpkgs-0.12pre11712-4lrp7j8x/MANIFEST</screen>
|
||||
|
||||
If you then issue the installation command, it should start
|
||||
downloading binaries from <systemitem
|
||||
class='fqdomainname'>nixos.org</systemitem>, instead of building
|
||||
them from source. This might still take a while since all
|
||||
dependencies must be downloaded, but on a reasonably fast connection
|
||||
such as an DSL line it’s on the order of a few minutes.</para>
|
||||
|
||||
<para>Naturally, packages can also be uninstalled:
|
||||
|
||||
<screen>
|
||||
$ nix-env -e subversion</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Upgrading to a new version is just as easy. If you have a new
|
||||
release of Nix Packages, you can do:
|
||||
|
||||
<screen>
|
||||
$ nix-env -f nixpkgs-<replaceable>version</replaceable> -u subversion</screen>
|
||||
|
||||
This will <emphasis>only</emphasis> upgrade Subversion if there is a
|
||||
“newer” version in the new set of Nix expressions, as
|
||||
defined by some pretty arbitrary rules regarding ordering of version
|
||||
numbers (which generally do what you’d expect of them). To just
|
||||
unconditionally replace Subversion with whatever version is in the Nix
|
||||
expressions, use <parameter>-i</parameter> instead of
|
||||
<parameter>-u</parameter>; <parameter>-i</parameter> will remove
|
||||
whatever version is already installed.</para>
|
||||
|
||||
<para>You can also upgrade all packages for which there are newer
|
||||
versions:
|
||||
|
||||
<screen>
|
||||
$ nix-env -f nixpkgs-<replaceable>version</replaceable> -u '*'</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Sometimes it’s useful to be able to ask what
|
||||
<command>nix-env</command> would do, without actually doing it. For
|
||||
instance, to find out what packages would be upgraded by
|
||||
<literal>nix-env -u '*'</literal>, you can do
|
||||
|
||||
<screen>
|
||||
$ nix-env ... -u '*' --dry-run
|
||||
(dry run; not doing anything)
|
||||
upgrading `libxslt-1.1.0' to `libxslt-1.1.10'
|
||||
upgrading `graphviz-1.10' to `graphviz-1.12'
|
||||
upgrading `coreutils-5.0' to `coreutils-5.2.1'</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-profiles"><title>Profiles</title>
|
||||
|
||||
<para>Profiles and user environments are Nix’s mechanism for
|
||||
implementing the ability to allow different users to have different
|
||||
configurations, and to do atomic upgrades and rollbacks. To
|
||||
understand how they work, it’s useful to know a bit about how Nix
|
||||
works. In Nix, packages are stored in unique locations in the
|
||||
<emphasis>Nix store</emphasis> (typically,
|
||||
<filename>/nix/store</filename>). For instance, a particular version
|
||||
of the Subversion package might be stored in a directory
|
||||
<filename>/nix/store/dpmvp969yhdqs7lm2r1a3gng7pyq6vy4-subversion-1.1.3/</filename>,
|
||||
while another version might be stored in
|
||||
<filename>/nix/store/5mq2jcn36ldlmh93yj1n8s9c95pj7c5s-subversion-1.1.2</filename>.
|
||||
The long strings prefixed to the directory names are cryptographic
|
||||
hashes<footnote><para>160-bit truncations of SHA-256 hashes encoded in
|
||||
a base-32 notation, to be precise.</para></footnote> of
|
||||
<emphasis>all</emphasis> inputs involved in building the package —
|
||||
sources, dependencies, compiler flags, and so on. So if two
|
||||
packages differ in any way, they end up in different locations in
|
||||
the file system, so they don’t interfere with each other. <xref
|
||||
linkend='fig-user-environments' /> shows a part of a typical Nix
|
||||
store.</para>
|
||||
|
||||
<figure xml:id='fig-user-environments'><title>User environments</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref='figures/user-environments.png' format='PNG' />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</figure>
|
||||
|
||||
<para>Of course, you wouldn’t want to type
|
||||
|
||||
<screen>
|
||||
$ /nix/store/dpmvp969yhdq...-subversion-1.1.3/bin/svn</screen>
|
||||
|
||||
every time you want to run Subversion. Of course we could set up the
|
||||
<envar>PATH</envar> environment variable to include the
|
||||
<filename>bin</filename> directory of every package we want to use,
|
||||
but this is not very convenient since changing <envar>PATH</envar>
|
||||
doesn’t take effect for already existing processes. The solution Nix
|
||||
uses is to create directory trees of symlinks to
|
||||
<emphasis>activated</emphasis> packages. These are called
|
||||
<emphasis>user environments</emphasis> and they are packages
|
||||
themselves (though automatically generated by
|
||||
<command>nix-env</command>), so they too reside in the Nix store. For
|
||||
instance, in <xref linkend='fig-user-environments' /> the user
|
||||
environment <filename>/nix/store/5mq2jcn36ldl...-user-env</filename>
|
||||
contains a symlink to just Subversion 1.1.2 (arrows in the figure
|
||||
indicate symlinks). This would be what we would obtain if we had done
|
||||
|
||||
<screen>
|
||||
$ nix-env -i subversion</screen>
|
||||
|
||||
on a set of Nix expressions that contained Subversion 1.1.2.</para>
|
||||
|
||||
<para>This doesn’t in itself solve the problem, of course; you
|
||||
wouldn’t want to type
|
||||
<filename>/nix/store/0c1p5z4kda11...-user-env/bin/svn</filename>
|
||||
either. That’s why there are symlinks outside of the store that point
|
||||
to the user environments in the store; for instance, the symlinks
|
||||
<filename>default-42-link</filename> and
|
||||
<filename>default-43-link</filename> in the example. These are called
|
||||
<emphasis>generations</emphasis> since every time you perform a
|
||||
<command>nix-env</command> operation, a new user environment is
|
||||
generated based on the current one. For instance, generation 43 was
|
||||
created from generation 42 when we did
|
||||
|
||||
<screen>
|
||||
$ nix-env -i subversion mozilla</screen>
|
||||
|
||||
on a set of Nix expressions that contained Mozilla and a new version
|
||||
of Subversion.</para>
|
||||
|
||||
<para>Generations are grouped together into
|
||||
<emphasis>profiles</emphasis> so that different users don’t interfere
|
||||
with each other if they don’t want to. For example:
|
||||
|
||||
<screen>
|
||||
$ ls -l /nix/var/nix/profiles/
|
||||
...
|
||||
lrwxrwxrwx 1 eelco ... default-42-link -> /nix/store/0c1p5z4kda11...-user-env
|
||||
lrwxrwxrwx 1 eelco ... default-43-link -> /nix/store/3aw2pdyx2jfc...-user-env
|
||||
lrwxrwxrwx 1 eelco ... default -> default-43-link</screen>
|
||||
|
||||
This shows a profile called <filename>default</filename>. The file
|
||||
<filename>default</filename> itself is actually a symlink that points
|
||||
to the current generation. When we do a <command>nix-env</command>
|
||||
operation, a new user environment and generation link are created
|
||||
based on the current one, and finally the <filename>default</filename>
|
||||
symlink is made to point at the new generation. This last step is
|
||||
atomic on Unix, which explains how we can do atomic upgrades. (Note
|
||||
that the building/installing of new packages doesn’t interfere in
|
||||
any way with old packages, since they are stored in different
|
||||
locations in the Nix store.)</para>
|
||||
|
||||
<para>If you find that you want to undo a <command>nix-env</command>
|
||||
operation, you can just do
|
||||
|
||||
<screen>
|
||||
$ nix-env --rollback</screen>
|
||||
|
||||
which will just make the current generation link point at the previous
|
||||
link. E.g., <filename>default</filename> would be made to point at
|
||||
<filename>default-42-link</filename>. You can also switch to a
|
||||
specific generation:
|
||||
|
||||
<screen>
|
||||
$ nix-env --switch-generation 43</screen>
|
||||
|
||||
which in this example would roll forward to generation 43 again. You
|
||||
can also see all available generations:
|
||||
|
||||
<screen>
|
||||
$ nix-env --list-generations</screen></para>
|
||||
|
||||
<para>Actually, there is another level of indirection not shown in the
|
||||
figure above. You generally wouldn’t have
|
||||
<filename>/nix/var/nix/profiles/<replaceable>some-profile</replaceable>/bin</filename>
|
||||
in your <envar>PATH</envar>. Rather, there is a symlink
|
||||
<filename>~/.nix-profile</filename> that points to your current
|
||||
profile. This means that you should put
|
||||
<filename>~/.nix-profile/bin</filename> in your <envar>PATH</envar>
|
||||
(and indeed, that’s what the initialisation script
|
||||
<filename>/nix/etc/profile.d/nix.sh</filename> does). This makes it
|
||||
easier to switch to a different profile. You can do that using the
|
||||
command <command>nix-env --switch-profile</command>:
|
||||
|
||||
<screen>
|
||||
$ nix-env --switch-profile /nix/var/nix/profiles/my-profile
|
||||
|
||||
$ nix-env --switch-profile /nix/var/nix/profiles/default</screen>
|
||||
|
||||
These commands switch to the <filename>my-profile</filename> and
|
||||
default profile, respectively. If the profile doesn’t exist, it will
|
||||
be created automatically. You should be careful about storing a
|
||||
profile in another location than the <filename>profiles</filename>
|
||||
directory, since otherwise it might not be used as a root of the
|
||||
garbage collector (see <xref linkend='sec-garbage-collection'
|
||||
/>).</para>
|
||||
|
||||
<para>All <command>nix-env</command> operations work on the profile
|
||||
pointed to by <command>~/.nix-profile</command>, but you can override
|
||||
this using the <option>--profile</option> option (abbreviation
|
||||
<option>-p</option>):
|
||||
|
||||
<screen>
|
||||
$ nix-env -p /nix/var/nix/profiles/other-profile -i subversion</screen>
|
||||
|
||||
This will <emphasis>not</emphasis> change the
|
||||
<command>~/.nix-profile</command> symlink.</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id='sec-garbage-collection'><title>Garbage collection</title>
|
||||
|
||||
<para><command>nix-env</command> operations such as upgrades
|
||||
(<option>-u</option>) and uninstall (<option>-e</option>) never
|
||||
actually delete packages from the system. All they do (as shown
|
||||
above) is to create a new user environment that no longer contains
|
||||
symlinks to the “deleted” packages.</para>
|
||||
|
||||
<para>Of course, since disk space is not infinite, unused packages
|
||||
should be removed at some point. You can do this by running the Nix
|
||||
garbage collector. It will remove from the Nix store any package
|
||||
not used (directly or indirectly) by any generation of any
|
||||
profile.</para>
|
||||
|
||||
<para>Note however that as long as old generations reference a
|
||||
package, it will not be deleted. After all, we wouldn’t be able to
|
||||
do a rollback otherwise. So in order for garbage collection to be
|
||||
effective, you should also delete (some) old generations. Of course,
|
||||
this should only be done if you are certain that you will not need to
|
||||
roll back.</para>
|
||||
|
||||
<para>To delete all old (non-current) generations of your current
|
||||
profile:
|
||||
|
||||
<screen>
|
||||
$ nix-env --delete-generations old</screen>
|
||||
|
||||
Instead of <literal>old</literal> you can also specify a list of
|
||||
generations, e.g.,
|
||||
|
||||
<screen>
|
||||
$ nix-env --delete-generations 10 11 14</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>After removing appropriate old generations you can run the
|
||||
garbage collector as follows:
|
||||
|
||||
<screen>
|
||||
$ nix-store --gc</screen>
|
||||
|
||||
If you are feeling uncertain, you can also first view what files would
|
||||
be deleted:
|
||||
|
||||
<screen>
|
||||
$ nix-store --gc --print-dead</screen>
|
||||
|
||||
Likewise, the option <option>--print-live</option> will show the paths
|
||||
that <emphasis>won’t</emphasis> be deleted.</para>
|
||||
|
||||
<para>There is also a convenient little utility
|
||||
<command>nix-collect-garbage</command>, which when invoked with the
|
||||
<option>-d</option> (<option>--delete-old</option>) switch deletes all
|
||||
old generations of all profiles in
|
||||
<filename>/nix/var/nix/profiles</filename>. So
|
||||
|
||||
<screen>
|
||||
$ nix-collect-garbage -d</screen>
|
||||
|
||||
is a quick and easy way to clean up your system.</para>
|
||||
|
||||
|
||||
|
||||
|
||||
<section xml:id="ssec-gc-roots"><title>Garbage collector roots</title>
|
||||
|
||||
<para>The roots of the garbage collector are all store paths to which
|
||||
there are symlinks in the directory
|
||||
<filename><replaceable>prefix</replaceable>/nix/var/nix/gcroots</filename>.
|
||||
For instance, the following command makes the path
|
||||
<filename>/nix/store/d718ef...-foo</filename> a root of the collector:
|
||||
|
||||
<screen>
|
||||
$ ln -s /nix/store/d718ef...-foo /nix/var/nix/gcroots/bar</screen>
|
||||
|
||||
That is, after this command, the garbage collector will not remove
|
||||
<filename>/nix/store/d718ef...-foo</filename> or any of its
|
||||
dependencies.</para>
|
||||
|
||||
<para>Subdirectories of
|
||||
<filename><replaceable>prefix</replaceable>/nix/var/nix/gcroots</filename>
|
||||
are also searched for symlinks. Symlinks to non-store paths are
|
||||
followed and searched for roots, but symlinks to non-store paths
|
||||
<emphasis>inside</emphasis> the paths reached in that way are not
|
||||
followed to prevent infinite recursion.</para>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-channels"><title>Channels</title>
|
||||
|
||||
<para>If you want to stay up to date with a set of packages, it’s not
|
||||
very convenient to manually download the latest set of Nix expressions
|
||||
for those packages, use <command>nix-pull</command> to register
|
||||
pre-built binaries (if available), and upgrade using
|
||||
<command>nix-env</command>. Fortunately, there’s a better way:
|
||||
<emphasis>Nix channels</emphasis>.</para>
|
||||
|
||||
<para>A Nix channel is just a URL that points to a place that contains
|
||||
a set of Nix expressions and a manifest. Using the command <link
|
||||
linkend="sec-nix-channel"><command>nix-channel</command></link> you
|
||||
can automatically stay up to date with whatever is available at that
|
||||
URL.</para>
|
||||
|
||||
<para>You can “subscribe” to a channel using
|
||||
<command>nix-channel --add</command>, e.g.,
|
||||
|
||||
<screen>
|
||||
$ nix-channel --add http://nixos.org/channels/nixpkgs-unstable</screen>
|
||||
|
||||
subscribes you to a channel that always contains that latest version
|
||||
of the Nix Packages collection. (Instead of
|
||||
<literal>nixpkgs-unstable</literal> you could also subscribe to
|
||||
<literal>nixpkgs-stable</literal>, which should have a higher level of
|
||||
stability, but right now is just outdated.) Subscribing really just
|
||||
means that the URL is added to the file
|
||||
<filename>~/.nix-channels</filename>. Right now there is no command
|
||||
to “unsubscribe”; you should just edit that file manually
|
||||
and delete the offending URL.</para>
|
||||
|
||||
<para>To obtain the latest Nix expressions available in a channel, do
|
||||
|
||||
<screen>
|
||||
$ nix-channel --update</screen>
|
||||
|
||||
This downloads the Nix expressions in every channel (downloaded from
|
||||
<literal><replaceable>url</replaceable>/nixexprs.tar.bz2</literal>)
|
||||
and registers any available pre-built binaries in every channel
|
||||
(by <command>nix-pull</command>ing
|
||||
<literal><replaceable>url</replaceable>/MANIFEST</literal>). It also
|
||||
makes the union of each channel’s Nix expressions the default for
|
||||
<command>nix-env</command> operations. Consequently, you can then say
|
||||
|
||||
<screen>
|
||||
$ nix-env -u '*'</screen>
|
||||
|
||||
to upgrade all packages in your profile to the latest versions
|
||||
available in the subscribed channels.</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-one-click"><title>One-click installs</title>
|
||||
|
||||
<para>Often, when you want to install a specific package (e.g., from
|
||||
the <link
|
||||
xlink:href="http://nixos.org/nixpkgs/">Nix
|
||||
Packages collection</link>), subscribing to a channel is a bit
|
||||
cumbersome. And channels don’t help you at all if you want to install
|
||||
an older version of a package than the one provided by the current
|
||||
contents of the channel, or a package that has been removed from the
|
||||
channel. That’s when <emphasis>one-click installs</emphasis> come in
|
||||
handy: you can just go to the web page that contains the package,
|
||||
click on it, and it will be installed with all the necessary
|
||||
dependencies.</para>
|
||||
|
||||
<para>For instance, you can go to <link
|
||||
xlink:href="http://hydra.nixos.org/jobset/nixpkgs/trunk/channel/latest"
|
||||
/> and click on any link for the individual packages for your
|
||||
platform. The first time you do this, your browser will ask what to
|
||||
do with <literal>application/nix-package</literal> files. You should
|
||||
open them with <filename>/nix/bin/nix-install-package</filename>.
|
||||
This will open a window that asks you to confirm that you want to
|
||||
install the package. When you answer <literal>Y</literal>, the
|
||||
package and all its dependencies will be installed. This is a binary
|
||||
deployment mechanism — you get packages pre-compiled for the selected
|
||||
platform type.</para>
|
||||
|
||||
<para>You can also install <literal>application/nix-package</literal>
|
||||
files from the command line directly. See <xref
|
||||
linkend='sec-nix-install-package' /> for details.</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-sharing-packages"><title>Sharing packages between machines</title>
|
||||
|
||||
<para>Sometimes you want to copy a package from one machine to
|
||||
another. Or, you want to install some packages and you know that
|
||||
another machine already has some or all of those packages or their
|
||||
dependencies. In that case there are mechanisms to quickly copy
|
||||
packages between machines.</para>
|
||||
|
||||
<para>The command <command
|
||||
linkend="sec-nix-copy-closure">nix-copy-closure</command> copies a Nix
|
||||
store path along with all its dependencies to or from another machine
|
||||
via the SSH protocol. It doesn’t copy store paths that are already
|
||||
present on the target machine. For example, the following command
|
||||
copies Firefox with all its dependencies:
|
||||
|
||||
<screen>
|
||||
$ nix-copy-closure --to alice@itchy.example.org $(type -p firefox)</screen>
|
||||
|
||||
See <xref linkend='sec-nix-copy-closure' /> for details.</para>
|
||||
|
||||
<para>With <command linkend='refsec-nix-store-export'>nix-store
|
||||
--export</command> and <command
|
||||
linkend='refsec-nix-store-import'>nix-store --import</command> you can
|
||||
write the closure of a store path (that is, the path and all its
|
||||
dependencies) to a file, and then unpack that file into another Nix
|
||||
store. For example,
|
||||
|
||||
<screen>
|
||||
$ nix-store --export $(type -p firefox) > firefox.closure</screen>
|
||||
|
||||
writes the closure of Firefox to a file. You can then copy this file
|
||||
to another machine and install the closure:
|
||||
|
||||
<screen>
|
||||
$ nix-store --import < firefox.closure</screen>
|
||||
|
||||
Any store paths in the closure that are already present in the target
|
||||
store are ignored. It is also possible to pipe the export into
|
||||
another command, e.g. to copy and install a closure directly to/on
|
||||
another machine:
|
||||
|
||||
<screen>
|
||||
$ nix-store --export $(type -p firefox) | bzip2 | \
|
||||
ssh alice@itchy.example.org "bunzip2 | nix-store --import"</screen>
|
||||
|
||||
But note that <command>nix-copy-closure</command> is generally more
|
||||
efficient in this example because it only copies paths that are not
|
||||
already present in the target Nix store.</para>
|
||||
|
||||
<para>Finally, if you can mount the Nix store of a remote machine in
|
||||
your local filesystem, Nix can copy paths from the remote Nix store to
|
||||
the local Nix store <emphasis>on demand</emphasis>. For instance,
|
||||
suppose that you mount a remote machine containing a Nix store via
|
||||
<command
|
||||
xlink:href="http://fuse.sourceforge.net/sshfs.html">sshfs</command>:
|
||||
|
||||
<screen>
|
||||
$ sshfs alice@itchy.example.org:/ /mnt</screen>
|
||||
|
||||
You should then set the <envar>NIX_OTHER_STORES</envar> environment
|
||||
variable to tell Nix about this remote Nix store:
|
||||
|
||||
<screen>
|
||||
$ export NIX_OTHER_STORES=/mnt/nix</screen>
|
||||
|
||||
Then if you do any Nix operation, e.g.
|
||||
|
||||
<screen>
|
||||
$ nix-env -i firefox</screen>
|
||||
|
||||
and Nix has to build a path that it sees is already present in
|
||||
<filename>/mnt/nix</filename>, then it will just copy from there
|
||||
instead of building it from source.</para>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
</chapter>
|
||||
144
doc/manual/quick-start.xml
Normal file
144
doc/manual/quick-start.xml
Normal file
@@ -0,0 +1,144 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-quick-start">
|
||||
|
||||
<title>Quick Start</title>
|
||||
|
||||
|
||||
<para>This chapter is for impatient people who don't like reading
|
||||
documentation. For more in-depth information you are kindly referred
|
||||
to the following chapters.</para>
|
||||
|
||||
<orderedlist>
|
||||
|
||||
<listitem><para>Download a source tarball or RPM or Debian/Ubuntu
|
||||
package from <link xlink:href='http://nixos.org/'/>. Build source
|
||||
distributions using the regular sequence:
|
||||
|
||||
<screen>
|
||||
$ tar xvfj nix-<replaceable>version</replaceable>.tar.bz2
|
||||
$ ./configure
|
||||
$ make
|
||||
$ make install <lineannotation>(as root)</lineannotation></screen>
|
||||
|
||||
This will install the Nix binaries in <filename>/usr/local</filename>
|
||||
and keep the Nix store and other state in <filename>/nix</filename>.
|
||||
You can change the former by specifying
|
||||
<option>--prefix=<replaceable>path</replaceable></option>. The
|
||||
location of the store can be changed using
|
||||
<option>--with-store-dir=<replaceable>path</replaceable></option>.
|
||||
However, you shouldn't change the store location, if at all possible,
|
||||
since that will make it impossible to use pre-built binaries from the
|
||||
Nixpkgs channel and other channels. The location of the state can be
|
||||
changed using
|
||||
<option>--localstatedir=<replaceable>path</replaceable>.</option></para></listitem>
|
||||
|
||||
<listitem><para>You should add
|
||||
<filename><replaceable>prefix</replaceable>/etc/profile.d/nix.sh</filename>
|
||||
to your <filename>~/.bashrc</filename> (or some other login
|
||||
file).</para></listitem>
|
||||
|
||||
<listitem><para>Subscribe to the Nix Packages channel.
|
||||
|
||||
<screen>
|
||||
$ nix-channel --add http://nixos.org/channels/nixpkgs-unstable</screen>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>Download the latest Nix expressions available in the channel.
|
||||
<screen>
|
||||
$ nix-channel --update</screen>
|
||||
|
||||
Note that this in itself doesn't download any packages, it just
|
||||
downloads the Nix expressions that build them and stores them
|
||||
somewhere (under <filename>~/.nix-defexpr</filename>, in case you're
|
||||
curious). Also, it registers the fact that pre-built binaries are
|
||||
available remotely.</para></listitem>
|
||||
|
||||
<listitem><para>See what installable packages are currently available
|
||||
in the channel:
|
||||
|
||||
<screen>
|
||||
$ nix-env -qa \*
|
||||
docbook-xml-4.2
|
||||
firefox-1.0pre-PR-0.10.1
|
||||
hello-2.1.1
|
||||
libxslt-1.1.0
|
||||
<replaceable>...</replaceable></screen>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>Install some packages from the channel:
|
||||
|
||||
<screen>
|
||||
$ nix-env -i hello firefox <replaceable>...</replaceable> </screen>
|
||||
|
||||
This should download pre-built packages; it should not build them
|
||||
locally (if it does, something went wrong).</para></listitem>
|
||||
|
||||
<listitem><para>Test that they work:
|
||||
|
||||
<screen>
|
||||
$ which hello
|
||||
/home/eelco/.nix-profile/bin/hello
|
||||
$ hello
|
||||
Hello, world!
|
||||
$ firefox
|
||||
<lineannotation>(read Slashdot or something)</lineannotation></screen>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>Uninstall a package:
|
||||
|
||||
<screen>
|
||||
$ nix-env -e hello</screen>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>To keep up-to-date with the channel, do:
|
||||
|
||||
<screen>
|
||||
$ nix-channel --update
|
||||
$ nix-env -u '*'</screen>
|
||||
|
||||
The latter command will upgrade each installed package for which there
|
||||
is a “newer” version (as determined by comparing the version
|
||||
numbers).</para></listitem>
|
||||
|
||||
<listitem><para>You can also install specific packages directly from
|
||||
your web browser. For instance, you can go to <link
|
||||
xlink:href="http://hydra.nixos.org/jobset/nixpkgs/trunk/channel/latest"
|
||||
/> and click on any link for the individual packages for your
|
||||
platform. Associate <literal>application/nix-package</literal> with
|
||||
the program <command>nix-install-package</command>. A window should
|
||||
appear asking you whether it’s okay to install the package. Say
|
||||
<literal>Y</literal>. The package and all its dependencies will be
|
||||
installed.</para></listitem>
|
||||
|
||||
<listitem><para>If you're unhappy with the result of a
|
||||
<command>nix-env</command> action (e.g., an upgraded package turned
|
||||
out not to work properly), you can go back:
|
||||
|
||||
<screen>
|
||||
$ nix-env --rollback</screen>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>You should periodically run the Nix garbage collector
|
||||
to get rid of unused packages, since uninstalls or upgrades don't
|
||||
actually delete them:
|
||||
|
||||
<screen>
|
||||
$ nix-collect-garbage -d</screen>
|
||||
|
||||
<!--
|
||||
The first command deletes old “generations” of your profile (making
|
||||
rollbacks impossible, but also making the packages in those old
|
||||
generations available for garbage collection), while the second
|
||||
command actually deletes them.-->
|
||||
|
||||
</para></listitem>
|
||||
|
||||
</orderedlist>
|
||||
|
||||
</chapter>
|
||||
44
doc/manual/quote-literals.xsl
Normal file
44
doc/manual/quote-literals.xsl
Normal file
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<xsl:stylesheet
|
||||
version="1.0"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:str="http://exslt.org/strings"
|
||||
extension-element-prefixes="str">
|
||||
|
||||
<xsl:output method="xml"/>
|
||||
|
||||
<xsl:template match="function|command|literal|varname|filename|option|quote">`<xsl:apply-templates/>'</xsl:template>
|
||||
|
||||
<xsl:template match="token"><xsl:text> </xsl:text><xsl:apply-templates /><xsl:text>
|
||||
</xsl:text></xsl:template>
|
||||
|
||||
<xsl:template match="screen|programlisting">
|
||||
<screen><xsl:apply-templates select="str:split(., '
')" /></screen>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="section[following::section]">
|
||||
<section>
|
||||
<xsl:apply-templates />
|
||||
<screen><xsl:text>
|
||||
</xsl:text></screen>
|
||||
</section>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="*">
|
||||
<xsl:element name="{name(.)}" namespace="{namespace-uri(.)}">
|
||||
<xsl:copy-of select="namespace::*" />
|
||||
<xsl:for-each select="@*">
|
||||
<xsl:attribute name="{name(.)}" namespace="{namespace-uri(.)}">
|
||||
<xsl:value-of select="."/>
|
||||
</xsl:attribute>
|
||||
</xsl:for-each>
|
||||
<xsl:apply-templates/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="text()">
|
||||
<xsl:value-of select="translate(., '‘’“”—', concat("`'", '""-'))" />
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
1928
doc/manual/release-notes.xml
Normal file
1928
doc/manual/release-notes.xml
Normal file
File diff suppressed because it is too large
Load Diff
4
doc/manual/schemas.xml
Normal file
4
doc/manual/schemas.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0"?>
|
||||
<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
|
||||
<uri pattern="*.xml" typeId="DocBook"/>
|
||||
</locatingRules>
|
||||
255
doc/manual/style.css
Normal file
255
doc/manual/style.css
Normal file
@@ -0,0 +1,255 @@
|
||||
/* Copied from http://bakefile.sourceforge.net/, which appears
|
||||
licensed under the GNU GPL. */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Basic headers and text:
|
||||
***************************************************************************/
|
||||
|
||||
body
|
||||
{
|
||||
font-family: "Nimbus Sans L", sans-serif;
|
||||
background: white;
|
||||
margin: 2em 1em 2em 1em;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4
|
||||
{
|
||||
color: #005aa0;
|
||||
}
|
||||
|
||||
h1 /* title */
|
||||
{
|
||||
font-size: 200%;
|
||||
}
|
||||
|
||||
h2 /* chapters, appendices, subtitle */
|
||||
{
|
||||
font-size: 180%;
|
||||
}
|
||||
|
||||
/* Extra space between chapters, appendices. */
|
||||
div.chapter > div.titlepage h2, div.appendix > div.titlepage h2
|
||||
{
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
div.section > div.titlepage h2 /* sections */
|
||||
{
|
||||
font-size: 150%;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
h3 /* subsections */
|
||||
{
|
||||
font-size: 125%;
|
||||
}
|
||||
|
||||
div.simplesect h2
|
||||
{
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
div.appendix h3
|
||||
{
|
||||
font-size: 150%;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
div.refnamediv h2, div.refsynopsisdiv h2, div.refsection h2 /* refentry parts */
|
||||
{
|
||||
margin-top: 1.4em;
|
||||
font-size: 125%;
|
||||
}
|
||||
|
||||
div.refsection h3
|
||||
{
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Examples:
|
||||
***************************************************************************/
|
||||
|
||||
div.example
|
||||
{
|
||||
border: 1px solid #b0b0b0;
|
||||
padding: 6px 6px;
|
||||
margin-left: 1.5em;
|
||||
margin-right: 1.5em;
|
||||
background: #f4f4f8;
|
||||
border-radius: 0.4em;
|
||||
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
|
||||
}
|
||||
|
||||
div.example p.title
|
||||
{
|
||||
margin-top: 0em;
|
||||
}
|
||||
|
||||
div.example pre
|
||||
{
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Screen dumps:
|
||||
***************************************************************************/
|
||||
|
||||
pre.screen, pre.programlisting
|
||||
{
|
||||
border: 1px solid #b0b0b0;
|
||||
padding: 3px 3px;
|
||||
margin-left: 1.5em;
|
||||
margin-right: 1.5em;
|
||||
color: #600000;
|
||||
background: #f4f4f8;
|
||||
font-family: monospace;
|
||||
border-radius: 0.4em;
|
||||
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
|
||||
}
|
||||
|
||||
div.example pre.programlisting
|
||||
{
|
||||
border: 0px;
|
||||
padding: 0 0;
|
||||
margin: 0 0 0 0;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Notes, warnings etc:
|
||||
***************************************************************************/
|
||||
|
||||
.note, .warning
|
||||
{
|
||||
border: 1px solid #b0b0b0;
|
||||
padding: 3px 3px;
|
||||
margin-left: 1.5em;
|
||||
margin-right: 1.5em;
|
||||
margin-bottom: 1em;
|
||||
padding: 0.3em 0.3em 0.3em 0.3em;
|
||||
background: #fffff5;
|
||||
border-radius: 0.4em;
|
||||
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
|
||||
}
|
||||
|
||||
div.note, div.warning
|
||||
{
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
div.note h3, div.warning h3
|
||||
{
|
||||
color: red;
|
||||
font-size: 100%;
|
||||
padding-right: 0.5em;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.note p, div.warning p
|
||||
{
|
||||
margin-bottom: 0em;
|
||||
}
|
||||
|
||||
div.note h3 + p, div.warning h3 + p
|
||||
{
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.note h3
|
||||
{
|
||||
color: blue;
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
div.navfooter *
|
||||
{
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Links colors and highlighting:
|
||||
***************************************************************************/
|
||||
|
||||
a { text-decoration: none; }
|
||||
a:hover { text-decoration: underline; }
|
||||
a:link { color: #0048b3; }
|
||||
a:visited { color: #002a6a; }
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Table of contents:
|
||||
***************************************************************************/
|
||||
|
||||
div.toc
|
||||
{
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
div.toc dl
|
||||
{
|
||||
margin-top: 0em;
|
||||
margin-bottom: 0em;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Special elements:
|
||||
***************************************************************************/
|
||||
|
||||
tt, code
|
||||
{
|
||||
color: #400000;
|
||||
}
|
||||
|
||||
.term
|
||||
{
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
div.variablelist dd p, div.glosslist dd p
|
||||
{
|
||||
margin-top: 0em;
|
||||
}
|
||||
|
||||
div.variablelist dd, div.glosslist dd
|
||||
{
|
||||
margin-left: 1.5em;
|
||||
}
|
||||
|
||||
div.glosslist dt
|
||||
{
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.varname
|
||||
{
|
||||
color: #400000;
|
||||
}
|
||||
|
||||
span.command strong
|
||||
{
|
||||
font-weight: normal;
|
||||
color: #400000;
|
||||
}
|
||||
|
||||
div.calloutlist table
|
||||
{
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
table
|
||||
{
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
|
||||
}
|
||||
|
||||
div.affiliation
|
||||
{
|
||||
font-style: italic;
|
||||
}
|
||||
92
doc/manual/troubleshooting.xml
Normal file
92
doc/manual/troubleshooting.xml
Normal file
@@ -0,0 +1,92 @@
|
||||
<appendix xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
|
||||
<title>Troubleshooting</title>
|
||||
|
||||
|
||||
<para>This section provides solutions for some common problems. See
|
||||
the <link xlink:href="http://bugs.strategoxt.org/browse/NIX">Nix
|
||||
bug tracker</link> for a list of currently known issues.</para>
|
||||
|
||||
|
||||
<section><title>Collisions in <command>nix-env</command></title>
|
||||
|
||||
<para>Symptom: when installing or upgrading, you get an error message such as
|
||||
|
||||
<screen>
|
||||
$ nix-env -i docbook-xml
|
||||
...
|
||||
adding /nix/store/s5hyxgm62gk2...-docbook-xml-4.2
|
||||
collission between `/nix/store/s5hyxgm62gk2...-docbook-xml-4.2/xml/dtd/docbook/calstblx.dtd'
|
||||
and `/nix/store/06h377hr4b33...-docbook-xml-4.3/xml/dtd/docbook/calstblx.dtd'
|
||||
at /nix/store/...-builder.pl line 62.</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The cause is that two installed packages in the user environment
|
||||
have overlapping filenames (e.g.,
|
||||
<filename>xml/dtd/docbook/calstblx.dtd</filename>. This usually
|
||||
happens when you accidentally try to install two versions of the same
|
||||
package. For instance, in the example above, the Nix Packages
|
||||
collection contains two versions of <literal>docbook-xml</literal>, so
|
||||
<command>nix-env -i</command> will try to install both. The default
|
||||
user environment builder has no way to way to resolve such conflicts,
|
||||
so it just gives up.</para>
|
||||
|
||||
<para>Solution: remove one of the offending packages from the user
|
||||
environment (if already installed) using <command>nix-env
|
||||
-e</command>, or specify exactly which version should be installed
|
||||
(e.g., <literal>nix-env -i docbook-xml-4.2</literal>).</para>
|
||||
|
||||
<para>Alternatively, you can modify the user environment builder
|
||||
script (in
|
||||
<filename><replaceable>prefix</replaceable>/share/nix/corepkgs/buildenv/builder.pl</filename>)
|
||||
to implement some conflict resolution policy. E.g., the script could
|
||||
be modified to rename conflicting file names, or to pick one over the
|
||||
other.</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section><title><quote>Too many links</quote> error in the Nix
|
||||
store</title>
|
||||
|
||||
|
||||
<para>Symptom: when building something, you get an error message such as
|
||||
|
||||
<screen>
|
||||
...
|
||||
<literal>mkdir: cannot create directory `/nix/store/<replaceable>name</replaceable>': Too many links</literal></screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>This is usually because you have more than 32,000 subdirectories
|
||||
in <filename>/nix/store</filename>, as can be seen using <command>ls
|
||||
-l</command>:
|
||||
|
||||
<screen>
|
||||
$ ls -l /nix/store
|
||||
drwxrwxrwt 32000 nix nix 4620288 Sep 8 15:08 store</screen>
|
||||
|
||||
The <literal>ext2</literal> file system is limited to a inode link
|
||||
count of 32,000 (each subdirectory increasing the count by one).
|
||||
Furthermore, the <literal>st_nlink</literal> field of the
|
||||
<function>stat</function> system call is a 16-bit value.</para>
|
||||
|
||||
<para>This only happens on very large Nix installations (such as build
|
||||
machines).</para>
|
||||
|
||||
<para>Quick solution: run the garbage collector. You may want to use
|
||||
the <option>--max-links</option> option.</para>
|
||||
|
||||
<para>Real solution: put the Nix store on a file system that supports
|
||||
more than 32,000 subdirectories per directory, such as ReiserFS.
|
||||
(This doesn’t solve the <literal>st_nlink</literal> limit, but
|
||||
ReiserFS lies to the kernel by reporting a link count of 1 if it
|
||||
exceeds the limit.)</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
</appendix>
|
||||
1877
doc/manual/writing-nix-expressions.xml
Normal file
1877
doc/manual/writing-nix-expressions.xml
Normal file
File diff suppressed because it is too large
Load Diff
24
doc/signing.txt
Normal file
24
doc/signing.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
Generate a private key:
|
||||
|
||||
$ (umask 277 && openssl genrsa -out /nix/etc/nix/signing-key.sec 2048)
|
||||
|
||||
The private key should be kept secret (only readable to the Nix daemon
|
||||
user).
|
||||
|
||||
|
||||
Generate the corresponding public key:
|
||||
|
||||
$ openssl rsa -in /nix/etc/nix/signing-key.sec -pubout > /nix/etc/nix/signing-key.pub
|
||||
|
||||
The public key should be copied to all machines to which you want to
|
||||
export store paths.
|
||||
|
||||
|
||||
Signing:
|
||||
|
||||
$ nix-hash --type sha256 --flat svn.nar | openssl rsautl -sign -inkey mykey.sec > svn.nar.sign
|
||||
|
||||
|
||||
Verifying a signature:
|
||||
|
||||
$ test "$(nix-hash --type sha256 --flat svn.nar)" = "$(openssl rsautl -verify -inkey mykey.pub -pubin -in svn.nar.sign)"
|
||||
1
misc/Makefile.am
Normal file
1
misc/Makefile.am
Normal file
@@ -0,0 +1 @@
|
||||
SUBDIRS = emacs
|
||||
5
misc/emacs/Makefile.am
Normal file
5
misc/emacs/Makefile.am
Normal file
@@ -0,0 +1,5 @@
|
||||
EXTRA_DIST = nix-mode.el
|
||||
|
||||
install-data-local:
|
||||
$(INSTALL) -d $(DESTDIR)$(datadir)/emacs/site-lisp
|
||||
$(INSTALL_DATA) $(srcdir)/nix-mode.el $(DESTDIR)$(datadir)/emacs/site-lisp
|
||||
10
misc/emacs/README
Normal file
10
misc/emacs/README
Normal file
@@ -0,0 +1,10 @@
|
||||
The Nix Emacs mode supports syntax highlighting, somewhat sensible
|
||||
indenting, and refilling of comments.
|
||||
|
||||
To enable Nix mode in Emacs, add something like this to your ~/.emacs
|
||||
file:
|
||||
|
||||
(load "/nix/share/emacs/site-lisp/nix-mode.el")
|
||||
|
||||
This automatically causes Nix mode to be activated for all files with
|
||||
extension `.nix'.
|
||||
113
misc/emacs/nix-mode.el
Normal file
113
misc/emacs/nix-mode.el
Normal file
@@ -0,0 +1,113 @@
|
||||
(defun nix-mode ()
|
||||
"Major mode for editing Nix expressions.
|
||||
|
||||
The following commands may be useful:
|
||||
|
||||
'\\[newline-and-indent]'
|
||||
Insert a newline and move the cursor to align with the previous
|
||||
non-empty line.
|
||||
|
||||
'\\[fill-paragraph]'
|
||||
Refill a paragraph so that all lines are at most `fill-column'
|
||||
lines long. This should do the right thing for comments beginning
|
||||
with `#'. However, this command doesn't work properly yet if the
|
||||
comment is adjacent to code (i.e., no intervening empty lines).
|
||||
In that case, select the text to be refilled and use
|
||||
`\\[fill-region]' instead.
|
||||
|
||||
The hook `nix-mode-hook' is run when Nix mode is started.
|
||||
|
||||
\\{nix-mode-map}
|
||||
"
|
||||
|
||||
(interactive)
|
||||
|
||||
(kill-all-local-variables)
|
||||
|
||||
(setq major-mode 'nix-mode)
|
||||
(setq mode-name "Nix")
|
||||
|
||||
(use-local-map nix-mode-map)
|
||||
|
||||
(set-syntax-table nix-mode-syntax-table)
|
||||
|
||||
;; Font lock support.
|
||||
(setq font-lock-defaults '(nix-keywords nil nil nil nil))
|
||||
|
||||
;; Automatic indentation [C-j].
|
||||
(make-local-variable 'indent-line-function)
|
||||
(setq indent-line-function 'nix-indent-line)
|
||||
|
||||
;; Indenting of comments.
|
||||
(make-local-variable 'comment-start)
|
||||
(setq comment-start "# ")
|
||||
(make-local-variable 'comment-end)
|
||||
(setq comment-end "")
|
||||
(make-local-variable 'comment-start-skip)
|
||||
(setq comment-start-skip "\\(^\\|\\s-\\);?#+ *")
|
||||
|
||||
;; Filling of comments.
|
||||
(make-local-variable 'adaptive-fill-mode)
|
||||
(setq adaptive-fill-mode t)
|
||||
(make-local-variable 'paragraph-start)
|
||||
(setq paragraph-start "[ \t]*\\(#+[ \t]*\\)?$")
|
||||
(make-local-variable 'paragraph-separate)
|
||||
(setq paragraph-separate paragraph-start)
|
||||
|
||||
(run-hooks 'nix-mode-hook)
|
||||
)
|
||||
|
||||
|
||||
(defvar nix-mode-map nil
|
||||
"Keymap for Nix mode.")
|
||||
|
||||
(setq nix-mode-map (make-sparse-keymap))
|
||||
;(define-key nix-mode-map [tab] 'tab-to-tab-stop)
|
||||
|
||||
|
||||
(defvar nix-keywords
|
||||
'("\\<if\\>" "\\<then\\>" "\\<else\\>" "\\<assert\\>" "\\<with\\>"
|
||||
"\\<let\\>" "\\<in\\>" "\\<rec\\>" "\\<inherit\\>" "\\<or\\>"
|
||||
("\\<true\\>" . font-lock-builtin-face)
|
||||
("\\<false\\>" . font-lock-builtin-face)
|
||||
("\\<null\\>" . font-lock-builtin-face)
|
||||
("\\<import\\>" . font-lock-builtin-face)
|
||||
("\\<derivation\\>" . font-lock-builtin-face)
|
||||
("\\<baseNameOf\\>" . font-lock-builtin-face)
|
||||
("\\<toString\\>" . font-lock-builtin-face)
|
||||
("\\<isNull\\>" . font-lock-builtin-face)
|
||||
("[a-zA-Z][a-zA-Z0-9\\+-\\.]*:[a-zA-Z0-9%/\\?:@&=\\+\\$,_\\.!~\\*'-]+"
|
||||
. 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)
|
||||
))
|
||||
|
||||
|
||||
(defvar nix-mode-syntax-table nil
|
||||
"Syntax table for Nix mode.")
|
||||
|
||||
(if nix-mode-syntax-table
|
||||
nil
|
||||
(progn
|
||||
(setq nix-mode-syntax-table (make-syntax-table))
|
||||
(modify-syntax-entry ?/ ". 14" nix-mode-syntax-table)
|
||||
(modify-syntax-entry ?* ". 23" nix-mode-syntax-table)
|
||||
(modify-syntax-entry ?# "< b" nix-mode-syntax-table)
|
||||
(modify-syntax-entry ?\n "> b" nix-mode-syntax-table)
|
||||
))
|
||||
|
||||
|
||||
(defun nix-indent-line ()
|
||||
"Indent current line in a Nix expression."
|
||||
(interactive)
|
||||
(indent-relative-maybe))
|
||||
|
||||
|
||||
(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)
|
||||
10
misc/systemd/nix-daemon.service
Normal file
10
misc/systemd/nix-daemon.service
Normal file
@@ -0,0 +1,10 @@
|
||||
[Unit]
|
||||
Description=Helper daemon for managing secure, multi-user Nix stores
|
||||
After=syslog.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/nix-daemon
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
37
misc/vim/syntax/nix.vim
Normal file
37
misc/vim/syntax/nix.vim
Normal file
@@ -0,0 +1,37 @@
|
||||
" Vim syntax file
|
||||
" Language: nix
|
||||
" Maintainer: Marc Weber <marco-oweber@gmx.de>
|
||||
" Modify and commit if you feel that way
|
||||
" Last Change: 2007 Dec
|
||||
|
||||
" Quit when a (custom) syntax file was already loaded
|
||||
if exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
|
||||
syn keyword nixKeyword let throw inherit import true false null with
|
||||
syn keyword nixConditional if else then
|
||||
syn keyword nixBrace ( ) { } =
|
||||
syn keyword nixBuiltin __currentSystem __currentTime __isFunction __getEnv __trace __toPath __pathExists
|
||||
\ __readFile __toXML __toFile __filterSource __attrNames __getAttr __hasAttr __isAttrs __listToAttrs __isList
|
||||
\ __head __tail __add __sub __lessThan __substring __stringLength
|
||||
|
||||
syn match nixAttr "\w\+\ze\s*="
|
||||
syn match nixFuncArg "\zs\w\+\ze\s*:"
|
||||
syn region nixStringParam start=+\${+ end=+}+
|
||||
syn region nixMultiLineComment start=+/\*+ skip=+\\"+ end=+\*/+
|
||||
syn match nixEndOfLineComment "#.*$"
|
||||
syn region nixStringIndented start=+''+ skip=+'''\|''${\|"+ end=+''+ contains=nixStringParam
|
||||
syn region nixString start=+"+ skip=+\\"+ end=+"+ contains=nixStringParam
|
||||
|
||||
hi def link nixKeyword Keyword
|
||||
hi def link nixConditional Conditional
|
||||
hi def link nixBrace Special
|
||||
hi def link nixString String
|
||||
hi def link nixStringIndented String
|
||||
hi def link nixBuiltin Special
|
||||
hi def link nixStringParam Macro
|
||||
hi def link nixMultiLineComment Comment
|
||||
hi def link nixEndOfLineComment Comment
|
||||
hi def link nixAttr Identifier
|
||||
hi def link nixFuncArg Identifier
|
||||
215
nix.spec.in
Normal file
215
nix.spec.in
Normal file
@@ -0,0 +1,215 @@
|
||||
%global nixbld_user "nix-builder-"
|
||||
%global nixbld_group "nix-builders"
|
||||
|
||||
Summary: The Nix software deployment system
|
||||
Name: nix
|
||||
Version: @version@
|
||||
Release: 2%{?dist}
|
||||
License: LGPLv2+
|
||||
%if 0%{?rhel}
|
||||
Group: Applications/System
|
||||
%endif
|
||||
URL: http://nixos.org/
|
||||
Source0: %{name}-%{version}.tar.gz
|
||||
%if 0%{?el5}
|
||||
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
|
||||
%endif
|
||||
BuildRequires: perl(DBD::SQLite)
|
||||
BuildRequires: perl(DBI)
|
||||
BuildRequires: perl(WWW::Curl)
|
||||
BuildRequires: perl(ExtUtils::ParseXS)
|
||||
Requires: /usr/bin/perl
|
||||
Requires: curl
|
||||
Requires: perl-DBD-SQLite
|
||||
Requires: bzip2
|
||||
Requires: xz
|
||||
BuildRequires: bzip2-devel
|
||||
BuildRequires: sqlite-devel
|
||||
|
||||
# Hack to make that shitty RPM scanning hack shut up.
|
||||
Provides: perl(Nix::SSH)
|
||||
|
||||
%description
|
||||
Nix is a purely functional package manager. It allows multiple
|
||||
versions of a package to be installed side-by-side, ensures that
|
||||
dependency specifications are complete, supports atomic upgrades and
|
||||
rollbacks, allows non-root users to install software, and has many
|
||||
other features. It is the basis of the NixOS Linux distribution, but
|
||||
it can be used equally well under other Unix systems.
|
||||
|
||||
%package devel
|
||||
Summary: Development files for %{name}
|
||||
%if 0%{?rhel}
|
||||
Group: Development/Libraries
|
||||
%endif
|
||||
Requires: %{name}%{?_isa} = %{version}-%{release}
|
||||
|
||||
%description devel
|
||||
The %{name}-devel package contains libraries and header files for
|
||||
developing applications that use %{name}.
|
||||
|
||||
|
||||
%package doc
|
||||
Summary: Documentation files for %{name}
|
||||
%if 0%{?rhel}
|
||||
Group: Documentation
|
||||
%endif
|
||||
BuildArch: noarch
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
|
||||
%description doc
|
||||
The %{name}-doc package contains documentation files for %{name}.
|
||||
|
||||
|
||||
%package -n emacs-%{name}
|
||||
Summary: Nix mode for Emacs
|
||||
%if 0%{?rhel}
|
||||
Group: Applications/Editors
|
||||
%endif
|
||||
BuildArch: noarch
|
||||
BuildRequires: emacs
|
||||
Requires: emacs(bin) >= %{_emacs_version}
|
||||
|
||||
%description -n emacs-%{name}
|
||||
This package provides a major mode for editing Nix expressions.
|
||||
|
||||
%package -n emacs-%{name}-el
|
||||
Summary: Elisp source files for emacs-%{name}
|
||||
%if 0%{?rhel}
|
||||
Group: Applications/Editors
|
||||
%endif
|
||||
BuildArch: noarch
|
||||
Requires: emacs-%{name} = %{version}-%{release}
|
||||
|
||||
%description -n emacs-%{name}-el
|
||||
This package contains the elisp source file for the Nix major mode for
|
||||
GNU Emacs. You do not need to install this package to run Nix. Install
|
||||
the emacs-%{name} package to edit Nix expressions with GNU Emacs.
|
||||
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
# Install Perl modules to vendor_perl
|
||||
# configure.ac need to be changed to make this global; however, this will
|
||||
# also affect NixOS. Use discretion.
|
||||
%{__sed} -i 's|perl5/site_perl/$perlversion/$perlarchname|perl5/vendor_perl|' \
|
||||
configure
|
||||
|
||||
|
||||
%build
|
||||
extraFlags=
|
||||
# - override docdir so large documentation files are owned by the
|
||||
# -doc subpackage
|
||||
# - set localstatedir by hand to the preferred nix value
|
||||
%configure --localstatedir=/nix/var \
|
||||
--docdir=%{_defaultdocdir}/%{name}-doc-%{version} \
|
||||
$extraFlags
|
||||
make %{?_smp_flags}
|
||||
%{_emacs_bytecompile} misc/emacs/nix-mode.el
|
||||
|
||||
|
||||
%install
|
||||
%if 0%{?el5}
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
%endif
|
||||
make DESTDIR=$RPM_BUILD_ROOT install
|
||||
|
||||
find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';'
|
||||
|
||||
# Fix symlink: we want to link to the versioned soname, not to the
|
||||
# unversioned one that'd be put in -devel
|
||||
pushd $RPM_BUILD_ROOT%{perl_vendorarch}/auto/Nix/Store
|
||||
ln -sf %{_libdir}/nix/libNixStore.so.0 Store.so
|
||||
popd
|
||||
|
||||
# Specify build users group
|
||||
echo "build-users-group = %{nixbld_group}" > $RPM_BUILD_ROOT%{_sysconfdir}/nix/nix.conf
|
||||
|
||||
# make per-user directories
|
||||
for d in profiles gcroots;
|
||||
do
|
||||
mkdir $RPM_BUILD_ROOT/nix/var/nix/$d/per-user
|
||||
chmod 1777 $RPM_BUILD_ROOT/nix/var/nix/$d/per-user
|
||||
done
|
||||
|
||||
# fix permission of nix profile
|
||||
# (until this is fixed in the relevant Makefile)
|
||||
chmod -x $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/nix.sh
|
||||
|
||||
# systemd not available on RHEL yet
|
||||
%if ! 0%{?rhel}
|
||||
# install systemd service descriptor
|
||||
mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/systemd/system
|
||||
cp -p misc/systemd/nix-daemon.service \
|
||||
$RPM_BUILD_ROOT%{_prefix}/lib/systemd/system/
|
||||
%endif
|
||||
|
||||
# Copy the byte-compiled mode file by hand
|
||||
cp -p misc/emacs/nix-mode.elc $RPM_BUILD_ROOT%{_emacs_sitelispdir}/
|
||||
|
||||
# we ship this file in the base package
|
||||
rm $RPM_BUILD_ROOT%{_defaultdocdir}/%{name}-doc-%{version}/README
|
||||
|
||||
|
||||
%check
|
||||
make check
|
||||
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
|
||||
%pre
|
||||
getent group %{nixbld_group} >/dev/null || groupadd -r %{nixbld_group}
|
||||
for i in $(seq 10);
|
||||
do
|
||||
getent passwd %{nixbld_user}$i >/dev/null || \
|
||||
useradd -r -g %{nixbld_group} -G %{nixbld_group} -d /var/empty \
|
||||
-s %{_sbindir}/nologin \
|
||||
-c "Nix build user $i" %{nixbld_user}$i
|
||||
done
|
||||
|
||||
%post
|
||||
chgrp %{nixbld_group} /nix/store
|
||||
chmod 1775 /nix/store
|
||||
%if ! 0%{?rhel}
|
||||
# Enable and start Nix worker
|
||||
systemctl enable nix-daemon.service
|
||||
systemctl start nix-daemon.service
|
||||
%endif
|
||||
|
||||
%files
|
||||
%doc COPYING AUTHORS README
|
||||
%{_bindir}/nix-*
|
||||
%dir %{_libdir}/nix
|
||||
%{_libdir}/nix/*.so.*
|
||||
%{perl_vendorarch}/*
|
||||
%exclude %dir %{perl_vendorarch}/auto/
|
||||
%{_prefix}/libexec/*
|
||||
%if ! 0%{?rhel}
|
||||
%{_prefix}/lib/systemd/system/nix-daemon.service
|
||||
%endif
|
||||
%{_datadir}/emacs/site-lisp/nix-mode.el
|
||||
%{_datadir}/nix
|
||||
%{_mandir}/man1/*.1*
|
||||
%{_mandir}/man5/*.5*
|
||||
%{_mandir}/man8/*.8*
|
||||
%config(noreplace) %{_sysconfdir}/profile.d/nix.sh
|
||||
/nix
|
||||
%dir %{_sysconfdir}/nix
|
||||
%config(noreplace) %{_sysconfdir}/nix/nix.conf
|
||||
|
||||
%files devel
|
||||
%{_includedir}/nix
|
||||
%{_libdir}/nix/*.so
|
||||
|
||||
%files doc
|
||||
%docdir %{_defaultdocdir}/%{name}-doc-%{version}
|
||||
%{_defaultdocdir}/%{name}-doc-%{version}
|
||||
|
||||
%files -n emacs-%{name}
|
||||
%{_emacs_sitelispdir}/*.elc
|
||||
#{_emacs_sitestartdir}/*.el
|
||||
|
||||
%files -n emacs-%{name}-el
|
||||
%{_emacs_sitelispdir}/*.el
|
||||
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
|
||||
38
perl/Makefile.am
Normal file
38
perl/Makefile.am
Normal file
@@ -0,0 +1,38 @@
|
||||
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 lib/Nix/Utils.pm
|
||||
|
||||
all: $(PERL_MODULES:.in=)
|
||||
|
||||
install-exec-local: $(PERL_MODULES:.in=) install-perl-xs
|
||||
$(INSTALL) -d $(DESTDIR)$(perllibdir)/Nix
|
||||
$(INSTALL_DATA) $(PERL_MODULES:.in=) $(DESTDIR)$(perllibdir)/Nix
|
||||
|
||||
if PERL_BINDINGS
|
||||
install-perl-xs:
|
||||
$(INSTALL) -d $(DESTDIR)$(perllibdir)/auto/Nix/Store
|
||||
ln -sfn $(pkglibdir)/libNixStore$(dynlib_suffix) $(DESTDIR)$(perllibdir)/auto/Nix/Store/Store$(dynlib_suffix)
|
||||
|
||||
# Awful hackery to get libtool to build Perl XS bindings.
|
||||
pkglib_LTLIBRARIES = libNixStore.la
|
||||
|
||||
nodist_libNixStore_la_SOURCES = lib/Nix/Store.cc
|
||||
|
||||
CLEANFILES = lib/Nix/Store.cc
|
||||
|
||||
libNixStore_la_LIBADD = $(top_builddir)/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 \
|
||||
-D_FILE_OFFSET_BITS=64
|
||||
|
||||
lib/Nix/Store.cc: lib/Nix/Store.xs
|
||||
$(INSTALL) -d lib/Nix
|
||||
xsubpp $^ -output $@
|
||||
|
||||
else
|
||||
install-perl-xs:
|
||||
endif
|
||||
|
||||
EXTRA_DIST = $(PERL_MODULES) lib/Nix/Store.xs
|
||||
|
||||
include ../substitute.mk
|
||||
41
perl/lib/Nix/Config.pm.in
Normal file
41
perl/lib/Nix/Config.pm.in
Normal file
@@ -0,0 +1,41 @@
|
||||
package Nix::Config;
|
||||
|
||||
$version = "@version@";
|
||||
|
||||
$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";
|
||||
$storeDir = $ENV{"NIX_STORE_DIR"} || "@storedir@";
|
||||
|
||||
$bzip2 = "@bzip2@";
|
||||
$xz = "@xz@";
|
||||
$curl = "@curl@";
|
||||
|
||||
$useBindings = "@perlbindings@" eq "yes";
|
||||
|
||||
%config = ();
|
||||
|
||||
sub readConfig {
|
||||
if (defined $ENV{'_NIX_OPTIONS'}) {
|
||||
foreach my $s (split '\n', $ENV{'_NIX_OPTIONS'}) {
|
||||
my ($n, $v) = split '=', $s, 2;
|
||||
$config{$n} = $v;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
my $config = "$confDir/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;
|
||||
}
|
||||
close CONFIG;
|
||||
}
|
||||
|
||||
return 1;
|
||||
53
perl/lib/Nix/CopyClosure.pm
Normal file
53
perl/lib/Nix/CopyClosure.pm
Normal file
@@ -0,0 +1,53 @@
|
||||
package Nix::CopyClosure;
|
||||
|
||||
use strict;
|
||||
use Nix::Config;
|
||||
use Nix::Store;
|
||||
|
||||
|
||||
sub copyTo {
|
||||
my ($sshHost, $sshOpts, $storePaths, $compressor, $decompressor,
|
||||
$includeOutputs, $dryRun, $sign, $progressViewer, $useSubstitutes) = @_;
|
||||
|
||||
$compressor = "$compressor |" if $compressor ne "";
|
||||
$decompressor = "$decompressor |" if $decompressor ne "";
|
||||
$progressViewer = "$progressViewer |" if $progressViewer ne "";
|
||||
|
||||
# Get the closure of this path.
|
||||
my @closure = reverse(topoSortPaths(computeFSClosure(0, $includeOutputs,
|
||||
map { followLinksToStorePath $_ } @{$storePaths})));
|
||||
|
||||
# Optionally use substitutes on the remote host.
|
||||
if (!$dryRun && $useSubstitutes) {
|
||||
system "ssh $sshHost @{$sshOpts} nix-store -r --ignore-unknown @closure";
|
||||
# Ignore exit status because this is just an optimisation.
|
||||
}
|
||||
|
||||
# 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";
|
||||
unless ($dryRun) {
|
||||
open SSH, "| $compressor $progressViewer ssh $sshHost @{$sshOpts} '$decompressor nix-store --import' > /dev/null" or die;
|
||||
exportPaths(fileno(SSH), $sign, @missing);
|
||||
close SSH or die "copying store paths to remote machine `$sshHost' failed: $?";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
340
perl/lib/Nix/GeneratePatches.pm
Normal file
340
perl/lib/Nix/GeneratePatches.pm
Normal file
@@ -0,0 +1,340 @@
|
||||
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.
|
||||
|
||||
# Max size of NAR archives to generate patches for.
|
||||
my $maxNarSize = $ENV{"NIX_MAX_NAR_SIZE"};
|
||||
$maxNarSize = 160 * 1024 * 1024 if !defined $maxNarSize;
|
||||
|
||||
# If patch is bigger than this fraction of full archive, reject.
|
||||
my $maxPatchFraction = $ENV{"NIX_PATCH_FRACTION"};
|
||||
$maxPatchFraction = 0.60 if !defined $maxPatchFraction;
|
||||
|
||||
my $timeLimit = $ENV{"NIX_BSDIFF_TIME_LIMIT"};
|
||||
$timeLimit = 180 if !defined $timeLimit;
|
||||
|
||||
my $hashAlgo = "sha256";
|
||||
|
||||
|
||||
sub findOutputPaths {
|
||||
my $narFiles = shift;
|
||||
|
||||
my %outPaths;
|
||||
|
||||
foreach my $p (keys %{$narFiles}) {
|
||||
|
||||
# Ignore derivations.
|
||||
next if ($p =~ /\.drv$/);
|
||||
|
||||
# Ignore builders (too much ambiguity -- they're all called
|
||||
# `builder.sh').
|
||||
next if ($p =~ /\.sh$/);
|
||||
next if ($p =~ /\.patch$/);
|
||||
|
||||
# Don't bother including tar files etc.
|
||||
next if ($p =~ /\.tar$/ || $p =~ /\.tar\.(gz|bz2|Z|lzma|xz)$/ || $p =~ /\.zip$/ || $p =~ /\.bin$/ || $p =~ /\.tgz$/ || $p =~ /\.rpm$/ || $p =~ /cvs-export$/ || $p =~ /fetchhg$/);
|
||||
|
||||
$outPaths{$p} = 1;
|
||||
}
|
||||
|
||||
return %outPaths;
|
||||
}
|
||||
|
||||
|
||||
sub getNameVersion {
|
||||
my $p = shift;
|
||||
$p =~ /\/[0-9a-z]+((?:-[a-zA-Z][^\/-]*)+)([^\/]*)$/;
|
||||
my $name = $1;
|
||||
my $version = $2;
|
||||
return undef unless defined $name && defined $version;
|
||||
$name =~ s/^-//;
|
||||
$version =~ s/^-//;
|
||||
return ($name, $version);
|
||||
}
|
||||
|
||||
|
||||
# A quick hack to get a measure of the `distance' between two
|
||||
# versions: it's just the position of the first character that differs
|
||||
# (or 999 if they are the same).
|
||||
sub versionDiff {
|
||||
my $s = shift;
|
||||
my $t = shift;
|
||||
my $i;
|
||||
return 999 if $s eq $t;
|
||||
for ($i = 0; $i < length $s; $i++) {
|
||||
return $i if $i >= length $t or
|
||||
substr($s, $i, 1) ne substr($t, $i, 1);
|
||||
}
|
||||
return $i;
|
||||
}
|
||||
|
||||
|
||||
sub getNarBz2 {
|
||||
my $narPath = shift;
|
||||
my $narFiles = shift;
|
||||
my $storePath = shift;
|
||||
|
||||
my $narFileList = $$narFiles{$storePath};
|
||||
die "missing path $storePath" unless defined $narFileList;
|
||||
|
||||
my $narFile = @{$narFileList}[0];
|
||||
die unless defined $narFile;
|
||||
|
||||
$narFile->{url} =~ /\/([^\/]+)$/;
|
||||
die unless defined $1;
|
||||
return "$narPath/$1";
|
||||
}
|
||||
|
||||
|
||||
sub containsPatch {
|
||||
my $patches = shift;
|
||||
my $storePath = shift;
|
||||
my $basePath = shift;
|
||||
my $patchList = $$patches{$storePath};
|
||||
return 0 if !defined $patchList;
|
||||
my $found = 0;
|
||||
foreach my $patch (@{$patchList}) {
|
||||
# !!! baseHash might differ
|
||||
return 1 if $patch->{basePath} eq $basePath;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
sub generatePatches {
|
||||
my ($srcNarFiles, $dstNarFiles, $srcPatches, $dstPatches, $narPath, $patchesPath, $patchesURL, $tmpDir) = @_;
|
||||
|
||||
my %srcOutPaths = findOutputPaths $srcNarFiles;
|
||||
my %dstOutPaths = findOutputPaths $dstNarFiles;
|
||||
|
||||
# For each output path in the destination, see if we need to / can
|
||||
# create a patch.
|
||||
|
||||
print STDERR "creating patches...\n";
|
||||
|
||||
foreach my $p (keys %dstOutPaths) {
|
||||
|
||||
# If exactly the same path already exists in the source, skip it.
|
||||
next if defined $srcOutPaths{$p};
|
||||
|
||||
print " $p\n";
|
||||
|
||||
# If not, then we should find the paths in the source that are
|
||||
# `most' likely to be present on a system that wants to
|
||||
# install this path.
|
||||
|
||||
(my $name, my $version) = getNameVersion $p;
|
||||
next unless defined $name && defined $version;
|
||||
|
||||
my @closest = ();
|
||||
my $closestVersion;
|
||||
my $minDist = -1; # actually, larger means closer
|
||||
|
||||
# Find all source paths with the same name.
|
||||
|
||||
foreach my $q (keys %srcOutPaths) {
|
||||
(my $name2, my $version2) = getNameVersion $q;
|
||||
next unless defined $name2 && defined $version2;
|
||||
|
||||
if ($name eq $name2) {
|
||||
|
||||
my $srcSystem = @{$$dstNarFiles{$p}}[0]->{system};
|
||||
my $dstSystem = @{$$srcNarFiles{$q}}[0]->{system};
|
||||
if (defined $srcSystem && defined $dstSystem && $srcSystem ne $dstSystem) {
|
||||
print " SKIPPING $q due to different systems ($srcSystem vs. $dstSystem)\n";
|
||||
next;
|
||||
}
|
||||
|
||||
# If the sizes differ too much, then skip. This
|
||||
# disambiguates between, e.g., a real component and a
|
||||
# wrapper component (cf. Firefox in Nixpkgs).
|
||||
my $srcSize = @{$$srcNarFiles{$q}}[0]->{size};
|
||||
my $dstSize = @{$$dstNarFiles{$p}}[0]->{size};
|
||||
my $ratio = $srcSize / $dstSize;
|
||||
$ratio = 1 / $ratio if $ratio < 1;
|
||||
# print " SIZE $srcSize $dstSize $ratio $q\n";
|
||||
|
||||
if ($ratio >= 3) {
|
||||
print " SKIPPING $q due to size ratio $ratio ($srcSize vs. $dstSize)\n";
|
||||
next;
|
||||
}
|
||||
|
||||
# If there are multiple matching names, include the
|
||||
# ones with the closest version numbers.
|
||||
my $dist = versionDiff $version, $version2;
|
||||
if ($dist > $minDist) {
|
||||
$minDist = $dist;
|
||||
@closest = ($q);
|
||||
$closestVersion = $version2;
|
||||
} elsif ($dist == $minDist) {
|
||||
push @closest, $q;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (scalar(@closest) == 0) {
|
||||
print " NO BASE: $p\n";
|
||||
next;
|
||||
}
|
||||
|
||||
foreach my $closest (@closest) {
|
||||
|
||||
# Generate a patch between $closest and $p.
|
||||
print STDERR " $p <- $closest\n";
|
||||
|
||||
# If the patch already exists, skip it.
|
||||
if (containsPatch($srcPatches, $p, $closest) ||
|
||||
containsPatch($dstPatches, $p, $closest))
|
||||
{
|
||||
print " skipping, already exists\n";
|
||||
next;
|
||||
}
|
||||
|
||||
my $srcNarBz2 = getNarBz2 $narPath, $srcNarFiles, $closest;
|
||||
my $dstNarBz2 = getNarBz2 $narPath, $dstNarFiles, $p;
|
||||
|
||||
if (! -f $srcNarBz2) {
|
||||
warn "patch source archive $srcNarBz2 is missing\n";
|
||||
next;
|
||||
}
|
||||
|
||||
system("$Nix::Config::bzip2 -d < $srcNarBz2 > $tmpDir/A") == 0
|
||||
or die "cannot unpack $srcNarBz2";
|
||||
|
||||
if (stat("$tmpDir/A")->size >= $maxNarSize) {
|
||||
print " skipping, source is too large\n";
|
||||
next;
|
||||
}
|
||||
|
||||
system("$Nix::Config::bzip2 -d < $dstNarBz2 > $tmpDir/B") == 0
|
||||
or die "cannot unpack $dstNarBz2";
|
||||
|
||||
if (stat("$tmpDir/B")->size >= $maxNarSize) {
|
||||
print " skipping, destination is too large\n";
|
||||
next;
|
||||
}
|
||||
|
||||
my $time1 = time();
|
||||
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 = `$Nix::Config::binDir/nix-hash --flat --type $hashAlgo --base32 $tmpDir/A` or die;
|
||||
chomp $baseHash;
|
||||
|
||||
my $narHash = `$Nix::Config::binDir/nix-hash --flat --type $hashAlgo --base32 $tmpDir/B` or die;
|
||||
chomp $narHash;
|
||||
|
||||
my $narDiffHash = `$Nix::Config::binDir/nix-hash --flat --type $hashAlgo --base32 $tmpDir/DIFF` or die;
|
||||
chomp $narDiffHash;
|
||||
|
||||
my $narDiffSize = stat("$tmpDir/DIFF")->size;
|
||||
my $dstNarBz2Size = stat($dstNarBz2)->size;
|
||||
|
||||
print " size $narDiffSize; full size $dstNarBz2Size; ", $time2 - $time1, " seconds\n";
|
||||
|
||||
if ($narDiffSize >= $dstNarBz2Size) {
|
||||
print " rejecting; patch bigger than full archive\n";
|
||||
next;
|
||||
}
|
||||
|
||||
if ($narDiffSize / $dstNarBz2Size >= $maxPatchFraction) {
|
||||
print " rejecting; patch too large relative to full archive\n";
|
||||
next;
|
||||
}
|
||||
|
||||
my $finalName = "$narDiffHash.nar-bsdiff";
|
||||
|
||||
if (-e "$patchesPath/$finalName") {
|
||||
print " not copying, already exists\n";
|
||||
}
|
||||
|
||||
else {
|
||||
system("cp '$tmpDir/DIFF' '$patchesPath/$finalName.tmp'") == 0
|
||||
or die "cannot copy diff";
|
||||
rename("$patchesPath/$finalName.tmp", "$patchesPath/$finalName")
|
||||
or die "cannot rename $patchesPath/$finalName.tmp";
|
||||
}
|
||||
|
||||
# Add the patch to the manifest.
|
||||
addPatch $dstPatches, $p,
|
||||
{ url => "$patchesURL/$finalName", hash => "$hashAlgo:$narDiffHash"
|
||||
, size => $narDiffSize, basePath => $closest, baseHash => "$hashAlgo:$baseHash"
|
||||
, narHash => "$hashAlgo:$narHash", patchType => "nar-bsdiff"
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Propagate useful patches from $srcPatches to $dstPatches. A patch
|
||||
# is useful if it produces either paths in the $dstNarFiles or paths
|
||||
# that can be used as the base for other useful patches.
|
||||
sub propagatePatches {
|
||||
my ($srcPatches, $dstNarFiles, $dstPatches) = @_;
|
||||
|
||||
print STDERR "propagating patches...\n";
|
||||
|
||||
my $changed;
|
||||
do {
|
||||
# !!! we repeat this to reach the transitive closure; inefficient
|
||||
$changed = 0;
|
||||
|
||||
print STDERR "loop\n";
|
||||
|
||||
my %dstBasePaths;
|
||||
foreach my $q (keys %{$dstPatches}) {
|
||||
foreach my $patch (@{$$dstPatches{$q}}) {
|
||||
$dstBasePaths{$patch->{basePath}} = 1;
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $p (keys %{$srcPatches}) {
|
||||
my $patchList = $$srcPatches{$p};
|
||||
|
||||
my $include = 0;
|
||||
|
||||
# Is path $p included in the destination? If so, include
|
||||
# patches that produce it.
|
||||
$include = 1 if defined $$dstNarFiles{$p};
|
||||
|
||||
# Is path $p a path that serves as a base for paths in the
|
||||
# destination? If so, include patches that produce it.
|
||||
# !!! check baseHash
|
||||
$include = 1 if defined $dstBasePaths{$p};
|
||||
|
||||
if ($include) {
|
||||
foreach my $patch (@{$patchList}) {
|
||||
$changed = 1 if addPatch $dstPatches, $p, $patch;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} while $changed;
|
||||
}
|
||||
|
||||
|
||||
# Add all new patches in $srcPatches to $dstPatches.
|
||||
sub copyPatches {
|
||||
my ($srcPatches, $dstPatches) = @_;
|
||||
foreach my $p (keys %{$srcPatches}) {
|
||||
addPatch $dstPatches, $p, $_ foreach @{$$srcPatches{$p}};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
429
perl/lib/Nix/Manifest.pm
Normal file
429
perl/lib/Nix/Manifest.pm
Normal file
@@ -0,0 +1,429 @@
|
||||
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 deleteOldManifests parseNARInfo);
|
||||
|
||||
|
||||
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, $compressionType);
|
||||
|
||||
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 = "";
|
||||
$compressionType = "bzip2";
|
||||
}
|
||||
|
||||
} 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
|
||||
, compressionType => $compressionType
|
||||
});
|
||||
}
|
||||
|
||||
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*Compression:\s*(\S+)\s*$/) { $compressionType = $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 " Compression: $narFile->{compressionType}\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);
|
||||
|
||||
unlink "$manifestDir/cache.sqlite"; # remove obsolete cache
|
||||
my $dbPath = "$manifestDir/cache-v2.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,
|
||||
compressionType 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, compressionType, 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->{compressionType}, $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\n";
|
||||
}
|
||||
if ($version >= 10) {
|
||||
die "manifest `$manifestLink' is too new; please delete it or upgrade Nix\n";
|
||||
}
|
||||
}
|
||||
|
||||
# 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Delete all old manifests downloaded from a given URL.
|
||||
sub deleteOldManifests {
|
||||
my ($url, $curUrlFile) = @_;
|
||||
for my $urlFile (glob "$Nix::Config::manifestDir/*.url") {
|
||||
next if defined $curUrlFile && $urlFile eq $curUrlFile;
|
||||
open URL, "<$urlFile" or die;
|
||||
my $url2 = <URL>;
|
||||
chomp $url2;
|
||||
close URL;
|
||||
next unless $url eq $url2;
|
||||
my $base = $urlFile; $base =~ s/.url$//;
|
||||
unlink "${base}.url";
|
||||
unlink "${base}.nixmanifest";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Parse a NAR info file.
|
||||
sub parseNARInfo {
|
||||
my ($storePath, $content) = @_;
|
||||
|
||||
my ($storePath2, $url, $fileHash, $fileSize, $narHash, $narSize, $deriver, $system);
|
||||
my $compression = "bzip2";
|
||||
my @refs;
|
||||
|
||||
foreach my $line (split "\n", $content) {
|
||||
return undef unless $line =~ /^(.*): (.*)$/;
|
||||
if ($1 eq "StorePath") { $storePath2 = $2; }
|
||||
elsif ($1 eq "URL") { $url = $2; }
|
||||
elsif ($1 eq "Compression") { $compression = $2; }
|
||||
elsif ($1 eq "FileHash") { $fileHash = $2; }
|
||||
elsif ($1 eq "FileSize") { $fileSize = int($2); }
|
||||
elsif ($1 eq "NarHash") { $narHash = $2; }
|
||||
elsif ($1 eq "NarSize") { $narSize = int($2); }
|
||||
elsif ($1 eq "References") { @refs = split / /, $2; }
|
||||
elsif ($1 eq "Deriver") { $deriver = $2; }
|
||||
elsif ($1 eq "System") { $system = $2; }
|
||||
}
|
||||
|
||||
return undef if $storePath ne $storePath2 || !defined $url || !defined $narHash;
|
||||
|
||||
return
|
||||
{ url => $url
|
||||
, compression => $compression
|
||||
, fileHash => $fileHash
|
||||
, fileSize => $fileSize
|
||||
, narHash => $narHash
|
||||
, narSize => $narSize
|
||||
, refs => [ @refs ]
|
||||
, deriver => $deriver
|
||||
, system => $system
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
52
perl/lib/Nix/SSH.pm
Normal file
52
perl/lib/Nix/SSH.pm
Normal file
@@ -0,0 +1,52 @@
|
||||
use strict;
|
||||
use File::Temp qw(tempdir);
|
||||
|
||||
our @sshOpts = split ' ', ($ENV{"NIX_SSHOPTS"} or "");
|
||||
|
||||
push @sshOpts, "-x";
|
||||
|
||||
my $sshStarted = 0;
|
||||
my $sshHost;
|
||||
|
||||
# Open a master SSH connection to `host', unless there already is a
|
||||
# running master connection (as determined by `-O check').
|
||||
sub openSSHConnection {
|
||||
my ($host) = @_;
|
||||
die if $sshStarted;
|
||||
$sshHost = $host;
|
||||
return 1 if system("ssh $sshHost @sshOpts -O check 2> /dev/null") == 0;
|
||||
|
||||
my $tmpDir = tempdir("nix-ssh.XXXXXX", CLEANUP => 1, TMPDIR => 1)
|
||||
or die "cannot create a temporary directory";
|
||||
|
||||
push @sshOpts, "-S", "$tmpDir/control";
|
||||
|
||||
# Start the master. We can't use the `-f' flag (fork into
|
||||
# background after establishing the connection) because then the
|
||||
# child continues to run if we are killed. So instead make SSH
|
||||
# print "started" when it has established the connection, and wait
|
||||
# until we see that.
|
||||
open SSHPIPE, "ssh $sshHost @sshOpts -M -N -o LocalCommand='echo started' -o PermitLocalCommand=yes |" or die;
|
||||
|
||||
while (<SSHPIPE>) {
|
||||
chomp;
|
||||
if ($_ eq "started") {
|
||||
$sshStarted = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Tell the master SSH client to exit.
|
||||
sub closeSSHConnection {
|
||||
if ($sshStarted) {
|
||||
system("ssh $sshHost @sshOpts -O exit 2> /dev/null") == 0
|
||||
or warn "unable to stop SSH master: $?";
|
||||
}
|
||||
}
|
||||
|
||||
END { my $saved = $?; closeSSHConnection; $? = $saved; }
|
||||
|
||||
return 1;
|
||||
92
perl/lib/Nix/Store.pm
Normal file
92
perl/lib/Nix/Store.pm
Normal file
@@ -0,0 +1,92 @@
|
||||
package Nix::Store;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Nix::Config;
|
||||
|
||||
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
|
||||
queryPathFromHashPart
|
||||
topoSortPaths computeFSClosure followLinksToStorePath exportPaths
|
||||
hashPath hashFile hashString
|
||||
addToStore makeFixedOutputPath
|
||||
derivationFromPath
|
||||
);
|
||||
|
||||
our $VERSION = '0.15';
|
||||
|
||||
sub backtick {
|
||||
open(RES, "-|", @_) or die;
|
||||
local $/;
|
||||
my $res = <RES> || "";
|
||||
close RES or die;
|
||||
return $res;
|
||||
}
|
||||
|
||||
if ($Nix::Config::useBindings) {
|
||||
require XSLoader;
|
||||
XSLoader::load('Nix::Store', $VERSION);
|
||||
} else {
|
||||
|
||||
# Provide slow fallbacks of some functions on platforms that don't
|
||||
# support the Perl bindings.
|
||||
|
||||
use File::Temp;
|
||||
use Fcntl qw/F_SETFD/;
|
||||
|
||||
sub hashFile {
|
||||
my ($algo, $base32, $path) = @_;
|
||||
my $res = backtick("$Nix::Config::binDir/nix-hash", "--flat", $path, "--type", $algo, $base32 ? "--base32" : ());
|
||||
chomp $res;
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub hashPath {
|
||||
my ($algo, $base32, $path) = @_;
|
||||
my $res = backtick("$Nix::Config::binDir/nix-hash", $path, "--type", $algo, $base32 ? "--base32" : ());
|
||||
chomp $res;
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub hashString {
|
||||
my ($algo, $base32, $s) = @_;
|
||||
my $fh = File::Temp->new();
|
||||
print $fh $s;
|
||||
my $res = backtick("$Nix::Config::binDir/nix-hash", $fh->filename, "--type", $algo, $base32 ? "--base32" : ());
|
||||
chomp $res;
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub addToStore {
|
||||
my ($srcPath, $recursive, $algo) = @_;
|
||||
die "not implemented" if $recursive || $algo ne "sha256";
|
||||
my $res = backtick("$Nix::Config::binDir/nix-store", "--add", $srcPath);
|
||||
chomp $res;
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub isValidPath {
|
||||
my ($path) = @_;
|
||||
my $res = backtick("$Nix::Config::binDir/nix-store", "--check-validity", "--print-invalid", $path);
|
||||
chomp $res;
|
||||
return $res ne $path;
|
||||
}
|
||||
|
||||
sub queryPathHash {
|
||||
my ($path) = @_;
|
||||
my $res = backtick("$Nix::Config::binDir/nix-store", "--query", "--hash", $path);
|
||||
chomp $res;
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
||||
271
perl/lib/Nix/Store.xs
Normal file
271
perl/lib/Nix/Store.xs
Normal file
@@ -0,0 +1,271 @@
|
||||
#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 {
|
||||
settings.processEnvironment();
|
||||
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, int base32)
|
||||
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:" + (base32 ? printHash32(info.hash) : 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 * queryPathFromHashPart(char * hashPart)
|
||||
PPCODE:
|
||||
try {
|
||||
doInit();
|
||||
Path path = store->queryPathFromHashPart(hashPart);
|
||||
XPUSHs(sv_2mortal(newSVpv(path.c_str(), 0)));
|
||||
} 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());
|
||||
}
|
||||
|
||||
|
||||
SV * derivationFromPath(char * drvPath)
|
||||
PREINIT:
|
||||
HV *hash;
|
||||
CODE:
|
||||
try {
|
||||
doInit();
|
||||
Derivation drv = derivationFromPath(*store, drvPath);
|
||||
hash = newHV();
|
||||
|
||||
/* TODO: handle drv.outputs */
|
||||
|
||||
AV * inputDrvs = newAV();
|
||||
for (DerivationInputs::iterator i = drv.inputDrvs.begin(); i != drv.inputDrvs.end(); ++i)
|
||||
av_push(inputDrvs, newSVpv(i->first.c_str(), 0)); // !!! ignores i->second
|
||||
hv_stores(hash, "inputDrvs", newRV((SV *) inputDrvs));
|
||||
|
||||
AV * inputSrcs = newAV();
|
||||
for (PathSet::iterator i = drv.inputSrcs.begin(); i != drv.inputSrcs.end(); ++i)
|
||||
av_push(inputSrcs, newSVpv(i->c_str(), 0));
|
||||
hv_stores(hash, "inputSrcs", newRV((SV *) inputSrcs));
|
||||
|
||||
hv_stores(hash, "platform", newSVpv(drv.platform.c_str(), 0));
|
||||
hv_stores(hash, "builder", newSVpv(drv.builder.c_str(), 0));
|
||||
|
||||
AV * args = newAV();
|
||||
for (Strings::iterator i = drv.args.begin(); i != drv.args.end(); ++i)
|
||||
av_push(args, newSVpv(i->c_str(), 0));
|
||||
hv_stores(hash, "args", newRV((SV *) args));
|
||||
|
||||
HV * env = newHV();
|
||||
for (StringPairs::iterator i = drv.env.begin(); i != drv.env.end(); ++i)
|
||||
hv_store(env, i->first.c_str(), i->first.size(), newSVpv(i->second.c_str(), 0), 0);
|
||||
hv_stores(hash, "env", newRV((SV *) env));
|
||||
|
||||
RETVAL = newRV_noinc((SV *)hash);
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
}
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
38
perl/lib/Nix/Utils.pm
Normal file
38
perl/lib/Nix/Utils.pm
Normal file
@@ -0,0 +1,38 @@
|
||||
package Nix::Utils;
|
||||
|
||||
our @ISA = qw(Exporter);
|
||||
our @EXPORT = qw(checkURL uniq writeFile readFile);
|
||||
|
||||
$urlRE = "(?: [a-zA-Z][a-zA-Z0-9\+\-\.]*\:[a-zA-Z0-9\%\/\?\:\@\&\=\+\$\,\-\_\.\!\~\*]+ )";
|
||||
|
||||
sub checkURL {
|
||||
my ($url) = @_;
|
||||
die "invalid URL ‘$url’\n" unless $url =~ /^ $urlRE $ /x;
|
||||
}
|
||||
|
||||
sub uniq {
|
||||
my %seen;
|
||||
my @res;
|
||||
foreach my $name (@_) {
|
||||
next if $seen{$name};
|
||||
$seen{$name} = 1;
|
||||
push @res, $name;
|
||||
}
|
||||
return @res;
|
||||
}
|
||||
|
||||
sub writeFile {
|
||||
my ($fn, $s) = @_;
|
||||
open TMP, ">$fn" or die;
|
||||
print TMP "$s" or die;
|
||||
close TMP or die;
|
||||
}
|
||||
|
||||
sub readFile {
|
||||
local $/ = undef;
|
||||
my ($fn) = @_;
|
||||
open TMP, "<$fn" or die;
|
||||
my $s = <TMP>;
|
||||
close TMP or die;
|
||||
return $s;
|
||||
}
|
||||
237
release.nix
Normal file
237
release.nix
Normal file
@@ -0,0 +1,237 @@
|
||||
{ nixpkgs ? <nixpkgs>
|
||||
, nix ? { outPath = ./.; revCount = 1234; shortRev = "abcdef"; }
|
||||
, officialRelease ? false
|
||||
}:
|
||||
|
||||
let
|
||||
|
||||
jobs = rec {
|
||||
|
||||
|
||||
tarball =
|
||||
with import nixpkgs {};
|
||||
|
||||
releaseTools.sourceTarball {
|
||||
name = "nix-tarball";
|
||||
version = builtins.readFile ./version;
|
||||
versionSuffix = if officialRelease then "" else "pre${toString nix.revCount}_${nix.shortRev}";
|
||||
src = nix;
|
||||
inherit officialRelease;
|
||||
|
||||
buildInputs =
|
||||
[ curl bison25 flex2535 perl libxml2 libxslt w3m bzip2
|
||||
tetex dblatex nukeReferences pkgconfig sqlite git
|
||||
];
|
||||
|
||||
configureFlags = ''
|
||||
--with-docbook-rng=${docbook5}/xml/rng/docbook
|
||||
--with-docbook-xsl=${docbook5_xsl}/xml/xsl/docbook
|
||||
--with-xml-flags=--nonet
|
||||
--with-dbi=${perlPackages.DBI}/${perl.libPrefix}
|
||||
--with-dbd-sqlite=${perlPackages.DBDSQLite}/${perl.libPrefix}
|
||||
--with-www-curl=${perlPackages.WWWCurl}/${perl.libPrefix}
|
||||
'';
|
||||
|
||||
postUnpack = ''
|
||||
# Clean up when building from a working tree.
|
||||
(cd $sourceRoot && (git ls-files -o | xargs -r rm -v))
|
||||
'';
|
||||
|
||||
preConfigure = ''
|
||||
# TeX needs a writable font cache.
|
||||
export VARTEXFONTS=$TMPDIR/texfonts
|
||||
'';
|
||||
|
||||
distPhase =
|
||||
''
|
||||
runHook preDist
|
||||
make dist-gzip
|
||||
make dist-xz
|
||||
mkdir -p $out/tarballs
|
||||
cp *.tar.* $out/tarballs
|
||||
'';
|
||||
|
||||
preDist = ''
|
||||
make -C doc/manual install prefix=$out
|
||||
|
||||
make -C doc/manual manual.pdf prefix=$out
|
||||
cp doc/manual/manual.pdf $out/manual.pdf
|
||||
|
||||
# The PDF containes filenames of included graphics (see
|
||||
# http://www.tug.org/pipermail/pdftex/2007-August/007290.html).
|
||||
# This causes a retained dependency on dblatex, which Hydra
|
||||
# doesn't like (the output of the tarball job is distributed
|
||||
# to Windows and Macs, so there should be no Linux binaries
|
||||
# in the closure).
|
||||
nuke-refs $out/manual.pdf
|
||||
|
||||
echo "doc manual $out/share/doc/nix/manual" >> $out/nix-support/hydra-build-products
|
||||
echo "doc-pdf manual $out/manual.pdf" >> $out/nix-support/hydra-build-products
|
||||
echo "doc release-notes $out/share/doc/nix/release-notes" >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
build =
|
||||
{ system ? "x86_64-linux" }:
|
||||
|
||||
with import nixpkgs { inherit system; };
|
||||
|
||||
releaseTools.nixBuild {
|
||||
name = "nix";
|
||||
src = tarball;
|
||||
|
||||
buildInputs = [ curl perl bzip2 openssl pkgconfig sqlite boehmgc ];
|
||||
|
||||
configureFlags = ''
|
||||
--disable-init-state
|
||||
--with-dbi=${perlPackages.DBI}/${perl.libPrefix}
|
||||
--with-dbd-sqlite=${perlPackages.DBDSQLite}/${perl.libPrefix}
|
||||
--with-www-curl=${perlPackages.WWWCurl}/${perl.libPrefix}
|
||||
--enable-gc
|
||||
'';
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
doInstallCheck = true;
|
||||
};
|
||||
|
||||
binaryTarball =
|
||||
{ system ? "x86_64-linux" }:
|
||||
|
||||
with import nixpkgs { inherit system; };
|
||||
|
||||
let
|
||||
toplevel = build { inherit system; };
|
||||
version = toplevel.src.version;
|
||||
in
|
||||
|
||||
runCommand "nix-binary-tarball-${version}"
|
||||
{ exportReferencesGraph = [ "closure" toplevel ];
|
||||
buildInputs = [ perl ];
|
||||
meta.description = "Distribution-independent Nix bootstrap binaries for ${system}";
|
||||
}
|
||||
''
|
||||
storePaths=$(perl ${pathsFromGraph} ./closure)
|
||||
printRegistration=1 perl ${pathsFromGraph} ./closure > $TMPDIR/reginfo
|
||||
substitute ${./scripts/install-nix-from-closure.sh} $TMPDIR/install \
|
||||
--subst-var-by nix ${toplevel} --subst-var-by regInfo /nix/store/reginfo
|
||||
chmod +x $TMPDIR/install
|
||||
fn=$out/nix-${version}-${system}.tar.bz2
|
||||
mkdir -p $out/nix-support
|
||||
echo "file binary-dist $fn" >> $out/nix-support/hydra-build-products
|
||||
tar cvfj $fn \
|
||||
--owner=0 --group=0 --absolute-names \
|
||||
--transform "s,$TMPDIR/install,/usr/bin/nix-finish-install," \
|
||||
--transform "s,$TMPDIR/reginfo,/nix/store/reginfo," \
|
||||
$TMPDIR/install $TMPDIR/reginfo $storePaths
|
||||
'';
|
||||
|
||||
|
||||
coverage =
|
||||
with import nixpkgs { system = "x86_64-linux"; };
|
||||
|
||||
releaseTools.coverageAnalysis {
|
||||
name = "nix-build";
|
||||
src = tarball;
|
||||
|
||||
buildInputs =
|
||||
[ curl perl bzip2 openssl pkgconfig sqlite
|
||||
# These are for "make check" only:
|
||||
graphviz libxml2 libxslt
|
||||
];
|
||||
|
||||
configureFlags = ''
|
||||
--disable-init-state
|
||||
--with-dbi=${perlPackages.DBI}/${perl.libPrefix}
|
||||
--with-dbd-sqlite=${perlPackages.DBDSQLite}/${perl.libPrefix}
|
||||
--with-www-curl=${perlPackages.WWWCurl}/${perl.libPrefix}
|
||||
'';
|
||||
|
||||
dontInstall = false;
|
||||
|
||||
doInstallCheck = true;
|
||||
|
||||
lcovFilter = [ "*/boost/*" "*-tab.*" ];
|
||||
|
||||
# We call `dot', and even though we just use it to
|
||||
# syntax-check generated dot files, it still requires some
|
||||
# fonts. So provide those.
|
||||
FONTCONFIG_FILE = texFunctions.fontsConf;
|
||||
};
|
||||
|
||||
|
||||
rpm_fedora13i386 = makeRPM_i686 (diskImageFuns: diskImageFuns.fedora13i386) 50;
|
||||
rpm_fedora13x86_64 = makeRPM_x86_64 (diskImageFunsFun: diskImageFunsFun.fedora13x86_64) 50;
|
||||
rpm_fedora16i386 = makeRPM_i686 (diskImageFuns: diskImageFuns.fedora16i386) 50;
|
||||
rpm_fedora16x86_64 = makeRPM_x86_64 (diskImageFunsFun: diskImageFunsFun.fedora16x86_64) 50;
|
||||
|
||||
|
||||
deb_debian60i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.debian60i386) 50;
|
||||
deb_debian60x86_64 = makeDeb_x86_64 (diskImageFunsFun: diskImageFunsFun.debian60x86_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;
|
||||
deb_ubuntu1110i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1110i386) 60;
|
||||
deb_ubuntu1110x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1110x86_64) 60;
|
||||
deb_ubuntu1204i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1204i386) 60;
|
||||
deb_ubuntu1204x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1204x86_64) 60;
|
||||
deb_ubuntu1210i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1210i386) 70;
|
||||
deb_ubuntu1210x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1210x86_64) 70;
|
||||
|
||||
|
||||
# System tests.
|
||||
tests.remote_builds = (import ./tests/remote-builds.nix rec {
|
||||
nix = build { inherit system; }; system = "x86_64-linux";
|
||||
}).test;
|
||||
|
||||
tests.nix_copy_closure = (import ./tests/nix-copy-closure.nix rec {
|
||||
nix = build { inherit system; }; system = "x86_64-linux";
|
||||
}).test;
|
||||
|
||||
};
|
||||
|
||||
|
||||
makeRPM_i686 = makeRPM "i686-linux";
|
||||
makeRPM_x86_64 = makeRPM "x86_64-linux";
|
||||
|
||||
makeRPM =
|
||||
system: diskImageFun: prio:
|
||||
|
||||
with import nixpkgs { inherit system; };
|
||||
|
||||
releaseTools.rpmBuild rec {
|
||||
name = "nix-rpm";
|
||||
src = jobs.tarball;
|
||||
diskImage = (diskImageFun vmTools.diskImageFuns)
|
||||
{ extraPackages = [ "perl-DBD-SQLite" "perl-devel" "sqlite" "sqlite-devel" "bzip2-devel" "emacs" "perl-WWW-Curl" ]; };
|
||||
memSize = 1024;
|
||||
meta.schedulingPriority = prio;
|
||||
postRPMInstall = "cd /tmp/rpmout/BUILD/nix-* && make installcheck";
|
||||
};
|
||||
|
||||
|
||||
makeDeb_i686 = makeDeb "i686-linux";
|
||||
makeDeb_x86_64 = makeDeb "x86_64-linux";
|
||||
|
||||
makeDeb =
|
||||
system: diskImageFun: prio:
|
||||
|
||||
with import nixpkgs { inherit system; };
|
||||
|
||||
releaseTools.debBuild {
|
||||
name = "nix-deb";
|
||||
src = jobs.tarball;
|
||||
diskImage = (diskImageFun vmTools.diskImageFuns)
|
||||
{ extraPackages = [ "libdbd-sqlite3-perl" "libsqlite3-dev" "libbz2-dev" "libwww-curl-perl" ]; };
|
||||
memSize = 1024;
|
||||
meta.schedulingPriority = prio;
|
||||
configureFlags = "--sysconfdir=/etc";
|
||||
debRequires = [ "curl" "libdbd-sqlite3-perl" "libsqlite3-0" "libbz2-1.0" "bzip2" "xz-utils" ];
|
||||
doInstallCheck = true;
|
||||
};
|
||||
|
||||
|
||||
in jobs
|
||||
@@ -1,9 +1,38 @@
|
||||
bin_SCRIPTS = nix-switch nix-collect-garbage \
|
||||
nix-pull-prebuilts nix-push-prebuilts
|
||||
bin_SCRIPTS = nix-collect-garbage \
|
||||
nix-pull nix-push nix-prefetch-url \
|
||||
nix-install-package nix-channel nix-build \
|
||||
nix-copy-closure nix-generate-patches
|
||||
|
||||
install-exec-local:
|
||||
$(INSTALL) -d $(sysconfdir)/profile.d
|
||||
$(INSTALL_PROGRAM) nix-profile.sh $(sysconfdir)/profile.d/nix.sh
|
||||
$(INSTALL) -d $(sysconfdir)/nix
|
||||
# !!! don't overwrite local modifications
|
||||
$(INSTALL_PROGRAM) prebuilts.conf $(sysconfdir)/nix/prebuilts.conf
|
||||
noinst_SCRIPTS = nix-profile.sh \
|
||||
find-runtime-roots.pl build-remote.pl nix-reduce-build \
|
||||
copy-from-other-stores.pl nix-http-export.cgi
|
||||
|
||||
install-exec-local: download-using-manifests.pl copy-from-other-stores.pl download-from-binary-cache.pl find-runtime-roots.pl
|
||||
$(INSTALL) -d $(DESTDIR)$(sysconfdir)/profile.d
|
||||
$(INSTALL_DATA) nix-profile.sh $(DESTDIR)$(sysconfdir)/profile.d/nix.sh
|
||||
$(INSTALL) -d $(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
|
||||
$(INSTALL_PROGRAM) download-using-manifests.pl copy-from-other-stores.pl download-from-binary-cache.pl $(DESTDIR)$(libexecdir)/nix/substituters
|
||||
$(INSTALL) -d $(DESTDIR)$(sysconfdir)/nix
|
||||
|
||||
include ../substitute.mk
|
||||
|
||||
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 \
|
||||
nix-build.in \
|
||||
download-using-manifests.pl.in \
|
||||
copy-from-other-stores.pl.in \
|
||||
download-from-binary-cache.pl.in \
|
||||
nix-copy-closure.in \
|
||||
find-runtime-roots.pl.in \
|
||||
build-remote.pl.in \
|
||||
nix-reduce-build.in \
|
||||
nix-http-export.cgi.in \
|
||||
nix-generate-patches.in
|
||||
|
||||
clean:
|
||||
rm -f $(bin_SCRIPTS) $(noinst_SCRIPTS)
|
||||
|
||||
299
scripts/build-remote.pl.in
Executable file
299
scripts/build-remote.pl.in
Executable file
@@ -0,0 +1,299 @@
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use Fcntl qw(:DEFAULT :flock);
|
||||
use English '-no_match_vars';
|
||||
use IO::Handle;
|
||||
use Nix::Config;
|
||||
use Nix::SSH qw/sshOpts openSSHConnection/;
|
||||
use Nix::CopyClosure;
|
||||
use Nix::Store;
|
||||
no warnings('once');
|
||||
|
||||
|
||||
# General operation:
|
||||
#
|
||||
# Try to find a free machine of type $neededSystem. We do this as
|
||||
# follows:
|
||||
# - We acquire an exclusive lock on $currentLoad/main-lock.
|
||||
# - For each machine $machine of type $neededSystem and for each $slot
|
||||
# less than the maximum load for that machine, we try to get an
|
||||
# exclusive lock on $currentLoad/$machine-$slot (without blocking).
|
||||
# If we get such a lock, we send "accept" to the caller. Otherwise,
|
||||
# we send "postpone" and exit.
|
||||
# - We release the exclusive lock on $currentLoad/main-lock.
|
||||
# - We perform the build on $neededSystem.
|
||||
# - We release the exclusive lock on $currentLoad/$machine-$slot.
|
||||
#
|
||||
# The nice thing about this scheme is that if we die prematurely, the
|
||||
# locks are released automatically.
|
||||
|
||||
|
||||
# Make sure that we don't get any SSH passphrase or host key popups -
|
||||
# if there is any problem it should fail, not do something
|
||||
# interactive.
|
||||
$ENV{"DISPLAY"} = "";
|
||||
$ENV{"SSH_ASKPASS"} = "";
|
||||
|
||||
|
||||
sub sendReply {
|
||||
my $reply = shift;
|
||||
print STDERR "# $reply\n";
|
||||
}
|
||||
|
||||
sub all { $_ || return 0 for @_; 1 }
|
||||
|
||||
|
||||
# Initialisation.
|
||||
my $loadIncreased = 0;
|
||||
|
||||
my ($localSystem, $maxSilentTime, $printBuildTrace, $buildTimeout) = @ARGV;
|
||||
|
||||
my $currentLoad = $ENV{"NIX_CURRENT_LOAD"};
|
||||
my $conf = $ENV{"NIX_REMOTE_SYSTEMS"};
|
||||
|
||||
|
||||
sub openSlotLock {
|
||||
my ($machine, $slot) = @_;
|
||||
my $slotLockFn = "$currentLoad/" . (join '+', @{$machine->{systemTypes}}) . "-" . $machine->{hostName} . "-$slot";
|
||||
my $slotLock = new IO::Handle;
|
||||
sysopen $slotLock, "$slotLockFn", O_RDWR|O_CREAT, 0600 or die;
|
||||
return $slotLock;
|
||||
}
|
||||
|
||||
|
||||
# Read the list of machines.
|
||||
my @machines;
|
||||
if (defined $conf && -e $conf) {
|
||||
open CONF, "<$conf" or die;
|
||||
while (<CONF>) {
|
||||
chomp;
|
||||
s/\#.*$//g;
|
||||
next if /^\s*$/;
|
||||
my @tokens = split /\s/, $_;
|
||||
my @supportedFeatures = split(/,/, $tokens[5] || "");
|
||||
my @mandatoryFeatures = split(/,/, $tokens[6] || "");
|
||||
push @machines,
|
||||
{ hostName => $tokens[0]
|
||||
, systemTypes => [ split(/,/, $tokens[1]) ]
|
||||
, sshKeys => $tokens[2]
|
||||
, maxJobs => int($tokens[3])
|
||||
, speedFactor => 1.0 * (defined $tokens[4] ? int($tokens[4]) : 1)
|
||||
, supportedFeatures => [ @supportedFeatures, @mandatoryFeatures ]
|
||||
, mandatoryFeatures => [ @mandatoryFeatures ]
|
||||
, enabled => 1
|
||||
};
|
||||
}
|
||||
close CONF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Wait for the calling process to ask us whether we can build some derivation.
|
||||
my ($drvPath, $hostName, $slotLock);
|
||||
|
||||
REQ: while (1) {
|
||||
$_ = <STDIN> || exit 0;
|
||||
(my $amWilling, my $neededSystem, $drvPath, my $requiredFeatures) = split;
|
||||
my @requiredFeatures = split /,/, $requiredFeatures;
|
||||
|
||||
my $canBuildLocally = $amWilling && ($localSystem eq $neededSystem);
|
||||
|
||||
if (!defined $currentLoad) {
|
||||
sendReply "decline";
|
||||
next;
|
||||
}
|
||||
|
||||
# Acquire the exclusive lock on $currentLoad/main-lock.
|
||||
mkdir $currentLoad, 0777 or die unless -d $currentLoad;
|
||||
my $mainLock = "$currentLoad/main-lock";
|
||||
sysopen MAINLOCK, "$mainLock", O_RDWR|O_CREAT, 0600 or die;
|
||||
flock(MAINLOCK, LOCK_EX) or die;
|
||||
|
||||
|
||||
while (1) {
|
||||
# Find all machine that can execute this build, i.e., that
|
||||
# support builds for the given platform and features, and are
|
||||
# not at their job limit.
|
||||
my $rightType = 0;
|
||||
my @available = ();
|
||||
LOOP: foreach my $cur (@machines) {
|
||||
if ($cur->{enabled}
|
||||
&& (grep { $neededSystem eq $_ } @{$cur->{systemTypes}})
|
||||
&& all(map { my $f = $_; 0 != grep { $f eq $_ } @{$cur->{supportedFeatures}} } (@requiredFeatures, @mandatoryFeatures))
|
||||
&& all(map { my $f = $_; 0 != grep { $f eq $_ } @requiredFeatures } @{$cur->{mandatoryFeatures}})
|
||||
)
|
||||
{
|
||||
$rightType = 1;
|
||||
|
||||
# We have a machine of the right type. Determine the load on
|
||||
# the machine.
|
||||
my $slot = 0;
|
||||
my $load = 0;
|
||||
my $free;
|
||||
while ($slot < $cur->{maxJobs}) {
|
||||
my $slotLock = openSlotLock($cur, $slot);
|
||||
if (flock($slotLock, LOCK_EX | LOCK_NB)) {
|
||||
$free = $slot unless defined $free;
|
||||
flock($slotLock, LOCK_UN) or die;
|
||||
} else {
|
||||
$load++;
|
||||
}
|
||||
close $slotLock;
|
||||
$slot++;
|
||||
}
|
||||
|
||||
push @available, { machine => $cur, load => $load, free => $free }
|
||||
if $load < $cur->{maxJobs};
|
||||
}
|
||||
}
|
||||
|
||||
if (defined $ENV{NIX_DEBUG_HOOK}) {
|
||||
print STDERR "load on " . $_->{machine}->{hostName} . " = " . $_->{load} . "\n"
|
||||
foreach @available;
|
||||
}
|
||||
|
||||
|
||||
# Didn't find any available machine? Then decline or postpone.
|
||||
if (scalar @available == 0) {
|
||||
# Postpone if we have a machine of the right type, except
|
||||
# if the local system can and wants to do the build.
|
||||
if ($rightType && !$canBuildLocally) {
|
||||
sendReply "postpone";
|
||||
} else {
|
||||
sendReply "decline";
|
||||
}
|
||||
close MAINLOCK;
|
||||
next REQ;
|
||||
}
|
||||
|
||||
|
||||
# Prioritise the available machines as follows:
|
||||
# - First by load divided by speed factor, rounded to the nearest
|
||||
# integer. This causes fast machines to be preferred over slow
|
||||
# machines with similar loads.
|
||||
# - Then by speed factor.
|
||||
# - Finally by load.
|
||||
sub lf { my $x = shift; return int($x->{load} / $x->{machine}->{speedFactor} + 0.4999); }
|
||||
@available = sort
|
||||
{ lf($a) <=> lf($b)
|
||||
|| $b->{machine}->{speedFactor} <=> $a->{machine}->{speedFactor}
|
||||
|| $a->{load} <=> $b->{load}
|
||||
} @available;
|
||||
|
||||
|
||||
# Select the best available machine and lock a free slot.
|
||||
my $selected = $available[0];
|
||||
my $machine = $selected->{machine};
|
||||
|
||||
$slotLock = openSlotLock($machine, $selected->{free});
|
||||
flock($slotLock, LOCK_EX | LOCK_NB) or die;
|
||||
utime undef, undef, $slotLock;
|
||||
|
||||
close MAINLOCK;
|
||||
|
||||
|
||||
# Connect to the selected machine.
|
||||
@sshOpts = ("-i", $machine->{sshKeys}, "-x");
|
||||
$hostName = $machine->{hostName};
|
||||
last REQ if openSSHConnection $hostName;
|
||||
|
||||
warn "unable to open SSH connection to $hostName, trying other available machines...\n";
|
||||
$machine->{enabled} = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Tell Nix we've accepted the build.
|
||||
sendReply "accept";
|
||||
my @inputs = split /\s/, readline(STDIN);
|
||||
my @outputs = split /\s/, readline(STDIN);
|
||||
|
||||
|
||||
print STDERR "building `$drvPath' on `$hostName'\n";
|
||||
print STDERR "@ build-remote $drvPath $hostName\n" if $printBuildTrace;
|
||||
|
||||
|
||||
my $maybeSign = "";
|
||||
$maybeSign = "--sign" if -e "$Nix::Config::confDir/signing-key.sec";
|
||||
|
||||
|
||||
# Register the derivation as a temporary GC root. Note that $PPID is
|
||||
# the PID of the remote SSH process, which, due to the use of a
|
||||
# persistant SSH connection, should be the same across all remote
|
||||
# command invocations for this session.
|
||||
my $rootsDir = "@localstatedir@/nix/gcroots/tmp";
|
||||
system("ssh $hostName @sshOpts 'mkdir -m 1777 -p $rootsDir; ln -sfn $drvPath $rootsDir/\$PPID.drv'");
|
||||
|
||||
sub removeRoots {
|
||||
system("ssh $hostName @sshOpts 'rm -f $rootsDir/\$PPID.drv $rootsDir/\$PPID.out'");
|
||||
}
|
||||
|
||||
|
||||
# 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 UPLOADLOCK, "$uploadLock", O_RDWR|O_CREAT, 0600 or die;
|
||||
eval {
|
||||
local $SIG{ALRM} = sub { die "alarm\n" };
|
||||
# Don't wait forever, so that a process that gets stuck while
|
||||
# holding the lock doesn't block everybody else indefinitely.
|
||||
# It's safe to continue after a timeout, just (potentially)
|
||||
# inefficient.
|
||||
alarm 15 * 60;
|
||||
flock(UPLOADLOCK, LOCK_EX);
|
||||
alarm 0;
|
||||
};
|
||||
if ($@) {
|
||||
die unless $@ eq "alarm\n";
|
||||
print STDERR "somebody is hogging $uploadLock, continuing...\n";
|
||||
unlink $uploadLock;
|
||||
}
|
||||
Nix::CopyClosure::copyTo($hostName, [ @sshOpts ], [ $drvPath, @inputs ], "", "", 0, 0, $maybeSign ne "", "");
|
||||
close UPLOADLOCK;
|
||||
|
||||
|
||||
# Perform the build.
|
||||
my $buildFlags =
|
||||
"--max-silent-time $maxSilentTime --option build-timeout $buildTimeout "
|
||||
. "--fallback --add-root $rootsDir/\$PPID.out --option verbosity 0";
|
||||
|
||||
# We let the remote side kill its process group when the connection is
|
||||
# closed unexpectedly. This is necessary to ensure that no processes
|
||||
# are left running on the remote system if the local Nix process is
|
||||
# killed. (SSH itself doesn't kill child processes if the connection
|
||||
# is interrupted unless the `-tt' flag is used to force a pseudo-tty,
|
||||
# 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("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
|
||||
# allow it to distinguish between transient and permanent
|
||||
# failures.
|
||||
my $res = $? >> 8;
|
||||
print STDERR "build of `$drvPath' on `$hostName' failed with exit code $res\n";
|
||||
removeRoots;
|
||||
exit $res;
|
||||
}
|
||||
|
||||
#print "build of `$drvPath' on `$hostName' succeeded\n";
|
||||
|
||||
|
||||
# Copy the output from the build machine.
|
||||
foreach my $output (@outputs) {
|
||||
my $maybeSignRemote = "";
|
||||
$maybeSignRemote = "--sign" if $UID != 0;
|
||||
next if isValidPath($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: $?";
|
||||
}
|
||||
|
||||
|
||||
# Get rid of the temporary GC roots.
|
||||
removeRoots;
|
||||
98
scripts/copy-from-other-stores.pl.in
Executable file
98
scripts/copy-from-other-stores.pl.in
Executable file
@@ -0,0 +1,98 @@
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use strict;
|
||||
use File::Basename;
|
||||
use IO::Handle;
|
||||
|
||||
my $binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
|
||||
|
||||
|
||||
STDOUT->autoflush(1);
|
||||
|
||||
my @remoteStoresAll = split ':', ($ENV{"NIX_OTHER_STORES"} or "");
|
||||
|
||||
my @remoteStores;
|
||||
foreach my $dir (@remoteStoresAll) {
|
||||
push @remoteStores, glob($dir);
|
||||
}
|
||||
|
||||
|
||||
$ENV{"NIX_REMOTE"} = "";
|
||||
|
||||
|
||||
sub findStorePath {
|
||||
my $storePath = shift;
|
||||
foreach my $store (@remoteStores) {
|
||||
my $sourcePath = "$store/store/" . basename $storePath;
|
||||
next unless -e $sourcePath || -l $sourcePath;
|
||||
$ENV{"NIX_DB_DIR"} = "$store/var/nix/db";
|
||||
return ($store, $sourcePath) if
|
||||
system("@bindir@/nix-store --check-validity $storePath") == 0;
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
if ($ARGV[0] eq "--query") {
|
||||
|
||||
while (<STDIN>) {
|
||||
chomp;
|
||||
my ($cmd, @args) = split " ", $_;
|
||||
|
||||
if ($cmd eq "have") {
|
||||
foreach my $storePath (@args) {
|
||||
print "$storePath\n" if defined findStorePath($storePath);
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
|
||||
elsif ($cmd eq "info") {
|
||||
foreach my $storePath (@args) {
|
||||
my ($store, $sourcePath) = findStorePath($storePath);
|
||||
next unless defined $store;
|
||||
|
||||
$ENV{"NIX_DB_DIR"} = "$store/var/nix/db";
|
||||
|
||||
my $deriver = `@bindir@/nix-store --query --deriver $storePath`;
|
||||
die "cannot query deriver of `$storePath'" if $? != 0;
|
||||
chomp $deriver;
|
||||
$deriver = "" if $deriver eq "unknown-deriver";
|
||||
|
||||
my @references = split "\n",
|
||||
`@bindir@/nix-store --query --references $storePath`;
|
||||
die "cannot query references of `$storePath'" if $? != 0;
|
||||
|
||||
my $narSize = `@bindir@/nix-store --query --size $storePath`;
|
||||
die "cannot query size of `$storePath'" if $? != 0;
|
||||
chomp $narSize;
|
||||
|
||||
print "$storePath\n";
|
||||
print "$deriver\n";
|
||||
print scalar @references, "\n";
|
||||
print "$_\n" foreach @references;
|
||||
print "$narSize\n";
|
||||
print "$narSize\n";
|
||||
}
|
||||
|
||||
print "\n";
|
||||
}
|
||||
|
||||
else { die "unknown command `$cmd'"; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
elsif ($ARGV[0] eq "--substitute") {
|
||||
die unless scalar @ARGV == 3;
|
||||
my $storePath = $ARGV[1];
|
||||
my $destPath = $ARGV[2];
|
||||
my ($store, $sourcePath) = findStorePath $storePath;
|
||||
die unless $store;
|
||||
print STDERR "\n*** Copying `$storePath' from `$sourcePath'\n\n";
|
||||
system("$binDir/nix-store --dump $sourcePath | $binDir/nix-store --restore $destPath") == 0
|
||||
or die "cannot copy `$sourcePath' to `$storePath'";
|
||||
print "\n"; # no hash to verify
|
||||
}
|
||||
|
||||
|
||||
else { die; }
|
||||
111
scripts/copying-collector.pl
Executable file
111
scripts/copying-collector.pl
Executable file
@@ -0,0 +1,111 @@
|
||||
#! /usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
|
||||
my @paths = `nix-store -qR /home/eelco/.nix-profile/bin/firefox`;
|
||||
|
||||
my %copyMap;
|
||||
my %rewriteMap;
|
||||
|
||||
|
||||
my $counter = 0;
|
||||
|
||||
foreach my $path (@paths) {
|
||||
chomp $path;
|
||||
|
||||
$path =~ /^(.*)\/([^-]+)-(.*)$/ or die "invalid store path `$path'";
|
||||
my $hash = $2;
|
||||
|
||||
# my $newHash = "deadbeef" . (sprintf "%024d", $counter++);
|
||||
my $newHash = "deadbeef" . substr($hash, 0, 24);
|
||||
my $newPath = "/home/eelco/chroot/$1/$newHash-$3";
|
||||
|
||||
die unless length $newHash == length $hash;
|
||||
|
||||
$copyMap{$path} = $newPath;
|
||||
$rewriteMap{$hash} = $newHash;
|
||||
}
|
||||
|
||||
|
||||
my %rewriteMap2;
|
||||
|
||||
|
||||
sub rewrite;
|
||||
sub rewrite {
|
||||
my $src = shift;
|
||||
my $dst = shift;
|
||||
|
||||
if (-l $dst) {
|
||||
|
||||
my $target = readlink $dst or die;
|
||||
|
||||
foreach my $srcHash (keys %rewriteMap2) {
|
||||
my $dstHash = $rewriteMap{$srcHash};
|
||||
print " $srcHash -> $dstHash\n";
|
||||
$target =~ s/$srcHash/$dstHash/g;
|
||||
}
|
||||
|
||||
unlink $dst or die;
|
||||
|
||||
symlink $target, $dst;
|
||||
|
||||
}
|
||||
|
||||
elsif (-f $dst) {
|
||||
|
||||
print "$dst\n";
|
||||
|
||||
foreach my $srcHash (keys %rewriteMap2) {
|
||||
my $dstHash = $rewriteMap{$srcHash};
|
||||
print " $srcHash -> $dstHash\n";
|
||||
|
||||
my @stats = lstat $dst or die;
|
||||
|
||||
system "sed s/$srcHash/$dstHash/g < '$dst' > '$dst.tmp'";
|
||||
die if $? != 0;
|
||||
rename "$dst.tmp", $dst or die;
|
||||
|
||||
chmod $stats[2], $dst or die;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
elsif (-d $dst) {
|
||||
|
||||
chmod 0755, $dst;
|
||||
|
||||
opendir(DIR, "$dst") or die "cannot open `$dst': $!";
|
||||
my @files = readdir DIR;
|
||||
closedir DIR;
|
||||
|
||||
foreach my $file (@files) {
|
||||
next if $file eq "." || $file eq "..";
|
||||
rewrite "$src/$file", "$dst/$file";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach my $src (keys %copyMap) {
|
||||
my $dst = $copyMap{$src};
|
||||
print "$src -> $dst\n";
|
||||
|
||||
if (!-e $dst) {
|
||||
system "cp -prd $src $dst";
|
||||
die if $? != 0;
|
||||
|
||||
my @refs = `nix-store -q --references $src`;
|
||||
|
||||
%rewriteMap2 = ();
|
||||
foreach my $ref (@refs) {
|
||||
chomp $ref;
|
||||
|
||||
$ref =~ /^(.*)\/([^-]+)-(.*)$/ or die "invalid store path `$ref'";
|
||||
my $hash = $2;
|
||||
|
||||
$rewriteMap2{$hash} = $rewriteMap{$hash};
|
||||
}
|
||||
|
||||
rewrite $src, $dst;
|
||||
}
|
||||
}
|
||||
550
scripts/download-from-binary-cache.pl.in
Normal file
550
scripts/download-from-binary-cache.pl.in
Normal file
@@ -0,0 +1,550 @@
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use DBI;
|
||||
use File::Basename;
|
||||
use IO::Select;
|
||||
use Nix::Config;
|
||||
use Nix::Store;
|
||||
use Nix::Utils;
|
||||
use Nix::Manifest;
|
||||
use WWW::Curl::Easy;
|
||||
use WWW::Curl::Multi;
|
||||
use strict;
|
||||
|
||||
|
||||
Nix::Config::readConfig;
|
||||
|
||||
my @caches;
|
||||
my $gotCaches = 0;
|
||||
|
||||
my $maxParallelRequests = int($Nix::Config::config{"binary-caches-parallel-connections"} // 150);
|
||||
$maxParallelRequests = 1 if $maxParallelRequests < 1;
|
||||
|
||||
my $ttlNegative = 24 * 3600; # when to purge negative lookups from the database
|
||||
my $ttlNegativeUse = 3600; # how long negative lookups are valid for non-"have" lookups
|
||||
my $didExpiration = 0;
|
||||
|
||||
my $debug = ($ENV{"NIX_DEBUG_SUBST"} // "") eq 1;
|
||||
open(STDERR, ">>/dev/tty") if $debug;
|
||||
|
||||
my ($dbh, $queryCache, $insertNAR, $queryNAR, $insertNARExistence, $queryNARExistence, $expireNARExistence);
|
||||
|
||||
my $curlm = WWW::Curl::Multi->new;
|
||||
my $activeRequests = 0;
|
||||
my $curlIdCount = 1;
|
||||
my %requests;
|
||||
my %scheduled;
|
||||
my $caBundle = $ENV{"CURL_CA_BUNDLE"} // $ENV{"OPENSSL_X509_CERT_FILE"};
|
||||
|
||||
|
||||
sub addRequest {
|
||||
my ($storePath, $url, $head) = @_;
|
||||
|
||||
my $curl = WWW::Curl::Easy->new;
|
||||
my $curlId = $curlIdCount++;
|
||||
$requests{$curlId} = { storePath => $storePath, url => $url, handle => $curl, content => "", type => $head ? "HEAD" : "GET" };
|
||||
|
||||
$curl->setopt(CURLOPT_PRIVATE, $curlId);
|
||||
$curl->setopt(CURLOPT_URL, $url);
|
||||
open (my $fh, ">", \$requests{$curlId}->{content});
|
||||
$curl->setopt(CURLOPT_WRITEDATA, $fh);
|
||||
$curl->setopt(CURLOPT_FOLLOWLOCATION, 1);
|
||||
$curl->setopt(CURLOPT_CAINFO, $caBundle) if defined $caBundle;
|
||||
$curl->setopt(CURLOPT_USERAGENT, "Nix/$Nix::Config::version");
|
||||
$curl->setopt(CURLOPT_NOBODY, 1) if $head;
|
||||
$curl->setopt(CURLOPT_FAILONERROR, 1);
|
||||
|
||||
if ($activeRequests >= $maxParallelRequests) {
|
||||
$scheduled{$curlId} = 1;
|
||||
} else {
|
||||
$curlm->add_handle($curl);
|
||||
$activeRequests++;
|
||||
}
|
||||
|
||||
return $requests{$curlId};
|
||||
}
|
||||
|
||||
|
||||
sub processRequests {
|
||||
while ($activeRequests) {
|
||||
my ($rfds, $wfds, $efds) = $curlm->fdset();
|
||||
#print STDERR "R = @{$rfds}, W = @{$wfds}, E = @{$efds}\n";
|
||||
|
||||
# Sleep until we can read or write some data.
|
||||
if (scalar @{$rfds} + scalar @{$wfds} + scalar @{$efds} > 0) {
|
||||
IO::Select->select(IO::Select->new(@{$rfds}), IO::Select->new(@{$wfds}), IO::Select->new(@{$efds}), 0.1);
|
||||
}
|
||||
|
||||
if ($curlm->perform() != $activeRequests) {
|
||||
while (my ($id, $result) = $curlm->info_read) {
|
||||
if ($id) {
|
||||
my $request = $requests{$id} or die;
|
||||
my $handle = $request->{handle};
|
||||
$request->{result} = $result;
|
||||
$request->{httpStatus} = $handle->getinfo(CURLINFO_RESPONSE_CODE);
|
||||
|
||||
print STDERR "$request->{type} on $request->{url} [$request->{result}, $request->{httpStatus}]\n" if $debug;
|
||||
|
||||
$activeRequests--;
|
||||
delete $request->{handle};
|
||||
|
||||
if (scalar(keys %scheduled) > 0) {
|
||||
my $id2 = (keys %scheduled)[0];
|
||||
$curlm->add_handle($requests{$id2}->{handle});
|
||||
$activeRequests++;
|
||||
delete $scheduled{$id2};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub initCache {
|
||||
my $dbPath = "$Nix::Config::stateDir/binary-cache-v2.sqlite";
|
||||
|
||||
unlink "$Nix::Config::stateDir/binary-cache-v1.sqlite";
|
||||
|
||||
# Open/create the database.
|
||||
$dbh = DBI->connect("dbi:SQLite:dbname=$dbPath", "", "")
|
||||
or die "cannot open database `$dbPath'";
|
||||
$dbh->{RaiseError} = 1;
|
||||
$dbh->{PrintError} = 0;
|
||||
|
||||
$dbh->sqlite_busy_timeout(60 * 60 * 1000);
|
||||
|
||||
$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 BinaryCaches (
|
||||
id integer primary key autoincrement not null,
|
||||
url text unique not null,
|
||||
timestamp integer not null,
|
||||
storeDir text not null,
|
||||
wantMassQuery integer not null,
|
||||
priority integer not null
|
||||
);
|
||||
EOF
|
||||
|
||||
$dbh->do(<<EOF);
|
||||
create table if not exists NARs (
|
||||
cache integer not null,
|
||||
storePath text not null,
|
||||
url text not null,
|
||||
compression text not null,
|
||||
fileHash text,
|
||||
fileSize integer,
|
||||
narHash text,
|
||||
narSize integer,
|
||||
refs text,
|
||||
deriver text,
|
||||
system text,
|
||||
timestamp integer not null,
|
||||
primary key (cache, storePath),
|
||||
foreign key (cache) references BinaryCaches(id) on delete cascade
|
||||
);
|
||||
EOF
|
||||
|
||||
$dbh->do(<<EOF);
|
||||
create table if not exists NARExistence (
|
||||
cache integer not null,
|
||||
storePath text not null,
|
||||
exist integer not null,
|
||||
timestamp integer not null,
|
||||
primary key (cache, storePath),
|
||||
foreign key (cache) references BinaryCaches(id) on delete cascade
|
||||
);
|
||||
EOF
|
||||
|
||||
$dbh->do("create index if not exists NARExistenceByExistTimestamp on NARExistence (exist, timestamp)");
|
||||
|
||||
$queryCache = $dbh->prepare("select id, storeDir, wantMassQuery, priority from BinaryCaches where url = ?") or die;
|
||||
|
||||
$insertNAR = $dbh->prepare(
|
||||
"insert or replace into NARs(cache, storePath, url, compression, fileHash, fileSize, narHash, " .
|
||||
"narSize, refs, deriver, system, timestamp) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") or die;
|
||||
|
||||
$queryNAR = $dbh->prepare("select * from NARs where cache = ? and storePath = ?") or die;
|
||||
|
||||
$insertNARExistence = $dbh->prepare(
|
||||
"insert or replace into NARExistence(cache, storePath, exist, timestamp) values (?, ?, ?, ?)") or die;
|
||||
|
||||
$queryNARExistence = $dbh->prepare("select exist, timestamp from NARExistence where cache = ? and storePath = ?") or die;
|
||||
|
||||
$expireNARExistence = $dbh->prepare("delete from NARExistence where exist = ? and timestamp < ?") or die;
|
||||
}
|
||||
|
||||
|
||||
sub getAvailableCaches {
|
||||
return if $gotCaches;
|
||||
$gotCaches = 1;
|
||||
|
||||
return if
|
||||
($Nix::Config::config{"use-binary-caches"} // "true") eq "false" ||
|
||||
($Nix::Config::config{"untrusted-use-binary-caches"} // "true") eq "false";
|
||||
|
||||
sub strToList {
|
||||
my ($s) = @_;
|
||||
return map { s/\/+$//; $_ } split(/ /, $s);
|
||||
}
|
||||
|
||||
my @urls = strToList ($Nix::Config::config{"binary-caches"} // "");
|
||||
# // ($Nix::Config::storeDir eq "/nix/store" ? "http://nixos.org/binary-cache" : ""));
|
||||
|
||||
my $urlsFiles = $Nix::Config::config{"binary-cache-files"}
|
||||
// "/nix/var/nix/profiles/per-user/root/channels/binary-caches/*";
|
||||
foreach my $urlFile (glob $urlsFiles) {
|
||||
next unless -f $urlFile;
|
||||
open FILE, "<$urlFile" or die "cannot open ‘$urlFile’\n";
|
||||
my $url = <FILE>; chomp $url;
|
||||
close FILE;
|
||||
push @urls, strToList($url);
|
||||
}
|
||||
|
||||
# Allow Nix daemon users to override the binary caches to a subset
|
||||
# of those listed in the config file. Note that ‘untrusted-*’
|
||||
# denotes options passed by the client.
|
||||
if (defined $Nix::Config::config{"untrusted-binary-caches"}) {
|
||||
my @untrustedUrls = strToList $Nix::Config::config{"untrusted-binary-caches"};
|
||||
my @trustedUrls = uniq(@urls, strToList($Nix::Config::config{"trusted-binary-caches"} // ""));
|
||||
@urls = ();
|
||||
foreach my $url (@untrustedUrls) {
|
||||
die "binary cache ‘$url’ is not trusted (please add it to ‘trusted-binary-caches’ [@trustedUrls] in $Nix::Config::confDir/nix.conf)\n"
|
||||
unless scalar(grep { $url eq $_ } @trustedUrls) > 0;
|
||||
push @urls, $url;
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $url (uniq @urls) {
|
||||
|
||||
# FIXME: not atomic.
|
||||
$queryCache->execute($url);
|
||||
my $res = $queryCache->fetchrow_hashref();
|
||||
if (defined $res) {
|
||||
next if $res->{storeDir} ne $Nix::Config::storeDir;
|
||||
push @caches, { id => $res->{id}, url => $url, wantMassQuery => $res->{wantMassQuery}, priority => $res->{priority} };
|
||||
next;
|
||||
}
|
||||
|
||||
# Get the cache info file.
|
||||
my $request = addRequest(undef, $url . "/nix-cache-info");
|
||||
processRequests;
|
||||
|
||||
if ($request->{result} != 0) {
|
||||
print STDERR "could not download ‘$request->{url}’ (" .
|
||||
($request->{result} != 0 ? "Curl error $request->{result}" : "HTTP status $request->{httpStatus}") . ")\n";
|
||||
next;
|
||||
}
|
||||
|
||||
my $storeDir = "/nix/store";
|
||||
my $wantMassQuery = 0;
|
||||
my $priority = 50;
|
||||
foreach my $line (split "\n", $request->{content}) {
|
||||
unless ($line =~ /^(.*): (.*)$/) {
|
||||
print STDERR "bad cache info file ‘$request->{url}’\n";
|
||||
return undef;
|
||||
}
|
||||
if ($1 eq "StoreDir") { $storeDir = $2; }
|
||||
elsif ($1 eq "WantMassQuery") { $wantMassQuery = int($2); }
|
||||
elsif ($1 eq "Priority") { $priority = int($2); }
|
||||
}
|
||||
|
||||
$dbh->do("insert into BinaryCaches(url, timestamp, storeDir, wantMassQuery, priority) values (?, ?, ?, ?, ?)",
|
||||
{}, $url, time(), $storeDir, $wantMassQuery, $priority);
|
||||
my $id = $dbh->last_insert_id("", "", "", "");
|
||||
next if $storeDir ne $Nix::Config::storeDir;
|
||||
push @caches, { id => $id, url => $url, wantMassQuery => $wantMassQuery, priority => $priority };
|
||||
}
|
||||
|
||||
@caches = sort { $a->{priority} <=> $b->{priority} } @caches;
|
||||
|
||||
expireNegative();
|
||||
}
|
||||
|
||||
|
||||
sub processNARInfo {
|
||||
my ($storePath, $cache, $request) = @_;
|
||||
|
||||
if ($request->{result} != 0) {
|
||||
if ($request->{result} != 37 && $request->{httpStatus} != 404) {
|
||||
print STDERR "could not download ‘$request->{url}’ (" .
|
||||
($request->{result} != 0 ? "Curl error $request->{result}" : "HTTP status $request->{httpStatus}") . ")\n";
|
||||
} else {
|
||||
$insertNARExistence->execute($cache->{id}, basename($storePath), 0, time())
|
||||
unless $request->{url} =~ /^file:/;
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
my $narInfo = parseNARInfo($storePath, $request->{content});
|
||||
return undef unless defined $narInfo;
|
||||
|
||||
# Cache the result.
|
||||
$insertNAR->execute(
|
||||
$cache->{id}, basename($storePath), $narInfo->{url}, $narInfo->{compression},
|
||||
$narInfo->{fileHash}, $narInfo->{fileSize}, $narInfo->{narHash}, $narInfo->{narSize},
|
||||
join(" ", @{$narInfo->{refs}}), $narInfo->{deriver}, $narInfo->{system}, time())
|
||||
unless $request->{url} =~ /^file:/;
|
||||
|
||||
return $narInfo;
|
||||
}
|
||||
|
||||
|
||||
sub getCachedInfoFrom {
|
||||
my ($storePath, $cache) = @_;
|
||||
|
||||
$queryNAR->execute($cache->{id}, basename($storePath));
|
||||
my $res = $queryNAR->fetchrow_hashref();
|
||||
return undef unless defined $res;
|
||||
|
||||
return
|
||||
{ url => $res->{url}
|
||||
, compression => $res->{compression}
|
||||
, fileHash => $res->{fileHash}
|
||||
, fileSize => $res->{fileSize}
|
||||
, narHash => $res->{narHash}
|
||||
, narSize => $res->{narSize}
|
||||
, refs => [ split " ", $res->{refs} ]
|
||||
, deriver => $res->{deriver}
|
||||
} if defined $res;
|
||||
}
|
||||
|
||||
|
||||
sub negativeHit {
|
||||
my ($storePath, $cache) = @_;
|
||||
$queryNARExistence->execute($cache->{id}, basename($storePath));
|
||||
my $res = $queryNARExistence->fetchrow_hashref();
|
||||
return defined $res && $res->{exist} == 0 && time() - $res->{timestamp} < $ttlNegativeUse;
|
||||
}
|
||||
|
||||
|
||||
sub positiveHit {
|
||||
my ($storePath, $cache) = @_;
|
||||
return 1 if defined getCachedInfoFrom($storePath, $cache);
|
||||
$queryNARExistence->execute($cache->{id}, basename($storePath));
|
||||
my $res = $queryNARExistence->fetchrow_hashref();
|
||||
return defined $res && $res->{exist} == 1;
|
||||
}
|
||||
|
||||
|
||||
sub expireNegative {
|
||||
return if $didExpiration;
|
||||
$didExpiration = 1;
|
||||
my $time = time();
|
||||
# Round up to the next multiple of the TTL to ensure that we do
|
||||
# expiration only once per time interval. E.g. if $ttlNegative ==
|
||||
# 3600, we expire entries at most once per hour. This is
|
||||
# presumably faster than expiring a few entries per request (and
|
||||
# thus doing a transaction).
|
||||
my $limit = (int($time / $ttlNegative) - 1) * $ttlNegative;
|
||||
$expireNARExistence->execute($limit, 0);
|
||||
print STDERR "expired ", $expireNARExistence->rows, " negative entries\n" if $debug;
|
||||
}
|
||||
|
||||
|
||||
sub printInfo {
|
||||
my ($storePath, $info) = @_;
|
||||
print "$storePath\n";
|
||||
print $info->{deriver} ? "$Nix::Config::storeDir/$info->{deriver}" : "", "\n";
|
||||
print scalar @{$info->{refs}}, "\n";
|
||||
print "$Nix::Config::storeDir/$_\n" foreach @{$info->{refs}};
|
||||
print $info->{fileSize} || 0, "\n";
|
||||
print $info->{narSize} || 0, "\n";
|
||||
}
|
||||
|
||||
|
||||
sub infoUrl {
|
||||
my ($binaryCacheUrl, $storePath) = @_;
|
||||
my $pathHash = substr(basename($storePath), 0, 32);
|
||||
my $infoUrl = "$binaryCacheUrl/$pathHash.narinfo";
|
||||
}
|
||||
|
||||
|
||||
sub printInfoParallel {
|
||||
my @paths = @_;
|
||||
|
||||
# First print all paths for which we have cached info.
|
||||
my @left;
|
||||
foreach my $storePath (@paths) {
|
||||
my $found = 0;
|
||||
foreach my $cache (@caches) {
|
||||
my $info = getCachedInfoFrom($storePath, $cache);
|
||||
if (defined $info) {
|
||||
printInfo($storePath, $info);
|
||||
$found = 1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
push @left, $storePath if !$found;
|
||||
}
|
||||
|
||||
return if scalar @left == 0;
|
||||
|
||||
foreach my $cache (@caches) {
|
||||
|
||||
my @left2;
|
||||
%requests = ();
|
||||
foreach my $storePath (@left) {
|
||||
if (negativeHit($storePath, $cache)) {
|
||||
push @left2, $storePath;
|
||||
next;
|
||||
}
|
||||
addRequest($storePath, infoUrl($cache->{url}, $storePath));
|
||||
}
|
||||
|
||||
processRequests;
|
||||
|
||||
foreach my $request (values %requests) {
|
||||
my $info = processNARInfo($request->{storePath}, $cache, $request);
|
||||
if (defined $info) {
|
||||
printInfo($request->{storePath}, $info);
|
||||
} else {
|
||||
push @left2, $request->{storePath};
|
||||
}
|
||||
}
|
||||
|
||||
@left = @left2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub printSubstitutablePaths {
|
||||
my @paths = @_;
|
||||
|
||||
# First look for paths that have cached info.
|
||||
my @left;
|
||||
foreach my $storePath (@paths) {
|
||||
my $found = 0;
|
||||
foreach my $cache (@caches) {
|
||||
next unless $cache->{wantMassQuery};
|
||||
if (positiveHit($storePath, $cache)) {
|
||||
print "$storePath\n";
|
||||
$found = 1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
push @left, $storePath if !$found;
|
||||
}
|
||||
|
||||
return if scalar @left == 0;
|
||||
|
||||
# For remaining paths, do HEAD requests.
|
||||
foreach my $cache (@caches) {
|
||||
next unless $cache->{wantMassQuery};
|
||||
my @left2;
|
||||
%requests = ();
|
||||
foreach my $storePath (@left) {
|
||||
if (negativeHit($storePath, $cache)) {
|
||||
push @left2, $storePath;
|
||||
next;
|
||||
}
|
||||
addRequest($storePath, infoUrl($cache->{url}, $storePath), 1);
|
||||
}
|
||||
|
||||
processRequests;
|
||||
|
||||
foreach my $request (values %requests) {
|
||||
if ($request->{result} != 0) {
|
||||
if ($request->{result} != 37 && $request->{httpStatus} != 404) {
|
||||
print STDERR "could not check ‘$request->{url}’ (" .
|
||||
($request->{result} != 0 ? "Curl error $request->{result}" : "HTTP status $request->{httpStatus}") . ")\n";
|
||||
} else {
|
||||
$insertNARExistence->execute($cache->{id}, basename($request->{storePath}), 0, time())
|
||||
unless $request->{url} =~ /^file:/;
|
||||
}
|
||||
push @left2, $request->{storePath};
|
||||
} else {
|
||||
$insertNARExistence->execute($cache->{id}, basename($request->{storePath}), 1, time())
|
||||
unless $request->{url} =~ /^file:/;
|
||||
print "$request->{storePath}\n";
|
||||
}
|
||||
}
|
||||
|
||||
@left = @left2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub downloadBinary {
|
||||
my ($storePath, $destPath) = @_;
|
||||
|
||||
foreach my $cache (@caches) {
|
||||
my $info = getCachedInfoFrom($storePath, $cache);
|
||||
|
||||
unless (defined $info) {
|
||||
next if negativeHit($storePath, $cache);
|
||||
my $request = addRequest($storePath, infoUrl($cache->{url}, $storePath));
|
||||
processRequests;
|
||||
$info = processNARInfo($storePath, $cache, $request);
|
||||
}
|
||||
|
||||
next unless defined $info;
|
||||
|
||||
my $decompressor;
|
||||
if ($info->{compression} eq "bzip2") { $decompressor = "$Nix::Config::bzip2 -d"; }
|
||||
elsif ($info->{compression} eq "xz") { $decompressor = "$Nix::Config::xz -d"; }
|
||||
else {
|
||||
print STDERR "unknown compression method ‘$info->{compression}’\n";
|
||||
next;
|
||||
}
|
||||
my $url = "$cache->{url}/$info->{url}"; # FIXME: handle non-relative URLs
|
||||
print STDERR "\n*** Downloading ‘$url’ to ‘$storePath’...\n";
|
||||
checkURL $url;
|
||||
if (system("$Nix::Config::curl --fail --location --insecure '$url' | $decompressor | $Nix::Config::binDir/nix-store --restore $destPath") != 0) {
|
||||
warn "download of `$url' failed" . ($! ? ": $!" : "") . "\n";
|
||||
next;
|
||||
}
|
||||
|
||||
# Tell Nix about the expected hash so it can verify it.
|
||||
print "$info->{narHash}\n";
|
||||
|
||||
print STDERR "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
print STDERR "could not download ‘$storePath’ from any binary cache\n";
|
||||
}
|
||||
|
||||
|
||||
initCache();
|
||||
|
||||
|
||||
if ($ARGV[0] eq "--query") {
|
||||
|
||||
while (<STDIN>) {
|
||||
getAvailableCaches;
|
||||
chomp;
|
||||
my ($cmd, @args) = split " ", $_;
|
||||
|
||||
if ($cmd eq "have") {
|
||||
print STDERR "checking binary caches for existence of @args\n" if $debug;
|
||||
printSubstitutablePaths(@args);
|
||||
print "\n";
|
||||
}
|
||||
|
||||
elsif ($cmd eq "info") {
|
||||
print STDERR "checking binary caches for info on @args\n" if $debug;
|
||||
printInfoParallel(@args);
|
||||
print "\n";
|
||||
}
|
||||
|
||||
else { die "unknown command `$cmd'"; }
|
||||
|
||||
flush STDOUT;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
elsif ($ARGV[0] eq "--substitute") {
|
||||
my $storePath = $ARGV[1] or die;
|
||||
my $destPath = $ARGV[2] or die;
|
||||
getAvailableCaches;
|
||||
downloadBinary($storePath, $destPath);
|
||||
}
|
||||
|
||||
else {
|
||||
die;
|
||||
}
|
||||
374
scripts/download-using-manifests.pl.in
Executable file
374
scripts/download-using-manifests.pl.in
Executable file
@@ -0,0 +1,374 @@
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use strict;
|
||||
use Nix::Config;
|
||||
use Nix::Manifest;
|
||||
use Nix::Store;
|
||||
use Nix::Utils;
|
||||
use POSIX qw(strftime);
|
||||
use File::Temp qw(tempdir);
|
||||
|
||||
STDOUT->autoflush(1);
|
||||
|
||||
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;
|
||||
|
||||
# ‘--insecure’ is fine because Nix verifies the hash of the result.
|
||||
my $curl = "$Nix::Config::curl --fail --location --insecure";
|
||||
|
||||
|
||||
# Open the manifest cache and update it if necessary.
|
||||
my $dbh = updateManifestDB();
|
||||
|
||||
|
||||
# $hashCache->{$algo}->{$path} yields the $algo-hash of $path.
|
||||
my $hashCache;
|
||||
|
||||
|
||||
sub parseHash {
|
||||
my $hash = shift;
|
||||
if ($hash =~ /^(.+):(.+)$/) {
|
||||
return ($1, $2);
|
||||
} else {
|
||||
return ("md5", $hash);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Compute the most efficient sequence of downloads to produce the
|
||||
# given path.
|
||||
sub computeSmallestDownload {
|
||||
my $targetPath = shift;
|
||||
|
||||
# Build a graph of all store paths that might contribute to the
|
||||
# construction of $targetPath, and the special node "start". The
|
||||
# edges are either patch operations, or downloads of full NAR
|
||||
# files. The latter edges only occur between "start" and a store
|
||||
# path.
|
||||
my %graph;
|
||||
|
||||
$graph{"start"} = {d => 0, pred => undef, edges => []};
|
||||
|
||||
my @queue = ();
|
||||
my $queueFront = 0;
|
||||
my %done;
|
||||
|
||||
sub addNode {
|
||||
my $graph = shift;
|
||||
my $u = shift;
|
||||
$$graph{$u} = {d => 999999999999, pred => undef, edges => []}
|
||||
unless defined $$graph{$u};
|
||||
}
|
||||
|
||||
sub addEdge {
|
||||
my $graph = shift;
|
||||
my $u = shift;
|
||||
my $v = shift;
|
||||
my $w = shift;
|
||||
my $type = shift;
|
||||
my $info = shift;
|
||||
addNode $graph, $u;
|
||||
push @{$$graph{$u}->{edges}},
|
||||
{weight => $w, start => $u, end => $v, type => $type, info => $info};
|
||||
my $n = scalar @{$$graph{$u}->{edges}};
|
||||
}
|
||||
|
||||
push @queue, $targetPath;
|
||||
|
||||
while ($queueFront < scalar @queue) {
|
||||
my $u = $queue[$queueFront++];
|
||||
next if defined $done{$u};
|
||||
$done{$u} = 1;
|
||||
|
||||
addNode \%graph, $u;
|
||||
|
||||
# If the path already exists, it has distance 0 from the
|
||||
# "start" node.
|
||||
if (isValidPath($u)) {
|
||||
addEdge \%graph, "start", $u, 0, "present", undef;
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
# Add patch edges.
|
||||
my $patchList = $dbh->selectall_arrayref(
|
||||
"select * from Patches where storePath = ?",
|
||||
{ Slice => {} }, $u);
|
||||
|
||||
foreach my $patch (@{$patchList}) {
|
||||
if (isValidPath($patch->{basePath})) {
|
||||
my ($baseHashAlgo, $baseHash) = parseHash $patch->{baseHash};
|
||||
|
||||
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};
|
||||
addEdge \%graph, $patch->{basePath}, $u, $patch->{size}, "patch", $patch;
|
||||
}
|
||||
|
||||
# Add NAR file edges to the start node.
|
||||
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 GB).
|
||||
# This has the side-effect of preferring non-Hydra downloads.
|
||||
addEdge \%graph, "start", $u, ($narFile->{size} || 1000000000), "narfile", $narFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Run Dijkstra's shortest path algorithm to determine the shortest
|
||||
# sequence of download and/or patch actions that will produce
|
||||
# $targetPath.
|
||||
|
||||
my @todo = keys %graph;
|
||||
|
||||
while (scalar @todo > 0) {
|
||||
|
||||
# Remove the closest element from the todo list.
|
||||
# !!! inefficient, use a priority queue
|
||||
@todo = sort { -($graph{$a}->{d} <=> $graph{$b}->{d}) } @todo;
|
||||
my $u = pop @todo;
|
||||
|
||||
my $u_ = $graph{$u};
|
||||
|
||||
foreach my $edge (@{$u_->{edges}}) {
|
||||
my $v_ = $graph{$edge->{end}};
|
||||
if ($v_->{d} > $u_->{d} + $edge->{weight}) {
|
||||
$v_->{d} = $u_->{d} + $edge->{weight};
|
||||
# Store the edge; to edge->start is actually the
|
||||
# predecessor.
|
||||
$v_->{pred} = $edge;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Retrieve the shortest path from "start" to $targetPath.
|
||||
my @path = ();
|
||||
my $cur = $targetPath;
|
||||
return () unless defined $graph{$targetPath}->{pred};
|
||||
while ($cur ne "start") {
|
||||
push @path, $graph{$cur}->{pred};
|
||||
$cur = $graph{$cur}->{pred}->{start};
|
||||
}
|
||||
|
||||
return @path;
|
||||
}
|
||||
|
||||
|
||||
# Parse the arguments.
|
||||
|
||||
if ($ARGV[0] eq "--query") {
|
||||
|
||||
while (<STDIN>) {
|
||||
chomp;
|
||||
my ($cmd, @args) = split " ", $_;
|
||||
|
||||
if ($cmd eq "have") {
|
||||
foreach my $storePath (@args) {
|
||||
print "$storePath\n" if scalar @{$dbh->selectcol_arrayref("select 1 from NARs where storePath = ?", {}, $storePath)} > 0;
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
|
||||
elsif ($cmd eq "info") {
|
||||
foreach my $storePath (@args) {
|
||||
|
||||
my $infos = $dbh->selectall_arrayref(
|
||||
"select * from NARs where storePath = ?",
|
||||
{ Slice => {} }, $storePath);
|
||||
|
||||
next unless scalar @{$infos} > 0;
|
||||
my $info = @{$infos}[0];
|
||||
|
||||
print "$storePath\n";
|
||||
print "$info->{deriver}\n";
|
||||
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;
|
||||
my $u = $edge->{start};
|
||||
my $v = $edge->{end};
|
||||
if ($edge->{type} eq "patch") {
|
||||
$downloadSize += $edge->{info}->{size} || 0;
|
||||
}
|
||||
elsif ($edge->{type} eq "narfile") {
|
||||
$downloadSize += $edge->{info}->{size} || 0;
|
||||
}
|
||||
}
|
||||
|
||||
print "$downloadSize\n";
|
||||
|
||||
my $narSize = $info->{narSize} || 0;
|
||||
print "$narSize\n";
|
||||
}
|
||||
|
||||
print "\n";
|
||||
}
|
||||
|
||||
else { die "unknown command `$cmd'"; }
|
||||
}
|
||||
|
||||
exit 0;
|
||||
}
|
||||
|
||||
elsif ($ARGV[0] ne "--substitute") {
|
||||
die;
|
||||
}
|
||||
|
||||
|
||||
die unless scalar @ARGV == 3;
|
||||
my $targetPath = $ARGV[1];
|
||||
my $destPath = $ARGV[2];
|
||||
$fast = 0;
|
||||
|
||||
|
||||
# Create a temporary directory.
|
||||
my $tmpDir = tempdir("nix-download.XXXXXX", CLEANUP => 1, TMPDIR => 1)
|
||||
or die "cannot create a temporary directory";
|
||||
|
||||
my $tmpNar = "$tmpDir/nar";
|
||||
my $tmpNar2 = "$tmpDir/nar2";
|
||||
|
||||
|
||||
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 STDERR "\n*** Trying to download/patch `$targetPath'\n";
|
||||
|
||||
|
||||
# Compute the shortest path.
|
||||
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;
|
||||
my $maxStep = scalar @path;
|
||||
|
||||
my $finalNarHash;
|
||||
|
||||
while (scalar @path > 0) {
|
||||
my $edge = pop @path;
|
||||
my $u = $edge->{start};
|
||||
my $v = $edge->{end};
|
||||
|
||||
print STDERR "\n*** Step $curStep/$maxStep: ";
|
||||
|
||||
if ($edge->{type} eq "present") {
|
||||
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 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 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 STDERR " downloading patch...\n";
|
||||
my $patchPath = "$tmpDir/patch";
|
||||
checkURL $patch->{url};
|
||||
system("$curl '$patch->{url}' -o $patchPath") == 0
|
||||
or die "cannot download patch `$patch->{url}'\n";
|
||||
|
||||
# Apply the patch to the NAR archive produced in step 1 (for
|
||||
# the already present path) or a later step (for patch sequences).
|
||||
print STDERR " applying patch...\n";
|
||||
system("$Nix::Config::libexecDir/bspatch $tmpNar $tmpNar2 $patchPath") == 0
|
||||
or die "cannot apply patch `$patchPath' to $tmpNar\n";
|
||||
|
||||
if ($curStep < $maxStep) {
|
||||
# The archive will be used as the base of the next patch.
|
||||
rename "$tmpNar2", "$tmpNar" or die "cannot rename NAR archive: $!";
|
||||
} else {
|
||||
# This was the last patch. Unpack the final NAR archive
|
||||
# into the target path.
|
||||
print STDERR " unpacking patched archive...\n";
|
||||
system("$Nix::Config::binDir/nix-store --restore $destPath < $tmpNar2") == 0
|
||||
or die "cannot unpack $tmpNar2 to `$v'\n";
|
||||
}
|
||||
|
||||
$finalNarHash = $patch->{narHash};
|
||||
}
|
||||
|
||||
elsif ($edge->{type} eq "narfile") {
|
||||
my $narFile = $edge->{info};
|
||||
print STDERR "downloading `$narFile->{url}' to `$v'\n";
|
||||
|
||||
my $size = $narFile->{size} || -1;
|
||||
print LOGFILE "$$ narfile $narFile->{url} $size $v\n";
|
||||
|
||||
checkURL $narFile->{url};
|
||||
|
||||
my $decompressor =
|
||||
$narFile->{compressionType} eq "bzip2" ? "$Nix::Config::bzip2 -d" :
|
||||
$narFile->{compressionType} eq "xz" ? "$Nix::Config::xz -d" :
|
||||
die "unknown compression type `$narFile->{compressionType}'";
|
||||
|
||||
if ($curStep < $maxStep) {
|
||||
# The archive will be used a base to a patch.
|
||||
system("$curl '$narFile->{url}' | $decompressor > $tmpNar") == 0
|
||||
or die "cannot download and unpack `$narFile->{url}' to `$v'\n";
|
||||
} else {
|
||||
# Unpack the archive to the target path.
|
||||
system("$curl '$narFile->{url}' | $decompressor | $Nix::Config::binDir/nix-store --restore '$destPath'") == 0
|
||||
or die "cannot download and unpack `$narFile->{url}' to `$v'\n";
|
||||
}
|
||||
|
||||
$finalNarHash = $narFile->{narHash};
|
||||
}
|
||||
|
||||
$curStep++;
|
||||
}
|
||||
|
||||
|
||||
# Tell Nix about the expected hash so it can verify it.
|
||||
die "cannot check integrity of the downloaded path since its hash is not known\n"
|
||||
unless defined $finalNarHash;
|
||||
print "$finalNarHash\n";
|
||||
|
||||
|
||||
print STDERR "\n";
|
||||
print LOGFILE "$$ success\n";
|
||||
close LOGFILE;
|
||||
75
scripts/find-runtime-roots.pl.in
Executable file
75
scripts/find-runtime-roots.pl.in
Executable file
@@ -0,0 +1,75 @@
|
||||
#! @perl@ -w
|
||||
|
||||
use strict;
|
||||
|
||||
my $procDir = "/proc";
|
||||
|
||||
|
||||
sub readProc {
|
||||
return unless -d $procDir;
|
||||
|
||||
opendir DIR, $procDir or return;
|
||||
|
||||
foreach my $name (readdir DIR) {
|
||||
next unless $name =~ /^\d+$/;
|
||||
|
||||
my $process = "$procDir/$name";
|
||||
|
||||
#print STDERR "=== $process\n";
|
||||
|
||||
my $target;
|
||||
print "$target\n" if $target = readlink "$process/exe";
|
||||
print "$target\n" if $target = readlink "$process/cwd";
|
||||
|
||||
if (opendir FDS, "$process/fd") {
|
||||
foreach my $name (readdir FDS) {
|
||||
$target = readlink "$process/fd/$name";
|
||||
print "$target\n" if $target && substr($target, 0, 1) eq "/";
|
||||
}
|
||||
closedir FDS;
|
||||
}
|
||||
|
||||
if (open MAP, "<$process/maps") {
|
||||
while (<MAP>) {
|
||||
next unless /^ \s* \S+ \s+ \S+ \s+ \S+ \s+ \S+ \s+ \S+ \s+ (\/\S+) \s* $/x;
|
||||
print "$1\n";
|
||||
}
|
||||
close MAP;
|
||||
}
|
||||
}
|
||||
|
||||
closedir DIR;
|
||||
}
|
||||
|
||||
|
||||
sub lsof {
|
||||
return unless open LSOF, "lsof -n -w -F n 2> /dev/null |";
|
||||
|
||||
while (<LSOF>) {
|
||||
next unless /^n (\/ .*)$/x;
|
||||
print $1, "\n";
|
||||
}
|
||||
|
||||
close LSOF;
|
||||
}
|
||||
|
||||
|
||||
readProc;
|
||||
lsof;
|
||||
|
||||
|
||||
sub readFile {
|
||||
my $path = shift;
|
||||
if (-e $path) {
|
||||
if (open FILE, "$path") {
|
||||
while (<FILE>) {
|
||||
print;
|
||||
}
|
||||
close FILE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# This is rather NixOS-specific, so it probably shouldn't be here.
|
||||
readFile "/proc/sys/kernel/modprobe";
|
||||
readFile "/proc/sys/kernel/fbsplash";
|
||||
34
scripts/install-nix-from-closure.sh
Normal file
34
scripts/install-nix-from-closure.sh
Normal file
@@ -0,0 +1,34 @@
|
||||
#! /bin/sh -e
|
||||
|
||||
nix=@nix@
|
||||
regInfo=@regInfo@
|
||||
|
||||
if ! $nix/bin/nix-store --load-db < $regInfo; then
|
||||
echo "$0: unable to register valid paths"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
. @nix@/etc/profile.d/nix.sh
|
||||
|
||||
if ! $nix/bin/nix-env -i @nix@; then
|
||||
echo "$0: unable to install Nix into your default profile"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Add nix.sh to the shell's profile.d directory.
|
||||
p=$NIX_LINK/etc/profile.d/nix.sh
|
||||
|
||||
if [ -w /etc/profile.d ]; then
|
||||
ln -s $p /etc/profile.d/
|
||||
elif [ -w /usr/local/etc/profile.d ]; then
|
||||
ln -s $p /usr/local/etc/profile.d/
|
||||
else
|
||||
cat <<EOF
|
||||
Installation finished. To ensure that the necessary environment
|
||||
variables are set, please add the line
|
||||
|
||||
source $p
|
||||
|
||||
to your shell profile (e.g. ~/.profile).
|
||||
EOF
|
||||
fi
|
||||
223
scripts/nix-build.in
Executable file
223
scripts/nix-build.in
Executable file
@@ -0,0 +1,223 @@
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use strict;
|
||||
use Nix::Config;
|
||||
use Nix::Store;
|
||||
use File::Temp qw(tempdir);
|
||||
|
||||
|
||||
my $dryRun = 0;
|
||||
my $verbose = 0;
|
||||
my $runEnv = 0;
|
||||
|
||||
my @instArgs = ();
|
||||
my @buildArgs = ();
|
||||
my @exprs = ();
|
||||
|
||||
my $shell = $ENV{SHELL} || "/bin/sh";
|
||||
my $envCommand = "p=\$PATH; source \$stdenv/setup; PATH=\$PATH:\$p; exec $shell";
|
||||
my @envExclude = ();
|
||||
|
||||
|
||||
my $tmpDir = tempdir("nix-build.XXXXXX", CLEANUP => 1, TMPDIR => 1)
|
||||
or die "cannot create a temporary directory";
|
||||
|
||||
my $outLink = "./result";
|
||||
my $drvLink = "$tmpDir/derivation";
|
||||
|
||||
# Ensure that the $tmpDir is deleted.
|
||||
$SIG{'INT'} = sub { exit 1 };
|
||||
|
||||
|
||||
for (my $n = 0; $n < scalar @ARGV; $n++) {
|
||||
my $arg = $ARGV[$n];
|
||||
|
||||
if ($arg eq "--help") {
|
||||
exec "man nix-build" or die;
|
||||
}
|
||||
|
||||
elsif ($arg eq "--version") {
|
||||
print "nix-build (Nix) $Nix::Config::version\n";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
elsif ($arg eq "--add-drv-link") {
|
||||
$drvLink = "./derivation";
|
||||
}
|
||||
|
||||
elsif ($arg eq "--no-out-link" or $arg eq "--no-link") {
|
||||
$outLink = "$tmpDir/result";
|
||||
}
|
||||
|
||||
elsif ($arg eq "--drv-link") {
|
||||
$n++;
|
||||
die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV;
|
||||
$drvLink = $ARGV[$n];
|
||||
}
|
||||
|
||||
elsif ($arg eq "--out-link" or $arg eq "-o") {
|
||||
$n++;
|
||||
die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV;
|
||||
$outLink = $ARGV[$n];
|
||||
}
|
||||
|
||||
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, ($arg, $ARGV[$n]);
|
||||
}
|
||||
|
||||
elsif ($arg eq "--arg" || $arg eq "--argstr") {
|
||||
die "$0: `$arg' requires two arguments\n" unless $n + 2 < scalar @ARGV;
|
||||
push @instArgs, ($arg, $ARGV[$n + 1], $ARGV[$n + 2]);
|
||||
$n += 2;
|
||||
}
|
||||
|
||||
elsif ($arg eq "--log-type") {
|
||||
$n++;
|
||||
die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV;
|
||||
push @instArgs, ($arg, $ARGV[$n]);
|
||||
push @buildArgs, ($arg, $ARGV[$n]);
|
||||
}
|
||||
|
||||
elsif ($arg eq "--option") {
|
||||
die "$0: `$arg' requires two arguments\n" unless $n + 2 < scalar @ARGV;
|
||||
push @instArgs, ($arg, $ARGV[$n + 1], $ARGV[$n + 2]);
|
||||
push @buildArgs, ($arg, $ARGV[$n + 1], $ARGV[$n + 2]);
|
||||
$n += 2;
|
||||
}
|
||||
|
||||
elsif ($arg eq "--max-jobs" or $arg eq "-j" or $arg eq "--max-silent-time" or $arg eq "--log-type" or $arg eq "--cores") {
|
||||
$n++;
|
||||
die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV;
|
||||
push @buildArgs, ($arg, $ARGV[$n]);
|
||||
}
|
||||
|
||||
elsif ($arg eq "--dry-run") {
|
||||
push @buildArgs, "--dry-run";
|
||||
$dryRun = 1;
|
||||
}
|
||||
|
||||
elsif ($arg eq "--show-trace") {
|
||||
push @instArgs, $arg;
|
||||
}
|
||||
|
||||
elsif ($arg eq "-") {
|
||||
@exprs = ("-");
|
||||
}
|
||||
|
||||
elsif ($arg eq "--verbose" or substr($arg, 0, 2) eq "-v") {
|
||||
push @buildArgs, $arg;
|
||||
push @instArgs, $arg;
|
||||
$verbose = 1;
|
||||
}
|
||||
|
||||
elsif ($arg eq "--quiet" || $arg eq "--repair") {
|
||||
push @buildArgs, $arg;
|
||||
push @instArgs, $arg;
|
||||
}
|
||||
|
||||
elsif ($arg eq "--run-env") {
|
||||
$runEnv = 1;
|
||||
}
|
||||
|
||||
elsif ($arg eq "--command") {
|
||||
$n++;
|
||||
die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV;
|
||||
$envCommand = $ARGV[$n];
|
||||
}
|
||||
|
||||
elsif ($arg eq "--exclude") {
|
||||
$n++;
|
||||
die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV;
|
||||
push @envExclude, $ARGV[$n];
|
||||
}
|
||||
|
||||
elsif (substr($arg, 0, 1) eq "-") {
|
||||
push @buildArgs, $arg;
|
||||
}
|
||||
|
||||
else {
|
||||
push @exprs, $arg;
|
||||
}
|
||||
}
|
||||
|
||||
@exprs = ("./default.nix") if scalar @exprs == 0;
|
||||
|
||||
|
||||
foreach my $expr (@exprs) {
|
||||
|
||||
# Instantiate.
|
||||
my @drvPaths;
|
||||
# !!! would prefer the perl 5.8.0 pipe open feature here.
|
||||
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);
|
||||
exit 1;
|
||||
}
|
||||
|
||||
if ($runEnv) {
|
||||
die "$0: ‘--run-env’ requires a single derivation\n" if scalar @drvPaths != 1;
|
||||
my $drvPath = readlink $drvPaths[0] or die "cannot read symlink `$drvPaths[0]'";
|
||||
my $drv = derivationFromPath($drvPath);
|
||||
|
||||
# Build or fetch all dependencies of the derivation.
|
||||
my @inputDrvs = grep { my $x = $_; (grep { $x =~ $_ } @envExclude) == 0 } @{$drv->{inputDrvs}};
|
||||
system("$Nix::Config::binDir/nix-store -r @buildArgs @inputDrvs @{$drv->{inputSrcs}} > /dev/null") == 0
|
||||
or die "$0: failed to build all dependencies\n";
|
||||
|
||||
# Set the environment.
|
||||
$ENV{'NIX_BUILD_TOP'} = $ENV{'TMPDIR'} || "/tmp";
|
||||
foreach (keys %{$drv->{env}}) {
|
||||
$ENV{$_} = $drv->{env}->{$_};
|
||||
}
|
||||
|
||||
# Run a shell using the derivation's environment. For
|
||||
# convenience, source $stdenv/setup to setup additional
|
||||
# environment variables. Also don't lose the current $PATH
|
||||
# directories.
|
||||
exec($ENV{SHELL}, "-c", $envCommand);
|
||||
die;
|
||||
}
|
||||
|
||||
# Ugly hackery to make "nix-build -A foo.all" produce symlinks
|
||||
# ./result, ./result-dev, and so on, rather than ./result,
|
||||
# ./result-2-dev, and so on. This combines multiple derivation
|
||||
# paths into one "/nix/store/drv-path!out1,out2,..." argument.
|
||||
my $prevDrvPath = "";
|
||||
my @drvPaths2;
|
||||
foreach my $drvPath (@drvPaths) {
|
||||
my $p = $drvPath; my $output = "out";
|
||||
if ($drvPath =~ /(.*)!(.*)/) {
|
||||
$p = $1; $output = $2;
|
||||
} else {
|
||||
$p = $drvPath;
|
||||
}
|
||||
my $target = readlink $p or die "cannot read symlink `$p'";
|
||||
print STDERR "derivation is $target\n" if $verbose;
|
||||
if ($target eq $prevDrvPath) {
|
||||
push @drvPaths2, (pop @drvPaths2) . "," . $output;
|
||||
} else {
|
||||
push @drvPaths2, $target . "!" . $output;
|
||||
$prevDrvPath = $target;
|
||||
}
|
||||
}
|
||||
|
||||
# Build.
|
||||
my @outPaths;
|
||||
$pid = open(OUTPATHS, "-|") || exec "$Nix::Config::binDir/nix-store", "--add-root", $outLink, "--indirect", "-r",
|
||||
@buildArgs, @drvPaths2;
|
||||
while (<OUTPATHS>) {chomp; push @outPaths, $_;}
|
||||
if (!close OUTPATHS) {
|
||||
die "nix-store killed by signal " . ($? & 127) . "\n" if ($? & 127);
|
||||
exit 1;
|
||||
}
|
||||
|
||||
next if $dryRun;
|
||||
|
||||
foreach my $outPath (@outPaths) {
|
||||
my $target = readlink $outPath or die "cannot read symlink `$outPath'";
|
||||
print "$target\n";
|
||||
}
|
||||
}
|
||||
209
scripts/nix-channel.in
Executable file
209
scripts/nix-channel.in
Executable file
@@ -0,0 +1,209 @@
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use strict;
|
||||
use File::Basename;
|
||||
use File::Path qw(mkpath);
|
||||
use Nix::Config;
|
||||
use Nix::Manifest;
|
||||
|
||||
Nix::Config::readConfig;
|
||||
|
||||
my $manifestDir = $Nix::Config::manifestDir;
|
||||
|
||||
|
||||
# Turn on caching in nix-prefetch-url.
|
||||
my $channelCache = "$Nix::Config::stateDir/channel-cache";
|
||||
mkdir $channelCache, 0755 unless -e $channelCache;
|
||||
$ENV{'NIX_DOWNLOAD_CACHE'} = $channelCache if -W $channelCache;
|
||||
|
||||
# Figure out the name of the `.nix-channels' file to use.
|
||||
my $home = $ENV{"HOME"} or die '$HOME not set\n';
|
||||
my $channelsList = "$home/.nix-channels";
|
||||
my $nixDefExpr = "$home/.nix-defexpr";
|
||||
|
||||
# Figure out the name of the channels profile.
|
||||
my $userName = getpwuid($<) or die "cannot figure out user name";
|
||||
my $profile = "$Nix::Config::stateDir/profiles/per-user/$userName/channels";
|
||||
mkpath(dirname $profile, 0, 0755);
|
||||
|
||||
my %channels;
|
||||
|
||||
|
||||
# Reads the list of channels.
|
||||
sub readChannels {
|
||||
return if (!-f $channelsList);
|
||||
open CHANNELS, "<$channelsList" or die "cannot open `$channelsList': $!";
|
||||
while (<CHANNELS>) {
|
||||
chomp;
|
||||
next if /^\s*\#/;
|
||||
my ($url, $name) = split ' ', $_;
|
||||
$url =~ s/\/*$//; # remove trailing slashes
|
||||
$name = basename $url unless defined $name;
|
||||
$channels{$name} = $url;
|
||||
}
|
||||
close CHANNELS;
|
||||
}
|
||||
|
||||
|
||||
# Writes the list of channels.
|
||||
sub writeChannels {
|
||||
open CHANNELS, ">$channelsList" or die "cannot open `$channelsList': $!";
|
||||
foreach my $name (keys %channels) {
|
||||
print CHANNELS "$channels{$name} $name\n";
|
||||
}
|
||||
close CHANNELS;
|
||||
}
|
||||
|
||||
|
||||
# Adds a channel.
|
||||
sub addChannel {
|
||||
my ($url, $name) = @_;
|
||||
readChannels;
|
||||
$channels{$name} = $url;
|
||||
writeChannels;
|
||||
}
|
||||
|
||||
|
||||
# Remove a channel.
|
||||
sub removeChannel {
|
||||
my ($name) = @_;
|
||||
readChannels;
|
||||
my $url = $channels{$name};
|
||||
deleteOldManifests($url . "/MANIFEST", undef) if defined $url;
|
||||
delete $channels{$name};
|
||||
writeChannels;
|
||||
|
||||
system("$Nix::Config::binDir/nix-env --profile '$profile' -e '$name'") == 0
|
||||
or die "cannot remove channel `$name'\n";
|
||||
}
|
||||
|
||||
|
||||
# Fetch Nix expressions and pull manifests from the subscribed
|
||||
# channels.
|
||||
sub update {
|
||||
my @channelNames = @_;
|
||||
|
||||
readChannels;
|
||||
|
||||
# Download each channel.
|
||||
my $exprs = "";
|
||||
foreach my $name (keys %channels) {
|
||||
next if scalar @channelNames > 0 && ! grep { $_ eq $name } @{channelNames};
|
||||
|
||||
my $url = $channels{$name};
|
||||
my $origUrl = "$url/MANIFEST";
|
||||
|
||||
# Check if $url is a redirect. If so, follow it now to ensure
|
||||
# consistency if the redirection is changed between
|
||||
# downloading the manifest and the tarball.
|
||||
my $headers = `$Nix::Config::curl --silent --head '$url'`;
|
||||
die "$0: unable to check `$url'\n" if $? != 0;
|
||||
$headers =~ s/\r//g;
|
||||
$url = $1 if $headers =~ /^Location:\s*(.*)\s*$/m;
|
||||
|
||||
# Check if the channel advertises a binary cache.
|
||||
my $binaryCacheURL = `$Nix::Config::curl --silent '$url'/binary-cache-url`;
|
||||
my $extraAttrs = "";
|
||||
my $getManifest = ($Nix::Config::config{"force-manifest"} // "false") eq "true";
|
||||
if ($? == 0 && $binaryCacheURL ne "") {
|
||||
$extraAttrs .= "binaryCacheURL = \"$binaryCacheURL\"; ";
|
||||
deleteOldManifests($origUrl, undef);
|
||||
} else {
|
||||
$getManifest = 1;
|
||||
}
|
||||
|
||||
if ($getManifest) {
|
||||
# No binary cache, so pull the channel manifest.
|
||||
mkdir $manifestDir, 0755 unless -e $manifestDir;
|
||||
die "$0: you do not have write permission to `$manifestDir'!\n" unless -W $manifestDir;
|
||||
$ENV{'NIX_ORIG_URL'} = $origUrl;
|
||||
system("$Nix::Config::binDir/nix-pull", "--skip-wrong-store", "$url/MANIFEST") == 0
|
||||
or die "cannot pull manifest from `$url'\n";
|
||||
}
|
||||
|
||||
# Download the channel tarball.
|
||||
my $fullURL = "$url/nixexprs.tar.xz";
|
||||
system("$Nix::Config::curl --fail --silent --head '$fullURL' > /dev/null") == 0 or
|
||||
$fullURL = "$url/nixexprs.tar.bz2";
|
||||
print STDERR "downloading Nix expressions from `$fullURL'...\n";
|
||||
my ($hash, $path) = `PRINT_PATH=1 QUIET=1 $Nix::Config::binDir/nix-prefetch-url '$fullURL'`;
|
||||
die "cannot fetch `$fullURL'\n" if $? != 0;
|
||||
chomp $path;
|
||||
|
||||
# If the URL contains a version number, append it to the name
|
||||
# attribute (so that "nix-env -q" on the channels profile
|
||||
# shows something useful).
|
||||
my $cname = $name;
|
||||
$cname .= $1 if basename($url) =~ /(-\d.*)$/;
|
||||
|
||||
$exprs .= "'f: f { name = \"$cname\"; channelName = \"$name\"; src = builtins.storePath \"$path\"; $extraAttrs }' ";
|
||||
}
|
||||
|
||||
# Unpack the channel tarballs into the Nix store and install them
|
||||
# into the channels profile.
|
||||
print STDERR "unpacking channels...\n";
|
||||
system("$Nix::Config::binDir/nix-env --profile '$profile' " .
|
||||
"-f '<nix/unpack-channel.nix>' -i -E $exprs --quiet") == 0
|
||||
or die "cannot unpack the channels";
|
||||
|
||||
# Make the channels appear in nix-env.
|
||||
unlink $nixDefExpr if -l $nixDefExpr; # old-skool ~/.nix-defexpr
|
||||
mkdir $nixDefExpr or die "cannot create directory `$nixDefExpr'" if !-e $nixDefExpr;
|
||||
my $channelLink = "$nixDefExpr/channels";
|
||||
unlink $channelLink; # !!! not atomic
|
||||
symlink($profile, $channelLink) or die "cannot symlink `$channelLink' to `$profile'";
|
||||
}
|
||||
|
||||
|
||||
die "$0: argument expected\n" if scalar @ARGV == 0;
|
||||
|
||||
|
||||
while (scalar @ARGV) {
|
||||
my $arg = shift @ARGV;
|
||||
|
||||
if ($arg eq "--add") {
|
||||
die "$0: `--add' requires one or two arguments\n" if scalar @ARGV < 1 || scalar @ARGV > 2;
|
||||
my $url = shift @ARGV;
|
||||
my $name = shift @ARGV;
|
||||
unless (defined $name) {
|
||||
$name = basename $url;
|
||||
$name =~ s/-unstable//;
|
||||
$name =~ s/-stable//;
|
||||
}
|
||||
addChannel($url, $name);
|
||||
last;
|
||||
}
|
||||
|
||||
if ($arg eq "--remove") {
|
||||
die "$0: `--remove' requires one argument\n" if scalar @ARGV != 1;
|
||||
removeChannel(shift @ARGV);
|
||||
last;
|
||||
}
|
||||
|
||||
if ($arg eq "--list") {
|
||||
die "$0: `--list' requires one argument\n" if scalar @ARGV != 0;
|
||||
readChannels;
|
||||
foreach my $name (keys %channels) {
|
||||
print "$name $channels{$name}\n";
|
||||
}
|
||||
last;
|
||||
}
|
||||
|
||||
elsif ($arg eq "--update") {
|
||||
update(@ARGV);
|
||||
last;
|
||||
}
|
||||
|
||||
elsif ($arg eq "--help") {
|
||||
exec "man nix-channel" or die;
|
||||
}
|
||||
|
||||
elsif ($arg eq "--version") {
|
||||
print "nix-channel (Nix) $Nix::Config::version\n";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
else {
|
||||
die "unknown argument `$arg'; try `--help'\n";
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
#! /usr/bin/perl -w
|
||||
|
||||
my $prefix = $ENV{"NIX"} || "/nix"; # !!! use prefix
|
||||
my $linkdir = "$prefix/var/nix/links";
|
||||
|
||||
my %alive;
|
||||
|
||||
open HASHES, "nix closure \$(cat $linkdir/*.hash) |";
|
||||
while (<HASHES>) {
|
||||
chomp;
|
||||
$alive{$_} = 1;
|
||||
}
|
||||
close HASHES;
|
||||
|
||||
open HASHES, "nix listinst |";
|
||||
while (<HASHES>) {
|
||||
chomp;
|
||||
if (!$alive{$_}) {
|
||||
print "$_\n";
|
||||
}
|
||||
}
|
||||
close HASHES;
|
||||
57
scripts/nix-collect-garbage.in
Executable file
57
scripts/nix-collect-garbage.in
Executable file
@@ -0,0 +1,57 @@
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use strict;
|
||||
use Nix::Config;
|
||||
|
||||
my $profilesDir = "@localstatedir@/nix/profiles";
|
||||
|
||||
|
||||
# Process the command line arguments.
|
||||
my @args = ();
|
||||
my $removeOld = 0;
|
||||
my $dryRun = 0;
|
||||
|
||||
for my $arg (@ARGV) {
|
||||
if ($arg eq "--delete-old" || $arg eq "-d") {
|
||||
$removeOld = 1;
|
||||
} elsif ($arg eq "--dry-run") {
|
||||
$dryRun = 1;
|
||||
} elsif ($arg eq "--help") {
|
||||
exec "man nix-collect-garbage" or die;
|
||||
} else {
|
||||
push @args, $arg;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# If `-d' was specified, remove all old generations of all profiles.
|
||||
# Of course, this makes rollbacks to before this point in time
|
||||
# impossible.
|
||||
|
||||
sub removeOldGenerations;
|
||||
sub removeOldGenerations {
|
||||
my $dir = shift;
|
||||
|
||||
my $dh;
|
||||
opendir $dh, $dir or die;
|
||||
|
||||
foreach my $name (sort (readdir $dh)) {
|
||||
next if $name eq "." || $name eq "..";
|
||||
$name = $dir . "/" . $name;
|
||||
if (-l $name && (readlink($name) =~ /link/)) {
|
||||
print STDERR "removing old generations of profile $name\n";
|
||||
system("$Nix::Config::binDir/nix-env", "-p", $name, "--delete-generations", "old", $dryRun ? "--dry-run" : ());
|
||||
}
|
||||
elsif (! -l $name && -d $name) {
|
||||
removeOldGenerations $name;
|
||||
}
|
||||
}
|
||||
|
||||
closedir $dh or die;
|
||||
}
|
||||
|
||||
removeOldGenerations $profilesDir if $removeOld;
|
||||
|
||||
|
||||
# Run the actual garbage collector.
|
||||
exec "$Nix::Config::binDir/nix-store", "--gc", @args unless $dryRun;
|
||||
123
scripts/nix-copy-closure.in
Executable file
123
scripts/nix-copy-closure.in
Executable file
@@ -0,0 +1,123 @@
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
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] [--bzip2] [--xz] PATHS...
|
||||
EOF
|
||||
;
|
||||
exit 1;
|
||||
}
|
||||
|
||||
|
||||
# Get the target host.
|
||||
my $sshHost;
|
||||
my $sign = 0;
|
||||
my $compressor = "";
|
||||
my $decompressor = "";
|
||||
my $progressViewer = "";
|
||||
my $toMode = 1;
|
||||
my $includeOutputs = 0;
|
||||
my $dryRun = 0;
|
||||
my $useSubstitutes = 0;
|
||||
|
||||
|
||||
# !!! Copied from nix-pack-closure, should put this in a module.
|
||||
my @storePaths = ();
|
||||
|
||||
while (@ARGV) {
|
||||
my $arg = shift @ARGV;
|
||||
|
||||
if ($arg eq "--help") {
|
||||
exec "man nix-copy-closure" or die;
|
||||
}
|
||||
elsif ($arg eq "--sign") {
|
||||
$sign = 1;
|
||||
}
|
||||
elsif ($arg eq "--gzip") {
|
||||
$compressor = "gzip";
|
||||
$decompressor = "gunzip";
|
||||
}
|
||||
elsif ($arg eq "--bzip2") {
|
||||
$compressor = "bzip2";
|
||||
$decompressor = "bunzip2";
|
||||
}
|
||||
elsif ($arg eq "--xz") {
|
||||
$compressor = "xz";
|
||||
$decompressor = "xz -d";
|
||||
}
|
||||
elsif ($arg eq "--from") {
|
||||
$toMode = 0;
|
||||
}
|
||||
elsif ($arg eq "--to") {
|
||||
$toMode = 1;
|
||||
}
|
||||
elsif ($arg eq "--include-outputs") {
|
||||
$includeOutputs = 1;
|
||||
}
|
||||
elsif ($arg eq "--show-progress") {
|
||||
$progressViewer = "@pv@";
|
||||
}
|
||||
elsif ($arg eq "--dry-run") {
|
||||
$dryRun = 1;
|
||||
}
|
||||
elsif ($arg eq "--use-substitutes" || $arg eq "-s") {
|
||||
$useSubstitutes = 1;
|
||||
}
|
||||
elsif (!defined $sshHost) {
|
||||
$sshHost = $arg;
|
||||
}
|
||||
else {
|
||||
push @storePaths, $arg;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
openSSHConnection $sshHost or die "$0: unable to start SSH\n";
|
||||
|
||||
|
||||
if ($toMode) { # Copy TO the remote machine.
|
||||
Nix::CopyClosure::copyTo(
|
||||
$sshHost, [ @sshOpts ], [ @storePaths ], $compressor, $decompressor,
|
||||
$includeOutputs, $dryRun, $sign, $progressViewer, $useSubstitutes);
|
||||
}
|
||||
|
||||
else { # Copy FROM the remote machine.
|
||||
|
||||
# Query the closure of the given store paths on the remote
|
||||
# machine. Paths are assumed to be store paths; there is no
|
||||
# resolution (following of symlinks).
|
||||
my $extraOpts = $includeOutputs ? "--include-outputs" : "";
|
||||
my $pid = open(READ,
|
||||
"set -f; ssh @sshOpts $sshHost nix-store --query --requisites $extraOpts @storePaths|") or die;
|
||||
|
||||
while (<READ>) {
|
||||
chomp;
|
||||
die "bad: $_" unless /^\//;
|
||||
push @missing, $_ unless isValidPath($_);
|
||||
}
|
||||
|
||||
close READ or die "nix-store on remote machine `$sshHost' failed: $?";
|
||||
|
||||
# Export the store paths on the remote machine and import them locally.
|
||||
if (scalar @missing > 0) {
|
||||
print STDERR "copying ", scalar @missing, " missing paths from ‘$sshHost’...\n";
|
||||
unless ($dryRun) {
|
||||
if ($useSubstitutes) {
|
||||
system "$Nix::Config::binDir/nix-store -r --ignore-unknown @missing";
|
||||
}
|
||||
$compressor = "| $compressor" if $compressor ne "";
|
||||
$decompressor = "$decompressor |" if $decompressor ne "";
|
||||
$progressViewer = "$progressViewer |" if $progressViewer ne "";
|
||||
my $extraOpts = $sign ? "--sign" : "";
|
||||
system("set -f; ssh $sshHost @sshOpts 'nix-store --export $extraOpts @missing $compressor' | $progressViewer $decompressor $Nix::Config::binDir/nix-store --import > /dev/null") == 0
|
||||
or die "copying store paths from remote machine `$sshHost' failed: $?";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
52
scripts/nix-generate-patches.in
Executable file
52
scripts/nix-generate-patches.in
Executable file
@@ -0,0 +1,52 @@
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use strict;
|
||||
use File::Temp qw(tempdir);
|
||||
use Nix::Manifest;
|
||||
use Nix::GeneratePatches;
|
||||
|
||||
if (scalar @ARGV != 5) {
|
||||
print STDERR <<EOF;
|
||||
Usage: nix-generate-patches NAR-DIR PATCH-DIR PATCH-URI OLD-MANIFEST NEW-MANIFEST
|
||||
|
||||
This command generates binary patches between NAR files listed in
|
||||
OLD-MANIFEST and NEW-MANIFEST. The patches are written to the
|
||||
directory PATCH-DIR, and the prefix PATCH-URI is used to generate URIs
|
||||
for the patches. The patches are added to NEW-MANIFEST. All NARs are
|
||||
required to exist in NAR-DIR. Patches are generated between
|
||||
succeeding versions of packages with the same name.
|
||||
EOF
|
||||
exit 1;
|
||||
}
|
||||
|
||||
my $narPath = $ARGV[0];
|
||||
my $patchesPath = $ARGV[1];
|
||||
my $patchesURL = $ARGV[2];
|
||||
my $srcManifest = $ARGV[3];
|
||||
my $dstManifest = $ARGV[4];
|
||||
|
||||
my (%srcNarFiles, %srcLocalPaths, %srcPatches);
|
||||
readManifest $srcManifest, \%srcNarFiles, \%srcPatches;
|
||||
|
||||
my (%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";
|
||||
|
||||
generatePatches \%srcNarFiles, \%dstNarFiles, \%srcPatches, \%dstPatches,
|
||||
$narPath, $patchesPath, $patchesURL, $tmpDir;
|
||||
|
||||
propagatePatches \%srcPatches, \%dstNarFiles, \%dstPatches;
|
||||
|
||||
# Optionally add all new patches to the manifest in $NIX_ALL_PATCHES.
|
||||
my $allPatchesFile = $ENV{"NIX_ALL_PATCHES"};
|
||||
if (defined $allPatchesFile) {
|
||||
my (%dummy, %allPatches);
|
||||
readManifest("$patchesPath/all-patches", \%dummy, \%allPatches)
|
||||
if -f $allPatchesFile;
|
||||
copyPatches \%dstPatches, \%allPatches;
|
||||
writeManifest($allPatchesFile, {}, \%allPatches, 0);
|
||||
}
|
||||
|
||||
writeManifest $dstManifest, \%dstNarFiles, \%dstPatches;
|
||||
51
scripts/nix-http-export.cgi.in
Executable file
51
scripts/nix-http-export.cgi.in
Executable file
@@ -0,0 +1,51 @@
|
||||
#! /bin/sh
|
||||
|
||||
export HOME=/tmp
|
||||
export NIX_REMOTE=daemon
|
||||
|
||||
TMP_DIR="${TMP_DIR:-/tmp/nix-export}"
|
||||
|
||||
@coreutils@/mkdir -p "$TMP_DIR" || true
|
||||
@coreutils@/chmod a+r "$TMP_DIR"
|
||||
|
||||
needed_path="?$QUERY_STRING"
|
||||
needed_path="${needed_path#*[?&]needed_path=}"
|
||||
needed_path="${needed_path%%&*}"
|
||||
#needed_path="$(echo $needed_path | ./unhttp)"
|
||||
needed_path="${needed_path//%2B/+}"
|
||||
needed_path="${needed_path//%3D/=}"
|
||||
|
||||
echo needed_path: "$needed_path" >&2
|
||||
|
||||
NIX_STORE="${NIX_STORE_DIR:-/nix/store}"
|
||||
|
||||
echo NIX_STORE: "${NIX_STORE}" >&2
|
||||
|
||||
full_path="${NIX_STORE}"/"$needed_path"
|
||||
|
||||
if [ "$needed_path" != "${needed_path%.drv}" ]; then
|
||||
echo "Status: 403 You should create the derivation file yourself"
|
||||
echo "Content-Type: text/plain"
|
||||
echo
|
||||
echo "Refusing to disclose derivation contents"
|
||||
exit
|
||||
fi
|
||||
|
||||
if @bindir@/nix-store --check-validity "$full_path"; then
|
||||
if ! [ -e nix-export/"$needed_path".nar.gz ]; then
|
||||
@bindir@/nix-store --export "$full_path" | @gzip@ > "$TMP_DIR"/"$needed_path".nar.gz
|
||||
@coreutils@/ln -fs "$TMP_DIR"/"$needed_path".nar.gz nix-export/"$needed_path".nar.gz
|
||||
fi;
|
||||
echo "Status: 301 Moved"
|
||||
echo "Location: nix-export/"$needed_path".nar.gz"
|
||||
echo
|
||||
else
|
||||
echo "Status: 404 No such path found"
|
||||
echo "Content-Type: text/plain"
|
||||
echo
|
||||
echo "Path not found:"
|
||||
echo "$needed_path"
|
||||
echo "checked:"
|
||||
echo "$full_path"
|
||||
fi
|
||||
|
||||
138
scripts/nix-install-package.in
Executable file
138
scripts/nix-install-package.in
Executable file
@@ -0,0 +1,138 @@
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use strict;
|
||||
use File::Temp qw(tempdir);
|
||||
use Nix::Config;
|
||||
use Nix::Utils;
|
||||
|
||||
|
||||
# Parse the command line arguments.
|
||||
my @args = @ARGV;
|
||||
|
||||
my $source;
|
||||
my $fromURL = 0;
|
||||
my @extraNixEnvArgs = ();
|
||||
my $interactive = 1;
|
||||
|
||||
while (scalar @args) {
|
||||
my $arg = shift @args;
|
||||
if ($arg eq "--help") {
|
||||
exec "man nix-install-package" or die;
|
||||
}
|
||||
elsif ($arg eq "--url") {
|
||||
$fromURL = 1;
|
||||
}
|
||||
elsif ($arg eq "--profile" || $arg eq "-p") {
|
||||
my $profile = shift @args;
|
||||
die "$0: `--profile' requires an argument\n" if !defined $profile;
|
||||
push @extraNixEnvArgs, "-p", $profile;
|
||||
}
|
||||
elsif ($arg eq "--non-interactive") {
|
||||
$interactive = 0;
|
||||
}
|
||||
else {
|
||||
$source = $arg;
|
||||
}
|
||||
}
|
||||
|
||||
die "$0: please specify a .nixpkg file or URL\n" unless defined $source;
|
||||
|
||||
|
||||
# Re-execute in a terminal, if necessary, so that if we're executed
|
||||
# from a web browser, the user gets to see us.
|
||||
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", "$Nix::Config::binDir/nix-install-package", @ARGV);
|
||||
}
|
||||
die "cannot execute `xterm'";
|
||||
}
|
||||
|
||||
|
||||
my $tmpDir = tempdir("nix-install-package.XXXXXX", CLEANUP => 1, TMPDIR => 1)
|
||||
or die "cannot create a temporary directory";
|
||||
|
||||
|
||||
sub barf {
|
||||
my $msg = shift;
|
||||
print "\nInstallation failed: $msg\n";
|
||||
<STDIN> if $interactive;
|
||||
exit 1;
|
||||
}
|
||||
|
||||
|
||||
# Download the package description, if necessary.
|
||||
my $pkgFile = $source;
|
||||
if ($fromURL) {
|
||||
$pkgFile = "$tmpDir/tmp.nixpkg";
|
||||
system("@curl@", "--silent", $source, "-o", $pkgFile) == 0
|
||||
or barf "curl failed: $?";
|
||||
}
|
||||
|
||||
|
||||
# Read and parse the package file.
|
||||
open PKGFILE, "<$pkgFile" or barf "cannot open `$pkgFile': $!";
|
||||
my $contents = <PKGFILE>;
|
||||
close PKGFILE;
|
||||
|
||||
my $nameRE = "(?: [A-Za-z0-9\+\-\.\_\?\=]+ )"; # see checkStoreName()
|
||||
my $systemRE = "(?: [A-Za-z0-9\+\-\_]+ )";
|
||||
my $pathRE = "(?: \/ [\/A-Za-z0-9\+\-\.\_\?\=]* )";
|
||||
|
||||
# Note: $pathRE doesn't check that whether we're looking at a valid
|
||||
# store path. We'll let nix-env do that.
|
||||
|
||||
$contents =~
|
||||
/ ^ \s* (\S+) \s+ ($Nix::Utils::urlRE) \s+ ($nameRE) \s+ ($systemRE) \s+ ($pathRE) \s+ ($pathRE) ( \s+ ($Nix::Utils::urlRE) )? /x
|
||||
or barf "invalid package contents";
|
||||
my $version = $1;
|
||||
my $manifestURL = $2;
|
||||
my $drvName = $3;
|
||||
my $system = $4;
|
||||
my $drvPath = $5;
|
||||
my $outPath = $6;
|
||||
my $binaryCacheURL = $8;
|
||||
|
||||
barf "invalid package version `$version'" unless $version eq "NIXPKG1";
|
||||
|
||||
|
||||
if ($interactive) {
|
||||
# Ask confirmation.
|
||||
print "Do you want to install `$drvName' (Y/N)? ";
|
||||
my $reply = <STDIN>;
|
||||
chomp $reply;
|
||||
exit if $reply ne "y" && $reply ne "Y";
|
||||
}
|
||||
|
||||
|
||||
if (defined $binaryCacheURL) {
|
||||
|
||||
push @extraNixEnvArgs, "--option", "binary-caches", $binaryCacheURL;
|
||||
|
||||
} else {
|
||||
|
||||
# Store the manifest in the temporary directory so that we don't
|
||||
# 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("$Nix::Config::binDir/nix-pull", $manifestURL) == 0
|
||||
or barf "nix-pull failed: $?";
|
||||
|
||||
}
|
||||
|
||||
|
||||
print "\nInstalling package...\n";
|
||||
system("$Nix::Config::binDir/nix-env", "--install", $outPath, "--force-name", $drvName, @extraNixEnvArgs) == 0
|
||||
or barf "nix-env failed: $?";
|
||||
|
||||
|
||||
if ($interactive) {
|
||||
print "\nInstallation succeeded! Press Enter to continue.\n";
|
||||
<STDIN>;
|
||||
}
|
||||
130
scripts/nix-prefetch-url.in
Executable file
130
scripts/nix-prefetch-url.in
Executable file
@@ -0,0 +1,130 @@
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use strict;
|
||||
use File::Basename;
|
||||
use File::Temp qw(tempdir);
|
||||
use File::stat;
|
||||
use Nix::Store;
|
||||
use Nix::Config;
|
||||
use Nix::Utils;
|
||||
|
||||
my $hashType = $ENV{'NIX_HASH_ALGO'} || "sha256"; # obsolete
|
||||
my $cacheDir = $ENV{'NIX_DOWNLOAD_CACHE'};
|
||||
|
||||
my @args;
|
||||
my $arg;
|
||||
while ($arg = shift) {
|
||||
if ($arg eq "--help") {
|
||||
exec "man nix-prefetch-url" or die;
|
||||
} elsif ($arg eq "--type") {
|
||||
$hashType = shift;
|
||||
die "$0: `$arg' requires an argument\n" unless defined $hashType;
|
||||
} elsif (substr($arg, 0, 1) eq "-") {
|
||||
die "$0: unknown flag `$arg'\n";
|
||||
} else {
|
||||
push @args, $arg;
|
||||
}
|
||||
}
|
||||
|
||||
my $url = $args[0];
|
||||
my $expHash = $args[1];
|
||||
|
||||
|
||||
if (!defined $url || $url eq "") {
|
||||
print STDERR <<EOF
|
||||
Usage: nix-prefetch-url URL [EXPECTED-HASH]
|
||||
EOF
|
||||
;
|
||||
exit 1;
|
||||
}
|
||||
|
||||
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.
|
||||
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 (defined $expHash) {
|
||||
$finalPath = makeFixedOutputPath(0, $hashType, $expHash, $name);
|
||||
if (isValidPath($finalPath)) { $hash = $expHash; } else { $finalPath = undef; }
|
||||
}
|
||||
|
||||
# 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 (!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.
|
||||
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.
|
||||
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 (defined $cacheDir && ! -e $tmpFile) {
|
||||
# Curl didn't create $tmpFile, so apparently there's no newer
|
||||
# file on the server.
|
||||
$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 (!defined $finalPath) {
|
||||
|
||||
# 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);
|
||||
}
|
||||
|
||||
die "$0: hash mismatch for ‘$url’\n" if defined $expHash && $expHash ne $hash;
|
||||
}
|
||||
|
||||
print STDERR "path is ‘$finalPath’\n" unless $ENV{'QUIET'};
|
||||
print "$hash\n";
|
||||
print "$finalPath\n" if $ENV{'PRINT_PATH'};
|
||||
@@ -1,19 +0,0 @@
|
||||
if test -z "$NIX_SET"; then
|
||||
|
||||
export NIX_SET=1
|
||||
|
||||
NIX_LINKS=/nix/var/nix/links/current
|
||||
|
||||
export PATH=$NIX_LINKS/bin:/nix/bin:$PATH
|
||||
|
||||
export LD_LIBRARY_PATH=$NIX_LINKS/lib:$LD_LIBRARY_PATH
|
||||
|
||||
export LIBRARY_PATH=$NIX_LINKS/lib:$LIBRARY_PATH
|
||||
|
||||
export C_INCLUDE_PATH=$NIX_LINKS/include:$C_INCLUDE_PATH
|
||||
|
||||
export PKG_CONFIG_PATH=$NIX_LINKS/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
|
||||
# export MANPATH=$NIX_LINKS/man:$MANPATH
|
||||
|
||||
fi
|
||||
17
scripts/nix-profile.sh.in
Normal file
17
scripts/nix-profile.sh.in
Normal file
@@ -0,0 +1,17 @@
|
||||
if test -n "$HOME"; then
|
||||
NIX_LINK="$HOME/.nix-profile"
|
||||
|
||||
# Set the default profile.
|
||||
if ! [ -L "$NIX_LINK" ]; then
|
||||
echo "creating $NIX_LINK" >&2
|
||||
_NIX_DEF_LINK=@localstatedir@/nix/profiles/default
|
||||
@coreutils@/ln -s "$_NIX_DEF_LINK" "$NIX_LINK"
|
||||
fi
|
||||
|
||||
# Subscribe the root user to the Nixpkgs channel by default.
|
||||
if [ ! -e $HOME/.nix-channels ]; then
|
||||
echo "http://nixos.org/channels/nixpkgs-unstable nixpkgs" > $HOME/.nix-channels
|
||||
fi
|
||||
|
||||
export PATH=$NIX_LINK/bin:$PATH
|
||||
fi
|
||||
@@ -1,83 +0,0 @@
|
||||
#! /usr/bin/perl -w
|
||||
|
||||
my $prefix = $ENV{"NIX"} || "/nix"; # !!! use prefix
|
||||
my $etcdir = "$prefix/etc/nix";
|
||||
my $knowns = "$prefix/var/nix/known-prebuilts";
|
||||
my $tmpfile = "$prefix/var/nix/prebuilts.tmp";
|
||||
|
||||
my $conffile = "$etcdir/prebuilts.conf";
|
||||
|
||||
umask 0022;
|
||||
|
||||
sub register {
|
||||
my $fn = shift;
|
||||
my $url = shift;
|
||||
return unless $fn =~ /([^\/]*)-([0-9a-z]{32})-([0-9a-z]{32})\.tar\.bz2/;
|
||||
my $id = $1;
|
||||
my $pkghash = $2;
|
||||
my $prebuilthash = $3;
|
||||
|
||||
print "$pkghash => $prebuilthash ($id)\n";
|
||||
|
||||
system "nix regprebuilt $pkghash $prebuilthash";
|
||||
if ($?) { die "`nix regprebuilt' failed"; }
|
||||
|
||||
if ($url =~ /^\//) {
|
||||
system "nix regfile $url";
|
||||
if ($?) { die "`nix regfile' failed"; }
|
||||
} else {
|
||||
system "nix regurl $prebuilthash $url";
|
||||
if ($?) { die "`nix regurl' failed"; }
|
||||
}
|
||||
|
||||
print KNOWNS "$pkghash\n";
|
||||
}
|
||||
|
||||
open KNOWNS, ">$knowns";
|
||||
|
||||
open CONFFILE, "<$conffile";
|
||||
|
||||
while (<CONFFILE>) {
|
||||
chomp;
|
||||
if (/^\s*(\S+)\s*(\#.*)?$/) {
|
||||
my $url = $1;
|
||||
|
||||
print "obtaining prebuilt list from $url...\n";
|
||||
|
||||
if ($url =~ /^\//) {
|
||||
|
||||
# It's a local path.
|
||||
|
||||
foreach my $fn (glob "$url/*") {
|
||||
register($fn, $fn);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
# It's a URL.
|
||||
|
||||
system "wget '$url' -O '$tmpfile' 2> /dev/null"; # !!! escape
|
||||
if ($?) { die "`wget' failed"; }
|
||||
|
||||
open INDEX, "<$tmpfile";
|
||||
|
||||
while (<INDEX>) {
|
||||
# Get all links to prebuilts, that is, file names of the
|
||||
# form foo-HASH-HASH.tar.bz2.
|
||||
next unless (/HREF=\"([^\"]*)\"/);
|
||||
my $fn = $1;
|
||||
next if $fn =~ /\.\./;
|
||||
next if $fn =~ /\//;
|
||||
register($fn, "$url/$fn");
|
||||
}
|
||||
|
||||
close INDEX;
|
||||
|
||||
unlink $tmpfile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close CONFFILE;
|
||||
|
||||
close KNOWNS;
|
||||
103
scripts/nix-pull.in
Executable file
103
scripts/nix-pull.in
Executable file
@@ -0,0 +1,103 @@
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use strict;
|
||||
use File::Temp qw(tempdir);
|
||||
use Nix::Config;
|
||||
use Nix::Manifest;
|
||||
|
||||
my $tmpDir = tempdir("nix-pull.XXXXXX", CLEANUP => 1, TMPDIR => 1)
|
||||
or die "cannot create a temporary directory";
|
||||
|
||||
my $manifestDir = $Nix::Config::manifestDir;
|
||||
|
||||
|
||||
# Prevent access problems in shared-stored installations.
|
||||
umask 0022;
|
||||
|
||||
|
||||
# Create the manifests directory if it doesn't exist.
|
||||
if (! -e $manifestDir) {
|
||||
mkdir $manifestDir, 0755 or die "cannot create directory `$manifestDir'";
|
||||
}
|
||||
|
||||
|
||||
# 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'";
|
||||
}
|
||||
|
||||
|
||||
# Process the URLs specified on the command line.
|
||||
|
||||
sub downloadFile {
|
||||
my $url = shift;
|
||||
$ENV{"PRINT_PATH"} = 1;
|
||||
$ENV{"QUIET"} = 1;
|
||||
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;
|
||||
return $path;
|
||||
}
|
||||
|
||||
sub processURL {
|
||||
my $url = shift;
|
||||
|
||||
$url =~ s/\/$//;
|
||||
|
||||
my $manifest;
|
||||
|
||||
my $origUrl = $ENV{'NIX_ORIG_URL'} || $url;
|
||||
|
||||
# First see if a bzipped manifest is available.
|
||||
if (system("$Nix::Config::curl --fail --silent --location --head '$url'.bz2 > /dev/null") == 0) {
|
||||
print "fetching list of Nix archives at `$url.bz2'...\n";
|
||||
$manifest = downloadFile "$url.bz2";
|
||||
}
|
||||
|
||||
# Otherwise, just get the uncompressed manifest.
|
||||
else {
|
||||
print "fetching list of Nix archives at `$url'...\n";
|
||||
$manifest = downloadFile $url;
|
||||
}
|
||||
|
||||
my $baseName = "unnamed";
|
||||
if ($url =~ /\/([^\/]+)\/[^\/]+$/) { # get the forelast component
|
||||
$baseName = $1;
|
||||
}
|
||||
|
||||
my $hash = `$Nix::Config::binDir/nix-hash --flat '$manifest'`
|
||||
or die "cannot hash `$manifest'";
|
||||
chomp $hash;
|
||||
|
||||
my $urlFile = "$manifestDir/$baseName-$hash.url";
|
||||
open URL, ">$urlFile" or die "cannot create `$urlFile'";
|
||||
print URL $origUrl;
|
||||
close URL;
|
||||
|
||||
my $finalPath = "$manifestDir/$baseName-$hash.nixmanifest";
|
||||
|
||||
unlink $finalPath if -e $finalPath;
|
||||
|
||||
symlink("$manifest", "$finalPath")
|
||||
or die "cannot link `$finalPath to `$manifest'";
|
||||
|
||||
deleteOldManifests($origUrl, $urlFile);
|
||||
}
|
||||
|
||||
while (@ARGV) {
|
||||
my $url = shift @ARGV;
|
||||
if ($url eq "--help") {
|
||||
exec "man nix-pull" or die;
|
||||
} elsif ($url eq "--skip-wrong-store") {
|
||||
# No-op, no longer supported.
|
||||
} else {
|
||||
processURL $url;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Update the cache.
|
||||
updateManifestDB();
|
||||
@@ -1,44 +0,0 @@
|
||||
#! /usr/bin/perl -w
|
||||
|
||||
my $prefix = $ENV{"NIX"} || "/nix"; # !!! use prefix
|
||||
my $etcdir = "$prefix/etc/nix";
|
||||
my $exportdir = "$prefix/var/nix/prebuilts/exports";
|
||||
my $knowns = "$prefix/var/nix/known-prebuilts";
|
||||
|
||||
umask 0022;
|
||||
|
||||
# For performance, put the known hashes in an associative array.
|
||||
my %knowns = ();
|
||||
open KNOWNS, "<$knowns";
|
||||
while (<KNOWNS>) {
|
||||
next unless /([0-9a-z]{32})/;
|
||||
$knowns{$1} = 1;
|
||||
}
|
||||
close KNOWNS;
|
||||
|
||||
# For each installed package, check whether a prebuilt is known.
|
||||
|
||||
open PKGS, "nix listinst|";
|
||||
|
||||
while (<PKGS>) {
|
||||
chomp;
|
||||
next unless /([0-9a-z]{32})/;
|
||||
my $pkghash = $1;
|
||||
if (!defined $knowns{$1}) {
|
||||
# No known prebuilt exists for this package; so export it.
|
||||
print "exporting $pkghash...\n";
|
||||
system "nix export '$exportdir' $pkghash";
|
||||
if ($?) { die "`nix export' failed"; }
|
||||
}
|
||||
}
|
||||
|
||||
close PKGS;
|
||||
|
||||
# Push the prebuilts to the server. !!! FIXME
|
||||
|
||||
system "rsync -av -e ssh '$exportdir'/ eelco\@losser.st-lab.cs.uu.nl:/home/eelco/public_html/nix-prebuilts/";
|
||||
|
||||
# Rerun `nix-pull-prebuilts' to rescan the prebuilt source locations.
|
||||
|
||||
print "running nix-pull-prebuilts...";
|
||||
system "nix-pull-prebuilts";
|
||||
275
scripts/nix-push.in
Executable file
275
scripts/nix-push.in
Executable file
@@ -0,0 +1,275 @@
|
||||
#! @perl@ -w @perlFlags@
|
||||
|
||||
use strict;
|
||||
use File::Basename;
|
||||
use File::Temp qw(tempdir);
|
||||
use File::Path qw(mkpath);
|
||||
use File::stat;
|
||||
use File::Copy;
|
||||
use Nix::Config;
|
||||
use Nix::Store;
|
||||
use Nix::Manifest;
|
||||
use Nix::Utils;
|
||||
|
||||
my $tmpDir = tempdir("nix-push.XXXXXX", CLEANUP => 1, TMPDIR => 1)
|
||||
or die "cannot create a temporary directory";
|
||||
|
||||
my $nixExpr = "$tmpDir/create-nars.nix";
|
||||
|
||||
|
||||
# Parse the command line.
|
||||
my $compressionType = "xz";
|
||||
my $force = 0;
|
||||
my $destDir;
|
||||
my $writeManifest = 0;
|
||||
my $manifestPath;
|
||||
my $archivesURL;
|
||||
my $link = 0;
|
||||
my @roots;
|
||||
|
||||
for (my $n = 0; $n < scalar @ARGV; $n++) {
|
||||
my $arg = $ARGV[$n];
|
||||
|
||||
if ($arg eq "--help") {
|
||||
exec "man nix-push" or die;
|
||||
} elsif ($arg eq "--bzip2") {
|
||||
$compressionType = "bzip2";
|
||||
} elsif ($arg eq "--force") {
|
||||
$force = 1;
|
||||
} elsif ($arg eq "--dest") {
|
||||
$n++;
|
||||
die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV;
|
||||
$destDir = $ARGV[$n];
|
||||
mkpath($destDir, 0, 0755);
|
||||
} elsif ($arg eq "--manifest") {
|
||||
$writeManifest = 1;
|
||||
} elsif ($arg eq "--manifest-path") {
|
||||
$n++;
|
||||
die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV;
|
||||
$manifestPath = $ARGV[$n];
|
||||
$writeManifest = 1;
|
||||
mkpath(dirname($manifestPath), 0, 0755);
|
||||
} elsif ($arg eq "--url-prefix") {
|
||||
$n++;
|
||||
die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV;
|
||||
$archivesURL = $ARGV[$n];
|
||||
} elsif ($arg eq "--link") {
|
||||
$link = 1;
|
||||
} elsif (substr($arg, 0, 1) eq "-") {
|
||||
die "$0: unknown flag `$arg'\n";
|
||||
} else {
|
||||
push @roots, $arg;
|
||||
}
|
||||
}
|
||||
|
||||
die "$0: please specify a destination directory\n" if !defined $destDir;
|
||||
|
||||
$archivesURL = "file://$destDir" unless defined $archivesURL;
|
||||
|
||||
|
||||
# From the given store paths, determine the set of requisite store
|
||||
# paths, i.e, the paths required to realise them.
|
||||
my %storePaths;
|
||||
|
||||
foreach my $path (@roots) {
|
||||
# Get all paths referenced by the normalisation of the given
|
||||
# Nix expression.
|
||||
my $pid = open(READ,
|
||||
"$Nix::Config::binDir/nix-store --query --requisites --force-realise " .
|
||||
"--include-outputs '$path'|") or die;
|
||||
|
||||
while (<READ>) {
|
||||
chomp;
|
||||
die "bad: $_" unless /^\//;
|
||||
$storePaths{$_} = "";
|
||||
}
|
||||
|
||||
close READ or die "nix-store failed: $?";
|
||||
}
|
||||
|
||||
my @storePaths = keys %storePaths;
|
||||
|
||||
|
||||
# Don't create archives for files that are already in the binary cache.
|
||||
my @storePaths2;
|
||||
my %narFiles;
|
||||
foreach my $storePath (@storePaths) {
|
||||
my $pathHash = substr(basename($storePath), 0, 32);
|
||||
my $narInfoFile = "$destDir/$pathHash.narinfo";
|
||||
if (-e $narInfoFile) {
|
||||
my $narInfo = parseNARInfo($storePath, readFile($narInfoFile));
|
||||
my $narFile = "$destDir/$narInfo->{url}";
|
||||
if (-e $narFile) {
|
||||
print STDERR "skipping existing $storePath\n";
|
||||
# Add the NAR info to $narFiles if we're writing a
|
||||
# manifest.
|
||||
$narFiles{$storePath} = [
|
||||
{ url => ("$archivesURL/" . basename $narInfo->{url})
|
||||
, hash => $narInfo->{fileHash}
|
||||
, size => $narInfo->{fileSize}
|
||||
, compressionType => $narInfo->{compression}
|
||||
, narHash => $narInfo->{narHash}
|
||||
, narSize => $narInfo->{narSize}
|
||||
, references => join(" ", map { "$Nix::Config::storeDir/$_" } @{$narInfo->{refs}})
|
||||
, deriver => $narInfo->{deriver} ? "$Nix::Config::storeDir/$narInfo->{deriver}" : undef
|
||||
}
|
||||
] if $writeManifest;
|
||||
next;
|
||||
}
|
||||
}
|
||||
push @storePaths2, $storePath;
|
||||
}
|
||||
|
||||
|
||||
# Create a list of Nix derivations that turn each path into a Nix
|
||||
# archive.
|
||||
open NIX, ">$nixExpr";
|
||||
print NIX "[";
|
||||
|
||||
foreach my $storePath (@storePaths2) {
|
||||
die unless ($storePath =~ /\/[0-9a-z]{32}[^\"\\\$]*$/);
|
||||
|
||||
# Construct a Nix expression that creates a Nix archive.
|
||||
my $nixexpr =
|
||||
"(import <nix/nar.nix> " .
|
||||
"{ storePath = builtins.storePath \"$storePath\"; hashAlgo = \"sha256\"; compressionType = \"$compressionType\"; }) ";
|
||||
|
||||
print NIX $nixexpr;
|
||||
}
|
||||
|
||||
print NIX "]";
|
||||
close NIX;
|
||||
|
||||
|
||||
# Build the Nix expression.
|
||||
print STDERR "building compressed archives...\n";
|
||||
my @narPaths;
|
||||
my $pid = open(READ, "$Nix::Config::binDir/nix-build $nixExpr -o $tmpDir/result |")
|
||||
or die "cannot run nix-build";
|
||||
while (<READ>) {
|
||||
chomp;
|
||||
die unless /^\//;
|
||||
push @narPaths, $_;
|
||||
}
|
||||
close READ or die "nix-build failed: $?";
|
||||
|
||||
|
||||
# Write the cache info file.
|
||||
my $cacheInfoFile = "$destDir/nix-cache-info";
|
||||
if (! -e $cacheInfoFile) {
|
||||
open FILE, ">$cacheInfoFile" or die "cannot create $cacheInfoFile: $!";
|
||||
print FILE "StoreDir: $Nix::Config::storeDir\n";
|
||||
print FILE "WantMassQuery: 0\n"; # by default, don't hit this cache for "nix-env -qas"
|
||||
close FILE;
|
||||
}
|
||||
|
||||
|
||||
# Copy the archives and the corresponding NAR info files.
|
||||
print STDERR "copying archives...\n";
|
||||
|
||||
my $totalNarSize = 0;
|
||||
my $totalCompressedSize = 0;
|
||||
|
||||
for (my $n = 0; $n < scalar @storePaths2; $n++) {
|
||||
my $storePath = $storePaths2[$n];
|
||||
my $narDir = $narPaths[$n];
|
||||
my $baseName = basename $storePath;
|
||||
|
||||
# Get info about the store path.
|
||||
my ($deriver, $narHash, $time, $narSize, $refs) = queryPathInfo($storePath, 1);
|
||||
|
||||
# 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*$/) {
|
||||
my $nar = "$tmpDir/nar";
|
||||
system("$Nix::Config::binDir/nix-store --dump $storePath > $nar") == 0
|
||||
or die "cannot dump $storePath\n";
|
||||
$narHash = `$Nix::Config::binDir/nix-hash --type sha256 --base32 --flat $nar`;
|
||||
die "cannot hash `$nar'" if $? != 0;
|
||||
chomp $narHash;
|
||||
$narHash = "sha256:$narHash";
|
||||
$narSize = stat("$nar")->size;
|
||||
unlink $nar or die;
|
||||
}
|
||||
|
||||
$totalNarSize += $narSize;
|
||||
|
||||
# Get info about the compressed NAR.
|
||||
open HASH, "$narDir/nar-compressed-hash" or die "cannot open nar-compressed-hash";
|
||||
my $compressedHash = <HASH>;
|
||||
chomp $compressedHash;
|
||||
$compressedHash =~ /^[0-9a-z]+$/ or die "invalid hash";
|
||||
close HASH;
|
||||
|
||||
my $narName = "$compressedHash.nar." . ($compressionType eq "xz" ? "xz" : "bz2");
|
||||
|
||||
my $narFile = "$narDir/$narName";
|
||||
(-f $narFile) or die "NAR file for $storePath not found";
|
||||
|
||||
my $compressedSize = stat($narFile)->size;
|
||||
$totalCompressedSize += $compressedSize;
|
||||
|
||||
printf STDERR "%s [%.2f MiB, %.1f%%]\n", $storePath,
|
||||
$compressedSize / (1024 * 1024), $compressedSize / $narSize * 100;
|
||||
|
||||
# Copy the compressed NAR.
|
||||
my $dst = "$destDir/$narName";
|
||||
if (! -f $dst) {
|
||||
my $tmp = "$destDir/.tmp.$$.$narName";
|
||||
if ($link) {
|
||||
link($narFile, $tmp) or die "cannot link $tmp to $narFile: $!\n";
|
||||
} else {
|
||||
copy($narFile, $tmp) or die "cannot copy $narFile to $tmp: $!\n";
|
||||
}
|
||||
rename($tmp, $dst) or die "cannot rename $tmp to $dst: $!\n";
|
||||
}
|
||||
|
||||
# Write the info file.
|
||||
my $info;
|
||||
$info .= "StorePath: $storePath\n";
|
||||
$info .= "URL: $narName\n";
|
||||
$info .= "Compression: $compressionType\n";
|
||||
$info .= "FileHash: sha256:$compressedHash\n";
|
||||
$info .= "FileSize: $compressedSize\n";
|
||||
$info .= "NarHash: $narHash\n";
|
||||
$info .= "NarSize: $narSize\n";
|
||||
$info .= "References: " . join(" ", map { basename $_ } @{$refs}) . "\n";
|
||||
if (defined $deriver) {
|
||||
$info .= "Deriver: " . basename $deriver . "\n";
|
||||
if (isValidPath($deriver)) {
|
||||
my $drv = derivationFromPath($deriver);
|
||||
$info .= "System: $drv->{platform}\n";
|
||||
}
|
||||
}
|
||||
|
||||
my $pathHash = substr(basename($storePath), 0, 32);
|
||||
|
||||
$dst = "$destDir/$pathHash.narinfo";
|
||||
if ($force || ! -f $dst) {
|
||||
my $tmp = "$destDir/.tmp.$$.$pathHash.narinfo";
|
||||
open INFO, ">$tmp" or die;
|
||||
print INFO "$info" or die;
|
||||
close INFO or die;
|
||||
rename($tmp, $dst) or die "cannot rename $tmp to $dst: $!\n";
|
||||
}
|
||||
|
||||
$narFiles{$storePath} = [
|
||||
{ url => "$archivesURL/$narName"
|
||||
, hash => "sha256:$compressedHash"
|
||||
, size => $compressedSize
|
||||
, compressionType => $compressionType
|
||||
, narHash => "$narHash"
|
||||
, narSize => $narSize
|
||||
, references => join(" ", @{$refs})
|
||||
, deriver => $deriver
|
||||
}
|
||||
] if $writeManifest;
|
||||
}
|
||||
|
||||
printf STDERR "total compressed size %.2f MiB, %.1f%%\n",
|
||||
$totalCompressedSize / (1024 * 1024), $totalCompressedSize / ($totalNarSize || 1) * 100;
|
||||
|
||||
|
||||
# Optionally write a manifest.
|
||||
writeManifest($manifestPath // "$destDir/MANIFEST", \%narFiles, \()) if $writeManifest;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user