Compare commits
1406 Commits
a7fd36beeb
...
ghcup-run-
| Author | SHA1 | Date | |
|---|---|---|---|
|
7a2a5074fa
|
|||
|
ce239ab88e
|
|||
|
f3c703d655
|
|||
|
b6ff5bc764
|
|||
|
b8aeb1f935
|
|||
|
b0ef0590a2
|
|||
|
256e1942f2
|
|||
|
aa71f0dfa1
|
|||
|
04d527c98a
|
|||
|
7b59621179
|
|||
|
9d59463ded
|
|||
|
9a72fa13d5
|
|||
|
86a8a32032
|
|||
|
13e01ab453
|
|||
|
873dd77a6f
|
|||
|
544c618473
|
|||
|
a264cb088e
|
|||
|
1a43fddca9
|
|||
|
bdfb1a3a9b
|
|||
|
9b8b3e8126
|
|||
|
d657c17df4
|
|||
|
|
e143c06697 | ||
|
|
29da21f5dc | ||
|
028696d4be
|
|||
|
4022edb12e
|
|||
|
fde5044194
|
|||
|
3af1286ab7
|
|||
|
bcff46d3d4
|
|||
|
d1c72cdff4
|
|||
|
565bb59f45
|
|||
|
aae3f31c50
|
|||
|
0ce9b5d352
|
|||
|
bf0e5b37ca
|
|||
|
fe620835be
|
|||
|
c7dc77e6bc
|
|||
|
05c72a3de6
|
|||
|
0653844931
|
|||
|
7661046bcb
|
|||
|
16888a12d4
|
|||
|
9f7df33692
|
|||
|
b7007aa100
|
|||
|
03dfd0cba0
|
|||
|
0e64d1f22f
|
|||
|
c7774450bf
|
|||
|
9375255452
|
|||
|
b8b3a16589
|
|||
|
e1d86c77d0
|
|||
|
001d33eabb
|
|||
|
2845425099
|
|||
|
c56b9ec3ce
|
|||
|
68c81577a4
|
|||
|
b5fb8772fe
|
|||
|
5741e069ad
|
|||
|
df89ddcdf5
|
|||
|
c9e1261af2
|
|||
|
d5efc86d85
|
|||
|
430b655785
|
|||
|
1cffa358b8
|
|||
|
ca89112a8e
|
|||
|
65f02a5a7a
|
|||
|
9ccf29903e
|
|||
|
e4b8c9748a
|
|||
|
3318c30cee
|
|||
|
b9aba98cd5
|
|||
|
55fdc41137
|
|||
|
c9790e5823
|
|||
|
fa924eac15
|
|||
|
db4e411dfd
|
|||
|
48aee1e76c
|
|||
|
2a2ace603b
|
|||
|
25f9ac71ca
|
|||
|
61e2801838
|
|||
|
e60b8ee238
|
|||
|
dc0ea5a59c
|
|||
|
10e704cd73
|
|||
|
8004cc0537
|
|||
|
0a2373f407
|
|||
|
96f87eaf5f
|
|||
|
e9bd687b8f
|
|||
|
3ffa38cf98
|
|||
|
a770c4bcca
|
|||
|
f648a6e698
|
|||
|
a72a12b96d
|
|||
|
591c54b5f7
|
|||
|
a6a54f34cf
|
|||
|
f7811961b5
|
|||
|
ee778e1177
|
|||
|
5787a662ed
|
|||
|
fce654f3c7
|
|||
|
0f052c3465
|
|||
|
c733810fdc
|
|||
|
5130cb013b
|
|||
|
991e540c11
|
|||
|
a34d9b7b89
|
|||
|
4e62f559fa
|
|||
|
8c3d2b6740
|
|||
|
b6779f4d75
|
|||
|
b036c9861f
|
|||
|
02cd773c2a
|
|||
|
3964d06f5d
|
|||
|
|
e83612a06c | ||
|
cf6c666b59
|
|||
|
ee0ec370c7
|
|||
|
ea0e35ddf0
|
|||
|
99c8501d47
|
|||
|
f8a1fed1f2
|
|||
|
9ad1f7cb97
|
|||
|
0856a96738
|
|||
|
ee9801a8c2
|
|||
|
cfecc11b43
|
|||
|
3d36348563
|
|||
|
dcbee9c7dc
|
|||
|
2d88b1197e
|
|||
|
6c12dc0d6f
|
|||
|
a4b69f29dc
|
|||
|
1680c5c448
|
|||
|
e74fb45680
|
|||
|
d19ab05a11
|
|||
|
433c73b23c
|
|||
|
2aa5211886
|
|||
|
81e7c02807
|
|||
|
a2373f2056
|
|||
|
ba8e4f6ac6
|
|||
|
76acc9a5f5
|
|||
|
92bd333552
|
|||
|
70a451b63e
|
|||
|
cfe6c47cd7
|
|||
|
8eeb32c495
|
|||
|
fdcd6822c4
|
|||
|
71390c84da
|
|||
|
84d01b1091
|
|||
|
8f9faaa39e
|
|||
|
0898244b2a
|
|||
|
0c70feb09c
|
|||
|
f9a38e616d
|
|||
|
e511fc3c0a
|
|||
|
3ff670134c
|
|||
|
4c0160bb28
|
|||
|
c1e0baedd3
|
|||
|
8f7d937e26
|
|||
|
604a6fc92b
|
|||
|
8c205fd18c
|
|||
|
41ecf897fb
|
|||
|
4c9c6e9223
|
|||
|
8be71c4c5c
|
|||
|
01d310e630
|
|||
|
96cb99e1b5
|
|||
|
2e08efeed7
|
|||
|
04fceb3134
|
|||
|
1f0a891bab
|
|||
|
6c63a65983
|
|||
|
199d3b7aee
|
|||
|
04fc04f586
|
|||
|
3f96a6460a
|
|||
|
bfcaa7f6fb
|
|||
|
e2bd4c4880
|
|||
|
ab702bba9b
|
|||
|
8afabf3ffb
|
|||
|
ebf6c60a10
|
|||
|
9a8291d391
|
|||
|
a6426901c5
|
|||
|
3b7dd36aa6
|
|||
|
dc635a6601
|
|||
|
08ec1bd923
|
|||
|
b78aab884e
|
|||
|
36e192ec32
|
|||
|
510675622b
|
|||
|
651722b935
|
|||
|
7a0d5a95c1
|
|||
|
2c583bcae9
|
|||
|
ab36d4418e
|
|||
|
f146c77797
|
|||
|
d863ac570b
|
|||
|
d05fad49a1
|
|||
|
fbbc4497ca
|
|||
|
4223586e62
|
|||
|
c859b3ee2b
|
|||
|
8a16b0de7c
|
|||
|
9faf17634b
|
|||
|
66a62c170c
|
|||
|
5186d959bc
|
|||
|
09a8a0bda0
|
|||
|
191f49adfc
|
|||
|
|
26b79c5763 | ||
|
c72841ca58
|
|||
|
63350dab71
|
|||
|
d110d20879
|
|||
|
b4e58478c3
|
|||
|
12d2acd7fd
|
|||
|
6073ebe476
|
|||
|
5c026591cb
|
|||
|
907365ddff
|
|||
|
684953464b
|
|||
|
6b978b42bc
|
|||
|
6831337289
|
|||
|
e40777a5d3
|
|||
|
51690d1df3
|
|||
|
72a06e964c
|
|||
|
9ffd402481
|
|||
|
dee8d4bc09
|
|||
|
6c57661797
|
|||
|
b9ff7c5af4
|
|||
|
072161ada2
|
|||
|
a67b3e8a57
|
|||
|
c9216fb444
|
|||
|
2aac17ac5f
|
|||
|
17a403b8ce
|
|||
|
b245c11b1d
|
|||
|
2ed047515e
|
|||
|
b16e561384
|
|||
|
|
2ebff1e887 | ||
|
655ee432f8
|
|||
|
67b7b2f292
|
|||
|
66961101c6
|
|||
|
326af49a8f
|
|||
|
3a7ed5ee2d
|
|||
|
56fa798406
|
|||
|
|
3fd9fae66a | ||
|
|
5d43168370 | ||
|
|
f8548fefb3 | ||
|
|
3565c32d51 | ||
|
7fab328acc
|
|||
|
a043b82b27
|
|||
|
20652fed94
|
|||
|
6fc52a4ec7
|
|||
|
834bcfa02c
|
|||
|
c99ecc0a66
|
|||
|
061e5dd832
|
|||
|
c97ade81fa
|
|||
|
82a22fe993
|
|||
|
dbadcf1858
|
|||
|
ff8865c5c3
|
|||
|
9833dee925
|
|||
|
aac2874f8f
|
|||
|
17524b21b3
|
|||
|
3f0befe30d
|
|||
|
76c286f95e
|
|||
|
0c415314b6
|
|||
|
717f386077
|
|||
|
7a841a480b
|
|||
|
43ea85b495
|
|||
|
8a6badca1d
|
|||
|
4064803e23
|
|||
|
2e03b075f8
|
|||
|
fe9c125bd6
|
|||
|
503fd57d7c
|
|||
|
e74e746213
|
|||
|
065f9c4965
|
|||
|
32f3c36589
|
|||
|
c2a8d39fb4
|
|||
|
f08cbe70fb
|
|||
|
a9630d0802
|
|||
|
c5c6c431b5
|
|||
|
71d78d2d72
|
|||
|
ccecda2eff
|
|||
|
3a5f8d6139
|
|||
|
74e0f39bc2
|
|||
|
274978a8a7
|
|||
|
8eea9bd6a5
|
|||
|
626a2dd020
|
|||
|
6b6ce221e0
|
|||
|
d038c361c0
|
|||
|
c05876cc60
|
|||
|
b9c4c9a0b7
|
|||
|
6697e804ee
|
|||
|
2c57def8f1
|
|||
|
62b16e957b
|
|||
|
18d7bdd85c
|
|||
|
190b5dedba
|
|||
|
886e45f788
|
|||
|
360daf2a09
|
|||
|
7bb67dd4c6
|
|||
|
72c4ea70c4
|
|||
|
0ae42dd71e
|
|||
|
1df1e7eb98
|
|||
|
9592021c48
|
|||
|
9a9c3b340e
|
|||
|
abd64cb3fa
|
|||
|
b366a50af1
|
|||
|
e4b9eeefc6
|
|||
|
4d7a8557eb
|
|||
|
c23357df81
|
|||
|
f728d5aa23
|
|||
|
ac59563adf
|
|||
|
b2d2996077
|
|||
|
df2337abf9
|
|||
|
d68ab3b657
|
|||
|
c10821c332
|
|||
|
219cba5fc7
|
|||
|
8e3c74958a
|
|||
|
ed08e0b166
|
|||
|
168f2e6d16
|
|||
|
4574f3aa4f
|
|||
|
2a11e85a95
|
|||
|
69df100b18
|
|||
|
920b027a32
|
|||
|
9f8c9c228d
|
|||
|
9d8fdfe090
|
|||
|
01956d694d
|
|||
|
09d2a1e815
|
|||
|
ccfaedb7ad
|
|||
|
356a69f575
|
|||
|
752efad4bf
|
|||
|
05adb224e9
|
|||
|
bf1a3fbbe8
|
|||
|
8b14b22b12
|
|||
|
b8b47a45ba
|
|||
|
2b9e51cc31
|
|||
|
d9fa0cdb45
|
|||
|
288af4abc6
|
|||
|
e77b2c39f9
|
|||
|
87e5d526cb
|
|||
|
2b33dd4871
|
|||
|
62b68cfa3e
|
|||
|
|
af14227862 | ||
|
|
eb0e9df6ab | ||
|
f1cc2ebf20
|
|||
|
74f14c68a4
|
|||
|
5dc5c2094e
|
|||
|
940b5842b6
|
|||
|
d19602d06f
|
|||
|
ae85f7152e
|
|||
|
|
2cb40af62f
|
||
|
|
569b46f0c4
|
||
|
|
6b0c915077
|
||
|
|
237ed173ee
|
||
|
c0c6cd4fb3
|
|||
|
1f100623a7
|
|||
|
f137d5cc21
|
|||
|
aea8af513b
|
|||
|
c846e52acb
|
|||
|
19e7f0df34
|
|||
|
cd218ce025
|
|||
|
c381f47a72
|
|||
|
a68355cb7d
|
|||
|
f53a10825e
|
|||
|
21bbb8be1c
|
|||
|
ab44e9d2ac
|
|||
|
32497f3a6f
|
|||
|
c06c6b6f12
|
|||
|
26335150b7
|
|||
|
5298aacac9
|
|||
|
|
7832399fb3 | ||
|
|
2b60830203 | ||
|
|
b9bf29ba2c | ||
|
00d67c270e
|
|||
|
2826fec975
|
|||
|
29a34f5edf
|
|||
|
c100daeba5
|
|||
|
ac66f6747e
|
|||
|
014f1ff125
|
|||
|
c4991425ab
|
|||
|
1c770aad58
|
|||
|
7c8912d48c
|
|||
|
67d9a0bd2c
|
|||
|
0115e2a13c
|
|||
|
e2f36611a1
|
|||
|
9143ac97c5
|
|||
|
b5b09d0ca2
|
|||
|
fa79f75072
|
|||
|
6459af419e
|
|||
|
2ff2655db0
|
|||
|
c4ab59f7bf
|
|||
|
a62365141e
|
|||
|
5ae649bccb
|
|||
|
2095b17d06
|
|||
|
336514b3e2
|
|||
|
37707e1df8
|
|||
|
57aa30c7af
|
|||
|
78c6dd5404
|
|||
|
c101c228d7
|
|||
|
0f6874bc0f
|
|||
|
399d89dae5
|
|||
|
ba6b540869
|
|||
|
249c5a5c59
|
|||
|
e2c59230b5
|
|||
|
1d1ace096e
|
|||
|
0381ccef64
|
|||
|
e5a0f836a4
|
|||
|
463915da1a
|
|||
|
ae7bc508e8
|
|||
|
d21e0473bc
|
|||
|
df05feb766
|
|||
|
e0dafa2093
|
|||
|
f1e01e8b18
|
|||
|
8a770de33e
|
|||
|
b3aeb3246f
|
|||
|
1fc3e0ee5d
|
|||
|
f2dcfbdc5f
|
|||
|
23d77ce1b4
|
|||
|
0e6688c2bc
|
|||
|
7ef1ef688f
|
|||
|
3b8f2e8307
|
|||
|
0af7aaef3c
|
|||
|
b8907335ba
|
|||
|
0073ca769b
|
|||
|
8a286156f6
|
|||
|
5a39ead523
|
|||
|
d2b4eccac2
|
|||
|
be9b3a3857
|
|||
|
a8e6fca128
|
|||
|
0483133857
|
|||
|
30d9eb5634
|
|||
|
9fe7af3335
|
|||
|
bedfb3d114
|
|||
|
c19dd5ee8b
|
|||
|
6ae3bfe395
|
|||
|
4f82e80dad
|
|||
|
8e8198546f
|
|||
|
9497e310ca
|
|||
|
02135bdbae
|
|||
|
041a341879
|
|||
|
15dd810d67
|
|||
|
7982f3aec0
|
|||
|
2fb07201c7
|
|||
|
b5ca01dc4f
|
|||
|
fa523d590e
|
|||
|
523f2f57e1
|
|||
|
d662682fb5
|
|||
|
ff2b06a5e8
|
|||
|
aece305003
|
|||
|
ef8da9bcec
|
|||
|
3cd55beab1
|
|||
|
6766501858
|
|||
|
d5b41683ca
|
|||
|
ff8dbe111d
|
|||
|
28d4071fac
|
|||
|
31a523755f
|
|||
|
3d1d8f1af7
|
|||
|
167f6d0683
|
|||
|
8580487b61
|
|||
|
a8b1c33280
|
|||
|
fca2a4134b
|
|||
|
f90741f4d3
|
|||
|
ba4b45f7fb
|
|||
|
4767f3db5b
|
|||
|
709658462c
|
|||
|
c431c0ae00
|
|||
|
6f61b5dbef
|
|||
|
c42c4b64f9
|
|||
|
d3a36c2c9a
|
|||
|
6799e9616e
|
|||
|
|
e8d962ac44 | ||
|
ac1e145028
|
|||
|
2fdf121167
|
|||
|
dcca8b0bf2
|
|||
|
b1f891b005
|
|||
|
648dcc7287
|
|||
|
2175f7dd3d
|
|||
|
aff90a52f1
|
|||
|
0f14dee72a
|
|||
|
ae2031174e
|
|||
|
c163278c64
|
|||
|
d10133f06f
|
|||
|
4377fc663e
|
|||
|
487e236882
|
|||
|
|
8fc128e89b | ||
|
|
737f72f90f | ||
|
|
c3aab65521 | ||
|
|
972474f79a | ||
| bc64d2ade0 | |||
|
|
eddda55fe6 | ||
|
|
13aca91231 | ||
|
|
6011242eae | ||
|
|
cadb5086e1 | ||
|
|
10a30bbf38 | ||
|
|
6ac7a75bab | ||
|
bbd11bfa26
|
|||
|
75548fa02d
|
|||
|
fb6956009f
|
|||
|
e029117c3e
|
|||
|
bc7c01de90
|
|||
|
cfcd8a4c20
|
|||
|
5e17eb7ca7
|
|||
|
|
756727ffe2 | ||
|
6bc602dead
|
|||
|
056c79e813
|
|||
|
68bbf31a86
|
|||
|
b58f380e75
|
|||
|
48c54bf374
|
|||
|
51da1578f4
|
|||
|
|
488f25aed6 | ||
|
|
d60f58cf43 | ||
|
|
7a6a119829 | ||
|
|
f0fb019c70 | ||
|
|
0f98ec6b78 | ||
|
|
107fed6e60 | ||
|
|
59a9a770a5 | ||
|
|
20bcb26e3d | ||
|
d355c46250
|
|||
|
787c927de6
|
|||
|
d15ff7bc67
|
|||
|
7c5c35f1b0
|
|||
|
001b090bc6
|
|||
|
db8207f8b9
|
|||
|
e5918de7af
|
|||
|
d2346a543a
|
|||
|
c057b4ae5c
|
|||
|
b962bf4af9
|
|||
|
c54dc05d92
|
|||
|
8c72bf697e
|
|||
|
cc8cf3d12a
|
|||
|
9bdf6bde17
|
|||
|
8363495843
|
|||
|
bc80b1048f
|
|||
|
d61981bc1b
|
|||
|
4ccdc5dd6c
|
|||
|
3240118226
|
|||
|
254989d63d
|
|||
|
283f2a6e46
|
|||
|
94637dfbab
|
|||
|
3e26d7057c
|
|||
|
3f710112f3
|
|||
|
34df41b44a
|
|||
|
3897434ef0
|
|||
|
375dba9dd1
|
|||
|
2edd1fb583
|
|||
|
11326060fb
|
|||
|
d343c01737
|
|||
|
3925f78721
|
|||
|
d98e54a743
|
|||
|
13143b8e4d
|
|||
|
3a7895e5ea
|
|||
|
2893b2e2d2
|
|||
|
987436fed2
|
|||
|
|
be82565775 | ||
|
|
f8d0243146 | ||
|
96ac66e909
|
|||
|
e5947f3490
|
|||
|
b35fe15703
|
|||
|
a269b60282
|
|||
|
fc6f7ffd73
|
|||
|
430dc2d20b
|
|||
|
77c464870f
|
|||
|
dda38ec52b
|
|||
|
|
f6b6b36eb7 | ||
|
|
3986677b06 | ||
|
1fb048777c
|
|||
|
e9c335eecc
|
|||
|
a7c7186aa4
|
|||
|
|
d7f82d643c | ||
|
|
15560a06b1 | ||
|
e38bd61066
|
|||
|
b086261c3c
|
|||
|
8c098d4e17
|
|||
|
e3a9c095c6
|
|||
|
678bdd7915
|
|||
|
14fc6b7281
|
|||
|
a2555cecc5
|
|||
|
9d6e469f79
|
|||
|
982c0a0fcf
|
|||
|
f8cfcd4038
|
|||
|
4d465efef1
|
|||
|
d667160027
|
|||
|
|
df55d972cf | ||
|
|
df758d828b | ||
|
7bc00c4e68
|
|||
|
bfc50e269c
|
|||
|
cea71beb4d
|
|||
|
8247c0b00b
|
|||
|
f624a83e87
|
|||
|
951e676bee
|
|||
|
281f310394
|
|||
|
|
8c486e8d46 | ||
|
c029713f23
|
|||
|
b86e2a1d5b
|
|||
|
099a6b9dcd
|
|||
|
3b13624117
|
|||
|
fad1efcefa
|
|||
|
1701b8a2f4
|
|||
|
608ee07940
|
|||
|
|
a0c2a5ccec | ||
|
cd41d3af97
|
|||
|
b5aafdee61
|
|||
|
9d9e4bb44e
|
|||
|
c708283547
|
|||
|
a4ddf95c8d
|
|||
|
ddbb396bf3
|
|||
|
e2a7c320ac
|
|||
|
06f998fa5e
|
|||
|
c48c73d34d
|
|||
|
cfb6ab31ab
|
|||
|
|
eac15541e8 | ||
|
984acebff8
|
|||
|
4cf2d125dd
|
|||
|
6701093c3b
|
|||
|
e9fdc073c6
|
|||
|
57c791106b
|
|||
|
fcba151fad
|
|||
|
3b24f503d1
|
|||
|
bd18fd9aa1
|
|||
|
|
c2c5625685 | ||
|
|
ce6fb0bb1e | ||
|
|
dcfb3afdad | ||
|
50c91345e8
|
|||
|
af3ecae792
|
|||
|
|
300cfd3ba6 | ||
|
|
bb430fa0b7 | ||
|
|
80fa7965a4 | ||
|
9975a2d4ba
|
|||
|
|
d1735bc446 | ||
|
dbf1d6f420
|
|||
|
0a0fbd0cb6
|
|||
|
f13f53b910
|
|||
|
6dfc04a9f6
|
|||
|
72133d0002
|
|||
|
6e07e9e56b
|
|||
|
e903aeb555
|
|||
|
2792f6f4b6
|
|||
|
|
80eb72ce49 | ||
|
|
2c6d0382cf | ||
|
|
e1bec789b0 | ||
|
|
5683493cae | ||
|
|
ae5e213b59 | ||
|
|
911089f334 | ||
|
|
6b89646c1e | ||
|
|
960d5ce79f | ||
|
|
90ed0895d6 | ||
|
|
7471f4f4dc | ||
|
|
781cf8eed5 | ||
|
|
236da31af6 | ||
|
|
1f760af880 | ||
|
|
62d03b776b | ||
|
|
37ea18a0d8 | ||
|
|
083dc59a8f | ||
|
|
a45d069cad | ||
|
|
fdbcd4fafd | ||
|
|
f3c1c925ed | ||
|
|
8f6a7ba39c | ||
|
|
f212eb4570 | ||
|
|
0d118e2fe1 | ||
|
|
c0f46ef81f | ||
|
|
476513b0a7 | ||
|
|
9a511669a8 | ||
|
|
a16a25a3cd | ||
|
|
8666fcd120 | ||
|
|
521ab0aedb | ||
|
|
1cfff674b7 | ||
|
88d1d19f55
|
|||
|
0fb1da5c3a
|
|||
|
b32f88e9a6
|
|||
|
9d2421fac5
|
|||
|
043e288fbf
|
|||
|
32e34876e2
|
|||
|
f12a2b3821
|
|||
|
844b4decab
|
|||
|
53ca60596d
|
|||
|
2d2894b0f4
|
|||
|
21d30cd8ce
|
|||
|
b38a569124
|
|||
|
810607e84f
|
|||
|
442ddfd4e4
|
|||
|
096103e65a
|
|||
|
60a56c337c
|
|||
|
11c1b2cc6c
|
|||
|
45db3bd913
|
|||
|
6d76561340
|
|||
|
00caeba067
|
|||
|
5a34191b88
|
|||
|
85003900d7
|
|||
|
0c666a6bbe
|
|||
|
e4e52ebf6b
|
|||
|
4512468108
|
|||
|
d3e3ebd63f
|
|||
|
ce616d3eb3
|
|||
|
5837e04e6e
|
|||
|
95ca79f3f8
|
|||
|
706fe1ffcc
|
|||
|
2774f026e8
|
|||
|
07604a2eb5
|
|||
|
|
03d77f5006 | ||
|
fdf45e0fe6
|
|||
|
1dc9ad7a57
|
|||
|
cc51d7b454
|
|||
|
c439693a8f
|
|||
|
af8c097092
|
|||
|
|
71e6dbfdca | ||
|
|
692cd1616b | ||
|
|
4e3dbea5d0 | ||
|
|
fd2add78bd | ||
|
|
e9da8ab439 | ||
|
|
9c22ba9d45 | ||
|
|
e5d3080b54 | ||
|
|
5995a8b592 | ||
|
|
bc6d006c57 | ||
|
|
b148d8e2e7 | ||
|
|
4f7d41a8cc | ||
|
|
5efe2e5f7a | ||
|
|
338f5f309d | ||
|
9639e695e2
|
|||
|
d2a2bde321
|
|||
|
c85ff686b6
|
|||
|
48d3b3bc3e
|
|||
|
94bd01aaca
|
|||
|
|
ba51cbad6f | ||
|
|
511272e86d | ||
|
|
873f75da9f | ||
|
|
42d4a66493 | ||
|
|
9a79af6fd2 | ||
|
|
63f10a1871 | ||
|
|
9686ee9826 | ||
|
|
4729364e99 | ||
|
|
91d982c7b2 | ||
|
|
8b7c22440e | ||
|
|
761b8cc750 | ||
|
3bdc82c99b
|
|||
|
|
9b3d55a095 | ||
|
db4e9fa432
|
|||
|
530c25c6a1
|
|||
|
1c2cf98850
|
|||
|
b35dbca22e
|
|||
|
a4a7f73fb7
|
|||
|
fd0ea3d858
|
|||
|
bbbe52f453
|
|||
|
|
e2daf5381c | ||
|
9e181b8820
|
|||
|
a6108f8319
|
|||
|
7a2570019a
|
|||
|
c5b4e82b48
|
|||
|
4ed72fb517
|
|||
|
5217aa0a1d
|
|||
|
3caf91c640
|
|||
|
eb26a5133f
|
|||
|
9e9402a3a2
|
|||
|
bc13a4555d
|
|||
|
eaad2caf25
|
|||
|
6143cdf2e0
|
|||
|
2c7176d998
|
|||
|
327b80cf56
|
|||
|
005c9fbb83
|
|||
|
42134fd2a5
|
|||
|
bc85a7d9c3
|
|||
|
7e14fd4a08
|
|||
|
bf74d1e828
|
|||
|
f04708e8ae
|
|||
|
80e1924e5f
|
|||
|
c7393bd7c5
|
|||
|
664713bb13
|
|||
|
01715fdefc
|
|||
|
ab9b24e109
|
|||
|
34ecb1a56e
|
|||
|
e3aef38f75
|
|||
|
ead2b76050
|
|||
|
2f35513f6e
|
|||
|
8573c99088
|
|||
|
dfe63332b2
|
|||
|
767ae48c7b
|
|||
|
f4160464c0
|
|||
|
a572b1d5f0
|
|||
|
82587d26b5
|
|||
|
ec98826e6d
|
|||
|
b4fcd05e8f
|
|||
|
1345ec938b
|
|||
|
227f3acaa5
|
|||
|
c20636f597
|
|||
|
c2d437150a
|
|||
|
9ff1467612
|
|||
|
9218efd71a
|
|||
|
bcd244a92a
|
|||
|
7de552ed82
|
|||
|
5cf297a4d2
|
|||
|
d86f84eef4
|
|||
|
83458c6c1e
|
|||
|
b862ca52a9
|
|||
|
928f4a97de
|
|||
|
e8d79c9d38
|
|||
|
59e1eee8ce
|
|||
|
57c8ffda35
|
|||
|
abbe51614d
|
|||
|
171ebd213d
|
|||
|
2a240cbd09
|
|||
|
068fa3454c
|
|||
|
6b2bcbf2ce
|
|||
|
19e46dac18
|
|||
|
e96c863120
|
|||
|
a30b3c84d7
|
|||
|
0ad5dc4583
|
|||
|
7189998f3b
|
|||
|
b6b24b8e0b
|
|||
|
8e820c6e89
|
|||
|
c74784a37c
|
|||
|
3d940cffcf
|
|||
|
0df044b284
|
|||
|
f576b9fb20
|
|||
|
5e00264119
|
|||
|
|
05eeba32fa | ||
|
|
61019ecd49 | ||
|
|
bed06d1334 | ||
|
|
f09f4bd1b7 | ||
|
|
a3b11f21bb | ||
|
|
69a461d9c3 | ||
|
|
1dfe5cfecf | ||
|
|
8e4550657e | ||
|
|
aee7fa52c3 | ||
|
|
d166cc84a1 | ||
|
|
bb7229d224 | ||
|
|
708cd5ead9 | ||
|
|
f7986cb4da | ||
|
|
395aeb415d | ||
|
|
830fb70492 | ||
|
|
6379a26afb | ||
|
|
2277013c76 | ||
|
|
8934e0e6bd | ||
|
|
59519febbc | ||
|
|
46fcdd356c | ||
|
|
9f343c45e8 | ||
|
|
931904f388 | ||
|
|
a40d0cbb5c | ||
|
|
9f5df9db10 | ||
|
|
d26ddf7015 | ||
|
|
9515065407 | ||
|
|
82a8c61cf6 | ||
|
|
3fae516ce4 | ||
|
|
33eaa765d7 | ||
|
|
3b3dde8413 | ||
|
|
118a2744fe | ||
|
|
2e3dceecf8 | ||
|
|
07fb04bb74 | ||
|
|
8a1dbe9dbb | ||
|
|
4ef3622616 | ||
|
|
82a704ab44 | ||
|
|
0cb22945fe | ||
|
|
d09adf9159 | ||
|
|
0b959c56fb | ||
|
|
ec29332657 | ||
|
|
0f6381e67b | ||
|
|
877b55e21d | ||
|
|
fa11ca665f | ||
|
d9d196439f
|
|||
|
a34fc4ad4f
|
|||
|
b4d52b88c1
|
|||
|
3fc3d27361
|
|||
|
56b86add38
|
|||
|
a608a105e3
|
|||
|
2e3e413f6c
|
|||
|
dfb6c09133
|
|||
|
9636276c17
|
|||
|
41783ff027
|
|||
|
08b0ecd057
|
|||
|
7e31798446
|
|||
|
534afa6e8d
|
|||
|
b56c44a210
|
|||
|
ef0c94fddd
|
|||
|
f14c281841
|
|||
|
b40cefee35
|
|||
|
ff32ccfb50
|
|||
|
581108ab65
|
|||
|
54e8e3efb0
|
|||
|
4dcc63606e
|
|||
|
a396b6044d
|
|||
|
94e5d2e19f
|
|||
|
a0976eee70
|
|||
|
61494d8c4b
|
|||
|
2b34c2dd69
|
|||
|
afc30b87dd
|
|||
|
|
ed0a63eb0c | ||
|
9ba590dd90
|
|||
|
d4bffd2c4a
|
|||
|
650f0a3e4e
|
|||
|
fd6ccf8f0a
|
|||
|
d9fe4b8723
|
|||
|
da2e7e0411
|
|||
|
79d6a50e44
|
|||
|
a13a5e5d20
|
|||
|
82743dda2b
|
|||
|
|
6f80dd1fcc | ||
|
1325dce493
|
|||
|
ac21c19b7e
|
|||
|
2b4088d068
|
|||
|
d86dc9b1d7
|
|||
|
9982311c87
|
|||
|
40c88d0b66
|
|||
|
e0ee1c2f94
|
|||
|
b4fa2780eb
|
|||
|
df86183e97
|
|||
|
f7868dc646
|
|||
|
e742be7693
|
|||
|
924bc8698d
|
|||
|
5214c35b20
|
|||
|
700e04535a
|
|||
|
fedc0bbef6
|
|||
|
468fc5ade9
|
|||
|
2c077db36b
|
|||
|
f80638bba4
|
|||
|
860aa0dafd
|
|||
|
27510b3b51
|
|||
|
96bcbbeeec
|
|||
|
8a632eb3b4
|
|||
|
aa992c0e5d
|
|||
|
810870e3a5
|
|||
|
d584e7b21b
|
|||
|
e93ac62c81
|
|||
|
0d7d6c8382
|
|||
|
5cd9ce8835
|
|||
|
443522d526
|
|||
|
9061e60518
|
|||
|
d65ab434b2
|
|||
|
cff592db82
|
|||
|
97029e8102
|
|||
|
|
828fd9eb10 | ||
|
03800d3b74
|
|||
|
a47304e599
|
|||
|
7b050e9fe2
|
|||
|
687a1d0c88
|
|||
|
e09e3c264d
|
|||
|
b56431b4e3
|
|||
|
70ad50010d
|
|||
|
|
ca3a249bea | ||
|
|
4337cdc38d | ||
|
9f92e0bc86
|
|||
|
98751cf8fb
|
|||
|
2f62067d96
|
|||
|
2cb1554244
|
|||
|
6f3c143228
|
|||
|
9793fc6888
|
|||
|
043cab08ae
|
|||
|
b7c83780da
|
|||
|
cff11135ff
|
|||
|
b94a4123eb
|
|||
|
8ef1c8b5d4
|
|||
|
132d331e7c
|
|||
|
734916728c
|
|||
|
5f6ed1292d
|
|||
|
a7dc03af50
|
|||
|
5a86a28d67
|
|||
|
a905c6322c
|
|||
|
49ccadd470
|
|||
|
9f0ac0ee19
|
|||
|
7e0f839ff8
|
|||
|
1e9ee260e7
|
|||
|
0b7d447aaf
|
|||
|
16a9336d31
|
|||
|
7d13836fea
|
|||
|
b645c4d57e
|
|||
|
5db43cd908
|
|||
|
93cd421ca3
|
|||
|
ec7130dac6
|
|||
|
f2b8cc530c
|
|||
|
de765088d1
|
|||
|
|
e11188aa99 | ||
|
0c6699c3c6
|
|||
|
c5858be6b8
|
|||
|
ffe00c7b1f
|
|||
|
43114959fd
|
|||
|
b1c3ffd729
|
|||
|
4f1a9e95a2
|
|||
|
f6a4f55384
|
|||
|
672b179446
|
|||
|
3111387e5a
|
|||
|
f8fda269f1
|
|||
|
fbac593739
|
|||
|
c80e54dff5
|
|||
|
4a86b2479e
|
|||
|
7bb2552d0f
|
|||
|
ad21640cd9
|
|||
|
e4aad4e645
|
|||
|
adf44ba141
|
|||
|
8707b194fd
|
|||
|
77bb7c4aba
|
|||
|
7383fdd0c0
|
|||
|
f4201d946a
|
|||
|
d5b5f1fddd
|
|||
| 910d660732 | |||
| ab4ad3a1bb | |||
| 13b27101f1 | |||
| 44b5d0dcff | |||
| df54b3711f | |||
| 197288453f | |||
| 00d5691a13 | |||
| 561b6684ce | |||
| a13bb3154d | |||
| fd9d3faf9f | |||
| f6cc467e95 | |||
| ef978c1230 | |||
| 52af598473 | |||
| 2acacd46c2 | |||
| 4b2f9ddb40 | |||
| 0d3dc4eba2 | |||
| 824faa8091 | |||
| d10cdfdf57 | |||
| 5e911793ce | |||
| 8c87c9aeb7 | |||
| 9da5998a5c | |||
| 08943dadca | |||
| 7fac7226c5 | |||
| 9686c8ebf9 | |||
| 4bf96d0ec9 | |||
| 34add82bee | |||
| f46e7e8c4b | |||
| 3baf254251 | |||
| 10ca9ea827 | |||
| 4a50c8ecb7 | |||
| 47d9766c78 | |||
| 45ab69960f | |||
| d3505d4ee6 | |||
| 9297d1a2f8 | |||
| 56feb7c09e | |||
| bede4b8712 | |||
| 95c1c55f22 | |||
| f547a6eb68 | |||
|
|
453a29fdf7 | ||
|
|
1a5f0259f4 | ||
|
|
d6fa61e223 | ||
| eab82b5d63 | |||
| c455b521a9 | |||
| b4f9e12293 | |||
| bbd353ea3a | |||
| 4189c5de69 | |||
| dee3218723 | |||
| 3c803a9f58 | |||
| a9b0c0fbc9 | |||
| 38b6c918f9 | |||
| 6e584c96c4 | |||
| 20338f7d14 | |||
| 1a995a5d63 | |||
| f964382175 | |||
| 0c7f60fae6 | |||
| 413e63d1ca | |||
| 8b000f4e48 | |||
| b0522507be | |||
| d4bcf7021e | |||
| 48cf0b1f67 | |||
| d82e189c01 | |||
| e5a60d1b9a | |||
| ff067351cb | |||
| 345712a617 | |||
| 118dac6907 | |||
| 5ca40caf81 | |||
| d858187fd4 | |||
| bd65517df1 | |||
| b1acad6c95 | |||
| a8333281ac | |||
| 2fdb08ac00 | |||
|
|
bd4e5a2314 | ||
| 34ed317b6b | |||
|
|
14661502ab | ||
| 097754ffdf | |||
|
|
f26ec6d295 | ||
| 858d430845 | |||
| 5134eccbf8 | |||
| 28b4737758 | |||
|
|
5c43ff4c9e | ||
|
|
53db68e39f | ||
| 9e628e34dd | |||
|
|
62d5d53232 | ||
|
|
56569a0698 | ||
|
|
ef44f818d0 | ||
|
|
8944ed6e36 | ||
| 51805b27aa | |||
| 0ec64510b3 | |||
| 20152443da | |||
|
|
7c8929fe9f | ||
| 5617516c93 | |||
| f6fe08367d | |||
| a5f02133e2 | |||
|
|
8ed9b4432d | ||
|
|
db1d05e8ad | ||
| eae58137c8 | |||
| b0f90c096f | |||
| e8361c564a | |||
|
|
54db9c9a92 | ||
|
|
73db341dc8 | ||
| 5fd30b412b | |||
|
|
bbe2e87640 | ||
|
|
67f59f6895 | ||
|
|
3e2df2e111 | ||
| 824d2149c6 | |||
|
|
c86dbe043b | ||
|
|
8043ac7f51 | ||
|
|
ead9d31647 | ||
|
|
a08e624309 | ||
| b20371c3ac | |||
| 0589a7cbcc | |||
| cf48961063 | |||
| 6046582b9c | |||
| 82aa6c70ea | |||
| e829bd8235 | |||
| 66f989e691 | |||
| eebb91fbb0 | |||
| 1d3e88bdfe | |||
| fbb03dee7e | |||
|
|
88e5afb70f | ||
| 67eabfd3af | |||
| cd1dd8c29e | |||
| 08ddb591b7 | |||
| 3e841b3c68 | |||
| 53f5a08924 | |||
| d368863c3d | |||
| c76cce5830 | |||
| 4fef93b7b1 | |||
| 241dadbeb5 | |||
| 12459c2544 | |||
| e250d6013f | |||
| 0d41d180d6 | |||
|
|
ef251ce17e | ||
| 956e11c3f8 | |||
| 951b0843b2 | |||
| a4e4080a1b | |||
| 2aa91c5d91 | |||
| 6471b3877f | |||
| 778ee142d5 | |||
| 1140132a25 | |||
| c5c299179d | |||
| 0ce4549eb8 | |||
| 97d568ddd6 | |||
| ea58465240 | |||
| 7afd262b1b | |||
| 34ceaa0823 | |||
| 57c34a07f2 | |||
| 73d1d97f1f | |||
| f7ed1a4bde | |||
| bdd80d0229 | |||
| 0238f70c64 | |||
| 24ff430c45 | |||
| 281fb14d4c | |||
| 03bac93929 | |||
| 1ae0c2a654 | |||
| 8140936bd3 | |||
| 8786acf476 | |||
| c460d4c743 | |||
| 5294adf0d7 | |||
| 00f3fa35fd | |||
| 9c9aa4f9c0 | |||
| e23a187cc4 | |||
| 3e429945dc | |||
| 8be2a8eed7 | |||
| 6b65167581 | |||
| 9d7914e69a | |||
| 6c62884b24 | |||
| 965d2a3ba8 | |||
| 40a1cc98c6 | |||
| 4c2d4ee6bd | |||
| 9276664465 | |||
| a94bcdb92d | |||
| 5da5fabfef | |||
| 05cc55c52d | |||
| 571df1349c | |||
| cbbb75062c | |||
| bb7c4205db | |||
| b2027f1625 | |||
| 65945c87df | |||
| 081582d3e1 | |||
| bf240af518 | |||
| a269131e2d | |||
| 59ece98fdc | |||
| 563924ff26 | |||
| 8ee3f55428 | |||
| 93c17607b5 | |||
| 8b4c239444 | |||
| 8bef17bf59 | |||
| a649146a39 | |||
| 9d6a5313ab | |||
| de09c950d5 | |||
| 47838b1bd9 | |||
| 02b360e2a9 | |||
| c10ab15e0c | |||
| 46f3da1a94 | |||
| 7ec9d90aab | |||
| 326bf510c9 | |||
| ce3d1f4309 | |||
| b31ba883e4 | |||
| e5d1c04616 | |||
| 34ff0ed9cf | |||
| 85bd87d5f3 | |||
| 8b274214af | |||
| 069e3102f4 | |||
| 8623b32721 | |||
| 6342e8edf0 | |||
| bbd8f0c84c | |||
| 873c951d6e | |||
| d9c864d3c5 | |||
| 4280d7109a | |||
| c8855c068f | |||
| 90503061e9 | |||
| 672ebf6426 | |||
| fd76fde23a | |||
| e24c9a3ffe | |||
| 2641d50c21 | |||
| 202f3ea3ba | |||
| 4f09e3ff7e | |||
| 1148219130 | |||
| 4b47800dfb | |||
| e2c4db9132 | |||
| 90af68b211 | |||
| 80603662b4 | |||
| d2c5d4dfd9 | |||
| 6f1b8b4041 | |||
| f63b2bf744 | |||
| 71cb75c170 | |||
| dac64f5718 | |||
| 27b2d2ac7d | |||
| 47142dd376 | |||
| d071a7e51b | |||
| 5c45884f5f | |||
| cafedd73a2 | |||
| 7163b77837 | |||
| 122c54b51e | |||
| b9d7d7d007 | |||
| 9050c9792a | |||
| aac8f760ad | |||
| 7d334c18f5 | |||
| 86b0e4b31b | |||
| af811f3dbc | |||
| d30d2ac8a5 | |||
| 86a4b10de6 | |||
| cfa7049ab9 | |||
| 391676e90a | |||
| 34e4ece8b5 | |||
| cf6443d83f | |||
| 846cf92fa4 | |||
| ab568901f8 | |||
| bfda95c0d6 | |||
| fb1875ee5b | |||
| 185d4f869b | |||
| 2ac8b61aa8 | |||
| 8739cb4656 | |||
| 826900cc41 | |||
| ec6bbdbf06 | |||
| 15a188c501 | |||
| b5440fc7d2 | |||
| 4b21adadf1 | |||
| 78ae77780b | |||
| ccb95bcbee | |||
| 21ac670bbe | |||
| 8b54dee66c | |||
| dad926f3ba | |||
| a298d949b5 | |||
| e1cf11f9d4 | |||
| a046f16308 | |||
| 97cd43792d | |||
| 08693e6d3a | |||
| e2227da8d2 | |||
| 5f20e4c583 | |||
| f82f1a12dd | |||
| 53148fd1c9 | |||
| 8985101b2a | |||
| d1949c8490 | |||
| b7faae1203 | |||
| b6a9d35c3e | |||
| 6cb6c7a448 | |||
| 22a5ad739e | |||
| 14c91bdd78 | |||
| 2c638cd2e2 | |||
| 9e59f484e3 | |||
| ac8419ecb2 | |||
| 3ecdb63063 | |||
| cfe24428fa | |||
| 4c4266dd8c | |||
| e8336bbc8a | |||
| 0f69c73e0e | |||
| e348de8dc4 | |||
| 55a3ba9be2 | |||
| 51b29b81b0 | |||
| 3c2e0334b7 | |||
| 0679626514 | |||
| 5035051135 | |||
| 63c70ee74b | |||
| 2e0bbca2e0 | |||
| b52fa23ca2 | |||
| ba03b78f23 | |||
| 04ef472c15 | |||
| 75cd8f2341 | |||
| f2e26c1800 | |||
| 0f7dd597d2 | |||
| fb0eba9201 | |||
| 3c80929c38 | |||
| b184ee835f | |||
| ef8e3bd940 | |||
| 1a64527e14 | |||
| 30b4d399b9 | |||
| 50424c2801 | |||
| 7e7c357e47 | |||
| 531b82a406 | |||
| 146ac38549 | |||
| c481956b07 | |||
| 8ef19f0825 | |||
| c1e29a8f16 | |||
| c3611eec6a | |||
| 74b58db7d1 | |||
| 9e4763c640 | |||
| abc4278fc8 | |||
| 8c4cde3d14 | |||
| 3824f6417a | |||
|
|
2be1aa2707 | ||
| da94fa5f92 | |||
| 35bf9b5ff2 | |||
| bed2cca8d2 | |||
| 9717a1c00f | |||
| 3ddc719d8a | |||
| 4b89810892 | |||
| b82367838d | |||
| dd7556ba21 | |||
| f4b6bfc594 | |||
| f9251589cd | |||
| 2de549862a | |||
| c502f70f68 | |||
| cbf076740a | |||
| 86c144b285 | |||
| 7ec6e8604c | |||
| de70f4820f | |||
|
|
febe6fcb35 | ||
|
|
3055529d4c | ||
|
|
d276bfb3ec | ||
| 9db0664465 | |||
| e9c727647a | |||
| 55eef8a3d3 | |||
| d07ad3eb26 | |||
|
|
ad53b141c7 | ||
|
|
23c13a07a9 | ||
|
|
a186b07763 | ||
|
|
1ca628aba1 | ||
| 8f4ef48891 | |||
|
|
d852ab3415 | ||
| a1bcc4b51f | |||
| be93a98bd4 | |||
| 85054d9c76 | |||
| 6c95218daf | |||
| ede6299681 | |||
| bf6e94cfb2 | |||
| 378942cbce | |||
| 1207c7b3dd | |||
| 788883df7b | |||
| 5ab1f6c203 | |||
| 175066780b | |||
| a629cf7b9f | |||
| 684130bfa3 | |||
| ee34d85dbc | |||
| d2b280da2d | |||
| a5593a725f | |||
| 5e35a91ef0 | |||
| 4abd10d9c9 | |||
| 0bbac877bd | |||
| f558bd9932 | |||
| 781c28b03c | |||
| a8be2efd85 | |||
| f46700e1cc | |||
| d7a6935a1a | |||
| a1282b2854 | |||
| 34b9ea7d20 | |||
| 0ff7ebb1fd | |||
| f83dcbc430 | |||
| 56e4a6b15f | |||
| ee9b2ec30d | |||
| 640cf1e2c1 | |||
| 56c439d716 | |||
| 1ed6e49a81 | |||
| fad9f83e6a | |||
| 2e28b0d00f | |||
| ed4ff15f96 | |||
| 1d623723a2 | |||
| 931080244f | |||
| 27e2e7f848 | |||
| 8b638c7ecb | |||
| acd370611f | |||
| e1b5a89cee | |||
| 5edebd57d9 | |||
| bcaccaaf31 | |||
| 818a5d2d85 | |||
| 13acce07d4 | |||
| 4ed5e21b7f | |||
| 86aab6bb59 | |||
| 7f5cb64b18 | |||
| 6c12eb16eb | |||
| e637f90fae | |||
| 5b33c3f491 | |||
| 1842ed464f | |||
| 296bbdd561 | |||
| 27ead1be7c | |||
| 5184609dba | |||
| 5d94d0bf75 | |||
| 72bcfa9270 | |||
| fafff9dadd | |||
| e3c20d53a8 | |||
| 8b7dc68491 | |||
| 7742fe08b5 | |||
| a773da037c | |||
| dfeb814dcc | |||
| 0623c7b1b1 | |||
| 62005f83a4 | |||
| eaafd77a7e | |||
| 9d9e415a09 | |||
| 6c1ae585b7 | |||
| 793aad7b6c | |||
| fd7807a66e | |||
| 879bd061dd | |||
| 75632b2cf1 | |||
| b65b9dc5e1 | |||
| 31d70e34e9 | |||
| 84de282655 | |||
| 997dcadf89 | |||
| b2312629ce | |||
| 3d10f964c6 | |||
| 404038edcb | |||
| ea4f9ceab1 | |||
| 5c481ea94e | |||
| 1ccaf4ba91 | |||
| b532511cd5 | |||
| b3105b439c | |||
| 2b6cb5f1a8 | |||
| f4242b10e7 | |||
| ad4d185ead | |||
| b18aafe2c4 | |||
| 340196bf9d | |||
| 883226aa70 | |||
| 0d393612a7 | |||
| 5635f6cc4e |
109
.github/release.yaml
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
name: Create Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
draft_release:
|
||||
name: Create Release
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
|
||||
steps:
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: Release ${{ github.ref }}
|
||||
body: |
|
||||
Changes in this Release
|
||||
- First Change
|
||||
- Second Change
|
||||
draft: true
|
||||
prerelease: false
|
||||
|
||||
release-mac:
|
||||
name: Create Release for macOS
|
||||
needs: draft_release
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.13
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- macOS-10.15
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- uses: haskell/actions/setup@v1.2
|
||||
with:
|
||||
ghc-version: 8.10.4
|
||||
cabal-version: 3.4.0.0
|
||||
|
||||
- name: create ~/.local/bin
|
||||
run: mkdir -p "$HOME/.local/bin"
|
||||
shell: bash
|
||||
|
||||
- name: Add ~/.local/bin to PATH
|
||||
run: echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
shell: bash
|
||||
|
||||
- name: Update cabal cache
|
||||
run: cabal update
|
||||
shell: bash
|
||||
|
||||
- name: Install cabal dependencies
|
||||
run: cabal build --only-dependencies
|
||||
shell: bash
|
||||
|
||||
- name: Build
|
||||
run: cabal build -w ghc-${GHC_VERSION} --constraint="zlib +bundled-c-zlib" --constraint="lzma +static" -ftui
|
||||
shell: bash
|
||||
|
||||
- name: Install
|
||||
run: cp "$(cabal list-bin exe:ghcup)" ~/.local/bin/ghcup
|
||||
shell: bash
|
||||
|
||||
- name: Strip
|
||||
run: strip ~/.local/bin/ghcup
|
||||
shell: bash
|
||||
|
||||
- name: Run tests
|
||||
run: cabal test --constraint="zlib +bundled-c-zlib" --constraint="lzma +static" all
|
||||
shell: bash
|
||||
|
||||
- name: Install git
|
||||
run: brew install git
|
||||
|
||||
- name: set HOME
|
||||
run: echo "HOME=$HOME" >> $GITHUB_ENV
|
||||
shell: bash
|
||||
|
||||
- name: Set ASSET_PATH
|
||||
run: echo "ASSET_PATH=$HOME/.local/bin/ghcup" >> $GITHUB_ENV
|
||||
shell: bash
|
||||
|
||||
- name: Upload Release Asset
|
||||
id: upload-release-asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ needs.draft_release.outputs.upload_url }}
|
||||
asset_path: ${{ env.ASSET_PATH }}
|
||||
asset_name: ghcup-${{ matrix.os }}
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- if: always()
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: plan.json
|
||||
path: ./dist-newstyle/cache/plan.json
|
||||
|
||||
109
.github/workflows/release.yaml
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
name: Create Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
draft_release:
|
||||
name: Draft Release
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
|
||||
steps:
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: Release ${{ github.ref }}
|
||||
body: |
|
||||
Changes in this Release
|
||||
- First Change
|
||||
- Second Change
|
||||
draft: true
|
||||
prerelease: false
|
||||
|
||||
release-mac:
|
||||
name: Create Release
|
||||
needs: draft_release
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.13
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- macOS-10.15
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- uses: haskell/actions/setup@v1.2
|
||||
with:
|
||||
ghc-version: 8.10.7
|
||||
cabal-version: 3.6.2.0
|
||||
|
||||
- name: create ~/.local/bin
|
||||
run: mkdir -p "$HOME/.local/bin"
|
||||
shell: bash
|
||||
|
||||
- name: Add ~/.local/bin to PATH
|
||||
run: echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
shell: bash
|
||||
|
||||
- name: Update cabal cache
|
||||
run: cabal update
|
||||
shell: bash
|
||||
|
||||
- name: Install cabal dependencies
|
||||
run: cabal build --only-dependencies --constraint="zlib +bundled-c-zlib" --constraint="lzma +static" -ftui
|
||||
shell: bash
|
||||
|
||||
- name: Build
|
||||
run: cabal build --constraint="zlib +bundled-c-zlib" --constraint="lzma +static" -ftui
|
||||
shell: bash
|
||||
|
||||
- name: Install
|
||||
run: cp "$(cabal list-bin exe:ghcup)" ~/.local/bin/ghcup
|
||||
shell: bash
|
||||
|
||||
- name: Strip
|
||||
run: strip ~/.local/bin/ghcup
|
||||
shell: bash
|
||||
|
||||
- name: Run tests
|
||||
run: cabal test --constraint="zlib +bundled-c-zlib" --constraint="lzma +static" all
|
||||
shell: bash
|
||||
|
||||
- name: Install git
|
||||
run: brew install git
|
||||
|
||||
- name: set HOME
|
||||
run: echo "HOME=$HOME" >> $GITHUB_ENV
|
||||
shell: bash
|
||||
|
||||
- name: Set ASSET_PATH
|
||||
run: echo "ASSET_PATH=$HOME/.local/bin/ghcup" >> $GITHUB_ENV
|
||||
shell: bash
|
||||
|
||||
- name: Upload Release Asset
|
||||
id: upload-release-asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ needs.draft_release.outputs.upload_url }}
|
||||
asset_path: ${{ env.ASSET_PATH }}
|
||||
asset_name: ghcup-${{ matrix.os }}
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- if: always()
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: plan.json
|
||||
path: ./dist-newstyle/cache/plan.json
|
||||
|
||||
29
.github/workflows/shimgen.yaml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
name: Shimgen CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build-shimgen:
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [windows-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
|
||||
- name: compile
|
||||
run: cl /O1 scoop-better-shimexe/shim.c
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: shim.exe
|
||||
path: shim.exe
|
||||
|
||||
15
.gitignore
vendored
@@ -1,2 +1,17 @@
|
||||
.ghci
|
||||
.vim
|
||||
codex.tags
|
||||
dist-newstyle/
|
||||
cabal.project.local
|
||||
.stack-work/
|
||||
bin/
|
||||
/*.prof
|
||||
/*.ps
|
||||
/*.hp
|
||||
tags
|
||||
TAGS
|
||||
/tmp/
|
||||
.entangled
|
||||
release/
|
||||
releases/
|
||||
site/
|
||||
|
||||
689
.gitlab-ci.yml
Normal file
@@ -0,0 +1,689 @@
|
||||
stages:
|
||||
- checks
|
||||
- quick-test
|
||||
- test
|
||||
- expensive-test
|
||||
- release
|
||||
|
||||
variables:
|
||||
GIT_SSL_NO_VERIFY: "1"
|
||||
|
||||
# Commit of ghc/ci-images repository from which to pull Docker images
|
||||
DOCKER_REV: 8d0224e6b2a08157649651e69302380b2bd24e11
|
||||
|
||||
# Sequential version number of all cached things.
|
||||
# Bump to invalidate GitLab CI cache.
|
||||
CACHE_REV: 1
|
||||
|
||||
GIT_SUBMODULE_STRATEGY: recursive
|
||||
|
||||
|
||||
############################################################
|
||||
# CI Step
|
||||
############################################################
|
||||
|
||||
.debian:
|
||||
image: "registry.gitlab.haskell.org/ghc/ci-images/x86_64-linux-deb10:$DOCKER_REV"
|
||||
tags:
|
||||
- x86_64-linux
|
||||
variables:
|
||||
OS: "LINUX"
|
||||
ARCH: "64"
|
||||
CABAL_DIR: "$CI_PROJECT_DIR/cabal"
|
||||
CROSS: ""
|
||||
|
||||
.alpine:64bit:
|
||||
image: "alpine:3.12"
|
||||
tags:
|
||||
- x86_64-linux
|
||||
variables:
|
||||
OS: "LINUX"
|
||||
ARCH: "64"
|
||||
CABAL_DIR: "$CI_PROJECT_DIR/cabal"
|
||||
|
||||
.alpine:32bit:
|
||||
image: "i386/alpine:3.12"
|
||||
tags:
|
||||
- x86_64-linux
|
||||
variables:
|
||||
OS: "LINUX"
|
||||
ARCH: "32"
|
||||
CABAL_DIR: "$CI_PROJECT_DIR/cabal"
|
||||
|
||||
.linux:armv7:
|
||||
image: "registry.gitlab.haskell.org/ghc/ci-images/armv7-linux-deb10:$DOCKER_REV"
|
||||
tags:
|
||||
- armv7-linux
|
||||
variables:
|
||||
OS: "LINUX"
|
||||
ARCH: "ARM"
|
||||
CABAL_DIR: "$CI_PROJECT_DIR/cabal"
|
||||
retry: 2
|
||||
|
||||
.linux:aarch64:
|
||||
image: "registry.gitlab.haskell.org/ghc/ci-images/aarch64-linux-deb10:$DOCKER_REV"
|
||||
tags:
|
||||
- aarch64-linux
|
||||
variables:
|
||||
OS: "LINUX"
|
||||
ARCH: "ARM64"
|
||||
CABAL_DIR: "$CI_PROJECT_DIR/cabal"
|
||||
|
||||
.darwin:
|
||||
tags:
|
||||
- x86_64-darwin
|
||||
variables:
|
||||
OS: "DARWIN"
|
||||
ARCH: "64"
|
||||
CABAL_DIR: "$CI_PROJECT_DIR/cabal"
|
||||
|
||||
.darwin:aarch64:
|
||||
tags:
|
||||
- aarch64-darwin-m1
|
||||
variables:
|
||||
OS: "DARWIN"
|
||||
ARCH: "ARM64"
|
||||
CABAL_DIR: "$CI_PROJECT_DIR/cabal"
|
||||
|
||||
.freebsd13:
|
||||
tags:
|
||||
- x86_64-freebsd13
|
||||
variables:
|
||||
OS: "FREEBSD"
|
||||
ARCH: "64"
|
||||
CABAL_DIR: "$CI_PROJECT_DIR/cabal"
|
||||
|
||||
.freebsd12:
|
||||
tags:
|
||||
- x86_64-freebsd12
|
||||
variables:
|
||||
OS: "FREEBSD"
|
||||
ARCH: "64"
|
||||
CABAL_DIR: "$CI_PROJECT_DIR/cabal"
|
||||
|
||||
.windows:
|
||||
tags:
|
||||
- new-x86_64-windows
|
||||
variables:
|
||||
OS: "WINDOWS"
|
||||
ARCH: "64"
|
||||
CABAL_DIR: "$CI_PROJECT_DIR/cabal"
|
||||
retry: 2
|
||||
|
||||
.root_cleanup:
|
||||
after_script:
|
||||
- bash ./.gitlab/after_script.sh
|
||||
|
||||
.test_ghcup_version:
|
||||
script:
|
||||
- bash ./.gitlab/script/ghcup_version.sh
|
||||
variables:
|
||||
JSON_VERSION: "0.0.7"
|
||||
artifacts:
|
||||
expire_in: 2 week
|
||||
paths:
|
||||
- test/golden
|
||||
- dist-newstyle/cache/
|
||||
when: on_failure
|
||||
cache:
|
||||
key: ghcup-test-$CACHE_REV
|
||||
paths:
|
||||
- cabal-cache
|
||||
|
||||
# .test_ghcup_scoop:
|
||||
# script:
|
||||
# - cl /O1 scoop-better-shimexe/shim.c
|
||||
|
||||
.test_ghcup_version:linux:
|
||||
extends:
|
||||
- .test_ghcup_version
|
||||
- .debian
|
||||
before_script:
|
||||
- ./.gitlab/before_script/linux/install_deps.sh
|
||||
- ./.gitlab/script/ci.sh extract_cabal_cache
|
||||
after_script:
|
||||
- ./.gitlab/script/ci.sh save_cabal_cache
|
||||
- bash ./.gitlab/after_script.sh
|
||||
|
||||
.test_ghcup_version:linux32:
|
||||
extends:
|
||||
- .test_ghcup_version
|
||||
- .alpine:32bit
|
||||
before_script:
|
||||
- ./.gitlab/before_script/linux/alpine/install_deps.sh
|
||||
- ./.gitlab/script/ci.sh extract_cabal_cache
|
||||
after_script:
|
||||
- ./.gitlab/script/ci.sh save_cabal_cache
|
||||
- bash ./.gitlab/after_script.sh
|
||||
|
||||
.test_ghcup_version:armv7:
|
||||
extends:
|
||||
- .test_ghcup_version
|
||||
- .linux:armv7
|
||||
before_script:
|
||||
- ./.gitlab/before_script/linux/install_deps.sh
|
||||
- ./.gitlab/script/ci.sh extract_cabal_cache
|
||||
after_script:
|
||||
- ./.gitlab/script/ci.sh save_cabal_cache
|
||||
- bash ./.gitlab/after_script.sh
|
||||
|
||||
.test_ghcup_version:aarch64:
|
||||
extends:
|
||||
- .test_ghcup_version
|
||||
- .linux:aarch64
|
||||
before_script:
|
||||
- ./.gitlab/before_script/linux/install_deps.sh
|
||||
- ./.gitlab/script/ci.sh extract_cabal_cache
|
||||
after_script:
|
||||
- ./.gitlab/script/ci.sh save_cabal_cache
|
||||
- bash ./.gitlab/after_script.sh
|
||||
|
||||
.test_ghcup_version:darwin:
|
||||
extends:
|
||||
- .test_ghcup_version
|
||||
- .darwin
|
||||
before_script:
|
||||
- ./.gitlab/before_script/darwin/install_deps.sh
|
||||
- ./.gitlab/script/ci.sh extract_cabal_cache
|
||||
after_script:
|
||||
- ./.gitlab/script/ci.sh save_cabal_cache
|
||||
- bash ./.gitlab/after_script.sh
|
||||
|
||||
.test_ghcup_version:darwin:aarch64:
|
||||
extends:
|
||||
- .test_ghcup_version
|
||||
- .darwin:aarch64
|
||||
cache:
|
||||
key: darwin-brew-$CACHE_REV
|
||||
paths:
|
||||
- brew_cache
|
||||
key: ghcup-test-$CACHE_REV
|
||||
paths:
|
||||
- cabal-cache
|
||||
before_script:
|
||||
# extract brew cache
|
||||
- ./.gitlab/script/ci.sh extract_brew_cache
|
||||
# otherwise we seem to get intel binaries
|
||||
- export HOMEBREW_CHANGE_ARCH_TO_ARM=1
|
||||
# update and install packages
|
||||
- /bin/bash ./.gitlab/script/brew.sh llvm autoconf automake coreutils
|
||||
# extract cabal cache
|
||||
- ./.gitlab/script/ci.sh extract_cabal_cache
|
||||
script: |
|
||||
export PATH="$CI_PROJECT_DIR/.brew/opt/llvm/bin:$CI_PROJECT_DIR/.brew/bin:$CI_PROJECT_DIR/.brew/sbin:$PATH"
|
||||
export CC=$CI_PROJECT_DIR/.brew/opt/llvm/bin/clang
|
||||
export CXX=$CI_PROJECT_DIR/.brew/opt/llvm/bin/clang++
|
||||
export LD=ld
|
||||
export AR=$CI_PROJECT_DIR/.brew/opt/llvm/bin/llvm-ar
|
||||
export RANLIB=$CI_PROJECT_DIR/.brew/opt/llvm/bin/llvm-ranlib
|
||||
./.gitlab/before_script/darwin/install_deps.sh
|
||||
./.gitlab/script/ghcup_version.sh
|
||||
after_script:
|
||||
- ./.gitlab/script/ci.sh save_cabal_cache
|
||||
- ./.gitlab/script/ci.sh save_brew_cache
|
||||
- bash ./.gitlab/after_script.sh
|
||||
|
||||
.test_ghcup_version:freebsd12:
|
||||
extends:
|
||||
- .test_ghcup_version
|
||||
- .freebsd12
|
||||
before_script:
|
||||
- ./.gitlab/before_script/freebsd/install_deps.sh
|
||||
- ./.gitlab/script/ci.sh extract_cabal_cache
|
||||
after_script:
|
||||
- ./.gitlab/script/ci.sh save_cabal_cache
|
||||
- bash ./.gitlab/after_script.sh
|
||||
|
||||
.test_ghcup_version:freebsd13:
|
||||
extends:
|
||||
- .test_ghcup_version
|
||||
- .freebsd13
|
||||
before_script:
|
||||
- sudo pkg update
|
||||
- sudo pkg install --yes compat12x-amd64
|
||||
- sudo ln -s libncurses.so.6 /usr/local/lib/libncurses.so.6.2
|
||||
- ./.gitlab/before_script/freebsd/install_deps.sh
|
||||
- ./.gitlab/script/ci.sh extract_cabal_cache
|
||||
after_script:
|
||||
- ./.gitlab/script/ci.sh save_cabal_cache
|
||||
- bash ./.gitlab/after_script.sh
|
||||
|
||||
.test_ghcup_version:windows:
|
||||
extends:
|
||||
- .test_ghcup_version
|
||||
- .windows
|
||||
before_script:
|
||||
- bash ./.gitlab/before_script/windows/install_deps.sh
|
||||
- bash ./.gitlab/script/ci.sh extract_cabal_cache
|
||||
after_script:
|
||||
- bash ./.gitlab/script/ci.sh save_cabal_cache
|
||||
- bash ./.gitlab/after_script.sh
|
||||
|
||||
# .test_ghcup_scoop:windows:
|
||||
# extends:
|
||||
# - .windows
|
||||
# - .test_ghcup_scoop
|
||||
|
||||
.release_ghcup:
|
||||
script:
|
||||
- bash ./.gitlab/script/ghcup_release.sh
|
||||
artifacts:
|
||||
expire_in: 2 week
|
||||
paths:
|
||||
- out
|
||||
- dist-newstyle/cache/
|
||||
only:
|
||||
- tags
|
||||
variables:
|
||||
JSON_VERSION: "0.0.7"
|
||||
|
||||
######## stack test ########
|
||||
|
||||
test:linux:stack:
|
||||
stage: test
|
||||
before_script:
|
||||
- ./.gitlab/script/ci.sh extract_stack_cache
|
||||
- ./.gitlab/before_script/linux/install_deps_minimal.sh
|
||||
script:
|
||||
- ./.gitlab/script/ghcup_stack.sh
|
||||
after_script:
|
||||
- ./.gitlab/script/ci.sh save_stack_cache
|
||||
extends:
|
||||
- .debian
|
||||
needs: []
|
||||
|
||||
######## bootstrap test ########
|
||||
|
||||
test:linux:bootstrap_script:
|
||||
stage: quick-test
|
||||
before_script:
|
||||
- ./.gitlab/before_script/linux/install_deps_minimal.sh
|
||||
script:
|
||||
- ./.gitlab/script/ghcup_bootstrap.sh
|
||||
variables:
|
||||
GHC_VERSION: "8.10.7"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
extends:
|
||||
- .debian
|
||||
- .root_cleanup
|
||||
needs: []
|
||||
|
||||
test:windows:bootstrap_powershell_script:
|
||||
stage: quick-test
|
||||
script:
|
||||
- ./scripts/bootstrap/bootstrap-haskell.ps1 -InstallDir $CI_PROJECT_DIR -BootstrapUrl $CI_PROJECT_DIR/bootstrap-haskell -InBash
|
||||
after_script:
|
||||
- "[Environment]::SetEnvironmentVariable('GHCUP_INSTALL_BASE_PREFIX', $null, [System.EnvironmentVariableTarget]::User)"
|
||||
- "[Environment]::SetEnvironmentVariable('GHCUP_MSYS2', $null, [System.EnvironmentVariableTarget]::User)"
|
||||
- "[Environment]::SetEnvironmentVariable('CABAL_DIR', $null, [System.EnvironmentVariableTarget]::User)"
|
||||
- bash ./.gitlab/after_script.sh
|
||||
- bash ./.gitlab/script/ci.sh save_cabal_cache
|
||||
variables:
|
||||
GHC_VERSION: "8.10.7"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
extends:
|
||||
- .windows
|
||||
needs: []
|
||||
|
||||
######## linux test ########
|
||||
|
||||
test:linux:
|
||||
stage: test
|
||||
extends: .test_ghcup_version:linux
|
||||
variables:
|
||||
GHC_VERSION: "8.10.7"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
needs: []
|
||||
|
||||
test:linux:hls:
|
||||
stage: expensive-test
|
||||
extends:
|
||||
- .test_ghcup_version
|
||||
- .debian
|
||||
variables:
|
||||
GHC_VERSION: "8.10.7"
|
||||
HLS_TARGET_VERSION: "1.4.0"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
needs: []
|
||||
when: manual
|
||||
allow_failure: true
|
||||
before_script:
|
||||
- ./.gitlab/before_script/linux/install_deps.sh
|
||||
script:
|
||||
- ./.gitlab/script/ghcup_hls.sh
|
||||
|
||||
test:linux:cross-armv7:
|
||||
stage: expensive-test
|
||||
extends:
|
||||
- .test_ghcup_version
|
||||
- .debian
|
||||
variables:
|
||||
GHC_VERSION: "8.10.6"
|
||||
GHC_TARGET_VERSION: "8.10.7"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
CROSS: "arm-linux-gnueabihf"
|
||||
needs: []
|
||||
when: manual
|
||||
allow_failure: true
|
||||
before_script:
|
||||
- ./.gitlab/before_script/linux/install_deps.sh
|
||||
script:
|
||||
- ./.gitlab/script/ghcup_cross.sh
|
||||
|
||||
test:linux:git:hadrian:
|
||||
stage: expensive-test
|
||||
extends:
|
||||
- .test_ghcup_version
|
||||
- .debian
|
||||
variables:
|
||||
GHC_VERSION: "8.10.7"
|
||||
GHC_GIT_TAG: "ghc-9.0.1-release"
|
||||
GHC_GIT_VERSION: "9.0.1"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
CROSS: ""
|
||||
needs: []
|
||||
when: manual
|
||||
allow_failure: true
|
||||
before_script:
|
||||
- ./.gitlab/before_script/linux/install_deps.sh
|
||||
script:
|
||||
- ./.gitlab/script/ghcup_git.sh
|
||||
|
||||
|
||||
######## linux 32bit test ########
|
||||
|
||||
test:linux:32bit:
|
||||
stage: test
|
||||
extends: .test_ghcup_version:linux32
|
||||
variables:
|
||||
GHC_VERSION: "8.10.7"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
needs: []
|
||||
|
||||
######## arm tests ########
|
||||
|
||||
test:linux:armv7:
|
||||
stage: test
|
||||
extends: .test_ghcup_version:armv7
|
||||
variables:
|
||||
GHC_VERSION: "8.10.7"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
CROSS: ""
|
||||
when: manual
|
||||
needs: []
|
||||
|
||||
test:linux:aarch64:
|
||||
stage: test
|
||||
extends: .test_ghcup_version:aarch64
|
||||
variables:
|
||||
GHC_VERSION: "8.10.7"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
CROSS: ""
|
||||
when: manual
|
||||
needs: []
|
||||
|
||||
######## darwin test ########
|
||||
|
||||
test:mac:
|
||||
stage: test
|
||||
extends: .test_ghcup_version:darwin
|
||||
variables:
|
||||
GHC_VERSION: "8.10.7"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
needs: []
|
||||
|
||||
test:mac:aarch64:
|
||||
stage: test
|
||||
extends: .test_ghcup_version:darwin:aarch64
|
||||
variables:
|
||||
GHC_VERSION: "8.10.7"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
needs: []
|
||||
allow_failure: true
|
||||
when: manual
|
||||
|
||||
|
||||
######## freebsd test ########
|
||||
|
||||
test:freebsd12:
|
||||
stage: test
|
||||
extends: .test_ghcup_version:freebsd12
|
||||
variables:
|
||||
GHC_VERSION: "8.10.7"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
allow_failure: true # freebsd runners are unreliable
|
||||
when: manual
|
||||
needs: []
|
||||
|
||||
test:freebsd13:
|
||||
stage: test
|
||||
extends: .test_ghcup_version:freebsd13
|
||||
variables:
|
||||
GHC_VERSION: "8.10.7"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
allow_failure: true # freebsd runners are unreliable
|
||||
when: manual
|
||||
needs: []
|
||||
|
||||
######## windows test ########
|
||||
|
||||
test:windows:
|
||||
stage: test
|
||||
extends: .test_ghcup_version:windows
|
||||
variables:
|
||||
GHC_VERSION: "8.10.7"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
needs: []
|
||||
|
||||
# test:windows:scoop:
|
||||
# stage: test
|
||||
# extends: .test_ghcup_scoop:windows
|
||||
# needs: []
|
||||
|
||||
######## linux release ########
|
||||
|
||||
release:linux:64bit:
|
||||
stage: release
|
||||
needs: ["test:linux"]
|
||||
extends:
|
||||
- .alpine:64bit
|
||||
- .release_ghcup
|
||||
before_script:
|
||||
- ./.gitlab/before_script/linux/alpine/install_deps.sh
|
||||
variables:
|
||||
ARTIFACT: "x86_64-linux-ghcup"
|
||||
GHC_VERSION: "8.10.7"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
|
||||
|
||||
release:linux:32bit:
|
||||
stage: release
|
||||
needs: ["test:linux:32bit"]
|
||||
extends:
|
||||
- .alpine:32bit
|
||||
- .release_ghcup
|
||||
before_script:
|
||||
- ./.gitlab/before_script/linux/alpine/install_deps.sh
|
||||
variables:
|
||||
ARTIFACT: "i386-linux-ghcup"
|
||||
GHC_VERSION: "8.10.7"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
|
||||
release:linux:armv7:
|
||||
stage: release
|
||||
needs: ["test:linux:armv7"]
|
||||
extends:
|
||||
- .linux:armv7
|
||||
- .release_ghcup
|
||||
before_script:
|
||||
- ./.gitlab/before_script/linux/install_deps.sh
|
||||
variables:
|
||||
ARTIFACT: "armv7-linux-ghcup"
|
||||
GHC_VERSION: "8.10.7"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
CROSS: ""
|
||||
|
||||
release:linux:aarch64:
|
||||
stage: release
|
||||
needs: ["test:linux:aarch64"]
|
||||
extends:
|
||||
- .linux:aarch64
|
||||
- .release_ghcup
|
||||
before_script:
|
||||
- ./.gitlab/before_script/linux/install_deps.sh
|
||||
variables:
|
||||
ARTIFACT: "aarch64-linux-ghcup"
|
||||
GHC_VERSION: "8.10.7"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
CROSS: ""
|
||||
|
||||
######## darwin release ########
|
||||
|
||||
release:darwin:
|
||||
stage: release
|
||||
needs: ["test:mac"]
|
||||
extends:
|
||||
- .darwin
|
||||
- .release_ghcup
|
||||
- .root_cleanup
|
||||
before_script:
|
||||
- ./.gitlab/before_script/darwin/install_deps.sh
|
||||
variables:
|
||||
ARTIFACT: "x86_64-apple-darwin-ghcup"
|
||||
GHC_VERSION: "8.10.7"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
MACOSX_DEPLOYMENT_TARGET: "10.7"
|
||||
|
||||
release:darwin:aarch64:
|
||||
stage: release
|
||||
needs: ["test:mac:aarch64"]
|
||||
extends:
|
||||
- .darwin:aarch64
|
||||
- .release_ghcup
|
||||
- .root_cleanup
|
||||
cache:
|
||||
key: darwin-brew-$CACHE_REV
|
||||
paths:
|
||||
- brew_cache
|
||||
key: ghcup-test-$CACHE_REV
|
||||
paths:
|
||||
- cabal-cache
|
||||
before_script:
|
||||
- ./.gitlab/script/ci.sh extract_brew_cache
|
||||
- ./.gitlab/script/ci.sh extract_cabal_cache
|
||||
# otherwise we seem to get intel binaries
|
||||
- export HOMEBREW_CHANGE_ARCH_TO_ARM=1
|
||||
# update and install packages
|
||||
- /bin/bash ./.gitlab/script/brew.sh llvm autoconf automake coreutils
|
||||
script: |
|
||||
export PATH="$CI_PROJECT_DIR/.brew/opt/llvm/bin:$CI_PROJECT_DIR/.brew/bin:$CI_PROJECT_DIR/.brew/sbin:$PATH"
|
||||
export CC=$CI_PROJECT_DIR/.brew/opt/llvm/bin/clang
|
||||
export CXX=$CI_PROJECT_DIR/.brew/opt/llvm/bin/clang++
|
||||
export LD=ld
|
||||
export AR=$CI_PROJECT_DIR/.brew/opt/llvm/bin/llvm-ar
|
||||
export RANLIB=$CI_PROJECT_DIR/.brew/opt/llvm/bin/llvm-ranlib
|
||||
./.gitlab/before_script/darwin/install_deps.sh
|
||||
./.gitlab/script/ghcup_release.sh
|
||||
after_script:
|
||||
- ./.gitlab/script/ci.sh save_cabal_cache
|
||||
- ./.gitlab/script/ci.sh save_brew_cache
|
||||
variables:
|
||||
ARTIFACT: "aarch64-apple-darwin-ghcup"
|
||||
GHC_VERSION: "8.10.7"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
MACOSX_DEPLOYMENT_TARGET: "10.7"
|
||||
allow_failure: true
|
||||
when: manual
|
||||
|
||||
|
||||
######## freebsd release ########
|
||||
|
||||
release:freebsd12:
|
||||
stage: release
|
||||
needs: ["test:freebsd12"]
|
||||
extends:
|
||||
- .freebsd12
|
||||
- .release_ghcup
|
||||
- .root_cleanup
|
||||
before_script:
|
||||
- ./.gitlab/before_script/freebsd/install_deps.sh
|
||||
variables:
|
||||
ARTIFACT: "x86_64-portbld-freebsd-ghcup"
|
||||
GHC_VERSION: "8.10.7"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
allow_failure: true
|
||||
|
||||
release:freebsd13:
|
||||
stage: release
|
||||
needs: ["test:freebsd13"]
|
||||
extends:
|
||||
- .freebsd13
|
||||
- .release_ghcup
|
||||
- .root_cleanup
|
||||
before_script:
|
||||
- sudo pkg update
|
||||
- sudo pkg install --yes compat12x-amd64
|
||||
- sudo ln -s libncurses.so.6 /usr/local/lib/libncurses.so.6.2
|
||||
- ./.gitlab/before_script/freebsd/install_deps.sh
|
||||
variables:
|
||||
ARTIFACT: "x86_64-portbld-freebsd-ghcup"
|
||||
GHC_VERSION: "8.10.7"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
allow_failure: true
|
||||
|
||||
######## windows release ########
|
||||
|
||||
release:windows:
|
||||
stage: release
|
||||
needs: ["test:windows"]
|
||||
extends:
|
||||
- .windows
|
||||
- .release_ghcup
|
||||
- .root_cleanup
|
||||
before_script:
|
||||
- bash ./.gitlab/before_script/windows/install_deps.sh
|
||||
variables:
|
||||
ARTIFACT: "x86_64-mingw64-ghcup"
|
||||
GHC_VERSION: "8.10.7"
|
||||
CABAL_VERSION: "3.6.2.0"
|
||||
|
||||
######## hlint ########
|
||||
|
||||
hlint:
|
||||
stage: checks
|
||||
extends:
|
||||
- .debian
|
||||
script:
|
||||
- curl -sSL https://raw.github.com/ndmitchell/hlint/master/misc/run.sh | sh -s -- -r lib/ test/
|
||||
allow_failure: true
|
||||
artifacts:
|
||||
expire_in: 2 week
|
||||
paths:
|
||||
- report.html
|
||||
when: on_failure
|
||||
|
||||
######## mkdocs ########
|
||||
|
||||
mkdocs:
|
||||
stage: checks
|
||||
extends:
|
||||
- .debian
|
||||
before_script:
|
||||
- sudo apt-get update -y
|
||||
- sudo apt-get install -y python3-pip
|
||||
- pip3 install mkdocs
|
||||
script:
|
||||
- ~/.local/bin/mkdocs build
|
||||
allow_failure: true
|
||||
|
||||
######## shellcheck ########
|
||||
|
||||
shellcheck:
|
||||
image: "koalaman/shellcheck-alpine"
|
||||
tags:
|
||||
- x86_64-linux
|
||||
stage: checks
|
||||
script:
|
||||
- shellcheck scripts/bootstrap/bootstrap-haskell
|
||||
allow_failure: true
|
||||
|
||||
19
.gitlab/after_script.sh
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
BUILD_DIR=$CI_PROJECT_DIR
|
||||
echo "Cleaning $BUILD_DIR"
|
||||
cd $HOME
|
||||
test -n "$BUILD_DIR"
|
||||
shopt -s extglob
|
||||
rm -Rf "$BUILD_DIR"/!(out)
|
||||
if [ "${OS}" = "WINDOWS" ] ; then
|
||||
rm -Rf /c/ghcup
|
||||
fi
|
||||
|
||||
if [ "${OS}" = "DARWIN" ] ; then
|
||||
rm -Rf /private/tmp/.brew_tmp
|
||||
fi
|
||||
|
||||
exit 0
|
||||
32
.gitlab/before_script/darwin/install_deps.sh
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../../ghcup_env"
|
||||
|
||||
mkdir -p "${TMPDIR}"
|
||||
|
||||
if [ $ARCH = 'ARM64' ] ; then
|
||||
curl -sSfL https://downloads.haskell.org/~ghcup/aarch64-apple-darwin-ghcup > ./ghcup-bin
|
||||
chmod +x ghcup-bin
|
||||
else
|
||||
curl -sSfL https://downloads.haskell.org/~ghcup/x86_64-apple-darwin-ghcup > ./ghcup-bin
|
||||
chmod +x ghcup-bin
|
||||
./ghcup-bin upgrade -i -f
|
||||
fi
|
||||
|
||||
./ghcup-bin install ${GHC_VERSION}
|
||||
./ghcup-bin set ${GHC_VERSION}
|
||||
./ghcup-bin install-cabal ${CABAL_VERSION}
|
||||
|
||||
if [ $ARCH = 'ARM64' ] ; then
|
||||
cabal update
|
||||
mkdir vendored
|
||||
cd vendored
|
||||
cabal unpack network-3.1.2.1
|
||||
cd network*
|
||||
autoreconf -fi
|
||||
cd ../..
|
||||
fi
|
||||
|
||||
exit 0
|
||||
27
.gitlab/before_script/freebsd/install_deps.sh
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
# pkg install --force --yes --no-repo-update curl gcc gmp gmake ncurses perl5 libffi libiconv
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../../ghcup_env"
|
||||
|
||||
mkdir -p "${TMPDIR}"
|
||||
|
||||
if freebsd-version | grep -E '^12.*' ; then
|
||||
freebsd_ver=12
|
||||
elif freebsd-version | grep -E '^13.*' ; then
|
||||
freebsd_ver=13
|
||||
else
|
||||
(>&2 echo "Unsupported FreeBSD version! Please report a bug at https://gitlab.haskell.org/haskell/ghcup-hs/-/issues")
|
||||
exit 1
|
||||
fi
|
||||
curl -sSfL https://downloads.haskell.org/~ghcup/x86_64-freebsd${freebsd_ver}-ghcup > ./ghcup-bin
|
||||
chmod +x ghcup-bin
|
||||
|
||||
./ghcup-bin -v upgrade -i -f
|
||||
./ghcup-bin -v install ${GHC_VERSION}
|
||||
./ghcup-bin -v set ${GHC_VERSION}
|
||||
./ghcup-bin -v install-cabal ${CABAL_VERSION}
|
||||
|
||||
exit 0
|
||||
58
.gitlab/before_script/linux/alpine/install_deps.sh
Executable file
@@ -0,0 +1,58 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../../../ghcup_env"
|
||||
|
||||
mkdir -p "${TMPDIR}"
|
||||
|
||||
apk add --no-cache \
|
||||
curl \
|
||||
gcc \
|
||||
g++ \
|
||||
binutils \
|
||||
binutils-gold \
|
||||
bsd-compat-headers \
|
||||
gmp-dev \
|
||||
ncurses-dev \
|
||||
libffi-dev \
|
||||
make \
|
||||
xz \
|
||||
tar \
|
||||
perl
|
||||
|
||||
if [ "${ARCH}" = "32" ] ; then
|
||||
curl -sSfL https://downloads.haskell.org/ghcup/i386-linux-ghcup > ./ghcup-bin
|
||||
else
|
||||
curl -sSfL https://downloads.haskell.org/ghcup/x86_64-linux-ghcup > ./ghcup-bin
|
||||
fi
|
||||
chmod +x ghcup-bin
|
||||
./ghcup-bin upgrade -i -f
|
||||
./ghcup-bin install ${GHC_VERSION}
|
||||
./ghcup-bin install-cabal ${CABAL_VERSION}
|
||||
|
||||
# utils
|
||||
apk add --no-cache \
|
||||
bash \
|
||||
git
|
||||
|
||||
## Package specific
|
||||
apk add --no-cache \
|
||||
zlib \
|
||||
zlib-dev \
|
||||
zlib-static \
|
||||
bzip2 \
|
||||
bzip2-dev \
|
||||
bzip2-static \
|
||||
gmp \
|
||||
gmp-dev \
|
||||
openssl-dev \
|
||||
openssl-libs-static \
|
||||
xz \
|
||||
xz-dev \
|
||||
ncurses-static
|
||||
|
||||
if [ "${ARCH}" = "32" ] ; then
|
||||
apk add --no-cache \
|
||||
bsd-compat-headers
|
||||
fi
|
||||
27
.gitlab/before_script/linux/install_deps.sh
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../../ghcup_env"
|
||||
|
||||
mkdir -p "${TMPDIR}"
|
||||
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y libnuma-dev zlib1g-dev libgmp-dev libgmp10 libssl-dev liblzma-dev libbz2-dev git wget lsb-release software-properties-common gnupg2 apt-transport-https gcc autoconf automake build-essential
|
||||
|
||||
if [ "${CROSS}" = "arm-linux-gnueabihf" ] ; then
|
||||
sudo apt-get install -y gcc-arm-linux-gnueabihf
|
||||
sudo dpkg --add-architecture armhf
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y libncurses-dev:armhf
|
||||
fi
|
||||
|
||||
export BOOTSTRAP_HASKELL_NONINTERACTIVE=1
|
||||
export BOOTSTRAP_HASKELL_GHC_VERSION=$GHC_VERSION
|
||||
export BOOTSTRAP_HASKELL_CABAL_VERSION=$CABAL_VERSION
|
||||
export BOOTSTRAP_HASKELL_VERBOSE=1
|
||||
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
|
||||
|
||||
rm "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin/ghcup
|
||||
|
||||
10
.gitlab/before_script/linux/install_deps_minimal.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../../ghcup_env"
|
||||
|
||||
mkdir -p "${TMPDIR}"
|
||||
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y libnuma-dev zlib1g-dev libgmp-dev libgmp10 libssl-dev liblzma-dev libbz2-dev git wget
|
||||
21
.gitlab/before_script/windows/install_deps.sh
Normal file
@@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../../ghcup_env"
|
||||
|
||||
mkdir -p "${TMPDIR}" "${CABAL_DIR}"
|
||||
|
||||
mkdir -p "$GHCUP_INSTALL_BASE_PREFIX/ghcup/bin"
|
||||
|
||||
CI_PROJECT_DIR=$(pwd)
|
||||
curl -o ghcup.exe https://downloads.haskell.org/~ghcup/x86_64-mingw64-ghcup.exe
|
||||
chmod +x ghcup.exe
|
||||
|
||||
./ghcup.exe install ${GHC_VERSION}
|
||||
./ghcup.exe set ${GHC_VERSION}
|
||||
./ghcup.exe install-cabal ${CABAL_VERSION}
|
||||
|
||||
rm ./ghcup.exe
|
||||
|
||||
exit 0
|
||||
8734
.gitlab/ghc-8.10.3-linux.files
Normal file
10321
.gitlab/ghc-8.10.3-windows.files
Normal file
37
.gitlab/ghcup-run.files
Normal file
@@ -0,0 +1,37 @@
|
||||
.
|
||||
./cabal
|
||||
./ghc
|
||||
./ghc-8.10.7
|
||||
./ghc-pkg
|
||||
./ghc-pkg-8.10.7
|
||||
./ghci
|
||||
./ghci-8.10.7
|
||||
./haddock
|
||||
./haddock-8.10.7
|
||||
./haskell-language-server-8.10.6
|
||||
./haskell-language-server-8.10.6~1.6.1.0
|
||||
./haskell-language-server-8.10.7
|
||||
./haskell-language-server-8.10.7~1.6.1.0
|
||||
./haskell-language-server-8.6.5
|
||||
./haskell-language-server-8.6.5~1.6.1.0
|
||||
./haskell-language-server-8.8.4
|
||||
./haskell-language-server-8.8.4~1.6.1.0
|
||||
./haskell-language-server-9.0.1
|
||||
./haskell-language-server-9.0.1~1.6.1.0
|
||||
./haskell-language-server-9.0.2
|
||||
./haskell-language-server-9.0.2~1.6.1.0
|
||||
./haskell-language-server-9.2.1
|
||||
./haskell-language-server-9.2.1~1.6.1.0
|
||||
./haskell-language-server-wrapper
|
||||
./haskell-language-server-wrapper-1.6.1.0
|
||||
./hp2ps
|
||||
./hp2ps-8.10.7
|
||||
./hpc
|
||||
./hpc-8.10.7
|
||||
./hsc2hs
|
||||
./hsc2hs-8.10.7
|
||||
./runghc
|
||||
./runghc-8.10.7
|
||||
./runhaskell
|
||||
./runhaskell-8.10.7
|
||||
./stack
|
||||
81
.gitlab/ghcup-run.files.windows
Normal file
@@ -0,0 +1,81 @@
|
||||
.
|
||||
./cabal.exe
|
||||
./cabal.shim
|
||||
./ghc-8.10.7.exe
|
||||
./ghc-8.10.7.shim
|
||||
./ghc-pkg-8.10.7.exe
|
||||
./ghc-pkg-8.10.7.shim
|
||||
./ghc-pkg.exe
|
||||
./ghc-pkg.shim
|
||||
./ghc.exe
|
||||
./ghc.shim
|
||||
./ghci-8.10.7.exe
|
||||
./ghci-8.10.7.shim
|
||||
./ghci.exe
|
||||
./ghci.shim
|
||||
./ghcii-8.10.7.sh-8.10.7.exe
|
||||
./ghcii-8.10.7.sh-8.10.7.shim
|
||||
./ghcii-8.10.7.sh.exe
|
||||
./ghcii-8.10.7.sh.shim
|
||||
./ghcii.sh-8.10.7.exe
|
||||
./ghcii.sh-8.10.7.shim
|
||||
./ghcii.sh.exe
|
||||
./ghcii.sh.shim
|
||||
./haddock-8.10.7.exe
|
||||
./haddock-8.10.7.shim
|
||||
./haddock.exe
|
||||
./haddock.shim
|
||||
./haskell-language-server-8.10.6.exe
|
||||
./haskell-language-server-8.10.6.shim
|
||||
./haskell-language-server-8.10.6~1.6.1.0.exe
|
||||
./haskell-language-server-8.10.6~1.6.1.0.shim
|
||||
./haskell-language-server-8.10.7.exe
|
||||
./haskell-language-server-8.10.7.shim
|
||||
./haskell-language-server-8.10.7~1.6.1.0.exe
|
||||
./haskell-language-server-8.10.7~1.6.1.0.shim
|
||||
./haskell-language-server-8.6.5.exe
|
||||
./haskell-language-server-8.6.5.shim
|
||||
./haskell-language-server-8.6.5~1.6.1.0.exe
|
||||
./haskell-language-server-8.6.5~1.6.1.0.shim
|
||||
./haskell-language-server-8.8.4.exe
|
||||
./haskell-language-server-8.8.4.shim
|
||||
./haskell-language-server-8.8.4~1.6.1.0.exe
|
||||
./haskell-language-server-8.8.4~1.6.1.0.shim
|
||||
./haskell-language-server-9.0.1.exe
|
||||
./haskell-language-server-9.0.1.shim
|
||||
./haskell-language-server-9.0.1~1.6.1.0.exe
|
||||
./haskell-language-server-9.0.1~1.6.1.0.shim
|
||||
./haskell-language-server-9.0.2.exe
|
||||
./haskell-language-server-9.0.2.shim
|
||||
./haskell-language-server-9.0.2~1.6.1.0.exe
|
||||
./haskell-language-server-9.0.2~1.6.1.0.shim
|
||||
./haskell-language-server-9.2.1.exe
|
||||
./haskell-language-server-9.2.1.shim
|
||||
./haskell-language-server-9.2.1~1.6.1.0.exe
|
||||
./haskell-language-server-9.2.1~1.6.1.0.shim
|
||||
./haskell-language-server-wrapper-1.6.1.0.exe
|
||||
./haskell-language-server-wrapper-1.6.1.0.shim
|
||||
./haskell-language-server-wrapper.exe
|
||||
./haskell-language-server-wrapper.shim
|
||||
./hp2ps-8.10.7.exe
|
||||
./hp2ps-8.10.7.shim
|
||||
./hp2ps.exe
|
||||
./hp2ps.shim
|
||||
./hpc-8.10.7.exe
|
||||
./hpc-8.10.7.shim
|
||||
./hpc.exe
|
||||
./hpc.shim
|
||||
./hsc2hs-8.10.7.exe
|
||||
./hsc2hs-8.10.7.shim
|
||||
./hsc2hs.exe
|
||||
./hsc2hs.shim
|
||||
./runghc-8.10.7.exe
|
||||
./runghc-8.10.7.shim
|
||||
./runghc.exe
|
||||
./runghc.shim
|
||||
./runhaskell-8.10.7.exe
|
||||
./runhaskell-8.10.7.shim
|
||||
./runhaskell.exe
|
||||
./runhaskell.shim
|
||||
./stack.exe
|
||||
./stack.shim
|
||||
23
.gitlab/ghcup_env
Normal file
@@ -0,0 +1,23 @@
|
||||
if [ "${OS}" = "WINDOWS" ] ; then
|
||||
export GHCUP_INSTALL_BASE_PREFIX="$CI_PROJECT_DIR"
|
||||
export GHCUP_BIN="$CI_PROJECT_DIR/ghcup/bin"
|
||||
export PATH="$GHCUP_BIN:$CI_PROJECT_DIR/.local/bin:$PATH"
|
||||
export TMPDIR="$CI_PROJECT_DIR/tmp"
|
||||
export CABAL_DIR="$CI_PROJECT_DIR/cabal"
|
||||
export CABAL_CACHE="$CI_PROJECT_DIR/cabal-cache"
|
||||
export STACK_ROOT="$CI_PROJECT_DIR/stack"
|
||||
export STACK_CACHE="$CI_PROJECT_DIR/stack-cache"
|
||||
export BREW_DIR="$CI_PROJECT_DIR/.brew_cache"
|
||||
export BREW_CACHE="$CI_PROJECT_DIR/brew-cache"
|
||||
else
|
||||
export GHCUP_INSTALL_BASE_PREFIX="$CI_PROJECT_DIR"
|
||||
export GHCUP_BIN="$CI_PROJECT_DIR/.ghcup/bin"
|
||||
export PATH="$GHCUP_BIN:$CI_PROJECT_DIR/.local/bin:$PATH"
|
||||
export TMPDIR="$CI_PROJECT_DIR/tmp"
|
||||
export CABAL_DIR="$CI_PROJECT_DIR/cabal"
|
||||
export CABAL_CACHE="$CI_PROJECT_DIR/cabal-cache"
|
||||
export STACK_ROOT="$CI_PROJECT_DIR/stack"
|
||||
export STACK_CACHE="$CI_PROJECT_DIR/stack-cache"
|
||||
export BREW_DIR="$CI_PROJECT_DIR/.brew_cache"
|
||||
export BREW_CACHE="$CI_PROJECT_DIR/brew-cache"
|
||||
fi
|
||||
19
.gitlab/script/brew.sh
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -Eeuxo pipefail
|
||||
|
||||
# Install brew locally in the project dir. Packages will also be installed here.
|
||||
[ -e "$CI_PROJECT_DIR/.brew" ] || git clone --depth=1 https://github.com/Homebrew/brew $CI_PROJECT_DIR/.brew
|
||||
export PATH="$CI_PROJECT_DIR/.brew/bin:$CI_PROJECT_DIR/.brew/sbin:$PATH"
|
||||
|
||||
# make sure to not pollute the machine with temp files etc
|
||||
mkdir -p $CI_PROJECT_DIR/.brew_cache
|
||||
export HOMEBREW_CACHE=$CI_PROJECT_DIR/.brew_cache
|
||||
mkdir -p $CI_PROJECT_DIR/.brew_logs
|
||||
export HOMEBREW_LOGS=$CI_PROJECT_DIR/.brew_logs
|
||||
mkdir -p /private/tmp/.brew_tmp
|
||||
export HOMEBREW_TEMP=/private/tmp/.brew_tmp
|
||||
|
||||
# update and install packages
|
||||
brew update
|
||||
brew install ${1+"$@"}
|
||||
70
.gitlab/script/ci.sh
Executable file
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -Eeuo pipefail
|
||||
|
||||
TOP="$( cd "$(dirname "$0")" ; pwd -P )"
|
||||
. "${TOP}/../ghcup_env"
|
||||
|
||||
function save_cabal_cache () {
|
||||
echo "Storing cabal cache from $CABAL_DIR to $CABAL_CACHE..."
|
||||
rm -Rf "$CABAL_CACHE"
|
||||
mkdir -p "$CABAL_CACHE"
|
||||
if [ -d "$CABAL_DIR" ]; then
|
||||
cp -Rf "$CABAL_DIR" "$CABAL_CACHE/"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function extract_cabal_cache () {
|
||||
if [ -d "$CABAL_CACHE" ]; then
|
||||
echo "Extracting cabal cache from $CABAL_CACHE to $CABAL_DIR..."
|
||||
mkdir -p "$CABAL_DIR"
|
||||
cp -Rf "$CABAL_CACHE"/* "$CABAL_DIR"
|
||||
fi
|
||||
}
|
||||
|
||||
function save_stack_cache () {
|
||||
echo "Storing stack cache from $STACK_ROOT to $STACK_CACHE..."
|
||||
rm -Rf "$STACK_CACHE"
|
||||
mkdir -p "$STACK_CACHE"
|
||||
if [ -d "$STACK_ROOT" ]; then
|
||||
cp -Rf "$STACK_DIR" "$STACK_CACHE"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function extract_stack_cache () {
|
||||
if [ -d "$STACK_CACHE" ]; then
|
||||
echo "Extracting stack cache from $STACK_CACHE to $STACK_ROOT..."
|
||||
mkdir -p "$STACK_ROOT"
|
||||
cp -Rf "$STACK_CACHE"/* "$STACK_ROOT"
|
||||
fi
|
||||
}
|
||||
|
||||
function save_brew_cache () {
|
||||
echo "Storing brew cache from $BREW_DIR to $BREW_CACHE..."
|
||||
rm -Rf "$BREW_CACHE"
|
||||
mkdir -p "$BREW_CACHE"
|
||||
if [ -d "$BREW_DIR" ]; then
|
||||
cp -Rf "$BREW_DIR" "$BREW_CACHE"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function extract_brew_cache () {
|
||||
if [ -d "$BREW_CACHE" ]; then
|
||||
echo "Extracting stack cache from $BREW_CACHE to $BREW_DIR..."
|
||||
mkdir -p "$BREW_DIR"
|
||||
cp -Rf "$BREW_CACHE"/* "$BREW_DIR"
|
||||
fi
|
||||
}
|
||||
|
||||
case $1 in
|
||||
extract_cabal_cache) extract_cabal_cache ;;
|
||||
save_cabal_cache) save_cabal_cache ;;
|
||||
extract_stack_cache) extract_stack_cache ;;
|
||||
save_stack_cache) save_stack_cache ;;
|
||||
extract_brew_cache) extract_brew_cache ;;
|
||||
save_brew_cache) save_brew_cache ;;
|
||||
*) echo "unknown mode $1" ; exit 11 ;;
|
||||
esac
|
||||
20
.gitlab/script/ghcup_bootstrap.sh
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
|
||||
|
||||
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
||||
|
||||
git describe --always
|
||||
|
||||
### build
|
||||
|
||||
export BOOTSTRAP_HASKELL_NONINTERACTIVE=yes
|
||||
export BOOTSTRAP_HASKELL_GHC_VERSION=$GHC_VERSION
|
||||
export BOOTSTRAP_HASKELL_CABAL_VERSION=$CABAL_VERSION
|
||||
|
||||
./scripts/bootstrap/bootstrap-haskell
|
||||
|
||||
[ "$(ghc --numeric-version)" = "${GHC_VERSION}" ]
|
||||
|
||||
52
.gitlab/script/ghcup_cross.sh
Executable file
@@ -0,0 +1,52 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
|
||||
|
||||
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
||||
|
||||
CI_PROJECT_DIR=$(pwd)
|
||||
|
||||
ecabal() {
|
||||
cabal "$@"
|
||||
}
|
||||
|
||||
eghcup() {
|
||||
ghcup -v -c -s file://$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml "$@"
|
||||
}
|
||||
|
||||
git describe --always
|
||||
|
||||
### build
|
||||
|
||||
ecabal update
|
||||
|
||||
ecabal build -w ghc-${GHC_VERSION}
|
||||
cp "$(ecabal new-exec -w ghc-${GHC_VERSION} --verbose=0 --offline sh -- -c 'command -v ghcup')" "$CI_PROJECT_DIR"/.local/bin/ghcup
|
||||
|
||||
### cleanup
|
||||
|
||||
rm -rf "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup
|
||||
|
||||
### manual cli based testing
|
||||
|
||||
eghcup --numeric-version
|
||||
|
||||
eghcup install ghc ${GHC_VERSION}
|
||||
eghcup set ghc ${GHC_VERSION}
|
||||
eghcup install cabal ${CABAL_VERSION}
|
||||
|
||||
cabal --version
|
||||
|
||||
eghcup debug-info
|
||||
|
||||
eghcup compile ghc -j $(nproc) -v ${GHC_TARGET_VERSION} -b ${GHC_VERSION} -x ${CROSS} -- --enable-unregisterised
|
||||
eghcup set ghc ${CROSS}-${GHC_TARGET_VERSION}
|
||||
|
||||
[ `$(eghcup whereis ghc ${CROSS}-${GHC_TARGET_VERSION}) --numeric-version` = "${GHC_TARGET_VERSION}" ]
|
||||
|
||||
# nuke
|
||||
eghcup nuke
|
||||
[ ! -e "${GHCUP_INSTALL_BASE_PREFIX}/.ghcup" ]
|
||||
|
||||
52
.gitlab/script/ghcup_git.sh
Executable file
@@ -0,0 +1,52 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
|
||||
|
||||
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
||||
|
||||
CI_PROJECT_DIR=$(pwd)
|
||||
|
||||
ecabal() {
|
||||
cabal "$@"
|
||||
}
|
||||
|
||||
eghcup() {
|
||||
ghcup -v -c -s file://$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml "$@"
|
||||
}
|
||||
|
||||
git describe --always
|
||||
|
||||
### build
|
||||
|
||||
ecabal update
|
||||
|
||||
ecabal build -w ghc-${GHC_VERSION}
|
||||
cp "$(ecabal new-exec -w ghc-${GHC_VERSION} --verbose=0 --offline sh -- -c 'command -v ghcup')" "$CI_PROJECT_DIR"/.local/bin/ghcup
|
||||
|
||||
### cleanup
|
||||
|
||||
rm -rf "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup
|
||||
|
||||
### manual cli based testing
|
||||
|
||||
eghcup --numeric-version
|
||||
|
||||
eghcup install ghc ${GHC_VERSION}
|
||||
eghcup set ghc ${GHC_VERSION}
|
||||
eghcup install cabal ${CABAL_VERSION}
|
||||
|
||||
cabal --version
|
||||
|
||||
eghcup debug-info
|
||||
|
||||
eghcup compile ghc -j $(nproc) -g ${GHC_GIT_TAG} -b ${GHC_VERSION} -- --enable-unregisterised
|
||||
eghcup set ghc ${GHC_GIT_VERSION}
|
||||
|
||||
[ `$(eghcup whereis ghc ${GHC_GIT_VERSION}) --numeric-version` = "${GHC_GIT_VERSION}" ]
|
||||
|
||||
# nuke
|
||||
eghcup nuke
|
||||
[ ! -e "${GHCUP_INSTALL_BASE_PREFIX}/.ghcup" ]
|
||||
|
||||
51
.gitlab/script/ghcup_hls.sh
Executable file
@@ -0,0 +1,51 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
|
||||
|
||||
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
||||
|
||||
CI_PROJECT_DIR=$(pwd)
|
||||
|
||||
ecabal() {
|
||||
cabal "$@"
|
||||
}
|
||||
|
||||
eghcup() {
|
||||
ghcup -v -c -s file://$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml "$@"
|
||||
}
|
||||
|
||||
git describe --always
|
||||
|
||||
### build
|
||||
|
||||
ecabal update
|
||||
|
||||
ecabal build -w ghc-${GHC_VERSION}
|
||||
cp "$(ecabal new-exec -w ghc-${GHC_VERSION} --verbose=0 --offline sh -- -c 'command -v ghcup')" "$CI_PROJECT_DIR"/.local/bin/ghcup
|
||||
|
||||
### cleanup
|
||||
|
||||
rm -rf "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup
|
||||
|
||||
### manual cli based testing
|
||||
|
||||
eghcup --numeric-version
|
||||
|
||||
eghcup install ghc ${GHC_VERSION}
|
||||
eghcup set ghc ${GHC_VERSION}
|
||||
eghcup install cabal ${CABAL_VERSION}
|
||||
|
||||
cabal --version
|
||||
|
||||
eghcup debug-info
|
||||
|
||||
eghcup compile hls -j $(nproc) -v ${HLS_TARGET_VERSION} --ghc ${GHC_VERSION}
|
||||
|
||||
[ `$(eghcup whereis hls ${HLS_TARGET_VERSION}) --numeric-version` = "${HLS_TARGET_VERSION}" ] || [ `$(eghcup whereis hls ${HLS_TARGET_VERSION}) --numeric-version | sed 's/.0$//'` = "${HLS_TARGET_VERSION}" ]
|
||||
|
||||
# nuke
|
||||
eghcup nuke
|
||||
[ ! -e "${GHCUP_INSTALL_BASE_PREFIX}/.ghcup" ]
|
||||
|
||||
44
.gitlab/script/ghcup_release.sh
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
|
||||
|
||||
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
||||
|
||||
ecabal() {
|
||||
cabal "$@"
|
||||
}
|
||||
|
||||
git describe
|
||||
|
||||
# build
|
||||
ecabal update
|
||||
|
||||
|
||||
if [ "${OS}" = "LINUX" ] ; then
|
||||
if [ "${ARCH}" = "32" ] ; then
|
||||
ecabal build -w ghc-${GHC_VERSION} --ghc-options='-split-sections -optl-static' -ftui
|
||||
elif [ "${ARCH}" = "64" ] ; then
|
||||
ecabal build -w ghc-${GHC_VERSION} --ghc-options='-split-sections -optl-static' -ftui
|
||||
else
|
||||
ecabal build -w ghc-${GHC_VERSION} -ftui
|
||||
fi
|
||||
elif [ "${OS}" = "FREEBSD" ] ; then
|
||||
ecabal build -w ghc-${GHC_VERSION} --ghc-options='-split-sections' --constraint="zlib +bundled-c-zlib" --constraint="zip +disable-zstd" -ftui
|
||||
elif [ "${OS}" = "WINDOWS" ] ; then
|
||||
ecabal build -w ghc-${GHC_VERSION} --constraint="zlib +bundled-c-zlib" --constraint="lzma +static"
|
||||
else
|
||||
ecabal build -w ghc-${GHC_VERSION} --constraint="zlib +bundled-c-zlib" --constraint="lzma +static" -ftui
|
||||
fi
|
||||
|
||||
mkdir out
|
||||
binary=$(ecabal new-exec -w ghc-${GHC_VERSION} --verbose=0 --offline sh -- -c 'command -v ghcup')
|
||||
ver=$("${binary}" --numeric-version)
|
||||
if [ "${OS}" = "DARWIN" ] ; then
|
||||
strip "${binary}"
|
||||
else
|
||||
strip -s "${binary}"
|
||||
fi
|
||||
cp "${binary}" out/${ARTIFACT}-${ver}
|
||||
|
||||
21
.gitlab/script/ghcup_stack.sh
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
|
||||
|
||||
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
||||
|
||||
git describe --always
|
||||
|
||||
### build
|
||||
|
||||
curl -L -O https://get.haskellstack.org/stable/linux-x86_64.tar.gz
|
||||
tar xf linux-x86_64.tar.gz
|
||||
cp stack-*-linux-*/stack "$CI_PROJECT_DIR"/.local/bin/stack
|
||||
chmod +x "$CI_PROJECT_DIR"/.local/bin/stack
|
||||
|
||||
mkdir -p "$CI_PROJECT_DIR"/.stack_root
|
||||
export TAR_OPTIONS=--no-same-owner
|
||||
stack --allow-different-user --stack-root "$CI_PROJECT_DIR"/.stack_root build
|
||||
stack --allow-different-user --stack-root "$CI_PROJECT_DIR"/.stack_root test
|
||||
314
.gitlab/script/ghcup_version.sh
Executable file
@@ -0,0 +1,314 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eux
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
|
||||
|
||||
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
||||
|
||||
CI_PROJECT_DIR=$(pwd)
|
||||
|
||||
|
||||
ecabal() {
|
||||
cabal "$@"
|
||||
}
|
||||
|
||||
raw_eghcup() {
|
||||
ghcup -v -c "$@"
|
||||
}
|
||||
|
||||
eghcup() {
|
||||
if [ "${OS}" = "WINDOWS" ] ; then
|
||||
ghcup -v -c -s file:/$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml "$@"
|
||||
else
|
||||
ghcup -v -c -s file://$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "${OS}" = "WINDOWS" ] ; then
|
||||
GHCUP_DIR="${GHCUP_INSTALL_BASE_PREFIX}"/ghcup
|
||||
else
|
||||
GHCUP_DIR="${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup
|
||||
fi
|
||||
|
||||
git describe --always
|
||||
|
||||
### build
|
||||
|
||||
rm -rf "${GHCUP_DIR}"/share
|
||||
|
||||
ecabal update
|
||||
|
||||
if [ "${OS}" = "DARWIN" ] ; then
|
||||
ecabal build -w ghc-${GHC_VERSION} -ftui
|
||||
ecabal test -w ghc-${GHC_VERSION} -ftui ghcup-test
|
||||
ecabal haddock -w ghc-${GHC_VERSION} -ftui
|
||||
elif [ "${OS}" = "LINUX" ] ; then
|
||||
if [ "${ARCH}" = "32" ] ; then
|
||||
ecabal build -w ghc-${GHC_VERSION} -finternal-downloader -ftui
|
||||
ecabal test -w ghc-${GHC_VERSION} -finternal-downloader -ftui ghcup-test
|
||||
ecabal haddock -w ghc-${GHC_VERSION} -finternal-downloader -ftui
|
||||
else
|
||||
ecabal build -w ghc-${GHC_VERSION} -finternal-downloader -ftui
|
||||
ecabal test -w ghc-${GHC_VERSION} -finternal-downloader -ftui ghcup-test
|
||||
ecabal haddock -w ghc-${GHC_VERSION} -finternal-downloader -ftui
|
||||
|
||||
if [ "${ARCH}" = "64" ] ; then
|
||||
# doctest
|
||||
curl -sL https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal-docspec/cabal-docspec-0.0.0.20210228_p1.tar.bz2 > cabal-docspec.tar.bz2
|
||||
echo '3a10f6fec16dbd18efdd331b1cef5d2d342082da42f5b520726d1fa6a3990d12 cabal-docspec.tar.bz2' | sha256sum -c -
|
||||
tar -xjf cabal-docspec.tar.bz2 cabal-docspec
|
||||
mv cabal-docspec "$CI_PROJECT_DIR"/.local/bin/cabal-docspec
|
||||
rm -f cabal-docspec.tar.bz2
|
||||
chmod a+x "$CI_PROJECT_DIR"/.local/bin/cabal-docspec
|
||||
|
||||
cabal-docspec -XCPP -XTypeSynonymInstances -XOverloadedStrings -XPackageImports --check-properties
|
||||
fi
|
||||
fi
|
||||
elif [ "${OS}" = "FREEBSD" ] ; then
|
||||
ecabal build -w ghc-${GHC_VERSION} -finternal-downloader -ftui --constraint="zip +disable-zstd"
|
||||
ecabal test -w ghc-${GHC_VERSION} -finternal-downloader -ftui --constraint="zip +disable-zstd" ghcup-test
|
||||
ecabal haddock -w ghc-${GHC_VERSION} -finternal-downloader -ftui --constraint="zip +disable-zstd"
|
||||
elif [ "${OS}" = "WINDOWS" ] ; then
|
||||
ecabal build -w ghc-${GHC_VERSION}
|
||||
ecabal test -w ghc-${GHC_VERSION} ghcup-test
|
||||
ecabal haddock -w ghc-${GHC_VERSION}
|
||||
else
|
||||
ecabal build -w ghc-${GHC_VERSION} -finternal-downloader -ftui
|
||||
ecabal test -w ghc-${GHC_VERSION} -finternal-downloader -ftui ghcup-test
|
||||
ecabal haddock -w ghc-${GHC_VERSION} -finternal-downloader -ftui
|
||||
fi
|
||||
|
||||
|
||||
if [ "${OS}" = "WINDOWS" ] ; then
|
||||
ext=".exe"
|
||||
else
|
||||
ext=''
|
||||
fi
|
||||
cp "$(ecabal new-exec -w ghc-${GHC_VERSION} --verbose=0 --offline sh -- -c 'command -v ghcup')" "$CI_PROJECT_DIR"/.local/bin/ghcup${ext}
|
||||
|
||||
### cleanup
|
||||
|
||||
rm -rf "${GHCUP_DIR}"
|
||||
|
||||
### manual cli based testing
|
||||
|
||||
|
||||
eghcup --numeric-version
|
||||
|
||||
eghcup install ghc ${GHC_VERSION}
|
||||
eghcup unset ghc ${GHC_VERSION}
|
||||
ls -lah "$(eghcup whereis -d ghc ${GHC_VERSION})"
|
||||
[ "`$(eghcup whereis ghc ${GHC_VERSION}) --numeric-version`" = "${GHC_VERSION}" ]
|
||||
[ "`eghcup run --ghc ${GHC_VERSION} -- ghc --numeric-version`" = "${GHC_VERSION}" ]
|
||||
[ "`ghcup run --ghc ${GHC_VERSION} -- ghc -e 'Control.Monad.join (Control.Monad.fmap System.IO.putStr System.Environment.getExecutablePath)'`" = "`$(ghcup whereis ghc ${GHC_VERSION}) -e 'Control.Monad.join (Control.Monad.fmap System.IO.putStr System.Environment.getExecutablePath)'`" ]
|
||||
eghcup set ghc ${GHC_VERSION}
|
||||
eghcup install cabal ${CABAL_VERSION}
|
||||
[ "`$(eghcup whereis cabal ${CABAL_VERSION}) --numeric-version`" = "${CABAL_VERSION}" ]
|
||||
eghcup unset cabal
|
||||
"$GHCUP_BIN"/cabal --version && exit 1 || echo yes
|
||||
|
||||
# make sure no cabal is set when running 'ghcup run' to check that PATH propagages properly
|
||||
# https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/375
|
||||
[ "`eghcup run --cabal ${CABAL_VERSION} -- cabal --numeric-version`" = "${CABAL_VERSION}" ]
|
||||
eghcup set cabal ${CABAL_VERSION}
|
||||
|
||||
[ "`$(eghcup whereis cabal ${CABAL_VERSION}) --numeric-version`" = "${CABAL_VERSION}" ]
|
||||
|
||||
if [ "${OS}" != "FREEBSD" ] ; then
|
||||
if [ "${ARCH}" = "64" ] ; then
|
||||
eghcup run --ghc 8.10.7 --cabal 3.4.1.0 --hls 1.6.1.0 --stack 2.7.3 --install --bindir "$(pwd)/.bin"
|
||||
if [ "${OS}" == "WINDOWS" ] ; then
|
||||
expected=$(cat "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup-run.files.windows" | sort)
|
||||
else
|
||||
expected=$(cat "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup-run.files" | sort)
|
||||
fi
|
||||
actual=$(cd ".bin" && find . | sort)
|
||||
[ "${actual}" = "${expected}" ]
|
||||
unset actual expected
|
||||
rm -rf .bin
|
||||
fi
|
||||
fi
|
||||
|
||||
cabal --version
|
||||
|
||||
eghcup debug-info
|
||||
|
||||
# also test etags
|
||||
eghcup list
|
||||
eghcup list -t ghc
|
||||
eghcup list -t cabal
|
||||
|
||||
ghc_ver=$(ghc --numeric-version)
|
||||
ghc --version
|
||||
ghc-${ghc_ver} --version
|
||||
if [ "${OS}" != "WINDOWS" ] ; then
|
||||
ghci --version
|
||||
ghci-${ghc_ver} --version
|
||||
fi
|
||||
|
||||
|
||||
if [ "${OS}" = "DARWIN" ] && [ "${ARCH}" = "ARM64" ] ; then
|
||||
echo
|
||||
else
|
||||
# test installing new ghc doesn't mess with currently set GHC
|
||||
# https://gitlab.haskell.org/haskell/ghcup-hs/issues/7
|
||||
if [ "${OS}" = "LINUX" ] ; then
|
||||
eghcup --downloader=wget prefetch ghc 8.10.3
|
||||
eghcup --offline install ghc 8.10.3
|
||||
if [ "${ARCH}" = "64" ] ; then
|
||||
expected=$(cat "$( cd "$(dirname "$0")" ; pwd -P )/../ghc-8.10.3-linux.files" | sort)
|
||||
actual=$(cd "${GHCUP_DIR}/ghc/8.10.3/" && find . | sort)
|
||||
[ "${actual}" = "${expected}" ]
|
||||
unset actual expected
|
||||
fi
|
||||
elif [ "${OS}" = "WINDOWS" ] ; then
|
||||
eghcup prefetch ghc 8.10.3
|
||||
eghcup --offline install ghc 8.10.3
|
||||
expected=$(cat "$( cd "$(dirname "$0")" ; pwd -P )/../ghc-8.10.3-windows.files" | sort)
|
||||
actual=$(cd "${GHCUP_DIR}/ghc/8.10.3/" && find . | sort)
|
||||
[ "${actual}" = "${expected}" ]
|
||||
unset actual expected
|
||||
else
|
||||
eghcup prefetch ghc 8.10.3
|
||||
eghcup --offline install ghc 8.10.3
|
||||
fi
|
||||
[ "$(ghc --numeric-version)" = "${ghc_ver}" ]
|
||||
eghcup --offline set 8.10.3
|
||||
eghcup set 8.10.3
|
||||
[ "$(ghc --numeric-version)" = "8.10.3" ]
|
||||
eghcup set ${GHC_VERSION}
|
||||
[ "$(ghc --numeric-version)" = "${ghc_ver}" ]
|
||||
eghcup unset ghc
|
||||
"$GHCUP_BIN"/ghc --numeric-version && exit 1 || echo yes
|
||||
eghcup set ${GHC_VERSION}
|
||||
eghcup --offline rm 8.10.3
|
||||
[ "$(ghc --numeric-version)" = "${ghc_ver}" ]
|
||||
|
||||
|
||||
ls -lah "$GHCUP_BIN"
|
||||
|
||||
if [ "${OS}" = "DARWIN" ] ; then
|
||||
eghcup install hls
|
||||
$(eghcup whereis hls) --version
|
||||
|
||||
eghcup install stack
|
||||
$(eghcup whereis stack) --version
|
||||
elif [ "${OS}" = "LINUX" ] ; then
|
||||
if [ "${ARCH}" = "64" ] ; then
|
||||
eghcup install hls
|
||||
haskell-language-server-wrapper --version
|
||||
eghcup unset hls
|
||||
"$GHCUP_BIN"/haskell-language-server-wrapper --version && exit 1 || echo yes
|
||||
|
||||
eghcup install stack
|
||||
stack --version
|
||||
eghcup unset stack
|
||||
"$GHCUP_BIN"/stack --version && exit 1 || echo yes
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# check that lazy loading works for 'whereis'
|
||||
cp "$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml" "$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml.bak"
|
||||
echo '**' > "$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml"
|
||||
eghcup whereis ghc $(ghc --numeric-version)
|
||||
mv -f "$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml.bak" "$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml"
|
||||
|
||||
eghcup rm $(ghc --numeric-version)
|
||||
|
||||
# https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/116
|
||||
if [ "${OS}" = "LINUX" ] ; then
|
||||
if [ "${ARCH}" = "64" ] ; then
|
||||
eghcup install cabal -u https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/3.7.0.0-pre20220407/cabal-install-3.7-x86_64-linux-alpine.tar.xz 3.4.0.0-rc4
|
||||
eghcup rm cabal 3.4.0.0-rc4
|
||||
fi
|
||||
fi
|
||||
|
||||
eghcup gc -c
|
||||
|
||||
sha_sum() {
|
||||
if [ "${OS}" = "FREEBSD" ] ; then
|
||||
sha256 "$@"
|
||||
else
|
||||
sha256sum "$@"
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
# test etags
|
||||
rm -f "${GHCUP_DIR}/cache/ghcup-${JSON_VERSION}.yaml"
|
||||
raw_eghcup -s https://www.haskell.org/ghcup/data/ghcup-${JSON_VERSION}.yaml list
|
||||
# snapshot yaml and etags file
|
||||
etag=$(cat "${GHCUP_DIR}/cache/ghcup-${JSON_VERSION}.yaml.etags")
|
||||
sha=$(sha_sum "${GHCUP_DIR}/cache/ghcup-${JSON_VERSION}.yaml")
|
||||
# invalidate access time timer, which is 5minutes, so we re-download
|
||||
touch -a -m -t '199901010101' "${GHCUP_DIR}/cache/ghcup-${JSON_VERSION}.yaml"
|
||||
# redownload same file with some newlines added
|
||||
raw_eghcup -s https://www.haskell.org/ghcup/exp/ghcup-${JSON_VERSION}.yaml list
|
||||
# snapshot new yaml and etags file
|
||||
etag2=$(cat "${GHCUP_DIR}/cache/ghcup-${JSON_VERSION}.yaml.etags")
|
||||
sha2=$(sha_sum "${GHCUP_DIR}/cache/ghcup-${JSON_VERSION}.yaml")
|
||||
# compare
|
||||
[ "${etag}" != "${etag2}" ]
|
||||
[ "${sha}" != "${sha2}" ]
|
||||
# invalidate access time timer, which is 5minutes, but don't expect a re-download
|
||||
touch -a -m -t '199901010101' "${GHCUP_DIR}/cache/ghcup-${JSON_VERSION}.yaml"
|
||||
# this time, we expect the same hash and etag
|
||||
raw_eghcup -s https://www.haskell.org/ghcup/exp/ghcup-${JSON_VERSION}.yaml list
|
||||
etag3=$(cat "${GHCUP_DIR}/cache/ghcup-${JSON_VERSION}.yaml.etags")
|
||||
sha3=$(sha_sum "${GHCUP_DIR}/cache/ghcup-${JSON_VERSION}.yaml")
|
||||
[ "${etag2}" = "${etag3}" ]
|
||||
[ "${sha2}" = "${sha3}" ]
|
||||
|
||||
# test isolated installs
|
||||
eghcup install ghc -i "$(pwd)/isolated" 8.10.5
|
||||
[ "$(isolated/bin/ghc --numeric-version)" = "8.10.5" ]
|
||||
! eghcup install ghc -i "$(pwd)/isolated" 8.10.5
|
||||
if [ "${ARCH}" = "64" ] ; then
|
||||
if [ "${OS}" = "LINUX" ] || [ "${OS}" = "WINDOWS" ] ; then
|
||||
eghcup install cabal -i "$(pwd)/isolated" 3.4.0.0
|
||||
[ "$(isolated/cabal --numeric-version)" = "3.4.0.0" ]
|
||||
eghcup install stack -i "$(pwd)/isolated" 2.7.3
|
||||
[ "$(isolated/stack --numeric-version)" = "2.7.3" ]
|
||||
eghcup install hls -i "$(pwd)/isolated" 1.3.0
|
||||
[ "$(isolated/haskell-language-server-wrapper --numeric-version)" = "1.3.0" ] ||
|
||||
[ "$(isolated/haskell-language-server-wrapper --numeric-version)" = "1.3.0.0" ]
|
||||
|
||||
# test that isolated installs don't clean up target directory
|
||||
cat <<EOF > "${GHCUP_BIN}/gmake"
|
||||
#!/bin/bash
|
||||
exit 1
|
||||
EOF
|
||||
chmod +x "${GHCUP_BIN}/gmake"
|
||||
mkdir isolated_tainted/
|
||||
touch isolated_tainted/lol
|
||||
|
||||
! eghcup install ghc -i "$(pwd)/isolated_tainted" 8.10.5 --force
|
||||
[ -e "$(pwd)/isolated_tainted/lol" ]
|
||||
rm "${GHCUP_BIN}/gmake"
|
||||
fi
|
||||
fi
|
||||
|
||||
eghcup upgrade
|
||||
eghcup upgrade -f
|
||||
|
||||
# test that doing fishy symlinks into GHCup dir doesn't cause weird stuff on 'ghcup nuke'
|
||||
mkdir no_nuke/
|
||||
mkdir no_nuke/bar
|
||||
echo 'foo' > no_nuke/file
|
||||
echo 'bar' > no_nuke/bar/file
|
||||
ln -s "$CI_PROJECT_DIR"/no_nuke/ "${GHCUP_DIR}"/cache/no_nuke
|
||||
ln -s "$CI_PROJECT_DIR"/no_nuke/ "${GHCUP_DIR}"/logs/no_nuke
|
||||
|
||||
# nuke
|
||||
eghcup nuke
|
||||
[ ! -e "${GHCUP_DIR}" ]
|
||||
|
||||
# make sure nuke doesn't resolve symlinks
|
||||
[ -e "$CI_PROJECT_DIR"/no_nuke/file ]
|
||||
[ -e "$CI_PROJECT_DIR"/no_nuke/bar/file ]
|
||||
|
||||
|
||||
19
.gitlab/script/hlint.sh
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
|
||||
|
||||
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
||||
|
||||
ecabal() {
|
||||
cabal --store-dir="$(pwd)"/.store "$@"
|
||||
}
|
||||
|
||||
git describe
|
||||
|
||||
ecabal update
|
||||
ecabal install -w ghc-${GHC_VERSION} --installdir="$CI_PROJECT_DIR"/.local/bin hlint
|
||||
|
||||
hlint -r app/ lib/ test/
|
||||
|
||||
4
.gitmodules
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
[submodule "data/metadata"]
|
||||
path = data/metadata
|
||||
url = https://github.com/haskell/ghcup-metadata.git
|
||||
branch = master
|
||||
84
.hlint.yaml
Normal file
@@ -0,0 +1,84 @@
|
||||
# HLint configuration file
|
||||
# https://github.com/ndmitchell/hlint
|
||||
##########################
|
||||
|
||||
# This file contains a template configuration file, which is typically
|
||||
# placed as .hlint.yaml in the root of your project
|
||||
|
||||
|
||||
# Warnings currently triggered by your code
|
||||
- ignore: {name: "Redundant bang pattern"}
|
||||
- ignore: {name: "Use camelCase"}
|
||||
- ignore: {name: "Use if"}
|
||||
- ignore: {name: "Use newtype instead of data"}
|
||||
- ignore: {name: "Use <$>"}
|
||||
- ignore: {name: "Use mapMaybe"}
|
||||
- ignore: {name: "Use const"}
|
||||
- ignore: {name: "Use list comprehension"}
|
||||
- ignore: {name: "Redundant multi-way if"}
|
||||
- ignore: {name: "Redundant lambda"}
|
||||
- ignore: {name: "Avoid lambda"}
|
||||
- ignore: {name: "Use uncurry"}
|
||||
- ignore: {name: "Use replicateM"}
|
||||
- ignore: {name: "Use unless"}
|
||||
- ignore: {name: "Redundant irrefutable pattern"}
|
||||
|
||||
|
||||
# Specify additional command line arguments
|
||||
#
|
||||
# - arguments: [--color, --cpp-simple, -XQuasiQuotes]
|
||||
|
||||
|
||||
# Control which extensions/flags/modules/functions can be used
|
||||
#
|
||||
# - extensions:
|
||||
# - default: false # all extension are banned by default
|
||||
# - name: [PatternGuards, ViewPatterns] # only these listed extensions can be used
|
||||
# - {name: CPP, within: CrossPlatform} # CPP can only be used in a given module
|
||||
#
|
||||
# - flags:
|
||||
# - {name: -w, within: []} # -w is allowed nowhere
|
||||
#
|
||||
# - modules:
|
||||
# - {name: [Data.Set, Data.HashSet], as: Set} # if you import Data.Set qualified, it must be as 'Set'
|
||||
# - {name: Control.Arrow, within: []} # Certain modules are banned entirely
|
||||
#
|
||||
# - functions:
|
||||
# - {name: unsafePerformIO, within: []} # unsafePerformIO can only appear in no modules
|
||||
|
||||
|
||||
# Add custom hints for this project
|
||||
#
|
||||
# Will suggest replacing "wibbleMany [myvar]" with "wibbleOne myvar"
|
||||
# - error: {lhs: "wibbleMany [x]", rhs: wibbleOne x}
|
||||
|
||||
# The hints are named by the string they display in warning messages.
|
||||
# For example, if you see a warning starting like
|
||||
#
|
||||
# Main.hs:116:51: Warning: Redundant ==
|
||||
#
|
||||
# You can refer to that hint with `{name: Redundant ==}` (see below).
|
||||
|
||||
# Turn on hints that are off by default
|
||||
#
|
||||
# Ban "module X(module X) where", to require a real export list
|
||||
# - warn: {name: Use explicit module export list}
|
||||
#
|
||||
# Replace a $ b $ c with a . b $ c
|
||||
# - group: {name: dollar, enabled: true}
|
||||
#
|
||||
# Generalise map to fmap, ++ to <>
|
||||
# - group: {name: generalise, enabled: true}
|
||||
|
||||
|
||||
# Ignore some builtin hints
|
||||
# - ignore: {name: Use let}
|
||||
# - ignore: {name: Use const, within: SpecialModule} # Only within certain modules
|
||||
|
||||
|
||||
# Define some custom infix operators
|
||||
# - fixity: infixr 3 ~^#^~
|
||||
|
||||
|
||||
# To generate a suitable file for HLint do:
|
||||
# $ hlint --default > .hlint.yaml
|
||||
@@ -10,12 +10,13 @@ jobs:
|
||||
language: generic
|
||||
env: ARTIFACT=x86_64-apple-darwin-10.14-ghcup
|
||||
|
||||
|
||||
script: ".travis/build.sh"
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: GEQR+HIwMUql+tFU0LoKCCzG+IG1s5XVA4yp8xMFk0IPsNjHEMh6djYgNqsS6MnujzRulinZe69RyJMZHW3UbtVKWd1D5nsCKmAVfnU8VRbubaL55Bz7C2WI9UCYtKY0isVIQu3KkY+0a6LhdjSkbatO2hl9v0nFmN28q/RpEzsJTI4kyVhmCBflH4fL/QvXzfLuyOae7qsiZBVQXEhmySYktKifNMANSI1aU+kyZ3JgykqZogMK+g/fmcxxTe9MPYMsRQxae/xqdf87IQpmK8v9BRShvF0wq1gO8NY+/fEemAVIHi5CYhPgiLntUD/HFr6AT04LcHnaGryDn/PhkvHuDuZ4INYgBrdNMeGVTjT93N7OtXyh7c+AP3/51E8nM0SkSWCeP4P2fMMksdeOnKtPbhzlqgEM9tbRMILOj1LcjcqurU5ku+WEwZ7d1osTyNug7FVCO5Vb0q3NYnDF4UPXc/d5/2SB+SjJSMxRc52+BiKskHmOa96TXirL3eo6KVNaokQRKvbLw1fEjZvqYJuhPWBRDMalyYjc77poj4kzfVL9CYjtP7h6N5wFR7AtPsMz2n2fQf7J3N4+oqHK+83fOPGyy4FYPZojKNw+L2X/XYrfVscsY/1KbBjULgGIrdr4euYz+rRrTHixUYIvGclKOx+g3SHAOXFWhXlldvI=
|
||||
secure: "hT2od8Iy04tdFVuonPSWv0NX5hZDmv4al8Q0GbIWmviUetROuM7c6/MCHUcgyiw6H2L3pmH4F24GBYWpKBT3ZMbxrKXhZOZ3KPLXzlnuRlm1qymKqqwsJs3466bMftaiBr16rx1VpAuditN4A32oSmTFcQAJc84Bxn2WZ4t8hk9muS8YPyLhqg3/NxT6ob8dzNp9eS2cA0WODMb/fMzaMruRtepSK8JvuXb/SnTvaDcl9plmPzEa+eW54jwVsDps8ZpQMQlTtGIjYHIwTQ36/iLH4LoAvD7OEnB7qf753LOzmI/bvlB75xYGsLxe1qgpzPMjuG3AK0jb2KGSZCzyAyrbBFSQMIyC1gNKMtab3CohnA9WdQqAT1xrzPzA9zNw516G5Fn/z+t9Ek1f6L2OYO2hJfweNhWh+ChAIsOags2QBpqc0qjkwUS4wqxCWBdyVfgPTUoGelvjCfjQgypgIyLEHFvXt9rlj+kd97FY7nG3vxZrsvWTKKKT551OqUYX5zWTyvGR71jKyNst/p93Pg3DkRy31gHrGnG9zfNgN5tWxJqDd/suR/BAFTp0VtkFb8fR3ct7WMVeJXtE2+bKqxO5Fnocs1VjEm8pKPk7glnp0muu08kaO0h54wiSOCbk1RvO1KZtHue4wKWrHcI18dwW2WtzoBQ4P1lOSkS81UY="
|
||||
file: $ARTIFACT
|
||||
on:
|
||||
repo: hasufell/ghcup-hs
|
||||
|
||||
@@ -1,22 +1,28 @@
|
||||
#/bin/sh
|
||||
#!/bin/sh
|
||||
|
||||
set -ex
|
||||
|
||||
## install ghc via old ghcup
|
||||
|
||||
mkdir -p ~/.ghcup/bin
|
||||
curl https://gitlab.haskell.org/haskell/ghcup/raw/master/ghcup > ~/.ghcup/bin/ghcup
|
||||
curl -sSfL https://downloads.haskell.org/~ghcup/x86_64-apple-darwin-ghcup > ~/.ghcup/bin/ghcup
|
||||
chmod +x ~/.ghcup/bin/ghcup
|
||||
|
||||
export PATH="$HOME/.ghcup/bin:$PATH"
|
||||
|
||||
ghcup install 8.8.3
|
||||
ghcup install-cabal 3.2.0.0
|
||||
ghcup set 8.8.3
|
||||
ghcup install 8.10.4
|
||||
ghcup install-cabal 3.4.0.0
|
||||
ghcup set 8.10.4
|
||||
|
||||
|
||||
## install ghcup
|
||||
|
||||
cabal update
|
||||
cabal build -fcurl
|
||||
cp "$(cabal new-exec --verbose=0 --offline sh -- -c 'command -v ghcup')" "./${ARTIFACT}"
|
||||
|
||||
(
|
||||
cd /tmp
|
||||
cabal install --installdir="$HOME"/.ghcup/bin hspec-discover
|
||||
)
|
||||
|
||||
cabal build --constraint="zlib +static" --constraint="lzma +static" -ftui
|
||||
cp "$(cabal new-exec --verbose=0 --offline sh -- -c 'command -v ghcup')" .
|
||||
strip ./ghcup
|
||||
cp ghcup "./${ARTIFACT}"
|
||||
|
||||
263
CHANGELOG.md
@@ -1,5 +1,268 @@
|
||||
# Revision history for ghcup
|
||||
|
||||
## 0.1.17.10 -- 2022-05-12
|
||||
|
||||
* windows hotfix (hackage-only release)
|
||||
|
||||
## 0.1.17.9 -- 2022-05-12
|
||||
|
||||
* broken sdist (hackage-only release)
|
||||
|
||||
## 0.1.17.8 -- 2022-05-11
|
||||
|
||||
* Fix a serious (but hard to trigger) bug when combining `--isolate <DIR>` with `--force`, please make sure to upgrade or avoid `--force`
|
||||
* Fix HLS build not cleaning up properly on failed installations, fixes [#361](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/361)
|
||||
* Fix parsing of symlinks with multiple slashes, wrt [#353](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/353)
|
||||
* Re-enable upgrade functionality for all configurations wrt [MR #250](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/250) and [VSCode haskell issue #601](https://github.com/haskell/vscode-haskell/issues/601)
|
||||
* Fix `ghcup run --ghc 8.10` (for short versions) wrt [#360](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/360)
|
||||
- this also introduces a `--quick` switch for `ghcup run`
|
||||
|
||||
## 0.1.17.7 -- 2022-04-21
|
||||
|
||||
* Fix `ghcup run` on windows wrt [#345](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/345)
|
||||
|
||||
## 0.1.17.6 -- 2022-03-18
|
||||
|
||||
* Vastly improve shell completions wrt [#242](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/242)
|
||||
* Fix 'ghcup install cabal/hls/stack --set' wrt [#324](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/324)
|
||||
* Fix bad error message wrt [#323](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/323)
|
||||
* Use predictable /tmp names for `ghcup run`, fixes [#329](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/329)
|
||||
* Fix bug with isolated installation of not previously installed versions
|
||||
* Add `--no-set` to install commands, fixes [#330](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/330)
|
||||
* Fix serious bug in `ghcup list --raw-format -t <tool> -c installed`
|
||||
* Overhaul metadata merging and add `ghcup config add-release-channel URI` wrt [#328](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/328)
|
||||
* Fix max path issues on windows with `ghcup run`
|
||||
|
||||
## 0.1.17.5 -- 2022-02-26
|
||||
|
||||
* Implement `ghcup run` subcommand wrt [#137](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/137)
|
||||
* Support installation of dynamic HLS bindists wrt [HLS #2675](https://github.com/haskell/haskell-language-server/pull/2675) and [#237](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/237)
|
||||
* Fix XDG support when `~/.local/bin` is a symlink wrt [#311](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/311)
|
||||
* Add support for quilt-style patches wrt [#230](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/230), by James Hobson
|
||||
* Fix redundant upgrade warnings in `ghcup upgrade`
|
||||
* Fix `ghcup whereis ghc` for non-standard versions wrt [#289](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/289)
|
||||
* Don't print logs to stdout, but stderr
|
||||
* Allow unpacking legacy lzma archives wrt [#307](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/307)
|
||||
* Allow to disable self-upgrade functionality wrt [#305](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/305)
|
||||
* Fix `ghcup install ghc --set` when ghc is already installed wrt [#291](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/291)
|
||||
|
||||
## 0.1.17.4 -- 2021-11-13
|
||||
|
||||
* add `--metadata-caching` option, allowing to also disable yaml metadata caching wrt [#278](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/278)
|
||||
* make upgrading ghcup in TUI more pleasant wrt [#276](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/276)
|
||||
* fix parsing of atypical GHC versions (e.g. `8.10.5-patch1`)
|
||||
* fix compiling HLS dynamically linked, also see [#245](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/245)
|
||||
* redo (and break) some of the `ghcup compile <tool>` interface, improving patch options and setting custom cabal.project files
|
||||
* avoid redundant update warnings wrt [#283](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/283)
|
||||
|
||||
## 0.1.17.3 -- 2021-10-27
|
||||
|
||||
* clean up during unpack failures as well
|
||||
* migrate te aeson-2.0.1.0
|
||||
* switch to yaml-streamly to fix performance regression wrt [#270](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/270)
|
||||
* use [github.com/haskell/ghcup-metadata](https://github.com/haskell/ghcup-metadata) for metadata file download (better caching)
|
||||
|
||||
## 0.1.17.2 -- 2021-09-30
|
||||
|
||||
* Honour GHC bootstrap compiler during git clone stages wrt [#250](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/250)
|
||||
* Speed up `unset` command
|
||||
* Fix `--overwrite-version` for `ghcup compile ghc` wrt [#253](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/253)
|
||||
* Apply patches before bootstrap
|
||||
|
||||
## 0.1.17.1 -- 2021-09-26
|
||||
|
||||
* Fix `NO_COLOR`
|
||||
* Fix `ghcup list -t` for hls/stack, wrt [#244](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/244)
|
||||
* Get rid of concurrent-output
|
||||
* Improve cli interface with partial versions (e.g. `ghcup install ghc 8`)
|
||||
* Fix HLS compilation builds
|
||||
* Implement `ghcup gc` (garbage collection) command
|
||||
|
||||
## 0.1.17 -- 2021-09-20
|
||||
|
||||
* Add `--force` option to install/compile wrt [#210](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/210) by Arjun Kathuria
|
||||
* Implement compiling HLS from source wrt [#201](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/201)
|
||||
* Implement experimental GPG verification of the metadata file (see README) wrt [#263](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/236)
|
||||
* Add `ghcup unset` command wrt [#145](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/145)
|
||||
* Add `ghcup whereis bindir` etc wrt [#221](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/221)
|
||||
* Greatly reduce dependency footprint wrt [#212](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/212)
|
||||
* Add `ghcup --plan-json`
|
||||
* Improve `--patchdir` option for GHC compilation wrt [#226](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/226)
|
||||
* Try to improve logging and failure modes, especially during downloads
|
||||
* Add descriptive warnings when HLS and GHC versions are incompatible
|
||||
* Improve curl header parsing wrt [#213](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/213)
|
||||
|
||||
## 0.1.16.2 -- 2021-08-12
|
||||
|
||||
* Add isolated installations wrt [#141](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/141) by Arjun Kathuria
|
||||
* Implement config cli MVP wrt [#134](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/134) by Oleksii Dorozhkin
|
||||
* Fix `ghcup compile ghc --flavor`
|
||||
* Fix minor installation bug causing increased disk space wrt [#139](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/139)
|
||||
* Improved error handling wrt [#136](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/136)
|
||||
* Various improvements to metadata download when using `file://` and `--offline` wrt [#137](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/137)
|
||||
|
||||
## 0.1.16.1 -- 2021-07-29
|
||||
|
||||
* Add 'nuke' subcommand wrt [#135](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/135), implemented by Arjun Kathuria
|
||||
* Add uninstallation powershell script on windows wrt [#150](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/150)
|
||||
* Improve logging
|
||||
* Fix building GHC cross compiler wrt [#180](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/180)
|
||||
* Allow to use hadrian as build system (for git based versions only) wrt [#35](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/35)
|
||||
* Allow passing `--flavor` to `ghcup compile ghc`
|
||||
* Support new GHC `bin/` directory format wrt [ghc/ghc#20074](https://gitlab.haskell.org/ghc/ghc/-/issues/20074#note_363720)
|
||||
* Implement `whereis` subcommand wrt [#173](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/173)
|
||||
* Add `--offline` switch and `prefetch` subcommand wrt [#186](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/186)
|
||||
* Implement ETAGs hashing for metadata downloads to speed up `ghcup list` wrt [#193](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/193)
|
||||
* Avoid unnecessary fetching of ghcup metadata in some commands
|
||||
* Avoid unnecessary update checks for some commands
|
||||
* Preserve mtimes on unpacked GHC tarballs on windows wrt [#187](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/187), fixing issues with `ghc-pkg`
|
||||
* Fix lesser bug in `ghcup list` for stray stack versions wrt [#183](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/183)
|
||||
* Major redo on how file removal on windows works, avoiding partial removals etc, wrt [#165](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/165)
|
||||
* Improve ghcup tui for screen readers wrt [github/#4](https://github.com/haskell/ghcup-hs/pull/4), thanks to Mario Lang
|
||||
|
||||
## 0.1.15.2 -- 2021-06-13
|
||||
|
||||
* Remove legacy handling of cabal binary and be more graceful about binaries not installed by ghcup (e.g. stack)
|
||||
* Fix GHC compilation from git
|
||||
* Fix 'ghcup upgrade' on windows
|
||||
* Allow to skip update checks via `GHCUP_SKIP_UPDATE_CHECK`
|
||||
* Use libarchive on windows as well, fixing unpack errors wrt [#147](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/147)
|
||||
|
||||
## 0.1.15.1 -- 2021-06-11
|
||||
|
||||
* Add Apple Silicon support
|
||||
* Add windows support wrt [#130](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/130)
|
||||
* Add stack support
|
||||
* Warn when /tmp doesn't have 5GB or more of disk space
|
||||
* Allow to compile GHC from git repo wrt [#126](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/126)
|
||||
* Allow to set custom ghc version when running 'ghcup compile ghc' wrt [#136](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/136)
|
||||
* Add date to GHC bindist names created by ghcup
|
||||
|
||||
## 0.1.14.2 -- 2021-05-12
|
||||
|
||||
* Remove dead dependency on ascii-string
|
||||
|
||||
## 0.1.14.1 -- 2021-04-11
|
||||
|
||||
* Make internal symlink target parser more lax, fixes [#119](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/119)
|
||||
* Prepare for hackage release
|
||||
|
||||
## 0.1.14 -- 2021-03-07
|
||||
|
||||
* Major bugfix: fix handling of stray versions wrt [#116](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/116)
|
||||
* Fix error messages and overhaul pretty printing wrt [#115](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/115)
|
||||
|
||||
## 0.1.13 -- 2021-02-26
|
||||
|
||||
* Support ARMv7/AARCH64
|
||||
* Add command line completions for installed and available versions wrt [MR #70](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/70)
|
||||
* Allow to cycle through set tools wrt [#114](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/114)
|
||||
* Fix item selection with unavailable versions wrt [#107](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/107)
|
||||
* Allow for dynamic post-install, post-remove and pre-compile msgs wrt [MR #68](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/68)
|
||||
* Alert user if upgraded ghcup is shadowed by old ghcup wrt [#111](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/111)
|
||||
* Fix to `ghcup` directory creation and placement for the XDG install mode ([MR #49](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/49))
|
||||
* Do 755 permissions on executables, wrt #97
|
||||
* Add [NO_COLOR](https://no-color.org/) support wrt [MR #47](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/47)
|
||||
|
||||
## 0.1.12 -- 2020-11-21
|
||||
|
||||
* Fix disappearing HLS symlinks wrt #91
|
||||
* improve TUI:
|
||||
- separators between tools sections
|
||||
- reverse list order so latest is on top
|
||||
- expand the blues selected bar
|
||||
- show new latest versions in bright white
|
||||
* allow configuration file and setting TUI hotkeys wrt #41
|
||||
- see https://gitlab.haskell.org/haskell/ghcup-hs#configuration for a more in-depth explanation
|
||||
* add a `--set` switch to `ghcup install ghc` to automatically set as default after install
|
||||
* emit warnings when CC/LD is set wrt #82
|
||||
* add support for version ranges in distro specifiers wrt #84
|
||||
- e.g. `"(>= 19 && <= 20) || ==0.2.2"` is a valid version key for distro
|
||||
|
||||
## 0.1.11 -- 2020-09-23
|
||||
|
||||
* Add support for installing haskell-language-server, wrt #65
|
||||
* When compiling GHC from source create a bindist first, store that bindist in `~/.ghcup/cache` and install it, wrt #51
|
||||
* Allow to compile over existing version (`ghcup compile ghc -v 8.6.5 -b 8.6.5`) and replace it wrt #59
|
||||
* simplify installing from custom bindist wrt #60
|
||||
- `ghcup install ghc -u <url> <version>`
|
||||
* fix bug when cabal isn't marked executable in bindist
|
||||
* fix bug when `~/.ghcup` is a valid symlink wrt #49
|
||||
* Drop support for compiling cabal from source (the old bootstrap script is discontinued)
|
||||
|
||||
## 0.1.10 -- 2020-08-14
|
||||
|
||||
* Show stray Cabals (useful for pre-releases or compiled ones)
|
||||
|
||||
## 0.1.9 -- 2020-08-14
|
||||
|
||||
* Fix bug when uninstalling all cabal versions
|
||||
* Fix bug when setting a non-installed ghc version as current default
|
||||
* Use yaml instead of generated json for download info for ease of adding new GHC versions #44
|
||||
* Allow pre-release versions of GHC/cabal
|
||||
* Add XDG dirs support (set `GHCUP_USE_XDG_DIRS`) wrt #39
|
||||
* Allow to specify regex for tarball subdir (e.g. `ghc-.*`)
|
||||
* Allow installing arbitrary bindists more seamlessly:
|
||||
- e.g. installing GHC HEAD: `ghcup -n install ghc -u '{"dlHash": "", "dlSubdir": { "RegexDir": "ghc-.*"}, "dlUri": "https://gitlab.haskell.org/api/v4/projects/1/jobs/artifacts/master/raw/ghc-x86_64-fedora27-linux.tar.xz?job=validate-x86_64-linux-fedora27" }' head`
|
||||
* Avoid duplicate edits to .bashrc/.zshrc wrt #43
|
||||
|
||||
## 0.1.8 -- 2020-07-21
|
||||
|
||||
* Fix bug in logging thread dying on newlines
|
||||
* Allow to install from arbitrary bindists: `ghcup -n install ghc -u '{"dlHash": "", "dlSubdir": "ghc-8.10.1", "dlUri": "https://github.com/commercialhaskell/ghc/releases/download/ghc-8.10.1-release/ghc-8.10.1-x86_64-deb9-linux.tar.xz"}' 8.10.1`
|
||||
|
||||
## 0.1.7 -- 2020-07-20
|
||||
|
||||
* Fix a bug in libarchive not unpacking some uncleanly packed bindists
|
||||
* Improved fish support in bootstrap-haskell
|
||||
* Only check for upgrades when not upgrading
|
||||
* Fix platform detection for i386 docker images
|
||||
* Improve alpine support
|
||||
- more/proper bindists
|
||||
- don't fall back to glibc based bindists
|
||||
- install bindists with `--disable-ld-override` to avoid ld.gold bugs
|
||||
|
||||
## 0.1.6 -- 2020-07-13
|
||||
|
||||
* Create a new curses (brick) based TUI, accessible via `ghcup tui` #24
|
||||
* Support multiple installed versions of cabal #23
|
||||
* Improvements to `ghcup list` (show unavailable bindists for platform)
|
||||
* Fix redhat downloads #29
|
||||
* Support for hadrian bindists (fixes alpine-8.10.1) #31
|
||||
* Add FreeBSD bindists 8.6.5 and 8.8.3
|
||||
* Fix memory leak during unpack
|
||||
|
||||
## 0.1.5 -- 2020-04-30
|
||||
|
||||
* Fix errors when PATH variable contains path components that are actually files
|
||||
* Add `--version` and `--numeric-version` options
|
||||
* Add `changelog` command
|
||||
* Also check for available GHC and Cabal updates on start
|
||||
* Add base versions as tags for every GHC version (these are "installable" tags and the latest GHC version matching the tag will be picked)
|
||||
* Added `--format-raw` to list subcommand
|
||||
* Allow to install X.Y versions (e.g.: ghcup install 8.8)
|
||||
* Implement `--keep=<always|errors|never>` to control temporary build directories cleanup
|
||||
* Add proper shell completions to the repo
|
||||
* Fix building of documentation
|
||||
* Allow to work in offline mode and use cached files if possible
|
||||
* Allow to set the downloader via `--downloader=<curl|wget>`
|
||||
* Support for compiling and installing a cross GHC (see README). This is experimental.
|
||||
|
||||
## 0.1.4 -- 2020-04-16
|
||||
|
||||
* build on all platforms with curl (as a binary), wrt https://gitlab.haskell.org/haskell/ghcup-hs/issues/6
|
||||
* Fix unlinking of ghc symlinks after new installation, wrt https://gitlab.haskell.org/haskell/ghcup-hs/issues/7
|
||||
|
||||
## 0.1.3 -- 2020-04-15
|
||||
|
||||
* Fix lesser bug when skipping ghcup update
|
||||
|
||||
## 0.1.2 -- 2020-04-15
|
||||
|
||||
* Fix bug when removing the set GHC version
|
||||
* Fix use of undocumented `GHCUP_INSTALL_BASE_PREFIX` variable
|
||||
* skip upgrade if ghcup is already latest version
|
||||
|
||||
## 0.1.1 -- 2020-04-15
|
||||
|
||||
* fix awful fdopendir bug on mac bug by updating hpath-posix
|
||||
|
||||
42
Dockerfile
@@ -1,42 +0,0 @@
|
||||
FROM alpine:edge
|
||||
|
||||
# ghc and cabal
|
||||
RUN apk add --no-cache \
|
||||
curl \
|
||||
gcc \
|
||||
g++ \
|
||||
gmp-dev \
|
||||
ncurses-dev \
|
||||
libffi-dev \
|
||||
make \
|
||||
xz \
|
||||
tar \
|
||||
perl \
|
||||
\
|
||||
cabal \
|
||||
ghc
|
||||
|
||||
# utils
|
||||
RUN apk add --no-cache \
|
||||
bash
|
||||
|
||||
## Package specific
|
||||
RUN apk add --no-cache \
|
||||
zlib \
|
||||
zlib-dev \
|
||||
zlib-static \
|
||||
gmp \
|
||||
gmp-dev \
|
||||
openssl-dev \
|
||||
openssl-libs-static \
|
||||
xz \
|
||||
xz-dev
|
||||
|
||||
RUN cabal v2-update
|
||||
|
||||
COPY . /app
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN chmod +x /app/docker/build.sh
|
||||
|
||||
45
HACKING.md
@@ -1,45 +0,0 @@
|
||||
# HACKING
|
||||
|
||||
## Design decisions
|
||||
|
||||
### Using [Excepts](https://hackage.haskell.org/package/haskus-utils-variant-3.0/docs/Haskus-Utils-Variant-Excepts.html) as a beefed up ExceptT
|
||||
|
||||
This is an open variant, similar to [plucky](https://hackage.haskell.org/package/plucky) or [oops](https://github.com/i-am-tom/oops) and allows us to combine different error types. Maybe it is too much and it's a little bit [unergonomic](https://github.com/haskus/packages/issues/32) at times. If it really hurts maintenance, it will be removed. It was more of an experiment.
|
||||
|
||||
### No use of filepath or directory
|
||||
|
||||
Filepath and directory have two fundamental problems: 1. they use String as filepath (see [AFPP](https://gitlab.haskell.org/ghc/ghc/-/wikis/proposal/abstract-file-path) as to why this is wrong) and 2. they try very hard to be cross-platform at the expense of low-level correctness. Instead, we use the [hpath](https://github.com/hasufell/hpath) libraries for file and filepath related stuff, which also gives us stronger filepath types.
|
||||
|
||||
### No use of haskell-TLS
|
||||
|
||||
I consider haskell-TLS an interesting experiment, but not a battle-tested and peer-reviewed crypto implementation. There is little to no research about what the intricacies of using haskell for low-level crypto are and how vulnerable such binaries are. Instead, we use either curl the binary (for FreeBSD and mac) or http-io-streams, which works with OpenSSL bindings.
|
||||
|
||||
### Optics instead of lens
|
||||
|
||||
They're a little safer (less Monoid weirdness with view) and have better error messages. Consider the following wit lens
|
||||
|
||||
```
|
||||
> view (_Just . to (++ "abc")) Nothing
|
||||
""
|
||||
```
|
||||
|
||||
vs optics
|
||||
|
||||
```
|
||||
> view (_Just % to (++ "abc")) Nothing
|
||||
|
||||
<interactive>:2:1: error:
|
||||
• An_AffineFold cannot be used as A_Getter
|
||||
• In the expression: view (_Just % to (++ "abc")) Nothing
|
||||
In an equation for ‘it’: it = view (_Just % to (++ "abc")) Nothing
|
||||
```
|
||||
|
||||
### Strict and StrictData on by default
|
||||
|
||||
Kazu Yamamoto [explained it in his PR](https://github.com/yesodweb/wai/pull/752#issuecomment-501531386) very well. I like to agree with him. The instances where we need non-strict behavior, we annotate it.
|
||||
|
||||
## Code style and formatting
|
||||
|
||||
1. Brittany
|
||||
2. mtl-style preferred
|
||||
3. no overly pointfree style
|
||||
149
README.md
@@ -1,144 +1,13 @@
|
||||
`ghcup` makes it easy to install specific versions of `ghc` on GNU/Linux,
|
||||
macOS (aka Darwin) and FreeBSD and can also bootstrap a fresh Haskell developer environment from scratch.
|
||||
It follows the unix UNIX philosophy of [do one thing and do it well](https://en.wikipedia.org/wiki/Unix_philosophy#Do_One_Thing_and_Do_It_Well).
|
||||
## The GHCup Haskell installer
|
||||
|
||||
Similar in scope to [rustup](https://github.com/rust-lang-nursery/rustup.rs), [pyenv](https://github.com/pyenv/pyenv) and [jenv](http://www.jenv.be).
|
||||
[](https://kiwiirc.com/nextclient/irc.libera.chat/?nick=Guest%7C?#haskell,#haskell-ghcup)
|
||||
[](https://app.element.io/#/room/#haskell-tooling:matrix.org)
|
||||
[](https://discord.gg/pKYf3zDQU7)
|
||||
[](https://gitter.im/haskell/ghcup?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
<a href="https://opencollective.com/ghcup#category-CONTRIBUTE"><img src="https://opencollective.com/webpack/donate/button@2x.png?color=blue" alt="Donate" width="150"></a>
|
||||
|
||||
*Ubuntu users may prefer [hvr's ppa](https://launchpad.net/~hvr/+archive/ubuntu/ghc).*
|
||||
GHCup is an installer for the general purpose language [Haskell](https://www.haskell.org/).
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Installation](#installation)
|
||||
* [Usage](#usage)
|
||||
* [Manpages](#manpages)
|
||||
* [Design goals](#design-goals)
|
||||
* [How](#how)
|
||||
* [Known users](#known-users)
|
||||
* [Known problems](#known-problems)
|
||||
* [FAQ](#faq)
|
||||
|
||||
## Installation
|
||||
|
||||
### Simple bootstrap
|
||||
|
||||
Follow the instructions at [https://www.haskell.org/ghcup/](https://www.haskell.org/ghcup/)
|
||||
|
||||
### Manual install
|
||||
|
||||
Download the binary for your platform at [https://downloads.haskell.org/~ghcup/](https://downloads.haskell.org/~ghcup/)
|
||||
and place it into your `PATH` anywhere.
|
||||
|
||||
Then adjust your `PATH` in `~/.bashrc` (or similar, depending on your shell) like so:
|
||||
|
||||
```sh
|
||||
export PATH="$HOME/.cabal/bin:$HOME/.ghcup/bin:$PATH"
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
See `ghcup --help`.
|
||||
|
||||
Common use cases are:
|
||||
|
||||
```sh
|
||||
# list available ghc/cabal versions
|
||||
ghcup list
|
||||
|
||||
# install the recommended GHC version
|
||||
ghcup install
|
||||
|
||||
# install a specific GHC version
|
||||
ghcup install 8.2.2
|
||||
|
||||
# set the currently "active" GHC version
|
||||
ghcup set 8.4.4
|
||||
|
||||
# install cabal-install
|
||||
ghcup install-cabal
|
||||
|
||||
# update ghcup itself
|
||||
ghcup upgrade
|
||||
```
|
||||
|
||||
Generally this is meant to be used with [`cabal-install`](https://hackage.haskell.org/package/cabal-install), which
|
||||
handles your haskell packages and can demand that [a specific version](https://cabal.readthedocs.io/en/latest/nix-local-build.html#cfg-flag---with-compiler) of `ghc` is available, which `ghcup` can do.
|
||||
|
||||
### Manpages
|
||||
|
||||
For man pages to work you need [man-db](http://man-db.nongnu.org/) as your `man` provider, then issue `man ghc`. Manpages only work for the currently set ghc.
|
||||
`MANPATH` may be required to be unset.
|
||||
|
||||
## Design goals
|
||||
|
||||
1. simplicity
|
||||
2. non-interactive
|
||||
3. portable (eh)
|
||||
4. do one thing and do it well (UNIX philosophy)
|
||||
|
||||
### Non-goals
|
||||
|
||||
1. invoking `sudo`, `apt-get` or *any* package manager
|
||||
2. handling system packages
|
||||
3. handling cabal projects
|
||||
4. being a stack alternative
|
||||
|
||||
## How
|
||||
|
||||
Installs a specified GHC version into `~/.ghcup/ghc/<ver>`, and places `ghc-<ver>` symlinks in `~/.ghcup/bin/`.
|
||||
|
||||
Optionally, an unversioned `ghc` link can point to a default version of your choice.
|
||||
|
||||
This uses precompiled GHC binaries that have been compiled on fedora/debian by [upstream GHC](https://www.haskell.org/ghc/download_ghc_8_6_1.html#binaries).
|
||||
|
||||
Alternatively, you can also tell it to compile from source (note that this might fail due to missing requirements).
|
||||
|
||||
In addition this script can also install `cabal-install`.
|
||||
|
||||
## Known users
|
||||
|
||||
* [vabal](https://github.com/Franciman/vabal)
|
||||
|
||||
## Known problems
|
||||
|
||||
### Limited distributions supported
|
||||
|
||||
Currently only GNU/Linux distributions compatible with the [upstream GHC](https://www.haskell.org/ghc/download_ghc_8_6_1.html#binaries) binaries are supported.
|
||||
|
||||
### Precompiled binaries
|
||||
|
||||
Since this uses precompiled binaries you may run into
|
||||
several problems.
|
||||
|
||||
#### Missing libtinfo (ncurses)
|
||||
|
||||
You may run into problems with *ncurses* and **missing libtinfo**, in case
|
||||
your distribution doesn't use the legacy way of building
|
||||
ncurses and has no compatibility symlinks in place.
|
||||
|
||||
Ask your distributor on how to solve this or
|
||||
try to compile from source via `ghcup compile <version>`.
|
||||
|
||||
#### Libnuma required
|
||||
|
||||
This was a [bug](https://ghc.haskell.org/trac/ghc/ticket/15688) in the build system of some GHC versions that lead to
|
||||
unconditionally enabled libnuma support. To mitigate this you might have to install the libnuma
|
||||
package of your distribution. See [here](https://gitlab.haskell.org/haskell/ghcup/issues/58) for a discussion.
|
||||
|
||||
### Compilation
|
||||
|
||||
Although this script can compile GHC for you, it's just a very thin
|
||||
wrapper around the build system. It makes no effort in trying
|
||||
to figure out whether you have the correct toolchain and
|
||||
the correct dependencies. Refer to [the official docs](https://ghc.haskell.org/trac/ghc/wiki/Building/Preparation/Linux)
|
||||
on how to prepare your environment for building GHC.
|
||||
|
||||
## FAQ
|
||||
|
||||
1. Why reimplement stack?
|
||||
|
||||
ghcup is not a reimplementation of stack. The only common part is automatic installation of GHC, but even that differs in scope and design.
|
||||
|
||||
2. Why not support windows?
|
||||
|
||||
Consider using [Chocolatey](https://chocolatey.org/search?q=ghc) or [ghcups](https://github.com/kakkun61/ghcups).
|
||||
Visit the [documentation](https://www.haskell.org/ghcup/) for installation instructions.
|
||||
|
||||
If you're looking for the metadata YAML files, see here: [https://github.com/haskell/ghcup-metadata](https://github.com/haskell/ghcup-metadata)
|
||||
|
||||
11
RELEASING.md
@@ -1,11 +0,0 @@
|
||||
# RELEASING
|
||||
|
||||
1. update `GHCup.Version` module. `ghcupURL` must only be updated if we change the `_toolRequirements` type or the JSON representation of it. The version of the json represents the change increments. `ghcUpVer` is the current application version.
|
||||
|
||||
2. Add/fix downloads to `GHCupDownloads` module, then run `ghcup-gen gen` to generate the new json and validate it via `ghcup-gen check`.
|
||||
|
||||
3. Commit and git push with tag. Wait for tests to succeed.
|
||||
|
||||
4. Upload the new `ghcup-<ver>.json` to `webhost.haskell.org/ghcup/data/`.
|
||||
|
||||
5. Build ghcup releases for Linux (fully static), mac (with `-fcurl`) and FreeBSD (with `-fcurl`). Upload to `webhost.haskell.org/ghcup/bin/` and update symlinks.
|
||||
@@ -1,11 +0,0 @@
|
||||
module GHCupInfo where
|
||||
|
||||
import GHCupDownloads
|
||||
import ToolRequirements
|
||||
import GHCup.Types
|
||||
|
||||
|
||||
ghcupInfo :: GHCupInfo
|
||||
ghcupInfo = GHCupInfo { _toolRequirements = toolRequirements
|
||||
, _ghcupDownloads = ghcupDownloads
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE DuplicateRecordFields #-}
|
||||
{-# LANGUAGE NamedFieldPuns #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
|
||||
|
||||
module Main where
|
||||
|
||||
import GHCup.Types
|
||||
import GHCup.Types.JSON ( )
|
||||
import GHCup.Utils.Logger
|
||||
import GHCupInfo
|
||||
|
||||
import Data.Aeson ( eitherDecode, encode )
|
||||
import Data.Aeson.Encode.Pretty
|
||||
#if !MIN_VERSION_base(4,13,0)
|
||||
import Data.Semigroup ( (<>) )
|
||||
#endif
|
||||
import Options.Applicative hiding ( style )
|
||||
import System.Console.Pretty
|
||||
import System.Exit
|
||||
import System.IO ( stdout )
|
||||
import Validate
|
||||
|
||||
import qualified Data.ByteString as B
|
||||
import qualified Data.ByteString.Lazy as L
|
||||
|
||||
|
||||
data Options = Options
|
||||
{ optCommand :: Command
|
||||
}
|
||||
|
||||
data Command = GenJSON GenJSONOpts
|
||||
| ValidateJSON ValidateJSONOpts
|
||||
| ValidateTarballs ValidateJSONOpts
|
||||
|
||||
data Output
|
||||
= FileOutput FilePath -- optsparse-applicative doesn't handle ByteString correctly anyway
|
||||
| StdOutput
|
||||
|
||||
fileOutput :: Parser Output
|
||||
fileOutput =
|
||||
FileOutput
|
||||
<$> (strOption
|
||||
(long "file" <> short 'f' <> metavar "FILENAME" <> help
|
||||
"Output to a file"
|
||||
)
|
||||
)
|
||||
|
||||
stdOutput :: Parser Output
|
||||
stdOutput = flag'
|
||||
StdOutput
|
||||
(short 'o' <> long "stdout" <> help "Print to stdout (default)")
|
||||
|
||||
outputP :: Parser Output
|
||||
outputP = fileOutput <|> stdOutput
|
||||
|
||||
|
||||
data GenJSONOpts = GenJSONOpts
|
||||
{ output :: Maybe Output
|
||||
, pretty :: Bool
|
||||
}
|
||||
|
||||
genJSONOpts :: Parser GenJSONOpts
|
||||
genJSONOpts = GenJSONOpts <$> optional outputP <*> switch
|
||||
(short 'p' <> long "pretty" <> help "Make JSON output pretty (human readable)"
|
||||
)
|
||||
|
||||
|
||||
data Input
|
||||
= FileInput FilePath -- optsparse-applicative doesn't handle ByteString correctly anyway
|
||||
| StdInput
|
||||
|
||||
fileInput :: Parser Input
|
||||
fileInput =
|
||||
FileInput
|
||||
<$> (strOption
|
||||
(long "file" <> short 'f' <> metavar "FILENAME" <> help
|
||||
"Input file to validate"
|
||||
)
|
||||
)
|
||||
|
||||
stdInput :: Parser Input
|
||||
stdInput = flag'
|
||||
StdInput
|
||||
(short 'i' <> long "stdin" <> help "Validate from stdin (default)")
|
||||
|
||||
inputP :: Parser Input
|
||||
inputP = fileInput <|> stdInput
|
||||
|
||||
data ValidateJSONOpts = ValidateJSONOpts
|
||||
{ input :: Maybe Input
|
||||
}
|
||||
|
||||
validateJSONOpts :: Parser ValidateJSONOpts
|
||||
validateJSONOpts = ValidateJSONOpts <$> optional inputP
|
||||
|
||||
opts :: Parser Options
|
||||
opts = Options <$> com
|
||||
|
||||
com :: Parser Command
|
||||
com = subparser
|
||||
( (command
|
||||
"gen"
|
||||
( GenJSON
|
||||
<$> (info (genJSONOpts <**> helper)
|
||||
(progDesc "Generate the json downloads file")
|
||||
)
|
||||
)
|
||||
)
|
||||
<> (command
|
||||
"check"
|
||||
( ValidateJSON
|
||||
<$> (info (validateJSONOpts <**> helper)
|
||||
(progDesc "Validate the JSON")
|
||||
)
|
||||
)
|
||||
)
|
||||
<> (command
|
||||
"check-tarballs"
|
||||
( ValidateTarballs
|
||||
<$> (info
|
||||
(validateJSONOpts <**> helper)
|
||||
(progDesc "Validate all tarballs (download and checksum)")
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
customExecParser (prefs showHelpOnError) (info (opts <**> helper) idm)
|
||||
>>= \Options {..} -> case optCommand of
|
||||
GenJSON gopts -> do
|
||||
let bs True =
|
||||
encodePretty' (defConfig { confIndent = Spaces 2 }) ghcupInfo
|
||||
bs False = encode ghcupInfo
|
||||
case gopts of
|
||||
GenJSONOpts { output = Nothing, pretty } ->
|
||||
L.hPutStr stdout (bs pretty)
|
||||
GenJSONOpts { output = Just StdOutput, pretty } ->
|
||||
L.hPutStr stdout (bs pretty)
|
||||
GenJSONOpts { output = Just (FileOutput file), pretty } ->
|
||||
L.writeFile file (bs pretty)
|
||||
ValidateJSON vopts -> case vopts of
|
||||
ValidateJSONOpts { input = Nothing } ->
|
||||
L.getContents >>= valAndExit validate
|
||||
ValidateJSONOpts { input = Just StdInput } ->
|
||||
L.getContents >>= valAndExit validate
|
||||
ValidateJSONOpts { input = Just (FileInput file) } ->
|
||||
L.readFile file >>= valAndExit validate
|
||||
ValidateTarballs vopts -> case vopts of
|
||||
ValidateJSONOpts { input = Nothing } ->
|
||||
L.getContents >>= valAndExit validateTarballs
|
||||
ValidateJSONOpts { input = Just StdInput } ->
|
||||
L.getContents >>= valAndExit validateTarballs
|
||||
ValidateJSONOpts { input = Just (FileInput file) } ->
|
||||
L.readFile file >>= valAndExit validateTarballs
|
||||
pure ()
|
||||
|
||||
where
|
||||
valAndExit f contents = do
|
||||
(GHCupInfo _ av) <- case eitherDecode contents of
|
||||
Right r -> pure r
|
||||
Left e -> die (color Red $ show e)
|
||||
myLoggerT (LoggerConfig True (B.hPut stdout) (\_ -> pure ())) (f av)
|
||||
>>= exitWith
|
||||
@@ -1,94 +0,0 @@
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
module ToolRequirements where
|
||||
|
||||
import GHCup.Types
|
||||
import GHCup.Utils.String.QQ
|
||||
|
||||
import qualified Data.Map as M
|
||||
|
||||
|
||||
|
||||
-- | Currently 'GHC' is used for both GHC and cabal to simplify
|
||||
-- this, until we need actual separation.
|
||||
toolRequirements :: ToolRequirements
|
||||
toolRequirements = M.fromList
|
||||
[ ( GHC
|
||||
, M.fromList
|
||||
[ ( Nothing
|
||||
, M.fromList
|
||||
[ ( Linux UnknownLinux
|
||||
, M.fromList
|
||||
[ ( Nothing
|
||||
, Requirements
|
||||
[]
|
||||
[s|You need the following packages: curl g++ gcc gmp make ncurses realpath xz-utils. Consult your distro documentation on the exact names of those packages.|]
|
||||
)
|
||||
]
|
||||
)
|
||||
, ( Linux Alpine
|
||||
, M.fromList
|
||||
[ ( Nothing
|
||||
, Requirements
|
||||
[ "curl"
|
||||
, "gcc"
|
||||
, "g++"
|
||||
, "gmp-dev"
|
||||
, "ncurses-dev"
|
||||
, "libffi-dev"
|
||||
, "make"
|
||||
, "xz"
|
||||
, "tar"
|
||||
, "perl"
|
||||
]
|
||||
""
|
||||
)
|
||||
]
|
||||
)
|
||||
, ( Linux Ubuntu
|
||||
, M.fromList
|
||||
[ ( Nothing
|
||||
, Requirements
|
||||
[ "build-essential"
|
||||
, "curl"
|
||||
, "libgmp-dev"
|
||||
, "libffi-dev"
|
||||
, "libncurses-dev"
|
||||
, "libtinfo5"
|
||||
]
|
||||
""
|
||||
)
|
||||
]
|
||||
)
|
||||
, ( Darwin
|
||||
, M.fromList
|
||||
[ ( Nothing
|
||||
, Requirements
|
||||
[]
|
||||
"On OS X, in the course of running ghcup you will be given a dialog box to install the command line tools. Accept and the requirements will be installed for you. You will then need to run the command again."
|
||||
)
|
||||
]
|
||||
)
|
||||
, ( FreeBSD
|
||||
, M.fromList
|
||||
[ ( Nothing
|
||||
, Requirements
|
||||
[ "curl"
|
||||
, "gcc"
|
||||
, "gmp"
|
||||
, "gmake"
|
||||
, "ncurses"
|
||||
, "perl5"
|
||||
, "libffi"
|
||||
, "libiconv"
|
||||
]
|
||||
""
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
@@ -1,181 +0,0 @@
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
module Validate where
|
||||
|
||||
import GHCup
|
||||
import GHCup.Download
|
||||
import GHCup.Types
|
||||
import GHCup.Utils.Logger
|
||||
|
||||
import Control.Exception.Safe
|
||||
import Control.Monad
|
||||
import Control.Monad.IO.Class
|
||||
import Control.Monad.Logger
|
||||
import Control.Monad.Reader.Class
|
||||
import Control.Monad.Trans.Class ( lift )
|
||||
import Control.Monad.Trans.Reader ( runReaderT )
|
||||
import Control.Monad.Trans.Resource ( runResourceT
|
||||
, MonadUnliftIO
|
||||
)
|
||||
import Data.IORef
|
||||
import Data.List
|
||||
import Data.String.Interpolate
|
||||
import Data.Versions
|
||||
import Haskus.Utils.Variant.Excepts
|
||||
import Optics
|
||||
import System.Exit
|
||||
import System.IO
|
||||
|
||||
import qualified Data.ByteString as B
|
||||
import qualified Data.Map.Strict as M
|
||||
|
||||
|
||||
data ValidationError = InternalError String
|
||||
deriving Show
|
||||
|
||||
instance Exception ValidationError
|
||||
|
||||
|
||||
addError :: (MonadReader (IORef Int) m, MonadIO m, Monad m) => m ()
|
||||
addError = do
|
||||
ref <- ask
|
||||
liftIO $ modifyIORef ref (+ 1)
|
||||
|
||||
|
||||
validate :: (Monad m, MonadLogger m, MonadThrow m, MonadIO m, MonadUnliftIO m)
|
||||
=> GHCupDownloads
|
||||
-> m ExitCode
|
||||
validate dls = do
|
||||
ref <- liftIO $ newIORef 0
|
||||
|
||||
-- * verify binary downloads * --
|
||||
flip runReaderT ref $ do
|
||||
-- unique tags
|
||||
forM_ (M.toList dls) $ \(t, _) -> checkUniqueTags t
|
||||
|
||||
-- required platforms
|
||||
forM_ (M.toList dls) $ \(t, versions) ->
|
||||
forM_ (M.toList versions) $ \(v, vi) ->
|
||||
forM_ (M.toList $ _viArch vi) $ \(arch, pspecs) -> do
|
||||
checkHasRequiredPlatforms t v arch (M.keys pspecs)
|
||||
|
||||
checkGHCisSemver
|
||||
forM_ (M.toList dls) $ \(t, _) -> checkMandatoryTags t
|
||||
|
||||
-- exit
|
||||
e <- liftIO $ readIORef ref
|
||||
if e > 0
|
||||
then pure $ ExitFailure e
|
||||
else do
|
||||
lift $ $(logInfo) [i|All good|]
|
||||
pure ExitSuccess
|
||||
where
|
||||
checkHasRequiredPlatforms t v arch pspecs = do
|
||||
let v' = prettyVer v
|
||||
when (not $ any (== Linux UnknownLinux) pspecs) $ do
|
||||
lift $ $(logError)
|
||||
[i|Linux UnknownLinux missing for for #{t} #{v'} #{arch}|]
|
||||
addError
|
||||
when ((not $ any (== Darwin) pspecs) && arch == A_64) $ do
|
||||
lift $ $(logError) [i|Darwin missing for #{t} #{v'} #{arch}|]
|
||||
addError
|
||||
when ((not $ any (== FreeBSD) pspecs) && arch == A_64) $ lift $ $(logWarn)
|
||||
[i|FreeBSD missing for #{t} #{v'} #{arch}|]
|
||||
|
||||
checkUniqueTags tool = do
|
||||
let allTags = join $ fmap snd $ availableToolVersions dls tool
|
||||
let nonUnique =
|
||||
fmap fst
|
||||
. filter (\(_, b) -> not b)
|
||||
<$> ( mapM
|
||||
(\case
|
||||
[] -> throwM $ InternalError "empty inner list"
|
||||
(t : ts) ->
|
||||
pure $ (t, ) $ if isUniqueTag t then ts == [] else True
|
||||
)
|
||||
. group
|
||||
. sort
|
||||
$ allTags
|
||||
)
|
||||
case join nonUnique of
|
||||
[] -> pure ()
|
||||
xs -> do
|
||||
lift $ $(logError) [i|Tags not unique for #{tool}: #{xs}|]
|
||||
addError
|
||||
where
|
||||
isUniqueTag Latest = True
|
||||
isUniqueTag Recommended = True
|
||||
|
||||
checkGHCisSemver = do
|
||||
let ghcVers = toListOf (ix GHC % to M.keys % folded) dls
|
||||
forM_ ghcVers $ \v -> case semver (prettyVer v) of
|
||||
Left _ -> do
|
||||
lift $ $(logError) [i|GHC version #{v} is not valid semver|]
|
||||
addError
|
||||
Right _ -> pure ()
|
||||
|
||||
-- a tool must have at least one of each mandatory tags
|
||||
checkMandatoryTags tool = do
|
||||
let allTags = join $ fmap snd $ availableToolVersions dls tool
|
||||
forM_ [Latest, Recommended] $ \t -> case elem t allTags of
|
||||
False -> do
|
||||
lift $ $(logError) [i|Tag #{t} missing from #{tool}|]
|
||||
addError
|
||||
True -> pure ()
|
||||
|
||||
|
||||
validateTarballs :: ( Monad m
|
||||
, MonadLogger m
|
||||
, MonadThrow m
|
||||
, MonadIO m
|
||||
, MonadUnliftIO m
|
||||
, MonadMask m
|
||||
)
|
||||
=> GHCupDownloads
|
||||
-> m ExitCode
|
||||
validateTarballs dls = do
|
||||
ref <- liftIO $ newIORef 0
|
||||
|
||||
flip runReaderT ref $ do
|
||||
-- download/verify all binary tarballs
|
||||
let
|
||||
dlbis = nub $ join $ (M.elems dls) <&> \versions ->
|
||||
join $ (M.elems versions) <&> \vi ->
|
||||
join $ (M.elems $ _viArch vi) <&> \pspecs ->
|
||||
join $ (M.elems pspecs) <&> \pverspecs -> (M.elems pverspecs)
|
||||
forM_ dlbis $ downloadAll
|
||||
|
||||
let dlsrc = nub $ join $ (M.elems dls) <&> \versions ->
|
||||
join $ (M.elems versions) <&> maybe [] (: []) . _viSourceDL
|
||||
forM_ dlsrc $ downloadAll
|
||||
|
||||
-- exit
|
||||
e <- liftIO $ readIORef ref
|
||||
if e > 0
|
||||
then pure $ ExitFailure e
|
||||
else do
|
||||
lift $ $(logInfo) [i|All good|]
|
||||
pure ExitSuccess
|
||||
|
||||
where
|
||||
downloadAll dli = do
|
||||
let settings = Settings True False
|
||||
let runLogger = myLoggerT LoggerConfig { lcPrintDebug = True
|
||||
, colorOutter = B.hPut stderr
|
||||
, rawOutter = (\_ -> pure ())
|
||||
}
|
||||
|
||||
r <-
|
||||
runLogger
|
||||
. flip runReaderT settings
|
||||
. runResourceT
|
||||
. runE
|
||||
$ downloadCached dli Nothing
|
||||
case r of
|
||||
VRight _ -> pure ()
|
||||
VLeft e -> do
|
||||
lift $ $(logError)
|
||||
[i|Could not download (or verify hash) of #{dli}, Error was: #{e}|]
|
||||
addError
|
||||
623
app/ghcup/BrickMain.hs
Normal file
@@ -0,0 +1,623 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
|
||||
module BrickMain where
|
||||
|
||||
import GHCup
|
||||
import GHCup.Download
|
||||
import GHCup.Errors
|
||||
import GHCup.Types.Optics ( getDirs )
|
||||
import GHCup.Types hiding ( LeanAppState(..) )
|
||||
import GHCup.Utils
|
||||
import GHCup.Prelude ( decUTF8Safe )
|
||||
import GHCup.Prelude.File
|
||||
import GHCup.Prelude.Logger
|
||||
import GHCup.Prelude.Process
|
||||
|
||||
import Brick
|
||||
import Brick.Widgets.Border
|
||||
import Brick.Widgets.Border.Style
|
||||
import Brick.Widgets.Center
|
||||
import Brick.Widgets.List ( listSelectedFocusedAttr
|
||||
, listSelectedAttr
|
||||
, listAttr
|
||||
)
|
||||
import Codec.Archive
|
||||
import Control.Exception.Safe
|
||||
#if !MIN_VERSION_base(4,13,0)
|
||||
import Control.Monad.Fail ( MonadFail )
|
||||
#endif
|
||||
import Control.Monad.Reader
|
||||
import Control.Monad.Trans.Except
|
||||
import Control.Monad.Trans.Resource
|
||||
import Data.Bool
|
||||
import Data.Functor
|
||||
import Data.List
|
||||
import Data.Maybe
|
||||
import Data.IORef
|
||||
import Data.Vector ( Vector
|
||||
, (!?)
|
||||
)
|
||||
import Data.Versions hiding ( str )
|
||||
import Haskus.Utils.Variant.Excepts
|
||||
import Prelude hiding ( appendFile )
|
||||
import System.FilePath
|
||||
import System.Exit
|
||||
import System.IO.Unsafe
|
||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
||||
import URI.ByteString
|
||||
|
||||
import qualified Data.Text as T
|
||||
import qualified Graphics.Vty as Vty
|
||||
import qualified Data.Vector as V
|
||||
import System.Environment (getExecutablePath)
|
||||
import qualified System.Posix.Process as SPP
|
||||
|
||||
|
||||
hiddenTools :: [Tool]
|
||||
hiddenTools = []
|
||||
|
||||
|
||||
data BrickData = BrickData
|
||||
{ lr :: [ListResult]
|
||||
}
|
||||
deriving Show
|
||||
|
||||
data BrickSettings = BrickSettings
|
||||
{ showAllVersions :: Bool
|
||||
, showAllTools :: Bool
|
||||
}
|
||||
deriving Show
|
||||
|
||||
data BrickInternalState = BrickInternalState
|
||||
{ clr :: Vector ListResult
|
||||
, ix :: Int
|
||||
}
|
||||
deriving Show
|
||||
|
||||
data BrickState = BrickState
|
||||
{ appData :: BrickData
|
||||
, appSettings :: BrickSettings
|
||||
, appState :: BrickInternalState
|
||||
, appKeys :: KeyBindings
|
||||
}
|
||||
deriving Show
|
||||
|
||||
|
||||
keyHandlers :: KeyBindings
|
||||
-> [ ( Vty.Key
|
||||
, BrickSettings -> String
|
||||
, BrickState -> EventM n (Next BrickState)
|
||||
)
|
||||
]
|
||||
keyHandlers KeyBindings {..} =
|
||||
[ (bQuit, const "Quit" , halt)
|
||||
, (bInstall, const "Install" , withIOAction install')
|
||||
, (bUninstall, const "Uninstall", withIOAction del')
|
||||
, (bSet, const "Set" , withIOAction ((liftIO .) . set'))
|
||||
, (bChangelog, const "ChangeLog", withIOAction changelog')
|
||||
, ( bShowAllVersions
|
||||
, \BrickSettings {..} ->
|
||||
if showAllVersions then "Don't show all versions" else "Show all versions"
|
||||
, hideShowHandler (not . showAllVersions) showAllTools
|
||||
)
|
||||
, ( bShowAllTools
|
||||
, \BrickSettings {..} ->
|
||||
if showAllTools then "Don't show all tools" else "Show all tools"
|
||||
, hideShowHandler showAllVersions (not . showAllTools)
|
||||
)
|
||||
, (bUp, const "Up", \BrickState {..} -> continue BrickState{ appState = moveCursor 1 appState Up, .. })
|
||||
, (bDown, const "Down", \BrickState {..} -> continue BrickState{ appState = moveCursor 1 appState Down, .. })
|
||||
]
|
||||
where
|
||||
hideShowHandler f p BrickState{..} =
|
||||
let newAppSettings = appSettings { showAllVersions = f appSettings , showAllTools = p appSettings }
|
||||
newInternalState = constructList appData newAppSettings (Just appState)
|
||||
in continue (BrickState appData newAppSettings newInternalState appKeys)
|
||||
|
||||
|
||||
showKey :: Vty.Key -> String
|
||||
showKey (Vty.KChar c) = [c]
|
||||
showKey Vty.KUp = "↑"
|
||||
showKey Vty.KDown = "↓"
|
||||
showKey key = tail (show key)
|
||||
|
||||
|
||||
ui :: AttrMap -> BrickState -> Widget String
|
||||
ui dimAttrs BrickState{ appSettings = as@BrickSettings{}, ..}
|
||||
= padBottom Max
|
||||
( withBorderStyle unicode
|
||||
$ borderWithLabel (str "GHCup")
|
||||
(center (header <=> hBorder <=> renderList' appState))
|
||||
)
|
||||
<=> footer
|
||||
|
||||
where
|
||||
footer =
|
||||
withAttr "help"
|
||||
. txtWrap
|
||||
. T.pack
|
||||
. foldr1 (\x y -> x <> " " <> y)
|
||||
. fmap (\(key, s, _) -> showKey key <> ":" <> s as)
|
||||
$ keyHandlers appKeys
|
||||
header =
|
||||
minHSize 2 emptyWidget
|
||||
<+> padLeft (Pad 2) (minHSize 6 $ str "Tool")
|
||||
<+> minHSize 15 (str "Version")
|
||||
<+> padLeft (Pad 1) (minHSize 25 $ str "Tags")
|
||||
<+> padLeft (Pad 5) (str "Notes")
|
||||
renderList' = withDefAttr listAttr . drawListElements renderItem True
|
||||
renderItem _ b listResult@ListResult{..} =
|
||||
let marks = if
|
||||
| lSet -> (withAttr "set" $ str "✔✔")
|
||||
| lInstalled -> (withAttr "installed" $ str "✓ ")
|
||||
| otherwise -> (withAttr "not-installed" $ str "✗ ")
|
||||
ver = case lCross of
|
||||
Nothing -> T.unpack . prettyVer $ lVer
|
||||
Just c -> T.unpack (c <> "-" <> prettyVer lVer)
|
||||
dim
|
||||
| lNoBindist && not lInstalled
|
||||
&& not b -- TODO: overloading dim and active ignores active
|
||||
-- so we hack around it here
|
||||
= updateAttrMap (const dimAttrs) . withAttr "no-bindist"
|
||||
| otherwise = id
|
||||
hooray
|
||||
| elem Latest lTag && not lInstalled =
|
||||
withAttr "hooray"
|
||||
| otherwise = id
|
||||
active = if b then putCursor "GHCup" (Location (0,0)) . forceAttr "active" else id
|
||||
in hooray $ active $ dim
|
||||
( marks
|
||||
<+> padLeft (Pad 2)
|
||||
( minHSize 6
|
||||
(printTool lTool)
|
||||
)
|
||||
<+> minHSize 15 (str ver)
|
||||
<+> (let l = catMaybes . fmap printTag $ sort lTag
|
||||
in padLeft (Pad 1) $ minHSize 25 $ if null l
|
||||
then emptyWidget
|
||||
else foldr1 (\x y -> x <+> str "," <+> y) l
|
||||
)
|
||||
<+> padLeft (Pad 5)
|
||||
( let notes = printNotes listResult
|
||||
in if null notes
|
||||
then emptyWidget
|
||||
else foldr1 (\x y -> x <+> str "," <+> y) notes
|
||||
)
|
||||
<+> vLimit 1 (fill ' ')
|
||||
)
|
||||
|
||||
printTag Recommended = Just $ withAttr "recommended" $ str "recommended"
|
||||
printTag Latest = Just $ withAttr "latest" $ str "latest"
|
||||
printTag Prerelease = Just $ withAttr "prerelease" $ str "prerelease"
|
||||
printTag (Base pvp'') = Just $ str ("base-" ++ T.unpack (prettyPVP pvp''))
|
||||
printTag Old = Nothing
|
||||
printTag (UnknownTag t) = Just $ str t
|
||||
|
||||
printTool Cabal = str "cabal"
|
||||
printTool GHC = str "GHC"
|
||||
printTool GHCup = str "GHCup"
|
||||
printTool HLS = str "HLS"
|
||||
printTool Stack = str "Stack"
|
||||
|
||||
printNotes ListResult {..} =
|
||||
(if hlsPowered then [withAttr "hls-powered" $ str "hls-powered"] else mempty
|
||||
)
|
||||
++ (if fromSrc then [withAttr "compiled" $ str "compiled"] else mempty)
|
||||
++ (if lStray then [withAttr "stray" $ str "stray"] else mempty)
|
||||
|
||||
-- | Draws the list elements.
|
||||
--
|
||||
-- Evaluates the underlying container up to, and a bit beyond, the
|
||||
-- selected element. The exact amount depends on available height
|
||||
-- for drawing and 'listItemHeight'. At most, it will evaluate up to
|
||||
-- element @(i + h + 1)@ where @i@ is the selected index and @h@ is the
|
||||
-- available height.
|
||||
drawListElements :: (Int -> Bool -> ListResult -> Widget String)
|
||||
-> Bool
|
||||
-> BrickInternalState
|
||||
-> Widget String
|
||||
drawListElements drawElem foc is@(BrickInternalState clr _) =
|
||||
Widget Greedy Greedy $
|
||||
let
|
||||
es = clr
|
||||
listSelected = fmap fst $ listSelectedElement' is
|
||||
|
||||
drawnElements = flip V.imap es $ \i' e ->
|
||||
let addSeparator w = case es !? (i' - 1) of
|
||||
Just e' | lTool e' /= lTool e ->
|
||||
hBorder <=> w
|
||||
_ -> w
|
||||
|
||||
isSelected = Just i' == listSelected
|
||||
elemWidget = drawElem i' isSelected e
|
||||
selItemAttr = if foc
|
||||
then withDefAttr listSelectedFocusedAttr
|
||||
else withDefAttr listSelectedAttr
|
||||
makeVisible = if isSelected then visible . selItemAttr else id
|
||||
in addSeparator $ makeVisible elemWidget
|
||||
|
||||
in render
|
||||
$ viewport "GHCup" Vertical
|
||||
$ vBox
|
||||
$ V.toList drawnElements
|
||||
|
||||
|
||||
minHSize :: Int -> Widget n -> Widget n
|
||||
minHSize s' = hLimit s' . vLimit 1 . (<+> fill ' ')
|
||||
|
||||
|
||||
app :: AttrMap -> AttrMap -> App BrickState e String
|
||||
app attrs dimAttrs =
|
||||
App { appDraw = \st -> [ui dimAttrs st]
|
||||
, appHandleEvent = eventHandler
|
||||
, appStartEvent = return
|
||||
, appAttrMap = const attrs
|
||||
, appChooseCursor = showFirstCursor
|
||||
}
|
||||
|
||||
defaultAttributes :: Bool -> AttrMap
|
||||
defaultAttributes no_color = attrMap
|
||||
Vty.defAttr
|
||||
[ ("active" , Vty.defAttr `withBackColor` Vty.blue)
|
||||
, ("not-installed", Vty.defAttr `withForeColor` Vty.red)
|
||||
, ("set" , Vty.defAttr `withForeColor` Vty.green)
|
||||
, ("installed" , Vty.defAttr `withForeColor` Vty.green)
|
||||
, ("recommended" , Vty.defAttr `withForeColor` Vty.green)
|
||||
, ("hls-powered" , Vty.defAttr `withForeColor` Vty.green)
|
||||
, ("latest" , Vty.defAttr `withForeColor` Vty.yellow)
|
||||
, ("prerelease" , Vty.defAttr `withForeColor` Vty.red)
|
||||
, ("compiled" , Vty.defAttr `withForeColor` Vty.blue)
|
||||
, ("stray" , Vty.defAttr `withForeColor` Vty.blue)
|
||||
, ("help" , Vty.defAttr `withStyle` Vty.italic)
|
||||
, ("hooray" , Vty.defAttr `withForeColor` Vty.brightWhite)
|
||||
]
|
||||
where
|
||||
withForeColor | no_color = const
|
||||
| otherwise = Vty.withForeColor
|
||||
|
||||
withBackColor | no_color = \attr _ -> attr `Vty.withStyle` Vty.reverseVideo
|
||||
| otherwise = Vty.withBackColor
|
||||
|
||||
withStyle = Vty.withStyle
|
||||
|
||||
dimAttributes :: Bool -> AttrMap
|
||||
dimAttributes no_color = attrMap
|
||||
(Vty.defAttr `Vty.withStyle` Vty.dim)
|
||||
[ ("active" , Vty.defAttr `withBackColor` Vty.blue) -- has no effect ??
|
||||
, ("no-bindist", Vty.defAttr `Vty.withStyle` Vty.dim)
|
||||
]
|
||||
where
|
||||
withBackColor | no_color = \attr _ -> attr `Vty.withStyle` Vty.reverseVideo
|
||||
| otherwise = Vty.withBackColor
|
||||
|
||||
eventHandler :: BrickState -> BrickEvent n e -> EventM n (Next BrickState)
|
||||
eventHandler st@BrickState{..} ev = do
|
||||
AppState { keyBindings = kb } <- liftIO $ readIORef settings'
|
||||
case ev of
|
||||
(MouseDown _ Vty.BScrollUp _ _) ->
|
||||
continue (BrickState { appState = moveCursor 1 appState Up, .. })
|
||||
(MouseDown _ Vty.BScrollDown _ _) ->
|
||||
continue (BrickState { appState = moveCursor 1 appState Down, .. })
|
||||
(VtyEvent (Vty.EvResize _ _)) -> continue st
|
||||
(VtyEvent (Vty.EvKey Vty.KUp _)) ->
|
||||
continue BrickState{ appState = moveCursor 1 appState Up, .. }
|
||||
(VtyEvent (Vty.EvKey Vty.KDown _)) ->
|
||||
continue BrickState{ appState = moveCursor 1 appState Down, .. }
|
||||
(VtyEvent (Vty.EvKey key _)) ->
|
||||
case find (\(key', _, _) -> key' == key) (keyHandlers kb) of
|
||||
Nothing -> continue st
|
||||
Just (_, _, handler) -> handler st
|
||||
_ -> continue st
|
||||
|
||||
|
||||
moveCursor :: Int -> BrickInternalState -> Direction -> BrickInternalState
|
||||
moveCursor steps ais@BrickInternalState{..} direction =
|
||||
let newIx = if direction == Down then ix + steps else ix - steps
|
||||
in case clr !? newIx of
|
||||
Just _ -> BrickInternalState { ix = newIx, .. }
|
||||
Nothing -> ais
|
||||
|
||||
|
||||
-- | Suspend the current UI and run an IO action in terminal. If the
|
||||
-- IO action returns a Left value, then it's thrown as userError.
|
||||
withIOAction :: (BrickState
|
||||
-> (Int, ListResult)
|
||||
-> ReaderT AppState IO (Either String a))
|
||||
-> BrickState
|
||||
-> EventM n (Next BrickState)
|
||||
withIOAction action as = case listSelectedElement' (appState as) of
|
||||
Nothing -> continue as
|
||||
Just (ix, e) -> do
|
||||
suspendAndResume $ do
|
||||
settings <- readIORef settings'
|
||||
flip runReaderT settings $ action as (ix, e) >>= \case
|
||||
Left err -> liftIO $ putStrLn ("Error: " <> err)
|
||||
Right _ -> liftIO $ putStrLn "Success"
|
||||
getAppData Nothing >>= \case
|
||||
Right data' -> do
|
||||
putStrLn "Press enter to continue"
|
||||
_ <- getLine
|
||||
pure (updateList data' as)
|
||||
Left err -> throwIO $ userError err
|
||||
|
||||
|
||||
-- | Update app data and list internal state based on new evidence.
|
||||
-- This synchronises @BrickInternalState@ with @BrickData@
|
||||
-- and @BrickSettings@.
|
||||
updateList :: BrickData -> BrickState -> BrickState
|
||||
updateList appD BrickState{..} =
|
||||
let newInternalState = constructList appD appSettings (Just appState)
|
||||
in BrickState { appState = newInternalState
|
||||
, appData = appD
|
||||
, appSettings = appSettings
|
||||
, appKeys = appKeys
|
||||
}
|
||||
|
||||
|
||||
constructList :: BrickData
|
||||
-> BrickSettings
|
||||
-> Maybe BrickInternalState
|
||||
-> BrickInternalState
|
||||
constructList appD appSettings =
|
||||
replaceLR (filterVisible (showAllVersions appSettings)
|
||||
(showAllTools appSettings))
|
||||
(lr appD)
|
||||
|
||||
listSelectedElement' :: BrickInternalState -> Maybe (Int, ListResult)
|
||||
listSelectedElement' BrickInternalState{..} = fmap (ix, ) $ clr !? ix
|
||||
|
||||
|
||||
selectLatest :: Vector ListResult -> Int
|
||||
selectLatest = fromMaybe 0 . V.findIndex (\ListResult {..} -> lTool == GHC && Latest `elem` lTag)
|
||||
|
||||
|
||||
-- | Replace the @appState@ or construct it based on a filter function
|
||||
-- and a new @[ListResult]@ evidence.
|
||||
-- When passed an existing @appState@, tries to keep the selected element.
|
||||
replaceLR :: (ListResult -> Bool)
|
||||
-> [ListResult]
|
||||
-> Maybe BrickInternalState
|
||||
-> BrickInternalState
|
||||
replaceLR filterF lr s =
|
||||
let oldElem = s >>= listSelectedElement'
|
||||
newVec = V.fromList . filter filterF $ lr
|
||||
newSelected =
|
||||
case oldElem >>= \(_, oldE) -> V.findIndex (toolEqual oldE) newVec of
|
||||
Just ix -> ix
|
||||
Nothing -> selectLatest newVec
|
||||
in BrickInternalState newVec newSelected
|
||||
where
|
||||
toolEqual e1 e2 =
|
||||
lTool e1 == lTool e2 && lVer e1 == lVer e2 && lCross e1 == lCross e2
|
||||
|
||||
|
||||
filterVisible :: Bool -> Bool -> ListResult -> Bool
|
||||
filterVisible v t e | lInstalled e = True
|
||||
| v
|
||||
, not t
|
||||
, lTool e `notElem` hiddenTools = True
|
||||
| not v
|
||||
, t
|
||||
, Old `notElem` lTag e = True
|
||||
| v
|
||||
, t = True
|
||||
| otherwise = (Old `notElem` lTag e) &&
|
||||
(lTool e `notElem` hiddenTools)
|
||||
|
||||
|
||||
install' :: (MonadReader AppState m, MonadIO m, MonadThrow m, MonadFail m, MonadMask m, MonadUnliftIO m)
|
||||
=> BrickState
|
||||
-> (Int, ListResult)
|
||||
-> m (Either String ())
|
||||
install' _ (_, ListResult {..}) = do
|
||||
AppState { ghcupInfo = GHCupInfo { _ghcupDownloads = dls }} <- ask
|
||||
|
||||
let run =
|
||||
runResourceT
|
||||
. runE
|
||||
@'[ AlreadyInstalled
|
||||
, ArchiveResult
|
||||
, UnknownArchive
|
||||
, FileDoesNotExistError
|
||||
, CopyError
|
||||
, NoDownload
|
||||
, NotInstalled
|
||||
, BuildFailed
|
||||
, TagNotFound
|
||||
, DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, DirNotEmpty
|
||||
, NoUpdate
|
||||
, TarDirDoesNotExist
|
||||
, FileAlreadyExistsError
|
||||
, ProcessError
|
||||
, ToolShadowed
|
||||
, UninstallFailed
|
||||
, MergeFileTreeError
|
||||
]
|
||||
|
||||
run (do
|
||||
ce <- liftIO $ fmap (either (const Nothing) Just) $
|
||||
try @_ @SomeException $ getExecutablePath >>= canonicalizePath
|
||||
dirs <- lift getDirs
|
||||
case lTool of
|
||||
GHC -> do
|
||||
let vi = getVersionInfo lVer GHC dls
|
||||
liftE $ installGHCBin lVer GHCupInternal False [] $> (vi, dirs, ce)
|
||||
Cabal -> do
|
||||
let vi = getVersionInfo lVer Cabal dls
|
||||
liftE $ installCabalBin lVer GHCupInternal False $> (vi, dirs, ce)
|
||||
GHCup -> do
|
||||
let vi = snd <$> getLatest dls GHCup
|
||||
liftE $ upgradeGHCup Nothing False False $> (vi, dirs, ce)
|
||||
HLS -> do
|
||||
let vi = getVersionInfo lVer HLS dls
|
||||
liftE $ installHLSBin lVer GHCupInternal False $> (vi, dirs, ce)
|
||||
Stack -> do
|
||||
let vi = getVersionInfo lVer Stack dls
|
||||
liftE $ installStackBin lVer GHCupInternal False $> (vi, dirs, ce)
|
||||
)
|
||||
>>= \case
|
||||
VRight (vi, Dirs{..}, Just ce) -> do
|
||||
forM_ (_viPostInstall =<< vi) $ \msg -> logInfo msg
|
||||
case lTool of
|
||||
GHCup -> do
|
||||
up <- liftIO $ fmap (either (const Nothing) Just)
|
||||
$ try @_ @SomeException $ canonicalizePath (binDir </> "ghcup" <.> exeExt)
|
||||
when ((normalise <$> up) == Just (normalise ce)) $
|
||||
-- TODO: track cli arguments of previous invocation
|
||||
liftIO $ SPP.executeFile ce False ["tui"] Nothing
|
||||
logInfo "Please restart 'ghcup' for the changes to take effect"
|
||||
_ -> pure ()
|
||||
pure $ Right ()
|
||||
VRight (vi, _, _) -> do
|
||||
forM_ (_viPostInstall =<< vi) $ \msg -> logInfo msg
|
||||
logInfo "Please restart 'ghcup' for the changes to take effect"
|
||||
pure $ Right ()
|
||||
VLeft (V (AlreadyInstalled _ _)) -> pure $ Right ()
|
||||
VLeft (V NoUpdate) -> pure $ Right ()
|
||||
VLeft e -> pure $ Left $ prettyShow e <> "\n"
|
||||
<> "Also check the logs in ~/.ghcup/logs"
|
||||
|
||||
|
||||
set' :: BrickState -> (Int, ListResult) -> IO (Either String ())
|
||||
set' _ (_, ListResult {..}) = do
|
||||
settings <- readIORef settings'
|
||||
|
||||
let run =
|
||||
flip runReaderT settings
|
||||
. runE @'[FileDoesNotExistError , NotInstalled , TagNotFound]
|
||||
|
||||
run (do
|
||||
case lTool of
|
||||
GHC -> liftE $ setGHC (GHCTargetVersion lCross lVer) SetGHCOnly Nothing $> ()
|
||||
Cabal -> liftE $ setCabal lVer $> ()
|
||||
HLS -> liftE $ setHLS lVer SetHLSOnly Nothing $> ()
|
||||
Stack -> liftE $ setStack lVer $> ()
|
||||
GHCup -> pure ()
|
||||
)
|
||||
>>= \case
|
||||
VRight _ -> pure $ Right ()
|
||||
VLeft e -> pure $ Left (prettyShow e)
|
||||
|
||||
|
||||
del' :: (MonadReader AppState m, MonadIO m, MonadFail m, MonadMask m, MonadUnliftIO m)
|
||||
=> BrickState
|
||||
-> (Int, ListResult)
|
||||
-> m (Either String ())
|
||||
del' _ (_, ListResult {..}) = do
|
||||
AppState { ghcupInfo = GHCupInfo { _ghcupDownloads = dls }} <- ask
|
||||
|
||||
let run = runE @'[NotInstalled, UninstallFailed]
|
||||
|
||||
run (do
|
||||
let vi = getVersionInfo lVer lTool dls
|
||||
case lTool of
|
||||
GHC -> liftE $ rmGHCVer (GHCTargetVersion lCross lVer) $> vi
|
||||
Cabal -> liftE $ rmCabalVer lVer $> vi
|
||||
HLS -> liftE $ rmHLSVer lVer $> vi
|
||||
Stack -> liftE $ rmStackVer lVer $> vi
|
||||
GHCup -> pure Nothing
|
||||
)
|
||||
>>= \case
|
||||
VRight vi -> do
|
||||
forM_ (_viPostRemove =<< vi) $ \msg ->
|
||||
logInfo msg
|
||||
pure $ Right ()
|
||||
VLeft e -> pure $ Left (prettyShow e)
|
||||
|
||||
|
||||
changelog' :: (MonadReader AppState m, MonadIO m)
|
||||
=> BrickState
|
||||
-> (Int, ListResult)
|
||||
-> m (Either String ())
|
||||
changelog' _ (_, ListResult {..}) = do
|
||||
AppState { pfreq, ghcupInfo = GHCupInfo { _ghcupDownloads = dls }} <- ask
|
||||
case getChangeLog dls lTool (Left lVer) of
|
||||
Nothing -> pure $ Left $
|
||||
"Could not find ChangeLog for " <> prettyShow lTool <> ", version " <> T.unpack (prettyVer lVer)
|
||||
Just uri -> do
|
||||
let cmd = case _rPlatform pfreq of
|
||||
Darwin -> "open"
|
||||
Linux _ -> "xdg-open"
|
||||
FreeBSD -> "xdg-open"
|
||||
Windows -> "start"
|
||||
exec cmd [T.unpack $ decUTF8Safe $ serializeURIRef' uri] Nothing Nothing >>= \case
|
||||
Right _ -> pure $ Right ()
|
||||
Left e -> pure $ Left $ prettyShow e
|
||||
|
||||
|
||||
settings' :: IORef AppState
|
||||
{-# NOINLINE settings' #-}
|
||||
settings' = unsafePerformIO $ do
|
||||
dirs <- getAllDirs
|
||||
let loggerConfig = LoggerConfig { lcPrintDebug = False
|
||||
, consoleOutter = \_ -> pure ()
|
||||
, fileOutter = \_ -> pure ()
|
||||
, fancyColors = True
|
||||
}
|
||||
newIORef $ AppState defaultSettings
|
||||
dirs
|
||||
defaultKeyBindings
|
||||
(GHCupInfo mempty mempty mempty)
|
||||
(PlatformRequest A_64 Darwin Nothing)
|
||||
loggerConfig
|
||||
|
||||
|
||||
|
||||
brickMain :: AppState
|
||||
-> IO ()
|
||||
brickMain s = do
|
||||
writeIORef settings' s
|
||||
|
||||
eAppData <- getAppData (Just $ ghcupInfo s)
|
||||
case eAppData of
|
||||
Right ad ->
|
||||
defaultMain
|
||||
(app (defaultAttributes (noColor $ settings s)) (dimAttributes (noColor $ settings s)))
|
||||
(BrickState ad
|
||||
defaultAppSettings
|
||||
(constructList ad defaultAppSettings Nothing)
|
||||
(keyBindings (s :: AppState))
|
||||
|
||||
)
|
||||
$> ()
|
||||
Left e -> do
|
||||
flip runReaderT s $ logError $ "Error building app state: " <> T.pack (show e)
|
||||
exitWith $ ExitFailure 2
|
||||
|
||||
|
||||
defaultAppSettings :: BrickSettings
|
||||
defaultAppSettings = BrickSettings { showAllVersions = False, showAllTools = False }
|
||||
|
||||
|
||||
getGHCupInfo :: IO (Either String GHCupInfo)
|
||||
getGHCupInfo = do
|
||||
settings <- readIORef settings'
|
||||
|
||||
r <-
|
||||
flip runReaderT settings
|
||||
. runE @'[DigestError, GPGError, JSONError , DownloadFailed , FileDoesNotExistError]
|
||||
$ liftE getDownloadsF
|
||||
|
||||
case r of
|
||||
VRight a -> pure $ Right a
|
||||
VLeft e -> pure $ Left (prettyShow e)
|
||||
|
||||
|
||||
getAppData :: Maybe GHCupInfo
|
||||
-> IO (Either String BrickData)
|
||||
getAppData mgi = runExceptT $ do
|
||||
r <- ExceptT $ maybe getGHCupInfo (pure . Right) mgi
|
||||
liftIO $ modifyIORef settings' (\s -> s { ghcupInfo = r })
|
||||
settings <- liftIO $ readIORef settings'
|
||||
|
||||
flip runReaderT settings $ do
|
||||
lV <- listVersions Nothing Nothing
|
||||
pure $ BrickData (reverse lV)
|
||||
331
app/ghcup/GHCup/OptParse.hs
Normal file
@@ -0,0 +1,331 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE DuplicateRecordFields #-}
|
||||
|
||||
|
||||
module GHCup.OptParse (
|
||||
module GHCup.OptParse.Common
|
||||
, module GHCup.OptParse.Install
|
||||
, module GHCup.OptParse.Set
|
||||
, module GHCup.OptParse.UnSet
|
||||
, module GHCup.OptParse.Rm
|
||||
, module GHCup.OptParse.Compile
|
||||
, module GHCup.OptParse.Config
|
||||
, module GHCup.OptParse.Whereis
|
||||
, module GHCup.OptParse.List
|
||||
#ifndef DISABLE_UPGRADE
|
||||
, module GHCup.OptParse.Upgrade
|
||||
#endif
|
||||
, module GHCup.OptParse.ChangeLog
|
||||
, module GHCup.OptParse.Prefetch
|
||||
, module GHCup.OptParse.GC
|
||||
, module GHCup.OptParse.DInfo
|
||||
, module GHCup.OptParse.Nuke
|
||||
, module GHCup.OptParse.ToolRequirements
|
||||
, module GHCup.OptParse.Run
|
||||
, module GHCup.OptParse
|
||||
) where
|
||||
|
||||
|
||||
import GHCup.OptParse.Common
|
||||
import GHCup.OptParse.Install
|
||||
import GHCup.OptParse.Set
|
||||
import GHCup.OptParse.UnSet
|
||||
import GHCup.OptParse.Rm
|
||||
import GHCup.OptParse.Run
|
||||
import GHCup.OptParse.Compile
|
||||
import GHCup.OptParse.Config
|
||||
import GHCup.OptParse.Whereis
|
||||
import GHCup.OptParse.List
|
||||
#ifndef DISABLE_UPGRADE
|
||||
import GHCup.OptParse.Upgrade
|
||||
#endif
|
||||
import GHCup.OptParse.ChangeLog
|
||||
import GHCup.OptParse.Prefetch
|
||||
import GHCup.OptParse.GC
|
||||
import GHCup.OptParse.DInfo
|
||||
import GHCup.OptParse.ToolRequirements
|
||||
import GHCup.OptParse.Nuke
|
||||
|
||||
import GHCup.Types
|
||||
|
||||
#if !MIN_VERSION_base(4,13,0)
|
||||
import Control.Monad.Fail ( MonadFail )
|
||||
#endif
|
||||
import Control.Monad.Reader
|
||||
import Data.Bifunctor
|
||||
import Data.Either
|
||||
import Data.Functor
|
||||
import Data.Maybe
|
||||
import Options.Applicative hiding ( style )
|
||||
import Options.Applicative.Help.Pretty ( text )
|
||||
import Prelude hiding ( appendFile )
|
||||
import URI.ByteString
|
||||
|
||||
import qualified Data.ByteString.UTF8 as UTF8
|
||||
|
||||
|
||||
|
||||
data Options = Options
|
||||
{
|
||||
-- global options
|
||||
optVerbose :: Maybe Bool
|
||||
, optCache :: Maybe Bool
|
||||
, optMetaCache :: Maybe Integer
|
||||
, optUrlSource :: Maybe URI
|
||||
, optNoVerify :: Maybe Bool
|
||||
, optKeepDirs :: Maybe KeepDirs
|
||||
, optsDownloader :: Maybe Downloader
|
||||
, optNoNetwork :: Maybe Bool
|
||||
, optGpg :: Maybe GPGSetting
|
||||
-- commands
|
||||
, optCommand :: Command
|
||||
}
|
||||
|
||||
data Command
|
||||
= Install (Either InstallCommand InstallOptions)
|
||||
| InstallCabalLegacy InstallOptions
|
||||
| Set (Either SetCommand SetOptions)
|
||||
| UnSet UnsetCommand
|
||||
| List ListOptions
|
||||
| Rm (Either RmCommand RmOptions)
|
||||
| DInfo
|
||||
| Compile CompileCommand
|
||||
| Config ConfigCommand
|
||||
| Whereis WhereisOptions WhereisCommand
|
||||
#ifndef DISABLE_UPGRADE
|
||||
| Upgrade UpgradeOpts Bool Bool
|
||||
#endif
|
||||
| ToolRequirements ToolReqOpts
|
||||
| ChangeLog ChangeLogOptions
|
||||
| Nuke
|
||||
#if defined(BRICK)
|
||||
| Interactive
|
||||
#endif
|
||||
| Prefetch PrefetchCommand
|
||||
| GC GCOptions
|
||||
| Run RunOptions
|
||||
|
||||
|
||||
|
||||
opts :: Parser Options
|
||||
opts =
|
||||
Options
|
||||
<$> invertableSwitch "verbose" (Just 'v') False (help "Enable verbosity (default: disabled)")
|
||||
<*> invertableSwitch "cache" (Just 'c') False (help "Cache downloads in ~/.ghcup/cache (default: disabled)")
|
||||
<*> optional (option auto (long "metadata-caching" <> help "How long the yaml metadata caching interval is (in seconds), 0 to disable" <> internal))
|
||||
<*> optional
|
||||
(option
|
||||
(eitherReader parseUri)
|
||||
( short 's'
|
||||
<> long "url-source"
|
||||
<> metavar "URL"
|
||||
<> help "Alternative ghcup download info url"
|
||||
<> internal
|
||||
<> completer fileUri
|
||||
)
|
||||
)
|
||||
<*> (fmap . fmap) not (invertableSwitch "verify" (Just 'n') True (help "Disable tarball checksum verification (default: enabled)"))
|
||||
<*> optional (option
|
||||
(eitherReader keepOnParser)
|
||||
( long "keep"
|
||||
<> metavar "<always|errors|never>"
|
||||
<> help
|
||||
"Keep build directories? (default: errors)"
|
||||
<> hidden
|
||||
<> completer (listCompleter ["always", "errors", "never"])
|
||||
))
|
||||
<*> optional (option
|
||||
(eitherReader downloaderParser)
|
||||
( long "downloader"
|
||||
#if defined(INTERNAL_DOWNLOADER)
|
||||
<> metavar "<internal|curl|wget>"
|
||||
<> help
|
||||
"Downloader to use (default: internal)"
|
||||
<> completer (listCompleter ["internal", "curl", "wget"])
|
||||
#else
|
||||
<> metavar "<curl|wget>"
|
||||
<> help
|
||||
"Downloader to use (default: curl)"
|
||||
<> completer (listCompleter ["curl", "wget"])
|
||||
#endif
|
||||
<> hidden
|
||||
))
|
||||
<*> invertableSwitch "offline" (Just 'o') False (help "Don't do any network calls, trying cached assets and failing if missing.")
|
||||
<*> optional (option
|
||||
(eitherReader gpgParser)
|
||||
( long "gpg"
|
||||
<> metavar "<strict|lax|none>"
|
||||
<> help
|
||||
"GPG verification (default: none)"
|
||||
<> completer (listCompleter ["strict", "lax", "none"])
|
||||
))
|
||||
<*> com
|
||||
where
|
||||
parseUri s' =
|
||||
first show $ parseURI strictURIParserOptions (UTF8.fromString s')
|
||||
|
||||
|
||||
com :: Parser Command
|
||||
com =
|
||||
subparser
|
||||
#if defined(BRICK)
|
||||
( command
|
||||
"tui"
|
||||
( (\_ -> Interactive)
|
||||
<$> info
|
||||
helper
|
||||
( progDesc "Start the interactive GHCup UI"
|
||||
)
|
||||
)
|
||||
<> command
|
||||
#else
|
||||
( command
|
||||
#endif
|
||||
"install"
|
||||
( Install
|
||||
<$> info
|
||||
(installParser <**> helper)
|
||||
( progDesc "Install or update GHC/cabal/HLS/stack"
|
||||
<> footerDoc (Just $ text installToolFooter)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"set"
|
||||
(info
|
||||
(Set <$> setParser <**> helper)
|
||||
( progDesc "Set currently active GHC/cabal version"
|
||||
<> footerDoc (Just $ text setFooter)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"unset"
|
||||
(info
|
||||
(UnSet <$> unsetParser <**> helper)
|
||||
( progDesc "Unset currently active GHC/cabal version"
|
||||
<> footerDoc (Just $ text unsetFooter)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"rm"
|
||||
(info
|
||||
(Rm <$> rmParser <**> helper)
|
||||
( progDesc "Remove a GHC/cabal/HLS/stack version"
|
||||
<> footerDoc (Just $ text rmFooter)
|
||||
)
|
||||
)
|
||||
|
||||
<> command
|
||||
"list"
|
||||
(info (List <$> listOpts <**> helper)
|
||||
(progDesc "Show available GHCs and other tools")
|
||||
)
|
||||
<> command
|
||||
"upgrade"
|
||||
(info
|
||||
( (Upgrade <$> upgradeOptsP <*> switch
|
||||
(short 'f' <> long "force" <> help "Force update")
|
||||
<*> switch
|
||||
(long "fail-if-shadowed" <> help "Fails after upgrading if the upgraded ghcup binary is shadowed by something else in PATH (useful for CI)")
|
||||
)
|
||||
<**> helper
|
||||
)
|
||||
(progDesc "Upgrade ghcup")
|
||||
)
|
||||
<> command
|
||||
"compile"
|
||||
( Compile
|
||||
<$> info (compileP <**> helper)
|
||||
(progDesc "Compile a tool from source")
|
||||
)
|
||||
<> command
|
||||
"whereis"
|
||||
(info
|
||||
( (Whereis
|
||||
<$> (WhereisOptions <$> switch (short 'd' <> long "directory" <> help "return directory of the binary instead of the binary location"))
|
||||
<*> whereisP
|
||||
) <**> helper
|
||||
)
|
||||
(progDesc "Find a tools location"
|
||||
<> footerDoc ( Just $ text whereisFooter ))
|
||||
)
|
||||
<> command
|
||||
"prefetch"
|
||||
(info
|
||||
( (Prefetch
|
||||
<$> prefetchP
|
||||
) <**> helper
|
||||
)
|
||||
(progDesc "Prefetch assets"
|
||||
<> footerDoc ( Just $ text prefetchFooter ))
|
||||
)
|
||||
<> command
|
||||
"gc"
|
||||
(info
|
||||
( (GC
|
||||
<$> gcP
|
||||
) <**> helper
|
||||
)
|
||||
(progDesc "Garbage collection"
|
||||
<> footerDoc ( Just $ text gcFooter ))
|
||||
)
|
||||
<> command
|
||||
"run"
|
||||
(Run
|
||||
<$>
|
||||
info
|
||||
(runOpts <**> helper)
|
||||
(progDesc "Run a command with the given tool in PATH"
|
||||
<> footerDoc ( Just $ text runFooter )
|
||||
)
|
||||
)
|
||||
<> commandGroup "Main commands:"
|
||||
)
|
||||
<|> subparser
|
||||
( command
|
||||
"debug-info"
|
||||
((\_ -> DInfo) <$> info helper (progDesc "Show debug info"))
|
||||
<> command
|
||||
"tool-requirements"
|
||||
( ToolRequirements
|
||||
<$> info (toolReqP <**> helper)
|
||||
(progDesc "Show the requirements for ghc/cabal")
|
||||
)
|
||||
<> command
|
||||
"changelog"
|
||||
(info
|
||||
(fmap ChangeLog changelogP <**> helper)
|
||||
( progDesc "Find/show changelog"
|
||||
<> footerDoc (Just $ text changeLogFooter)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"config"
|
||||
( Config
|
||||
<$> info (configP <**> helper)
|
||||
(progDesc "Show or set config" <> footerDoc (Just $ text configFooter))
|
||||
)
|
||||
<> commandGroup "Other commands:"
|
||||
<> hidden
|
||||
)
|
||||
<|> subparser
|
||||
( command
|
||||
"install-cabal"
|
||||
(info
|
||||
((InstallCabalLegacy <$> installOpts (Just Cabal)) <**> helper)
|
||||
( progDesc "Install or update cabal"
|
||||
<> footerDoc (Just $ text installCabalFooter)
|
||||
)
|
||||
)
|
||||
<> internal
|
||||
)
|
||||
<|> subparser
|
||||
(command
|
||||
"nuke"
|
||||
(info (pure Nuke <**> helper)
|
||||
(progDesc "Completely remove ghcup from your system"))
|
||||
<> commandGroup "Nuclear Commands:"
|
||||
<> hidden
|
||||
)
|
||||
153
app/ghcup/GHCup/OptParse/ChangeLog.hs
Normal file
@@ -0,0 +1,153 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE DuplicateRecordFields #-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
|
||||
module GHCup.OptParse.ChangeLog where
|
||||
|
||||
|
||||
import GHCup.Types
|
||||
import GHCup.OptParse.Common
|
||||
import GHCup.Prelude
|
||||
import GHCup.Prelude.Logger
|
||||
import GHCup.Prelude.String.QQ
|
||||
import GHCup.Prelude.Process (exec)
|
||||
|
||||
#if !MIN_VERSION_base(4,13,0)
|
||||
import Control.Monad.Fail ( MonadFail )
|
||||
#endif
|
||||
import Control.Monad.Reader
|
||||
import Control.Monad.Trans.Resource
|
||||
import Data.Functor
|
||||
import Data.Maybe
|
||||
import Options.Applicative hiding ( style )
|
||||
import Prelude hiding ( appendFile )
|
||||
import System.Exit
|
||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
||||
|
||||
import qualified Data.Text as T
|
||||
import Control.Exception.Safe (MonadMask)
|
||||
import GHCup.Types.Optics
|
||||
import GHCup.Utils
|
||||
import Data.Versions
|
||||
import URI.ByteString (serializeURIRef')
|
||||
import Data.Char (toLower)
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Options ]--
|
||||
---------------
|
||||
|
||||
|
||||
data ChangeLogOptions = ChangeLogOptions
|
||||
{ clOpen :: Bool
|
||||
, clTool :: Maybe Tool
|
||||
, clToolVer :: Maybe ToolVersion
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Parsers ]--
|
||||
---------------
|
||||
|
||||
|
||||
changelogP :: Parser ChangeLogOptions
|
||||
changelogP =
|
||||
(\x y -> ChangeLogOptions x y)
|
||||
<$> switch (short 'o' <> long "open" <> help "xdg-open the changelog url")
|
||||
<*> optional
|
||||
(option
|
||||
(eitherReader
|
||||
(\s' -> case fmap toLower s' of
|
||||
"ghc" -> Right GHC
|
||||
"cabal" -> Right Cabal
|
||||
"ghcup" -> Right GHCup
|
||||
"stack" -> Right Stack
|
||||
"hls" -> Right HLS
|
||||
e -> Left e
|
||||
)
|
||||
)
|
||||
(short 't' <> long "tool" <> metavar "<ghc|cabal|hls|ghcup>" <> help
|
||||
"Open changelog for given tool (default: ghc)"
|
||||
<> completer toolCompleter
|
||||
)
|
||||
)
|
||||
<*> optional (toolVersionTagArgument Nothing Nothing)
|
||||
|
||||
|
||||
|
||||
--------------
|
||||
--[ Footer ]--
|
||||
--------------
|
||||
|
||||
|
||||
changeLogFooter :: String
|
||||
changeLogFooter = [s|Discussion:
|
||||
By default returns the URI of the ChangeLog of the latest GHC release.
|
||||
Pass '-o' to automatically open via xdg-open.|]
|
||||
|
||||
|
||||
|
||||
------------------
|
||||
--[ Entrypoint ]--
|
||||
------------------
|
||||
|
||||
|
||||
|
||||
changelog :: ( Monad m
|
||||
, MonadMask m
|
||||
, MonadUnliftIO m
|
||||
, MonadFail m
|
||||
)
|
||||
=> ChangeLogOptions
|
||||
-> (forall a . ReaderT AppState m a -> m a)
|
||||
-> (ReaderT LeanAppState m () -> m ())
|
||||
-> m ExitCode
|
||||
changelog ChangeLogOptions{..} runAppState runLogger = do
|
||||
GHCupInfo { _ghcupDownloads = dls } <- runAppState getGHCupInfo
|
||||
let tool = fromMaybe GHC clTool
|
||||
ver' = maybe
|
||||
(Right Latest)
|
||||
(\case
|
||||
GHCVersion tv -> Left (_tvVersion tv)
|
||||
ToolVersion tv -> Left tv
|
||||
ToolTag t -> Right t
|
||||
)
|
||||
clToolVer
|
||||
muri = getChangeLog dls tool ver'
|
||||
case muri of
|
||||
Nothing -> do
|
||||
runLogger
|
||||
(logWarn $
|
||||
"Could not find ChangeLog for " <> T.pack (prettyShow tool) <> ", version " <> either prettyVer (T.pack . show) ver'
|
||||
)
|
||||
pure ExitSuccess
|
||||
Just uri -> do
|
||||
pfreq <- runAppState getPlatformReq
|
||||
let uri' = T.unpack . decUTF8Safe . serializeURIRef' $ uri
|
||||
cmd = case _rPlatform pfreq of
|
||||
Darwin -> "open"
|
||||
Linux _ -> "xdg-open"
|
||||
FreeBSD -> "xdg-open"
|
||||
Windows -> "start"
|
||||
|
||||
if clOpen
|
||||
then do
|
||||
runAppState $
|
||||
exec cmd
|
||||
[T.unpack $ decUTF8Safe $ serializeURIRef' uri]
|
||||
Nothing
|
||||
Nothing
|
||||
>>= \case
|
||||
Right _ -> pure ExitSuccess
|
||||
Left e -> logError (T.pack $ prettyShow e)
|
||||
>> pure (ExitFailure 13)
|
||||
else liftIO $ putStrLn uri' >> pure ExitSuccess
|
||||
789
app/ghcup/GHCup/OptParse/Common.hs
Normal file
@@ -0,0 +1,789 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE DuplicateRecordFields #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# LANGUAGE NumericUnderscores #-}
|
||||
|
||||
module GHCup.OptParse.Common where
|
||||
|
||||
|
||||
import GHCup
|
||||
import GHCup.Download
|
||||
import GHCup.Errors
|
||||
import GHCup.Platform
|
||||
import GHCup.Types
|
||||
import GHCup.Types.Optics
|
||||
import GHCup.Utils
|
||||
import GHCup.Prelude
|
||||
import GHCup.Prelude.Process
|
||||
import GHCup.Prelude.Logger
|
||||
import GHCup.Prelude.MegaParsec
|
||||
|
||||
import Control.DeepSeq
|
||||
import Control.Concurrent
|
||||
import Control.Concurrent.Async
|
||||
import Control.Exception.Safe
|
||||
#if !MIN_VERSION_base(4,13,0)
|
||||
import Control.Monad.Fail ( MonadFail )
|
||||
#endif
|
||||
import Control.Monad.Reader
|
||||
import Data.Aeson
|
||||
#if MIN_VERSION_aeson(2,0,0)
|
||||
import qualified Data.Aeson.Key as KM
|
||||
import qualified Data.Aeson.KeyMap as KM
|
||||
#else
|
||||
import qualified Data.HashMap.Strict as KM
|
||||
#endif
|
||||
import Data.ByteString.Lazy ( ByteString )
|
||||
import Data.Bifunctor
|
||||
import Data.Char
|
||||
import Data.Either
|
||||
import Data.Functor
|
||||
import Data.List ( nub, sort, sortBy, isPrefixOf, stripPrefix )
|
||||
import Data.Maybe
|
||||
import Data.Text ( Text )
|
||||
import Data.Versions hiding ( str )
|
||||
import Data.Void
|
||||
import qualified Data.Vector as V
|
||||
import GHC.IO.Exception
|
||||
import Haskus.Utils.Variant.Excepts
|
||||
import Options.Applicative hiding ( style )
|
||||
import Prelude hiding ( appendFile )
|
||||
import Safe
|
||||
import System.Process ( readProcess )
|
||||
import System.FilePath
|
||||
import Text.HTML.TagSoup hiding ( Tag )
|
||||
import URI.ByteString
|
||||
|
||||
import qualified Data.ByteString.UTF8 as UTF8
|
||||
import qualified Data.Map.Strict as M
|
||||
import qualified Data.Text as T
|
||||
import qualified Text.Megaparsec as MP
|
||||
import qualified System.FilePath.Posix as FP
|
||||
import GHCup.Version
|
||||
import Control.Exception (evaluate)
|
||||
|
||||
|
||||
-------------
|
||||
--[ Types ]--
|
||||
-------------
|
||||
|
||||
data ToolVersion = GHCVersion GHCTargetVersion
|
||||
| ToolVersion Version
|
||||
| ToolTag Tag
|
||||
|
||||
-- a superset of ToolVersion
|
||||
data SetToolVersion = SetGHCVersion GHCTargetVersion
|
||||
| SetToolVersion Version
|
||||
| SetToolTag Tag
|
||||
| SetRecommended
|
||||
| SetNext
|
||||
|
||||
prettyToolVer :: ToolVersion -> String
|
||||
prettyToolVer (GHCVersion v') = T.unpack $ tVerToText v'
|
||||
prettyToolVer (ToolVersion v') = T.unpack $ prettyVer v'
|
||||
prettyToolVer (ToolTag t) = show t
|
||||
|
||||
toSetToolVer :: Maybe ToolVersion -> SetToolVersion
|
||||
toSetToolVer (Just (GHCVersion v')) = SetGHCVersion v'
|
||||
toSetToolVer (Just (ToolVersion v')) = SetToolVersion v'
|
||||
toSetToolVer (Just (ToolTag t')) = SetToolTag t'
|
||||
toSetToolVer Nothing = SetRecommended
|
||||
|
||||
|
||||
|
||||
|
||||
--------------
|
||||
--[ Parser ]--
|
||||
--------------
|
||||
|
||||
|
||||
toolVersionTagArgument :: Maybe ListCriteria -> Maybe Tool -> Parser ToolVersion
|
||||
toolVersionTagArgument criteria tool =
|
||||
argument (eitherReader (parser tool))
|
||||
(metavar (mv tool)
|
||||
<> completer (tagCompleter (fromMaybe GHC tool) [])
|
||||
<> foldMap (completer . versionCompleter criteria) tool)
|
||||
where
|
||||
mv (Just GHC) = "GHC_VERSION|TAG"
|
||||
mv (Just HLS) = "HLS_VERSION|TAG"
|
||||
mv _ = "VERSION|TAG"
|
||||
|
||||
parser (Just GHC) = ghcVersionTagEither
|
||||
parser Nothing = ghcVersionTagEither
|
||||
parser _ = toolVersionTagEither
|
||||
|
||||
|
||||
versionParser' :: Maybe ListCriteria -> Maybe Tool -> Parser Version
|
||||
versionParser' criteria tool = argument
|
||||
(eitherReader (first show . version . T.pack))
|
||||
(metavar "VERSION" <> foldMap (completer . versionCompleter criteria) tool)
|
||||
|
||||
ghcVersionArgument :: Maybe ListCriteria -> Maybe Tool -> Parser GHCTargetVersion
|
||||
ghcVersionArgument criteria tool = argument (eitherReader ghcVersionEither)
|
||||
(metavar "VERSION" <> foldMap (completer . versionCompleter criteria) tool)
|
||||
|
||||
|
||||
-- https://github.com/pcapriotti/optparse-applicative/issues/148
|
||||
|
||||
-- | A switch that can be enabled using --foo and disabled using --no-foo.
|
||||
--
|
||||
-- The option modifier is applied to only the option that is *not* enabled
|
||||
-- by default. For example:
|
||||
--
|
||||
-- > invertableSwitch "recursive" True (help "do not recurse into directories")
|
||||
--
|
||||
-- This example makes --recursive enabled by default, so
|
||||
-- the help is shown only for --no-recursive.
|
||||
invertableSwitch
|
||||
:: String -- ^ long option
|
||||
-> Maybe Char -- ^ short option for the non-default option
|
||||
-> Bool -- ^ is switch enabled by default?
|
||||
-> Mod FlagFields Bool -- ^ option modifier
|
||||
-> Parser (Maybe Bool)
|
||||
invertableSwitch longopt shortopt defv optmod = invertableSwitch' longopt shortopt defv
|
||||
(if defv then mempty else optmod)
|
||||
(if defv then optmod else mempty)
|
||||
|
||||
-- | Allows providing option modifiers for both --foo and --no-foo.
|
||||
invertableSwitch'
|
||||
:: String -- ^ long option (eg "foo")
|
||||
-> Maybe Char -- ^ short option for the non-default option
|
||||
-> Bool -- ^ is switch enabled by default?
|
||||
-> Mod FlagFields Bool -- ^ option modifier for --foo
|
||||
-> Mod FlagFields Bool -- ^ option modifier for --no-foo
|
||||
-> Parser (Maybe Bool)
|
||||
invertableSwitch' longopt shortopt defv enmod dismod = optional
|
||||
( flag' True ( enmod <> long longopt <> if defv then mempty else maybe mempty short shortopt)
|
||||
<|> flag' False (dismod <> long nolongopt <> if defv then maybe mempty short shortopt else mempty)
|
||||
)
|
||||
where
|
||||
nolongopt = "no-" ++ longopt
|
||||
|
||||
|
||||
|
||||
---------------------
|
||||
--[ Either Parser ]--
|
||||
---------------------
|
||||
|
||||
|
||||
platformParser :: String -> Either String PlatformRequest
|
||||
platformParser s' = case MP.parse (platformP <* MP.eof) "" (T.pack s') of
|
||||
Right r -> pure r
|
||||
Left e -> Left $ errorBundlePretty e
|
||||
where
|
||||
archP :: MP.Parsec Void Text Architecture
|
||||
archP = MP.try (MP.chunk "x86_64" $> A_64) <|> (MP.chunk "i386" $> A_32)
|
||||
platformP :: MP.Parsec Void Text PlatformRequest
|
||||
platformP = choice'
|
||||
[ (`PlatformRequest` FreeBSD)
|
||||
<$> (archP <* MP.chunk "-")
|
||||
<*> ( MP.chunk "portbld"
|
||||
*> ( MP.try (Just <$> verP (MP.chunk "-freebsd" <* MP.eof))
|
||||
<|> pure Nothing
|
||||
)
|
||||
<* MP.chunk "-freebsd"
|
||||
)
|
||||
, (`PlatformRequest` Darwin)
|
||||
<$> (archP <* MP.chunk "-")
|
||||
<*> ( MP.chunk "apple"
|
||||
*> ( MP.try (Just <$> verP (MP.chunk "-darwin" <* MP.eof))
|
||||
<|> pure Nothing
|
||||
)
|
||||
<* MP.chunk "-darwin"
|
||||
)
|
||||
, (\a d mv -> PlatformRequest a (Linux d) mv)
|
||||
<$> (archP <* MP.chunk "-")
|
||||
<*> distroP
|
||||
<*> ((MP.try (Just <$> verP (MP.chunk "-linux" <* MP.eof)) <|> pure Nothing
|
||||
)
|
||||
<* MP.chunk "-linux"
|
||||
)
|
||||
]
|
||||
distroP :: MP.Parsec Void Text LinuxDistro
|
||||
distroP = choice'
|
||||
[ MP.chunk "debian" $> Debian
|
||||
, MP.chunk "deb" $> Debian
|
||||
, MP.chunk "ubuntu" $> Ubuntu
|
||||
, MP.chunk "mint" $> Mint
|
||||
, MP.chunk "fedora" $> Fedora
|
||||
, MP.chunk "centos" $> CentOS
|
||||
, MP.chunk "redhat" $> RedHat
|
||||
, MP.chunk "alpine" $> Alpine
|
||||
, MP.chunk "gentoo" $> Gentoo
|
||||
, MP.chunk "exherbo" $> Exherbo
|
||||
, MP.chunk "unknown" $> UnknownLinux
|
||||
]
|
||||
|
||||
|
||||
uriParser :: String -> Either String URI
|
||||
uriParser = first show . parseURI strictURIParserOptions . UTF8.fromString
|
||||
|
||||
|
||||
absolutePathParser :: FilePath -> Either String FilePath
|
||||
absolutePathParser f = case isValid f && isAbsolute f of
|
||||
True -> Right $ normalise f
|
||||
False -> Left "Please enter a valid absolute filepath."
|
||||
|
||||
isolateParser :: FilePath -> Either String FilePath
|
||||
isolateParser f = case isValid f && isAbsolute f of
|
||||
True -> Right $ normalise f
|
||||
False -> Left "Please enter a valid filepath for isolate dir."
|
||||
|
||||
-- this accepts cross prefix
|
||||
ghcVersionTagEither :: String -> Either String ToolVersion
|
||||
ghcVersionTagEither s' =
|
||||
second ToolTag (tagEither s') <|> second GHCVersion (ghcVersionEither s')
|
||||
|
||||
-- this ignores cross prefix
|
||||
toolVersionTagEither :: String -> Either String ToolVersion
|
||||
toolVersionTagEither s' =
|
||||
second ToolTag (tagEither s') <|> second ToolVersion (toolVersionEither s')
|
||||
|
||||
tagEither :: String -> Either String Tag
|
||||
tagEither s' = case fmap toLower s' of
|
||||
"recommended" -> Right Recommended
|
||||
"latest" -> Right Latest
|
||||
('b':'a':'s':'e':'-':ver') -> case pvp (T.pack ver') of
|
||||
Right x -> Right (Base x)
|
||||
Left _ -> Left $ "Invalid PVP version for base " <> ver'
|
||||
other -> Left $ "Unknown tag " <> other
|
||||
|
||||
|
||||
ghcVersionEither :: String -> Either String GHCTargetVersion
|
||||
ghcVersionEither =
|
||||
first (const "Not a valid version") . MP.parse ghcTargetVerP "" . T.pack
|
||||
|
||||
toolVersionEither :: String -> Either String Version
|
||||
toolVersionEither =
|
||||
first (const "Not a valid version") . MP.parse version' "" . T.pack
|
||||
|
||||
|
||||
toolParser :: String -> Either String Tool
|
||||
toolParser s' | t == T.pack "ghc" = Right GHC
|
||||
| t == T.pack "cabal" = Right Cabal
|
||||
| t == T.pack "hls" = Right HLS
|
||||
| t == T.pack "stack" = Right Stack
|
||||
| otherwise = Left ("Unknown tool: " <> s')
|
||||
where t = T.toLower (T.pack s')
|
||||
|
||||
|
||||
criteriaParser :: String -> Either String ListCriteria
|
||||
criteriaParser s' | t == T.pack "installed" = Right ListInstalled
|
||||
| t == T.pack "set" = Right ListSet
|
||||
| t == T.pack "available" = Right ListAvailable
|
||||
| otherwise = Left ("Unknown criteria: " <> s')
|
||||
where t = T.toLower (T.pack s')
|
||||
|
||||
|
||||
|
||||
keepOnParser :: String -> Either String KeepDirs
|
||||
keepOnParser s' | t == T.pack "always" = Right Always
|
||||
| t == T.pack "errors" = Right Errors
|
||||
| t == T.pack "never" = Right Never
|
||||
| otherwise = Left ("Unknown keep value: " <> s')
|
||||
where t = T.toLower (T.pack s')
|
||||
|
||||
|
||||
downloaderParser :: String -> Either String Downloader
|
||||
downloaderParser s' | t == T.pack "curl" = Right Curl
|
||||
| t == T.pack "wget" = Right Wget
|
||||
#if defined(INTERNAL_DOWNLOADER)
|
||||
| t == T.pack "internal" = Right Internal
|
||||
#endif
|
||||
| otherwise = Left ("Unknown downloader value: " <> s')
|
||||
where t = T.toLower (T.pack s')
|
||||
|
||||
gpgParser :: String -> Either String GPGSetting
|
||||
gpgParser s' | t == T.pack "strict" = Right GPGStrict
|
||||
| t == T.pack "lax" = Right GPGLax
|
||||
| t == T.pack "none" = Right GPGNone
|
||||
| otherwise = Left ("Unknown gpg setting value: " <> s')
|
||||
where t = T.toLower (T.pack s')
|
||||
|
||||
|
||||
|
||||
------------------
|
||||
--[ Completers ]--
|
||||
------------------
|
||||
|
||||
|
||||
toolCompleter :: Completer
|
||||
toolCompleter = listCompleter ["ghc", "cabal", "hls", "stack"]
|
||||
|
||||
gitFileUri :: [String] -> Completer
|
||||
gitFileUri add = mkCompleter $ fileUri' (["git://"] <> add)
|
||||
|
||||
fileUri :: Completer
|
||||
fileUri = mkCompleter $ fileUri' []
|
||||
|
||||
fileUri' :: [String] -> String -> IO [String]
|
||||
fileUri' add = \case
|
||||
"" -> do
|
||||
pwd <- getCurrentDirectory
|
||||
pure $ ["https://", "http://", "file:///", "file://" <> pwd <> "/"] <> add
|
||||
xs
|
||||
| "file:///" `isPrefixOf` xs -> fmap ("file://" <>) <$>
|
||||
case stripPrefix "file://" xs of
|
||||
Nothing -> pure []
|
||||
Just r -> do
|
||||
pwd <- getCurrentDirectory
|
||||
dirs <- compgen "directory" r ["-S", "/"]
|
||||
files <- filter (\f -> (f <> "/") `notElem` dirs) <$> compgen "file" r []
|
||||
pure (dirs <> files <> if r `isPrefixOf` pwd then [pwd <> "/"] else [])
|
||||
| xs `isPrefixOf` "file:///" -> pure ["file:///"]
|
||||
| xs `isPrefixOf` "https://" -> pure ["https://"]
|
||||
| xs `isPrefixOf` "http://" -> pure ["http://"]
|
||||
| otherwise -> pure []
|
||||
where
|
||||
compgen :: String -> String -> [String] -> IO [String]
|
||||
compgen action' r opts = do
|
||||
let cmd = unwords $ ["compgen", "-A", action'] <> opts <> ["--", requote r]
|
||||
result <- tryIO $ readProcess "bash" ["-c", cmd] ""
|
||||
return . lines . either (const []) id $ result
|
||||
|
||||
-- | Strongly quote the string we pass to compgen.
|
||||
--
|
||||
-- We need to do this so bash doesn't expand out any ~ or other
|
||||
-- chars we want to complete on, or emit an end of line error
|
||||
-- when seeking the close to the quote.
|
||||
--
|
||||
-- NOTE: copied from https://hackage.haskell.org/package/optparse-applicative-0.17.0.0/docs/src/Options.Applicative.Builder.Completer.html#requote
|
||||
requote :: String -> String
|
||||
requote s =
|
||||
let
|
||||
-- Bash doesn't appear to allow "mixed" escaping
|
||||
-- in bash completions. So we don't have to really
|
||||
-- worry about people swapping between strong and
|
||||
-- weak quotes.
|
||||
unescaped =
|
||||
case s of
|
||||
-- It's already strongly quoted, so we
|
||||
-- can use it mostly as is, but we must
|
||||
-- ensure it's closed off at the end and
|
||||
-- there's no single quotes in the
|
||||
-- middle which might confuse bash.
|
||||
('\'': rs) -> unescapeN rs
|
||||
|
||||
-- We're weakly quoted.
|
||||
('"': rs) -> unescapeD rs
|
||||
|
||||
-- We're not quoted at all.
|
||||
-- We need to unescape some characters like
|
||||
-- spaces and quotation marks.
|
||||
elsewise -> unescapeU elsewise
|
||||
in
|
||||
strong unescaped
|
||||
|
||||
where
|
||||
strong ss = '\'' : foldr go "'" ss
|
||||
where
|
||||
-- If there's a single quote inside the
|
||||
-- command: exit from the strong quote and
|
||||
-- emit it the quote escaped, then resume.
|
||||
go '\'' t = "'\\''" ++ t
|
||||
go h t = h : t
|
||||
|
||||
-- Unescape a strongly quoted string
|
||||
-- We have two recursive functions, as we
|
||||
-- can enter and exit the strong escaping.
|
||||
unescapeN = goX
|
||||
where
|
||||
goX ('\'' : xs) = goN xs
|
||||
goX (x : xs) = x : goX xs
|
||||
goX [] = []
|
||||
|
||||
goN ('\\' : '\'' : xs) = '\'' : goN xs
|
||||
goN ('\'' : xs) = goX xs
|
||||
goN (x : xs) = x : goN xs
|
||||
goN [] = []
|
||||
|
||||
-- Unescape an unquoted string
|
||||
unescapeU = goX
|
||||
where
|
||||
goX [] = []
|
||||
goX ('\\' : x : xs) = x : goX xs
|
||||
goX (x : xs) = x : goX xs
|
||||
|
||||
-- Unescape a weakly quoted string
|
||||
unescapeD = goX
|
||||
where
|
||||
-- Reached an escape character
|
||||
goX ('\\' : x : xs)
|
||||
-- If it's true escapable, strip the
|
||||
-- slashes, as we're going to strong
|
||||
-- escape instead.
|
||||
| x `elem` ("$`\"\\\n" :: String) = x : goX xs
|
||||
| otherwise = '\\' : x : goX xs
|
||||
-- We've ended quoted section, so we
|
||||
-- don't recurse on goX, it's done.
|
||||
goX ('"' : xs)
|
||||
= xs
|
||||
-- Not done, but not a special character
|
||||
-- just continue the fold.
|
||||
goX (x : xs)
|
||||
= x : goX xs
|
||||
goX []
|
||||
= []
|
||||
|
||||
|
||||
tagCompleter :: Tool -> [String] -> Completer
|
||||
tagCompleter tool add = listIOCompleter $ do
|
||||
dirs' <- liftIO getAllDirs
|
||||
let loggerConfig = LoggerConfig
|
||||
{ lcPrintDebug = False
|
||||
, consoleOutter = mempty
|
||||
, fileOutter = mempty
|
||||
, fancyColors = False
|
||||
}
|
||||
let appState = LeanAppState
|
||||
(defaultSettings { noNetwork = True })
|
||||
dirs'
|
||||
defaultKeyBindings
|
||||
loggerConfig
|
||||
|
||||
mGhcUpInfo <- flip runReaderT appState . runE $ getDownloadsF
|
||||
case mGhcUpInfo of
|
||||
VRight ghcupInfo -> do
|
||||
let allTags = filter (/= Old)
|
||||
$ _viTags =<< M.elems (availableToolVersions (_ghcupDownloads ghcupInfo) tool)
|
||||
pure $ nub $ (add ++) $ fmap tagToString allTags
|
||||
VLeft _ -> pure (nub $ ["recommended", "latest"] ++ add)
|
||||
|
||||
|
||||
versionCompleter :: Maybe ListCriteria -> Tool -> Completer
|
||||
versionCompleter criteria tool = listIOCompleter $ do
|
||||
dirs' <- liftIO getAllDirs
|
||||
let loggerConfig = LoggerConfig
|
||||
{ lcPrintDebug = False
|
||||
, consoleOutter = mempty
|
||||
, fileOutter = mempty
|
||||
, fancyColors = False
|
||||
}
|
||||
let settings = defaultSettings { noNetwork = True }
|
||||
let leanAppState = LeanAppState
|
||||
settings
|
||||
dirs'
|
||||
defaultKeyBindings
|
||||
loggerConfig
|
||||
mpFreq <- flip runReaderT leanAppState . runE $ platformRequest
|
||||
mGhcUpInfo <- flip runReaderT leanAppState . runE $ getDownloadsF
|
||||
forFold mpFreq $ \pfreq -> do
|
||||
forFold mGhcUpInfo $ \ghcupInfo -> do
|
||||
let appState = AppState
|
||||
settings
|
||||
dirs'
|
||||
defaultKeyBindings
|
||||
ghcupInfo
|
||||
pfreq
|
||||
loggerConfig
|
||||
|
||||
runEnv = flip runReaderT appState
|
||||
|
||||
installedVersions <- runEnv $ listVersions (Just tool) criteria
|
||||
return $ T.unpack . prettyVer . lVer <$> installedVersions
|
||||
|
||||
|
||||
toolDlCompleter :: Tool -> Completer
|
||||
toolDlCompleter tool = mkCompleter $ \case
|
||||
"" -> pure (initUrl tool <> ["https://", "http://", "file:///"])
|
||||
word
|
||||
| "file://" `isPrefixOf` word -> fileUri' [] word
|
||||
-- downloads.haskell.org
|
||||
| "https://downloads.haskell.org/" `isPrefixOf` word ->
|
||||
fmap (completePrefix word) . prefixMatch (FP.takeFileName word) <$> fromHRef word
|
||||
|
||||
-- github releases
|
||||
| "https://github.com/haskell/haskell-language-server/releases/download/" `isPrefixOf` word
|
||||
, let xs = splitPath word
|
||||
, (length xs == 6 && last word == '/') || (length xs == 7 && last word /= '/') ->
|
||||
fmap (\x -> completePrefix word x <> "/") . prefixMatch (FP.takeFileName word) <$> getGithubReleases "haskell" "haskell-language-server"
|
||||
| "https://github.com/commercialhaskell/stack/releases/download/" == word
|
||||
, let xs = splitPath word
|
||||
, (length xs == 6 && last word == '/') || (length xs == 7 && last word /= '/') ->
|
||||
fmap (\x -> completePrefix word x <> "/") . prefixMatch (FP.takeFileName word) <$> getGithubReleases "commercialhaskell" "stack"
|
||||
|
||||
-- github release assets
|
||||
| "https://github.com/haskell/haskell-language-server/releases/download/" `isPrefixOf` word
|
||||
, let xs = splitPath word
|
||||
, (length xs == 7 && last word == '/') || length xs == 8
|
||||
, let rel = xs !! 6
|
||||
, length rel > 1 -> do
|
||||
fmap (completePrefix word) . prefixMatch (FP.takeFileName word) <$> getGithubAssets "haskell" "haskell-language-server" (init rel)
|
||||
| "https://github.com/commercialhaskell/stack/releases/download/" `isPrefixOf` word
|
||||
, let xs = splitPath word
|
||||
, (length xs == 7 && last word == '/') || length xs == 8
|
||||
, let rel = xs !! 6
|
||||
, length rel > 1 -> do
|
||||
fmap (completePrefix word) . prefixMatch (FP.takeFileName word) <$> getGithubAssets "commercialhaskell" "stack" (init rel)
|
||||
|
||||
-- github
|
||||
| "https://github.com/c" `isPrefixOf` word -> pure ["https://github.com/commercialhaskell/stack/releases/download/"]
|
||||
| "https://github.com/h" `isPrefixOf` word -> pure ["https://github.com/haskell/haskell-language-server/releases/download/"]
|
||||
| "https://g" `isPrefixOf` word
|
||||
, tool == Stack -> pure ["https://github.com/commercialhaskell/stack/releases/download/"]
|
||||
| "https://g" `isPrefixOf` word
|
||||
, tool == HLS -> pure ["https://github.com/haskell/haskell-language-server/releases/download/"]
|
||||
|
||||
| "https://d" `isPrefixOf` word -> pure $ filter ("https://downloads.haskell.org/" `isPrefixOf`) $ initUrl tool
|
||||
|
||||
| "h" `isPrefixOf` word -> pure $ initUrl tool
|
||||
|
||||
| word `isPrefixOf` "file:///" -> pure ["file:///"]
|
||||
| word `isPrefixOf` "https://" -> pure ["https://"]
|
||||
| word `isPrefixOf` "http://" -> pure ["http://"]
|
||||
|
||||
| otherwise -> pure []
|
||||
where
|
||||
initUrl :: Tool -> [String]
|
||||
initUrl GHC = [ "https://downloads.haskell.org/~ghc/"
|
||||
, "https://downloads.haskell.org/~ghcup/unofficial-bindists/ghc/"
|
||||
]
|
||||
initUrl Cabal = [ "https://downloads.haskell.org/~cabal/"
|
||||
, "https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/"
|
||||
]
|
||||
initUrl GHCup = [ "https://downloads.haskell.org/~ghcup/" ]
|
||||
initUrl HLS = [ "https://github.com/haskell/haskell-language-server/releases/download/"
|
||||
, "https://downloads.haskell.org/~ghcup/unofficial-bindists/haskell-language-server/"
|
||||
]
|
||||
initUrl Stack = [ "https://github.com/commercialhaskell/stack/releases/download/"
|
||||
, "https://downloads.haskell.org/~ghcup/unofficial-bindists/stack/"
|
||||
]
|
||||
|
||||
completePrefix :: String -- ^ url, e.g. 'https://github.com/haskell/haskell-languag'
|
||||
-> String -- ^ match, e.g. 'haskell-language-server'
|
||||
-> String -- ^ result, e.g. 'https://github.com/haskell/haskell-language-server'
|
||||
completePrefix url match =
|
||||
let base = FP.takeDirectory url
|
||||
fn = FP.takeFileName url
|
||||
in if fn `isPrefixOf` match then base <> "/" <> match else url
|
||||
|
||||
prefixMatch :: String -> [String] -> [String]
|
||||
prefixMatch pref = filter (pref `isPrefixOf`)
|
||||
|
||||
fromHRef :: String -> IO [String]
|
||||
fromHRef url = withCurl (FP.takeDirectory url) 2_000_000 $ \stdout ->
|
||||
pure
|
||||
. fmap (T.unpack . decUTF8Safe' . fromAttrib "href")
|
||||
. filter isTagOpen
|
||||
. filter (~== ("<a href>" :: String))
|
||||
. parseTags
|
||||
$ stdout
|
||||
|
||||
withCurl :: String -- ^ url
|
||||
-> Int -- ^ delay
|
||||
-> (ByteString -> IO [String]) -- ^ callback
|
||||
-> IO [String]
|
||||
withCurl url delay cb = do
|
||||
let limit = threadDelay delay
|
||||
race limit (executeOut "curl" ["-fL", url] Nothing) >>= \case
|
||||
Right (CapturedProcess {_exitCode, _stdOut}) -> do
|
||||
case _exitCode of
|
||||
ExitSuccess ->
|
||||
(try @_ @SomeException . cb $ _stdOut) >>= \case
|
||||
Left _ -> pure []
|
||||
Right r' -> do
|
||||
r <- try @_ @SomeException
|
||||
. evaluate
|
||||
. force
|
||||
$ r'
|
||||
either (\_ -> pure []) pure r
|
||||
ExitFailure _ -> pure []
|
||||
Left _ -> pure []
|
||||
|
||||
getGithubReleases :: String
|
||||
-> String
|
||||
-> IO [String]
|
||||
getGithubReleases owner repo = withCurl url 3_000_000 $ \stdout -> do
|
||||
Just xs <- pure $ decode' @Array stdout
|
||||
fmap V.toList $ forM xs $ \x -> do
|
||||
(Object r) <- pure x
|
||||
Just (String name) <- pure $ KM.lookup (mkval "tag_name") r
|
||||
pure $ T.unpack name
|
||||
where
|
||||
url = "https://api.github.com/repos/" <> owner <> "/" <> repo <> "/releases"
|
||||
|
||||
getGithubAssets :: String
|
||||
-> String
|
||||
-> String
|
||||
-> IO [String]
|
||||
getGithubAssets owner repo tag = withCurl url 3_000_000 $ \stdout -> do
|
||||
Just xs <- pure $ decode' @Object stdout
|
||||
Just (Array assets) <- pure $ KM.lookup (mkval "assets") xs
|
||||
as <- fmap V.toList $ forM assets $ \val -> do
|
||||
(Object asset) <- pure val
|
||||
Just (String name) <- pure $ KM.lookup (mkval "name") asset
|
||||
pure $ T.unpack name
|
||||
pure as
|
||||
where
|
||||
url = "https://api.github.com/repos/" <> owner <> "/" <> repo <> "/releases/tags/" <> tag
|
||||
|
||||
|
||||
#if MIN_VERSION_aeson(2,0,0)
|
||||
mkval = KM.fromString
|
||||
#else
|
||||
mkval = id
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-----------------
|
||||
--[ Utilities ]--
|
||||
-----------------
|
||||
|
||||
|
||||
fromVersion :: ( HasLog env
|
||||
, MonadFail m
|
||||
, MonadReader env m
|
||||
, HasGHCupInfo env
|
||||
, HasDirs env
|
||||
, MonadThrow m
|
||||
, MonadIO m
|
||||
, MonadCatch m
|
||||
)
|
||||
=> Maybe ToolVersion
|
||||
-> Tool
|
||||
-> Excepts
|
||||
'[ TagNotFound
|
||||
, NextVerNotFound
|
||||
, NoToolVersionSet
|
||||
] m (GHCTargetVersion, Maybe VersionInfo)
|
||||
fromVersion tv = fromVersion' (toSetToolVer tv)
|
||||
|
||||
fromVersion' :: ( HasLog env
|
||||
, MonadFail m
|
||||
, MonadReader env m
|
||||
, HasGHCupInfo env
|
||||
, HasDirs env
|
||||
, MonadThrow m
|
||||
, MonadIO m
|
||||
, MonadCatch m
|
||||
)
|
||||
=> SetToolVersion
|
||||
-> Tool
|
||||
-> Excepts
|
||||
'[ TagNotFound
|
||||
, NextVerNotFound
|
||||
, NoToolVersionSet
|
||||
] m (GHCTargetVersion, Maybe VersionInfo)
|
||||
fromVersion' SetRecommended tool = do
|
||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||
bimap mkTVer Just <$> getRecommended dls tool
|
||||
?? TagNotFound Recommended tool
|
||||
fromVersion' (SetGHCVersion v) tool = do
|
||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||
let vi = getVersionInfo (_tvVersion v) tool dls
|
||||
case pvp $ prettyVer (_tvVersion v) of -- need to be strict here
|
||||
Left _ -> pure (v, vi)
|
||||
Right pvpIn ->
|
||||
lift (getLatestToolFor tool pvpIn dls) >>= \case
|
||||
Just (pvp_, vi') -> do
|
||||
v' <- lift $ pvpToVersion pvp_ ""
|
||||
when (v' /= _tvVersion v) $ lift $ logWarn ("Assuming you meant version " <> prettyVer v')
|
||||
pure (GHCTargetVersion (_tvTarget v) v', Just vi')
|
||||
Nothing -> pure (v, vi)
|
||||
fromVersion' (SetToolVersion v) tool = do
|
||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||
let vi = getVersionInfo v tool dls
|
||||
case pvp $ prettyVer v of -- need to be strict here
|
||||
Left _ -> pure (mkTVer v, vi)
|
||||
Right pvpIn ->
|
||||
lift (getLatestToolFor tool pvpIn dls) >>= \case
|
||||
Just (pvp_, vi') -> do
|
||||
v' <- lift $ pvpToVersion pvp_ ""
|
||||
when (v' /= v) $ lift $ logWarn ("Assuming you meant version " <> prettyVer v')
|
||||
pure (GHCTargetVersion mempty v', Just vi')
|
||||
Nothing -> pure (mkTVer v, vi)
|
||||
fromVersion' (SetToolTag Latest) tool = do
|
||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||
bimap mkTVer Just <$> getLatest dls tool ?? TagNotFound Latest tool
|
||||
fromVersion' (SetToolTag Recommended) tool = do
|
||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||
bimap mkTVer Just <$> getRecommended dls tool ?? TagNotFound Recommended tool
|
||||
fromVersion' (SetToolTag (Base pvp'')) GHC = do
|
||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||
bimap mkTVer Just <$> getLatestBaseVersion dls pvp'' ?? TagNotFound (Base pvp'') GHC
|
||||
fromVersion' SetNext tool = do
|
||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||
next <- case tool of
|
||||
GHC -> do
|
||||
set <- fmap _tvVersion $ ghcSet Nothing !? NoToolVersionSet tool
|
||||
ghcs <- rights <$> lift getInstalledGHCs
|
||||
(headMay
|
||||
. tail
|
||||
. dropWhile (\GHCTargetVersion {..} -> _tvVersion /= set)
|
||||
. cycle
|
||||
. sortBy (\x y -> compare (_tvVersion x) (_tvVersion y))
|
||||
. filter (\GHCTargetVersion {..} -> isNothing _tvTarget)
|
||||
$ ghcs) ?? NoToolVersionSet tool
|
||||
Cabal -> do
|
||||
set <- cabalSet !? NoToolVersionSet tool
|
||||
cabals <- rights <$> lift getInstalledCabals
|
||||
(fmap (GHCTargetVersion Nothing)
|
||||
. headMay
|
||||
. tail
|
||||
. dropWhile (/= set)
|
||||
. cycle
|
||||
. sort
|
||||
$ cabals) ?? NoToolVersionSet tool
|
||||
HLS -> do
|
||||
set <- hlsSet !? NoToolVersionSet tool
|
||||
hlses <- rights <$> lift getInstalledHLSs
|
||||
(fmap (GHCTargetVersion Nothing)
|
||||
. headMay
|
||||
. tail
|
||||
. dropWhile (/= set)
|
||||
. cycle
|
||||
. sort
|
||||
$ hlses) ?? NoToolVersionSet tool
|
||||
Stack -> do
|
||||
set <- stackSet !? NoToolVersionSet tool
|
||||
stacks <- rights <$> lift getInstalledStacks
|
||||
(fmap (GHCTargetVersion Nothing)
|
||||
. headMay
|
||||
. tail
|
||||
. dropWhile (/= set)
|
||||
. cycle
|
||||
. sort
|
||||
$ stacks) ?? NoToolVersionSet tool
|
||||
GHCup -> fail "GHCup cannot be set"
|
||||
let vi = getVersionInfo (_tvVersion next) tool dls
|
||||
pure (next, vi)
|
||||
fromVersion' (SetToolTag t') tool =
|
||||
throwE $ TagNotFound t' tool
|
||||
|
||||
|
||||
checkForUpdates :: ( MonadReader env m
|
||||
, HasGHCupInfo env
|
||||
, HasDirs env
|
||||
, HasPlatformReq env
|
||||
, MonadCatch m
|
||||
, HasLog env
|
||||
, MonadThrow m
|
||||
, MonadIO m
|
||||
, MonadFail m
|
||||
)
|
||||
=> m [(Tool, Version)]
|
||||
checkForUpdates = do
|
||||
GHCupInfo { _ghcupDownloads = dls } <- getGHCupInfo
|
||||
lInstalled <- listVersions Nothing (Just ListInstalled)
|
||||
let latestInstalled tool = (fmap lVer . lastMay . filter (\lr -> lTool lr == tool)) lInstalled
|
||||
|
||||
ghcup <- forMM (getLatest dls GHCup) $ \(l, _) -> do
|
||||
(Right ghcup_ver) <- pure $ version $ prettyPVP ghcUpVer
|
||||
if (l > ghcup_ver) then pure $ Just (GHCup, l) else pure Nothing
|
||||
|
||||
otherTools <- forM [GHC, Cabal, HLS, Stack] $ \t ->
|
||||
forMM (getLatest dls t) $ \(l, _) -> do
|
||||
let mver = latestInstalled t
|
||||
forMM mver $ \ver ->
|
||||
if (l > ver) then pure $ Just (t, l) else pure Nothing
|
||||
|
||||
pure $ catMaybes (ghcup:otherTools)
|
||||
where
|
||||
forMM a f = fmap join $ forM a f
|
||||
574
app/ghcup/GHCup/OptParse/Compile.hs
Normal file
@@ -0,0 +1,574 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
{-# LANGUAGE DuplicateRecordFields #-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
|
||||
module GHCup.OptParse.Compile where
|
||||
|
||||
|
||||
import GHCup
|
||||
import GHCup.Errors
|
||||
import GHCup.Types
|
||||
import GHCup.Types.Optics
|
||||
import GHCup.Utils
|
||||
import GHCup.Prelude.Logger
|
||||
import GHCup.Prelude.String.QQ
|
||||
import GHCup.OptParse.Common
|
||||
|
||||
#if !MIN_VERSION_base(4,13,0)
|
||||
import Control.Monad.Fail ( MonadFail )
|
||||
#endif
|
||||
import Codec.Archive ( ArchiveResult )
|
||||
import Control.Concurrent (threadDelay)
|
||||
import Control.Monad.Reader
|
||||
import Control.Monad.Trans.Resource
|
||||
import Data.Bifunctor
|
||||
import Data.Functor
|
||||
import Data.Maybe
|
||||
import Data.Versions ( Version, prettyVer, version )
|
||||
import Data.Text ( Text )
|
||||
import Haskus.Utils.Variant.Excepts
|
||||
import Options.Applicative hiding ( style )
|
||||
import Options.Applicative.Help.Pretty ( text )
|
||||
import Prelude hiding ( appendFile )
|
||||
import System.Exit
|
||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
||||
|
||||
import URI.ByteString hiding ( uriParser )
|
||||
import qualified Data.Text as T
|
||||
import Control.Exception.Safe (MonadMask)
|
||||
import System.FilePath (isPathSeparator)
|
||||
import Text.Read (readEither)
|
||||
|
||||
|
||||
|
||||
|
||||
----------------
|
||||
--[ Commands ]--
|
||||
----------------
|
||||
|
||||
|
||||
data CompileCommand = CompileGHC GHCCompileOptions
|
||||
| CompileHLS HLSCompileOptions
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Options ]--
|
||||
---------------
|
||||
|
||||
|
||||
data GHCCompileOptions = GHCCompileOptions
|
||||
{ targetGhc :: Either Version GitBranch
|
||||
, bootstrapGhc :: Either Version FilePath
|
||||
, jobs :: Maybe Int
|
||||
, buildConfig :: Maybe FilePath
|
||||
, patches :: Maybe (Either FilePath [URI])
|
||||
, crossTarget :: Maybe Text
|
||||
, addConfArgs :: [Text]
|
||||
, setCompile :: Bool
|
||||
, ovewrwiteVer :: Maybe Version
|
||||
, buildFlavour :: Maybe String
|
||||
, hadrian :: Bool
|
||||
, isolateDir :: Maybe FilePath
|
||||
}
|
||||
|
||||
data HLSCompileOptions = HLSCompileOptions
|
||||
{ targetHLS :: Either Version GitBranch
|
||||
, jobs :: Maybe Int
|
||||
, setCompile :: Bool
|
||||
, ovewrwiteVer :: Either Bool Version
|
||||
, isolateDir :: Maybe FilePath
|
||||
, cabalProject :: Maybe (Either FilePath URI)
|
||||
, cabalProjectLocal :: Maybe URI
|
||||
, patches :: Maybe (Either FilePath [URI])
|
||||
, targetGHCs :: [ToolVersion]
|
||||
, cabalArgs :: [Text]
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Parsers ]--
|
||||
---------------
|
||||
|
||||
|
||||
compileP :: Parser CompileCommand
|
||||
compileP = subparser
|
||||
( command
|
||||
"ghc"
|
||||
( CompileGHC
|
||||
<$> info
|
||||
(ghcCompileOpts <**> helper)
|
||||
( progDesc "Compile GHC from source"
|
||||
<> footerDoc (Just $ text compileFooter)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"hls"
|
||||
( CompileHLS
|
||||
<$> info
|
||||
(hlsCompileOpts <**> helper)
|
||||
( progDesc "Compile HLS from source"
|
||||
<> footerDoc (Just $ text compileHLSFooter)
|
||||
)
|
||||
)
|
||||
)
|
||||
where
|
||||
compileFooter = [s|Discussion:
|
||||
Compiles and installs the specified GHC version into
|
||||
a self-contained "~/.ghcup/ghc/<ghcver>" directory
|
||||
and symlinks the ghc binaries to "~/.ghcup/bin/<binary>-<ghcver>".
|
||||
|
||||
This also allows building a cross-compiler. Consult the documentation
|
||||
first: <https://gitlab.haskell.org/ghc/ghc/-/wikis/building/cross-compiling#configuring-the-build>
|
||||
|
||||
ENV variables:
|
||||
Various toolchain variables will be passed onto the ghc build system,
|
||||
such as: CC, LD, OBJDUMP, NM, AR, RANLIB.
|
||||
|
||||
Examples:
|
||||
# compile from known version
|
||||
ghcup compile ghc -j 4 -v 8.4.2 -b 8.2.2
|
||||
# compile from git commit/reference
|
||||
ghcup compile ghc -j 4 -g master -b 8.2.2
|
||||
# specify path to bootstrap ghc
|
||||
ghcup compile ghc -j 4 -v 8.4.2 -b /usr/bin/ghc-8.2.2
|
||||
# build cross compiler
|
||||
ghcup compile ghc -j 4 -v 8.4.2 -b 8.2.2 -x armv7-unknown-linux-gnueabihf --config $(pwd)/build.mk -- --enable-unregisterised|]
|
||||
|
||||
compileHLSFooter = [s|Discussion:
|
||||
Compiles and installs the specified HLS version.
|
||||
The --ghc arguments are necessary to specify which GHC version to build for/against.
|
||||
These need to be available in PATH prior to compilation.
|
||||
|
||||
Examples:
|
||||
# compile 1.7.0.0 for ghc 8.10.5 and 8.10.7, passing '--allow-newer' to cabal
|
||||
ghcup compile hls -v 1.7.0.0 -j 12 --ghc 8.10.5 --ghc 8.10.7 -- --allow-newer
|
||||
# compile from master for ghc 9.2.3 and use 'git describe' to name the binary
|
||||
ghcup compile hls -g master --git-describe-version --ghc 9.2.3
|
||||
# compile a specific commit for ghc 9.2.3 and set a specifc version for the binary name
|
||||
ghcup compile hls -g a32db0b -o 1.7.0.0-p1 --ghc 9.2.3|]
|
||||
|
||||
|
||||
ghcCompileOpts :: Parser GHCCompileOptions
|
||||
ghcCompileOpts =
|
||||
GHCCompileOptions
|
||||
<$> ((Left <$> option
|
||||
(eitherReader
|
||||
(first (const "Not a valid version") . version . T.pack)
|
||||
)
|
||||
(short 'v' <> long "version" <> metavar "VERSION" <> help
|
||||
"The tool version to compile"
|
||||
<> (completer $ versionCompleter Nothing GHC)
|
||||
)
|
||||
) <|>
|
||||
(Right <$> (GitBranch <$> option
|
||||
str
|
||||
(short 'g' <> long "git-ref" <> metavar "GIT_REFERENCE" <> help
|
||||
"The git commit/branch/ref to build from"
|
||||
) <*>
|
||||
optional (option str (
|
||||
short 'r' <> long "repository" <> metavar "GIT_REPOSITORY" <> help "The git repository to build from (defaults to GHC upstream)"
|
||||
<> completer (gitFileUri ["https://gitlab.haskell.org/ghc/ghc.git"])
|
||||
))
|
||||
)))
|
||||
<*> option
|
||||
(eitherReader
|
||||
(\x ->
|
||||
(bimap (const "Not a valid version") Left . version . T.pack $ x) <|> (if isPathSeparator (head x) then pure $ Right x else Left "Not an absolute Path")
|
||||
)
|
||||
)
|
||||
( short 'b'
|
||||
<> long "bootstrap-ghc"
|
||||
<> metavar "BOOTSTRAP_GHC"
|
||||
<> help
|
||||
"The GHC version (or full path) to bootstrap with (must be installed)"
|
||||
<> (completer $ versionCompleter Nothing GHC)
|
||||
)
|
||||
<*> optional
|
||||
(option
|
||||
(eitherReader (readEither @Int))
|
||||
(short 'j' <> long "jobs" <> metavar "JOBS" <> help
|
||||
"How many jobs to use for make"
|
||||
<> (completer $ listCompleter $ fmap show ([1..12] :: [Int]))
|
||||
)
|
||||
)
|
||||
<*> optional
|
||||
(option
|
||||
str
|
||||
(short 'c' <> long "config" <> metavar "CONFIG" <> help
|
||||
"Absolute path to build config file"
|
||||
<> completer (bashCompleter "file")
|
||||
)
|
||||
)
|
||||
<*> (optional
|
||||
(
|
||||
(fmap Right $ many $ option
|
||||
(eitherReader uriParser)
|
||||
(long "patch" <> metavar "PATCH_URI" <> help
|
||||
"URI to a patch (https/http/file)"
|
||||
<> completer fileUri
|
||||
)
|
||||
)
|
||||
<|>
|
||||
(fmap Left $ option
|
||||
str
|
||||
(short 'p' <> long "patchdir" <> metavar "PATCH_DIR" <> help
|
||||
"Absolute path to patch directory (applies all .patch and .diff files in order using -p1. This order is determined by a quilt series file if it exists, or the patches are lexicographically ordered)"
|
||||
<> completer (bashCompleter "directory")
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
<*> optional
|
||||
(option
|
||||
str
|
||||
(short 'x' <> long "cross-target" <> metavar "CROSS_TARGET" <> help
|
||||
"Build cross-compiler for this platform"
|
||||
)
|
||||
)
|
||||
<*> many (argument str (metavar "CONFIGURE_ARGS" <> help "Additional arguments to compile configure, prefix with '-- ' (longopts)"))
|
||||
<*> fmap (fromMaybe False) (invertableSwitch "set" Nothing False (help "Set as active version after install"))
|
||||
<*> optional
|
||||
(option
|
||||
(eitherReader
|
||||
(first (const "Not a valid version") . version . T.pack)
|
||||
)
|
||||
(short 'o' <> long "overwrite-version" <> metavar "OVERWRITE_VERSION" <> help
|
||||
"Allows to overwrite the finally installed VERSION with a different one, e.g. when you build 8.10.4 with your own patches, you might want to set this to '8.10.4-p1'"
|
||||
<> (completer $ versionCompleter Nothing GHC)
|
||||
)
|
||||
)
|
||||
<*> optional
|
||||
(option
|
||||
str
|
||||
(short 'f' <> long "flavour" <> metavar "BUILD_FLAVOUR" <> help
|
||||
"Set the compile build flavour (this value depends on the build system type: 'make' vs 'hadrian')"
|
||||
)
|
||||
)
|
||||
<*> switch
|
||||
(long "hadrian" <> help "Use the hadrian build system instead of make (only git versions seem to be properly supported atm)"
|
||||
)
|
||||
<*> optional
|
||||
(option
|
||||
(eitherReader isolateParser)
|
||||
( short 'i'
|
||||
<> long "isolate"
|
||||
<> metavar "DIR"
|
||||
<> help "install in an isolated directory instead of the default one, no symlinks to this installation will be made"
|
||||
<> completer (bashCompleter "directory")
|
||||
)
|
||||
)
|
||||
|
||||
hlsCompileOpts :: Parser HLSCompileOptions
|
||||
hlsCompileOpts =
|
||||
HLSCompileOptions
|
||||
<$> ((Left <$> option
|
||||
(eitherReader
|
||||
(first (const "Not a valid version") . version . T.pack)
|
||||
)
|
||||
(short 'v' <> long "version" <> metavar "VERSION" <> help
|
||||
"The tool version to compile"
|
||||
<> (completer $ versionCompleter Nothing HLS)
|
||||
)
|
||||
) <|>
|
||||
(Right <$> (GitBranch <$> option
|
||||
str
|
||||
(short 'g' <> long "git-ref" <> metavar "GIT_REFERENCE" <> help
|
||||
"The git commit/branch/ref to build from (accepts anything 'git checkout' accepts)"
|
||||
) <*>
|
||||
optional (option str (short 'r' <> long "repository" <> metavar "GIT_REPOSITORY" <> help "The git repository to build from (defaults to HLS upstream)"
|
||||
<> completer (gitFileUri ["https://github.com/haskell/haskell-language-server.git"])
|
||||
))
|
||||
)))
|
||||
<*> optional
|
||||
(option
|
||||
(eitherReader (readEither @Int))
|
||||
(short 'j' <> long "jobs" <> metavar "JOBS" <> help
|
||||
"How many jobs to use for make"
|
||||
<> (completer $ listCompleter $ fmap show ([1..12] :: [Int]))
|
||||
)
|
||||
)
|
||||
<*> fmap (fromMaybe True) (invertableSwitch "set" Nothing True (help "Don't set as active version after install"))
|
||||
<*>
|
||||
(
|
||||
(Right <$> option
|
||||
(eitherReader
|
||||
(first (const "Not a valid version") . version . T.pack)
|
||||
)
|
||||
(short 'o' <> long "overwrite-version" <> metavar "OVERWRITE_VERSION" <> help
|
||||
"Allows to overwrite the finally installed VERSION with a different one, e.g. when you build 8.10.4 with your own patches, you might want to set this to '8.10.4-p1'"
|
||||
<> (completer $ versionCompleter Nothing HLS)
|
||||
)
|
||||
)
|
||||
<|>
|
||||
(Left <$> (switch
|
||||
(long "git-describe-version"
|
||||
<> help "Use the output of 'git describe' (if building from git) as the VERSION component of the installed binary."
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
<*> optional
|
||||
(option
|
||||
(eitherReader isolateParser)
|
||||
( short 'i'
|
||||
<> long "isolate"
|
||||
<> metavar "DIR"
|
||||
<> help "install in an isolated directory instead of the default one, no symlinks to this installation will be made"
|
||||
<> completer (bashCompleter "directory")
|
||||
)
|
||||
)
|
||||
<*> optional
|
||||
(option
|
||||
((fmap Right $ eitherReader uriParser) <|> (fmap Left str))
|
||||
(long "cabal-project" <> metavar "CABAL_PROJECT" <> help
|
||||
"If relative filepath, specifies the path to cabal.project inside the unpacked HLS tarball/checkout. Otherwise expects a full URI with https/http/file scheme."
|
||||
<> completer fileUri
|
||||
)
|
||||
)
|
||||
<*> optional
|
||||
(option
|
||||
(eitherReader uriParser)
|
||||
(long "cabal-project-local" <> metavar "CABAL_PROJECT_LOCAL" <> help
|
||||
"URI (https/http/file) to a cabal.project.local to be used for the build. Will be copied over."
|
||||
<> completer fileUri
|
||||
)
|
||||
)
|
||||
<*> (optional
|
||||
(
|
||||
(fmap Right $ many $ option
|
||||
(eitherReader uriParser)
|
||||
(long "patch" <> metavar "PATCH_URI" <> help
|
||||
"URI to a patch (https/http/file)"
|
||||
<> completer fileUri
|
||||
)
|
||||
)
|
||||
<|>
|
||||
(fmap Left $ option
|
||||
str
|
||||
(short 'p' <> long "patchdir" <> metavar "PATCH_DIR" <> help
|
||||
"Absolute path to patch directory (applies all .patch and .diff files in order using -p1)"
|
||||
<> completer (bashCompleter "directory")
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
<*> some (
|
||||
option (eitherReader ghcVersionTagEither)
|
||||
( long "ghc" <> metavar "GHC_VERSION|TAG" <> help "For which GHC version to compile for (can be specified multiple times)"
|
||||
<> completer (tagCompleter GHC [])
|
||||
<> completer (versionCompleter Nothing GHC))
|
||||
)
|
||||
<*> many (argument str (metavar "CABAL_ARGS" <> help "Additional arguments to cabal install, prefix with '-- ' (longopts)"))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
---------------------------
|
||||
--[ Effect interpreters ]--
|
||||
---------------------------
|
||||
|
||||
|
||||
type GHCEffects = '[ AlreadyInstalled
|
||||
, BuildFailed
|
||||
, DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, GHCupSetError
|
||||
, NoDownload
|
||||
, NotFoundInPATH
|
||||
, PatchFailed
|
||||
, UnknownArchive
|
||||
, TarDirDoesNotExist
|
||||
, NotInstalled
|
||||
, DirNotEmpty
|
||||
, ArchiveResult
|
||||
, FileDoesNotExistError
|
||||
, HadrianNotFound
|
||||
, InvalidBuildConfig
|
||||
, ProcessError
|
||||
, CopyError
|
||||
, BuildFailed
|
||||
, UninstallFailed
|
||||
, MergeFileTreeError
|
||||
]
|
||||
type HLSEffects = '[ AlreadyInstalled
|
||||
, BuildFailed
|
||||
, DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, GHCupSetError
|
||||
, NoDownload
|
||||
, NotFoundInPATH
|
||||
, PatchFailed
|
||||
, UnknownArchive
|
||||
, TarDirDoesNotExist
|
||||
, TagNotFound
|
||||
, NextVerNotFound
|
||||
, NoToolVersionSet
|
||||
, NotInstalled
|
||||
, DirNotEmpty
|
||||
, ArchiveResult
|
||||
, UninstallFailed
|
||||
, MergeFileTreeError
|
||||
]
|
||||
|
||||
|
||||
|
||||
runCompileGHC :: (MonadUnliftIO m, MonadIO m)
|
||||
=> (ReaderT AppState m (VEither GHCEffects a) -> m (VEither GHCEffects a))
|
||||
-> Excepts GHCEffects (ResourceT (ReaderT AppState m)) a
|
||||
-> m (VEither GHCEffects a)
|
||||
runCompileGHC runAppState =
|
||||
runAppState
|
||||
. runResourceT
|
||||
. runE
|
||||
@GHCEffects
|
||||
|
||||
runCompileHLS :: (MonadUnliftIO m, MonadIO m)
|
||||
=> (ReaderT AppState m (VEither HLSEffects a) -> m (VEither HLSEffects a))
|
||||
-> Excepts HLSEffects (ResourceT (ReaderT AppState m)) a
|
||||
-> m (VEither HLSEffects a)
|
||||
runCompileHLS runAppState =
|
||||
runAppState
|
||||
. runResourceT
|
||||
. runE
|
||||
@HLSEffects
|
||||
|
||||
|
||||
|
||||
------------------
|
||||
--[ Entrypoint ]--
|
||||
------------------
|
||||
|
||||
|
||||
|
||||
compile :: ( Monad m
|
||||
, MonadMask m
|
||||
, MonadUnliftIO m
|
||||
, MonadFail m
|
||||
)
|
||||
=> CompileCommand
|
||||
-> Settings
|
||||
-> Dirs
|
||||
-> (forall eff a . ReaderT AppState m (VEither eff a) -> m (VEither eff a))
|
||||
-> (ReaderT LeanAppState m () -> m ())
|
||||
-> m ExitCode
|
||||
compile compileCommand settings Dirs{..} runAppState runLogger = do
|
||||
case compileCommand of
|
||||
(CompileHLS HLSCompileOptions { .. }) -> do
|
||||
runCompileHLS runAppState (do
|
||||
case targetHLS of
|
||||
Left targetVer -> do
|
||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||
let vi = getVersionInfo targetVer HLS dls
|
||||
forM_ (_viPreCompile =<< vi) $ \msg -> do
|
||||
lift $ logInfo msg
|
||||
lift $ logInfo
|
||||
"...waiting for 5 seconds, you can still abort..."
|
||||
liftIO $ threadDelay 5000000 -- for compilation, give the user a sec to intervene
|
||||
Right _ -> pure ()
|
||||
ghcs <- liftE $ forM targetGHCs (\ghc -> fmap (_tvVersion . fst) . fromVersion (Just ghc) $ GHC)
|
||||
targetVer <- liftE $ compileHLS
|
||||
targetHLS
|
||||
ghcs
|
||||
jobs
|
||||
ovewrwiteVer
|
||||
(maybe GHCupInternal IsolateDir isolateDir)
|
||||
cabalProject
|
||||
cabalProjectLocal
|
||||
patches
|
||||
cabalArgs
|
||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||
let vi = getVersionInfo targetVer HLS dls
|
||||
when setCompile $ void $ liftE $
|
||||
setHLS targetVer SetHLSOnly Nothing
|
||||
pure (vi, targetVer)
|
||||
)
|
||||
>>= \case
|
||||
VRight (vi, tv) -> do
|
||||
runLogger $ logInfo
|
||||
"HLS successfully compiled and installed"
|
||||
forM_ (_viPostInstall =<< vi) $ \msg ->
|
||||
runLogger $ logInfo msg
|
||||
liftIO $ putStr (T.unpack $ prettyVer tv)
|
||||
pure ExitSuccess
|
||||
VLeft err@(V (BuildFailed tmpdir _)) -> do
|
||||
case keepDirs settings of
|
||||
Never -> runLogger $ logError $ T.pack $ prettyShow err
|
||||
_ -> runLogger (logError $ T.pack (prettyShow err) <> "\n" <>
|
||||
"Check the logs at " <> T.pack (fromGHCupPath logsDir) <> " and the build directory "
|
||||
<> T.pack tmpdir <> " for more clues." <> "\n" <>
|
||||
"Make sure to clean up " <> T.pack tmpdir <> " afterwards.")
|
||||
pure $ ExitFailure 9
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 9
|
||||
(CompileGHC GHCCompileOptions { hadrian = True, crossTarget = Just _ }) -> do
|
||||
runLogger $ logError "Hadrian cross compile support is not yet implemented!"
|
||||
pure $ ExitFailure 9
|
||||
(CompileGHC GHCCompileOptions {..}) ->
|
||||
runCompileGHC runAppState (do
|
||||
case targetGhc of
|
||||
Left targetVer -> do
|
||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||
let vi = getVersionInfo targetVer GHC dls
|
||||
forM_ (_viPreCompile =<< vi) $ \msg -> do
|
||||
lift $ logInfo msg
|
||||
lift $ logInfo
|
||||
"...waiting for 5 seconds, you can still abort..."
|
||||
liftIO $ threadDelay 5000000 -- for compilation, give the user a sec to intervene
|
||||
Right _ -> pure ()
|
||||
targetVer <- liftE $ compileGHC
|
||||
(first (GHCTargetVersion crossTarget) targetGhc)
|
||||
ovewrwiteVer
|
||||
bootstrapGhc
|
||||
jobs
|
||||
buildConfig
|
||||
patches
|
||||
addConfArgs
|
||||
buildFlavour
|
||||
hadrian
|
||||
(maybe GHCupInternal IsolateDir isolateDir)
|
||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||
let vi = getVersionInfo (_tvVersion targetVer) GHC dls
|
||||
when setCompile $ void $ liftE $
|
||||
setGHC targetVer SetGHCOnly Nothing
|
||||
pure (vi, targetVer)
|
||||
)
|
||||
>>= \case
|
||||
VRight (vi, tv) -> do
|
||||
runLogger $ logInfo
|
||||
"GHC successfully compiled and installed"
|
||||
forM_ (_viPostInstall =<< vi) $ \msg ->
|
||||
runLogger $ logInfo msg
|
||||
liftIO $ putStr (T.unpack $ tVerToText tv)
|
||||
pure ExitSuccess
|
||||
VLeft (V (AlreadyInstalled _ v)) -> do
|
||||
runLogger $ logWarn $
|
||||
"GHC ver " <> prettyVer v <> " already installed, remove it first to reinstall"
|
||||
pure ExitSuccess
|
||||
VLeft (V (DirNotEmpty fp)) -> do
|
||||
runLogger $ logError $
|
||||
"Install directory " <> T.pack fp <> " is not empty."
|
||||
pure $ ExitFailure 3
|
||||
VLeft err@(V (BuildFailed tmpdir _)) -> do
|
||||
case keepDirs settings of
|
||||
Never -> runLogger $ logError $ T.pack $ prettyShow err
|
||||
_ -> runLogger (logError $ T.pack (prettyShow err) <> "\n" <>
|
||||
"Check the logs at " <> T.pack (fromGHCupPath logsDir) <> " and the build directory "
|
||||
<> T.pack tmpdir <> " for more clues." <> "\n" <>
|
||||
"Make sure to clean up " <> T.pack tmpdir <> " afterwards.")
|
||||
pure $ ExitFailure 9
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 9
|
||||
203
app/ghcup/GHCup/OptParse/Config.hs
Normal file
@@ -0,0 +1,203 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE DuplicateRecordFields #-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
|
||||
module GHCup.OptParse.Config where
|
||||
|
||||
|
||||
import GHCup.Errors
|
||||
import GHCup.Types
|
||||
import GHCup.Utils
|
||||
import GHCup.Prelude
|
||||
import GHCup.Prelude.Logger
|
||||
import GHCup.Prelude.String.QQ
|
||||
import GHCup.OptParse.Common
|
||||
|
||||
#if !MIN_VERSION_base(4,13,0)
|
||||
import Control.Monad.Fail ( MonadFail )
|
||||
#endif
|
||||
import Control.Exception ( displayException )
|
||||
import Control.Monad.Reader
|
||||
import Control.Monad.Trans.Resource
|
||||
import Data.Functor
|
||||
import Data.Maybe
|
||||
import Haskus.Utils.Variant.Excepts
|
||||
import Options.Applicative hiding ( style, ParseError )
|
||||
import Options.Applicative.Help.Pretty ( text )
|
||||
import Prelude hiding ( appendFile )
|
||||
import System.Exit
|
||||
import URI.ByteString hiding ( uriParser )
|
||||
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.ByteString.UTF8 as UTF8
|
||||
import qualified Data.Yaml.Aeson as Y
|
||||
import Control.Exception.Safe (MonadMask)
|
||||
|
||||
|
||||
|
||||
|
||||
----------------
|
||||
--[ Commands ]--
|
||||
----------------
|
||||
|
||||
|
||||
data ConfigCommand
|
||||
= ShowConfig
|
||||
| SetConfig String (Maybe String)
|
||||
| InitConfig
|
||||
| AddReleaseChannel URI
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Parsers ]--
|
||||
---------------
|
||||
|
||||
|
||||
configP :: Parser ConfigCommand
|
||||
configP = subparser
|
||||
( command "init" initP
|
||||
<> command "set" setP -- [set] KEY VALUE at help lhs
|
||||
<> command "show" showP
|
||||
<> command "add-release-channel" addP
|
||||
)
|
||||
<|> argsP -- add show for a single option
|
||||
<|> pure ShowConfig
|
||||
where
|
||||
initP = info (pure InitConfig) (progDesc "Write default config to ~/.ghcup/config.yaml")
|
||||
showP = info (pure ShowConfig) (progDesc "Show current config (default)")
|
||||
setP = info argsP (progDesc "Set config KEY to VALUE (or specify as single json value)" <> footerDoc (Just $ text configSetFooter))
|
||||
argsP = SetConfig <$> argument str (metavar "<JSON_VALUE | YAML_KEY>") <*> optional (argument str (metavar "YAML_VALUE"))
|
||||
addP = info (AddReleaseChannel <$> argument (eitherReader uriParser) (metavar "URI" <> completer fileUri))
|
||||
(progDesc "Add a release channel from a URI")
|
||||
|
||||
|
||||
|
||||
|
||||
--------------
|
||||
--[ Footer ]--
|
||||
--------------
|
||||
|
||||
|
||||
configFooter :: String
|
||||
configFooter = [s|Examples:
|
||||
|
||||
# show current config
|
||||
ghcup config
|
||||
|
||||
# initialize config
|
||||
ghcup config init
|
||||
|
||||
# set <key> <value> configuration pair
|
||||
ghcup config set <key> <value>|]
|
||||
|
||||
|
||||
configSetFooter :: String
|
||||
configSetFooter = [s|Examples:
|
||||
# disable caching
|
||||
ghcup config set cache false
|
||||
|
||||
# switch downloader to wget
|
||||
ghcup config set downloader Wget
|
||||
|
||||
# set mirror for ghcup metadata
|
||||
ghcup config set '{url-source: { OwnSource: "<url>"}}'|]
|
||||
|
||||
|
||||
|
||||
-----------------
|
||||
--[ Utilities ]--
|
||||
-----------------
|
||||
|
||||
|
||||
formatConfig :: UserSettings -> String
|
||||
formatConfig = UTF8.toString . Y.encode
|
||||
|
||||
|
||||
updateSettings :: UserSettings -> Settings -> Settings
|
||||
updateSettings UserSettings{..} Settings{..} =
|
||||
let cache' = fromMaybe cache uCache
|
||||
metaCache' = fromMaybe metaCache uMetaCache
|
||||
noVerify' = fromMaybe noVerify uNoVerify
|
||||
keepDirs' = fromMaybe keepDirs uKeepDirs
|
||||
downloader' = fromMaybe downloader uDownloader
|
||||
verbose' = fromMaybe verbose uVerbose
|
||||
urlSource' = fromMaybe urlSource uUrlSource
|
||||
noNetwork' = fromMaybe noNetwork uNoNetwork
|
||||
gpgSetting' = fromMaybe gpgSetting uGPGSetting
|
||||
in Settings cache' metaCache' noVerify' keepDirs' downloader' verbose' urlSource' noNetwork' gpgSetting' noColor
|
||||
|
||||
|
||||
|
||||
------------------
|
||||
--[ Entrypoint ]--
|
||||
------------------
|
||||
|
||||
|
||||
|
||||
config :: forall m. ( Monad m
|
||||
, MonadMask m
|
||||
, MonadUnliftIO m
|
||||
, MonadFail m
|
||||
)
|
||||
=> ConfigCommand
|
||||
-> Settings
|
||||
-> KeyBindings
|
||||
-> (ReaderT LeanAppState m () -> m ())
|
||||
-> m ExitCode
|
||||
config configCommand settings keybindings runLogger = case configCommand of
|
||||
InitConfig -> do
|
||||
path <- getConfigFilePath
|
||||
liftIO $ writeFile path $ formatConfig $ fromSettings settings (Just keybindings)
|
||||
runLogger $ logDebug $ "config.yaml initialized at " <> T.pack path
|
||||
pure ExitSuccess
|
||||
|
||||
ShowConfig -> do
|
||||
liftIO $ putStrLn $ formatConfig $ fromSettings settings (Just keybindings)
|
||||
pure ExitSuccess
|
||||
|
||||
(SetConfig k mv) -> do
|
||||
r <- runE @'[JSONError, ParseError] $ do
|
||||
case mv of
|
||||
Just "" ->
|
||||
throwE $ ParseError "Empty values are not allowed"
|
||||
Nothing -> do
|
||||
usersettings <- decodeSettings k
|
||||
lift $ doConfig usersettings
|
||||
pure ()
|
||||
Just v -> do
|
||||
usersettings <- decodeSettings (k <> ": " <> v <> "\n")
|
||||
lift $ doConfig usersettings
|
||||
pure ()
|
||||
case r of
|
||||
VRight _ -> pure ExitSuccess
|
||||
VLeft (V (JSONDecodeError e)) -> do
|
||||
runLogger $ logError $ "Error decoding config: " <> T.pack e
|
||||
pure $ ExitFailure 65
|
||||
VLeft _ -> pure $ ExitFailure 65
|
||||
|
||||
AddReleaseChannel uri -> do
|
||||
case urlSource settings of
|
||||
AddSource xs -> do
|
||||
doConfig (defaultUserSettings { uUrlSource = Just $ AddSource (xs <> [Right uri]) })
|
||||
pure ExitSuccess
|
||||
_ -> do
|
||||
doConfig (defaultUserSettings { uUrlSource = Just $ AddSource [Right uri] })
|
||||
pure ExitSuccess
|
||||
|
||||
where
|
||||
doConfig :: MonadIO m => UserSettings -> m ()
|
||||
doConfig usersettings = do
|
||||
let settings' = updateSettings usersettings settings
|
||||
path <- liftIO getConfigFilePath
|
||||
liftIO $ writeFile path $ formatConfig $ fromSettings settings' (Just keybindings)
|
||||
runLogger $ logDebug $ T.pack $ show settings'
|
||||
pure ()
|
||||
|
||||
decodeSettings = lE' (JSONDecodeError . displayException) . Y.decodeEither' . UTF8.fromString
|
||||
119
app/ghcup/GHCup/OptParse/DInfo.hs
Normal file
@@ -0,0 +1,119 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
{-# LANGUAGE DuplicateRecordFields #-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
|
||||
module GHCup.OptParse.DInfo where
|
||||
|
||||
|
||||
|
||||
|
||||
import GHCup
|
||||
import GHCup.Errors
|
||||
import GHCup.Version
|
||||
import GHCup.Types
|
||||
import GHCup.Utils.Dirs
|
||||
import GHCup.Prelude
|
||||
import GHCup.Prelude.Logger
|
||||
import GHCup.Prelude.Process
|
||||
|
||||
#if !MIN_VERSION_base(4,13,0)
|
||||
import Control.Monad.Fail ( MonadFail )
|
||||
#endif
|
||||
import Control.Monad.Reader
|
||||
import Control.Monad.Trans.Resource
|
||||
import Data.Functor
|
||||
import Data.Maybe
|
||||
import Haskus.Utils.Variant.Excepts
|
||||
import Options.Applicative hiding ( style )
|
||||
import Prelude hiding ( appendFile )
|
||||
import System.Exit
|
||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
||||
|
||||
import qualified Data.Text as T
|
||||
import Control.Exception.Safe (MonadMask)
|
||||
import Language.Haskell.TH
|
||||
|
||||
|
||||
|
||||
-----------------
|
||||
--[ Utilities ]--
|
||||
-----------------
|
||||
|
||||
|
||||
describe_result :: String
|
||||
describe_result = $( LitE . StringL <$>
|
||||
runIO (do
|
||||
CapturedProcess{..} <- do
|
||||
dirs <- liftIO getAllDirs
|
||||
let settings = AppState (defaultSettings { noNetwork = True })
|
||||
dirs
|
||||
defaultKeyBindings
|
||||
flip runReaderT settings $ executeOut "git" ["describe"] Nothing
|
||||
case _exitCode of
|
||||
ExitSuccess -> pure . T.unpack . decUTF8Safe' $ _stdOut
|
||||
ExitFailure _ -> pure numericVer
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
prettyDebugInfo :: DebugInfo -> String
|
||||
prettyDebugInfo DebugInfo {..} = "Debug Info" <> "\n" <>
|
||||
"==========" <> "\n" <>
|
||||
"GHCup base dir: " <> diBaseDir <> "\n" <>
|
||||
"GHCup bin dir: " <> diBinDir <> "\n" <>
|
||||
"GHCup GHC directory: " <> diGHCDir <> "\n" <>
|
||||
"GHCup cache directory: " <> diCacheDir <> "\n" <>
|
||||
"Architecture: " <> prettyShow diArch <> "\n" <>
|
||||
"Platform: " <> prettyShow diPlatform <> "\n" <>
|
||||
"Version: " <> describe_result
|
||||
|
||||
|
||||
|
||||
---------------------------
|
||||
--[ Effect interpreters ]--
|
||||
---------------------------
|
||||
|
||||
|
||||
type DInfoEffects = '[ NoCompatiblePlatform , NoCompatibleArch , DistroNotFound ]
|
||||
|
||||
runDebugInfo :: (ReaderT env m (VEither DInfoEffects a) -> m (VEither DInfoEffects a))
|
||||
-> Excepts DInfoEffects (ReaderT env m) a
|
||||
-> m (VEither DInfoEffects a)
|
||||
runDebugInfo runAppState =
|
||||
runAppState
|
||||
. runE
|
||||
@DInfoEffects
|
||||
|
||||
|
||||
|
||||
------------------
|
||||
--[ Entrypoint ]--
|
||||
------------------
|
||||
|
||||
|
||||
|
||||
dinfo :: ( Monad m
|
||||
, MonadMask m
|
||||
, MonadUnliftIO m
|
||||
, MonadFail m
|
||||
, Alternative m
|
||||
)
|
||||
=> (ReaderT AppState m (VEither DInfoEffects DebugInfo)
|
||||
-> m (VEither DInfoEffects DebugInfo))
|
||||
-> (ReaderT LeanAppState m () -> m ())
|
||||
-> m ExitCode
|
||||
dinfo runAppState runLogger = do
|
||||
runDebugInfo runAppState (liftE getDebugInfo)
|
||||
>>= \case
|
||||
VRight di -> do
|
||||
liftIO $ putStrLn $ prettyDebugInfo di
|
||||
pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 8
|
||||
143
app/ghcup/GHCup/OptParse/GC.hs
Normal file
@@ -0,0 +1,143 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
{-# LANGUAGE DuplicateRecordFields #-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
|
||||
module GHCup.OptParse.GC where
|
||||
|
||||
|
||||
import GHCup
|
||||
import GHCup.Errors
|
||||
import GHCup.Types
|
||||
import GHCup.Prelude.Logger
|
||||
import GHCup.Prelude.String.QQ
|
||||
|
||||
#if !MIN_VERSION_base(4,13,0)
|
||||
import Control.Monad.Fail ( MonadFail )
|
||||
#endif
|
||||
import Control.Monad.Reader
|
||||
import Control.Monad.Trans.Resource
|
||||
import Data.Functor
|
||||
import Haskus.Utils.Variant.Excepts
|
||||
import Options.Applicative hiding ( style )
|
||||
import Prelude hiding ( appendFile )
|
||||
import System.Exit
|
||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
||||
|
||||
import qualified Data.Text as T
|
||||
import Control.Exception.Safe (MonadMask)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Options ]--
|
||||
---------------
|
||||
|
||||
|
||||
data GCOptions = GCOptions
|
||||
{ gcOldGHC :: Bool
|
||||
, gcProfilingLibs :: Bool
|
||||
, gcShareDir :: Bool
|
||||
, gcHLSNoGHC :: Bool
|
||||
, gcCache :: Bool
|
||||
, gcTmp :: Bool
|
||||
}
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Parsers ]--
|
||||
---------------
|
||||
|
||||
|
||||
gcP :: Parser GCOptions
|
||||
gcP =
|
||||
GCOptions
|
||||
<$>
|
||||
switch
|
||||
(short 'o' <> long "ghc-old" <> help "Remove GHC versions marked as 'old'")
|
||||
<*>
|
||||
switch
|
||||
(short 'p' <> long "profiling-libs" <> help "Remove profiling libs of GHC versions")
|
||||
<*>
|
||||
switch
|
||||
(short 's' <> long "share-dir" <> help "Remove GHC share directories (documentation)")
|
||||
<*>
|
||||
switch
|
||||
(short 'h' <> long "hls-no-ghc" <> help "Remove HLS versions that don't have a corresponding installed GHC version")
|
||||
<*>
|
||||
switch
|
||||
(short 'c' <> long "cache" <> help "GC the GHCup cache")
|
||||
<*>
|
||||
switch
|
||||
(short 't' <> long "tmpdirs" <> help "Remove tmpdir leftovers")
|
||||
|
||||
|
||||
|
||||
--------------
|
||||
--[ Footer ]--
|
||||
--------------
|
||||
|
||||
|
||||
gcFooter :: String
|
||||
gcFooter = [s|Discussion:
|
||||
Performs garbage collection. If no switches are specified, does nothing.|]
|
||||
|
||||
|
||||
|
||||
|
||||
---------------------------
|
||||
--[ Effect interpreters ]--
|
||||
---------------------------
|
||||
|
||||
|
||||
type GCEffects = '[ NotInstalled, UninstallFailed ]
|
||||
|
||||
|
||||
runGC :: MonadUnliftIO m
|
||||
=> (ReaderT AppState m (VEither GCEffects a) -> m (VEither GCEffects a))
|
||||
-> Excepts GCEffects (ResourceT (ReaderT AppState m)) a
|
||||
-> m (VEither GCEffects a)
|
||||
runGC runAppState =
|
||||
runAppState
|
||||
. runResourceT
|
||||
. runE
|
||||
@GCEffects
|
||||
|
||||
|
||||
|
||||
------------------
|
||||
--[ Entrypoint ]--
|
||||
------------------
|
||||
|
||||
|
||||
|
||||
gc :: ( Monad m
|
||||
, MonadMask m
|
||||
, MonadUnliftIO m
|
||||
, MonadFail m
|
||||
)
|
||||
=> GCOptions
|
||||
-> (forall a. ReaderT AppState m (VEither GCEffects a) -> m (VEither GCEffects a))
|
||||
-> (ReaderT LeanAppState m () -> m ())
|
||||
-> m ExitCode
|
||||
gc GCOptions{..} runAppState runLogger = runGC runAppState (do
|
||||
when gcOldGHC (liftE rmOldGHC)
|
||||
lift $ when gcProfilingLibs rmProfilingLibs
|
||||
lift $ when gcShareDir rmShareDir
|
||||
liftE $ when gcHLSNoGHC rmHLSNoGHC
|
||||
lift $ when gcCache rmCache
|
||||
lift $ when gcTmp rmTmp
|
||||
) >>= \case
|
||||
VRight _ -> do
|
||||
pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 27
|
||||
549
app/ghcup/GHCup/OptParse/Install.hs
Normal file
@@ -0,0 +1,549 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE DuplicateRecordFields #-}
|
||||
{-# LANGUAGE ViewPatterns #-}
|
||||
{-# LANGUAGE TypeOperators #-}
|
||||
|
||||
module GHCup.OptParse.Install where
|
||||
|
||||
|
||||
|
||||
|
||||
import GHCup.OptParse.Common
|
||||
|
||||
import GHCup
|
||||
import GHCup.Errors
|
||||
import GHCup.Types
|
||||
import GHCup.Utils.Dirs
|
||||
import GHCup.Prelude
|
||||
import GHCup.Prelude.Logger
|
||||
import GHCup.Prelude.String.QQ
|
||||
|
||||
import Codec.Archive
|
||||
#if !MIN_VERSION_base(4,13,0)
|
||||
import Control.Monad.Fail ( MonadFail )
|
||||
#endif
|
||||
import Control.Monad.Reader
|
||||
import Control.Monad.Trans.Resource
|
||||
import Data.Either
|
||||
import Data.Functor
|
||||
import Data.Maybe
|
||||
import Haskus.Utils.Variant.Excepts
|
||||
import Options.Applicative hiding ( style )
|
||||
import Options.Applicative.Help.Pretty ( text )
|
||||
import Prelude hiding ( appendFile )
|
||||
import System.Exit
|
||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
||||
import URI.ByteString hiding ( uriParser )
|
||||
|
||||
import qualified Data.Text as T
|
||||
|
||||
|
||||
|
||||
|
||||
----------------
|
||||
--[ Commands ]--
|
||||
----------------
|
||||
|
||||
|
||||
data InstallCommand = InstallGHC InstallOptions
|
||||
| InstallCabal InstallOptions
|
||||
| InstallHLS InstallOptions
|
||||
| InstallStack InstallOptions
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Options ]--
|
||||
---------------
|
||||
|
||||
|
||||
data InstallOptions = InstallOptions
|
||||
{ instVer :: Maybe ToolVersion
|
||||
, instPlatform :: Maybe PlatformRequest
|
||||
, instBindist :: Maybe URI
|
||||
, instSet :: Bool
|
||||
, isolateDir :: Maybe FilePath
|
||||
, forceInstall :: Bool
|
||||
, addConfArgs :: [T.Text]
|
||||
}
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Footers ]--
|
||||
---------------
|
||||
|
||||
installCabalFooter :: String
|
||||
installCabalFooter = [s|Discussion:
|
||||
Installs the specified cabal-install version (or a recommended default one)
|
||||
into "~/.ghcup/bin", so it can be overwritten by later
|
||||
"cabal install cabal-install", which installs into "~/.cabal/bin" by
|
||||
default. Make sure to set up your PATH appropriately, so the cabal
|
||||
installation takes precedence.|]
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Parsers ]--
|
||||
---------------
|
||||
|
||||
installParser :: Parser (Either InstallCommand InstallOptions)
|
||||
installParser =
|
||||
(Left <$> subparser
|
||||
( command
|
||||
"ghc"
|
||||
( InstallGHC
|
||||
<$> info
|
||||
(installOpts (Just GHC) <**> helper)
|
||||
( progDesc "Install GHC"
|
||||
<> footerDoc (Just $ text installGHCFooter)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"cabal"
|
||||
( InstallCabal
|
||||
<$> info
|
||||
(installOpts (Just Cabal) <**> helper)
|
||||
( progDesc "Install Cabal"
|
||||
<> footerDoc (Just $ text installCabalFooter)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"hls"
|
||||
( InstallHLS
|
||||
<$> info
|
||||
(installOpts (Just HLS) <**> helper)
|
||||
( progDesc "Install haskell-language-server"
|
||||
<> footerDoc (Just $ text installHLSFooter)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"stack"
|
||||
( InstallStack
|
||||
<$> info
|
||||
(installOpts (Just Stack) <**> helper)
|
||||
( progDesc "Install stack"
|
||||
<> footerDoc (Just $ text installStackFooter)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
<|> (Right <$> installOpts Nothing)
|
||||
where
|
||||
installHLSFooter :: String
|
||||
installHLSFooter = [s|Discussion:
|
||||
Installs haskell-language-server binaries and wrapper
|
||||
into "~/.ghcup/bin"
|
||||
|
||||
Examples:
|
||||
# install recommended HLS
|
||||
ghcup install hls|]
|
||||
|
||||
installStackFooter :: String
|
||||
installStackFooter = [s|Discussion:
|
||||
Installs stack binaries into "~/.ghcup/bin"
|
||||
|
||||
Examples:
|
||||
# install recommended Stack
|
||||
ghcup install stack|]
|
||||
|
||||
installGHCFooter :: String
|
||||
installGHCFooter = [s|Discussion:
|
||||
Installs the specified GHC version (or a recommended default one) into
|
||||
a self-contained "~/.ghcup/ghc/<ghcver>" directory
|
||||
and symlinks the ghc binaries to "~/.ghcup/bin/<binary>-<ghcver>".
|
||||
|
||||
Examples:
|
||||
# install recommended GHC
|
||||
ghcup install ghc
|
||||
|
||||
# install latest GHC
|
||||
ghcup install ghc latest
|
||||
|
||||
# install GHC 8.10.2
|
||||
ghcup install ghc 8.10.2
|
||||
|
||||
# install GHC head fedora bindist
|
||||
ghcup install ghc -u https://gitlab.haskell.org/api/v4/projects/1/jobs/artifacts/master/raw/ghc-x86_64-fedora27-linux.tar.xz?job=validate-x86_64-linux-fedora27 head|]
|
||||
|
||||
|
||||
installOpts :: Maybe Tool -> Parser InstallOptions
|
||||
installOpts tool =
|
||||
(\p (u, v) b is f -> InstallOptions v p u b is f)
|
||||
<$> optional
|
||||
(option
|
||||
(eitherReader platformParser)
|
||||
( short 'p'
|
||||
<> long "platform"
|
||||
<> metavar "PLATFORM"
|
||||
<> help
|
||||
"Override for platform (triple matching ghc tarball names), e.g. x86_64-fedora27-linux"
|
||||
)
|
||||
)
|
||||
<*> ( ( (,)
|
||||
<$> optional
|
||||
(option
|
||||
(eitherReader uriParser)
|
||||
(short 'u' <> long "url" <> metavar "BINDIST_URL" <> help
|
||||
"Install the specified version from this bindist"
|
||||
<> completer (toolDlCompleter (fromMaybe GHC tool))
|
||||
)
|
||||
)
|
||||
<*> (Just <$> toolVersionTagArgument Nothing tool)
|
||||
)
|
||||
<|> pure (Nothing, Nothing)
|
||||
)
|
||||
<*> fmap (fromMaybe setDefault) (invertableSwitch "set" Nothing setDefault
|
||||
(help $ if not setDefault then "Set as active version after install" else "Don't set as active version after install"))
|
||||
<*> optional
|
||||
(option
|
||||
(eitherReader isolateParser)
|
||||
( short 'i'
|
||||
<> long "isolate"
|
||||
<> metavar "DIR"
|
||||
<> help "install in an isolated dir instead of the default one"
|
||||
<> completer (bashCompleter "directory")
|
||||
)
|
||||
)
|
||||
<*> switch
|
||||
(short 'f' <> long "force" <> help "Force install (THIS IS UNSAFE, only use it in Dockerfiles or CI)")
|
||||
<*> many (argument str (metavar "CONFIGURE_ARGS" <> help "Additional arguments to bindist configure, prefix with '-- ' (longopts)"))
|
||||
where
|
||||
setDefault = case tool of
|
||||
Nothing -> False
|
||||
Just GHC -> False
|
||||
Just _ -> True
|
||||
|
||||
|
||||
|
||||
|
||||
--------------
|
||||
--[ Footer ]--
|
||||
--------------
|
||||
|
||||
|
||||
installToolFooter :: String
|
||||
installToolFooter = [s|Discussion:
|
||||
Installs GHC or cabal. When no command is given, installs GHC
|
||||
with the specified version/tag.
|
||||
It is recommended to always specify a subcommand (ghc/cabal/hls/stack).|]
|
||||
|
||||
|
||||
|
||||
|
||||
---------------------------
|
||||
--[ Effect interpreters ]--
|
||||
---------------------------
|
||||
|
||||
type InstallEffects = '[ AlreadyInstalled
|
||||
, UnknownArchive
|
||||
, ArchiveResult
|
||||
, FileDoesNotExistError
|
||||
, CopyError
|
||||
, NotInstalled
|
||||
, DirNotEmpty
|
||||
, NoDownload
|
||||
, NotInstalled
|
||||
, BuildFailed
|
||||
, TagNotFound
|
||||
, DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, TarDirDoesNotExist
|
||||
, NextVerNotFound
|
||||
, NoToolVersionSet
|
||||
, FileAlreadyExistsError
|
||||
, ProcessError
|
||||
, UninstallFailed
|
||||
, MergeFileTreeError
|
||||
, InstallSetError
|
||||
]
|
||||
|
||||
|
||||
runInstTool :: AppState
|
||||
-> Maybe PlatformRequest
|
||||
-> Excepts InstallEffects (ResourceT (ReaderT AppState IO)) a
|
||||
-> IO (VEither InstallEffects a)
|
||||
runInstTool appstate' mInstPlatform =
|
||||
flip runReaderT (maybe appstate' (\x -> appstate'{ pfreq = x } :: AppState) mInstPlatform)
|
||||
. runResourceT
|
||||
. runE
|
||||
@InstallEffects
|
||||
|
||||
|
||||
type InstallGHCEffects = '[ AlreadyInstalled
|
||||
, ArchiveResult
|
||||
, BuildFailed
|
||||
, CopyError
|
||||
, DigestError
|
||||
, DirNotEmpty
|
||||
, DownloadFailed
|
||||
, FileAlreadyExistsError
|
||||
, FileDoesNotExistError
|
||||
, GPGError
|
||||
, MergeFileTreeError
|
||||
, NextVerNotFound
|
||||
, NoDownload
|
||||
, NoToolVersionSet
|
||||
, NotInstalled
|
||||
, ProcessError
|
||||
, TagNotFound
|
||||
, TarDirDoesNotExist
|
||||
, UninstallFailed
|
||||
, UnknownArchive
|
||||
, InstallSetError
|
||||
]
|
||||
|
||||
runInstGHC :: AppState
|
||||
-> Maybe PlatformRequest
|
||||
-> Excepts InstallGHCEffects (ResourceT (ReaderT AppState IO)) a
|
||||
-> IO (VEither InstallGHCEffects a)
|
||||
runInstGHC appstate' mInstPlatform =
|
||||
flip runReaderT (maybe appstate' (\x -> appstate'{ pfreq = x } :: AppState) mInstPlatform)
|
||||
. runResourceT
|
||||
. runE
|
||||
@InstallGHCEffects
|
||||
|
||||
|
||||
-------------------
|
||||
--[ Entrypoints ]--
|
||||
-------------------
|
||||
|
||||
|
||||
install :: Either InstallCommand InstallOptions -> Settings -> IO AppState -> (ReaderT LeanAppState IO () -> IO ()) -> IO ExitCode
|
||||
install installCommand settings getAppState' runLogger = case installCommand of
|
||||
(Right iopts) -> do
|
||||
runLogger (logWarn "This is an old-style command for installing GHC. Use 'ghcup install ghc' instead.")
|
||||
installGHC iopts
|
||||
(Left (InstallGHC iopts)) -> installGHC iopts
|
||||
(Left (InstallCabal iopts)) -> installCabal iopts
|
||||
(Left (InstallHLS iopts)) -> installHLS iopts
|
||||
(Left (InstallStack iopts)) -> installStack iopts
|
||||
where
|
||||
installGHC :: InstallOptions -> IO ExitCode
|
||||
installGHC InstallOptions{..} = do
|
||||
s'@AppState{ dirs = Dirs{ .. } } <- liftIO getAppState'
|
||||
(case instBindist of
|
||||
Nothing -> runInstGHC s' instPlatform $ do
|
||||
(v, vi) <- liftE $ fromVersion instVer GHC
|
||||
liftE $ runBothE' (installGHCBin
|
||||
(_tvVersion v)
|
||||
(maybe GHCupInternal IsolateDir isolateDir)
|
||||
forceInstall
|
||||
addConfArgs
|
||||
)
|
||||
$ when instSet $ when (isNothing isolateDir) $ liftE $ void $ setGHC v SetGHCOnly Nothing
|
||||
pure vi
|
||||
Just uri -> do
|
||||
runInstGHC s'{ settings = settings {noVerify = True}} instPlatform $ do
|
||||
(v, vi) <- liftE $ fromVersion instVer GHC
|
||||
liftE $ runBothE' (installGHCBindist
|
||||
(DownloadInfo uri (Just $ RegexDir "ghc-.*") "")
|
||||
(_tvVersion v)
|
||||
(maybe GHCupInternal IsolateDir isolateDir)
|
||||
forceInstall
|
||||
addConfArgs
|
||||
)
|
||||
$ when instSet $ when (isNothing isolateDir) $ liftE $ void $ setGHC v SetGHCOnly Nothing
|
||||
pure vi
|
||||
)
|
||||
>>= \case
|
||||
VRight vi -> do
|
||||
runLogger $ logInfo "GHC installation successful"
|
||||
forM_ (_viPostInstall =<< vi) $ \msg ->
|
||||
runLogger $ logInfo msg
|
||||
pure ExitSuccess
|
||||
|
||||
VLeft e@(V (AlreadyInstalled _ _)) -> do
|
||||
runLogger $ logWarn $ T.pack $ prettyShow e
|
||||
pure ExitSuccess
|
||||
VLeft e@(V (AlreadyInstalled _ _)) -> do
|
||||
runLogger $ logWarn $ T.pack $ prettyShow e
|
||||
pure ExitSuccess
|
||||
|
||||
VLeft (V (DirNotEmpty fp)) -> do
|
||||
runLogger $ logError $
|
||||
"Install directory " <> T.pack fp <> " is not empty."
|
||||
pure $ ExitFailure 3
|
||||
VLeft (V (DirNotEmpty fp)) -> do
|
||||
runLogger $ logError $
|
||||
"Install directory " <> T.pack fp <> " is not empty."
|
||||
pure $ ExitFailure 3
|
||||
|
||||
VLeft err@(V (BuildFailed tmpdir _)) -> do
|
||||
case keepDirs settings of
|
||||
Never -> runLogger (logError $ T.pack $ prettyShow err)
|
||||
_ -> runLogger (logError $ T.pack (prettyShow err) <> "\n" <>
|
||||
"Check the logs at " <> T.pack (fromGHCupPath logsDir) <> " and the build directory " <> T.pack tmpdir <> " for more clues." <> "\n" <>
|
||||
"Make sure to clean up " <> T.pack tmpdir <> " afterwards.")
|
||||
pure $ ExitFailure 3
|
||||
VLeft err@(V (BuildFailed tmpdir _)) -> do
|
||||
case keepDirs settings of
|
||||
Never -> runLogger (logError $ T.pack $ prettyShow err)
|
||||
_ -> runLogger (logError $ T.pack (prettyShow err) <> "\n" <>
|
||||
"Check the logs at " <> T.pack (fromGHCupPath logsDir) <> " and the build directory " <> T.pack tmpdir <> " for more clues." <> "\n" <>
|
||||
"Make sure to clean up " <> T.pack tmpdir <> " afterwards.")
|
||||
pure $ ExitFailure 3
|
||||
|
||||
VLeft e -> do
|
||||
runLogger $ do
|
||||
logError $ T.pack $ prettyShow e
|
||||
logError $ "Also check the logs in " <> T.pack (fromGHCupPath logsDir)
|
||||
pure $ ExitFailure 3
|
||||
|
||||
|
||||
installCabal :: InstallOptions -> IO ExitCode
|
||||
installCabal InstallOptions{..} = do
|
||||
s'@AppState{ dirs = Dirs{ .. } } <- liftIO getAppState'
|
||||
(case instBindist of
|
||||
Nothing -> runInstTool s' instPlatform $ do
|
||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Cabal
|
||||
liftE $ runBothE' (installCabalBin
|
||||
v
|
||||
(maybe GHCupInternal IsolateDir isolateDir)
|
||||
forceInstall
|
||||
) $ when instSet $ when (isNothing isolateDir) $ liftE $ setCabal v
|
||||
pure vi
|
||||
Just uri -> do
|
||||
runInstTool s'{ settings = settings { noVerify = True}} instPlatform $ do
|
||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Cabal
|
||||
liftE $ runBothE' (installCabalBindist
|
||||
(DownloadInfo uri Nothing "")
|
||||
v
|
||||
(maybe GHCupInternal IsolateDir isolateDir)
|
||||
forceInstall
|
||||
) $ when instSet $ when (isNothing isolateDir) $ liftE $ setCabal v
|
||||
pure vi
|
||||
)
|
||||
>>= \case
|
||||
VRight vi -> do
|
||||
runLogger $ logInfo "Cabal installation successful"
|
||||
forM_ (_viPostInstall =<< vi) $ \msg ->
|
||||
runLogger $ logInfo msg
|
||||
pure ExitSuccess
|
||||
VLeft e@(V (AlreadyInstalled _ _)) -> do
|
||||
runLogger $ logWarn $ T.pack $ prettyShow e
|
||||
pure ExitSuccess
|
||||
VLeft (V (FileAlreadyExistsError fp)) -> do
|
||||
runLogger $ logWarn $
|
||||
"File " <> T.pack fp <> " already exists. Use 'ghcup install cabal --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
||||
pure $ ExitFailure 3
|
||||
VLeft e@(V (AlreadyInstalled _ _)) -> do
|
||||
runLogger $ logWarn $ T.pack $ prettyShow e
|
||||
pure ExitSuccess
|
||||
VLeft (V (FileAlreadyExistsError fp)) -> do
|
||||
runLogger $ logWarn $
|
||||
"File " <> T.pack fp <> " already exists. Use 'ghcup install cabal --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
||||
pure $ ExitFailure 3
|
||||
VLeft e -> do
|
||||
runLogger $ do
|
||||
logError $ T.pack $ prettyShow e
|
||||
logError $ "Also check the logs in " <> T.pack (fromGHCupPath logsDir)
|
||||
pure $ ExitFailure 4
|
||||
|
||||
installHLS :: InstallOptions -> IO ExitCode
|
||||
installHLS InstallOptions{..} = do
|
||||
s'@AppState{ dirs = Dirs{ .. } } <- liftIO getAppState'
|
||||
(case instBindist of
|
||||
Nothing -> runInstTool s' instPlatform $ do
|
||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer HLS
|
||||
liftE $ runBothE' (installHLSBin
|
||||
v
|
||||
(maybe GHCupInternal IsolateDir isolateDir)
|
||||
forceInstall
|
||||
) $ when instSet $ when (isNothing isolateDir) $ liftE $ setHLS v SetHLSOnly Nothing
|
||||
pure vi
|
||||
Just uri -> do
|
||||
runInstTool s'{ settings = settings { noVerify = True}} instPlatform $ do
|
||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer HLS
|
||||
-- TODO: support legacy
|
||||
liftE $ runBothE' (installHLSBindist
|
||||
(DownloadInfo uri (Just $ RegexDir "haskell-language-server-*") "")
|
||||
v
|
||||
(maybe GHCupInternal IsolateDir isolateDir)
|
||||
forceInstall
|
||||
) $ when instSet $ when (isNothing isolateDir) $ liftE $ setHLS v SetHLSOnly Nothing
|
||||
pure vi
|
||||
)
|
||||
>>= \case
|
||||
VRight vi -> do
|
||||
runLogger $ logInfo "HLS installation successful"
|
||||
forM_ (_viPostInstall =<< vi) $ \msg ->
|
||||
runLogger $ logInfo msg
|
||||
pure ExitSuccess
|
||||
VLeft e@(V (AlreadyInstalled _ _)) -> do
|
||||
runLogger $ logWarn $ T.pack $ prettyShow e
|
||||
pure ExitSuccess
|
||||
VLeft (V (FileAlreadyExistsError fp)) -> do
|
||||
runLogger $ logWarn $
|
||||
"File " <> T.pack fp <> " already exists. Use 'ghcup install hls --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
||||
pure $ ExitFailure 3
|
||||
VLeft e@(V (AlreadyInstalled _ _)) -> do
|
||||
runLogger $ logWarn $ T.pack $ prettyShow e
|
||||
pure ExitSuccess
|
||||
VLeft (V (FileAlreadyExistsError fp)) -> do
|
||||
runLogger $ logWarn $
|
||||
"File " <> T.pack fp <> " already exists. Use 'ghcup install hls --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
||||
pure $ ExitFailure 3
|
||||
VLeft e -> do
|
||||
runLogger $ do
|
||||
logError $ T.pack $ prettyShow e
|
||||
logError $ "Also check the logs in " <> T.pack (fromGHCupPath logsDir)
|
||||
pure $ ExitFailure 4
|
||||
|
||||
installStack :: InstallOptions -> IO ExitCode
|
||||
installStack InstallOptions{..} = do
|
||||
s'@AppState{ dirs = Dirs{ .. } } <- liftIO getAppState'
|
||||
(case instBindist of
|
||||
Nothing -> runInstTool s' instPlatform $ do
|
||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Stack
|
||||
liftE $ runBothE' (installStackBin
|
||||
v
|
||||
(maybe GHCupInternal IsolateDir isolateDir)
|
||||
forceInstall
|
||||
) $ when instSet $ when (isNothing isolateDir) $ liftE $ setStack v
|
||||
pure vi
|
||||
Just uri -> do
|
||||
runInstTool s'{ settings = settings { noVerify = True}} instPlatform $ do
|
||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Stack
|
||||
liftE $ runBothE' (installStackBindist
|
||||
(DownloadInfo uri Nothing "")
|
||||
v
|
||||
(maybe GHCupInternal IsolateDir isolateDir)
|
||||
forceInstall
|
||||
) $ when instSet $ when (isNothing isolateDir) $ liftE $ setStack v
|
||||
pure vi
|
||||
)
|
||||
>>= \case
|
||||
VRight vi -> do
|
||||
runLogger $ logInfo "Stack installation successful"
|
||||
forM_ (_viPostInstall =<< vi) $ \msg ->
|
||||
runLogger $ logInfo msg
|
||||
pure ExitSuccess
|
||||
VLeft e@(V (AlreadyInstalled _ _)) -> do
|
||||
runLogger $ logWarn $ T.pack $ prettyShow e
|
||||
pure ExitSuccess
|
||||
VLeft (V (FileAlreadyExistsError fp)) -> do
|
||||
runLogger $ logWarn $
|
||||
"File " <> T.pack fp <> " already exists. Use 'ghcup install stack --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
||||
pure $ ExitFailure 3
|
||||
VLeft e@(V (AlreadyInstalled _ _)) -> do
|
||||
runLogger $ logWarn $ T.pack $ prettyShow e
|
||||
pure ExitSuccess
|
||||
VLeft (V (FileAlreadyExistsError fp)) -> do
|
||||
runLogger $ logWarn $
|
||||
"File " <> T.pack fp <> " already exists. Use 'ghcup install stack --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
||||
pure $ ExitFailure 3
|
||||
VLeft e -> do
|
||||
runLogger $ do
|
||||
logError $ T.pack $ prettyShow e
|
||||
logError $ "Also check the logs in " <> T.pack (fromGHCupPath logsDir)
|
||||
pure $ ExitFailure 4
|
||||
|
||||
265
app/ghcup/GHCup/OptParse/List.hs
Normal file
@@ -0,0 +1,265 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE DuplicateRecordFields #-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
|
||||
module GHCup.OptParse.List where
|
||||
|
||||
|
||||
|
||||
|
||||
import GHCup
|
||||
import GHCup.Prelude
|
||||
import GHCup.Types
|
||||
import GHCup.OptParse.Common
|
||||
|
||||
#if !MIN_VERSION_base(4,13,0)
|
||||
import Control.Monad.Fail ( MonadFail )
|
||||
#endif
|
||||
import Control.Monad.Reader
|
||||
import Control.Monad.Trans.Resource
|
||||
import Data.Char
|
||||
import Data.List ( intercalate, sort )
|
||||
import Data.Functor
|
||||
import Data.Maybe
|
||||
import Data.Versions hiding ( str )
|
||||
import Data.Void
|
||||
import Options.Applicative hiding ( style )
|
||||
import Prelude hiding ( appendFile )
|
||||
import System.Exit
|
||||
import System.Console.Pretty hiding ( color )
|
||||
|
||||
import qualified Data.Text as T
|
||||
import qualified System.Console.Pretty as Pretty
|
||||
import Control.Exception.Safe (MonadMask)
|
||||
import qualified Text.Megaparsec as MP
|
||||
import qualified Text.Megaparsec.Char as MPC
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Options ]--
|
||||
---------------
|
||||
|
||||
|
||||
data ListOptions = ListOptions
|
||||
{ loTool :: Maybe Tool
|
||||
, lCriteria :: Maybe ListCriteria
|
||||
, lRawFormat :: Bool
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Parsers ]--
|
||||
---------------
|
||||
|
||||
|
||||
listOpts :: Parser ListOptions
|
||||
listOpts =
|
||||
ListOptions
|
||||
<$> optional
|
||||
(option
|
||||
(eitherReader toolParser)
|
||||
(short 't' <> long "tool" <> metavar "<ghc|cabal|hls|stack>" <> help
|
||||
"Tool to list versions for. Default is all"
|
||||
<> completer (toolCompleter)
|
||||
)
|
||||
)
|
||||
<*> optional
|
||||
(option
|
||||
(eitherReader criteriaParser)
|
||||
( short 'c'
|
||||
<> long "show-criteria"
|
||||
<> metavar "<installed|set|available>"
|
||||
<> help "Show only installed/set/available tool versions"
|
||||
<> completer (listCompleter ["installed", "set", "available"])
|
||||
)
|
||||
)
|
||||
<*> switch
|
||||
(short 'r' <> long "raw-format" <> help "More machine-parsable format"
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
-----------------
|
||||
--[ Utilities ]--
|
||||
-----------------
|
||||
|
||||
|
||||
printListResult :: Bool -> Bool -> [ListResult] -> IO ()
|
||||
printListResult no_color raw lr = do
|
||||
|
||||
let
|
||||
color | raw || no_color = (\_ x -> x)
|
||||
| otherwise = Pretty.color
|
||||
|
||||
let
|
||||
printTag Recommended = color Green "recommended"
|
||||
printTag Latest = color Yellow "latest"
|
||||
printTag Prerelease = color Red "prerelease"
|
||||
printTag (Base pvp'') = "base-" ++ T.unpack (prettyPVP pvp'')
|
||||
printTag (UnknownTag t ) = t
|
||||
printTag Old = ""
|
||||
|
||||
let
|
||||
rows =
|
||||
(\x -> if raw
|
||||
then x
|
||||
else [color Green "", "Tool", "Version", "Tags", "Notes"] : x
|
||||
)
|
||||
. fmap
|
||||
(\ListResult {..} ->
|
||||
let marks = if
|
||||
| lSet -> (color Green (if isWindows then "IS" else "✔✔"))
|
||||
| lInstalled -> (color Green (if isWindows then "I " else "✓ "))
|
||||
| otherwise -> (color Red (if isWindows then "X " else "✗ "))
|
||||
in
|
||||
(if raw then [] else [marks])
|
||||
++ [ fmap toLower . show $ lTool
|
||||
, case lCross of
|
||||
Nothing -> T.unpack . prettyVer $ lVer
|
||||
Just c -> T.unpack (c <> "-" <> prettyVer lVer)
|
||||
, intercalate "," (filter (/= "") . fmap printTag $ sort lTag)
|
||||
, intercalate ","
|
||||
$ (if hlsPowered
|
||||
then [color Green "hls-powered"]
|
||||
else mempty
|
||||
)
|
||||
++ (if fromSrc then [color Blue "compiled"] else mempty)
|
||||
++ (if lStray then [color Yellow "stray"] else mempty)
|
||||
++ (if lNoBindist
|
||||
then [color Red "no-bindist"]
|
||||
else mempty
|
||||
)
|
||||
]
|
||||
)
|
||||
$ lr
|
||||
let cols =
|
||||
foldr (\xs ys -> zipWith (:) xs ys) (repeat []) rows
|
||||
lengths = fmap (maximum . fmap strWidth) cols
|
||||
padded = fmap (\xs -> zipWith padTo xs lengths) rows
|
||||
|
||||
forM_ (if raw then rows else padded) $ \row -> putStrLn $ unwords row
|
||||
where
|
||||
|
||||
padTo str' x =
|
||||
let lstr = strWidth str'
|
||||
add' = x - lstr
|
||||
in if add' < 0 then str' else str' ++ replicate add' ' '
|
||||
|
||||
-- | Calculate the render width of a string, considering
|
||||
-- wide characters (counted as double width), ANSI escape codes
|
||||
-- (not counted), and line breaks (in a multi-line string, the longest
|
||||
-- line determines the width).
|
||||
strWidth :: String -> Int
|
||||
strWidth =
|
||||
maximum
|
||||
. (0 :)
|
||||
. map (foldr (\a b -> charWidth a + b) 0)
|
||||
. lines
|
||||
. stripAnsi
|
||||
|
||||
-- | Strip ANSI escape sequences from a string.
|
||||
--
|
||||
-- >>> stripAnsi "\ESC[31m-1\ESC[m"
|
||||
-- "-1"
|
||||
stripAnsi :: String -> String
|
||||
stripAnsi s' =
|
||||
case
|
||||
MP.parseMaybe (many $ "" <$ MP.try ansi <|> pure <$> MP.anySingle) s'
|
||||
of
|
||||
Nothing -> error "Bad ansi escape" -- PARTIAL: should not happen
|
||||
Just xs -> concat xs
|
||||
where
|
||||
-- This parses lots of invalid ANSI escape codes, but that should be fine
|
||||
ansi =
|
||||
MPC.string "\ESC[" *> digitSemicolons *> suffix MP.<?> "ansi" :: MP.Parsec
|
||||
Void
|
||||
String
|
||||
Char
|
||||
digitSemicolons = MP.takeWhileP Nothing (\c -> isDigit c || c == ';')
|
||||
suffix = MP.oneOf ['A', 'B', 'C', 'D', 'H', 'J', 'K', 'f', 'm', 's', 'u']
|
||||
|
||||
-- | Get the designated render width of a character: 0 for a combining
|
||||
-- character, 1 for a regular character, 2 for a wide character.
|
||||
-- (Wide characters are rendered as exactly double width in apps and
|
||||
-- fonts that support it.) (From Pandoc.)
|
||||
charWidth :: Char -> Int
|
||||
charWidth c = case c of
|
||||
_ | c < '\x0300' -> 1
|
||||
| c >= '\x0300' && c <= '\x036F' -> 0
|
||||
| -- combining
|
||||
c >= '\x0370' && c <= '\x10FC' -> 1
|
||||
| c >= '\x1100' && c <= '\x115F' -> 2
|
||||
| c >= '\x1160' && c <= '\x11A2' -> 1
|
||||
| c >= '\x11A3' && c <= '\x11A7' -> 2
|
||||
| c >= '\x11A8' && c <= '\x11F9' -> 1
|
||||
| c >= '\x11FA' && c <= '\x11FF' -> 2
|
||||
| c >= '\x1200' && c <= '\x2328' -> 1
|
||||
| c >= '\x2329' && c <= '\x232A' -> 2
|
||||
| c >= '\x232B' && c <= '\x2E31' -> 1
|
||||
| c >= '\x2E80' && c <= '\x303E' -> 2
|
||||
| c == '\x303F' -> 1
|
||||
| c >= '\x3041' && c <= '\x3247' -> 2
|
||||
| c >= '\x3248' && c <= '\x324F' -> 1
|
||||
| -- ambiguous
|
||||
c >= '\x3250' && c <= '\x4DBF' -> 2
|
||||
| c >= '\x4DC0' && c <= '\x4DFF' -> 1
|
||||
| c >= '\x4E00' && c <= '\xA4C6' -> 2
|
||||
| c >= '\xA4D0' && c <= '\xA95F' -> 1
|
||||
| c >= '\xA960' && c <= '\xA97C' -> 2
|
||||
| c >= '\xA980' && c <= '\xABF9' -> 1
|
||||
| c >= '\xAC00' && c <= '\xD7FB' -> 2
|
||||
| c >= '\xD800' && c <= '\xDFFF' -> 1
|
||||
| c >= '\xE000' && c <= '\xF8FF' -> 1
|
||||
| -- ambiguous
|
||||
c >= '\xF900' && c <= '\xFAFF' -> 2
|
||||
| c >= '\xFB00' && c <= '\xFDFD' -> 1
|
||||
| c >= '\xFE00' && c <= '\xFE0F' -> 1
|
||||
| -- ambiguous
|
||||
c >= '\xFE10' && c <= '\xFE19' -> 2
|
||||
| c >= '\xFE20' && c <= '\xFE26' -> 1
|
||||
| c >= '\xFE30' && c <= '\xFE6B' -> 2
|
||||
| c >= '\xFE70' && c <= '\xFEFF' -> 1
|
||||
| c >= '\xFF01' && c <= '\xFF60' -> 2
|
||||
| c >= '\xFF61' && c <= '\x16A38' -> 1
|
||||
| c >= '\x1B000' && c <= '\x1B001' -> 2
|
||||
| c >= '\x1D000' && c <= '\x1F1FF' -> 1
|
||||
| c >= '\x1F200' && c <= '\x1F251' -> 2
|
||||
| c >= '\x1F300' && c <= '\x1F773' -> 1
|
||||
| c >= '\x20000' && c <= '\x3FFFD' -> 2
|
||||
| otherwise -> 1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
------------------
|
||||
--[ Entrypoint ]--
|
||||
------------------
|
||||
|
||||
|
||||
|
||||
list :: ( Monad m
|
||||
, MonadMask m
|
||||
, MonadUnliftIO m
|
||||
, MonadFail m
|
||||
)
|
||||
=> ListOptions
|
||||
-> Bool
|
||||
-> (ReaderT AppState m ExitCode -> m ExitCode)
|
||||
-> m ExitCode
|
||||
list ListOptions{..} no_color runAppState =
|
||||
runAppState (do
|
||||
l <- listVersions loTool lCriteria
|
||||
liftIO $ printListResult no_color lRawFormat l
|
||||
pure ExitSuccess
|
||||
)
|
||||
99
app/ghcup/GHCup/OptParse/Nuke.hs
Normal file
@@ -0,0 +1,99 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE DuplicateRecordFields #-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
|
||||
module GHCup.OptParse.Nuke where
|
||||
|
||||
|
||||
|
||||
|
||||
import GHCup
|
||||
import GHCup.Errors
|
||||
import GHCup.Types
|
||||
import GHCup.Prelude.Logger
|
||||
|
||||
#if !MIN_VERSION_base(4,13,0)
|
||||
import Control.Monad.Fail ( MonadFail )
|
||||
#endif
|
||||
import Control.Monad.Reader
|
||||
import Control.Monad.Trans.Resource
|
||||
import Data.Maybe
|
||||
import Haskus.Utils.Variant.Excepts
|
||||
import Options.Applicative hiding ( style )
|
||||
import Prelude hiding ( appendFile )
|
||||
import System.Exit
|
||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
||||
|
||||
import qualified Data.Text as T
|
||||
import Control.Exception.Safe (MonadMask)
|
||||
import Control.DeepSeq
|
||||
import Control.Exception
|
||||
import Control.Concurrent (threadDelay)
|
||||
|
||||
|
||||
|
||||
|
||||
---------------------------
|
||||
--[ Effect interpreters ]--
|
||||
---------------------------
|
||||
|
||||
|
||||
type NukeEffects = '[ NotInstalled, UninstallFailed ]
|
||||
|
||||
|
||||
runNuke :: AppState
|
||||
-> Excepts NukeEffects (ReaderT AppState m) a
|
||||
-> m (VEither NukeEffects a)
|
||||
runNuke s' =
|
||||
flip runReaderT s' . runE @NukeEffects
|
||||
|
||||
|
||||
|
||||
------------------
|
||||
--[ Entrypoint ]--
|
||||
------------------
|
||||
|
||||
|
||||
|
||||
nuke :: ( Monad m
|
||||
, MonadMask m
|
||||
, MonadUnliftIO m
|
||||
, MonadFail m
|
||||
)
|
||||
=> IO AppState
|
||||
-> (ReaderT LeanAppState m () -> m ())
|
||||
-> m ExitCode
|
||||
nuke appState runLogger = do
|
||||
s' <- liftIO appState
|
||||
void $ liftIO $ evaluate $ force s'
|
||||
runNuke s' (do
|
||||
lift $ logWarn "WARNING: This will remove GHCup and all installed components from your system."
|
||||
lift $ logWarn "Waiting 10 seconds before commencing, if you want to cancel it, now would be the time."
|
||||
liftIO $ threadDelay 10000000 -- wait 10s
|
||||
|
||||
lift $ logInfo "Initiating Nuclear Sequence 🚀🚀🚀"
|
||||
lift $ logInfo "Nuking in 3...2...1"
|
||||
|
||||
lInstalled <- lift $ listVersions Nothing (Just ListInstalled)
|
||||
|
||||
forM_ lInstalled (liftE . rmTool)
|
||||
|
||||
lift rmGhcupDirs
|
||||
|
||||
) >>= \case
|
||||
VRight leftOverFiles
|
||||
| null leftOverFiles -> do
|
||||
runLogger $ logInfo "Nuclear Annihilation complete!"
|
||||
pure ExitSuccess
|
||||
| otherwise -> do
|
||||
runLogger $ logError "These Files have survived Nuclear Annihilation, you may remove them manually."
|
||||
liftIO $ forM_ leftOverFiles putStrLn
|
||||
pure ExitSuccess
|
||||
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 15
|
||||
219
app/ghcup/GHCup/OptParse/Prefetch.hs
Normal file
@@ -0,0 +1,219 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
{-# LANGUAGE DuplicateRecordFields #-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
|
||||
module GHCup.OptParse.Prefetch where
|
||||
|
||||
|
||||
import GHCup
|
||||
import GHCup.Errors
|
||||
import GHCup.Types
|
||||
import GHCup.Prelude.File
|
||||
import GHCup.Prelude.Logger
|
||||
import GHCup.Prelude.String.QQ
|
||||
import GHCup.OptParse.Common
|
||||
|
||||
#if !MIN_VERSION_base(4,13,0)
|
||||
import Control.Monad.Fail ( MonadFail )
|
||||
#endif
|
||||
import Control.Monad.Reader
|
||||
import Control.Monad.Trans.Resource
|
||||
import Data.Functor
|
||||
import Data.Maybe
|
||||
import Haskus.Utils.Variant.Excepts
|
||||
import Options.Applicative hiding ( style )
|
||||
import Prelude hiding ( appendFile )
|
||||
import System.Exit
|
||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
||||
|
||||
import qualified Data.Text as T
|
||||
import Control.Exception.Safe (MonadMask)
|
||||
import GHCup.Download (getDownloadsF)
|
||||
|
||||
|
||||
|
||||
|
||||
----------------
|
||||
--[ Commands ]--
|
||||
----------------
|
||||
|
||||
|
||||
data PrefetchCommand = PrefetchGHC PrefetchGHCOptions (Maybe ToolVersion)
|
||||
| PrefetchCabal PrefetchOptions (Maybe ToolVersion)
|
||||
| PrefetchHLS PrefetchOptions (Maybe ToolVersion)
|
||||
| PrefetchStack PrefetchOptions (Maybe ToolVersion)
|
||||
| PrefetchMetadata
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Options ]--
|
||||
---------------
|
||||
|
||||
|
||||
data PrefetchOptions = PrefetchOptions {
|
||||
pfCacheDir :: Maybe FilePath
|
||||
}
|
||||
|
||||
data PrefetchGHCOptions = PrefetchGHCOptions {
|
||||
pfGHCSrc :: Bool
|
||||
, pfGHCCacheDir :: Maybe FilePath
|
||||
}
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Parsers ]--
|
||||
---------------
|
||||
|
||||
|
||||
prefetchP :: Parser PrefetchCommand
|
||||
prefetchP = subparser
|
||||
( command
|
||||
"ghc"
|
||||
(info
|
||||
(PrefetchGHC
|
||||
<$> (PrefetchGHCOptions
|
||||
<$> ( switch (short 's' <> long "source" <> help "Download source tarball instead of bindist") <**> helper )
|
||||
<*> optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)" <> completer (bashCompleter "directory"))))
|
||||
<*> optional (toolVersionTagArgument Nothing (Just GHC)) )
|
||||
( progDesc "Download GHC assets for installation")
|
||||
)
|
||||
<>
|
||||
command
|
||||
"cabal"
|
||||
(info
|
||||
(PrefetchCabal
|
||||
<$> fmap PrefetchOptions (optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)" <> completer (bashCompleter "directory"))))
|
||||
<*> ( optional (toolVersionTagArgument Nothing (Just Cabal)) <**> helper ))
|
||||
( progDesc "Download cabal assets for installation")
|
||||
)
|
||||
<>
|
||||
command
|
||||
"hls"
|
||||
(info
|
||||
(PrefetchHLS
|
||||
<$> fmap PrefetchOptions (optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)" <> completer (bashCompleter "directory"))))
|
||||
<*> ( optional (toolVersionTagArgument Nothing (Just HLS)) <**> helper ))
|
||||
( progDesc "Download HLS assets for installation")
|
||||
)
|
||||
<>
|
||||
command
|
||||
"stack"
|
||||
(info
|
||||
(PrefetchStack
|
||||
<$> fmap PrefetchOptions (optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)" <> completer (bashCompleter "directory"))))
|
||||
<*> ( optional (toolVersionTagArgument Nothing (Just Stack)) <**> helper ))
|
||||
( progDesc "Download stack assets for installation")
|
||||
)
|
||||
<>
|
||||
command
|
||||
"metadata"
|
||||
(PrefetchMetadata <$ info
|
||||
helper
|
||||
( progDesc "Download ghcup's metadata, needed for various operations")
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
--------------
|
||||
--[ Footer ]--
|
||||
--------------
|
||||
|
||||
|
||||
prefetchFooter :: String
|
||||
prefetchFooter = [s|Discussion:
|
||||
Prefetches tools or assets into "~/.ghcup/cache" directory. This can
|
||||
be then combined later with '--offline' flag, ensuring all assets that
|
||||
are required for offline use have been prefetched.
|
||||
|
||||
Examples:
|
||||
ghcup prefetch metadata
|
||||
ghcup prefetch ghc 8.10.5
|
||||
ghcup --offline install ghc 8.10.5|]
|
||||
|
||||
|
||||
|
||||
---------------------------
|
||||
--[ Effect interpreters ]--
|
||||
---------------------------
|
||||
|
||||
|
||||
type PrefetchEffects = '[ TagNotFound
|
||||
, NextVerNotFound
|
||||
, NoToolVersionSet
|
||||
, NoDownload
|
||||
, DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, JSONError
|
||||
, FileDoesNotExistError ]
|
||||
|
||||
|
||||
runPrefetch :: MonadUnliftIO m
|
||||
=> (ReaderT AppState m (VEither PrefetchEffects a) -> m (VEither PrefetchEffects a))
|
||||
-> Excepts PrefetchEffects (ResourceT (ReaderT AppState m)) a
|
||||
-> m (VEither PrefetchEffects a)
|
||||
runPrefetch runAppState =
|
||||
runAppState
|
||||
. runResourceT
|
||||
. runE
|
||||
@PrefetchEffects
|
||||
|
||||
|
||||
|
||||
------------------
|
||||
--[ Entrypoint ]--
|
||||
------------------
|
||||
|
||||
|
||||
|
||||
prefetch :: ( Monad m
|
||||
, MonadMask m
|
||||
, MonadUnliftIO m
|
||||
, MonadFail m
|
||||
)
|
||||
=> PrefetchCommand
|
||||
-> (forall a. ReaderT AppState m (VEither PrefetchEffects a) -> m (VEither PrefetchEffects a))
|
||||
-> (ReaderT LeanAppState m () -> m ())
|
||||
-> m ExitCode
|
||||
prefetch prefetchCommand runAppState runLogger =
|
||||
runPrefetch runAppState (do
|
||||
case prefetchCommand of
|
||||
PrefetchGHC
|
||||
(PrefetchGHCOptions pfGHCSrc pfCacheDir) mt -> do
|
||||
forM_ pfCacheDir (liftIO . createDirRecursive')
|
||||
(v, _) <- liftE $ fromVersion mt GHC
|
||||
if pfGHCSrc
|
||||
then liftE $ fetchGHCSrc (_tvVersion v) pfCacheDir
|
||||
else liftE $ fetchToolBindist (_tvVersion v) GHC pfCacheDir
|
||||
PrefetchCabal PrefetchOptions {pfCacheDir} mt -> do
|
||||
forM_ pfCacheDir (liftIO . createDirRecursive')
|
||||
(v, _) <- liftE $ fromVersion mt Cabal
|
||||
liftE $ fetchToolBindist (_tvVersion v) Cabal pfCacheDir
|
||||
PrefetchHLS PrefetchOptions {pfCacheDir} mt -> do
|
||||
forM_ pfCacheDir (liftIO . createDirRecursive')
|
||||
(v, _) <- liftE $ fromVersion mt HLS
|
||||
liftE $ fetchToolBindist (_tvVersion v) HLS pfCacheDir
|
||||
PrefetchStack PrefetchOptions {pfCacheDir} mt -> do
|
||||
forM_ pfCacheDir (liftIO . createDirRecursive')
|
||||
(v, _) <- liftE $ fromVersion mt Stack
|
||||
liftE $ fetchToolBindist (_tvVersion v) Stack pfCacheDir
|
||||
PrefetchMetadata -> do
|
||||
_ <- liftE getDownloadsF
|
||||
pure ""
|
||||
) >>= \case
|
||||
VRight _ -> do
|
||||
pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 15
|
||||
232
app/ghcup/GHCup/OptParse/Rm.hs
Normal file
@@ -0,0 +1,232 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
{-# LANGUAGE DuplicateRecordFields #-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
|
||||
module GHCup.OptParse.Rm where
|
||||
|
||||
|
||||
|
||||
|
||||
import GHCup
|
||||
import GHCup.Errors
|
||||
import GHCup.Types
|
||||
import GHCup.Types.Optics
|
||||
import GHCup.Utils
|
||||
import GHCup.Prelude.Logger
|
||||
import GHCup.Prelude.String.QQ
|
||||
import GHCup.OptParse.Common
|
||||
|
||||
#if !MIN_VERSION_base(4,13,0)
|
||||
import Control.Monad.Fail ( MonadFail )
|
||||
#endif
|
||||
import Control.Monad.Reader
|
||||
import Control.Monad.Trans.Resource
|
||||
import Data.Functor
|
||||
import Data.Maybe
|
||||
import Data.Versions hiding ( str )
|
||||
import Haskus.Utils.Variant.Excepts
|
||||
import Options.Applicative hiding ( style )
|
||||
import Prelude hiding ( appendFile )
|
||||
import System.Exit
|
||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
||||
|
||||
import qualified Data.Text as T
|
||||
import Control.Exception.Safe (MonadMask)
|
||||
|
||||
|
||||
|
||||
|
||||
----------------
|
||||
--[ Commands ]--
|
||||
----------------
|
||||
|
||||
|
||||
data RmCommand = RmGHC RmOptions
|
||||
| RmCabal Version
|
||||
| RmHLS Version
|
||||
| RmStack Version
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Options ]--
|
||||
---------------
|
||||
|
||||
|
||||
data RmOptions = RmOptions
|
||||
{ ghcVer :: GHCTargetVersion
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Parsers ]--
|
||||
---------------
|
||||
|
||||
|
||||
rmParser :: Parser (Either RmCommand RmOptions)
|
||||
rmParser =
|
||||
(Left <$> subparser
|
||||
( command
|
||||
"ghc"
|
||||
(RmGHC <$> info (rmOpts (Just GHC) <**> helper) (progDesc "Remove GHC version"))
|
||||
<> command
|
||||
"cabal"
|
||||
( RmCabal
|
||||
<$> info (versionParser' (Just ListInstalled) (Just Cabal) <**> helper)
|
||||
(progDesc "Remove Cabal version")
|
||||
)
|
||||
<> command
|
||||
"hls"
|
||||
( RmHLS
|
||||
<$> info (versionParser' (Just ListInstalled) (Just HLS) <**> helper)
|
||||
(progDesc "Remove haskell-language-server version")
|
||||
)
|
||||
<> command
|
||||
"stack"
|
||||
( RmStack
|
||||
<$> info (versionParser' (Just ListInstalled) (Just Stack) <**> helper)
|
||||
(progDesc "Remove stack version")
|
||||
)
|
||||
)
|
||||
)
|
||||
<|> (Right <$> rmOpts Nothing)
|
||||
|
||||
|
||||
|
||||
rmOpts :: Maybe Tool -> Parser RmOptions
|
||||
rmOpts tool = RmOptions <$> ghcVersionArgument (Just ListInstalled) tool
|
||||
|
||||
|
||||
|
||||
|
||||
--------------
|
||||
--[ Footer ]--
|
||||
--------------
|
||||
|
||||
|
||||
rmFooter :: String
|
||||
rmFooter = [s|Discussion:
|
||||
Remove the given GHC or cabal version. When no command is given,
|
||||
defaults to removing GHC with the specified version.
|
||||
It is recommended to always specify a subcommand (ghc/cabal/hls/stack).|]
|
||||
|
||||
|
||||
|
||||
|
||||
---------------------------
|
||||
--[ Effect interpreters ]--
|
||||
---------------------------
|
||||
|
||||
|
||||
type RmEffects = '[ NotInstalled, UninstallFailed ]
|
||||
|
||||
|
||||
runRm :: (ReaderT env m (VEither RmEffects a) -> m (VEither RmEffects a))
|
||||
-> Excepts RmEffects (ReaderT env m) a
|
||||
-> m (VEither RmEffects a)
|
||||
runRm runAppState =
|
||||
runAppState
|
||||
. runE
|
||||
@RmEffects
|
||||
|
||||
|
||||
|
||||
------------------
|
||||
--[ Entrypoint ]--
|
||||
------------------
|
||||
|
||||
|
||||
|
||||
rm :: ( Monad m
|
||||
, MonadMask m
|
||||
, MonadUnliftIO m
|
||||
, MonadFail m
|
||||
)
|
||||
=> Either RmCommand RmOptions
|
||||
-> (ReaderT AppState m (VEither RmEffects (Maybe VersionInfo))
|
||||
-> m (VEither RmEffects (Maybe VersionInfo)))
|
||||
-> (ReaderT LeanAppState m () -> m ())
|
||||
-> m ExitCode
|
||||
rm rmCommand runAppState runLogger = case rmCommand of
|
||||
(Right rmopts) -> do
|
||||
runLogger (logWarn "This is an old-style command for removing GHC. Use 'ghcup rm ghc' instead.")
|
||||
rmGHC' rmopts
|
||||
(Left (RmGHC rmopts)) -> rmGHC' rmopts
|
||||
(Left (RmCabal rmopts)) -> rmCabal' rmopts
|
||||
(Left (RmHLS rmopts)) -> rmHLS' rmopts
|
||||
(Left (RmStack rmopts)) -> rmStack' rmopts
|
||||
|
||||
where
|
||||
rmGHC' RmOptions{..} =
|
||||
runRm runAppState (do
|
||||
liftE $
|
||||
rmGHCVer ghcVer
|
||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||
pure (getVersionInfo (_tvVersion ghcVer) GHC dls)
|
||||
)
|
||||
>>= \case
|
||||
VRight vi -> do
|
||||
forM_ (_viPostRemove =<< vi) $ \msg ->
|
||||
runLogger $ logInfo msg
|
||||
pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 7
|
||||
|
||||
rmCabal' tv =
|
||||
runRm runAppState (do
|
||||
liftE $
|
||||
rmCabalVer tv
|
||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||
pure (getVersionInfo tv Cabal dls)
|
||||
)
|
||||
>>= \case
|
||||
VRight vi -> do
|
||||
forM_ (_viPostRemove =<< vi) $ \msg ->
|
||||
runLogger $ logInfo msg
|
||||
pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 15
|
||||
|
||||
rmHLS' tv =
|
||||
runRm runAppState (do
|
||||
liftE $
|
||||
rmHLSVer tv
|
||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||
pure (getVersionInfo tv HLS dls)
|
||||
)
|
||||
>>= \case
|
||||
VRight vi -> do
|
||||
forM_ (_viPostRemove =<< vi) $ \msg ->
|
||||
runLogger $ logInfo msg
|
||||
pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 15
|
||||
|
||||
rmStack' tv =
|
||||
runRm runAppState (do
|
||||
liftE $
|
||||
rmStackVer tv
|
||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||
pure (getVersionInfo tv Stack dls)
|
||||
)
|
||||
>>= \case
|
||||
VRight vi -> do
|
||||
forM_ (_viPostRemove =<< vi) $ \msg ->
|
||||
runLogger $ logInfo msg
|
||||
pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 15
|
||||
|
||||
502
app/ghcup/GHCup/OptParse/Run.hs
Normal file
@@ -0,0 +1,502 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE TypeFamilies #-}
|
||||
{-# LANGUAGE ViewPatterns #-}
|
||||
module GHCup.OptParse.Run where
|
||||
|
||||
|
||||
import GHCup
|
||||
import GHCup.Utils
|
||||
import GHCup.OptParse.Common
|
||||
import GHCup.Errors
|
||||
import GHCup.Types
|
||||
import GHCup.Types.Optics
|
||||
import GHCup.Prelude
|
||||
import GHCup.Prelude.File
|
||||
#ifdef IS_WINDOWS
|
||||
import GHCup.Prelude.Process
|
||||
import GHCup.Prelude.Process.Windows ( execNoMinGW )
|
||||
#endif
|
||||
import GHCup.Prelude.Logger
|
||||
import GHCup.Prelude.String.QQ
|
||||
|
||||
import Control.Exception.Safe ( MonadMask, MonadCatch )
|
||||
#if !MIN_VERSION_base(4,13,0)
|
||||
import Control.Monad.Fail ( MonadFail )
|
||||
#endif
|
||||
import Codec.Archive
|
||||
import Control.Monad.Reader
|
||||
import Control.Monad.Trans.Resource
|
||||
import Data.Functor
|
||||
import Data.Maybe (isNothing)
|
||||
import Data.List ( intercalate )
|
||||
import Haskus.Utils.Variant.Excepts
|
||||
import Options.Applicative hiding ( style )
|
||||
import Prelude hiding ( appendFile )
|
||||
import System.FilePath
|
||||
import System.Environment
|
||||
import System.Exit
|
||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
||||
|
||||
import qualified Data.Map.Strict as Map
|
||||
import qualified Data.Text as T
|
||||
#ifndef IS_WINDOWS
|
||||
import qualified System.Posix.Process as SPP
|
||||
#endif
|
||||
import Data.Versions ( prettyVer, Version )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Options ]--
|
||||
---------------
|
||||
|
||||
|
||||
data RunOptions = RunOptions
|
||||
{ runAppendPATH :: Bool
|
||||
, runInstTool' :: Bool
|
||||
, runMinGWPath :: Bool
|
||||
, runGHCVer :: Maybe ToolVersion
|
||||
, runCabalVer :: Maybe ToolVersion
|
||||
, runHLSVer :: Maybe ToolVersion
|
||||
, runStackVer :: Maybe ToolVersion
|
||||
, runBinDir :: Maybe FilePath
|
||||
, runQuick :: Bool
|
||||
, runCOMMAND :: [String]
|
||||
}
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Parsers ]--
|
||||
---------------
|
||||
|
||||
|
||||
|
||||
runOpts :: Parser RunOptions
|
||||
runOpts =
|
||||
RunOptions
|
||||
<$> switch
|
||||
(short 'a' <> long "append" <> help "Append bin/ dir to PATH instead of prepending (this means that e.g. a system installation may take precedence)")
|
||||
<*> switch
|
||||
(short 'i' <> long "install" <> help "Install the tool, if missing")
|
||||
<*> switch
|
||||
(short 'm' <> long "mingw-path" <> help "On windows, add mingw64 PATHs to environment (does nothing on unix)")
|
||||
<*> optional
|
||||
(option
|
||||
(eitherReader ghcVersionTagEither)
|
||||
(metavar "GHC_VERSION" <> long "ghc" <> help "The ghc version"
|
||||
<> completer (tagCompleter GHC [])
|
||||
<> (completer $ versionCompleter Nothing GHC)
|
||||
)
|
||||
)
|
||||
<*> optional
|
||||
(option
|
||||
(eitherReader toolVersionTagEither)
|
||||
(metavar "CABAL_VERSION" <> long "cabal" <> help "The cabal version"
|
||||
<> completer (tagCompleter Cabal [])
|
||||
<> (completer $ versionCompleter Nothing Cabal)
|
||||
)
|
||||
)
|
||||
<*> optional
|
||||
(option
|
||||
(eitherReader toolVersionTagEither)
|
||||
(metavar "HLS_VERSION" <> long "hls" <> help "The HLS version"
|
||||
<> completer (tagCompleter HLS [])
|
||||
<> (completer $ versionCompleter Nothing HLS)
|
||||
)
|
||||
)
|
||||
<*> optional
|
||||
(option
|
||||
(eitherReader toolVersionTagEither)
|
||||
(metavar "STACK_VERSION" <> long "stack" <> help "The stack version"
|
||||
<> completer (tagCompleter Stack [])
|
||||
<> (completer $ versionCompleter Nothing Stack)
|
||||
)
|
||||
)
|
||||
<*> optional
|
||||
(option
|
||||
(eitherReader isolateParser)
|
||||
( short 'b'
|
||||
<> long "bindir"
|
||||
<> metavar "DIR"
|
||||
<> help "directory where to create the tool symlinks (default: newly created system temp dir)"
|
||||
<> completer (bashCompleter "directory")
|
||||
)
|
||||
)
|
||||
<*> switch
|
||||
(short 'q' <> long "quick" <> help "Avoid any expensive work (such as downloads, version/tag resolution etc.). Disables --install.")
|
||||
<*> many (argument str (metavar "COMMAND" <> help "The command to run, with arguments (use longopts --). If omitted, just prints the created bin/ dir to stdout and exits."))
|
||||
|
||||
|
||||
|
||||
|
||||
--------------
|
||||
--[ Footer ]--
|
||||
--------------
|
||||
|
||||
|
||||
runFooter :: String
|
||||
runFooter = [s|Discussion:
|
||||
Adds the given tools to a dedicated bin/ directory and adds them to PATH, exposing
|
||||
the relevant binaries, then executes a command.
|
||||
|
||||
Examples:
|
||||
# run VSCode with all latest toolchain exposed, installing missing versions if necessary
|
||||
ghcup run --ghc latest --cabal latest --hls latest --stack latest --install -- code Setup.hs
|
||||
|
||||
# create a custom toolchain bin/ dir with GHC and cabal that can be manually added to PATH
|
||||
ghcup run --ghc 8.10.7 --cabal 3.2.0.0 --bindir $HOME/toolchain/bin
|
||||
|
||||
# run a specific ghc version
|
||||
ghcup run --ghc 8.10.7 -- ghc --version|]
|
||||
|
||||
|
||||
|
||||
|
||||
---------------------------
|
||||
--[ Effect interpreters ]--
|
||||
---------------------------
|
||||
|
||||
|
||||
type RunEffects = '[ AlreadyInstalled
|
||||
, UnknownArchive
|
||||
, ArchiveResult
|
||||
, FileDoesNotExistError
|
||||
, CopyError
|
||||
, NotInstalled
|
||||
, DirNotEmpty
|
||||
, NoDownload
|
||||
, NotInstalled
|
||||
, BuildFailed
|
||||
, TagNotFound
|
||||
, DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, TarDirDoesNotExist
|
||||
, NextVerNotFound
|
||||
, NoToolVersionSet
|
||||
, FileAlreadyExistsError
|
||||
, ProcessError
|
||||
, UninstallFailed
|
||||
, MergeFileTreeError
|
||||
]
|
||||
|
||||
runLeanRUN :: (MonadUnliftIO m, MonadIO m)
|
||||
=> LeanAppState
|
||||
-> Excepts RunEffects (ReaderT LeanAppState m) a
|
||||
-> m (VEither RunEffects a)
|
||||
runLeanRUN leanAppstate =
|
||||
-- Don't use runLeanAppState here, which is disabled on windows.
|
||||
-- This is the only command on all platforms that doesn't need full appstate.
|
||||
flip runReaderT leanAppstate
|
||||
. runE
|
||||
@RunEffects
|
||||
|
||||
runRUN :: MonadUnliftIO m
|
||||
=> IO AppState
|
||||
-> Excepts RunEffects (ResourceT (ReaderT AppState m)) a
|
||||
-> m (VEither RunEffects a)
|
||||
runRUN appState action' = do
|
||||
s' <- liftIO appState
|
||||
flip runReaderT s'
|
||||
. runResourceT
|
||||
. runE
|
||||
@RunEffects
|
||||
$ action'
|
||||
|
||||
|
||||
|
||||
------------------
|
||||
--[ Entrypoint ]--
|
||||
------------------
|
||||
|
||||
|
||||
|
||||
run :: forall m .
|
||||
( MonadFail m
|
||||
, MonadMask m
|
||||
, MonadCatch m
|
||||
, MonadIO m
|
||||
, MonadUnliftIO m
|
||||
)
|
||||
=> RunOptions
|
||||
-> IO AppState
|
||||
-> LeanAppState
|
||||
-> (ReaderT LeanAppState m () -> m ())
|
||||
-> m ExitCode
|
||||
run RunOptions{..} runAppState leanAppstate runLogger = do
|
||||
r <- if not runQuick
|
||||
then runRUN runAppState $ do
|
||||
toolchain <- liftE resolveToolchainFull
|
||||
|
||||
-- oh dear
|
||||
r <- lift ask
|
||||
tmp <- lift . lift . lift . flip runReaderT (fromAppState r) $ createTmpDir toolchain
|
||||
|
||||
liftE $ installToolChainFull toolchain tmp
|
||||
pure tmp
|
||||
else runLeanRUN leanAppstate $ do
|
||||
toolchain <- resolveToolchain
|
||||
tmp <- lift $ createTmpDir toolchain
|
||||
liftE $ installToolChain toolchain tmp
|
||||
pure tmp
|
||||
case r of
|
||||
VRight tmp -> do
|
||||
case runCOMMAND of
|
||||
[] -> do
|
||||
liftIO $ putStr tmp
|
||||
pure ExitSuccess
|
||||
(cmd:args) -> do
|
||||
newEnv <- liftIO $ addToPath tmp
|
||||
#ifndef IS_WINDOWS
|
||||
void $ liftIO $ SPP.executeFile cmd True args (Just newEnv)
|
||||
pure ExitSuccess
|
||||
#else
|
||||
r' <- if runMinGWPath
|
||||
then runLeanRUN leanAppstate $ liftE $ lEM @_ @'[ProcessError] $ exec cmd args Nothing (Just newEnv)
|
||||
else runLeanRUN leanAppstate $ liftE $ lEM @_ @'[ProcessError] $ execNoMinGW cmd args Nothing (Just newEnv)
|
||||
case r' of
|
||||
VRight _ -> pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 28
|
||||
#endif
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 27
|
||||
|
||||
where
|
||||
|
||||
-- TODO: doesn't work for cross
|
||||
resolveToolchainFull :: ( MonadFail m
|
||||
, MonadThrow m
|
||||
, MonadIO m
|
||||
, MonadCatch m
|
||||
)
|
||||
=> Excepts
|
||||
'[ TagNotFound
|
||||
, NextVerNotFound
|
||||
, NoToolVersionSet
|
||||
] (ResourceT (ReaderT AppState m)) Toolchain
|
||||
resolveToolchainFull = do
|
||||
ghcVer <- forM runGHCVer $ \ver -> do
|
||||
(v, _) <- liftE $ fromVersion (Just ver) GHC
|
||||
pure v
|
||||
cabalVer <- forM runCabalVer $ \ver -> do
|
||||
(v, _) <- liftE $ fromVersion (Just ver) Cabal
|
||||
pure (_tvVersion v)
|
||||
hlsVer <- forM runHLSVer $ \ver -> do
|
||||
(v, _) <- liftE $ fromVersion (Just ver) HLS
|
||||
pure (_tvVersion v)
|
||||
stackVer <- forM runStackVer $ \ver -> do
|
||||
(v, _) <- liftE $ fromVersion (Just ver) Stack
|
||||
pure (_tvVersion v)
|
||||
pure Toolchain{..}
|
||||
|
||||
resolveToolchain = do
|
||||
ghcVer <- case runGHCVer of
|
||||
Just (GHCVersion v) -> pure $ Just v
|
||||
Just (ToolVersion v) -> pure $ Just (mkTVer v)
|
||||
Nothing -> pure Nothing
|
||||
_ -> fail "Internal error"
|
||||
cabalVer <- case runCabalVer of
|
||||
Just (GHCVersion v) -> pure $ Just (_tvVersion v)
|
||||
Just (ToolVersion v) -> pure $ Just v
|
||||
Nothing -> pure Nothing
|
||||
_ -> fail "Internal error"
|
||||
hlsVer <- case runHLSVer of
|
||||
Just (GHCVersion v) -> pure $ Just (_tvVersion v)
|
||||
Just (ToolVersion v) -> pure $ Just v
|
||||
Nothing -> pure Nothing
|
||||
_ -> fail "Internal error"
|
||||
stackVer <- case runStackVer of
|
||||
Just (GHCVersion v) -> pure $ Just (_tvVersion v)
|
||||
Just (ToolVersion v) -> pure $ Just v
|
||||
Nothing -> pure Nothing
|
||||
_ -> fail "Internal error"
|
||||
pure Toolchain{..}
|
||||
|
||||
installToolChainFull :: ( MonadFail m
|
||||
, MonadThrow m
|
||||
, MonadIO m
|
||||
, MonadCatch m
|
||||
)
|
||||
=> Toolchain
|
||||
-> FilePath
|
||||
-> Excepts
|
||||
'[ TagNotFound
|
||||
, NextVerNotFound
|
||||
, NoToolVersionSet
|
||||
, UnknownArchive
|
||||
, TarDirDoesNotExist
|
||||
, ProcessError
|
||||
, NotInstalled
|
||||
, NoDownload
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, DirNotEmpty
|
||||
, DigestError
|
||||
, BuildFailed
|
||||
, ArchiveResult
|
||||
, AlreadyInstalled
|
||||
, FileAlreadyExistsError
|
||||
, CopyError
|
||||
, UninstallFailed
|
||||
, MergeFileTreeError
|
||||
] (ResourceT (ReaderT AppState m)) ()
|
||||
installToolChainFull Toolchain{..} tmp = do
|
||||
case ghcVer of
|
||||
Just v -> do
|
||||
isInstalled <- lift $ checkIfToolInstalled' GHC v
|
||||
unless isInstalled $ when (runInstTool' && isNothing (_tvTarget v)) $ void $ liftE $ installGHCBin
|
||||
(_tvVersion v)
|
||||
GHCupInternal
|
||||
False
|
||||
[]
|
||||
setGHC' v tmp
|
||||
_ -> pure ()
|
||||
case cabalVer of
|
||||
Just v -> do
|
||||
isInstalled <- lift $ checkIfToolInstalled' Cabal (mkTVer v)
|
||||
unless isInstalled $ when runInstTool' $ void $ liftE $ installCabalBin
|
||||
v
|
||||
GHCupInternal
|
||||
False
|
||||
setCabal' v tmp
|
||||
_ -> pure ()
|
||||
case stackVer of
|
||||
Just v -> do
|
||||
isInstalled <- lift $ checkIfToolInstalled' Stack (mkTVer v)
|
||||
unless isInstalled $ when runInstTool' $ void $ liftE $ installStackBin
|
||||
v
|
||||
GHCupInternal
|
||||
False
|
||||
setStack' v tmp
|
||||
_ -> pure ()
|
||||
case hlsVer of
|
||||
Just v -> do
|
||||
isInstalled <- lift $ checkIfToolInstalled' HLS (mkTVer v)
|
||||
unless isInstalled $ when runInstTool' $ void $ liftE $ installHLSBin
|
||||
v
|
||||
GHCupInternal
|
||||
False
|
||||
setHLS' v tmp
|
||||
_ -> pure ()
|
||||
|
||||
installToolChain :: ( MonadFail m
|
||||
, MonadThrow m
|
||||
, MonadIO m
|
||||
, MonadCatch m
|
||||
)
|
||||
=> Toolchain
|
||||
-> FilePath
|
||||
-> Excepts '[NotInstalled] (ReaderT LeanAppState m) ()
|
||||
installToolChain Toolchain{..} tmp = do
|
||||
case ghcVer of
|
||||
Just v -> setGHC' v tmp
|
||||
_ -> pure ()
|
||||
case cabalVer of
|
||||
Just v -> setCabal' v tmp
|
||||
_ -> pure ()
|
||||
case stackVer of
|
||||
Just v -> setStack' v tmp
|
||||
_ -> pure ()
|
||||
case hlsVer of
|
||||
Just v -> setHLS' v tmp
|
||||
_ -> pure ()
|
||||
|
||||
setGHC' v tmp = do
|
||||
void $ liftE $ setGHC v SetGHC_XYZ (Just tmp)
|
||||
void $ liftE $ setGHC v SetGHCOnly (Just tmp)
|
||||
setCabal' v tmp = do
|
||||
bin <- liftE $ whereIsTool Cabal (mkTVer v)
|
||||
cbin <- liftIO $ canonicalizePath bin
|
||||
lift $ createLink (relativeSymlink tmp cbin) (tmp </> ("cabal" <.> exeExt))
|
||||
setStack' v tmp = do
|
||||
bin <- liftE $ whereIsTool Stack (mkTVer v)
|
||||
cbin <- liftIO $ canonicalizePath bin
|
||||
lift $ createLink (relativeSymlink tmp cbin) (tmp </> ("stack" <.> exeExt))
|
||||
setHLS' v tmp = do
|
||||
Dirs {..} <- getDirs
|
||||
legacy <- isLegacyHLS v
|
||||
if legacy
|
||||
then do
|
||||
-- TODO: factor this out
|
||||
hlsWrapper <- liftE @_ @'[NotInstalled] $ hlsWrapperBinary v !? (NotInstalled HLS (mkTVer v))
|
||||
cw <- liftIO $ canonicalizePath (binDir </> hlsWrapper)
|
||||
lift $ createLink (relativeSymlink tmp cw) (tmp </> takeFileName cw)
|
||||
hlsBins <- hlsServerBinaries v Nothing >>= liftIO . traverse (canonicalizePath . (binDir </>))
|
||||
forM_ hlsBins $ \bin ->
|
||||
lift $ createLink (relativeSymlink tmp bin) (tmp </> takeFileName bin)
|
||||
liftE $ setHLS v SetHLSOnly (Just tmp)
|
||||
else do
|
||||
liftE $ setHLS v SetHLS_XYZ (Just tmp)
|
||||
liftE $ setHLS v SetHLSOnly (Just tmp)
|
||||
|
||||
addToPath path = do
|
||||
cEnv <- Map.fromList <$> getEnvironment
|
||||
let paths = ["PATH", "Path"]
|
||||
curPaths = (\x -> maybe [] splitSearchPath (Map.lookup x cEnv)) =<< paths
|
||||
newPath = intercalate [searchPathSeparator] (if runAppendPATH then (curPaths ++ [path]) else (path : curPaths))
|
||||
envWithoutPath = foldr (\x y -> Map.delete x y) cEnv paths
|
||||
pathVar = if isWindows then "Path" else "PATH"
|
||||
envWithNewPath = Map.toList $ Map.insert pathVar newPath envWithoutPath
|
||||
liftIO $ setEnv pathVar newPath
|
||||
return envWithNewPath
|
||||
|
||||
createTmpDir :: ( MonadUnliftIO m
|
||||
, MonadCatch m
|
||||
, MonadThrow m
|
||||
, MonadMask m
|
||||
, MonadIO m
|
||||
)
|
||||
=> Toolchain
|
||||
-> ReaderT LeanAppState m FilePath
|
||||
createTmpDir toolchain =
|
||||
case runBinDir of
|
||||
Just bindir -> do
|
||||
liftIO $ createDirRecursive' bindir
|
||||
liftIO $ canonicalizePath bindir
|
||||
Nothing -> do
|
||||
d <- predictableTmpDir toolchain
|
||||
liftIO $ createDirRecursive' d
|
||||
liftIO $ canonicalizePath d
|
||||
|
||||
predictableTmpDir :: Monad m
|
||||
=> Toolchain
|
||||
-> ReaderT LeanAppState m FilePath
|
||||
predictableTmpDir (Toolchain Nothing Nothing Nothing Nothing) = do
|
||||
Dirs { tmpDir } <- getDirs
|
||||
pure (fromGHCupPath tmpDir </> "ghcup-none")
|
||||
predictableTmpDir Toolchain{..} = do
|
||||
Dirs { tmpDir } <- getDirs
|
||||
pure $ fromGHCupPath tmpDir
|
||||
</> ("ghcup-" <> intercalate "_"
|
||||
( maybe [] ( (:[]) . ("ghc-" <>) . T.unpack . tVerToText) ghcVer
|
||||
<> maybe [] ( (:[]) . ("cabal-" <>) . T.unpack . prettyVer) cabalVer
|
||||
<> maybe [] ( (:[]) . ("hls-" <>) . T.unpack . prettyVer) hlsVer
|
||||
<> maybe [] ( (:[]) . ("stack-" <>) . T.unpack . prettyVer) stackVer
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
-------------------------
|
||||
--[ Other local types ]--
|
||||
-------------------------
|
||||
|
||||
|
||||
|
||||
data Toolchain = Toolchain
|
||||
{ ghcVer :: Maybe GHCTargetVersion
|
||||
, cabalVer :: Maybe Version
|
||||
, hlsVer :: Maybe Version
|
||||
, stackVer :: Maybe Version
|
||||
} deriving Show
|
||||
352
app/ghcup/GHCup/OptParse/Set.hs
Normal file
@@ -0,0 +1,352 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE DuplicateRecordFields #-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
|
||||
module GHCup.OptParse.Set where
|
||||
|
||||
|
||||
|
||||
|
||||
import GHCup.OptParse.Common
|
||||
|
||||
import GHCup
|
||||
import GHCup.Errors
|
||||
import GHCup.Types
|
||||
import GHCup.Prelude.Logger
|
||||
import GHCup.Prelude.String.QQ
|
||||
|
||||
#if !MIN_VERSION_base(4,13,0)
|
||||
import Control.Monad.Fail ( MonadFail )
|
||||
#endif
|
||||
import Control.Monad.Reader
|
||||
import Control.Monad.Trans.Resource
|
||||
import Data.Either
|
||||
import Data.Functor
|
||||
import Data.Maybe
|
||||
import Data.Versions hiding ( str )
|
||||
import GHC.Unicode
|
||||
import Haskus.Utils.Variant.Excepts
|
||||
import Options.Applicative hiding ( style )
|
||||
import Options.Applicative.Help.Pretty ( text )
|
||||
import Prelude hiding ( appendFile )
|
||||
import System.Exit
|
||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
||||
|
||||
import qualified Data.Text as T
|
||||
import Data.Bifunctor (second)
|
||||
import Control.Exception.Safe (MonadMask)
|
||||
import GHCup.Types.Optics
|
||||
|
||||
|
||||
|
||||
|
||||
----------------
|
||||
--[ Commands ]--
|
||||
----------------
|
||||
|
||||
|
||||
data SetCommand = SetGHC SetOptions
|
||||
| SetCabal SetOptions
|
||||
| SetHLS SetOptions
|
||||
| SetStack SetOptions
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Options ]--
|
||||
---------------
|
||||
|
||||
|
||||
data SetOptions = SetOptions
|
||||
{ sToolVer :: SetToolVersion
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Parsers ]--
|
||||
---------------
|
||||
|
||||
|
||||
setParser :: Parser (Either SetCommand SetOptions)
|
||||
setParser =
|
||||
(Left <$> subparser
|
||||
( command
|
||||
"ghc"
|
||||
( SetGHC
|
||||
<$> info
|
||||
(setOpts GHC <**> helper)
|
||||
( progDesc "Set GHC version"
|
||||
<> footerDoc (Just $ text setGHCFooter)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"cabal"
|
||||
( SetCabal
|
||||
<$> info
|
||||
(setOpts Cabal <**> helper)
|
||||
( progDesc "Set Cabal version"
|
||||
<> footerDoc (Just $ text setCabalFooter)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"hls"
|
||||
( SetHLS
|
||||
<$> info
|
||||
(setOpts HLS <**> helper)
|
||||
( progDesc "Set haskell-language-server version"
|
||||
<> footerDoc (Just $ text setHLSFooter)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"stack"
|
||||
( SetStack
|
||||
<$> info
|
||||
(setOpts Stack <**> helper)
|
||||
( progDesc "Set stack version"
|
||||
<> footerDoc (Just $ text setStackFooter)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
<|> (Right <$> setOpts GHC)
|
||||
where
|
||||
setGHCFooter :: String
|
||||
setGHCFooter = [s|Discussion:
|
||||
Sets the the current GHC version by creating non-versioned
|
||||
symlinks for all ghc binaries of the specified version in
|
||||
"~/.ghcup/bin/<binary>".|]
|
||||
|
||||
setCabalFooter :: String
|
||||
setCabalFooter = [s|Discussion:
|
||||
Sets the the current Cabal version.|]
|
||||
|
||||
setStackFooter :: String
|
||||
setStackFooter = [s|Discussion:
|
||||
Sets the the current Stack version.|]
|
||||
|
||||
setHLSFooter :: String
|
||||
setHLSFooter = [s|Discussion:
|
||||
Sets the the current haskell-language-server version.|]
|
||||
|
||||
|
||||
setOpts :: Tool -> Parser SetOptions
|
||||
setOpts tool = SetOptions <$>
|
||||
(fromMaybe SetRecommended <$>
|
||||
optional (setVersionArgument (Just ListInstalled) tool))
|
||||
|
||||
setVersionArgument :: Maybe ListCriteria -> Tool -> Parser SetToolVersion
|
||||
setVersionArgument criteria tool =
|
||||
argument (eitherReader setEither)
|
||||
(metavar "VERSION|TAG|next"
|
||||
<> completer (tagCompleter tool ["next"])
|
||||
<> (completer . versionCompleter criteria) tool)
|
||||
where
|
||||
setEither s' =
|
||||
parseSet s'
|
||||
<|> second SetToolTag (tagEither s')
|
||||
<|> se s'
|
||||
se s' = case tool of
|
||||
GHC -> second SetGHCVersion (ghcVersionEither s')
|
||||
_ -> second SetToolVersion (toolVersionEither s')
|
||||
parseSet s' = case fmap toLower s' of
|
||||
"next" -> Right SetNext
|
||||
other -> Left $ "Unknown tag/version " <> other
|
||||
|
||||
|
||||
|
||||
|
||||
--------------
|
||||
--[ Footer ]--
|
||||
--------------
|
||||
|
||||
|
||||
setFooter :: String
|
||||
setFooter = [s|Discussion:
|
||||
Sets the currently active GHC or cabal version. When no command is given,
|
||||
defaults to setting GHC with the specified version/tag (if no tag
|
||||
is given, sets GHC to 'recommended' version).
|
||||
It is recommended to always specify a subcommand (ghc/cabal/hls/stack).|]
|
||||
|
||||
|
||||
|
||||
---------------------------
|
||||
--[ Effect interpreters ]--
|
||||
---------------------------
|
||||
|
||||
|
||||
type SetGHCEffects = '[ FileDoesNotExistError
|
||||
, NotInstalled
|
||||
, TagNotFound
|
||||
, NextVerNotFound
|
||||
, NoToolVersionSet]
|
||||
|
||||
runSetGHC :: (ReaderT env m (VEither SetGHCEffects a) -> m (VEither SetGHCEffects a))
|
||||
-> Excepts SetGHCEffects (ReaderT env m) a
|
||||
-> m (VEither SetGHCEffects a)
|
||||
runSetGHC runAppState =
|
||||
runAppState
|
||||
. runE
|
||||
@SetGHCEffects
|
||||
|
||||
|
||||
type SetCabalEffects = '[ NotInstalled
|
||||
, TagNotFound
|
||||
, NextVerNotFound
|
||||
, NoToolVersionSet]
|
||||
|
||||
runSetCabal :: (ReaderT env m (VEither SetCabalEffects a) -> m (VEither SetCabalEffects a))
|
||||
-> Excepts SetCabalEffects (ReaderT env m) a
|
||||
-> m (VEither SetCabalEffects a)
|
||||
runSetCabal runAppState =
|
||||
runAppState
|
||||
. runE
|
||||
@SetCabalEffects
|
||||
|
||||
|
||||
type SetHLSEffects = '[ NotInstalled
|
||||
, TagNotFound
|
||||
, NextVerNotFound
|
||||
, NoToolVersionSet]
|
||||
|
||||
runSetHLS :: (ReaderT env m (VEither SetHLSEffects a) -> m (VEither SetHLSEffects a))
|
||||
-> Excepts SetHLSEffects (ReaderT env m) a
|
||||
-> m (VEither SetHLSEffects a)
|
||||
runSetHLS runAppState =
|
||||
runAppState
|
||||
. runE
|
||||
@SetHLSEffects
|
||||
|
||||
|
||||
type SetStackEffects = '[ NotInstalled
|
||||
, TagNotFound
|
||||
, NextVerNotFound
|
||||
, NoToolVersionSet]
|
||||
|
||||
runSetStack :: (ReaderT env m (VEither SetStackEffects a) -> m (VEither SetStackEffects a))
|
||||
-> Excepts SetStackEffects (ReaderT env m) a
|
||||
-> m (VEither SetStackEffects a)
|
||||
runSetStack runAppState =
|
||||
runAppState
|
||||
. runE
|
||||
@SetStackEffects
|
||||
|
||||
|
||||
|
||||
-------------------
|
||||
--[ Entrypoints ]--
|
||||
-------------------
|
||||
|
||||
|
||||
set :: forall m env.
|
||||
( Monad m
|
||||
, MonadMask m
|
||||
, MonadUnliftIO m
|
||||
, MonadFail m
|
||||
, HasDirs env
|
||||
, HasLog env
|
||||
)
|
||||
=> Either SetCommand SetOptions
|
||||
-> (forall eff . ReaderT AppState m (VEither eff GHCTargetVersion)
|
||||
-> m (VEither eff GHCTargetVersion))
|
||||
-> (forall eff. ReaderT env m (VEither eff GHCTargetVersion)
|
||||
-> m (VEither eff GHCTargetVersion))
|
||||
-> (ReaderT LeanAppState m () -> m ())
|
||||
-> m ExitCode
|
||||
set setCommand runAppState runLeanAppState runLogger = case setCommand of
|
||||
(Right sopts) -> do
|
||||
runLogger (logWarn "This is an old-style command for setting GHC. Use 'ghcup set ghc' instead.")
|
||||
setGHC' sopts
|
||||
(Left (SetGHC sopts)) -> setGHC' sopts
|
||||
(Left (SetCabal sopts)) -> setCabal' sopts
|
||||
(Left (SetHLS sopts)) -> setHLS' sopts
|
||||
(Left (SetStack sopts)) -> setStack' sopts
|
||||
|
||||
where
|
||||
setGHC' :: SetOptions
|
||||
-> m ExitCode
|
||||
setGHC' SetOptions{ sToolVer } =
|
||||
case sToolVer of
|
||||
(SetGHCVersion v) -> runSetGHC runLeanAppState (liftE $ setGHC v SetGHCOnly Nothing >> pure v)
|
||||
_ -> runSetGHC runAppState (do
|
||||
v <- liftE $ fst <$> fromVersion' sToolVer GHC
|
||||
liftE $ setGHC v SetGHCOnly Nothing
|
||||
)
|
||||
>>= \case
|
||||
VRight GHCTargetVersion{..} -> do
|
||||
runLogger
|
||||
$ logInfo $
|
||||
"GHC " <> prettyVer _tvVersion <> " successfully set as default version" <> maybe "" (" for cross target " <>) _tvTarget
|
||||
pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 5
|
||||
|
||||
|
||||
setCabal' :: SetOptions
|
||||
-> m ExitCode
|
||||
setCabal' SetOptions{ sToolVer } =
|
||||
case sToolVer of
|
||||
(SetToolVersion v) -> runSetCabal runLeanAppState (liftE $ setCabal v >> pure (mkTVer v))
|
||||
_ -> runSetCabal runAppState (do
|
||||
v <- liftE $ fst <$> fromVersion' sToolVer Cabal
|
||||
liftE $ setCabal (_tvVersion v)
|
||||
pure v
|
||||
)
|
||||
>>= \case
|
||||
VRight v -> do
|
||||
runLogger
|
||||
$ logInfo $
|
||||
"Cabal " <> prettyVer (_tvVersion v) <> " successfully set as default version"
|
||||
pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 14
|
||||
|
||||
setHLS' :: SetOptions
|
||||
-> m ExitCode
|
||||
setHLS' SetOptions{ sToolVer } =
|
||||
case sToolVer of
|
||||
(SetToolVersion v) -> runSetHLS runLeanAppState (liftE $ setHLS v SetHLSOnly Nothing >> pure (mkTVer v))
|
||||
_ -> runSetHLS runAppState (do
|
||||
v <- liftE $ fst <$> fromVersion' sToolVer HLS
|
||||
liftE $ setHLS (_tvVersion v) SetHLSOnly Nothing
|
||||
pure v
|
||||
)
|
||||
>>= \case
|
||||
VRight v -> do
|
||||
runLogger
|
||||
$ logInfo $
|
||||
"HLS " <> prettyVer (_tvVersion v) <> " successfully set as default version"
|
||||
pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 14
|
||||
|
||||
|
||||
setStack' :: SetOptions
|
||||
-> m ExitCode
|
||||
setStack' SetOptions{ sToolVer } =
|
||||
case sToolVer of
|
||||
(SetToolVersion v) -> runSetStack runLeanAppState (liftE $ setStack v >> pure (mkTVer v))
|
||||
_ -> runSetStack runAppState (do
|
||||
v <- liftE $ fst <$> fromVersion' sToolVer Stack
|
||||
liftE $ setStack (_tvVersion v)
|
||||
pure v
|
||||
)
|
||||
>>= \case
|
||||
VRight v -> do
|
||||
runLogger
|
||||
$ logInfo $
|
||||
"Stack " <> prettyVer (_tvVersion v) <> " successfully set as default version"
|
||||
pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 14
|
||||
122
app/ghcup/GHCup/OptParse/ToolRequirements.hs
Normal file
@@ -0,0 +1,122 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE DuplicateRecordFields #-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
module GHCup.OptParse.ToolRequirements where
|
||||
|
||||
|
||||
import GHCup.Errors
|
||||
import GHCup.Types
|
||||
import GHCup.Prelude.Logger
|
||||
import GHCup.Prelude.String.QQ
|
||||
|
||||
#if !MIN_VERSION_base(4,13,0)
|
||||
import Control.Monad.Fail ( MonadFail )
|
||||
#endif
|
||||
import Control.Monad.Reader
|
||||
import Control.Monad.Trans.Resource
|
||||
import Haskus.Utils.Variant.Excepts
|
||||
import Options.Applicative hiding ( style )
|
||||
import Prelude hiding ( appendFile )
|
||||
import System.Exit
|
||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
||||
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Text.IO as T
|
||||
import Control.Exception.Safe (MonadMask)
|
||||
import GHCup.Types.Optics
|
||||
import GHCup.Platform
|
||||
import GHCup.Prelude
|
||||
import GHCup.Requirements
|
||||
import System.IO
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Options ]--
|
||||
---------------
|
||||
|
||||
|
||||
data ToolReqOpts = ToolReqOpts
|
||||
{ tlrRaw :: Bool
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Parsers ]--
|
||||
---------------
|
||||
|
||||
|
||||
toolReqP :: Parser ToolReqOpts
|
||||
toolReqP =
|
||||
ToolReqOpts
|
||||
<$> switch (short 'r' <> long "raw-format" <> help "machine-parsable format")
|
||||
|
||||
|
||||
|
||||
|
||||
--------------
|
||||
--[ Footer ]--
|
||||
--------------
|
||||
|
||||
|
||||
toolReqFooter :: String
|
||||
toolReqFooter = [s|Discussion:
|
||||
Print tool requirements on the current platform.
|
||||
If you want to pass this to your package manage, use '--raw-format'.|]
|
||||
|
||||
|
||||
|
||||
---------------------------
|
||||
--[ Effect interpreters ]--
|
||||
---------------------------
|
||||
|
||||
|
||||
type ToolRequirementsEffects = '[ NoCompatiblePlatform , DistroNotFound , NoToolRequirements ]
|
||||
|
||||
|
||||
runToolRequirements :: (ReaderT env m (VEither ToolRequirementsEffects a) -> m (VEither ToolRequirementsEffects a))
|
||||
-> Excepts ToolRequirementsEffects (ReaderT env m) a
|
||||
-> m (VEither ToolRequirementsEffects a)
|
||||
runToolRequirements runAppState =
|
||||
runAppState
|
||||
. runE
|
||||
@ToolRequirementsEffects
|
||||
|
||||
|
||||
|
||||
------------------
|
||||
--[ Entrypoint ]--
|
||||
------------------
|
||||
|
||||
|
||||
|
||||
toolRequirements :: ( Monad m
|
||||
, MonadMask m
|
||||
, MonadUnliftIO m
|
||||
, MonadFail m
|
||||
, Alternative m
|
||||
)
|
||||
=> ToolReqOpts
|
||||
-> (ReaderT AppState m (VEither ToolRequirementsEffects ()) -> m (VEither ToolRequirementsEffects ()))
|
||||
-> (ReaderT LeanAppState m () -> m ())
|
||||
-> m ExitCode
|
||||
toolRequirements ToolReqOpts{..} runAppState runLogger = runToolRequirements runAppState (do
|
||||
GHCupInfo { .. } <- lift getGHCupInfo
|
||||
platform' <- liftE getPlatform
|
||||
req <- getCommonRequirements platform' _toolRequirements ?? NoToolRequirements
|
||||
if tlrRaw
|
||||
then liftIO $ T.hPutStr stdout (rawRequirements req)
|
||||
else liftIO $ T.hPutStr stdout (prettyRequirements req)
|
||||
)
|
||||
>>= \case
|
||||
VRight _ -> pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 12
|
||||
205
app/ghcup/GHCup/OptParse/UnSet.hs
Normal file
@@ -0,0 +1,205 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE DuplicateRecordFields #-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
|
||||
module GHCup.OptParse.UnSet where
|
||||
|
||||
|
||||
|
||||
|
||||
import GHCup
|
||||
import GHCup.Errors
|
||||
import GHCup.Types
|
||||
import GHCup.Prelude.Logger
|
||||
import GHCup.Prelude.String.QQ
|
||||
|
||||
#if !MIN_VERSION_base(4,13,0)
|
||||
import Control.Monad.Fail ( MonadFail )
|
||||
#endif
|
||||
import Control.Monad.Reader
|
||||
import Control.Monad.Trans.Resource
|
||||
import Data.Functor
|
||||
import Data.Maybe
|
||||
import Haskus.Utils.Variant.Excepts
|
||||
import Options.Applicative hiding ( style )
|
||||
import Options.Applicative.Help.Pretty ( text )
|
||||
import Prelude hiding ( appendFile )
|
||||
import System.Exit
|
||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
||||
|
||||
import qualified Data.Text as T
|
||||
import Control.Exception.Safe (MonadMask)
|
||||
import GHCup.Types.Optics
|
||||
|
||||
|
||||
|
||||
|
||||
----------------
|
||||
--[ Commands ]--
|
||||
----------------
|
||||
|
||||
|
||||
data UnsetCommand = UnsetGHC UnsetOptions
|
||||
| UnsetCabal UnsetOptions
|
||||
| UnsetHLS UnsetOptions
|
||||
| UnsetStack UnsetOptions
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Options ]--
|
||||
---------------
|
||||
|
||||
|
||||
data UnsetOptions = UnsetOptions
|
||||
{ sToolVer :: Maybe T.Text -- target platform triple
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Parsers ]--
|
||||
---------------
|
||||
|
||||
|
||||
unsetParser :: Parser UnsetCommand
|
||||
unsetParser =
|
||||
subparser
|
||||
( command
|
||||
"ghc"
|
||||
( UnsetGHC
|
||||
<$> info
|
||||
(unsetOpts <**> helper)
|
||||
( progDesc "Unset GHC version"
|
||||
<> footerDoc (Just $ text unsetGHCFooter)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"cabal"
|
||||
( UnsetCabal
|
||||
<$> info
|
||||
(unsetOpts <**> helper)
|
||||
( progDesc "Unset Cabal version"
|
||||
<> footerDoc (Just $ text unsetCabalFooter)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"hls"
|
||||
( UnsetHLS
|
||||
<$> info
|
||||
(unsetOpts <**> helper)
|
||||
( progDesc "Unset haskell-language-server version"
|
||||
<> footerDoc (Just $ text unsetHLSFooter)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"stack"
|
||||
( UnsetStack
|
||||
<$> info
|
||||
(unsetOpts <**> helper)
|
||||
( progDesc "Unset stack version"
|
||||
<> footerDoc (Just $ text unsetStackFooter)
|
||||
)
|
||||
)
|
||||
)
|
||||
where
|
||||
unsetGHCFooter :: String
|
||||
unsetGHCFooter = [s|Discussion:
|
||||
Unsets the the current GHC version. That means there won't
|
||||
be a ~/.ghcup/bin/ghc anymore.|]
|
||||
|
||||
unsetCabalFooter :: String
|
||||
unsetCabalFooter = [s|Discussion:
|
||||
Unsets the the current Cabal version.|]
|
||||
|
||||
unsetStackFooter :: String
|
||||
unsetStackFooter = [s|Discussion:
|
||||
Unsets the the current Stack version.|]
|
||||
|
||||
unsetHLSFooter :: String
|
||||
unsetHLSFooter = [s|Discussion:
|
||||
Unsets the the current haskell-language-server version.|]
|
||||
|
||||
|
||||
unsetOpts :: Parser UnsetOptions
|
||||
unsetOpts = UnsetOptions . fmap T.pack <$> optional (argument str (metavar "TRIPLE"))
|
||||
|
||||
|
||||
|
||||
--------------
|
||||
--[ Footer ]--
|
||||
--------------
|
||||
|
||||
|
||||
unsetFooter :: String
|
||||
unsetFooter = [s|Discussion:
|
||||
Unsets the currently active GHC or cabal version.|]
|
||||
|
||||
|
||||
|
||||
|
||||
---------------------------
|
||||
--[ Effect interpreters ]--
|
||||
---------------------------
|
||||
|
||||
|
||||
type UnsetEffects = '[ NotInstalled ]
|
||||
|
||||
|
||||
runUnsetGHC :: (ReaderT env m (VEither UnsetEffects a) -> m (VEither UnsetEffects a))
|
||||
-> Excepts UnsetEffects (ReaderT env m) a
|
||||
-> m (VEither UnsetEffects a)
|
||||
runUnsetGHC runLeanAppState =
|
||||
runLeanAppState
|
||||
. runE
|
||||
@UnsetEffects
|
||||
|
||||
|
||||
|
||||
------------------
|
||||
--[ Entrypoint ]--
|
||||
------------------
|
||||
|
||||
|
||||
|
||||
unset :: ( Monad m
|
||||
, MonadMask m
|
||||
, MonadUnliftIO m
|
||||
, MonadFail m
|
||||
, HasDirs env
|
||||
, HasLog env
|
||||
)
|
||||
=> UnsetCommand
|
||||
-> (ReaderT env m (VEither UnsetEffects ())
|
||||
-> m (VEither UnsetEffects ()))
|
||||
-> (ReaderT LeanAppState m () -> m ())
|
||||
-> m ExitCode
|
||||
unset unsetCommand runLeanAppState runLogger = case unsetCommand of
|
||||
(UnsetGHC (UnsetOptions triple)) -> runUnsetGHC runLeanAppState (unsetGHC triple)
|
||||
>>= \case
|
||||
VRight _ -> do
|
||||
runLogger $ logInfo "GHC successfully unset"
|
||||
pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 14
|
||||
(UnsetCabal (UnsetOptions _)) -> do
|
||||
void $ runLeanAppState (VRight <$> unsetCabal)
|
||||
runLogger $ logInfo "Cabal successfully unset"
|
||||
pure ExitSuccess
|
||||
(UnsetHLS (UnsetOptions _)) -> do
|
||||
void $ runLeanAppState (VRight <$> unsetHLS)
|
||||
runLogger $ logInfo "HLS successfully unset"
|
||||
pure ExitSuccess
|
||||
(UnsetStack (UnsetOptions _)) -> do
|
||||
void $ runLeanAppState (VRight <$> unsetStack)
|
||||
runLogger $ logInfo "Stack successfully unset"
|
||||
pure ExitSuccess
|
||||
155
app/ghcup/GHCup/OptParse/Upgrade.hs
Normal file
@@ -0,0 +1,155 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE DuplicateRecordFields #-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
|
||||
module GHCup.OptParse.Upgrade where
|
||||
|
||||
|
||||
|
||||
|
||||
import GHCup
|
||||
import GHCup.Errors
|
||||
import GHCup.Types
|
||||
import GHCup.Prelude.File
|
||||
import GHCup.Prelude.Logger
|
||||
|
||||
#if !MIN_VERSION_base(4,13,0)
|
||||
import Control.Monad.Fail ( MonadFail )
|
||||
#endif
|
||||
import Control.Monad.Reader
|
||||
import Control.Monad.Trans.Resource
|
||||
import Data.Functor
|
||||
import Data.Maybe
|
||||
import Haskus.Utils.Variant.Excepts
|
||||
import Options.Applicative hiding ( style )
|
||||
import Prelude hiding ( appendFile )
|
||||
import System.Exit
|
||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
||||
|
||||
import qualified Data.Text as T
|
||||
import Control.Exception.Safe (MonadMask)
|
||||
import System.Environment
|
||||
import GHCup.Utils
|
||||
import System.FilePath
|
||||
import GHCup.Types.Optics
|
||||
import Data.Versions hiding (str)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Options ]--
|
||||
---------------
|
||||
|
||||
|
||||
data UpgradeOpts = UpgradeInplace
|
||||
| UpgradeAt FilePath
|
||||
| UpgradeGHCupDir
|
||||
deriving Show
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Parsers ]--
|
||||
---------------
|
||||
|
||||
|
||||
upgradeOptsP :: Parser UpgradeOpts
|
||||
upgradeOptsP =
|
||||
flag'
|
||||
UpgradeInplace
|
||||
(short 'i' <> long "inplace" <> help
|
||||
"Upgrade ghcup in-place"
|
||||
)
|
||||
<|>
|
||||
( UpgradeAt
|
||||
<$> option
|
||||
str
|
||||
(short 't' <> long "target" <> metavar "TARGET_DIR" <> help
|
||||
"Absolute filepath to write ghcup into"
|
||||
<> completer (bashCompleter "file")
|
||||
)
|
||||
)
|
||||
<|> pure UpgradeGHCupDir
|
||||
|
||||
|
||||
|
||||
|
||||
---------------------------
|
||||
--[ Effect interpreters ]--
|
||||
---------------------------
|
||||
|
||||
|
||||
type UpgradeEffects = '[ DigestError
|
||||
, GPGError
|
||||
, NoDownload
|
||||
, NoUpdate
|
||||
, FileDoesNotExistError
|
||||
, CopyError
|
||||
, DownloadFailed
|
||||
, ToolShadowed
|
||||
]
|
||||
|
||||
|
||||
runUpgrade :: MonadUnliftIO m
|
||||
=> (ReaderT AppState m (VEither UpgradeEffects a) -> m (VEither UpgradeEffects a))
|
||||
-> Excepts UpgradeEffects (ResourceT (ReaderT AppState m)) a
|
||||
-> m (VEither UpgradeEffects a)
|
||||
runUpgrade runAppState =
|
||||
runAppState
|
||||
. runResourceT
|
||||
. runE
|
||||
@UpgradeEffects
|
||||
|
||||
|
||||
|
||||
------------------
|
||||
--[ Entrypoint ]--
|
||||
------------------
|
||||
|
||||
|
||||
|
||||
upgrade :: ( Monad m
|
||||
, MonadMask m
|
||||
, MonadUnliftIO m
|
||||
, MonadFail m
|
||||
)
|
||||
=> UpgradeOpts
|
||||
-> Bool
|
||||
-> Bool
|
||||
-> Dirs
|
||||
-> (forall a. ReaderT AppState m (VEither UpgradeEffects a) -> m (VEither UpgradeEffects a))
|
||||
-> (ReaderT LeanAppState m () -> m ())
|
||||
-> m ExitCode
|
||||
upgrade uOpts force' fatal Dirs{..} runAppState runLogger = do
|
||||
target <- case uOpts of
|
||||
UpgradeInplace -> Just <$> liftIO getExecutablePath
|
||||
(UpgradeAt p) -> pure $ Just p
|
||||
UpgradeGHCupDir -> pure (Just (binDir </> "ghcup" <> exeExt))
|
||||
|
||||
runUpgrade runAppState (do
|
||||
v' <- liftE $ upgradeGHCup target force' fatal
|
||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||
pure (v', dls)
|
||||
) >>= \case
|
||||
VRight (v', dls) -> do
|
||||
let pretty_v = prettyVer v'
|
||||
let vi = fromJust $ snd <$> getLatest dls GHCup
|
||||
runLogger $ logInfo $
|
||||
"Successfully upgraded GHCup to version " <> pretty_v
|
||||
forM_ (_viPostInstall vi) $ \msg ->
|
||||
runLogger $ logInfo msg
|
||||
pure ExitSuccess
|
||||
VLeft (V NoUpdate) -> do
|
||||
runLogger $ logWarn "No GHCup update available"
|
||||
pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 11
|
||||
334
app/ghcup/GHCup/OptParse/Whereis.hs
Normal file
@@ -0,0 +1,334 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
{-# LANGUAGE DuplicateRecordFields #-}
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
|
||||
module GHCup.OptParse.Whereis where
|
||||
|
||||
|
||||
|
||||
|
||||
import GHCup
|
||||
import GHCup.Errors
|
||||
import GHCup.OptParse.Common
|
||||
import GHCup.Types
|
||||
import GHCup.Utils
|
||||
import GHCup.Prelude.Logger
|
||||
import GHCup.Prelude.String.QQ
|
||||
|
||||
#if !MIN_VERSION_base(4,13,0)
|
||||
import Control.Monad.Fail ( MonadFail )
|
||||
#endif
|
||||
import Control.Monad.Reader
|
||||
import Control.Monad.Trans.Resource
|
||||
import Data.Functor
|
||||
import Data.Maybe
|
||||
import Haskus.Utils.Variant.Excepts
|
||||
import Options.Applicative hiding ( style )
|
||||
import Options.Applicative.Help.Pretty ( text )
|
||||
import Prelude hiding ( appendFile )
|
||||
import System.Exit
|
||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
||||
|
||||
import qualified Data.Text as T
|
||||
import Control.Exception.Safe (MonadMask)
|
||||
import System.FilePath (takeDirectory)
|
||||
import GHCup.Types.Optics
|
||||
|
||||
|
||||
|
||||
|
||||
----------------
|
||||
--[ Commands ]--
|
||||
----------------
|
||||
|
||||
|
||||
data WhereisCommand = WhereisTool Tool (Maybe ToolVersion)
|
||||
| WhereisBaseDir
|
||||
| WhereisBinDir
|
||||
| WhereisCacheDir
|
||||
| WhereisLogsDir
|
||||
| WhereisConfDir
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Options ]--
|
||||
---------------
|
||||
|
||||
|
||||
data WhereisOptions = WhereisOptions {
|
||||
directory :: Bool
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--[ Parsers ]--
|
||||
---------------
|
||||
|
||||
|
||||
whereisP :: Parser WhereisCommand
|
||||
whereisP = subparser
|
||||
(commandGroup "Tools locations:" <>
|
||||
command
|
||||
"ghc"
|
||||
(WhereisTool GHC <$> info
|
||||
( optional (toolVersionTagArgument Nothing (Just GHC)) <**> helper )
|
||||
( progDesc "Get GHC location"
|
||||
<> footerDoc (Just $ text whereisGHCFooter ))
|
||||
)
|
||||
<>
|
||||
command
|
||||
"cabal"
|
||||
(WhereisTool Cabal <$> info
|
||||
( optional (toolVersionTagArgument Nothing (Just Cabal)) <**> helper )
|
||||
( progDesc "Get cabal location"
|
||||
<> footerDoc (Just $ text whereisCabalFooter ))
|
||||
)
|
||||
<>
|
||||
command
|
||||
"hls"
|
||||
(WhereisTool HLS <$> info
|
||||
( optional (toolVersionTagArgument Nothing (Just HLS)) <**> helper )
|
||||
( progDesc "Get HLS location"
|
||||
<> footerDoc (Just $ text whereisHLSFooter ))
|
||||
)
|
||||
<>
|
||||
command
|
||||
"stack"
|
||||
(WhereisTool Stack <$> info
|
||||
( optional (toolVersionTagArgument Nothing (Just Stack)) <**> helper )
|
||||
( progDesc "Get stack location"
|
||||
<> footerDoc (Just $ text whereisStackFooter ))
|
||||
)
|
||||
<>
|
||||
command
|
||||
"ghcup"
|
||||
(WhereisTool GHCup <$> info ( pure Nothing <**> helper ) ( progDesc "Get ghcup location" ))
|
||||
) <|> subparser ( commandGroup "Directory locations:"
|
||||
<>
|
||||
command
|
||||
"basedir"
|
||||
(info (pure WhereisBaseDir <**> helper)
|
||||
( progDesc "Get ghcup base directory location" )
|
||||
)
|
||||
<>
|
||||
command
|
||||
"bindir"
|
||||
(info (pure WhereisBinDir <**> helper)
|
||||
( progDesc "Get ghcup binary directory location" )
|
||||
)
|
||||
<>
|
||||
command
|
||||
"cachedir"
|
||||
(info (pure WhereisCacheDir <**> helper)
|
||||
( progDesc "Get ghcup cache directory location" )
|
||||
)
|
||||
<>
|
||||
command
|
||||
"logsdir"
|
||||
(info (pure WhereisLogsDir <**> helper)
|
||||
( progDesc "Get ghcup logs directory location" )
|
||||
)
|
||||
<>
|
||||
command
|
||||
"confdir"
|
||||
(info (pure WhereisConfDir <**> helper)
|
||||
( progDesc "Get ghcup config directory location" )
|
||||
)
|
||||
)
|
||||
where
|
||||
whereisGHCFooter = [s|Discussion:
|
||||
Finds the location of a GHC executable, which usually resides in
|
||||
a self-contained "~/.ghcup/ghc/<ghcver>" directory.
|
||||
|
||||
Examples:
|
||||
# outputs ~/.ghcup/ghc/8.10.5/bin/ghc.exe
|
||||
ghcup whereis ghc 8.10.5
|
||||
# outputs ~/.ghcup/ghc/8.10.5/bin/
|
||||
ghcup whereis --directory ghc 8.10.5 |]
|
||||
|
||||
whereisCabalFooter = [s|Discussion:
|
||||
Finds the location of a Cabal executable, which usually resides in
|
||||
"~/.ghcup/bin/".
|
||||
|
||||
Examples:
|
||||
# outputs ~/.ghcup/bin/cabal-3.4.0.0
|
||||
ghcup whereis cabal 3.4.0.0
|
||||
# outputs ~/.ghcup/bin
|
||||
ghcup whereis --directory cabal 3.4.0.0|]
|
||||
|
||||
whereisHLSFooter = [s|Discussion:
|
||||
Finds the location of a HLS executable, which usually resides in
|
||||
"~/.ghcup/bin/".
|
||||
|
||||
Examples:
|
||||
# outputs ~/.ghcup/bin/haskell-language-server-wrapper-1.2.0
|
||||
ghcup whereis hls 1.2.0
|
||||
# outputs ~/.ghcup/bin/
|
||||
ghcup whereis --directory hls 1.2.0|]
|
||||
|
||||
whereisStackFooter = [s|Discussion:
|
||||
Finds the location of a stack executable, which usually resides in
|
||||
"~/.ghcup/bin/".
|
||||
|
||||
Examples:
|
||||
# outputs ~/.ghcup/bin/stack-2.7.1
|
||||
ghcup whereis stack 2.7.1
|
||||
# outputs ~/.ghcup/bin/
|
||||
ghcup whereis --directory stack 2.7.1|]
|
||||
|
||||
|
||||
|
||||
--------------
|
||||
--[ Footer ]--
|
||||
--------------
|
||||
|
||||
|
||||
whereisFooter :: String
|
||||
whereisFooter = [s|Discussion:
|
||||
Finds the location of a tool. For GHC, this is the ghc binary, that
|
||||
usually resides in a self-contained "~/.ghcup/ghc/<ghcver>" directory.
|
||||
For cabal/stack/hls this the binary usually at "~/.ghcup/bin/<tool>-<ver>".
|
||||
|
||||
Examples:
|
||||
# outputs ~/.ghcup/ghc/8.10.5/bin/ghc.exe
|
||||
ghcup whereis ghc 8.10.5
|
||||
# outputs ~/.ghcup/ghc/8.10.5/bin/
|
||||
ghcup whereis --directory ghc 8.10.5
|
||||
# outputs ~/.ghcup/bin/cabal-3.4.0.0
|
||||
ghcup whereis cabal 3.4.0.0
|
||||
# outputs ~/.ghcup/bin/
|
||||
ghcup whereis --directory cabal 3.4.0.0|]
|
||||
|
||||
|
||||
|
||||
|
||||
---------------------------
|
||||
--[ Effect interpreters ]--
|
||||
---------------------------
|
||||
|
||||
|
||||
type WhereisEffects = '[ NotInstalled
|
||||
, NoToolVersionSet
|
||||
, NextVerNotFound
|
||||
, TagNotFound
|
||||
]
|
||||
|
||||
|
||||
runLeanWhereIs :: (MonadUnliftIO m, MonadIO m)
|
||||
=> LeanAppState
|
||||
-> Excepts WhereisEffects (ReaderT LeanAppState m) a
|
||||
-> m (VEither WhereisEffects a)
|
||||
runLeanWhereIs leanAppstate =
|
||||
-- Don't use runLeanAppState here, which is disabled on windows.
|
||||
-- This is the only command on all platforms that doesn't need full appstate.
|
||||
flip runReaderT leanAppstate
|
||||
. runE
|
||||
@WhereisEffects
|
||||
|
||||
|
||||
runWhereIs :: (MonadUnliftIO m, MonadIO m)
|
||||
=> (ReaderT AppState m (VEither WhereisEffects a) -> m (VEither WhereisEffects a))
|
||||
-> Excepts WhereisEffects (ReaderT AppState m) a
|
||||
-> m (VEither WhereisEffects a)
|
||||
runWhereIs runAppState =
|
||||
runAppState
|
||||
. runE
|
||||
@WhereisEffects
|
||||
|
||||
|
||||
|
||||
------------------
|
||||
--[ Entrypoint ]--
|
||||
------------------
|
||||
|
||||
|
||||
|
||||
whereis :: ( Monad m
|
||||
, MonadMask m
|
||||
, MonadUnliftIO m
|
||||
, MonadFail m
|
||||
)
|
||||
=> WhereisCommand
|
||||
-> WhereisOptions
|
||||
-> (forall a. ReaderT AppState m (VEither WhereisEffects a) -> m (VEither WhereisEffects a))
|
||||
-> LeanAppState
|
||||
-> (ReaderT LeanAppState m () -> m ())
|
||||
-> m ExitCode
|
||||
whereis whereisCommand whereisOptions runAppState leanAppstate runLogger = do
|
||||
Dirs{ .. } <- runReaderT getDirs leanAppstate
|
||||
case (whereisCommand, whereisOptions) of
|
||||
(WhereisTool tool (Just (GHCVersion v)), WhereisOptions{..}) ->
|
||||
runLeanWhereIs leanAppstate (do
|
||||
loc <- liftE $ whereIsTool tool v
|
||||
if directory
|
||||
then pure $ takeDirectory loc
|
||||
else pure loc
|
||||
)
|
||||
>>= \case
|
||||
VRight r -> do
|
||||
liftIO $ putStr r
|
||||
pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 30
|
||||
(WhereisTool tool (Just (ToolVersion v)), WhereisOptions{..}) ->
|
||||
runLeanWhereIs leanAppstate (do
|
||||
loc <- liftE $ whereIsTool tool (mkTVer v)
|
||||
if directory
|
||||
then pure $ takeDirectory loc
|
||||
else pure loc
|
||||
)
|
||||
>>= \case
|
||||
VRight r -> do
|
||||
liftIO $ putStr r
|
||||
pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 30
|
||||
|
||||
(WhereisTool tool whereVer, WhereisOptions{..}) -> do
|
||||
runWhereIs runAppState (do
|
||||
(v, _) <- liftE $ fromVersion whereVer tool
|
||||
loc <- liftE $ whereIsTool tool v
|
||||
if directory
|
||||
then pure $ takeDirectory loc
|
||||
else pure loc
|
||||
)
|
||||
>>= \case
|
||||
VRight r -> do
|
||||
liftIO $ putStr r
|
||||
pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 30
|
||||
|
||||
(WhereisBaseDir, _) -> do
|
||||
liftIO $ putStr $ fromGHCupPath baseDir
|
||||
pure ExitSuccess
|
||||
|
||||
(WhereisBinDir, _) -> do
|
||||
liftIO $ putStr binDir
|
||||
pure ExitSuccess
|
||||
|
||||
(WhereisCacheDir, _) -> do
|
||||
liftIO $ putStr $ fromGHCupPath cacheDir
|
||||
pure ExitSuccess
|
||||
|
||||
(WhereisLogsDir, _) -> do
|
||||
liftIO $ putStr $ fromGHCupPath logsDir
|
||||
pure ExitSuccess
|
||||
|
||||
(WhereisConfDir, _) -> do
|
||||
liftIO $ putStr $ fromGHCupPath confDir
|
||||
pure ExitSuccess
|
||||
1129
app/ghcup/Main.hs
@@ -1,201 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# safety subshell to avoid executing anything in case this script is not downloaded properly
|
||||
(
|
||||
|
||||
: "${GHCUP_INSTALL_BASE_PREFIX:=$HOME}"
|
||||
|
||||
die() {
|
||||
(>&2 printf "\\033[0;31m%s\\033[0m\\n" "$1")
|
||||
exit 2
|
||||
}
|
||||
|
||||
edo()
|
||||
{
|
||||
"$@" || die "\"$*\" failed!"
|
||||
}
|
||||
|
||||
eghcup() {
|
||||
if [ -z "${BOOTSTRAP_HASKELL_VERBOSE}" ] ; then
|
||||
edo ghcup "$@"
|
||||
else
|
||||
edo ghcup --verbose "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
download_ghcup() {
|
||||
_plat="$(uname -s)"
|
||||
_arch=$(uname -m)
|
||||
|
||||
case "${_plat}" in
|
||||
"linux"|"Linux")
|
||||
case "${_arch}" in
|
||||
x86_64|amd64)
|
||||
_url=https://downloads.haskell.org/~ghcup/x86_64-linux-ghcup
|
||||
;;
|
||||
i*86)
|
||||
_url=https://downloads.haskell.org/~ghcup/i386-linux-ghcup
|
||||
;;
|
||||
*) die "Unknown architecture: ${_arch}"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
"FreeBSD"|"freebsd")
|
||||
case "${_arch}" in
|
||||
x86_64|amd64)
|
||||
;;
|
||||
i*86)
|
||||
die "i386 currently not supported!"
|
||||
;;
|
||||
*) die "Unknown architecture: ${_arch}"
|
||||
;;
|
||||
esac
|
||||
_url=https://downloads.haskell.org/~ghcup/x86_64-portbld-freebsd-ghcup
|
||||
;;
|
||||
"Darwin"|"darwin")
|
||||
case "${_arch}" in
|
||||
x86_64|amd64)
|
||||
;;
|
||||
i*86)
|
||||
die "i386 currently not supported!"
|
||||
;;
|
||||
*) die "Unknown architecture: ${_arch}"
|
||||
;;
|
||||
esac
|
||||
_url=https://downloads.haskell.org/~ghcup/x86_64-apple-darwin-ghcup ;;
|
||||
*) die "Unknown platform: ${_plat}"
|
||||
;;
|
||||
esac
|
||||
|
||||
edo curl -Lf "${_url}" > "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin/ghcup
|
||||
|
||||
unset _plat _arch _url
|
||||
}
|
||||
|
||||
|
||||
echo
|
||||
echo "Welcome to Haskell!"
|
||||
echo
|
||||
echo "This will download and install the Glasgow Haskell Compiler (GHC)"
|
||||
echo "and the Cabal build tool."
|
||||
echo
|
||||
echo "ghcup installs only into the following directory, which can be removed anytime:"
|
||||
echo " $GHCUP_INSTALL_BASE_PREFIX/.ghcup"
|
||||
echo
|
||||
|
||||
if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then
|
||||
printf "\\033[0;35m%s\\033[0m\\n" "Press ENTER to proceed"
|
||||
printf "\\033[0;35m%s\\033[0m\\n" "or ctrl-c to abort."
|
||||
printf "\\033[0;35m%s\\033[0m\\n" "Note that this script can be re-run at any given time."
|
||||
echo
|
||||
# Wait for user input to continue.
|
||||
# shellcheck disable=SC2034
|
||||
read -r answer </dev/tty
|
||||
fi
|
||||
|
||||
edo mkdir -p "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin
|
||||
|
||||
if command -V "ghcup" >/dev/null 2>&1 ; then
|
||||
if [ -z "${BOOTSTRAP_HASKELL_NO_UPGRADE}" ] ; then
|
||||
eghcup upgrade
|
||||
fi
|
||||
else
|
||||
download_ghcup
|
||||
edo chmod +x "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin/ghcup
|
||||
|
||||
cat <<-EOF > "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/env || die "Failed to create env file"
|
||||
export PATH="\$HOME/.cabal/bin:\${GHCUP_INSTALL_BASE_PREFIX:=\$HOME}/.ghcup/bin:\$PATH"
|
||||
EOF
|
||||
# shellcheck disable=SC1090
|
||||
edo . "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/env
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "$(ghcup tool-requirements)"
|
||||
echo
|
||||
|
||||
if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then
|
||||
printf "\\033[0;35m%s\\033[0m\\n" "Press ENTER to proceed"
|
||||
printf "\\033[0;35m%s\\033[0m\\n" "or ctrl-c to abort."
|
||||
printf "\\033[0;35m%s\\033[0m\\n" "Installation may take a while."
|
||||
echo
|
||||
|
||||
# Wait for user input to continue.
|
||||
# shellcheck disable=SC2034
|
||||
read -r answer </dev/tty
|
||||
fi
|
||||
|
||||
eghcup --cache install
|
||||
|
||||
eghcup set
|
||||
eghcup --cache install-cabal
|
||||
|
||||
edo cabal new-update
|
||||
|
||||
printf "\\033[0;35m%s\\033[0m\\n" ""
|
||||
printf "\\033[0;35m%s\\033[0m\\n" "Installation done!"
|
||||
printf "\\033[0;35m%s\\033[0m\\n" ""
|
||||
|
||||
if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then
|
||||
echo "In order to run ghc and cabal, you need to adjust your PATH variable."
|
||||
echo "You may want to source '$GHCUP_INSTALL_BASE_PREFIX/.ghcup/env' in your shell"
|
||||
echo "configuration to do so (e.g. ~/.bashrc)."
|
||||
|
||||
case $SHELL in
|
||||
*/zsh) # login shell is zsh
|
||||
GHCUP_PROFILE_FILE="$HOME/.zshrc"
|
||||
MY_SHELL="zsh" ;;
|
||||
*/bash) # login shell is bash
|
||||
if [ -f "$HOME/.bashrc" ] ; then # bashrc is not sourced by default, so assume it isn't if file does not exist
|
||||
GHCUP_PROFILE_FILE="$HOME/.bashrc"
|
||||
else
|
||||
GHCUP_PROFILE_FILE="$HOME/.bash_profile"
|
||||
fi
|
||||
|
||||
MY_SHELL="bash" ;;
|
||||
*/sh) # login shell is sh, but might be a symlink to bash or zsh
|
||||
if [ -n "${BASH}" ] ; then
|
||||
if [ -f "$HOME/.bashrc" ] ; then # bashrc is not sourced by default, so assume it isn't if file does not exist
|
||||
GHCUP_PROFILE_FILE="$HOME/.bashrc"
|
||||
else
|
||||
GHCUP_PROFILE_FILE="$HOME/.bash_profile"
|
||||
fi
|
||||
|
||||
MY_SHELL="bash"
|
||||
elif [ -n "${ZSH_VERSION}" ] ; then
|
||||
GHCUP_PROFILE_FILE="$HOME/.zshrc"
|
||||
MY_SHELL="zsh"
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
;;
|
||||
*) exit 0 ;;
|
||||
esac
|
||||
|
||||
|
||||
printf "\\033[0;35m%s\\033[0m\\n" ""
|
||||
printf "\\033[0;35m%s\\033[0m\\n" "Detected ${MY_SHELL} shell on your system..."
|
||||
printf "\\033[0;35m%s\\033[0m\\n" "If you want ghcup to automatically add the required PATH variable to \"${GHCUP_PROFILE_FILE}\""
|
||||
printf "\\033[0;35m%s\\033[0m\\n" "answer with YES, otherwise with NO and press ENTER."
|
||||
printf "\\033[0;35m%s\\033[0m\\n" ""
|
||||
|
||||
while true; do
|
||||
read -r next_answer </dev/tty
|
||||
|
||||
case $next_answer in
|
||||
[Yy]*)
|
||||
echo "[ -f \"\${GHCUP_INSTALL_BASE_PREFIX:=\$HOME}/.ghcup/env\" ] && source \"\${GHCUP_INSTALL_BASE_PREFIX:=\$HOME}/.ghcup/env\"" >> "${GHCUP_PROFILE_FILE}"
|
||||
printf "\\033[0;35m%s\\033[0m\\n" "OK! ${GHCUP_PROFILE_FILE} has been modified. Restart your terminal for the changes to take effect,"
|
||||
printf "\\033[0;35m%s\\033[0m\\n" "or type \"source ${GHCUP_INSTALL_BASE_PREFIX}/.ghcup/env\" to apply them in your current terminal session."
|
||||
exit 0;;
|
||||
[Nn]*)
|
||||
exit 0;;
|
||||
*)
|
||||
echo "Please type YES or NO and press enter.";;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
)
|
||||
|
||||
# vim: tabstop=4 shiftwidth=4 expandtab
|
||||
|
||||
37
cabal.ghc8107.project
Normal file
@@ -0,0 +1,37 @@
|
||||
packages: ./ghcup.cabal
|
||||
|
||||
optional-packages: ./vendored/*/*.cabal
|
||||
|
||||
optimization: 2
|
||||
|
||||
package ghcup
|
||||
tests: True
|
||||
flags: +tui
|
||||
|
||||
source-repository-package
|
||||
type: git
|
||||
location: https://github.com/bgamari/terminal-size.git
|
||||
tag: 34ea816bd63f75f800eedac12c6908c6f3736036
|
||||
|
||||
constraints: http-io-streams -brotli,
|
||||
any.Cabal ==3.6.2.0,
|
||||
any.aeson >= 2.0.1.0,
|
||||
|
||||
package libarchive
|
||||
flags: -system-libarchive
|
||||
|
||||
package aeson-pretty
|
||||
flags: +lib-only
|
||||
|
||||
package cabal-plan
|
||||
flags: -exe
|
||||
|
||||
package aeson
|
||||
flags: +ordered-keymap
|
||||
|
||||
package streamly
|
||||
flags: +use-unliftio
|
||||
|
||||
allow-newer: base, ghc-prim, template-haskell, language-c
|
||||
|
||||
with-compiler: ghc-8.10.7
|
||||
238
cabal.ghc8107.project.freeze
Normal file
@@ -0,0 +1,238 @@
|
||||
active-repositories: hackage.haskell.org:merge
|
||||
constraints: any.Cabal ==3.6.2.0,
|
||||
Cabal -bundled-binary-generic,
|
||||
any.HUnit ==1.6.2.0,
|
||||
any.HsOpenSSL ==0.11.7.2,
|
||||
HsOpenSSL -fast-bignum -homebrew-openssl -macports-openssl -use-pkg-config,
|
||||
any.OneTuple ==0.3.1,
|
||||
any.QuickCheck ==2.14.2,
|
||||
QuickCheck -old-random +templatehaskell,
|
||||
any.StateVar ==1.2.2,
|
||||
any.abstract-deque ==0.3,
|
||||
abstract-deque -usecas,
|
||||
any.aeson ==2.0.3.0,
|
||||
aeson -cffi +ordered-keymap,
|
||||
any.aeson-pretty ==0.8.9,
|
||||
aeson-pretty +lib-only,
|
||||
any.alex ==3.2.7.1,
|
||||
any.ansi-terminal ==0.11.3,
|
||||
ansi-terminal -example,
|
||||
any.ansi-wl-pprint ==0.6.9,
|
||||
ansi-wl-pprint -example,
|
||||
any.array ==0.5.4.0,
|
||||
any.assoc ==1.0.2,
|
||||
any.async ==2.2.4,
|
||||
async -bench,
|
||||
any.atomic-primops ==0.8.4,
|
||||
atomic-primops -debug,
|
||||
any.attoparsec ==0.14.4,
|
||||
attoparsec -developer,
|
||||
any.base ==4.14.3.0,
|
||||
any.base-compat ==0.12.1,
|
||||
any.base-compat-batteries ==0.12.1,
|
||||
any.base-orphans ==0.8.6,
|
||||
any.base16-bytestring ==1.0.2.0,
|
||||
any.base64-bytestring ==1.2.1.0,
|
||||
any.bifunctors ==5.5.12,
|
||||
bifunctors +semigroups +tagged,
|
||||
any.binary ==0.8.8.0,
|
||||
any.blaze-builder ==0.4.2.2,
|
||||
any.brick ==0.64.2,
|
||||
brick -demos,
|
||||
any.bytestring ==0.10.12.0,
|
||||
any.bz2 ==1.0.1.0,
|
||||
bz2 -cross +with-bzlib,
|
||||
any.c2hs ==0.28.8,
|
||||
c2hs +base3 -regression,
|
||||
any.cabal-plan ==0.7.2.1,
|
||||
cabal-plan -_ -exe -license-report,
|
||||
any.call-stack ==0.4.0,
|
||||
any.case-insensitive ==1.2.1.0,
|
||||
any.casing ==0.1.4.1,
|
||||
any.chs-cabal ==0.1.1.1,
|
||||
any.chs-deps ==0.1.0.0,
|
||||
chs-deps -cross,
|
||||
any.clock ==0.8.3,
|
||||
clock -llvm,
|
||||
any.colour ==2.3.6,
|
||||
any.comonad ==5.0.8,
|
||||
comonad +containers +distributive +indexed-traversable,
|
||||
any.composition-prelude ==3.0.0.2,
|
||||
composition-prelude -development,
|
||||
any.config-ini ==0.2.4.0,
|
||||
config-ini -enable-doctests,
|
||||
any.containers ==0.6.5.1,
|
||||
any.contravariant ==1.5.5,
|
||||
contravariant +semigroups +statevar +tagged,
|
||||
any.cpphs ==1.20.9.1,
|
||||
cpphs -old-locale,
|
||||
any.cryptohash-sha1 ==0.11.101.0,
|
||||
any.cryptohash-sha256 ==0.11.102.1,
|
||||
cryptohash-sha256 -exe +use-cbits,
|
||||
any.data-clist ==0.2,
|
||||
any.data-fix ==0.3.2,
|
||||
any.deepseq ==1.4.4.0,
|
||||
any.directory ==1.3.6.0,
|
||||
any.disk-free-space ==0.1.0.1,
|
||||
any.distributive ==0.6.2.1,
|
||||
distributive +semigroups +tagged,
|
||||
any.dlist ==1.0,
|
||||
dlist -werror,
|
||||
any.exceptions ==0.10.4,
|
||||
any.filepath ==1.4.2.1,
|
||||
any.free ==5.1.8,
|
||||
any.fusion-plugin-types ==0.1.0,
|
||||
any.generic-arbitrary ==0.2.2,
|
||||
any.ghc ==8.10.7,
|
||||
any.ghc-boot ==8.10.7,
|
||||
any.ghc-boot-th ==8.10.7,
|
||||
any.ghc-byteorder ==4.11.0.0.10,
|
||||
any.ghc-heap ==8.10.7,
|
||||
any.ghc-prim ==0.6.1,
|
||||
any.ghci ==8.10.7,
|
||||
any.happy ==1.20.0,
|
||||
any.hashable ==1.4.0.2,
|
||||
hashable +containers +integer-gmp -random-initial-seed,
|
||||
any.haskus-utils-data ==1.4,
|
||||
any.haskus-utils-types ==1.5.1,
|
||||
any.haskus-utils-variant ==3.2.1,
|
||||
any.heaps ==0.4,
|
||||
any.hpc ==0.6.1.0,
|
||||
any.hsc2hs ==0.68.8,
|
||||
hsc2hs -in-ghc-tree,
|
||||
any.hspec ==2.9.7,
|
||||
any.hspec-core ==2.9.7,
|
||||
any.hspec-discover ==2.9.7,
|
||||
any.hspec-expectations ==0.8.2,
|
||||
any.hspec-golden-aeson ==0.9.0.0,
|
||||
any.http-io-streams ==0.1.6.1,
|
||||
http-io-streams -brotli +fast-xor,
|
||||
any.indexed-profunctors ==0.1.1,
|
||||
any.indexed-traversable ==0.1.2,
|
||||
any.indexed-traversable-instances ==0.1.1,
|
||||
any.integer-gmp ==1.0.3.0,
|
||||
any.integer-logarithms ==1.0.3.1,
|
||||
integer-logarithms -check-bounds +integer-gmp,
|
||||
any.io-streams ==1.5.2.1,
|
||||
io-streams +network -nointeractivetests +zlib,
|
||||
any.language-c ==0.9.1,
|
||||
language-c -allwarnings +iecfpextension +usebytestrings,
|
||||
any.libarchive ==3.0.3.2,
|
||||
libarchive -cross -low-memory +no-exe -system-libarchive,
|
||||
any.libyaml-streamly ==0.2.1,
|
||||
libyaml-streamly -no-unicode -system-libyaml,
|
||||
any.lockfree-queue ==0.2.3.1,
|
||||
any.lzma-static ==5.2.5.4,
|
||||
any.megaparsec ==9.2.1,
|
||||
megaparsec -dev,
|
||||
any.microlens ==0.4.12.0,
|
||||
any.microlens-mtl ==0.2.0.2,
|
||||
any.microlens-th ==0.4.3.10,
|
||||
any.mtl ==2.2.2,
|
||||
any.network ==3.1.2.7,
|
||||
network -devel,
|
||||
any.network-uri ==2.6.4.1,
|
||||
any.openssl-streams ==1.2.3.0,
|
||||
any.optics ==0.4.2,
|
||||
any.optics-core ==0.4.1,
|
||||
optics-core -explicit-generic-labels,
|
||||
any.optics-extra ==0.4.2.1,
|
||||
any.optics-th ==0.4.1,
|
||||
any.optparse-applicative ==0.17.0.0,
|
||||
optparse-applicative +process,
|
||||
any.os-release ==1.0.2.1,
|
||||
os-release -devel,
|
||||
any.parallel ==3.2.2.0,
|
||||
any.parsec ==3.1.14.0,
|
||||
any.parser-combinators ==1.3.0,
|
||||
parser-combinators -dev,
|
||||
any.polyparse ==1.13,
|
||||
any.pretty ==1.1.3.6,
|
||||
any.pretty-terminal ==0.1.0.0,
|
||||
any.primitive ==0.7.4.0,
|
||||
any.process ==1.6.13.2,
|
||||
any.profunctors ==5.6.2,
|
||||
any.quickcheck-arbitrary-adt ==0.3.1.0,
|
||||
any.quickcheck-io ==0.2.0,
|
||||
any.random ==1.2.1.1,
|
||||
any.recursion-schemes ==5.2.2.2,
|
||||
recursion-schemes +template-haskell,
|
||||
any.regex-base ==0.94.0.2,
|
||||
any.regex-posix ==0.96.0.1,
|
||||
regex-posix -_regex-posix-clib,
|
||||
any.resourcet ==1.2.5,
|
||||
any.retry ==0.8.1.2,
|
||||
retry -lib-werror,
|
||||
any.rts ==1.0.1,
|
||||
any.safe ==0.3.19,
|
||||
any.safe-exceptions ==0.1.7.3,
|
||||
any.scientific ==0.3.7.0,
|
||||
scientific -bytestring-builder -integer-simple,
|
||||
any.semialign ==1.2.0.1,
|
||||
semialign +semigroupoids,
|
||||
any.semigroupoids ==5.3.7,
|
||||
semigroupoids +comonad +containers +contravariant +distributive +tagged +unordered-containers,
|
||||
any.setenv ==0.1.1.3,
|
||||
any.split ==0.2.3.4,
|
||||
any.splitmix ==0.1.0.4,
|
||||
splitmix -optimised-mixer,
|
||||
any.stm ==2.5.0.1,
|
||||
any.streamly ==0.8.2,
|
||||
streamly -debug -dev -fusion-plugin -has-llvm -inspection -limit-build-mem -no-fusion +opt -streamk -streamly-core -use-c-malloc +use-unliftio,
|
||||
any.strict ==0.4.0.1,
|
||||
strict +assoc,
|
||||
any.strict-base ==0.4.0.0,
|
||||
any.tagged ==0.8.6.1,
|
||||
tagged +deepseq +transformers,
|
||||
any.tagsoup ==0.14.8,
|
||||
any.template-haskell ==2.16.0.0,
|
||||
any.temporary ==1.3,
|
||||
any.terminal-progress-bar ==0.4.1,
|
||||
any.terminal-size ==0.3.2.1,
|
||||
any.terminfo ==0.4.1.4,
|
||||
any.text ==1.2.4.1,
|
||||
any.text-short ==0.1.5,
|
||||
text-short -asserts,
|
||||
any.text-zipper ==0.11,
|
||||
any.tf-random ==0.5,
|
||||
any.th-abstraction ==0.4.3.0,
|
||||
any.th-compat ==0.1.3,
|
||||
any.th-lift ==0.8.2,
|
||||
any.th-lift-instances ==0.1.19,
|
||||
any.these ==1.1.1.1,
|
||||
these +assoc,
|
||||
any.time ==1.9.3,
|
||||
any.time-compat ==1.9.6.1,
|
||||
time-compat -old-locale,
|
||||
any.transformers ==0.5.6.2,
|
||||
any.transformers-base ==0.4.6,
|
||||
transformers-base +orphaninstances,
|
||||
any.transformers-compat ==0.7.1,
|
||||
transformers-compat -five +five-three -four +generic-deriving +mtl -three -two,
|
||||
any.unicode-data ==0.3.0,
|
||||
unicode-data -ucd2haskell,
|
||||
any.unix ==2.7.2.2,
|
||||
any.unix-bytestring ==0.3.7.7,
|
||||
any.unix-compat ==0.6,
|
||||
unix-compat -old-time,
|
||||
any.unliftio-core ==0.2.0.1,
|
||||
any.unordered-containers ==0.2.19.1,
|
||||
unordered-containers -debug,
|
||||
any.uri-bytestring ==0.3.3.1,
|
||||
uri-bytestring -lib-werror,
|
||||
any.utf8-string ==1.0.2,
|
||||
any.uuid-types ==1.0.5,
|
||||
any.vector ==0.12.3.1,
|
||||
vector +boundschecks -internalchecks -unsafechecks -wall,
|
||||
any.versions ==5.0.3,
|
||||
any.vty ==5.33,
|
||||
any.witherable ==0.4.2,
|
||||
any.word-wrap ==0.5,
|
||||
any.word8 ==0.1.3,
|
||||
any.xor ==0.0.1.1,
|
||||
any.yaml-streamly ==0.12.1,
|
||||
yaml-streamly +no-examples +no-exe,
|
||||
any.zlib ==0.6.3.0,
|
||||
zlib -bundled-c-zlib -non-blocking-ffi -pkg-config,
|
||||
any.zlib-bindings ==0.1.1.5
|
||||
index-state: hackage.haskell.org 2022-06-04T19:47:01Z
|
||||
37
cabal.ghc902.project
Normal file
@@ -0,0 +1,37 @@
|
||||
packages: ./ghcup.cabal
|
||||
|
||||
optional-packages: ./vendored/*/*.cabal
|
||||
|
||||
optimization: 2
|
||||
|
||||
package ghcup
|
||||
tests: True
|
||||
flags: +tui
|
||||
|
||||
source-repository-package
|
||||
type: git
|
||||
location: https://github.com/bgamari/terminal-size.git
|
||||
tag: 34ea816bd63f75f800eedac12c6908c6f3736036
|
||||
|
||||
constraints: http-io-streams -brotli,
|
||||
any.Cabal ==3.6.2.0,
|
||||
any.aeson >= 2.0.1.0,
|
||||
|
||||
package libarchive
|
||||
flags: -system-libarchive
|
||||
|
||||
package aeson-pretty
|
||||
flags: +lib-only
|
||||
|
||||
package cabal-plan
|
||||
flags: -exe
|
||||
|
||||
package aeson
|
||||
flags: +ordered-keymap
|
||||
|
||||
package streamly
|
||||
flags: +use-unliftio
|
||||
|
||||
allow-newer: base, ghc-prim, template-haskell, language-c
|
||||
|
||||
with-compiler: ghc-9.0.2
|
||||
238
cabal.ghc902.project.freeze
Normal file
@@ -0,0 +1,238 @@
|
||||
active-repositories: hackage.haskell.org:merge
|
||||
constraints: any.Cabal ==3.6.2.0,
|
||||
Cabal -bundled-binary-generic,
|
||||
any.HUnit ==1.6.2.0,
|
||||
any.HsOpenSSL ==0.11.7.2,
|
||||
HsOpenSSL -fast-bignum -homebrew-openssl -macports-openssl -use-pkg-config,
|
||||
any.OneTuple ==0.3.1,
|
||||
any.QuickCheck ==2.14.2,
|
||||
QuickCheck -old-random +templatehaskell,
|
||||
any.StateVar ==1.2.2,
|
||||
any.abstract-deque ==0.3,
|
||||
abstract-deque -usecas,
|
||||
any.aeson ==2.0.3.0,
|
||||
aeson -cffi +ordered-keymap,
|
||||
any.aeson-pretty ==0.8.9,
|
||||
aeson-pretty +lib-only,
|
||||
any.alex ==3.2.7.1,
|
||||
any.ansi-terminal ==0.11.3,
|
||||
ansi-terminal -example,
|
||||
any.ansi-wl-pprint ==0.6.9,
|
||||
ansi-wl-pprint -example,
|
||||
any.array ==0.5.4.0,
|
||||
any.assoc ==1.0.2,
|
||||
any.async ==2.2.4,
|
||||
async -bench,
|
||||
any.atomic-primops ==0.8.4,
|
||||
atomic-primops -debug,
|
||||
any.attoparsec ==0.14.4,
|
||||
attoparsec -developer,
|
||||
any.base ==4.15.1.0,
|
||||
any.base-compat ==0.12.1,
|
||||
any.base-compat-batteries ==0.12.1,
|
||||
any.base-orphans ==0.8.6,
|
||||
any.base16-bytestring ==1.0.2.0,
|
||||
any.base64-bytestring ==1.2.1.0,
|
||||
any.bifunctors ==5.5.12,
|
||||
bifunctors +semigroups +tagged,
|
||||
any.binary ==0.8.8.0,
|
||||
any.blaze-builder ==0.4.2.2,
|
||||
any.brick ==0.64.2,
|
||||
brick -demos,
|
||||
any.bytestring ==0.10.12.1,
|
||||
any.bz2 ==1.0.1.0,
|
||||
bz2 -cross +with-bzlib,
|
||||
any.c2hs ==0.28.8,
|
||||
c2hs +base3 -regression,
|
||||
any.cabal-plan ==0.7.2.1,
|
||||
cabal-plan -_ -exe -license-report,
|
||||
any.call-stack ==0.4.0,
|
||||
any.case-insensitive ==1.2.1.0,
|
||||
any.casing ==0.1.4.1,
|
||||
any.chs-cabal ==0.1.1.1,
|
||||
any.chs-deps ==0.1.0.0,
|
||||
chs-deps -cross,
|
||||
any.clock ==0.8.3,
|
||||
clock -llvm,
|
||||
any.colour ==2.3.6,
|
||||
any.comonad ==5.0.8,
|
||||
comonad +containers +distributive +indexed-traversable,
|
||||
any.composition-prelude ==3.0.0.2,
|
||||
composition-prelude -development,
|
||||
any.config-ini ==0.2.4.0,
|
||||
config-ini -enable-doctests,
|
||||
any.containers ==0.6.4.1,
|
||||
any.contravariant ==1.5.5,
|
||||
contravariant +semigroups +statevar +tagged,
|
||||
any.cpphs ==1.20.9.1,
|
||||
cpphs -old-locale,
|
||||
any.cryptohash-sha1 ==0.11.101.0,
|
||||
any.cryptohash-sha256 ==0.11.102.1,
|
||||
cryptohash-sha256 -exe +use-cbits,
|
||||
any.data-clist ==0.2,
|
||||
any.data-fix ==0.3.2,
|
||||
any.deepseq ==1.4.5.0,
|
||||
any.directory ==1.3.6.2,
|
||||
any.disk-free-space ==0.1.0.1,
|
||||
any.distributive ==0.6.2.1,
|
||||
distributive +semigroups +tagged,
|
||||
any.dlist ==1.0,
|
||||
dlist -werror,
|
||||
any.exceptions ==0.10.4,
|
||||
any.filepath ==1.4.2.1,
|
||||
any.free ==5.1.8,
|
||||
any.fusion-plugin-types ==0.1.0,
|
||||
any.generic-arbitrary ==0.2.2,
|
||||
any.ghc ==9.0.2,
|
||||
any.ghc-bignum ==1.1,
|
||||
any.ghc-boot ==9.0.2,
|
||||
any.ghc-boot-th ==9.0.2,
|
||||
any.ghc-byteorder ==4.11.0.0.10,
|
||||
any.ghc-heap ==9.0.2,
|
||||
any.ghc-prim ==0.7.0,
|
||||
any.ghci ==9.0.2,
|
||||
any.happy ==1.20.0,
|
||||
any.hashable ==1.4.0.2,
|
||||
hashable +containers +integer-gmp -random-initial-seed,
|
||||
any.haskus-utils-data ==1.4,
|
||||
any.haskus-utils-types ==1.5.1,
|
||||
any.haskus-utils-variant ==3.2.1,
|
||||
any.heaps ==0.4,
|
||||
any.hpc ==0.6.1.0,
|
||||
any.hsc2hs ==0.68.8,
|
||||
hsc2hs -in-ghc-tree,
|
||||
any.hspec ==2.9.7,
|
||||
any.hspec-core ==2.9.7,
|
||||
any.hspec-discover ==2.9.7,
|
||||
any.hspec-expectations ==0.8.2,
|
||||
any.hspec-golden-aeson ==0.9.0.0,
|
||||
any.http-io-streams ==0.1.6.1,
|
||||
http-io-streams -brotli +fast-xor,
|
||||
any.indexed-profunctors ==0.1.1,
|
||||
any.indexed-traversable ==0.1.2,
|
||||
any.indexed-traversable-instances ==0.1.1,
|
||||
any.integer-logarithms ==1.0.3.1,
|
||||
integer-logarithms -check-bounds +integer-gmp,
|
||||
any.io-streams ==1.5.2.1,
|
||||
io-streams +network -nointeractivetests +zlib,
|
||||
any.language-c ==0.9.1,
|
||||
language-c -allwarnings +iecfpextension +usebytestrings,
|
||||
any.libarchive ==3.0.3.2,
|
||||
libarchive -cross -low-memory +no-exe -system-libarchive,
|
||||
any.libyaml-streamly ==0.2.1,
|
||||
libyaml-streamly -no-unicode -system-libyaml,
|
||||
any.lockfree-queue ==0.2.3.1,
|
||||
any.lzma-static ==5.2.5.4,
|
||||
any.megaparsec ==9.2.1,
|
||||
megaparsec -dev,
|
||||
any.microlens ==0.4.12.0,
|
||||
any.microlens-mtl ==0.2.0.2,
|
||||
any.microlens-th ==0.4.3.10,
|
||||
any.mtl ==2.2.2,
|
||||
any.network ==3.1.2.7,
|
||||
network -devel,
|
||||
any.network-uri ==2.6.4.1,
|
||||
any.openssl-streams ==1.2.3.0,
|
||||
any.optics ==0.4.2,
|
||||
any.optics-core ==0.4.1,
|
||||
optics-core -explicit-generic-labels,
|
||||
any.optics-extra ==0.4.2.1,
|
||||
any.optics-th ==0.4.1,
|
||||
any.optparse-applicative ==0.17.0.0,
|
||||
optparse-applicative +process,
|
||||
any.os-release ==1.0.2.1,
|
||||
os-release -devel,
|
||||
any.parallel ==3.2.2.0,
|
||||
any.parsec ==3.1.14.0,
|
||||
any.parser-combinators ==1.3.0,
|
||||
parser-combinators -dev,
|
||||
any.polyparse ==1.13,
|
||||
any.pretty ==1.1.3.6,
|
||||
any.pretty-terminal ==0.1.0.0,
|
||||
any.primitive ==0.7.4.0,
|
||||
any.process ==1.6.13.2,
|
||||
any.profunctors ==5.6.2,
|
||||
any.quickcheck-arbitrary-adt ==0.3.1.0,
|
||||
any.quickcheck-io ==0.2.0,
|
||||
any.random ==1.2.1.1,
|
||||
any.recursion-schemes ==5.2.2.2,
|
||||
recursion-schemes +template-haskell,
|
||||
any.regex-base ==0.94.0.2,
|
||||
any.regex-posix ==0.96.0.1,
|
||||
regex-posix -_regex-posix-clib,
|
||||
any.resourcet ==1.2.5,
|
||||
any.retry ==0.8.1.2,
|
||||
retry -lib-werror,
|
||||
any.rts ==1.0.2,
|
||||
any.safe ==0.3.19,
|
||||
any.safe-exceptions ==0.1.7.3,
|
||||
any.scientific ==0.3.7.0,
|
||||
scientific -bytestring-builder -integer-simple,
|
||||
any.semialign ==1.2.0.1,
|
||||
semialign +semigroupoids,
|
||||
any.semigroupoids ==5.3.7,
|
||||
semigroupoids +comonad +containers +contravariant +distributive +tagged +unordered-containers,
|
||||
any.setenv ==0.1.1.3,
|
||||
any.split ==0.2.3.4,
|
||||
any.splitmix ==0.1.0.4,
|
||||
splitmix -optimised-mixer,
|
||||
any.stm ==2.5.0.0,
|
||||
any.streamly ==0.8.2,
|
||||
streamly -debug -dev -fusion-plugin -has-llvm -inspection -limit-build-mem -no-fusion +opt -streamk -streamly-core -use-c-malloc +use-unliftio,
|
||||
any.strict ==0.4.0.1,
|
||||
strict +assoc,
|
||||
any.strict-base ==0.4.0.0,
|
||||
any.tagged ==0.8.6.1,
|
||||
tagged +deepseq +transformers,
|
||||
any.tagsoup ==0.14.8,
|
||||
any.template-haskell ==2.17.0.0,
|
||||
any.temporary ==1.3,
|
||||
any.terminal-progress-bar ==0.4.1,
|
||||
any.terminal-size ==0.3.2.1,
|
||||
any.terminfo ==0.4.1.5,
|
||||
any.text ==1.2.5.0,
|
||||
any.text-short ==0.1.5,
|
||||
text-short -asserts,
|
||||
any.text-zipper ==0.11,
|
||||
any.tf-random ==0.5,
|
||||
any.th-abstraction ==0.4.3.0,
|
||||
any.th-compat ==0.1.3,
|
||||
any.th-lift ==0.8.2,
|
||||
any.th-lift-instances ==0.1.19,
|
||||
any.these ==1.1.1.1,
|
||||
these +assoc,
|
||||
any.time ==1.9.3,
|
||||
any.time-compat ==1.9.6.1,
|
||||
time-compat -old-locale,
|
||||
any.transformers ==0.5.6.2,
|
||||
any.transformers-base ==0.4.6,
|
||||
transformers-base +orphaninstances,
|
||||
any.transformers-compat ==0.7.1,
|
||||
transformers-compat -five +five-three -four +generic-deriving +mtl -three -two,
|
||||
any.unicode-data ==0.3.0,
|
||||
unicode-data -ucd2haskell,
|
||||
any.unix ==2.7.2.2,
|
||||
any.unix-bytestring ==0.3.7.7,
|
||||
any.unix-compat ==0.6,
|
||||
unix-compat -old-time,
|
||||
any.unliftio-core ==0.2.0.1,
|
||||
any.unordered-containers ==0.2.19.1,
|
||||
unordered-containers -debug,
|
||||
any.uri-bytestring ==0.3.3.1,
|
||||
uri-bytestring -lib-werror,
|
||||
any.utf8-string ==1.0.2,
|
||||
any.uuid-types ==1.0.5,
|
||||
any.vector ==0.12.3.1,
|
||||
vector +boundschecks -internalchecks -unsafechecks -wall,
|
||||
any.versions ==5.0.3,
|
||||
any.vty ==5.33,
|
||||
any.witherable ==0.4.2,
|
||||
any.word-wrap ==0.5,
|
||||
any.word8 ==0.1.3,
|
||||
any.xor ==0.0.1.1,
|
||||
any.yaml-streamly ==0.12.1,
|
||||
yaml-streamly +no-examples +no-exe,
|
||||
any.zlib ==0.6.3.0,
|
||||
zlib -bundled-c-zlib -non-blocking-ffi -pkg-config,
|
||||
any.zlib-bindings ==0.1.1.5
|
||||
index-state: hackage.haskell.org 2022-06-04T19:47:01Z
|
||||
37
cabal.ghc923.project
Normal file
@@ -0,0 +1,37 @@
|
||||
packages: ./ghcup.cabal
|
||||
|
||||
optional-packages: ./vendored/*/*.cabal
|
||||
|
||||
optimization: 2
|
||||
|
||||
package ghcup
|
||||
tests: True
|
||||
flags: +tui
|
||||
|
||||
source-repository-package
|
||||
type: git
|
||||
location: https://github.com/bgamari/terminal-size.git
|
||||
tag: 34ea816bd63f75f800eedac12c6908c6f3736036
|
||||
|
||||
constraints: http-io-streams -brotli,
|
||||
any.Cabal ==3.6.2.0,
|
||||
any.aeson >= 2.0.1.0,
|
||||
|
||||
package libarchive
|
||||
flags: -system-libarchive
|
||||
|
||||
package aeson-pretty
|
||||
flags: +lib-only
|
||||
|
||||
package cabal-plan
|
||||
flags: -exe
|
||||
|
||||
package aeson
|
||||
flags: +ordered-keymap
|
||||
|
||||
package streamly
|
||||
flags: +use-unliftio
|
||||
|
||||
allow-newer: base, ghc-prim, template-haskell, language-c
|
||||
|
||||
with-compiler: ghc-9.2.3
|
||||
233
cabal.ghc923.project.freeze
Normal file
@@ -0,0 +1,233 @@
|
||||
active-repositories: hackage.haskell.org:merge
|
||||
constraints: any.Cabal ==3.6.2.0,
|
||||
Cabal -bundled-binary-generic,
|
||||
any.HUnit ==1.6.2.0,
|
||||
any.HsOpenSSL ==0.11.7.2,
|
||||
HsOpenSSL -fast-bignum -homebrew-openssl -macports-openssl -use-pkg-config,
|
||||
any.OneTuple ==0.3.1,
|
||||
any.QuickCheck ==2.14.2,
|
||||
QuickCheck -old-random +templatehaskell,
|
||||
any.StateVar ==1.2.2,
|
||||
any.abstract-deque ==0.3,
|
||||
abstract-deque -usecas,
|
||||
any.aeson ==2.0.3.0,
|
||||
aeson -cffi +ordered-keymap,
|
||||
any.aeson-pretty ==0.8.9,
|
||||
aeson-pretty +lib-only,
|
||||
any.alex ==3.2.7.1,
|
||||
any.ansi-terminal ==0.11.3,
|
||||
ansi-terminal -example,
|
||||
any.ansi-wl-pprint ==0.6.9,
|
||||
ansi-wl-pprint -example,
|
||||
any.array ==0.5.4.0,
|
||||
any.assoc ==1.0.2,
|
||||
any.async ==2.2.4,
|
||||
async -bench,
|
||||
any.atomic-primops ==0.8.4,
|
||||
atomic-primops -debug,
|
||||
any.attoparsec ==0.14.4,
|
||||
attoparsec -developer,
|
||||
any.base ==4.16.2.0,
|
||||
any.base-compat ==0.12.1,
|
||||
any.base-compat-batteries ==0.12.1,
|
||||
any.base-orphans ==0.8.6,
|
||||
any.base16-bytestring ==1.0.2.0,
|
||||
any.base64-bytestring ==1.2.1.0,
|
||||
any.bifunctors ==5.5.12,
|
||||
bifunctors +semigroups +tagged,
|
||||
any.binary ==0.8.9.0,
|
||||
any.blaze-builder ==0.4.2.2,
|
||||
any.brick ==0.64.2,
|
||||
brick -demos,
|
||||
any.bytestring ==0.11.3.1,
|
||||
any.bz2 ==1.0.1.0,
|
||||
bz2 -cross +with-bzlib,
|
||||
any.c2hs ==0.28.8,
|
||||
c2hs +base3 -regression,
|
||||
any.cabal-plan ==0.7.2.1,
|
||||
cabal-plan -_ -exe -license-report,
|
||||
any.call-stack ==0.4.0,
|
||||
any.case-insensitive ==1.2.1.0,
|
||||
any.casing ==0.1.4.1,
|
||||
any.chs-cabal ==0.1.1.1,
|
||||
any.chs-deps ==0.1.0.0,
|
||||
chs-deps -cross,
|
||||
any.clock ==0.8.3,
|
||||
clock -llvm,
|
||||
any.colour ==2.3.6,
|
||||
any.comonad ==5.0.8,
|
||||
comonad +containers +distributive +indexed-traversable,
|
||||
any.composition-prelude ==3.0.0.2,
|
||||
composition-prelude -development,
|
||||
any.config-ini ==0.2.4.0,
|
||||
config-ini -enable-doctests,
|
||||
any.containers ==0.6.5.1,
|
||||
any.contravariant ==1.5.5,
|
||||
contravariant +semigroups +statevar +tagged,
|
||||
any.cpphs ==1.20.9.1,
|
||||
cpphs -old-locale,
|
||||
any.cryptohash-sha1 ==0.11.101.0,
|
||||
any.cryptohash-sha256 ==0.11.102.1,
|
||||
cryptohash-sha256 -exe +use-cbits,
|
||||
any.data-clist ==0.2,
|
||||
any.data-fix ==0.3.2,
|
||||
any.deepseq ==1.4.6.1,
|
||||
any.directory ==1.3.7.0,
|
||||
any.disk-free-space ==0.1.0.1,
|
||||
any.distributive ==0.6.2.1,
|
||||
distributive +semigroups +tagged,
|
||||
any.dlist ==1.0,
|
||||
dlist -werror,
|
||||
any.exceptions ==0.10.4,
|
||||
any.filepath ==1.4.2.2,
|
||||
any.free ==5.1.8,
|
||||
any.fusion-plugin-types ==0.1.0,
|
||||
any.generic-arbitrary ==0.2.2,
|
||||
any.ghc-bignum ==1.2,
|
||||
any.ghc-boot-th ==9.2.3,
|
||||
any.ghc-byteorder ==4.11.0.0.10,
|
||||
any.ghc-prim ==0.8.0,
|
||||
any.happy ==1.20.0,
|
||||
any.hashable ==1.4.0.2,
|
||||
hashable +containers +integer-gmp -random-initial-seed,
|
||||
any.haskus-utils-data ==1.4,
|
||||
any.haskus-utils-types ==1.5.1,
|
||||
any.haskus-utils-variant ==3.2.1,
|
||||
any.heaps ==0.4,
|
||||
any.hsc2hs ==0.68.8,
|
||||
hsc2hs -in-ghc-tree,
|
||||
any.hspec ==2.9.2,
|
||||
any.hspec-core ==2.9.2,
|
||||
any.hspec-discover ==2.9.2,
|
||||
any.hspec-expectations ==0.8.2,
|
||||
any.hspec-golden-aeson ==0.9.0.0,
|
||||
any.http-io-streams ==0.1.6.1,
|
||||
http-io-streams -brotli +fast-xor,
|
||||
any.indexed-profunctors ==0.1.1,
|
||||
any.indexed-traversable ==0.1.2,
|
||||
any.indexed-traversable-instances ==0.1.1,
|
||||
any.integer-logarithms ==1.0.3.1,
|
||||
integer-logarithms -check-bounds +integer-gmp,
|
||||
any.io-streams ==1.5.2.1,
|
||||
io-streams +network -nointeractivetests +zlib,
|
||||
any.language-c ==0.9.1,
|
||||
language-c -allwarnings +iecfpextension +usebytestrings,
|
||||
any.libarchive ==3.0.3.2,
|
||||
libarchive -cross -low-memory +no-exe -system-libarchive,
|
||||
any.libyaml-streamly ==0.2.1,
|
||||
libyaml-streamly -no-unicode -system-libyaml,
|
||||
any.lockfree-queue ==0.2.3.1,
|
||||
any.lzma-static ==5.2.5.4,
|
||||
any.megaparsec ==9.2.1,
|
||||
megaparsec -dev,
|
||||
any.microlens ==0.4.12.0,
|
||||
any.microlens-mtl ==0.2.0.2,
|
||||
any.microlens-th ==0.4.3.10,
|
||||
any.mtl ==2.2.2,
|
||||
any.network ==3.1.2.7,
|
||||
network -devel,
|
||||
any.network-uri ==2.6.4.1,
|
||||
any.openssl-streams ==1.2.3.0,
|
||||
any.optics ==0.4.2,
|
||||
any.optics-core ==0.4.1,
|
||||
optics-core -explicit-generic-labels,
|
||||
any.optics-extra ==0.4.2.1,
|
||||
any.optics-th ==0.4.1,
|
||||
any.optparse-applicative ==0.17.0.0,
|
||||
optparse-applicative +process,
|
||||
any.os-release ==1.0.2.1,
|
||||
os-release -devel,
|
||||
any.parallel ==3.2.2.0,
|
||||
any.parsec ==3.1.15.0,
|
||||
any.parser-combinators ==1.3.0,
|
||||
parser-combinators -dev,
|
||||
any.polyparse ==1.13,
|
||||
any.pretty ==1.1.3.6,
|
||||
any.pretty-terminal ==0.1.0.0,
|
||||
any.primitive ==0.7.4.0,
|
||||
any.process ==1.6.14.0,
|
||||
any.profunctors ==5.6.2,
|
||||
any.quickcheck-arbitrary-adt ==0.3.1.0,
|
||||
any.quickcheck-io ==0.2.0,
|
||||
any.random ==1.2.1.1,
|
||||
any.recursion-schemes ==5.2.2.2,
|
||||
recursion-schemes +template-haskell,
|
||||
any.regex-base ==0.94.0.2,
|
||||
any.regex-posix ==0.96.0.1,
|
||||
regex-posix -_regex-posix-clib,
|
||||
any.resourcet ==1.2.5,
|
||||
any.retry ==0.8.1.2,
|
||||
retry -lib-werror,
|
||||
any.rts ==1.0.2,
|
||||
any.safe ==0.3.19,
|
||||
any.safe-exceptions ==0.1.7.3,
|
||||
any.scientific ==0.3.7.0,
|
||||
scientific -bytestring-builder -integer-simple,
|
||||
any.semialign ==1.2.0.1,
|
||||
semialign +semigroupoids,
|
||||
any.semigroupoids ==5.3.7,
|
||||
semigroupoids +comonad +containers +contravariant +distributive +tagged +unordered-containers,
|
||||
any.setenv ==0.1.1.3,
|
||||
any.split ==0.2.3.4,
|
||||
any.splitmix ==0.1.0.4,
|
||||
splitmix -optimised-mixer,
|
||||
any.stm ==2.5.0.2,
|
||||
any.streamly ==0.8.2,
|
||||
streamly -debug -dev -fusion-plugin -has-llvm -inspection -limit-build-mem -no-fusion +opt -streamk -streamly-core -use-c-malloc +use-unliftio,
|
||||
any.strict ==0.4.0.1,
|
||||
strict +assoc,
|
||||
any.strict-base ==0.4.0.0,
|
||||
any.tagged ==0.8.6.1,
|
||||
tagged +deepseq +transformers,
|
||||
any.tagsoup ==0.14.8,
|
||||
any.template-haskell ==2.18.0.0,
|
||||
any.temporary ==1.3,
|
||||
any.terminal-progress-bar ==0.4.1,
|
||||
any.terminal-size ==0.3.2.1,
|
||||
any.terminfo ==0.4.1.5,
|
||||
any.text ==1.2.5.0,
|
||||
any.text-short ==0.1.5,
|
||||
text-short -asserts,
|
||||
any.text-zipper ==0.11,
|
||||
any.tf-random ==0.5,
|
||||
any.th-abstraction ==0.4.3.0,
|
||||
any.th-compat ==0.1.3,
|
||||
any.th-lift ==0.8.2,
|
||||
any.th-lift-instances ==0.1.19,
|
||||
any.these ==1.1.1.1,
|
||||
these +assoc,
|
||||
any.time ==1.9.3,
|
||||
any.time-compat ==1.9.6.1,
|
||||
time-compat -old-locale,
|
||||
any.transformers ==0.5.6.2,
|
||||
any.transformers-base ==0.4.6,
|
||||
transformers-base +orphaninstances,
|
||||
any.transformers-compat ==0.7.1,
|
||||
transformers-compat -five +five-three -four +generic-deriving +mtl -three -two,
|
||||
any.unicode-data ==0.3.0,
|
||||
unicode-data -ucd2haskell,
|
||||
any.unix ==2.7.2.2,
|
||||
any.unix-bytestring ==0.3.7.7,
|
||||
any.unix-compat ==0.6,
|
||||
unix-compat -old-time,
|
||||
any.unliftio-core ==0.2.0.1,
|
||||
any.unordered-containers ==0.2.19.1,
|
||||
unordered-containers -debug,
|
||||
any.uri-bytestring ==0.3.3.1,
|
||||
uri-bytestring -lib-werror,
|
||||
any.utf8-string ==1.0.2,
|
||||
any.uuid-types ==1.0.5,
|
||||
any.vector ==0.12.3.1,
|
||||
vector +boundschecks -internalchecks -unsafechecks -wall,
|
||||
any.versions ==5.0.3,
|
||||
any.vty ==5.33,
|
||||
any.witherable ==0.4.2,
|
||||
any.word-wrap ==0.5,
|
||||
any.word8 ==0.1.3,
|
||||
any.xor ==0.0.1.1,
|
||||
any.yaml-streamly ==0.12.1,
|
||||
yaml-streamly +no-examples +no-exe,
|
||||
any.zlib ==0.6.3.0,
|
||||
zlib -bundled-c-zlib -non-blocking-ffi -pkg-config,
|
||||
any.zlib-bindings ==0.1.1.5
|
||||
index-state: hackage.haskell.org 2022-06-04T19:47:01Z
|
||||
@@ -1,16 +1,35 @@
|
||||
packages: ./ghcup.cabal
|
||||
|
||||
optional-packages: ./vendored/*/*.cabal
|
||||
|
||||
optimization: 2
|
||||
|
||||
package streamly
|
||||
ghc-options: -O2 -fspec-constr-recursive=16 -fmax-worker-args=16
|
||||
|
||||
package ghcup
|
||||
ghc-options: -O2 -fspec-constr-recursive=16 -fmax-worker-args=16
|
||||
tests: True
|
||||
flags: +tui
|
||||
|
||||
package tar-bytestring
|
||||
ghc-options: -O2
|
||||
source-repository-package
|
||||
type: git
|
||||
location: https://github.com/bgamari/terminal-size.git
|
||||
tag: 34ea816bd63f75f800eedac12c6908c6f3736036
|
||||
|
||||
constraints: http-io-streams -brotli
|
||||
constraints: http-io-streams -brotli,
|
||||
any.Cabal ==3.6.2.0,
|
||||
any.aeson >= 2.0.1.0,
|
||||
|
||||
allow-newer: base
|
||||
package libarchive
|
||||
flags: -system-libarchive
|
||||
|
||||
package aeson-pretty
|
||||
flags: +lib-only
|
||||
|
||||
package cabal-plan
|
||||
flags: -exe
|
||||
|
||||
package aeson
|
||||
flags: +ordered-keymap
|
||||
|
||||
package streamly
|
||||
flags: +use-unliftio
|
||||
|
||||
allow-newer: base, ghc-prim, template-haskell, language-c
|
||||
|
||||
2
cabal.project.freeze
Normal file
@@ -0,0 +1,2 @@
|
||||
-- windows picks weird version
|
||||
constraints: any.hsc2hs ==0.68.7
|
||||
7
cbits/dirutils.c
Normal file
@@ -0,0 +1,7 @@
|
||||
#include "dirutils.h"
|
||||
|
||||
unsigned int
|
||||
__posixdir_d_type(struct dirent* d)
|
||||
{
|
||||
return(d -> d_type);
|
||||
}
|
||||
15
cbits/dirutils.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef POSIXPATHS_CBITS_DIRUTILS_H
|
||||
#define POSIXPATHS_CBITS_DIRUTILS_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
extern unsigned int
|
||||
__posixdir_d_type(struct dirent* d)
|
||||
;
|
||||
|
||||
#endif
|
||||
9
data/build_mk/cross
Normal file
@@ -0,0 +1,9 @@
|
||||
V=0
|
||||
BUILD_MAN = NO
|
||||
BUILD_SPHINX_HTML = NO
|
||||
BUILD_SPHINX_PDF = NO
|
||||
HADDOCK_DOCS = NO
|
||||
ifneq "$(BuildFlavour)" ""
|
||||
include mk/flavours/$(BuildFlavour).mk
|
||||
endif
|
||||
Stage1Only = YES
|
||||
8
data/build_mk/default
Normal file
@@ -0,0 +1,8 @@
|
||||
V=0
|
||||
BUILD_MAN = NO
|
||||
BUILD_SPHINX_HTML = NO
|
||||
BUILD_SPHINX_PDF = NO
|
||||
HADDOCK_DOCS = YES
|
||||
ifneq "$(BuildFlavour)" ""
|
||||
include mk/flavours/$(BuildFlavour).mk
|
||||
endif
|
||||
77
data/config.yaml
Normal file
@@ -0,0 +1,77 @@
|
||||
# Cache downloads in ~/.ghcup/cache
|
||||
cache: False
|
||||
# Skip tarball checksum verification
|
||||
no-verify: False
|
||||
# enable verbosity
|
||||
verbose: False
|
||||
# When to keep build directories
|
||||
keep-dirs: Errors # Always | Never | Errors
|
||||
# Which downloader to use
|
||||
downloader: Curl # Curl | Wget | Internal
|
||||
# whether to run in offline mode
|
||||
no-network: False
|
||||
# whether/how to do gpg verification
|
||||
gpg-setting: GPGNone # GPGStrict | GPGLax | GPGNone
|
||||
|
||||
# TUI key bindings,
|
||||
# see https://hackage.haskell.org/package/vty-5.31/docs/Graphics-Vty-Input-Events.html#t:Key
|
||||
# for possible values.
|
||||
key-bindings:
|
||||
up:
|
||||
KUp: []
|
||||
down:
|
||||
KDown: []
|
||||
quit:
|
||||
KChar: 'q'
|
||||
install:
|
||||
KChar: 'i'
|
||||
uninstall:
|
||||
KChar: 'u'
|
||||
set:
|
||||
KChar: 's'
|
||||
changelog:
|
||||
KChar: 'c'
|
||||
show-all:
|
||||
KChar: 'a'
|
||||
show-all-tools:
|
||||
KChar: 't'
|
||||
|
||||
# The caching for the metadata files containing download info, depending on last access time
|
||||
# of the file. These usually are in '~/.ghcup/cache/ghcup-<ver>.yaml'.
|
||||
meta-cache: 300 # in seconds
|
||||
|
||||
# Where to get GHC/cabal/hls download info/versions from. For more detailed explanation
|
||||
# check the 'URLSource' type in the code.
|
||||
url-source:
|
||||
## Use the internal download uri, this is the default
|
||||
GHCupURL: []
|
||||
|
||||
## Example 1: Read download info from this location instead
|
||||
## Accepts file/http/https scheme
|
||||
## Can also be an array of URLs or an array of 'Either GHCupInfo URL', in
|
||||
## which case they are merged right-biased (overwriting duplicate versions).
|
||||
# OwnSource: "file:///home/jule/git/ghcup-hs/ghcup-0.0.3.yaml"
|
||||
|
||||
## Example 2: Add custom tarballs to the default downloads, overwriting duplicate versions.
|
||||
## Can also be an array of 'Either GHCupInfo URL', also see Example 3.
|
||||
# AddSource:
|
||||
# Left:
|
||||
# globalTools: {}
|
||||
# toolRequirements: {}
|
||||
# ghcupDownloads:
|
||||
# GHC:
|
||||
# 9.10.2:
|
||||
# viTags: []
|
||||
# viArch:
|
||||
# A_64:
|
||||
# Linux_UnknownLinux:
|
||||
# unknown_versioning:
|
||||
# dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-deb8-linux.tar.bz2
|
||||
# dlSubdir: ghc-7.10.3
|
||||
# dlHash: 01cfbad8dff1e8b34a5fdca8caeaf843b56e36af919e29cd68870d2588563db5
|
||||
|
||||
## Example 3: Add multiple custom download files to the default downloads via right-biased merge (overwriting duplicate
|
||||
## versions).
|
||||
# AddSource:
|
||||
# - Right: "file:///home/jule/git/ghcup-hs/ghcup-prereleases.yaml"
|
||||
# - Right: "file:///home/jule/git/ghcup-hs/ghcup-custom.yaml"
|
||||
1
data/metadata
Submodule
@@ -1,14 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -ex
|
||||
|
||||
cd /app
|
||||
|
||||
cabal v2-update
|
||||
|
||||
cabal v2-install \
|
||||
--install-method=copy \
|
||||
--overwrite-policy=always \
|
||||
--installdir="/bin" \
|
||||
--ghc-options='-optl-static'
|
||||
|
||||
1
docs/BUGS.md
Normal file
@@ -0,0 +1 @@
|
||||
# Known BUGS
|
||||
10
docs/Discord-Logo-Black.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg width="71" height="55" viewBox="0 0 71 55" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0)">
|
||||
<path d="M60.1045 4.8978C55.5792 2.8214 50.7265 1.2916 45.6527 0.41542C45.5603 0.39851 45.468 0.440769 45.4204 0.525289C44.7963 1.6353 44.105 3.0834 43.6209 4.2216C38.1637 3.4046 32.7345 3.4046 27.3892 4.2216C26.905 3.0581 26.1886 1.6353 25.5617 0.525289C25.5141 0.443589 25.4218 0.40133 25.3294 0.41542C20.2584 1.2888 15.4057 2.8186 10.8776 4.8978C10.8384 4.9147 10.8048 4.9429 10.7825 4.9795C1.57795 18.7309 -0.943561 32.1443 0.293408 45.3914C0.299005 45.4562 0.335386 45.5182 0.385761 45.5576C6.45866 50.0174 12.3413 52.7249 18.1147 54.5195C18.2071 54.5477 18.305 54.5139 18.3638 54.4378C19.7295 52.5728 20.9469 50.6063 21.9907 48.5383C22.0523 48.4172 21.9935 48.2735 21.8676 48.2256C19.9366 47.4931 18.0979 46.6 16.3292 45.5858C16.1893 45.5041 16.1781 45.304 16.3068 45.2082C16.679 44.9293 17.0513 44.6391 17.4067 44.3461C17.471 44.2926 17.5606 44.2813 17.6362 44.3151C29.2558 49.6202 41.8354 49.6202 53.3179 44.3151C53.3935 44.2785 53.4831 44.2898 53.5502 44.3433C53.9057 44.6363 54.2779 44.9293 54.6529 45.2082C54.7816 45.304 54.7732 45.5041 54.6333 45.5858C52.8646 46.6197 51.0259 47.4931 49.0921 48.2228C48.9662 48.2707 48.9102 48.4172 48.9718 48.5383C50.038 50.6034 51.2554 52.5699 52.5959 54.435C52.6519 54.5139 52.7526 54.5477 52.845 54.5195C58.6464 52.7249 64.529 50.0174 70.6019 45.5576C70.6551 45.5182 70.6887 45.459 70.6943 45.3942C72.1747 30.0791 68.2147 16.7757 60.1968 4.9823C60.1772 4.9429 60.1437 4.9147 60.1045 4.8978ZM23.7259 37.3253C20.2276 37.3253 17.3451 34.1136 17.3451 30.1693C17.3451 26.225 20.1717 23.0133 23.7259 23.0133C27.308 23.0133 30.1626 26.2532 30.1066 30.1693C30.1066 34.1136 27.28 37.3253 23.7259 37.3253ZM47.3178 37.3253C43.8196 37.3253 40.9371 34.1136 40.9371 30.1693C40.9371 26.225 43.7636 23.0133 47.3178 23.0133C50.9 23.0133 53.7545 26.2532 53.6986 30.1693C53.6986 34.1136 50.9 37.3253 47.3178 37.3253Z" fill="#23272A"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0">
|
||||
<rect width="71" height="55" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
7
docs/Matrix_logo.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg version="1.1" viewBox="0 0 75 32" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<title>Matrix (protocol) logo</title>
|
||||
<g fill="#040404">
|
||||
<path d="m0.936 0.732v30.52h2.194v0.732h-3.035v-31.98h3.034v0.732zm8.45 9.675v1.544h0.044a4.461 4.461 0 0 1 1.487-1.368c0.58-0.323 1.245-0.485 1.993-0.485 0.72 0 1.377 0.14 1.972 0.42 0.595 0.279 1.047 0.771 1.355 1.477 0.338-0.5 0.796-0.941 1.377-1.323 0.58-0.383 1.266-0.574 2.06-0.574 0.602 0 1.16 0.074 1.674 0.22 0.514 0.148 0.954 0.383 1.322 0.707 0.366 0.323 0.653 0.746 0.859 1.268 0.205 0.522 0.308 1.15 0.308 1.887v7.633h-3.127v-6.464c0-0.383-0.015-0.743-0.044-1.082a2.305 2.305 0 0 0-0.242-0.882 1.473 1.473 0 0 0-0.584-0.596c-0.257-0.146-0.606-0.22-1.047-0.22-0.44 0-0.796 0.085-1.068 0.253-0.272 0.17-0.485 0.39-0.639 0.662a2.654 2.654 0 0 0-0.308 0.927 7.074 7.074 0 0 0-0.078 1.048v6.354h-3.128v-6.398c0-0.338-7e-3 -0.673-0.021-1.004a2.825 2.825 0 0 0-0.188-0.916 1.411 1.411 0 0 0-0.55-0.673c-0.258-0.168-0.636-0.253-1.135-0.253a2.33 2.33 0 0 0-0.584 0.1 1.94 1.94 0 0 0-0.705 0.374c-0.228 0.184-0.422 0.449-0.584 0.794-0.161 0.346-0.242 0.798-0.242 1.357v6.619h-3.129v-11.41zm16.46 1.677a3.751 3.751 0 0 1 1.233-1.17 5.37 5.37 0 0 1 1.685-0.629 9.579 9.579 0 0 1 1.884-0.187c0.573 0 1.153 0.04 1.74 0.121 0.588 0.081 1.124 0.24 1.609 0.475 0.484 0.235 0.88 0.562 1.19 0.981 0.308 0.42 0.462 0.975 0.462 1.666v5.934c0 0.516 0.03 1.008 0.088 1.478 0.058 0.471 0.161 0.824 0.308 1.06h-3.171a4.435 4.435 0 0 1-0.22-1.104c-0.5 0.515-1.087 0.876-1.762 1.081a7.084 7.084 0 0 1-2.071 0.31c-0.544 0-1.05-0.067-1.52-0.2a3.472 3.472 0 0 1-1.234-0.617 2.87 2.87 0 0 1-0.826-1.059c-0.199-0.426-0.298-0.934-0.298-1.522 0-0.647 0.114-1.18 0.342-1.6 0.227-0.419 0.52-0.753 0.881-1.004 0.36-0.25 0.771-0.437 1.234-0.562 0.462-0.125 0.929-0.224 1.399-0.298 0.47-0.073 0.932-0.132 1.387-0.176 0.456-0.044 0.86-0.11 1.212-0.199 0.353-0.088 0.631-0.217 0.837-0.386s0.301-0.415 0.287-0.74c0-0.337-0.055-0.606-0.166-0.804a1.217 1.217 0 0 0-0.44-0.464 1.737 1.737 0 0 0-0.639-0.22 5.292 5.292 0 0 0-0.782-0.055c-0.617 0-1.101 0.132-1.454 0.397-0.352 0.264-0.558 0.706-0.617 1.323h-3.128c0.044-0.735 0.227-1.345 0.55-1.83zm6.179 4.423a5.095 5.095 0 0 1-0.639 0.165 9.68 9.68 0 0 1-0.716 0.11c-0.25 0.03-0.5 0.067-0.749 0.11a5.616 5.616 0 0 0-0.694 0.177 2.057 2.057 0 0 0-0.594 0.298c-0.17 0.125-0.305 0.284-0.408 0.474-0.103 0.192-0.154 0.434-0.154 0.728 0 0.28 0.051 0.515 0.154 0.706 0.103 0.192 0.242 0.342 0.419 0.453 0.176 0.11 0.381 0.187 0.617 0.231 0.234 0.044 0.477 0.066 0.726 0.066 0.617 0 1.094-0.102 1.432-0.309 0.338-0.205 0.587-0.452 0.75-0.739 0.16-0.286 0.26-0.576 0.297-0.87 0.036-0.295 0.055-0.53 0.055-0.707v-1.17a1.4 1.4 0 0 1-0.496 0.277zm11.86-6.1v2.096h-2.291v5.647c0 0.53 0.088 0.883 0.264 1.059 0.176 0.177 0.529 0.265 1.057 0.265 0.177 0 0.345-7e-3 0.507-0.022 0.161-0.015 0.316-0.037 0.463-0.066v2.426a7.49 7.49 0 0 1-0.882 0.089 21.67 21.67 0 0 1-0.947 0.022c-0.484 0-0.944-0.034-1.377-0.1a3.233 3.233 0 0 1-1.145-0.386 2.04 2.04 0 0 1-0.782-0.816c-0.191-0.353-0.287-0.816-0.287-1.39v-6.728h-1.894v-2.096h1.894v-3.42h3.129v3.42h2.29zm4.471 0v2.118h0.044a3.907 3.907 0 0 1 1.454-1.754 4.213 4.213 0 0 1 1.036-0.497 3.734 3.734 0 0 1 1.145-0.176c0.206 0 0.433 0.037 0.683 0.11v2.912a5.862 5.862 0 0 0-0.528-0.077 5.566 5.566 0 0 0-0.595-0.033c-0.573 0-1.058 0.096-1.454 0.287a2.52 2.52 0 0 0-0.958 0.783 3.143 3.143 0 0 0-0.518 1.158 6.32 6.32 0 0 0-0.154 1.434v5.14h-3.128v-11.4zm5.684-1.765v-2.582h3.128v2.582h-3.127zm3.128 1.765v11.4h-3.127v-11.4h3.128zm1.63 0h3.569l2.005 2.978 1.982-2.978h3.459l-3.745 5.339 4.208 6.067h-3.57l-2.378-3.596-2.38 3.596h-3.502l4.097-6.001zm15.3 20.84v-30.52h-2.194v-0.732h3.035v31.98h-3.035v-0.732z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
36
docs/Octicons-bug.svg
Normal file
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
height="800.3468"
|
||||
width="733.88495"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="Octicons-bug.svg"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.85253906"
|
||||
inkscape:cx="367.1386"
|
||||
inkscape:cy="432.23826"
|
||||
inkscape:window-width="3828"
|
||||
inkscape:window-height="2081"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="46"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<path
|
||||
d="m 243.6206,76.877783 c -52.874,56.780997 -38.281,147.468997 -38.281,147.468997 0,0 53.968,64 160,64 106.031,0 160.031,-64 160.031,-64 0,0 14.375,-89.469 -37.375,-146.311997 32.375,-18.031 51.438,-44.094 43.562,-61.812 -8.938,-19.9689999 -48.375,-21.7499999 -88.25,-3.969 -14.812,6.594 -27.438,14.969 -37.25,23.875 -12.438,-2.25 -25.625,-3.781 -40.72,-3.781 -14.061,0 -26.561,1.344 -38.344,3.25 -9.656,-8.75 -22.062,-16.875 -36.531,-23.344 -39.875,-17.7189999 -79.375,-15.9379999 -88.25,3.969 -7.748,17.343 10.284,42.686 41.408,60.655 z m 401.125,413.218997 c -8.25,-1.75 -16.125,-2.75 -23.75,-3.5 0,-2.125 0.375,-4.125 0.375,-6.312 0,-33.594 -4.75,-65.654 -12.438,-96.125 16.438,1.406 37.375,-2.375 58.562,-11.779 39.875,-17.781 65,-48.375 56.125,-68.219 -8.875,-19.969 -48.375,-21.75 -88.25,-3.969 -18.625,8.312 -33.812,19.469 -44,30.906 -7.75,-18.25 -16.5,-35.781 -26.812,-51.719 -30.188,25.156 -87.312,62.719 -167.062,71.062 v 321.781 c 0,0 -0.25,32 -32.031,32 -31.75,0 -32,-32 -32,-32 v -321.657 c -79.811,-8.344 -136.968,-45.969 -167.093,-71.062 -9.875,15.312 -18.375,32 -25.938,49.344 -10.281,-10.625 -24.625,-20.844 -41.969,-28.594 -39.875,-17.719 -79.375,-15.938 -88.25,3.969 -8.9060001,19.906 16.25,50.438 56.125,68.219 19.844,8.846 39.531,12.812 55.469,12.096 -7.656,30.404 -12.469,62.344 -12.469,95.812 0,2.188 0.375,4.25 0.438,6.5 -6.719,0.75 -13.688,1.75 -20.781,3.25 -51.969,10.75 -91.7810001,37.625 -88.84400014,59.812 2.93800004,22.312 47.50000014,31.5 99.59400014,20.688 6.781,-1.375 13.438,-3.125 19.781,-5.062 9.156,40.809 23.812,78.684 44.094,111.309 -12.031,6.062 -24.531,15 -36.031,26.625 -31.876,31.875 -44.812,70.625 -28.876,86.563 15.938,15.937 54.656,3 86.531,-28.812 9.344,-9.375 16.844,-19.25 22.656,-29 43.532,42.624 98.063,68.124 157.563,68.124 60.343,0 115.781,-26.25 159.531,-69.938 5.875,10.312 13.75,20.812 23.625,30.688 31.812,31.875 70.625,44.812 86.562,28.875 15.937,-15.937 3,-54.625 -28.875,-86.5 -12.312,-12.375 -25.688,-21.75 -38.438,-27.938 20.125,-32.5 34.625,-70.375 43.688,-111.062 7.188,2.25 14.688,4.375 22.562,6.062 52.061,10.812 96.625,1.562 99.625,-20.688 2.813,-22.124 -36.999,-48.999 -88.999,-59.749 z"
|
||||
id="path2" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
@@ -2,30 +2,38 @@
|
||||
|
||||
## Now
|
||||
|
||||
* ghcup migration
|
||||
* update static links
|
||||
* ghcup init?
|
||||
* merge two download files
|
||||
* fetch/unpack functionality
|
||||
* installing multiple versions of the same
|
||||
* post-install
|
||||
|
||||
* releases, update download info and bootstrap-haskell
|
||||
* proper test suite
|
||||
|
||||
* !! update of 0.1.5 must go in ghcup-0.0.1.json !!
|
||||
|
||||
* try to run exe before upgrade (backup to ~/.ghcup/bin/ghcup.old)
|
||||
* stdout flushing?
|
||||
* resume support (for make-install only)
|
||||
|
||||
## Maybe
|
||||
|
||||
* maybe: changelog Show the changelog of a GHC release (online)
|
||||
* version ranges in json
|
||||
* sign the JSON? (Or check gpg keys?)
|
||||
* testing (especially distro detection -> unit tests)
|
||||
|
||||
## Later
|
||||
|
||||
* i386 support
|
||||
* add support for RC/alpha/HEAD versions
|
||||
|
||||
## Cleanups
|
||||
|
||||
* too many decodeutf8
|
||||
* avoid alternative for IO
|
||||
* use plucky or oops instead of Excepts
|
||||
|
||||
## Questions
|
||||
|
||||
* move out GHCup.Version module, bc it's not library-ish?
|
||||
* mirror support
|
||||
* interactive handling when distro doesn't exist and we know the tarball is incompatible?
|
||||
* ghcup-with wrapper to execute a command with a given ghc in PATH?
|
||||
225
docs/about.md
Normal file
@@ -0,0 +1,225 @@
|
||||
# About
|
||||
|
||||
All you wanted to know about GHCup.
|
||||
|
||||
## Team
|
||||
|
||||
### Author and Maintainer
|
||||
|
||||
* [Julian Ospald](https://github.com/hasufell) (aka: maerwald, hasufell)
|
||||
|
||||
### Collaborators
|
||||
|
||||
* [Arjun Kathuria](https://github.com/arjunkathuria)
|
||||
* [Ben Gamari](https://github.com/bgamari)
|
||||
* [Javier Neira](https://github.com/jneira)
|
||||
|
||||
### Contributors
|
||||
|
||||
* amesgen
|
||||
* Chris Smith
|
||||
* Anton-Latukha
|
||||
* Brian McKenna
|
||||
* Huw campbell
|
||||
* Tom Ellis
|
||||
* Sigmund Vestergaard
|
||||
* Ron Toland
|
||||
* Paolo Martini
|
||||
* Mario Lang
|
||||
* Jan Hrček
|
||||
* vglfr
|
||||
* Fendor
|
||||
* Enrico Maria De Angelis
|
||||
* Emily Pillmore
|
||||
* Colin Barrett
|
||||
* Artur Gajowy
|
||||
|
||||
### Sponsors
|
||||
|
||||
* All [opencollective](https://opencollective.com/ghcup#category-CONTRIBUTE) contributors
|
||||
* [haskell.org](https://www.haskell.org/haskell-org-committee/) via CI and infrastructure
|
||||
* [Haskell Foundation](https://haskell.foundation/affiliates/) via affiliation
|
||||
|
||||
## How to help
|
||||
|
||||
* if you want to contribute code or documentation, check out the [issue tracker](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues) and the [Development guide](./dev.md)
|
||||
* if you want to propose features or write user feedback, feel free to [open a ticket](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/new?issue)
|
||||
* if you want to donate to the project, visit our [opencollective](https://opencollective.com/ghcup#category-CONTRIBUTE) page
|
||||
|
||||
## Design goals
|
||||
|
||||
1. simplicity
|
||||
2. non-interactive CLI interface
|
||||
3. portable
|
||||
4. do one thing and do it well (UNIX philosophy)
|
||||
|
||||
## Non-goals
|
||||
|
||||
1. invoking `sudo`, `apt-get` or *any* package manager
|
||||
2. handling system packages
|
||||
3. handling cabal projects
|
||||
4. being a stack alternative
|
||||
|
||||
## How
|
||||
|
||||
Installs a specified GHC version into `~/.ghcup/ghc/<ver>`, and places `ghc-<ver>` symlinks in `~/.ghcup/bin/`.
|
||||
|
||||
Optionally, an unversioned `ghc` link can point to a default version of your choice.
|
||||
|
||||
This uses precompiled GHC binaries that have been compiled on fedora/debian by [upstream GHC](https://www.haskell.org/ghc/download_ghc_8_6_1.html#binaries).
|
||||
|
||||
Alternatively, you can also tell it to compile from source (note that this might fail due to missing requirements).
|
||||
|
||||
cabal-install/HLS/stack are installed in `~/.ghcup/bin/<tool>-<ver>` and have unversioned symlinks to the latest version by default (`~/.ghcup/bin/<tool>-<ver>`).
|
||||
|
||||
## Known users
|
||||
|
||||
* CI:
|
||||
- [Github actions/virtual-environments](https://github.com/actions/virtual-environments)
|
||||
- [Github haskell/actions/setup](https://github.com/haskell/actions/tree/main/setup)
|
||||
- [haskell-ci](https://github.com/haskell-CI/haskell-ci)
|
||||
* mirrors:
|
||||
- [sjtug](https://mirror.sjtu.edu.cn/docs/ghcup)
|
||||
* tools:
|
||||
- [vscode-haskell](https://github.com/haskell/vscode-haskell)
|
||||
- [nvim-lsp-installer](https://github.com/williamboman/nvim-lsp-installer)
|
||||
- [vabal](https://github.com/Franciman/vabal)
|
||||
|
||||
## Known problems
|
||||
|
||||
### Custom ghc version names
|
||||
|
||||
When installing ghc bindists with custom version names as outlined in
|
||||
[installing custom bindists](#installing-custom-bindists), then cabal might
|
||||
be unable to find the correct `ghc-pkg` (also see [#73](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/73))
|
||||
if you use `cabal build --with-compiler=ghc-foo`. Instead, point it to the full path, such as:
|
||||
`cabal build --with-compiler=$HOME/.ghcup/ghc/<version-name>/bin/ghc` or set that GHC version
|
||||
as the current one via: `ghcup set ghc <version-name>`.
|
||||
|
||||
This problem doesn't exist for regularly installed GHC versions.
|
||||
|
||||
### Limited distributions supported
|
||||
|
||||
Currently only GNU/Linux distributions compatible with the [upstream GHC](https://www.haskell.org/ghc/download_ghc_8_6_1.html#binaries) binaries are supported.
|
||||
|
||||
### Precompiled binaries
|
||||
|
||||
Since this uses precompiled binaries you may run into
|
||||
several problems.
|
||||
|
||||
#### Missing libtinfo (ncurses)
|
||||
|
||||
You may run into problems with *ncurses* and **missing libtinfo**, in case
|
||||
your distribution doesn't use the legacy way of building
|
||||
ncurses and has no compatibility symlinks in place.
|
||||
|
||||
Ask your distributor on how to solve this or
|
||||
try to compile from source via `ghcup compile <version>`.
|
||||
|
||||
#### Libnuma required
|
||||
|
||||
This was a [bug](https://ghc.haskell.org/trac/ghc/ticket/15688) in the build system of some GHC versions that lead to
|
||||
unconditionally enabled libnuma support. To mitigate this you might have to install the libnuma
|
||||
package of your distribution. See [here](https://gitlab.haskell.org/haskell/ghcup/issues/58) for a discussion.
|
||||
|
||||
### Compilation
|
||||
|
||||
Although this script can compile GHC for you, it's just a very thin
|
||||
wrapper around the build system. It makes no effort in trying
|
||||
to figure out whether you have the correct toolchain and
|
||||
the correct dependencies. Refer to [the official docs](https://ghc.haskell.org/trac/ghc/wiki/Building/Preparation/Linux)
|
||||
on how to prepare your environment for building GHC.
|
||||
|
||||
### Stack support
|
||||
|
||||
There may be a number of bugs when trying to make ghcup installed GHC versions work with stack,
|
||||
such as:
|
||||
|
||||
- https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/188
|
||||
|
||||
Further, stack's upgrade procedure may break/confuse ghcup. There are a number of integration
|
||||
issues discussed here:
|
||||
|
||||
- https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/153
|
||||
|
||||
### Windows support
|
||||
|
||||
Windows support is in early stages. Since windows doesn't support symbolic links properly,
|
||||
ghcup uses a [shimgen wrapper](https://github.com/71/scoop-better-shimexe). It seems to work
|
||||
well, but there may be unknown issues with that approach.
|
||||
|
||||
Windows 7 and Powershell 2.0 aren't well supported at the moment, also see:
|
||||
|
||||
- https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/140
|
||||
- https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/197
|
||||
|
||||
## FAQ
|
||||
|
||||
### Why reimplement stack?
|
||||
|
||||
GHCup is not a reimplementation of stack. The only common part is automatic installation of GHC,
|
||||
but even that differs in scope and design.
|
||||
|
||||
### Why should I use ghcup over stack?
|
||||
|
||||
GHCup is not a replacement for stack. Instead, it supports installing and managing stack versions.
|
||||
It does the same for cabal, GHC and HLS. As such, It doesn't make a workflow choice for you.
|
||||
|
||||
### Why should I let ghcup manage stack?
|
||||
|
||||
You don't need to. However, some users seem to prefer to have a central tool that manages cabal and stack
|
||||
at the same time. Additionally, it can allow better sharing of GHC installation across these tools.
|
||||
Also see:
|
||||
|
||||
* https://docs.haskellstack.org/en/stable/yaml_configuration/#system-ghc
|
||||
* https://github.com/commercialhaskell/stack/pull/5585
|
||||
|
||||
### Why does ghcup not use stack code?
|
||||
|
||||
1. GHCup started as a shell script. At the time of rewriting it in Haskell, the authors didn't even know that stack exposes *some* of its [installation API](https://hackage.haskell.org/package/stack-2.5.1.1/docs/Stack-Setup.html)
|
||||
2. it doesn't support cabal installation, which was the main motivation behind GHCup back then
|
||||
3. depending on a codebase as big as stack for a central part of one's application without having a short contribution pipeline would likely have caused stagnation or resulted in simply copy-pasting the relevant code in order to adjust it
|
||||
4. it's not clear how GHCup would have been implemented with the provided API. It seems the codebases are fairly different. GHCup does a lot of symlink handling to expose a central `bin/` directory that users can easily put in PATH, without having to worry about anything more. It also provides explicit removal functionality, GHC cross-compilation, a TUI, etc etc.
|
||||
|
||||
### Why not unify...
|
||||
|
||||
#### ...stack and Cabal and do away with standalone installers
|
||||
|
||||
GHCup is not involved in such decisions. cabal-install and stack might have a
|
||||
sufficiently different user experience to warrant having a choice.
|
||||
|
||||
#### ...installer implementations and have a common library
|
||||
|
||||
This sounds like an interesting goal. However, GHC installation isn't a hard engineering problem
|
||||
and the shared code wouldn't be too exciting. For such an effort to make sense, all involved
|
||||
parties would need to collaborate and have a short pipeline to get patches in.
|
||||
|
||||
It's true this would solve the integration problem, but following unix principles, we can
|
||||
do similar via **hooks**. Both cabal and stack can support installation hooks. These hooks
|
||||
can then call into ghcup or anything else, also see:
|
||||
|
||||
* https://github.com/haskell/cabal/issues/7394
|
||||
* https://github.com/commercialhaskell/stack/pull/5585
|
||||
|
||||
#### ...installers (like, all of it)
|
||||
|
||||
So far, there hasn't been an open discussion about this. Is this even a good idea?
|
||||
Sometimes projects converge eventually if their overlap is big enough, sometimes they don't.
|
||||
|
||||
While unification sounds like a simplification of the ecosystem, it also takes away choice.
|
||||
Take `curl` and `wget` as an example.
|
||||
|
||||
### Why not support windows?
|
||||
|
||||
Windows is supported since GHCup version 0.1.15.1.
|
||||
|
||||
### Why the haskell reimplementation?
|
||||
|
||||
GHCup started as a portable posix shell script of maybe 50 LOC. GHC installation itself can be carried out in
|
||||
about ~3 lines of shell code (download, unpack , configure+make install). However, much convenient functionality
|
||||
has been added since, as well as ensuring that all operations are safe and correct. The shell script ended up with
|
||||
over 2k LOC, which was very hard to maintain.
|
||||
|
||||
The main concern when switching from a portable shell script to haskell was platform/architecture support.
|
||||
However, ghcup now re-uses GHCs CI infrastructure and as such is perfectly in sync with all platforms that
|
||||
GHC supports.
|
||||
333
docs/css/extra.css
Normal file
@@ -0,0 +1,333 @@
|
||||
:root {
|
||||
--theme-purple: #5E5184;
|
||||
--theme-purple-dark: rgba(69, 59, 97, 0.5);
|
||||
--ukraine-top: #0057B8;
|
||||
--ukraine-bottom: #FFD700;
|
||||
--link-pink: #9E358F;
|
||||
}
|
||||
|
||||
h2
|
||||
{
|
||||
border-bottom:1px solid #CCC;
|
||||
padding-bottom:5px;
|
||||
padding-top:15px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
font-size: 60px;
|
||||
font-weight: 300;
|
||||
padding-top:15px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 30px;
|
||||
padding-top:10px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 25px;
|
||||
padding-top:10px;
|
||||
}
|
||||
|
||||
.index-ghcup-hero {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.index-ghcup-hero img {
|
||||
width: 10%;
|
||||
min-width: 110px;
|
||||
max-width: 120px;
|
||||
border: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.index-ghcup-hero h1 {
|
||||
}
|
||||
|
||||
div.col-md-9 h1:first-of-type {
|
||||
text-align: center;
|
||||
font-size: 60px;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
div.col-md-9>p:first-of-type {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.col-md-9 p.admonition-title:first-of-type {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.col-md-9 h1:first-of-type .headerlink {
|
||||
display: none;
|
||||
}
|
||||
|
||||
code.no-highlight {
|
||||
color: black;
|
||||
}
|
||||
|
||||
div.gh-badge img {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 25px;
|
||||
}
|
||||
|
||||
/* Definition List styles */
|
||||
|
||||
dd {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
/* Homepage */
|
||||
|
||||
body.homepage div.jumbotron {
|
||||
margin-top: 1.5rem;
|
||||
padding-top: 1rem;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
body.homepage div.jumbotron div.card {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
body.homepage>div.container div.col-md-3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body.homepage>div.container div.col-md-9 {
|
||||
/* margin-left: 0; */
|
||||
/* padding-left: 0; */
|
||||
flex: 0 0 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.center {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.bg-primary {
|
||||
background-image: none;
|
||||
background-color: var(--ukraine-top) !important;
|
||||
}
|
||||
|
||||
body .bg-primary {
|
||||
background-image: none;
|
||||
background-color: var(--ukraine-top);
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
body .btn-primary {
|
||||
background-image: none;
|
||||
background-color: var(--theme-purple);
|
||||
border: 1px solid var(--theme-purple);
|
||||
}
|
||||
|
||||
.navbar.fixed-top {
|
||||
background-image: none;
|
||||
background-color: var(--ukraine-top);
|
||||
border-bottom: 40px solid var(--ukraine-bottom);
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: var(--theme-purple);
|
||||
border: 1px solid var(--theme-purple);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--link-pink);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #996FC2;
|
||||
}
|
||||
|
||||
.col-md-9 img.main-logo {
|
||||
border: 0px;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.ghcup-intro {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.main-buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.main-buttons a {
|
||||
margin-right: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.command-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.command-button > pre {
|
||||
flex: 0 1 80%;
|
||||
margin: 0;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
background-color: #515151;
|
||||
color: white;
|
||||
border-radius: 3px;
|
||||
box-shadow: inset 0px 0px 20px 0px #333333;
|
||||
font-size: 1em;
|
||||
white-space: nowrap;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.ghcup-command:before {
|
||||
color: #999;
|
||||
content: " $ ";
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
div.command-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.command-button pre {
|
||||
|
||||
}
|
||||
|
||||
div.command-button button {
|
||||
color: #515151;
|
||||
background: rgb(230, 230, 230);
|
||||
border: 1px solid grey;
|
||||
margin: 0 0 0 10px;
|
||||
padding: 10px;
|
||||
flex-basis: 0 0 20%;
|
||||
}
|
||||
|
||||
div.command-button button .fa {
|
||||
font-size: x-large;
|
||||
}
|
||||
|
||||
div.command-button button:hover {
|
||||
background: rgb(220, 220, 220);
|
||||
color: black;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
div.command-button button:focus {
|
||||
background-color: #04aa6d;
|
||||
}
|
||||
|
||||
footer > hr {
|
||||
border-top: 0.5px solid #CCC;
|
||||
}
|
||||
|
||||
.qi-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
padding: 0.75rem;
|
||||
background-color: rgb(250, 250, 250);
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-radius: 3px;
|
||||
border: 1px solid rgb(204, 204, 204);
|
||||
box-shadow:
|
||||
4px 8px 10px -6px rgb(204, 204, 204),
|
||||
4px 8px 10px -6px rgb(153, 111, 194);
|
||||
}
|
||||
|
||||
@media only screen and (max-width:1000px) {
|
||||
.qi-container {
|
||||
box-shadow:
|
||||
4px 10px 10px -6px rgb(204, 204, 204),
|
||||
4px 10px 10px -9px rgb(153, 111, 194);
|
||||
}
|
||||
}
|
||||
|
||||
.index-cta-donate .donate-button a {
|
||||
position: absolute;
|
||||
top:0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.index-cta-donate .donate-button {
|
||||
margin: 10px auto;
|
||||
position: relative;
|
||||
display: block;
|
||||
background: none;
|
||||
padding: none;
|
||||
border: none;
|
||||
background: url("https://opencollective.com/webpack/donate/button@2x.png?color=blue");
|
||||
width: 35%;
|
||||
min-width: 240px;
|
||||
max-width: 280px;
|
||||
height: 40px;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.ghcup-os-container {
|
||||
width: 100%;
|
||||
margin: 10px 0;
|
||||
}
|
||||
.ghcup-os-container > * {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* fix list overflows (esp about page) */
|
||||
ul > li {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
|
||||
.footer {
|
||||
color: grey;
|
||||
font-size: 0.7em;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.footer div.show-all-platforms {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#help, #collective {
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#help img {
|
||||
border: none;
|
||||
margin: 0px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.ghcup-help {
|
||||
margin: 10px auto;
|
||||
padding: 10px 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#collective img {
|
||||
border: none;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
#collective {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
122
docs/dev.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# Development
|
||||
|
||||
All you wanted to know about GHCup development.
|
||||
|
||||
## Module graph
|
||||
|
||||
[{: .center style="width:900px"}](./modules_wide.svg)
|
||||
|
||||
Main functionality is in `GHCup` module. Utility functions are
|
||||
organised tree-ish in `GHCup.Utils` and `GHCup.Utils.*`.
|
||||
|
||||
Anything dealing with ghcup specific directories is in
|
||||
`GHCup.Utils.Dirs`.
|
||||
|
||||
Download information on where to fetch bindists from is in the [ghcup-metadata](https://github.com/haskell/ghcup-metadata) repository.
|
||||
|
||||
## Design decisions
|
||||
|
||||
### Using [Excepts](https://hackage.haskell.org/package/haskus-utils-variant-3.0/docs/Haskus-Utils-Variant-Excepts.html) as a beefed up ExceptT
|
||||
|
||||
This is an open variant, similar to [plucky](https://hackage.haskell.org/package/plucky) or [oops](https://github.com/i-am-tom/oops) and allows us to combine different error types. Maybe it is too much and it's a little bit [unergonomic](https://github.com/haskus/packages/issues/32) at times. If it really hurts maintenance, it will be removed. It was more of an experiment.
|
||||
|
||||
### No use of haskell-TLS
|
||||
|
||||
I consider haskell-TLS an interesting experiment, but not a battle-tested and peer-reviewed crypto implementation. There is little to no research about what the intricacies of using haskell for low-level crypto are and how vulnerable such binaries are. Instead, we use either curl the binary or wget. There's also an implementation based on OpenSSL bindings, but it isn't enabled by default, since it would complicate shipping static binaries.
|
||||
|
||||
### Optics instead of lens
|
||||
|
||||
They're a little safer (less Monoid weirdness with view) and have better error messages. Consider the following with [lens](https://hackage.haskell.org/package/lens):
|
||||
|
||||
```
|
||||
> view (_Just . to (++ "abc")) Nothing
|
||||
""
|
||||
```
|
||||
|
||||
vs [optics](https://hackage.haskell.org/package/optics):
|
||||
|
||||
```
|
||||
> view (_Just % to (++ "abc")) Nothing
|
||||
|
||||
<interactive>:2:1: error:
|
||||
• An_AffineFold cannot be used as A_Getter
|
||||
• In the expression: view (_Just % to (++ "abc")) Nothing
|
||||
In an equation for ‘it’: it = view (_Just % to (++ "abc")) Nothing
|
||||
```
|
||||
|
||||
### StrictData on by default
|
||||
|
||||
Kazu Yamamoto [explained it in his PR](https://github.com/yesodweb/wai/pull/752#issuecomment-501531386) very well. I like to agree with him. The instances where we need non-strict behavior, we annotate it.
|
||||
|
||||
`Strict` is a little more odd as a default, since it depends on how you define your functions as well.
|
||||
|
||||
## Code style and formatting
|
||||
|
||||
Unfortunately, code formatters are semi-broken on this codebase, due to TH and CPP.
|
||||
|
||||
Some light suggestions:
|
||||
|
||||
1. mtl-style preferred
|
||||
2. no overly pointfree style
|
||||
3. use `where` a lot, so the main function body reads like prose
|
||||
4. documentation is part of the code
|
||||
|
||||
## Common Tasks
|
||||
|
||||
### Adding a new GHC version
|
||||
|
||||
Head over to: [https://github.com/haskell/ghcup-metadata#adding-a-new-ghc-version](https://github.com/haskell/ghcup-metadata#adding-a-new-ghc-version)
|
||||
|
||||
### Adding a new CLI command
|
||||
|
||||
An example illustration on how to deal with [optparse-applicative](https://hackage.haskell.org/package/optparse-applicative) can be seen here: [https://gitlab.haskell.org/haskell/ghcup-hs/-/commit/c19dd5ee8b2edbaf0336af143f1c75b6f4843e26](https://gitlab.haskell.org/haskell/ghcup-hs/-/commit/c19dd5ee8b2edbaf0336af143f1c75b6f4843e26)
|
||||
|
||||
Every subcommand now lives in its own module under [GHCup.OptParse.MyCommand](https://gitlab.haskell.org/haskell/ghcup-hs/-/tree/master/app/ghcup/GHCup/OptParse).
|
||||
|
||||
## Major refactors
|
||||
|
||||
1. First major refactor included adding cross support. This added
|
||||
`GHCTargetVersion`, which includes the target in addition to the version.
|
||||
Most of the `Version` parameters to functions had to be replaced with
|
||||
that and ensured the logic is consistent for cross and non-cross
|
||||
installs.
|
||||
2. This refactor added windows support wrt [#130](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/130).
|
||||
The major changes here were switching `hpath` library out for `filepath`/`directory` (sadly) and
|
||||
introducing a non-unix way of handling processes via the `process` library. It also introduced considerable
|
||||
amounts of CPP wrt file handling, installation etc.
|
||||
3. This refactor split up the huge `Main.hs` and put every subcommand in its own module: [#212](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/212)
|
||||
|
||||
# Releasing
|
||||
|
||||
1. Update version in `ghcup.cabal`
|
||||
|
||||
2. Update `GHCup.Version` module. `ghcupURL` must only be updated if we change the `GHCupInfo` type or the YAML representation of it. The version of the YAML represents the change increments. `ghcUpVer` is the current application version, read from `ghcup.cabal`.
|
||||
|
||||
3. Add ChangeLog entry
|
||||
|
||||
4. If a new ghcup yaml version is needed, create one at [ghcup-metadata repo](https://github.com/haskell/ghcup-metadata) and push to a temporary release branch, then update the `data/metadata` submodule in ghcup-hs repo to that branch, so CI can pass
|
||||
|
||||
5. Commit and git push with tag. Wait for tests to succeed and release artifacts to build.
|
||||
|
||||
6. Download release artifacts and upload them `downloads.haskell.org/~ghcup` along with checksum files (also check `scripts/releasing/pull_release_artifacts.sh` and `scripts/releasing/sftp-upload-artifacts.sh`)
|
||||
|
||||
7. Add ghcup release artifacts to ALL yaml files, see [ghcup-metadata repo](https://github.com/haskell/ghcup-metadata)
|
||||
|
||||
8. Upload the final `ghcup-<ver>.yaml` (and a detached GPG sig of it) to `webhost.haskell.org/ghcup/data/` (for yaml versions <= 0.0.6) as well as [https://github.com/haskell/ghcup-metadata](https://github.com/haskell/ghcup-metadata) (for all versions).
|
||||
|
||||
9. Update version in `scripts/bootstrap/bootstrap-haskell` (`ghver` variable at the top of the script)
|
||||
|
||||
10. Upload `scripts/bootstrap/bootstrap-haskell` and `scripts/bootstrap/bootstrap-haskell.ps1` to `webhost.haskell.org/ghcup/sh/`
|
||||
|
||||
11. Update the top-level ghcup symlinks at `downloads.haskell.org/~ghcup` (see `scripts/releasing/sftp-symlink-artifacts.sh`)
|
||||
|
||||
12. Update the `data/metadata` submodule in ghcup-hs repo to master
|
||||
|
||||
13. Do hackage release
|
||||
|
||||
14. Post on reddit/discourse/etc. and collect rewards
|
||||
|
||||
# Documentation
|
||||
|
||||
This documentation page is built via [mkdocs](https://www.mkdocs.org/), see `mkdocs.yml` and `docs/` subfolder.
|
||||
The module graph needs [graphmod](https://github.com/yav/graphmod) and is generated via `scripts/dev/modgraph.sh`.
|
||||
65
docs/expand-piece.svg
Normal file
@@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="158.21451"
|
||||
height="33.036404"
|
||||
id="svg2997"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
sodipodi:docname="expand-piece.svg">
|
||||
<defs
|
||||
id="defs2999" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="11.2"
|
||||
inkscape:cx="74.534935"
|
||||
inkscape:cy="-6.6497355"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1374"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata3002">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-218.01937,-324.40519)">
|
||||
<path
|
||||
style="fill:none;stroke:#524a67;stroke-width:13;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 224.64286,330.93361 74.64102,20 70.35898,-18.85263"
|
||||
id="path2994"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
BIN
docs/ghcup.gif
Normal file
|
After Width: | Height: | Size: 198 KiB |
357
docs/guide.md
Normal file
@@ -0,0 +1,357 @@
|
||||
# User Guide
|
||||
|
||||
This is a more in-depth guide specific to GHCup. `ghcup --help` is your friend.
|
||||
|
||||
## Basic usage
|
||||
|
||||
For the simple interactive TUI (not available on windows), run:
|
||||
|
||||
```sh
|
||||
ghcup tui
|
||||
```
|
||||
|
||||
For the full functionality via cli:
|
||||
|
||||
```sh
|
||||
# list available ghc/cabal versions
|
||||
ghcup list
|
||||
|
||||
# install the recommended GHC version
|
||||
ghcup install ghc
|
||||
|
||||
# install a specific GHC version
|
||||
ghcup install ghc 8.2.2
|
||||
|
||||
# set the currently "active" GHC version
|
||||
ghcup set ghc 8.4.4
|
||||
|
||||
# install cabal-install
|
||||
ghcup install cabal
|
||||
|
||||
# update ghcup itself
|
||||
ghcup upgrade
|
||||
```
|
||||
|
||||
### Tags and shortcuts
|
||||
|
||||
GHCup has a number of tags and version shortcuts, that can be used as arguments to **install**/**set** etc.
|
||||
All of the following are valid arguments to `ghcup install ghc`:
|
||||
|
||||
* `latest`, `recommended`
|
||||
* `base-4.15.1.0`
|
||||
* `9.0.2`, `9.0`, `9`
|
||||
|
||||
If the argument is omitted, the default is `recommended`.
|
||||
|
||||
## Manpages
|
||||
|
||||
For man pages to work you need [man-db](http://man-db.nongnu.org/) as your `man` provider, then issue `man ghc`. Manpages only work for the currently set ghc.
|
||||
`MANPATH` may be required to be unset.
|
||||
|
||||
## Shell-completion
|
||||
|
||||
Shell completions are in [scripts/shell-completions](https://gitlab.haskell.org/haskell/ghcup-hs/-/tree/master/scripts/shell-completions) directory of this repository.
|
||||
|
||||
For bash: install `shell-completions/bash`
|
||||
as e.g. `/etc/bash_completion.d/ghcup` (depending on distro)
|
||||
and make sure your bashrc sources the startup script
|
||||
(`/usr/share/bash-completion/bash_completion` on some distros).
|
||||
|
||||
## Portability
|
||||
|
||||
`ghcup` is very portable. There are a few exceptions though:
|
||||
|
||||
1. `ghcup tui` is only available on non-windows platforms
|
||||
2. legacy subcommands `ghcup install` (without a tool identifier) and `ghcup install-cabal` may be removed in the future
|
||||
|
||||
# Configuration
|
||||
|
||||
A configuration file can be put in `~/.ghcup/config.yaml`. The default config file
|
||||
explaining all possible configurations can be found in this repo: [config.yaml](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/data/config.yaml).
|
||||
|
||||
Partial configuration is fine. Command line options always override the config file settings.
|
||||
|
||||
## Env variables
|
||||
|
||||
This is the complete list of env variables that change GHCup behavior:
|
||||
|
||||
* `GHCUP_USE_XDG_DIRS`: see [XDG support](#xdg-support) above
|
||||
* `GHCUP_INSTALL_BASE_PREFIX`: the base of ghcup (default: `$HOME`)
|
||||
* `GHCUP_CURL_OPTS`: additional options that can be passed to curl
|
||||
* `GHCUP_WGET_OPTS`: additional options that can be passed to wget
|
||||
* `GHCUP_GPG_OPTS`: additional options that can be passed to gpg
|
||||
* `GHCUP_SKIP_UPDATE_CHECK`: Skip the (possibly annoying) update check when you run a command
|
||||
* `CC`/`LD` etc.: full environment is passed to the build system when compiling GHC via GHCup
|
||||
|
||||
### XDG support
|
||||
|
||||
To enable XDG style directories, set the environment variable `GHCUP_USE_XDG_DIRS` to anything.
|
||||
|
||||
Then you can control the locations via XDG environment variables as such:
|
||||
|
||||
* `XDG_DATA_HOME`: GHCs will be unpacked in `ghcup/ghc` subdir (default: `~/.local/share`)
|
||||
* `XDG_CACHE_HOME`: logs and download files will be stored in `ghcup` subdir (default: `~/.cache`)
|
||||
* `XDG_BIN_HOME`: binaries end up here (default: `~/.local/bin`)
|
||||
* `XDG_CONFIG_HOME`: the config file is stored in `ghcup` subdir as `config.yaml` (default: `~/.config`)
|
||||
|
||||
**Note that `ghcup` makes some assumptions about structure of files in `XDG_BIN_HOME`. So if you have other tools
|
||||
installing e.g. stack/cabal/ghc into it, this will likely clash. In that case consider disabling XDG support.**
|
||||
|
||||
## Caching
|
||||
|
||||
GHCup has a few caching mechanisms to avoid redownloads. All cached files end up in `~/.ghcup/cache` by default.
|
||||
|
||||
### Downloads cache
|
||||
|
||||
Downloaded tarballs (such as GHC, cabal, etc.) are not cached by default unless you pass `ghcup --cache` or set caching
|
||||
in your [config](#configuration) via `ghcup config set cache true`.
|
||||
|
||||
### Metadata cache
|
||||
|
||||
The metadata files (also see [github.com/haskell/ghcup-metadata](https://github.com/haskell/ghcup-metadata))
|
||||
have a 5 minutes cache per default depending on the last access time of the file. That means if you run
|
||||
`ghcup list` 10 times in a row, only the first time will trigger a download attempt.
|
||||
|
||||
### Clearing the cache
|
||||
|
||||
If you experience problems, consider clearing the cache via `ghcup gc --cache`.
|
||||
|
||||
## Metadata
|
||||
|
||||
The metadata are the files that describe tool versions, where to download them etc. and
|
||||
can be viewed here: [https://github.com/haskell/ghcup-metadata](https://github.com/haskell/ghcup-metadata)
|
||||
|
||||
### Mirrors
|
||||
|
||||
GHCup allows to use custom mirrors/download-info hosted by yourself or 3rd parties.
|
||||
|
||||
To use a mirror, set the following option in `~/.ghcup/config.yaml`:
|
||||
|
||||
```yml
|
||||
url-source:
|
||||
# Accepts file/http/https scheme
|
||||
OwnSource: "https://some-url/ghcup-0.0.6.yaml"
|
||||
```
|
||||
|
||||
See [config.yaml](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/data/config.yaml)
|
||||
for more options.
|
||||
|
||||
Alternatively you can do it via a cli switch:
|
||||
|
||||
```sh
|
||||
ghcup --url-source=https://some-url/ghcup-0.0.6.yaml list
|
||||
```
|
||||
|
||||
#### Known mirrors
|
||||
|
||||
1. [https://mirror.sjtu.edu.cn/docs/ghcup](https://mirror.sjtu.edu.cn/docs/ghcup)
|
||||
|
||||
### (Pre-)Release channels
|
||||
|
||||
A release channel is basically just a metadata file location. You can add additional release
|
||||
channels that complement the default one, such as the **prerelease channel** like so:
|
||||
|
||||
```sh
|
||||
ghcup config add-release-channel https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-prereleases-0.0.7.yaml
|
||||
```
|
||||
|
||||
This will result in `~/.ghcup/config.yaml` to contain this record:
|
||||
|
||||
```yml
|
||||
url-source:
|
||||
AddSource:
|
||||
- Right: https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-prereleases-0.0.7.yaml
|
||||
```
|
||||
|
||||
You can add as many channels as you like. They are combined under *Last*, so versions from the prerelease channel
|
||||
here overwrite the default ones, if any.
|
||||
|
||||
To remove the channel, delete the entire `url-source` section or set it back to the default:
|
||||
|
||||
```yml
|
||||
url-source:
|
||||
GHCupURL: []
|
||||
```
|
||||
|
||||
If you want to combine your release channel with a mirror, you'd do it like so:
|
||||
|
||||
```yml
|
||||
url-source:
|
||||
OwnSource:
|
||||
# base metadata
|
||||
- "https://mirror.sjtu.edu.cn/ghcup/yaml/ghcup/data/ghcup-0.0.6.yaml"
|
||||
# prerelease channel
|
||||
- "https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-prereleases-0.0.7.yaml"
|
||||
```
|
||||
|
||||
# More on installation
|
||||
|
||||
## Installing custom bindists
|
||||
|
||||
There are a couple of good use cases to install custom bindists:
|
||||
|
||||
1. manually built bindists (e.g. with patches)
|
||||
- example: `ghcup install ghc -u 'file:///home/mearwald/tmp/ghc-eff-patches/ghc-8.10.2-x86_64-deb10-linux.tar.xz' 8.10.2-eff`
|
||||
2. GHC head CI bindists
|
||||
- example: `ghcup install ghc -u 'https://gitlab.haskell.org/api/v4/projects/1/jobs/artifacts/master/raw/ghc-x86_64-fedora27-linux.tar.xz?job=validate-x86_64-linux-fedora27' head`
|
||||
3. DWARF bindists
|
||||
- example: `ghcup install ghc -u 'https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-deb10-linux-dwarf.tar.xz' 8.10.2-dwarf`
|
||||
|
||||
Since the version parser is pretty lax, `8.10.2-eff` and `head` are both valid versions
|
||||
and produce the binaries `ghc-8.10.2-eff` and `ghc-head` respectively.
|
||||
GHCup always needs to know which version the bindist corresponds to (this is not automatically
|
||||
detected).
|
||||
|
||||
## Compiling GHC from source
|
||||
|
||||
Compiling from source is supported for both source tarballs and arbitrary git refs. See `ghcup compile ghc --help`
|
||||
for a list of all available options.
|
||||
|
||||
If you need to overwrite the existing `build.mk`, check the default files
|
||||
in [data/build_mk](https://gitlab.haskell.org/haskell/ghcup-hs/-/tree/master/data/build_mk), copy them somewhere, adjust them and
|
||||
pass `--config path/to/build.mk` to `ghcup compile ghc`.
|
||||
Common `build.mk` options are explained [here](https://gitlab.haskell.org/ghc/ghc/-/wikis/building/using#build-configuration).
|
||||
|
||||
Make sure your system meets all the [prerequisites](https://gitlab.haskell.org/ghc/ghc/-/wikis/building/preparation).
|
||||
|
||||
### Cross support
|
||||
|
||||
ghcup can compile and install a cross GHC for any target. However, this
|
||||
requires that the build host has a complete cross toolchain and various
|
||||
libraries installed for the target platform.
|
||||
|
||||
Consult the GHC documentation on the [prerequisites](https://gitlab.haskell.org/ghc/ghc/-/wikis/building/cross-compiling#tools-to-install).
|
||||
For distributions with non-standard locations of cross toolchain and
|
||||
libraries, this may need some tweaking of `build.mk` or configure args.
|
||||
See `ghcup compile ghc --help` for further information.
|
||||
|
||||
## Isolated installs
|
||||
|
||||
**Before using isolated installs, make sure to have at least GHCup version 0.1.17.8!**
|
||||
|
||||
Ghcup also enables you to install a tool (GHC, Cabal, HLS, Stack) at an isolated location of your choosing.
|
||||
These installs, as the name suggests, are separate from your main installs and DO NOT conflict with them.
|
||||
|
||||
|
||||
- No symlinks are made to these isolated installed tools, you'd have to manually point to them wherever you intend to use them.
|
||||
|
||||
- These installs, can also NOT be deleted from ghcup, you'd have to go and manually delete these.
|
||||
|
||||
You need to use the `--isolate` or `-i` flag followed by the directory path.
|
||||
|
||||
Examples:
|
||||
|
||||
1. install an isolated GHC version at location /home/user/isolated_dir/ghc/
|
||||
- `ghcup install ghc 8.10.5 --isolate /home/user/isolated_dir/ghc`
|
||||
|
||||
2. isolated install Cabal at a location you desire
|
||||
- `ghcup install cabal --isolate /home/username/my_isolated_dir/`
|
||||
|
||||
3. do an isolated install with a custom bindist
|
||||
- `ghcup install ghc --isolate /home/username/my_isolated_dir/ -u 'https://gitlab.haskell.org/api/v4/projects/1/jobs/artifacts/master/raw/ghc-x86_64-fedora27-linux.tar.xz?job=validate-x86_64-linux-fedora27' head`
|
||||
|
||||
4. isolated install HLS
|
||||
- `ghcup install hls --isolate /home/username/dir/hls/`
|
||||
|
||||
5. you can even compile ghc to an isolated location.
|
||||
- `ghcup compile ghc -j 4 -v 9.0.1 -b 8.10.5 -i /home/username/my/dir/ghc`
|
||||
|
||||
## Continuous integration
|
||||
|
||||
On windows, ghcup can be installed automatically on a CI runner non-interactively like so:
|
||||
|
||||
```ps
|
||||
Set-ExecutionPolicy Bypass -Scope Process -Force;[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -ArgumentList $false,$true,$true,$false,$false,$false,$false,"C:\"
|
||||
```
|
||||
|
||||
On linux/darwin/freebsd, run the following on your runner:
|
||||
|
||||
```sh
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 BOOTSTRAP_HASKELL_MINIMAL=1 sh
|
||||
```
|
||||
|
||||
This will just install `ghcup` and on windows additionally `msys2`.
|
||||
|
||||
For the full list of env variables and parameters to tweak the script behavior, see:
|
||||
|
||||
* [bootstrap-haskell for linux/darwin/freebsd](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/scripts/bootstrap/bootstrap-haskell#L7)
|
||||
* [bootstrap-haskell.ps1 for windows](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/scripts/bootstrap/bootstrap-haskell.ps1#L17)
|
||||
|
||||
### github workflows
|
||||
|
||||
On github workflows you can use [https://github.com/haskell/actions/](https://github.com/haskell/actions/).
|
||||
GHCup itself is also pre-installed on all platforms, but may use non-standard install locations.
|
||||
|
||||
## GPG verification
|
||||
|
||||
GHCup supports verifying the GPG signature of the metadata file. The metadata file then contains SHA256 hashes of all downloads, so
|
||||
this is cryptographically secure.
|
||||
|
||||
First, obtain the gpg keys:
|
||||
|
||||
```sh
|
||||
gpg --batch --keyserver keys.openpgp.org --recv-keys 7784930957807690A66EBDBE3786C5262ECB4A3F
|
||||
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys FE5AB6C91FEA597C3B31180B73EDE9E8CFBAEF01
|
||||
```
|
||||
|
||||
Then verify the gpg key in one of these ways:
|
||||
|
||||
1. find out where I live and visit me to do offline key signing
|
||||
2. figure out my mobile phone number and call me to verify the fingerprint
|
||||
3. more boring: contact me on Libera IRC (`maerwald`) and verify the fingerprint
|
||||
|
||||
Once you've verified the key, you have to figure out if you trust me.
|
||||
|
||||
If you trust me, then you can configure gpg in `~/.ghcup/config.yaml`:
|
||||
|
||||
```yml
|
||||
gpg-setting: GPGLax # GPGStrict | GPGLax | GPGNone
|
||||
```
|
||||
|
||||
In `GPGStrict` mode, ghcup will fail if verification fails. In `GPGLax` mode it will just print a warning.
|
||||
You can also pass the mode via `ghcup --gpg <strict|lax|none>`.
|
||||
|
||||
# Tips and tricks
|
||||
|
||||
## ghcup run
|
||||
|
||||
If you don't want to explicitly switch the active GHC all the time and are using
|
||||
tools that rely on the plain `ghc` binary, GHCup provides an easy way to execute
|
||||
commands with a certain toolchain prepended to PATH, e.g.:
|
||||
|
||||
```sh
|
||||
ghcup run --ghc 8.10.7 --cabal latest --hls latest --stack latest --install -- code Setup.hs
|
||||
```
|
||||
|
||||
This will execute vscode with GHC set to 8.10.7 and all other tools to their latest version.
|
||||
|
||||
# Troubleshooting
|
||||
|
||||
## Script immediately exits on windows
|
||||
|
||||
There are two possible reasons:
|
||||
|
||||
1. your company blocks the script (some have a whitelist)... ask your administrator
|
||||
2. your Antivirus or Windows Defender interfere with the installation. Disable them temporarily.
|
||||
|
||||
## C compiler cannot create executables
|
||||
|
||||
### Darwin
|
||||
|
||||
You need to update your XCode command line tools, e.g. [like this](https://stackoverflow.com/questions/34617452/how-to-update-xcode-from-command-line).
|
||||
|
||||
## Certificate authority errors (curl)
|
||||
|
||||
If your certificates are outdated or improperly configured, curl may be unable
|
||||
to download ghcup.
|
||||
|
||||
There are two known workarounds:
|
||||
|
||||
1. Tell curl to ignore certificate errors (dangerous): `curl -k https://gitlab.haskell.org/haskell/ghcup-hs/-/raw/master/scripts/bootstrap/bootstrap-haskell | GHCUP_CURL_OPTS="-k" sh`
|
||||
2. Try to use wget instead: `wget -O /dev/stdout https://gitlab.haskell.org/haskell/ghcup-hs/-/raw/master/scripts/bootstrap/bootstrap-haskell | BOOTSTRAP_HASKELL_DOWNLOADER=wget sh`
|
||||
|
||||
On windows, you can disable curl like so:
|
||||
|
||||
```pwsh
|
||||
Set-ExecutionPolicy Bypass -Scope Process -Force;[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -ArgumentList $true,$false,$false,$false,$false,$false,$false,"","","","",$true
|
||||
```
|
||||
BIN
docs/haskell_logo.png
Normal file
|
After Width: | Height: | Size: 93 KiB |
100
docs/index.md
Normal file
@@ -0,0 +1,100 @@
|
||||
---
|
||||
hide:
|
||||
- navigation
|
||||
- toc
|
||||
---
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||
<script src="javascripts/extra.js"></script>
|
||||
|
||||
|
||||
<section class="index-ghcup-hero">
|
||||
<img alt="haskell logo" src="./haskell_logo.png" />
|
||||
<h1>GHCup</h1>
|
||||
</section>
|
||||
|
||||
<p class="ghcup-intro">GHCup is an installer for the general purpose language <a href="https://www.haskell.org">Haskell</a>.</p>
|
||||
|
||||
<div class="text-center main-buttons">
|
||||
<a href="install/" class="btn btn-primary" role="button">Getting Started</a>
|
||||
<a href="steps/" class="btn btn-primary" role="button">First steps</a>
|
||||
<a href="guide/" class="btn btn-primary" role="button">User Guide</a>
|
||||
</div>
|
||||
|
||||
<section class="qi-container">
|
||||
|
||||
<div class="ghcup-os-container" id="ghcup-instructions-unix">
|
||||
<h3>To install on Linux, macOS, FreeBSD or <a href="https://docs.microsoft.com/en-us/windows/wsl/"> WSL2</a></h3>
|
||||
<p>run the following in a terminal (as a non-root user):<p>
|
||||
<div class="command-button">
|
||||
<pre>
|
||||
<span class="ghcup-command" id="ghcup-command-linux">curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh</span>
|
||||
</pre>
|
||||
<button class="btn" onclick="copyToClipboardNux()" id="ghcup-linux-button"><i class="fa fa-copy"></i></button>
|
||||
</div>
|
||||
<span>
|
||||
</span>
|
||||
<div class="footer">
|
||||
<a href="https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/scripts/bootstrap/bootstrap-haskell" target="_blank">What does this do?</a> <b> · </b> <a href="https://www.haskell.org/ghcup/install/#manual-install">I don't like curl | sh</a> <div class="show-all-platforms"><b> · </b> <a class="show-all-platforms-button" href="#">Show all platforms</a></div></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ghcup-os-container" id="ghcup-instructions-win">
|
||||
<h3>To install on Windows</h3>
|
||||
<p>run the following in a PowerShell session (as a non-admin user):<p>
|
||||
|
||||
<div class="command-button">
|
||||
<pre>
|
||||
<span class="ghcup-command" id="ghcup-command-windows">Set-ExecutionPolicy Bypass -Scope Process -Force;[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -ArgumentList $true
|
||||
</span>
|
||||
</pre>
|
||||
<button class="btn" onclick="copyToClipboardWin()" id="ghcup-windows-button"><i class="fa fa-copy"></i></button>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<a href="https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/scripts/bootstrap/bootstrap-haskell.ps1" target="_blank">What does this do?</a> <b> · </b> <a href="https://www.haskell.org/ghcup/install/#manual-install">I don't like curl | sh</a> <div class="show-all-platforms"><b> · </b> <a class="show-all-platforms-button" href="#">Show all platforms</a></div></p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<p id="help" class="ghcup-help">
|
||||
Need help? Check the <a href="guide/#troubleshooting">Troubleshooting section</a> or ask on
|
||||
<span>
|
||||
<a href="https://kiwiirc.com/nextclient/irc.libera.chat/?nick=Guest%7C?#haskell,#haskell-ghcup">
|
||||
<img src="irc.svg" alt="" />
|
||||
IRC
|
||||
</a>
|
||||
</span>,
|
||||
<span>
|
||||
<a href="https://discord.gg/pKYf3zDQU7">
|
||||
<img src="Discord-Logo-Black.svg" alt="" />
|
||||
Discord
|
||||
</a>
|
||||
</span>,
|
||||
<span>
|
||||
<a href="https://app.element.io/#/room/#haskell-tooling:matrix.org">
|
||||
<img src="Matrix_logo.svg" alt=""/>
|
||||
</a>
|
||||
</span>
|
||||
or
|
||||
<span>
|
||||
<a href="https://gitlab.haskell.org/haskell/ghcup-hs/issues">
|
||||
report a bug
|
||||
<img src="Octicons-bug.svg" alt="" />
|
||||
</a>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<script type="text/javascript" src="javascripts/ghcup.js"></script>
|
||||
|
||||
|
||||
----
|
||||
|
||||
|
||||
{: .center style="width:700px"}
|
||||
|
||||
<section class="index-cta-donate">
|
||||
<button class="donate-button">
|
||||
<a href="https://opencollective.com/ghcup#category-CONTRIBUTE" class="donate-badge" />
|
||||
</a>
|
||||
</button>
|
||||
</section>
|
||||
217
docs/install.md
Normal file
@@ -0,0 +1,217 @@
|
||||
# Getting started
|
||||
|
||||
GHCup makes it easy to install specific versions of GHC on GNU/Linux,
|
||||
macOS (aka Darwin), FreeBSD and Windows and can also bootstrap a fresh [Haskell developer environment](./install/#supported-tools) from scratch.
|
||||
It follows the UNIX philosophy of [do one thing and do it well](https://en.wikipedia.org/wiki/Unix_philosophy#Do_One_Thing_and_Do_It_Well). Similar in scope to [rustup](https://github.com/rust-lang-nursery/rustup.rs), [pyenv](https://github.com/pyenv/pyenv) and [jenv](http://www.jenv.be).
|
||||
|
||||
## Installation
|
||||
|
||||
The following commands will download the `ghcup` binary into `~/.ghcup/bin` (or `C:\ghcup\bin` on windows) and then
|
||||
run it to interactively install the [Haskell Toolchain](#supported-tools). These commands should be run as **non-root/non-admin
|
||||
user**.
|
||||
|
||||
For Linux, macOS, FreeBSD or Windows Subsystem 2 for Linux, run this in a terminal:
|
||||
|
||||
```sh
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
|
||||
```
|
||||
|
||||
For Windows, run this in a PowerShell session:
|
||||
|
||||
```psh
|
||||
Set-ExecutionPolicy Bypass -Scope Process -Force;[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -ArgumentList $true
|
||||
```
|
||||
|
||||
There's also a [youtube video](https://www.youtube.com/watch?v=bB4fmQiUYPw) explaining installation on windows.
|
||||
|
||||
If you want to know what these scripts do, check out the [source code at the repository](https://gitlab.haskell.org/haskell/ghcup-hs/-/tree/master/scripts/bootstrap). Advanced users may want to perform a [manual installation](#manual-install) and GPG verify the binaries.
|
||||
|
||||
### Which versions get installed?
|
||||
|
||||
GHCup has two main channels for every tool: **recommended** and **latest**. By default, it installs *recommended*.
|
||||
|
||||
*latest* follows the latest release of every tool, while *recommended* is at the discretion of the GHCup maintainers and based on community adoption (hackage libraries, tools like HLS, stackage support, etc.) and known bugs.
|
||||
|
||||
Also see [tags and shortcuts](../guide/#tags-and-shortcuts) for more information.
|
||||
|
||||
## Next steps
|
||||
|
||||
1. Follow the [First steps guide](../steps) on how to build a "Hello world" program, use `ghc`, run an interactive REPL and create a Haskell project
|
||||
2. To understand the difference and overlap of `stack` and `cabal`, read on [here](https://gist.github.com/merijn/8152d561fb8b011f9313c48d876ceb07)
|
||||
3. To learn Haskell proper check out the links at [How to learn Haskell proper](../steps#how-to-learn-haskell-proper)
|
||||
4. To learn more about Haskell Toolchain management, check out the [ghcup user guide](./guide.md)
|
||||
|
||||
## Uninstallation
|
||||
|
||||
On linux, just run `ghcup nuke`, then make sure any ghcup added lines in your `~/.bashrc` (or similar) are removed.
|
||||
|
||||
On windows, right click on the `Uninstall Haskell.ps1` PowerShell script on your Desktop and select *Run with PowerShell*.
|
||||
|
||||
## Supported tools
|
||||
|
||||
GHCup supports the following tools, which are also known as the **Haskell Toolchain**:
|
||||
|
||||
<details> <summary>Show all supported <a href='https://www.haskell.org/ghc/'>GHC</a> versions</summary>
|
||||
<table>
|
||||
<thead><tr><th>GHC Version</th><th>Tags</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>9.2.3</td><td><span style="color:blue">latest</span>, base-4.16.2.0</td></tr>
|
||||
<tr><td>9.2.2</td><td>base-4.16.1.0</td></tr>
|
||||
<tr><td>9.2.1</td><td>base-4.16.0.0</td></tr>
|
||||
<tr><td>9.0.2</td><td>base-4.15.1.0</td></tr>
|
||||
<tr><td>9.0.1</td><td>base-4.15.0.0</td></tr>
|
||||
<tr><td>8.10.7</td><td><span style="color:green">recommended</span>, base-4.14.3.0</td></tr>
|
||||
<tr><td>8.10.6</td><td>base-4.14.3.0</td></tr>
|
||||
<tr><td>8.10.5</td><td>base-4.14.2.0</td></tr>
|
||||
<tr><td>8.10.4</td><td>base-4.14.1.0</td></tr>
|
||||
<tr><td>8.10.3</td><td>base-4.14.1.0</td></tr>
|
||||
<tr><td>8.10.2</td><td>base-4.14.1.0</td></tr>
|
||||
<tr><td>8.10.1</td><td>base-4.14.0.0</td></tr>
|
||||
<tr><td>8.8.4</td><td>base-4.13.0.0</td></tr>
|
||||
<tr><td>8.8.3</td><td>base-4.13.0.0</td></tr>
|
||||
<tr><td>8.8.2</td><td>base-4.13.0.0</td></tr>
|
||||
<tr><td>8.8.1</td><td>base-4.13.0.0</td></tr>
|
||||
<tr><td>8.6.5</td><td>base-4.12.0.0</td></tr>
|
||||
<tr><td>8.6.4</td><td>base-4.12.0.0</td></tr>
|
||||
<tr><td>8.6.3</td><td>base-4.12.0.0</td></tr>
|
||||
<tr><td>8.6.2</td><td>base-4.12.0.0</td></tr>
|
||||
<tr><td>8.6.1</td><td>base-4.12.0.0</td></tr>
|
||||
<tr><td>8.4.4</td><td>base-4.11.1.0</td></tr>
|
||||
<tr><td>8.4.3</td><td>base-4.11.1.0</td></tr>
|
||||
<tr><td>8.4.2</td><td>base-4.11.1.0</td></tr>
|
||||
<tr><td>8.4.1</td><td>base-4.11.0.0</td></tr>
|
||||
<tr><td>8.2.2</td><td>base-4.10.1.0</td></tr>
|
||||
<tr><td>8.0.2</td><td>base-4.9.1.0</td></tr>
|
||||
<tr><td>7.10.3</td><td>base-4.8.2.0</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</details>
|
||||
|
||||
<details> <summary>Show all supported <a href='https://cabal.readthedocs.io/en/stable/'>cabal-install</a> versions</summary>
|
||||
<table>
|
||||
<thead><tr><th>Cabal Version</th><th>Tags</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>3.6.2.0</td><td><span style="color:blue">latest</span>, <span style="color:green">recommended</span></td></tr>
|
||||
<tr><td>3.6.0.0</td><td></td></tr>
|
||||
<tr><td>3.4.1.0</td><td></td></tr>
|
||||
<tr><td>3.4.0.0</td><td></td></tr>
|
||||
<tr><td>3.2.0.0</td><td></td></tr>
|
||||
<tr><td>3.0.0.0</td><td></td></tr>
|
||||
<tr><td>2.4.1.0</td><td></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</details>
|
||||
|
||||
<details> <summary>Show all supported <a href='https://haskell-language-server.readthedocs.io/en/stable/'>HLS</a> versions</summary>
|
||||
<table>
|
||||
<thead><tr><th>HLS Version</th><th>Tags</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>1.7.0.0</td><td><span style="color:blue">latest</span>, <span style="color:green">recommended</span></td></tr>
|
||||
<tr><td>1.6.1.0</td><td></td></tr>
|
||||
<tr><td>1.6.0.0</td><td></td></tr>
|
||||
<tr><td>1.5.1</td><td></td></tr>
|
||||
<tr><td>1.5.0</td><td></td></tr>
|
||||
<tr><td>1.4.0</td><td></td></tr>
|
||||
<tr><td>1.3.0</td><td></td></tr>
|
||||
<tr><td>1.2.0</td><td></td></tr>
|
||||
<tr><td>1.1.0</td><td></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</details>
|
||||
|
||||
<details> <summary>Show all supported <a href='https://docs.haskellstack.org/en/stable/README/'>Stack</a> versions</summary>
|
||||
<table>
|
||||
<thead><tr><th>Stack Version</th><th>Tags</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>2.7.5</td><td><span style="color:blue">latest</span>, <span style="color:green">recommended</span></td></tr>
|
||||
<tr><td>2.7.3</td><td></td></tr>
|
||||
<tr><td>2.7.1</td><td></td></tr>
|
||||
<tr><td>2.5.1</td><td></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</details>
|
||||
|
||||
## Supported platforms
|
||||
|
||||
This list may not be exhaustive and specifies support for bindists only.
|
||||
|
||||
| Platform | Architecture | ghcup | GHC | cabal | HLS | stack |
|
||||
| ------ | ------ | ------ | ------ | ------ | ------ | ------ |
|
||||
| Windows 7 | amd64 | ❔ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Windows 10 | amd64 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Windows Server 2016 | amd64 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Windows Server 2019 | amd64 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Windows Server 2022 | amd64 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Windows WSL1 | amd64 | ❌ | ❔ | ❔ | ❔ | ❔ |
|
||||
| Windows WSL2 | amd64 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| MacOS >=10.13 | amd64 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| MacOS <10.13 | amd64 | ❌ | ❔ | ❔ | ❔ | ❔ |
|
||||
| MacOS | aarch64 | ✅ | ✅ | ✅ | ⚠️ | ❌ |
|
||||
| FreeBSD | amd64 | ✅ | ⚠️ | ✅ | ⚠️ | ❌ |
|
||||
| Linux generic | x86 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Linux generic | amd64 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Linux generic | aarch64 | ✅ | ⚠️ | ✅ | ⚠️ | ❌ |
|
||||
| Linux generic | armv7 | ✅ | ⚠️ | ✅ | ⚠️ | ❌ |
|
||||
|
||||
### Windows 7
|
||||
|
||||
May or may not work, several issues:
|
||||
|
||||
* [https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/140](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/140)
|
||||
* [https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/197](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/197)
|
||||
|
||||
### WSL1
|
||||
|
||||
Unsupported. GHC may or may not work. Upgrade to WSL2.
|
||||
|
||||
### MacOS <10.13
|
||||
|
||||
Not supported. Would require separate binaries, since >=10.13 binaries are incompatible.
|
||||
Please upgrade.
|
||||
|
||||
### MacOS aarch64
|
||||
|
||||
HLS bindists are still experimental. Stack has only unofficial binaries for this platform.
|
||||
There are various issues with GHC itself.
|
||||
|
||||
### FreeBSD
|
||||
|
||||
Lacks some upstream bindists and may need compat libs, since most bindists are built on FreeBSD-12.
|
||||
HLS bindists are experimental.
|
||||
|
||||
### Linux ARMv7/AARCH64
|
||||
|
||||
Lower availability of bindists. Stack and HLS binaries are experimental.
|
||||
|
||||
## Manual install
|
||||
|
||||
Download the binary for your platform at [https://downloads.haskell.org/~ghcup/](https://downloads.haskell.org/~ghcup/)
|
||||
and place it into your `PATH` anywhere.
|
||||
|
||||
If you want to GPG verify the binaries, import the following keys first: `7784930957807690A66EBDBE3786C5262ECB4A3F` and `FE5AB6C91FEA597C3B31180B73EDE9E8CFBAEF01`.
|
||||
|
||||
Then adjust your `PATH` in `~/.bashrc` (or similar, depending on your shell) like so:
|
||||
|
||||
```sh
|
||||
export PATH="$HOME/.cabal/bin:$HOME/.ghcup/bin:$PATH"
|
||||
```
|
||||
|
||||
## Vim integration
|
||||
|
||||
See [ghcup.vim](https://github.com/hasufell/ghcup.vim).
|
||||
|
||||
## VSCode integration
|
||||
The developers of the Haskell Language Server offer an [extension](https://github.com/haskell/vscode-haskell) tightly integrated with the [Haskell Language Server](https://github.com/haskell/haskell-language-server). To get started:
|
||||
|
||||
1. Install GHCup. During installation, opt in to install the Haskell Language Server (HLS).
|
||||
2. Install the extension (from VSCode: Ctrl + P and then `ext install haskell.haskell`).
|
||||
3. Make sure your project uses the GHC version installed from GHCup (otherwise HLS is likely to fail on launch):
|
||||
- instructions for [stack](https://docs.haskellstack.org/en/stable/yaml_configuration/#system-ghc)
|
||||
|
||||
## Get help
|
||||
|
||||
* [Libera IRC chat on #haskell-ghcup or #haskell](https://kiwiirc.com/nextclient/irc.libera.chat/?nick=Guest%7C?#haskell,#haskell-ghcup)
|
||||
* [GHCup issue tracker](https://gitlab.haskell.org/haskell/ghcup-hs/issues)
|
||||
* [Matrix](https://app.element.io/#/room/#haskell-tooling:matrix.org)
|
||||
* [Discord](https://discord.gg/pKYf3zDQU7)
|
||||
|
||||
38
docs/irc.svg
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
height="18.043058"
|
||||
viewBox="0 0 18 18.043058"
|
||||
width="18"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="irc.svg"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="36.375"
|
||||
inkscape:cx="3.3814433"
|
||||
inkscape:cy="9.0309278"
|
||||
inkscape:window-width="3828"
|
||||
inkscape:window-height="2081"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="46"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<path
|
||||
class="heroicon-ui"
|
||||
d="m 8.03,5.0375961 h 3.94 l 1.06,-4.23999995 a 1,1 0 1 1 1.94,0.47999995 l -0.94,3.76 H 17 a 1,1 0 0 1 0,2 h -3.47 l -1,3.9999999 H 15 a 1,1 0 1 1 0,2 h -2.97 l -1.06,4.25 a 1.0004624,1.0004624 0 1 1 -1.94,-0.49 l 0.94,-3.76 H 6.03 l -1.06,4.25 a 1.0004624,1.0004624 0 1 1 -1.94,-0.49 l 0.94,-3.76 H 1 a 1,1 0 0 1 0,-2 h 3.47 l 1,-3.9999999 H 3 a 1,1 0 0 1 0,-2 H 5.97 L 7.03,0.79759615 A 1,1 0 1 1 8.97,1.2775961 Z m -0.5,2 -1,3.9999999 h 3.94 l 1,-3.9999999 z"
|
||||
id="path2" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
119
docs/javascripts/extra.js
Normal file
@@ -0,0 +1,119 @@
|
||||
var platforms = ["win", "unix"];
|
||||
var platform_override = null;
|
||||
|
||||
function detect_platform() {
|
||||
"use strict";
|
||||
|
||||
if (platform_override !== null) {
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
var os = "unknown";
|
||||
|
||||
if (navigator.platform == "Linux x86_64") {os = "unix";}
|
||||
if (navigator.platform == "Linux i686") {os = "unix";}
|
||||
if (navigator.platform == "Linux i686 on x86_64") {os = "unix";}
|
||||
if (navigator.platform == "Linux aarch64") {os = "unix";}
|
||||
if (navigator.platform == "Linux armv6l") {os = "unix";}
|
||||
if (navigator.platform == "Linux armv7l") {os = "unix";}
|
||||
if (navigator.platform == "Linux armv8l") {os = "unix";}
|
||||
if (navigator.platform == "Linux ppc64") {os = "unix";}
|
||||
if (navigator.platform == "Linux mips") {os = "unix";}
|
||||
if (navigator.platform == "Linux mips64") {os = "unix";}
|
||||
if (navigator.platform == "Mac") {os = "unix";}
|
||||
if (navigator.platform == "Win32") {os = "win";}
|
||||
if (navigator.platform == "Win64" ||
|
||||
navigator.userAgent.indexOf("WOW64") != -1 ||
|
||||
navigator.userAgent.indexOf("Win64") != -1) {os = "win";}
|
||||
if (navigator.platform == "FreeBSD x86_64") {os = "unix";}
|
||||
if (navigator.platform == "FreeBSD amd64") {os = "unix";}
|
||||
// if (navigator.platform == "NetBSD x86_64") {os = "unix";}
|
||||
// if (navigator.platform == "NetBSD amd64") {os = "unix";}
|
||||
|
||||
// I wish I knew by now, but I don't. Try harder.
|
||||
if (os == "unknown") {
|
||||
if (navigator.appVersion.indexOf("Win")!=-1) {os = "win";}
|
||||
if (navigator.appVersion.indexOf("Mac")!=-1) {os = "unix";}
|
||||
if (navigator.appVersion.indexOf("FreeBSD")!=-1) {os = "unix";}
|
||||
}
|
||||
|
||||
// Firefox Quantum likes to hide platform and appVersion but oscpu works
|
||||
if (navigator.oscpu) {
|
||||
if (navigator.oscpu.indexOf("Win32")!=-1) {os = "win";}
|
||||
if (navigator.oscpu.indexOf("Win64")!=-1) {os = "win";}
|
||||
if (navigator.oscpu.indexOf("Mac")!=-1) {os = "unix";}
|
||||
if (navigator.oscpu.indexOf("Linux")!=-1) {os = "unix";}
|
||||
if (navigator.oscpu.indexOf("FreeBSD")!=-1) {os = "unix";}
|
||||
// if (navigator.oscpu.indexOf("NetBSD")!=-1) {os = "unix";}
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
function adjust_for_platform() {
|
||||
"use strict";
|
||||
|
||||
var platform = detect_platform();
|
||||
|
||||
if (platforms.includes(platform)) {
|
||||
platforms.forEach(function (platform_elem) {
|
||||
var platform_div = document.getElementById("ghcup-instructions-" + platform_elem);
|
||||
platform_div.style.display = "none";
|
||||
if (platform == platform_elem) {
|
||||
platform_div.style.display = "block";
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function show_all_platforms() {
|
||||
platforms.forEach(function (platform_elem) {
|
||||
var platform_div = document.getElementById("ghcup-instructions-" + platform_elem);
|
||||
platform_div.style.display = "block";
|
||||
});
|
||||
|
||||
var buttons = document.getElementsByClassName("show-all-platforms");
|
||||
console.log(buttons);
|
||||
Array.from(buttons).forEach(function (button) {
|
||||
button.style.display = "none";
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function set_up_default_platform_buttons() {
|
||||
var defaults_buttons = document.getElementsByClassName('show-all-platforms-button');
|
||||
for (var i = 0; i < defaults_buttons.length; i++) {
|
||||
defaults_buttons[i].onclick = show_all_platforms;
|
||||
}
|
||||
}
|
||||
|
||||
function copyToClipboardNux() {
|
||||
const text = document.getElementById("ghcup-command-linux").innerText;
|
||||
const el = document.createElement('textarea');
|
||||
el.value = text;
|
||||
document.body.appendChild(el);
|
||||
el.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(el);
|
||||
const button = document.getElementById("ghcup-linux-button");
|
||||
button.focus();
|
||||
}
|
||||
|
||||
function copyToClipboardWin() {
|
||||
const text = document.getElementById("ghcup-command-windows").innerText;
|
||||
const el = document.createElement('textarea');
|
||||
el.value = text;
|
||||
document.body.appendChild(el);
|
||||
el.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(el);
|
||||
const button = document.getElementById("ghcup-windows-button");
|
||||
button.focus();
|
||||
}
|
||||
|
||||
(function () {
|
||||
adjust_for_platform();
|
||||
set_up_default_platform_buttons();
|
||||
}());
|
||||
|
||||
788
docs/modules_small.svg
Normal file
@@ -0,0 +1,788 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 2.48.0 (0)
|
||||
-->
|
||||
<!-- Title: G Pages: 1 -->
|
||||
<svg width="720pt" height="648pt"
|
||||
viewBox="0.00 0.00 719.63 648.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(0.41 0.41) rotate(0) translate(4 1562.8)">
|
||||
<title>G</title>
|
||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-1562.8 1736,-1562.8 1736,4 -4,4"/>
|
||||
<g id="clust1" class="cluster">
|
||||
<title>cluster_0</title>
|
||||
<polygon fill="#000000" fill-opacity="0.058824" stroke="#000000" stroke-opacity="0.058824" points="8,-13.67 8,-1483.59 1724,-1483.59 1724,-13.67 8,-13.67"/>
|
||||
<text text-anchor="middle" x="866" y="-1468.39" font-family="Times,serif" font-size="14.00">GHCup</text>
|
||||
</g>
|
||||
<g id="clust2" class="cluster">
|
||||
<title>cluster_1</title>
|
||||
<polygon fill="#000000" fill-opacity="0.058824" stroke="#000000" stroke-opacity="0.058824" points="1032,-487.12 1032,-810.17 1300,-810.17 1300,-487.12 1032,-487.12"/>
|
||||
<text text-anchor="middle" x="1166" y="-794.97" font-family="Times,serif" font-size="14.00">Download</text>
|
||||
</g>
|
||||
<g id="clust3" class="cluster">
|
||||
<title>cluster_2</title>
|
||||
<polygon fill="#000000" fill-opacity="0.058824" stroke="#000000" stroke-opacity="0.058824" points="176,-1056.29 176,-1430.61 1716,-1430.61 1716,-1056.29 176,-1056.29"/>
|
||||
<text text-anchor="middle" x="946" y="-1415.41" font-family="Times,serif" font-size="14.00">OptParse</text>
|
||||
</g>
|
||||
<g id="clust4" class="cluster">
|
||||
<title>cluster_3</title>
|
||||
<polygon fill="#000000" fill-opacity="0.058824" stroke="#000000" stroke-opacity="0.058824" points="439,-27.35 439,-668.3 972,-668.3 972,-27.35 439,-27.35"/>
|
||||
<text text-anchor="middle" x="705.5" y="-653.1" font-family="Times,serif" font-size="14.00">Prelude</text>
|
||||
</g>
|
||||
<g id="clust5" class="cluster">
|
||||
<title>cluster_4</title>
|
||||
<polygon fill="#000000" fill-opacity="0.058824" stroke="#000000" stroke-opacity="0.058824" points="479,-150.41 479,-278.6 656,-278.6 656,-150.41 479,-150.41"/>
|
||||
<text text-anchor="middle" x="567.5" y="-263.4" font-family="Times,serif" font-size="14.00">File</text>
|
||||
</g>
|
||||
<g id="clust6" class="cluster">
|
||||
<title>cluster_5</title>
|
||||
<polygon fill="#000000" fill-opacity="0.058824" stroke="#000000" stroke-opacity="0.058824" points="583,-292.27 583,-420.47 801,-420.47 801,-292.27 583,-292.27"/>
|
||||
<text text-anchor="middle" x="692" y="-405.27" font-family="Times,serif" font-size="14.00">Logger</text>
|
||||
</g>
|
||||
<g id="clust7" class="cluster">
|
||||
<title>cluster_6</title>
|
||||
<polygon fill="#000000" fill-opacity="0.058824" stroke="#000000" stroke-opacity="0.058824" points="447,-487.12 447,-615.32 517,-615.32 517,-487.12 447,-487.12"/>
|
||||
<text text-anchor="middle" x="482" y="-600.12" font-family="Times,serif" font-size="14.00">String</text>
|
||||
</g>
|
||||
<g id="clust8" class="cluster">
|
||||
<title>cluster_7</title>
|
||||
<polygon fill="#000000" fill-opacity="0.058824" stroke="#000000" stroke-opacity="0.058824" points="525,-487.12 525,-615.32 595,-615.32 595,-487.12 525,-487.12"/>
|
||||
<text text-anchor="middle" x="560" y="-600.12" font-family="Times,serif" font-size="14.00">Version</text>
|
||||
</g>
|
||||
<g id="clust9" class="cluster">
|
||||
<title>cluster_8</title>
|
||||
<polygon fill="#000000" fill-opacity="0.058824" stroke="#000000" stroke-opacity="0.058824" points="992,-136.74 992,-473.45 1186,-473.45 1186,-136.74 992,-136.74"/>
|
||||
<text text-anchor="middle" x="1089" y="-458.25" font-family="Times,serif" font-size="14.00">Types</text>
|
||||
</g>
|
||||
<g id="clust10" class="cluster">
|
||||
<title>cluster_9</title>
|
||||
<polygon fill="#000000" fill-opacity="0.058824" stroke="#000000" stroke-opacity="0.058824" points="1090,-150.41 1090,-420.47 1178,-420.47 1178,-150.41 1090,-150.41"/>
|
||||
<text text-anchor="middle" x="1134" y="-405.27" font-family="Times,serif" font-size="14.00">JSON</text>
|
||||
</g>
|
||||
<g id="clust11" class="cluster">
|
||||
<title>cluster_10</title>
|
||||
<polygon fill="#000000" fill-opacity="0.058824" stroke="#000000" stroke-opacity="0.058824" points="443,-681.97 443,-810.17 605,-810.17 605,-681.97 443,-681.97"/>
|
||||
<text text-anchor="middle" x="524" y="-794.97" font-family="Times,serif" font-size="14.00">Utils</text>
|
||||
</g>
|
||||
<!-- u2 -->
|
||||
<g id="node1" class="node">
|
||||
<title>u2</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="2" cx="1097" cy="-726.67" rx="56.59" ry="18"/>
|
||||
<text text-anchor="middle" x="1097" y="-722.97" font-family="Times,serif" font-size="14.00">Download</text>
|
||||
</g>
|
||||
<!-- u13 -->
|
||||
<g id="node27" class="node">
|
||||
<title>u13</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="2" cx="652" cy="-531.67" rx="46.59" ry="18"/>
|
||||
<text text-anchor="middle" x="652" y="-527.97" font-family="Times,serif" font-size="14.00">Prelude</text>
|
||||
</g>
|
||||
<!-- u2->u13 -->
|
||||
<g id="edge20" class="edge">
|
||||
<title>u2->u13</title>
|
||||
<path fill="none" stroke="black" d="M1064.99,-711.68C1055.73,-707.87 1045.54,-703.91 1036,-700.67 892.95,-652.16 831.85,-698.15 708,-611.67 688.81,-598.27 673.93,-576.08 664.35,-558.63"/>
|
||||
<polygon fill="black" stroke="black" points="667.31,-556.74 659.58,-549.5 661.11,-559.99 667.31,-556.74"/>
|
||||
</g>
|
||||
<!-- u17 -->
|
||||
<g id="node30" class="node">
|
||||
<title>u17</title>
|
||||
<ellipse fill="#bbffff" stroke="black" stroke-width="0" cx="764" cy="-531.67" rx="46.59" ry="18"/>
|
||||
<text text-anchor="middle" x="764" y="-527.97" font-family="Times,serif" font-size="14.00">Process</text>
|
||||
</g>
|
||||
<!-- u2->u17 -->
|
||||
<g id="edge21" class="edge">
|
||||
<title>u2->u17</title>
|
||||
<path fill="none" stroke="black" d="M1063.77,-712.05C990.02,-681.83 819.16,-611.8 819,-611.67 801.07,-597.3 786.53,-575.56 776.91,-558.53"/>
|
||||
<polygon fill="black" stroke="black" points="779.93,-556.75 772.09,-549.63 773.78,-560.09 779.93,-556.75"/>
|
||||
</g>
|
||||
<!-- u18 -->
|
||||
<g id="node40" class="node">
|
||||
<title>u18</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="0" cx="352" cy="-531.67" rx="45.49" ry="18"/>
|
||||
<text text-anchor="middle" x="352" y="-527.97" font-family="Times,serif" font-size="14.00">Version</text>
|
||||
</g>
|
||||
<!-- u2->u18 -->
|
||||
<g id="edge19" class="edge">
|
||||
<title>u2->u18</title>
|
||||
<path fill="none" stroke="black" d="M1066.47,-711.48C1056.88,-707.49 1046.15,-703.47 1036,-700.67 779.07,-629.85 685.03,-723.24 443,-611.67 415.32,-598.91 389.67,-575.09 372.71,-556.93"/>
|
||||
<polygon fill="black" stroke="black" points="374.86,-554.1 365.55,-549.04 369.68,-558.8 374.86,-554.1"/>
|
||||
</g>
|
||||
<!-- u26 -->
|
||||
<g id="node2" class="node">
|
||||
<title>u26</title>
|
||||
<ellipse fill="#bbbbff" stroke="black" stroke-width="0" cx="1153" cy="-531.67" rx="33.29" ry="18"/>
|
||||
<text text-anchor="middle" x="1153" y="-527.97" font-family="Times,serif" font-size="14.00">Utils</text>
|
||||
</g>
|
||||
<!-- u26->u13 -->
|
||||
<g id="edge22" class="edge">
|
||||
<title>u26->u13</title>
|
||||
<path fill="none" stroke="black" d="M1141.42,-548.74C1120.79,-577.43 1074.57,-634.34 1019,-656.17 956.54,-680.71 774.39,-690.95 717,-656.17 682.49,-635.26 665.44,-589.36 657.69,-559.52"/>
|
||||
<polygon fill="black" stroke="black" points="661.07,-558.6 655.32,-549.7 654.26,-560.24 661.07,-558.6"/>
|
||||
</g>
|
||||
<!-- u28 -->
|
||||
<g id="node3" class="node">
|
||||
<title>u28</title>
|
||||
<ellipse fill="#bbbbff" stroke="black" stroke-width="0" cx="1232" cy="-726.67" rx="60.39" ry="18"/>
|
||||
<text text-anchor="middle" x="1232" y="-722.97" font-family="Times,serif" font-size="14.00">IOStreams</text>
|
||||
</g>
|
||||
<!-- u28->u26 -->
|
||||
<g id="edge23" class="edge">
|
||||
<title>u28->u26</title>
|
||||
<path fill="none" stroke="black" d="M1224.99,-708.55C1211.13,-674.7 1180.17,-599.04 1163.73,-558.89"/>
|
||||
<polygon fill="black" stroke="black" points="1166.91,-557.42 1159.88,-549.49 1160.43,-560.07 1166.91,-557.42"/>
|
||||
</g>
|
||||
<!-- u30 -->
|
||||
<g id="node4" class="node">
|
||||
<title>u30</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="2" cx="938" cy="-1346.67" rx="53.89" ry="18"/>
|
||||
<text text-anchor="middle" x="938" y="-1342.97" font-family="Times,serif" font-size="14.00">OptParse</text>
|
||||
</g>
|
||||
<!-- u32 -->
|
||||
<g id="node6" class="node">
|
||||
<title>u32</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="781" cy="-1223.67" rx="40.09" ry="18"/>
|
||||
<text text-anchor="middle" x="781" y="-1219.97" font-family="Times,serif" font-size="14.00">Install</text>
|
||||
</g>
|
||||
<!-- u30->u32 -->
|
||||
<g id="edge24" class="edge">
|
||||
<title>u30->u32</title>
|
||||
<path fill="none" stroke="black" d="M917.47,-1329.86C889.67,-1308.42 839.93,-1270.09 808.8,-1246.1"/>
|
||||
<polygon fill="black" stroke="black" points="810.6,-1243.07 800.54,-1239.73 806.33,-1248.61 810.6,-1243.07"/>
|
||||
</g>
|
||||
<!-- u33 -->
|
||||
<g id="node7" class="node">
|
||||
<title>u33</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="866" cy="-1223.67" rx="27" ry="18"/>
|
||||
<text text-anchor="middle" x="866" y="-1219.97" font-family="Times,serif" font-size="14.00">Set</text>
|
||||
</g>
|
||||
<!-- u30->u33 -->
|
||||
<g id="edge25" class="edge">
|
||||
<title>u30->u33</title>
|
||||
<path fill="none" stroke="black" d="M927.99,-1328.85C915.71,-1308.21 894.79,-1273.06 880.69,-1249.36"/>
|
||||
<polygon fill="black" stroke="black" points="883.59,-1247.39 875.47,-1240.59 877.57,-1250.97 883.59,-1247.39"/>
|
||||
</g>
|
||||
<!-- u34 -->
|
||||
<g id="node8" class="node">
|
||||
<title>u34</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="682" cy="-1223.67" rx="40.09" ry="18"/>
|
||||
<text text-anchor="middle" x="682" y="-1219.97" font-family="Times,serif" font-size="14.00">UnSet</text>
|
||||
</g>
|
||||
<!-- u30->u34 -->
|
||||
<g id="edge26" class="edge">
|
||||
<title>u30->u34</title>
|
||||
<path fill="none" stroke="black" d="M908.13,-1331.56C860.8,-1309.18 768.72,-1265.66 717.88,-1241.63"/>
|
||||
<polygon fill="black" stroke="black" points="719.12,-1238.35 708.59,-1237.24 716.13,-1244.68 719.12,-1238.35"/>
|
||||
</g>
|
||||
<!-- u35 -->
|
||||
<g id="node9" class="node">
|
||||
<title>u35</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="938" cy="-1223.67" rx="27" ry="18"/>
|
||||
<text text-anchor="middle" x="938" y="-1219.97" font-family="Times,serif" font-size="14.00">Rm</text>
|
||||
</g>
|
||||
<!-- u30->u35 -->
|
||||
<g id="edge27" class="edge">
|
||||
<title>u30->u35</title>
|
||||
<path fill="none" stroke="black" d="M938,-1328.59C938,-1308.71 938,-1275.6 938,-1252.1"/>
|
||||
<polygon fill="black" stroke="black" points="941.5,-1252.06 938,-1242.06 934.5,-1252.06 941.5,-1252.06"/>
|
||||
</g>
|
||||
<!-- u36 -->
|
||||
<g id="node10" class="node">
|
||||
<title>u36</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="1012" cy="-1223.67" rx="29.5" ry="18"/>
|
||||
<text text-anchor="middle" x="1012" y="-1219.97" font-family="Times,serif" font-size="14.00">Run</text>
|
||||
</g>
|
||||
<!-- u30->u36 -->
|
||||
<g id="edge28" class="edge">
|
||||
<title>u30->u36</title>
|
||||
<path fill="none" stroke="black" d="M948.29,-1328.85C960.84,-1308.33 982.17,-1273.45 996.66,-1249.75"/>
|
||||
<polygon fill="black" stroke="black" points="999.8,-1251.33 1002.03,-1240.97 993.83,-1247.67 999.8,-1251.33"/>
|
||||
</g>
|
||||
<!-- u37 -->
|
||||
<g id="node11" class="node">
|
||||
<title>u37</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="1108" cy="-1223.67" rx="48.99" ry="18"/>
|
||||
<text text-anchor="middle" x="1108" y="-1219.97" font-family="Times,serif" font-size="14.00">Compile</text>
|
||||
</g>
|
||||
<!-- u30->u37 -->
|
||||
<g id="edge29" class="edge">
|
||||
<title>u30->u37</title>
|
||||
<path fill="none" stroke="black" d="M959.88,-1330.1C989.92,-1308.72 1044.08,-1270.17 1077.92,-1246.08"/>
|
||||
<polygon fill="black" stroke="black" points="1080.36,-1248.64 1086.48,-1239.99 1076.3,-1242.94 1080.36,-1248.64"/>
|
||||
</g>
|
||||
<!-- u38 -->
|
||||
<g id="node12" class="node">
|
||||
<title>u38</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="1215" cy="-1223.67" rx="40.09" ry="18"/>
|
||||
<text text-anchor="middle" x="1215" y="-1219.97" font-family="Times,serif" font-size="14.00">Config</text>
|
||||
</g>
|
||||
<!-- u30->u38 -->
|
||||
<g id="edge30" class="edge">
|
||||
<title>u30->u38</title>
|
||||
<path fill="none" stroke="black" d="M969.51,-1331.91C1021.01,-1309.41 1122.97,-1264.87 1177.89,-1240.88"/>
|
||||
<polygon fill="black" stroke="black" points="1179.49,-1244 1187.26,-1236.79 1176.69,-1237.59 1179.49,-1244"/>
|
||||
</g>
|
||||
<!-- u39 -->
|
||||
<g id="node13" class="node">
|
||||
<title>u39</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="1322" cy="-1223.67" rx="48.99" ry="18"/>
|
||||
<text text-anchor="middle" x="1322" y="-1219.97" font-family="Times,serif" font-size="14.00">Whereis</text>
|
||||
</g>
|
||||
<!-- u30->u39 -->
|
||||
<g id="edge31" class="edge">
|
||||
<title>u30->u39</title>
|
||||
<path fill="none" stroke="black" d="M975.87,-1333.74C1046.85,-1311.37 1199.65,-1263.23 1276.25,-1239.09"/>
|
||||
<polygon fill="black" stroke="black" points="1277.61,-1242.33 1286.1,-1235.99 1275.51,-1235.65 1277.61,-1242.33"/>
|
||||
</g>
|
||||
<!-- u40 -->
|
||||
<g id="node14" class="node">
|
||||
<title>u40</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="1417" cy="-1223.67" rx="28.7" ry="18"/>
|
||||
<text text-anchor="middle" x="1417" y="-1219.97" font-family="Times,serif" font-size="14.00">List</text>
|
||||
</g>
|
||||
<!-- u30->u40 -->
|
||||
<g id="edge32" class="edge">
|
||||
<title>u30->u40</title>
|
||||
<path fill="none" stroke="black" d="M985,-1337.81C1066.71,-1323.43 1239.65,-1289.89 1380,-1241.67 1381.91,-1241.02 1383.85,-1240.3 1385.79,-1239.54"/>
|
||||
<polygon fill="black" stroke="black" points="1387.54,-1242.6 1395.38,-1235.48 1384.81,-1236.15 1387.54,-1242.6"/>
|
||||
</g>
|
||||
<!-- u41 -->
|
||||
<g id="node15" class="node">
|
||||
<title>u41</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="1527" cy="-1223.67" rx="63.09" ry="18"/>
|
||||
<text text-anchor="middle" x="1527" y="-1219.97" font-family="Times,serif" font-size="14.00">ChangeLog</text>
|
||||
</g>
|
||||
<!-- u30->u41 -->
|
||||
<g id="edge33" class="edge">
|
||||
<title>u30->u41</title>
|
||||
<path fill="none" stroke="black" d="M983.75,-1337C1074.05,-1319.77 1281.48,-1279.6 1455,-1241.67 1460.05,-1240.57 1465.28,-1239.39 1470.53,-1238.2"/>
|
||||
<polygon fill="black" stroke="black" points="1471.62,-1241.54 1480.57,-1235.88 1470.04,-1234.72 1471.62,-1241.54"/>
|
||||
</g>
|
||||
<!-- u42 -->
|
||||
<g id="node16" class="node">
|
||||
<title>u42</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="1658" cy="-1223.67" rx="50.09" ry="18"/>
|
||||
<text text-anchor="middle" x="1658" y="-1219.97" font-family="Times,serif" font-size="14.00">Prefetch</text>
|
||||
</g>
|
||||
<!-- u30->u42 -->
|
||||
<g id="edge34" class="edge">
|
||||
<title>u30->u42</title>
|
||||
<path fill="none" stroke="black" d="M988.15,-1339.95C1099.08,-1326.81 1373.31,-1291.74 1599,-1241.67 1603.1,-1240.76 1607.33,-1239.73 1611.56,-1238.64"/>
|
||||
<polygon fill="black" stroke="black" points="1612.61,-1241.98 1621.36,-1236 1610.79,-1235.22 1612.61,-1241.98"/>
|
||||
</g>
|
||||
<!-- u43 -->
|
||||
<g id="node17" class="node">
|
||||
<title>u43</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="211" cy="-1223.67" rx="27" ry="18"/>
|
||||
<text text-anchor="middle" x="211" y="-1219.97" font-family="Times,serif" font-size="14.00">GC</text>
|
||||
</g>
|
||||
<!-- u30->u43 -->
|
||||
<g id="edge35" class="edge">
|
||||
<title>u30->u43</title>
|
||||
<path fill="none" stroke="black" d="M884.84,-1342.95C767.4,-1335.8 477.97,-1311.93 247,-1241.67 245.07,-1241.09 243.1,-1240.41 241.15,-1239.67"/>
|
||||
<polygon fill="black" stroke="black" points="242.1,-1236.28 231.53,-1235.63 239.39,-1242.73 242.1,-1236.28"/>
|
||||
</g>
|
||||
<!-- u44 -->
|
||||
<g id="node18" class="node">
|
||||
<title>u44</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="292" cy="-1223.67" rx="36.29" ry="18"/>
|
||||
<text text-anchor="middle" x="292" y="-1219.97" font-family="Times,serif" font-size="14.00">DInfo</text>
|
||||
</g>
|
||||
<!-- u30->u44 -->
|
||||
<g id="edge36" class="edge">
|
||||
<title>u30->u44</title>
|
||||
<path fill="none" stroke="black" d="M887.43,-1340.21C783.15,-1328.24 537.23,-1296.29 337,-1241.67 334.37,-1240.96 331.68,-1240.15 328.99,-1239.28"/>
|
||||
<polygon fill="black" stroke="black" points="329.93,-1235.9 319.33,-1235.94 327.64,-1242.52 329.93,-1235.9"/>
|
||||
</g>
|
||||
<!-- u45 -->
|
||||
<g id="node19" class="node">
|
||||
<title>u45</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="441" cy="-1223.67" rx="94.78" ry="18"/>
|
||||
<text text-anchor="middle" x="441" y="-1219.97" font-family="Times,serif" font-size="14.00">ToolRequirements</text>
|
||||
</g>
|
||||
<!-- u30->u45 -->
|
||||
<g id="edge37" class="edge">
|
||||
<title>u30->u45</title>
|
||||
<path fill="none" stroke="black" d="M895.63,-1335.36C808.87,-1314.24 610.48,-1265.94 506.82,-1240.7"/>
|
||||
<polygon fill="black" stroke="black" points="507.64,-1237.3 497.1,-1238.33 505.98,-1244.1 507.64,-1237.3"/>
|
||||
</g>
|
||||
<!-- u46 -->
|
||||
<g id="node20" class="node">
|
||||
<title>u46</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="589" cy="-1223.67" rx="35.19" ry="18"/>
|
||||
<text text-anchor="middle" x="589" y="-1219.97" font-family="Times,serif" font-size="14.00">Nuke</text>
|
||||
</g>
|
||||
<!-- u30->u46 -->
|
||||
<g id="edge38" class="edge">
|
||||
<title>u30->u46</title>
|
||||
<path fill="none" stroke="black" d="M900.74,-1333.5C843.11,-1314.56 728.96,-1276.55 633,-1241.67 630.49,-1240.76 627.9,-1239.8 625.3,-1238.83"/>
|
||||
<polygon fill="black" stroke="black" points="626.52,-1235.55 615.93,-1235.27 624.04,-1242.09 626.52,-1235.55"/>
|
||||
</g>
|
||||
<!-- u31 -->
|
||||
<g id="node5" class="node">
|
||||
<title>u31</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="1012" cy="-1100.67" rx="51.99" ry="18"/>
|
||||
<text text-anchor="middle" x="1012" y="-1096.97" font-family="Times,serif" font-size="14.00">Common</text>
|
||||
</g>
|
||||
<!-- u0 -->
|
||||
<g id="node37" class="node">
|
||||
<title>u0</title>
|
||||
<ellipse fill="#bbffbb" stroke="black" stroke-width="2" cx="589" cy="-977.67" rx="44.39" ry="18"/>
|
||||
<text text-anchor="middle" x="589" y="-973.97" font-family="Times,serif" font-size="14.00">GHCup</text>
|
||||
</g>
|
||||
<!-- u31->u0 -->
|
||||
<g id="edge39" class="edge">
|
||||
<title>u31->u0</title>
|
||||
<path fill="none" stroke="black" d="M983.01,-1085.65C974.43,-1081.79 964.94,-1077.81 956,-1074.67 844.36,-1035.45 708.66,-1004 637.66,-988.73"/>
|
||||
<polygon fill="black" stroke="black" points="638.17,-985.26 627.66,-986.59 636.71,-992.11 638.17,-985.26"/>
|
||||
</g>
|
||||
<!-- u32->u31 -->
|
||||
<g id="edge40" class="edge">
|
||||
<title>u32->u31</title>
|
||||
<path fill="none" stroke="black" d="M806.16,-1209.49C847.05,-1188.08 928.1,-1145.62 975.38,-1120.85"/>
|
||||
<polygon fill="black" stroke="black" points="977.13,-1123.89 984.37,-1116.15 973.89,-1117.69 977.13,-1123.89"/>
|
||||
</g>
|
||||
<!-- u33->u31 -->
|
||||
<g id="edge41" class="edge">
|
||||
<title>u33->u31</title>
|
||||
<path fill="none" stroke="black" d="M882.18,-1209.26C907.02,-1188.68 954.82,-1149.06 984.98,-1124.07"/>
|
||||
<polygon fill="black" stroke="black" points="987.51,-1126.51 992.98,-1117.44 983.05,-1121.12 987.51,-1126.51"/>
|
||||
</g>
|
||||
<!-- u34->u0 -->
|
||||
<g id="edge42" class="edge">
|
||||
<title>u34->u0</title>
|
||||
<path fill="none" stroke="black" d="M675.46,-1205.52C659.45,-1163.5 618.18,-1055.24 599.04,-1005"/>
|
||||
<polygon fill="black" stroke="black" points="602.24,-1003.59 595.41,-995.49 595.7,-1006.08 602.24,-1003.59"/>
|
||||
</g>
|
||||
<!-- u35->u31 -->
|
||||
<g id="edge43" class="edge">
|
||||
<title>u35->u31</title>
|
||||
<path fill="none" stroke="black" d="M947.67,-1206.86C960.04,-1186.63 981.61,-1151.36 996.33,-1127.29"/>
|
||||
<polygon fill="black" stroke="black" points="999.38,-1129.02 1001.61,-1118.67 993.41,-1125.37 999.38,-1129.02"/>
|
||||
</g>
|
||||
<!-- u36->u31 -->
|
||||
<g id="edge44" class="edge">
|
||||
<title>u36->u31</title>
|
||||
<path fill="none" stroke="black" d="M1012,-1205.59C1012,-1185.71 1012,-1152.6 1012,-1129.1"/>
|
||||
<polygon fill="black" stroke="black" points="1015.5,-1129.06 1012,-1119.06 1008.5,-1129.06 1015.5,-1129.06"/>
|
||||
</g>
|
||||
<!-- u37->u31 -->
|
||||
<g id="edge45" class="edge">
|
||||
<title>u37->u31</title>
|
||||
<path fill="none" stroke="black" d="M1094.65,-1205.85C1078.24,-1185.17 1050.27,-1149.91 1031.47,-1126.21"/>
|
||||
<polygon fill="black" stroke="black" points="1034.19,-1124.01 1025.24,-1118.36 1028.71,-1128.36 1034.19,-1124.01"/>
|
||||
</g>
|
||||
<!-- u38->u31 -->
|
||||
<g id="edge46" class="edge">
|
||||
<title>u38->u31</title>
|
||||
<path fill="none" stroke="black" d="M1191.71,-1208.79C1155.81,-1187.4 1086.79,-1146.26 1045.52,-1121.66"/>
|
||||
<polygon fill="black" stroke="black" points="1047.29,-1118.64 1036.91,-1116.52 1043.71,-1124.65 1047.29,-1118.64"/>
|
||||
</g>
|
||||
<!-- u39->u31 -->
|
||||
<g id="edge47" class="edge">
|
||||
<title>u39->u31</title>
|
||||
<path fill="none" stroke="black" d="M1289.7,-1210.07C1233.47,-1188.12 1117.6,-1142.89 1054.77,-1118.37"/>
|
||||
<polygon fill="black" stroke="black" points="1055.75,-1114.99 1045.16,-1114.62 1053.2,-1121.51 1055.75,-1114.99"/>
|
||||
</g>
|
||||
<!-- u40->u31 -->
|
||||
<g id="edge48" class="edge">
|
||||
<title>u40->u31</title>
|
||||
<path fill="none" stroke="black" d="M1394.93,-1211.86C1390.07,-1209.67 1384.91,-1207.48 1380,-1205.67 1269.63,-1165 1135.77,-1130.82 1063.8,-1113.62"/>
|
||||
<polygon fill="black" stroke="black" points="1064.6,-1110.21 1054.06,-1111.3 1062.98,-1117.02 1064.6,-1110.21"/>
|
||||
</g>
|
||||
<!-- u41->u31 -->
|
||||
<g id="edge49" class="edge">
|
||||
<title>u41->u31</title>
|
||||
<path fill="none" stroke="black" d="M1480.14,-1211.6C1471.77,-1209.62 1463.13,-1207.59 1455,-1205.67 1313.45,-1172.35 1146.42,-1133.18 1063.74,-1113.8"/>
|
||||
<polygon fill="black" stroke="black" points="1064.38,-1110.35 1053.84,-1111.48 1062.78,-1117.17 1064.38,-1110.35"/>
|
||||
</g>
|
||||
<!-- u42->u31 -->
|
||||
<g id="edge50" class="edge">
|
||||
<title>u42->u31</title>
|
||||
<path fill="none" stroke="black" d="M1621.02,-1211.37C1613.75,-1209.34 1606.16,-1207.34 1599,-1205.67 1406.54,-1161.03 1174.71,-1125.14 1069.25,-1109.77"/>
|
||||
<polygon fill="black" stroke="black" points="1069.53,-1106.27 1059.14,-1108.3 1068.53,-1113.2 1069.53,-1106.27"/>
|
||||
</g>
|
||||
<!-- u43->u0 -->
|
||||
<g id="edge51" class="edge">
|
||||
<title>u43->u0</title>
|
||||
<path fill="none" stroke="black" d="M228.01,-1209.54C262.83,-1182.88 345.11,-1121 418,-1074.67 463.76,-1045.59 518.77,-1015.54 553.81,-996.98"/>
|
||||
<polygon fill="black" stroke="black" points="555.49,-1000.05 562.7,-992.29 552.22,-993.86 555.49,-1000.05"/>
|
||||
</g>
|
||||
<!-- u44->u0 -->
|
||||
<g id="edge52" class="edge">
|
||||
<title>u44->u0</title>
|
||||
<path fill="none" stroke="black" d="M310.13,-1207.78C360.65,-1166.27 503.18,-1049.18 562.54,-1000.41"/>
|
||||
<polygon fill="black" stroke="black" points="564.84,-1003.05 570.35,-994 560.4,-997.64 564.84,-1003.05"/>
|
||||
</g>
|
||||
<!-- u25 -->
|
||||
<g id="node45" class="node">
|
||||
<title>u25</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="0" cx="764" cy="-726.67" rx="51.19" ry="18"/>
|
||||
<text text-anchor="middle" x="764" y="-722.97" font-family="Times,serif" font-size="14.00">Platform</text>
|
||||
</g>
|
||||
<!-- u45->u25 -->
|
||||
<g id="edge53" class="edge">
|
||||
<title>u45->u25</title>
|
||||
<path fill="none" stroke="black" d="M510.37,-1211.33C674.38,-1184.51 1072.43,-1119.35 1073,-1118.67 1191.08,-979.57 904.93,-804.32 800.41,-746.86"/>
|
||||
<polygon fill="black" stroke="black" points="801.91,-743.7 791.46,-741.99 798.57,-749.84 801.91,-743.7"/>
|
||||
</g>
|
||||
<!-- u27 -->
|
||||
<g id="node46" class="node">
|
||||
<title>u27</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="0" cx="92" cy="-1100.67" rx="76.09" ry="18"/>
|
||||
<text text-anchor="middle" x="92" y="-1096.97" font-family="Times,serif" font-size="14.00">Requirements</text>
|
||||
</g>
|
||||
<!-- u45->u27 -->
|
||||
<g id="edge54" class="edge">
|
||||
<title>u45->u27</title>
|
||||
<path fill="none" stroke="black" d="M397.5,-1207.59C332.8,-1185.16 211.48,-1143.1 142.79,-1119.28"/>
|
||||
<polygon fill="black" stroke="black" points="143.65,-1115.88 133.05,-1115.91 141.36,-1122.49 143.65,-1115.88"/>
|
||||
</g>
|
||||
<!-- u46->u0 -->
|
||||
<g id="edge55" class="edge">
|
||||
<title>u46->u0</title>
|
||||
<path fill="none" stroke="black" d="M589,-1205.52C589,-1163.78 589,-1056.66 589,-1006"/>
|
||||
<polygon fill="black" stroke="black" points="592.5,-1005.81 589,-995.81 585.5,-1005.81 592.5,-1005.81"/>
|
||||
</g>
|
||||
<!-- u16 -->
|
||||
<g id="node21" class="node">
|
||||
<title>u16</title>
|
||||
<ellipse fill="#bbffff" stroke="black" stroke-width="2" cx="619" cy="-194.67" rx="28.7" ry="18"/>
|
||||
<text text-anchor="middle" x="619" y="-190.97" font-family="Times,serif" font-size="14.00">File</text>
|
||||
</g>
|
||||
<!-- u14 -->
|
||||
<g id="node29" class="node">
|
||||
<title>u14</title>
|
||||
<ellipse fill="#bbffff" stroke="black" stroke-width="0" cx="619" cy="-71.67" rx="48.19" ry="18"/>
|
||||
<text text-anchor="middle" x="619" y="-67.97" font-family="Times,serif" font-size="14.00">Internal</text>
|
||||
</g>
|
||||
<!-- u16->u14 -->
|
||||
<g id="edge59" class="edge">
|
||||
<title>u16->u14</title>
|
||||
<path fill="none" stroke="black" d="M619,-176.59C619,-156.71 619,-123.6 619,-100.1"/>
|
||||
<polygon fill="black" stroke="black" points="622.5,-100.06 619,-90.06 615.5,-100.06 622.5,-100.06"/>
|
||||
</g>
|
||||
<!-- u3 -->
|
||||
<g id="node39" class="node">
|
||||
<title>u3</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="0" cx="390" cy="-336.67" rx="40.89" ry="18"/>
|
||||
<text text-anchor="middle" x="390" y="-332.97" font-family="Times,serif" font-size="14.00">Errors</text>
|
||||
</g>
|
||||
<!-- u16->u3 -->
|
||||
<g id="edge58" class="edge">
|
||||
<title>u16->u3</title>
|
||||
<path fill="none" stroke="black" d="M609.27,-211.94C602.58,-222.07 592.96,-234.8 582,-243.67 536.12,-280.81 472.76,-307.42 431.59,-322.18"/>
|
||||
<polygon fill="black" stroke="black" points="430.41,-318.88 422.14,-325.5 432.73,-325.49 430.41,-318.88"/>
|
||||
</g>
|
||||
<!-- u10 -->
|
||||
<g id="node22" class="node">
|
||||
<title>u10</title>
|
||||
<ellipse fill="#ffbbff" stroke="black" stroke-width="0" cx="530" cy="-194.67" rx="42.79" ry="18"/>
|
||||
<text text-anchor="middle" x="530" y="-190.97" font-family="Times,serif" font-size="14.00">Search</text>
|
||||
</g>
|
||||
<!-- u4 -->
|
||||
<g id="node33" class="node">
|
||||
<title>u4</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="2" cx="1038" cy="-194.67" rx="38.19" ry="18"/>
|
||||
<text text-anchor="middle" x="1038" y="-190.97" font-family="Times,serif" font-size="14.00">Types</text>
|
||||
</g>
|
||||
<!-- u10->u4 -->
|
||||
<g id="edge60" class="edge">
|
||||
<title>u10->u4</title>
|
||||
<path fill="none" stroke="black" d="M537.16,-212.79C546.14,-232.73 563.64,-263.75 590,-277.17 614.16,-289.48 624.04,-280.02 651,-277.17 777.98,-263.79 924.57,-226.35 995.36,-206.85"/>
|
||||
<polygon fill="black" stroke="black" points="996.54,-210.15 1005.24,-204.1 994.67,-203.4 996.54,-210.15"/>
|
||||
</g>
|
||||
<!-- u15 -->
|
||||
<g id="node23" class="node">
|
||||
<title>u15</title>
|
||||
<ellipse fill="#bbffff" stroke="black" stroke-width="2" cx="635" cy="-336.67" rx="43.59" ry="18"/>
|
||||
<text text-anchor="middle" x="635" y="-332.97" font-family="Times,serif" font-size="14.00">Logger</text>
|
||||
</g>
|
||||
<!-- u15->u16 -->
|
||||
<g id="edge61" class="edge">
|
||||
<title>u15->u16</title>
|
||||
<path fill="none" stroke="black" d="M633.04,-318.51C630.32,-294.68 625.36,-251.33 622.13,-223.02"/>
|
||||
<polygon fill="black" stroke="black" points="625.59,-222.52 620.98,-212.98 618.64,-223.31 625.59,-222.52"/>
|
||||
</g>
|
||||
<!-- u12 -->
|
||||
<g id="node24" class="node">
|
||||
<title>u12</title>
|
||||
<ellipse fill="#77ff77" stroke="black" stroke-width="0" cx="745" cy="-336.67" rx="48.19" ry="18"/>
|
||||
<text text-anchor="middle" x="745" y="-332.97" font-family="Times,serif" font-size="14.00">Internal</text>
|
||||
</g>
|
||||
<!-- u12->u4 -->
|
||||
<g id="edge62" class="edge">
|
||||
<title>u12->u4</title>
|
||||
<path fill="none" stroke="black" d="M773.33,-322.04C781.01,-318.34 789.32,-314.35 797,-310.67 870.15,-275.64 955.87,-234.78 1002.82,-212.42"/>
|
||||
<polygon fill="black" stroke="black" points="1004.43,-215.53 1011.95,-208.07 1001.42,-209.21 1004.43,-215.53"/>
|
||||
</g>
|
||||
<!-- u11 -->
|
||||
<g id="node25" class="node">
|
||||
<title>u11</title>
|
||||
<ellipse fill="#ffff77" stroke="black" stroke-width="0" cx="482" cy="-531.67" rx="27" ry="18"/>
|
||||
<text text-anchor="middle" x="482" y="-527.97" font-family="Times,serif" font-size="14.00">QQ</text>
|
||||
</g>
|
||||
<!-- u21 -->
|
||||
<g id="node26" class="node">
|
||||
<title>u21</title>
|
||||
<ellipse fill="#7777ff" stroke="black" stroke-width="0" cx="560" cy="-531.67" rx="27" ry="18"/>
|
||||
<text text-anchor="middle" x="560" y="-527.97" font-family="Times,serif" font-size="14.00">QQ</text>
|
||||
</g>
|
||||
<!-- u13->u15 -->
|
||||
<g id="edge56" class="edge">
|
||||
<title>u13->u15</title>
|
||||
<path fill="none" stroke="black" d="M650.49,-513.55C647.54,-480 640.96,-405.38 637.4,-364.96"/>
|
||||
<polygon fill="black" stroke="black" points="640.87,-364.42 636.51,-354.76 633.9,-365.03 640.87,-364.42"/>
|
||||
</g>
|
||||
<!-- u8 -->
|
||||
<g id="node28" class="node">
|
||||
<title>u8</title>
|
||||
<ellipse fill="#bbffff" stroke="black" stroke-width="0" cx="896" cy="-531.67" rx="67.69" ry="18"/>
|
||||
<text text-anchor="middle" x="896" y="-527.97" font-family="Times,serif" font-size="14.00">MegaParsec</text>
|
||||
</g>
|
||||
<!-- u8->u4 -->
|
||||
<g id="edge57" class="edge">
|
||||
<title>u8->u4</title>
|
||||
<path fill="none" stroke="black" d="M901.3,-513.5C913.07,-476.01 942.99,-384.28 976,-310.67 990.2,-279.02 1009.56,-244.15 1022.85,-221.2"/>
|
||||
<polygon fill="black" stroke="black" points="1025.94,-222.83 1027.96,-212.43 1019.9,-219.3 1025.94,-222.83"/>
|
||||
</g>
|
||||
<!-- u6 -->
|
||||
<g id="node31" class="node">
|
||||
<title>u6</title>
|
||||
<ellipse fill="#ff7777" stroke="black" stroke-width="2" cx="1134" cy="-336.67" rx="36" ry="18"/>
|
||||
<text text-anchor="middle" x="1134" y="-332.97" font-family="Times,serif" font-size="14.00">JSON</text>
|
||||
</g>
|
||||
<!-- u6->u8 -->
|
||||
<g id="edge65" class="edge">
|
||||
<title>u6->u8</title>
|
||||
<path fill="none" stroke="black" d="M1128.71,-354.49C1122.6,-371.76 1111.13,-398.6 1094,-416.67 1051.3,-461.74 986.8,-494.31 943.12,-512.82"/>
|
||||
<polygon fill="black" stroke="black" points="941.75,-509.6 933.86,-516.67 944.43,-516.07 941.75,-509.6"/>
|
||||
</g>
|
||||
<!-- u7 -->
|
||||
<g id="node32" class="node">
|
||||
<title>u7</title>
|
||||
<ellipse fill="#77ffff" stroke="black" stroke-width="0" cx="1134" cy="-194.67" rx="33.29" ry="18"/>
|
||||
<text text-anchor="middle" x="1134" y="-190.97" font-family="Times,serif" font-size="14.00">Utils</text>
|
||||
</g>
|
||||
<!-- u6->u7 -->
|
||||
<g id="edge66" class="edge">
|
||||
<title>u6->u7</title>
|
||||
<path fill="none" stroke="black" d="M1134,-318.51C1134,-294.68 1134,-251.33 1134,-223.02"/>
|
||||
<polygon fill="black" stroke="black" points="1137.5,-222.98 1134,-212.98 1130.5,-222.98 1137.5,-222.98"/>
|
||||
</g>
|
||||
<!-- u5 -->
|
||||
<g id="node36" class="node">
|
||||
<title>u5</title>
|
||||
<ellipse fill="#ff77ff" stroke="black" stroke-width="0" cx="482" cy="-726.67" rx="30.59" ry="18"/>
|
||||
<text text-anchor="middle" x="482" y="-722.97" font-family="Times,serif" font-size="14.00">Dirs</text>
|
||||
</g>
|
||||
<!-- u4->u5 -->
|
||||
<g id="edge63" class="edge">
|
||||
<title>u4->u5</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M1029.13,-212.24C1017.93,-234.08 999.15,-274.04 991,-310.67 987.36,-327.02 986.96,-599.01 976,-611.67 841.43,-767.14 713.25,-625.15 522,-700.67 517.68,-702.38 513.32,-704.55 509.14,-706.91"/>
|
||||
<polygon fill="black" stroke="black" points="507.1,-704.05 500.37,-712.23 510.74,-710.03 507.1,-704.05"/>
|
||||
</g>
|
||||
<!-- u9 -->
|
||||
<g id="node34" class="node">
|
||||
<title>u9</title>
|
||||
<ellipse fill="#ff7777" stroke="black" stroke-width="0" cx="1040" cy="-336.67" rx="40.09" ry="18"/>
|
||||
<text text-anchor="middle" x="1040" y="-332.97" font-family="Times,serif" font-size="14.00">Optics</text>
|
||||
</g>
|
||||
<!-- u9->u4 -->
|
||||
<g id="edge64" class="edge">
|
||||
<title>u9->u4</title>
|
||||
<path fill="none" stroke="black" d="M1039.75,-318.51C1039.41,-294.68 1038.8,-251.33 1038.39,-223.02"/>
|
||||
<polygon fill="black" stroke="black" points="1041.89,-222.93 1038.25,-212.98 1034.89,-223.03 1041.89,-222.93"/>
|
||||
</g>
|
||||
<!-- u19 -->
|
||||
<g id="node35" class="node">
|
||||
<title>u19</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="2" cx="564" cy="-726.67" rx="33.29" ry="18"/>
|
||||
<text text-anchor="middle" x="564" y="-722.97" font-family="Times,serif" font-size="14.00">Utils</text>
|
||||
</g>
|
||||
<!-- u19->u2 -->
|
||||
<g id="edge67" class="edge">
|
||||
<title>u19->u2</title>
|
||||
<path fill="none" stroke="black" d="M568.67,-744.69C574.69,-763.8 587.21,-793.03 610,-806.17 650.14,-829.32 984.78,-825.25 1027,-806.17 1050.91,-795.37 1069.91,-771.92 1082.04,-753.27"/>
|
||||
<polygon fill="black" stroke="black" points="1085.14,-754.92 1087.44,-744.58 1079.19,-751.23 1085.14,-754.92"/>
|
||||
</g>
|
||||
<!-- u5->u10 -->
|
||||
<g id="edge69" class="edge">
|
||||
<title>u5->u10</title>
|
||||
<path fill="none" stroke="black" d="M454.49,-718.48C411.04,-705.45 327.86,-673.4 293,-611.67 227.22,-495.18 221.99,-424.05 293,-310.67 333.99,-245.22 424.02,-216.08 480.56,-203.83"/>
|
||||
<polygon fill="black" stroke="black" points="481.28,-207.25 490.37,-201.8 479.87,-200.4 481.28,-207.25"/>
|
||||
</g>
|
||||
<!-- u5->u12 -->
|
||||
<g id="edge70" class="edge">
|
||||
<title>u5->u12</title>
|
||||
<path fill="none" stroke="black" d="M474.4,-709.13C464.84,-687.34 448.97,-647.58 443,-611.67 439.14,-588.44 429.48,-524.97 443,-505.67 509.48,-410.79 595.57,-486.52 688,-416.67 706.67,-402.56 721.81,-380.63 731.78,-363.45"/>
|
||||
<polygon fill="black" stroke="black" points="734.97,-364.91 736.78,-354.47 728.86,-361.5 734.97,-364.91"/>
|
||||
</g>
|
||||
<!-- u5->u11 -->
|
||||
<g id="edge71" class="edge">
|
||||
<title>u5->u11</title>
|
||||
<path fill="none" stroke="black" d="M482,-708.55C482,-675 482,-600.38 482,-559.96"/>
|
||||
<polygon fill="black" stroke="black" points="485.5,-559.76 482,-549.76 478.5,-559.76 485.5,-559.76"/>
|
||||
</g>
|
||||
<!-- u5->u6 -->
|
||||
<g id="edge73" class="edge">
|
||||
<title>u5->u6</title>
|
||||
<path fill="none" stroke="black" d="M500.35,-712.18C506.9,-707.92 514.52,-703.58 522,-700.67 725.9,-621.54 849.59,-764.56 1006,-611.67 1040.41,-578.04 1008.32,-549.58 1028,-505.67 1048.14,-460.74 1068.12,-458.57 1094,-416.67 1104.57,-399.56 1114.79,-379.3 1122.25,-363.59"/>
|
||||
<polygon fill="black" stroke="black" points="1125.45,-365 1126.51,-354.46 1119.11,-362.03 1125.45,-365"/>
|
||||
</g>
|
||||
<!-- u5->u9 -->
|
||||
<g id="edge72" class="edge">
|
||||
<title>u5->u9</title>
|
||||
<path fill="none" stroke="black" d="M500.36,-712.21C506.92,-707.95 514.53,-703.6 522,-700.67 718.31,-623.71 838.99,-760.86 988,-611.67 1005.46,-594.19 1028.14,-430.37 1036.61,-364.7"/>
|
||||
<polygon fill="black" stroke="black" points="1040.1,-365.05 1037.89,-354.69 1033.15,-364.17 1040.1,-365.05"/>
|
||||
</g>
|
||||
<!-- u5->u3 -->
|
||||
<g id="edge68" class="edge">
|
||||
<title>u5->u3</title>
|
||||
<path fill="none" stroke="black" d="M472.91,-709.22C461.35,-687.54 441.59,-647.88 431,-611.67 405.26,-523.69 395.12,-414.85 391.62,-364.97"/>
|
||||
<polygon fill="black" stroke="black" points="395.09,-364.44 390.94,-354.7 388.11,-364.91 395.09,-364.44"/>
|
||||
</g>
|
||||
<!-- u1 -->
|
||||
<g id="node38" class="node">
|
||||
<title>u1</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="0" cx="546" cy="-854.67" rx="37.09" ry="18"/>
|
||||
<text text-anchor="middle" x="546" y="-850.97" font-family="Times,serif" font-size="14.00">Cabal</text>
|
||||
</g>
|
||||
<!-- u0->u1 -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>u0->u1</title>
|
||||
<path fill="none" stroke="black" d="M582.93,-959.59C575.79,-939.51 563.86,-905.92 555.49,-882.38"/>
|
||||
<polygon fill="black" stroke="black" points="558.69,-880.92 552.04,-872.67 552.09,-883.26 558.69,-880.92"/>
|
||||
</g>
|
||||
<!-- u20 -->
|
||||
<g id="node41" class="node">
|
||||
<title>u20</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="0" cx="713" cy="-854.67" rx="32.49" ry="18"/>
|
||||
<text text-anchor="middle" x="713" y="-850.97" font-family="Times,serif" font-size="14.00">GHC</text>
|
||||
</g>
|
||||
<!-- u0->u20 -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>u0->u20</title>
|
||||
<path fill="none" stroke="black" d="M605.21,-960.86C626.89,-939.7 665.45,-902.07 690.09,-878.03"/>
|
||||
<polygon fill="black" stroke="black" points="692.85,-880.22 697.57,-870.73 687.96,-875.21 692.85,-880.22"/>
|
||||
</g>
|
||||
<!-- u22 -->
|
||||
<g id="node42" class="node">
|
||||
<title>u22</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="0" cx="632" cy="-854.67" rx="30.59" ry="18"/>
|
||||
<text text-anchor="middle" x="632" y="-850.97" font-family="Times,serif" font-size="14.00">HLS</text>
|
||||
</g>
|
||||
<!-- u0->u22 -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>u0->u22</title>
|
||||
<path fill="none" stroke="black" d="M595.07,-959.59C602.21,-939.51 614.14,-905.92 622.51,-882.38"/>
|
||||
<polygon fill="black" stroke="black" points="625.91,-883.26 625.96,-872.67 619.31,-880.92 625.91,-883.26"/>
|
||||
</g>
|
||||
<!-- u23 -->
|
||||
<g id="node43" class="node">
|
||||
<title>u23</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="0" cx="379" cy="-854.67" rx="36.29" ry="18"/>
|
||||
<text text-anchor="middle" x="379" y="-850.97" font-family="Times,serif" font-size="14.00">Stack</text>
|
||||
</g>
|
||||
<!-- u0->u23 -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>u0->u23</title>
|
||||
<path fill="none" stroke="black" d="M564.5,-962.56C526.3,-940.54 452.56,-898.06 410.47,-873.81"/>
|
||||
<polygon fill="black" stroke="black" points="412.16,-870.74 401.75,-868.78 408.66,-876.81 412.16,-870.74"/>
|
||||
</g>
|
||||
<!-- u24 -->
|
||||
<g id="node44" class="node">
|
||||
<title>u24</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="0" cx="462" cy="-854.67" rx="28.7" ry="18"/>
|
||||
<text text-anchor="middle" x="462" y="-850.97" font-family="Times,serif" font-size="14.00">List</text>
|
||||
</g>
|
||||
<!-- u0->u24 -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>u0->u24</title>
|
||||
<path fill="none" stroke="black" d="M572.4,-960.86C549.97,-939.49 509.92,-901.33 484.72,-877.32"/>
|
||||
<polygon fill="black" stroke="black" points="487.07,-874.72 477.41,-870.36 482.24,-879.79 487.07,-874.72"/>
|
||||
</g>
|
||||
<!-- u0->u25 -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>u0->u25</title>
|
||||
<path fill="none" stroke="black" d="M622.7,-965.95C661.77,-951.56 724.56,-921.94 754,-872.67 775.65,-836.44 773.28,-785.65 769.03,-754.79"/>
|
||||
<polygon fill="black" stroke="black" points="772.47,-754.12 767.49,-744.77 765.55,-755.19 772.47,-754.12"/>
|
||||
</g>
|
||||
<!-- u1->u19 -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>u1->u19</title>
|
||||
<path fill="none" stroke="black" d="M548.43,-836.68C551.42,-815.73 556.54,-779.86 560.09,-755.02"/>
|
||||
<polygon fill="black" stroke="black" points="563.6,-755.19 561.55,-744.8 556.67,-754.2 563.6,-755.19"/>
|
||||
</g>
|
||||
<!-- u3->u4 -->
|
||||
<g id="edge9" class="edge">
|
||||
<title>u3->u4</title>
|
||||
<path fill="none" stroke="black" d="M426.23,-327.85C537.33,-303.84 873.04,-231.31 993.98,-205.18"/>
|
||||
<polygon fill="black" stroke="black" points="994.96,-208.55 1004,-203.02 993.48,-201.71 994.96,-208.55"/>
|
||||
</g>
|
||||
<!-- u18->u3 -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>u18->u3</title>
|
||||
<path fill="none" stroke="black" d="M355.37,-513.55C361.99,-479.93 376.73,-405.06 384.68,-364.7"/>
|
||||
<polygon fill="black" stroke="black" points="388.14,-365.25 386.64,-354.76 381.27,-363.9 388.14,-365.25"/>
|
||||
</g>
|
||||
<!-- u20->u21 -->
|
||||
<g id="edge11" class="edge">
|
||||
<title>u20->u21</title>
|
||||
<path fill="none" stroke="black" d="M704.03,-837.21C683.06,-798.45 629.7,-698.22 591,-611.67 583.26,-594.35 575.46,-574.46 569.62,-558.98"/>
|
||||
<polygon fill="black" stroke="black" points="572.86,-557.65 566.09,-549.51 566.3,-560.1 572.86,-557.65"/>
|
||||
</g>
|
||||
<!-- u20->u19 -->
|
||||
<g id="edge12" class="edge">
|
||||
<title>u20->u19</title>
|
||||
<path fill="none" stroke="black" d="M690.9,-841.08C667.19,-826.95 629.13,-802.48 601,-775.67 593.62,-768.64 586.52,-760.05 580.55,-752.09"/>
|
||||
<polygon fill="black" stroke="black" points="583.25,-749.86 574.56,-743.81 577.58,-753.96 583.25,-749.86"/>
|
||||
</g>
|
||||
<!-- u22->u19 -->
|
||||
<g id="edge13" class="edge">
|
||||
<title>u22->u19</title>
|
||||
<path fill="none" stroke="black" d="M623.11,-837.2C611.55,-815.79 591.25,-778.18 577.72,-753.09"/>
|
||||
<polygon fill="black" stroke="black" points="580.72,-751.29 572.89,-744.15 574.56,-754.61 580.72,-751.29"/>
|
||||
</g>
|
||||
<!-- u23->u19 -->
|
||||
<g id="edge14" class="edge">
|
||||
<title>u23->u19</title>
|
||||
<path fill="none" stroke="black" d="M406.01,-842.42C436.12,-829.11 485.37,-805.03 522,-775.67 530.68,-768.71 539.02,-759.82 545.95,-751.59"/>
|
||||
<polygon fill="black" stroke="black" points="548.79,-753.64 552.36,-743.66 543.35,-749.23 548.79,-753.64"/>
|
||||
</g>
|
||||
<!-- u24->u19 -->
|
||||
<g id="edge15" class="edge">
|
||||
<title>u24->u19</title>
|
||||
<path fill="none" stroke="black" d="M474.51,-838.22C492,-816.61 523.94,-777.16 544.55,-751.7"/>
|
||||
<polygon fill="black" stroke="black" points="547.5,-753.62 551.07,-743.65 542.06,-749.22 547.5,-753.62"/>
|
||||
</g>
|
||||
<!-- u25->u13 -->
|
||||
<g id="edge16" class="edge">
|
||||
<title>u25->u13</title>
|
||||
<path fill="none" stroke="black" d="M754.26,-708.88C734.61,-675.02 690.12,-598.36 666.83,-558.23"/>
|
||||
<polygon fill="black" stroke="black" points="669.85,-556.45 661.8,-549.56 663.79,-559.97 669.85,-556.45"/>
|
||||
</g>
|
||||
<!-- u25->u17 -->
|
||||
<g id="edge17" class="edge">
|
||||
<title>u25->u17</title>
|
||||
<path fill="none" stroke="black" d="M764,-708.55C764,-675 764,-600.38 764,-559.96"/>
|
||||
<polygon fill="black" stroke="black" points="767.5,-559.76 764,-549.76 760.5,-559.76 767.5,-559.76"/>
|
||||
</g>
|
||||
<!-- u27->u18 -->
|
||||
<g id="edge18" class="edge">
|
||||
<title>u27->u18</title>
|
||||
<path fill="none" stroke="black" d="M99.78,-1082.7C136.79,-1002.01 295.03,-656.91 340.02,-558.79"/>
|
||||
<polygon fill="black" stroke="black" points="343.26,-560.13 344.25,-549.58 336.9,-557.21 343.26,-560.13"/>
|
||||
</g>
|
||||
<!-- u29 -->
|
||||
<g id="node47" class="node">
|
||||
<title>u29</title>
|
||||
<ellipse fill="#bbffbb" stroke="black" stroke-width="0" cx="938" cy="-1527.67" rx="34.39" ry="18"/>
|
||||
<text text-anchor="middle" x="938" y="-1523.97" font-family="Times,serif" font-size="14.00">Main</text>
|
||||
</g>
|
||||
<!-- u29->u30 -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>u29->u30</title>
|
||||
<path fill="none" stroke="black" d="M938,-1509.51C938,-1478.37 938,-1412.33 938,-1374.96"/>
|
||||
<polygon fill="black" stroke="black" points="941.5,-1374.78 938,-1364.78 934.5,-1374.79 941.5,-1374.78"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 40 KiB |
788
docs/modules_wide.svg
Normal file
@@ -0,0 +1,788 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 2.48.0 (0)
|
||||
-->
|
||||
<!-- Title: G Pages: 1 -->
|
||||
<svg width="1077pt" height="648pt"
|
||||
viewBox="0.00 0.00 1076.70 648.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(0.62 0.62) rotate(0) translate(4 1043.2)">
|
||||
<title>G</title>
|
||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-1043.2 1736,-1043.2 1736,4 -4,4"/>
|
||||
<g id="clust1" class="cluster">
|
||||
<title>cluster_0</title>
|
||||
<polygon fill="#000000" fill-opacity="0.058824" stroke="#000000" stroke-opacity="0.058824" points="8,-9.12 8,-989.06 1724,-989.06 1724,-9.12 8,-9.12"/>
|
||||
<text text-anchor="middle" x="866" y="-973.86" font-family="Times,serif" font-size="14.00">GHCup</text>
|
||||
</g>
|
||||
<g id="clust2" class="cluster">
|
||||
<title>cluster_1</title>
|
||||
<polygon fill="#000000" fill-opacity="0.058824" stroke="#000000" stroke-opacity="0.058824" points="1032,-324.75 1032,-540.11 1300,-540.11 1300,-324.75 1032,-324.75"/>
|
||||
<text text-anchor="middle" x="1166" y="-524.91" font-family="Times,serif" font-size="14.00">Download</text>
|
||||
</g>
|
||||
<g id="clust3" class="cluster">
|
||||
<title>cluster_2</title>
|
||||
<polygon fill="#000000" fill-opacity="0.058824" stroke="#000000" stroke-opacity="0.058824" points="176,-704.19 176,-953.74 1716,-953.74 1716,-704.19 176,-704.19"/>
|
||||
<text text-anchor="middle" x="946" y="-938.54" font-family="Times,serif" font-size="14.00">OptParse</text>
|
||||
</g>
|
||||
<g id="clust4" class="cluster">
|
||||
<title>cluster_3</title>
|
||||
<polygon fill="#000000" fill-opacity="0.058824" stroke="#000000" stroke-opacity="0.058824" points="439,-18.23 439,-445.53 972,-445.53 972,-18.23 439,-18.23"/>
|
||||
<text text-anchor="middle" x="705.5" y="-430.33" font-family="Times,serif" font-size="14.00">Prelude</text>
|
||||
</g>
|
||||
<g id="clust5" class="cluster">
|
||||
<title>cluster_4</title>
|
||||
<polygon fill="#000000" fill-opacity="0.058824" stroke="#000000" stroke-opacity="0.058824" points="479,-100.27 479,-185.73 656,-185.73 656,-100.27 479,-100.27"/>
|
||||
<text text-anchor="middle" x="567.5" y="-170.53" font-family="Times,serif" font-size="14.00">File</text>
|
||||
</g>
|
||||
<g id="clust6" class="cluster">
|
||||
<title>cluster_5</title>
|
||||
<polygon fill="#000000" fill-opacity="0.058824" stroke="#000000" stroke-opacity="0.058824" points="583,-194.85 583,-280.31 801,-280.31 801,-194.85 583,-194.85"/>
|
||||
<text text-anchor="middle" x="692" y="-265.11" font-family="Times,serif" font-size="14.00">Logger</text>
|
||||
</g>
|
||||
<g id="clust7" class="cluster">
|
||||
<title>cluster_6</title>
|
||||
<polygon fill="#000000" fill-opacity="0.058824" stroke="#000000" stroke-opacity="0.058824" points="447,-324.75 447,-410.21 517,-410.21 517,-324.75 447,-324.75"/>
|
||||
<text text-anchor="middle" x="482" y="-395.01" font-family="Times,serif" font-size="14.00">String</text>
|
||||
</g>
|
||||
<g id="clust8" class="cluster">
|
||||
<title>cluster_7</title>
|
||||
<polygon fill="#000000" fill-opacity="0.058824" stroke="#000000" stroke-opacity="0.058824" points="525,-324.75 525,-410.21 595,-410.21 595,-324.75 525,-324.75"/>
|
||||
<text text-anchor="middle" x="560" y="-395.01" font-family="Times,serif" font-size="14.00">Version</text>
|
||||
</g>
|
||||
<g id="clust9" class="cluster">
|
||||
<title>cluster_8</title>
|
||||
<polygon fill="#000000" fill-opacity="0.058824" stroke="#000000" stroke-opacity="0.058824" points="992,-91.16 992,-315.63 1186,-315.63 1186,-91.16 992,-91.16"/>
|
||||
<text text-anchor="middle" x="1089" y="-300.43" font-family="Times,serif" font-size="14.00">Types</text>
|
||||
</g>
|
||||
<g id="clust10" class="cluster">
|
||||
<title>cluster_9</title>
|
||||
<polygon fill="#000000" fill-opacity="0.058824" stroke="#000000" stroke-opacity="0.058824" points="1090,-100.27 1090,-280.31 1178,-280.31 1178,-100.27 1090,-100.27"/>
|
||||
<text text-anchor="middle" x="1134" y="-265.11" font-family="Times,serif" font-size="14.00">JSON</text>
|
||||
</g>
|
||||
<g id="clust11" class="cluster">
|
||||
<title>cluster_10</title>
|
||||
<polygon fill="#000000" fill-opacity="0.058824" stroke="#000000" stroke-opacity="0.058824" points="443,-454.65 443,-540.11 605,-540.11 605,-454.65 443,-454.65"/>
|
||||
<text text-anchor="middle" x="524" y="-524.91" font-family="Times,serif" font-size="14.00">Utils</text>
|
||||
</g>
|
||||
<!-- u2 -->
|
||||
<g id="node1" class="node">
|
||||
<title>u2</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="2" cx="1097" cy="-484.12" rx="56.59" ry="18"/>
|
||||
<text text-anchor="middle" x="1097" y="-480.42" font-family="Times,serif" font-size="14.00">Download</text>
|
||||
</g>
|
||||
<!-- u13 -->
|
||||
<g id="node27" class="node">
|
||||
<title>u13</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="2" cx="652" cy="-354.12" rx="46.59" ry="18"/>
|
||||
<text text-anchor="middle" x="652" y="-350.42" font-family="Times,serif" font-size="14.00">Prelude</text>
|
||||
</g>
|
||||
<!-- u2->u13 -->
|
||||
<g id="edge20" class="edge">
|
||||
<title>u2->u13</title>
|
||||
<path fill="none" stroke="black" d="M1067.21,-468.71C1057.48,-464.6 1046.47,-460.58 1036,-458.12 964.86,-441.38 771.65,-470.02 708,-434.12 687.37,-422.48 672.48,-399.72 663.27,-381.6"/>
|
||||
<polygon fill="black" stroke="black" points="666.2,-379.63 658.73,-372.12 659.89,-382.65 666.2,-379.63"/>
|
||||
</g>
|
||||
<!-- u17 -->
|
||||
<g id="node30" class="node">
|
||||
<title>u17</title>
|
||||
<ellipse fill="#bbffff" stroke="black" stroke-width="0" cx="764" cy="-354.12" rx="46.59" ry="18"/>
|
||||
<text text-anchor="middle" x="764" y="-350.42" font-family="Times,serif" font-size="14.00">Process</text>
|
||||
</g>
|
||||
<!-- u2->u17 -->
|
||||
<g id="edge21" class="edge">
|
||||
<title>u2->u17</title>
|
||||
<path fill="none" stroke="black" d="M1066.85,-468.81C1057.18,-464.76 1046.31,-460.74 1036,-458.12 941.97,-434.15 902.41,-483.7 819,-434.12 798.76,-422.08 784.14,-399.36 775.08,-381.36"/>
|
||||
<polygon fill="black" stroke="black" points="778.07,-379.49 770.62,-371.95 771.74,-382.49 778.07,-379.49"/>
|
||||
</g>
|
||||
<!-- u18 -->
|
||||
<g id="node40" class="node">
|
||||
<title>u18</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="0" cx="352" cy="-354.12" rx="45.49" ry="18"/>
|
||||
<text text-anchor="middle" x="352" y="-350.42" font-family="Times,serif" font-size="14.00">Version</text>
|
||||
</g>
|
||||
<!-- u2->u18 -->
|
||||
<g id="edge19" class="edge">
|
||||
<title>u2->u18</title>
|
||||
<path fill="none" stroke="black" d="M1067.57,-468.64C1057.76,-464.47 1046.62,-460.43 1036,-458.12 907.14,-430.02 565.59,-482.75 443,-434.12 414.07,-422.64 388.04,-397.83 371.3,-379.05"/>
|
||||
<polygon fill="black" stroke="black" points="373.9,-376.71 364.72,-371.43 368.61,-381.29 373.9,-376.71"/>
|
||||
</g>
|
||||
<!-- u26 -->
|
||||
<g id="node2" class="node">
|
||||
<title>u26</title>
|
||||
<ellipse fill="#bbbbff" stroke="black" stroke-width="0" cx="1153" cy="-354.12" rx="33.29" ry="18"/>
|
||||
<text text-anchor="middle" x="1153" y="-350.42" font-family="Times,serif" font-size="14.00">Utils</text>
|
||||
</g>
|
||||
<!-- u26->u13 -->
|
||||
<g id="edge22" class="edge">
|
||||
<title>u26->u13</title>
|
||||
<path fill="none" stroke="black" d="M1137.02,-370.02C1113.54,-392.13 1067.24,-431.15 1019,-446.12 986.95,-456.06 747.01,-461.12 717,-446.12 690.64,-432.94 672.79,-403.39 662.57,-381.32"/>
|
||||
<polygon fill="black" stroke="black" points="665.74,-379.84 658.52,-372.09 659.33,-382.65 665.74,-379.84"/>
|
||||
</g>
|
||||
<!-- u28 -->
|
||||
<g id="node3" class="node">
|
||||
<title>u28</title>
|
||||
<ellipse fill="#bbbbff" stroke="black" stroke-width="0" cx="1232" cy="-484.12" rx="60.39" ry="18"/>
|
||||
<text text-anchor="middle" x="1232" y="-480.42" font-family="Times,serif" font-size="14.00">IOStreams</text>
|
||||
</g>
|
||||
<!-- u28->u26 -->
|
||||
<g id="edge23" class="edge">
|
||||
<title>u28->u26</title>
|
||||
<path fill="none" stroke="black" d="M1221.51,-466.12C1207.9,-444.07 1184.06,-405.44 1168.4,-380.07"/>
|
||||
<polygon fill="black" stroke="black" points="1171.26,-378.05 1163.03,-371.37 1165.31,-381.72 1171.26,-378.05"/>
|
||||
</g>
|
||||
<!-- u30 -->
|
||||
<g id="node4" class="node">
|
||||
<title>u30</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="2" cx="938" cy="-898.12" rx="53.89" ry="18"/>
|
||||
<text text-anchor="middle" x="938" y="-894.42" font-family="Times,serif" font-size="14.00">OptParse</text>
|
||||
</g>
|
||||
<!-- u32 -->
|
||||
<g id="node6" class="node">
|
||||
<title>u32</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="781" cy="-816.12" rx="40.09" ry="18"/>
|
||||
<text text-anchor="middle" x="781" y="-812.42" font-family="Times,serif" font-size="14.00">Install</text>
|
||||
</g>
|
||||
<!-- u30->u32 -->
|
||||
<g id="edge24" class="edge">
|
||||
<title>u30->u32</title>
|
||||
<path fill="none" stroke="black" d="M909.57,-882.63C883.21,-869.2 843.93,-849.18 815.73,-834.81"/>
|
||||
<polygon fill="black" stroke="black" points="817.12,-831.59 806.62,-830.17 813.94,-837.83 817.12,-831.59"/>
|
||||
</g>
|
||||
<!-- u33 -->
|
||||
<g id="node7" class="node">
|
||||
<title>u33</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="866" cy="-816.12" rx="27" ry="18"/>
|
||||
<text text-anchor="middle" x="866" y="-812.42" font-family="Times,serif" font-size="14.00">Set</text>
|
||||
</g>
|
||||
<!-- u30->u33 -->
|
||||
<g id="edge25" class="edge">
|
||||
<title>u30->u33</title>
|
||||
<path fill="none" stroke="black" d="M923.08,-880.54C912.44,-868.71 898,-852.67 886.31,-839.68"/>
|
||||
<polygon fill="black" stroke="black" points="888.73,-837.14 879.44,-832.05 883.53,-841.83 888.73,-837.14"/>
|
||||
</g>
|
||||
<!-- u34 -->
|
||||
<g id="node8" class="node">
|
||||
<title>u34</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="682" cy="-816.12" rx="40.09" ry="18"/>
|
||||
<text text-anchor="middle" x="682" y="-812.42" font-family="Times,serif" font-size="14.00">UnSet</text>
|
||||
</g>
|
||||
<!-- u30->u34 -->
|
||||
<g id="edge26" class="edge">
|
||||
<title>u30->u34</title>
|
||||
<path fill="none" stroke="black" d="M898.78,-885.51C857.25,-873.14 789.83,-852.79 732,-834.12 728.9,-833.12 725.7,-832.07 722.49,-831"/>
|
||||
<polygon fill="black" stroke="black" points="723.48,-827.64 712.89,-827.79 721.26,-834.28 723.48,-827.64"/>
|
||||
</g>
|
||||
<!-- u35 -->
|
||||
<g id="node9" class="node">
|
||||
<title>u35</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="938" cy="-816.12" rx="27" ry="18"/>
|
||||
<text text-anchor="middle" x="938" y="-812.42" font-family="Times,serif" font-size="14.00">Rm</text>
|
||||
</g>
|
||||
<!-- u30->u35 -->
|
||||
<g id="edge27" class="edge">
|
||||
<title>u30->u35</title>
|
||||
<path fill="none" stroke="black" d="M938,-879.76C938,-869.41 938,-856.06 938,-844.34"/>
|
||||
<polygon fill="black" stroke="black" points="941.5,-844.17 938,-834.17 934.5,-844.17 941.5,-844.17"/>
|
||||
</g>
|
||||
<!-- u36 -->
|
||||
<g id="node10" class="node">
|
||||
<title>u36</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="1012" cy="-816.12" rx="29.5" ry="18"/>
|
||||
<text text-anchor="middle" x="1012" y="-812.42" font-family="Times,serif" font-size="14.00">Run</text>
|
||||
</g>
|
||||
<!-- u30->u36 -->
|
||||
<g id="edge28" class="edge">
|
||||
<title>u30->u36</title>
|
||||
<path fill="none" stroke="black" d="M953.33,-880.54C964.27,-868.71 979.11,-852.67 991.13,-839.68"/>
|
||||
<polygon fill="black" stroke="black" points="993.96,-841.77 998.18,-832.05 988.82,-837.02 993.96,-841.77"/>
|
||||
</g>
|
||||
<!-- u37 -->
|
||||
<g id="node11" class="node">
|
||||
<title>u37</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="1108" cy="-816.12" rx="48.99" ry="18"/>
|
||||
<text text-anchor="middle" x="1108" y="-812.42" font-family="Times,serif" font-size="14.00">Compile</text>
|
||||
</g>
|
||||
<!-- u30->u37 -->
|
||||
<g id="edge29" class="edge">
|
||||
<title>u30->u37</title>
|
||||
<path fill="none" stroke="black" d="M968,-883C996.42,-869.62 1039.22,-849.48 1070.01,-834.99"/>
|
||||
<polygon fill="black" stroke="black" points="1071.59,-838.12 1079.15,-830.69 1068.61,-831.78 1071.59,-838.12"/>
|
||||
</g>
|
||||
<!-- u38 -->
|
||||
<g id="node12" class="node">
|
||||
<title>u38</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="1215" cy="-816.12" rx="40.09" ry="18"/>
|
||||
<text text-anchor="middle" x="1215" y="-812.42" font-family="Times,serif" font-size="14.00">Config</text>
|
||||
</g>
|
||||
<!-- u30->u38 -->
|
||||
<g id="edge30" class="edge">
|
||||
<title>u30->u38</title>
|
||||
<path fill="none" stroke="black" d="M979.42,-886.53C1025.29,-874.6 1101.3,-854.25 1166,-834.12 1168.92,-833.21 1171.92,-832.24 1174.93,-831.25"/>
|
||||
<polygon fill="black" stroke="black" points="1176.15,-834.53 1184.52,-828.03 1173.92,-827.9 1176.15,-834.53"/>
|
||||
</g>
|
||||
<!-- u39 -->
|
||||
<g id="node13" class="node">
|
||||
<title>u39</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="1322" cy="-816.12" rx="48.99" ry="18"/>
|
||||
<text text-anchor="middle" x="1322" y="-812.42" font-family="Times,serif" font-size="14.00">Whereis</text>
|
||||
</g>
|
||||
<!-- u30->u39 -->
|
||||
<g id="edge31" class="edge">
|
||||
<title>u30->u39</title>
|
||||
<path fill="none" stroke="black" d="M985.27,-889.42C1048.96,-878.72 1165.69,-857.97 1264,-834.12 1267.9,-833.17 1271.94,-832.12 1275.97,-831.03"/>
|
||||
<polygon fill="black" stroke="black" points="1277.25,-834.31 1285.94,-828.26 1275.37,-827.57 1277.25,-834.31"/>
|
||||
</g>
|
||||
<!-- u40 -->
|
||||
<g id="node14" class="node">
|
||||
<title>u40</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="1417" cy="-816.12" rx="28.7" ry="18"/>
|
||||
<text text-anchor="middle" x="1417" y="-812.42" font-family="Times,serif" font-size="14.00">List</text>
|
||||
</g>
|
||||
<!-- u30->u40 -->
|
||||
<g id="edge32" class="edge">
|
||||
<title>u30->u40</title>
|
||||
<path fill="none" stroke="black" d="M991.1,-894.5C1075.16,-889.26 1243.36,-874.32 1380,-834.12 1381.93,-833.55 1383.89,-832.89 1385.85,-832.18"/>
|
||||
<polygon fill="black" stroke="black" points="1387.55,-835.27 1395.49,-828.26 1384.91,-828.79 1387.55,-835.27"/>
|
||||
</g>
|
||||
<!-- u41 -->
|
||||
<g id="node15" class="node">
|
||||
<title>u41</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="1527" cy="-816.12" rx="63.09" ry="18"/>
|
||||
<text text-anchor="middle" x="1527" y="-812.42" font-family="Times,serif" font-size="14.00">ChangeLog</text>
|
||||
</g>
|
||||
<!-- u30->u41 -->
|
||||
<g id="edge33" class="edge">
|
||||
<title>u30->u41</title>
|
||||
<path fill="none" stroke="black" d="M989.65,-892.73C1083.01,-884.38 1285.87,-864.29 1455,-834.12 1460.37,-833.16 1465.95,-832.05 1471.51,-830.87"/>
|
||||
<polygon fill="black" stroke="black" points="1472.44,-834.24 1481.45,-828.67 1470.93,-827.41 1472.44,-834.24"/>
|
||||
</g>
|
||||
<!-- u42 -->
|
||||
<g id="node16" class="node">
|
||||
<title>u42</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="1658" cy="-816.12" rx="50.09" ry="18"/>
|
||||
<text text-anchor="middle" x="1658" y="-812.42" font-family="Times,serif" font-size="14.00">Prefetch</text>
|
||||
</g>
|
||||
<!-- u30->u42 -->
|
||||
<g id="edge34" class="edge">
|
||||
<title>u30->u42</title>
|
||||
<path fill="none" stroke="black" d="M991.59,-895.37C1104.73,-890.96 1375.9,-876.51 1599,-834.12 1603.18,-833.32 1607.5,-832.36 1611.8,-831.31"/>
|
||||
<polygon fill="black" stroke="black" points="1612.96,-834.62 1621.75,-828.7 1611.19,-827.85 1612.96,-834.62"/>
|
||||
</g>
|
||||
<!-- u43 -->
|
||||
<g id="node17" class="node">
|
||||
<title>u43</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="211" cy="-816.12" rx="27" ry="18"/>
|
||||
<text text-anchor="middle" x="211" y="-812.42" font-family="Times,serif" font-size="14.00">GC</text>
|
||||
</g>
|
||||
<!-- u30->u43 -->
|
||||
<g id="edge35" class="edge">
|
||||
<title>u30->u43</title>
|
||||
<path fill="none" stroke="black" d="M884.97,-894.68C744.84,-887.86 367.29,-866.9 247,-834.12 245.05,-833.58 243.07,-832.95 241.11,-832.25"/>
|
||||
<polygon fill="black" stroke="black" points="242.05,-828.85 231.47,-828.29 239.38,-835.33 242.05,-828.85"/>
|
||||
</g>
|
||||
<!-- u44 -->
|
||||
<g id="node18" class="node">
|
||||
<title>u44</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="292" cy="-816.12" rx="36.29" ry="18"/>
|
||||
<text text-anchor="middle" x="292" y="-812.42" font-family="Times,serif" font-size="14.00">DInfo</text>
|
||||
</g>
|
||||
<!-- u30->u44 -->
|
||||
<g id="edge36" class="edge">
|
||||
<title>u30->u44</title>
|
||||
<path fill="none" stroke="black" d="M884.17,-896.08C778.07,-893.04 535.04,-881.08 337,-834.12 334.18,-833.45 331.3,-832.65 328.43,-831.77"/>
|
||||
<polygon fill="black" stroke="black" points="329.37,-828.39 318.78,-828.51 327.13,-835.02 329.37,-828.39"/>
|
||||
</g>
|
||||
<!-- u45 -->
|
||||
<g id="node19" class="node">
|
||||
<title>u45</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="441" cy="-816.12" rx="94.78" ry="18"/>
|
||||
<text text-anchor="middle" x="441" y="-812.42" font-family="Times,serif" font-size="14.00">ToolRequirements</text>
|
||||
</g>
|
||||
<!-- u30->u45 -->
|
||||
<g id="edge37" class="edge">
|
||||
<title>u30->u45</title>
|
||||
<path fill="none" stroke="black" d="M890.5,-889.55C816.61,-877.77 669.66,-854.3 545,-834.12 537.04,-832.83 528.74,-831.48 520.45,-830.13"/>
|
||||
<polygon fill="black" stroke="black" points="520.8,-826.64 510.36,-828.48 519.67,-833.55 520.8,-826.64"/>
|
||||
</g>
|
||||
<!-- u46 -->
|
||||
<g id="node20" class="node">
|
||||
<title>u46</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="589" cy="-816.12" rx="35.19" ry="18"/>
|
||||
<text text-anchor="middle" x="589" y="-812.42" font-family="Times,serif" font-size="14.00">Nuke</text>
|
||||
</g>
|
||||
<!-- u30->u46 -->
|
||||
<g id="edge38" class="edge">
|
||||
<title>u30->u46</title>
|
||||
<path fill="none" stroke="black" d="M890.12,-889.74C829.54,-879.84 722.35,-860.41 633,-834.12 630.37,-833.34 627.67,-832.48 624.97,-831.56"/>
|
||||
<polygon fill="black" stroke="black" points="625.88,-828.17 615.28,-828.08 623.51,-834.76 625.88,-828.17"/>
|
||||
</g>
|
||||
<!-- u31 -->
|
||||
<g id="node5" class="node">
|
||||
<title>u31</title>
|
||||
<ellipse fill="#ffbbbb" stroke="black" stroke-width="0" cx="1012" cy="-734.12" rx="51.99" ry="18"/>
|
||||
<text text-anchor="middle" x="1012" y="-730.42" font-family="Times,serif" font-size="14.00">Common</text>
|
||||
</g>
|
||||
<!-- u0 -->
|
||||
<g id="node37" class="node">
|
||||
<title>u0</title>
|
||||
<ellipse fill="#bbffbb" stroke="black" stroke-width="2" cx="589" cy="-652.12" rx="44.39" ry="18"/>
|
||||
<text text-anchor="middle" x="589" y="-648.42" font-family="Times,serif" font-size="14.00">GHCup</text>
|
||||
</g>
|
||||
<!-- u31->u0 -->
|
||||
<g id="edge39" class="edge">
|
||||
<title>u31->u0</title>
|
||||
<path fill="none" stroke="black" d="M984.07,-718.86C975.28,-714.86 965.4,-710.86 956,-708.12 847.4,-676.38 715.09,-662.3 642.71,-656.59"/>
|
||||
<polygon fill="black" stroke="black" points="642.71,-653.08 632.48,-655.81 642.18,-660.06 642.71,-653.08"/>
|
||||
</g>
|
||||
<!-- u32->u31 -->
|
||||
<g id="edge40" class="edge">
|
||||
<title>u32->u31</title>
|
||||
<path fill="none" stroke="black" d="M811.84,-804.41C817.86,-802.32 824.13,-800.15 830,-798.12 876.69,-781.93 930.13,-763.44 966.97,-750.69"/>
|
||||
<polygon fill="black" stroke="black" points="968.12,-754 976.43,-747.42 965.83,-747.38 968.12,-754"/>
|
||||
</g>
|
||||
<!-- u33->u31 -->
|
||||
<g id="edge41" class="edge">
|
||||
<title>u33->u31</title>
|
||||
<path fill="none" stroke="black" d="M886.3,-803.99C909.63,-791.21 948.34,-770 976.65,-754.49"/>
|
||||
<polygon fill="black" stroke="black" points="978.36,-757.54 985.44,-749.67 974.99,-751.4 978.36,-757.54"/>
|
||||
</g>
|
||||
<!-- u34->u0 -->
|
||||
<g id="edge42" class="edge">
|
||||
<title>u34->u0</title>
|
||||
<path fill="none" stroke="black" d="M672.4,-798.39C656.11,-770.01 622.96,-712.27 603.72,-678.76"/>
|
||||
<polygon fill="black" stroke="black" points="606.7,-676.92 598.69,-669.99 600.63,-680.41 606.7,-676.92"/>
|
||||
</g>
|
||||
<!-- u35->u31 -->
|
||||
<g id="edge43" class="edge">
|
||||
<title>u35->u31</title>
|
||||
<path fill="none" stroke="black" d="M951.57,-800.44C962.25,-788.9 977.34,-772.59 989.77,-759.15"/>
|
||||
<polygon fill="black" stroke="black" points="992.5,-761.35 996.73,-751.63 987.37,-756.59 992.5,-761.35"/>
|
||||
</g>
|
||||
<!-- u36->u31 -->
|
||||
<g id="edge44" class="edge">
|
||||
<title>u36->u31</title>
|
||||
<path fill="none" stroke="black" d="M1012,-797.76C1012,-787.41 1012,-774.06 1012,-762.34"/>
|
||||
<polygon fill="black" stroke="black" points="1015.5,-762.17 1012,-752.17 1008.5,-762.17 1015.5,-762.17"/>
|
||||
</g>
|
||||
<!-- u37->u31 -->
|
||||
<g id="edge45" class="edge">
|
||||
<title>u37->u31</title>
|
||||
<path fill="none" stroke="black" d="M1089.03,-799.31C1074.7,-787.37 1054.84,-770.81 1038.87,-757.51"/>
|
||||
<polygon fill="black" stroke="black" points="1040.85,-754.6 1030.93,-750.89 1036.37,-759.98 1040.85,-754.6"/>
|
||||
</g>
|
||||
<!-- u38->u31 -->
|
||||
<g id="edge46" class="edge">
|
||||
<title>u38->u31</title>
|
||||
<path fill="none" stroke="black" d="M1185.92,-803.65C1151.55,-790.11 1094.08,-767.46 1054.68,-751.93"/>
|
||||
<polygon fill="black" stroke="black" points="1055.66,-748.56 1045.07,-748.15 1053.09,-755.07 1055.66,-748.56"/>
|
||||
</g>
|
||||
<!-- u39->u31 -->
|
||||
<g id="edge47" class="edge">
|
||||
<title>u39->u31</title>
|
||||
<path fill="none" stroke="black" d="M1285.24,-804.1C1278.21,-802.06 1270.89,-799.98 1264,-798.12 1194.84,-779.34 1114.44,-759.6 1063.41,-747.33"/>
|
||||
<polygon fill="black" stroke="black" points="1064.14,-743.91 1053.6,-744.97 1062.51,-750.71 1064.14,-743.91"/>
|
||||
</g>
|
||||
<!-- u40->u31 -->
|
||||
<g id="edge48" class="edge">
|
||||
<title>u40->u31</title>
|
||||
<path fill="none" stroke="black" d="M1395.46,-804.08C1390.48,-801.85 1385.13,-799.7 1380,-798.12 1274.14,-765.36 1145.55,-748.25 1071.8,-740.51"/>
|
||||
<polygon fill="black" stroke="black" points="1072.07,-737.02 1061.77,-739.48 1071.36,-743.98 1072.07,-737.02"/>
|
||||
</g>
|
||||
<!-- u41->u31 -->
|
||||
<g id="edge49" class="edge">
|
||||
<title>u41->u31</title>
|
||||
<path fill="none" stroke="black" d="M1481.04,-803.61C1472.42,-801.64 1463.46,-799.71 1455,-798.12 1318.2,-772.29 1155.83,-751.75 1070.73,-741.75"/>
|
||||
<polygon fill="black" stroke="black" points="1071.08,-738.27 1060.75,-740.58 1070.27,-745.22 1071.08,-738.27"/>
|
||||
</g>
|
||||
<!-- u42->u31 -->
|
||||
<g id="edge50" class="edge">
|
||||
<title>u42->u31</title>
|
||||
<path fill="none" stroke="black" d="M1621.73,-803.6C1614.27,-801.53 1606.43,-799.57 1599,-798.12 1409.25,-760.89 1180.36,-744.32 1073.09,-738.17"/>
|
||||
<polygon fill="black" stroke="black" points="1073.27,-734.68 1063.09,-737.61 1072.88,-741.67 1073.27,-734.68"/>
|
||||
</g>
|
||||
<!-- u43->u0 -->
|
||||
<g id="edge51" class="edge">
|
||||
<title>u43->u0</title>
|
||||
<path fill="none" stroke="black" d="M230.04,-803.16C264.62,-781.82 340.51,-736.75 409,-708.12 452.95,-689.74 505.22,-674.46 542.08,-664.7"/>
|
||||
<polygon fill="black" stroke="black" points="543.26,-668.01 552.05,-662.1 541.49,-661.24 543.26,-668.01"/>
|
||||
</g>
|
||||
<!-- u44->u0 -->
|
||||
<g id="edge52" class="edge">
|
||||
<title>u44->u0</title>
|
||||
<path fill="none" stroke="black" d="M315.55,-802.27C367.75,-773.8 493.37,-705.28 554.47,-671.95"/>
|
||||
<polygon fill="black" stroke="black" points="556.25,-674.97 563.35,-667.11 552.89,-668.82 556.25,-674.97"/>
|
||||
</g>
|
||||
<!-- u25 -->
|
||||
<g id="node45" class="node">
|
||||
<title>u25</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="0" cx="764" cy="-484.12" rx="51.19" ry="18"/>
|
||||
<text text-anchor="middle" x="764" y="-480.42" font-family="Times,serif" font-size="14.00">Platform</text>
|
||||
</g>
|
||||
<!-- u45->u25 -->
|
||||
<g id="edge53" class="edge">
|
||||
<title>u45->u25</title>
|
||||
<path fill="none" stroke="black" d="M508.31,-803.36C520.5,-801.44 533.11,-799.6 545,-798.12 603.43,-790.81 1033.21,-795.53 1073,-752.12 1170.68,-645.56 916.77,-539.37 809.35,-500.56"/>
|
||||
<polygon fill="black" stroke="black" points="810.32,-497.19 799.73,-497.12 807.97,-503.78 810.32,-497.19"/>
|
||||
</g>
|
||||
<!-- u27 -->
|
||||
<g id="node46" class="node">
|
||||
<title>u27</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="0" cx="92" cy="-734.12" rx="76.09" ry="18"/>
|
||||
<text text-anchor="middle" x="92" y="-730.42" font-family="Times,serif" font-size="14.00">Requirements</text>
|
||||
</g>
|
||||
<!-- u45->u27 -->
|
||||
<g id="edge54" class="edge">
|
||||
<title>u45->u27</title>
|
||||
<path fill="none" stroke="black" d="M382.98,-801.82C319.96,-787.37 219.65,-764.38 154.82,-749.52"/>
|
||||
<polygon fill="black" stroke="black" points="155.26,-746.03 144.73,-747.2 153.69,-752.85 155.26,-746.03"/>
|
||||
</g>
|
||||
<!-- u46->u0 -->
|
||||
<g id="edge55" class="edge">
|
||||
<title>u46->u0</title>
|
||||
<path fill="none" stroke="black" d="M589,-798.09C589,-770.08 589,-714.08 589,-680.47"/>
|
||||
<polygon fill="black" stroke="black" points="592.5,-680.41 589,-670.41 585.5,-680.41 592.5,-680.41"/>
|
||||
</g>
|
||||
<!-- u16 -->
|
||||
<g id="node21" class="node">
|
||||
<title>u16</title>
|
||||
<ellipse fill="#bbffff" stroke="black" stroke-width="2" cx="619" cy="-130.12" rx="28.7" ry="18"/>
|
||||
<text text-anchor="middle" x="619" y="-126.42" font-family="Times,serif" font-size="14.00">File</text>
|
||||
</g>
|
||||
<!-- u14 -->
|
||||
<g id="node29" class="node">
|
||||
<title>u14</title>
|
||||
<ellipse fill="#bbffff" stroke="black" stroke-width="0" cx="619" cy="-48.12" rx="48.19" ry="18"/>
|
||||
<text text-anchor="middle" x="619" y="-44.42" font-family="Times,serif" font-size="14.00">Internal</text>
|
||||
</g>
|
||||
<!-- u16->u14 -->
|
||||
<g id="edge59" class="edge">
|
||||
<title>u16->u14</title>
|
||||
<path fill="none" stroke="black" d="M619,-111.76C619,-101.41 619,-88.06 619,-76.34"/>
|
||||
<polygon fill="black" stroke="black" points="622.5,-76.17 619,-66.17 615.5,-76.17 622.5,-76.17"/>
|
||||
</g>
|
||||
<!-- u3 -->
|
||||
<g id="node39" class="node">
|
||||
<title>u3</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="0" cx="390" cy="-224.12" rx="40.89" ry="18"/>
|
||||
<text text-anchor="middle" x="390" y="-220.42" font-family="Times,serif" font-size="14.00">Errors</text>
|
||||
</g>
|
||||
<!-- u16->u3 -->
|
||||
<g id="edge58" class="edge">
|
||||
<title>u16->u3</title>
|
||||
<path fill="none" stroke="black" d="M610.46,-147.32C604.02,-157.95 594.23,-171.28 582,-179.12 539.39,-206.41 481.9,-216.85 440.96,-220.8"/>
|
||||
<polygon fill="black" stroke="black" points="440.59,-217.32 430.93,-221.67 441.19,-224.3 440.59,-217.32"/>
|
||||
</g>
|
||||
<!-- u10 -->
|
||||
<g id="node22" class="node">
|
||||
<title>u10</title>
|
||||
<ellipse fill="#ffbbff" stroke="black" stroke-width="0" cx="530" cy="-130.12" rx="42.79" ry="18"/>
|
||||
<text text-anchor="middle" x="530" y="-126.42" font-family="Times,serif" font-size="14.00">Search</text>
|
||||
</g>
|
||||
<!-- u4 -->
|
||||
<g id="node33" class="node">
|
||||
<title>u4</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="2" cx="1038" cy="-130.12" rx="38.19" ry="18"/>
|
||||
<text text-anchor="middle" x="1038" y="-126.42" font-family="Times,serif" font-size="14.00">Types</text>
|
||||
</g>
|
||||
<!-- u10->u4 -->
|
||||
<g id="edge60" class="edge">
|
||||
<title>u10->u4</title>
|
||||
<path fill="none" stroke="black" d="M541.94,-147.67C552.66,-161.72 569.79,-180.39 590,-188.62 615.11,-198.83 623.97,-190.65 651,-188.62 775.48,-179.26 920.61,-153.2 992.63,-139.24"/>
|
||||
<polygon fill="black" stroke="black" points="993.58,-142.62 1002.72,-137.27 992.23,-135.75 993.58,-142.62"/>
|
||||
</g>
|
||||
<!-- u15 -->
|
||||
<g id="node23" class="node">
|
||||
<title>u15</title>
|
||||
<ellipse fill="#bbffff" stroke="black" stroke-width="2" cx="635" cy="-224.12" rx="43.59" ry="18"/>
|
||||
<text text-anchor="middle" x="635" y="-220.42" font-family="Times,serif" font-size="14.00">Logger</text>
|
||||
</g>
|
||||
<!-- u15->u16 -->
|
||||
<g id="edge61" class="edge">
|
||||
<title>u15->u16</title>
|
||||
<path fill="none" stroke="black" d="M631.99,-205.81C629.65,-192.36 626.37,-173.47 623.68,-158.04"/>
|
||||
<polygon fill="black" stroke="black" points="627.1,-157.28 621.94,-148.03 620.21,-158.48 627.1,-157.28"/>
|
||||
</g>
|
||||
<!-- u12 -->
|
||||
<g id="node24" class="node">
|
||||
<title>u12</title>
|
||||
<ellipse fill="#77ff77" stroke="black" stroke-width="0" cx="745" cy="-224.12" rx="48.19" ry="18"/>
|
||||
<text text-anchor="middle" x="745" y="-220.42" font-family="Times,serif" font-size="14.00">Internal</text>
|
||||
</g>
|
||||
<!-- u12->u4 -->
|
||||
<g id="edge62" class="edge">
|
||||
<title>u12->u4</title>
|
||||
<path fill="none" stroke="black" d="M771.86,-209.09C779.83,-205.23 788.66,-201.25 797,-198.12 864.17,-172.86 945.04,-152.29 993.94,-140.88"/>
|
||||
<polygon fill="black" stroke="black" points="994.91,-144.25 1003.87,-138.59 993.34,-137.43 994.91,-144.25"/>
|
||||
</g>
|
||||
<!-- u11 -->
|
||||
<g id="node25" class="node">
|
||||
<title>u11</title>
|
||||
<ellipse fill="#ffff77" stroke="black" stroke-width="0" cx="482" cy="-354.12" rx="27" ry="18"/>
|
||||
<text text-anchor="middle" x="482" y="-350.42" font-family="Times,serif" font-size="14.00">QQ</text>
|
||||
</g>
|
||||
<!-- u21 -->
|
||||
<g id="node26" class="node">
|
||||
<title>u21</title>
|
||||
<ellipse fill="#7777ff" stroke="black" stroke-width="0" cx="560" cy="-354.12" rx="27" ry="18"/>
|
||||
<text text-anchor="middle" x="560" y="-350.42" font-family="Times,serif" font-size="14.00">QQ</text>
|
||||
</g>
|
||||
<!-- u13->u15 -->
|
||||
<g id="edge56" class="edge">
|
||||
<title>u13->u15</title>
|
||||
<path fill="none" stroke="black" d="M649.74,-336.12C646.9,-314.7 641.97,-277.62 638.6,-252.26"/>
|
||||
<polygon fill="black" stroke="black" points="642.05,-251.64 637.27,-242.18 635.11,-252.56 642.05,-251.64"/>
|
||||
</g>
|
||||
<!-- u8 -->
|
||||
<g id="node28" class="node">
|
||||
<title>u8</title>
|
||||
<ellipse fill="#bbffff" stroke="black" stroke-width="0" cx="896" cy="-354.12" rx="67.69" ry="18"/>
|
||||
<text text-anchor="middle" x="896" y="-350.42" font-family="Times,serif" font-size="14.00">MegaParsec</text>
|
||||
</g>
|
||||
<!-- u8->u4 -->
|
||||
<g id="edge57" class="edge">
|
||||
<title>u8->u4</title>
|
||||
<path fill="none" stroke="black" d="M903.02,-335.98C915.49,-306.47 943.31,-244.73 976,-198.12 987.15,-182.21 1001.84,-166.18 1014.12,-153.79"/>
|
||||
<polygon fill="black" stroke="black" points="1016.76,-156.1 1021.4,-146.57 1011.83,-151.13 1016.76,-156.1"/>
|
||||
</g>
|
||||
<!-- u6 -->
|
||||
<g id="node31" class="node">
|
||||
<title>u6</title>
|
||||
<ellipse fill="#ff7777" stroke="black" stroke-width="2" cx="1134" cy="-224.12" rx="36" ry="18"/>
|
||||
<text text-anchor="middle" x="1134" y="-220.42" font-family="Times,serif" font-size="14.00">JSON</text>
|
||||
</g>
|
||||
<!-- u6->u8 -->
|
||||
<g id="edge65" class="edge">
|
||||
<title>u6->u8</title>
|
||||
<path fill="none" stroke="black" d="M1129.86,-242.31C1124.59,-260.41 1113.72,-288.41 1094,-304.12 1083.21,-312.71 1012.21,-328.99 958.29,-340.42"/>
|
||||
<polygon fill="black" stroke="black" points="957.51,-337.01 948.44,-342.5 958.95,-343.86 957.51,-337.01"/>
|
||||
</g>
|
||||
<!-- u7 -->
|
||||
<g id="node32" class="node">
|
||||
<title>u7</title>
|
||||
<ellipse fill="#77ffff" stroke="black" stroke-width="0" cx="1134" cy="-130.12" rx="33.29" ry="18"/>
|
||||
<text text-anchor="middle" x="1134" y="-126.42" font-family="Times,serif" font-size="14.00">Utils</text>
|
||||
</g>
|
||||
<!-- u6->u7 -->
|
||||
<g id="edge66" class="edge">
|
||||
<title>u6->u7</title>
|
||||
<path fill="none" stroke="black" d="M1134,-205.81C1134,-192.58 1134,-174.06 1134,-158.78"/>
|
||||
<polygon fill="black" stroke="black" points="1137.5,-158.34 1134,-148.34 1130.5,-158.34 1137.5,-158.34"/>
|
||||
</g>
|
||||
<!-- u5 -->
|
||||
<g id="node36" class="node">
|
||||
<title>u5</title>
|
||||
<ellipse fill="#ff77ff" stroke="black" stroke-width="0" cx="482" cy="-484.12" rx="30.59" ry="18"/>
|
||||
<text text-anchor="middle" x="482" y="-480.42" font-family="Times,serif" font-size="14.00">Dirs</text>
|
||||
</g>
|
||||
<!-- u4->u5 -->
|
||||
<g id="edge63" class="edge">
|
||||
<title>u4->u5</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M1023.23,-146.75C1012.19,-159.5 997.87,-178.54 991,-198.12 982.3,-222.91 994.68,-415.64 976,-434.12 940.09,-469.64 570.17,-442.91 522,-458.12 517.36,-459.58 512.73,-461.71 508.34,-464.12"/>
|
||||
<polygon fill="black" stroke="black" points="506.49,-461.14 499.76,-469.33 510.12,-467.13 506.49,-461.14"/>
|
||||
</g>
|
||||
<!-- u9 -->
|
||||
<g id="node34" class="node">
|
||||
<title>u9</title>
|
||||
<ellipse fill="#ff7777" stroke="black" stroke-width="0" cx="1040" cy="-224.12" rx="40.09" ry="18"/>
|
||||
<text text-anchor="middle" x="1040" y="-220.42" font-family="Times,serif" font-size="14.00">Optics</text>
|
||||
</g>
|
||||
<!-- u9->u4 -->
|
||||
<g id="edge64" class="edge">
|
||||
<title>u9->u4</title>
|
||||
<path fill="none" stroke="black" d="M1039.62,-205.81C1039.34,-192.58 1038.93,-174.06 1038.6,-158.78"/>
|
||||
<polygon fill="black" stroke="black" points="1042.09,-158.26 1038.37,-148.34 1035.09,-158.42 1042.09,-158.26"/>
|
||||
</g>
|
||||
<!-- u19 -->
|
||||
<g id="node35" class="node">
|
||||
<title>u19</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="2" cx="564" cy="-484.12" rx="33.29" ry="18"/>
|
||||
<text text-anchor="middle" x="564" y="-480.42" font-family="Times,serif" font-size="14.00">Utils</text>
|
||||
</g>
|
||||
<!-- u19->u2 -->
|
||||
<g id="edge67" class="edge">
|
||||
<title>u19->u2</title>
|
||||
<path fill="none" stroke="black" d="M571.82,-501.68C579.29,-515.94 592.08,-534.91 610,-542.62 631.28,-551.77 1005.22,-550.52 1027,-542.62 1045.67,-535.84 1062.84,-521.67 1075.51,-508.97"/>
|
||||
<polygon fill="black" stroke="black" points="1078.05,-511.38 1082.42,-501.73 1072.98,-506.55 1078.05,-511.38"/>
|
||||
</g>
|
||||
<!-- u5->u10 -->
|
||||
<g id="edge69" class="edge">
|
||||
<title>u5->u10</title>
|
||||
<path fill="none" stroke="black" d="M452.05,-479.77C403.81,-473.7 312.34,-459.11 293,-434.12 228.81,-351.16 229.72,-281.77 293,-198.12 315.48,-168.4 417.21,-148.09 479.86,-138.15"/>
|
||||
<polygon fill="black" stroke="black" points="480.59,-141.58 489.94,-136.59 479.52,-134.66 480.59,-141.58"/>
|
||||
</g>
|
||||
<!-- u5->u12 -->
|
||||
<g id="edge70" class="edge">
|
||||
<title>u5->u12</title>
|
||||
<path fill="none" stroke="black" d="M465.94,-468.47C457.34,-459.5 447.59,-447.25 443,-434.12 435.23,-411.88 427.18,-345.57 443,-328.12 479.75,-287.59 640.57,-331.38 688,-304.12 708.66,-292.24 723.85,-269.5 733.32,-251.46"/>
|
||||
<polygon fill="black" stroke="black" points="736.7,-252.53 738,-242.02 730.43,-249.43 736.7,-252.53"/>
|
||||
</g>
|
||||
<!-- u5->u11 -->
|
||||
<g id="edge71" class="edge">
|
||||
<title>u5->u11</title>
|
||||
<path fill="none" stroke="black" d="M482,-465.85C482,-444.48 482,-407.81 482,-382.56"/>
|
||||
<polygon fill="black" stroke="black" points="485.5,-382.51 482,-372.51 478.5,-382.51 485.5,-382.51"/>
|
||||
</g>
|
||||
<!-- u5->u6 -->
|
||||
<g id="edge73" class="edge">
|
||||
<title>u5->u6</title>
|
||||
<path fill="none" stroke="black" d="M499.75,-469.31C506.37,-464.92 514.19,-460.57 522,-458.12 573.48,-441.96 966.16,-469.38 1007,-434.12 1043.35,-402.73 996.74,-364.57 1028,-328.12 1048.32,-304.42 1070.65,-324.82 1094,-304.12 1109.53,-290.35 1119.8,-269.14 1126.04,-252.16"/>
|
||||
<polygon fill="black" stroke="black" points="1129.51,-252.83 1129.42,-242.24 1122.89,-250.57 1129.51,-252.83"/>
|
||||
</g>
|
||||
<!-- u5->u9 -->
|
||||
<g id="edge72" class="edge">
|
||||
<title>u5->u9</title>
|
||||
<path fill="none" stroke="black" d="M499.76,-469.32C506.38,-464.93 514.19,-460.58 522,-458.12 571.45,-442.55 947.99,-467.09 988,-434.12 995.12,-428.25 1022.15,-307.3 1034.17,-252.13"/>
|
||||
<polygon fill="black" stroke="black" points="1037.6,-252.85 1036.3,-242.33 1030.76,-251.36 1037.6,-252.85"/>
|
||||
</g>
|
||||
<!-- u5->u3 -->
|
||||
<g id="edge68" class="edge">
|
||||
<title>u5->u3</title>
|
||||
<path fill="none" stroke="black" d="M463.16,-469.78C452.08,-460.93 438.76,-448.34 431,-434.12 422.36,-418.29 403.08,-305.24 394.4,-252.32"/>
|
||||
<polygon fill="black" stroke="black" points="397.82,-251.59 392.76,-242.28 390.91,-252.72 397.82,-251.59"/>
|
||||
</g>
|
||||
<!-- u1 -->
|
||||
<g id="node38" class="node">
|
||||
<title>u1</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="0" cx="546" cy="-570.12" rx="37.09" ry="18"/>
|
||||
<text text-anchor="middle" x="546" y="-566.42" font-family="Times,serif" font-size="14.00">Cabal</text>
|
||||
</g>
|
||||
<!-- u0->u1 -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>u0->u1</title>
|
||||
<path fill="none" stroke="black" d="M579.88,-634.15C574.03,-623.26 566.31,-608.91 559.73,-596.65"/>
|
||||
<polygon fill="black" stroke="black" points="562.78,-594.93 554.96,-587.78 556.61,-598.25 562.78,-594.93"/>
|
||||
</g>
|
||||
<!-- u20 -->
|
||||
<g id="node41" class="node">
|
||||
<title>u20</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="0" cx="713" cy="-570.12" rx="32.49" ry="18"/>
|
||||
<text text-anchor="middle" x="713" y="-566.42" font-family="Times,serif" font-size="14.00">GHC</text>
|
||||
</g>
|
||||
<!-- u0->u20 -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>u0->u20</title>
|
||||
<path fill="none" stroke="black" d="M611.74,-636.44C632.02,-623.36 661.82,-604.14 683.84,-589.93"/>
|
||||
<polygon fill="black" stroke="black" points="685.95,-592.73 692.46,-584.37 682.16,-586.85 685.95,-592.73"/>
|
||||
</g>
|
||||
<!-- u22 -->
|
||||
<g id="node42" class="node">
|
||||
<title>u22</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="0" cx="632" cy="-570.12" rx="30.59" ry="18"/>
|
||||
<text text-anchor="middle" x="632" y="-566.42" font-family="Times,serif" font-size="14.00">HLS</text>
|
||||
</g>
|
||||
<!-- u0->u22 -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>u0->u22</title>
|
||||
<path fill="none" stroke="black" d="M598.12,-634.15C604.01,-623.19 611.79,-608.72 618.41,-596.41"/>
|
||||
<polygon fill="black" stroke="black" points="621.54,-597.98 623.19,-587.51 615.37,-594.66 621.54,-597.98"/>
|
||||
</g>
|
||||
<!-- u23 -->
|
||||
<g id="node43" class="node">
|
||||
<title>u23</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="0" cx="379" cy="-570.12" rx="36.29" ry="18"/>
|
||||
<text text-anchor="middle" x="379" y="-566.42" font-family="Times,serif" font-size="14.00">Stack</text>
|
||||
</g>
|
||||
<!-- u0->u23 -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>u0->u23</title>
|
||||
<path fill="none" stroke="black" d="M557.56,-639.14C519.82,-624.76 456.61,-600.68 416.4,-585.37"/>
|
||||
<polygon fill="black" stroke="black" points="417.55,-582.05 406.96,-581.77 415.05,-588.6 417.55,-582.05"/>
|
||||
</g>
|
||||
<!-- u24 -->
|
||||
<g id="node44" class="node">
|
||||
<title>u24</title>
|
||||
<ellipse fill="#ffffbb" stroke="black" stroke-width="0" cx="462" cy="-570.12" rx="28.7" ry="18"/>
|
||||
<text text-anchor="middle" x="462" y="-566.42" font-family="Times,serif" font-size="14.00">List</text>
|
||||
</g>
|
||||
<!-- u0->u24 -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>u0->u24</title>
|
||||
<path fill="none" stroke="black" d="M566,-636.63C544.67,-623.19 512.88,-603.17 490.06,-588.79"/>
|
||||
<polygon fill="black" stroke="black" points="491.83,-585.77 481.5,-583.4 488.1,-591.69 491.83,-585.77"/>
|
||||
</g>
|
||||
<!-- u0->u25 -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>u0->u25</title>
|
||||
<path fill="none" stroke="black" d="M631.59,-647.2C670.07,-641.23 725,-626.15 754,-588.12 770.36,-566.66 770.97,-534.92 768.67,-512.35"/>
|
||||
<polygon fill="black" stroke="black" points="772.14,-511.88 767.41,-502.4 765.19,-512.76 772.14,-511.88"/>
|
||||
</g>
|
||||
<!-- u1->u19 -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>u1->u19</title>
|
||||
<path fill="none" stroke="black" d="M549.64,-552.12C552.11,-540.62 555.41,-525.19 558.23,-512.03"/>
|
||||
<polygon fill="black" stroke="black" points="561.69,-512.6 560.36,-502.09 554.85,-511.13 561.69,-512.6"/>
|
||||
</g>
|
||||
<!-- u3->u4 -->
|
||||
<g id="edge9" class="edge">
|
||||
<title>u3->u4</title>
|
||||
<path fill="none" stroke="black" d="M428.59,-217.64C541.25,-201.64 869.35,-155.06 991.48,-137.72"/>
|
||||
<polygon fill="black" stroke="black" points="992.21,-141.15 1001.62,-136.28 991.23,-134.22 992.21,-141.15"/>
|
||||
</g>
|
||||
<!-- u18->u3 -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>u18->u3</title>
|
||||
<path fill="none" stroke="black" d="M357.05,-336.12C363.43,-314.6 374.51,-277.29 382.04,-251.92"/>
|
||||
<polygon fill="black" stroke="black" points="385.44,-252.77 384.93,-242.18 378.73,-250.77 385.44,-252.77"/>
|
||||
</g>
|
||||
<!-- u20->u21 -->
|
||||
<g id="edge11" class="edge">
|
||||
<title>u20->u21</title>
|
||||
<path fill="none" stroke="black" d="M697.84,-553.78C668.88,-524.26 607.13,-460.17 591,-434.12 580.88,-417.78 573.03,-397.58 567.76,-381.7"/>
|
||||
<polygon fill="black" stroke="black" points="571.03,-380.44 564.67,-371.97 564.36,-382.56 571.03,-380.44"/>
|
||||
</g>
|
||||
<!-- u20->u19 -->
|
||||
<g id="edge12" class="edge">
|
||||
<title>u20->u19</title>
|
||||
<path fill="none" stroke="black" d="M688.05,-558.16C682.8,-556.02 677.25,-553.9 672,-552.12 641.07,-541.62 628.18,-551.23 601,-533.12 592.16,-527.23 584.54,-518.52 578.55,-510.13"/>
|
||||
<polygon fill="black" stroke="black" points="581.36,-508.04 572.92,-501.64 575.53,-511.91 581.36,-508.04"/>
|
||||
</g>
|
||||
<!-- u22->u19 -->
|
||||
<g id="edge13" class="edge">
|
||||
<title>u22->u19</title>
|
||||
<path fill="none" stroke="black" d="M618.54,-553.85C613.02,-547.51 606.63,-540.02 601,-533.12 594.75,-525.45 588.1,-516.94 582.19,-509.24"/>
|
||||
<polygon fill="black" stroke="black" points="584.97,-507.11 576.12,-501.29 579.4,-511.36 584.97,-507.11"/>
|
||||
</g>
|
||||
<!-- u23->u19 -->
|
||||
<g id="edge14" class="edge">
|
||||
<title>u23->u19</title>
|
||||
<path fill="none" stroke="black" d="M406.36,-557.94C412.12,-555.82 418.22,-553.76 424,-552.12 466.68,-540.01 483.54,-555.23 522,-533.12 532.04,-527.34 540.89,-518.28 547.84,-509.57"/>
|
||||
<polygon fill="black" stroke="black" points="550.72,-511.56 553.9,-501.45 545.11,-507.37 550.72,-511.56"/>
|
||||
</g>
|
||||
<!-- u24->u19 -->
|
||||
<g id="edge15" class="edge">
|
||||
<title>u24->u19</title>
|
||||
<path fill="none" stroke="black" d="M483.62,-558.29C495.54,-551.81 510.26,-542.93 522,-533.12 530.54,-525.98 538.85,-517.05 545.79,-508.83"/>
|
||||
<polygon fill="black" stroke="black" points="548.61,-510.9 552.23,-500.95 543.19,-506.47 548.61,-510.9"/>
|
||||
</g>
|
||||
<!-- u25->u13 -->
|
||||
<g id="edge16" class="edge">
|
||||
<title>u25->u13</title>
|
||||
<path fill="none" stroke="black" d="M743.78,-467.39C732.64,-458.26 718.91,-446.2 708,-434.12 693.03,-417.53 678.51,-396.87 668,-380.84"/>
|
||||
<polygon fill="black" stroke="black" points="670.67,-378.51 662.31,-372 664.78,-382.3 670.67,-378.51"/>
|
||||
</g>
|
||||
<!-- u25->u17 -->
|
||||
<g id="edge17" class="edge">
|
||||
<title>u25->u17</title>
|
||||
<path fill="none" stroke="black" d="M764,-465.85C764,-444.48 764,-407.81 764,-382.56"/>
|
||||
<polygon fill="black" stroke="black" points="767.5,-382.51 764,-372.51 760.5,-382.51 767.5,-382.51"/>
|
||||
</g>
|
||||
<!-- u27->u18 -->
|
||||
<g id="edge18" class="edge">
|
||||
<title>u27->u18</title>
|
||||
<path fill="none" stroke="black" d="M103.85,-715.89C145.57,-655.23 285.85,-451.29 334.9,-379.98"/>
|
||||
<polygon fill="black" stroke="black" points="337.89,-381.8 340.67,-371.58 332.12,-377.84 337.89,-381.8"/>
|
||||
</g>
|
||||
<!-- u29 -->
|
||||
<g id="node47" class="node">
|
||||
<title>u29</title>
|
||||
<ellipse fill="#bbffbb" stroke="black" stroke-width="0" cx="938" cy="-1019.12" rx="34.39" ry="18"/>
|
||||
<text text-anchor="middle" x="938" y="-1015.42" font-family="Times,serif" font-size="14.00">Main</text>
|
||||
</g>
|
||||
<!-- u29->u30 -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>u29->u30</title>
|
||||
<path fill="none" stroke="black" d="M938,-1001.07C938,-981.54 938,-949.28 938,-926.28"/>
|
||||
<polygon fill="black" stroke="black" points="941.5,-926.13 938,-916.13 934.5,-926.13 941.5,-926.13"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 40 KiB |
7
docs/os-freebsd.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
|
||||
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
|
||||
<g><path d="M81.5,647.7C11,409.2,148.6,158.9,388.6,88.9c106.5-31.1,215.5-21.4,309.8,19.8c-4.9,6.9-9.5,14-13.7,21c-46.1-10.7-81.4,3.8-90.2,43.3c-13.9,62.1,42.9,162.8,126.6,224.7c83.7,61.9,162.9,61.7,176.8-0.4c3.5-15.9,2.5-34.4-2.5-54.1c9.7-5.8,19.2-12.3,28.6-19.3c10.9,22.2,20,45.6,27.3,70.1c70.5,238.4-67.1,488.8-307.1,558.8C403.9,1022.8,151.9,886.1,81.5,647.7L81.5,647.7z M667.1,204.7c0.4-0.4,0.7-0.7,1-1.1C776.9,92.3,912.3,26.4,970.4,56.4c58.1,30.1-25.5,176.7-91.7,256.3c-20.1,20.6-41.2,39.7-62.5,56.8C742.2,343.2,686.1,282.8,667.1,204.7L667.1,204.7z M11,108.5C0.7,28.8,68.9,4.9,163.2,55.2c22.4,11.9,44.3,27,64.7,44.1c-56.2,38.6-104.5,90.4-139.5,154C46.4,206.7,16.9,153.5,11,108.5L11,108.5z"/></g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
69
docs/os-linux.svg
Normal file
|
After Width: | Height: | Size: 14 KiB |
143
docs/os-osx.svg
Normal file
@@ -0,0 +1,143 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
version="1.0"
|
||||
width="800"
|
||||
height="950"
|
||||
id="svg2">
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
id="linearGradient3784">
|
||||
<stop
|
||||
id="stop3786"
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3788"
|
||||
style="stop-color:#888888;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3776">
|
||||
<stop
|
||||
id="stop3778"
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3780"
|
||||
style="stop-color:#ffffff;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3754">
|
||||
<stop
|
||||
id="stop3756"
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3758"
|
||||
style="stop-color:#ffffff;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3734">
|
||||
<stop
|
||||
id="stop3736"
|
||||
style="stop-color:#6c6d6f;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3738"
|
||||
style="stop-color:#010101;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="581.96649"
|
||||
y1="409.16061"
|
||||
x2="544.40381"
|
||||
y2="311.21347"
|
||||
id="linearGradient3760"
|
||||
xlink:href="#linearGradient3754"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
x1="591.31964"
|
||||
y1="593.75946"
|
||||
x2="587.03571"
|
||||
y2="434.31064"
|
||||
id="linearGradient3764"
|
||||
xlink:href="#linearGradient3734"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
x1="591.31964"
|
||||
y1="593.75946"
|
||||
x2="587.03571"
|
||||
y2="434.31064"
|
||||
id="linearGradient3773"
|
||||
xlink:href="#linearGradient3734"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-2.7999999e-6,-5.0000001e-6)" />
|
||||
<linearGradient
|
||||
x1="592.88464"
|
||||
y1="409.21036"
|
||||
x2="572.06653"
|
||||
y2="317.52728"
|
||||
id="linearGradient3782"
|
||||
xlink:href="#linearGradient3776"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(4.1074798,0,0,4.1074798,-2012.1445,-1474.6712)" />
|
||||
<linearGradient
|
||||
x1="621.8504"
|
||||
y1="527.79108"
|
||||
x2="575.15466"
|
||||
y2="358.30902"
|
||||
id="linearGradient3790"
|
||||
xlink:href="#linearGradient3784"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
x1="591.31964"
|
||||
y1="593.75946"
|
||||
x2="587.03571"
|
||||
y2="434.31064"
|
||||
id="linearGradient3796"
|
||||
xlink:href="#linearGradient3734"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
x1="591.31964"
|
||||
y1="593.75946"
|
||||
x2="587.03571"
|
||||
y2="434.31064"
|
||||
id="linearGradient3813"
|
||||
xlink:href="#linearGradient3734"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(4.1074798,0,0,4.1074798,-2012.1445,-1474.6712)" />
|
||||
<linearGradient
|
||||
x1="621.8504"
|
||||
y1="527.79108"
|
||||
x2="575.15466"
|
||||
y2="358.30902"
|
||||
id="linearGradient3815"
|
||||
xlink:href="#linearGradient3784"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(4.1074798,0,0,4.1074798,-2012.1445,-1474.6712)" />
|
||||
</defs>
|
||||
<path
|
||||
d="M -1763.2143,1058.9693 L -1763.2143,950.04075 L -1724.2857,1040.5765 L -1685.3571,950.04075 L -1685.3571,1058.9693"
|
||||
id="path3199"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
d="M 9.2490229,7.8722656 C 9.0747426,10.220019 9.5551534,12.587324 10.789328,14.675279 L 283.03823,474.32796 L 15.153526,926.66418 C 13.0537,930.26743 13.090092,934.72063 15.153526,938.34483 C 17.216918,941.9691 20.995183,944.21594 25.165508,944.24933 L 230.41114,944.24933 C 234.53312,944.22267 238.33677,942.02829 240.42312,938.47319 L 399.07452,670.58848 L 557.72593,938.47319 C 559.81228,942.02829 563.61593,944.22267 567.73791,944.24933 L 773.1119,944.24933 C 777.28223,944.21594 781.06049,941.96906 783.12389,938.34483 C 785.18744,934.72067 785.22371,930.26743 783.12389,926.66418 L 515.23918,474.32796 L 787.35972,14.675279 C 788.58462,12.5734 788.96226,10.218047 788.77167,7.8722656 L 559.13787,7.8722656 L 399.07452,278.19578 L 239.01118,7.8722656 L 9.2490229,7.8722656 z"
|
||||
id="path3762"
|
||||
style="fill:url(#linearGradient3815);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
|
||||
<path
|
||||
d="M 20.80131,8.7707768 L 296.51589,474.32796 L 25.165508,932.56868 L 230.41114,932.56868 L 399.07452,647.74063 L 567.73791,932.56868 L 773.1119,932.56868 L 501.76152,474.32796 L 777.34774,8.7707768 L 572.10211,8.7707768 L 399.07452,301.04364 L 226.04694,8.7707768 L 20.80131,8.7707768 z"
|
||||
id="path3705"
|
||||
style="fill:url(#linearGradient3813);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
d="M 20.80131,8.7707768 L 201.9155,314.64967 C 251.61658,285.27827 303.41256,257.12462 357.61466,230.95977 L 226.04694,8.7707768 L 20.80131,8.7707768 z M 572.10211,8.7707768 L 470.05691,181.15657 C 548.90117,149.37671 632.73447,122.22713 722.53856,101.31743 L 777.34774,8.7707768 L 572.10211,8.7707768 z"
|
||||
id="path3771"
|
||||
style="opacity:0.47619048;fill:url(#linearGradient3782);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.0 KiB |
18
docs/os-windows.svg
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) by Marsupilami -->
|
||||
<svg
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
version="1.1"
|
||||
width="766"
|
||||
height="768"
|
||||
viewBox="-2.61977004 -2.61977004 92.56520808 92.83416708"
|
||||
id="svg8375">
|
||||
<defs
|
||||
id="defs8377" />
|
||||
<path
|
||||
d="M 0,12.40183 35.68737,7.5416 35.70297,41.96435 0.03321,42.16748 z m 35.67037,33.52906 0.0277,34.45332 -35.66989,-4.9041 -0.002,-29.77972 z M 39.99644,6.90595 87.31462,0 l 0,41.527 -47.31818,0.37565 z M 87.32567,46.25471 87.31457,87.59463 39.9964,80.91625 39.9301,46.17767 z"
|
||||
id="path13" />
|
||||
</svg>
|
||||
<!-- version: 20110311, original size: 87.325668 87.594627, border: 3% -->
|
||||
|
After Width: | Height: | Size: 861 B |
201
docs/overrides/base.html
Normal file
@@ -0,0 +1,201 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ config.theme.locale|default('en') }}">
|
||||
<head>
|
||||
{%- block site_meta %}
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
{% if page and page.is_homepage %}<meta name="description" content="{{ config['site_description'] }}">{% endif %}
|
||||
{% if config.site_author %}<meta name="author" content="{{ config.site_author }}">{% endif %}
|
||||
{% if page and page.canonical_url %}<link rel="canonical" href="{{ page.canonical_url }}">{% endif %}
|
||||
{% if config.site_favicon %}<link rel="shortcut icon" href="{{ config.site_favicon|url }}">
|
||||
{% else %}<link rel="shortcut icon" href="{{ 'img/favicon.ico'|url }}">{% endif %}
|
||||
{%- endblock %}
|
||||
|
||||
{%- block htmltitle %}
|
||||
<title>{% if page and page.title and not page.is_homepage %}{{ page.title }} - {% endif %}{{ config.site_name }}</title>
|
||||
{%- endblock %}
|
||||
|
||||
{%- block styles %}
|
||||
<link href="{{ 'css/bootstrap.min.css'|url }}" rel="stylesheet">
|
||||
<link href="{{ 'css/font-awesome.min.css'|url }}" rel="stylesheet">
|
||||
<link href="{{ 'css/base.css'|url }}" rel="stylesheet">
|
||||
{%- if config.theme.highlightjs %}
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/styles/{{ config.theme.hljs_style }}.min.css">
|
||||
{%- endif %}
|
||||
{%- for path in extra_css %}
|
||||
<link href="{{ path }}" rel="stylesheet">
|
||||
{%- endfor %}
|
||||
{%- endblock %}
|
||||
|
||||
{%- block libs %}
|
||||
|
||||
<script src="{{ 'js/jquery-1.10.2.min.js'|url }}" defer></script>
|
||||
<script src="{{ 'js/bootstrap.min.js'|url }}" defer></script>
|
||||
{%- if config.theme.highlightjs %}
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/highlight.min.js"></script>
|
||||
{%- for lang in config.theme.hljs_languages %}
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/languages/{{lang}}.min.js"></script>
|
||||
{%- endfor %}
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
{%- endif %}
|
||||
{%- endblock %}
|
||||
|
||||
{%- block analytics %}
|
||||
{%- if config.theme.analytics.gtag %}
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id={{ config.theme.analytics.gtag }}"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', '{{ config.theme.analytics.gtag }}');
|
||||
</script>
|
||||
{%- elif config.google_analytics %}
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', '{{ config.google_analytics[0] }}', '{{ config.google_analytics[1] }}');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
{%- endif %}
|
||||
{%- endblock %}
|
||||
|
||||
{%- block extrahead %} {% endblock %}
|
||||
</head>
|
||||
|
||||
<body{% if page and page.is_homepage %} class="homepage"{% endif %}>
|
||||
<div class="navbar fixed-top navbar-expand-lg navbar-{% if config.theme.nav_style == "light" %}light{% else %}dark{% endif %} bg-{{ config.theme.nav_style }}">
|
||||
<div class="container">
|
||||
|
||||
{%- block site_name %}
|
||||
<a class="navbar-brand" href="{{ nav.homepage.url|url }}">{{ config.site_name }}</a>
|
||||
{%- endblock %}
|
||||
|
||||
{%- if nav|length>1 or (page and (page.next_page or page.previous_page)) or config.repo_url %}
|
||||
<!-- Expander button -->
|
||||
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar-collapse">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
{%- endif %}
|
||||
|
||||
<!-- Expanded navigation -->
|
||||
<div id="navbar-collapse" class="navbar-collapse collapse">
|
||||
{%- block site_nav %}
|
||||
{%- if nav|length>1 %}
|
||||
<!-- Main navigation -->
|
||||
<ul class="nav navbar-nav">
|
||||
{%- for nav_item in nav %}
|
||||
{%- if nav_item.children %}
|
||||
<li class="dropdown{% if nav_item.active %} active{% endif %}">
|
||||
<a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">{{ nav_item.title }} <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
{%- for nav_item in nav_item.children %}
|
||||
{% include "nav-sub.html" %}
|
||||
{%- endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
{%- else %}
|
||||
<li class="navitem{% if nav_item.active %} active{% endif %}">
|
||||
<a href="{{ nav_item.url|url }}" class="nav-link">{{ nav_item.title }}</a>
|
||||
</li>
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
</ul>
|
||||
{%- endif %}
|
||||
{%- endblock %}
|
||||
|
||||
<ul class="nav navbar-nav ml-auto">
|
||||
{%- block search_button %}
|
||||
{%- if 'search' in config['plugins'] %}
|
||||
<li class="nav-item">
|
||||
<a href="#" class="nav-link" data-toggle="modal" data-target="#mkdocs_search_modal">
|
||||
<i class="fa fa-search"></i> {% trans %}Search{% endtrans %}
|
||||
</a>
|
||||
</li>
|
||||
{%- endif %}
|
||||
{%- endblock %}
|
||||
|
||||
{%- block next_prev %}
|
||||
{%- endblock %}
|
||||
|
||||
{%- block repo %}
|
||||
{%- if page and page.edit_url %}
|
||||
<li class="nav-item">
|
||||
<a href="{{ page.edit_url }}" class="nav-link">
|
||||
{%- if config.repo_name == 'GitHub' -%}
|
||||
<i class="fa fa-github"></i> {% trans repo_name=config.repo_name %}Edit on {{ repo_name }}{% endtrans %}
|
||||
{%- elif config.repo_name == 'Bitbucket' -%}
|
||||
<i class="fa fa-bitbucket"></i> {% trans repo_name=config.repo_name %}Edit on {{ repo_name }}{% endtrans %}
|
||||
{%- elif config.repo_name == 'GitLab' -%}
|
||||
<i class="fa fa-gitlab"></i> {% trans repo_name=config.repo_name %}Edit on {{ repo_name }}{% endtrans %}
|
||||
{%- else -%}
|
||||
{% trans repo_name=config.repo_name%}Edit on {{ repo_name }}{% endtrans %}
|
||||
{%- endif -%}
|
||||
</a>
|
||||
</li>
|
||||
{%- elif config.repo_url %}
|
||||
<li class="nav-item">
|
||||
<a href="{{ config.repo_url }}" class="nav-link">
|
||||
{%- if config.repo_name == 'GitHub' -%}
|
||||
<i class="fa fa-github"></i> {{ config.repo_name }}
|
||||
{%- elif config.repo_name == 'Bitbucket' -%}
|
||||
<i class="fa fa-bitbucket"></i> {{ config.repo_name }}
|
||||
{%- elif config.repo_name == 'GitLab' -%}
|
||||
<i class="fa fa-gitlab"></i> {{ config.repo_name }}
|
||||
{%- else -%}
|
||||
{{ config.repo_name }}
|
||||
{%- endif -%}
|
||||
</a>
|
||||
</li>
|
||||
{%- endif %}
|
||||
{%- endblock %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
{%- block content %}
|
||||
<div class="col-md-3">{% include "toc.html" %}</div>
|
||||
<div class="col-md-9" role="main">{% include "content.html" %}</div>
|
||||
{%- endblock %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="col-md-12">
|
||||
{%- block footer %}
|
||||
<hr>
|
||||
{%- if config.copyright %}
|
||||
<p>{{ config.copyright }}</p>
|
||||
{%- endif %}
|
||||
<p>{% trans mkdocs_link='<a href="https://www.mkdocs.org/">MkDocs</a>' %}Documentation built with {{ mkdocs_link }}.{% endtrans %}</p>
|
||||
{%- endblock %}
|
||||
</footer>
|
||||
|
||||
{%- block scripts %}
|
||||
<script>
|
||||
var base_url = {{ base_url | tojson }},
|
||||
shortcuts = {{ config.theme.shortcuts | tojson }};
|
||||
</script>
|
||||
<script src="{{ 'js/base.js'|url }}" defer></script>
|
||||
{%- for path in extra_javascript %}
|
||||
<script src="{{ path }}" defer></script>
|
||||
{%- endfor %}
|
||||
{%- endblock %}
|
||||
|
||||
{% if 'search' in config['plugins'] %}{%- include "search-modal.html" %}{% endif %}
|
||||
{%- include "keyboard-modal.html" %}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
{% if page and page.is_homepage %}
|
||||
<!--
|
||||
MkDocs version : {{ mkdocs_version }}
|
||||
Build Date UTC : {{ build_date_utc }}
|
||||
-->
|
||||
{% endif %}
|
||||