mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-06-08 14:23:40 +00:00
Compare commits
631 Commits
v206
...
release-14
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca323ed1bb | ||
|
|
8a3eea0548 | ||
|
|
e4ee5c797c | ||
|
|
92dd442e43 | ||
|
|
ed574b950a | ||
|
|
d16b0e3ae5 | ||
|
|
592b4f7a3e | ||
|
|
11ba869ae7 | ||
|
|
cf3d27a6e9 | ||
|
|
924fe493df | ||
|
|
9be183955d | ||
|
|
a4e0357cae | ||
|
|
92466a8454 | ||
|
|
c343d80490 | ||
|
|
3fa379d9a3 | ||
|
|
b9d5e14d1b | ||
|
|
7c238fbd59 | ||
|
|
0e04ba396e | ||
|
|
f83b2c4178 | ||
|
|
e501adfb64 | ||
|
|
6173acfd98 | ||
|
|
71c13be184 | ||
|
|
f4bc92fb99 | ||
|
|
d91bffeb13 | ||
|
|
0efa789071 | ||
|
|
3365f39da4 | ||
|
|
9ff4738e5f | ||
|
|
20fb57a528 | ||
|
|
a3b3205179 | ||
|
|
3b43da9fa5 | ||
|
|
7e7f00c898 | ||
|
|
1f2d6a022e | ||
|
|
e7a8157372 | ||
|
|
dbbe29e095 | ||
|
|
167dcce8ff | ||
|
|
55170645ef | ||
|
|
2253aa9b75 | ||
|
|
0420a025e3 | ||
|
|
b2cb57e1c3 | ||
|
|
58c9322244 | ||
|
|
aa61c12112 | ||
|
|
1ed7214396 | ||
|
|
bcd78d6564 | ||
|
|
7fcafc09a5 | ||
|
|
f77806acdf | ||
|
|
0521f9d125 | ||
|
|
fa0adad077 | ||
|
|
4290f2c74b | ||
|
|
410a4ea663 | ||
|
|
8183166846 | ||
|
|
cd261645fa | ||
|
|
1901da5bbd | ||
|
|
59ce92eb62 | ||
|
|
c3a8624ac2 | ||
|
|
969090442b | ||
|
|
a34c0c58d3 | ||
|
|
ef67865e5d | ||
|
|
fbd732860a | ||
|
|
6a9e7582b4 | ||
|
|
2b0caccb7b | ||
|
|
5b1015578c | ||
|
|
0a24b3da2d | ||
|
|
a40ea27684 | ||
|
|
6b704bcdcc | ||
|
|
37edf304b8 | ||
|
|
910364a0af | ||
|
|
89dda7a106 | ||
|
|
c9de7b93c0 | ||
|
|
2b022ca153 | ||
|
|
c19dd1e04a | ||
|
|
975f36b68a | ||
|
|
a640ee54b2 | ||
|
|
ffb3ead6c5 | ||
|
|
dbb8603c5d | ||
|
|
0c9dad3bde | ||
|
|
e6e9bdf846 | ||
|
|
211914a4a6 | ||
|
|
cbacb16cee | ||
|
|
3a6555c18a | ||
|
|
d7ceaf4f4e | ||
|
|
c3ddfef8f6 | ||
|
|
d7d593b57f | ||
|
|
8fc1927e2d | ||
|
|
ae1c5b8783 | ||
|
|
1fc25b90dd | ||
|
|
997e1ebb2c | ||
|
|
6f91248649 | ||
|
|
d0ccb711a0 | ||
|
|
ba886d92ae | ||
|
|
4c9ef9f75c | ||
|
|
71b2df28fc | ||
|
|
15efb9ccf9 | ||
|
|
6982c7ccf8 | ||
|
|
af217bae29 | ||
|
|
29b8c6a4e6 | ||
|
|
6aa0a568ab | ||
|
|
054d9939b5 | ||
|
|
66af731b14 | ||
|
|
fec11dcecb | ||
|
|
852cecdd39 | ||
|
|
26b37474e7 | ||
|
|
3f0360927e | ||
|
|
b7451d91e8 | ||
|
|
654eaeb2ca | ||
|
|
0e935f1eb2 | ||
|
|
dbadfad0a2 | ||
|
|
3d86e80ef3 | ||
|
|
e903ad0fa5 | ||
|
|
8aa0157de9 | ||
|
|
964d18d89e | ||
|
|
41d3d1b306 | ||
|
|
56b7e164eb | ||
|
|
b9bde98161 | ||
|
|
01dfd5a44a | ||
|
|
562ff9c1e1 | ||
|
|
fece51a8a6 | ||
|
|
9a66026234 | ||
|
|
c294fe0f53 | ||
|
|
4f85481ce0 | ||
|
|
9766bd2f4e | ||
|
|
9eb8f47666 | ||
|
|
77cda0aa83 | ||
|
|
3baef65dc6 | ||
|
|
d530f889ed | ||
|
|
6e1a74d284 | ||
|
|
eb02ca8c03 | ||
|
|
d2739c17ef | ||
|
|
4438e5d9d8 | ||
|
|
847ec71960 | ||
|
|
a0f9aa8184 | ||
|
|
0115853aa9 | ||
|
|
8da96f6b0e | ||
|
|
5f2f1b05e3 | ||
|
|
8cf5281744 | ||
|
|
4dfca8e14a | ||
|
|
7185fc1054 | ||
|
|
d927ce03e4 | ||
|
|
095d42101c | ||
|
|
caeba6f22a | ||
|
|
f1ce80f98e | ||
|
|
f963f57b62 | ||
|
|
2c7acc6731 | ||
|
|
360b0a7b70 | ||
|
|
a296abde48 | ||
|
|
ebacaf95f9 | ||
|
|
6bee20d12f | ||
|
|
eda84cb2fd | ||
|
|
4e5c8b34f8 | ||
|
|
1361e2f97e | ||
|
|
ef2f94c6fe | ||
|
|
0a3dc55ffc | ||
|
|
4962edc4d0 | ||
|
|
f446555c23 | ||
|
|
83f7e4689b | ||
|
|
9e580c1944 | ||
|
|
c0d4ce3e5b | ||
|
|
0569cc408a | ||
|
|
5900bfb4ee | ||
|
|
6797cb5c3b | ||
|
|
953433939b | ||
|
|
494b315d3a | ||
|
|
b951b618e8 | ||
|
|
7d8cffa31a | ||
|
|
8954ea814e | ||
|
|
a617e80aa4 | ||
|
|
4800bbbe57 | ||
|
|
300e25cfaa | ||
|
|
9e170188ee | ||
|
|
8d9f9d5b87 | ||
|
|
72162706a7 | ||
|
|
03bec38123 | ||
|
|
f9c24179f1 | ||
|
|
c0182b6b07 | ||
|
|
ec17cf89cc | ||
|
|
9203f22238 | ||
|
|
a5e7f0831c | ||
|
|
0aeed5baa6 | ||
|
|
c5d63cb35e | ||
|
|
e4805e3d34 | ||
|
|
41f8b13fa1 | ||
|
|
5a6541ec28 | ||
|
|
3b9fceab24 | ||
|
|
e64237cdb4 | ||
|
|
2bc3109460 | ||
|
|
521399f5cd | ||
|
|
2a6fee4c06 | ||
|
|
41df91401e | ||
|
|
1e42f0625a | ||
|
|
3e8072659a | ||
|
|
1aa1cb700b | ||
|
|
77fcd5fc23 | ||
|
|
2a173d70c2 | ||
|
|
2b27053695 | ||
|
|
233a5db368 | ||
|
|
75fb186f50 | ||
|
|
155996ebde | ||
|
|
1c9afeed07 | ||
|
|
4d8f020912 | ||
|
|
e8b62a519a | ||
|
|
a0e7caac60 | ||
|
|
bd5036c890 | ||
|
|
5a06477a3d | ||
|
|
b7f86f56d1 | ||
|
|
7d031e5a2c | ||
|
|
9cc04de7eb | ||
|
|
f0a363c910 | ||
|
|
2048460bdf | ||
|
|
aed21bd6d5 | ||
|
|
48a10fc66e | ||
|
|
b79e3ce6a7 | ||
|
|
1c0068a0c9 | ||
|
|
23789cc23e | ||
|
|
217724b340 | ||
|
|
0d133f7c62 | ||
|
|
f9f5be6113 | ||
|
|
2abcf20f7b | ||
|
|
8d413eb4a7 | ||
|
|
351aec7002 | ||
|
|
48c543c32f | ||
|
|
1b117a59d2 | ||
|
|
1ec17b2585 | ||
|
|
f4eaaee52a | ||
|
|
71e68bb52c | ||
|
|
e592a0e94b | ||
|
|
526be644a8 | ||
|
|
11e57b88ee | ||
|
|
e6da853ad1 | ||
|
|
9425114fbd | ||
|
|
dd1e64444d | ||
|
|
857d14dbba | ||
|
|
71dce79daa | ||
|
|
c3cce5d11f | ||
|
|
a8df3f1166 | ||
|
|
3e4e106674 | ||
|
|
7f5d30572d | ||
|
|
a6cdb424ba | ||
|
|
379116980f | ||
|
|
2def4e4b64 | ||
|
|
6593a986a9 | ||
|
|
8e338e3a0b | ||
|
|
de12367e89 | ||
|
|
937ee6c191 | ||
|
|
3f95644a28 | ||
|
|
6077ef462e | ||
|
|
ca377078b2 | ||
|
|
33afc8161e | ||
|
|
6de89bfa66 | ||
|
|
bee9b9c2d1 | ||
|
|
94e0149a18 | ||
|
|
e3cf157d15 | ||
|
|
85a15ddfd7 | ||
|
|
d1fddb2698 | ||
|
|
2227e07345 | ||
|
|
085ef8f1b4 | ||
|
|
1d480b97ba | ||
|
|
f6ad69a9d8 | ||
|
|
57f53ed84e | ||
|
|
6c4b4c146f | ||
|
|
6ec5022ac6 | ||
|
|
6a89670576 | ||
|
|
735bfb9847 | ||
|
|
e5fe68dd34 | ||
|
|
87d2fbb50a | ||
|
|
6756ec27dd | ||
|
|
7b19f22bb4 | ||
|
|
a351ad3edd | ||
|
|
0f6f98755e | ||
|
|
971b92057a | ||
|
|
235cceac93 | ||
|
|
99a7a9cd34 | ||
|
|
ea433712c2 | ||
|
|
93160b855e | ||
|
|
c920b9f9f7 | ||
|
|
9c4ea0631e | ||
|
|
67b4e3ff73 | ||
|
|
6c47697e72 | ||
|
|
a94ce55ddb | ||
|
|
7bd5fb33ee | ||
|
|
7bb5592d59 | ||
|
|
5179b515da | ||
|
|
d2cc427e6d | ||
|
|
a8f6601fc6 | ||
|
|
713e7482f3 | ||
|
|
d0bd55da53 | ||
|
|
51dc1ddb7c | ||
|
|
1c5a92c530 | ||
|
|
79b206e63f | ||
|
|
9093b344ae | ||
|
|
c0121397f8 | ||
|
|
d62d4704de | ||
|
|
a4060bbb98 | ||
|
|
4076129dcb | ||
|
|
5ccfe62082 | ||
|
|
03f1e336c7 | ||
|
|
73c4148685 | ||
|
|
3106853c1b | ||
|
|
231d76abe0 | ||
|
|
c7e73e8436 | ||
|
|
c4245c8e7b | ||
|
|
05543ef6e0 | ||
|
|
e007559e95 | ||
|
|
5591fb606c | ||
|
|
e66d3953ae | ||
|
|
acc00a7ee1 | ||
|
|
a4ad3b8127 | ||
|
|
69852b1c64 | ||
|
|
dfcb042f67 | ||
|
|
74859a88e5 | ||
|
|
d22d14f878 | ||
|
|
e6fe1e0e86 | ||
|
|
aedffc6b62 | ||
|
|
9024912a53 | ||
|
|
764d0effa4 | ||
|
|
368e66cd0b | ||
|
|
b9c312fe27 | ||
|
|
f6f9e85e25 | ||
|
|
b22f28b0e3 | ||
|
|
96d1ffd082 | ||
|
|
b84584f5dc | ||
|
|
276a5e3b88 | ||
|
|
c0867734e4 | ||
|
|
0a8c8839df | ||
|
|
136d6771b5 | ||
|
|
56cfab3831 | ||
|
|
2d3a73ae5c | ||
|
|
93c0f4a5f1 | ||
|
|
2e8ce570e7 | ||
|
|
06d781bea3 | ||
|
|
0276eb144c | ||
|
|
b3d9172470 | ||
|
|
08b679e732 | ||
|
|
9fa93015c0 | ||
|
|
a088ed9fe5 | ||
|
|
cc492d6d0a | ||
|
|
d5e50145de | ||
|
|
802d2a8e54 | ||
|
|
b49d853a18 | ||
|
|
94b3b435ca | ||
|
|
45413771e8 | ||
|
|
a4ac76b895 | ||
|
|
c029464778 | ||
|
|
80661f4dc2 | ||
|
|
67a5cd73a4 | ||
|
|
d8a6402373 | ||
|
|
4e74129777 | ||
|
|
798a989145 | ||
|
|
3214a5f293 | ||
|
|
ba23a02094 | ||
|
|
65f5c730df | ||
|
|
ca5061b125 | ||
|
|
a89bac9e4d | ||
|
|
979adb866c | ||
|
|
dc71acb8cd | ||
|
|
00312d90b9 | ||
|
|
24edc80145 | ||
|
|
239043c826 | ||
|
|
e478101a9b | ||
|
|
8a29cd0b33 | ||
|
|
ea1952bff2 | ||
|
|
01d67b7d59 | ||
|
|
d5a98173b4 | ||
|
|
6045631acf | ||
|
|
9c4a974b5a | ||
|
|
dfb9cc2d4c | ||
|
|
501c32aaf8 | ||
|
|
2937a30a32 | ||
|
|
31f9fcf420 | ||
|
|
154e06c178 | ||
|
|
39e7705f50 | ||
|
|
dc1a196287 | ||
|
|
aa19ce936b | ||
|
|
6fe0fead28 | ||
|
|
fecc667e90 | ||
|
|
e07b9938d0 | ||
|
|
d98716ded4 | ||
|
|
acae580f9a | ||
|
|
f5de056bc8 | ||
|
|
51d3efed02 | ||
|
|
044a24e58b | ||
|
|
c9763e20e5 | ||
|
|
35c76d9173 | ||
|
|
97d9d26a7b | ||
|
|
ce13d17856 | ||
|
|
9819094b89 | ||
|
|
3abf903a5a | ||
|
|
82ab2f6363 | ||
|
|
58312cab7c | ||
|
|
c071a4573c | ||
|
|
14695233ea | ||
|
|
eb6309c87f | ||
|
|
06d38cd60a | ||
|
|
ef3c59c5ec | ||
|
|
1d24df4063 | ||
|
|
4dc6e22c21 | ||
|
|
bfff5e4475 | ||
|
|
0884ff51ea | ||
|
|
6de37e68e0 | ||
|
|
b3747fc9d5 | ||
|
|
2e22c13a35 | ||
|
|
c739957979 | ||
|
|
054eae1cc3 | ||
|
|
e06e9e1105 | ||
|
|
c49f640ed8 | ||
|
|
d50ce3a21f | ||
|
|
1b4a5c52b0 | ||
|
|
e774419033 | ||
|
|
ecdb0f7867 | ||
|
|
18602b0656 | ||
|
|
f73e7d33c2 | ||
|
|
dad7523db2 | ||
|
|
fab8b036f3 | ||
|
|
5b26870e18 | ||
|
|
1e02e79a16 | ||
|
|
028d2479dd | ||
|
|
1a5ce29795 | ||
|
|
530ad13c26 | ||
|
|
106ff6fb37 | ||
|
|
feab8c784d | ||
|
|
4d36234940 | ||
|
|
4e87d1b90e | ||
|
|
a58455c024 | ||
|
|
7c5691ba70 | ||
|
|
2c3184a0ce | ||
|
|
6acb503cba | ||
|
|
243fe226f5 | ||
|
|
c23360496c | ||
|
|
77cf3a8a70 | ||
|
|
4e61a2ae87 | ||
|
|
2fd0d5bffb | ||
|
|
5aad39e6da | ||
|
|
2c8f6e0679 | ||
|
|
b2d29943fa | ||
|
|
5c3f2c1087 | ||
|
|
7fba471dc2 | ||
|
|
9d0d374bd8 | ||
|
|
9baa033f8d | ||
|
|
8d6688d866 | ||
|
|
4497554833 | ||
|
|
e77c1cf891 | ||
|
|
8d3f066bc4 | ||
|
|
78916e0257 | ||
|
|
2c176a2a6e | ||
|
|
888af166ca | ||
|
|
7bc02074b1 | ||
|
|
9bb943b14d | ||
|
|
a5a5a87f2e | ||
|
|
17d074d0b5 | ||
|
|
53f82b134b | ||
|
|
62f157e5f4 | ||
|
|
648edae309 | ||
|
|
82d96b5a18 | ||
|
|
457f2c2835 | ||
|
|
314952cdc8 | ||
|
|
d719c77dd0 | ||
|
|
3d992546f9 | ||
|
|
03cc78bbde | ||
|
|
3a76854aad | ||
|
|
00af817900 | ||
|
|
c3bc254628 | ||
|
|
1f07b94d39 | ||
|
|
ccf34c6d99 | ||
|
|
9642d4158b | ||
|
|
a8d06d2ea1 | ||
|
|
eb22292305 | ||
|
|
ccd3b3397e | ||
|
|
41895eabb9 | ||
|
|
6db3164d1f | ||
|
|
5250ce3e89 | ||
|
|
0a18a7b5b7 | ||
|
|
430a2bf52f | ||
|
|
5de4e94028 | ||
|
|
75441a5abb | ||
|
|
33587cd7ba | ||
|
|
6a0c87ccfe | ||
|
|
2764a05d4e | ||
|
|
02b056c5b1 | ||
|
|
e6f4bdb1bb | ||
|
|
6f8ee84cc9 | ||
|
|
b89c5378d0 | ||
|
|
84308245e8 | ||
|
|
c476f4a237 | ||
|
|
ccea12cba2 | ||
|
|
4cbc48f236 | ||
|
|
21e8cfac80 | ||
|
|
b8564f7bb0 | ||
|
|
ff8ce29764 | ||
|
|
0711574c29 | ||
|
|
9d9c797d75 | ||
|
|
fcdf7e80ab | ||
|
|
5ceef8d2b1 | ||
|
|
3cc279966d | ||
|
|
faf51667ea | ||
|
|
6d27026353 | ||
|
|
54a7d1d23e | ||
|
|
9f4d06adae | ||
|
|
24214d8517 | ||
|
|
42b9f99db1 | ||
|
|
42bf7ca3e1 | ||
|
|
48f3bb944e | ||
|
|
e3be224207 | ||
|
|
13ce9bc60f | ||
|
|
568930ca3e | ||
|
|
ff2bd64a4c | ||
|
|
f9cb9a67ab | ||
|
|
7b1401ba29 | ||
|
|
958fc5076f | ||
|
|
9cafa3c615 | ||
|
|
a21155609e | ||
|
|
5a6090529f | ||
|
|
4df0681dfe | ||
|
|
5619db6872 | ||
|
|
4829a4d14c | ||
|
|
65aed4c96f | ||
|
|
b8d1205fdc | ||
|
|
b20e64b32b | ||
|
|
387237fcb8 | ||
|
|
6bb78819c0 | ||
|
|
84ab83d261 | ||
|
|
31bf76e3e2 | ||
|
|
094fc34810 | ||
|
|
68744afca3 | ||
|
|
066855bc88 | ||
|
|
ba3b38d73f | ||
|
|
20f79ee906 | ||
|
|
d9e69e3136 | ||
|
|
a2ebf3a767 | ||
|
|
10ef32c08d | ||
|
|
86e1778409 | ||
|
|
f7cdc5d5fe | ||
|
|
64fd7e5757 | ||
|
|
7392915ddc | ||
|
|
11c5154b47 | ||
|
|
ca0d0f83ca | ||
|
|
b72398906f | ||
|
|
00c45fb8ba | ||
|
|
a2d659a4e6 | ||
|
|
fcc00bd0b5 | ||
|
|
3f4e115444 | ||
|
|
ef4d792827 | ||
|
|
6f5fff79a8 | ||
|
|
795de7faf5 | ||
|
|
a88b0e4bc2 | ||
|
|
718faf3116 | ||
|
|
26e8a18ce7 | ||
|
|
97cb3ea472 | ||
|
|
48234a5f3d | ||
|
|
08efdc72e6 | ||
|
|
abd636291f | ||
|
|
5b3a2abaa0 | ||
|
|
63c27b367a | ||
|
|
27261cc765 | ||
|
|
02d920f3c4 | ||
|
|
9131402036 | ||
|
|
aec0d8b0f5 | ||
|
|
e874b13935 | ||
|
|
b030f2bd8f | ||
|
|
e1f2ba1f54 | ||
|
|
e59a864a18 | ||
|
|
44e3b9e808 | ||
|
|
e237476d64 | ||
|
|
9dfbab0b52 | ||
|
|
673b2d1650 | ||
|
|
1417d2226f | ||
|
|
b725dc2ed9 | ||
|
|
b09da697d3 | ||
|
|
85c8b16fd4 | ||
|
|
7644e30eb2 | ||
|
|
3c4ee44079 | ||
|
|
d9e02c1df3 | ||
|
|
3bd9a1ae03 | ||
|
|
7109965cd5 | ||
|
|
bea158d89c | ||
|
|
a0b81c40a2 | ||
|
|
cc614c0d4c | ||
|
|
56285c17db | ||
|
|
a37635ee56 | ||
|
|
47def457a1 | ||
|
|
6a9d230040 | ||
|
|
3073e062d6 | ||
|
|
9a10937f32 | ||
|
|
770cd1cd32 | ||
|
|
1062181037 | ||
|
|
5546e5b5a4 | ||
|
|
689d7e048d | ||
|
|
8851990313 | ||
|
|
dddbcae845 | ||
|
|
1ddbdcdc2d | ||
|
|
c6d2739d4b | ||
|
|
8c65992314 | ||
|
|
a58e004778 | ||
|
|
109a2bee28 | ||
|
|
4001f85b0c | ||
|
|
c3917f4d84 | ||
|
|
feecc6067a | ||
|
|
0d5e3df9d9 | ||
|
|
ef618678b8 | ||
|
|
4a0c468043 | ||
|
|
18d2284d15 | ||
|
|
7e375e9aa2 | ||
|
|
efd39af1f4 | ||
|
|
4e15c2ecc0 | ||
|
|
14fd47651a | ||
|
|
c46e466c40 | ||
|
|
f171ed481b | ||
|
|
242eadeb48 | ||
|
|
9cdf29589c | ||
|
|
46c3c741b0 | ||
|
|
0cb2766511 | ||
|
|
827c9be4e3 | ||
|
|
36d73c923c | ||
|
|
86a3024dc2 | ||
|
|
14090a2fe3 | ||
|
|
1c38eb71e6 | ||
|
|
f1faa45bdb | ||
|
|
b226e4af87 | ||
|
|
372647f6ab | ||
|
|
18ced7db7b | ||
|
|
7e5a05ce9b | ||
|
|
0c84492519 | ||
|
|
ae7ea8dc06 | ||
|
|
5ca1f24a96 | ||
|
|
973f83d91a | ||
|
|
2f9b9de73c | ||
|
|
afbe2b6720 | ||
|
|
85f8efc834 | ||
|
|
b845776a90 | ||
|
|
7043225be2 | ||
|
|
e46e9fe4ac | ||
|
|
4dda8b76fe | ||
|
|
bc4361ee29 | ||
|
|
e001ac6a9e |
16
.gitignore
vendored
16
.gitignore
vendored
@@ -3,16 +3,8 @@
|
||||
.*.swp
|
||||
.*.swo
|
||||
result
|
||||
result-*
|
||||
/doc/NEWS.html
|
||||
/doc/NEWS.txt
|
||||
/doc/manual.html
|
||||
/doc/manual.pdf
|
||||
doc/NEWS.html
|
||||
doc/NEWS.txt
|
||||
doc/manual.html
|
||||
doc/manual.pdf
|
||||
.version-suffix
|
||||
|
||||
.DS_Store
|
||||
|
||||
/pkgs/applications/kde-apps-*/tmp/
|
||||
/pkgs/development/libraries/kde-frameworks-*/tmp/
|
||||
/pkgs/development/libraries/qt-5/*/tmp/
|
||||
/pkgs/desktops/plasma-*/tmp/
|
||||
@@ -1,6 +1,5 @@
|
||||
language: python
|
||||
python: "3.4"
|
||||
sudo: required
|
||||
before_install: ./maintainers/scripts/travis-nox-review-pr.sh nix
|
||||
install: ./maintainers/scripts/travis-nox-review-pr.sh nox
|
||||
script: ./maintainers/scripts/travis-nox-review-pr.sh build
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
# How to contribute
|
||||
|
||||
## Opening issues
|
||||
|
||||
* Make sure you have a [GitHub account](https://github.com/signup/free)
|
||||
* [Submit an issue](https://github.com/NixOS/nixpkgs/issues) - assuming one does not already exist.
|
||||
* Clearly describe the issue including steps to reproduce when it is a bug.
|
||||
* Include information what version of nixpkgs and Nix are you using (nixos-version or git revision).
|
||||
|
||||
## Submitting changes
|
||||
|
||||
See the nixpkgs manual for details on how to [Submit changes to nixpkgs](http://hydra.nixos.org/job/nixpkgs/trunk/manual/latest/download-by-type/doc/manual#chap-submitting-changes).
|
||||
48
README.md
48
README.md
@@ -1,44 +1,10 @@
|
||||
[<img src="http://nixos.org/logo/nixos-hires.png" width="500px" alt="logo" />](https://nixos.org/nixos)
|
||||
|
||||
[](https://travis-ci.org/NixOS/nixpkgs)
|
||||
[](http://www.issuestats.com/github/nixos/nixpkgs)
|
||||
[](http://www.issuestats.com/github/nixos/nixpkgs)
|
||||
|
||||
Nixpkgs is a collection of packages for the [Nix](https://nixos.org/nix/) package
|
||||
manager. It is periodically built and tested by the [hydra](http://hydra.nixos.org/)
|
||||
build daemon as so-called channels. To get channel information via git, add
|
||||
[nixpkgs-channels](https://github.com/NixOS/nixpkgs-channels.git) as a remote:
|
||||
|
||||
```
|
||||
% git remote add channels git://github.com/NixOS/nixpkgs-channels.git
|
||||
```
|
||||
|
||||
For stability and maximum binary package support, it is recommended to maintain
|
||||
custom changes on top of one of the channels, e.g. `nixos-15.09` for the latest
|
||||
release and `nixos-unstable` for the latest successful build of master:
|
||||
|
||||
```
|
||||
% git remote update channels
|
||||
% git rebase channels/nixos-15.09
|
||||
```
|
||||
|
||||
For pull-requests, please rebase onto nixpkgs `master`.
|
||||
|
||||
[NixOS](https://nixos.org/nixos/) linux distribution source code is located inside
|
||||
`nixos/` folder.
|
||||
|
||||
* [NixOS installation instructions](https://nixos.org/nixos/manual/#ch-installation)
|
||||
* [Documentation (Nix Expression Language chapter)](https://nixos.org/nix/manual/#ch-expression-language)
|
||||
* [Manual (How to write packages for Nix)](https://nixos.org/nixpkgs/manual/)
|
||||
* [Manual (NixOS)](https://nixos.org/nixos/manual/)
|
||||
* [Continuous package builds for unstable/master](https://hydra.nixos.org/jobset/nixos/trunk-combined)
|
||||
* [Continuous package builds for 14.12 release](https://hydra.nixos.org/jobset/nixos/release-14.12)
|
||||
* [Continuous package builds for 15.09 release](https://hydra.nixos.org/jobset/nixos/release-15.09)
|
||||
* [Tests for unstable/master](https://hydra.nixos.org/job/nixos/trunk-combined/tested#tabs-constituents)
|
||||
* [Tests for 14.12 release](https://hydra.nixos.org/job/nixos/release-14.12/tested#tabs-constituents)
|
||||
* [Tests for 15.09 release](https://hydra.nixos.org/job/nixos/release-15.09/tested#tabs-constituents)
|
||||
|
||||
Communication:
|
||||
Nixpkgs is a collection of packages for [Nix](http://nixos.org/nix/) package
|
||||
manager. Nixpkgs also includes [NixOS](http://nixos.org/nixos/) linux distribution source code.
|
||||
|
||||
* [NixOS installation instructions](http://nixos.org/nixos/manual/#installing-nixos)
|
||||
* [Manual (How to write packages for Nix)](http://nixos.org/nixpkgs/manual/)
|
||||
* [Manual (NixOS)](http://nixos.org/nixos/manual/)
|
||||
* [Continuous build](http://hydra.nixos.org/jobset/nixos/trunk-combined)
|
||||
* [Tests](http://hydra.nixos.org/job/nixos/trunk-combined/tested#tabs-constituents)
|
||||
* [Mailing list](http://lists.science.uu.nl/mailman/listinfo/nix-dev)
|
||||
* [IRC - #nixos on freenode.net](irc://irc.freenode.net/#nixos)
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
let requiredVersion = "1.10"; in
|
||||
if ! builtins ? nixVersion || builtins.compareVersions "1.6" builtins.nixVersion == 1 then
|
||||
|
||||
if ! builtins ? nixVersion || builtins.compareVersions requiredVersion builtins.nixVersion == 1 then
|
||||
|
||||
abort "This version of Nixpkgs requires Nix >= ${requiredVersion}, please upgrade! See https://nixos.org/wiki/How_to_update_when_Nix_is_too_old_to_evaluate_Nixpkgs"
|
||||
abort "This version of Nixpkgs requires Nix >= 1.6, please upgrade!"
|
||||
|
||||
else
|
||||
|
||||
|
||||
41
doc/Makefile
Normal file
41
doc/Makefile
Normal file
@@ -0,0 +1,41 @@
|
||||
# You may need to override this.
|
||||
docbookxsl = $(HOME)/.nix-profile/xml/xsl/docbook
|
||||
dblatex = dblatex
|
||||
|
||||
XMLLINT = xmllint --catalogs
|
||||
XSLTPROC = xsltproc --catalogs \
|
||||
--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\'
|
||||
|
||||
NEWS_OPTS = \
|
||||
--stringparam generate.toc "article nop" \
|
||||
--stringparam section.autolabel.max.depth 0 \
|
||||
--stringparam header.rule 0
|
||||
|
||||
all: NEWS.html NEWS.txt manual.html manual.pdf
|
||||
|
||||
NEWS.html: release-notes.xml
|
||||
$(XSLTPROC) --nonet --xinclude --output $@ $(NEWS_OPTS) \
|
||||
$(docbookxsl)/xhtml/docbook.xsl release-notes.xml
|
||||
|
||||
NEWS.txt: release-notes.xml
|
||||
$(XSLTPROC) --nonet --xinclude quote-literals.xsl release-notes.xml | \
|
||||
$(XSLTPROC) --nonet --output $@.tmp.html $(NEWS_OPTS) \
|
||||
$(docbookxsl)/xhtml/docbook.xsl -
|
||||
LANG=en_US w3m -dump $@.tmp.html > $@
|
||||
rm $@.tmp.html
|
||||
|
||||
manual.html: *.xml
|
||||
$(XSLTPROC) --nonet --xinclude --output manual.html \
|
||||
$(docbookxsl)/xhtml/docbook.xsl manual.xml
|
||||
|
||||
manual.pdf: *.xml
|
||||
$(dblatex) \
|
||||
-P doc.collab.show=0 \
|
||||
-P latex.output.revhistory=0 \
|
||||
manual.xml
|
||||
@@ -5,7 +5,7 @@
|
||||
<title>Coding conventions</title>
|
||||
|
||||
|
||||
<section xml:id="sec-syntax"><title>Syntax</title>
|
||||
<section><title>Syntax</title>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
@@ -169,8 +169,8 @@ stdenv.mkDerivation { ...
|
||||
args: with args; <replaceable>...</replaceable>
|
||||
</programlisting>
|
||||
|
||||
or
|
||||
|
||||
or
|
||||
|
||||
<programlisting>
|
||||
{ stdenv, fetchurl, perl, ... }: <replaceable>...</replaceable>
|
||||
</programlisting>
|
||||
@@ -207,7 +207,7 @@ args.stdenv.mkDerivation (args // {
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-package-naming"><title>Package naming</title>
|
||||
<section><title>Package naming</title>
|
||||
|
||||
<para>In Nixpkgs, there are generally three different names associated with a package:
|
||||
|
||||
@@ -256,12 +256,6 @@ bound to the variable name <varname>e2fsprogs</varname> in
|
||||
a package named <literal>hello-svn</literal> by
|
||||
<command>nix-env</command>.</para></listitem>
|
||||
|
||||
<listitem><para>If package is fetched from git's commit then
|
||||
the version part of the name <emphasis>must</emphasis> be the date of that
|
||||
(fetched) commit. The date must be in <literal>"YYYY-MM-DD"</literal> format.
|
||||
Also add <literal>"git"</literal> to the name - e.g.,
|
||||
<literal>"pkgname-git-2014-09-23"</literal>.</para></listitem>
|
||||
|
||||
<listitem><para>Dashes in the package name should be preserved
|
||||
in new variable names, rather than converted to underscores
|
||||
(which was convention up to around 2013 and most names
|
||||
@@ -292,7 +286,7 @@ dashes between words — not in camel case. For instance, it should be
|
||||
<filename>allPackages.nix</filename> or
|
||||
<filename>AllPackages.nix</filename>.</para>
|
||||
|
||||
<section xml:id="sec-hierarchy"><title>Hierarchy</title>
|
||||
<section><title>Hierarchy</title>
|
||||
|
||||
<para>Each package should be stored in its own directory somewhere in
|
||||
the <filename>pkgs/</filename> tree, i.e. in
|
||||
@@ -451,17 +445,12 @@ splitting up an existing category.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s a <emphasis>desktop environment</emphasis>:</term>
|
||||
<term>If it’s a <emphasis>desktop environment</emphasis>
|
||||
(including <emphasis>window managers</emphasis>):</term>
|
||||
<listitem>
|
||||
<para><filename>desktops</filename> (e.g. <filename>kde</filename>, <filename>gnome</filename>, <filename>enlightenment</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s a <emphasis>window manager</emphasis>:</term>
|
||||
<listitem>
|
||||
<para><filename>applications/window-managers</filename> (e.g. <filename>awesome</filename>, <filename>compiz</filename>, <filename>stumpwm</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s an <emphasis>application</emphasis>:</term>
|
||||
<listitem>
|
||||
@@ -609,57 +598,6 @@ evaluate correctly.</para>
|
||||
</section>
|
||||
|
||||
</section>
|
||||
<section xml:id="sec-sources"><title>Fetching Sources</title>
|
||||
<para>There are multiple ways to fetch a package source in nixpkgs. The
|
||||
general guidline is that you should package sources with a high degree of
|
||||
availability. Right now there is only one fetcher which has mirroring
|
||||
support and that is <literal>fetchurl</literal>. Note that you should also
|
||||
prefer protocols which have a corresponding proxy environment variable.
|
||||
</para>
|
||||
<para>You can find many source fetch helpers in <literal>pkgs/build-support/fetch*</literal>.
|
||||
</para>
|
||||
<para>In the file <literal>pkgs/top-level/all-packages.nix</literal> you can
|
||||
find fetch helpers, these have names on the form
|
||||
<literal>fetchFrom*</literal>. The intention of these are to provide
|
||||
snapshot fetches but using the same api as some of the version controlled
|
||||
fetchers from <literal>pkgs/build-support/</literal>. As an example going
|
||||
from bad to good:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Uses <literal>git://</literal> which won't be proxied.
|
||||
<programlisting>
|
||||
src = fetchgit {
|
||||
url = "git://github.com/NixOS/nix.git";
|
||||
rev = "1f795f9f44607cc5bec70d1300150bfefcef2aae";
|
||||
sha256 = "1cw5fszffl5pkpa6s6wjnkiv6lm5k618s32sp60kvmvpy7a2v9kg";
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>This is ok, but an archive fetch will still be faster.
|
||||
<programlisting>
|
||||
src = fetchgit {
|
||||
url = "https://github.com/NixOS/nix.git";
|
||||
rev = "1f795f9f44607cc5bec70d1300150bfefcef2aae";
|
||||
sha256 = "1cw5fszffl5pkpa6s6wjnkiv6lm5k618s32sp60kvmvpy7a2v9kg";
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Fetches a snapshot archive and you get the rev you want.
|
||||
<programlisting>
|
||||
src = fetchFromGitHub {
|
||||
owner = "NixOS";
|
||||
repo = "nix";
|
||||
rev = "1f795f9f44607cc5bec70d1300150bfefcef2aae";
|
||||
sha256 = "04yri911rj9j19qqqn6m82266fl05pz98inasni0vxr1cf1gdgv9";
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
||||
</chapter>
|
||||
|
||||
@@ -2,19 +2,20 @@
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-contributing">
|
||||
|
||||
<title>Contributing to this documentation</title>
|
||||
<title>Contributing</title>
|
||||
|
||||
<para>The DocBook sources of the Nixpkgs manual are in the <filename
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/tree/master/doc">doc</filename>
|
||||
subdirectory of the Nixpkgs repository. If you make modifications to
|
||||
the manual, it's important to build it before committing. You can do that as follows:
|
||||
<para>If you make modifications to the manual, it's important to build the manual before contributing:</para>
|
||||
|
||||
<screen>
|
||||
$ cd /path/to/nixpkgs
|
||||
$ nix-build doc
|
||||
</screen>
|
||||
<orderedlist>
|
||||
|
||||
If the build succeeds, the manual will be in
|
||||
<filename>./result/share/doc/nixpkgs/manual.html</filename>.</para>
|
||||
<listitem><para><command>$ git clone git://github.com/NixOS/nixpkgs.git</command></para></listitem>
|
||||
|
||||
<listitem><para><command>$ cd nixpkgs/pkgs/top-level</command></para></listitem>
|
||||
|
||||
<listitem><para><command>$ nix-build -A tarball release.nix</command></para></listitem>
|
||||
|
||||
<listitem><para>Inside the built derivation you shall see <literal>manual/index.html</literal> file.</para></listitem>
|
||||
|
||||
</orderedlist>
|
||||
|
||||
</chapter>
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
with import ./.. { };
|
||||
with lib;
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "nixpkgs-manual";
|
||||
|
||||
sources = sourceFilesBySuffices ./. [".xml"];
|
||||
|
||||
buildInputs = [ pandoc libxml2 libxslt ];
|
||||
|
||||
xsltFlags = ''
|
||||
--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'
|
||||
'';
|
||||
|
||||
buildCommand = ''
|
||||
{
|
||||
echo "<chapter xmlns=\"http://docbook.org/ns/docbook\""
|
||||
echo " xmlns:xlink=\"http://www.w3.org/1999/xlink\""
|
||||
echo " xml:id=\"users-guide-to-the-haskell-infrastructure\">"
|
||||
echo ""
|
||||
echo "<title>User's Guide to the Haskell Infrastructure</title>"
|
||||
echo ""
|
||||
pandoc ${./haskell-users-guide.md} -w docbook | \
|
||||
sed -e 's|<ulink url=|<link xlink:href=|' \
|
||||
-e 's|</ulink>|</link>|' \
|
||||
-e 's|<sect. id=|<section xml:id=|' \
|
||||
-e 's|</sect[0-9]>|</section>|'
|
||||
echo ""
|
||||
echo "</chapter>"
|
||||
} >haskell-users-guide.xml
|
||||
|
||||
ln -s "$sources/"*.xml .
|
||||
|
||||
echo ${nixpkgsVersion} > .version
|
||||
|
||||
xmllint --noout --nonet --xinclude --noxincludenode \
|
||||
--relaxng ${docbook5}/xml/rng/docbook/docbook.rng \
|
||||
manual.xml
|
||||
|
||||
dst=$out/share/doc/nixpkgs
|
||||
mkdir -p $dst
|
||||
xsltproc $xsltFlags --nonet --xinclude \
|
||||
--output $dst/manual.html \
|
||||
${docbook5_xsl}/xml/xsl/docbook/xhtml/docbook.xsl \
|
||||
./manual.xml
|
||||
|
||||
cp ${./style.css} $dst/style.css
|
||||
|
||||
mkdir -p $dst/images/callouts
|
||||
cp "${docbook5_xsl}/xml/xsl/docbook/images/callouts/"*.gif $dst/images/callouts/
|
||||
|
||||
mkdir -p $out/nix-support
|
||||
echo "doc manual $dst manual.html" >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
}
|
||||
@@ -1,287 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-functions">
|
||||
|
||||
<title>Functions reference</title>
|
||||
|
||||
<para>
|
||||
The nixpkgs repository has several utility functions to manipulate Nix expressions.
|
||||
</para>
|
||||
|
||||
<section xml:id="sec-pkgs-overridePackages">
|
||||
<title>pkgs.overridePackages</title>
|
||||
|
||||
<para>
|
||||
This function inside the nixpkgs expression (<varname>pkgs</varname>)
|
||||
can be used to override the set of packages itself.
|
||||
</para>
|
||||
<para>
|
||||
Warning: this function is expensive and must not be used from within
|
||||
the nixpkgs repository.
|
||||
</para>
|
||||
<para>
|
||||
Example usage:
|
||||
|
||||
<programlisting>let
|
||||
pkgs = import <nixpkgs> {};
|
||||
newpkgs = pkgs.overridePackages (self: super: {
|
||||
foo = super.foo.override { ... };
|
||||
};
|
||||
in ...</programlisting>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The resulting <varname>newpkgs</varname> will have the new <varname>foo</varname>
|
||||
expression, and all other expressions depending on <varname>foo</varname> will also
|
||||
use the new <varname>foo</varname> expression.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The behavior of this function is similar to <link
|
||||
linkend="sec-modify-via-packageOverrides">config.packageOverrides</link>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <varname>self</varname> parameter refers to the final package set with the
|
||||
applied overrides. Using this parameter may lead to infinite recursion if not
|
||||
used consciously.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <varname>super</varname> parameter refers to the old package set.
|
||||
It's equivalent to <varname>pkgs</varname> in the above example.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="sec-pkg-override">
|
||||
<title><pkg>.override</title>
|
||||
|
||||
<para>
|
||||
The function <varname>override</varname> is usually available for all the
|
||||
derivations in the nixpkgs expression (<varname>pkgs</varname>).
|
||||
</para>
|
||||
<para>
|
||||
It is used to override the arguments passed to a function.
|
||||
</para>
|
||||
<para>
|
||||
Example usages:
|
||||
|
||||
<programlisting>pkgs.foo.override { arg1 = val1; arg2 = val2; ... }</programlisting>
|
||||
<programlisting>pkgs.overridePackages (self: super: {
|
||||
foo = super.foo.override { barSupport = true ; };
|
||||
})</programlisting>
|
||||
<programlisting>mypkg = pkgs.callPackage ./mypkg.nix {
|
||||
mydep = pkgs.mydep.override { ... };
|
||||
})</programlisting>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In the first example, <varname>pkgs.foo</varname> is the result of a function call
|
||||
with some default arguments, usually a derivation.
|
||||
Using <varname>pkgs.foo.override</varname> will call the same function with
|
||||
the given new arguments.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="sec-pkg-overrideDerivation">
|
||||
<title><pkg>.overrideDerivation</title>
|
||||
|
||||
<para>
|
||||
The function <varname>overrideDerivation</varname> is usually available for all the
|
||||
derivations in the nixpkgs expression (<varname>pkgs</varname>).
|
||||
</para>
|
||||
<para>
|
||||
It is used to create a new derivation by overriding the attributes of
|
||||
the original derivation according to the given function.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Example usage:
|
||||
|
||||
<programlisting>mySed = pkgs.gnused.overrideDerivation (oldAttrs: {
|
||||
name = "sed-4.2.2-pre";
|
||||
src = fetchurl {
|
||||
url = ftp://alpha.gnu.org/gnu/sed/sed-4.2.2-pre.tar.bz2;
|
||||
sha256 = "11nq06d131y4wmf3drm0yk502d2xc6n5qy82cg88rb9nqd2lj41k";
|
||||
};
|
||||
patches = [];
|
||||
});</programlisting>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In the above example, the name, src and patches of the derivation
|
||||
will be overridden, while all other attributes will be retained from the
|
||||
original derivation.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The argument <varname>oldAttrs</varname> is used to refer to the attribute set of
|
||||
the original derivation.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="sec-lib-makeOverridable">
|
||||
<title>lib.makeOverridable</title>
|
||||
|
||||
<para>
|
||||
The function <varname>lib.makeOverridable</varname> is used to make the result
|
||||
of a function easily customizable. This utility only makes sense for functions
|
||||
that accept an argument set and return an attribute set.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Example usage:
|
||||
|
||||
<programlisting>f = { a, b }: { result = a+b; }
|
||||
c = lib.makeOverridable f { a = 1; b = 2; }</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The variable <varname>c</varname> is the value of the <varname>f</varname> function
|
||||
applied with some default arguments. Hence the value of <varname>c.result</varname>
|
||||
is <literal>3</literal>, in this example.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The variable <varname>c</varname> however also has some additional functions, like
|
||||
<link linkend="sec-pkg-override">c.override</link> which can be used to
|
||||
override the default arguments. In this example the value of
|
||||
<varname>(c.override { a = 4; }).result</varname> is 6.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-fhs-environments">
|
||||
<title>buildFHSChrootEnv/buildFHSUserEnv</title>
|
||||
|
||||
<para>
|
||||
<function>buildFHSChrootEnv</function> and
|
||||
<function>buildFHSUserEnv</function> provide a way to build and run
|
||||
FHS-compatible lightweight sandboxes. They get their own isolated root with
|
||||
binded <filename>/nix/store</filename>, so their footprint in terms of disk
|
||||
space needed is quite small. This allows one to run software which is hard or
|
||||
unfeasible to patch for NixOS -- 3rd-party source trees with FHS assumptions,
|
||||
games distributed as tarballs, software with integrity checking and/or external
|
||||
self-updated binaries.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<function>buildFHSChrootEnv</function> allows to create persistent
|
||||
environments, which can be constructed, deconstructed and entered by
|
||||
multiple users at once. A downside is that it requires
|
||||
<literal>root</literal> access for both those who create and destroy and
|
||||
those who enter it. It can be useful to create environments for daemons that
|
||||
one can enter and observe.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<function>buildFHSUserEnv</function> uses Linux namespaces feature to create
|
||||
temporary lightweight environments which are destroyed after all child
|
||||
processes exit. It does not require root access, and can be useful to create
|
||||
sandboxes and wrap applications.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Those functions both rely on <function>buildFHSEnv</function>, which creates
|
||||
an actual directory structure given a list of necessary packages and extra
|
||||
build commands.
|
||||
<function>buildFHSChrootEnv</function> and <function>buildFHSUserEnv</function>
|
||||
both accept those arguments which are passed to
|
||||
<function>buildFHSEnv</function>:
|
||||
</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><literal>name</literal></term>
|
||||
|
||||
<listitem><para>Environment name.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><literal>targetPkgs</literal></term>
|
||||
|
||||
<listitem><para>Packages to be installed for the main host's architecture
|
||||
(i.e. x86_64 on x86_64 installations).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><literal>multiPkgs</literal></term>
|
||||
|
||||
<listitem><para>Packages to be installed for all architectures supported by
|
||||
a host (i.e. i686 and x86_64 on x86_64 installations).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><literal>extraBuildCommands</literal></term>
|
||||
|
||||
<listitem><para>Additional commands to be executed for finalizing the
|
||||
directory structure.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><literal>extraBuildCommandsMulti</literal></term>
|
||||
|
||||
<listitem><para>Like <literal>extraBuildCommandsMulti</literal>, but
|
||||
executed only on multilib architectures.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>
|
||||
Additionally, <function>buildFHSUserEnv</function> accepts
|
||||
<literal>runScript</literal> parameter, which is a command that would be
|
||||
executed inside the sandbox and passed all the command line arguments. It
|
||||
default to <literal>bash</literal>.
|
||||
</para>
|
||||
<para>
|
||||
It also uses <literal>CHROOTENV_EXTRA_BINDS</literal> environment variable
|
||||
for binding extra directories in the sandbox to outside places. The format of
|
||||
the variable is <literal>/mnt=test-mnt:/data</literal>, where
|
||||
<literal>/mnt</literal> would be mounted as <literal>/test-mnt</literal>
|
||||
and <literal>/data</literal> would be mounted as <literal>/data</literal>.
|
||||
<literal>extraBindMounts</literal> array argument to
|
||||
<function>buildFHSUserEnv</function> function is prepended to this variable.
|
||||
Latter entries take priority if defined several times -- i.e. in case of
|
||||
<literal>/data=data1:/data=data2</literal> the actual bind path would be
|
||||
<literal>/data2</literal>.
|
||||
</para>
|
||||
<para>
|
||||
One can create a simple environment using a <literal>shell.nix</literal>
|
||||
like that:
|
||||
</para>
|
||||
|
||||
<programlisting><![CDATA[
|
||||
{ pkgs ? import <nixpkgs> {} }:
|
||||
|
||||
(pkgs.buildFHSUserEnv {
|
||||
name = "simple-x11-env";
|
||||
targetPkgs = pkgs: (with pkgs;
|
||||
[ udev
|
||||
alsaLib
|
||||
]) ++ (with pkgs.xorg;
|
||||
[ libX11
|
||||
libXcursor
|
||||
libXrandr
|
||||
]);
|
||||
multiPkgs = pkgs: (with pkgs;
|
||||
[ udev
|
||||
alsaLib
|
||||
]) ++ (with [];
|
||||
runScript = "bash";
|
||||
}).env
|
||||
]]></programlisting>
|
||||
|
||||
<para>
|
||||
Running <literal>nix-shell</literal> would then drop you into a shell with
|
||||
these libraries and binaries available. You can use this to run
|
||||
closed-source applications which expect FHS structure without hassles:
|
||||
simply change <literal>runScript</literal> to the application path,
|
||||
e.g. <filename>./bin/start.sh</filename> -- relative paths are supported.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
@@ -1,719 +0,0 @@
|
||||
---
|
||||
title: User's Guide for Haskell in Nixpkgs
|
||||
author: Peter Simons
|
||||
date: 2015-06-01
|
||||
---
|
||||
|
||||
# How to install Haskell packages
|
||||
|
||||
Nixpkgs distributes build instructions for all Haskell packages registered on
|
||||
[Hackage](http://hackage.haskell.org/), but strangely enough normal Nix package
|
||||
lookups don't seem to discover any of them, except for the default version of ghc, cabal-install, and stack:
|
||||
|
||||
$ nix-env -i alex
|
||||
error: selector ‘alex’ matches no derivations
|
||||
$ nix-env -qa ghc
|
||||
ghc-7.10.2
|
||||
|
||||
The Haskell package set is not registered in the top-level namespace because it
|
||||
is *huge*. If all Haskell packages were visible to these commands, then
|
||||
name-based search/install operations would be much slower than they are now. We
|
||||
avoided that by keeping all Haskell-related packages in a separate attribute
|
||||
set called `haskellPackages`, which the following command will list:
|
||||
|
||||
$ nix-env -f "<nixpkgs>" -qaP -A haskellPackages
|
||||
haskellPackages.a50 a50-0.5
|
||||
haskellPackages.abacate haskell-abacate-0.0.0.0
|
||||
haskellPackages.abcBridge haskell-abcBridge-0.12
|
||||
haskellPackages.afv afv-0.1.1
|
||||
haskellPackages.alex alex-3.1.4
|
||||
haskellPackages.Allure Allure-0.4.101.1
|
||||
haskellPackages.alms alms-0.6.7
|
||||
[... some 8000 entries omitted ...]
|
||||
|
||||
To install any of those packages into your profile, refer to them by their
|
||||
attribute path (first column):
|
||||
|
||||
$ nix-env -f "<nixpkgs>" -iA haskellPackages.Allure ...
|
||||
|
||||
The attribute path of any Haskell packages corresponds to the name of that
|
||||
particular package on Hackage: the package `cabal-install` has the attribute
|
||||
`haskellPackages.cabal-install`, and so on. (Actually, this convention causes
|
||||
trouble with packages like `3dmodels` and `4Blocks`, because these names are
|
||||
invalid identifiers in the Nix language. The issue of how to deal with these
|
||||
rare corner cases is currently unresolved.)
|
||||
|
||||
Haskell packages who's Nix name (second column) begins with a `haskell-` prefix
|
||||
are packages that provide a library whereas packages without that prefix
|
||||
provide just executables. Libraries may provide executables too, though: the
|
||||
package `haskell-pandoc`, for example, installs both a library and an
|
||||
application. You can install and use Haskell executables just like any other
|
||||
program in Nixpkgs, but using Haskell libraries for development is a bit
|
||||
trickier and we'll address that subject in great detail in section [How to
|
||||
create a development environment].
|
||||
|
||||
Attribute paths are deterministic inside of Nixpkgs, but the path necessary to
|
||||
reach Nixpkgs varies from system to system. We dodged that problem by giving
|
||||
`nix-env` an explicit `-f "<nixpkgs>"` parameter, but if you call `nix-env`
|
||||
without that flag, then chances are the invocation fails:
|
||||
|
||||
$ nix-env -iA haskellPackages.cabal-install
|
||||
error: attribute ‘haskellPackages’ in selection path
|
||||
‘haskellPackages.cabal-install’ not found
|
||||
|
||||
On NixOS, for example, Nixpkgs does *not* exist in the top-level namespace by
|
||||
default. To figure out the proper attribute path, it's easiest to query for the
|
||||
path of a well-known Nixpkgs package, i.e.:
|
||||
|
||||
$ nix-env -qaP coreutils
|
||||
nixos.coreutils coreutils-8.23
|
||||
|
||||
If your system responds like that (most NixOS installations will), then the
|
||||
attribute path to `haskellPackages` is `nixos.haskellPackages`. Thus, if you
|
||||
want to use `nix-env` without giving an explicit `-f` flag, then that's the way
|
||||
to do it:
|
||||
|
||||
$ nix-env -qaP -A nixos.haskellPackages
|
||||
$ nix-env -iA nixos.haskellPackages.cabal-install
|
||||
|
||||
Our current default compiler is GHC 7.10.x and the `haskellPackages` set
|
||||
contains packages built with that particular version. Nixpkgs contains the
|
||||
latest major release of every GHC since 6.10.4, however, and there is a whole
|
||||
family of package sets available that defines Hackage packages built with each
|
||||
of those compilers, too:
|
||||
|
||||
$ nix-env -f "<nixpkgs>" -qaP -A haskell.packages.ghc6123
|
||||
$ nix-env -f "<nixpkgs>" -qaP -A haskell.packages.ghc763
|
||||
|
||||
The name `haskellPackages` is really just a synonym for
|
||||
`haskell.packages.ghc7102`, because we prefer that package set internally and
|
||||
recommend it to our users as their default choice, but ultimately you are free
|
||||
to compile your Haskell packages with any GHC version you please. The following
|
||||
command displays the complete list of available compilers:
|
||||
|
||||
$ nix-env -f "<nixpkgs>" -qaP -A haskell.compiler
|
||||
haskell.compiler.ghc6104 ghc-6.10.4
|
||||
haskell.compiler.ghc6123 ghc-6.12.3
|
||||
haskell.compiler.ghc704 ghc-7.0.4
|
||||
haskell.compiler.ghc722 ghc-7.2.2
|
||||
haskell.compiler.ghc742 ghc-7.4.2
|
||||
haskell.compiler.ghc763 ghc-7.6.3
|
||||
haskell.compiler.ghc784 ghc-7.8.4
|
||||
haskell.compiler.ghc7102 ghc-7.10.2
|
||||
haskell.compiler.ghcHEAD ghc-7.11.20150402
|
||||
haskell.compiler.ghcNokinds ghc-nokinds-7.11.20150704
|
||||
haskell.compiler.ghcjs ghcjs-0.1.0
|
||||
haskell.compiler.jhc jhc-0.8.2
|
||||
haskell.compiler.uhc uhc-1.1.9.0
|
||||
|
||||
We have no package sets for `jhc` or `uhc` yet, unfortunately, but for every
|
||||
version of GHC listed above, there exists a package set based on that compiler.
|
||||
Also, the attributes `haskell.compiler.ghcXYC` and
|
||||
`haskell.packages.ghcXYC.ghc` are synonymous for the sake of convenience.
|
||||
|
||||
# How to create a development environment
|
||||
|
||||
## How to install a compiler
|
||||
|
||||
A simple development environment consists of a Haskell compiler and the tool
|
||||
`cabal-install`, and we saw in section [How to install Haskell packages] how
|
||||
you can install those programs into your user profile:
|
||||
|
||||
$ nix-env -f "<nixpkgs>" -iA haskellPackages.ghc haskellPackages.cabal-install
|
||||
|
||||
Instead of the default package set `haskellPackages`, you can also use the more
|
||||
precise name `haskell.compiler.ghc7102`, which has the advantage that it refers
|
||||
to the same GHC version regardless of what Nixpkgs considers "default" at any
|
||||
given time.
|
||||
|
||||
Once you've made those tools available in `$PATH`, it's possible to build
|
||||
Hackage packages the same way people without access to Nix do it all the time:
|
||||
|
||||
$ cabal get lens-4.11 && cd lens-4.11
|
||||
$ cabal install -j --dependencies-only
|
||||
$ cabal configure
|
||||
$ cabal build
|
||||
|
||||
If you enjoy working with Cabal sandboxes, then that's entirely possible too:
|
||||
just execute the command
|
||||
|
||||
$ cabal sandbox init
|
||||
|
||||
before installing the required dependencies.
|
||||
|
||||
The `nix-shell` utility makes it easy to switch to a different compiler
|
||||
version; just enter the Nix shell environment with the command
|
||||
|
||||
$ nix-shell -p haskell.compiler.ghc784
|
||||
|
||||
to bring GHC 7.8.4 into `$PATH`. Re-running `cabal configure` switches your
|
||||
build to use that compiler instead. If you're working on a project that doesn't
|
||||
depend on any additional system libraries outside of GHC, then it's sufficient
|
||||
even to run the `cabal configure` command inside of the shell:
|
||||
|
||||
$ nix-shell -p haskell.compiler.ghc784 --command "cabal configure"
|
||||
|
||||
Afterwards, all other commands like `cabal build` work just fine in any shell
|
||||
environment, because the configure phase recorded the absolute paths to all
|
||||
required tools like GHC in its build configuration inside of the `dist/`
|
||||
directory. Please note, however, that `nix-collect-garbage` can break such an
|
||||
environment because the Nix store paths created by `nix-shell` aren't "alive"
|
||||
anymore once `nix-shell` has terminated. If you find that your Haskell builds
|
||||
no longer work after garbage collection, then you'll have to re-run `cabal
|
||||
configure` inside of a new `nix-shell` environment.
|
||||
|
||||
## How to install a compiler with libraries
|
||||
|
||||
GHC expects to find all installed libraries inside of its own `lib` directory.
|
||||
This approach works fine on traditional Unix systems, but it doesn't work for
|
||||
Nix, because GHC's store path is immutable once it's built. We cannot install
|
||||
additional libraries into that location. As a consequence, our copies of GHC
|
||||
don't know any packages except their own core libraries, like `base`,
|
||||
`containers`, `Cabal`, etc.
|
||||
|
||||
We can register additional libraries to GHC, however, using a special build
|
||||
function called `ghcWithPackages`. That function expects one argument: a
|
||||
function that maps from an attribute set of Haskell packages to a list of
|
||||
packages, which determines the libraries known to that particular version of
|
||||
GHC. For example, the Nix expression `ghcWithPackages (pkgs: [pkgs.mtl])`
|
||||
generates a copy of GHC that has the `mtl` library registered in addition to
|
||||
its normal core packages:
|
||||
|
||||
$ nix-shell -p "haskellPackages.ghcWithPackages (pkgs: [pkgs.mtl])"
|
||||
|
||||
[nix-shell:~]$ ghc-pkg list mtl
|
||||
/nix/store/zy79...-ghc-7.10.2/lib/ghc-7.10.2/package.conf.d:
|
||||
mtl-2.2.1
|
||||
|
||||
This function allows users to define their own development environment by means
|
||||
of an override. After adding the following snippet to `~/.nixpkgs/config.nix`,
|
||||
|
||||
{
|
||||
packageOverrides = super: let self = super.pkgs; in
|
||||
{
|
||||
myHaskellEnv = self.haskell.packages.ghc7102.ghcWithPackages
|
||||
(haskellPackages: with haskellPackages; [
|
||||
# libraries
|
||||
arrows async cgi criterion
|
||||
# tools
|
||||
cabal-install haskintex
|
||||
]);
|
||||
};
|
||||
}
|
||||
|
||||
it's possible to install that compiler with `nix-env -f "<nixpkgs>" -iA
|
||||
myHaskellEnv`. If you'd like to switch that development environment to a
|
||||
different version of GHC, just replace the `ghc7102` bit in the previous
|
||||
definition with the appropriate name. Of course, it's also possible to define
|
||||
any number of these development environments! (You can't install two of them
|
||||
into the same profile at the same time, though, because that would result in
|
||||
file conflicts.)
|
||||
|
||||
The generated `ghc` program is a wrapper script that re-directs the real
|
||||
GHC executable to use a new `lib` directory --- one that we specifically
|
||||
constructed to contain all those packages the user requested:
|
||||
|
||||
$ cat $(type -p ghc)
|
||||
#! /nix/store/xlxj...-bash-4.3-p33/bin/bash -e
|
||||
export NIX_GHC=/nix/store/19sm...-ghc-7.10.2/bin/ghc
|
||||
export NIX_GHCPKG=/nix/store/19sm...-ghc-7.10.2/bin/ghc-pkg
|
||||
export NIX_GHC_DOCDIR=/nix/store/19sm...-ghc-7.10.2/share/doc/ghc/html
|
||||
export NIX_GHC_LIBDIR=/nix/store/19sm...-ghc-7.10.2/lib/ghc-7.10.2
|
||||
exec /nix/store/j50p...-ghc-7.10.2/bin/ghc "-B$NIX_GHC_LIBDIR" "$@"
|
||||
|
||||
The variables `$NIX_GHC`, `$NIX_GHCPKG`, etc. point to the *new* store path
|
||||
`ghcWithPackages` constructed specifically for this environment. The last line
|
||||
of the wrapper script then executes the real `ghc`, but passes the path to the
|
||||
new `lib` directory using GHC's `-B` flag.
|
||||
|
||||
The purpose of those environment variables is to work around an impurity in the
|
||||
popular [ghc-paths](http://hackage.haskell.org/package/ghc-paths) library. That
|
||||
library promises to give its users access to GHC's installation paths. Only,
|
||||
the library can't possible know that path when it's compiled, because the path
|
||||
GHC considers its own is determined only much later, when the user configures
|
||||
it through `ghcWithPackages`. So we [patched
|
||||
ghc-paths](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/haskell-modules/ghc-paths-nix.patch)
|
||||
to return the paths found in those environment variables at run-time rather
|
||||
than trying to guess them at compile-time.
|
||||
|
||||
To make sure that mechanism works properly all the time, we recommend that you
|
||||
set those variables to meaningful values in your shell environment, too, i.e.
|
||||
by adding the following code to your `~/.bashrc`:
|
||||
|
||||
if type >/dev/null 2>&1 -p ghc; then
|
||||
eval "$(egrep ^export "$(type -p ghc)")"
|
||||
fi
|
||||
|
||||
If you are certain that you'll use only one GHC environment which is located in
|
||||
your user profile, then you can use the following code, too, which has the
|
||||
advantage that it doesn't contain any paths from the Nix store, i.e. those
|
||||
settings always remain valid even if a `nix-env -u` operation updates the GHC
|
||||
environment in your profile:
|
||||
|
||||
if [ -e ~/.nix-profile/bin/ghc ]; then
|
||||
export NIX_GHC="$HOME/.nix-profile/bin/ghc"
|
||||
export NIX_GHCPKG="$HOME/.nix-profile/bin/ghc-pkg"
|
||||
export NIX_GHC_DOCDIR="$HOME/.nix-profile/share/doc/ghc/html"
|
||||
export NIX_GHC_LIBDIR="$HOME/.nix-profile/lib/ghc-$($NIX_GHC --numeric-version)"
|
||||
fi
|
||||
|
||||
## How to install a compiler with libraries, hoogle and documentation indexes
|
||||
|
||||
If you plan to use your environment for interactive programming, not just
|
||||
compiling random Haskell code, you might want to replace `ghcWithPackages` in
|
||||
all the listings above with `ghcWithHoogle`.
|
||||
|
||||
This environment generator not only produces an environment with GHC and all
|
||||
the specified libraries, but also generates a `hoogle` and `haddock` indexes
|
||||
for all the packages, and provides a wrapper script around `hoogle` binary that
|
||||
uses all those things. A precise name for this thing would be
|
||||
"`ghcWithPackagesAndHoogleAndDocumentationIndexes`", which is, regrettably, too
|
||||
long and scary.
|
||||
|
||||
For example, installing the following environment
|
||||
|
||||
{
|
||||
packageOverrides = super: let self = super.pkgs; in
|
||||
{
|
||||
myHaskellEnv = self.haskellPackages.ghcWithHoogle
|
||||
(haskellPackages: with haskellPackages; [
|
||||
# libraries
|
||||
arrows async cgi criterion
|
||||
# tools
|
||||
cabal-install haskintex
|
||||
]);
|
||||
};
|
||||
}
|
||||
|
||||
allows one to browse module documentation index [not too dissimilar to
|
||||
this](https://downloads.haskell.org/~ghc/latest/docs/html/libraries/index.html)
|
||||
for all the specified packages and their dependencies by directing a browser of
|
||||
choice to `~/.nix-profiles/share/doc/hoogle/index.html` (or
|
||||
`/run/current-system/sw/share/doc/hoogle/index.html` in case you put it in
|
||||
`environment.systemPackages` in NixOS).
|
||||
|
||||
After you've marveled enough at that try adding the following to your
|
||||
`~/.ghc/ghci.conf`
|
||||
|
||||
:def hoogle \s -> return $ ":! hoogle search -cl --count=15 \"" ++ s ++ "\""
|
||||
:def doc \s -> return $ ":! hoogle search -cl --info \"" ++ s ++ "\""
|
||||
|
||||
and test it by typing into `ghci`:
|
||||
|
||||
:hoogle a -> a
|
||||
:doc a -> a
|
||||
|
||||
Be sure to note the links to `haddock` files in the output. With any modern and
|
||||
properly configured terminal emulator you can just click those links to
|
||||
navigate there.
|
||||
|
||||
Finally, you can run
|
||||
|
||||
hoogle server -p 8080
|
||||
|
||||
and navigate to http://localhost:8080/ for your own local
|
||||
[Hoogle](https://www.haskell.org/hoogle/). Note, however, that Firefox and
|
||||
possibly other browsers disallow navigation from `http:` to `file:` URIs for
|
||||
security reasons, which might be quite an inconvenience. See [this
|
||||
page](http://kb.mozillazine.org/Links_to_local_pages_do_not_work) for
|
||||
workarounds.
|
||||
|
||||
|
||||
## How to create ad hoc environments for `nix-shell`
|
||||
|
||||
The easiest way to create an ad hoc development environment is to run
|
||||
`nix-shell` with the appropriate GHC environment given on the command-line:
|
||||
|
||||
nix-shell -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [mtl pandoc])"
|
||||
|
||||
For more sophisticated use-cases, however, it's more convenient to save the
|
||||
desired configuration in a file called `shell.nix` that looks like this:
|
||||
|
||||
{ nixpkgs ? import <nixpkgs> {}, compiler ? "ghc7102" }:
|
||||
let
|
||||
inherit (nixpkgs) pkgs;
|
||||
ghc = pkgs.haskell.packages.${compiler}.ghcWithPackages (ps: with ps; [
|
||||
monad-par mtl
|
||||
]);
|
||||
in
|
||||
pkgs.stdenv.mkDerivation {
|
||||
name = "my-haskell-env-0";
|
||||
buildInputs = [ ghc ];
|
||||
shellHook = "eval $(egrep ^export ${ghc}/bin/ghc)";
|
||||
}
|
||||
|
||||
Now run `nix-shell` --- or even `nix-shell --pure` --- to enter a shell
|
||||
environment that has the appropriate compiler in `$PATH`. If you use `--pure`,
|
||||
then add all other packages that your development environment needs into the
|
||||
`buildInputs` attribute. If you'd like to switch to a different compiler
|
||||
version, then pass an appropriate `compiler` argument to the expression, i.e.
|
||||
`nix-shell --argstr compiler ghc784`.
|
||||
|
||||
If you need such an environment because you'd like to compile a Hackage package
|
||||
outside of Nix --- i.e. because you're hacking on the latest version from Git
|
||||
---, then the package set provides suitable nix-shell environments for you
|
||||
already! Every Haskell package has an `env` attribute that provides a shell
|
||||
environment suitable for compiling that particular package. If you'd like to
|
||||
hack the `lens` library, for example, then you just have to check out the
|
||||
source code and enter the appropriate environment:
|
||||
|
||||
$ cabal get lens-4.11 && cd lens-4.11
|
||||
Downloading lens-4.11...
|
||||
Unpacking to lens-4.11/
|
||||
|
||||
$ nix-shell "<nixpkgs>" -A haskellPackages.lens.env
|
||||
[nix-shell:/tmp/lens-4.11]$
|
||||
|
||||
At point, you can run `cabal configure`, `cabal build`, and all the other
|
||||
development commands. Note that you need `cabal-install` installed in your
|
||||
`$PATH` already to use it here --- the `nix-shell` environment does not provide
|
||||
it.
|
||||
|
||||
# How to create Nix builds for your own private Haskell packages
|
||||
|
||||
If your own Haskell packages have build instructions for Cabal, then you can
|
||||
convert those automatically into build instructions for Nix using the
|
||||
`cabal2nix` utility, which you can install into your profile by running
|
||||
`nix-env -i cabal2nix`.
|
||||
|
||||
## How to build a stand-alone project
|
||||
|
||||
For example, let's assume that you're working on a private project called
|
||||
`foo`. To generate a Nix build expression for it, change into the project's
|
||||
top-level directory and run the command:
|
||||
|
||||
$ cabal2nix . >foo.nix
|
||||
|
||||
Then write the following snippet into a file called `default.nix`:
|
||||
|
||||
{ nixpkgs ? import <nixpkgs> {}, compiler ? "ghc7102" }:
|
||||
nixpkgs.pkgs.haskell.packages.${compiler}.callPackage ./foo.nix { }
|
||||
|
||||
Finally, store the following code in a file called `shell.nix`:
|
||||
|
||||
{ nixpkgs ? import <nixpkgs> {}, compiler ? "ghc7102" }:
|
||||
(import ./default.nix { inherit nixpkgs compiler; }).env
|
||||
|
||||
At this point, you can run `nix-build` to have Nix compile your project and
|
||||
install it into a Nix store path. The local directory will contain a symlink
|
||||
called `result` after `nix-build` returns that points into that location. Of
|
||||
course, passing the flag `--argstr compiler ghc763` allows switching the build
|
||||
to any version of GHC currently supported.
|
||||
|
||||
Furthermore, you can call `nix-shell` to enter an interactive development
|
||||
environment in which you can use `cabal configure` and `cabal build` to develop
|
||||
your code. That environment will automatically contain a proper GHC derivation
|
||||
with all the required libraries registered as well as all the system-level
|
||||
libraries your package might need.
|
||||
|
||||
If your package does not depend on any system-level libraries, then it's
|
||||
sufficient to run
|
||||
|
||||
$ nix-shell --command "cabal configure"
|
||||
|
||||
once to set up your build. `cabal-install` determines the absolute paths to all
|
||||
resources required for the build and writes them into a config file in the
|
||||
`dist/` directory. Once that's done, you can run `cabal build` and any other
|
||||
command for that project even outside of the `nix-shell` environment. This
|
||||
feature is particularly nice for those of us who like to edit their code with
|
||||
an IDE, like Emacs' `haskell-mode`, because it's not necessary to start Emacs
|
||||
inside of nix-shell just to make it find out the necessary settings for
|
||||
building the project; `cabal-install` has already done that for us.
|
||||
|
||||
If you want to do some quick-and-dirty hacking and don't want to bother setting
|
||||
up a `default.nix` and `shell.nix` file manually, then you can use the
|
||||
`--shell` flag offered by `cabal2nix` to have it generate a stand-alone
|
||||
`nix-shell` environment for you. With that feature, running
|
||||
|
||||
$ cabal2nix --shell . >shell.nix
|
||||
$ nix-shell --command "cabal configure"
|
||||
|
||||
is usually enough to set up a build environment for any given Haskell package.
|
||||
You can even use that generated file to run `nix-build`, too:
|
||||
|
||||
$ nix-build shell.nix
|
||||
|
||||
## How to build projects that depend on each other
|
||||
|
||||
If you have multiple private Haskell packages that depend on each other, then
|
||||
you'll have to register those packages in the Nixpkgs set to make them visible
|
||||
for the dependency resolution performed by `callPackage`. First of all, change
|
||||
into each of your projects top-level directories and generate a `default.nix`
|
||||
file with `cabal2nix`:
|
||||
|
||||
$ cd ~/src/foo && cabal2nix . >default.nix
|
||||
$ cd ~/src/bar && cabal2nix . >default.nix
|
||||
|
||||
Then edit your `~/.nixpkgs/config.nix` file to register those builds in the
|
||||
default Haskell package set:
|
||||
|
||||
{
|
||||
packageOverrides = super: let self = super.pkgs; in
|
||||
{
|
||||
haskellPackages = super.haskellPackages.override {
|
||||
overrides = self: super: {
|
||||
foo = self.callPackage ../src/foo {};
|
||||
bar = self.callPackage ../src/bar {};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
Once that's accomplished, `nix-env -f "<nixpkgs>" -qA haskellPackages` will
|
||||
show your packages like any other package from Hackage, and you can build them
|
||||
|
||||
$ nix-build "<nixpkgs>" -A haskellPackages.foo
|
||||
|
||||
or enter an interactive shell environment suitable for building them:
|
||||
|
||||
$ nix-shell "<nixpkgs>" -A haskellPackages.bar.env
|
||||
|
||||
# Miscellaneous Topics
|
||||
|
||||
## How to build with profiling enabled
|
||||
|
||||
Every Haskell package set takes a function called `overrides` that you can use
|
||||
to manipulate the package as much as you please. One useful application of this
|
||||
feature is to replace the default `mkDerivation` function with one that enables
|
||||
library profiling for all packages. To accomplish that, add configure the
|
||||
following snippet in your `~/.nixpkgs/config.nix` file:
|
||||
|
||||
{
|
||||
packageOverrides = super: let self = super.pkgs; in
|
||||
{
|
||||
profiledHaskellPackages = self.haskellPackages.override {
|
||||
overrides = self: super: {
|
||||
mkDerivation = args: super.mkDerivation (args // {
|
||||
enableLibraryProfiling = true;
|
||||
});
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
Then, replace instances of `haskellPackages` in the `cabal2nix`-generated
|
||||
`default.nix` or `shell.nix` files with `profiledHaskellPackages`.
|
||||
|
||||
## How to override package versions in a compiler-specific package set
|
||||
|
||||
Nixpkgs provides the latest version of
|
||||
[`ghc-events`](http://hackage.haskell.org/package/ghc-events), which is 0.4.4.0
|
||||
at the time of this writing. This is fine for users of GHC 7.10.x, but GHC
|
||||
7.8.4 cannot compile that binary. Now, one way to solve that problem is to
|
||||
register an older version of `ghc-events` in the 7.8.x-specific package set.
|
||||
The first step is to generate Nix build instructions with `cabal2nix`:
|
||||
|
||||
$ cabal2nix cabal://ghc-events-0.4.3.0 >~/.nixpkgs/ghc-events-0.4.3.0.nix
|
||||
|
||||
Then add the override in `~/.nixpkgs/config.nix`:
|
||||
|
||||
{
|
||||
packageOverrides = super: let self = super.pkgs; in
|
||||
{
|
||||
haskell = super.haskell // {
|
||||
packages = super.haskell.packages // {
|
||||
ghc784 = super.haskell.packages.ghc784.override {
|
||||
overrides = self: super: {
|
||||
ghc-events = self.callPackage ./ghc-events-0.4.3.0.nix {};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
This code is a little crazy, no doubt, but it's necessary because the intuitive
|
||||
version
|
||||
|
||||
haskell.packages.ghc784 = super.haskell.packages.ghc784.override {
|
||||
overrides = self: super: {
|
||||
ghc-events = self.callPackage ./ghc-events-0.4.3.0.nix {};
|
||||
};
|
||||
};
|
||||
|
||||
doesn't do what we want it to: that code replaces the `haskell` package set in
|
||||
Nixpkgs with one that contains only one entry,`packages`, which contains only
|
||||
one entry `ghc784`. This override loses the `haskell.compiler` set, and it
|
||||
loses the `haskell.packages.ghcXYZ` sets for all compilers but GHC 7.8.4. To
|
||||
avoid that problem, we have to perform the convoluted little dance from above,
|
||||
iterating over each step in hierarchy.
|
||||
|
||||
Once it's accomplished, however, we can install a variant of `ghc-events`
|
||||
that's compiled with GHC 7.8.4:
|
||||
|
||||
nix-env -f "<nixpkgs>" -iA haskell.packages.ghc784.ghc-events
|
||||
|
||||
Unfortunately, it turns out that this build fails again while executing the
|
||||
test suite! Apparently, the release archive on Hackage is missing some data
|
||||
files that the test suite requires, so we cannot run it. We accomplish that by
|
||||
re-generating the Nix expression with the `--no-check` flag:
|
||||
|
||||
$ cabal2nix --no-check cabal://ghc-events-0.4.3.0 >~/.nixpkgs/ghc-events-0.4.3.0.nix
|
||||
|
||||
Now the builds succeeds.
|
||||
|
||||
Of course, in the concrete example of `ghc-events` this whole exercise is not
|
||||
an ideal solution, because `ghc-events` can analyze the output emitted by any
|
||||
version of GHC later than 6.12 regardless of the compiler version that was used
|
||||
to build the `ghc-events' executable, so strictly speaking there's no reason to
|
||||
prefer one built with GHC 7.8.x in the first place. However, for users who
|
||||
cannot use GHC 7.10.x at all for some reason, the approach of downgrading to an
|
||||
older version might be useful.
|
||||
|
||||
## How to recover from GHC's infamous non-deterministic library ID bug
|
||||
|
||||
GHC and distributed build farms don't get along well:
|
||||
|
||||
https://ghc.haskell.org/trac/ghc/ticket/4012
|
||||
|
||||
When you see an error like this one
|
||||
|
||||
package foo-0.7.1.0 is broken due to missing package
|
||||
text-1.2.0.4-98506efb1b9ada233bb5c2b2db516d91
|
||||
|
||||
then you have to download and re-install `foo` and all its dependents from
|
||||
scratch:
|
||||
|
||||
# nix-store -q --referrers /nix/store/*-haskell-text-1.2.0.4 \
|
||||
| xargs -L 1 nix-store --repair-path --option binary-caches http://hydra.nixos.org
|
||||
|
||||
If you're using additional Hydra servers other than `hydra.nixos.org`, then it
|
||||
might be necessary to purge the local caches that store data from those
|
||||
machines to disable these binary channels for the duration of the previous
|
||||
command, i.e. by running:
|
||||
|
||||
rm /nix/var/nix/binary-cache-v3.sqlite
|
||||
rm /nix/var/nix/manifests/*
|
||||
rm /nix/var/nix/channel-cache/*
|
||||
|
||||
## Builds on Darwin fail with `math.h` not found
|
||||
|
||||
Users of GHC on Darwin have occasionally reported that builds fail, because the
|
||||
compiler complains about a missing include file:
|
||||
|
||||
fatal error: 'math.h' file not found
|
||||
|
||||
The issue has been discussed at length in [ticket
|
||||
6390](https://github.com/NixOS/nixpkgs/issues/6390), and so far no good
|
||||
solution has been proposed. As a work-around, users who run into this problem
|
||||
can configure the environment variables
|
||||
|
||||
export NIX_CFLAGS_COMPILE="-idirafter /usr/include"
|
||||
export NIX_CFLAGS_LINK="-L/usr/lib"
|
||||
|
||||
in their `~/.bashrc` file to avoid the compiler error.
|
||||
|
||||
## Using Stack together with Nix
|
||||
|
||||
-- While building package zlib-0.5.4.2 using:
|
||||
runhaskell -package=Cabal-1.22.4.0 -clear-package-db [... lots of flags ...]
|
||||
Process exited with code: ExitFailure 1
|
||||
Logs have been written to: /home/foo/src/stack-ide/.stack-work/logs/zlib-0.5.4.2.log
|
||||
|
||||
Configuring zlib-0.5.4.2...
|
||||
Setup.hs: Missing dependency on a foreign library:
|
||||
* Missing (or bad) header file: zlib.h
|
||||
This problem can usually be solved by installing the system package that
|
||||
provides this library (you may need the "-dev" version). If the library is
|
||||
already installed but in a non-standard location then you can use the flags
|
||||
--extra-include-dirs= and --extra-lib-dirs= to specify where it is.
|
||||
If the header file does exist, it may contain errors that are caught by the C
|
||||
compiler at the preprocessing stage. In this case you can re-run configure
|
||||
with the verbosity flag -v3 to see the error messages.
|
||||
|
||||
When you run the build inside of the nix-shell environment, the system
|
||||
is configured to find libz.so without any special flags -- the compiler
|
||||
and linker "just know" how to find it. Consequently, Cabal won't record
|
||||
any search paths for libz.so in the package description, which means
|
||||
that the package works fine inside of nix-shell, but once you leave the
|
||||
shell the shared object can no longer be found. That issue is by no
|
||||
means specific to Stack: you'll have that problem with any other
|
||||
Haskell package that's built inside of nix-shell but run outside of that
|
||||
environment.
|
||||
|
||||
I suppose we could try to remedy the issue by wrapping `stack` or
|
||||
`cabal` with a script that tries to find those kind of implicit search
|
||||
paths and makes them explicit on the "cabal configure" command line. I
|
||||
don't think anyone is working on that subject yet, though, because the
|
||||
problem doesn't seem so bad in practice.
|
||||
|
||||
You can remedy that issue in several ways. First of all, run
|
||||
|
||||
$ nix-build --no-out-link "<nixpkgs>" -A zlib
|
||||
/nix/store/alsvwzkiw4b7ip38l4nlfjijdvg3fvzn-zlib-1.2.8
|
||||
|
||||
to find out the store path of the system's zlib library. Now, you can
|
||||
|
||||
1) add that path (plus a "/lib" suffix) to your $LD_LIBRARY_PATH
|
||||
environment variable to make sure your system linker finds libz.so
|
||||
automatically. It's no pretty solution, but it will work.
|
||||
|
||||
2) As a variant of (1), you can also install any number of system
|
||||
libraries into your user's profile (or some other profile) and point
|
||||
$LD_LIBRARY_PATH to that profile instead, so that you don't have to
|
||||
list dozens of those store paths all over the place.
|
||||
|
||||
3) The solution I prefer is to call stack with an appropriate
|
||||
--extra-lib-dirs flag like so:
|
||||
|
||||
$ stack --extra-lib-dirs=/nix/store/alsvwzkiw4b7ip38l4nlfjijdvg3fvzn-zlib-1.2.8/lib build
|
||||
|
||||
Typically, you'll need --extra-include-dirs as well. It's possible
|
||||
to add those flag to the project's "stack.yaml" or your user's
|
||||
global "~/.stack/global/stack.yaml" file so that you don't have to
|
||||
specify them manually every time.
|
||||
|
||||
The same thing applies to `cabal configure`, of course, if you're
|
||||
building with `cabal-install` instead of Stack.
|
||||
|
||||
## Creating statically linked binaries
|
||||
|
||||
There are two levels of static linking. The first option is to configure the
|
||||
build with the Cabal flag `--disable-executable-dynamic`. In Nix expressions,
|
||||
this can be achieved by setting the attribute:
|
||||
|
||||
enableSharedExecutables = false;
|
||||
|
||||
That gives you a binary with statically linked Haskell libraries and
|
||||
dynamically linked system libraries.
|
||||
|
||||
To link both Haskell libraries and system libraries statically, the additional
|
||||
flags `--ghc-option=-optl=-static --ghc-option=-optl=-pthread` need to be used.
|
||||
In Nix, this is accomplished with:
|
||||
|
||||
configureFlags = [ "--ghc-option=-optl=-static" "--ghc-option=-optl=-pthread" ];
|
||||
|
||||
It's important to realize, however, that most system libraries in Nix are built
|
||||
as shared libraries only, i.e. there is just no static library available that
|
||||
Cabal could link!
|
||||
|
||||
|
||||
# Other resources
|
||||
|
||||
- The Youtube video [Nix Loves Haskell](https://www.youtube.com/watch?v=BsBhi_r-OeE)
|
||||
provides an introduction into Haskell NG aimed at beginners. The slides are
|
||||
available at http://cryp.to/nixos-meetup-3-slides.pdf and also -- in a form
|
||||
ready for cut & paste -- at
|
||||
https://github.com/NixOS/cabal2nix/blob/master/doc/nixos-meetup-3-slides.md.
|
||||
|
||||
- Another Youtube video is [Escaping Cabal Hell with Nix](https://www.youtube.com/watch?v=mQd3s57n_2Y),
|
||||
which discusses the subject of Haskell development with Nix but also provides
|
||||
a basic introduction to Nix as well, i.e. it's suitable for viewers with
|
||||
almost no prior Nix experience.
|
||||
|
||||
- Oliver Charles wrote a very nice [Tutorial how to develop Haskell packages with Nix](http://wiki.ocharles.org.uk/Nix).
|
||||
|
||||
- The *Journey into the Haskell NG infrastructure* series of postings
|
||||
describe the new Haskell infrastructure in great detail:
|
||||
|
||||
- [Part 1](http://lists.science.uu.nl/pipermail/nix-dev/2015-January/015591.html)
|
||||
explains the differences between the old and the new code and gives
|
||||
instructions how to migrate to the new setup.
|
||||
|
||||
- [Part 2](http://lists.science.uu.nl/pipermail/nix-dev/2015-January/015608.html)
|
||||
looks in-depth at how to tweak and configure your setup by means of
|
||||
overrides.
|
||||
|
||||
- [Part 3](http://lists.science.uu.nl/pipermail/nix-dev/2015-April/016912.html)
|
||||
describes the infrastructure that keeps the Haskell package set in Nixpkgs
|
||||
up-to-date.
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-language-support">
|
||||
@@ -14,7 +13,7 @@ in Nixpkgs to easily build packages for other programming languages,
|
||||
such as Perl or Haskell. These are described in this chapter.</para>
|
||||
|
||||
|
||||
<section xml:id="sec-language-perl"><title>Perl</title>
|
||||
<section xml:id="ssec-language-perl"><title>Perl</title>
|
||||
|
||||
<para>Nixpkgs provides a function <varname>buildPerlPackage</varname>,
|
||||
a generic package builder function for any Perl package that has a
|
||||
@@ -109,7 +108,7 @@ a <varname>preConfigure</varname> hook to generate a configuration
|
||||
file used by <filename>Makefile.PL</filename>:
|
||||
|
||||
<programlisting>
|
||||
{ buildPerlPackage, fetchurl, db }:
|
||||
{buildPerlPackage, fetchurl, db}:
|
||||
|
||||
buildPerlPackage rec {
|
||||
name = "BerkeleyDB-0.36";
|
||||
@@ -152,7 +151,7 @@ ClassC3Componentised = buildPerlPackage rec {
|
||||
|
||||
</para>
|
||||
|
||||
<section xml:id="ssec-generation-from-CPAN"><title>Generation from CPAN</title>
|
||||
<section><title>Generation from CPAN</title>
|
||||
|
||||
<para>Nix expressions for Perl packages can be generated (almost)
|
||||
automatically from CPAN. This is done by the program
|
||||
@@ -192,631 +191,49 @@ you need it.</para>
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-python"><title>Python</title>
|
||||
|
||||
<para>
|
||||
Currently supported interpreters are <varname>python26</varname>, <varname>python27</varname>,
|
||||
<varname>python32</varname>, <varname>python33</varname>, <varname>python34</varname>
|
||||
and <varname>pypy</varname>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<varname>python</varname> is an alias of <varname>python27</varname> and <varname>python3</varname> is an alias of <varname>python34</varname>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<varname>python26</varname> and <varname>python27</varname> do not include modules that require
|
||||
external dependencies (to reduce dependency bloat). Following modules need to be added as
|
||||
<varname>buildInput</varname> explicitly:
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para><varname>python.modules.bsddb</varname></para></listitem>
|
||||
<listitem><para><varname>python.modules.curses</varname></para></listitem>
|
||||
<listitem><para><varname>python.modules.curses_panel</varname></para></listitem>
|
||||
<listitem><para><varname>python.modules.crypt</varname></para></listitem>
|
||||
<listitem><para><varname>python.modules.gdbm</varname></para></listitem>
|
||||
<listitem><para><varname>python.modules.sqlite3</varname></para></listitem>
|
||||
<listitem><para><varname>python.modules.tkinter</varname></para></listitem>
|
||||
<listitem><para><varname>python.modules.readline</varname></para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>For convenience <varname>python27Full</varname> and <varname>python26Full</varname>
|
||||
are provided with all modules included.</para>
|
||||
<section><title>Python</title>
|
||||
|
||||
<para>
|
||||
Python packages that
|
||||
use <link xlink:href="http://pypi.python.org/pypi/setuptools/"><literal>setuptools</literal></link> or <literal>distutils</literal>,
|
||||
can be built using the <varname>buildPythonPackage</varname> function as documented below.
|
||||
use <link xlink:href="http://pypi.python.org/pypi/setuptools/"><literal>setuptools</literal></link>,
|
||||
which many Python packages do nowadays, can be built very simply using
|
||||
the <varname>buildPythonPackage</varname> function. This function is
|
||||
implemented
|
||||
in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/python-modules/generic/default.nix"><filename>pkgs/development/python-modules/generic/default.nix</filename></link>
|
||||
and works similarly to <varname>buildPerlPackage</varname>. (See
|
||||
<xref linkend="ssec-language-perl"/> for details.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
All packages depending on any Python interpreter get appended <varname>$out/${python.libPrefix}/site-packages</varname>
|
||||
to <literal>$PYTHONPATH</literal> if such directory exists.
|
||||
</para>
|
||||
Python packages that use <varname>buildPythonPackage</varname> are
|
||||
defined
|
||||
in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/python-packages.nix"><filename>pkgs/top-level/python-packages.nix</filename></link>.
|
||||
Most of them are simple. For example:
|
||||
|
||||
<variablelist>
|
||||
<title>
|
||||
Useful attributes on interpreters packages:
|
||||
</title>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>libPrefix</varname></term>
|
||||
<listitem><para>
|
||||
Name of the folder in <literal>${python}/lib/</literal> for corresponding interpreter.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>interpreter</varname></term>
|
||||
<listitem><para>
|
||||
Alias for <literal>${python}/bin/${executable}.</literal>
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>buildEnv</varname></term>
|
||||
<listitem><para>
|
||||
Function to build python interpreter environments with extra packages bundled together.
|
||||
See <xref linkend="ssec-python-build-env" /> for usage and documentation.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>sitePackages</varname></term>
|
||||
<listitem><para>
|
||||
Alias for <literal>lib/${libPrefix}/site-packages</literal>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>executable</varname></term>
|
||||
<listitem><para>
|
||||
Name of the interpreter executable, ie <literal>python3.4</literal>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
<section xml:id="ssec-build-python-package"><title><varname>buildPythonPackage</varname> function</title>
|
||||
|
||||
<para>
|
||||
The function is implemented in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/python-modules/generic/default.nix">
|
||||
<filename>pkgs/development/python-modules/generic/default.nix</filename></link>.
|
||||
Example usage:
|
||||
|
||||
<programlisting language="nix">
|
||||
<programlisting>
|
||||
twisted = buildPythonPackage {
|
||||
name = "twisted-8.1.0";
|
||||
|
||||
src = pkgs.fetchurl {
|
||||
src = fetchurl {
|
||||
url = http://tmrc.mit.edu/mirror/twisted/Twisted/8.1/Twisted-8.1.0.tar.bz2;
|
||||
sha256 = "0q25zbr4xzknaghha72mq57kh53qw1bf8csgp63pm9sfi72qhirl";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [ self.ZopeInterface ];
|
||||
propagatedBuildInputs = [ pkgs.ZopeInterface ];
|
||||
|
||||
meta = {
|
||||
homepage = http://twistedmatrix.com/;
|
||||
description = "Twisted, an event-driven networking engine written in Python";
|
||||
license = stdenv.lib.licenses.mit;
|
||||
license = "MIT";
|
||||
};
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
Most of Python packages that use <varname>buildPythonPackage</varname> are defined
|
||||
in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/python-packages.nix"><filename>pkgs/top-level/python-packages.nix</filename></link>
|
||||
and generated for each python interpreter separately into attribute sets <varname>python26Packages</varname>,
|
||||
<varname>python27Packages</varname>, <varname>python32Packages</varname>, <varname>python33Packages</varname>,
|
||||
<varname>python34Packages</varname> and <varname>pypyPackages</varname>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<function>buildPythonPackage</function> mainly does four things:
|
||||
|
||||
<orderedlist>
|
||||
<listitem><para>
|
||||
In the <varname>configurePhase</varname>, it patches
|
||||
<literal>setup.py</literal> to always include setuptools before
|
||||
distutils for monkeypatching machinery to take place.
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
In the <varname>buildPhase</varname>, it calls
|
||||
<literal>${python.interpreter} setup.py build ...</literal>
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
In the <varname>installPhase</varname>, it calls
|
||||
<literal>${python.interpreter} setup.py install ...</literal>
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
In the <varname>postFixup</varname> phase, <literal>wrapPythonPrograms</literal>
|
||||
bash function is called to wrap all programs in <filename>$out/bin/*</filename>
|
||||
directory to include <literal>$PYTHONPATH</literal> and <literal>$PATH</literal>
|
||||
environment variables.
|
||||
</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
|
||||
<para>By default <varname>doCheck = true</varname> is set and tests are run with
|
||||
<literal>${python.interpreter} setup.py test</literal> command in <varname>checkPhase</varname>.</para>
|
||||
|
||||
<para>
|
||||
As in Perl, dependencies on other Python packages can be specified in the
|
||||
<varname>buildInputs</varname> and
|
||||
<varname>propagatedBuildInputs</varname> attributes. If something is
|
||||
exclusively a build-time dependency, use
|
||||
<varname>buildInputs</varname>; if it’s (also) a runtime dependency,
|
||||
use <varname>propagatedBuildInputs</varname>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
By default <varname>meta.platforms</varname> is set to the same value
|
||||
as the interpreter unless overriden otherwise.
|
||||
</para>
|
||||
|
||||
<variablelist>
|
||||
<title>
|
||||
<varname>buildPythonPackage</varname> parameters
|
||||
(all parameters from <varname>mkDerivation</varname> function are still supported)
|
||||
</title>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>namePrefix</varname></term>
|
||||
<listitem><para>
|
||||
Prepended text to <varname>${name}</varname> parameter.
|
||||
Defaults to <literal>"python3.3-"</literal> for Python 3.3, etc. Set it to
|
||||
<literal>""</literal>
|
||||
if you're packaging an application or a command line tool.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>disabled</varname></term>
|
||||
<listitem><para>
|
||||
If <varname>true</varname>, package is not build for
|
||||
particular python interpreter version. Grep around
|
||||
<filename>pkgs/top-level/python-packages.nix</filename>
|
||||
for examples.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>setupPyInstallFlags</varname></term>
|
||||
<listitem><para>
|
||||
List of flags passed to <command>setup.py install</command> command.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>setupPyBuildFlags</varname></term>
|
||||
<listitem><para>
|
||||
List of flags passed to <command>setup.py build</command> command.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>pythonPath</varname></term>
|
||||
<listitem><para>
|
||||
List of packages to be added into <literal>$PYTHONPATH</literal>.
|
||||
Packages in <varname>pythonPath</varname> are not propagated into user environment
|
||||
(contrary to <varname>propagatedBuildInputs</varname>).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>preShellHook</varname></term>
|
||||
<listitem><para>
|
||||
Hook to execute commands before <varname>shellHook</varname>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>postShellHook</varname></term>
|
||||
<listitem><para>
|
||||
Hook to execute commands after <varname>shellHook</varname>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>distutilsExtraCfg</varname></term>
|
||||
<listitem><para>
|
||||
Extra lines passed to <varname>[easy_install]</varname> section of
|
||||
<filename>distutils.cfg</filename> (acts as global setup.cfg
|
||||
configuration).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>makeWrapperArgs</varname></term>
|
||||
<listitem><para>
|
||||
A list of strings. Arguments to be passed to
|
||||
<varname>makeWrapper</varname>, which wraps generated binaries. By
|
||||
default, the arguments to <varname>makeWrapper</varname> set
|
||||
<varname>PATH</varname> and <varname>PYTHONPATH</varname> environment
|
||||
variables before calling the binary. Additional arguments here can
|
||||
allow a developer to set environment variables which will be
|
||||
available when the binary is run. For example,
|
||||
<varname>makeWrapperArgs = ["--set FOO BAR" "--set BAZ QUX"]</varname>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="ssec-python-build-env"><title><function>python.buildEnv</function> function</title>
|
||||
<para>
|
||||
Create Python environments using low-level <function>pkgs.buildEnv</function> function. Example <filename>default.nix</filename>:
|
||||
|
||||
<programlisting language="nix">
|
||||
<![CDATA[with import <nixpkgs> {};
|
||||
|
||||
python.buildEnv.override {
|
||||
extraLibs = [ pkgs.pythonPackages.pyramid ];
|
||||
ignoreCollisions = true;
|
||||
}]]>
|
||||
</programlisting>
|
||||
|
||||
Running <command>nix-build</command> will create
|
||||
<filename>/nix/store/cf1xhjwzmdki7fasgr4kz6di72ykicl5-python-2.7.8-env</filename>
|
||||
with wrapped binaries in <filename>bin/</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You can also use <varname>env</varname> attribute to create local
|
||||
environments with needed packages installed (somewhat comparable to
|
||||
<literal>virtualenv</literal>). For example, with the following
|
||||
<filename>shell.nix</filename>:
|
||||
|
||||
<programlisting language="nix">
|
||||
<![CDATA[with import <nixpkgs> {};
|
||||
|
||||
(python3.buildEnv.override {
|
||||
extraLibs = with python3Packages;
|
||||
[ numpy
|
||||
requests
|
||||
];
|
||||
}).env]]>
|
||||
</programlisting>
|
||||
|
||||
Running <command>nix-shell</command> will drop you into a shell where
|
||||
<command>python</command> will have specified packages in its path.
|
||||
</para>
|
||||
|
||||
<variablelist>
|
||||
<title>
|
||||
<function>python.buildEnv</function> arguments
|
||||
</title>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>extraLibs</varname></term>
|
||||
<listitem><para>
|
||||
List of packages installed inside the environment.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>postBuild</varname></term>
|
||||
<listitem><para>
|
||||
Shell command executed after the build of environment.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>ignoreCollisions</varname></term>
|
||||
<listitem><para>
|
||||
Ignore file collisions inside the environment (default is <varname>false</varname>).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</section>
|
||||
|
||||
<section xml:id="ssec-python-tools"><title>Tools</title>
|
||||
|
||||
<para>Packages inside nixpkgs are written by hand. However many tools
|
||||
exist in community to help save time. No tool is preferred at the moment.
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>
|
||||
<link xlink:href="https://github.com/proger/python2nix">python2nix</link>
|
||||
by Vladimir Kirillov
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
<link xlink:href="https://github.com/garbas/pypi2nix">pypi2nix</link>
|
||||
by Rok Garbas
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
<link xlink:href="https://github.com/offlinehacker/pypi2nix">pypi2nix</link>
|
||||
by Jaka Hudoklin
|
||||
</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="ssec-python-development"><title>Development</title>
|
||||
|
||||
<para>
|
||||
To develop Python packages <function>buildPythonPackage</function> has
|
||||
additional logic inside <varname>shellPhase</varname> to run
|
||||
<command>${python.interpreter} setup.py develop</command> for the package.
|
||||
</para>
|
||||
|
||||
<warning><para><varname>shellPhase</varname> is executed only if <filename>setup.py</filename>
|
||||
exists.</para></warning>
|
||||
|
||||
<para>
|
||||
Given a <filename>default.nix</filename>:
|
||||
|
||||
<programlisting language="nix">
|
||||
<![CDATA[with import <nixpkgs> {};
|
||||
|
||||
buildPythonPackage {
|
||||
name = "myproject";
|
||||
|
||||
buildInputs = with pkgs.pythonPackages; [ pyramid ];
|
||||
|
||||
src = ./.;
|
||||
}]]>
|
||||
</programlisting>
|
||||
|
||||
Running <command>nix-shell</command> with no arguments should give you
|
||||
the environment in which the package would be build with
|
||||
<command>nix-build</command>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Shortcut to setup environments with C headers/libraries and python packages:
|
||||
|
||||
<programlisting language="bash">$ nix-shell -p pythonPackages.pyramid zlib libjpeg git</programlisting>
|
||||
</para>
|
||||
|
||||
<note><para>
|
||||
There is a boolean value <varname>lib.inNixShell</varname> set to
|
||||
<varname>true</varname> if nix-shell is invoked.
|
||||
</para></note>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="ssec-python-faq"><title>FAQ</title>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry>
|
||||
<term>How to solve circular dependencies?</term>
|
||||
<listitem><para>
|
||||
If you have packages <varname>A</varname> and <varname>B</varname> that
|
||||
depend on each other, when packaging <varname>B</varname> override package
|
||||
<varname>A</varname> not to depend on <varname>B</varname> as input
|
||||
(and also the other way around).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>install_data / data_files</varname> problems resulting into <literal>error: could not create '/nix/store/6l1bvljpy8gazlsw2aw9skwwp4pmvyxw-python-2.7.8/etc': Permission denied</literal></term>
|
||||
<listitem><para>
|
||||
<link xlink:href="https://bitbucket.org/pypa/setuptools/issue/130/install_data-doesnt-respect-prefix">
|
||||
Known bug in setuptools <varname>install_data</varname> does not respect --prefix</link>. Example of
|
||||
such package using the feature is <filename>pkgs/tools/X11/xpra/default.nix</filename>. As workaround
|
||||
install it as an extra <varname>preInstall</varname> step:
|
||||
|
||||
<programlisting>${python.interpreter} setup.py install_data --install-dir=$out --root=$out
|
||||
sed -i '/ = data_files/d' setup.py</programlisting>
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>Rationale of non-existent global site-packages</term>
|
||||
<listitem><para>
|
||||
There is no need to have global site-packages in Nix. Each package has isolated
|
||||
dependency tree and installing any python package will only populate <varname>$PATH</varname>
|
||||
inside user environment. See <xref linkend="ssec-python-build-env" /> to create self-contained
|
||||
interpreter with a set of packages.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="ssec-python-contrib"><title>Contributing guidelines</title>
|
||||
<para>
|
||||
Following rules are desired to be respected:
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>
|
||||
Make sure package builds for all python interpreters. Use <varname>disabled</varname> argument to
|
||||
<function>buildPythonPackage</function> to set unsupported interpreters.
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
If tests need to be disabled for a package, make sure you leave a comment about reasoning.
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
Packages in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/python-packages.nix"><filename>pkgs/top-level/python-packages.nix</filename></link>
|
||||
are sorted quasi-alphabetically to avoid merge conflicts.
|
||||
</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-language-ruby"><title>Ruby</title>
|
||||
<para>There currently is support to bundle applications that are packaged as Ruby gems. The utility "bundix" allows you to write a <filename>Gemfile</filename>, let bundler create a <filename>Gemfile.lock</filename>, and then convert
|
||||
this into a nix expression that contains all Gem dependencies automatically.</para>
|
||||
|
||||
<para>For example, to package sensu, we did:</para>
|
||||
|
||||
<screen>
|
||||
<![CDATA[$ cd pkgs/servers/monitoring
|
||||
$ mkdir sensu
|
||||
$ cat > Gemfile
|
||||
source 'https://rubygems.org'
|
||||
gem 'sensu'
|
||||
$ bundler package --path /tmp/vendor/bundle
|
||||
$ $(nix-build '<nixpkgs>' -A bundix)/bin/bundix
|
||||
$ cat > default.nix
|
||||
{ lib, bundlerEnv, ruby }:
|
||||
|
||||
bundlerEnv {
|
||||
name = "sensu-0.17.1";
|
||||
|
||||
inherit ruby;
|
||||
gemfile = ./Gemfile;
|
||||
lockfile = ./Gemfile.lock;
|
||||
gemset = ./gemset.nix;
|
||||
|
||||
meta = with lib; {
|
||||
description = "A monitoring framework that aims to be simple, malleable,
|
||||
and scalable.";
|
||||
homepage = http://sensuapp.org/;
|
||||
license = with licenses; mit;
|
||||
maintainers = with maintainers; [ theuni ];
|
||||
platforms = platforms.unix;
|
||||
};
|
||||
}]]>
|
||||
</screen>
|
||||
|
||||
<para>Please check in the <filename>Gemfile</filename>, <filename>Gemfile.lock</filename> and the <filename>gemset.nix</filename> so future updates can be run easily.
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="sec-language-go"><title>Go</title>
|
||||
|
||||
<para>The function <varname>buildGoPackage</varname> builds
|
||||
standard Go packages.
|
||||
</para>
|
||||
|
||||
<example xml:id='ex-buildGoPackage'><title>buildGoPackage</title>
|
||||
<programlisting>
|
||||
net = buildGoPackage rec {
|
||||
name = "go.net-${rev}";
|
||||
goPackagePath = "golang.org/x/net"; <co xml:id='ex-buildGoPackage-1' />
|
||||
subPackages = [ "ipv4" "ipv6" ]; <co xml:id='ex-buildGoPackage-2' />
|
||||
rev = "e0403b4e005";
|
||||
src = fetchFromGitHub {
|
||||
inherit rev;
|
||||
owner = "golang";
|
||||
repo = "net";
|
||||
sha256 = "1g7cjzw4g4301a3yqpbk8n1d4s97sfby2aysl275x04g0zh8jxqp";
|
||||
};
|
||||
goPackageAliases = [ "code.google.com/p/go.net" ]; <co xml:id='ex-buildGoPackage-3' />
|
||||
propagatedBuildInputs = [ goPackages.text ]; <co xml:id='ex-buildGoPackage-4' />
|
||||
buildFlags = "--tags release"; <co xml:id='ex-buildGoPackage-5' />
|
||||
disabled = isGo13;<co xml:id='ex-buildGoPackage-6' />
|
||||
};
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
<para><xref linkend='ex-buildGoPackage'/> is an example expression using buildGoPackage,
|
||||
the following arguments are of special significance to the function:
|
||||
|
||||
<calloutlist>
|
||||
|
||||
<callout arearefs='ex-buildGoPackage-1'>
|
||||
<para>
|
||||
<varname>goPackagePath</varname> specifies the package's canonical Go import path.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
<callout arearefs='ex-buildGoPackage-2'>
|
||||
<para>
|
||||
<varname>subPackages</varname> limits the builder from building child packages that
|
||||
have not been listed. If <varname>subPackages</varname> is not specified, all child
|
||||
packages will be built.
|
||||
</para>
|
||||
<para>
|
||||
In this example only <literal>code.google.com/p/go.net/ipv4</literal> and
|
||||
<literal>code.google.com/p/go.net/ipv4</literal> will be built.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
<callout arearefs='ex-buildGoPackage-3'>
|
||||
<para>
|
||||
<varname>goPackageAliases</varname> is a list of alternative import paths
|
||||
that are valid for this library.
|
||||
Packages that depend on this library will automatically rename
|
||||
import paths that match any of the aliases to <literal>goPackagePath</literal>.
|
||||
</para>
|
||||
<para>
|
||||
In this example imports will be renamed from
|
||||
<literal>code.google.com/p/go.net</literal> to
|
||||
<literal>golang.org/x/net</literal> in every package that depend on the
|
||||
<literal>go.net</literal> library.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
<callout arearefs='ex-buildGoPackage-4'>
|
||||
<para>
|
||||
<varname>propagatedBuildInputs</varname> is where the dependencies of a Go library are
|
||||
listed. Only libraries should list <varname>propagatedBuildInputs</varname>. If a standalone
|
||||
program is being build instead, use <varname>buildInputs</varname>. If a library's tests require
|
||||
additional dependencies that are not propagated, they should be listed in <varname>buildInputs</varname>.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
<callout arearefs='ex-buildGoPackage-5'>
|
||||
<para>
|
||||
<varname>buildFlags</varname> is a list of flags passed to the go build command.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
<callout arearefs='ex-buildGoPackage-6'>
|
||||
<para>
|
||||
If <varname>disabled</varname> is <literal>true</literal>,
|
||||
nix will refuse to build this package.
|
||||
</para>
|
||||
<para>
|
||||
In this example the package will not be built for go 1.3. The <literal>isGo13</literal>
|
||||
is an utility function that returns <literal>true</literal> if go used to build the
|
||||
package has version 1.3.x.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
</calloutlist>
|
||||
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Reusable Go libraries may be found in the <varname>goPackages</varname> set. You can test
|
||||
build a Go package as follows:
|
||||
|
||||
<screen>
|
||||
$ nix-build -A goPackages.net
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You may use Go packages installed into the active Nix profiles by adding
|
||||
the following to your ~/.bashrc:
|
||||
|
||||
<screen>
|
||||
for p in $NIX_PROFILES; do
|
||||
GOPATH="$p/share/go:$GOPATH"
|
||||
done
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
<para>To extract dependency information from a Go package in automated way use <link xlink:href="https://github.com/cstrahan/go2nix">go2nix</link>.</para>
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-language-java"><title>Java</title>
|
||||
<section xml:id="ssec-language-java"><title>Java</title>
|
||||
|
||||
<para>Ant-based Java packages are typically built from source as follows:
|
||||
|
||||
@@ -897,156 +314,6 @@ Runtime) instead of the OpenJRE.</para>
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-language-lua"><title>Lua</title>
|
||||
|
||||
<para>
|
||||
Lua packages are built by the <varname>buildLuaPackage</varname> function. This function is
|
||||
implemented
|
||||
in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/lua-modules/generic/default.nix">
|
||||
<filename>pkgs/development/lua-modules/generic/default.nix</filename></link>
|
||||
and works similarly to <varname>buildPerlPackage</varname>. (See
|
||||
<xref linkend="sec-language-perl"/> for details.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Lua packages are defined
|
||||
in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/lua-packages.nix"><filename>pkgs/top-level/lua-packages.nix</filename></link>.
|
||||
Most of them are simple. For example:
|
||||
|
||||
<programlisting>
|
||||
fileSystem = buildLuaPackage {
|
||||
name = "filesystem-1.6.2";
|
||||
src = fetchurl {
|
||||
url = "https://github.com/keplerproject/luafilesystem/archive/v1_6_2.tar.gz";
|
||||
sha256 = "1n8qdwa20ypbrny99vhkmx8q04zd2jjycdb5196xdhgvqzk10abz";
|
||||
};
|
||||
meta = {
|
||||
homepage = "https://github.com/keplerproject/luafilesystem";
|
||||
hydraPlatforms = stdenv.lib.platforms.linux;
|
||||
maintainers = with maintainers; [ flosse ];
|
||||
};
|
||||
};
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Though, more complicated package should be placed in a seperate file in
|
||||
<link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/lua-modules"><filename>pkgs/development/lua-modules</filename></link>.
|
||||
</para>
|
||||
<para>
|
||||
Lua packages accept additional parameter <varname>disabled</varname>, which defines
|
||||
the condition of disabling package from luaPackages. For example, if package has
|
||||
<varname>disabled</varname> assigned to <literal>lua.luaversion != "5.1"</literal>,
|
||||
it will not be included in any luaPackages except lua51Packages, making it
|
||||
only be built for lua 5.1.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="sec-language-coq"><title>Coq</title>
|
||||
<para>
|
||||
Coq libraries should be installed in
|
||||
<literal>$(out)/lib/coq/${coq.coq-version}/user-contrib/</literal>.
|
||||
Such directories are automatically added to the
|
||||
<literal>$COQPATH</literal> environment variable by the hook defined
|
||||
in the Coq derivation.
|
||||
</para>
|
||||
<para>
|
||||
Some libraries require OCaml and sometimes also Camlp5. The exact
|
||||
versions that were used to build Coq are saved in the
|
||||
<literal>coq.ocaml</literal> and <literal>coq.camlp5</literal>
|
||||
attributes.
|
||||
</para>
|
||||
<para>
|
||||
Here is a simple package example. It is a pure Coq library, thus it
|
||||
only depends on Coq. Its <literal>makefile</literal> has been
|
||||
generated using <literal>coq_makefile</literal> so we only have to
|
||||
set the <literal>$COQLIB</literal> variable at install time.
|
||||
</para>
|
||||
<programlisting>
|
||||
{stdenv, fetchurl, coq}:
|
||||
stdenv.mkDerivation {
|
||||
src = fetchurl {
|
||||
url = http://coq.inria.fr/pylons/contribs/files/Karatsuba/v8.4/Karatsuba.tar.gz;
|
||||
sha256 = "0ymfpv4v49k4fm63nq6gcl1hbnnxrvjjp7yzc4973n49b853c5b1";
|
||||
};
|
||||
|
||||
name = "coq-karatsuba";
|
||||
|
||||
buildInputs = [ coq ];
|
||||
|
||||
installFlags = "COQLIB=$(out)/lib/coq/${coq.coq-version}/";
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
|
||||
<section xml:id="sec-language-qt"><title>Qt</title>
|
||||
|
||||
<para>The information in this section applies to Qt 5.5 and later.</para>
|
||||
|
||||
<para>Qt is an application development toolkit for C++. Although it is
|
||||
not a distinct programming language, there are special considerations
|
||||
for packaging Qt-based programs and libraries. A small set of tools
|
||||
and conventions has grown out of these considerations.</para>
|
||||
|
||||
<section xml:id="ssec-qt-libraries"><title>Libraries</title>
|
||||
|
||||
<para>Packages that provide libraries should be listed in
|
||||
<varname>qt5LibsFun</varname> so that the library is built with each
|
||||
Qt version. A set of packages is provided for each version of Qt; for
|
||||
example, <varname>qt5Libs</varname> always provides libraries built
|
||||
with the latest version, <varname>qt55Libs</varname> provides
|
||||
libraries built with Qt 5.5, and so on. To avoid version conflicts, no
|
||||
top-level attributes are created for these packages.</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="ssec-qt-programs"><title>Programs</title>
|
||||
|
||||
<para>Application packages do not need to be built with every Qt
|
||||
version. To ensure consistency between the package's dependencies,
|
||||
call the package with <literal>qt5Libs.callPackage</literal> instead
|
||||
of the usual <literal>callPackage</literal>. An older version may be
|
||||
selected in case of incompatibility. For example, to build with Qt
|
||||
5.5, call the package with
|
||||
<literal>qt55Libs.callPackage</literal>.</para>
|
||||
|
||||
<para>Several environment variables must be set at runtime for Qt
|
||||
applications to function correctly, including:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para><envar>QT_PLUGIN_PATH</envar></para></listitem>
|
||||
<listitem><para><envar>QML_IMPORT_PATH</envar></para></listitem>
|
||||
<listitem><para><envar>QML2_IMPORT_PATH</envar></para></listitem>
|
||||
<listitem><para><envar>XDG_DATA_DIRS</envar></para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>To ensure that these are set correctly, the program must be wrapped by
|
||||
invoking <literal>wrapQtProgram <replaceable>program</replaceable></literal>
|
||||
during installation (for example, during
|
||||
<literal>fixupPhase</literal>). <literal>wrapQtProgram</literal>
|
||||
accepts the same options as <literal>makeWrapper</literal>.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="ssec-qt-kde"><title>KDE</title>
|
||||
|
||||
<para>Many of the considerations above also apply to KDE packages,
|
||||
especially the need to set the correct environment variables at
|
||||
runtime. To ensure that this is done, invoke <literal>wrapKDEProgram
|
||||
<replaceable>program</replaceable></literal> during
|
||||
installation. <literal>wrapKDEProgram</literal> also generates a
|
||||
<literal>ksycoca</literal> database so that required data and services
|
||||
can be found. Like its Qt counterpart,
|
||||
<literal>wrapKDEProgram</literal> accepts the same options as
|
||||
<literal>makeWrapper</literal>.</para>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
<!--
|
||||
<section><title>Haskell</title>
|
||||
|
||||
|
||||
@@ -3,23 +3,36 @@
|
||||
|
||||
<info>
|
||||
|
||||
<title>Nixpkgs Contributors Guide</title>
|
||||
<title>Nixpkgs Manual</title>
|
||||
|
||||
<subtitle>Version <xi:include href=".version" parse="text" /></subtitle>
|
||||
<subtitle>Draft (Version <xi:include href="../.version"
|
||||
parse="text" />)</subtitle>
|
||||
|
||||
<author>
|
||||
<personname>
|
||||
<firstname>Eelco</firstname>
|
||||
<surname>Dolstra</surname>
|
||||
</personname>
|
||||
<affiliation>
|
||||
<orgname>LogicBlox</orgname>
|
||||
</affiliation>
|
||||
</author>
|
||||
|
||||
<copyright>
|
||||
<year>2008-2012</year>
|
||||
<holder>Eelco Dolstra</holder>
|
||||
</copyright>
|
||||
|
||||
</info>
|
||||
|
||||
<xi:include href="introduction.xml" />
|
||||
<xi:include href="quick-start.xml" />
|
||||
<xi:include href="stdenv.xml" />
|
||||
<xi:include href="packageconfig.xml" />
|
||||
<xi:include href="functions.xml" />
|
||||
<xi:include href="meta.xml" />
|
||||
<xi:include href="language-support.xml" />
|
||||
<xi:include href="package-notes.xml" />
|
||||
<xi:include href="coding-conventions.xml" />
|
||||
<xi:include href="submitting-changes.xml" />
|
||||
<xi:include href="haskell-users-guide.xml" />
|
||||
<xi:include href="contributing.xml" />
|
||||
|
||||
|
||||
|
||||
</book>
|
||||
|
||||
81
doc/meta.xml
81
doc/meta.xml
@@ -27,7 +27,7 @@ meta = {
|
||||
|
||||
<para>Meta-attributes are not passed to the builder of the package.
|
||||
Thus, a change to a meta-attribute doesn’t trigger a recompilation of
|
||||
the package. The value of a meta-attribute must be a string.</para>
|
||||
the package. The value of a meta-attribute must a string.</para>
|
||||
|
||||
<para>The meta-attributes of a package can be queried from the
|
||||
command-line using <command>nix-env</command>:
|
||||
@@ -61,7 +61,7 @@ $ nix-env -qa hello --meta --json
|
||||
"i686-openbsd",
|
||||
"x86_64-openbsd"
|
||||
],
|
||||
"position": "/home/user/dev/nixpkgs/pkgs/applications/misc/hello/default.nix:14"
|
||||
"position": "/home/user/dev/nixpkgs/pkgs/applications/misc/hello/ex-2/default.nix:14"
|
||||
},
|
||||
"name": "hello-2.9",
|
||||
"system": "x86_64-linux"
|
||||
@@ -82,10 +82,10 @@ hello-2.3 A program that produces a familiar, friendly greeting
|
||||
</para>
|
||||
|
||||
|
||||
<section xml:id="sec-standard-meta-attributes"><title>Standard
|
||||
meta-attributes</title>
|
||||
<section><title>Standard meta-attributes</title>
|
||||
|
||||
<para>It is expected that each meta-attribute is one of the following:</para>
|
||||
<para>The following meta-attributes have a standard
|
||||
interpretation:</para>
|
||||
|
||||
<variablelist>
|
||||
|
||||
@@ -112,65 +112,20 @@ meta-attributes</title>
|
||||
package.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>version</varname></term>
|
||||
<listitem><para>Package version.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>branch</varname></term>
|
||||
<listitem><para>Release branch. Used to specify that a package is not
|
||||
going to receive updates that are not in this branch; for example, Linux
|
||||
kernel 3.0 is supposed to be updated to 3.0.X, not 3.1.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>homepage</varname></term>
|
||||
<listitem><para>The package’s homepage. Example:
|
||||
<literal>http://www.gnu.org/software/hello/manual/</literal></para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>downloadPage</varname></term>
|
||||
<listitem><para>The page where a link to the current version can be found. Example:
|
||||
<literal>http://ftp.gnu.org/gnu/hello/</literal></para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>license</varname></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The license, or licenses, for the package. One from the attribute set
|
||||
defined in <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/lib/licenses.nix">
|
||||
<filename>nixpkgs/lib/licenses.nix</filename></link>. At this moment
|
||||
using both a list of licenses and a single license is valid. If the
|
||||
license field is in the form of a list representation, then it means
|
||||
that parts of the package are licensed differently. Each license
|
||||
should preferably be referenced by their attribute. The non-list
|
||||
attribute value can also be a space delimited string representation of
|
||||
the contained attribute shortNames or spdxIds. The following are all valid
|
||||
examples:
|
||||
<itemizedlist>
|
||||
<listitem><para>Single license referenced by attribute (preferred)
|
||||
<literal>stdenv.lib.licenses.gpl3</literal>.
|
||||
</para></listitem>
|
||||
<listitem><para>Single license referenced by its attribute shortName (frowned upon)
|
||||
<literal>"gpl3"</literal>.
|
||||
</para></listitem>
|
||||
<listitem><para>Single license referenced by its attribute spdxId (frowned upon)
|
||||
<literal>"GPL-3.0"</literal>.
|
||||
</para></listitem>
|
||||
<listitem><para>Multiple licenses referenced by attribute (preferred)
|
||||
<literal>with stdenv.lib.licenses; [ asl20 free ofl ]</literal>.
|
||||
</para></listitem>
|
||||
<listitem><para>Multiple licenses referenced as a space delimited string of attribute shortNames (frowned upon)
|
||||
<literal>"asl20 free ofl"</literal>.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
For details, see <xref linkend='sec-meta-license'/>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem><para>The license for the package. One from attribute set defined in
|
||||
<link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/lib/licenses.nix">
|
||||
<filename>nixpkgs/lib/licenses.nix</filename></link>.
|
||||
Example:
|
||||
<literal>stdenv.lib.licenses.gpl3</literal>.</para></listitem>
|
||||
See details in <xref linkend='sec-meta-license'/>,
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -240,16 +195,6 @@ meta.hydraPlatforms = [];
|
||||
they are fixed.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>updateWalker</varname></term>
|
||||
<listitem><para>If set to <literal>true</literal>, the package is
|
||||
tested to be updated correctly by the <literal>update-walker.sh</literal>
|
||||
script without additional settings. Such packages have
|
||||
<varname>meta.version</varname> set and their homepage (or
|
||||
the page specified by <varname>meta.downloadPage</varname>) contains
|
||||
a direct link to the package tarball.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
|
||||
@@ -311,9 +256,9 @@ to indicate the specific license:
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
</chapter>
|
||||
|
||||
@@ -184,10 +184,10 @@ if test "$noSysDirs" = "1"; then
|
||||
if test "$noSysDirs" = "1"; then
|
||||
# Figure out what extra flags to pass to the gcc compilers
|
||||
# being generated to make sure that they use our glibc.
|
||||
if test -e $NIX_CC/nix-support/orig-glibc; then
|
||||
glibc=$(cat $NIX_CC/nix-support/orig-glibc)
|
||||
if test -e $NIX_GCC/nix-support/orig-glibc; then
|
||||
glibc=$(cat $NIX_GCC/nix-support/orig-glibc)
|
||||
# Ugh. Copied from gcc-wrapper/builder.sh. We can't just
|
||||
# source in $NIX_CC/nix-support/add-flags, since that
|
||||
# source in $NIX_GCC/nix-support/add-flags, since that
|
||||
# would cause *this* GCC to be linked against the
|
||||
# *previous* GCC. Need some more modularity there.
|
||||
extraCFlags="-B$glibc/lib -isystem $glibc/include"
|
||||
|
||||
@@ -141,7 +141,7 @@ $ make menuconfig ARCH=<replaceable>arch</replaceable></screen>
|
||||
|
||||
<!--============================================================-->
|
||||
|
||||
<section xml:id="sec-xorg">
|
||||
<section>
|
||||
|
||||
<title>X.org</title>
|
||||
|
||||
@@ -219,151 +219,5 @@ you should modify
|
||||
</section>
|
||||
-->
|
||||
|
||||
<!--============================================================-->
|
||||
|
||||
<section xml:id="sec-eclipse">
|
||||
|
||||
<title>Eclipse</title>
|
||||
|
||||
<para>
|
||||
The Nix expressions related to the Eclipse platform and IDE are in
|
||||
<link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/eclipse"><filename>pkgs/applications/editors/eclipse</filename></link>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Nixpkgs provides a number of packages that will install Eclipse in
|
||||
its various forms, these range from the bare-bones Eclipse
|
||||
Platform to the more fully featured Eclipse SDK or Scala-IDE
|
||||
packages and multiple version are often available. It is possible
|
||||
to list available Eclipse packages by issuing the command:
|
||||
|
||||
<screen>
|
||||
$ nix-env -f '<nixpkgs>' -qaP -A eclipses --description
|
||||
</screen>
|
||||
|
||||
Once an Eclipse variant is installed it can be run using the
|
||||
<command>eclipse</command> command, as expected. From within
|
||||
Eclipse it is then possible to install plugins in the usual manner
|
||||
by either manually specifying an Eclipse update site or by
|
||||
installing the Marketplace Client plugin and using it to discover
|
||||
and install other plugins. This installation method provides an
|
||||
Eclipse installation that closely resemble a manually installed
|
||||
Eclipse.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you prefer to install plugins in a more declarative manner then
|
||||
Nixpkgs also offer a number of Eclipse plugins that can be
|
||||
installed in an <emphasis>Eclipse environment</emphasis>. This
|
||||
type of environment is created using the function
|
||||
<varname>eclipseWithPlugins</varname> found inside the
|
||||
<varname>nixpkgs.eclipses</varname> attribute set. This function
|
||||
takes as argument <literal>{ eclipse, plugins ? [], jvmArgs ? []
|
||||
}</literal> where <varname>eclipse</varname> is a one of the
|
||||
Eclipse packages described above, <varname>plugins</varname> is a
|
||||
list of plugin derivations, and <varname>jvmArgs</varname> is a
|
||||
list of arguments given to the JVM running the Eclipse. For
|
||||
example, say you wish to install the latest Eclipse Platform with
|
||||
the popular Eclipse Color Theme plugin and also allow Eclipse to
|
||||
use more RAM. You could then add
|
||||
|
||||
<screen>
|
||||
packageOverrides = pkgs: {
|
||||
myEclipse = with pkgs.eclipses; eclipseWithPlugins {
|
||||
eclipse = eclipse-platform;
|
||||
jvmArgs = [ "-Xmx2048m" ];
|
||||
plugins = [ plugins.color-theme ];
|
||||
};
|
||||
}
|
||||
</screen>
|
||||
|
||||
to your Nixpkgs configuration
|
||||
(<filename>~/.nixpkgs/config.nix</filename>) and install it by
|
||||
running <command>nix-env -f '<nixpkgs>' -iA
|
||||
myEclipse</command> and afterward run Eclipse as usual. It is
|
||||
possible to find out which plugins are available for installation
|
||||
using <varname>eclipseWithPlugins</varname> by running
|
||||
|
||||
<screen>
|
||||
$ nix-env -f '<nixpkgs>' -qaP -A eclipses.plugins --description
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If there is a need to install plugins that are not available in
|
||||
Nixpkgs then it may be possible to define these plugins outside
|
||||
Nixpkgs using the <varname>buildEclipseUpdateSite</varname> and
|
||||
<varname>buildEclipsePlugin</varname> functions found in the
|
||||
<varname>nixpkgs.eclipses.plugins</varname> attribute set. Use the
|
||||
<varname>buildEclipseUpdateSite</varname> function to install a
|
||||
plugin distributed as an Eclipse update site. This function takes
|
||||
<literal>{ name, src }</literal> as argument where
|
||||
<literal>src</literal> indicates the Eclipse update site archive.
|
||||
All Eclipse features and plugins within the downloaded update site
|
||||
will be installed. When an update site archive is not available
|
||||
then the <varname>buildEclipsePlugin</varname> function can be
|
||||
used to install a plugin that consists of a pair of feature and
|
||||
plugin JARs. This function takes an argument <literal>{ name,
|
||||
srcFeature, srcPlugin }</literal> where
|
||||
<literal>srcFeature</literal> and <literal>srcPlugin</literal> are
|
||||
the feature and plugin JARs, respectively.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Expanding the previous example with two plugins using the above
|
||||
functions we have
|
||||
<screen>
|
||||
packageOverrides = pkgs: {
|
||||
myEclipse = with pkgs.eclipses; eclipseWithPlugins {
|
||||
eclipse = eclipse-platform;
|
||||
jvmArgs = [ "-Xmx2048m" ];
|
||||
plugins = [
|
||||
plugins.color-theme
|
||||
(plugins.buildEclipsePlugin {
|
||||
name = "myplugin1-1.0";
|
||||
srcFeature = fetchurl {
|
||||
url = "http://…/features/myplugin1.jar";
|
||||
sha256 = "123…";
|
||||
};
|
||||
srcPlugin = fetchurl {
|
||||
url = "http://…/plugins/myplugin1.jar";
|
||||
sha256 = "123…";
|
||||
};
|
||||
});
|
||||
(plugins.buildEclipseUpdateSite {
|
||||
name = "myplugin2-1.0";
|
||||
src = fetchurl {
|
||||
stripRoot = false;
|
||||
url = "http://…/myplugin2.zip";
|
||||
sha256 = "123…";
|
||||
};
|
||||
});
|
||||
];
|
||||
};
|
||||
}
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="sec-elm">
|
||||
|
||||
<title>Elm</title>
|
||||
|
||||
<para>
|
||||
The Nix expressions for Elm reside in
|
||||
<filename>pkgs/development/compilers/elm</filename>. They are generated
|
||||
automatically by <command>update-elm.rb</command> script. One should
|
||||
specify versions of Elm packages inside the script, clear the
|
||||
<filename>packages</filename> directory and run the script from inside it.
|
||||
<literal>elm-reactor</literal> is special because it also has Elm package
|
||||
dependencies. The process is not automated very much for now -- you should
|
||||
get the <literal>elm-reactor</literal> source tree (e.g. with
|
||||
<command>nix-shell</command>) and run <command>elm2nix.rb</command> inside
|
||||
it. Place the resulting <filename>package.nix</filename> file into
|
||||
<filename>packages/elm-reactor-elm.nix</filename>.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-packageconfig">
|
||||
|
||||
<title><filename>~/.nixpkgs/config.nix</filename>: global configuration</title>
|
||||
|
||||
<para>
|
||||
Nix packages can be configured to allow or deny certain options.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To apply the configuration edit <filename>~/.nixpkgs/config.nix</filename>
|
||||
and set it like
|
||||
<programlisting>{
|
||||
allowUnfree = true;
|
||||
}</programlisting>
|
||||
and will allow the Nix package manager to install unfree licensed packages.
|
||||
|
||||
The configuration as listed also applies to NixOS under <option>nixpkgs.config</option> set.
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Allow installing of packages that are distributed under unfree license by setting
|
||||
<programlisting>allowUnfree = true;</programlisting>
|
||||
or deny them by setting it to <literal>false</literal>.
|
||||
</para>
|
||||
<para>
|
||||
Same can be achieved by setting the environment variable:
|
||||
<programlisting>$ export NIXPKGS_ALLOW_UNFREE=1</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Whenever unfree packages are not allowed, single packages can
|
||||
still be allowed by a predicate function that accepts package
|
||||
as an argument and should return a boolean:
|
||||
<programlisting>allowUnfreePredicate = (pkg: ...);</programlisting>
|
||||
|
||||
Example to allow flash player only:
|
||||
<programlisting>allowUnfreePredicate = (pkg: pkgs.lib.hasPrefix "flashplayer-" pkg.name);</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Whenever unfree packages are not allowed, packages can still be
|
||||
whitelisted by their license:
|
||||
<programlisting>whitelistedLicenses = with stdenv.lib.licenses; [ amd wtfpl ];</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
In addition to whitelisting licenses which are denied by the
|
||||
<literal>allowUnfree</literal> setting, you can also explicitely
|
||||
deny installation of packages which have a certain license:
|
||||
<programlisting>blacklistedLicenses = with stdenv.lib.licenses; [ agpl3 gpl3 ];</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
A complete list of licenses can be found in the file
|
||||
<filename>lib/licenses.nix</filename> of the nix package tree.
|
||||
</para>
|
||||
|
||||
<section xml:id="sec-modify-via-packageOverrides"><title>Modify
|
||||
packages via <literal>packageOverrides</literal></title>
|
||||
|
||||
<para>
|
||||
|
||||
You can define a function called <varname>packageOverrides</varname>
|
||||
in your local <filename>~/.nixpkgs/config</filename> to overide nix
|
||||
packages. It must be a function that takes pkgs as an argument and
|
||||
return modified set of packages.
|
||||
|
||||
<programlisting>{
|
||||
packageOverrides = pkgs: rec {
|
||||
foo = pkgs.foo.override { ... };
|
||||
};
|
||||
}</programlisting>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
@@ -55,18 +55,18 @@ $ git add pkgs/development/libraries/libfoo/default.nix</screen>
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para>GNU Hello: <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/misc/hello/default.nix"><filename>pkgs/applications/misc/hello/default.nix</filename></link>.
|
||||
Trivial package, which specifies some <varname>meta</varname>
|
||||
attributes which is good practice.</para>
|
||||
<para>GNU cpio: <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/archivers/cpio/default.nix"><filename>pkgs/tools/archivers/cpio/default.nix</filename></link>.
|
||||
The simplest possible package. The generic builder in
|
||||
<varname>stdenv</varname> does everything for you. It has
|
||||
no dependencies beyond <varname>stdenv</varname>.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>GNU cpio: <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/archivers/cpio/default.nix"><filename>pkgs/tools/archivers/cpio/default.nix</filename></link>.
|
||||
Also a simple package. The generic builder in
|
||||
<varname>stdenv</varname> does everything for you. It has
|
||||
no dependencies beyond <varname>stdenv</varname>.</para>
|
||||
<para>GNU Hello: <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/misc/hello/ex-2/default.nix"><filename>pkgs/applications/misc/hello/ex-2/default.nix</filename></link>.
|
||||
Also trivial, but it specifies some <varname>meta</varname>
|
||||
attributes which is good practice.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
@@ -92,6 +92,17 @@ $ git add pkgs/development/libraries/libfoo/default.nix</screen>
|
||||
hackery.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>BitTorrent (wxPython-based): <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/networking/p2p/bittorrent/default.nix"><filename>pkgs/tools/networking/p2p/bittorrent/default.nix</filename></link>.
|
||||
Uses an external <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/networking/p2p/bittorrent/builder.sh">build
|
||||
script</link>, which can be useful if you have lots of code
|
||||
that you don’t want cluttering up the Nix expression. But
|
||||
external builders are mostly obsolete.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Thunderbird: <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/networking/mailreaders/thunderbird/default.nix"><filename>pkgs/applications/networking/mailreaders/thunderbird/default.nix</filename></link>.
|
||||
|
||||
44
doc/quote-literals.xsl
Normal file
44
doc/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>
|
||||
114
doc/stdenv.xml
114
doc/stdenv.xml
@@ -15,8 +15,7 @@ environment does everything automatically. If
|
||||
can easily customise or override the various build phases.</para>
|
||||
|
||||
|
||||
<section xml:id="sec-using-stdenv"><title>Using
|
||||
<literal>stdenv</literal></title>
|
||||
<section><title>Using <literal>stdenv</literal></title>
|
||||
|
||||
<para>To build a package with the standard environment, you use the
|
||||
function <varname>stdenv.mkDerivation</varname>, instead of the
|
||||
@@ -59,7 +58,7 @@ build. To make this easier, the standard environment breaks the
|
||||
package build into a number of <emphasis>phases</emphasis>, all of
|
||||
which can be overridden or modified individually: unpacking the
|
||||
sources, applying patches, configuring, building, and installing.
|
||||
(There are some others; see <xref linkend="sec-stdenv-phases"/>.)
|
||||
(There are some others; see <xref linkend="ssec-stdenv-phases"/>.)
|
||||
For instance, a package that doesn’t supply a makefile but instead has
|
||||
to be compiled “manually” could be handled like this:
|
||||
|
||||
@@ -125,8 +124,7 @@ genericBuild
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-tools-of-stdenv"><title>Tools provided by
|
||||
<literal>stdenv</literal></title>
|
||||
<section><title>Tools provided by <literal>stdenv</literal></title>
|
||||
|
||||
<para>The standard environment provides the following packages:
|
||||
|
||||
@@ -152,8 +150,8 @@ genericBuild
|
||||
|
||||
<listitem><para>GNU <command>tar</command>.</para></listitem>
|
||||
|
||||
<listitem><para><command>gzip</command>, <command>bzip2</command>
|
||||
and <command>xz</command>.</para></listitem>
|
||||
<listitem><para><command>gzip</command> and
|
||||
<command>bzip2</command>.</para></listitem>
|
||||
|
||||
<listitem><para>GNU Make. It has been patched to provide
|
||||
<quote>nested</quote> output that can be fed into the
|
||||
@@ -227,7 +225,7 @@ genericBuild
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-stdenv-phases"><title>Phases</title>
|
||||
<section xml:id="ssec-stdenv-phases"><title>Phases</title>
|
||||
|
||||
<para>The generic builder has a number of <emphasis>phases</emphasis>.
|
||||
Package builds are split into phases to make it easier to override
|
||||
@@ -245,8 +243,7 @@ is convenient to override a phase from the derivation, while the
|
||||
latter is convenient from a build script.</para>
|
||||
|
||||
|
||||
<section xml:id="ssec-controlling-phases"><title>Controlling
|
||||
phases</title>
|
||||
<section><title>Controlling phases</title>
|
||||
|
||||
<para>There are a number of variables that control what phases are
|
||||
executed and in what order:
|
||||
@@ -330,7 +327,7 @@ executed and in what order:
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="ssec-unpack-phase"><title>The unpack phase</title>
|
||||
<section><title>The unpack phase</title>
|
||||
|
||||
<para>The unpack phase is responsible for unpacking the source code of
|
||||
the package. The default implementation of
|
||||
@@ -344,11 +341,9 @@ It supports the following files by default:
|
||||
<term>Tar files</term>
|
||||
<listitem><para>These can optionally be compressed using
|
||||
<command>gzip</command> (<filename>.tar.gz</filename>,
|
||||
<filename>.tgz</filename> or <filename>.tar.Z</filename>),
|
||||
<filename>.tgz</filename> or <filename>.tar.Z</filename>) or
|
||||
<command>bzip2</command> (<filename>.tar.bz2</filename> or
|
||||
<filename>.tbz2</filename>) or <command>xz</command>
|
||||
(<filename>.tar.xz</filename> or
|
||||
<filename>.tar.lzma</filename>).</para></listitem>
|
||||
<filename>.tbz2</filename>).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -437,7 +432,7 @@ Additional file types can be supported by setting the
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="ssec-patch-phase"><title>The patch phase</title>
|
||||
<section><title>The patch phase</title>
|
||||
|
||||
<para>The patch phase applies the list of patches defined in the
|
||||
<varname>patches</varname> variable.</para>
|
||||
@@ -450,10 +445,9 @@ Additional file types can be supported by setting the
|
||||
<listitem><para>The list of patches. They must be in the format
|
||||
accepted by the <command>patch</command> command, and may
|
||||
optionally be compressed using <command>gzip</command>
|
||||
(<filename>.gz</filename>), <command>bzip2</command>
|
||||
(<filename>.bz2</filename>) or <command>xz</command>
|
||||
(<filename>.xz</filename>).</para></listitem>
|
||||
</varlistentry>
|
||||
(<filename>.gz</filename>) or <command>bzip2</command>
|
||||
(<filename>.bz2</filename>).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>patchFlags</varname></term>
|
||||
@@ -480,7 +474,7 @@ Additional file types can be supported by setting the
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="ssec-configure-phase"><title>The configure phase</title>
|
||||
<section><title>The configure phase</title>
|
||||
|
||||
<para>The configure phase prepares the source tree for building. The
|
||||
default <function>configurePhase</function> runs
|
||||
@@ -516,8 +510,8 @@ script) if it exists.</para>
|
||||
<term><varname>dontAddPrefix</varname></term>
|
||||
<listitem><para>By default, the flag
|
||||
<literal>--prefix=$prefix</literal> is added to the configure
|
||||
flags. If this is undesirable, set this variable to
|
||||
true.</para></listitem>
|
||||
flags. If this is undesirable, set this variable to a non-empty
|
||||
value.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -533,7 +527,8 @@ script) if it exists.</para>
|
||||
<listitem><para>By default, the flag
|
||||
<literal>--disable-dependency-tracking</literal> is added to the
|
||||
configure flags to speed up Automake-based builds. If this is
|
||||
undesirable, set this variable to true.</para></listitem>
|
||||
undesirable, set this variable to a non-empty
|
||||
value.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -546,16 +541,7 @@ script) if it exists.</para>
|
||||
variables in the Libtool script to prevent Libtool from using
|
||||
libraries in <filename>/usr/lib</filename> and
|
||||
such.</para></footnote>. If this is undesirable, set this
|
||||
variable to true.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>dontDisableStatic</varname></term>
|
||||
<listitem><para>By default, when the configure script has
|
||||
<option>--enable-static</option>, the option
|
||||
<option>--disable-static</option> is added to the configure flags.</para>
|
||||
<para>If this is undesirable, set this variable to
|
||||
true.</para></listitem>
|
||||
variable to a non-empty value.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -576,7 +562,7 @@ script) if it exists.</para>
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="build-phase"><title>The build phase</title>
|
||||
<section><title>The build phase</title>
|
||||
|
||||
<para>The build phase is responsible for actually building the package
|
||||
(e.g. compiling it). The default <function>buildPhase</function>
|
||||
@@ -660,7 +646,7 @@ called, respectively.</para>
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="ssec-check-phase"><title>The check phase</title>
|
||||
<section><title>The check phase</title>
|
||||
|
||||
<para>The check phase checks whether the package was built correctly
|
||||
by running its test suite. The default
|
||||
@@ -720,7 +706,7 @@ doCheck = true;</programlisting>
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="ssec-install-phase"><title>The install phase</title>
|
||||
<section><title>The install phase</title>
|
||||
|
||||
<para>The install phase is responsible for installing the package in
|
||||
the Nix store under <envar>out</envar>. The default
|
||||
@@ -729,7 +715,7 @@ the Nix store under <envar>out</envar>. The default
|
||||
install</command>.</para>
|
||||
|
||||
<variablelist>
|
||||
<title>Variables controlling the install phase</title>
|
||||
<title>Variables controlling the check phase</title>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>makeFlags</varname> /
|
||||
@@ -775,7 +761,7 @@ installTargets = "install-bin install-doc";</programlisting>
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="ssec-fixup-phase"><title>The fixup phase</title>
|
||||
<section><title>The fixup phase</title>
|
||||
|
||||
<para>The fixup phase performs some (Nix-specific) post-processing
|
||||
actions on the files installed under <filename>$out</filename> by the
|
||||
@@ -808,7 +794,7 @@ following:
|
||||
</para>
|
||||
|
||||
<variablelist>
|
||||
<title>Variables controlling the fixup phase</title>
|
||||
<title>Variables controlling the check phase</title>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>dontStrip</varname></term>
|
||||
@@ -816,12 +802,6 @@ following:
|
||||
stripped. By default, they are.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>dontMoveSbin</varname></term>
|
||||
<listitem><para>If set, files in <filename>$out/sbin</filename> are not moved
|
||||
to <filename>$out/bin</filename>. By default, they are.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>stripAllList</varname></term>
|
||||
<listitem><para>List of directories to search for libraries and
|
||||
@@ -899,41 +879,12 @@ following:
|
||||
phase.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>separateDebugInfo</varname></term>
|
||||
<listitem><para>If set to <literal>true</literal>, the standard
|
||||
environment will enable debug information in C/C++ builds. After
|
||||
installation, the debug information will be separated from the
|
||||
executables and stored in the output named
|
||||
<literal>debug</literal>. (This output is enabled automatically;
|
||||
you don’t need to set the <varname>outputs</varname> attribute
|
||||
explicitly.) To be precise, the debug information is stored in
|
||||
<filename><replaceable>debug</replaceable>/lib/debug/.build-id/<replaceable>XX</replaceable>/<replaceable>YYYY…</replaceable></filename>,
|
||||
where <replaceable>XXYYYY…</replaceable> is the <replaceable>build
|
||||
ID</replaceable> of the binary — a SHA-1 hash of the contents of
|
||||
the binary. Debuggers like GDB use the build ID to look up the
|
||||
separated debug information.</para>
|
||||
|
||||
<para>For example, with GDB, you can add
|
||||
|
||||
<programlisting>
|
||||
set debug-file-directory ~/.nix-profile/lib/debug
|
||||
</programlisting>
|
||||
|
||||
to <filename>~/.gdbinit</filename>. GDB will then be able to find
|
||||
debug information installed via <literal>nix-env
|
||||
-i</literal>.</para>
|
||||
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="ssec-distribution-phase"><title>The distribution
|
||||
phase</title>
|
||||
<section><title>The distribution phase</title>
|
||||
|
||||
<para>The distribution phase is intended to produce a source
|
||||
distribution of the package. The default
|
||||
@@ -1166,9 +1117,12 @@ echo @foo@
|
||||
<varlistentry>
|
||||
<term>Python</term>
|
||||
<listitem><para>Adds the
|
||||
<filename>lib/${python.libPrefix}/site-packages</filename> subdirectory of
|
||||
<filename>lib/python2.5/site-packages</filename> subdirectory of
|
||||
each build input to the <envar>PYTHONPATH</envar> environment
|
||||
variable.</para></listitem>
|
||||
variable.</para>
|
||||
|
||||
<note><para>This should be generalised: the Python version
|
||||
shouldn’t be hard-coded.</para></note></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -1204,7 +1158,7 @@ echo @foo@
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>Qt 4</term>
|
||||
<term>Qt</term>
|
||||
<listitem><para>Sets the <envar>QTDIR</envar> environment variable
|
||||
to Qt’s path.</para></listitem>
|
||||
</varlistentry>
|
||||
@@ -1237,7 +1191,7 @@ echo @foo@
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-purity-in-nixpkgs"><title>Purity in Nixpkgs</title>
|
||||
<section><title>Purity in Nixpkgs</title>
|
||||
|
||||
<para>[measures taken to prevent dependencies on packages outside the
|
||||
store, and what you can do to prevent them]</para>
|
||||
|
||||
@@ -1,283 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-submitting-changes">
|
||||
|
||||
<title>Submitting changes</title>
|
||||
|
||||
<section>
|
||||
<title>Making patches</title>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Read <link xlink:href="https://nixos.org/nixpkgs/manual/">Manual (How to write packages for Nix)</link>.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Fork the repository on GitHub.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Create a branch for your future fix.
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>You can make branch from a commit of your local <command>nixos-version</command>. That will help you to avoid additional local compilations. Because you will receive packages from binary cache.
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>For example: <command>nixos-version</command> returns <command>15.05.git.0998212 (Dingo)</command>. So you can do:</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<screen>
|
||||
$ git checkout 0998212
|
||||
$ git checkout -b 'fix/pkg-name-update'
|
||||
</screen>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Please avoid working directly on the <command>master</command> branch.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Make commits of logical units.
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>If you removed pkgs, made some major NixOS changes etc., write about them in <command>nixos/doc/manual/release-notes/rl-unstable.xml</command>.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Check for unnecessary whitespace with <command>git diff --check</command> before committing.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Format the commit in a following way:</para>
|
||||
<programlisting>
|
||||
(pkg-name | service-name): (from -> to | init at version | refactor | etc)
|
||||
Additional information.
|
||||
</programlisting>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Examples:
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<command>nginx: init at 2.0.1</command>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command>firefox: 3.0 -> 3.1.1</command>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command>hydra service: add bazBaz option</command>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command>nginx service: refactor config generation</command>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Test your changes. If you work with
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>nixpkgs:
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>update pkg ->
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<command>nix-env -i pkg-name -f <path to your local nixpkgs folder></command>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>add pkg ->
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Make sure it's in <command>pkgs/top-level/all-packages.nix</command>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command>nix-env -i pkg-name -f <path to your local nixpkgs folder></command>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<emphasis>If you don't want to install pkg in you profile</emphasis>.
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<command>nix-build -A pkg-attribute-name <path to your local nixpkgs folder>/default.nix</command> and check results in the folder <command>result</command>. It will appear in the same directory where you did <command>nix-build</command>.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>If you did <command>nix-env -i pkg-name</command> you can do <command>nix-env -e pkg-name</command> to uninstall it from your system.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>NixOS and its modules:
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>You can add new module to your NixOS configuration file (usually it's <command>/etc/nixos/configuration.nix</command>).
|
||||
And do <command>sudo nixos-rebuild test -I nixpkgs=<path to your local nixpkgs folder> --fast</command>.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>If you have commits <command>pkg-name: oh, forgot to insert whitespace</command>: squash commits in this case. Use <command>git rebase -i</command>.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Rebase you branch against current <command>master</command>.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Submitting changes</title>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Push your changes to your fork of nixpkgs.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Create pull request:
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Write the title in format <command>(pkg-name | service): improvement</command>.
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>If you update the pkg, write versions <command>from -> to</command>.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Write in comment if you have tested your patch. Do not rely much on <command>TravisCI</command>.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>If you make an improvement, write about your motivation.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Notify maintainers of the package. For example add to the message: <command>cc @jagajaga @domenkozar</command>.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Hotfixing pull requests</title>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Make the appropriate changes in you branch.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Don't create additional commits, do
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><command>git rebase -i</command></para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<command>git push --force</command> to your branch.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Commit policy</title>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Commits must be sufficiently tested before being merged, both for the master and staging branches.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Hydra builds for master and staging should not be used as testing platform, it's a build farm for changes that have been already tested.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Master should only see non-breaking commits that do not cause mass rebuilds.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Staging should only see non-breaking mass-rebuild commits. That means it's not to be used for testing, and changes must have been well tested already. <link xlink:href="http://comments.gmane.org/gmane.linux.distributions.nixos/13447">Read policy here</link>.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>If staging is already in a broken state, please refrain from adding extra new breakages. Stabilize it for a few days, merge into master, then resume development on staging. <link xlink:href="http://hydra.nixos.org/jobset/nixpkgs/staging#tabs-evaluations">Keep an eye on the staging evaluations here</link>.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>When changing the bootloader installation process, extra care must be taken. Grub installations cannot be rolled back, hence changes may break people's installations forever. For any non-trivial change to the bootloader please file a PR asking for review, especially from @edolstra.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
</chapter>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
# Operations on attribute sets.
|
||||
|
||||
with {
|
||||
inherit (builtins) head tail length;
|
||||
inherit (builtins) head tail;
|
||||
inherit (import ./trivial.nix) or;
|
||||
inherit (import ./default.nix) fold;
|
||||
inherit (import ./strings.nix) concatStringsSep;
|
||||
inherit (import ./lists.nix) concatMap concatLists all deepSeqList;
|
||||
inherit (import ./misc.nix) maybeAttr;
|
||||
};
|
||||
|
||||
rec {
|
||||
@@ -19,8 +20,8 @@ rec {
|
||||
let attr = head attrPath;
|
||||
in
|
||||
if attrPath == [] then e
|
||||
else if e ? ${attr}
|
||||
then attrByPath (tail attrPath) default e.${attr}
|
||||
else if hasAttr attr e
|
||||
then attrByPath (tail attrPath) default (getAttr attr e)
|
||||
else default;
|
||||
|
||||
|
||||
@@ -43,7 +44,8 @@ rec {
|
||||
attrVals ["a" "b" "c"] as
|
||||
=> [as.a as.b as.c]
|
||||
*/
|
||||
attrVals = nameList: set: map (x: set.${x}) nameList;
|
||||
attrVals = nameList: set:
|
||||
map (x: getAttr x set) nameList;
|
||||
|
||||
|
||||
/* Return the values of all attributes in the given set, sorted by
|
||||
@@ -53,7 +55,7 @@ rec {
|
||||
attrValues {c = 3; a = 1; b = 2;}
|
||||
=> [1 2 3]
|
||||
*/
|
||||
attrValues = builtins.attrValues or (attrs: attrVals (attrNames attrs) attrs);
|
||||
attrValues = attrs: attrVals (attrNames attrs) attrs;
|
||||
|
||||
|
||||
/* Collect each attribute named `attr' from a list of attribute
|
||||
@@ -63,8 +65,7 @@ rec {
|
||||
catAttrs "a" [{a = 1;} {b = 0;} {a = 2;}]
|
||||
=> [1 2]
|
||||
*/
|
||||
catAttrs = builtins.catAttrs or
|
||||
(attr: l: concatLists (map (s: if s ? ${attr} then [s.${attr}] else []) l));
|
||||
catAttrs = attr: l: concatLists (map (s: if hasAttr attr s then [(getAttr attr s)] else []) l);
|
||||
|
||||
|
||||
/* Filter an attribute set by removing all attributes for which the
|
||||
@@ -75,29 +76,9 @@ rec {
|
||||
=> { foo = 1; }
|
||||
*/
|
||||
filterAttrs = pred: set:
|
||||
listToAttrs (concatMap (name: let v = set.${name}; in if pred name v then [(nameValuePair name v)] else []) (attrNames set));
|
||||
listToAttrs (fold (n: ys: let v = getAttr n set; in if pred n v then [(nameValuePair n v)] ++ ys else ys) [] (attrNames set));
|
||||
|
||||
|
||||
/* Filter an attribute set recursivelly by removing all attributes for
|
||||
which the given predicate return false.
|
||||
|
||||
Example:
|
||||
filterAttrsRecursive (n: v: v != null) { foo = { bar = null; }; }
|
||||
=> { foo = {}; }
|
||||
*/
|
||||
filterAttrsRecursive = pred: set:
|
||||
listToAttrs (
|
||||
concatMap (name:
|
||||
let v = set.${name}; in
|
||||
if pred name v then [
|
||||
(nameValuePair name (
|
||||
if isAttrs v then filterAttrsRecursive pred v
|
||||
else v
|
||||
))
|
||||
] else []
|
||||
) (attrNames set)
|
||||
);
|
||||
|
||||
/* foldAttrs: apply fold functions to values grouped by key. Eg accumulate values as list:
|
||||
foldAttrs (n: a: [n] ++ a) [] [{ a = 2; } { a = 3; }]
|
||||
=> { a = [ 2 3 ]; }
|
||||
@@ -105,7 +86,7 @@ rec {
|
||||
foldAttrs = op: nul: list_of_attrs:
|
||||
fold (n: a:
|
||||
fold (name: o:
|
||||
o // (listToAttrs [{inherit name; value = op n.${name} (a.${name} or nul); }])
|
||||
o // (listToAttrs [{inherit name; value = op (getAttr name n) (maybeAttr name nul a); }])
|
||||
) a (attrNames n)
|
||||
) {} list_of_attrs;
|
||||
|
||||
@@ -151,7 +132,7 @@ rec {
|
||||
=> { x = "x-foo"; y = "y-bar"; }
|
||||
*/
|
||||
mapAttrs = f: set:
|
||||
listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set));
|
||||
listToAttrs (map (attr: { name = attr; value = f attr (getAttr attr set); }) (attrNames set));
|
||||
|
||||
|
||||
/* Like `mapAttrs', but allows the name of each attribute to be
|
||||
@@ -164,7 +145,7 @@ rec {
|
||||
=> { foo_x = "bar-a"; foo_y = "bar-b"; }
|
||||
*/
|
||||
mapAttrs' = f: set:
|
||||
listToAttrs (map (attr: f attr set.${attr}) (attrNames set));
|
||||
listToAttrs (map (attr: f attr (getAttr attr set)) (attrNames set));
|
||||
|
||||
|
||||
/* Call a function for each attribute in the given set and return
|
||||
@@ -176,7 +157,7 @@ rec {
|
||||
=> [ "xa" "yb" ]
|
||||
*/
|
||||
mapAttrsToList = f: attrs:
|
||||
map (name: f name attrs.${name}) (attrNames attrs);
|
||||
map (name: f name (getAttr name attrs)) (attrNames attrs);
|
||||
|
||||
|
||||
/* Like `mapAttrs', except that it recursively applies itself to
|
||||
@@ -241,16 +222,6 @@ rec {
|
||||
isDerivation = x: isAttrs x && x ? type && x.type == "derivation";
|
||||
|
||||
|
||||
/* Convert a store path to a fake derivation. */
|
||||
toDerivation = path:
|
||||
let path' = builtins.storePath path; in
|
||||
{ type = "derivation";
|
||||
name = builtins.unsafeDiscardStringContext (builtins.substring 33 (-1) (baseNameOf path'));
|
||||
outPath = path';
|
||||
outputs = [ "out" ];
|
||||
};
|
||||
|
||||
|
||||
/* If the Boolean `cond' is true, return the attribute set `as',
|
||||
otherwise an empty attribute set. */
|
||||
optionalAttrs = cond: as: if cond then as else {};
|
||||
@@ -351,7 +322,7 @@ rec {
|
||||
# override only the attributes that are already present in the old set
|
||||
# useful for deep-overriding
|
||||
overrideExisting = old: new:
|
||||
old // listToAttrs (map (attr: nameValuePair attr (attrByPath [attr] old.${attr} new)) (attrNames old));
|
||||
old // listToAttrs (map (attr: nameValuePair attr (attrByPath [attr] (getAttr attr old) new)) (attrNames old));
|
||||
|
||||
deepSeqAttrs = x: y: deepSeqList (attrValues x) y;
|
||||
}
|
||||
|
||||
@@ -1,74 +1,15 @@
|
||||
{lib, pkgs} :
|
||||
let inherit (lib) nv nvs; in
|
||||
{
|
||||
|
||||
# composableDerivation basically mixes these features:
|
||||
# - fix function
|
||||
# - mergeAttrBy
|
||||
# - provides shortcuts for "options" such as "--enable-foo" and adding
|
||||
# buildInputs, see php example
|
||||
# see for example:
|
||||
# - development/interpreters/php_configurable/default.nix
|
||||
# - .. search composableDerivation in all-packages.nix ..
|
||||
#
|
||||
# It predates styles which are common today, such as
|
||||
# * the config attr
|
||||
# * mkDerivation.override feature
|
||||
# * overrideDerivation (lib/customization.nix)
|
||||
#
|
||||
# Some of the most more important usage examples (which could be rewritten if it was important):
|
||||
# * php
|
||||
# * postgis
|
||||
# * vim_configurable
|
||||
#
|
||||
# A minimal example illustrating most features would look like this:
|
||||
# let base = composableDerivation { (fixed : let inherit (fixed.fixed) name in {
|
||||
# src = fetchurl {
|
||||
# }
|
||||
# buildInputs = [A];
|
||||
# preConfigre = "echo ${name}";
|
||||
# # attention, "name" attr is missing, thus you cannot instantiate "base".
|
||||
# }
|
||||
# in {
|
||||
# # These all add name attribute, thus you can instantiate those:
|
||||
# v1 = base.merge ({ name = "foo-add-B"; buildInputs = [B]; }); // B gets merged into buildInputs
|
||||
# v2 = base.merge ({ name = "mix-in-pre-configure-lines" preConfigre = ""; });
|
||||
# v3 = base.replace ({ name = "foo-no-A-only-B;" buildInputs = [B]; });
|
||||
# }
|
||||
#
|
||||
# So yes, you can think about it being something like nixos modules, and
|
||||
# you'd be merging "features" in one at a time using .merge or .replace
|
||||
# Thanks Shea for telling me that I rethink the documentation ..
|
||||
#
|
||||
# issues:
|
||||
# * its complicated to understand
|
||||
# * some "features" such as exact merge behaviour are burried in mergeAttrBy
|
||||
# and defaultOverridableDelayableArgs assuming the default behaviour does
|
||||
# the right thing in the common case
|
||||
# * Eelco once said using such fix style functions are slow to evaluate
|
||||
# * Too quick & dirty. Hard to understand for others. The benefit was that
|
||||
# you were able to create a kernel builder like base derivation and replace
|
||||
# / add patches the way you want without having to declare function arguments
|
||||
#
|
||||
# nice features:
|
||||
# declaring "optional featuers" is modular. For instance:
|
||||
# flags.curl = {
|
||||
# configureFlags = ["--with-curl=${curl}" "--with-curlwrappers"];
|
||||
# buildInputs = [curl openssl];
|
||||
# };
|
||||
# flags.other = { .. }
|
||||
# (Example taken from PHP)
|
||||
#
|
||||
# alternative styles / related features:
|
||||
# * Eg see function supporting building the kernel
|
||||
# * versionedDerivation (discussion about this is still going on - or ended)
|
||||
# * composedArgsAndFun
|
||||
# * mkDerivation.override
|
||||
# * overrideDerivation
|
||||
# * using { .., *Support ? false }: like configurable options.
|
||||
# To find those examples use grep
|
||||
#
|
||||
# To sum up: It exists for historical reasons - and for most commonly used
|
||||
# tasks the alternatives should be used
|
||||
#
|
||||
# If you have questions about this code ping Marc Weber.
|
||||
# You should be able to override anything you like easily
|
||||
# grep the mailinglist by title "python proposal" (dec 08)
|
||||
# -> http://mail.cs.uu.nl/pipermail/nix-dev/2008-December/001571.html
|
||||
# to see why this got complicated when using all its features
|
||||
# TODO add newer example using new syntax (kernel derivation proposal -> mailinglist)
|
||||
composableDerivation = {
|
||||
mkDerivation ? pkgs.stdenv.mkDerivation,
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
let
|
||||
|
||||
lib = import ./default.nix;
|
||||
inherit (builtins) attrNames isFunction;
|
||||
let lib = import ./default.nix;
|
||||
inherit (builtins) getAttr attrNames isFunction;
|
||||
|
||||
in
|
||||
|
||||
@@ -31,8 +29,8 @@ rec {
|
||||
|
||||
For another application, see build-support/vm, where this
|
||||
function is used to build arbitrary derivations inside a QEMU
|
||||
virtual machine.
|
||||
*/
|
||||
virtual machine. */
|
||||
|
||||
overrideDerivation = drv: f:
|
||||
let
|
||||
newDrv = derivation (drv.drvAttrs // (f drv));
|
||||
@@ -51,23 +49,27 @@ rec {
|
||||
else { }));
|
||||
|
||||
|
||||
# usage: (you can use override multiple times)
|
||||
# let d = makeOverridable stdenv.mkDerivation { name = ..; buildInputs; }
|
||||
# noBuildInputs = d.override { buildInputs = []; }
|
||||
# additionalBuildInputs = d.override ( args : args // { buildInputs = args.buildInputs ++ [ additional ]; } )
|
||||
makeOverridable = f: origArgs:
|
||||
let
|
||||
ff = f origArgs;
|
||||
overrideWith = newArgs: origArgs // (if builtins.isFunction newArgs then newArgs origArgs else newArgs);
|
||||
in
|
||||
if builtins.isAttrs ff then (ff //
|
||||
{ override = newArgs: makeOverridable f (overrideWith newArgs);
|
||||
overrideDerivation = fdrv:
|
||||
makeOverridable (args: overrideDerivation (f args) fdrv) origArgs;
|
||||
{ override = newArgs:
|
||||
makeOverridable f (origArgs // (if builtins.isFunction newArgs then newArgs origArgs else newArgs));
|
||||
deepOverride = newArgs:
|
||||
makeOverridable f (lib.overrideExisting (lib.mapAttrs (deepOverrider newArgs) origArgs) newArgs);
|
||||
})
|
||||
else if builtins.isFunction ff then
|
||||
{ override = newArgs: makeOverridable f (overrideWith newArgs);
|
||||
__functor = self: ff;
|
||||
overrideDerivation = throw "overrideDerivation not yet supported for functors";
|
||||
}
|
||||
else ff;
|
||||
|
||||
deepOverrider = newArgs: name: x: if builtins.isAttrs x then (
|
||||
if x ? deepOverride then (x.deepOverride newArgs) else
|
||||
if x ? override then (x.override newArgs) else
|
||||
x) else x;
|
||||
|
||||
|
||||
/* Call the package function in the file `fn' with the required
|
||||
arguments automatically. The function is called with the
|
||||
@@ -91,29 +93,10 @@ rec {
|
||||
};
|
||||
*/
|
||||
callPackageWith = autoArgs: fn: args:
|
||||
let
|
||||
f = if builtins.isFunction fn then fn else import fn;
|
||||
auto = builtins.intersectAttrs (builtins.functionArgs f) autoArgs;
|
||||
in makeOverridable f (auto // args);
|
||||
let f = if builtins.isFunction fn then fn else import fn; in
|
||||
makeOverridable f ((builtins.intersectAttrs (builtins.functionArgs f) autoArgs) // args);
|
||||
|
||||
|
||||
/* Like callPackage, but for a function that returns an attribute
|
||||
set of derivations. The override function is added to the
|
||||
individual attributes. */
|
||||
callPackagesWith = autoArgs: fn: args:
|
||||
let
|
||||
f = if builtins.isFunction fn then fn else import fn;
|
||||
auto = builtins.intersectAttrs (builtins.functionArgs f) autoArgs;
|
||||
finalArgs = auto // args;
|
||||
pkgs = f finalArgs;
|
||||
mkAttrOverridable = name: pkg: pkg // {
|
||||
override = newArgs: mkAttrOverridable name (f (finalArgs // newArgs)).${name};
|
||||
};
|
||||
in lib.mapAttrs mkAttrOverridable pkgs;
|
||||
|
||||
|
||||
/* Add attributes to each output of a derivation without changing
|
||||
the derivation itself. */
|
||||
/* Add attributes to each output of a derivation without changing the derivation itself */
|
||||
addPassthru = drv: passthru:
|
||||
let
|
||||
outputs = drv.outputs or [ "out" ];
|
||||
@@ -124,63 +107,10 @@ rec {
|
||||
outputToAttrListElement = outputName:
|
||||
{ name = outputName;
|
||||
value = commonAttrs // {
|
||||
inherit (drv.${outputName}) outPath drvPath type outputName;
|
||||
inherit (builtins.getAttr outputName drv) outPath drvPath type outputName;
|
||||
};
|
||||
};
|
||||
|
||||
outputsList = map outputToAttrListElement outputs;
|
||||
in commonAttrs.${drv.outputName};
|
||||
|
||||
|
||||
/* Strip a derivation of all non-essential attributes, returning
|
||||
only those needed by hydra-eval-jobs. Also strictly evaluate the
|
||||
result to ensure that there are no thunks kept alive to prevent
|
||||
garbage collection. */
|
||||
hydraJob = drv:
|
||||
let
|
||||
outputs = drv.outputs or ["out"];
|
||||
|
||||
commonAttrs =
|
||||
{ inherit (drv) name system meta; inherit outputs; }
|
||||
// lib.optionalAttrs (drv._hydraAggregate or false) {
|
||||
_hydraAggregate = true;
|
||||
constituents = map hydraJob (lib.flatten drv.constituents);
|
||||
}
|
||||
// (lib.listToAttrs outputsList);
|
||||
|
||||
makeOutput = outputName:
|
||||
let output = drv.${outputName}; in
|
||||
{ name = outputName;
|
||||
value = commonAttrs // {
|
||||
outPath = output.outPath;
|
||||
drvPath = output.drvPath;
|
||||
type = "derivation";
|
||||
inherit outputName;
|
||||
};
|
||||
};
|
||||
|
||||
outputsList = map makeOutput outputs;
|
||||
|
||||
drv' = (lib.head outputsList).value;
|
||||
in lib.deepSeq drv' drv';
|
||||
|
||||
/* Make a set of packages with a common scope. All packages called
|
||||
with the provided `callPackage' will be evaluated with the same
|
||||
arguments. Any package in the set may depend on any other. The
|
||||
`override' function allows subsequent modification of the package
|
||||
set in a consistent way, i.e. all packages in the set will be
|
||||
called with the overridden packages. The package sets may be
|
||||
hierarchical: the packages in the set are called with the scope
|
||||
provided by `newScope' and the set provides a `newScope' attribute
|
||||
which can form the parent scope for later package sets. */
|
||||
makeScope = newScope: f:
|
||||
let self = f self // {
|
||||
newScope = scope: newScope (self // scope);
|
||||
callPackage = self.newScope {};
|
||||
override = g: makeScope newScope (self_:
|
||||
let super = f self_;
|
||||
in super // g super self_);
|
||||
};
|
||||
in self;
|
||||
|
||||
in builtins.getAttr drv.outputName commonAttrs;
|
||||
}
|
||||
|
||||
@@ -9,16 +9,23 @@ in
|
||||
|
||||
rec {
|
||||
|
||||
inherit (builtins) addErrorContext;
|
||||
|
||||
addErrorContextToAttrs = lib.mapAttrs (a: v: lib.addErrorContext "while evaluating ${a}" v);
|
||||
# Wrapper aroung the primop `addErrorContext', which shouldn't used
|
||||
# directly. It evaluates and returns `val', but if an evaluation
|
||||
# error occurs, the text in `msg' is added to the error context
|
||||
# (stack trace) printed by Nix.
|
||||
addErrorContext =
|
||||
if builtins ? addErrorContext
|
||||
then builtins.addErrorContext
|
||||
else msg: val: val;
|
||||
|
||||
traceIf = p: msg: x: if p then trace msg x else x;
|
||||
|
||||
traceVal = x: trace x x;
|
||||
traceXMLVal = x: trace (builtins.toXML x) x;
|
||||
traceXMLValMarked = str: x: trace (str + builtins.toXML x) x;
|
||||
addErrorContextToAttrs = lib.mapAttrs (a : v : lib.addErrorContext "while evaluating ${a}" v);
|
||||
|
||||
|
||||
traceVal = if builtins ? trace then x: (builtins.trace x x) else x: x;
|
||||
traceXMLVal = if builtins ? trace then x: (builtins.trace (builtins.toXML x) x) else x: x;
|
||||
traceXMLValMarked = str: if builtins ? trace then x: (builtins.trace ( str + builtins.toXML x) x) else x: x;
|
||||
|
||||
# this can help debug your code as well - designed to not produce thousands of lines
|
||||
traceShowVal = x : trace (showVal x) x;
|
||||
traceShowValMarked = str: x: trace (str + showVal x) x;
|
||||
@@ -37,13 +44,12 @@ rec {
|
||||
else if isString x then "x is a string `${substring 0 50 x}...'"
|
||||
else "x is probably a path `${substring 0 50 (toString x)}...'";
|
||||
|
||||
# trace the arguments passed to function and its result
|
||||
# trace the arguments passed to function and its result
|
||||
# maybe rewrite these functions in a traceCallXml like style. Then one function is enough
|
||||
traceCall = n : f : a : let t = n2 : x : traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a));
|
||||
traceCall2 = n : f : a : b : let t = n2 : x : traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b));
|
||||
traceCall3 = n : f : a : b : c : let t = n2 : x : traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b) (t "arg 3" c));
|
||||
|
||||
# FIXME: rename this?
|
||||
traceValIfNot = c: x:
|
||||
if c x then true else trace (showVal x) false;
|
||||
|
||||
@@ -64,7 +70,7 @@ rec {
|
||||
|
||||
then [ { inherit name; expected = test.expected; result = test.expr; } ]
|
||||
else [] ) tests));
|
||||
|
||||
|
||||
# create a test assuming that list elements are true
|
||||
# usage: { testX = allTrue [ true ]; }
|
||||
testAllTrue = expr : { inherit expr; expected = map (x: true) expr; };
|
||||
@@ -103,11 +109,11 @@ rec {
|
||||
let nr = a;
|
||||
in (str: expr:
|
||||
if isFunction expr then
|
||||
(arg:
|
||||
(arg:
|
||||
traceCallXml (builtins.add 1 nr) "${str}\n arg ${builtins.toString nr} is \n ${builtins.toXML (strict arg)}" (expr arg)
|
||||
)
|
||||
else
|
||||
else
|
||||
let r = strict expr;
|
||||
in trace "${str}\n result:\n${builtins.toXML r}" r
|
||||
in builtins.trace "${str}\n result:\n${builtins.toXML r}" r
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ let
|
||||
types = import ./types.nix;
|
||||
meta = import ./meta.nix;
|
||||
debug = import ./debug.nix;
|
||||
misc = import ./deprecated.nix;
|
||||
misc = import ./misc.nix;
|
||||
maintainers = import ./maintainers.nix;
|
||||
platforms = import ./platforms.nix;
|
||||
systems = import ./systems.nix;
|
||||
|
||||
@@ -1,423 +0,0 @@
|
||||
let lib = import ./default.nix;
|
||||
inherit (builtins) isFunction head tail isList isAttrs isInt attrNames;
|
||||
|
||||
in
|
||||
|
||||
with import ./lists.nix;
|
||||
with import ./attrsets.nix;
|
||||
with import ./strings.nix;
|
||||
|
||||
rec {
|
||||
|
||||
# returns default if env var is not set
|
||||
maybeEnv = name: default:
|
||||
let value = builtins.getEnv name; in
|
||||
if value == "" then default else value;
|
||||
|
||||
defaultMergeArg = x : y: if builtins.isAttrs y then
|
||||
y
|
||||
else
|
||||
(y x);
|
||||
defaultMerge = x: y: x // (defaultMergeArg x y);
|
||||
foldArgs = merger: f: init: x:
|
||||
let arg=(merger init (defaultMergeArg init x));
|
||||
# now add the function with composed args already applied to the final attrs
|
||||
base = (setAttrMerge "passthru" {} (f arg)
|
||||
( z : z // rec {
|
||||
function = foldArgs merger f arg;
|
||||
args = (lib.attrByPath ["passthru" "args"] {} z) // x;
|
||||
} ));
|
||||
withStdOverrides = base // {
|
||||
override = base.passthru.function;
|
||||
} ;
|
||||
in
|
||||
withStdOverrides;
|
||||
|
||||
|
||||
# predecessors: proposed replacement for applyAndFun (which has a bug cause it merges twice)
|
||||
# the naming "overridableDelayableArgs" tries to express that you can
|
||||
# - override attr values which have been supplied earlier
|
||||
# - use attr values before they have been supplied by accessing the fix point
|
||||
# name "fixed"
|
||||
# f: the (delayed overridden) arguments are applied to this
|
||||
#
|
||||
# initial: initial attrs arguments and settings. see defaultOverridableDelayableArgs
|
||||
#
|
||||
# returns: f applied to the arguments // special attributes attrs
|
||||
# a) merge: merge applied args with new args. Wether an argument is overridden depends on the merge settings
|
||||
# b) replace: this let's you replace and remove names no matter which merge function has been set
|
||||
#
|
||||
# examples: see test cases "res" below;
|
||||
overridableDelayableArgs =
|
||||
f : # the function applied to the arguments
|
||||
initial : # you pass attrs, the functions below are passing a function taking the fix argument
|
||||
let
|
||||
takeFixed = if isFunction initial then initial else (fixed : initial); # transform initial to an expression always taking the fixed argument
|
||||
tidy = args :
|
||||
let # apply all functions given in "applyPreTidy" in sequence
|
||||
applyPreTidyFun = fold ( n : a : x : n ( a x ) ) lib.id (maybeAttr "applyPreTidy" [] args);
|
||||
in removeAttrs (applyPreTidyFun args) ( ["applyPreTidy"] ++ (maybeAttr "removeAttrs" [] args) ); # tidy up args before applying them
|
||||
fun = n : x :
|
||||
let newArgs = fixed :
|
||||
let args = takeFixed fixed;
|
||||
mergeFun = args.${n};
|
||||
in if isAttrs x then (mergeFun args x)
|
||||
else assert isFunction x;
|
||||
mergeFun args (x ( args // { inherit fixed; }));
|
||||
in overridableDelayableArgs f newArgs;
|
||||
in
|
||||
(f (tidy (lib.fix takeFixed))) // {
|
||||
merge = fun "mergeFun";
|
||||
replace = fun "keepFun";
|
||||
};
|
||||
defaultOverridableDelayableArgs = f :
|
||||
let defaults = {
|
||||
mergeFun = mergeAttrByFunc; # default merge function. merge strategie (concatenate lists, strings) is given by mergeAttrBy
|
||||
keepFun = a : b : { inherit (a) removeAttrs mergeFun keepFun mergeAttrBy; } // b; # even when using replace preserve these values
|
||||
applyPreTidy = []; # list of functions applied to args before args are tidied up (usage case : prepareDerivationArgs)
|
||||
mergeAttrBy = mergeAttrBy // {
|
||||
applyPreTidy = a : b : a ++ b;
|
||||
removeAttrs = a : b: a ++ b;
|
||||
};
|
||||
removeAttrs = ["mergeFun" "keepFun" "mergeAttrBy" "removeAttrs" "fixed" ]; # before applying the arguments to the function make sure these names are gone
|
||||
};
|
||||
in (overridableDelayableArgs f defaults).merge;
|
||||
|
||||
|
||||
|
||||
# rec { # an example of how composedArgsAndFun can be used
|
||||
# a = composedArgsAndFun (x : x) { a = ["2"]; meta = { d = "bar";}; };
|
||||
# # meta.d will be lost ! It's your task to preserve it (eg using a merge function)
|
||||
# b = a.passthru.function { a = [ "3" ]; meta = { d2 = "bar2";}; };
|
||||
# # instead of passing/ overriding values you can use a merge function:
|
||||
# c = b.passthru.function ( x: { a = x.a ++ ["4"]; }); # consider using (maybeAttr "a" [] x)
|
||||
# }
|
||||
# result:
|
||||
# {
|
||||
# a = { a = ["2"]; meta = { d = "bar"; }; passthru = { function = .. }; };
|
||||
# b = { a = ["3"]; meta = { d2 = "bar2"; }; passthru = { function = .. }; };
|
||||
# c = { a = ["3" "4"]; meta = { d2 = "bar2"; }; passthru = { function = .. }; };
|
||||
# # c2 is equal to c
|
||||
# }
|
||||
composedArgsAndFun = f: foldArgs defaultMerge f {};
|
||||
|
||||
|
||||
# shortcut for attrByPath ["name"] default attrs
|
||||
maybeAttrNullable = maybeAttr;
|
||||
|
||||
# shortcut for attrByPath ["name"] default attrs
|
||||
maybeAttr = name: default: attrs: attrs.${name} or default;
|
||||
|
||||
|
||||
# Return the second argument if the first one is true or the empty version
|
||||
# of the second argument.
|
||||
ifEnable = cond: val:
|
||||
if cond then val
|
||||
else if builtins.isList val then []
|
||||
else if builtins.isAttrs val then {}
|
||||
# else if builtins.isString val then ""
|
||||
else if val == true || val == false then false
|
||||
else null;
|
||||
|
||||
|
||||
# Return true only if there is an attribute and it is true.
|
||||
checkFlag = attrSet: name:
|
||||
if name == "true" then true else
|
||||
if name == "false" then false else
|
||||
if (elem name (attrByPath ["flags"] [] attrSet)) then true else
|
||||
attrByPath [name] false attrSet ;
|
||||
|
||||
|
||||
# Input : attrSet, [ [name default] ... ], name
|
||||
# Output : its value or default.
|
||||
getValue = attrSet: argList: name:
|
||||
( attrByPath [name] (if checkFlag attrSet name then true else
|
||||
if argList == [] then null else
|
||||
let x = builtins.head argList; in
|
||||
if (head x) == name then
|
||||
(head (tail x))
|
||||
else (getValue attrSet
|
||||
(tail argList) name)) attrSet );
|
||||
|
||||
|
||||
# Input : attrSet, [[name default] ...], [ [flagname reqs..] ... ]
|
||||
# Output : are reqs satisfied? It's asserted.
|
||||
checkReqs = attrSet : argList : condList :
|
||||
(
|
||||
fold lib.and true
|
||||
(map (x: let name = (head x) ; in
|
||||
|
||||
((checkFlag attrSet name) ->
|
||||
(fold lib.and true
|
||||
(map (y: let val=(getValue attrSet argList y); in
|
||||
(val!=null) && (val!=false))
|
||||
(tail x))))) condList)) ;
|
||||
|
||||
|
||||
# This function has O(n^2) performance.
|
||||
uniqList = {inputList, acc ? []} :
|
||||
let go = xs : acc :
|
||||
if xs == []
|
||||
then []
|
||||
else let x = head xs;
|
||||
y = if elem x acc then [] else [x];
|
||||
in y ++ go (tail xs) (y ++ acc);
|
||||
in go inputList acc;
|
||||
|
||||
uniqListExt = {inputList, outputList ? [],
|
||||
getter ? (x : x), compare ? (x: y: x==y)}:
|
||||
if inputList == [] then outputList else
|
||||
let x=head inputList;
|
||||
isX = y: (compare (getter y) (getter x));
|
||||
newOutputList = outputList ++
|
||||
(if any isX outputList then [] else [x]);
|
||||
in uniqListExt {outputList=newOutputList;
|
||||
inputList = (tail inputList);
|
||||
inherit getter compare;
|
||||
};
|
||||
|
||||
|
||||
|
||||
condConcat = name: list: checker:
|
||||
if list == [] then name else
|
||||
if checker (head list) then
|
||||
condConcat
|
||||
(name + (head (tail list)))
|
||||
(tail (tail list))
|
||||
checker
|
||||
else condConcat
|
||||
name (tail (tail list)) checker;
|
||||
|
||||
lazyGenericClosure = {startSet, operator}:
|
||||
let
|
||||
work = list: doneKeys: result:
|
||||
if list == [] then
|
||||
result
|
||||
else
|
||||
let x = head list; key = x.key; in
|
||||
if elem key doneKeys then
|
||||
work (tail list) doneKeys result
|
||||
else
|
||||
work (tail list ++ operator x) ([key] ++ doneKeys) ([x] ++ result);
|
||||
in
|
||||
work startSet [] [];
|
||||
|
||||
innerModifySumArgs = f: x: a: b: if b == null then (f a b) // x else
|
||||
innerModifySumArgs f x (a // b);
|
||||
modifySumArgs = f: x: innerModifySumArgs f x {};
|
||||
|
||||
|
||||
innerClosePropagation = acc : xs :
|
||||
if xs == []
|
||||
then acc
|
||||
else let y = head xs;
|
||||
ys = tail xs;
|
||||
in if ! isAttrs y
|
||||
then innerClosePropagation acc ys
|
||||
else let acc' = [y] ++ acc;
|
||||
in innerClosePropagation
|
||||
acc'
|
||||
(uniqList { inputList = (maybeAttrNullable "propagatedBuildInputs" [] y)
|
||||
++ (maybeAttrNullable "propagatedNativeBuildInputs" [] y)
|
||||
++ ys;
|
||||
acc = acc';
|
||||
}
|
||||
);
|
||||
|
||||
closePropagation = list: (uniqList {inputList = (innerClosePropagation [] list);});
|
||||
|
||||
# calls a function (f attr value ) for each record item. returns a list
|
||||
mapAttrsFlatten = f : r : map (attr: f attr r.${attr}) (attrNames r);
|
||||
|
||||
# attribute set containing one attribute
|
||||
nvs = name : value : listToAttrs [ (nameValuePair name value) ];
|
||||
# adds / replaces an attribute of an attribute set
|
||||
setAttr = set : name : v : set // (nvs name v);
|
||||
|
||||
# setAttrMerge (similar to mergeAttrsWithFunc but only merges the values of a particular name)
|
||||
# setAttrMerge "a" [] { a = [2];} (x : x ++ [3]) -> { a = [2 3]; }
|
||||
# setAttrMerge "a" [] { } (x : x ++ [3]) -> { a = [ 3]; }
|
||||
setAttrMerge = name : default : attrs : f :
|
||||
setAttr attrs name (f (maybeAttr name default attrs));
|
||||
|
||||
# Using f = a : b = b the result is similar to //
|
||||
# merge attributes with custom function handling the case that the attribute
|
||||
# exists in both sets
|
||||
mergeAttrsWithFunc = f : set1 : set2 :
|
||||
fold (n: set : if set ? ${n}
|
||||
then setAttr set n (f set.${n} set2.${n})
|
||||
else set )
|
||||
(set2 // set1) (attrNames set2);
|
||||
|
||||
# merging two attribute set concatenating the values of same attribute names
|
||||
# eg { a = 7; } { a = [ 2 3 ]; } becomes { a = [ 7 2 3 ]; }
|
||||
mergeAttrsConcatenateValues = mergeAttrsWithFunc ( a : b : (toList a) ++ (toList b) );
|
||||
|
||||
# merges attributes using //, if a name exisits in both attributes
|
||||
# an error will be triggered unless its listed in mergeLists
|
||||
# so you can mergeAttrsNoOverride { buildInputs = [a]; } { buildInputs = [a]; } {} to get
|
||||
# { buildInputs = [a b]; }
|
||||
# merging buildPhase does'nt really make sense. The cases will be rare where appending /prefixing will fit your needs?
|
||||
# in these cases the first buildPhase will override the second one
|
||||
# ! deprecated, use mergeAttrByFunc instead
|
||||
mergeAttrsNoOverride = { mergeLists ? ["buildInputs" "propagatedBuildInputs"],
|
||||
overrideSnd ? [ "buildPhase" ]
|
||||
} : attrs1 : attrs2 :
|
||||
fold (n: set :
|
||||
setAttr set n ( if set ? ${n}
|
||||
then # merge
|
||||
if elem n mergeLists # attribute contains list, merge them by concatenating
|
||||
then attrs2.${n} ++ attrs1.${n}
|
||||
else if elem n overrideSnd
|
||||
then attrs1.${n}
|
||||
else throw "error mergeAttrsNoOverride, attribute ${n} given in both attributes - no merge func defined"
|
||||
else attrs2.${n} # add attribute not existing in attr1
|
||||
)) attrs1 (attrNames attrs2);
|
||||
|
||||
|
||||
# example usage:
|
||||
# mergeAttrByFunc {
|
||||
# inherit mergeAttrBy; # defined below
|
||||
# buildInputs = [ a b ];
|
||||
# } {
|
||||
# buildInputs = [ c d ];
|
||||
# };
|
||||
# will result in
|
||||
# { mergeAttrsBy = [...]; buildInputs = [ a b c d ]; }
|
||||
# is used by prepareDerivationArgs, defaultOverridableDelayableArgs and can be used when composing using
|
||||
# foldArgs, composedArgsAndFun or applyAndFun. Example: composableDerivation in all-packages.nix
|
||||
mergeAttrByFunc = x : y :
|
||||
let
|
||||
mergeAttrBy2 = { mergeAttrBy=lib.mergeAttrs; }
|
||||
// (maybeAttr "mergeAttrBy" {} x)
|
||||
// (maybeAttr "mergeAttrBy" {} y); in
|
||||
fold lib.mergeAttrs {} [
|
||||
x y
|
||||
(mapAttrs ( a : v : # merge special names using given functions
|
||||
if x ? ${a}
|
||||
then if y ? ${a}
|
||||
then v x.${a} y.${a} # both have attr, use merge func
|
||||
else x.${a} # only x has attr
|
||||
else y.${a} # only y has attr)
|
||||
) (removeAttrs mergeAttrBy2
|
||||
# don't merge attrs which are neither in x nor y
|
||||
(filter (a: ! x ? ${a} && ! y ? ${a})
|
||||
(attrNames mergeAttrBy2))
|
||||
)
|
||||
)
|
||||
];
|
||||
mergeAttrsByFuncDefaults = foldl mergeAttrByFunc { inherit mergeAttrBy; };
|
||||
mergeAttrsByFuncDefaultsClean = list: removeAttrs (mergeAttrsByFuncDefaults list) ["mergeAttrBy"];
|
||||
|
||||
# merge attrs based on version key into mkDerivation args, see mergeAttrBy to learn about smart merge defaults
|
||||
#
|
||||
# This function is best explained by an example:
|
||||
#
|
||||
# {version ? "2.x"} :
|
||||
#
|
||||
# mkDerivation (mergeAttrsByVersion "package-name" version
|
||||
# { # version specific settings
|
||||
# "git" = { src = ..; preConfigre = "autogen.sh"; buildInputs = [automake autoconf libtool]; };
|
||||
# "2.x" = { src = ..; };
|
||||
# }
|
||||
# { // shared settings
|
||||
# buildInputs = [ common build inputs ];
|
||||
# meta = { .. }
|
||||
# }
|
||||
# )
|
||||
#
|
||||
# Please note that e.g. Eelco Dolstra usually prefers having one file for
|
||||
# each version. On the other hand there are valuable additional design goals
|
||||
# - readability
|
||||
# - do it once only
|
||||
# - try to avoid duplication
|
||||
#
|
||||
# Marc Weber and Michael Raskin sometimes prefer keeping older
|
||||
# versions around for testing and regression tests - as long as its cheap to
|
||||
# do so.
|
||||
#
|
||||
# Very often it just happens that the "shared" code is the bigger part.
|
||||
# Then using this function might be appropriate.
|
||||
#
|
||||
# Be aware that its easy to cause recompilations in all versions when using
|
||||
# this function - also if derivations get too complex splitting into multiple
|
||||
# files is the way to go.
|
||||
#
|
||||
# See misc.nix -> versionedDerivation
|
||||
# discussion: nixpkgs: pull/310
|
||||
mergeAttrsByVersion = name: version: attrsByVersion: base:
|
||||
mergeAttrsByFuncDefaultsClean [ { name = "${name}-${version}"; } base (maybeAttr version (throw "bad version ${version} for ${name}") attrsByVersion)];
|
||||
|
||||
# sane defaults (same name as attr name so that inherit can be used)
|
||||
mergeAttrBy = # { buildInputs = concatList; [...]; passthru = mergeAttr; [..]; }
|
||||
listToAttrs (map (n : nameValuePair n lib.concat)
|
||||
[ "nativeBuildInputs" "buildInputs" "propagatedBuildInputs" "configureFlags" "prePhases" "postAll" "patches" ])
|
||||
// listToAttrs (map (n : nameValuePair n lib.mergeAttrs) [ "passthru" "meta" "cfg" "flags" ])
|
||||
// listToAttrs (map (n : nameValuePair n (a: b: "${a}\n${b}") ) [ "preConfigure" "postInstall" ])
|
||||
;
|
||||
|
||||
# prepareDerivationArgs tries to make writing configurable derivations easier
|
||||
# example:
|
||||
# prepareDerivationArgs {
|
||||
# mergeAttrBy = {
|
||||
# myScript = x : y : x ++ "\n" ++ y;
|
||||
# };
|
||||
# cfg = {
|
||||
# readlineSupport = true;
|
||||
# };
|
||||
# flags = {
|
||||
# readline = {
|
||||
# set = {
|
||||
# configureFlags = [ "--with-compiler=${compiler}" ];
|
||||
# buildInputs = [ compiler ];
|
||||
# pass = { inherit compiler; READLINE=1; };
|
||||
# assertion = compiler.dllSupport;
|
||||
# myScript = "foo";
|
||||
# };
|
||||
# unset = { configureFlags = ["--without-compiler"]; };
|
||||
# };
|
||||
# };
|
||||
# src = ...
|
||||
# buildPhase = '' ... '';
|
||||
# name = ...
|
||||
# myScript = "bar";
|
||||
# };
|
||||
# if you don't have need for unset you can omit the surrounding set = { .. } attr
|
||||
# all attrs except flags cfg and mergeAttrBy will be merged with the
|
||||
# additional data from flags depending on config settings
|
||||
# It's used in composableDerivation in all-packages.nix. It's also used
|
||||
# heavily in the new python and libs implementation
|
||||
#
|
||||
# should we check for misspelled cfg options?
|
||||
# TODO use args.mergeFun here as well?
|
||||
prepareDerivationArgs = args:
|
||||
let args2 = { cfg = {}; flags = {}; } // args;
|
||||
flagName = name : "${name}Support";
|
||||
cfgWithDefaults = (listToAttrs (map (n : nameValuePair (flagName n) false) (attrNames args2.flags)))
|
||||
// args2.cfg;
|
||||
opts = attrValues (mapAttrs (a : v :
|
||||
let v2 = if v ? set || v ? unset then v else { set = v; };
|
||||
n = if cfgWithDefaults.${flagName a} then "set" else "unset";
|
||||
attr = maybeAttr n {} v2; in
|
||||
if (maybeAttr "assertion" true attr)
|
||||
then attr
|
||||
else throw "assertion of flag ${a} of derivation ${args.name} failed"
|
||||
) args2.flags );
|
||||
in removeAttrs
|
||||
(mergeAttrsByFuncDefaults ([args] ++ opts ++ [{ passthru = cfgWithDefaults; }]))
|
||||
["flags" "cfg" "mergeAttrBy" ];
|
||||
|
||||
|
||||
nixType = x:
|
||||
if isAttrs x then
|
||||
if x ? outPath then "derivation"
|
||||
else "aattrs"
|
||||
else if isFunction x then "function"
|
||||
else if isList x then "list"
|
||||
else if x == true then "bool"
|
||||
else if x == false then "bool"
|
||||
else if x == null then "null"
|
||||
else if isInt x then "int"
|
||||
else "string";
|
||||
|
||||
}
|
||||
525
lib/licenses.nix
525
lib/licenses.nix
@@ -1,466 +1,263 @@
|
||||
let
|
||||
|
||||
lib = import ./default.nix;
|
||||
|
||||
spdx = lic: lic // {
|
||||
url = "http://spdx.org/licenses/${lic.spdxId}";
|
||||
};
|
||||
|
||||
in
|
||||
|
||||
lib.mapAttrs (n: v: v // { shortName = n; }) rec {
|
||||
/* License identifiers from spdx.org where possible.
|
||||
{
|
||||
/* License identifiers loosely based on: http://fedoraproject.org/wiki/Licensing
|
||||
* If you cannot find your license here, then look for a similar license or
|
||||
* add it to this list. The URL mentioned above is a good source for inspiration.
|
||||
*/
|
||||
|
||||
afl21 = spdx {
|
||||
spdxId = "AFL-2.1";
|
||||
fullName = "Academic Free License";
|
||||
artistic2 = {
|
||||
shortName = "Artistic 2.0";
|
||||
fullName = "Artistic 2.0";
|
||||
url = "http://opensource.org/licenses/artistic-license-2.0.php";
|
||||
};
|
||||
|
||||
agpl3 = spdx {
|
||||
spdxId = "AGPL-3.0";
|
||||
fullName = "GNU Affero General Public License v3.0";
|
||||
agpl3 = {
|
||||
shortName = "AGPLv3";
|
||||
fullName = "GNU Affero General Public License version 3 only";
|
||||
url = https://www.gnu.org/licenses/agpl.html;
|
||||
};
|
||||
|
||||
agpl3Plus = {
|
||||
fullName = "GNU Affero General Public License v3.0 or later";
|
||||
inherit (agpl3) url;
|
||||
};
|
||||
|
||||
amazonsl = {
|
||||
fullName = "Amazon Software License";
|
||||
url = http://aws.amazon.com/asl/;
|
||||
free = false;
|
||||
shortName = "AGPLv3+";
|
||||
fullName = "GNU Affero General Public License version 3 or later";
|
||||
url = https://www.gnu.org/licenses/agpl.html;
|
||||
};
|
||||
|
||||
amd = {
|
||||
shortName = "amd";
|
||||
fullName = "AMD License Agreement";
|
||||
url = http://developer.amd.com/amd-license-agreement/;
|
||||
};
|
||||
};#
|
||||
|
||||
apsl20 = spdx {
|
||||
spdxId = "APSL-2.0";
|
||||
apsl20 = {
|
||||
shortName = "APSL 2.0";
|
||||
fullName = "Apple Public Source License 2.0";
|
||||
url = http://opensource.org/licenses/APSL-2.0;
|
||||
};
|
||||
|
||||
artistic1 = spdx {
|
||||
spdxId = "Artistic-1.0";
|
||||
fullName = "Artistic License 1.0";
|
||||
asl20 = {
|
||||
shortName = "ASL2.0";
|
||||
fullName = "Apache Software License 2.0";
|
||||
url = http://www.apache.org/licenses/LICENSE-2.0;
|
||||
};
|
||||
|
||||
artistic2 = spdx {
|
||||
spdxId = "Artistic-2.0";
|
||||
fullName = "Artistic License 2.0";
|
||||
boost = {
|
||||
shortName = "boost";
|
||||
fullName = "Boost Software License";
|
||||
url = http://www.boost.org/LICENSE_1_0.txt;
|
||||
};
|
||||
|
||||
asl20 = spdx {
|
||||
spdxId = "Apache-2.0";
|
||||
fullName = "Apache License 2.0";
|
||||
bsd2 = {
|
||||
shortName = "BSD-2";
|
||||
fullName = "BSD license (2 clause)";
|
||||
url = http://opensource.org/licenses/BSD-2-Clause;
|
||||
};
|
||||
|
||||
boost = spdx {
|
||||
spdxId = "BSL-1.0";
|
||||
fullName = "Boost Software License 1.0";
|
||||
bsd3 = {
|
||||
shortName = "BSD-3";
|
||||
fullName = "BSD license (3 clause)";
|
||||
url = http://opensource.org/licenses/BSD-3-Clause;
|
||||
};
|
||||
|
||||
bsd2 = spdx {
|
||||
spdxId = "BSD-2-Clause";
|
||||
fullName = ''BSD 2-clause "Simplified" License'';
|
||||
bsdOriginal = {
|
||||
shortName = "BSD-original";
|
||||
fullName = "Original BSD license with advertising clause";
|
||||
url = https://fedoraproject.org/wiki/Licensing/BSD;
|
||||
};
|
||||
|
||||
bsd3 = spdx {
|
||||
spdxId = "BSD-3-Clause";
|
||||
fullName = ''BSD 3-clause "New" or "Revised" License'';
|
||||
};
|
||||
|
||||
bsdOriginal = spdx {
|
||||
spdxId = "BSD-4-Clause";
|
||||
fullName = ''BSD 4-clause "Original" or "Old" License'';
|
||||
};
|
||||
|
||||
cc0 = spdx {
|
||||
spdxId = "CC0-1.0";
|
||||
fullName = "Creative Commons Zero v1.0 Universal";
|
||||
};
|
||||
|
||||
cc-by-sa-25 = spdx {
|
||||
spdxId = "CC-BY-SA-2.5";
|
||||
fullName = "Creative Commons Attribution Share Alike 2.5";
|
||||
};
|
||||
|
||||
cc-by-30 = spdx {
|
||||
spdxId = "CC-BY-3.0";
|
||||
cc-by-30 = {
|
||||
shortName = "CC BY 3.0";
|
||||
fullName = "Creative Commons Attribution 3.0";
|
||||
url = http://creativecommons.org/licenses/by/3.0;
|
||||
};
|
||||
|
||||
cc-by-sa-30 = spdx {
|
||||
spdxId = "CC-BY-SA-3.0";
|
||||
fullName = "Creative Commons Attribution Share Alike 3.0";
|
||||
cddl = {
|
||||
shortName = "CDDL";
|
||||
fullName = "Common Development Distribution License ";
|
||||
url = http://www.opensolaris.org/os/licensing/cddllicense.txt;
|
||||
};
|
||||
|
||||
cc-by-40 = spdx {
|
||||
spdxId = "CC-BY-4.0";
|
||||
fullName = "Creative Commons Attribution 4.0";
|
||||
cpl10 = {
|
||||
shortName = "CPL 1.0";
|
||||
fullName = "Common Public License version 1.0";
|
||||
url = http://www.eclipse.org/legal/cpl-v10.html;
|
||||
};
|
||||
|
||||
cc-by-sa-40 = spdx {
|
||||
spdxId = "CC-BY-SA-4.0";
|
||||
fullName = "Creative Commons Attribution Share Alike 4.0";
|
||||
epl10 = {
|
||||
shortName = "EPL 1.0";
|
||||
fullName = "Eclipse Public License version 1.0";
|
||||
url = http://www.eclipse.org/legal/epl-v10.html;
|
||||
};
|
||||
|
||||
cddl = spdx {
|
||||
spdxId = "CDDL-1.0";
|
||||
fullName = "Common Development and Distribution License 1.0";
|
||||
};
|
||||
|
||||
cecill20 = spdx {
|
||||
spdxId = "CECILL-2.0";
|
||||
fullName = "CeCILL Free Software License Agreement v2.0";
|
||||
};
|
||||
|
||||
cecill-b = spdx {
|
||||
spdxId = "CECILL-B";
|
||||
fullName = "CeCILL-B Free Software License Agreement";
|
||||
};
|
||||
|
||||
cecill-c = spdx {
|
||||
spdxId = "CECILL-C";
|
||||
fullName = "CeCILL-C Free Software License Agreement";
|
||||
};
|
||||
|
||||
cpl10 = spdx {
|
||||
spdxId = "CPL-1.0";
|
||||
fullName = "Common Public License 1.0";
|
||||
};
|
||||
|
||||
efl10 = spdx {
|
||||
spdxId = "EFL-1.0";
|
||||
fullName = "Eiffel Forum License v1.0";
|
||||
};
|
||||
|
||||
efl20 = spdx {
|
||||
spdxId = "EFL-2.0";
|
||||
fullName = "Eiffel Forum License v2.0";
|
||||
};
|
||||
|
||||
epl10 = spdx {
|
||||
spdxId = "EPL-1.0";
|
||||
fullName = "Eclipse Public License 1.0";
|
||||
};
|
||||
|
||||
fdl12 = spdx {
|
||||
spdxId = "GFDL-1.2";
|
||||
fullName = "GNU Free Documentation License v1.2";
|
||||
};
|
||||
|
||||
fdl13 = spdx {
|
||||
spdxId = "GFDL-1.3";
|
||||
fullName = "GNU Free Documentation License v1.2";
|
||||
};
|
||||
|
||||
free = {
|
||||
fullName = "Unspecified free software license";
|
||||
};
|
||||
|
||||
gpl1 = spdx {
|
||||
spdxId = "GPL-1.0";
|
||||
fullName = "GNU General Public License v1.0 only";
|
||||
};
|
||||
|
||||
gpl1Plus = spdx {
|
||||
spdxId = "GPL-1.0+";
|
||||
fullName = "GNU General Public License v1.0 or later";
|
||||
};
|
||||
|
||||
gpl2 = spdx {
|
||||
spdxId = "GPL-2.0";
|
||||
fullName = "GNU General Public License v2.0 only";
|
||||
};
|
||||
|
||||
gpl2ClasspathPlus = {
|
||||
fullName = "GNU General Public License v2.0 or later (with Classpath exception)";
|
||||
url = https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception;
|
||||
gpl2 = {
|
||||
shortName = "GPLv2";
|
||||
fullName = "GNU General Public License version 2";
|
||||
url = http://www.gnu.org/licenses/old-licenses/gpl-2.0.html;
|
||||
};
|
||||
|
||||
gpl2Oss = {
|
||||
shortName = "GPLv2+OSS";
|
||||
fullName = "GNU General Public License version 2 only (with OSI approved licenses linking exception)";
|
||||
url = http://www.mysql.com/about/legal/licensing/foss-exception;
|
||||
};
|
||||
|
||||
gpl2Plus = spdx {
|
||||
spdxId = "GPL-2.0+";
|
||||
fullName = "GNU General Public License v2.0 or later";
|
||||
gpl2Plus = {
|
||||
shortName = "GPLv2+";
|
||||
fullName = "GNU General Public License version 2 or later";
|
||||
url = http://www.gnu.org/licenses/old-licenses/gpl-2.0.html;
|
||||
};
|
||||
|
||||
gpl3 = spdx {
|
||||
spdxId = "GPL-3.0";
|
||||
fullName = "GNU General Public License v3.0 only";
|
||||
gpl3 = {
|
||||
shortName = "GPLv3";
|
||||
fullName = "GNU General Public License version 3 only";
|
||||
url = http://www.fsf.org/licensing/licenses/gpl.html;
|
||||
};
|
||||
|
||||
gpl3Plus = spdx {
|
||||
spdxId = "GPL-3.0+";
|
||||
fullName = "GNU General Public License v3.0 or later";
|
||||
gpl3Plus = {
|
||||
shortName = "GPLv3+";
|
||||
fullName = "GNU General Public License version 3 or later";
|
||||
url = http://www.fsf.org/licensing/licenses/gpl.html;
|
||||
};
|
||||
|
||||
gpl3ClasspathPlus = {
|
||||
fullName = "GNU General Public License v3.0 or later (with Classpath exception)";
|
||||
shortName = "GPLv3+classpath+";
|
||||
fullName = "GNU General Public License version 3 or later (with Classpath exception)";
|
||||
url = https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception;
|
||||
};
|
||||
|
||||
# Intel's license, seems free
|
||||
iasl = {
|
||||
fullName = "iASL";
|
||||
url = http://www.calculate-linux.org/packages/licenses/iASL;
|
||||
isc = {
|
||||
shortName = "ISC";
|
||||
fullName = "Internet Systems Consortium License";
|
||||
url = http://www.opensource.org/licenses/ISC;
|
||||
};
|
||||
|
||||
ijg = spdx {
|
||||
spdxId = "IJG";
|
||||
ipl10 = {
|
||||
shortName = "IPL 1.0";
|
||||
fullName = "IBM Public License Version 1.0";
|
||||
url = http://www.ibm.com/developerworks/opensource/library/os-i18n2/os-ipl.html;
|
||||
};
|
||||
|
||||
ijg = {
|
||||
shortName = "IJG";
|
||||
fullName = "Independent JPEG Group License";
|
||||
url = https://fedoraproject.org/wiki/Licensing/IJG;
|
||||
};
|
||||
|
||||
inria = {
|
||||
fullName = "INRIA Non-Commercial License Agreement";
|
||||
url = "http://compcert.inria.fr/doc/LICENSE";
|
||||
libtiff = {
|
||||
shortName = "libtiff";
|
||||
fullName = "libtiff license";
|
||||
url = https://fedoraproject.org/wiki/Licensing/libtiff;
|
||||
};
|
||||
|
||||
ipa = spdx {
|
||||
spdxId = "IPA";
|
||||
fullName = "IPA Font License";
|
||||
lgpl2 = {
|
||||
shortName = "LGPLv2";
|
||||
fullName = "GNU Library General Public License version 2";
|
||||
url = http://www.gnu.org/licenses/old-licenses/lgpl-2.0.html;
|
||||
};
|
||||
|
||||
ipl10 = spdx {
|
||||
spdxId = "IPL-1.0";
|
||||
fullName = "IBM Public License v1.0";
|
||||
lgpl2Plus = {
|
||||
shortName = "LGPLv2+";
|
||||
fullName = "GNU Library General Public License version 2 or later";
|
||||
url = http://www.gnu.org/licenses/old-licenses/lgpl-2.0.html;
|
||||
};
|
||||
|
||||
isc = spdx {
|
||||
spdxId = "ISC";
|
||||
fullName = "ISC License";
|
||||
lgpl21 = {
|
||||
shortName = "LGPLv2.1";
|
||||
fullName = "GNU Lesser General Public License version 2.1";
|
||||
url = http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html;
|
||||
};
|
||||
|
||||
lgpl2 = spdx {
|
||||
spdxId = "LGPL-2.0";
|
||||
fullName = "GNU Library General Public License v2 only";
|
||||
};
|
||||
|
||||
lgpl2Plus = spdx {
|
||||
spdxId = "LGPL-2.0+";
|
||||
fullName = "GNU Library General Public License v2 or later";
|
||||
};
|
||||
|
||||
lgpl21 = spdx {
|
||||
spdxId = "LGPL-2.1";
|
||||
fullName = "GNU Library General Public License v2.1 only";
|
||||
};
|
||||
|
||||
lgpl21Plus = spdx {
|
||||
spdxId = "LGPL-2.1+";
|
||||
fullName = "GNU Library General Public License v2.1 or later";
|
||||
};
|
||||
|
||||
lgpl3 = spdx {
|
||||
spdxId = "LGPL-3.0";
|
||||
fullName = "GNU Lesser General Public License v3.0 only";
|
||||
};
|
||||
|
||||
lgpl3Plus = spdx {
|
||||
spdxId = "LGPL-3.0+";
|
||||
fullName = "GNU Lesser General Public License v3.0 or later";
|
||||
};
|
||||
|
||||
libpng = spdx {
|
||||
spdxId = "Libpng";
|
||||
fullName = "libpng License";
|
||||
};
|
||||
|
||||
libtiff = spdx {
|
||||
spdxId = "libtiff";
|
||||
fullName = "libtiff License";
|
||||
lgpl21Plus = {
|
||||
shortName = "LGPLv2.1+";
|
||||
fullName = "GNU Lesser General Public License version 2.1 or later";
|
||||
url = http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html;
|
||||
};
|
||||
|
||||
llgpl21 = {
|
||||
shortName = "LLGPLv2.1";
|
||||
fullName = "Lisp LGPL; GNU Lesser General Public License version 2.1 with Franz Inc. preamble for clarification of LGPL terms in context of Lisp";
|
||||
url = http://opensource.franz.com/preamble.html;
|
||||
};
|
||||
|
||||
lppl12 = spdx {
|
||||
spdxId = "LPPL-1.2";
|
||||
fullName = "LaTeX Project Public License v1.2";
|
||||
lgpl3 = {
|
||||
shortName = "LGPLv3";
|
||||
fullName = "GNU Lesser General Public License version 3 only";
|
||||
url = http://www.fsf.org/licensing/licenses/lgpl.html;
|
||||
};
|
||||
|
||||
lppl13c = spdx {
|
||||
spdxId = "LPPL-1.3c";
|
||||
fullName = "LaTeX Project Public License v1.3c";
|
||||
lgpl3Plus = {
|
||||
shortName = "LGPLv3+";
|
||||
fullName = "GNU Lesser General Public License version 3 or later";
|
||||
url = http://www.fsf.org/licensing/licenses/lgpl.html;
|
||||
};
|
||||
|
||||
lpl-102 = spdx {
|
||||
spdxId = "LPL-1.02";
|
||||
fullName = "Lucent Public License v1.02";
|
||||
mit = {
|
||||
shortName = "MIT";
|
||||
fullName = "MIT/X11 license";
|
||||
url = http://www.opensource.org/licenses/mit-license.php;
|
||||
};
|
||||
|
||||
# spdx.org does not (yet) differentiate between the X11 and Expat versions
|
||||
# for details see http://en.wikipedia.org/wiki/MIT_License#Various_versions
|
||||
mit = spdx {
|
||||
spdxId = "MIT";
|
||||
fullName = "MIT License";
|
||||
mpl11 = {
|
||||
shortName = "MPL1.1";
|
||||
fullName = "Mozilla Public License version 1.1";
|
||||
url = http://www.mozilla.org/MPL/MPL-1.1.html;
|
||||
};
|
||||
|
||||
mpl10 = spdx {
|
||||
spdxId = "MPL-1.0";
|
||||
fullName = "Mozilla Public License 1.0";
|
||||
mpl20 = {
|
||||
shortName = "MPL2.0";
|
||||
fullName = "Mozilla Public License version 2.0";
|
||||
url = https://www.mozilla.org/MPL/2.0;
|
||||
};
|
||||
|
||||
mpl11 = spdx {
|
||||
spdxId = "MPL-1.1";
|
||||
fullName = "Mozilla Public License 1.1";
|
||||
};
|
||||
|
||||
mpl20 = spdx {
|
||||
spdxId = "MPL-2.0";
|
||||
fullName = "Mozilla Public License 2.0";
|
||||
};
|
||||
|
||||
msrla = {
|
||||
fullName = "Microsoft Research License Agreement";
|
||||
url = "http://research.microsoft.com/en-us/projects/pex/msr-la.txt";
|
||||
};
|
||||
|
||||
ncsa = spdx {
|
||||
spdxId = "NCSA";
|
||||
fullName = "University of Illinois/NCSA Open Source License";
|
||||
};
|
||||
|
||||
notion_lgpl = {
|
||||
url = "https://raw.githubusercontent.com/raboof/notion/master/LICENSE";
|
||||
fullName = "Notion modified LGPL";
|
||||
};
|
||||
|
||||
ofl = spdx {
|
||||
spdxId = "OFL-1.1";
|
||||
fullName = "SIL Open Font License 1.1";
|
||||
};
|
||||
|
||||
openldap = spdx {
|
||||
spdxId = "OLDAP-2.8";
|
||||
fullName = "Open LDAP Public License v2.8";
|
||||
};
|
||||
|
||||
openssl = spdx {
|
||||
spdxId = "OpenSSL";
|
||||
fullName = "OpenSSL License";
|
||||
};
|
||||
|
||||
php301 = spdx {
|
||||
spdxId = "PHP-3.01";
|
||||
fullName = "PHP License v3.01";
|
||||
};
|
||||
|
||||
postgresql = spdx {
|
||||
spdxId = "PostgreSQL";
|
||||
fullName = "PostgreSQL License";
|
||||
};
|
||||
|
||||
psfl = spdx {
|
||||
spdxId = "Python-2.0";
|
||||
fullName = "Python Software Foundation License version 2";
|
||||
#url = http://docs.python.org/license.html;
|
||||
openssl = {
|
||||
shortName = "openssl";
|
||||
fullName = "OpenSSL license";
|
||||
url = http://www.openssl.org/source/license.html;
|
||||
};
|
||||
|
||||
publicDomain = {
|
||||
fullName = "Public Domain";
|
||||
shortName = "Public Domain";
|
||||
fullname = "Public Domain";
|
||||
};
|
||||
|
||||
qpl = spdx {
|
||||
spdxId = "QPL-1.0";
|
||||
fullName = "Q Public License 1.0";
|
||||
psfl = {
|
||||
shortName = "PSFL";
|
||||
fullName = "Python Software Foundation License";
|
||||
url = http://docs.python.org/license.html;
|
||||
};
|
||||
|
||||
qwt = {
|
||||
fullName = "Qwt License, Version 1.0";
|
||||
url = http://qwt.sourceforge.net/qwtlicense.html;
|
||||
tcltk = {
|
||||
shortName = "Tcl/Tk";
|
||||
fullName = "Tcl/Tk license";
|
||||
url = http://www.tcl.tk/software/tcltk/license.html;
|
||||
};
|
||||
|
||||
ruby = spdx {
|
||||
spdxId = "Ruby";
|
||||
fullName = "Ruby License";
|
||||
unfree = "unfree";
|
||||
|
||||
unfreeRedistributable = "unfree-redistributable";
|
||||
|
||||
unfreeRedistributableFirmware = "unfree-redistributable-firmware";
|
||||
|
||||
zlib = {
|
||||
shortName = "zlib";
|
||||
fullName = "zlib license";
|
||||
url = http://www.gzip.org/zlib/zlib_license.html;
|
||||
};
|
||||
|
||||
sgi-b-20 = spdx {
|
||||
spdxId = "SGI-B-2.0";
|
||||
fullName = "SGI Free Software License B v2.0";
|
||||
};
|
||||
|
||||
sleepycat = spdx {
|
||||
spdxId = "Sleepycat";
|
||||
fullName = "Sleepycat License";
|
||||
};
|
||||
|
||||
tcltk = spdx {
|
||||
spdxId = "TCL";
|
||||
fullName = "TCL/TK License";
|
||||
};
|
||||
|
||||
unfree = {
|
||||
fullName = "Unfree";
|
||||
free = false;
|
||||
};
|
||||
|
||||
unfreeRedistributable = {
|
||||
fullName = "Unfree redistributable";
|
||||
free = false;
|
||||
};
|
||||
|
||||
unfreeRedistributableFirmware = {
|
||||
fullName = "Unfree redistributable firmware";
|
||||
# Note: we currently consider these "free" for inclusion in the
|
||||
# channel and NixOS images.
|
||||
};
|
||||
|
||||
unlicense = spdx {
|
||||
spdxId = "Unlicense";
|
||||
fullName = "The Unlicense";
|
||||
};
|
||||
|
||||
vim = spdx {
|
||||
spdxId = "Vim";
|
||||
fullName = "Vim License";
|
||||
};
|
||||
|
||||
vsl10 = spdx {
|
||||
spdxId = "VSL-1.0";
|
||||
fullName = "Vovida Software License v1.0";
|
||||
};
|
||||
|
||||
w3c = spdx {
|
||||
spdxId = "W3C";
|
||||
fullName = "W3C Software Notice and License";
|
||||
};
|
||||
|
||||
wadalab = {
|
||||
fullName = "Wadalab Font License";
|
||||
url = https://fedoraproject.org/wiki/Licensing:Wadalab?rd=Licensing/Wadalab;
|
||||
};
|
||||
|
||||
wtfpl = spdx {
|
||||
spdxId = "WTFPL";
|
||||
fullName = "Do What The F*ck You Want To Public License";
|
||||
};
|
||||
|
||||
zlib = spdx {
|
||||
spdxId = "Zlib";
|
||||
fullName = "zlib License";
|
||||
};
|
||||
|
||||
zpt20 = spdx { # FIXME: why zpt* instead of zpl*
|
||||
spdxId = "ZPL-2.0";
|
||||
zpt20 = {
|
||||
shortName = "ZPT2.0";
|
||||
fullName = "Zope Public License 2.0";
|
||||
url = "http://old.zope.org/Resources/License/ZPL-2.0";
|
||||
};
|
||||
|
||||
zpt21 = spdx {
|
||||
spdxId = "ZPL-2.1";
|
||||
zpt21 = {
|
||||
shortName = "ZPT2.1";
|
||||
fullName = "Zope Public License 2.1";
|
||||
url = "http://old.zope.org/Resources/License/ZPL-2.1";
|
||||
};
|
||||
|
||||
sleepycat = {
|
||||
shortName = "Sleepycat";
|
||||
fullName = "Sleepycat Public License";
|
||||
url = "https://en.wikipedia.org/wiki/Sleepycat_License";
|
||||
};
|
||||
}
|
||||
|
||||
203
lib/lists.nix
203
lib/lists.nix
@@ -2,9 +2,15 @@
|
||||
|
||||
with import ./trivial.nix;
|
||||
|
||||
rec {
|
||||
let
|
||||
|
||||
inherit (builtins) head tail length isList elemAt concatLists filter elem genList;
|
||||
inc = builtins.add 1;
|
||||
|
||||
dec = n: builtins.sub n 1;
|
||||
|
||||
in rec {
|
||||
|
||||
inherit (builtins) head tail length isList elemAt concatLists filter elem;
|
||||
|
||||
|
||||
# Create a list consisting of a single element. `singleton x' is
|
||||
@@ -23,7 +29,7 @@ rec {
|
||||
fold' = n:
|
||||
if n == len
|
||||
then nul
|
||||
else op (elemAt list n) (fold' (n + 1));
|
||||
else op (elemAt list n) (fold' (inc n));
|
||||
in fold' 0;
|
||||
|
||||
# Left fold: `fold op nul [x_1 x_2 ... x_n] == op (... (op (op nul
|
||||
@@ -32,30 +38,24 @@ rec {
|
||||
let
|
||||
len = length list;
|
||||
foldl' = n:
|
||||
if n == -1
|
||||
if n == minus1
|
||||
then nul
|
||||
else op (foldl' (n - 1)) (elemAt list n);
|
||||
in foldl' (length list - 1);
|
||||
else op (foldl' (dec n)) (elemAt list n);
|
||||
in foldl' (dec (length list));
|
||||
|
||||
minus1 = dec 0;
|
||||
|
||||
|
||||
# Strict version of foldl.
|
||||
foldl' = builtins.foldl' or foldl;
|
||||
|
||||
|
||||
# Map with index: `imap (i: v: "${v}-${toString i}") ["a" "b"] ==
|
||||
# ["a-1" "b-2"]'. FIXME: why does this start to count at 1?
|
||||
imap =
|
||||
if builtins ? genList then
|
||||
f: list: genList (n: f (n + 1) (elemAt list n)) (length list)
|
||||
else
|
||||
f: list:
|
||||
let
|
||||
len = length list;
|
||||
imap' = n:
|
||||
if n == len
|
||||
then []
|
||||
else [ (f (n + 1) (elemAt list n)) ] ++ imap' (n + 1);
|
||||
in imap' 0;
|
||||
# map with index: `imap (i: v: "${v}-${toString i}") ["a" "b"] ==
|
||||
# ["a-1" "b-2"]'
|
||||
imap = f: list:
|
||||
let
|
||||
len = length list;
|
||||
imap' = n:
|
||||
if n == len
|
||||
then []
|
||||
else [ (f (inc n) (elemAt list n)) ] ++ imap' (inc n);
|
||||
in imap' 0;
|
||||
|
||||
|
||||
# Map and concatenate the result.
|
||||
@@ -67,7 +67,7 @@ rec {
|
||||
# == [1 2 3 4 5]' and `flatten 1 == [1]'.
|
||||
flatten = x:
|
||||
if isList x
|
||||
then foldl' (x: y: x ++ (flatten y)) [] x
|
||||
then fold (x: y: (flatten x) ++ y) [] x
|
||||
else [x];
|
||||
|
||||
|
||||
@@ -94,17 +94,17 @@ rec {
|
||||
|
||||
# Return true iff function `pred' returns true for at least element
|
||||
# of `list'.
|
||||
any = builtins.any or (pred: fold (x: y: if pred x then true else y) false);
|
||||
any = pred: fold (x: y: if pred x then true else y) false;
|
||||
|
||||
|
||||
# Return true iff function `pred' returns true for all elements of
|
||||
# `list'.
|
||||
all = builtins.all or (pred: fold (x: y: if pred x then y else false) true);
|
||||
all = pred: fold (x: y: if pred x then y else false) true;
|
||||
|
||||
|
||||
# Count how many times function `pred' returns true for the elements
|
||||
# of `list'.
|
||||
count = pred: foldl' (c: x: if pred x then c + 1 else c) 0;
|
||||
count = pred: fold (x: c: if pred x then inc c else c) 0;
|
||||
|
||||
|
||||
# Return a singleton list or an empty list, depending on a boolean
|
||||
@@ -124,17 +124,10 @@ rec {
|
||||
|
||||
|
||||
# Return a list of integers from `first' up to and including `last'.
|
||||
range =
|
||||
if builtins ? genList then
|
||||
first: last:
|
||||
if first > last
|
||||
then []
|
||||
else genList (n: first + n) (last - first + 1)
|
||||
else
|
||||
first: last:
|
||||
if last < first
|
||||
then []
|
||||
else [first] ++ range (first + 1) last;
|
||||
range = first: last:
|
||||
if lessThan last first
|
||||
then []
|
||||
else [first] ++ range (add first 1) last;
|
||||
|
||||
|
||||
# Partition the elements of a list in two lists, `right' and
|
||||
@@ -147,41 +140,34 @@ rec {
|
||||
) { right = []; wrong = []; };
|
||||
|
||||
|
||||
zipListsWith =
|
||||
if builtins ? genList then
|
||||
f: fst: snd: genList (n: f (elemAt fst n) (elemAt snd n)) (min (length fst) (length snd))
|
||||
else
|
||||
f: fst: snd:
|
||||
let
|
||||
len = min (length fst) (length snd);
|
||||
zipListsWith' = n:
|
||||
if n != len then
|
||||
[ (f (elemAt fst n) (elemAt snd n)) ]
|
||||
++ zipListsWith' (n + 1)
|
||||
else [];
|
||||
in zipListsWith' 0;
|
||||
zipListsWith = f: fst: snd:
|
||||
let
|
||||
len1 = length fst;
|
||||
len2 = length snd;
|
||||
len = if lessThan len1 len2 then len1 else len2;
|
||||
zipListsWith' = n:
|
||||
if n != len then
|
||||
[ (f (elemAt fst n) (elemAt snd n)) ]
|
||||
++ zipListsWith' (inc n)
|
||||
else [];
|
||||
in zipListsWith' 0;
|
||||
|
||||
zipLists = zipListsWith (fst: snd: { inherit fst snd; });
|
||||
|
||||
|
||||
# Reverse the order of the elements of a list.
|
||||
reverseList =
|
||||
if builtins ? genList then
|
||||
xs: let l = length xs; in genList (n: elemAt xs (l - n - 1)) l
|
||||
else
|
||||
fold (e: acc: acc ++ [ e ]) [];
|
||||
# Reverse the order of the elements of a list. FIXME: O(n^2)!
|
||||
reverseList = fold (e: acc: acc ++ [ e ]) [];
|
||||
|
||||
|
||||
# Sort a list based on a comparator function which compares two
|
||||
# elements and returns true if the first argument is strictly below
|
||||
# the second argument. The returned list is sorted in an increasing
|
||||
# order. The implementation does a quick-sort.
|
||||
sort = builtins.sort or (
|
||||
strictLess: list:
|
||||
sort = strictLess: list:
|
||||
let
|
||||
len = length list;
|
||||
first = head list;
|
||||
pivot' = n: acc@{ left, right }: let el = elemAt list n; next = pivot' (n + 1); in
|
||||
pivot' = n: acc@{ left, right }: let el = elemAt list n; next = pivot' (inc n); in
|
||||
if n == len
|
||||
then acc
|
||||
else if strictLess first el
|
||||
@@ -190,84 +176,55 @@ rec {
|
||||
next { left = [ el ] ++ left; inherit right; };
|
||||
pivot = pivot' 1 { left = []; right = []; };
|
||||
in
|
||||
if len < 2 then list
|
||||
else (sort strictLess pivot.left) ++ [ first ] ++ (sort strictLess pivot.right));
|
||||
if lessThan len 2 then list
|
||||
else (sort strictLess pivot.left) ++ [ first ] ++ (sort strictLess pivot.right);
|
||||
|
||||
|
||||
# Return the first (at most) N elements of a list.
|
||||
take =
|
||||
if builtins ? genList then
|
||||
count: sublist 0 count
|
||||
else
|
||||
count: list:
|
||||
let
|
||||
len = length list;
|
||||
take' = n:
|
||||
if n == len || n == count
|
||||
then []
|
||||
else
|
||||
[ (elemAt list n) ] ++ take' (n + 1);
|
||||
in take' 0;
|
||||
take = count: list:
|
||||
let
|
||||
len = length list;
|
||||
take' = n:
|
||||
if n == len || n == count
|
||||
then []
|
||||
else
|
||||
[ (elemAt list n) ] ++ take' (inc n);
|
||||
in take' 0;
|
||||
|
||||
|
||||
# Remove the first (at most) N elements of a list.
|
||||
drop =
|
||||
if builtins ? genList then
|
||||
count: list: sublist count (length list) list
|
||||
else
|
||||
count: list:
|
||||
let
|
||||
len = length list;
|
||||
drop' = n:
|
||||
if n == -1 || n < count
|
||||
then []
|
||||
else
|
||||
drop' (n - 1) ++ [ (elemAt list n) ];
|
||||
in drop' (len - 1);
|
||||
|
||||
|
||||
# Return a list consisting of at most ‘count’ elements of ‘list’,
|
||||
# starting at index ‘start’.
|
||||
sublist = start: count: list:
|
||||
let len = length list; in
|
||||
genList
|
||||
(n: elemAt list (n + start))
|
||||
(if start >= len then 0
|
||||
else if start + count > len then len - start
|
||||
else count);
|
||||
drop = count: list:
|
||||
let
|
||||
len = length list;
|
||||
drop' = n:
|
||||
if n == minus1 || lessThan n count
|
||||
then []
|
||||
else
|
||||
drop' (dec n) ++ [ (elemAt list n) ];
|
||||
in drop' (dec len);
|
||||
|
||||
|
||||
# Return the last element of a list.
|
||||
last = list:
|
||||
assert list != []; elemAt list (length list - 1);
|
||||
assert list != []; elemAt list (dec (length list));
|
||||
|
||||
|
||||
# Return all elements but the last
|
||||
init = list: assert list != []; take (length list - 1) list;
|
||||
# Zip two lists together.
|
||||
zipTwoLists = xs: ys:
|
||||
let
|
||||
len1 = length xs;
|
||||
len2 = length ys;
|
||||
len = if lessThan len1 len2 then len1 else len2;
|
||||
zipTwoLists' = n:
|
||||
if n != len then
|
||||
[ { first = elemAt xs n; second = elemAt ys n; } ]
|
||||
++ zipTwoLists' (inc n)
|
||||
else [];
|
||||
in zipTwoLists' 0;
|
||||
|
||||
|
||||
deepSeqList = xs: y: if any (x: deepSeq x false) xs then y else y;
|
||||
|
||||
|
||||
crossLists = f: foldl (fs: args: concatMap (f: map f args) fs) [f];
|
||||
|
||||
|
||||
# Remove duplicate elements from the list. O(n^2) complexity.
|
||||
unique = list:
|
||||
if list == [] then
|
||||
[]
|
||||
else
|
||||
let
|
||||
x = head list;
|
||||
xs = unique (drop 1 list);
|
||||
in [x] ++ remove x xs;
|
||||
|
||||
|
||||
# Intersects list 'e' and another list. O(nm) complexity.
|
||||
intersectLists = e: filter (x: elem x e);
|
||||
|
||||
|
||||
# Subtracts list 'e' from another list. O(nm) complexity.
|
||||
subtractLists = e: filter (x: !(elem x e));
|
||||
|
||||
}
|
||||
|
||||
@@ -1,307 +1,101 @@
|
||||
/* -*- coding: utf-8; -*- */
|
||||
|
||||
{
|
||||
/* Add your name and email address here.
|
||||
Keep the list alphabetically sorted.
|
||||
Prefer the same attrname as your github username, please,
|
||||
so it's easy to ping a package @maintainer.
|
||||
*/
|
||||
/* Add your name and email address here. Keep the list
|
||||
alphabetically sorted. */
|
||||
|
||||
a1russell = "Adam Russell <adamlr6+pub@gmail.com>";
|
||||
abaldeau = "Andreas Baldeau <andreas@baldeau.net>";
|
||||
abbradar = "Nikolay Amiantov <ab@fmap.me>";
|
||||
adev = "Adrien Devresse <adev@adev.name>";
|
||||
_1126 = "Christian Lask <mail@elfsechsundzwanzig.de>";
|
||||
aforemny = "Alexander Foremny <alexanderforemny@googlemail.com>";
|
||||
aflatter = "Alexander Flatter <flatter@fastmail.fm>";
|
||||
aherrmann = "Andreas Herrmann <andreash87@gmx.ch>";
|
||||
ak = "Alexander Kjeldaas <ak@formalprivacy.com>";
|
||||
akaWolf = "Artjom Vejsel <akawolf0@gmail.com>";
|
||||
akc = "Anders Claesson <akc@akc.is>";
|
||||
algorith = "Dries Van Daele <dries_van_daele@telenet.be>";
|
||||
all = "Nix Committers <nix-commits@lists.science.uu.nl>";
|
||||
ambrop72 = "Ambroz Bizjak <ambrop7@gmail.com>";
|
||||
amiddelk = "Arie Middelkoop <amiddelk@gmail.com>";
|
||||
amorsillo = "Andrew Morsillo <andrew.morsillo@gmail.com>";
|
||||
AndersonTorres = "Anderson Torres <torres.anderson.85@gmail.com>";
|
||||
anderspapitto = "Anders Papitto <anderspapitto@gmail.com>";
|
||||
andres = "Andres Loeh <ksnixos@andres-loeh.de>";
|
||||
andrewrk = "Andrew Kelley <superjoe30@gmail.com>";
|
||||
antono = "Antono Vasiljev <self@antono.info>";
|
||||
ardumont = "Antoine R. Dumont <eniotna.t@gmail.com>";
|
||||
aristid = "Aristid Breitkreuz <aristidb@gmail.com>";
|
||||
arobyn = "Alexei Robyn <shados@shados.net>";
|
||||
asppsa = "Alastair Pharo <asppsa@gmail.com>";
|
||||
astsmtl = "Alexander Tsamutali <astsmtl@yandex.ru>";
|
||||
aszlig = "aszlig <aszlig@redmoonstudios.org>";
|
||||
auntie = "Jonathan Glines <auntieNeo@gmail.com>";
|
||||
avnik = "Alexander V. Nikolaev <avn@avnik.info>";
|
||||
aycanirican = "Aycan iRiCAN <iricanaycan@gmail.com>";
|
||||
badi = "Badi' Abdul-Wahid <abdulwahidc@gmail.com>";
|
||||
balajisivaraman = "Balaji Sivaraman<sivaraman.balaji@gmail.com>";
|
||||
bbenoist = "Baptist BENOIST <return_0@live.com>";
|
||||
bcarrell = "Brandon Carrell <brandoncarrell@gmail.com>";
|
||||
bcdarwin = "Ben Darwin <bcdarwin@gmail.com>";
|
||||
bdimcheff = "Brandon Dimcheff <brandon@dimcheff.com>";
|
||||
bennofs = "Benno Fünfstück <benno.fuenfstueck@gmail.com>";
|
||||
benley = "Benjamin Staffin <benley@gmail.com>";
|
||||
berdario = "Dario Bertini <berdario@gmail.com>";
|
||||
bergey = "Daniel Bergey <bergey@teallabs.org>";
|
||||
bjg = "Brian Gough <bjg@gnu.org>";
|
||||
bjornfor = "Bjørn Forsman <bjorn.forsman@gmail.com>";
|
||||
bluescreen303 = "Mathijs Kwik <mathijs@bluescreen303.nl>";
|
||||
bobvanderlinden = "Bob van der Linden <bobvanderlinden@gmail.com>";
|
||||
bodil = "Bodil Stokke <nix@bodil.org>";
|
||||
boothead = "Ben Ford <ben@perurbis.com>";
|
||||
bosu = "Boris Sukholitko <boriss@gmail.com>";
|
||||
bramd = "Bram Duvigneau <bram@bramd.nl>";
|
||||
bstrik = "Berno Strik <dutchman55@gmx.com>";
|
||||
c0dehero = "CodeHero <codehero@nerdpol.ch>";
|
||||
calrama = "Moritz Maxeiner <moritz@ucworks.org>";
|
||||
campadrenalin = "Philip Horger <campadrenalin@gmail.com>";
|
||||
cdepillabout = "Dennis Gosnell <cdep.illabout@gmail.com>";
|
||||
cfouche = "Chaddaï Fouché <chaddai.fouche@gmail.com>";
|
||||
chaoflow = "Florian Friesdorf <flo@chaoflow.net>";
|
||||
chattered = "Phil Scott <me@philscotted.com>";
|
||||
christopherpoole = "Christopher Mark Poole <mail@christopherpoole.net>";
|
||||
coconnor = "Corey O'Connor <coreyoconnor@gmail.com>";
|
||||
codyopel = "Cody Opel <codyopel@gmail.com>";
|
||||
copumpkin = "Dan Peebles <pumpkingod@gmail.com>";
|
||||
coroa = "Jonas Hörsch <jonas@chaoflow.net>";
|
||||
couchemar = "Andrey Pavlov <couchemar@yandex.ru>";
|
||||
cstrahan = "Charles Strahan <charles.c.strahan@gmail.com>";
|
||||
cwoac = "Oliver Matthews <oliver@codersoffortune.net>";
|
||||
DamienCassou = "Damien Cassou <damien@cassou.me>";
|
||||
davidak = "David Kleuker <post@davidak.de>";
|
||||
davidrusu = "David Rusu <davidrusu.me@gmail.com>";
|
||||
dbohdan = "Danyil Bohdan <danyil.bohdan@gmail.com>";
|
||||
DerGuteMoritz = "Moritz Heidkamp <moritz@twoticketsplease.de>";
|
||||
deepfire = "Kosyrev Serge <_deepfire@feelingofgreen.ru>";
|
||||
desiderius = "Didier J. Devroye <didier@devroye.name>";
|
||||
devhell = "devhell <\"^\"@regexmail.net>";
|
||||
dezgeg = "Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>";
|
||||
dfoxfranke = "Daniel Fox Franke <dfoxfranke@gmail.com>";
|
||||
dmalikov = "Dmitry Malikov <malikov.d.y@gmail.com>";
|
||||
dochang = "Desmond O. Chang <dochang@gmail.com>";
|
||||
doublec = "Chris Double <chris.double@double.co.nz>";
|
||||
ebzzry = "Rommel Martinez <ebzzry@gmail.com>";
|
||||
ederoyd46 = "Matthew Brown <matt@ederoyd.co.uk>";
|
||||
eduarrrd = "Eduard Bachmakov <e.bachmakov@gmail.com>";
|
||||
edwtjo = "Edward Tjörnhammar <ed@cflags.cc>";
|
||||
eelco = "Eelco Dolstra <eelco.dolstra@logicblox.com>";
|
||||
eikek = "Eike Kettner <eike.kettner@posteo.de>";
|
||||
ellis = "Ellis Whitehead <nixos@ellisw.net>";
|
||||
emery = "Emery Hemingway <emery@vfemail.net>";
|
||||
enolan = "Echo Nolan <echo@echonolan.net>";
|
||||
epitrochoid = "Mabry Cervin <mpcervin@uncg.edu>";
|
||||
ericbmerritt = "Eric Merritt <eric@afiniate.com>";
|
||||
erikryb = "Erik Rybakken <erik.rybakken@math.ntnu.no>";
|
||||
emery = "Emery Hemingawy <emery@vfemail.net>";
|
||||
ertes = "Ertugrul Söylemez <ertesx@gmx.de>";
|
||||
exlevan = "Alexey Levan <exlevan@gmail.com>";
|
||||
falsifian = "James Cook <james.cook@utoronto.ca>";
|
||||
flosse = "Markus Kohlhase <mail@markus-kohlhase.de>";
|
||||
fluffynukeit = "Daniel Austin <dan@fluffynukeit.com>";
|
||||
forkk = "Andrew Okin <forkk@forkk.net>";
|
||||
fpletz = "Franz Pletz <fpletz@fnordicwalking.de>";
|
||||
fps = "Florian Paul Schmidt <mista.tapas@gmx.net>";
|
||||
fridh = "Frederik Rietdijk <fridh@fridh.nl>";
|
||||
fro_ozen = "fro_ozen <fro_ozen@gmx.de>";
|
||||
ftrvxmtrx = "Siarhei Zirukin <ftrvxmtrx@gmail.com>";
|
||||
funfunctor = "Edward O'Callaghan <eocallaghan@alterapraxis.com>";
|
||||
fuuzetsu = "Mateusz Kowalczyk <fuuzetsu@fuuzetsu.co.uk>";
|
||||
gal_bolle = "Florent Becker <florent.becker@ens-lyon.org>";
|
||||
garbas = "Rok Garbas <rok@garbas.si>";
|
||||
garrison = "Jim Garrison <jim@garrison.cc>";
|
||||
gavin = "Gavin Rogers <gavin@praxeology.co.uk>";
|
||||
gebner = "Gabriel Ebner <gebner@gebner.org>";
|
||||
gfxmonk = "Tim Cuthbertson <tim@gfxmonk.net>";
|
||||
giogadi = "Luis G. Torres <lgtorres42@gmail.com>";
|
||||
globin = "Robin Gloster <robin@glob.in>";
|
||||
goibhniu = "Cillian de Róiste <cillian.deroiste@gmail.com>";
|
||||
gridaphobe = "Eric Seidel <eric@seidel.io>";
|
||||
guibert = "David Guibert <david.guibert@gmail.com>";
|
||||
havvy = "Ryan Scheel <ryan.havvy@gmail.com>";
|
||||
hbunke = "Hendrik Bunke <bunke.hendrik@gmail.com>";
|
||||
henrytill = "Henry Till <henrytill@gmail.com>";
|
||||
hiberno = "Christian Lask <mail@elfsechsundzwanzig.de>";
|
||||
hinton = "Tom Hinton <t@larkery.com>";
|
||||
hrdinka = "Christoph Hrdinka <c.nix@hrdinka.at>";
|
||||
iand675 = "Ian Duncan <ian@iankduncan.com>";
|
||||
ianwookim = "Ian-Woo Kim <ianwookim@gmail.com>";
|
||||
iElectric = "Domen Kozar <domen@dev.si>";
|
||||
ikervagyok = "Balázs Lengyel <ikervagyok@gmail.com>";
|
||||
iyzsong = "Song Wenwu <iyzsong@gmail.com>";
|
||||
j-keck = "Jürgen Keck <jhyphenkeck@gmail.com>";
|
||||
jagajaga = "Arseniy Seroka <ars.seroka@gmail.com>";
|
||||
javaguirre = "Javier Aguirre <contacto@javaguirre.net>";
|
||||
jb55 = "William Casarin <bill@casarin.me>";
|
||||
jcumming = "Jack Cummings <jack@mudshark.org>";
|
||||
jefdaj = "Jeffrey David Johnson <jefdaj@gmail.com>";
|
||||
jfb = "James Felix Black <james@yamtime.com>";
|
||||
jgeerds = "Jascha Geerds <jg@ekby.de>";
|
||||
jirkamarsik = "Jirka Marsik <jiri.marsik89@gmail.com>";
|
||||
joachifm = "Joachim Fasting <joachifm@fastmail.fm>";
|
||||
joamaki = "Jussi Maki <joamaki@gmail.com>";
|
||||
joelmo = "Joel Moberg <joel.moberg@gmail.com>";
|
||||
joelteon = "Joel Taylor <me@joelt.io>";
|
||||
jpbernardy = "Jean-Philippe Bernardy <jeanphilippe.bernardy@gmail.com>";
|
||||
jwiegley = "John Wiegley <johnw@newartisans.com>";
|
||||
jwilberding = "Jordan Wilberding <jwilberding@afiniate.com>";
|
||||
jzellner = "Jeff Zellner <jeffz@eml.cc>";
|
||||
kamilchm = "Kamil Chmielewski <kamil.chm@gmail.com>";
|
||||
kampfschlaefer = "Arnold Krille <arnold@arnoldarts.de>";
|
||||
khumba = "Bryan Gardiner <bog@khumba.net>";
|
||||
kkallio = "Karn Kallio <tierpluspluslists@gmail.com>";
|
||||
koral = "Koral <koral@mailoo.org>";
|
||||
kovirobi = "Kovacsics Robert <kovirobi@gmail.com>";
|
||||
kragniz = "Louis Taylor <louis@kragniz.eu>";
|
||||
ktosiek = "Tomasz Kontusz <tomasz.kontusz@gmail.com>";
|
||||
lassulus = "Lassulus <lassulus@gmail.com>";
|
||||
layus = "Guillaume Maudoux <layus.on@gmail.com>";
|
||||
lebastr = "Alexander Lebedev <lebastr@gmail.com>";
|
||||
leonardoce = "Leonardo Cecchi <leonardo.cecchi@gmail.com>";
|
||||
lethalman = "Luca Bruno <lucabru@src.gnome.org>";
|
||||
lhvwb = "Nathaniel Baxter <nathaniel.baxter@gmail.com>";
|
||||
lihop = "Leroy Hopson <nixos@leroy.geek.nz>";
|
||||
linquize = "Linquize <linquize@yahoo.com.hk>";
|
||||
linus = "Linus Arver <linusarver@gmail.com>";
|
||||
lnl7 = "Daiderd Jordan <daiderd@gmail.com>";
|
||||
lovek323 = "Jason O'Conal <jason@oconal.id.au>";
|
||||
lowfatcomputing = "Andreas Wagner <andreas.wagner@lowfatcomputing.org>";
|
||||
lsix = "Lancelot SIX <lsix@lancelotsix.com>";
|
||||
ludo = "Ludovic Courtès <ludo@gnu.org>";
|
||||
lukego = "Luke Gorrie <luke@snabb.co>";
|
||||
madjar = "Georges Dubus <georges.dubus@compiletoi.net>";
|
||||
magnetophon = "Bart Brouns <bart@magnetophon.nl>";
|
||||
mahe = "Matthias Herrmann <matthias.mh.herrmann@gmail.com>";
|
||||
makefu = "Felix Richter <makefu@syntax-fehler.de>";
|
||||
malyn = "Michael Alyn Miller <malyn@strangeGizmo.com>";
|
||||
manveru = "Michael Fellinger <m.fellinger@gmail.com>";
|
||||
marcweber = "Marc Weber <marco-oweber@gmx.de>";
|
||||
maurer = "Matthew Maurer <matthew.r.maurer+nix@gmail.com>";
|
||||
matejc = "Matej Cotman <cotman.matej@gmail.com>";
|
||||
mathnerd314 = "Mathnerd314 <mathnerd314.gph+hs@gmail.com>";
|
||||
matthiasbeyer = "Matthias Beyer <mail@beyermatthias.de>";
|
||||
mbakke = "Marius Bakke <ymse@tuta.io>";
|
||||
meditans = "Carlo Nucera <meditans@gmail.com>";
|
||||
meisternu = "Matt Miemiec <meister@krutt.org>";
|
||||
michelk = "Michel Kuhlmann <michel@kuhlmanns.info>";
|
||||
michaelpj = "Michael Peyton Jones <michaelpj@gmail.com>";
|
||||
mirdhyn = "Merlin Gaillard <mirdhyn@gmail.com>";
|
||||
mschristiansen = "Mikkel Christiansen <mikkel@rheosystems.com>";
|
||||
modulistic = "Pablo Costa <modulistic@gmail.com>";
|
||||
mornfall = "Petr Ročkai <me@mornfall.net>";
|
||||
MP2E = "Cray Elliott <MP2E@archlinux.us>";
|
||||
msackman = "Matthew Sackman <matthew@wellquite.org>";
|
||||
mtreskin = "Max Treskin <zerthurd@gmail.com>";
|
||||
mudri = "James Wood <lamudri@gmail.com>";
|
||||
muflax = "Stefan Dorn <mail@muflax.com>";
|
||||
nathan-gs = "Nathan Bijnens <nathan@nathan.gs>";
|
||||
nckx = "Tobias Geerinckx-Rice <tobias.geerinckx.rice@gmail.com>";
|
||||
nico202 = "Nicolò Balzarotti <anothersms@gmail.com>";
|
||||
notthemessiah = "Brian Cohen <brian.cohen.88@gmail.com>";
|
||||
np = "Nicolas Pouillard <np.nix@nicolaspouillard.fr>";
|
||||
nslqqq = "Nikita Mikhailov <nslqqq@gmail.com>";
|
||||
obadz = "obadz <dav-nixos@odav.org>";
|
||||
ocharles = "Oliver Charles <ollie@ocharles.org.uk>";
|
||||
odi = "Oliver Dunkl <oliver.dunkl@gmail.com>";
|
||||
offline = "Jaka Hudoklin <jakahudoklin@gmail.com>";
|
||||
olcai = "Erik Timan <dev@timan.info>";
|
||||
orbitz = "Malcolm Matalka <mmatalka@gmail.com>";
|
||||
osener = "Ozan Sener <ozan@ozansener.com>";
|
||||
page = "Carles Pagès <page@cubata.homelinux.net>";
|
||||
paholg = "Paho Lurie-Gregg <paho@paholg.com>";
|
||||
pakhfn = "Fedor Pakhomov <pakhfn@gmail.com>";
|
||||
pashev = "Igor Pashev <pashev.igor@gmail.com>";
|
||||
pesterhazy = "Paulus Esterhazy <pesterhazy@gmail.com>";
|
||||
phausmann = "Philipp Hausmann <nix@314.ch>";
|
||||
philandstuff = "Philip Potter <philip.g.potter@gmail.com>";
|
||||
phreedom = "Evgeny Egorochkin <phreedom@yandex.ru>";
|
||||
pierron = "Nicolas B. Pierron <nixos@nbp.name>";
|
||||
piotr = "Piotr Pietraszkiewicz <ppietrasa@gmail.com>";
|
||||
pjones = "Peter Jones <pjones@devalot.com>";
|
||||
pkmx = "Chih-Mao Chen <pkmx.tw@gmail.com>";
|
||||
plcplc = "Philip Lykke Carlsen <plcplc@gmail.com>";
|
||||
pmahoney = "Patrick Mahoney <pat@polycrystal.org>";
|
||||
pmiddend = "Philipp Middendorf <pmidden@secure.mailbox.org>";
|
||||
prikhi = "Pavan Rikhi <pavan.rikhi@gmail.com>";
|
||||
psibi = "Sibi <sibi@psibi.in>";
|
||||
pSub = "Pascal Wittmann <mail@pascal-wittmann.de>";
|
||||
puffnfresh = "Brian McKenna <brian@brianmckenna.org>";
|
||||
qknight = "Joachim Schiele <js@lastlog.de>";
|
||||
ragge = "Ragnar Dahlen <r.dahlen@gmail.com>";
|
||||
raskin = "Michael Raskin <7c6f434c@mail.ru>";
|
||||
redbaron = "Maxim Ivanov <ivanov.maxim@gmail.com>";
|
||||
refnil = "Martin Lavoie <broemartino@gmail.com>";
|
||||
relrod = "Ricky Elrod <ricky@elrod.me>";
|
||||
renzo = "Renzo Carbonara <renzocarbonara@gmail.com>";
|
||||
rick68 = "Wei-Ming Yang <rick68@gmail.com>";
|
||||
rickynils = "Rickard Nilsson <rickynils@gmail.com>";
|
||||
rob = "Rob Vermaas <rob.vermaas@gmail.com>";
|
||||
robberer = "Longrin Wischnewski <robberer@freakmail.de>";
|
||||
robbinch = "Robbin C. <robbinch33@gmail.com>";
|
||||
roconnor = "Russell O'Connor <roconnor@theorem.ca>";
|
||||
roelof = "Roelof Wobben <rwobben@hotmail.com>";
|
||||
romildo = "José Romildo Malaquias <malaquias@gmail.com>";
|
||||
rszibele = "Richard Szibele <richard_szibele@hotmail.com>";
|
||||
rushmorem = "Rushmore Mushambi <rushmore@webenchanter.com>";
|
||||
rycee = "Robert Helgesson <robert@rycee.net>";
|
||||
samuelrivas = "Samuel Rivas <samuelrivas@gmail.com>";
|
||||
sander = "Sander van der Burg <s.vanderburg@tudelft.nl>";
|
||||
schmitthenner = "Fabian Schmitthenner <development@schmitthenner.eu>";
|
||||
schristo = "Scott Christopher <schristopher@konputa.com>";
|
||||
sepi = "Raffael Mancini <raffael@mancini.lu>";
|
||||
sheganinans = "Aistis Raulinaitis <sheganinans@gmail.com>";
|
||||
shell = "Shell Turner <cam.turn@gmail.com>";
|
||||
shlevy = "Shea Levy <shea@shealevy.com>";
|
||||
simons = "Peter Simons <simons@cryp.to>";
|
||||
simonvandel = "Simon Vandel Sillesen <simon.vandel@gmail.com>";
|
||||
sjagoe = "Simon Jagoe <simon@simonjagoe.com>";
|
||||
sjmackenzie = "Stewart Mackenzie <setori88@gmail.com>";
|
||||
skeidel = "Sven Keidel <svenkeidel@gmail.com>";
|
||||
smironov = "Sergey Mironov <ierton@gmail.com>";
|
||||
spacefrogg = "Michael Raitza <spacefrogg-nixos@meterriblecrew.net>";
|
||||
sprock = "Roger Mason <rmason@mun.ca>";
|
||||
spwhitt = "Spencer Whitt <sw@swhitt.me>";
|
||||
stephenmw = "Stephen Weinberg <stephen@q5comm.com>";
|
||||
szczyp = "Szczyp <qb@szczyp.com>";
|
||||
sztupi = "Attila Sztupak <attila.sztupak@gmail.com>";
|
||||
tailhook = "Paul Colomiets <paul@colomiets.name>";
|
||||
taktoa = "Remy Goldschmidt <taktoa@gmail.com>";
|
||||
telotortium = "Robert Irelan <rirelan@gmail.com>";
|
||||
thammers = "Tobias Hammerschmidt <jawr@gmx.de>";
|
||||
the-kenny = "Moritz Ulrich <moritz@tarn-vedra.de>";
|
||||
theuni = "Christian Theune <ct@flyingcircus.io>";
|
||||
thoughtpolice = "Austin Seipp <aseipp@pobox.com>";
|
||||
titanous = "Jonathan Rudenberg <jonathan@titanous.com>";
|
||||
tomberek = "Thomas Bereknyei <tomberek@gmail.com>";
|
||||
travisbhartwell = "Travis B. Hartwell <nafai@travishartwell.net>";
|
||||
trino = "Hubert Mühlhans <muehlhans.hubert@ekodia.de>";
|
||||
tstrobel = "Thomas Strobel <ts468@cam.ac.uk>";
|
||||
ttuegel = "Thomas Tuegel <ttuegel@gmail.com>";
|
||||
tv = "Tomislav Viljetić <tv@shackspace.de>";
|
||||
twey = "James ‘Twey’ Kay <twey@twey.co.uk>";
|
||||
urkud = "Yury G. Kudryashov <urkud+nix@ya.ru>";
|
||||
vandenoever = "Jos van den Oever <jos@vandenoever.info>";
|
||||
vbgl = "Vincent Laporte <Vincent.Laporte@gmail.com>";
|
||||
vbmithr = "Vincent Bernardoff <vb@luminar.eu.org>";
|
||||
vcunat = "Vladimír Čunát <vcunat@gmail.com>";
|
||||
viric = "Lluís Batlle i Rossell <viric@viric.name>";
|
||||
vizanto = "Danny Wilson <danny@prime.vc>";
|
||||
vlstill = "Vladimír Štill <xstill@fi.muni.cz>";
|
||||
vmandela = "Venkateswara Rao Mandela <venkat.mandela@gmail.com>";
|
||||
vozz = "Oliver Hunt <oliver.huntuk@gmail.com>";
|
||||
winden = "Antonio Vargas Gonzalez <windenntw@gmail.com>";
|
||||
wizeman = "Ricardo M. Correia <rcorreia@wizy.org>";
|
||||
wjlroe = "William Roe <willroe@gmail.com>";
|
||||
womfoo = "Kranium Gikos Mendoza <kranium@gikos.net>";
|
||||
wkennington = "William A. Kennington III <william@wkennington.com>";
|
||||
wmertens = "Wout Mertens <Wout.Mertens@gmail.com>";
|
||||
wscott = "Wayne Scott <wsc9tt@gmail.com>";
|
||||
wyvie = "Elijah Rum <elijahrum@gmail.com>";
|
||||
yarr = "Dmitry V. <savraz@gmail.com>";
|
||||
z77z = "Marco Maggesi <maggesi@math.unifi.it>";
|
||||
zef = "Zef Hemel <zef@zef.me>";
|
||||
zimbatm = "zimbatm <zimbatm@zimbatm.com>";
|
||||
zoomulator = "Kim Simmons <zoomulator@gmail.com>";
|
||||
Gonzih = "Max Gonzih <gonzih@gmail.com>";
|
||||
}
|
||||
|
||||
429
lib/misc.nix
Normal file
429
lib/misc.nix
Normal file
@@ -0,0 +1,429 @@
|
||||
let lib = import ./default.nix;
|
||||
inherit (builtins) isFunction hasAttr getAttr head tail isList isAttrs isInt attrNames;
|
||||
|
||||
in
|
||||
|
||||
with import ./lists.nix;
|
||||
with import ./attrsets.nix;
|
||||
with import ./strings.nix;
|
||||
|
||||
rec {
|
||||
|
||||
# returns default if env var is not set
|
||||
maybeEnv = name: default:
|
||||
let value = builtins.getEnv name; in
|
||||
if value == "" then default else value;
|
||||
|
||||
defaultMergeArg = x : y: if builtins.isAttrs y then
|
||||
y
|
||||
else
|
||||
(y x);
|
||||
defaultMerge = x: y: x // (defaultMergeArg x y);
|
||||
foldArgs = merger: f: init: x:
|
||||
let arg=(merger init (defaultMergeArg init x));
|
||||
# now add the function with composed args already applied to the final attrs
|
||||
base = (setAttrMerge "passthru" {} (f arg)
|
||||
( z : z // rec {
|
||||
function = foldArgs merger f arg;
|
||||
args = (lib.attrByPath ["passthru" "args"] {} z) // x;
|
||||
} ));
|
||||
withStdOverrides = base // {
|
||||
override = base.passthru.function;
|
||||
deepOverride = a : (base.passthru.function ((lib.mapAttrs (lib.deepOverrider a) base.passthru.args) // a));
|
||||
} ;
|
||||
in
|
||||
withStdOverrides;
|
||||
|
||||
|
||||
# predecessors: proposed replacement for applyAndFun (which has a bug cause it merges twice)
|
||||
# the naming "overridableDelayableArgs" tries to express that you can
|
||||
# - override attr values which have been supplied earlier
|
||||
# - use attr values before they have been supplied by accessing the fix point
|
||||
# name "fixed"
|
||||
# f: the (delayed overridden) arguments are applied to this
|
||||
#
|
||||
# initial: initial attrs arguments and settings. see defaultOverridableDelayableArgs
|
||||
#
|
||||
# returns: f applied to the arguments // special attributes attrs
|
||||
# a) merge: merge applied args with new args. Wether an argument is overridden depends on the merge settings
|
||||
# b) replace: this let's you replace and remove names no matter which merge function has been set
|
||||
#
|
||||
# examples: see test cases "res" below;
|
||||
overridableDelayableArgs =
|
||||
f : # the function applied to the arguments
|
||||
initial : # you pass attrs, the functions below are passing a function taking the fix argument
|
||||
let
|
||||
takeFixed = if isFunction initial then initial else (fixed : initial); # transform initial to an expression always taking the fixed argument
|
||||
tidy = args :
|
||||
let # apply all functions given in "applyPreTidy" in sequence
|
||||
applyPreTidyFun = fold ( n : a : x : n ( a x ) ) lib.id (maybeAttr "applyPreTidy" [] args);
|
||||
in removeAttrs (applyPreTidyFun args) ( ["applyPreTidy"] ++ (maybeAttr "removeAttrs" [] args) ); # tidy up args before applying them
|
||||
fun = n : x :
|
||||
let newArgs = fixed :
|
||||
let args = takeFixed fixed;
|
||||
mergeFun = getAttr n args;
|
||||
in if isAttrs x then (mergeFun args x)
|
||||
else assert isFunction x;
|
||||
mergeFun args (x ( args // { inherit fixed; }));
|
||||
in overridableDelayableArgs f newArgs;
|
||||
in
|
||||
(f (tidy (lib.fix takeFixed))) // {
|
||||
merge = fun "mergeFun";
|
||||
replace = fun "keepFun";
|
||||
};
|
||||
defaultOverridableDelayableArgs = f :
|
||||
let defaults = {
|
||||
mergeFun = mergeAttrByFunc; # default merge function. merge strategie (concatenate lists, strings) is given by mergeAttrBy
|
||||
keepFun = a : b : { inherit (a) removeAttrs mergeFun keepFun mergeAttrBy; } // b; # even when using replace preserve these values
|
||||
applyPreTidy = []; # list of functions applied to args before args are tidied up (usage case : prepareDerivationArgs)
|
||||
mergeAttrBy = mergeAttrBy // {
|
||||
applyPreTidy = a : b : a ++ b;
|
||||
removeAttrs = a : b: a ++ b;
|
||||
};
|
||||
removeAttrs = ["mergeFun" "keepFun" "mergeAttrBy" "removeAttrs" "fixed" ]; # before applying the arguments to the function make sure these names are gone
|
||||
};
|
||||
in (overridableDelayableArgs f defaults).merge;
|
||||
|
||||
|
||||
|
||||
# rec { # an example of how composedArgsAndFun can be used
|
||||
# a = composedArgsAndFun (x : x) { a = ["2"]; meta = { d = "bar";}; };
|
||||
# # meta.d will be lost ! It's your task to preserve it (eg using a merge function)
|
||||
# b = a.passthru.function { a = [ "3" ]; meta = { d2 = "bar2";}; };
|
||||
# # instead of passing/ overriding values you can use a merge function:
|
||||
# c = b.passthru.function ( x: { a = x.a ++ ["4"]; }); # consider using (maybeAttr "a" [] x)
|
||||
# }
|
||||
# result:
|
||||
# {
|
||||
# a = { a = ["2"]; meta = { d = "bar"; }; passthru = { function = .. }; };
|
||||
# b = { a = ["3"]; meta = { d2 = "bar2"; }; passthru = { function = .. }; };
|
||||
# c = { a = ["3" "4"]; meta = { d2 = "bar2"; }; passthru = { function = .. }; };
|
||||
# # c2 is equal to c
|
||||
# }
|
||||
composedArgsAndFun = f: foldArgs defaultMerge f {};
|
||||
|
||||
|
||||
# shortcut for attrByPath ["name"] default attrs
|
||||
maybeAttrNullable = name: default: attrs:
|
||||
if attrs == null then default else
|
||||
if __hasAttr name attrs then (__getAttr name attrs) else default;
|
||||
|
||||
# shortcut for attrByPath ["name"] default attrs
|
||||
maybeAttr = name: default: attrs:
|
||||
if __hasAttr name attrs then (__getAttr name attrs) else default;
|
||||
|
||||
|
||||
# Return the second argument if the first one is true or the empty version
|
||||
# of the second argument.
|
||||
ifEnable = cond: val:
|
||||
if cond then val
|
||||
else if builtins.isList val then []
|
||||
else if builtins.isAttrs val then {}
|
||||
# else if builtins.isString val then ""
|
||||
else if val == true || val == false then false
|
||||
else null;
|
||||
|
||||
|
||||
# Return true only if there is an attribute and it is true.
|
||||
checkFlag = attrSet: name:
|
||||
if name == "true" then true else
|
||||
if name == "false" then false else
|
||||
if (elem name (attrByPath ["flags"] [] attrSet)) then true else
|
||||
attrByPath [name] false attrSet ;
|
||||
|
||||
|
||||
# Input : attrSet, [ [name default] ... ], name
|
||||
# Output : its value or default.
|
||||
getValue = attrSet: argList: name:
|
||||
( attrByPath [name] (if checkFlag attrSet name then true else
|
||||
if argList == [] then null else
|
||||
let x = builtins.head argList; in
|
||||
if (head x) == name then
|
||||
(head (tail x))
|
||||
else (getValue attrSet
|
||||
(tail argList) name)) attrSet );
|
||||
|
||||
|
||||
# Input : attrSet, [[name default] ...], [ [flagname reqs..] ... ]
|
||||
# Output : are reqs satisfied? It's asserted.
|
||||
checkReqs = attrSet : argList : condList :
|
||||
(
|
||||
fold lib.and true
|
||||
(map (x: let name = (head x) ; in
|
||||
|
||||
((checkFlag attrSet name) ->
|
||||
(fold lib.and true
|
||||
(map (y: let val=(getValue attrSet argList y); in
|
||||
(val!=null) && (val!=false))
|
||||
(tail x))))) condList)) ;
|
||||
|
||||
|
||||
# This function has O(n^2) performance.
|
||||
uniqList = {inputList, acc ? []} :
|
||||
let go = xs : acc :
|
||||
if xs == []
|
||||
then []
|
||||
else let x = head xs;
|
||||
y = if elem x acc then [] else [x];
|
||||
in y ++ go (tail xs) (y ++ acc);
|
||||
in go inputList acc;
|
||||
|
||||
uniqListExt = {inputList, outputList ? [],
|
||||
getter ? (x : x), compare ? (x: y: x==y)}:
|
||||
if inputList == [] then outputList else
|
||||
let x=head inputList;
|
||||
isX = y: (compare (getter y) (getter x));
|
||||
newOutputList = outputList ++
|
||||
(if any isX outputList then [] else [x]);
|
||||
in uniqListExt {outputList=newOutputList;
|
||||
inputList = (tail inputList);
|
||||
inherit getter compare;
|
||||
};
|
||||
|
||||
|
||||
|
||||
condConcat = name: list: checker:
|
||||
if list == [] then name else
|
||||
if checker (head list) then
|
||||
condConcat
|
||||
(name + (head (tail list)))
|
||||
(tail (tail list))
|
||||
checker
|
||||
else condConcat
|
||||
name (tail (tail list)) checker;
|
||||
|
||||
lazyGenericClosure = {startSet, operator}:
|
||||
let
|
||||
work = list: doneKeys: result:
|
||||
if list == [] then
|
||||
result
|
||||
else
|
||||
let x = head list; key = x.key; in
|
||||
if elem key doneKeys then
|
||||
work (tail list) doneKeys result
|
||||
else
|
||||
work (tail list ++ operator x) ([key] ++ doneKeys) ([x] ++ result);
|
||||
in
|
||||
work startSet [] [];
|
||||
|
||||
genericClosure = builtins.genericClosure or lazyGenericClosure;
|
||||
|
||||
innerModifySumArgs = f: x: a: b: if b == null then (f a b) // x else
|
||||
innerModifySumArgs f x (a // b);
|
||||
modifySumArgs = f: x: innerModifySumArgs f x {};
|
||||
|
||||
|
||||
innerClosePropagation = acc : xs :
|
||||
if xs == []
|
||||
then acc
|
||||
else let y = head xs;
|
||||
ys = tail xs;
|
||||
in if ! isAttrs y
|
||||
then innerClosePropagation acc ys
|
||||
else let acc' = [y] ++ acc;
|
||||
in innerClosePropagation
|
||||
acc'
|
||||
(uniqList { inputList = (maybeAttrNullable "propagatedBuildInputs" [] y)
|
||||
++ (maybeAttrNullable "propagatedNativeBuildInputs" [] y)
|
||||
++ ys;
|
||||
acc = acc';
|
||||
}
|
||||
);
|
||||
|
||||
closePropagation = list: (uniqList {inputList = (innerClosePropagation [] list);});
|
||||
|
||||
# calls a function (f attr value ) for each record item. returns a list
|
||||
mapAttrsFlatten = f : r : map (attr: f attr (builtins.getAttr attr r) ) (attrNames r);
|
||||
|
||||
# attribute set containing one attribute
|
||||
nvs = name : value : listToAttrs [ (nameValuePair name value) ];
|
||||
# adds / replaces an attribute of an attribute set
|
||||
setAttr = set : name : v : set // (nvs name v);
|
||||
|
||||
# setAttrMerge (similar to mergeAttrsWithFunc but only merges the values of a particular name)
|
||||
# setAttrMerge "a" [] { a = [2];} (x : x ++ [3]) -> { a = [2 3]; }
|
||||
# setAttrMerge "a" [] { } (x : x ++ [3]) -> { a = [ 3]; }
|
||||
setAttrMerge = name : default : attrs : f :
|
||||
setAttr attrs name (f (maybeAttr name default attrs));
|
||||
|
||||
# Using f = a : b = b the result is similar to //
|
||||
# merge attributes with custom function handling the case that the attribute
|
||||
# exists in both sets
|
||||
mergeAttrsWithFunc = f : set1 : set2 :
|
||||
fold (n: set : if (__hasAttr n set)
|
||||
then setAttr set n (f (__getAttr n set) (__getAttr n set2))
|
||||
else set )
|
||||
(set2 // set1) (__attrNames set2);
|
||||
|
||||
# merging two attribute set concatenating the values of same attribute names
|
||||
# eg { a = 7; } { a = [ 2 3 ]; } becomes { a = [ 7 2 3 ]; }
|
||||
mergeAttrsConcatenateValues = mergeAttrsWithFunc ( a : b : (toList a) ++ (toList b) );
|
||||
|
||||
# merges attributes using //, if a name exisits in both attributes
|
||||
# an error will be triggered unless its listed in mergeLists
|
||||
# so you can mergeAttrsNoOverride { buildInputs = [a]; } { buildInputs = [a]; } {} to get
|
||||
# { buildInputs = [a b]; }
|
||||
# merging buildPhase does'nt really make sense. The cases will be rare where appending /prefixing will fit your needs?
|
||||
# in these cases the first buildPhase will override the second one
|
||||
# ! deprecated, use mergeAttrByFunc instead
|
||||
mergeAttrsNoOverride = { mergeLists ? ["buildInputs" "propagatedBuildInputs"],
|
||||
overrideSnd ? [ "buildPhase" ]
|
||||
} : attrs1 : attrs2 :
|
||||
fold (n: set :
|
||||
setAttr set n ( if (__hasAttr n set)
|
||||
then # merge
|
||||
if elem n mergeLists # attribute contains list, merge them by concatenating
|
||||
then (__getAttr n attrs2) ++ (__getAttr n attrs1)
|
||||
else if elem n overrideSnd
|
||||
then __getAttr n attrs1
|
||||
else throw "error mergeAttrsNoOverride, attribute ${n} given in both attributes - no merge func defined"
|
||||
else __getAttr n attrs2 # add attribute not existing in attr1
|
||||
)) attrs1 (__attrNames attrs2);
|
||||
|
||||
|
||||
# example usage:
|
||||
# mergeAttrByFunc {
|
||||
# inherit mergeAttrBy; # defined below
|
||||
# buildInputs = [ a b ];
|
||||
# } {
|
||||
# buildInputs = [ c d ];
|
||||
# };
|
||||
# will result in
|
||||
# { mergeAttrsBy = [...]; buildInputs = [ a b c d ]; }
|
||||
# is used by prepareDerivationArgs, defaultOverridableDelayableArgs and can be used when composing using
|
||||
# foldArgs, composedArgsAndFun or applyAndFun. Example: composableDerivation in all-packages.nix
|
||||
mergeAttrByFunc = x : y :
|
||||
let
|
||||
mergeAttrBy2 = { mergeAttrBy=lib.mergeAttrs; }
|
||||
// (maybeAttr "mergeAttrBy" {} x)
|
||||
// (maybeAttr "mergeAttrBy" {} y); in
|
||||
fold lib.mergeAttrs {} [
|
||||
x y
|
||||
(mapAttrs ( a : v : # merge special names using given functions
|
||||
if (hasAttr a x)
|
||||
then if (hasAttr a y)
|
||||
then v (getAttr a x) (getAttr a y) # both have attr, use merge func
|
||||
else (getAttr a x) # only x has attr
|
||||
else (getAttr a y) # only y has attr)
|
||||
) (removeAttrs mergeAttrBy2
|
||||
# don't merge attrs which are neither in x nor y
|
||||
(filter (a : (! hasAttr a x) && (! hasAttr a y) )
|
||||
(attrNames mergeAttrBy2))
|
||||
)
|
||||
)
|
||||
];
|
||||
mergeAttrsByFuncDefaults = foldl mergeAttrByFunc { inherit mergeAttrBy; };
|
||||
mergeAttrsByFuncDefaultsClean = list: removeAttrs (mergeAttrsByFuncDefaults list) ["mergeAttrBy"];
|
||||
|
||||
# merge attrs based on version key into mkDerivation args, see mergeAttrBy to learn about smart merge defaults
|
||||
#
|
||||
# This function is best explained by an example:
|
||||
#
|
||||
# {version ? "2.x"} :
|
||||
#
|
||||
# mkDerivation (mergeAttrsByVersion "package-name" version
|
||||
# { # version specific settings
|
||||
# "git" = { src = ..; preConfigre = "autogen.sh"; buildInputs = [automake autoconf libtool]; };
|
||||
# "2.x" = { src = ..; };
|
||||
# }
|
||||
# { // shared settings
|
||||
# buildInputs = [ common build inputs ];
|
||||
# meta = { .. }
|
||||
# }
|
||||
# )
|
||||
#
|
||||
# Please note that e.g. Eelco Dolstra usually prefers having one file for
|
||||
# each version. On the other hand there are valuable additional design goals
|
||||
# - readability
|
||||
# - do it once only
|
||||
# - try to avoid duplication
|
||||
#
|
||||
# Marc Weber and Michael Raskin sometimes prefer keeping older
|
||||
# versions around for testing and regression tests - as long as its cheap to
|
||||
# do so.
|
||||
#
|
||||
# Very often it just happens that the "shared" code is the bigger part.
|
||||
# Then using this function might be appropriate.
|
||||
#
|
||||
# Be aware that its easy to cause recompilations in all versions when using
|
||||
# this function - also if derivations get too complex splitting into multiple
|
||||
# files is the way to go.
|
||||
#
|
||||
# See misc.nix -> versionedDerivation
|
||||
# discussion: nixpkgs: pull/310
|
||||
mergeAttrsByVersion = name: version: attrsByVersion: base:
|
||||
mergeAttrsByFuncDefaultsClean [ { name = "${name}-${version}"; } base (maybeAttr version (throw "bad version ${version} for ${name}") attrsByVersion)];
|
||||
|
||||
# sane defaults (same name as attr name so that inherit can be used)
|
||||
mergeAttrBy = # { buildInputs = concatList; [...]; passthru = mergeAttr; [..]; }
|
||||
listToAttrs (map (n : nameValuePair n lib.concat)
|
||||
[ "nativeBuildInputs" "buildInputs" "propagatedBuildInputs" "configureFlags" "prePhases" "postAll" "patches" ])
|
||||
// listToAttrs (map (n : nameValuePair n lib.mergeAttrs) [ "passthru" "meta" "cfg" "flags" ])
|
||||
// listToAttrs (map (n : nameValuePair n (a: b: "${a}\n${b}") ) [ "preConfigure" "postInstall" ])
|
||||
;
|
||||
|
||||
# prepareDerivationArgs tries to make writing configurable derivations easier
|
||||
# example:
|
||||
# prepareDerivationArgs {
|
||||
# mergeAttrBy = {
|
||||
# myScript = x : y : x ++ "\n" ++ y;
|
||||
# };
|
||||
# cfg = {
|
||||
# readlineSupport = true;
|
||||
# };
|
||||
# flags = {
|
||||
# readline = {
|
||||
# set = {
|
||||
# configureFlags = [ "--with-compiler=${compiler}" ];
|
||||
# buildInputs = [ compiler ];
|
||||
# pass = { inherit compiler; READLINE=1; };
|
||||
# assertion = compiler.dllSupport;
|
||||
# myScript = "foo";
|
||||
# };
|
||||
# unset = { configureFlags = ["--without-compiler"]; };
|
||||
# };
|
||||
# };
|
||||
# src = ...
|
||||
# buildPhase = '' ... '';
|
||||
# name = ...
|
||||
# myScript = "bar";
|
||||
# };
|
||||
# if you don't have need for unset you can omit the surrounding set = { .. } attr
|
||||
# all attrs except flags cfg and mergeAttrBy will be merged with the
|
||||
# additional data from flags depending on config settings
|
||||
# It's used in composableDerivation in all-packages.nix. It's also used
|
||||
# heavily in the new python and libs implementation
|
||||
#
|
||||
# should we check for misspelled cfg options?
|
||||
# TODO use args.mergeFun here as well?
|
||||
prepareDerivationArgs = args:
|
||||
let args2 = { cfg = {}; flags = {}; } // args;
|
||||
flagName = name : "${name}Support";
|
||||
cfgWithDefaults = (listToAttrs (map (n : nameValuePair (flagName n) false) (attrNames args2.flags)))
|
||||
// args2.cfg;
|
||||
opts = attrValues (mapAttrs (a : v :
|
||||
let v2 = if v ? set || v ? unset then v else { set = v; };
|
||||
n = if (getAttr (flagName a) cfgWithDefaults) then "set" else "unset";
|
||||
attr = maybeAttr n {} v2; in
|
||||
if (maybeAttr "assertion" true attr)
|
||||
then attr
|
||||
else throw "assertion of flag ${a} of derivation ${args.name} failed"
|
||||
) args2.flags );
|
||||
in removeAttrs
|
||||
(mergeAttrsByFuncDefaults ([args] ++ opts ++ [{ passthru = cfgWithDefaults; }]))
|
||||
["flags" "cfg" "mergeAttrBy" ];
|
||||
|
||||
|
||||
nixType = x:
|
||||
if isAttrs x then
|
||||
if x ? outPath then "derivation"
|
||||
else "aattrs"
|
||||
else if isFunction x then "function"
|
||||
else if isList x then "list"
|
||||
else if x == true then "bool"
|
||||
else if x == false then "bool"
|
||||
else if x == null then "null"
|
||||
else if isInt x then "int"
|
||||
else "string";
|
||||
|
||||
}
|
||||
368
lib/modules.nix
368
lib/modules.nix
@@ -9,76 +9,28 @@ rec {
|
||||
|
||||
/* Evaluate a set of modules. The result is a set of two
|
||||
attributes: ‘options’: the nested set of all option declarations,
|
||||
and ‘config’: the nested set of all option values.
|
||||
!!! Please think twice before adding to this argument list! The more
|
||||
that is specified here instead of in the modules themselves the harder
|
||||
it is to transparently move a set of modules to be a submodule of another
|
||||
config (as the proper arguments need to be replicated at each call to
|
||||
evalModules) and the less declarative the module set is. */
|
||||
evalModules = { modules
|
||||
, prefix ? []
|
||||
, # This should only be used for special arguments that need to be evaluated
|
||||
# when resolving module structure (like in imports). For everything else,
|
||||
# there's _module.args.
|
||||
specialArgs ? {}
|
||||
, # This would be remove in the future, Prefer _module.args option instead.
|
||||
args ? {}
|
||||
, # This would be remove in the future, Prefer _module.check option instead.
|
||||
check ? true
|
||||
}:
|
||||
and ‘config’: the nested set of all option values. */
|
||||
evalModules = { modules, prefix ? [], args ? {}, check ? true }:
|
||||
let
|
||||
# This internal module declare internal options under the `_module'
|
||||
# attribute. These options are fragile, as they are used by the
|
||||
# module system to change the interpretation of modules.
|
||||
internalModule = rec {
|
||||
_file = ./modules.nix;
|
||||
|
||||
key = _file;
|
||||
|
||||
options = {
|
||||
_module.args = mkOption {
|
||||
type = types.attrsOf types.unspecified;
|
||||
internal = true;
|
||||
description = "Arguments passed to each module.";
|
||||
};
|
||||
|
||||
_module.check = mkOption {
|
||||
type = types.bool;
|
||||
internal = true;
|
||||
default = check;
|
||||
description = "Whether to check whether all option definitions have matching declarations.";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
_module.args = args;
|
||||
};
|
||||
};
|
||||
|
||||
closed = closeModules (modules ++ [ internalModule ]) ({ inherit config options; lib = import ./.; } // specialArgs);
|
||||
|
||||
args' = args // { lib = import ./.; } // result;
|
||||
closed = closeModules modules args';
|
||||
# Note: the list of modules is reversed to maintain backward
|
||||
# compatibility with the old module system. Not sure if this is
|
||||
# the most sensible policy.
|
||||
options = mergeModules prefix (reverseList closed);
|
||||
|
||||
# Traverse options and extract the option values into the final
|
||||
# config set. At the same time, check whether all option
|
||||
# definitions have matching declarations.
|
||||
# !!! _module.check's value can't depend on any other config values
|
||||
# without an infinite recursion. One way around this is to make the
|
||||
# 'config' passed around to the modules be unconditionally unchecked,
|
||||
# and only do the check in 'result'.
|
||||
config = yieldConfig prefix options;
|
||||
yieldConfig = prefix: set:
|
||||
let res = removeAttrs (mapAttrs (n: v:
|
||||
if isOption v then v.value
|
||||
else yieldConfig (prefix ++ [n]) v) set) ["_definedNames"];
|
||||
in
|
||||
if options._module.check.value && set ? _definedNames then
|
||||
foldl' (res: m:
|
||||
foldl' (res: name:
|
||||
if set ? ${name} then res else throw "The option `${showOption (prefix ++ [name])}' defined in `${m.file}' does not exist.")
|
||||
if check && set ? _definedNames then
|
||||
fold (m: res:
|
||||
fold (name: res:
|
||||
if hasAttr name set then res else throw "The option `${showOption (prefix ++ [name])}' defined in `${m.file}' does not exist.")
|
||||
res m.names)
|
||||
res set._definedNames
|
||||
else
|
||||
@@ -91,11 +43,9 @@ rec {
|
||||
let
|
||||
toClosureList = file: parentKey: imap (n: x:
|
||||
if isAttrs x || isFunction x then
|
||||
let key = "${parentKey}:anon-${toString n}"; in
|
||||
unifyModuleSyntax file key (unpackSubmodule (applyIfFunction key) x args)
|
||||
unifyModuleSyntax file "${parentKey}:anon-${toString n}" (applyIfFunction x args)
|
||||
else
|
||||
let file = toString x; key = toString x; in
|
||||
unifyModuleSyntax file key (applyIfFunction key (import x) args));
|
||||
unifyModuleSyntax (toString x) (toString x) (applyIfFunction (import x) args));
|
||||
in
|
||||
builtins.genericClosure {
|
||||
startSet = toClosureList unknownModule "" modules;
|
||||
@@ -108,7 +58,7 @@ rec {
|
||||
if m ? config || m ? options then
|
||||
let badAttrs = removeAttrs m ["imports" "options" "config" "key" "_file"]; in
|
||||
if badAttrs != {} then
|
||||
throw "Module `${key}' has an unsupported attribute `${head (attrNames badAttrs)}'. This is caused by assignments to the top-level attributes `config' or `options'."
|
||||
throw "Module `${key}' has an unsupported attribute `${head (attrNames badAttrs)}'."
|
||||
else
|
||||
{ file = m._file or file;
|
||||
key = toString m.key or key;
|
||||
@@ -124,46 +74,7 @@ rec {
|
||||
config = removeAttrs m ["key" "_file" "require" "imports"];
|
||||
};
|
||||
|
||||
applyIfFunction = key: f: args@{ config, options, lib, ... }: if isFunction f then
|
||||
let
|
||||
# Module arguments are resolved in a strict manner when attribute set
|
||||
# deconstruction is used. As the arguments are now defined with the
|
||||
# config._module.args option, the strictness used on the attribute
|
||||
# set argument would cause an infinite loop, if the result of the
|
||||
# option is given as argument.
|
||||
#
|
||||
# To work-around the strictness issue on the deconstruction of the
|
||||
# attributes set argument, we create a new attribute set which is
|
||||
# constructed to satisfy the expected set of attributes. Thus calling
|
||||
# a module will resolve strictly the attributes used as argument but
|
||||
# not their values. The values are forwarding the result of the
|
||||
# evaluation of the option.
|
||||
requiredArgs = builtins.attrNames (builtins.functionArgs f);
|
||||
context = name: ''while evaluating the module argument `${name}' in "${key}":'';
|
||||
extraArgs = builtins.listToAttrs (map (name: {
|
||||
inherit name;
|
||||
value = addErrorContext (context name)
|
||||
(args.${name} or config._module.args.${name});
|
||||
}) requiredArgs);
|
||||
|
||||
# Note: we append in the opposite order such that we can add an error
|
||||
# context on the explicited arguments of "args" too. This update
|
||||
# operator is used to make the "args@{ ... }: with args.lib;" notation
|
||||
# works.
|
||||
in f (args // extraArgs)
|
||||
else
|
||||
f;
|
||||
|
||||
/* We have to pack and unpack submodules. We cannot wrap the expected
|
||||
result of the function as we would no longer be able to list the arguments
|
||||
of the submodule. (see applyIfFunction) */
|
||||
unpackSubmodule = unpack: m: args:
|
||||
if isType "submodule" m then
|
||||
{ _file = m.file; } // (unpack m.submodule args)
|
||||
else unpack m args;
|
||||
|
||||
packSubmodule = file: m:
|
||||
{ _type = "submodule"; file = file; submodule = m; };
|
||||
applyIfFunction = f: arg: if isFunction f then f arg else f;
|
||||
|
||||
/* Merge a list of modules. This will recurse over the option
|
||||
declarations in all modules, combining them into a single set.
|
||||
@@ -182,22 +93,25 @@ rec {
|
||||
let
|
||||
loc = prefix ++ [name];
|
||||
# Get all submodules that declare ‘name’.
|
||||
decls = concatMap (m:
|
||||
if m.options ? ${name}
|
||||
then [ { inherit (m) file; options = m.options.${name}; } ]
|
||||
decls = concatLists (map (m:
|
||||
if hasAttr name m.options
|
||||
then [ { inherit (m) file; options = getAttr name m.options; } ]
|
||||
else []
|
||||
) options;
|
||||
) options);
|
||||
# Get all submodules that define ‘name’.
|
||||
defns = concatMap (m:
|
||||
if m.config ? ${name}
|
||||
defns = concatLists (map (m:
|
||||
if hasAttr name m.config
|
||||
then map (config: { inherit (m) file; inherit config; })
|
||||
(pushDownProperties m.config.${name})
|
||||
(pushDownProperties (getAttr name m.config))
|
||||
else []
|
||||
) configs);
|
||||
nrOptions = count (m: isOption m.options) decls;
|
||||
# Process mkMerge and mkIf properties.
|
||||
defns' = concatMap (m:
|
||||
if hasAttr name m.config
|
||||
then map (m': { inherit (m) file; value = m'; }) (dischargeProperties (getAttr name m.config))
|
||||
else []
|
||||
) configs;
|
||||
nrOptions = count (m: isOption m.options) decls;
|
||||
# Extract the definitions for this loc
|
||||
defns' = map (m: { inherit (m) file; value = m.config.${name}; })
|
||||
(filter (m: m.config ? ${name}) configs);
|
||||
in
|
||||
if nrOptions == length decls then
|
||||
let opt = fixupOptionType loc (mergeOptionDecls loc decls);
|
||||
@@ -218,41 +132,20 @@ rec {
|
||||
The exception is the ‘options’ attribute, which specifies
|
||||
sub-options. These can be specified multiple times to allow one
|
||||
module to add sub-options to an option declared somewhere else
|
||||
(e.g. multiple modules define sub-options for ‘fileSystems’).
|
||||
|
||||
'loc' is the list of attribute names where the option is located.
|
||||
|
||||
'opts' is a list of modules. Each module has an options attribute which
|
||||
correspond to the definition of 'loc' in 'opt.file'. */
|
||||
(e.g. multiple modules define sub-options for ‘fileSystems’). */
|
||||
mergeOptionDecls = loc: opts:
|
||||
foldl' (res: opt:
|
||||
fold (opt: res:
|
||||
if opt.options ? default && res ? default ||
|
||||
opt.options ? example && res ? example ||
|
||||
opt.options ? description && res ? description ||
|
||||
opt.options ? apply && res ? apply ||
|
||||
# Accept to merge options which have identical types.
|
||||
opt.options ? type && res ? type && opt.options.type.name != res.type.name
|
||||
opt.options ? type && res ? type
|
||||
then
|
||||
throw "The option `${showOption loc}' in `${opt.file}' is already declared in ${showFiles res.declarations}."
|
||||
else
|
||||
let
|
||||
/* Add the modules of the current option to the list of modules
|
||||
already collected. The options attribute except either a list of
|
||||
submodules or a submodule. For each submodule, we add the file of the
|
||||
current option declaration as the file use for the submodule. If the
|
||||
submodule defines any filename, then we ignore the enclosing option file. */
|
||||
options' = toList opt.options.options;
|
||||
coerceOption = file: opt:
|
||||
if isFunction opt then packSubmodule file opt
|
||||
else packSubmodule file { options = opt; };
|
||||
getSubModules = opt.options.type.getSubModules or null;
|
||||
submodules =
|
||||
if getSubModules != null then map (packSubmodule opt.file) getSubModules ++ res.options
|
||||
else if opt.options ? options then map (coerceOption opt.file) options' ++ res.options
|
||||
else res.options;
|
||||
in opt.options // res //
|
||||
{ declarations = res.declarations ++ [opt.file];
|
||||
options = submodules;
|
||||
opt.options // res //
|
||||
{ declarations = [opt.file] ++ res.declarations;
|
||||
options = if opt.options ? options then [(toList opt.options.options ++ res.options)] else [];
|
||||
}
|
||||
) { inherit loc; declarations = []; options = []; } opts;
|
||||
|
||||
@@ -260,69 +153,38 @@ rec {
|
||||
config value. */
|
||||
evalOptionValue = loc: opt: defs:
|
||||
let
|
||||
# Add in the default value for this option, if any.
|
||||
defs' =
|
||||
(optional (opt ? default)
|
||||
{ file = head opt.declarations; value = mkOptionDefault opt.default; }) ++ defs;
|
||||
|
||||
# Handle properties, check types, and merge everything together.
|
||||
res =
|
||||
if opt.readOnly or false && length defs' > 1 then
|
||||
throw "The option `${showOption loc}' is read-only, but it's set multiple times."
|
||||
else
|
||||
mergeDefinitions loc opt.type defs';
|
||||
|
||||
# Check whether the option is defined, and apply the ‘apply’
|
||||
# function to the merged value. This allows options to yield a
|
||||
# value computed from the definitions.
|
||||
value =
|
||||
if !res.isDefined then
|
||||
# Process mkOverride properties, adding in the default
|
||||
# value specified in the option declaration (if any).
|
||||
defsFinal' = filterOverrides
|
||||
((if opt ? default then [{ file = head opt.declarations; value = mkOptionDefault opt.default; }] else []) ++ defs);
|
||||
# Sort mkOrder properties.
|
||||
defsFinal =
|
||||
# Avoid sorting if we don't have to.
|
||||
if any (def: def.value._type or "" == "order") defsFinal'
|
||||
then sortProperties defsFinal'
|
||||
else defsFinal';
|
||||
files = map (def: def.file) defsFinal;
|
||||
# Type-check the remaining definitions, and merge them if
|
||||
# possible.
|
||||
merged =
|
||||
if defsFinal == [] then
|
||||
throw "The option `${showOption loc}' is used but not defined."
|
||||
else if opt ? apply then
|
||||
opt.apply res.mergedValue
|
||||
else
|
||||
res.mergedValue;
|
||||
|
||||
fold (def: res:
|
||||
if opt.type.check def.value then res
|
||||
else throw "The option value `${showOption loc}' in `${def.file}' is not a ${opt.type.name}.")
|
||||
(opt.type.merge loc defsFinal) defsFinal;
|
||||
# Finally, apply the ‘apply’ function to the merged
|
||||
# value. This allows options to yield a value computed
|
||||
# from the definitions.
|
||||
value = (opt.apply or id) merged;
|
||||
in opt //
|
||||
{ value = addErrorContext "while evaluating the option `${showOption loc}':" value;
|
||||
definitions = map (def: def.value) res.defsFinal;
|
||||
files = map (def: def.file) res.defsFinal;
|
||||
inherit (res) isDefined;
|
||||
definitions = map (def: def.value) defsFinal;
|
||||
isDefined = defsFinal != [];
|
||||
inherit files;
|
||||
};
|
||||
|
||||
# Merge definitions of a value of a given type.
|
||||
mergeDefinitions = loc: type: defs: rec {
|
||||
defsFinal =
|
||||
let
|
||||
# Process mkMerge and mkIf properties.
|
||||
defs' = concatMap (m:
|
||||
map (value: { inherit (m) file; inherit value; }) (dischargeProperties m.value)
|
||||
) defs;
|
||||
|
||||
# Process mkOverride properties.
|
||||
defs'' = filterOverrides defs';
|
||||
|
||||
# Sort mkOrder properties.
|
||||
defs''' =
|
||||
# Avoid sorting if we don't have to.
|
||||
if any (def: def.value._type or "" == "order") defs''
|
||||
then sortProperties defs''
|
||||
else defs'';
|
||||
in defs''';
|
||||
|
||||
# Type-check the remaining definitions, and merge them.
|
||||
mergedValue = foldl' (res: def:
|
||||
if type.check def.value then res
|
||||
else throw "The option value `${showOption loc}' in `${def.file}' is not a ${type.name}.")
|
||||
(type.merge loc defsFinal) defsFinal;
|
||||
|
||||
isDefined = defsFinal != [];
|
||||
|
||||
optionalValue =
|
||||
if isDefined then { value = mergedValue; }
|
||||
else {};
|
||||
};
|
||||
|
||||
/* Given a config set, expand mkMerge properties, and push down the
|
||||
other properties into the children. The result is a list of
|
||||
config sets that do not have properties at top-level. For
|
||||
@@ -332,7 +194,7 @@ rec {
|
||||
|
||||
is transformed into
|
||||
|
||||
[ { boot = set1; } { boot = mkIf cond set2; services = mkIf cond set3; } ].
|
||||
[ { boot = set1; } { boot = mkIf cond set2; services mkIf cond set3; } ].
|
||||
|
||||
This transform is the critical step that allows mkIf conditions
|
||||
to refer to the full configuration without creating an infinite
|
||||
@@ -392,7 +254,8 @@ rec {
|
||||
let
|
||||
defaultPrio = 100;
|
||||
getPrio = def: if def.value._type or "" == "override" then def.value.priority else defaultPrio;
|
||||
highestPrio = foldl' (prio: def: min (getPrio def) prio) 9999 defs;
|
||||
min = x: y: if builtins.lessThan x y then x else y;
|
||||
highestPrio = fold (def: prio: min (getPrio def) prio) 9999 defs;
|
||||
strip = def: if def.value._type or "" == "override" then def // { value = def.value.content; } else def;
|
||||
in concatMap (def: if getPrio def == highestPrio then [(strip def)] else []) defs;
|
||||
|
||||
@@ -410,24 +273,23 @@ rec {
|
||||
in sort compare defs';
|
||||
|
||||
/* Hack for backward compatibility: convert options of type
|
||||
optionSet to options of type submodule. FIXME: remove
|
||||
eventually. */
|
||||
optionSet to configOf. FIXME: remove eventually. */
|
||||
fixupOptionType = loc: opt:
|
||||
let
|
||||
options = opt.options or
|
||||
(throw "Option `${showOption loc'}' has type optionSet but has no option attribute, in ${showFiles opt.declarations}.");
|
||||
options' = opt.options or
|
||||
(throw "Option `${showOption loc'}' has type optionSet but has no option attribute.");
|
||||
coerce = x:
|
||||
if isFunction x then x
|
||||
else { config, ... }: { options = x; };
|
||||
options = map coerce (flatten options');
|
||||
f = tp:
|
||||
if tp.name == "option set" || tp.name == "submodule" then
|
||||
throw "The option ${showOption loc} uses submodules without a wrapping type, in ${showFiles opt.declarations}."
|
||||
if tp.name == "option set" then types.submodule options
|
||||
else if tp.name == "attribute set of option sets" then types.attrsOf (types.submodule options)
|
||||
else if tp.name == "list or attribute set of option sets" then types.loaOf (types.submodule options)
|
||||
else if tp.name == "list of option sets" then types.listOf (types.submodule options)
|
||||
else if tp.name == "null or option set" then types.nullOr (types.submodule options)
|
||||
else tp;
|
||||
in
|
||||
if opt.type.getSubModules or null == null
|
||||
then opt // { type = f (opt.type or types.unspecified); }
|
||||
else opt // { type = opt.type.substSubModules opt.options; options = []; };
|
||||
in opt // { type = f (opt.type or types.unspecified); };
|
||||
|
||||
|
||||
/* Properties. */
|
||||
@@ -470,97 +332,7 @@ rec {
|
||||
mkAfter = mkOrder 1500;
|
||||
|
||||
|
||||
# Convenient property used to transfer all definitions and their
|
||||
# properties from one option to another. This property is useful for
|
||||
# renaming options, and also for including properties from another module
|
||||
# system, including sub-modules.
|
||||
#
|
||||
# { config, options, ... }:
|
||||
#
|
||||
# {
|
||||
# # 'bar' might not always be defined in the current module-set.
|
||||
# config.foo.enable = mkAliasDefinitions (options.bar.enable or {});
|
||||
#
|
||||
# # 'barbaz' has to be defined in the current module-set.
|
||||
# config.foobar.paths = mkAliasDefinitions options.barbaz.paths;
|
||||
# }
|
||||
#
|
||||
# Note, this is different than taking the value of the option and using it
|
||||
# as a definition, as the new definition will not keep the mkOverride /
|
||||
# mkDefault properties of the previous option.
|
||||
#
|
||||
mkAliasDefinitions = mkAliasAndWrapDefinitions id;
|
||||
mkAliasAndWrapDefinitions = wrap: option:
|
||||
mkMerge
|
||||
(optional (isOption option && option.isDefined)
|
||||
(wrap (mkMerge option.definitions)));
|
||||
|
||||
|
||||
/* Compatibility. */
|
||||
fixMergeModules = modules: args: evalModules { inherit modules args; check = false; };
|
||||
|
||||
|
||||
/* Return a module that causes a warning to be shown if the
|
||||
specified option is defined. For example,
|
||||
|
||||
mkRemovedOptionModule [ "boot" "loader" "grub" "bootDevice" ]
|
||||
|
||||
causes a warning if the user defines boot.loader.grub.bootDevice.
|
||||
*/
|
||||
mkRemovedOptionModule = optionName:
|
||||
{ options, ... }:
|
||||
{ options = setAttrByPath optionName (mkOption {
|
||||
visible = false;
|
||||
});
|
||||
config.warnings =
|
||||
let opt = getAttrFromPath optionName options; in
|
||||
optional opt.isDefined
|
||||
"The option definition `${showOption optionName}' in ${showFiles opt.files} no longer has any effect; please remove it.";
|
||||
};
|
||||
|
||||
/* Return a module that causes a warning to be shown if the
|
||||
specified "from" option is defined; the defined value is however
|
||||
forwarded to the "to" option. This can be used to rename options
|
||||
while providing backward compatibility. For example,
|
||||
|
||||
mkRenamedOptionModule [ "boot" "copyKernels" ] [ "boot" "loader" "grub" "copyKernels" ]
|
||||
|
||||
forwards any definitions of boot.copyKernels to
|
||||
boot.loader.grub.copyKernels while printing a warning.
|
||||
*/
|
||||
mkRenamedOptionModule = from: to: doRename {
|
||||
inherit from to;
|
||||
visible = false;
|
||||
warn = true;
|
||||
use = builtins.trace "Obsolete option `${showOption from}' is used. It was renamed to `${showOption to}'.";
|
||||
};
|
||||
|
||||
/* Like ‘mkRenamedOptionModule’, but doesn't show a warning. */
|
||||
mkAliasOptionModule = from: to: doRename {
|
||||
inherit from to;
|
||||
visible = true;
|
||||
warn = false;
|
||||
use = id;
|
||||
};
|
||||
|
||||
doRename = { from, to, visible, warn, use }:
|
||||
let
|
||||
toOf = attrByPath to
|
||||
(abort "Renaming error: option `${showOption to}' does not exists.");
|
||||
in
|
||||
{ config, options, ... }:
|
||||
{ options = setAttrByPath from (mkOption {
|
||||
description = "Alias of <option>${showOption to}</option>.";
|
||||
apply = x: use (toOf config);
|
||||
});
|
||||
config = {
|
||||
/*
|
||||
warnings =
|
||||
let opt = getAttrFromPath from options; in
|
||||
optional (warn && opt.isDefined)
|
||||
"The option `${showOption from}' defined in ${showFiles opt.files} has been renamed to `${showOption to}'.";
|
||||
*/
|
||||
} // setAttrByPath to (mkAliasDefinitions (getAttrFromPath from options));
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ let lib = import ./default.nix; in
|
||||
|
||||
with import ./trivial.nix;
|
||||
with import ./lists.nix;
|
||||
with import ./misc.nix;
|
||||
with import ./attrsets.nix;
|
||||
with import ./strings.nix;
|
||||
|
||||
@@ -19,7 +20,6 @@ rec {
|
||||
, apply ? null # Function that converts the option value to something else.
|
||||
, internal ? null # Whether the option is for NixOS developers only.
|
||||
, visible ? null # Whether the option shows up in the manual.
|
||||
, readOnly ? null # Whether the option can be set only once
|
||||
, options ? null # Obsolete, used by types.optionSet.
|
||||
} @ attrs:
|
||||
attrs // { _type = "option"; };
|
||||
@@ -31,49 +31,37 @@ rec {
|
||||
type = lib.types.bool;
|
||||
};
|
||||
|
||||
# This option accept anything, but it does not produce any result. This
|
||||
# is useful for sharing a module across different module sets without
|
||||
# having to implement similar features as long as the value of the options
|
||||
# are not expected.
|
||||
mkSinkUndeclaredOptions = attrs: mkOption ({
|
||||
internal = true;
|
||||
visible = false;
|
||||
default = false;
|
||||
description = "Sink for option definitions.";
|
||||
type = mkOptionType {
|
||||
name = "sink";
|
||||
check = x: true;
|
||||
merge = loc: defs: false;
|
||||
};
|
||||
apply = x: throw "Option value is not readable because the option is not declared.";
|
||||
} // attrs);
|
||||
|
||||
mergeDefaultOption = loc: defs:
|
||||
let list = getValues defs; in
|
||||
if length list == 1 then head list
|
||||
else if all isFunction list then x: mergeDefaultOption loc (map (f: f x) list)
|
||||
else if all isList list then concatLists list
|
||||
else if all isAttrs list then foldl' lib.mergeAttrs {} list
|
||||
else if all isBool list then foldl' lib.or false list
|
||||
else if all isAttrs list then fold lib.mergeAttrs {} list
|
||||
else if all isBool list then fold lib.or false list
|
||||
else if all isString list then lib.concatStrings list
|
||||
else if all isInt list && all (x: x == head list) list then head list
|
||||
else throw "Cannot merge definitions of `${showOption loc}' given in ${showFiles (getFiles defs)}.";
|
||||
|
||||
/* Obsolete, will remove soon. Specify an option type or apply
|
||||
function instead. */
|
||||
mergeTypedOption = typeName: predicate: merge: loc: list:
|
||||
let list' = map (x: x.value) list; in
|
||||
if all predicate list then merge list'
|
||||
else throw "Expected a ${typeName}.";
|
||||
|
||||
mergeEnableOption = mergeTypedOption "boolean"
|
||||
(x: true == x || false == x) (fold lib.or false);
|
||||
|
||||
mergeListOption = mergeTypedOption "list" isList concatLists;
|
||||
|
||||
mergeStringOption = mergeTypedOption "string" isString lib.concatStrings;
|
||||
|
||||
mergeOneOption = loc: defs:
|
||||
if defs == [] then abort "This case should never happen."
|
||||
else if length defs != 1 then
|
||||
throw "The unique option `${showOption loc}' is defined multiple times, in ${showFiles (getFiles defs)}."
|
||||
else (head defs).value;
|
||||
|
||||
/* "Merge" option definitions by checking that they all have the same value. */
|
||||
mergeEqualOption = loc: defs:
|
||||
if defs == [] then abort "This case should never happen."
|
||||
else foldl' (val: def:
|
||||
if def.value != val then
|
||||
throw "The option `${showOption loc}' has conflicting definitions, in ${showFiles (getFiles defs)}."
|
||||
else
|
||||
val) (head defs).value defs;
|
||||
|
||||
getValues = map (x: x.value);
|
||||
getFiles = map (x: x.file);
|
||||
|
||||
@@ -83,7 +71,7 @@ rec {
|
||||
optionAttrSetToDocList = optionAttrSetToDocList' [];
|
||||
|
||||
optionAttrSetToDocList' = prefix: options:
|
||||
concatMap (opt:
|
||||
fold (opt: rest:
|
||||
let
|
||||
docOption = rec {
|
||||
name = showOption opt.loc;
|
||||
@@ -91,18 +79,17 @@ rec {
|
||||
declarations = filter (x: x != unknownModule) opt.declarations;
|
||||
internal = opt.internal or false;
|
||||
visible = opt.visible or true;
|
||||
readOnly = opt.readOnly or false;
|
||||
type = opt.type.name or null;
|
||||
}
|
||||
// (if opt ? example then { example = scrubOptionValue opt.example; } else {})
|
||||
// (if opt ? default then { default = scrubOptionValue opt.default; } else {})
|
||||
// (if opt ? defaultText then { default = opt.defaultText; } else {});
|
||||
// optionalAttrs (opt ? example) { example = scrubOptionValue opt.example; }
|
||||
// optionalAttrs (opt ? default) { default = scrubOptionValue opt.default; }
|
||||
// optionalAttrs (opt ? defaultText) { default = opt.defaultText; };
|
||||
|
||||
subOptions =
|
||||
let ss = opt.type.getSubOptions opt.loc;
|
||||
in if ss != {} then optionAttrSetToDocList' opt.loc ss else [];
|
||||
in
|
||||
[ docOption ] ++ subOptions) (collect isOption options);
|
||||
# FIXME: expensive, O(n^2)
|
||||
[ docOption ] ++ subOptions ++ rest) [] (collect isOption options);
|
||||
|
||||
|
||||
/* This function recursively removes all derivation attributes from
|
||||
|
||||
@@ -7,14 +7,10 @@ rec {
|
||||
freebsd = ["i686-freebsd" "x86_64-freebsd"];
|
||||
openbsd = ["i686-openbsd" "x86_64-openbsd"];
|
||||
netbsd = ["i686-netbsd" "x86_64-netbsd"];
|
||||
cygwin = ["i686-cygwin" "x86_64-cygwin"];
|
||||
cygwin = ["i686-cygwin"];
|
||||
unix = linux ++ darwin ++ freebsd ++ openbsd;
|
||||
all = linux ++ darwin ++ cygwin ++ freebsd ++ openbsd;
|
||||
none = [];
|
||||
allBut = platforms: lists.filter (x: !(builtins.elem x platforms)) all;
|
||||
allBut = platform: lists.filter (x: platform != x) all;
|
||||
mesaPlatforms = ["i686-linux" "x86_64-linux" "x86_64-darwin" "armv5tel-linux" "armv6l-linux"];
|
||||
x86_64 = ["x86_64-linux" "x86_64-darwin" "x86_64-freebsd" "x86_64-openbsd" "x86_64-netbsd" "x86_64-cygwin"];
|
||||
i686 = ["i686-linux" "i686-freebsd" "i686-netbsd" "i686-cygwin"];
|
||||
arm = ["armv5tel-linux" "armv6l-linux" "armv7l-linux" ];
|
||||
mips = [ "mips64el-linux" ];
|
||||
}
|
||||
|
||||
@@ -21,12 +21,12 @@ rec {
|
||||
|
||||
|
||||
# Get all files ending with the specified suffices from the given
|
||||
# directory or its descendants. E.g. `sourceFilesBySuffices ./dir
|
||||
# [".xml" ".c"]'.
|
||||
# directory. E.g. `sourceFilesBySuffices ./dir [".xml" ".c"]'.
|
||||
sourceFilesBySuffices = path: exts:
|
||||
let filter = name: type:
|
||||
let base = baseNameOf (toString name);
|
||||
in type == "directory" || lib.any (ext: lib.hasSuffix ext base) exts;
|
||||
in type != "directory" && lib.any (ext: lib.hasSuffix ext base) exts;
|
||||
in builtins.filterSource filter path;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -62,8 +62,8 @@ rec {
|
||||
in { result = x.result ++ [entry.text] ++ y.result;
|
||||
done = y.done;
|
||||
}
|
||||
else if done ? ${entry} then f done (tail todo)
|
||||
else f (done // listToAttrs [{name = entry; value = 1;}]) ([predefined.${entry}] ++ tail todo);
|
||||
else if hasAttr entry done then f done (tail todo)
|
||||
else f (done // listToAttrs [{name = entry; value = 1;}]) ([(builtins.getAttr entry predefined)] ++ tail todo);
|
||||
in (f {} arg).result;
|
||||
|
||||
textClosureMap = f: predefined: names:
|
||||
|
||||
141
lib/strings.nix
141
lib/strings.nix
@@ -2,21 +2,17 @@
|
||||
|
||||
let lib = import ./default.nix;
|
||||
|
||||
inherit (builtins) length;
|
||||
inherit (builtins) add sub lessThan length;
|
||||
|
||||
in
|
||||
|
||||
rec {
|
||||
|
||||
inherit (builtins) stringLength substring head tail isString replaceStrings;
|
||||
inherit (builtins) stringLength substring head tail isString;
|
||||
|
||||
|
||||
# Concatenate a list of strings.
|
||||
concatStrings =
|
||||
if builtins ? concatStringsSep then
|
||||
builtins.concatStringsSep ""
|
||||
else
|
||||
lib.foldl' (x: y: x + y) "";
|
||||
concatStrings = lib.fold (x: y: x + y) "";
|
||||
|
||||
|
||||
# Map a function over a list and concatenate the resulting strings.
|
||||
@@ -29,16 +25,14 @@ rec {
|
||||
intersperse = separator: list:
|
||||
if list == [] || length list == 1
|
||||
then list
|
||||
else tail (lib.concatMap (x: [separator x]) list);
|
||||
else [(head list) separator]
|
||||
++ (intersperse separator (tail list));
|
||||
|
||||
|
||||
# Concatenate a list of strings with a separator between each element, e.g.
|
||||
# concatStringsSep " " ["foo" "bar" "xyzzy"] == "foo bar xyzzy"
|
||||
concatStringsSep = builtins.concatStringsSep or (separator: list:
|
||||
concatStrings (intersperse separator list));
|
||||
|
||||
concatMapStringsSep = sep: f: list: concatStringsSep sep (map f list);
|
||||
concatImapStringsSep = sep: f: list: concatStringsSep sep (lib.imap f list);
|
||||
concatStringsSep = separator: list:
|
||||
concatStrings (intersperse separator list);
|
||||
|
||||
|
||||
# Construct a Unix-style search path consisting of each `subDir"
|
||||
@@ -62,15 +56,12 @@ rec {
|
||||
optionalString = cond: string: if cond then string else "";
|
||||
|
||||
|
||||
# Determine whether a string has given prefix/suffix.
|
||||
hasPrefix = pref: str:
|
||||
substring 0 (stringLength pref) str == pref;
|
||||
hasSuffix = suff: str:
|
||||
let
|
||||
lenStr = stringLength str;
|
||||
lenSuff = stringLength suff;
|
||||
in lenStr >= lenSuff &&
|
||||
substring (lenStr - lenSuff) lenStr str == suff;
|
||||
# Determine whether a filename ends in the given suffix.
|
||||
hasSuffix = ext: fileName:
|
||||
let lenFileName = stringLength fileName;
|
||||
lenExt = stringLength ext;
|
||||
in !(lessThan lenFileName lenExt) &&
|
||||
substring (sub lenFileName lenExt) lenFileName fileName == ext;
|
||||
|
||||
|
||||
# Convert a string to a list of characters (i.e. singleton strings).
|
||||
@@ -79,75 +70,77 @@ rec {
|
||||
# will likely be horribly inefficient; Nix is not a general purpose
|
||||
# programming language. Complex string manipulations should, if
|
||||
# appropriate, be done in a derivation.
|
||||
stringToCharacters = s:
|
||||
map (p: substring p 1 s) (lib.range 0 (stringLength s - 1));
|
||||
stringToCharacters = s: let l = stringLength s; in
|
||||
if l == 0
|
||||
then []
|
||||
else map (p: substring p 1 s) (lib.range 0 (sub l 1));
|
||||
|
||||
|
||||
# Manipulate a string charactter by character and replace them by
|
||||
# strings before concatenating the results.
|
||||
# Manipulate a string charcater by character and replace them by strings
|
||||
# before concatenating the results.
|
||||
stringAsChars = f: s:
|
||||
concatStrings (
|
||||
map f (stringToCharacters s)
|
||||
);
|
||||
|
||||
|
||||
# Escape occurrence of the elements of ‘list’ in ‘string’ by
|
||||
# prefixing it with a backslash. For example, ‘escape ["(" ")"]
|
||||
# "(foo)"’ returns the string ‘\(foo\)’.
|
||||
escape = list: replaceChars list (map (c: "\\${c}") list);
|
||||
# same as vim escape function.
|
||||
# Each character contained in list is prefixed by "\"
|
||||
escape = list : string :
|
||||
stringAsChars (c: if lib.elem c list then "\\${c}" else c) string;
|
||||
|
||||
|
||||
# Escape all characters that have special meaning in the Bourne shell.
|
||||
# still ugly slow. But more correct now
|
||||
# [] for zsh
|
||||
escapeShellArg = lib.escape (stringToCharacters "\\ ';$`()|<>\t*[]");
|
||||
|
||||
|
||||
# Obsolete - use replaceStrings instead.
|
||||
replaceChars = builtins.replaceStrings or (
|
||||
del: new: s:
|
||||
# replace characters by their substitutes. This function is equivalent to
|
||||
# the `tr' command except that one character can be replace by multiple
|
||||
# ones. e.g.,
|
||||
# replaceChars ["<" ">"] ["<" ">"] "<foo>" returns "<foo>".
|
||||
replaceChars = del: new: s:
|
||||
let
|
||||
substList = lib.zipLists del new;
|
||||
subst = c:
|
||||
let found = lib.findFirst (sub: sub.fst == c) null substList; in
|
||||
if found == null then
|
||||
c
|
||||
else
|
||||
found.snd;
|
||||
(lib.fold
|
||||
(sub: res: if sub.fst == c then sub else res)
|
||||
{fst = c; snd = c;} (lib.zipLists del new)
|
||||
).snd;
|
||||
in
|
||||
stringAsChars subst s);
|
||||
stringAsChars subst s;
|
||||
|
||||
|
||||
# Case conversion utilities.
|
||||
# Case conversion utilities
|
||||
lowerChars = stringToCharacters "abcdefghijklmnopqrstuvwxyz";
|
||||
upperChars = stringToCharacters "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
toLower = replaceChars upperChars lowerChars;
|
||||
toUpper = replaceChars lowerChars upperChars;
|
||||
|
||||
|
||||
# Appends string context from another string.
|
||||
addContextFrom = a: b: substring 0 0 a + b;
|
||||
# Compares strings not requiring context equality
|
||||
# Obviously, a workaround but works on all Nix versions
|
||||
eqStrings = a: b: (a+(substring 0 0 b)) == ((substring 0 0 a)+b);
|
||||
|
||||
|
||||
# Cut a string with a separator and produces a list of strings which
|
||||
# were separated by this separator; e.g., `splitString "."
|
||||
# "foo.bar.baz"' returns ["foo" "bar" "baz"].
|
||||
splitString = _sep: _s:
|
||||
# Cut a string with a separator and produces a list of strings which were
|
||||
# separated by this separator. e.g.,
|
||||
# `splitString "." "foo.bar.baz"' returns ["foo" "bar" "baz"].
|
||||
splitString = sep: s:
|
||||
let
|
||||
sep = addContextFrom _s _sep;
|
||||
s = addContextFrom _sep _s;
|
||||
sepLen = stringLength sep;
|
||||
sLen = stringLength s;
|
||||
lastSearch = sLen - sepLen;
|
||||
lastSearch = sub sLen sepLen;
|
||||
startWithSep = startAt:
|
||||
substring startAt sepLen s == sep;
|
||||
|
||||
recurse = index: startAt:
|
||||
let cutUntil = i: [(substring startAt (i - startAt) s)]; in
|
||||
if index < lastSearch then
|
||||
let cutUntil = i: [(substring startAt (sub i startAt) s)]; in
|
||||
if lessThan index lastSearch then
|
||||
if startWithSep index then
|
||||
let restartAt = index + sepLen; in
|
||||
let restartAt = add index sepLen; in
|
||||
cutUntil index ++ recurse restartAt restartAt
|
||||
else
|
||||
recurse (index + 1) startAt
|
||||
recurse (add index 1) startAt
|
||||
else
|
||||
cutUntil sLen;
|
||||
in
|
||||
@@ -162,8 +155,8 @@ rec {
|
||||
preLen = stringLength pre;
|
||||
sLen = stringLength s;
|
||||
in
|
||||
if hasPrefix pre s then
|
||||
substring preLen (sLen - preLen) s
|
||||
if pre == substring 0 preLen s then
|
||||
substring preLen (sub sLen preLen) s
|
||||
else
|
||||
s;
|
||||
|
||||
@@ -191,36 +184,18 @@ rec {
|
||||
|
||||
|
||||
# Extract name with version from URL. Ask for separator which is
|
||||
# supposed to start extension.
|
||||
nameFromURL = url: sep:
|
||||
let
|
||||
components = splitString "/" url;
|
||||
filename = lib.last components;
|
||||
name = builtins.head (splitString sep filename);
|
||||
in assert name != filename; name;
|
||||
# supposed to start extension
|
||||
nameFromURL = url: sep: let
|
||||
components = splitString "/" url;
|
||||
filename = lib.last components;
|
||||
name = builtins.head (splitString sep filename);
|
||||
in
|
||||
assert ! eqStrings name filename;
|
||||
name;
|
||||
|
||||
|
||||
# Create an --{enable,disable}-<feat> string that can be passed to
|
||||
# standard GNU Autoconf scripts.
|
||||
enableFeature = enable: feat: "--${if enable then "enable" else "disable"}-${feat}";
|
||||
|
||||
|
||||
# Create a fixed width string with additional prefix to match
|
||||
# required width.
|
||||
fixedWidthString = width: filler: str:
|
||||
let
|
||||
strw = lib.stringLength str;
|
||||
reqWidth = width - (lib.stringLength filler);
|
||||
in
|
||||
assert strw <= width;
|
||||
if strw == width then str else filler + fixedWidthString reqWidth filler str;
|
||||
|
||||
|
||||
# Format a number adding leading zeroes up to fixed width.
|
||||
fixedWidthNumber = width: n: fixedWidthString width "0" (toString n);
|
||||
|
||||
|
||||
# Check whether a value is a store path.
|
||||
isStorePath = x: builtins.substring 0 1 (toString x) == "/" && dirOf (builtins.toPath x) == builtins.storeDir;
|
||||
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ rec {
|
||||
|
||||
isCpuType = x: isType "cpu-type" x
|
||||
&& elem x.bits [8 16 32 64 128]
|
||||
&& (8 < x.bits -> isSignificantByte x.significantByte);
|
||||
&& (builtins.lessThan 8 x.bits -> isSignificantByte x.significantByte);
|
||||
|
||||
cpuTypes = with significantBytes;
|
||||
setTypes "cpu-type" {
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# This script is used to test that the module system is working as expected.
|
||||
# By default it test the version of nixpkgs which is defined in the NIX_PATH.
|
||||
|
||||
cd ./modules
|
||||
|
||||
pass=0
|
||||
fail=0
|
||||
|
||||
evalConfig() {
|
||||
local attr=$1
|
||||
shift;
|
||||
local script="import ./default.nix { modules = [ $@ ];}"
|
||||
nix-instantiate --timeout 1 -E "$script" -A "$attr" --eval-only --show-trace
|
||||
}
|
||||
|
||||
reportFailure() {
|
||||
local attr=$1
|
||||
shift;
|
||||
local script="import ./default.nix { modules = [ $@ ];}"
|
||||
echo 2>&1 "$ nix-instantiate -E '$script' -A '$attr' --eval-only"
|
||||
evalConfig "$attr" "$@"
|
||||
fail=$((fail + 1))
|
||||
}
|
||||
|
||||
checkConfigOutput() {
|
||||
local outputContains=$1
|
||||
shift;
|
||||
if evalConfig "$@" 2>/dev/null | grep --silent "$outputContains" ; then
|
||||
pass=$((pass + 1))
|
||||
return 0;
|
||||
else
|
||||
echo 2>&1 "error: Expected result matching '$outputContains', while evaluating"
|
||||
reportFailure "$@"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
checkConfigError() {
|
||||
local errorContains=$1
|
||||
local err=""
|
||||
shift;
|
||||
if err==$(evalConfig "$@" 2>&1 >/dev/null); then
|
||||
echo 2>&1 "error: Expected error code, got exit code 0, while evaluating"
|
||||
reportFailure "$@"
|
||||
return 1
|
||||
else
|
||||
if echo "$err" | grep --silent "$errorContains" ; then
|
||||
pass=$((pass + 1))
|
||||
return 0;
|
||||
else
|
||||
echo 2>&1 "error: Expected error matching '$errorContains', while evaluating"
|
||||
reportFailure "$@"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Check boolean option.
|
||||
checkConfigOutput "false" config.enable ./declare-enable.nix
|
||||
checkConfigError 'The option .* defined in .* does not exist.' config.enable ./define-enable.nix
|
||||
|
||||
# Check mkForce without submodules.
|
||||
set -- config.enable ./declare-enable.nix ./define-enable.nix
|
||||
checkConfigOutput "true" "$@"
|
||||
checkConfigOutput "false" "$@" ./define-force-enable.nix
|
||||
checkConfigOutput "false" "$@" ./define-enable-force.nix
|
||||
|
||||
# Check mkForce with option and submodules.
|
||||
checkConfigError 'attribute .*foo.* .* not found' config.loaOfSub.foo.enable ./declare-loaOfSub-any-enable.nix
|
||||
checkConfigOutput 'false' config.loaOfSub.foo.enable ./declare-loaOfSub-any-enable.nix ./define-loaOfSub-foo.nix
|
||||
set -- config.loaOfSub.foo.enable ./declare-loaOfSub-any-enable.nix ./define-loaOfSub-foo-enable.nix
|
||||
checkConfigOutput 'true' "$@"
|
||||
checkConfigOutput 'false' "$@" ./define-force-loaOfSub-foo-enable.nix
|
||||
checkConfigOutput 'false' "$@" ./define-loaOfSub-force-foo-enable.nix
|
||||
checkConfigOutput 'false' "$@" ./define-loaOfSub-foo-force-enable.nix
|
||||
checkConfigOutput 'false' "$@" ./define-loaOfSub-foo-enable-force.nix
|
||||
|
||||
# Check overriding effect of mkForce on submodule definitions.
|
||||
checkConfigError 'attribute .*bar.* .* not found' config.loaOfSub.bar.enable ./declare-loaOfSub-any-enable.nix ./define-loaOfSub-foo.nix
|
||||
checkConfigOutput 'false' config.loaOfSub.bar.enable ./declare-loaOfSub-any-enable.nix ./define-loaOfSub-foo.nix ./define-loaOfSub-bar.nix
|
||||
set -- config.loaOfSub.bar.enable ./declare-loaOfSub-any-enable.nix ./define-loaOfSub-foo.nix ./define-loaOfSub-bar-enable.nix
|
||||
checkConfigOutput 'true' "$@"
|
||||
checkConfigError 'attribute .*bar.* .* not found' "$@" ./define-force-loaOfSub-foo-enable.nix
|
||||
checkConfigError 'attribute .*bar.* .* not found' "$@" ./define-loaOfSub-force-foo-enable.nix
|
||||
checkConfigOutput 'true' "$@" ./define-loaOfSub-foo-force-enable.nix
|
||||
checkConfigOutput 'true' "$@" ./define-loaOfSub-foo-enable-force.nix
|
||||
|
||||
# Check mkIf with submodules.
|
||||
checkConfigError 'attribute .*foo.* .* not found' config.loaOfSub.foo.enable ./declare-enable.nix ./declare-loaOfSub-any-enable.nix
|
||||
set -- config.loaOfSub.foo.enable ./declare-enable.nix ./declare-loaOfSub-any-enable.nix
|
||||
checkConfigError 'attribute .*foo.* .* not found' "$@" ./define-if-loaOfSub-foo-enable.nix
|
||||
checkConfigError 'attribute .*foo.* .* not found' "$@" ./define-loaOfSub-if-foo-enable.nix
|
||||
checkConfigError 'attribute .*foo.* .* not found' "$@" ./define-loaOfSub-foo-if-enable.nix
|
||||
checkConfigOutput 'false' "$@" ./define-loaOfSub-foo-enable-if.nix
|
||||
checkConfigOutput 'true' "$@" ./define-enable.nix ./define-if-loaOfSub-foo-enable.nix
|
||||
checkConfigOutput 'true' "$@" ./define-enable.nix ./define-loaOfSub-if-foo-enable.nix
|
||||
checkConfigOutput 'true' "$@" ./define-enable.nix ./define-loaOfSub-foo-if-enable.nix
|
||||
checkConfigOutput 'true' "$@" ./define-enable.nix ./define-loaOfSub-foo-enable-if.nix
|
||||
|
||||
# Check _module.args.
|
||||
set -- config.enable ./declare-enable.nix ./define-enable-with-custom-arg.nix
|
||||
checkConfigError 'while evaluating the module argument .*custom.* in .*define-enable-with-custom-arg.nix.*:' "$@"
|
||||
checkConfigOutput "true" "$@" ./define-_module-args-custom.nix
|
||||
|
||||
# Check that using _module.args on imports cause infinite recursions, with
|
||||
# the proper error context.
|
||||
set -- "$@" ./define-_module-args-custom.nix ./import-custom-arg.nix
|
||||
checkConfigError 'while evaluating the module argument .*custom.* in .*import-custom-arg.nix.*:' "$@"
|
||||
checkConfigError 'infinite recursion encountered' "$@"
|
||||
|
||||
# Check _module.check.
|
||||
set -- config.enable ./declare-enable.nix ./define-enable.nix ./define-loaOfSub-foo.nix
|
||||
checkConfigError 'The option .* defined in .* does not exist.' "$@"
|
||||
checkConfigOutput "true" "$@" ./define-module-check.nix
|
||||
|
||||
cat <<EOF
|
||||
====== module tests ======
|
||||
$pass Pass
|
||||
$fail Fail
|
||||
EOF
|
||||
|
||||
if test $fail -ne 0; then
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
@@ -1,14 +0,0 @@
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
options = {
|
||||
enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
type = lib.types.bool;
|
||||
description = ''
|
||||
Some descriptive text
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
{ lib, ... }:
|
||||
|
||||
let
|
||||
submod = { ... }: {
|
||||
options = {
|
||||
enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
type = lib.types.bool;
|
||||
description = ''
|
||||
Some descriptive text
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
|
||||
{
|
||||
options = {
|
||||
loaOfSub = lib.mkOption {
|
||||
default = {};
|
||||
example = {};
|
||||
type = lib.types.loaOf (lib.types.submodule [ submod ]);
|
||||
description = ''
|
||||
Some descriptive text
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{ lib ? import <nixpkgs/lib>, modules ? [] }:
|
||||
|
||||
{
|
||||
inherit (lib.evalModules {
|
||||
inherit modules;
|
||||
}) config options;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
config = {
|
||||
_module.args.custom = true;
|
||||
};
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
enable = lib.mkForce false;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{ lib, custom, ... }:
|
||||
|
||||
{
|
||||
config = {
|
||||
enable = custom;
|
||||
};
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
enable = true;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{ lib, ... }:
|
||||
|
||||
lib.mkForce {
|
||||
enable = false;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{ lib, ... }:
|
||||
|
||||
lib.mkForce {
|
||||
loaOfSub.foo.enable = false;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
lib.mkIf config.enable {
|
||||
loaOfSub.foo.enable = true;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
loaOfSub.bar.enable = true;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
loaOfSub.bar = {};
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
loaOfSub.foo.enable = lib.mkForce false;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
loaOfSub.foo.enable = lib.mkIf config.enable true;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
loaOfSub.foo.enable = true;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
loaOfSub.foo = lib.mkForce {
|
||||
enable = false;
|
||||
};
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
loaOfSub.foo = lib.mkIf config.enable {
|
||||
enable = true;
|
||||
};
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
loaOfSub.foo = {};
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
loaOfSub = lib.mkForce {
|
||||
foo.enable = false;
|
||||
};
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
loaOfSub = lib.mkIf config.enable {
|
||||
foo.enable = true;
|
||||
};
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
_module.check = false;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{ lib, custom, ... }:
|
||||
|
||||
{
|
||||
imports = []
|
||||
++ lib.optional custom ./define-enable-force.nix;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
{ nixpkgs }:
|
||||
|
||||
with import ./../.. { };
|
||||
with lib;
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "nixpkgs-lib-tests";
|
||||
buildInputs = [ nix ];
|
||||
NIX_PATH="nixpkgs=${nixpkgs}";
|
||||
|
||||
buildCommand = ''
|
||||
datadir="${nix}/share"
|
||||
export TEST_ROOT=$(pwd)/test-tmp
|
||||
export NIX_STORE_DIR=$TEST_ROOT/store
|
||||
export NIX_LOCALSTATE_DIR=$TEST_ROOT/var
|
||||
export NIX_LOG_DIR=$TEST_ROOT/var/log/nix
|
||||
export NIX_STATE_DIR=$TEST_ROOT/var/nix
|
||||
export NIX_DB_DIR=$TEST_ROOT/db
|
||||
export NIX_CONF_DIR=$TEST_ROOT/etc
|
||||
export NIX_MANIFESTS_DIR=$TEST_ROOT/var/nix/manifests
|
||||
export NIX_BUILD_HOOK=
|
||||
export PAGER=cat
|
||||
cacheDir=$TEST_ROOT/binary-cache
|
||||
nix-store --init
|
||||
|
||||
cd ${nixpkgs}/lib/tests
|
||||
./modules.sh
|
||||
|
||||
touch $out
|
||||
'';
|
||||
}
|
||||
@@ -1,3 +1,8 @@
|
||||
with {
|
||||
inherit (import ./lists.nix) deepSeqList;
|
||||
inherit (import ./attrsets.nix) deepSeqAttrs;
|
||||
};
|
||||
|
||||
rec {
|
||||
|
||||
# Identity function.
|
||||
@@ -18,11 +23,23 @@ rec {
|
||||
# Flip the order of the arguments of a binary function.
|
||||
flip = f: a: b: f b a;
|
||||
|
||||
# `seq x y' evaluates x, then returns y. That is, it forces strict
|
||||
# evaluation of its first argument.
|
||||
seq = x: y: if x == null then y else y;
|
||||
|
||||
# Like `seq', but recurses into lists and attribute sets to force evaluation
|
||||
# of all list elements/attributes.
|
||||
deepSeq = x: y:
|
||||
if builtins.isList x
|
||||
then deepSeqList x y
|
||||
else if builtins.isAttrs x
|
||||
then deepSeqAttrs x y
|
||||
else seq x y;
|
||||
|
||||
# Pull in some builtins not included elsewhere.
|
||||
inherit (builtins)
|
||||
pathExists readFile isBool isFunction
|
||||
isInt add sub lessThan
|
||||
seq deepSeq genericClosure;
|
||||
isInt add sub lessThan;
|
||||
|
||||
# Return the Nixpkgs version number.
|
||||
nixpkgsVersion =
|
||||
@@ -30,11 +47,7 @@ rec {
|
||||
readFile ../.version
|
||||
+ (if pathExists suffixFile then readFile suffixFile else "pre-git");
|
||||
|
||||
# Whether we're being called by nix-shell.
|
||||
# Whether we're being called by nix-shell. This is useful to
|
||||
inNixShell = builtins.getEnv "IN_NIX_SHELL" == "1";
|
||||
|
||||
# Return minimum/maximum of two numbers.
|
||||
min = x: y: if x < y then x else y;
|
||||
max = x: y: if x > y then x else y;
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ with import ./attrsets.nix;
|
||||
with import ./options.nix;
|
||||
with import ./trivial.nix;
|
||||
with import ./strings.nix;
|
||||
with {inherit (import ./modules.nix) mergeDefinitions filterOverrides; };
|
||||
|
||||
rec {
|
||||
|
||||
@@ -34,14 +33,9 @@ rec {
|
||||
, # Return a flat list of sub-options. Used to generate
|
||||
# documentation.
|
||||
getSubOptions ? prefix: {}
|
||||
, # List of modules if any, or null if none.
|
||||
getSubModules ? null
|
||||
, # Function for building the same option type with a different list of
|
||||
# modules.
|
||||
substSubModules ? m: null
|
||||
}:
|
||||
{ _type = "option-type";
|
||||
inherit name check merge getSubOptions getSubModules substSubModules;
|
||||
inherit name check merge getSubOptions;
|
||||
};
|
||||
|
||||
|
||||
@@ -54,7 +48,7 @@ rec {
|
||||
bool = mkOptionType {
|
||||
name = "boolean";
|
||||
check = isBool;
|
||||
merge = mergeEqualOption;
|
||||
merge = loc: fold (x: y: x.value || y) false;
|
||||
};
|
||||
|
||||
int = mkOptionType {
|
||||
@@ -88,22 +82,20 @@ rec {
|
||||
attrs = mkOptionType {
|
||||
name = "attribute set";
|
||||
check = isAttrs;
|
||||
merge = loc: foldl' (res: def: mergeAttrs res def.value) {};
|
||||
merge = loc: fold (def: mergeAttrs def.value) {};
|
||||
};
|
||||
|
||||
# derivation is a reserved keyword.
|
||||
package = mkOptionType {
|
||||
name = "derivation";
|
||||
check = x: isDerivation x || isStorePath x;
|
||||
merge = loc: defs:
|
||||
let res = mergeOneOption loc defs;
|
||||
in if isDerivation res then res else toDerivation res;
|
||||
check = isDerivation;
|
||||
merge = mergeOneOption;
|
||||
};
|
||||
|
||||
path = mkOptionType {
|
||||
name = "path";
|
||||
# Hacky: there is no ‘isPath’ primop.
|
||||
check = x: builtins.substring 0 1 (toString x) == "/";
|
||||
check = x: builtins.unsafeDiscardStringContext (builtins.substring 0 1 (toString x)) == "/";
|
||||
merge = mergeOneOption;
|
||||
};
|
||||
|
||||
@@ -112,33 +104,23 @@ rec {
|
||||
|
||||
listOf = elemType: mkOptionType {
|
||||
name = "list of ${elemType.name}s";
|
||||
check = isList;
|
||||
check = value: isList value && all elemType.check value;
|
||||
merge = loc: defs:
|
||||
map (x: x.value) (filter (x: x ? value) (concatLists (imap (n: def: imap (m: def':
|
||||
(mergeDefinitions
|
||||
(loc ++ ["[definition ${toString n}-entry ${toString m}]"])
|
||||
elemType
|
||||
[{ inherit (def) file; value = def'; }]
|
||||
).optionalValue
|
||||
) def.value) defs)));
|
||||
concatLists (imap (n: def: imap (m: def':
|
||||
elemType.merge (loc ++ ["[${toString n}-${toString m}]"])
|
||||
[{ inherit (def) file; value = def'; }]) def.value) defs);
|
||||
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["*"]);
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = m: listOf (elemType.substSubModules m);
|
||||
};
|
||||
|
||||
attrsOf = elemType: mkOptionType {
|
||||
name = "attribute set of ${elemType.name}s";
|
||||
check = isAttrs;
|
||||
check = x: isAttrs x && all elemType.check (attrValues x);
|
||||
merge = loc: defs:
|
||||
mapAttrs (n: v: v.value) (filterAttrs (n: v: v ? value) (zipAttrsWith (name: defs:
|
||||
(mergeDefinitions (loc ++ [name]) elemType defs).optionalValue
|
||||
)
|
||||
zipAttrsWith (name: elemType.merge (loc ++ [name]))
|
||||
# Push down position info.
|
||||
(map (def: listToAttrs (mapAttrsToList (n: def':
|
||||
{ name = n; value = { inherit (def) file; value = def'; }; }) def.value)) defs)));
|
||||
{ name = n; value = { inherit (def) file; value = def'; }; }) def.value)) defs);
|
||||
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name>"]);
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = m: attrsOf (elemType.substSubModules m);
|
||||
};
|
||||
|
||||
# List or attribute set of ...
|
||||
@@ -159,36 +141,18 @@ rec {
|
||||
attrOnly = attrsOf elemType;
|
||||
in mkOptionType {
|
||||
name = "list or attribute set of ${elemType.name}s";
|
||||
check = x: isList x || isAttrs x;
|
||||
check = x:
|
||||
if isList x then listOnly.check x
|
||||
else if isAttrs x then attrOnly.check x
|
||||
else false;
|
||||
merge = loc: defs: attrOnly.merge loc (imap convertIfList defs);
|
||||
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name?>"]);
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = m: loaOf (elemType.substSubModules m);
|
||||
};
|
||||
|
||||
# List or element of ...
|
||||
loeOf = elemType: mkOptionType {
|
||||
name = "element or list of ${elemType.name}s";
|
||||
check = x: isList x || elemType.check x;
|
||||
merge = loc: defs:
|
||||
let
|
||||
defs' = filterOverrides defs;
|
||||
res = (head defs').value;
|
||||
in
|
||||
if isList res then concatLists (getValues defs')
|
||||
else if lessThan 1 (length defs') then
|
||||
throw "The option `${showOption loc}' is defined multiple times, in ${showFiles (getFiles defs)}."
|
||||
else if !isString res then
|
||||
throw "The option `${showOption loc}' does not have a string value, in ${showFiles (getFiles defs)}."
|
||||
else res;
|
||||
};
|
||||
|
||||
uniq = elemType: mkOptionType {
|
||||
inherit (elemType) name check;
|
||||
merge = mergeOneOption;
|
||||
getSubOptions = elemType.getSubOptions;
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = m: uniq (elemType.substSubModules m);
|
||||
};
|
||||
|
||||
nullOr = elemType: mkOptionType {
|
||||
@@ -201,8 +165,14 @@ rec {
|
||||
throw "The option `${showOption loc}' is defined both null and not null, in ${showFiles (getFiles defs)}."
|
||||
else elemType.merge loc defs;
|
||||
getSubOptions = elemType.getSubOptions;
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = m: nullOr (elemType.substSubModules m);
|
||||
};
|
||||
|
||||
functionTo = elemType: mkOptionType {
|
||||
name = "function that evaluates to a(n) ${elemType.name}";
|
||||
check = isFunction;
|
||||
merge = loc: defs:
|
||||
fnArgs: elemType.merge loc (map (fn: { inherit (fn) file; value = fn.value fnArgs; }) defs);
|
||||
getSubOptions = elemType.getSubOptions;
|
||||
};
|
||||
|
||||
submodule = opts:
|
||||
@@ -217,17 +187,11 @@ rec {
|
||||
let
|
||||
coerce = def: if isFunction def then def else { config = def; };
|
||||
modules = opts' ++ map (def: { _file = def.file; imports = [(coerce def.value)]; }) defs;
|
||||
in (evalModules {
|
||||
inherit modules;
|
||||
args.name = last loc;
|
||||
prefix = loc;
|
||||
}).config;
|
||||
in (evalModules { inherit modules; args.name = last loc; prefix = loc; }).config;
|
||||
getSubOptions = prefix: (evalModules
|
||||
{ modules = opts'; inherit prefix;
|
||||
# FIXME: hack to get shit to evaluate.
|
||||
args = { name = ""; }; }).options;
|
||||
getSubModules = opts';
|
||||
substSubModules = m: submodule m;
|
||||
};
|
||||
|
||||
enum = values: mkOptionType {
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
*~
|
||||
,*
|
||||
.*.swp
|
||||
.*.swo
|
||||
result
|
||||
result-*
|
||||
/doc/NEWS.html
|
||||
/doc/NEWS.txt
|
||||
/doc/manual.html
|
||||
/doc/manual.pdf
|
||||
.version-suffix
|
||||
|
||||
.DS_Store
|
||||
.git
|
||||
@@ -1,12 +0,0 @@
|
||||
FROM busybox
|
||||
|
||||
RUN dir=`mktemp -d` && trap 'rm -rf "$dir"' EXIT && \
|
||||
wget -O- https://nixos.org/releases/nix/nix-1.7/nix-1.7-x86_64-linux.tar.bz2 | bzcat | tar x -C $dir && \
|
||||
mkdir -m 0755 /nix && USER=root sh $dir/*/install && \
|
||||
echo ". /root/.nix-profile/etc/profile.d/nix.sh" >> /etc/profile
|
||||
|
||||
ADD . /root/nix/nixpkgs
|
||||
ONBUILD ENV NIX_PATH nixpkgs=/root/nix/nixpkgs:nixos=/root/nix/nixpkgs/nixos
|
||||
ONBUILD ENV PATH /root/.nix-profile/bin:/root/.nix-profile/sbin:/bin:/sbin:/usr/bin:/usr/sbin
|
||||
ONBUILD ENV ENV /etc/profile
|
||||
ENV ENV /etc/profile
|
||||
95
maintainers/scripts/gnome-latest.sh
Executable file
95
maintainers/scripts/gnome-latest.sh
Executable file
@@ -0,0 +1,95 @@
|
||||
#!/bin/sh
|
||||
|
||||
GNOME_FTP="ftp.gnome.org/pub/GNOME/sources"
|
||||
|
||||
project=$1
|
||||
|
||||
if [ "$project" == "--help" ]; then
|
||||
echo "Usage: $0 project [major.minor]"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
baseVersion=$2
|
||||
|
||||
if [ -z "$project" ]; then
|
||||
echo "No project specified, exiting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# curl -l ftp://... doesn't work from my office in HSE, and I don't want to have
|
||||
# any conversations with sysadmin. Somehow lftp works.
|
||||
if [ "$FTP_CLIENT" = "lftp" ]; then
|
||||
ls_ftp() {
|
||||
lftp -c "open $1; cls"
|
||||
}
|
||||
else
|
||||
ls_ftp() {
|
||||
curl -l "$1"/
|
||||
}
|
||||
fi
|
||||
|
||||
if [ -z "$baseVersion" ]; then
|
||||
echo "Looking for available versions..." >&2
|
||||
available_baseversions=( `ls_ftp ftp://${GNOME_FTP}/${project} | grep '[0-9]\.[0-9]' | sort -t. -k1,1n -k 2,2n` )
|
||||
echo -e "The following versions are available:\n ${available_baseversions[@]}" >&2
|
||||
echo -en "Choose one of them: " >&2
|
||||
read baseVersion
|
||||
fi
|
||||
|
||||
FTPDIR="${GNOME_FTP}/${project}/${baseVersion}"
|
||||
|
||||
#version=`curl -l ${FTPDIR}/ 2>/dev/null | grep LATEST-IS | sed -e s/LATEST-IS-//`
|
||||
# gnome's LATEST-IS is broken. Do not trust it.
|
||||
|
||||
files=$(ls_ftp "${FTPDIR}")
|
||||
declare -A versions
|
||||
|
||||
for f in $files; do
|
||||
case $f in
|
||||
(LATEST-IS-*|*.news|*.changes|*.sha256sum|*.diff*):
|
||||
;;
|
||||
($project-*.*.9*.tar.*):
|
||||
tmp=${f#$project-}
|
||||
tmp=${tmp%.tar*}
|
||||
echo "Ignored unstable version ${tmp}" >&2
|
||||
;;
|
||||
($project-*.tar.*):
|
||||
tmp=${f#$project-}
|
||||
tmp=${tmp%.tar*}
|
||||
versions[${tmp}]=1
|
||||
;;
|
||||
(*):
|
||||
echo "UNKNOWN FILE $f"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
echo "Found versions ${!versions[@]}" >&2
|
||||
version=`echo ${!versions[@]} | sed -e 's/ /\n/g' | sort -t. -k1,1n -k 2,2n -k 3,3n | tail -n1`
|
||||
echo "Latest version is: ${version}" >&2
|
||||
|
||||
name=${project}-${version}
|
||||
echo "Fetching .sha256 file" >&2
|
||||
curl -O http://${FTPDIR}/${name}.sha256sum
|
||||
|
||||
extensions=( "xz" "bz2" "gz" )
|
||||
echo "Choosing archive extension (known are ${extensions[@]})..." >&2
|
||||
for ext in ${extensions[@]}; do
|
||||
if grep "\\.tar\\.${ext}$" ${name}.sha256sum >& /dev/null; then
|
||||
ext_pref=$ext
|
||||
sha256=$(grep "\\.tar\\.${ext}$" ${name}.sha256sum | cut -f1 -d\ )
|
||||
break
|
||||
fi
|
||||
done
|
||||
sha256=`nix-hash --to-base32 --type sha256 $sha256`
|
||||
echo "Chosen ${ext_pref}, hash is ${sha256}" >&2
|
||||
|
||||
cat <<EOF
|
||||
name = "${project}-${version}";
|
||||
|
||||
src = fetchurl {
|
||||
url = mirror://gnome/sources/${project}/${baseVersion}/${project}-${version}.tar.${ext_pref};
|
||||
sha256 = "${sha256}";
|
||||
};
|
||||
EOF
|
||||
|
||||
rm -v ${name}.sha256sum >&2
|
||||
@@ -1,138 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -o pipefail
|
||||
|
||||
GNOME_FTP="ftp.gnome.org/pub/GNOME/sources"
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 show|update project [major.minor]" >&2
|
||||
exit 0
|
||||
}
|
||||
|
||||
if [ "$#" -lt 1 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
action="$1"
|
||||
project="$2"
|
||||
majorVersion="$3"
|
||||
|
||||
if [ "$action" != "show" ] && [ "$action" != "update" ]; then
|
||||
echo "Unknown action $action" >&2
|
||||
usage
|
||||
fi
|
||||
|
||||
if [ -z "$project" ]; then
|
||||
echo "No project specified, exiting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# curl -l ftp://... doesn't work from my office in HSE, and I don't want to have
|
||||
# any conversations with sysadmin. Somehow lftp works.
|
||||
if [ "$FTP_CLIENT" = "lftp" ]; then
|
||||
ls_ftp() {
|
||||
lftp -c "open $1; cls"
|
||||
}
|
||||
else
|
||||
ls_ftp() {
|
||||
curl -s -l "$1"/
|
||||
}
|
||||
fi
|
||||
|
||||
if [ -z "$majorVersion" ]; then
|
||||
echo "Looking for available versions..." >&2
|
||||
available_baseversions=( `ls_ftp ftp://${GNOME_FTP}/${project} | grep '[0-9]\.[0-9]' | sort -t. -k1,1n -k 2,2n` )
|
||||
if [ "$?" -ne "0" ]; then
|
||||
echo "Project $project not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "The following versions are available:\n ${available_baseversions[@]}" >&2
|
||||
echo -en "Choose one of them: " >&2
|
||||
read majorVersion
|
||||
fi
|
||||
|
||||
if echo "$majorVersion" | grep -q "[0-9]\+\.[0-9]\+\.[0-9]\+"; then
|
||||
# not a major version
|
||||
version="$majorVersion"
|
||||
majorVersion=$(echo "$majorVersion" | cut -d '.' -f 1,2)
|
||||
fi
|
||||
|
||||
FTPDIR="${GNOME_FTP}/${project}/${majorVersion}"
|
||||
|
||||
#version=`curl -l ${FTPDIR}/ 2>/dev/null | grep LATEST-IS | sed -e s/LATEST-IS-//`
|
||||
# gnome's LATEST-IS is broken. Do not trust it.
|
||||
|
||||
if [ -z "$version" ]; then
|
||||
files=$(ls_ftp "${FTPDIR}")
|
||||
declare -A versions
|
||||
|
||||
for f in $files; do
|
||||
case $f in
|
||||
(LATEST-IS-*|*.news|*.changes|*.sha256sum|*.diff*):
|
||||
;;
|
||||
($project-*.*.9*.tar.*):
|
||||
tmp=${f#$project-}
|
||||
tmp=${tmp%.tar*}
|
||||
echo "Ignored unstable version ${tmp}" >&2
|
||||
;;
|
||||
($project-*.tar.*):
|
||||
tmp=${f#$project-}
|
||||
tmp=${tmp%.tar*}
|
||||
versions[${tmp}]=1
|
||||
;;
|
||||
(*):
|
||||
echo "UNKNOWN FILE $f"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
echo "Found versions ${!versions[@]}" >&2
|
||||
version=`echo ${!versions[@]} | sed -e 's/ /\n/g' | sort -t. -k1,1n -k 2,2n -k 3,3n | tail -n1`
|
||||
echo "Latest version is: ${version}" >&2
|
||||
fi
|
||||
|
||||
name=${project}-${version}
|
||||
echo "Fetching .sha256 file" >&2
|
||||
sha256out=$(curl -s -f http://${FTPDIR}/${name}.sha256sum)
|
||||
|
||||
if [ "$?" -ne "0" ]; then
|
||||
echo "Version not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
extensions=( "xz" "bz2" "gz" )
|
||||
echo "Choosing archive extension (known are ${extensions[@]})..." >&2
|
||||
for ext in ${extensions[@]}; do
|
||||
if echo -e "$sha256out" | grep -q "\\.tar\\.${ext}$"; then
|
||||
ext_pref=$ext
|
||||
sha256=$(echo -e "$sha256out" | grep "\\.tar\\.${ext}$" | cut -f1 -d\ )
|
||||
break
|
||||
fi
|
||||
done
|
||||
echo "Chosen ${ext_pref}, hash is ${sha256}" >&2
|
||||
|
||||
src="# Autogenerated by maintainers/scripts/gnome.sh update
|
||||
|
||||
fetchurl: {
|
||||
name = \"${project}-${version}\";
|
||||
|
||||
src = fetchurl {
|
||||
url = mirror://gnome/sources/${project}/${majorVersion}/${project}-${version}.tar.${ext_pref};
|
||||
sha256 = \"${sha256}\";
|
||||
};
|
||||
}"
|
||||
|
||||
if [ "$action" == "update" ]; then
|
||||
# find project in nixpkgs tree
|
||||
GNOME_TOP=$(readlink -e $(dirname "${BASH_SOURCE[0]}")"/../../pkgs/desktops/gnome-3/")
|
||||
projectPath=$(find "$GNOME_TOP" -name "$project" -print)
|
||||
if [ -z "$projectPath" ]; then
|
||||
echo "Project $project not found under $GNOME_TOP"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Updating $projectPath/src.nix"
|
||||
echo -e "$src" > "$projectPath/src.nix"
|
||||
else
|
||||
echo -e "\n$src"
|
||||
fi
|
||||
@@ -6,7 +6,6 @@ hydra_eval_jobs \
|
||||
--argstr system i686-linux \
|
||||
--argstr system x86_64-darwin \
|
||||
--argstr system i686-cygwin \
|
||||
--argstr system x86_64-cygwin \
|
||||
--argstr system i686-freebsd \
|
||||
--arg officialRelease false \
|
||||
--arg nixpkgs "{ outPath = builtins.storePath ./. ; rev = 1234; }" \
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
stdenv.mkDerivation {
|
||||
name = "nix-generate-from-cpan-1";
|
||||
|
||||
buildInputs = [ makeWrapper perl perlPackages.YAMLLibYAML perlPackages.JSON perlPackages.CPANPLUS ];
|
||||
buildInputs = [ makeWrapper perl perlPackages.YAMLLibYAML perlPackages.JSON ];
|
||||
|
||||
unpackPhase = "true";
|
||||
buildPhase = "true";
|
||||
@@ -19,4 +19,4 @@ stdenv.mkDerivation {
|
||||
maintainers = [ stdenv.lib.maintainers.eelco ];
|
||||
description = "Utility to generate a Nix expression for a Perl package from CPAN";
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -100,7 +100,7 @@ sub get_deps {
|
||||
foreach my $n (keys %{$deps}) {
|
||||
next if $n eq "perl";
|
||||
# Hacky way to figure out if this module is part of Perl.
|
||||
if ($n !~ /^JSON/ && $n !~ /^YAML/ && $n !~ /^Module::Pluggable/) {
|
||||
if ($n !~ /^JSON/ && $n !~ /^YAML/) {
|
||||
eval "use $n;";
|
||||
if (!$@) {
|
||||
print STDERR "skipping Perl-builtin module $n\n";
|
||||
|
||||
@@ -62,7 +62,7 @@ for bin in $(find $binaryDist -executable -type f) :; do
|
||||
)
|
||||
|
||||
if test "$names" = "glibc"; then names="stdenv.glibc"; fi
|
||||
if echo $names | grep -c "gcc" &> /dev/null; then names="stdenv.cc.cc"; fi
|
||||
if echo $names | grep -c "gcc" &> /dev/null; then names="stdenv.gcc.gcc"; fi
|
||||
|
||||
if test $lib != $libPath; then
|
||||
interpreter="--interpreter \${$names}/lib/$lib"
|
||||
|
||||
146
maintainers/scripts/sort-attrs.str
Normal file
146
maintainers/scripts/sort-attrs.str
Normal file
@@ -0,0 +1,146 @@
|
||||
/* Tool to sort attribute sets. Primarily useful for keeping
|
||||
all-packages.nix tidy.
|
||||
|
||||
To compile:
|
||||
|
||||
$ strc -i ../../maintainers/scripts/sort-attrs.str -la stratego-lib
|
||||
|
||||
Typical invocation:
|
||||
|
||||
$ sglr -m -p ~/Dev/nix/src/libexpr/nix.tbl -i all-packages.nix \
|
||||
| implode-asfix --lex \
|
||||
| ../../maintainers/scripts/sort-attrs \
|
||||
| asfix-yield
|
||||
*/
|
||||
|
||||
module sort-attrs
|
||||
|
||||
imports
|
||||
libstratego-lib
|
||||
libstratego-sglr
|
||||
|
||||
|
||||
strategies
|
||||
|
||||
no-wsp = !appl(prod([], cf(opt(layout())), no-attrs()), [])
|
||||
|
||||
|
||||
rules
|
||||
|
||||
list-sep(s): [] -> []
|
||||
list-sep(s): [x | xs] -> [[x | before] | <list-sep(s)> [split | after]]
|
||||
where
|
||||
<split-fetch-keep(s)> xs => (before, split, after)
|
||||
list-sep(s): [x | xs] -> [[x | xs]]
|
||||
where
|
||||
<not(split-fetch-keep(s))> xs
|
||||
|
||||
list-sep-end(s): xs -> [<conc> (before, [split]) | <list-sep-end(s)> after]
|
||||
where
|
||||
<split-fetch-keep(s)> xs => (before, split, after)
|
||||
list-sep-end(s): xs -> [xs]
|
||||
where
|
||||
<not(split-fetch-keep(s))> xs
|
||||
|
||||
|
||||
sort-attrs:
|
||||
appl(p@prod(_, _, attrs([term(cons("Attrs"))])),
|
||||
[ lit("{")
|
||||
, ws1
|
||||
, appl(p2@list(cf(iter-star(sort("Bind")))), attrs)
|
||||
, ws2
|
||||
, lit("}")
|
||||
]
|
||||
) ->
|
||||
appl(p, [lit("{"), <no-wsp>, appl(p2, <concat> attrs'), ws2, lit("}")])
|
||||
where
|
||||
<debug> "found it";
|
||||
<attach-wsp> [ws1 | attrs] => withWSP;
|
||||
<list-sep(starts-section)> withWSP => groups;
|
||||
<length; debug> groups;
|
||||
<map({x', x'', x''', xs', starts, starts': \[x | xs] -> [x''' | xs']
|
||||
where
|
||||
<remove-section-start> x => (x', starts);
|
||||
<map(regularise-empty-lines); if !starts; debug; sortable-section; debug then qsort(compare-attrs) else id end> [x' | xs] => [x'' | xs'];
|
||||
<[] <+ \x -> ["\n\n\n" | x]\ > starts => starts';
|
||||
<prepend-layout> (starts', x'') => x'''
|
||||
\ })> groups => attrs';
|
||||
<debug> "did it"
|
||||
|
||||
|
||||
attach-wsp: [a, b | cs] -> [(a, b) | <attach-wsp> cs]
|
||||
attach-wsp: [] -> []
|
||||
|
||||
|
||||
strategies
|
||||
|
||||
starts-section =
|
||||
?x@(appl(prod([cf(layout())], cf(opt(layout())), no-attrs()), cs), attr);
|
||||
<implode-string; is-substring(!"###")> cs;
|
||||
!x
|
||||
|
||||
rules
|
||||
|
||||
|
||||
sortable-section = ?[s]; !s; explode-string; not(fetch({x: ?x; !(x, 97); geq}))
|
||||
|
||||
|
||||
remove-section-start:
|
||||
(appl(prod([cf(layout())], cf(opt(layout())), no-attrs()), cs), attr) ->
|
||||
((appl(prod([cf(layout())], cf(opt(layout())), no-attrs()), cs'), attr), starts)
|
||||
where
|
||||
!cs;
|
||||
list-sep-end(?10); // separate into lines, keeping the \n
|
||||
map(implode-string);
|
||||
partition(where(is-substring(!"###"))) => (starts, rest);
|
||||
<map(explode-string); concat> rest => cs'
|
||||
|
||||
|
||||
regularise-empty-lines:
|
||||
(appl(prod([cf(layout())], cf(opt(layout())), no-attrs()), cs), attr) ->
|
||||
(appl(prod([cf(layout())], cf(opt(layout())), no-attrs()), cs''), attr)
|
||||
where
|
||||
// separate into lines, keeping the \n
|
||||
// last whitespace is significant, keep
|
||||
<list-sep-end(?10); split-init-last> cs => (init, last);
|
||||
<regularise-empty-lines'> init => cs'; // remove whitespace-only lines
|
||||
<concat> [<explode-string> "\n\n", <concat> cs', last] => cs'' // add one empty line
|
||||
|
||||
/* Dirty hack: *do* keep the first empty line following a non-empty line. !!! order matters */
|
||||
regularise-empty-lines': [] -> []
|
||||
|
||||
regularise-empty-lines': [x, y | xs] -> [x, y | <regularise-empty-lines'> xs]
|
||||
where
|
||||
<fetch-elem(not(?10 <+ ?32))> x;
|
||||
<not(fetch-elem(not(?10 <+ ?32)))> y
|
||||
|
||||
regularise-empty-lines': [x | xs] -> [x | <regularise-empty-lines'> xs]
|
||||
where <fetch-elem(not(?10 <+ ?32))> x
|
||||
|
||||
regularise-empty-lines': [x | xs] -> <regularise-empty-lines'> xs
|
||||
where <not(fetch-elem(not(?10 <+ ?32)))> x
|
||||
|
||||
|
||||
prepend-layout:
|
||||
(text, (appl(prod([cf(layout())], cf(opt(layout())), no-attrs()), cs), attr)) ->
|
||||
(appl(prod([cf(layout())], cf(opt(layout())), no-attrs()), cs''), attr)
|
||||
where
|
||||
<implode-string> cs => cs';
|
||||
<conc-strings; explode-string> (<concat-strings> text, cs') => cs''
|
||||
|
||||
|
||||
compare-attrs:
|
||||
x@
|
||||
( (_, appl(p1@prod(_, _, attrs([term(cons("Bind"))])), [id1 | xs1]))
|
||||
, (_, appl(p2@prod(_, _, attrs([term(cons("Bind"))])), [id2 | xs2]))
|
||||
)
|
||||
-> x
|
||||
where
|
||||
<string-lt> (id1, id2)
|
||||
|
||||
|
||||
strategies
|
||||
|
||||
main = io-wrap(
|
||||
oncetd(sort-attrs)
|
||||
)
|
||||
@@ -28,21 +28,14 @@ elif [[ $1 == build ]]; then
|
||||
source $HOME/.nix-profile/etc/profile.d/nix.sh
|
||||
|
||||
if [[ $TRAVIS_PULL_REQUEST == false ]]; then
|
||||
echo "=== Not a pull request"
|
||||
echo "===> Not a pull request, checking evaluation"
|
||||
nix-build pkgs/top-level/release.nix -A tarball
|
||||
else
|
||||
echo "=== Checking PR"
|
||||
|
||||
if ! nox-review pr ${TRAVIS_PULL_REQUEST}; then
|
||||
if sudo dmesg | egrep 'Out of memory|Killed process' > /tmp/oom-log; then
|
||||
echo "=== The build failed due to running out of memory:"
|
||||
cat /tmp/oom-log
|
||||
echo "=== Please disregard the result of this Travis build."
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
# The current HEAD is the PR merged into origin/master, so we compare
|
||||
# against origin/master
|
||||
nox-review wip --against origin/master
|
||||
fi
|
||||
# echo "=== Checking tarball creation"
|
||||
# nix-build pkgs/top-level/release.nix -A tarball
|
||||
else
|
||||
echo "$0: Unknown option $1" >&2
|
||||
false
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
: ${NIXOS_CHANNELS:=https://nixos.org/channels/}
|
||||
: ${CHANNELS_NAMESPACE:=refs/heads/channels/}
|
||||
|
||||
# List all channels which are currently in the repository which we would
|
||||
# have to remove if they are not found again.
|
||||
deadChannels=$(git for-each-ref --format="%(refname)" "$CHANNELS_NAMESPACE")
|
||||
|
||||
updateRef() {
|
||||
local channelName=$1
|
||||
local newRev=$2
|
||||
|
||||
# if the inputs are not valid, then we do not update any branch.
|
||||
test -z "$newRev" -o -z "$channelName" && return;
|
||||
|
||||
# Update the local refs/heads/channels/* branches to be in-sync with the
|
||||
# channel references.
|
||||
local branch=$CHANNELS_NAMESPACE$channelName
|
||||
oldRev=$(git rev-parse --short "$branch" 2>/dev/null || true)
|
||||
if test "$oldRev" != "$newRev"; then
|
||||
if git update-ref "$branch" "$newRev" 2>/dev/null; then
|
||||
if test -z "$oldRev"; then
|
||||
echo " * [new branch] $newRev -> ${branch#refs/heads/}"
|
||||
else
|
||||
echo " $oldRev..$newRev -> ${branch#refs/heads/}"
|
||||
fi
|
||||
else
|
||||
if test -z "$oldRev"; then
|
||||
echo " * [missing rev] $newRev -> ${branch#refs/heads/}"
|
||||
else
|
||||
echo " [missing rev] $oldRev..$newRev -> ${branch#refs/heads/}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Filter out the current channel from the list of dead channels.
|
||||
deadChannels=$(grep -v "$CHANNELS_NAMESPACE$channelName" <<EOF
|
||||
$deadChannels
|
||||
EOF
|
||||
) ||true
|
||||
}
|
||||
|
||||
# Find the name of all channels which are listed in the directory.
|
||||
echo "Fetching channels from $NIXOS_CHANNELS:"
|
||||
for channelName in : $(curl -s "$NIXOS_CHANNELS" | sed -n '/folder/ { s,.*href=",,; s,/".*,,; p }'); do
|
||||
test "$channelName" = : && continue;
|
||||
|
||||
# Do not follow redirections, such that we can extract the
|
||||
# short-changeset from the name of the directory where we are
|
||||
# redirected to.
|
||||
sha1=$(curl -sI "$NIXOS_CHANNELS$channelName" | sed -n '/Location/ { s,.*\.\([a-f0-9]*\)[ \r]*$,\1,; p; }')
|
||||
|
||||
updateRef "remotes/$channelName" "$sha1"
|
||||
done
|
||||
|
||||
echo "Fetching channels from nixos-version:"
|
||||
if currentSystem=$(nixos-version 2>/dev/null); then
|
||||
# If the system is entirely build from a custom nixpkgs version,
|
||||
# then the version is not annotated in git version. This sed
|
||||
# expression is basically matching that the expressions end with
|
||||
# ".<sha1> (Name)" to extract the sha1.
|
||||
sha1=$(echo "$currentSystem" | sed -n 's,^.*\.\([a-f0-9]*\) *(.*)$,\1,; T skip; p; :skip;')
|
||||
|
||||
updateRef current-system "$sha1"
|
||||
fi
|
||||
|
||||
echo "Fetching channels from $HOME/.nix-defexpr:"
|
||||
for revFile in : $(find -L "$HOME/.nix-defexpr/" -maxdepth 4 -name svn-revision); do
|
||||
test "$revFile" = : && continue;
|
||||
|
||||
# Deconstruct a path such as, into:
|
||||
#
|
||||
# /home/luke/.nix-defexpr/channels_root/nixos/nixpkgs/svn-revision
|
||||
# channelName = root/nixos
|
||||
#
|
||||
# /home/luke/.nix-defexpr/channels/nixpkgs/svn-revision
|
||||
# channelName = nixpkgs
|
||||
#
|
||||
user=${revFile#*.nix-defexpr/channels}
|
||||
repo=${user#*/}
|
||||
repo=${repo%%/*}
|
||||
user=${user%%/*}
|
||||
user=${user#_}
|
||||
test -z "$user" && user=$USER
|
||||
channelName="$user${user:+/}$repo"
|
||||
|
||||
sha1=$(sed -n 's,^.*\.\([a-f0-9]*\)$,\1,; T skip; p; :skip;' "$revFile")
|
||||
|
||||
updateRef "$channelName" "$sha1"
|
||||
done
|
||||
|
||||
# Suggest to remove channel branches which are no longer found by this
|
||||
# script. This is to handle the cases where a local/remote channel
|
||||
# disappear. We should not attempt to remove manually any branches, as they
|
||||
# might be user branches.
|
||||
if test -n "$deadChannels"; then
|
||||
|
||||
echo "
|
||||
Some old channel branches are still in your repository, if you
|
||||
want to remove them, run the following command(s):
|
||||
"
|
||||
|
||||
while read branch; do
|
||||
echo " git update-ref -d $branch"
|
||||
done <<EOF
|
||||
$deadChannels
|
||||
EOF
|
||||
|
||||
echo
|
||||
fi
|
||||
@@ -1,7 +0,0 @@
|
||||
viric viriketo@gmail.com
|
||||
Pjotr Prins pjotr.public01@thebird.nl
|
||||
Pjotr Prins pjotr.public05@thebird.nl
|
||||
Wouter den Breejen wbreejen
|
||||
MarcWeber marcweber
|
||||
Ricardo Correia Ricardo M. Correia
|
||||
ertesx@gmx.de ertes
|
||||
@@ -1,122 +0,0 @@
|
||||
#! /bin/sh
|
||||
|
||||
export LANG=C LC_ALL=C LC_COLLATE=C
|
||||
|
||||
# Load git log
|
||||
raw_git_log="$(git log)"
|
||||
git_data="$(echo "$raw_git_log" | grep 'Author:' |
|
||||
sed -e 's/^ *Author://; s/\\//g; s/^ *//; s/ *$//;
|
||||
s/ @ .*//; s/ *[<]/\t/; s/[>]//')"
|
||||
|
||||
# Name - nick - email correspondence from log and from maintainer list
|
||||
# Also there are a few manual entries
|
||||
maintainers="$(cat "$(dirname "$0")/../../lib/maintainers.nix" |
|
||||
grep '=' | sed -re 's/\\"/''/g;
|
||||
s/ *([^ =]*) *= *" *(.*[^ ]) *[<](.*)[>] *".*/\1\t\2\t\3/')"
|
||||
git_lines="$( ( echo "$git_data";
|
||||
cat "$(dirname "$0")/vanity-manual-equalities.txt") | sort |uniq)"
|
||||
|
||||
emails="$(
|
||||
( echo "$maintainers" | cut -f 3; echo "$git_data" | cut -f 2 ) |
|
||||
sort | uniq | grep -E ".+@.+[.].+"
|
||||
)"
|
||||
|
||||
fetchGithubName () {
|
||||
commitid="$(
|
||||
echo "$raw_git_log" | grep -B3 "Author: .*[<]$1[>]" | head -n 3 |
|
||||
grep '^commit ' | tail -n 1 | sed -e 's/^commit //'
|
||||
)"
|
||||
userid="$(
|
||||
curl https://github.com/NixOS/nixpkgs/commit/"$commitid" 2>/dev/null |
|
||||
grep authored -B10 | grep 'href="/' |
|
||||
sed -re 's@.* href="/@@; s@".*@@' |
|
||||
grep -v "/commit/"
|
||||
)";
|
||||
echo "$userid"
|
||||
}
|
||||
|
||||
[ -n "$NIXPKGS_GITHUB_NAME_CACHE" ] && {
|
||||
echo "$emails" | while read email; do
|
||||
line="$(grep "$email " "$NIXPKGS_GITHUB_NAME_CACHE")"
|
||||
[ -z "$line" ] && {
|
||||
echo "$email $(fetchGithubName "$email")" >> \
|
||||
"$NIXPKGS_GITHUB_NAME_CACHE"
|
||||
}
|
||||
done
|
||||
}
|
||||
|
||||
# For RDF
|
||||
normalize_name () {
|
||||
sed -e 's/%/%25/g; s/ /%20/g; s/'\''/%27/g; s/"/%22/g; s/`/%60/g; s/\^/%5e/g; '
|
||||
}
|
||||
|
||||
denormalize_name () {
|
||||
sed -e 's/%20/ /g; s/%27/'\''/g; s/%22/"/g; s/%60/`/g; s/%5e/^/g; s/%25/%/g;';
|
||||
}
|
||||
|
||||
n3="$(mktemp --suffix .n3)"
|
||||
|
||||
# «The same person» relation and a sorting hint
|
||||
# Full name is something with a space
|
||||
(
|
||||
echo "$git_lines" | sed -re 's@(.*)\t(.*)@<my://name/\1> <my://can-be> <my://name/\2>.@'
|
||||
echo "$git_lines" | sed -re 's@(.*)\t(.*)@<my://name/\2> <my://can-be> <my://name/\1>.@'
|
||||
echo "$maintainers" | sed -re 's@(.*)\t(.*)\t(.*)@<my://name/\1> <my://can-be> <my://name/\2>.@'
|
||||
echo "$maintainers" | sed -re 's@(.*)\t(.*)\t(.*)@<my://name/\2> <my://can-be> <my://name/\3>.@'
|
||||
echo "$maintainers" | sed -re 's@(.*)\t(.*)\t(.*)@<my://name/\3> <my://can-be> <my://name/\1>.@'
|
||||
echo "$git_lines" | grep ' ' | cut -f 1 | sed -e 's@.*@<my://name/&> <my://is-name> <my://0>.@'
|
||||
echo "$git_lines" | grep -v ' ' | cut -f 1 | sed -e 's@.*@<my://name/&> <my://is-name> <my://1>.@'
|
||||
echo "$maintainers" | cut -f 2 | sed -e 's@.*@<my://name/&> <my://is-name> <my://0>.@'
|
||||
[ -n "$NIXPKGS_GITHUB_NAME_CACHE" ] && cat "$NIXPKGS_GITHUB_NAME_CACHE" |
|
||||
grep -v " $" |
|
||||
sed -re 's@(.*)\t(.*)@<my://name/\1> <my://at-github> <my://github/\2>.@'
|
||||
) | normalize_name | grep -E '<my://[-a-z]+>' | sort | uniq > "$n3"
|
||||
|
||||
# Get transitive closure
|
||||
sparql="$(nix-build '<nixpkgs>' -Q -A apache-jena --no-out-link)/bin/sparql"
|
||||
name_list="$(
|
||||
"$sparql" --results=TSV --data="$n3" "
|
||||
select ?x ?y ?g where {
|
||||
?x <my://can-be>+ ?y.
|
||||
?x <my://is-name> ?g.
|
||||
}
|
||||
" | tail -n +2 |
|
||||
sed -re 's@<my://name/@@g; s@<my://@@g; s@>@@g;' |
|
||||
sort -k 2,3 -t ' '
|
||||
)"
|
||||
github_name_list="$(
|
||||
"$sparql" --results=TSV --data="$n3" "
|
||||
select ?x ?y where {
|
||||
?x (<my://can-be>+ / <my://at-github>) ?y.
|
||||
}
|
||||
" | tail -n +2 |
|
||||
sed -re 's@<my://(name|github)/@@g; s@<my://@@g; s@>@@g;'
|
||||
)"
|
||||
|
||||
# Take first spelling option for every person
|
||||
name_list_canonical="$(echo "$name_list" | cut -f 1,2 | uniq -f1)"
|
||||
|
||||
cleaner_script="$(echo "$name_list_canonical" | denormalize_name |
|
||||
sed -re 's/(.*)\t(.*)/s#^\2$#\1#g/g')"
|
||||
|
||||
# Add github usernames
|
||||
if [ -n "$NIXPKGS_GITHUB_NAME_CACHE" ]; then
|
||||
github_adder_script="$(echo "$github_name_list" |
|
||||
grep -E "$(echo "$name_list_canonical" | cut -f 2 |
|
||||
tr '\n' '|' )" |
|
||||
sort | uniq |
|
||||
sed -re 's/(.*)\t(.*)/s| \1$| \1\t\2|g;/' |
|
||||
denormalize_name
|
||||
)"
|
||||
else
|
||||
github_adder_script=''
|
||||
fi
|
||||
|
||||
echo "$name_list" | denormalize_name
|
||||
|
||||
echo
|
||||
|
||||
echo "$git_data" | cut -f 1 |
|
||||
sed -e "$cleaner_script" |
|
||||
sort | uniq -c | sort -k1n | sed -re "$github_adder_script" |
|
||||
sed -re 's/^ *([0-9]+) /\1\t/'
|
||||
21
nixos/doc/config-examples/basic.nix
Normal file
21
nixos/doc/config-examples/basic.nix
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
boot = {
|
||||
loader.grub.device = "/dev/sda";
|
||||
};
|
||||
|
||||
fileSystems = [
|
||||
{ mountPoint = "/";
|
||||
device = "/dev/sda1";
|
||||
}
|
||||
];
|
||||
|
||||
swapDevices = [
|
||||
{ device = "/dev/sdb1"; }
|
||||
];
|
||||
|
||||
services = {
|
||||
openssh = {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
32
nixos/doc/config-examples/closed-install-configuration.nix
Normal file
32
nixos/doc/config-examples/closed-install-configuration.nix
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
boot = {
|
||||
loader.grub.device = "/dev/sda";
|
||||
copyKernels = true;
|
||||
bootMount = "(hd0,0)";
|
||||
};
|
||||
|
||||
fileSystems = [
|
||||
{ mountPoint = "/";
|
||||
device = "/dev/sda3";
|
||||
}
|
||||
{ mountPoint = "/boot";
|
||||
device = "/dev/sda1";
|
||||
neededForBoot = true;
|
||||
}
|
||||
];
|
||||
|
||||
swapDevices = [
|
||||
{ device = "/dev/sda2"; }
|
||||
];
|
||||
|
||||
services = {
|
||||
sshd = {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
fonts = {
|
||||
enableFontConfig = false;
|
||||
};
|
||||
|
||||
}
|
||||
27
nixos/doc/config-examples/root-on-lvm.nix
Normal file
27
nixos/doc/config-examples/root-on-lvm.nix
Normal file
@@ -0,0 +1,27 @@
|
||||
# This configuration has / on a LVM volume. Since Grub
|
||||
# doesn't know about LVM, a separate /boot is therefore
|
||||
# needed.
|
||||
#
|
||||
# In this example, labels are used for file systems and
|
||||
# swap devices: "boot" might be /dev/sda1, "root" might be
|
||||
# /dev/my-volume-group/root, and "swap" might be /dev/sda2.
|
||||
# In particular there is no specific reference to the fact
|
||||
# that / is on LVM; that's figured out automatically.
|
||||
|
||||
{
|
||||
boot.loader.grub.device = "/dev/sda";
|
||||
boot.initrd.kernelModules = ["ata_piix"];
|
||||
|
||||
fileSystems = [
|
||||
{ mountPoint = "/";
|
||||
label = "root";
|
||||
}
|
||||
{ mountPoint = "/boot";
|
||||
label = "boot";
|
||||
}
|
||||
];
|
||||
|
||||
swapDevices = [
|
||||
{ label = "swap"; }
|
||||
];
|
||||
}
|
||||
36
nixos/doc/config-examples/svn-server.nix
Normal file
36
nixos/doc/config-examples/svn-server.nix
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
boot = {
|
||||
loader.grub.device = "/dev/sda";
|
||||
};
|
||||
|
||||
fileSystems = [
|
||||
{ mountPoint = "/";
|
||||
device = "/dev/sda1";
|
||||
}
|
||||
];
|
||||
|
||||
services = {
|
||||
|
||||
sshd = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
httpd = {
|
||||
enable = true;
|
||||
adminAddr = "admin@example.org";
|
||||
|
||||
subservices = {
|
||||
|
||||
subversion = {
|
||||
enable = true;
|
||||
dataDir = "/data/subversion";
|
||||
notificationSender = "svn@example.org";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
20
nixos/doc/config-examples/x86_64-usbstick.nix
Normal file
20
nixos/doc/config-examples/x86_64-usbstick.nix
Normal file
@@ -0,0 +1,20 @@
|
||||
# Configuration file used to install NixOS-x86_64 on a USB stick.
|
||||
|
||||
{
|
||||
boot = {
|
||||
loader.grub.device = "/dev/sda";
|
||||
initrd = {
|
||||
kernelModules = ["usb_storage" "ehci_hcd" "ohci_hcd"];
|
||||
};
|
||||
};
|
||||
|
||||
fileSystems = [
|
||||
{ mountPoint = "/";
|
||||
label = "nixos-usb";
|
||||
}
|
||||
];
|
||||
|
||||
fonts = {
|
||||
enableFontConfig = false;
|
||||
};
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
To build the manual, you need Nix installed on your system (no need
|
||||
for NixOS). To install Nix, follow the instructions at
|
||||
|
||||
https://nixos.org/nix/download.html
|
||||
|
||||
When you have Nix on your system, in the root directory of the project
|
||||
(i.e., `nixpkgs`), run:
|
||||
|
||||
nix-build nixos/release.nix -A manual.x86_64-linux
|
||||
|
||||
When this command successfully finishes, it will tell you where the
|
||||
manual got generated.
|
||||
@@ -1,65 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-boot-problems">
|
||||
|
||||
<title>Boot Problems</title>
|
||||
|
||||
<para>If NixOS fails to boot, there are a number of kernel command
|
||||
line parameters that may help you to identify or fix the issue. You
|
||||
can add these parameters in the GRUB boot menu by pressing “e” to
|
||||
modify the selected boot entry and editing the line starting with
|
||||
<literal>linux</literal>. The following are some useful kernel command
|
||||
line parameters that are recognised by the NixOS boot scripts or by
|
||||
systemd:
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><literal>boot.shell_on_fail</literal></term>
|
||||
<listitem><para>Start a root shell if something goes wrong in
|
||||
stage 1 of the boot process (the initial ramdisk). This is
|
||||
disabled by default because there is no authentication for the
|
||||
root shell.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>boot.debug1</literal></term>
|
||||
<listitem><para>Start an interactive shell in stage 1 before
|
||||
anything useful has been done. That is, no modules have been
|
||||
loaded and no file systems have been mounted, except for
|
||||
<filename>/proc</filename> and
|
||||
<filename>/sys</filename>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>boot.trace</literal></term>
|
||||
<listitem><para>Print every shell command executed by the stage 1
|
||||
and 2 boot scripts.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>single</literal></term>
|
||||
<listitem><para>Boot into rescue mode (a.k.a. single user mode).
|
||||
This will cause systemd to start nothing but the unit
|
||||
<literal>rescue.target</literal>, which runs
|
||||
<command>sulogin</command> to prompt for the root password and
|
||||
start a root login shell. Exiting the shell causes the system to
|
||||
continue with the normal boot process.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>systemd.log_level=debug systemd.log_target=console</literal></term>
|
||||
<listitem><para>Make systemd very verbose and send log messages to
|
||||
the console instead of the journal.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
For more parameters recognised by systemd, see
|
||||
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
|
||||
|
||||
<para>If no login prompts or X11 login screens appear (e.g. due to
|
||||
hanging dependencies), you can press Alt+ArrowUp. If you’re lucky,
|
||||
this will start rescue mode (described above). (Also note that since
|
||||
most units have a 90-second timeout before systemd gives up on them,
|
||||
the <command>agetty</command> login prompts should appear eventually
|
||||
unless something is very wrong.)</para>
|
||||
|
||||
</section>
|
||||
@@ -1,62 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-nix-gc">
|
||||
|
||||
<title>Cleaning the Nix Store</title>
|
||||
|
||||
<para>Nix has a purely functional model, meaning that packages are
|
||||
never upgraded in place. Instead new versions of packages end up in a
|
||||
different location in the Nix store (<filename>/nix/store</filename>).
|
||||
You should periodically run Nix’s <emphasis>garbage
|
||||
collector</emphasis> to remove old, unreferenced packages. This is
|
||||
easy:
|
||||
|
||||
<screen>
|
||||
$ nix-collect-garbage
|
||||
</screen>
|
||||
|
||||
Alternatively, you can use a systemd unit that does the same in the
|
||||
background:
|
||||
|
||||
<screen>
|
||||
$ systemctl start nix-gc.service
|
||||
</screen>
|
||||
|
||||
You can tell NixOS in <filename>configuration.nix</filename> to run
|
||||
this unit automatically at certain points in time, for instance, every
|
||||
night at 03:15:
|
||||
|
||||
<programlisting>
|
||||
nix.gc.automatic = true;
|
||||
nix.gc.dates = "03:15";
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The commands above do not remove garbage collector roots, such
|
||||
as old system configurations. Thus they do not remove the ability to
|
||||
roll back to previous configurations. The following command deletes
|
||||
old roots, removing the ability to roll back to them:
|
||||
<screen>
|
||||
$ nix-collect-garbage -d
|
||||
</screen>
|
||||
You can also do this for specific profiles, e.g.
|
||||
<screen>
|
||||
$ nix-env -p /nix/var/nix/profiles/per-user/eelco/profile --delete-generations old
|
||||
</screen>
|
||||
Note that NixOS system configurations are stored in the profile
|
||||
<filename>/nix/var/nix/profiles/system</filename>.</para>
|
||||
|
||||
<para>Another way to reclaim disk space (often as much as 40% of the
|
||||
size of the Nix store) is to run Nix’s store optimiser, which seeks
|
||||
out identical files in the store and replaces them with hard links to
|
||||
a single copy.
|
||||
<screen>
|
||||
$ nix-store --optimise
|
||||
</screen>
|
||||
Since this command needs to read the entire Nix store, it can take
|
||||
quite a while to finish.</para>
|
||||
|
||||
</chapter>
|
||||
@@ -1,50 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-container-networking">
|
||||
|
||||
|
||||
<title>Container Networking</title>
|
||||
|
||||
<para>When you create a container using <literal>nixos-container
|
||||
create</literal>, it gets it own private IPv4 address in the range
|
||||
<literal>10.233.0.0/16</literal>. You can get the container’s IPv4
|
||||
address as follows:
|
||||
|
||||
<screen>
|
||||
$ nixos-container show-ip foo
|
||||
10.233.4.2
|
||||
|
||||
$ ping -c1 10.233.4.2
|
||||
64 bytes from 10.233.4.2: icmp_seq=1 ttl=64 time=0.106 ms
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Networking is implemented using a pair of virtual Ethernet
|
||||
devices. The network interface in the container is called
|
||||
<literal>eth0</literal>, while the matching interface in the host is
|
||||
called <literal>ve-<replaceable>container-name</replaceable></literal>
|
||||
(e.g., <literal>ve-foo</literal>). The container has its own network
|
||||
namespace and the <literal>CAP_NET_ADMIN</literal> capability, so it
|
||||
can perform arbitrary network configuration such as setting up
|
||||
firewall rules, without affecting or having access to the host’s
|
||||
network.</para>
|
||||
|
||||
<para>By default, containers cannot talk to the outside network. If
|
||||
you want that, you should set up Network Address Translation (NAT)
|
||||
rules on the host to rewrite container traffic to use your external
|
||||
IP address. This can be accomplished using the following configuration
|
||||
on the host:
|
||||
|
||||
<programlisting>
|
||||
networking.nat.enable = true;
|
||||
networking.nat.internalInterfaces = ["ve-+"];
|
||||
networking.nat.externalInterface = "eth0";
|
||||
</programlisting>
|
||||
where <literal>eth0</literal> should be replaced with the desired
|
||||
external interface. Note that <literal>ve-+</literal> is a wildcard
|
||||
that matches all container interfaces.</para>
|
||||
|
||||
</section>
|
||||
@@ -1,34 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="ch-containers">
|
||||
|
||||
<title>Container Management</title>
|
||||
|
||||
<para>NixOS allows you to easily run other NixOS instances as
|
||||
<emphasis>containers</emphasis>. Containers are a light-weight
|
||||
approach to virtualisation that runs software in the container at the
|
||||
same speed as in the host system. NixOS containers share the Nix store
|
||||
of the host, making container creation very efficient.</para>
|
||||
|
||||
<warning><para>Currently, NixOS containers are not perfectly isolated
|
||||
from the host system. This means that a user with root access to the
|
||||
container can do things that affect the host. So you should not give
|
||||
container root access to untrusted users.</para></warning>
|
||||
|
||||
<para>NixOS containers can be created in two ways: imperatively, using
|
||||
the command <command>nixos-container</command>, and declaratively, by
|
||||
specifying them in your <filename>configuration.nix</filename>. The
|
||||
declarative approach implies that containers get upgraded along with
|
||||
your host system when you run <command>nixos-rebuild</command>, which
|
||||
is often not what you want. By contrast, in the imperative approach,
|
||||
containers are configured and updated independently from the host
|
||||
system.</para>
|
||||
|
||||
<xi:include href="imperative-containers.xml" />
|
||||
<xi:include href="declarative-containers.xml" />
|
||||
<xi:include href="container-networking.xml" />
|
||||
|
||||
</chapter>
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-cgroups">
|
||||
|
||||
<title>Control Groups</title>
|
||||
|
||||
<para>To keep track of the processes in a running system, systemd uses
|
||||
<emphasis>control groups</emphasis> (cgroups). A control group is a
|
||||
set of processes used to allocate resources such as CPU, memory or I/O
|
||||
bandwidth. There can be multiple control group hierarchies, allowing
|
||||
each kind of resource to be managed independently.</para>
|
||||
|
||||
<para>The command <command>systemd-cgls</command> lists all control
|
||||
groups in the <literal>systemd</literal> hierarchy, which is what
|
||||
systemd uses to keep track of the processes belonging to each service
|
||||
or user session:
|
||||
|
||||
<screen>
|
||||
$ systemd-cgls
|
||||
├─user
|
||||
│ └─eelco
|
||||
│ └─c1
|
||||
│ ├─ 2567 -:0
|
||||
│ ├─ 2682 kdeinit4: kdeinit4 Running...
|
||||
│ ├─ <replaceable>...</replaceable>
|
||||
│ └─10851 sh -c less -R
|
||||
└─system
|
||||
├─httpd.service
|
||||
│ ├─2444 httpd -f /nix/store/3pyacby5cpr55a03qwbnndizpciwq161-httpd.conf -DNO_DETACH
|
||||
│ └─<replaceable>...</replaceable>
|
||||
├─dhcpcd.service
|
||||
│ └─2376 dhcpcd --config /nix/store/f8dif8dsi2yaa70n03xir8r653776ka6-dhcpcd.conf
|
||||
└─ <replaceable>...</replaceable>
|
||||
</screen>
|
||||
|
||||
Similarly, <command>systemd-cgls cpu</command> shows the cgroups in
|
||||
the CPU hierarchy, which allows per-cgroup CPU scheduling priorities.
|
||||
By default, every systemd service gets its own CPU cgroup, while all
|
||||
user sessions are in the top-level CPU cgroup. This ensures, for
|
||||
instance, that a thousand run-away processes in the
|
||||
<literal>httpd.service</literal> cgroup cannot starve the CPU for one
|
||||
process in the <literal>postgresql.service</literal> cgroup. (By
|
||||
contrast, it they were in the same cgroup, then the PostgreSQL process
|
||||
would get 1/1001 of the cgroup’s CPU time.) You can limit a service’s
|
||||
CPU share in <filename>configuration.nix</filename>:
|
||||
|
||||
<programlisting>
|
||||
systemd.services.httpd.serviceConfig.CPUShares = 512;
|
||||
</programlisting>
|
||||
|
||||
By default, every cgroup has 1024 CPU shares, so this will halve the
|
||||
CPU allocation of the <literal>httpd.service</literal> cgroup.</para>
|
||||
|
||||
<para>There also is a <literal>memory</literal> hierarchy that
|
||||
controls memory allocation limits; by default, all processes are in
|
||||
the top-level cgroup, so any service or session can exhaust all
|
||||
available memory. Per-cgroup memory limits can be specified in
|
||||
<filename>configuration.nix</filename>; for instance, to limit
|
||||
<literal>httpd.service</literal> to 512 MiB of RAM (excluding swap):
|
||||
|
||||
<programlisting>
|
||||
systemd.services.httpd.serviceConfig.MemoryLimit = "512M";
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The command <command>systemd-cgtop</command> shows a
|
||||
continuously updated list of all cgroups with their CPU and memory
|
||||
usage.</para>
|
||||
|
||||
</chapter>
|
||||
@@ -1,56 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-declarative-containers">
|
||||
|
||||
<title>Declarative Container Specification</title>
|
||||
|
||||
<para>You can also specify containers and their configuration in the
|
||||
host’s <filename>configuration.nix</filename>. For example, the
|
||||
following specifies that there shall be a container named
|
||||
<literal>database</literal> running PostgreSQL:
|
||||
|
||||
<programlisting>
|
||||
containers.database =
|
||||
{ config =
|
||||
{ config, pkgs, ... }:
|
||||
{ services.postgresql.enable = true;
|
||||
services.postgresql.package = pkgs.postgresql92;
|
||||
};
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
If you run <literal>nixos-rebuild switch</literal>, the container will
|
||||
be built and started. If the container was already running, it will be
|
||||
updated in place, without rebooting.</para>
|
||||
|
||||
<para>By default, declarative containers share the network namespace
|
||||
of the host, meaning that they can listen on (privileged)
|
||||
ports. However, they cannot change the network configuration. You can
|
||||
give a container its own network as follows:
|
||||
|
||||
<programlisting>
|
||||
containers.database =
|
||||
{ privateNetwork = true;
|
||||
hostAddress = "192.168.100.10";
|
||||
localAddress = "192.168.100.11";
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
This gives the container a private virtual Ethernet interface with IP
|
||||
address <literal>192.168.100.11</literal>, which is hooked up to a
|
||||
virtual Ethernet interface on the host with IP address
|
||||
<literal>192.168.100.10</literal>. (See the next section for details
|
||||
on container networking.)</para>
|
||||
|
||||
<para>To disable the container, just remove it from
|
||||
<filename>configuration.nix</filename> and run <literal>nixos-rebuild
|
||||
switch</literal>. Note that this will not delete the root directory of
|
||||
the container in <literal>/var/lib/containers</literal>.</para>
|
||||
|
||||
<para>Declarative containers can be started and stopped using the
|
||||
corresponding systemd service, e.g. <literal>systemctl start
|
||||
container@database</literal>.</para>
|
||||
|
||||
</section>
|
||||
@@ -1,124 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-imperative-containers">
|
||||
|
||||
<title>Imperative Container Management</title>
|
||||
|
||||
<para>We’ll cover imperative container management using
|
||||
<command>nixos-container</command> first. You create a container with
|
||||
identifier <literal>foo</literal> as follows:
|
||||
|
||||
<screen>
|
||||
$ nixos-container create foo
|
||||
</screen>
|
||||
|
||||
This creates the container’s root directory in
|
||||
<filename>/var/lib/containers/foo</filename> and a small configuration
|
||||
file in <filename>/etc/containers/foo.conf</filename>. It also builds
|
||||
the container’s initial system configuration and stores it in
|
||||
<filename>/nix/var/nix/profiles/per-container/foo/system</filename>. You
|
||||
can modify the initial configuration of the container on the command
|
||||
line. For instance, to create a container that has
|
||||
<command>sshd</command> running, with the given public key for
|
||||
<literal>root</literal>:
|
||||
|
||||
<screen>
|
||||
$ nixos-container create foo --config 'services.openssh.enable = true; \
|
||||
users.extraUsers.root.openssh.authorizedKeys.keys = ["ssh-dss AAAAB3N…"];'
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Creating a container does not start it. To start the container,
|
||||
run:
|
||||
|
||||
<screen>
|
||||
$ nixos-container start foo
|
||||
</screen>
|
||||
|
||||
This command will return as soon as the container has booted and has
|
||||
reached <literal>multi-user.target</literal>. On the host, the
|
||||
container runs within a systemd unit called
|
||||
<literal>container@<replaceable>container-name</replaceable>.service</literal>.
|
||||
Thus, if something went wrong, you can get status info using
|
||||
<command>systemctl</command>:
|
||||
|
||||
<screen>
|
||||
$ systemctl status container@foo
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>If the container has started succesfully, you can log in as
|
||||
root using the <command>root-login</command> operation:
|
||||
|
||||
<screen>
|
||||
$ nixos-container root-login foo
|
||||
[root@foo:~]#
|
||||
</screen>
|
||||
|
||||
Note that only root on the host can do this (since there is no
|
||||
authentication). You can also get a regular login prompt using the
|
||||
<command>login</command> operation, which is available to all users on
|
||||
the host:
|
||||
|
||||
<screen>
|
||||
$ nixos-container login foo
|
||||
foo login: alice
|
||||
Password: ***
|
||||
</screen>
|
||||
|
||||
With <command>nixos-container run</command>, you can execute arbitrary
|
||||
commands in the container:
|
||||
|
||||
<screen>
|
||||
$ nixos-container run foo -- uname -a
|
||||
Linux foo 3.4.82 #1-NixOS SMP Thu Mar 20 14:44:05 UTC 2014 x86_64 GNU/Linux
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>There are several ways to change the configuration of the
|
||||
container. First, on the host, you can edit
|
||||
<literal>/var/lib/container/<replaceable>name</replaceable>/etc/nixos/configuration.nix</literal>,
|
||||
and run
|
||||
|
||||
<screen>
|
||||
$ nixos-container update foo
|
||||
</screen>
|
||||
|
||||
This will build and activate the new configuration. You can also
|
||||
specify a new configuration on the command line:
|
||||
|
||||
<screen>
|
||||
$ nixos-container update foo --config 'services.httpd.enable = true; \
|
||||
services.httpd.adminAddr = "foo@example.org";'
|
||||
|
||||
$ curl http://$(nixos-container show-ip foo)/
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">…
|
||||
</screen>
|
||||
|
||||
However, note that this will overwrite the container’s
|
||||
<filename>/etc/nixos/configuration.nix</filename>.</para>
|
||||
|
||||
<para>Alternatively, you can change the configuration from within the
|
||||
container itself by running <command>nixos-rebuild switch</command>
|
||||
inside the container. Note that the container by default does not have
|
||||
a copy of the NixOS channel, so you should run <command>nix-channel
|
||||
--update</command> first.</para>
|
||||
|
||||
<para>Containers can be stopped and started using
|
||||
<literal>nixos-container stop</literal> and <literal>nixos-container
|
||||
start</literal>, respectively, or by using
|
||||
<command>systemctl</command> on the container’s service unit. To
|
||||
destroy a container, including its file system, do
|
||||
|
||||
<screen>
|
||||
$ nixos-container destroy foo
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
@@ -1,52 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-logging">
|
||||
|
||||
<title>Logging</title>
|
||||
|
||||
<para>System-wide logging is provided by systemd’s
|
||||
<emphasis>journal</emphasis>, which subsumes traditional logging
|
||||
daemons such as syslogd and klogd. Log entries are kept in binary
|
||||
files in <filename>/var/log/journal/</filename>. The command
|
||||
<literal>journalctl</literal> allows you to see the contents of the
|
||||
journal. For example,
|
||||
|
||||
<screen>
|
||||
$ journalctl -b
|
||||
</screen>
|
||||
|
||||
shows all journal entries since the last reboot. (The output of
|
||||
<command>journalctl</command> is piped into <command>less</command> by
|
||||
default.) You can use various options and match operators to restrict
|
||||
output to messages of interest. For instance, to get all messages
|
||||
from PostgreSQL:
|
||||
|
||||
<screen>
|
||||
$ journalctl -u postgresql.service
|
||||
-- Logs begin at Mon, 2013-01-07 13:28:01 CET, end at Tue, 2013-01-08 01:09:57 CET. --
|
||||
...
|
||||
Jan 07 15:44:14 hagbard postgres[2681]: [2-1] LOG: database system is shut down
|
||||
-- Reboot --
|
||||
Jan 07 15:45:10 hagbard postgres[2532]: [1-1] LOG: database system was shut down at 2013-01-07 15:44:14 CET
|
||||
Jan 07 15:45:13 hagbard postgres[2500]: [1-1] LOG: database system is ready to accept connections
|
||||
</screen>
|
||||
|
||||
Or to get all messages since the last reboot that have at least a
|
||||
“critical” severity level:
|
||||
|
||||
<screen>
|
||||
$ journalctl -b -p crit
|
||||
Dec 17 21:08:06 mandark sudo[3673]: pam_unix(sudo:auth): auth could not identify password for [alice]
|
||||
Dec 29 01:30:22 mandark kernel[6131]: [1053513.909444] CPU6: Core temperature above threshold, cpu clock throttled (total events = 1)
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The system journal is readable by root and by users in the
|
||||
<literal>wheel</literal> and <literal>systemd-journal</literal>
|
||||
groups. All users have a private journal that can be read using
|
||||
<command>journalctl</command>.</para>
|
||||
|
||||
</chapter>
|
||||
@@ -1,18 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-maintenance-mode">
|
||||
|
||||
<title>Maintenance Mode</title>
|
||||
|
||||
<para>You can enter rescue mode by running:
|
||||
|
||||
<screen>
|
||||
$ systemctl rescue</screen>
|
||||
|
||||
This will eventually give you a single-user root shell. Systemd will
|
||||
stop (almost) all system services. To get out of maintenance mode,
|
||||
just exit from the rescue shell.</para>
|
||||
|
||||
</section>
|
||||
@@ -1,33 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-nix-network-issues">
|
||||
|
||||
<title>Network Problems</title>
|
||||
|
||||
<para>Nix uses a so-called <emphasis>binary cache</emphasis> to
|
||||
optimise building a package from source into downloading it as a
|
||||
pre-built binary. That is, whenever a command like
|
||||
<command>nixos-rebuild</command> needs a path in the Nix store, Nix
|
||||
will try to download that path from the Internet rather than build it
|
||||
from source. The default binary cache is
|
||||
<uri>https://cache.nixos.org/</uri>. If this cache is unreachable,
|
||||
Nix operations may take a long time due to HTTP connection timeouts.
|
||||
You can disable the use of the binary cache by adding <option>--option
|
||||
use-binary-caches false</option>, e.g.
|
||||
|
||||
<screen>
|
||||
$ nixos-rebuild switch --option use-binary-caches false
|
||||
</screen>
|
||||
|
||||
If you have an alternative binary cache at your disposal, you can use
|
||||
it instead:
|
||||
|
||||
<screen>
|
||||
$ nixos-rebuild switch --option binary-caches http://my-cache.example.org/
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
@@ -1,44 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-rebooting">
|
||||
|
||||
<title>Rebooting and Shutting Down</title>
|
||||
|
||||
<para>The system can be shut down (and automatically powered off) by
|
||||
doing:
|
||||
|
||||
<screen>
|
||||
$ shutdown
|
||||
</screen>
|
||||
|
||||
This is equivalent to running <command>systemctl
|
||||
poweroff</command>.</para>
|
||||
|
||||
<para>To reboot the system, run
|
||||
|
||||
<screen>
|
||||
$ reboot
|
||||
</screen>
|
||||
|
||||
which is equivalent to <command>systemctl reboot</command>.
|
||||
Alternatively, you can quickly reboot the system using
|
||||
<literal>kexec</literal>, which bypasses the BIOS by directly loading
|
||||
the new kernel into memory:
|
||||
|
||||
<screen>
|
||||
$ systemctl kexec
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The machine can be suspended to RAM (if supported) using
|
||||
<command>systemctl suspend</command>, and suspended to disk using
|
||||
<command>systemctl hibernate</command>.</para>
|
||||
|
||||
<para>These commands can be run by any user who is logged in locally,
|
||||
i.e. on a virtual console or in X11; otherwise, the user is asked for
|
||||
authentication.</para>
|
||||
|
||||
</chapter>
|
||||
@@ -1,48 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-rollback">
|
||||
|
||||
<title>Rolling Back Configuration Changes</title>
|
||||
|
||||
<para>After running <command>nixos-rebuild</command> to switch to a
|
||||
new configuration, you may find that the new configuration doesn’t
|
||||
work very well. In that case, there are several ways to return to a
|
||||
previous configuration.</para>
|
||||
|
||||
<para>First, the GRUB boot manager allows you to boot into any
|
||||
previous configuration that hasn’t been garbage-collected. These
|
||||
configurations can be found under the GRUB submenu “NixOS - All
|
||||
configurations”. This is especially useful if the new configuration
|
||||
fails to boot. After the system has booted, you can make the selected
|
||||
configuration the default for subsequent boots:
|
||||
|
||||
<screen>
|
||||
$ /run/current-system/bin/switch-to-configuration boot</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Second, you can switch to the previous configuration in a running
|
||||
system:
|
||||
|
||||
<screen>
|
||||
$ nixos-rebuild switch --rollback</screen>
|
||||
|
||||
This is equivalent to running:
|
||||
|
||||
<screen>
|
||||
$ /nix/var/nix/profiles/system-<replaceable>N</replaceable>-link/bin/switch-to-configuration switch</screen>
|
||||
|
||||
where <replaceable>N</replaceable> is the number of the NixOS system
|
||||
configuration. To get a list of the available configurations, do:
|
||||
|
||||
<screen>
|
||||
$ ls -l /nix/var/nix/profiles/system-*-link
|
||||
<replaceable>...</replaceable>
|
||||
lrwxrwxrwx 1 root root 78 Aug 12 13:54 /nix/var/nix/profiles/system-268-link -> /nix/store/202b...-nixos-13.07pre4932_5a676e4-4be1055
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
@@ -1,24 +0,0 @@
|
||||
<part xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="ch-running">
|
||||
|
||||
<title>Administration</title>
|
||||
|
||||
<partintro>
|
||||
<para>This chapter describes various aspects of managing a running
|
||||
NixOS system, such as how to use the <command>systemd</command>
|
||||
service manager.</para>
|
||||
</partintro>
|
||||
|
||||
<xi:include href="service-mgmt.xml" />
|
||||
<xi:include href="rebooting.xml" />
|
||||
<xi:include href="user-sessions.xml" />
|
||||
<xi:include href="control-groups.xml" />
|
||||
<xi:include href="logging.xml" />
|
||||
<xi:include href="cleaning-store.xml" />
|
||||
<xi:include href="containers.xml" />
|
||||
<xi:include href="troubleshooting.xml" />
|
||||
|
||||
</part>
|
||||
@@ -1,83 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-systemctl">
|
||||
|
||||
<title>Service Management</title>
|
||||
|
||||
<para>In NixOS, all system services are started and monitored using
|
||||
the systemd program. Systemd is the “init” process of the system
|
||||
(i.e. PID 1), the parent of all other processes. It manages a set of
|
||||
so-called “units”, which can be things like system services
|
||||
(programs), but also mount points, swap files, devices, targets
|
||||
(groups of units) and more. Units can have complex dependencies; for
|
||||
instance, one unit can require that another unit must be successfully
|
||||
started before the first unit can be started. When the system boots,
|
||||
it starts a unit named <literal>default.target</literal>; the
|
||||
dependencies of this unit cause all system services to be started,
|
||||
file systems to be mounted, swap files to be activated, and so
|
||||
on.</para>
|
||||
|
||||
<para>The command <command>systemctl</command> is the main way to
|
||||
interact with <command>systemd</command>. Without any arguments, it
|
||||
shows the status of active units:
|
||||
|
||||
<screen>
|
||||
$ systemctl
|
||||
-.mount loaded active mounted /
|
||||
swapfile.swap loaded active active /swapfile
|
||||
sshd.service loaded active running SSH Daemon
|
||||
graphical.target loaded active active Graphical Interface
|
||||
<replaceable>...</replaceable>
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>You can ask for detailed status information about a unit, for
|
||||
instance, the PostgreSQL database service:
|
||||
|
||||
<screen>
|
||||
$ systemctl status postgresql.service
|
||||
postgresql.service - PostgreSQL Server
|
||||
Loaded: loaded (/nix/store/pn3q73mvh75gsrl8w7fdlfk3fq5qm5mw-unit/postgresql.service)
|
||||
Active: active (running) since Mon, 2013-01-07 15:55:57 CET; 9h ago
|
||||
Main PID: 2390 (postgres)
|
||||
CGroup: name=systemd:/system/postgresql.service
|
||||
├─2390 postgres
|
||||
├─2418 postgres: writer process
|
||||
├─2419 postgres: wal writer process
|
||||
├─2420 postgres: autovacuum launcher process
|
||||
├─2421 postgres: stats collector process
|
||||
└─2498 postgres: zabbix zabbix [local] idle
|
||||
|
||||
Jan 07 15:55:55 hagbard postgres[2394]: [1-1] LOG: database system was shut down at 2013-01-07 15:55:05 CET
|
||||
Jan 07 15:55:57 hagbard postgres[2390]: [1-1] LOG: database system is ready to accept connections
|
||||
Jan 07 15:55:57 hagbard postgres[2420]: [1-1] LOG: autovacuum launcher started
|
||||
Jan 07 15:55:57 hagbard systemd[1]: Started PostgreSQL Server.
|
||||
</screen>
|
||||
|
||||
Note that this shows the status of the unit (active and running), all
|
||||
the processes belonging to the service, as well as the most recent log
|
||||
messages from the service.
|
||||
|
||||
</para>
|
||||
|
||||
<para>Units can be stopped, started or restarted:
|
||||
|
||||
<screen>
|
||||
$ systemctl stop postgresql.service
|
||||
$ systemctl start postgresql.service
|
||||
$ systemctl restart postgresql.service
|
||||
</screen>
|
||||
|
||||
These operations are synchronous: they wait until the service has
|
||||
finished starting or stopping (or has failed). Starting a unit will
|
||||
cause the dependencies of that unit to be started as well (if
|
||||
necessary).</para>
|
||||
|
||||
<!-- - cgroups: each service and user session is a cgroup
|
||||
|
||||
- cgroup resource management -->
|
||||
|
||||
</chapter>
|
||||
@@ -1,37 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-nix-store-corruption">
|
||||
|
||||
<title>Nix Store Corruption</title>
|
||||
|
||||
<para>After a system crash, it’s possible for files in the Nix store
|
||||
to become corrupted. (For instance, the Ext4 file system has the
|
||||
tendency to replace un-synced files with zero bytes.) NixOS tries
|
||||
hard to prevent this from happening: it performs a
|
||||
<command>sync</command> before switching to a new configuration, and
|
||||
Nix’s database is fully transactional. If corruption still occurs,
|
||||
you may be able to fix it automatically.</para>
|
||||
|
||||
<para>If the corruption is in a path in the closure of the NixOS
|
||||
system configuration, you can fix it by doing
|
||||
|
||||
<screen>
|
||||
$ nixos-rebuild switch --repair
|
||||
</screen>
|
||||
|
||||
This will cause Nix to check every path in the closure, and if its
|
||||
cryptographic hash differs from the hash recorded in Nix’s database,
|
||||
the path is rebuilt or redownloaded.</para>
|
||||
|
||||
<para>You can also scan the entire Nix store for corrupt paths:
|
||||
|
||||
<screen>
|
||||
$ nix-store --verify --check-contents --repair
|
||||
</screen>
|
||||
|
||||
Any corrupt paths will be redownloaded if they’re available in a
|
||||
binary cache; otherwise, they cannot be repaired.</para>
|
||||
|
||||
</section>
|
||||
@@ -1,18 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="ch-troubleshooting">
|
||||
|
||||
<title>Troubleshooting</title>
|
||||
|
||||
<para>This chapter describes solutions to common problems you might
|
||||
encounter when you manage your NixOS system.</para>
|
||||
|
||||
<xi:include href="boot-problems.xml" />
|
||||
<xi:include href="maintenance-mode.xml" />
|
||||
<xi:include href="rollback.xml" />
|
||||
<xi:include href="store-corruption.xml" />
|
||||
<xi:include href="network-problems.xml" />
|
||||
|
||||
</chapter>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user