Compare commits
934 Commits
merge-requ
...
check-msys
| Author | SHA1 | Date | |
|---|---|---|---|
| 699b183f62 | |||
| e67a9c93fe | |||
| 06eae56646 | |||
| bdbbeb1040 | |||
| 1eed02c8c7 | |||
| 6d325a1804 | |||
| a05f272b58 | |||
| 07dfb1e94b | |||
| 6ff07d3dbc | |||
| 0da5572164 | |||
| 422b99a222 | |||
| 055df584a4 | |||
| 9798e0f1d2 | |||
| a43fa7d63e | |||
| 4361ef7a72 | |||
|
|
3218aaa378 | ||
| 186a37cf3e | |||
|
|
7b1f591cc4 | ||
| 0ecd244177 | |||
| e14600ae75 | |||
| 0884756139 | |||
| 4c539d62c1 | |||
| f5b58d1db7 | |||
| 18f6a74d08 | |||
| becb3436d0 | |||
| 1f220cd488 | |||
| 572ee06bbb | |||
| 6e1380ef2e | |||
| 3e83a7fd83 | |||
| 34ac9cec4d | |||
| 513f7446b3 | |||
| aed478153d | |||
| 210816769a | |||
| 42bf21c86e | |||
| 4b34cddcda | |||
| 1ba2361fea | |||
| 278a3005d1 | |||
|
|
78d68e381a | ||
| 17ffc459db | |||
| afcb482866 | |||
|
c28de19faa
|
|||
|
7ae952c82e
|
|||
|
|
98098035c9 | ||
|
acdc0786ba
|
|||
|
7fa72a8892
|
|||
|
fa22920e51
|
|||
|
f084fbce43
|
|||
|
|
1850c00e9d | ||
|
c20deceaa8
|
|||
|
89e4145baf
|
|||
|
|
f5f7c26d8a | ||
|
784942ca58
|
|||
|
75de2a7bc1
|
|||
|
ea6c8d338c
|
|||
|
ae625b181c
|
|||
|
89ae54a083
|
|||
|
1bd73591ba
|
|||
|
f709f6e714
|
|||
|
3d7e07c371
|
|||
|
8bf17379ac
|
|||
|
4b1225ad71
|
|||
|
d628848af6
|
|||
|
48381be001
|
|||
|
b547324253
|
|||
|
2b1599c234
|
|||
|
7ac8989dfc
|
|||
|
cd6666ed30
|
|||
|
5b7478438a
|
|||
|
4a830d9fb7
|
|||
|
785fb895b4
|
|||
|
75e801e9e6
|
|||
|
6ffd5328a4
|
|||
|
ed509e482b
|
|||
|
420323f43b
|
|||
|
432962792c
|
|||
|
cb193f6069
|
|||
|
2f268b6a25
|
|||
|
580606af14
|
|||
|
faa1c3992b
|
|||
|
d17efef853
|
|||
|
179d4dd493
|
|||
|
e03c5ee4a1
|
|||
|
e57a8abd3d
|
|||
|
5fa10390a3
|
|||
|
e1e6f579d5
|
|||
|
72f8e53344
|
|||
|
9c464ec9fc
|
|||
|
1c9b296a5e
|
|||
|
|
275522584e | ||
|
|
804520c4bb | ||
|
|
9d25581f3c | ||
|
|
e798037d80 | ||
|
|
2afe5858cb | ||
|
f575dcdad6
|
|||
|
6cf9967e7c
|
|||
|
15a75d790a
|
|||
|
988672ea75
|
|||
|
6d3e8d65e1
|
|||
|
895e4b3f18
|
|||
|
20f0505120
|
|||
|
31e83cac5e
|
|||
|
|
9baba88f75 | ||
|
d3a1115b99
|
|||
|
6d46849fec
|
|||
|
53e324bfee
|
|||
|
2e39b7b603
|
|||
|
048932bf50
|
|||
|
69d325bf90
|
|||
|
3d1b8859cd
|
|||
|
db89ca9942
|
|||
|
bba009d98c
|
|||
|
9d954ea174
|
|||
|
da9c9049d2
|
|||
|
a4c00d2c56
|
|||
|
|
b30f565871 | ||
|
|
fa378a1d34 | ||
|
|
119efb1ff4 | ||
|
1fb4101b49
|
|||
|
ec8333b223
|
|||
|
54b979aa0b
|
|||
|
ba274307c0
|
|||
|
|
a623d0809d | ||
|
e00899d176
|
|||
|
a38ca1954b
|
|||
|
3f5a19c63e
|
|||
|
525e9672e8
|
|||
|
070c6e1cf1
|
|||
|
195fd00e0a
|
|||
|
733d014c19
|
|||
|
16039769d5
|
|||
|
5eeb8ca9fc
|
|||
|
317a06bbc3
|
|||
|
f693adcd7c
|
|||
|
ac88d2bd50
|
|||
|
a427146de5
|
|||
|
a16bcddeaa
|
|||
|
74edf1fc07
|
|||
|
1e32639873
|
|||
|
0704d2640a
|
|||
|
26a6368d79
|
|||
|
54af66d115
|
|||
|
850799c21a
|
|||
| d4834d7541 | |||
|
2895dd9d13
|
|||
|
eb9a0b66c4
|
|||
|
8d0432b961
|
|||
|
ab2c01d1c9
|
|||
|
fffaa65b7f
|
|||
|
703be0a706
|
|||
|
4be97ffd7c
|
|||
|
009f9211a9
|
|||
|
109187eb6f
|
|||
|
e881705323
|
|||
|
ea06c155a7
|
|||
|
d4732e15a7
|
|||
|
db6f784a1f
|
|||
|
82e3837dd9
|
|||
|
957c5918b8
|
|||
|
9d4c923649
|
|||
|
24c36ef856
|
|||
|
2783b8f693
|
|||
|
d5a680e3c6
|
|||
|
d1075987de
|
|||
|
e116a2392e
|
|||
|
7dd6f1f4a4
|
|||
|
4d82c37539
|
|||
|
801b1edfa7
|
|||
|
c1b67e1787
|
|||
|
70dd106549
|
|||
|
b098aa4e65
|
|||
|
74b784fcfb
|
|||
|
673db344d6
|
|||
|
5594a19c02
|
|||
|
|
a5bc13fe50 | ||
|
a5f2067d76
|
|||
|
be8fa57be1
|
|||
|
6ad9963889
|
|||
|
bcddb05b1d
|
|||
|
f7d2033e25
|
|||
|
6ce7649cfe
|
|||
|
cb0d8b80c3
|
|||
|
95869f9560
|
|||
|
e8586cf993
|
|||
|
d195a3f86c
|
|||
|
b171afa09d
|
|||
|
5cf49bffac
|
|||
|
5659de8516
|
|||
|
0cd2b6d549
|
|||
|
ae092de4b6
|
|||
|
a7e6e7c27d
|
|||
|
175a301a0d
|
|||
|
823458910b
|
|||
|
2abcb46199
|
|||
|
75b891147a
|
|||
|
de208f004e
|
|||
|
ecb0676fea
|
|||
|
957867ff1c
|
|||
|
b1b21f000d
|
|||
|
fbbafc33be
|
|||
|
4a46de4c49
|
|||
|
77419ea41d
|
|||
|
043500e8e8
|
|||
|
e924ad8278
|
|||
|
010db93b93
|
|||
|
9fdc6eebe8
|
|||
|
7c8d013b6e
|
|||
|
96eb0c3532
|
|||
|
94c01ee362
|
|||
|
4297a46f13
|
|||
|
c07e1bbc8f
|
|||
|
9ee2df3841
|
|||
|
3c5505d222
|
|||
|
|
70df740f9d | ||
|
|
761f3253c3 | ||
|
787edc17af
|
|||
|
9902adab6d
|
|||
|
156b4724f3
|
|||
|
e9575aba5c
|
|||
|
81c7f6a32a
|
|||
|
|
ab97c80b80 | ||
|
|
04369673ef | ||
|
|
63dfdc2da6 | ||
|
14de382129
|
|||
|
d97c10dbe6
|
|||
|
|
8420bf093e | ||
|
|
5e28074522 | ||
|
c842c41a78
|
|||
|
8b93eaad59
|
|||
|
2cba97cf1c
|
|||
|
7d74178295
|
|||
|
c37bef55e9
|
|||
|
837ba8b46a
|
|||
|
|
c25e73408a | ||
|
|
71c3172cf5 | ||
|
|
1f2855a107 | ||
|
|
d949c4375e | ||
|
|
22f0081303 | ||
|
5562be18e3
|
|||
|
6baa891424
|
|||
|
a544feffb3
|
|||
|
3b6bb0df46
|
|||
|
60299b6bb8
|
|||
|
4d20f4e07c
|
|||
|
5f6b5f845d
|
|||
|
b0fecce0d1
|
|||
|
|
27c06ddde7 | ||
|
3154d2839b
|
|||
|
|
511d8d5ed8 | ||
|
fe22405ee1
|
|||
|
ea828cd13a
|
|||
|
00fa70b9de
|
|||
|
823275363c
|
|||
|
2f299ee48d
|
|||
|
284fe1b3b6
|
|||
|
35bda8d67a
|
|||
|
7a2a5074fa
|
|||
|
ce239ab88e
|
|||
|
f3c703d655
|
|||
|
b6ff5bc764
|
|||
|
b8aeb1f935
|
|||
|
9673d28d3e
|
|||
|
99a51d67a1
|
|||
|
b0ef0590a2
|
|||
|
256e1942f2
|
|||
|
aa71f0dfa1
|
|||
|
04d527c98a
|
|||
|
|
ca5c5550ab | ||
|
7b59621179
|
|||
|
9d59463ded
|
|||
|
|
3d49f79beb | ||
|
|
e9740d13fc | ||
|
|
2bd5a8fe1a | ||
|
|
0acccae523 | ||
|
974112016e
|
|||
|
9fb2889696
|
|||
|
63f22b28d7
|
|||
|
9a72fa13d5
|
|||
|
86a8a32032
|
|||
|
13e01ab453
|
|||
|
873dd77a6f
|
|||
|
544c618473
|
|||
|
a264cb088e
|
|||
|
1a43fddca9
|
|||
|
|
9ceb66ef21 | ||
|
|
7cbe38b011 | ||
|
|
3bbc1edb19 | ||
|
|
b8dac2d7cd | ||
|
bdfb1a3a9b
|
|||
|
9b8b3e8126
|
|||
|
d657c17df4
|
|||
|
|
0e1fd68d93 | ||
|
|
c7eceb2330 | ||
|
|
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 | ||
|
|
03d77f5006 | ||
|
|
71e6dbfdca | ||
|
|
692cd1616b | ||
|
|
4e3dbea5d0 | ||
|
|
fd2add78bd | ||
|
|
e9da8ab439 | ||
|
|
9c22ba9d45 | ||
|
|
e5d3080b54 | ||
|
|
5995a8b592 | ||
|
|
bc6d006c57 | ||
|
|
b148d8e2e7 | ||
|
|
4f7d41a8cc | ||
|
|
5efe2e5f7a | ||
|
|
338f5f309d | ||
|
|
ba51cbad6f | ||
|
|
511272e86d | ||
|
|
873f75da9f | ||
|
|
42d4a66493 | ||
|
|
9a79af6fd2 | ||
|
|
63f10a1871 | ||
|
|
9686ee9826 | ||
|
|
4729364e99 | ||
|
|
91d982c7b2 | ||
|
|
8b7c22440e | ||
|
|
9b3d55a095 | ||
|
|
e2daf5381c |
28
.cirrus.yml
Normal file
28
.cirrus.yml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
freebsd_instance:
|
||||||
|
image_family: freebsd-13-2
|
||||||
|
|
||||||
|
build_task:
|
||||||
|
name: build
|
||||||
|
env:
|
||||||
|
GHC_VER: 9.2.4
|
||||||
|
CABAL_VER: 3.8.1.0
|
||||||
|
ARTIFACT: "x86_64-portbld-freebsd-ghcup"
|
||||||
|
ARCH: 64
|
||||||
|
RUNNER_OS: FreeBSD
|
||||||
|
DISTRO: na
|
||||||
|
GITHUB_WORKSPACE: ${CIRRUS_WORKING_DIR}
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
CIRRUS_CLONE_SUBMODULES: true
|
||||||
|
AWS_ACCESS_KEY_ID: ENCRYPTED[6ed6287e2dd78ab5f84b22232c5245834ab042bd8ba443883aaf4b4d1ecc0481add1fdfad5ae6f6a8cfb418e6f19b2fc]
|
||||||
|
AWS_SECRET_ACCESS_KEY: ENCRYPTED[16f3cda2954c7cee99444e6788eb5997382aa4ce1477e7523fef2586077541f43b5c816156961fc6b4677259679875a7]
|
||||||
|
S3_HOST: ENCRYPTED[ce961780a33159f7d1d8046956b5ac6ebc3bfc8149428e5f538576cda51d9f3d0c35b79cdd1e325793639ff6e31f889d]
|
||||||
|
install_script:
|
||||||
|
- sed -i.bak -e 's/quarterly/latest/' /etc/pkg/FreeBSD.conf
|
||||||
|
- pkg install -y ghc hs-cabal-install git bash misc/compat10x misc/compat11x misc/compat12x gmake llvm14
|
||||||
|
script:
|
||||||
|
- tzsetup Etc/GMT
|
||||||
|
- adjkerntz -a
|
||||||
|
- bash .github/scripts/build.sh
|
||||||
|
- bash .github/scripts/test.sh
|
||||||
|
binaries_artifacts:
|
||||||
|
path: "out/*"
|
||||||
4946
.github/ghc-8.10.3-linux.alpine.files
vendored
Normal file
4946
.github/ghc-8.10.3-linux.alpine.files
vendored
Normal file
File diff suppressed because it is too large
Load Diff
8734
.github/ghc-8.10.3-linux.files
vendored
Normal file
8734
.github/ghc-8.10.3-linux.files
vendored
Normal file
File diff suppressed because it is too large
Load Diff
10321
.github/ghc-8.10.3-windows.files
vendored
Normal file
10321
.github/ghc-8.10.3-windows.files
vendored
Normal file
File diff suppressed because it is too large
Load Diff
37
.github/ghcup-run.files
vendored
Normal file
37
.github/ghcup-run.files
vendored
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
|
||||||
31
.github/ghcup-run.files.alpine
vendored
Normal file
31
.github/ghcup-run.files.alpine
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
.
|
||||||
|
./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.7
|
||||||
|
./haskell-language-server-8.10.7~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.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
.github/ghcup-run.files.windows
vendored
Normal file
81
.github/ghcup-run.files.windows
vendored
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
|
||||||
18
.github/scripts/bootstrap.sh
vendored
Normal file
18
.github/scripts/bootstrap.sh
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
. .github/scripts/env.sh
|
||||||
|
|
||||||
|
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
||||||
|
|
||||||
|
git describe --always
|
||||||
|
|
||||||
|
### build
|
||||||
|
|
||||||
|
./scripts/bootstrap/bootstrap-haskell
|
||||||
|
|
||||||
|
[ "$(ghc --numeric-version)" = "${BOOTSTRAP_HASKELL_GHC_VERSION}" ]
|
||||||
|
# https://github.com/actions/runner-images/issues/7061
|
||||||
|
[ "$(ghcup config | grep --color=never meta-mode)" = "meta-mode: Lax" ]
|
||||||
|
|
||||||
27
.github/scripts/brew.sh
vendored
Normal file
27
.github/scripts/brew.sh
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
. .github/scripts/env.sh
|
||||||
|
|
||||||
|
if [ -e "$HOME/.brew" ] ; then
|
||||||
|
(
|
||||||
|
cd "$HOME/.brew"
|
||||||
|
git fetch --depth 1
|
||||||
|
git reset --hard origin/master
|
||||||
|
)
|
||||||
|
else
|
||||||
|
git clone --depth=1 https://github.com/Homebrew/brew "$HOME/.brew"
|
||||||
|
fi
|
||||||
|
export PATH="$HOME/.brew/bin:$HOME/.brew/sbin:$PATH"
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
brew update
|
||||||
|
brew install ${1+"$@"}
|
||||||
|
|
||||||
35
.github/scripts/build.sh
vendored
Normal file
35
.github/scripts/build.sh
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
. .github/scripts/common.sh
|
||||||
|
|
||||||
|
git_describe
|
||||||
|
|
||||||
|
# ensure ghcup
|
||||||
|
install_ghcup
|
||||||
|
|
||||||
|
# ensure cabal-cache
|
||||||
|
download_cabal_cache "$HOME/.local/bin/cabal-cache"
|
||||||
|
|
||||||
|
# install toolchain (if necessary)
|
||||||
|
ghcup -v install ghc --set --force "$GHC_VER"
|
||||||
|
ghcup -v install cabal --force "$CABAL_VER"
|
||||||
|
ghc --version
|
||||||
|
cabal --version
|
||||||
|
GHC="ghc-${GHC_VER}"
|
||||||
|
|
||||||
|
# build
|
||||||
|
ecabal update
|
||||||
|
build_with_cache --project-file=cabal.project.release -w "${GHC}" --enable-tests
|
||||||
|
|
||||||
|
# set up artifacts
|
||||||
|
mkdir -p out
|
||||||
|
binary=$(cabal --project-file=cabal.project.release list-bin ghcup)
|
||||||
|
binary_test=$(cabal --project-file=cabal.project.release list-bin ghcup-test)
|
||||||
|
ver=$("${binary}" --numeric-version)
|
||||||
|
strip_binary "${binary}"
|
||||||
|
cp "${binary}" "out/${ARTIFACT}-${ver}${ext}"
|
||||||
|
cp "${binary_test}" "out/test-${ARTIFACT}-${ver}${ext}"
|
||||||
|
cp ./dist-newstyle/cache/plan.json "out/${ARTIFACT}.plan.json"
|
||||||
|
|
||||||
13
.github/scripts/cabal-cache.sh
vendored
Normal file
13
.github/scripts/cabal-cache.sh
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
case "$(uname -s)" in
|
||||||
|
MSYS_*|MINGW*)
|
||||||
|
ext=".exe"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
ext=""
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "cabal-cache disabled (CABAL_CACHE_DISABLE set)"
|
||||||
|
|
||||||
174
.github/scripts/common.sh
vendored
Normal file
174
.github/scripts/common.sh
vendored
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
. .github/scripts/env.sh
|
||||||
|
|
||||||
|
ecabal() {
|
||||||
|
cabal "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
nonfatal() {
|
||||||
|
"$@" || "$* failed"
|
||||||
|
}
|
||||||
|
|
||||||
|
sync_from() {
|
||||||
|
if [ "${RUNNER_OS}" != "Windows" ] ; then
|
||||||
|
cabal_store_path="$(dirname "$(cabal help user-config | tail -n 1 | xargs)")/store"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cabal-cache.sh sync-from-archive \
|
||||||
|
--host-name-override=${S3_HOST} \
|
||||||
|
--host-port-override=443 \
|
||||||
|
--host-ssl-override=True \
|
||||||
|
--region us-west-2 \
|
||||||
|
$([ "${RUNNER_OS}" != "Windows" ] && echo --store-path="$cabal_store_path") \
|
||||||
|
--archive-uri "s3://ghcup-hs/${RUNNER_OS}-${ARCH}-${DISTRO}"
|
||||||
|
}
|
||||||
|
|
||||||
|
sync_to() {
|
||||||
|
if [ "${RUNNER_OS}" != "Windows" ] ; then
|
||||||
|
cabal_store_path="$(dirname "$(cabal help user-config | tail -n 1 | xargs)")/store"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cabal-cache.sh sync-to-archive \
|
||||||
|
--host-name-override=${S3_HOST} \
|
||||||
|
--host-port-override=443 \
|
||||||
|
--host-ssl-override=True \
|
||||||
|
--region us-west-2 \
|
||||||
|
$([ "${RUNNER_OS}" != "Windows" ] && echo --store-path="$cabal_store_path") \
|
||||||
|
--archive-uri "s3://ghcup-hs/${RUNNER_OS}-${ARCH}-${DISTRO}"
|
||||||
|
}
|
||||||
|
|
||||||
|
raw_eghcup() {
|
||||||
|
"$GHCUP_BIN/ghcup${ext}" -v -c "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
eghcup() {
|
||||||
|
if [ "${OS}" = "Windows" ] ; then
|
||||||
|
"$GHCUP_BIN/ghcup${ext}" -c -s "file:/$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml" "$@"
|
||||||
|
else
|
||||||
|
"$GHCUP_BIN/ghcup${ext}" -c -s "file://$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml" "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
sha_sum() {
|
||||||
|
if [ "${OS}" = "FreeBSD" ] ; then
|
||||||
|
sha256 "$@"
|
||||||
|
else
|
||||||
|
sha256sum "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
git_describe() {
|
||||||
|
git config --global --get-all safe.directory | grep '^\*$' || git config --global --add safe.directory "*"
|
||||||
|
git describe --always
|
||||||
|
}
|
||||||
|
|
||||||
|
download_cabal_cache() {
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
mkdir -p "$HOME/.local/bin"
|
||||||
|
dest="$HOME/.local/bin/cabal-cache"
|
||||||
|
url=""
|
||||||
|
exe=""
|
||||||
|
cd /tmp
|
||||||
|
case "${RUNNER_OS}" in
|
||||||
|
"Linux")
|
||||||
|
case "${ARCH}" in
|
||||||
|
"32") url=https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal-cache/experimental5/i386-linux-cabal-cache
|
||||||
|
;;
|
||||||
|
"64") url=https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal-cache/experimental5/x86_64-linux-cabal-cache
|
||||||
|
;;
|
||||||
|
"ARM64") url=https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal-cache/experimental5/aarch64-linux-cabal-cache
|
||||||
|
;;
|
||||||
|
"ARM") url=https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal-cache/experimental5/armv7-linux-cabal-cache
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
"FreeBSD")
|
||||||
|
url=https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal-cache/experimental5/x86_64-portbld-freebsd-cabal-cache
|
||||||
|
;;
|
||||||
|
"Windows")
|
||||||
|
exe=".exe"
|
||||||
|
url=https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal-cache/experimental5/x86_64-mingw64-cabal-cache
|
||||||
|
;;
|
||||||
|
"macOS")
|
||||||
|
case "${ARCH}" in
|
||||||
|
"ARM64") url=https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal-cache/experimental5/aarch64-apple-darwin-cabal-cache
|
||||||
|
;;
|
||||||
|
"64") url=https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal-cache/experimental5/x86_64-apple-darwin-cabal-cache
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -n "${url}" ] ; then
|
||||||
|
case "${url##*.}" in
|
||||||
|
"gz")
|
||||||
|
curl -L -o - "${url}" | gunzip > cabal-cache${exe}
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
curl -o cabal-cache${exe} -L "${url}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
sha_sum cabal-cache${exe}
|
||||||
|
mv "cabal-cache${exe}" "${dest}${exe}"
|
||||||
|
chmod +x "${dest}${exe}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# install shell wrapper
|
||||||
|
cp "${CI_PROJECT_DIR}"/.github/scripts/cabal-cache.sh "$HOME"/.local/bin/
|
||||||
|
chmod +x "$HOME"/.local/bin/cabal-cache.sh
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
build_with_cache() {
|
||||||
|
ecabal configure "$@"
|
||||||
|
ecabal build --dependencies-only "$@" --dry-run
|
||||||
|
sync_from
|
||||||
|
ecabal build --dependencies-only "$@" || sync_to
|
||||||
|
sync_to
|
||||||
|
ecabal build "$@"
|
||||||
|
sync_to
|
||||||
|
}
|
||||||
|
|
||||||
|
install_ghcup() {
|
||||||
|
case "${RUNNER_OS}" in
|
||||||
|
"Linux")
|
||||||
|
case "${ARCH}" in
|
||||||
|
"ARM"*)
|
||||||
|
if command -v ghcup ; then
|
||||||
|
mkdir -p "$GHCUP_BIN"
|
||||||
|
cp "$(command -v ghcup)" "$GHCUP_BIN/ghcup${ext}"
|
||||||
|
else
|
||||||
|
install_ghcup_curl_sh
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*) install_ghcup_curl_sh
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
*) install_ghcup_curl_sh
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
install_ghcup_curl_sh() {
|
||||||
|
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 BOOTSTRAP_HASKELL_MINIMAL=1 BOOTSTRAP_HASKELL_INSTALL_NO_STACK=yes sh
|
||||||
|
}
|
||||||
|
|
||||||
|
strip_binary() {
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
local binary=$1
|
||||||
|
case "$(uname -s)" in
|
||||||
|
"Darwin"|"darwin")
|
||||||
|
;;
|
||||||
|
MSYS_*|MINGW*)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
strip -s "${binary}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
)
|
||||||
|
}
|
||||||
30
.github/scripts/env.sh
vendored
Normal file
30
.github/scripts/env.sh
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
if [ "${RUNNER_OS}" = "Windows" ] ; then
|
||||||
|
ext=".exe"
|
||||||
|
else
|
||||||
|
ext=''
|
||||||
|
fi
|
||||||
|
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
export TZ=Asia/Singapore
|
||||||
|
|
||||||
|
export OS="$RUNNER_OS"
|
||||||
|
export PATH="$HOME/.local/bin:$PATH"
|
||||||
|
|
||||||
|
if [ "${RUNNER_OS}" = "Windows" ] ; then
|
||||||
|
# on windows use pwd to get unix style path
|
||||||
|
CI_PROJECT_DIR="$(pwd)"
|
||||||
|
export CI_PROJECT_DIR
|
||||||
|
export GHCUP_INSTALL_BASE_PREFIX="/c"
|
||||||
|
export GHCUP_BIN="$GHCUP_INSTALL_BASE_PREFIX/ghcup/bin"
|
||||||
|
export PATH="$GHCUP_BIN:$PATH"
|
||||||
|
export CABAL_DIR="C:\\Users\\runneradmin\\AppData\\Roaming\\cabal"
|
||||||
|
else
|
||||||
|
export CI_PROJECT_DIR="${GITHUB_WORKSPACE}"
|
||||||
|
export GHCUP_INSTALL_BASE_PREFIX="$CI_PROJECT_DIR"
|
||||||
|
export GHCUP_BIN="$GHCUP_INSTALL_BASE_PREFIX/.ghcup/bin"
|
||||||
|
export PATH="$GHCUP_BIN:$PATH"
|
||||||
|
export CABAL_DIR="$CI_PROJECT_DIR/cabal"
|
||||||
|
export CABAL_CACHE="$CI_PROJECT_DIR/cabal-cache"
|
||||||
|
fi
|
||||||
72
.github/scripts/hls.sh
vendored
Normal file
72
.github/scripts/hls.sh
vendored
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
. .github/scripts/common.sh
|
||||||
|
|
||||||
|
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
||||||
|
|
||||||
|
### build
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if [ "${OS}" = "Windows" ] ; then
|
||||||
|
GHCUP_DIR="${GHCUP_INSTALL_BASE_PREFIX}"/ghcup
|
||||||
|
else
|
||||||
|
GHCUP_DIR="${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf "${GHCUP_DIR}"
|
||||||
|
mkdir -p "${GHCUP_BIN}"
|
||||||
|
|
||||||
|
ls -lah out
|
||||||
|
find out
|
||||||
|
cp "out/${ARTIFACT}"-* "$GHCUP_BIN/ghcup${ext}"
|
||||||
|
chmod +x "$GHCUP_BIN/ghcup${ext}"
|
||||||
|
echo "$PATH"
|
||||||
|
|
||||||
|
"$GHCUP_BIN/ghcup${ext}" --version
|
||||||
|
eghcup --version
|
||||||
|
sha_sum "$GHCUP_BIN/ghcup${ext}"
|
||||||
|
sha_sum "$(raw_eghcup --offline whereis ghcup)"
|
||||||
|
|
||||||
|
git_describe
|
||||||
|
|
||||||
|
eghcup install ghc "${GHC_VERSION}"
|
||||||
|
eghcup install cabal "${CABAL_VERSION}"
|
||||||
|
|
||||||
|
ecabal update
|
||||||
|
|
||||||
|
if ! command -v cabal-cache ; then
|
||||||
|
download_cabal_cache "$HOME/.local/bin/cabal-cache"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! cabal-cache version ; then
|
||||||
|
build_cabal_cache "$HOME/.local/bin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
eghcup debug-info
|
||||||
|
|
||||||
|
(
|
||||||
|
cd /tmp
|
||||||
|
git clone --depth 1 --branch "${HLS_TARGET_VERSION}" \
|
||||||
|
https://github.com/haskell/haskell-language-server.git \
|
||||||
|
"haskell-language-server-${HLS_TARGET_VERSION}"
|
||||||
|
cd "haskell-language-server-${HLS_TARGET_VERSION}/"
|
||||||
|
ecabal configure -w "ghc-${GHC_VERSION}" --disable-profiling --disable-tests --jobs="$(nproc)"
|
||||||
|
ecabal build --dependencies-only -w "ghc-${GHC_VERSION}" --disable-profiling --disable-tests --jobs="$(nproc)" --dry-run
|
||||||
|
sync_from
|
||||||
|
ecabal build --dependencies-only -w "ghc-${GHC_VERSION}" --disable-profiling --disable-tests --jobs="$(nproc)" || sync_to
|
||||||
|
sync_to
|
||||||
|
)
|
||||||
|
|
||||||
|
eghcup -v compile hls -j "$(nproc)" -g "${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_DIR}" ]
|
||||||
|
|
||||||
262
.github/scripts/test.sh
vendored
Normal file
262
.github/scripts/test.sh
vendored
Normal file
@@ -0,0 +1,262 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
. .github/scripts/common.sh
|
||||||
|
|
||||||
|
|
||||||
|
if [ "${OS}" = "Windows" ] ; then
|
||||||
|
GHCUP_DIR="${GHCUP_INSTALL_BASE_PREFIX}"/ghcup
|
||||||
|
else
|
||||||
|
GHCUP_DIR="${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup
|
||||||
|
fi
|
||||||
|
|
||||||
|
git_describe
|
||||||
|
|
||||||
|
rm -rf "${GHCUP_DIR}"
|
||||||
|
mkdir -p "${GHCUP_BIN}"
|
||||||
|
|
||||||
|
cp "out/${ARTIFACT}"-* "$GHCUP_BIN/ghcup${ext}"
|
||||||
|
cp "out/test-${ARTIFACT}"-* "ghcup-test${ext}"
|
||||||
|
chmod +x "$GHCUP_BIN/ghcup${ext}"
|
||||||
|
chmod +x "ghcup-test${ext}"
|
||||||
|
|
||||||
|
"$GHCUP_BIN/ghcup${ext}" --version
|
||||||
|
eghcup --version
|
||||||
|
sha_sum "$GHCUP_BIN/ghcup${ext}"
|
||||||
|
sha_sum "$(raw_eghcup --offline whereis ghcup)"
|
||||||
|
|
||||||
|
### Haskell test suite
|
||||||
|
|
||||||
|
./ghcup-test${ext}
|
||||||
|
rm ghcup-test${ext}
|
||||||
|
|
||||||
|
### manual cli based testing
|
||||||
|
|
||||||
|
eghcup --numeric-version
|
||||||
|
|
||||||
|
eghcup install ghc ${GHC_VER}
|
||||||
|
eghcup unset ghc ${GHC_VER}
|
||||||
|
ls -lah "$(eghcup whereis -d ghc ${GHC_VER})"
|
||||||
|
[ "`$(eghcup whereis ghc ${GHC_VER}) --numeric-version`" = "${GHC_VER}" ]
|
||||||
|
[ "`eghcup run --ghc ${GHC_VER} -- ghc --numeric-version`" = "${GHC_VER}" ]
|
||||||
|
[ "`ghcup run --ghc ${GHC_VER} -- ghc -e 'Control.Monad.join (Control.Monad.fmap System.IO.putStr System.Environment.getExecutablePath)'`" = "`$(ghcup whereis ghc ${GHC_VER}) -e 'Control.Monad.join (Control.Monad.fmap System.IO.putStr System.Environment.getExecutablePath)'`" ]
|
||||||
|
eghcup set ghc ${GHC_VER}
|
||||||
|
eghcup install cabal ${CABAL_VER}
|
||||||
|
[ "`$(eghcup whereis cabal ${CABAL_VER}) --numeric-version`" = "${CABAL_VER}" ]
|
||||||
|
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_VER} -- cabal --numeric-version`" = "${CABAL_VER}" ]
|
||||||
|
eghcup set cabal ${CABAL_VER}
|
||||||
|
|
||||||
|
[ "`$(eghcup whereis cabal ${CABAL_VER}) --numeric-version`" = "${CABAL_VER}" ]
|
||||||
|
|
||||||
|
if [ "${OS}" != "FreeBSD" ] ; then
|
||||||
|
if [ "${ARCH}" = "64" ] && [ "${DISTRO}" != "Alpine" ] ; 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
|
||||||
|
cat "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup-run.files.windows" | sort > expected.txt
|
||||||
|
elif [ "${DISTRO}" = "Alpine" ] ; then
|
||||||
|
cat "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup-run.files.alpine" | sort > expected.txt
|
||||||
|
else
|
||||||
|
cat "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup-run.files" | sort > expected.txt
|
||||||
|
fi
|
||||||
|
(cd ".bin" && find . | sort) > actual.txt
|
||||||
|
diff --strip-trailing-cr -w -u actual.txt expected.txt
|
||||||
|
rm actual.txt expected.txt
|
||||||
|
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}" = "macOS" ] && [ "${ARCH}" = "ARM64" ] ; then
|
||||||
|
# missing bindists
|
||||||
|
echo
|
||||||
|
elif [ "${OS}" = "FreeBSD" ] ; then
|
||||||
|
# not enough space
|
||||||
|
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
|
||||||
|
if [ "${DISTRO}" = "Alpine" ] ; then
|
||||||
|
(cat "$( cd "$(dirname "$0")" ; pwd -P )/../ghc-8.10.3-linux.alpine.files" | sort) > expected.txt
|
||||||
|
else
|
||||||
|
(cat "$( cd "$(dirname "$0")" ; pwd -P )/../ghc-8.10.3-linux.files" | sort) > expected.txt
|
||||||
|
fi
|
||||||
|
(cd "${GHCUP_DIR}/ghc/8.10.3/" && find . | sort) > actual.txt
|
||||||
|
# ignore docs
|
||||||
|
sed -i '/share\/doc/d' actual.txt
|
||||||
|
sed -i '/share\/doc/d' expected.txt
|
||||||
|
diff --strip-trailing-cr -w -u actual.txt expected.txt
|
||||||
|
rm actual.txt expected.txt
|
||||||
|
fi
|
||||||
|
elif [ "${OS}" = "Windows" ] ; then
|
||||||
|
eghcup prefetch ghc 8.10.3
|
||||||
|
eghcup --offline install ghc 8.10.3
|
||||||
|
(cat "$( cd "$(dirname "$0")" ; pwd -P )/../ghc-8.10.3-windows.files" | sort) > expected.txt
|
||||||
|
(cd "${GHCUP_DIR}/ghc/8.10.3/" && find . | sort) > actual.txt
|
||||||
|
diff --strip-trailing-cr -w -u actual.txt expected.txt
|
||||||
|
rm actual.txt expected.txt
|
||||||
|
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_VER}
|
||||||
|
[ "$(ghc --numeric-version)" = "${ghc_ver}" ]
|
||||||
|
eghcup unset ghc
|
||||||
|
"$GHCUP_BIN"/ghc --numeric-version && exit 1 || echo yes
|
||||||
|
eghcup set ${GHC_VER}
|
||||||
|
eghcup --offline rm 8.10.3
|
||||||
|
[ "$(ghc --numeric-version)" = "${ghc_ver}" ]
|
||||||
|
|
||||||
|
|
||||||
|
ls -lah "$GHCUP_BIN"
|
||||||
|
|
||||||
|
if [ "${OS}" = "macOS" ] ; then
|
||||||
|
eghcup install hls
|
||||||
|
$(eghcup whereis hls) --version
|
||||||
|
|
||||||
|
eghcup install stack
|
||||||
|
$(eghcup whereis stack) --version
|
||||||
|
elif [ "${OS}" = "Linux" ] ; then
|
||||||
|
if [ "${ARCH}" = "64" ] && [ "${DISTRO}" != "Alpine" ] ; 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
|
||||||
|
|
||||||
|
# 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://raw.githubusercontent.com/haskell/ghcup-metadata/exp/ghcup-0.0.7.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://raw.githubusercontent.com/haskell/ghcup-metadata/exp/ghcup-0.0.7.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
|
||||||
|
if [ "${DISTRO}" != "Alpine" ] ; then
|
||||||
|
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
|
||||||
|
fi
|
||||||
|
|
||||||
|
eghcup upgrade
|
||||||
|
eghcup upgrade -f
|
||||||
|
|
||||||
|
# restore old ghcup, because we want to test nuke
|
||||||
|
cp "out/${ARTIFACT}"-* "$GHCUP_BIN/ghcup${ext}"
|
||||||
|
chmod +x "$GHCUP_BIN/ghcup${ext}"
|
||||||
|
|
||||||
|
# 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 ]
|
||||||
|
|
||||||
58
.github/workflows/bootstrap.yaml
vendored
Normal file
58
.github/workflows/bootstrap.yaml
vendored
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
name: Bootstrap tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
bootstrap:
|
||||||
|
name: bootstrap
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
BOOTSTRAP_HASKELL_CABAL_VERSION: 3.6.2.0
|
||||||
|
BOOTSTRAP_HASKELL_GHC_VERSION: 8.10.7
|
||||||
|
BOOTSTRAP_HASKELL_NONINTERACTIVE: yes
|
||||||
|
ARCH: 64
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: ubuntu-latest
|
||||||
|
DISTRO: Ubuntu
|
||||||
|
- os: macOS-11
|
||||||
|
DISTRO: na
|
||||||
|
- os: windows-latest
|
||||||
|
DISTRO: na
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- if: runner.os == 'Linux'
|
||||||
|
name: Run bootstrap
|
||||||
|
run: |
|
||||||
|
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 curl gzip
|
||||||
|
sh ./.github/scripts/bootstrap.sh
|
||||||
|
env:
|
||||||
|
DISTRO: ${{ matrix.DISTRO }}
|
||||||
|
|
||||||
|
- if: runner.os == 'macOS'
|
||||||
|
name: Run bootstrap
|
||||||
|
run: sh ./.github/scripts/bootstrap.sh
|
||||||
|
env:
|
||||||
|
DISTRO: ${{ matrix.DISTRO }}
|
||||||
|
|
||||||
|
- if: runner.os == 'Windows'
|
||||||
|
name: Run bootstrap
|
||||||
|
run: |
|
||||||
|
$curDir = Get-Location
|
||||||
|
Write-Host "Current Working Directory: $curDir"
|
||||||
|
./scripts/bootstrap/bootstrap-haskell.ps1 -InstallDir ${GITHUB_WORKSPACE} -BootstrapUrl ("{0}/scripts/bootstrap/bootstrap-haskell" -f $curDir) -InBash
|
||||||
|
shell: pwsh
|
||||||
37
.github/workflows/cache.yaml
vendored
Normal file
37
.github/workflows/cache.yaml
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
name: Cache eviction
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
key:
|
||||||
|
description: Which cache to evict
|
||||||
|
required: true
|
||||||
|
default: '/'
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- FreeBSD-64-na
|
||||||
|
- Linux-32-Alpine
|
||||||
|
- Linux-64-Alpine
|
||||||
|
- Linux-64-Ubuntu
|
||||||
|
- Linux-ARM-Ubuntu
|
||||||
|
- Linux-ARM64-Ubuntu
|
||||||
|
- Windows-64-na
|
||||||
|
- macOS-64-na
|
||||||
|
- macOS-ARM64-na
|
||||||
|
- /
|
||||||
|
jobs:
|
||||||
|
evict:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Remove from S3
|
||||||
|
uses: vitorsgomes/s3-rm-action@master
|
||||||
|
with:
|
||||||
|
args: --recursive
|
||||||
|
env:
|
||||||
|
AWS_S3_ENDPOINT: https://${{ secrets.S3_HOST }}
|
||||||
|
AWS_S3_BUCKET: ghcup-hs
|
||||||
|
AWS_REGION: us-west-2
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
PATH_TO_DELETE: ${{ github.event.inputs.key }}
|
||||||
125
.github/workflows/docker.yaml
vendored
Normal file
125
.github/workflows/docker.yaml
vendored
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
name: Docker image builds
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker-alpine32:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
- name: Build and push (alpine 32bit)
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: ./docker/alpine32
|
||||||
|
push: true
|
||||||
|
tags: hasufell/i386-alpine-haskell:3.12
|
||||||
|
platforms: |
|
||||||
|
linux/i386
|
||||||
|
linux/amd64
|
||||||
|
|
||||||
|
docker-alpine:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
- name: Build and push (alpine 64bit)
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: ./docker/alpine64
|
||||||
|
push: true
|
||||||
|
tags: hasufell/alpine-haskell:3.12
|
||||||
|
platforms: linux/amd64
|
||||||
|
|
||||||
|
docker-arm32:
|
||||||
|
runs-on: [self-hosted, Linux, ARM64]
|
||||||
|
steps:
|
||||||
|
- uses: docker://arm64v8/ubuntu:focal
|
||||||
|
name: Cleanup (aarch64 linux)
|
||||||
|
with:
|
||||||
|
args: "find . -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +"
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and push (debian buster)
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: ./docker/arm32v7/buster
|
||||||
|
push: true
|
||||||
|
tags: hasufell/arm32v7-debian-haskell:10
|
||||||
|
platforms: linux/arm
|
||||||
|
|
||||||
|
- name: Build and push (ubuntu focal)
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: ./docker/arm32v7/focal
|
||||||
|
push: true
|
||||||
|
tags: hasufell/arm32v7-ubuntu-haskell:focal
|
||||||
|
platforms: linux/arm
|
||||||
|
|
||||||
|
docker-aarch:
|
||||||
|
runs-on: [self-hosted, Linux, ARM64]
|
||||||
|
steps:
|
||||||
|
- uses: docker://arm64v8/ubuntu:focal
|
||||||
|
name: Cleanup (aarch64 linux)
|
||||||
|
with:
|
||||||
|
args: "find . -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +"
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and push (debian buster)
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: ./docker/arm64v8/buster
|
||||||
|
push: true
|
||||||
|
tags: hasufell/arm64v8-debian-haskell:10
|
||||||
|
platforms: linux/arm64
|
||||||
|
|
||||||
|
- name: Build and push (ubuntu focal)
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: ./docker/arm64v8/focal
|
||||||
|
push: true
|
||||||
|
tags: hasufell/arm64v8-ubuntu-haskell:focal
|
||||||
|
platforms: linux/arm64
|
||||||
26
.github/workflows/hlint.yaml
vendored
Normal file
26
.github/workflows/hlint.yaml
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
name: Hlint
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
hlint:
|
||||||
|
name: hlint
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- name: Run hlint
|
||||||
|
run: curl -sSL https://raw.github.com/ndmitchell/hlint/master/misc/run.sh | sh -s -- -r lib/ test/
|
||||||
33
.github/workflows/mkdocs.yaml
vendored
Normal file
33
.github/workflows/mkdocs.yaml
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
name: MkDocs
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
mkdocs:
|
||||||
|
name: mkdocs
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- name: Install mkdocs deps
|
||||||
|
run: |
|
||||||
|
sudo apt-get update -y
|
||||||
|
sudo apt-get install -y python3-pip
|
||||||
|
sudo pip3 install mkdocs
|
||||||
|
|
||||||
|
- name: Run mkdocs
|
||||||
|
run: |
|
||||||
|
mkdocs build
|
||||||
585
.github/workflows/release.yaml
vendored
585
.github/workflows/release.yaml
vendored
@@ -1,109 +1,518 @@
|
|||||||
name: Create Release
|
name: Build and release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
tags:
|
tags:
|
||||||
- 'v*'
|
- 'v*'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
schedule:
|
||||||
|
- cron: '0 2 * * *'
|
||||||
|
|
||||||
|
env:
|
||||||
|
CABAL_CACHE_DISABLE: ${{ vars.CABAL_CACHE_DISABLE }}
|
||||||
|
CABAL_CACHE_NONFATAL: yes
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
draft_release:
|
build-linux:
|
||||||
name: Draft Release
|
name: Build linux binary
|
||||||
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 }}
|
runs-on: ${{ matrix.os }}
|
||||||
env:
|
env:
|
||||||
MACOSX_DEPLOYMENT_TARGET: 10.13
|
CABAL_VER: 3.10.1.0
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
S3_HOST: ${{ secrets.S3_HOST }}
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: true
|
||||||
matrix:
|
matrix:
|
||||||
os:
|
include:
|
||||||
- macOS-10.15
|
- os: ubuntu-latest
|
||||||
|
ARTIFACT: "i386-linux-ghcup"
|
||||||
|
GHC_VER: 8.10.7
|
||||||
|
ARCH: 32
|
||||||
|
- os: ubuntu-latest
|
||||||
|
ARTIFACT: "x86_64-linux-ghcup"
|
||||||
|
GHC_VER: 8.10.7
|
||||||
|
ARCH: 64
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- uses: haskell/actions/setup@v1.2
|
|
||||||
with:
|
with:
|
||||||
ghc-version: 8.10.4
|
submodules: 'true'
|
||||||
cabal-version: 3.4.0.0
|
|
||||||
|
|
||||||
- name: create ~/.local/bin
|
- if: matrix.ARCH == '32'
|
||||||
run: mkdir -p "$HOME/.local/bin"
|
name: Run build (32 bit linux)
|
||||||
shell: bash
|
uses: docker://hasufell/i386-alpine-haskell:3.12
|
||||||
|
with:
|
||||||
- name: Add ~/.local/bin to PATH
|
args: sh .github/scripts/build.sh
|
||||||
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:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: Alpine
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }}
|
||||||
|
S3_HOST: ${{ env.S3_HOST }}
|
||||||
|
|
||||||
|
- if: matrix.ARCH == '64'
|
||||||
|
name: Run build (64 bit linux)
|
||||||
|
uses: docker://hasufell/alpine-haskell:3.12
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ needs.draft_release.outputs.upload_url }}
|
args: sh .github/scripts/build.sh
|
||||||
asset_path: ${{ env.ASSET_PATH }}
|
env:
|
||||||
asset_name: ghcup-${{ matrix.os }}
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
asset_content_type: application/octet-stream
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: Alpine
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }}
|
||||||
|
S3_HOST: ${{ env.S3_HOST }}
|
||||||
|
|
||||||
- if: always()
|
- if: always()
|
||||||
uses: actions/upload-artifact@v2
|
name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: plan.json
|
name: artifacts
|
||||||
path: ./dist-newstyle/cache/plan.json
|
path: |
|
||||||
|
./out/*
|
||||||
|
|
||||||
|
|
||||||
|
build-arm:
|
||||||
|
name: Build ARM binary
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
CABAL_VER: 3.10.1.0
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
S3_HOST: ${{ secrets.S3_HOST }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: true
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: [self-hosted, Linux, ARM64]
|
||||||
|
ARTIFACT: "armv7-linux-ghcup"
|
||||||
|
GHC_VER: 9.2.2
|
||||||
|
ARCH: ARM
|
||||||
|
- os: [self-hosted, Linux, ARM64]
|
||||||
|
ARTIFACT: "aarch64-linux-ghcup"
|
||||||
|
GHC_VER: 9.2.6
|
||||||
|
ARCH: ARM64
|
||||||
|
steps:
|
||||||
|
- uses: docker://arm64v8/debian:10
|
||||||
|
name: Cleanup (aarch64 linux)
|
||||||
|
with:
|
||||||
|
args: "find . -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +"
|
||||||
|
|
||||||
|
- name: git config
|
||||||
|
run: |
|
||||||
|
git config --global --get-all safe.directory | grep '^\*$' || git config --global --add safe.directory "*"
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- if: matrix.ARCH == 'ARM'
|
||||||
|
uses: docker://hasufell/arm32v7-debian-haskell:10
|
||||||
|
name: Run build (armv7 linux)
|
||||||
|
with:
|
||||||
|
args: sh .github/scripts/build.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: Ubuntu
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }}
|
||||||
|
S3_HOST: ${{ env.S3_HOST }}
|
||||||
|
|
||||||
|
- if: matrix.ARCH == 'ARM64'
|
||||||
|
uses: docker://hasufell/arm64v8-debian-haskell:10
|
||||||
|
name: Run build (aarch64 linux)
|
||||||
|
with:
|
||||||
|
args: sh .github/scripts/build.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: Ubuntu
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }}
|
||||||
|
S3_HOST: ${{ env.S3_HOST }}
|
||||||
|
|
||||||
|
- if: always()
|
||||||
|
name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts
|
||||||
|
path: |
|
||||||
|
./out/*
|
||||||
|
|
||||||
|
build-macwin:
|
||||||
|
name: Build binary (Mac/Win)
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
CABAL_VER: 3.10.1.0
|
||||||
|
MACOSX_DEPLOYMENT_TARGET: 10.13
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
S3_HOST: ${{ secrets.S3_HOST }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: [self-hosted, macOS, ARM64]
|
||||||
|
ARTIFACT: "aarch64-apple-darwin-ghcup"
|
||||||
|
GHC_VER: 9.2.6
|
||||||
|
ARCH: ARM64
|
||||||
|
- os: macOS-11
|
||||||
|
ARTIFACT: "x86_64-apple-darwin-ghcup"
|
||||||
|
GHC_VER: 9.2.6
|
||||||
|
ARCH: 64
|
||||||
|
- os: windows-latest
|
||||||
|
ARTIFACT: "x86_64-mingw64-ghcup"
|
||||||
|
GHC_VER: 8.10.7
|
||||||
|
ARCH: 64
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- if: matrix.ARCH == 'ARM64' && runner.os == 'macOS'
|
||||||
|
name: Run build
|
||||||
|
run: |
|
||||||
|
bash .github/scripts/brew.sh git coreutils llvm@11 autoconf automake
|
||||||
|
export PATH="$HOME/.brew/bin:$HOME/.brew/sbin:$HOME/.brew/opt/llvm@11/bin:$PATH"
|
||||||
|
export CC="$HOME/.brew/opt/llvm@11/bin/clang"
|
||||||
|
export CXX="$HOME/.brew/opt/llvm@11/bin/clang++"
|
||||||
|
export LD=ld
|
||||||
|
export AR="$HOME/.brew/opt/llvm@11/bin/llvm-ar"
|
||||||
|
export RANLIB="$HOME/.brew/opt/llvm@11/bin/llvm-ranlib"
|
||||||
|
bash .github/scripts/build.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: na
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }}
|
||||||
|
S3_HOST: ${{ env.S3_HOST }}
|
||||||
|
HOMEBREW_CHANGE_ARCH_TO_ARM: 1
|
||||||
|
|
||||||
|
- if: matrix.ARCH == '64' && runner.os == 'macOS'
|
||||||
|
name: Run build (windows/mac)
|
||||||
|
run: |
|
||||||
|
bash .github/scripts/brew.sh coreutils
|
||||||
|
export PATH="$HOME/.brew/bin:$HOME/.brew/sbin:$PATH"
|
||||||
|
bash .github/scripts/build.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: na
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }}
|
||||||
|
S3_HOST: ${{ env.S3_HOST }}
|
||||||
|
HOMEBREW_CHANGE_ARCH_TO_ARM: 1
|
||||||
|
|
||||||
|
- if: runner.os == 'Windows'
|
||||||
|
name: Run build (windows/mac)
|
||||||
|
run: |
|
||||||
|
bash .github/scripts/brew.sh git coreutils autoconf automake
|
||||||
|
bash .github/scripts/build.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: na
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }}
|
||||||
|
S3_HOST: ${{ env.S3_HOST }}
|
||||||
|
HOMEBREW_CHANGE_ARCH_TO_ARM: 1
|
||||||
|
|
||||||
|
- if: always()
|
||||||
|
name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts
|
||||||
|
path: |
|
||||||
|
./out/*
|
||||||
|
|
||||||
|
test-linux:
|
||||||
|
name: Test linux
|
||||||
|
needs: "build-linux"
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
CABAL_VER: 3.10.1.0
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: ubuntu-latest
|
||||||
|
ARTIFACT: "i386-linux-ghcup"
|
||||||
|
GHC_VER: 8.10.7
|
||||||
|
ARCH: 32
|
||||||
|
DISTRO: Alpine
|
||||||
|
- os: ubuntu-latest
|
||||||
|
ARTIFACT: "x86_64-linux-ghcup"
|
||||||
|
GHC_VER: 8.10.7
|
||||||
|
ARCH: 64
|
||||||
|
DISTRO: Alpine
|
||||||
|
- os: ubuntu-latest
|
||||||
|
ARTIFACT: "x86_64-linux-ghcup"
|
||||||
|
GHC_VER: 8.10.7
|
||||||
|
ARCH: 64
|
||||||
|
DISTRO: Ubuntu
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts
|
||||||
|
path: ./out
|
||||||
|
|
||||||
|
- if: matrix.ARCH == '32' && matrix.DISTRO == 'Alpine'
|
||||||
|
name: Run test (32 bit linux Alpine)
|
||||||
|
uses: docker://hasufell/i386-alpine-haskell:3.12
|
||||||
|
with:
|
||||||
|
args: sh .github/scripts/test.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: ${{ matrix.DISTRO }}
|
||||||
|
|
||||||
|
- if: matrix.ARCH == '64' && matrix.DISTRO == 'Alpine'
|
||||||
|
name: Run test (64 bit linux Alpine)
|
||||||
|
uses: docker://hasufell/alpine-haskell:3.12
|
||||||
|
with:
|
||||||
|
args: sh .github/scripts/test.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: ${{ matrix.DISTRO }}
|
||||||
|
|
||||||
|
- if: matrix.DISTRO != 'Alpine'
|
||||||
|
name: Run test (64 bit linux)
|
||||||
|
run: |
|
||||||
|
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 curl gzip
|
||||||
|
sh .github/scripts/test.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: ${{ matrix.DISTRO }}
|
||||||
|
|
||||||
|
- if: failure()
|
||||||
|
name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: testfiles
|
||||||
|
path: |
|
||||||
|
./test/golden/unix/GHCupInfo*json
|
||||||
|
|
||||||
|
test-arm:
|
||||||
|
name: Test ARM
|
||||||
|
needs: "build-arm"
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
CABAL_VER: 3.10.1.0
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: [self-hosted, Linux, ARM64]
|
||||||
|
ARTIFACT: "armv7-linux-ghcup"
|
||||||
|
GHC_VER: 9.2.2
|
||||||
|
ARCH: ARM
|
||||||
|
DISTRO: Ubuntu
|
||||||
|
- os: [self-hosted, Linux, ARM64]
|
||||||
|
ARTIFACT: "aarch64-linux-ghcup"
|
||||||
|
GHC_VER: 9.2.6
|
||||||
|
ARCH: ARM64
|
||||||
|
DISTRO: Ubuntu
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: docker://arm64v8/debian:10
|
||||||
|
name: Cleanup (aarch64 linux)
|
||||||
|
with:
|
||||||
|
args: "find . -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +"
|
||||||
|
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts
|
||||||
|
path: ./out
|
||||||
|
|
||||||
|
- if: matrix.ARCH == 'ARM'
|
||||||
|
uses: docker://hasufell/arm32v7-debian-haskell:10
|
||||||
|
name: Run test (armv7 linux)
|
||||||
|
with:
|
||||||
|
args: sh .github/scripts/test.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: Ubuntu
|
||||||
|
|
||||||
|
- if: matrix.ARCH == 'ARM64'
|
||||||
|
uses: docker://hasufell/arm64v8-debian-haskell:10
|
||||||
|
name: Run test (aarch64 linux)
|
||||||
|
with:
|
||||||
|
args: sh .github/scripts/test.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: Ubuntu
|
||||||
|
|
||||||
|
- if: failure()
|
||||||
|
name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: testfiles
|
||||||
|
path: |
|
||||||
|
./test/golden/unix/GHCupInfo*json
|
||||||
|
|
||||||
|
test-macwin:
|
||||||
|
name: Test Mac/Win
|
||||||
|
needs: "build-macwin"
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
CABAL_VER: 3.10.1.0
|
||||||
|
MACOSX_DEPLOYMENT_TARGET: 10.13
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: [self-hosted, macOS, ARM64]
|
||||||
|
ARTIFACT: "aarch64-apple-darwin-ghcup"
|
||||||
|
GHC_VER: 9.2.6
|
||||||
|
ARCH: ARM64
|
||||||
|
DISTRO: na
|
||||||
|
- os: macOS-11
|
||||||
|
ARTIFACT: "x86_64-apple-darwin-ghcup"
|
||||||
|
GHC_VER: 9.2.6
|
||||||
|
ARCH: 64
|
||||||
|
DISTRO: na
|
||||||
|
- os: windows-latest
|
||||||
|
ARTIFACT: "x86_64-mingw64-ghcup"
|
||||||
|
GHC_VER: 8.10.7
|
||||||
|
ARCH: 64
|
||||||
|
DISTRO: na
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts
|
||||||
|
path: ./out
|
||||||
|
|
||||||
|
- if: runner.os == 'macOS'
|
||||||
|
name: Run test
|
||||||
|
run: |
|
||||||
|
bash .github/scripts/brew.sh coreutils
|
||||||
|
export PATH="$HOME/.brew/bin:$HOME/.brew/sbin:$PATH"
|
||||||
|
bash .github/scripts/test.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: ${{ matrix.DISTRO }}
|
||||||
|
HOMEBREW_CHANGE_ARCH_TO_ARM: 1
|
||||||
|
|
||||||
|
- if: runner.os != 'macOS'
|
||||||
|
name: Run test
|
||||||
|
run: bash .github/scripts/test.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: ${{ matrix.DISTRO }}
|
||||||
|
HOMEBREW_CHANGE_ARCH_TO_ARM: 1
|
||||||
|
|
||||||
|
- if: failure() && runner.os == 'Windows'
|
||||||
|
name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: testfiles
|
||||||
|
path: |
|
||||||
|
./test/golden/windows/GHCupInfo*json
|
||||||
|
|
||||||
|
- if: failure() && runner.os != 'Windows'
|
||||||
|
name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: testfiles
|
||||||
|
path: |
|
||||||
|
./test/golden/unix/GHCupInfo*json
|
||||||
|
hls:
|
||||||
|
name: hls
|
||||||
|
needs: build-linux
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GHC_VERSION: "8.10.7"
|
||||||
|
HLS_TARGET_VERSION: "1.8.0.0"
|
||||||
|
CABAL_VERSION: "3.8.1.0"
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
ARTIFACT: "x86_64-linux-ghcup"
|
||||||
|
DISTRO: Ubuntu
|
||||||
|
ARCH: 64
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
S3_HOST: ${{ secrets.S3_HOST }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts
|
||||||
|
path: ./out
|
||||||
|
|
||||||
|
- name: Run hls build
|
||||||
|
run: |
|
||||||
|
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 curl gzip
|
||||||
|
sh .github/scripts/hls.sh
|
||||||
|
|
||||||
|
release:
|
||||||
|
name: release
|
||||||
|
needs: ["test-linux", "test-arm", "test-macwin", "hls"]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: startsWith(github.ref, 'refs/tags/v')
|
||||||
|
steps:
|
||||||
|
- name: Download artifacts
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts
|
||||||
|
path: ./out
|
||||||
|
|
||||||
|
- name: Release
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
draft: true
|
||||||
|
files: |
|
||||||
|
./out/*
|
||||||
|
|||||||
28
.github/workflows/shellcheck.yaml
vendored
Normal file
28
.github/workflows/shellcheck.yaml
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
name: Shellcheck
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
shellcheck:
|
||||||
|
name: shellcheck
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- name: Run shellcheck
|
||||||
|
uses: docker://koalaman/shellcheck-alpine
|
||||||
|
with:
|
||||||
|
args: shellcheck scripts/bootstrap/bootstrap-haskell
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -13,3 +13,5 @@ TAGS
|
|||||||
/tmp/
|
/tmp/
|
||||||
.entangled
|
.entangled
|
||||||
release/
|
release/
|
||||||
|
releases/
|
||||||
|
site/
|
||||||
|
|||||||
417
.gitlab-ci.yml
417
.gitlab-ci.yml
@@ -1,6 +1,8 @@
|
|||||||
stages:
|
stages:
|
||||||
- hlint
|
- checks
|
||||||
|
- quick-test
|
||||||
- test
|
- test
|
||||||
|
- expensive-test
|
||||||
- release
|
- release
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
@@ -9,12 +11,19 @@ variables:
|
|||||||
# Commit of ghc/ci-images repository from which to pull Docker images
|
# Commit of ghc/ci-images repository from which to pull Docker images
|
||||||
DOCKER_REV: 8d0224e6b2a08157649651e69302380b2bd24e11
|
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
|
# CI Step
|
||||||
############################################################
|
############################################################
|
||||||
|
|
||||||
.debian:
|
.debian:
|
||||||
image: "registry.gitlab.haskell.org/ghc/ci-images/x86_64-linux-deb9:$DOCKER_REV"
|
image: "registry.gitlab.haskell.org/ghc/ci-images/x86_64-linux-deb10:$DOCKER_REV"
|
||||||
tags:
|
tags:
|
||||||
- x86_64-linux
|
- x86_64-linux
|
||||||
variables:
|
variables:
|
||||||
@@ -49,6 +58,7 @@ variables:
|
|||||||
OS: "LINUX"
|
OS: "LINUX"
|
||||||
ARCH: "ARM"
|
ARCH: "ARM"
|
||||||
CABAL_DIR: "$CI_PROJECT_DIR/cabal"
|
CABAL_DIR: "$CI_PROJECT_DIR/cabal"
|
||||||
|
retry: 2
|
||||||
|
|
||||||
.linux:aarch64:
|
.linux:aarch64:
|
||||||
image: "registry.gitlab.haskell.org/ghc/ci-images/aarch64-linux-deb10:$DOCKER_REV"
|
image: "registry.gitlab.haskell.org/ghc/ci-images/aarch64-linux-deb10:$DOCKER_REV"
|
||||||
@@ -75,9 +85,17 @@ variables:
|
|||||||
ARCH: "ARM64"
|
ARCH: "ARM64"
|
||||||
CABAL_DIR: "$CI_PROJECT_DIR/cabal"
|
CABAL_DIR: "$CI_PROJECT_DIR/cabal"
|
||||||
|
|
||||||
.freebsd:
|
.freebsd13:
|
||||||
tags:
|
tags:
|
||||||
- x86_64-freebsd
|
- x86_64-freebsd13
|
||||||
|
variables:
|
||||||
|
OS: "FREEBSD"
|
||||||
|
ARCH: "64"
|
||||||
|
CABAL_DIR: "$CI_PROJECT_DIR/cabal"
|
||||||
|
|
||||||
|
.freebsd12:
|
||||||
|
tags:
|
||||||
|
- x86_64-freebsd12
|
||||||
variables:
|
variables:
|
||||||
OS: "FREEBSD"
|
OS: "FREEBSD"
|
||||||
ARCH: "64"
|
ARCH: "64"
|
||||||
@@ -90,6 +108,7 @@ variables:
|
|||||||
OS: "WINDOWS"
|
OS: "WINDOWS"
|
||||||
ARCH: "64"
|
ARCH: "64"
|
||||||
CABAL_DIR: "$CI_PROJECT_DIR/cabal"
|
CABAL_DIR: "$CI_PROJECT_DIR/cabal"
|
||||||
|
retry: 2
|
||||||
|
|
||||||
.root_cleanup:
|
.root_cleanup:
|
||||||
after_script:
|
after_script:
|
||||||
@@ -99,13 +118,17 @@ variables:
|
|||||||
script:
|
script:
|
||||||
- bash ./.gitlab/script/ghcup_version.sh
|
- bash ./.gitlab/script/ghcup_version.sh
|
||||||
variables:
|
variables:
|
||||||
JSON_VERSION: "0.0.6"
|
JSON_VERSION: "0.0.7"
|
||||||
artifacts:
|
artifacts:
|
||||||
expire_in: 2 week
|
expire_in: 2 week
|
||||||
paths:
|
paths:
|
||||||
- golden
|
- test/golden
|
||||||
- dist-newstyle/cache/
|
- dist-newstyle/cache/
|
||||||
when: on_failure
|
when: on_failure
|
||||||
|
cache:
|
||||||
|
key: ghcup-test-$CACHE_REV
|
||||||
|
paths:
|
||||||
|
- cabal-cache
|
||||||
|
|
||||||
# .test_ghcup_scoop:
|
# .test_ghcup_scoop:
|
||||||
# script:
|
# script:
|
||||||
@@ -117,6 +140,10 @@ variables:
|
|||||||
- .debian
|
- .debian
|
||||||
before_script:
|
before_script:
|
||||||
- ./.gitlab/before_script/linux/install_deps.sh
|
- ./.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:
|
.test_ghcup_version:linux32:
|
||||||
extends:
|
extends:
|
||||||
@@ -124,6 +151,10 @@ variables:
|
|||||||
- .alpine:32bit
|
- .alpine:32bit
|
||||||
before_script:
|
before_script:
|
||||||
- ./.gitlab/before_script/linux/alpine/install_deps.sh
|
- ./.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:
|
.test_ghcup_version:armv7:
|
||||||
extends:
|
extends:
|
||||||
@@ -131,6 +162,10 @@ variables:
|
|||||||
- .linux:armv7
|
- .linux:armv7
|
||||||
before_script:
|
before_script:
|
||||||
- ./.gitlab/before_script/linux/install_deps.sh
|
- ./.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:
|
.test_ghcup_version:aarch64:
|
||||||
extends:
|
extends:
|
||||||
@@ -138,63 +173,96 @@ variables:
|
|||||||
- .linux:aarch64
|
- .linux:aarch64
|
||||||
before_script:
|
before_script:
|
||||||
- ./.gitlab/before_script/linux/install_deps.sh
|
- ./.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:
|
.test_ghcup_version:darwin:
|
||||||
extends:
|
extends:
|
||||||
- .test_ghcup_version
|
- .test_ghcup_version
|
||||||
- .darwin
|
- .darwin
|
||||||
- .root_cleanup
|
|
||||||
before_script:
|
before_script:
|
||||||
- ./.gitlab/before_script/darwin/install_deps.sh
|
- ./.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:
|
.test_ghcup_version:darwin:aarch64:
|
||||||
extends:
|
extends:
|
||||||
- .test_ghcup_version
|
- .test_ghcup_version
|
||||||
- .darwin:aarch64
|
- .darwin:aarch64
|
||||||
- .root_cleanup
|
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: |
|
script: |
|
||||||
set -Eeuo pipefail
|
export PATH="$CI_PROJECT_DIR/.brew/opt/llvm/bin:$CI_PROJECT_DIR/.brew/bin:$CI_PROJECT_DIR/.brew/sbin:$PATH"
|
||||||
function runInNixShell() {
|
export CC=$CI_PROJECT_DIR/.brew/opt/llvm/bin/clang
|
||||||
time nix-shell $CI_PROJECT_DIR/.gitlab/shell.nix \
|
export CXX=$CI_PROJECT_DIR/.brew/opt/llvm/bin/clang++
|
||||||
-I nixpkgs=https://github.com/angerman/nixpkgs/archive/75f7281738b.tar.gz \
|
export LD=ld
|
||||||
--argstr system "aarch64-darwin" \
|
export AR=$CI_PROJECT_DIR/.brew/opt/llvm/bin/llvm-ar
|
||||||
--pure \
|
export RANLIB=$CI_PROJECT_DIR/.brew/opt/llvm/bin/llvm-ranlib
|
||||||
--keep CI_PROJECT_DIR \
|
./.gitlab/before_script/darwin/install_deps.sh
|
||||||
--keep MACOSX_DEPLOYMENT_TARGET \
|
./.gitlab/script/ghcup_version.sh
|
||||||
--keep JSON_VERSION \
|
after_script:
|
||||||
--keep ARTIFACT \
|
- ./.gitlab/script/ci.sh save_cabal_cache
|
||||||
--keep OS \
|
- ./.gitlab/script/ci.sh save_brew_cache
|
||||||
--keep ARCH \
|
- bash ./.gitlab/after_script.sh
|
||||||
--keep CABAL_DIR \
|
|
||||||
--keep GHC_VERSION \
|
|
||||||
--keep CABAL_VERSION \
|
|
||||||
--run "$1" 2>&1
|
|
||||||
}
|
|
||||||
runInNixShell ./.gitlab/before_script/darwin/install_deps.sh 2>&1
|
|
||||||
runInNixShell ./.gitlab/script/ghcup_version.sh 2>&1
|
|
||||||
|
|
||||||
.test_ghcup_version:freebsd:
|
.test_ghcup_version:freebsd12:
|
||||||
extends:
|
extends:
|
||||||
- .test_ghcup_version
|
- .test_ghcup_version
|
||||||
- .freebsd
|
- .freebsd12
|
||||||
- .root_cleanup
|
|
||||||
before_script:
|
before_script:
|
||||||
- ./.gitlab/before_script/freebsd/install_deps.sh
|
- ./.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:
|
.test_ghcup_version:windows:
|
||||||
extends:
|
extends:
|
||||||
- .test_ghcup_version
|
- .test_ghcup_version
|
||||||
- .windows
|
- .windows
|
||||||
- .root_cleanup
|
|
||||||
before_script:
|
before_script:
|
||||||
- set CABAL_DIR="$CI_PROJECT_DIR/cabal"
|
|
||||||
- bash ./.gitlab/before_script/windows/install_deps.sh
|
- 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:
|
# .test_ghcup_scoop:windows:
|
||||||
# extends:
|
# extends:
|
||||||
# - .windows
|
# - .windows
|
||||||
# - .test_ghcup_scoop
|
# - .test_ghcup_scoop
|
||||||
# - .root_cleanup
|
|
||||||
|
|
||||||
.release_ghcup:
|
.release_ghcup:
|
||||||
script:
|
script:
|
||||||
@@ -207,16 +275,19 @@ variables:
|
|||||||
only:
|
only:
|
||||||
- tags
|
- tags
|
||||||
variables:
|
variables:
|
||||||
JSON_VERSION: "0.0.6"
|
JSON_VERSION: "0.0.7"
|
||||||
|
|
||||||
######## stack test ########
|
######## stack test ########
|
||||||
|
|
||||||
test:linux:stack:
|
test:linux:stack:
|
||||||
stage: test
|
stage: test
|
||||||
before_script:
|
before_script:
|
||||||
|
- ./.gitlab/script/ci.sh extract_stack_cache
|
||||||
- ./.gitlab/before_script/linux/install_deps_minimal.sh
|
- ./.gitlab/before_script/linux/install_deps_minimal.sh
|
||||||
script:
|
script:
|
||||||
- ./.gitlab/script/ghcup_stack.sh
|
- ./.gitlab/script/ghcup_stack.sh
|
||||||
|
after_script:
|
||||||
|
- ./.gitlab/script/ci.sh save_stack_cache
|
||||||
extends:
|
extends:
|
||||||
- .debian
|
- .debian
|
||||||
needs: []
|
needs: []
|
||||||
@@ -224,62 +295,72 @@ test:linux:stack:
|
|||||||
######## bootstrap test ########
|
######## bootstrap test ########
|
||||||
|
|
||||||
test:linux:bootstrap_script:
|
test:linux:bootstrap_script:
|
||||||
stage: test
|
stage: quick-test
|
||||||
before_script:
|
before_script:
|
||||||
- ./.gitlab/before_script/linux/install_deps_minimal.sh
|
- ./.gitlab/before_script/linux/install_deps_minimal.sh
|
||||||
script:
|
script:
|
||||||
- ./.gitlab/script/ghcup_bootstrap.sh
|
- ./.gitlab/script/ghcup_bootstrap.sh
|
||||||
variables:
|
variables:
|
||||||
GHC_VERSION: "8.10.5"
|
GHC_VERSION: "8.10.7"
|
||||||
CABAL_VERSION: "3.4.0.0"
|
CABAL_VERSION: "3.6.2.0"
|
||||||
extends:
|
extends:
|
||||||
- .debian
|
- .debian
|
||||||
- .root_cleanup
|
- .root_cleanup
|
||||||
needs: []
|
needs: []
|
||||||
|
|
||||||
test:windows:bootstrap_powershell_script:
|
test:windows:bootstrap_powershell_script:
|
||||||
stage: test
|
stage: quick-test
|
||||||
script:
|
script:
|
||||||
- ./bootstrap-haskell.ps1 -InstallDir $CI_PROJECT_DIR -BootstrapUrl $CI_PROJECT_DIR/bootstrap-haskell -InBash
|
- ./scripts/bootstrap/bootstrap-haskell.ps1 -InstallDir $CI_PROJECT_DIR -BootstrapUrl $CI_PROJECT_DIR/bootstrap-haskell -InBash
|
||||||
after_script:
|
after_script:
|
||||||
- "[Environment]::SetEnvironmentVariable('GHCUP_INSTALL_BASE_PREFIX', $null, [System.EnvironmentVariableTarget]::User)"
|
- "[Environment]::SetEnvironmentVariable('GHCUP_INSTALL_BASE_PREFIX', $null, [System.EnvironmentVariableTarget]::User)"
|
||||||
- "[Environment]::SetEnvironmentVariable('GHCUP_MSYS2', $null, [System.EnvironmentVariableTarget]::User)"
|
- "[Environment]::SetEnvironmentVariable('GHCUP_MSYS2', $null, [System.EnvironmentVariableTarget]::User)"
|
||||||
- "[Environment]::SetEnvironmentVariable('CABAL_DIR', $null, [System.EnvironmentVariableTarget]::User)"
|
- "[Environment]::SetEnvironmentVariable('CABAL_DIR', $null, [System.EnvironmentVariableTarget]::User)"
|
||||||
- bash ./.gitlab/after_script.sh
|
- bash ./.gitlab/after_script.sh
|
||||||
|
- bash ./.gitlab/script/ci.sh save_cabal_cache
|
||||||
variables:
|
variables:
|
||||||
GHC_VERSION: "8.10.5"
|
GHC_VERSION: "8.10.7"
|
||||||
CABAL_VERSION: "3.4.0.0"
|
CABAL_VERSION: "3.6.2.0"
|
||||||
extends:
|
extends:
|
||||||
- .windows
|
- .windows
|
||||||
needs: []
|
needs: []
|
||||||
|
|
||||||
######## linux test ########
|
######## linux test ########
|
||||||
|
|
||||||
test:linux:recommended:
|
test:linux:
|
||||||
stage: test
|
stage: test
|
||||||
extends: .test_ghcup_version:linux
|
extends: .test_ghcup_version:linux
|
||||||
variables:
|
variables:
|
||||||
GHC_VERSION: "8.10.5"
|
GHC_VERSION: "8.10.7"
|
||||||
CABAL_VERSION: "3.4.0.0"
|
CABAL_VERSION: "3.6.2.0"
|
||||||
needs: []
|
needs: []
|
||||||
|
|
||||||
test:linux:latest:
|
test:linux:hls:
|
||||||
stage: test
|
stage: expensive-test
|
||||||
extends: .test_ghcup_version:linux
|
|
||||||
variables:
|
|
||||||
GHC_VERSION: "9.0.1"
|
|
||||||
CABAL_VERSION: "3.4.0.0"
|
|
||||||
needs: []
|
|
||||||
|
|
||||||
test:linux:cross-armv7:
|
|
||||||
stage: test
|
|
||||||
extends:
|
extends:
|
||||||
- .test_ghcup_version
|
- .test_ghcup_version
|
||||||
- .debian
|
- .debian
|
||||||
variables:
|
variables:
|
||||||
GHC_VERSION: "8.10.4"
|
GHC_VERSION: "8.10.7"
|
||||||
GHC_TARGET_VERSION: "8.10.5"
|
HLS_TARGET_VERSION: "1.4.0"
|
||||||
CABAL_VERSION: "3.4.0.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"
|
CROSS: "arm-linux-gnueabihf"
|
||||||
needs: []
|
needs: []
|
||||||
when: manual
|
when: manual
|
||||||
@@ -290,15 +371,15 @@ test:linux:cross-armv7:
|
|||||||
- ./.gitlab/script/ghcup_cross.sh
|
- ./.gitlab/script/ghcup_cross.sh
|
||||||
|
|
||||||
test:linux:git:hadrian:
|
test:linux:git:hadrian:
|
||||||
stage: test
|
stage: expensive-test
|
||||||
extends:
|
extends:
|
||||||
- .test_ghcup_version
|
- .test_ghcup_version
|
||||||
- .debian
|
- .debian
|
||||||
variables:
|
variables:
|
||||||
GHC_VERSION: "8.10.5"
|
GHC_VERSION: "8.10.7"
|
||||||
GHC_GIT_TAG: "ghc-9.0.1-release"
|
GHC_GIT_TAG: "ghc-9.0.1-release"
|
||||||
GHC_GIT_VERSION: "9.0.1"
|
GHC_GIT_VERSION: "9.0.1"
|
||||||
CABAL_VERSION: "3.4.0.0"
|
CABAL_VERSION: "3.6.2.0"
|
||||||
CROSS: ""
|
CROSS: ""
|
||||||
needs: []
|
needs: []
|
||||||
when: manual
|
when: manual
|
||||||
@@ -311,84 +392,87 @@ test:linux:git:hadrian:
|
|||||||
|
|
||||||
######## linux 32bit test ########
|
######## linux 32bit test ########
|
||||||
|
|
||||||
test:linux:recommended:32bit:
|
test:linux:32bit:
|
||||||
stage: test
|
stage: test
|
||||||
extends: .test_ghcup_version:linux32
|
extends: .test_ghcup_version:linux32
|
||||||
variables:
|
variables:
|
||||||
GHC_VERSION: "8.10.5"
|
GHC_VERSION: "8.10.7"
|
||||||
CABAL_VERSION: "3.2.0.0"
|
CABAL_VERSION: "3.6.2.0"
|
||||||
needs: []
|
needs: []
|
||||||
|
|
||||||
######## arm tests ########
|
######## arm tests ########
|
||||||
|
|
||||||
test:linux:recommended:armv7:
|
test:linux:armv7:
|
||||||
stage: test
|
stage: test
|
||||||
extends: .test_ghcup_version:armv7
|
extends: .test_ghcup_version:armv7
|
||||||
variables:
|
variables:
|
||||||
GHC_VERSION: "8.10.4"
|
GHC_VERSION: "8.10.7"
|
||||||
CABAL_VERSION: "3.4.0.0"
|
CABAL_VERSION: "3.6.2.0"
|
||||||
CROSS: ""
|
CROSS: ""
|
||||||
when: manual
|
when: manual
|
||||||
needs: []
|
needs: []
|
||||||
|
|
||||||
test:linux:recommended:aarch64:
|
test:linux:aarch64:
|
||||||
stage: test
|
stage: test
|
||||||
extends: .test_ghcup_version:aarch64
|
extends: .test_ghcup_version:aarch64
|
||||||
variables:
|
variables:
|
||||||
GHC_VERSION: "8.10.4"
|
GHC_VERSION: "8.10.7"
|
||||||
CABAL_VERSION: "3.4.0.0"
|
CABAL_VERSION: "3.6.2.0"
|
||||||
CROSS: ""
|
CROSS: ""
|
||||||
when: manual
|
when: manual
|
||||||
needs: []
|
needs: []
|
||||||
|
|
||||||
######## darwin test ########
|
######## darwin test ########
|
||||||
|
|
||||||
test:mac:recommended:
|
test:mac:
|
||||||
stage: test
|
stage: test
|
||||||
extends: .test_ghcup_version:darwin
|
extends: .test_ghcup_version:darwin
|
||||||
variables:
|
variables:
|
||||||
GHC_VERSION: "8.10.4"
|
GHC_VERSION: "8.10.7"
|
||||||
CABAL_VERSION: "3.4.0.0"
|
CABAL_VERSION: "3.6.2.0"
|
||||||
needs: []
|
needs: []
|
||||||
|
|
||||||
test:mac:latest:
|
test:mac:aarch64:
|
||||||
stage: test
|
|
||||||
extends: .test_ghcup_version:darwin
|
|
||||||
variables:
|
|
||||||
GHC_VERSION: "9.0.1"
|
|
||||||
CABAL_VERSION: "3.4.0.0"
|
|
||||||
needs: []
|
|
||||||
|
|
||||||
test:mac:recommended:aarch64:
|
|
||||||
stage: test
|
stage: test
|
||||||
extends: .test_ghcup_version:darwin:aarch64
|
extends: .test_ghcup_version:darwin:aarch64
|
||||||
variables:
|
variables:
|
||||||
GHC_VERSION: "8.10.5"
|
GHC_VERSION: "8.10.7"
|
||||||
CABAL_VERSION: "3.4.0.0"
|
CABAL_VERSION: "3.6.2.0"
|
||||||
needs: []
|
needs: []
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
|
||||||
######## freebsd test ########
|
######## freebsd test ########
|
||||||
|
|
||||||
test:freebsd:recommended:
|
test:freebsd12:
|
||||||
stage: test
|
stage: test
|
||||||
extends: .test_ghcup_version:freebsd
|
extends: .test_ghcup_version:freebsd12
|
||||||
variables:
|
variables:
|
||||||
GHC_VERSION: "8.10.4"
|
GHC_VERSION: "8.10.7"
|
||||||
CABAL_VERSION: "3.4.0.0"
|
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
|
allow_failure: true # freebsd runners are unreliable
|
||||||
when: manual
|
when: manual
|
||||||
needs: []
|
needs: []
|
||||||
|
|
||||||
######## windows test ########
|
######## windows test ########
|
||||||
|
|
||||||
test:windows:recommended:
|
test:windows:
|
||||||
stage: test
|
stage: test
|
||||||
extends: .test_ghcup_version:windows
|
extends: .test_ghcup_version:windows
|
||||||
variables:
|
variables:
|
||||||
GHC_VERSION: "8.10.5"
|
GHC_VERSION: "8.10.7"
|
||||||
CABAL_VERSION: "3.4.0.0"
|
CABAL_VERSION: "3.6.2.0"
|
||||||
needs: []
|
needs: []
|
||||||
|
|
||||||
# test:windows:scoop:
|
# test:windows:scoop:
|
||||||
@@ -400,7 +484,7 @@ test:windows:recommended:
|
|||||||
|
|
||||||
release:linux:64bit:
|
release:linux:64bit:
|
||||||
stage: release
|
stage: release
|
||||||
needs: ["test:linux:recommended", "test:linux:latest"]
|
needs: ["test:linux"]
|
||||||
extends:
|
extends:
|
||||||
- .alpine:64bit
|
- .alpine:64bit
|
||||||
- .release_ghcup
|
- .release_ghcup
|
||||||
@@ -408,13 +492,13 @@ release:linux:64bit:
|
|||||||
- ./.gitlab/before_script/linux/alpine/install_deps.sh
|
- ./.gitlab/before_script/linux/alpine/install_deps.sh
|
||||||
variables:
|
variables:
|
||||||
ARTIFACT: "x86_64-linux-ghcup"
|
ARTIFACT: "x86_64-linux-ghcup"
|
||||||
GHC_VERSION: "8.10.5"
|
GHC_VERSION: "8.10.7"
|
||||||
CABAL_VERSION: "3.4.0.0"
|
CABAL_VERSION: "3.6.2.0"
|
||||||
|
|
||||||
|
|
||||||
release:linux:32bit:
|
release:linux:32bit:
|
||||||
stage: release
|
stage: release
|
||||||
needs: ["test:linux:recommended:32bit"]
|
needs: ["test:linux:32bit"]
|
||||||
extends:
|
extends:
|
||||||
- .alpine:32bit
|
- .alpine:32bit
|
||||||
- .release_ghcup
|
- .release_ghcup
|
||||||
@@ -422,12 +506,12 @@ release:linux:32bit:
|
|||||||
- ./.gitlab/before_script/linux/alpine/install_deps.sh
|
- ./.gitlab/before_script/linux/alpine/install_deps.sh
|
||||||
variables:
|
variables:
|
||||||
ARTIFACT: "i386-linux-ghcup"
|
ARTIFACT: "i386-linux-ghcup"
|
||||||
GHC_VERSION: "8.10.5"
|
GHC_VERSION: "8.10.7"
|
||||||
CABAL_VERSION: "3.2.0.0"
|
CABAL_VERSION: "3.6.2.0"
|
||||||
|
|
||||||
release:linux:armv7:
|
release:linux:armv7:
|
||||||
stage: release
|
stage: release
|
||||||
needs: ["test:linux:recommended:armv7"]
|
needs: ["test:linux:armv7"]
|
||||||
extends:
|
extends:
|
||||||
- .linux:armv7
|
- .linux:armv7
|
||||||
- .release_ghcup
|
- .release_ghcup
|
||||||
@@ -435,13 +519,13 @@ release:linux:armv7:
|
|||||||
- ./.gitlab/before_script/linux/install_deps.sh
|
- ./.gitlab/before_script/linux/install_deps.sh
|
||||||
variables:
|
variables:
|
||||||
ARTIFACT: "armv7-linux-ghcup"
|
ARTIFACT: "armv7-linux-ghcup"
|
||||||
GHC_VERSION: "8.10.4"
|
GHC_VERSION: "8.10.7"
|
||||||
CABAL_VERSION: "3.4.0.0"
|
CABAL_VERSION: "3.6.2.0"
|
||||||
CROSS: ""
|
CROSS: ""
|
||||||
|
|
||||||
release:linux:aarch64:
|
release:linux:aarch64:
|
||||||
stage: release
|
stage: release
|
||||||
needs: ["test:linux:recommended:aarch64"]
|
needs: ["test:linux:aarch64"]
|
||||||
extends:
|
extends:
|
||||||
- .linux:aarch64
|
- .linux:aarch64
|
||||||
- .release_ghcup
|
- .release_ghcup
|
||||||
@@ -449,15 +533,15 @@ release:linux:aarch64:
|
|||||||
- ./.gitlab/before_script/linux/install_deps.sh
|
- ./.gitlab/before_script/linux/install_deps.sh
|
||||||
variables:
|
variables:
|
||||||
ARTIFACT: "aarch64-linux-ghcup"
|
ARTIFACT: "aarch64-linux-ghcup"
|
||||||
GHC_VERSION: "8.10.4"
|
GHC_VERSION: "8.10.7"
|
||||||
CABAL_VERSION: "3.4.0.0"
|
CABAL_VERSION: "3.6.2.0"
|
||||||
CROSS: ""
|
CROSS: ""
|
||||||
|
|
||||||
######## darwin release ########
|
######## darwin release ########
|
||||||
|
|
||||||
release:darwin:
|
release:darwin:
|
||||||
stage: release
|
stage: release
|
||||||
needs: ["test:mac:recommended", "test:mac:latest"]
|
needs: ["test:mac"]
|
||||||
extends:
|
extends:
|
||||||
- .darwin
|
- .darwin
|
||||||
- .release_ghcup
|
- .release_ghcup
|
||||||
@@ -466,67 +550,92 @@ release:darwin:
|
|||||||
- ./.gitlab/before_script/darwin/install_deps.sh
|
- ./.gitlab/before_script/darwin/install_deps.sh
|
||||||
variables:
|
variables:
|
||||||
ARTIFACT: "x86_64-apple-darwin-ghcup"
|
ARTIFACT: "x86_64-apple-darwin-ghcup"
|
||||||
GHC_VERSION: "8.10.5"
|
GHC_VERSION: "8.10.7"
|
||||||
CABAL_VERSION: "3.4.0.0"
|
CABAL_VERSION: "3.6.2.0"
|
||||||
MACOSX_DEPLOYMENT_TARGET: "10.7"
|
MACOSX_DEPLOYMENT_TARGET: "10.7"
|
||||||
|
|
||||||
release:darwin:aarch64:
|
release:darwin:aarch64:
|
||||||
stage: release
|
stage: release
|
||||||
needs: ["test:mac:recommended:aarch64"]
|
needs: ["test:mac:aarch64"]
|
||||||
extends:
|
extends:
|
||||||
- .darwin:aarch64
|
- .darwin:aarch64
|
||||||
- .release_ghcup
|
- .release_ghcup
|
||||||
- .root_cleanup
|
- .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: |
|
script: |
|
||||||
set -Eeuo pipefail
|
export PATH="$CI_PROJECT_DIR/.brew/opt/llvm/bin:$CI_PROJECT_DIR/.brew/bin:$CI_PROJECT_DIR/.brew/sbin:$PATH"
|
||||||
function runInNixShell() {
|
export CC=$CI_PROJECT_DIR/.brew/opt/llvm/bin/clang
|
||||||
time nix-shell $CI_PROJECT_DIR/.gitlab/shell.nix \
|
export CXX=$CI_PROJECT_DIR/.brew/opt/llvm/bin/clang++
|
||||||
-I nixpkgs=https://github.com/angerman/nixpkgs/archive/75f7281738b.tar.gz \
|
export LD=ld
|
||||||
--argstr system "aarch64-darwin" \
|
export AR=$CI_PROJECT_DIR/.brew/opt/llvm/bin/llvm-ar
|
||||||
--pure \
|
export RANLIB=$CI_PROJECT_DIR/.brew/opt/llvm/bin/llvm-ranlib
|
||||||
--keep CI_PROJECT_DIR \
|
./.gitlab/before_script/darwin/install_deps.sh
|
||||||
--keep MACOSX_DEPLOYMENT_TARGET \
|
./.gitlab/script/ghcup_release.sh
|
||||||
--keep JSON_VERSION \
|
after_script:
|
||||||
--keep ARTIFACT \
|
- ./.gitlab/script/ci.sh save_cabal_cache
|
||||||
--keep OS \
|
- ./.gitlab/script/ci.sh save_brew_cache
|
||||||
--keep ARCH \
|
|
||||||
--keep CABAL_DIR \
|
|
||||||
--keep GHC_VERSION \
|
|
||||||
--keep CABAL_VERSION \
|
|
||||||
--run "$1" 2>&1
|
|
||||||
}
|
|
||||||
runInNixShell ./.gitlab/before_script/darwin/install_deps.sh 2>&1
|
|
||||||
runInNixShell ./.gitlab/script/ghcup_release.sh 2>&1
|
|
||||||
variables:
|
variables:
|
||||||
ARTIFACT: "aarch64-apple-darwin-ghcup"
|
ARTIFACT: "aarch64-apple-darwin-ghcup"
|
||||||
GHC_VERSION: "8.10.5"
|
GHC_VERSION: "8.10.7"
|
||||||
CABAL_VERSION: "3.4.0.0"
|
CABAL_VERSION: "3.6.2.0"
|
||||||
MACOSX_DEPLOYMENT_TARGET: "10.7"
|
MACOSX_DEPLOYMENT_TARGET: "10.7"
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
|
||||||
######## freebsd release ########
|
######## freebsd release ########
|
||||||
|
|
||||||
release:freebsd:
|
release:freebsd12:
|
||||||
stage: release
|
stage: release
|
||||||
needs: ["test:freebsd:recommended"]
|
needs: ["test:freebsd12"]
|
||||||
extends:
|
extends:
|
||||||
- .freebsd
|
- .freebsd12
|
||||||
- .release_ghcup
|
- .release_ghcup
|
||||||
- .root_cleanup
|
- .root_cleanup
|
||||||
before_script:
|
before_script:
|
||||||
- ./.gitlab/before_script/freebsd/install_deps.sh
|
- ./.gitlab/before_script/freebsd/install_deps.sh
|
||||||
variables:
|
variables:
|
||||||
ARTIFACT: "x86_64-portbld-freebsd-ghcup"
|
ARTIFACT: "x86_64-portbld-freebsd-ghcup"
|
||||||
GHC_VERSION: "8.10.5"
|
GHC_VERSION: "8.10.7"
|
||||||
CABAL_VERSION: "3.4.0.0"
|
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
|
allow_failure: true
|
||||||
|
|
||||||
######## windows release ########
|
######## windows release ########
|
||||||
|
|
||||||
release:windows:
|
release:windows:
|
||||||
stage: release
|
stage: release
|
||||||
needs: ["test:windows:recommended"]
|
needs: ["test:windows"]
|
||||||
extends:
|
extends:
|
||||||
- .windows
|
- .windows
|
||||||
- .release_ghcup
|
- .release_ghcup
|
||||||
@@ -535,26 +644,46 @@ release:windows:
|
|||||||
- bash ./.gitlab/before_script/windows/install_deps.sh
|
- bash ./.gitlab/before_script/windows/install_deps.sh
|
||||||
variables:
|
variables:
|
||||||
ARTIFACT: "x86_64-mingw64-ghcup"
|
ARTIFACT: "x86_64-mingw64-ghcup"
|
||||||
GHC_VERSION: "8.10.5"
|
GHC_VERSION: "8.10.7"
|
||||||
CABAL_VERSION: "3.4.0.0"
|
CABAL_VERSION: "3.6.2.0"
|
||||||
|
|
||||||
######## hlint ########
|
######## hlint ########
|
||||||
|
|
||||||
hlint:
|
hlint:
|
||||||
stage: hlint
|
stage: checks
|
||||||
extends:
|
extends:
|
||||||
- .alpine:64bit
|
- .debian
|
||||||
before_script:
|
|
||||||
- ./.gitlab/before_script/linux/alpine/install_deps.sh
|
|
||||||
script:
|
script:
|
||||||
- ./.gitlab/script/hlint.sh
|
- curl -sSL https://raw.github.com/ndmitchell/hlint/master/misc/run.sh | sh -s -- -r lib/ test/
|
||||||
variables:
|
|
||||||
GHC_VERSION: "8.10.5"
|
|
||||||
CABAL_VERSION: "3.4.0.0"
|
|
||||||
JSON_VERSION: "0.0.4"
|
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
artifacts:
|
artifacts:
|
||||||
expire_in: 2 week
|
expire_in: 2 week
|
||||||
paths:
|
paths:
|
||||||
- report.html
|
- report.html
|
||||||
when: on_failure
|
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
|
||||||
|
|
||||||
|
|||||||
@@ -12,4 +12,8 @@ if [ "${OS}" = "WINDOWS" ] ; then
|
|||||||
rm -Rf /c/ghcup
|
rm -Rf /c/ghcup
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "${OS}" = "DARWIN" ] ; then
|
||||||
|
rm -Rf /private/tmp/.brew_tmp
|
||||||
|
fi
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ set -eux
|
|||||||
mkdir -p "${TMPDIR}"
|
mkdir -p "${TMPDIR}"
|
||||||
|
|
||||||
if [ $ARCH = 'ARM64' ] ; then
|
if [ $ARCH = 'ARM64' ] ; then
|
||||||
curl -sSfL https://downloads.haskell.org/~ghcup/0.1.15.1/aarch64-apple-darwin-ghcup-0.1.15.1 > ./ghcup-bin
|
curl -sSfL https://downloads.haskell.org/~ghcup/aarch64-apple-darwin-ghcup > ./ghcup-bin
|
||||||
chmod +x ghcup-bin
|
chmod +x ghcup-bin
|
||||||
else
|
else
|
||||||
curl -sSfL https://downloads.haskell.org/~ghcup/x86_64-apple-darwin-ghcup > ./ghcup-bin
|
curl -sSfL https://downloads.haskell.org/~ghcup/x86_64-apple-darwin-ghcup > ./ghcup-bin
|
||||||
|
|||||||
@@ -8,12 +8,20 @@ set -eux
|
|||||||
|
|
||||||
mkdir -p "${TMPDIR}"
|
mkdir -p "${TMPDIR}"
|
||||||
|
|
||||||
curl -sSfL https://downloads.haskell.org/~ghcup/x86_64-portbld-freebsd-ghcup > ./ghcup-bin
|
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
|
chmod +x ghcup-bin
|
||||||
|
|
||||||
./ghcup-bin upgrade -i -f
|
./ghcup-bin -v upgrade -i -f
|
||||||
./ghcup-bin install ${GHC_VERSION}
|
./ghcup-bin -v install ${GHC_VERSION}
|
||||||
./ghcup-bin set ${GHC_VERSION}
|
./ghcup-bin -v set ${GHC_VERSION}
|
||||||
./ghcup-bin install-cabal ${CABAL_VERSION}
|
./ghcup-bin -v install-cabal ${CABAL_VERSION}
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -52,3 +52,7 @@ apk add --no-cache \
|
|||||||
xz-dev \
|
xz-dev \
|
||||||
ncurses-static
|
ncurses-static
|
||||||
|
|
||||||
|
if [ "${ARCH}" = "32" ] ; then
|
||||||
|
apk add --no-cache \
|
||||||
|
bsd-compat-headers
|
||||||
|
fi
|
||||||
|
|||||||
@@ -7,67 +7,21 @@ set -eux
|
|||||||
mkdir -p "${TMPDIR}"
|
mkdir -p "${TMPDIR}"
|
||||||
|
|
||||||
sudo apt-get update -y
|
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
|
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
|
if [ "${CROSS}" = "arm-linux-gnueabihf" ] ; then
|
||||||
sudo apt-get install -y autoconf build-essential gcc-arm-linux-gnueabihf
|
sudo apt-get install -y gcc-arm-linux-gnueabihf
|
||||||
sudo dpkg --add-architecture armhf
|
sudo dpkg --add-architecture armhf
|
||||||
sudo apt-get update -y
|
sudo apt-get update -y
|
||||||
sudo apt-get install -y libncurses-dev:armhf
|
sudo apt-get install -y libncurses-dev:armhf
|
||||||
fi
|
fi
|
||||||
|
|
||||||
case "${ARCH}" in
|
export BOOTSTRAP_HASKELL_NONINTERACTIVE=1
|
||||||
ARM*)
|
export BOOTSTRAP_HASKELL_GHC_VERSION=$GHC_VERSION
|
||||||
case "${ARCH}" in
|
export BOOTSTRAP_HASKELL_CABAL_VERSION=$CABAL_VERSION
|
||||||
"ARM")
|
export BOOTSTRAP_HASKELL_VERBOSE=1
|
||||||
ghc_url=https://downloads.haskell.org/~ghc/${GHC_VERSION}/ghc-${GHC_VERSION}-armv7-deb10-linux.tar.xz
|
|
||||||
cabal_url=home.smart-cactus.org/~ben/cabal-install-${CABAL_VERSION}-armv7-linux-bootstrapped.tar.xz
|
|
||||||
;;
|
|
||||||
"ARM64")
|
|
||||||
ghc_url=https://downloads.haskell.org/~ghc/${GHC_VERSION}/ghc-${GHC_VERSION}-aarch64-deb10-linux.tar.xz
|
|
||||||
cabal_url=https://downloads.haskell.org/~cabal/cabal-install-${CABAL_VERSION}/cabal-install-${CABAL_VERSION}-aarch64-ubuntu-18.04.tar.xz
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
exit 1 ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
mkdir -p "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin
|
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
|
||||||
|
|
||||||
curl -O "${ghc_url}"
|
rm "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin/ghcup
|
||||||
tar -xf ghc-*.tar.*
|
|
||||||
cd ghc-${GHC_VERSION}
|
|
||||||
./configure --prefix="${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/ghc/${GHC_VERSION}
|
|
||||||
make install
|
|
||||||
for i in "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/ghc/${GHC_VERSION}/bin/*-${GHC_VERSION} ; do
|
|
||||||
ln -s "${i}" "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin/${i##*/}
|
|
||||||
done
|
|
||||||
for x in "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin/*-${GHC_VERSION} ; do
|
|
||||||
ln -s ${x##*/} ${x%-${GHC_VERSION}}
|
|
||||||
done
|
|
||||||
cd ..
|
|
||||||
rm -rf ghc-${GHC_VERSION} ghc-*.tar.*
|
|
||||||
unset x i
|
|
||||||
|
|
||||||
mkdir cabal-install
|
|
||||||
cd cabal-install
|
|
||||||
curl -O "${cabal_url}"
|
|
||||||
tar -xf cabal-install-*
|
|
||||||
mv cabal "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin/cabal
|
|
||||||
cd ..
|
|
||||||
rm -rf cabal-install
|
|
||||||
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
url=https://downloads.haskell.org/~ghcup/x86_64-linux-ghcup
|
|
||||||
|
|
||||||
curl -sSfL "${url}" > ./ghcup-bin
|
|
||||||
chmod +x ghcup-bin
|
|
||||||
|
|
||||||
./ghcup-bin upgrade -i -f
|
|
||||||
./ghcup-bin install ghc ${GHC_VERSION}
|
|
||||||
./ghcup-bin set ghc ${GHC_VERSION}
|
|
||||||
./ghcup-bin install cabal ${CABAL_VERSION}
|
|
||||||
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ mkdir -p "${TMPDIR}" "${CABAL_DIR}"
|
|||||||
mkdir -p "$GHCUP_INSTALL_BASE_PREFIX/ghcup/bin"
|
mkdir -p "$GHCUP_INSTALL_BASE_PREFIX/ghcup/bin"
|
||||||
|
|
||||||
CI_PROJECT_DIR=$(pwd)
|
CI_PROJECT_DIR=$(pwd)
|
||||||
curl -o ghcup.exe https://downloads.haskell.org/~ghcup/0.1.15.1/x86_64-mingw64-ghcup-0.1.15.1.exe
|
curl -o ghcup.exe https://downloads.haskell.org/~ghcup/x86_64-mingw64-ghcup.exe
|
||||||
chmod +x ghcup.exe
|
chmod +x ghcup.exe
|
||||||
|
|
||||||
./ghcup.exe install ${GHC_VERSION}
|
./ghcup.exe install ${GHC_VERSION}
|
||||||
|
|||||||
8734
.gitlab/ghc-8.10.3-linux.files
Normal file
8734
.gitlab/ghc-8.10.3-linux.files
Normal file
File diff suppressed because it is too large
Load Diff
10321
.gitlab/ghc-8.10.3-windows.files
Normal file
10321
.gitlab/ghc-8.10.3-windows.files
Normal file
File diff suppressed because it is too large
Load Diff
37
.gitlab/ghcup-run.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
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
|
||||||
@@ -1,9 +1,23 @@
|
|||||||
if [ "${OS}" = "WINDOWS" ] ; then
|
if [ "${OS}" = "WINDOWS" ] ; then
|
||||||
export GHCUP_INSTALL_BASE_PREFIX="$CI_PROJECT_DIR"
|
export GHCUP_INSTALL_BASE_PREFIX="$CI_PROJECT_DIR"
|
||||||
export PATH="$GHCUP_INSTALL_BASE_PREFIX/ghcup/bin:$CI_PROJECT_DIR/.local/bin:$PATH"
|
export GHCUP_BIN="$CI_PROJECT_DIR/ghcup/bin"
|
||||||
export TMPDIR="$CI_PROJECT_DIR/tmp"
|
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
|
else
|
||||||
export GHCUP_INSTALL_BASE_PREFIX="$CI_PROJECT_DIR"
|
export GHCUP_INSTALL_BASE_PREFIX="$CI_PROJECT_DIR"
|
||||||
export PATH="$CI_PROJECT_DIR/.ghcup/bin:$CI_PROJECT_DIR/.local/bin:/opt/llvm/bin:$PATH"
|
export GHCUP_BIN="$CI_PROJECT_DIR/.ghcup/bin"
|
||||||
export TMPDIR="$CI_PROJECT_DIR/tmp"
|
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
|
fi
|
||||||
|
|||||||
19
.gitlab/script/brew.sh
Executable file
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
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
|
||||||
@@ -6,25 +6,15 @@ set -eux
|
|||||||
|
|
||||||
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
||||||
|
|
||||||
ecabal() {
|
|
||||||
cabal "$@"
|
|
||||||
}
|
|
||||||
|
|
||||||
eghcup() {
|
|
||||||
ghcup -v -c -s file://$(pwd)/ghcup-${JSON_VERSION}.yaml "$@"
|
|
||||||
}
|
|
||||||
|
|
||||||
git describe --always
|
git describe --always
|
||||||
|
|
||||||
### build
|
### build
|
||||||
|
|
||||||
ecabal update
|
|
||||||
|
|
||||||
export BOOTSTRAP_HASKELL_NONINTERACTIVE=yes
|
export BOOTSTRAP_HASKELL_NONINTERACTIVE=yes
|
||||||
export BOOTSTRAP_HASKELL_GHC_VERSION=$GHC_VERSION
|
export BOOTSTRAP_HASKELL_GHC_VERSION=$GHC_VERSION
|
||||||
export BOOTSTRAP_HASKELL_CABAL_VERSION=$CABAL_VERSION
|
export BOOTSTRAP_HASKELL_CABAL_VERSION=$CABAL_VERSION
|
||||||
|
|
||||||
./bootstrap-haskell
|
./scripts/bootstrap/bootstrap-haskell
|
||||||
|
|
||||||
[ "$(ghc --numeric-version)" = "${GHC_VERSION}" ]
|
[ "$(ghc --numeric-version)" = "${GHC_VERSION}" ]
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ ecabal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
eghcup() {
|
eghcup() {
|
||||||
ghcup -v -c -s file://$CI_PROJECT_DIR/ghcup-${JSON_VERSION}.yaml "$@"
|
ghcup -v -c -s file://$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
git describe --always
|
git describe --always
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ ecabal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
eghcup() {
|
eghcup() {
|
||||||
ghcup -v -c -s file://$CI_PROJECT_DIR/ghcup-${JSON_VERSION}.yaml "$@"
|
ghcup -v -c -s file://$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
git describe --always
|
git describe --always
|
||||||
|
|||||||
51
.gitlab/script/ghcup_hls.sh
Executable file
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" ]
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ ecabal update
|
|||||||
|
|
||||||
if [ "${OS}" = "LINUX" ] ; then
|
if [ "${OS}" = "LINUX" ] ; then
|
||||||
if [ "${ARCH}" = "32" ] ; then
|
if [ "${ARCH}" = "32" ] ; then
|
||||||
ecabal build -w ghc-${GHC_VERSION} --ghc-options='-split-sections -optl-static' -ftui -ftar
|
ecabal build -w ghc-${GHC_VERSION} --ghc-options='-split-sections -optl-static' -ftui
|
||||||
elif [ "${ARCH}" = "64" ] ; then
|
elif [ "${ARCH}" = "64" ] ; then
|
||||||
ecabal build -w ghc-${GHC_VERSION} --ghc-options='-split-sections -optl-static' -ftui
|
ecabal build -w ghc-${GHC_VERSION} --ghc-options='-split-sections -optl-static' -ftui
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
set -eux
|
set -eux
|
||||||
|
|
||||||
@@ -8,6 +8,7 @@ mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
|||||||
|
|
||||||
CI_PROJECT_DIR=$(pwd)
|
CI_PROJECT_DIR=$(pwd)
|
||||||
|
|
||||||
|
|
||||||
ecabal() {
|
ecabal() {
|
||||||
cabal "$@"
|
cabal "$@"
|
||||||
}
|
}
|
||||||
@@ -18,9 +19,9 @@ raw_eghcup() {
|
|||||||
|
|
||||||
eghcup() {
|
eghcup() {
|
||||||
if [ "${OS}" = "WINDOWS" ] ; then
|
if [ "${OS}" = "WINDOWS" ] ; then
|
||||||
ghcup -v -c -s file:/$CI_PROJECT_DIR/ghcup-${JSON_VERSION}.yaml "$@"
|
ghcup -v -c -s file:/$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml "$@"
|
||||||
else
|
else
|
||||||
ghcup -v -c -s file://$CI_PROJECT_DIR/ghcup-${JSON_VERSION}.yaml "$@"
|
ghcup -v -c -s file://$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml "$@"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,6 +35,8 @@ git describe --always
|
|||||||
|
|
||||||
### build
|
### build
|
||||||
|
|
||||||
|
rm -rf "${GHCUP_DIR}"/share
|
||||||
|
|
||||||
ecabal update
|
ecabal update
|
||||||
|
|
||||||
if [ "${OS}" = "DARWIN" ] ; then
|
if [ "${OS}" = "DARWIN" ] ; then
|
||||||
@@ -42,13 +45,25 @@ if [ "${OS}" = "DARWIN" ] ; then
|
|||||||
ecabal haddock -w ghc-${GHC_VERSION} -ftui
|
ecabal haddock -w ghc-${GHC_VERSION} -ftui
|
||||||
elif [ "${OS}" = "LINUX" ] ; then
|
elif [ "${OS}" = "LINUX" ] ; then
|
||||||
if [ "${ARCH}" = "32" ] ; then
|
if [ "${ARCH}" = "32" ] ; then
|
||||||
ecabal build -w ghc-${GHC_VERSION} -finternal-downloader -ftui -ftar
|
ecabal build -w ghc-${GHC_VERSION} -finternal-downloader -ftui
|
||||||
ecabal test -w ghc-${GHC_VERSION} -finternal-downloader -ftui -ftar ghcup-test
|
ecabal test -w ghc-${GHC_VERSION} -finternal-downloader -ftui ghcup-test
|
||||||
ecabal haddock -w ghc-${GHC_VERSION} -finternal-downloader -ftui -ftar
|
ecabal haddock -w ghc-${GHC_VERSION} -finternal-downloader -ftui
|
||||||
else
|
else
|
||||||
ecabal build -w ghc-${GHC_VERSION} -finternal-downloader -ftui
|
ecabal build -w ghc-${GHC_VERSION} -finternal-downloader -ftui
|
||||||
ecabal test -w ghc-${GHC_VERSION} -finternal-downloader -ftui ghcup-test
|
ecabal test -w ghc-${GHC_VERSION} -finternal-downloader -ftui ghcup-test
|
||||||
ecabal haddock -w ghc-${GHC_VERSION} -finternal-downloader -ftui
|
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
|
fi
|
||||||
elif [ "${OS}" = "FREEBSD" ] ; then
|
elif [ "${OS}" = "FREEBSD" ] ; then
|
||||||
ecabal build -w ghc-${GHC_VERSION} -finternal-downloader -ftui --constraint="zip +disable-zstd"
|
ecabal build -w ghc-${GHC_VERSION} -finternal-downloader -ftui --constraint="zip +disable-zstd"
|
||||||
@@ -71,7 +86,6 @@ else
|
|||||||
ext=''
|
ext=''
|
||||||
fi
|
fi
|
||||||
cp "$(ecabal new-exec -w ghc-${GHC_VERSION} --verbose=0 --offline sh -- -c 'command -v ghcup')" "$CI_PROJECT_DIR"/.local/bin/ghcup${ext}
|
cp "$(ecabal new-exec -w ghc-${GHC_VERSION} --verbose=0 --offline sh -- -c 'command -v ghcup')" "$CI_PROJECT_DIR"/.local/bin/ghcup${ext}
|
||||||
cp "$(ecabal new-exec -w ghc-${GHC_VERSION} --verbose=0 --offline sh -- -c 'command -v ghcup-gen')" "$CI_PROJECT_DIR"/.local/bin/ghcup-gen${ext}
|
|
||||||
|
|
||||||
### cleanup
|
### cleanup
|
||||||
|
|
||||||
@@ -80,15 +94,41 @@ rm -rf "${GHCUP_DIR}"
|
|||||||
### manual cli based testing
|
### manual cli based testing
|
||||||
|
|
||||||
|
|
||||||
ghcup-gen check -f ghcup-${JSON_VERSION}.yaml
|
|
||||||
|
|
||||||
eghcup --numeric-version
|
eghcup --numeric-version
|
||||||
|
|
||||||
eghcup install ghc ${GHC_VERSION}
|
eghcup install ghc ${GHC_VERSION}
|
||||||
[ `$(eghcup whereis ghc ${GHC_VERSION}) --numeric-version` = "${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 set ghc ${GHC_VERSION}
|
||||||
eghcup install cabal ${CABAL_VERSION}
|
eghcup install cabal ${CABAL_VERSION}
|
||||||
[ `$(eghcup whereis cabal ${CABAL_VERSION}) --numeric-version` = "${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
|
cabal --version
|
||||||
|
|
||||||
@@ -116,7 +156,20 @@ else
|
|||||||
if [ "${OS}" = "LINUX" ] ; then
|
if [ "${OS}" = "LINUX" ] ; then
|
||||||
eghcup --downloader=wget prefetch ghc 8.10.3
|
eghcup --downloader=wget prefetch ghc 8.10.3
|
||||||
eghcup --offline install ghc 8.10.3
|
eghcup --offline install ghc 8.10.3
|
||||||
else # test wget a bit
|
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 prefetch ghc 8.10.3
|
||||||
eghcup --offline install ghc 8.10.3
|
eghcup --offline install ghc 8.10.3
|
||||||
fi
|
fi
|
||||||
@@ -126,9 +179,15 @@ else
|
|||||||
[ "$(ghc --numeric-version)" = "8.10.3" ]
|
[ "$(ghc --numeric-version)" = "8.10.3" ]
|
||||||
eghcup set ${GHC_VERSION}
|
eghcup set ${GHC_VERSION}
|
||||||
[ "$(ghc --numeric-version)" = "${ghc_ver}" ]
|
[ "$(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
|
eghcup --offline rm 8.10.3
|
||||||
[ "$(ghc --numeric-version)" = "${ghc_ver}" ]
|
[ "$(ghc --numeric-version)" = "${ghc_ver}" ]
|
||||||
|
|
||||||
|
|
||||||
|
ls -lah "$GHCUP_BIN"
|
||||||
|
|
||||||
if [ "${OS}" = "DARWIN" ] ; then
|
if [ "${OS}" = "DARWIN" ] ; then
|
||||||
eghcup install hls
|
eghcup install hls
|
||||||
$(eghcup whereis hls) --version
|
$(eghcup whereis hls) --version
|
||||||
@@ -139,29 +198,37 @@ else
|
|||||||
if [ "${ARCH}" = "64" ] ; then
|
if [ "${ARCH}" = "64" ] ; then
|
||||||
eghcup install hls
|
eghcup install hls
|
||||||
haskell-language-server-wrapper --version
|
haskell-language-server-wrapper --version
|
||||||
|
eghcup unset hls
|
||||||
|
"$GHCUP_BIN"/haskell-language-server-wrapper --version && exit 1 || echo yes
|
||||||
|
|
||||||
eghcup install stack
|
eghcup install stack
|
||||||
stack --version
|
stack --version
|
||||||
|
eghcup unset stack
|
||||||
|
"$GHCUP_BIN"/stack --version && exit 1 || echo yes
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# check that lazy loading works for 'whereis'
|
# check that lazy loading works for 'whereis'
|
||||||
cp "$CI_PROJECT_DIR/ghcup-${JSON_VERSION}.yaml" "$CI_PROJECT_DIR/ghcup-${JSON_VERSION}.yaml.bak"
|
cp "$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml" "$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml.bak"
|
||||||
echo '**' > "$CI_PROJECT_DIR/ghcup-${JSON_VERSION}.yaml"
|
echo '**' > "$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml"
|
||||||
eghcup whereis ghc $(ghc --numeric-version)
|
eghcup whereis ghc $(ghc --numeric-version)
|
||||||
mv -f "$CI_PROJECT_DIR/ghcup-${JSON_VERSION}.yaml.bak" "$CI_PROJECT_DIR/ghcup-${JSON_VERSION}.yaml"
|
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)
|
eghcup rm $(ghc --numeric-version)
|
||||||
|
|
||||||
# https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/116
|
# https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/116
|
||||||
if [ "${OS}" = "LINUX" ] ; then
|
if [ "${OS}" = "LINUX" ] ; then
|
||||||
if [ "${ARCH}" = "64" ] ; then
|
if [ "${ARCH}" = "64" ] ; then
|
||||||
eghcup install cabal -u https://oleg.fi/cabal-install-3.4.0.0-rc4/cabal-install-3.4.0.0-x86_64-ubuntu-16.04.tar.xz 3.4.0.0-rc4
|
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
|
eghcup rm cabal 3.4.0.0-rc4
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
eghcup gc -c
|
||||||
|
|
||||||
sha_sum() {
|
sha_sum() {
|
||||||
if [ "${OS}" = "FREEBSD" ] ; then
|
if [ "${OS}" = "FREEBSD" ] ; then
|
||||||
sha256 "$@"
|
sha256 "$@"
|
||||||
@@ -196,11 +263,52 @@ sha3=$(sha_sum "${GHCUP_DIR}/cache/ghcup-${JSON_VERSION}.yaml")
|
|||||||
[ "${etag2}" = "${etag3}" ]
|
[ "${etag2}" = "${etag3}" ]
|
||||||
[ "${sha2}" = "${sha3}" ]
|
[ "${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
|
||||||
eghcup upgrade -f
|
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
|
# nuke
|
||||||
eghcup nuke
|
eghcup nuke
|
||||||
[ ! -e "${GHCUP_DIR}" ]
|
[ ! -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 ]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -15,5 +15,5 @@ git describe
|
|||||||
ecabal update
|
ecabal update
|
||||||
ecabal install -w ghc-${GHC_VERSION} --installdir="$CI_PROJECT_DIR"/.local/bin hlint
|
ecabal install -w ghc-${GHC_VERSION} --installdir="$CI_PROJECT_DIR"/.local/bin hlint
|
||||||
|
|
||||||
hlint -r lib/ test/
|
hlint -r app/ lib/ test/
|
||||||
|
|
||||||
|
|||||||
@@ -1,89 +0,0 @@
|
|||||||
{ system ? "aarch64-darwin"
|
|
||||||
#, nixpkgs ? fetchTarball https://github.com/angerman/nixpkgs/archive/257cb120334.tar.gz #apple-silicon.tar.gz
|
|
||||||
, pkgs ? import <nixpkgs> { inherit system; }
|
|
||||||
, compiler ? if system == "aarch64-darwin" then "ghc8103Binary" else "ghc8103"
|
|
||||||
}: pkgs.mkShell {
|
|
||||||
# this prevents nix from trying to write the env-vars file.
|
|
||||||
# we can't really, as NIX_BUILD_TOP/env-vars is not set.
|
|
||||||
noDumpEnvVars=1;
|
|
||||||
|
|
||||||
# stop polluting LDFLAGS with -liconv
|
|
||||||
dontAddExtraLibs = true;
|
|
||||||
|
|
||||||
# we need to inject ncurses into --with-curses-libraries.
|
|
||||||
# the real fix is to teach terminfo to use libcurses on macOS.
|
|
||||||
# CONFIGURE_ARGS = "--with-intree-gmp --with-curses-libraries=${pkgs.ncurses.out}/lib";
|
|
||||||
CONFIGURE_ARGS = "--with-intree-gmp --with-curses-libraries=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib --with-iconv-includes=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include --with-iconv-libraries=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib SH=/bin/bash";
|
|
||||||
|
|
||||||
# magic speedup pony :facepalm:
|
|
||||||
#
|
|
||||||
# nix has the ugly habbit of duplicating ld flags more than necessary. This
|
|
||||||
# somewhat consolidates this.
|
|
||||||
shellHook = ''
|
|
||||||
export NIX_LDFLAGS=$(for a in $NIX_LDFLAGS; do echo $a; done |sort|uniq|xargs)
|
|
||||||
export NIX_LDFLAGS_FOR_TARGET=$(for a in $NIX_LDFLAGS_FOR_TARGET; do echo $a; done |sort|uniq|xargs)
|
|
||||||
export NIX_LDFLAGS_FOR_TARGET=$(comm -3 <(for l in $NIX_LDFLAGS_FOR_TARGET; do echo $l; done) <(for l in $NIX_LDFLAGS; do echo $l; done))
|
|
||||||
|
|
||||||
|
|
||||||
# Impurity hack for GHC releases.
|
|
||||||
#################################
|
|
||||||
# We don't want binary releases to depend on nix, thus we'll need to make sure we don't leak in references.
|
|
||||||
# GHC externally depends only on iconv and curses. However we can't force a specific curses library for
|
|
||||||
# the terminfo package, as such we'll need to make sure we only look in the system path for the curses library
|
|
||||||
# and not pick up the tinfo from the nix provided ncurses package.
|
|
||||||
#
|
|
||||||
# We also need to force us to use the systems COREFOUNDATION, not the one that nix builds. Again this is impure,
|
|
||||||
# but it will allow us to have proper binary distributions.
|
|
||||||
#
|
|
||||||
# do not use nixpkgs provided core foundation
|
|
||||||
export NIX_COREFOUNDATION_RPATH=/System/Library/Frameworks
|
|
||||||
# drop curses from the LDFLAGS, we really want the system ones, not the nix ones.
|
|
||||||
export NIX_LDFLAGS=$(for lib in $NIX_LDFLAGS; do case "$lib" in *curses*);; *) echo -n "$lib ";; esac; done;)
|
|
||||||
export NIX_CFLAGS_COMPILE+=" -Wno-nullability-completeness -Wno-availability -Wno-expansion-to-defined -Wno-builtin-requires-header -Wno-unused-command-line-argument"
|
|
||||||
|
|
||||||
# unconditionally add the MacOSX.sdk and TargetConditional.h
|
|
||||||
export NIX_CFLAGS_COMPILE+=" -isystem /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include"
|
|
||||||
|
|
||||||
'';
|
|
||||||
|
|
||||||
nativeBuildInputs = (with pkgs; [
|
|
||||||
# This needs to come *before* ghc,
|
|
||||||
# otherwise we migth end up with the clang from
|
|
||||||
# the bootstrap GHC in PATH with higher priority.
|
|
||||||
clang_11
|
|
||||||
llvm_11
|
|
||||||
|
|
||||||
haskell.compiler.${compiler}
|
|
||||||
haskell.packages.${compiler}.cabal-install
|
|
||||||
haskell.packages.${compiler}.alex
|
|
||||||
haskell.packages.${compiler}.happy # _1_19_12 is needed for older GHCs.
|
|
||||||
|
|
||||||
automake
|
|
||||||
autoconf
|
|
||||||
m4
|
|
||||||
|
|
||||||
gmp
|
|
||||||
zlib.out
|
|
||||||
zlib.dev
|
|
||||||
glibcLocales
|
|
||||||
# locale doesn't build yet :-/
|
|
||||||
# locale
|
|
||||||
|
|
||||||
git
|
|
||||||
|
|
||||||
python3
|
|
||||||
# python3Full
|
|
||||||
# python3Packages.sphinx
|
|
||||||
perl
|
|
||||||
|
|
||||||
which
|
|
||||||
wget
|
|
||||||
curl
|
|
||||||
file
|
|
||||||
|
|
||||||
xz
|
|
||||||
xlibs.lndir
|
|
||||||
|
|
||||||
cacert ])
|
|
||||||
++ (with pkgs.darwin.apple_sdk.frameworks; [ Foundation Security ]);
|
|
||||||
}
|
|
||||||
4
.gitmodules
vendored
Normal file
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
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
- ignore: {name: "Avoid lambda"}
|
- ignore: {name: "Avoid lambda"}
|
||||||
- ignore: {name: "Use uncurry"}
|
- ignore: {name: "Use uncurry"}
|
||||||
- ignore: {name: "Use replicateM"}
|
- ignore: {name: "Use replicateM"}
|
||||||
|
- ignore: {name: "Use unless"}
|
||||||
- ignore: {name: "Redundant irrefutable pattern"}
|
- ignore: {name: "Redundant irrefutable pattern"}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
25
.travis.yml
25
.travis.yml
@@ -1,25 +0,0 @@
|
|||||||
jobs:
|
|
||||||
include:
|
|
||||||
- os: osx
|
|
||||||
osx_image: xcode10.1
|
|
||||||
language: generic
|
|
||||||
env: ARTIFACT=x86_64-apple-darwin-10.13-ghcup
|
|
||||||
|
|
||||||
- os: osx
|
|
||||||
osx_image: xcode11.3
|
|
||||||
language: generic
|
|
||||||
env: ARTIFACT=x86_64-apple-darwin-10.14-ghcup
|
|
||||||
|
|
||||||
|
|
||||||
script: ".travis/build.sh"
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
provider: releases
|
|
||||||
api_key:
|
|
||||||
secure: "hT2od8Iy04tdFVuonPSWv0NX5hZDmv4al8Q0GbIWmviUetROuM7c6/MCHUcgyiw6H2L3pmH4F24GBYWpKBT3ZMbxrKXhZOZ3KPLXzlnuRlm1qymKqqwsJs3466bMftaiBr16rx1VpAuditN4A32oSmTFcQAJc84Bxn2WZ4t8hk9muS8YPyLhqg3/NxT6ob8dzNp9eS2cA0WODMb/fMzaMruRtepSK8JvuXb/SnTvaDcl9plmPzEa+eW54jwVsDps8ZpQMQlTtGIjYHIwTQ36/iLH4LoAvD7OEnB7qf753LOzmI/bvlB75xYGsLxe1qgpzPMjuG3AK0jb2KGSZCzyAyrbBFSQMIyC1gNKMtab3CohnA9WdQqAT1xrzPzA9zNw516G5Fn/z+t9Ek1f6L2OYO2hJfweNhWh+ChAIsOags2QBpqc0qjkwUS4wqxCWBdyVfgPTUoGelvjCfjQgypgIyLEHFvXt9rlj+kd97FY7nG3vxZrsvWTKKKT551OqUYX5zWTyvGR71jKyNst/p93Pg3DkRy31gHrGnG9zfNgN5tWxJqDd/suR/BAFTp0VtkFb8fR3ct7WMVeJXtE2+bKqxO5Fnocs1VjEm8pKPk7glnp0muu08kaO0h54wiSOCbk1RvO1KZtHue4wKWrHcI18dwW2WtzoBQ4P1lOSkS81UY="
|
|
||||||
file: $ARTIFACT
|
|
||||||
on:
|
|
||||||
repo: hasufell/ghcup-hs
|
|
||||||
tags: true
|
|
||||||
skip_cleanup: true
|
|
||||||
draft: true
|
|
||||||
181
CHANGELOG.md
181
CHANGELOG.md
@@ -1,5 +1,186 @@
|
|||||||
# Revision history for ghcup
|
# Revision history for ghcup
|
||||||
|
|
||||||
|
## 0.1.19.5 -- ????-?-??
|
||||||
|
|
||||||
|
* support JS cross compilers wrt [#838](https://github.com/haskell/ghcup-hs/issues/838)
|
||||||
|
|
||||||
|
## 0.1.19.4 -- 2023-7-02
|
||||||
|
|
||||||
|
* fix missing TUI for aarch64 linux binaries
|
||||||
|
|
||||||
|
## 0.1.19.3 -- 2023-6-29
|
||||||
|
|
||||||
|
* Implement support for nightlies, wrt [#824](https://github.com/haskell/ghcup-hs/issues/824)
|
||||||
|
* Fix GC with XDG dirs, fixes [#810](https://github.com/haskell/ghcup-hs/issues/810)
|
||||||
|
|
||||||
|
## 0.1.19.2 -- 2023-2-24
|
||||||
|
|
||||||
|
* Follow-up fix for JFS/ReiserFS and other filesystem that don't support `d_type`, fixes [#787](https://github.com/haskell/ghcup-hs/issues/787)
|
||||||
|
- the previous release had a bug that invalidated that broke it
|
||||||
|
* Implement 'latest-prerelease' tag wrt [#788](https://github.com/haskell/ghcup-hs/issues/788)
|
||||||
|
* Fix 'Could not parse version of stray directory.DS_Store' warnings on macOs wrt [#797](https://github.com/haskell/ghcup-hs/issues/797)
|
||||||
|
|
||||||
|
## 0.1.19.1 -- 2023-2-19
|
||||||
|
|
||||||
|
* Fix GHCup on JFS/ReiserFS and other filesystem that don't support `d_type`, fixes [#766](https://github.com/haskell/ghcup-hs/issues/766)
|
||||||
|
* Don't fail on setModificationTime, fixes [#784](https://github.com/haskell/ghcup-hs/issues/784) and many GitHub actions issues
|
||||||
|
* Make armv7/aarch64 linux binaries more portable (built on Debian buster)
|
||||||
|
* Improve usability on 'ghcup config add-release-channel', fixes [#751](https://github.com/haskell/ghcup-hs/issues/751)
|
||||||
|
* Make version shortcuts work with 'ghcup set', fixes [#757](https://github.com/haskell/ghcup-hs/issues/757)
|
||||||
|
* Don't implicitly smuggle in config options in `ghcup config set` wrt [#775](https://github.com/haskell/ghcup-hs/issues/775)
|
||||||
|
* Fix build on unix with -ftui
|
||||||
|
|
||||||
|
## 0.1.19.0 -- 2023-1-13
|
||||||
|
|
||||||
|
* restore proper support for FreeBSD and Linux armv7
|
||||||
|
* integrate with [errors.haskell.org](https://errors.haskell.org/index.html), wrt [#434](https://github.com/haskell/ghcup-hs/issues/434)
|
||||||
|
* allow to overwrite distro detection via config wrt [#421](https://github.com/haskell/ghcup-hs/issues/421)
|
||||||
|
- this is particularly useful for e.g. Ubuntu derivates, where ghcup doesn't pick the optimal bindist, also see the [GHCup documentation on overriding distro detection](https://www.haskell.org/ghcup/guide/#overriding-distro-detection)
|
||||||
|
* Add proper support for mirrors wrt [#357](https://github.com/haskell/ghcup-hs/issues/357)
|
||||||
|
* fix a (harmless) bug in `ghcup nuke` on windows
|
||||||
|
* improvements to `ghcup add-release-channel` wrt [#708](https://github.com/haskell/ghcup-hs/issues/708)
|
||||||
|
* fix building newer GHC from source wrt [#433](https://github.com/haskell/ghcup-hs/issues/433)
|
||||||
|
* Fix `ghcup install hls -u` on windows
|
||||||
|
* Fix failure with `--isolate=dir --force`
|
||||||
|
* Add `--metadata-fetching-mode` arg, fixes [#440](https://github.com/haskell/ghcup-hs/issues/440)
|
||||||
|
* Add content-length property to downloads
|
||||||
|
* [Fix a grave bug on armv7](https://github.com/haskell/ghcup-hs/commit/78ee956df2618862f421178a565c82548ff7e578) during installation wrt [#415](https://github.com/haskell/ghcup-hs/issues/415)
|
||||||
|
* improve many warning/error messages (contributions by @taylorfausak)
|
||||||
|
* some minor optimization in `ghcup whereis ghcup`
|
||||||
|
* improve `--keep=always` to not clean up directories in certain circumstances
|
||||||
|
|
||||||
|
## 0.1.18.1 -- 2022-08-06
|
||||||
|
|
||||||
|
* fix sdist and unbreak hackage, wrt [#399](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/399)
|
||||||
|
|
||||||
|
## 0.1.18.0 -- 2022-07-30
|
||||||
|
|
||||||
|
* Fix tui set wrt [#266](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/266) by Arjun Kathuria
|
||||||
|
- Ask the user to install the tool via prompt when setting an non-installed version
|
||||||
|
* improvements to safe (un-)installations
|
||||||
|
- bindists that don't support `make DESTDIR=/some/tmp/dir install` are now unsupported
|
||||||
|
- installed GHC files are now recorded to avoid use of `removePathForcibly`
|
||||||
|
- internally uses a newtype wrapper for user-input paths and restrict destructive operations to validated paths
|
||||||
|
* Add `--disable-ld-override` for darwin bindists wrt #391
|
||||||
|
* Allow passing bindist configure args wrt #377
|
||||||
|
* use of `TMPDIR` is dropped... now uses an internal tmp dir `~/.ghcup/tmp`
|
||||||
|
* improvements to error handling and warnings
|
||||||
|
* Require --isolate to have an absolute directory, fixes #367
|
||||||
|
* Fix mingw PATH handling wrt #371
|
||||||
|
* Add --mingw-path switch to `ghcup run`
|
||||||
|
* Fix `ghcup run` on windows, fixes #375
|
||||||
|
* Improve `ghcup compile <hls|ghc>`
|
||||||
|
- short hashes now work
|
||||||
|
- print the long hash in addition to the detected version
|
||||||
|
* Improve `ghcup compile hls`
|
||||||
|
- add `--git-describe-version` switch as an alternative to `--overwrite-version`
|
||||||
|
- Allow to build HLS from hackage (now is the default)
|
||||||
|
- Allow to run 'cabal update' automatically before the HLS build
|
||||||
|
- Fix parser and completer for 'ghcup compile hls --version'
|
||||||
|
* Improve `ghcup compile ghc`
|
||||||
|
- Allow to build from arbitrary GHC source dists
|
||||||
|
|
||||||
|
## 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
|
## 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 'nuke' subcommand wrt [#135](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/135), implemented by Arjun Kathuria
|
||||||
|
|||||||
75
HACKING.md
75
HACKING.md
@@ -1,75 +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 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
|
|
||||||
|
|
||||||
## Code structure
|
|
||||||
|
|
||||||
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 appropriate
|
|
||||||
yaml files: `ghcup-<yaml-ver>.yaml`.
|
|
||||||
|
|
||||||
## Common Tasks
|
|
||||||
|
|
||||||
### Adding a new GHC version
|
|
||||||
|
|
||||||
1. open the latest `ghcup-<yaml-ver>.yaml`
|
|
||||||
2. find the latest ghc version (in yaml tree e.g. `ghcupDownloads -> GHC -> 8.10.3`)
|
|
||||||
3. copy-paste it
|
|
||||||
4. adjust the version, tags, changelog, source url
|
|
||||||
5. adjust the various bindist urls (make sure to also change the yaml anchors)
|
|
||||||
6. run `cabal run exe:ghcup-gen -- check-tarballs -f ghcup-<yaml-ver>.yaml -u 'ghc-8\.10\.4'`
|
|
||||||
|
|
||||||
## 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.
|
|
||||||
392
README.md
392
README.md
@@ -1,387 +1,13 @@
|
|||||||
`ghcup` makes it easy to install specific versions of `ghc` on GNU/Linux,
|
## The GHCup Haskell installer
|
||||||
macOS (aka Darwin), FreeBSD and Windows 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).
|
|
||||||
|
|
||||||
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>
|
||||||
|
|
||||||
## Table of Contents
|
GHCup is the main installer for the general purpose language [Haskell](https://www.haskell.org/).
|
||||||
|
|
||||||
* [Installation](#installation)
|
Visit the [documentation](https://www.haskell.org/ghcup/) for installation instructions.
|
||||||
* [Simple bootstrap](#simple-bootstrap)
|
|
||||||
* [Manual install](#manual-install)
|
|
||||||
* [Vim integration](#vim-integration)
|
|
||||||
* [Usage](#usage)
|
|
||||||
* [Configuration](#configuration)
|
|
||||||
* [Manpages](#manpages)
|
|
||||||
* [Shell-completion](#shell-completion)
|
|
||||||
* [Cross support](#cross-support)
|
|
||||||
* [XDG support](#xdg-support)
|
|
||||||
* [Env variables](#env-variables)
|
|
||||||
* [Installing custom bindists](#installing-custom-bindists)
|
|
||||||
* [Tips and tricks](#tips-and-tricks)
|
|
||||||
* [Design goals](#design-goals)
|
|
||||||
* [How](#how)
|
|
||||||
* [Known users](#known-users)
|
|
||||||
* [Known problems](#known-problems)
|
|
||||||
* [FAQ](#faq)
|
|
||||||
|
|
||||||
## Installation
|
If you're looking for the metadata YAML files, see here: [https://github.com/haskell/ghcup-metadata](https://github.com/haskell/ghcup-metadata)
|
||||||
|
|
||||||
### 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"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Vim integration
|
|
||||||
|
|
||||||
See [ghcup.vim](https://github.com/hasufell/ghcup.vim).
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
See `ghcup --help`.
|
|
||||||
|
|
||||||
For the simple interactive TUI, 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
|
|
||||||
```
|
|
||||||
|
|
||||||
GHCup works very well 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.
|
|
||||||
|
|
||||||
### 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](./config.yaml).
|
|
||||||
|
|
||||||
Partial configuration is fine. Command line options always override the config file settings.
|
|
||||||
|
|
||||||
### 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 `shell-completions`.
|
|
||||||
|
|
||||||
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).
|
|
||||||
|
|
||||||
### 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.
|
|
||||||
|
|
||||||
### 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.**
|
|
||||||
|
|
||||||
### Env variables
|
|
||||||
|
|
||||||
This is the complete list of env variables that change GHCup behavior:
|
|
||||||
|
|
||||||
* `GHCUP_USE_XDG_DIRS`: see [XDG support](#xdg-support) above
|
|
||||||
* `TMPDIR`: where ghcup does the work (unpacking, building, ...)
|
|
||||||
* `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_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
|
|
||||||
|
|
||||||
### 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).
|
|
||||||
|
|
||||||
### Tips and tricks
|
|
||||||
|
|
||||||
#### with_ghc wrapper (e.g. for HLS)
|
|
||||||
|
|
||||||
Due to some HLS [bugs](https://github.com/mpickering/hie-bios/issues/194) it's necessary that the `ghc` in PATH
|
|
||||||
is the one defined in `cabal.project`. With some simple shell functions, we can start our editor with the appropriate
|
|
||||||
path prepended.
|
|
||||||
|
|
||||||
For bash, in e.g. `~/.bashrc` define:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
with_ghc() {
|
|
||||||
local np=$(ghcup --offline whereis -d ghc $1 || { ghcup --cache install ghc $1 && ghcup whereis -d ghc $1 ;})
|
|
||||||
if [ -e "${np}" ] ; then
|
|
||||||
shift
|
|
||||||
PATH="$np:$PATH" "$@"
|
|
||||||
else
|
|
||||||
>&2 echo "Cannot find or install GHC version $1"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
For fish shell, in e.g. `~/.config/fish/config.fish` define:
|
|
||||||
|
|
||||||
```fish
|
|
||||||
function with_ghc
|
|
||||||
set --local np (ghcup --offline whereis -d ghc $argv[1] ; or begin ghcup --cache install ghc $argv[1] ; and ghcup whereis -d ghc $argv[1] ; end)
|
|
||||||
if test -e "$np"
|
|
||||||
PATH="$np:$PATH" $argv[2..-1]
|
|
||||||
else
|
|
||||||
echo "Cannot find or install GHC version $argv[1]" 1>&2
|
|
||||||
return 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
Then start a new shell and issue:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# replace 'code' with your editor
|
|
||||||
with_ghc 8.10.5 code path/to/haskell/source
|
|
||||||
```
|
|
||||||
|
|
||||||
Cabal and HLS will now see `8.10.5` as the primary GHC, without the need to
|
|
||||||
run `ghcup set` all the time when switching between projects.
|
|
||||||
|
|
||||||
## 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
|
|
||||||
|
|
||||||
* Github action [haskell/actions/setup](https://github.com/haskell/actions/tree/main/setup)
|
|
||||||
* [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?
|
|
||||||
|
|
||||||
Oddly, this question has been asked a couple of times. For the curious, here are a few reasons:
|
|
||||||
|
|
||||||
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. Even if they did, it doesn't seem it would have satisfied their needs
|
|
||||||
- it didn't support cabal installation, which was the main motivation behind GHCup back then
|
|
||||||
- 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
|
|
||||||
- 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.
|
|
||||||
3. GHCup is built around unix principles and supposed to be simple.
|
|
||||||
|
|
||||||
### 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.
|
|
||||||
|
|
||||||
How bad do we need this?
|
|
||||||
|
|
||||||
### 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.
|
|
||||||
|
|
||||||
### Is GHCup affiliated with the Haskell Foundation?
|
|
||||||
|
|
||||||
There has been some collaboration: Windows and Stack support were mainly requested by the Haskell Foundation
|
|
||||||
and those seemed interesting features to add.
|
|
||||||
|
|
||||||
Other than that, GHCup is dedicated only to its users and is supported by haskell.org through hosting and CI
|
|
||||||
infrastructure.
|
|
||||||
|
|||||||
19
RELEASING.md
19
RELEASING.md
@@ -1,19 +0,0 @@
|
|||||||
# RELEASING
|
|
||||||
|
|
||||||
1. update `GHCup.Version` module. `ghcupURL` must only be updated if we change the `_toolRequirements` type or the YAML representation of it. The version of the YAML represents the change increments. `ghcUpVer` is the current application version.
|
|
||||||
|
|
||||||
2. Update version in ghcup.cabal
|
|
||||||
|
|
||||||
3. Add ChangeLog entry
|
|
||||||
|
|
||||||
4. Add/fix downloads in `ghcup-<ver>.yaml`, then verify with `ghcup-gen check -f ghcup-<ver>.yaml`
|
|
||||||
|
|
||||||
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`
|
|
||||||
|
|
||||||
7. Add release artifacts to yaml file (see point 4.)
|
|
||||||
|
|
||||||
8. Upload the final `ghcup-<ver>.yaml` to `webhost.haskell.org/ghcup/data/`.
|
|
||||||
|
|
||||||
9. Update bootstrap-haskell and symlinks on `downloads.haskell.org/ghcup`
|
|
||||||
@@ -1,127 +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 Data.Char ( toLower )
|
|
||||||
#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 Text.Regex.Posix
|
|
||||||
import Validate
|
|
||||||
|
|
||||||
import qualified Data.ByteString as B
|
|
||||||
import qualified Data.Yaml as Y
|
|
||||||
|
|
||||||
|
|
||||||
data Options = Options
|
|
||||||
{ optCommand :: Command
|
|
||||||
}
|
|
||||||
|
|
||||||
data Command = ValidateYAML ValidateYAMLOpts
|
|
||||||
| ValidateTarballs ValidateYAMLOpts TarballFilter
|
|
||||||
|
|
||||||
|
|
||||||
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 ValidateYAMLOpts = ValidateYAMLOpts
|
|
||||||
{ vInput :: Maybe Input
|
|
||||||
}
|
|
||||||
|
|
||||||
validateYAMLOpts :: Parser ValidateYAMLOpts
|
|
||||||
validateYAMLOpts = ValidateYAMLOpts <$> optional inputP
|
|
||||||
|
|
||||||
tarballFilterP :: Parser TarballFilter
|
|
||||||
tarballFilterP = option readm $
|
|
||||||
long "tarball-filter" <> short 'u' <> metavar "<tool>-<version>" <> value def
|
|
||||||
<> help "Only check certain tarballs (format: <tool>-<version>)"
|
|
||||||
where
|
|
||||||
def = TarballFilter (Right Nothing) (makeRegex ("" :: String))
|
|
||||||
readm = do
|
|
||||||
s <- str
|
|
||||||
case span (/= '-') s of
|
|
||||||
(_, []) -> fail "invalid format, missing '-' after the tool name"
|
|
||||||
(t, v) | [tool] <- [ tool | tool <- [minBound..maxBound], low (show tool) == low t ] ->
|
|
||||||
pure (TarballFilter $ Right $ Just tool) <*> makeRegexOptsM compIgnoreCase execBlank (drop 1 v)
|
|
||||||
(t, v) | [tool] <- [ tool | tool <- [minBound..maxBound], low (show tool) == low t ] ->
|
|
||||||
pure (TarballFilter $ Left tool) <*> makeRegexOptsM compIgnoreCase execBlank (drop 1 v)
|
|
||||||
_ -> fail "invalid tool"
|
|
||||||
low = fmap toLower
|
|
||||||
|
|
||||||
|
|
||||||
opts :: Parser Options
|
|
||||||
opts = Options <$> com
|
|
||||||
|
|
||||||
com :: Parser Command
|
|
||||||
com = subparser
|
|
||||||
( command
|
|
||||||
"check"
|
|
||||||
( ValidateYAML
|
|
||||||
<$> info (validateYAMLOpts <**> helper)
|
|
||||||
(progDesc "Validate the YAML")
|
|
||||||
)
|
|
||||||
<> command
|
|
||||||
"check-tarballs"
|
|
||||||
(info
|
|
||||||
((ValidateTarballs <$> validateYAMLOpts <*> tarballFilterP) <**> helper)
|
|
||||||
(progDesc "Validate all tarballs (download and checksum)")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
main :: IO ()
|
|
||||||
main = do
|
|
||||||
_ <- customExecParser (prefs showHelpOnError) (info (opts <**> helper) idm)
|
|
||||||
>>= \Options {..} -> case optCommand of
|
|
||||||
ValidateYAML vopts -> withValidateYamlOpts vopts validate
|
|
||||||
ValidateTarballs vopts tarballFilter -> withValidateYamlOpts vopts (validateTarballs tarballFilter)
|
|
||||||
pure ()
|
|
||||||
|
|
||||||
where
|
|
||||||
withValidateYamlOpts vopts f = case vopts of
|
|
||||||
ValidateYAMLOpts { vInput = Nothing } ->
|
|
||||||
B.getContents >>= valAndExit f
|
|
||||||
ValidateYAMLOpts { vInput = Just StdInput } ->
|
|
||||||
B.getContents >>= valAndExit f
|
|
||||||
ValidateYAMLOpts { vInput = Just (FileInput file) } ->
|
|
||||||
B.readFile file >>= valAndExit f
|
|
||||||
valAndExit f contents = do
|
|
||||||
(GHCupInfo _ av gt) <- case Y.decodeEither' contents of
|
|
||||||
Right r -> pure r
|
|
||||||
Left e -> die (color Red $ show e)
|
|
||||||
myLoggerT (LoggerConfig True (B.hPut stdout) (\_ -> pure ())) (f av gt)
|
|
||||||
>>= exitWith
|
|
||||||
@@ -1,297 +0,0 @@
|
|||||||
{-# LANGUAGE CPP #-}
|
|
||||||
{-# LANGUAGE DataKinds #-}
|
|
||||||
{-# LANGUAGE FlexibleContexts #-}
|
|
||||||
{-# LANGUAGE QuasiQuotes #-}
|
|
||||||
{-# LANGUAGE TemplateHaskell #-}
|
|
||||||
{-# LANGUAGE TypeApplications #-}
|
|
||||||
{-# LANGUAGE ViewPatterns #-}
|
|
||||||
|
|
||||||
module Validate where
|
|
||||||
|
|
||||||
import GHCup
|
|
||||||
import GHCup.Download
|
|
||||||
import GHCup.Errors
|
|
||||||
import GHCup.Platform
|
|
||||||
import GHCup.Types hiding ( LeanAppState (..) )
|
|
||||||
import GHCup.Types.Optics
|
|
||||||
import GHCup.Utils
|
|
||||||
import GHCup.Utils.Logger
|
|
||||||
import GHCup.Utils.Version.QQ
|
|
||||||
|
|
||||||
#if defined(TAR)
|
|
||||||
import qualified Codec.Archive.Tar as Tar
|
|
||||||
#else
|
|
||||||
import Codec.Archive
|
|
||||||
#endif
|
|
||||||
import Control.Applicative
|
|
||||||
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.Containers.ListUtils ( nubOrd )
|
|
||||||
import Data.IORef
|
|
||||||
import Data.List
|
|
||||||
import Data.String.Interpolate
|
|
||||||
import Data.Versions
|
|
||||||
import Haskus.Utils.Variant.Excepts
|
|
||||||
import Optics
|
|
||||||
import System.FilePath
|
|
||||||
import System.Exit
|
|
||||||
import System.IO
|
|
||||||
import Text.ParserCombinators.ReadP
|
|
||||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
|
||||||
import Text.Regex.Posix
|
|
||||||
|
|
||||||
import qualified Data.ByteString as B
|
|
||||||
import qualified Data.Map.Strict as M
|
|
||||||
import qualified Data.Text as T
|
|
||||||
import qualified Data.Version as V
|
|
||||||
|
|
||||||
|
|
||||||
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.Map GlobalTool DownloadInfo
|
|
||||||
-> 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 (_viTags vi) arch (M.keys pspecs)
|
|
||||||
|
|
||||||
checkGHCVerIsValid
|
|
||||||
forM_ (M.toList dls) $ \(t, _) -> checkMandatoryTags t
|
|
||||||
_ <- checkGHCHasBaseVersion
|
|
||||||
|
|
||||||
-- 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 tags arch pspecs = do
|
|
||||||
let v' = prettyVer v
|
|
||||||
arch' = prettyShow arch
|
|
||||||
when (notElem (Linux UnknownLinux) pspecs) $ do
|
|
||||||
lift $ $(logError)
|
|
||||||
[i|Linux UnknownLinux missing for for #{t} #{v'} #{arch'}|]
|
|
||||||
addError
|
|
||||||
when ((notElem Darwin pspecs) && arch == A_64) $ do
|
|
||||||
lift $ $(logError) [i|Darwin missing for #{t} #{v'} #{arch'}|]
|
|
||||||
addError
|
|
||||||
when ((notElem FreeBSD pspecs) && arch == A_64) $ lift $ $(logWarn)
|
|
||||||
[i|FreeBSD missing for #{t} #{v'} #{arch'}|]
|
|
||||||
when (notElem Windows pspecs && arch == A_64) $ do
|
|
||||||
lift $ $(logError)
|
|
||||||
[i|Windows missing for for #{t} #{v'} #{arch'}|]
|
|
||||||
addError
|
|
||||||
|
|
||||||
-- alpine needs to be set explicitly, because
|
|
||||||
-- we cannot assume that "Linux UnknownLinux" runs on Alpine
|
|
||||||
-- (although it could be static)
|
|
||||||
when (notElem (Linux Alpine) pspecs) $
|
|
||||||
case t of
|
|
||||||
GHCup | arch `elem` [A_64, A_32] -> lift ($(logError) [i|Linux Alpine missing for #{t} #{v'} #{arch}|]) >> addError
|
|
||||||
Cabal | v > [vver|2.4.1.0|]
|
|
||||||
, arch `elem` [A_64, A_32] -> lift ($(logError) [i|Linux Alpine missing for #{t} #{v'} #{arch'}|]) >> addError
|
|
||||||
GHC | Latest `elem` tags || Recommended `elem` tags
|
|
||||||
, arch `elem` [A_64, A_32] -> lift ($(logError) [i|Linux Alpine missing for #{t} #{v'} #{arch'}|])
|
|
||||||
_ -> lift $ $(logWarn) [i|Linux Alpine missing for #{t} #{v'} #{arch'}|]
|
|
||||||
|
|
||||||
checkUniqueTags tool = do
|
|
||||||
let allTags = join $ fmap _viTags $ M.elems $ availableToolVersions dls tool
|
|
||||||
let nonUnique =
|
|
||||||
fmap fst
|
|
||||||
. filter (\(_, b) -> not b)
|
|
||||||
<$> ( mapM
|
|
||||||
(\case
|
|
||||||
[] -> throwM $ InternalError "empty inner list"
|
|
||||||
(t : ts) ->
|
|
||||||
pure $ (t, ) (not (isUniqueTag t) || null ts)
|
|
||||||
)
|
|
||||||
. 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
|
|
||||||
isUniqueTag Old = False
|
|
||||||
isUniqueTag Prerelease = False
|
|
||||||
isUniqueTag (Base _) = False
|
|
||||||
isUniqueTag (UnknownTag _) = False
|
|
||||||
|
|
||||||
checkGHCVerIsValid = do
|
|
||||||
let ghcVers = toListOf (ix GHC % to M.keys % folded) dls
|
|
||||||
forM_ ghcVers $ \v ->
|
|
||||||
case [ x | (x,"") <- readP_to_S V.parseVersion (T.unpack . prettyVer $ v) ] of
|
|
||||||
[_] -> pure ()
|
|
||||||
_ -> do
|
|
||||||
lift $ $(logError) [i|GHC version #{v} is not valid |]
|
|
||||||
addError
|
|
||||||
|
|
||||||
-- a tool must have at least one of each mandatory tags
|
|
||||||
checkMandatoryTags tool = do
|
|
||||||
let allTags = join $ fmap _viTags $ M.elems $ 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 ()
|
|
||||||
|
|
||||||
-- all GHC versions must have a base tag
|
|
||||||
checkGHCHasBaseVersion = do
|
|
||||||
let allTags = M.toList $ availableToolVersions dls GHC
|
|
||||||
forM allTags $ \(ver, _viTags -> tags) -> case any isBase tags of
|
|
||||||
False -> do
|
|
||||||
lift $ $(logError) [i|Base tag missing from GHC ver #{ver}|]
|
|
||||||
addError
|
|
||||||
True -> pure ()
|
|
||||||
|
|
||||||
isBase (Base _) = True
|
|
||||||
isBase _ = False
|
|
||||||
|
|
||||||
data TarballFilter = TarballFilter
|
|
||||||
{ tfTool :: Either GlobalTool (Maybe Tool)
|
|
||||||
, tfVersion :: Regex
|
|
||||||
}
|
|
||||||
|
|
||||||
validateTarballs :: ( Monad m
|
|
||||||
, MonadLogger m
|
|
||||||
, MonadThrow m
|
|
||||||
, MonadIO m
|
|
||||||
, MonadUnliftIO m
|
|
||||||
, MonadMask m
|
|
||||||
, Alternative m
|
|
||||||
, MonadFail m
|
|
||||||
)
|
|
||||||
=> TarballFilter
|
|
||||||
-> GHCupDownloads
|
|
||||||
-> M.Map GlobalTool DownloadInfo
|
|
||||||
-> m ExitCode
|
|
||||||
validateTarballs (TarballFilter etool versionRegex) dls gt = do
|
|
||||||
ref <- liftIO $ newIORef 0
|
|
||||||
|
|
||||||
flip runReaderT ref $ do
|
|
||||||
-- download/verify all tarballs
|
|
||||||
let dlis = either (const []) (\tool -> nubOrd $ dls ^.. each %& indices (maybe (const True) (==) tool) %> each %& indices (matchTest versionRegex . T.unpack . prettyVer) % (viSourceDL % _Just `summing` viArch % each % each % each)) etool
|
|
||||||
let gdlis = nubOrd $ gt ^.. each
|
|
||||||
let allDls = either (const gdlis) (const dlis) etool
|
|
||||||
when (null allDls) $ $(logError) [i|no tarballs selected by filter|] *> addError
|
|
||||||
forM_ allDls downloadAll
|
|
||||||
|
|
||||||
-- exit
|
|
||||||
e <- liftIO $ readIORef ref
|
|
||||||
if e > 0
|
|
||||||
then pure $ ExitFailure e
|
|
||||||
else do
|
|
||||||
lift $ $(logInfo) [i|All good|]
|
|
||||||
pure ExitSuccess
|
|
||||||
|
|
||||||
where
|
|
||||||
runLogger = myLoggerT LoggerConfig { lcPrintDebug = True
|
|
||||||
, colorOutter = B.hPut stderr
|
|
||||||
, rawOutter = \_ -> pure ()
|
|
||||||
}
|
|
||||||
downloadAll dli = do
|
|
||||||
dirs <- liftIO getAllDirs
|
|
||||||
|
|
||||||
pfreq <- (
|
|
||||||
runLogger . runE @'[NoCompatiblePlatform, NoCompatibleArch, DistroNotFound] . liftE $ platformRequest
|
|
||||||
) >>= \case
|
|
||||||
VRight r -> pure r
|
|
||||||
VLeft e -> do
|
|
||||||
lift $ runLogger
|
|
||||||
($(logError) $ T.pack $ prettyShow e)
|
|
||||||
liftIO $ exitWith (ExitFailure 2)
|
|
||||||
|
|
||||||
let appstate = AppState (Settings True False Never Curl False GHCupURL False) dirs defaultKeyBindings (GHCupInfo mempty mempty mempty) pfreq
|
|
||||||
|
|
||||||
r <-
|
|
||||||
runLogger
|
|
||||||
. flip runReaderT appstate
|
|
||||||
. runResourceT
|
|
||||||
. runE @'[DigestError
|
|
||||||
, DownloadFailed
|
|
||||||
, UnknownArchive
|
|
||||||
#if defined(TAR)
|
|
||||||
, Tar.FormatError
|
|
||||||
#else
|
|
||||||
, ArchiveResult
|
|
||||||
#endif
|
|
||||||
]
|
|
||||||
$ do
|
|
||||||
case etool of
|
|
||||||
Right (Just GHCup) -> do
|
|
||||||
tmpUnpack <- lift mkGhcupTmpDir
|
|
||||||
_ <- liftE $ download (_dlUri dli) (Just (_dlHash dli)) tmpUnpack Nothing False
|
|
||||||
pure Nothing
|
|
||||||
Right _ -> do
|
|
||||||
p <- liftE $ downloadCached dli Nothing
|
|
||||||
fmap (Just . head . splitDirectories . head)
|
|
||||||
. liftE
|
|
||||||
. getArchiveFiles
|
|
||||||
$ p
|
|
||||||
Left ShimGen -> do
|
|
||||||
tmpUnpack <- lift mkGhcupTmpDir
|
|
||||||
_ <- liftE $ download (_dlUri dli) (Just (_dlHash dli)) tmpUnpack Nothing False
|
|
||||||
pure Nothing
|
|
||||||
case r of
|
|
||||||
VRight (Just basePath) -> do
|
|
||||||
case _dlSubdir dli of
|
|
||||||
Just (RealDir prel) -> do
|
|
||||||
lift $ $(logInfo)
|
|
||||||
[i|verifying subdir: #{prel}|]
|
|
||||||
when (basePath /= prel) $ do
|
|
||||||
lift $ $(logError)
|
|
||||||
[i|Subdir doesn't match: expected "#{prel}", got "#{basePath}"|]
|
|
||||||
addError
|
|
||||||
Just (RegexDir regexString) -> do
|
|
||||||
lift $ $(logInfo)
|
|
||||||
[i|verifying subdir (regex): #{regexString}|]
|
|
||||||
let regex = makeRegexOpts
|
|
||||||
compIgnoreCase
|
|
||||||
execBlank
|
|
||||||
regexString
|
|
||||||
when (not (match regex basePath)) $ do
|
|
||||||
lift $ $(logError)
|
|
||||||
[i|Subdir doesn't match: expected regex "#{regexString}", got "#{basePath}"|]
|
|
||||||
addError
|
|
||||||
Nothing -> pure ()
|
|
||||||
VRight Nothing -> pure ()
|
|
||||||
VLeft e -> do
|
|
||||||
lift $ $(logError)
|
|
||||||
[i|Could not download (or verify hash) of #{dli}, Error was: #{prettyShow e}|]
|
|
||||||
addError
|
|
||||||
@@ -2,22 +2,24 @@
|
|||||||
{-# LANGUAGE DataKinds #-}
|
{-# LANGUAGE DataKinds #-}
|
||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE QuasiQuotes #-}
|
|
||||||
{-# LANGUAGE TemplateHaskell #-}
|
|
||||||
{-# LANGUAGE TypeApplications #-}
|
{-# LANGUAGE TypeApplications #-}
|
||||||
{-# LANGUAGE ViewPatterns #-}
|
|
||||||
{-# LANGUAGE RankNTypes #-}
|
{-# LANGUAGE RankNTypes #-}
|
||||||
|
{-# LANGUAGE ViewPatterns #-}
|
||||||
|
|
||||||
module BrickMain where
|
module BrickMain where
|
||||||
|
|
||||||
import GHCup
|
import GHCup
|
||||||
import GHCup.Download
|
import GHCup.Download
|
||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
|
import GHCup.Types.Optics ( getDirs )
|
||||||
import GHCup.Types hiding ( LeanAppState(..) )
|
import GHCup.Types hiding ( LeanAppState(..) )
|
||||||
import GHCup.Utils
|
import GHCup.Utils
|
||||||
import GHCup.Utils.Prelude ( decUTF8Safe )
|
import GHCup.OptParse.Common (logGHCPostRm)
|
||||||
import GHCup.Utils.File
|
import GHCup.Prelude ( decUTF8Safe )
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Prelude.File
|
||||||
|
import GHCup.Prelude.Logger
|
||||||
|
import GHCup.Prelude.Process
|
||||||
|
import GHCup.Prompts
|
||||||
|
|
||||||
import Brick
|
import Brick
|
||||||
import Brick.Widgets.Border
|
import Brick.Widgets.Border
|
||||||
@@ -27,11 +29,11 @@ import Brick.Widgets.List ( listSelectedFocusedAttr
|
|||||||
, listSelectedAttr
|
, listSelectedAttr
|
||||||
, listAttr
|
, listAttr
|
||||||
)
|
)
|
||||||
#if !defined(TAR)
|
|
||||||
import Codec.Archive
|
import Codec.Archive
|
||||||
#endif
|
|
||||||
import Control.Exception.Safe
|
import Control.Exception.Safe
|
||||||
import Control.Monad.Logger
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
|
import Control.Monad.Fail ( MonadFail )
|
||||||
|
#endif
|
||||||
import Control.Monad.Reader
|
import Control.Monad.Reader
|
||||||
import Control.Monad.Trans.Except
|
import Control.Monad.Trans.Except
|
||||||
import Control.Monad.Trans.Resource
|
import Control.Monad.Trans.Resource
|
||||||
@@ -40,22 +42,25 @@ import Data.Functor
|
|||||||
import Data.List
|
import Data.List
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Data.IORef
|
import Data.IORef
|
||||||
import Data.String.Interpolate
|
|
||||||
import Data.Vector ( Vector
|
import Data.Vector ( Vector
|
||||||
, (!?)
|
, (!?)
|
||||||
)
|
)
|
||||||
import Data.Versions hiding ( str )
|
import Data.Versions hiding ( str )
|
||||||
import Haskus.Utils.Variant.Excepts
|
import Haskus.Utils.Variant.Excepts
|
||||||
import Prelude hiding ( appendFile )
|
import Prelude hiding ( appendFile )
|
||||||
import System.Environment
|
import System.FilePath
|
||||||
import System.Exit
|
import System.Exit
|
||||||
import System.IO.Unsafe
|
import System.IO.Unsafe
|
||||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
||||||
import URI.ByteString
|
import URI.ByteString
|
||||||
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
import qualified Data.Text.Lazy.Builder as B
|
||||||
|
import qualified Data.Text.Lazy as L
|
||||||
import qualified Graphics.Vty as Vty
|
import qualified Graphics.Vty as Vty
|
||||||
import qualified Data.Vector as V
|
import qualified Data.Vector as V
|
||||||
|
import System.Environment (getExecutablePath)
|
||||||
|
import qualified System.Posix.Process as SPP
|
||||||
|
|
||||||
|
|
||||||
hiddenTools :: [Tool]
|
hiddenTools :: [Tool]
|
||||||
@@ -68,8 +73,8 @@ data BrickData = BrickData
|
|||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
data BrickSettings = BrickSettings
|
data BrickSettings = BrickSettings
|
||||||
{ showAllVersions :: Bool
|
{ showAllVersions :: Bool
|
||||||
, showAllTools :: Bool
|
, showAllTools :: Bool
|
||||||
}
|
}
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
@@ -91,14 +96,14 @@ data BrickState = BrickState
|
|||||||
keyHandlers :: KeyBindings
|
keyHandlers :: KeyBindings
|
||||||
-> [ ( Vty.Key
|
-> [ ( Vty.Key
|
||||||
, BrickSettings -> String
|
, BrickSettings -> String
|
||||||
, BrickState -> EventM n (Next BrickState)
|
, BrickState -> EventM String BrickState ()
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
keyHandlers KeyBindings {..} =
|
keyHandlers KeyBindings {..} =
|
||||||
[ (bQuit, const "Quit" , halt)
|
[ (bQuit, const "Quit" , \_ -> halt)
|
||||||
, (bInstall, const "Install" , withIOAction install')
|
, (bInstall, const "Install" , withIOAction install')
|
||||||
, (bUninstall, const "Uninstall", withIOAction del')
|
, (bUninstall, const "Uninstall", withIOAction del')
|
||||||
, (bSet, const "Set" , withIOAction ((liftIO .) . set'))
|
, (bSet, const "Set" , withIOAction set')
|
||||||
, (bChangelog, const "ChangeLog", withIOAction changelog')
|
, (bChangelog, const "ChangeLog", withIOAction changelog')
|
||||||
, ( bShowAllVersions
|
, ( bShowAllVersions
|
||||||
, \BrickSettings {..} ->
|
, \BrickSettings {..} ->
|
||||||
@@ -110,14 +115,14 @@ keyHandlers KeyBindings {..} =
|
|||||||
if showAllTools then "Don't show all tools" else "Show all tools"
|
if showAllTools then "Don't show all tools" else "Show all tools"
|
||||||
, hideShowHandler showAllVersions (not . showAllTools)
|
, hideShowHandler showAllVersions (not . showAllTools)
|
||||||
)
|
)
|
||||||
, (bUp, const "Up", \BrickState {..} -> continue BrickState{ appState = moveCursor 1 appState Up, .. })
|
, (bUp, const "Up", \BrickState {..} -> put BrickState{ appState = moveCursor 1 appState Up, .. })
|
||||||
, (bDown, const "Down", \BrickState {..} -> continue BrickState{ appState = moveCursor 1 appState Down, .. })
|
, (bDown, const "Down", \BrickState {..} -> put BrickState{ appState = moveCursor 1 appState Down, .. })
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
hideShowHandler f p BrickState{..} =
|
hideShowHandler f p BrickState{..} =
|
||||||
let newAppSettings = appSettings { showAllVersions = f appSettings , showAllTools = p appSettings }
|
let newAppSettings = appSettings { showAllVersions = f appSettings , showAllTools = p appSettings }
|
||||||
newInternalState = constructList appData newAppSettings (Just appState)
|
newInternalState = constructList appData newAppSettings (Just appState)
|
||||||
in continue (BrickState appData newAppSettings newInternalState appKeys)
|
in put (BrickState appData newAppSettings newInternalState appKeys)
|
||||||
|
|
||||||
|
|
||||||
showKey :: Vty.Key -> String
|
showKey :: Vty.Key -> String
|
||||||
@@ -138,7 +143,7 @@ ui dimAttrs BrickState{ appSettings = as@BrickSettings{}, ..}
|
|||||||
|
|
||||||
where
|
where
|
||||||
footer =
|
footer =
|
||||||
withAttr "help"
|
withAttr (attrName "help")
|
||||||
. txtWrap
|
. txtWrap
|
||||||
. T.pack
|
. T.pack
|
||||||
. foldr1 (\x y -> x <> " " <> y)
|
. foldr1 (\x y -> x <> " " <> y)
|
||||||
@@ -150,12 +155,15 @@ ui dimAttrs BrickState{ appSettings = as@BrickSettings{}, ..}
|
|||||||
<+> minHSize 15 (str "Version")
|
<+> minHSize 15 (str "Version")
|
||||||
<+> padLeft (Pad 1) (minHSize 25 $ str "Tags")
|
<+> padLeft (Pad 1) (minHSize 25 $ str "Tags")
|
||||||
<+> padLeft (Pad 5) (str "Notes")
|
<+> padLeft (Pad 5) (str "Notes")
|
||||||
renderList' = withDefAttr listAttr . drawListElements renderItem True
|
renderList' bis@BrickInternalState{..} =
|
||||||
renderItem _ b listResult@ListResult{..} =
|
let minTagSize = V.maximum $ V.map (length . intercalate "," . fmap tagToString . lTag) clr
|
||||||
|
minVerSize = V.maximum $ V.map (\ListResult{..} -> T.length $ tVerToText (GHCTargetVersion lCross lVer)) clr
|
||||||
|
in withDefAttr listAttr . drawListElements (renderItem minTagSize minVerSize) True $ bis
|
||||||
|
renderItem minTagSize minVerSize _ b listResult@ListResult{lTag = lTag', ..} =
|
||||||
let marks = if
|
let marks = if
|
||||||
| lSet -> (withAttr "set" $ str "✔✔")
|
| lSet -> (withAttr (attrName "set") $ str "✔✔")
|
||||||
| lInstalled -> (withAttr "installed" $ str "✓ ")
|
| lInstalled -> (withAttr (attrName "installed") $ str "✓ ")
|
||||||
| otherwise -> (withAttr "not-installed" $ str "✗ ")
|
| otherwise -> (withAttr (attrName "not-installed") $ str "✗ ")
|
||||||
ver = case lCross of
|
ver = case lCross of
|
||||||
Nothing -> T.unpack . prettyVer $ lVer
|
Nothing -> T.unpack . prettyVer $ lVer
|
||||||
Just c -> T.unpack (c <> "-" <> prettyVer lVer)
|
Just c -> T.unpack (c <> "-" <> prettyVer lVer)
|
||||||
@@ -163,22 +171,22 @@ ui dimAttrs BrickState{ appSettings = as@BrickSettings{}, ..}
|
|||||||
| lNoBindist && not lInstalled
|
| lNoBindist && not lInstalled
|
||||||
&& not b -- TODO: overloading dim and active ignores active
|
&& not b -- TODO: overloading dim and active ignores active
|
||||||
-- so we hack around it here
|
-- so we hack around it here
|
||||||
= updateAttrMap (const dimAttrs) . withAttr "no-bindist"
|
= updateAttrMap (const dimAttrs) . withAttr (attrName "no-bindist")
|
||||||
| otherwise = id
|
| otherwise = id
|
||||||
hooray
|
hooray
|
||||||
| elem Latest lTag && not lInstalled =
|
| elem Latest lTag' && not lInstalled =
|
||||||
withAttr "hooray"
|
withAttr (attrName "hooray")
|
||||||
| otherwise = id
|
| otherwise = id
|
||||||
active = if b then putCursor "GHCup" (Location (0,0)) . forceAttr "active" else id
|
active = if b then putCursor "GHCup" (Location (0,0)) . forceAttr (attrName "active") else id
|
||||||
in hooray $ active $ dim
|
in hooray $ active $ dim
|
||||||
( marks
|
( marks
|
||||||
<+> padLeft (Pad 2)
|
<+> padLeft (Pad 2)
|
||||||
( minHSize 6
|
( minHSize 6
|
||||||
(printTool lTool)
|
(printTool lTool)
|
||||||
)
|
)
|
||||||
<+> minHSize 15 (str ver)
|
<+> minHSize minVerSize (str ver)
|
||||||
<+> (let l = catMaybes . fmap printTag $ sort lTag
|
<+> (let l = catMaybes . fmap printTag $ sort lTag'
|
||||||
in padLeft (Pad 1) $ minHSize 25 $ if null l
|
in padLeft (Pad 1) $ minHSize minTagSize $ if null l
|
||||||
then emptyWidget
|
then emptyWidget
|
||||||
else foldr1 (\x y -> x <+> str "," <+> y) l
|
else foldr1 (\x y -> x <+> str "," <+> y) l
|
||||||
)
|
)
|
||||||
@@ -191,11 +199,14 @@ ui dimAttrs BrickState{ appSettings = as@BrickSettings{}, ..}
|
|||||||
<+> vLimit 1 (fill ' ')
|
<+> vLimit 1 (fill ' ')
|
||||||
)
|
)
|
||||||
|
|
||||||
printTag Recommended = Just $ withAttr "recommended" $ str "recommended"
|
printTag Recommended = Just $ withAttr (attrName "recommended") $ str "recommended"
|
||||||
printTag Latest = Just $ withAttr "latest" $ str "latest"
|
printTag Latest = Just $ withAttr (attrName "latest") $ str "latest"
|
||||||
printTag Prerelease = Just $ withAttr "prerelease" $ str "prerelease"
|
printTag Prerelease = Just $ withAttr (attrName "prerelease") $ str "prerelease"
|
||||||
|
printTag Nightly = Just $ withAttr (attrName "nightly") $ str "nightly"
|
||||||
printTag (Base pvp'') = Just $ str ("base-" ++ T.unpack (prettyPVP pvp''))
|
printTag (Base pvp'') = Just $ str ("base-" ++ T.unpack (prettyPVP pvp''))
|
||||||
printTag Old = Nothing
|
printTag Old = Nothing
|
||||||
|
printTag LatestPrerelease = Just $ withAttr (attrName "latest-prerelease") $ str "latest-prerelease"
|
||||||
|
printTag LatestNightly = Just $ withAttr (attrName "latest-nightly") $ str "latest-nightly"
|
||||||
printTag (UnknownTag t) = Just $ str t
|
printTag (UnknownTag t) = Just $ str t
|
||||||
|
|
||||||
printTool Cabal = str "cabal"
|
printTool Cabal = str "cabal"
|
||||||
@@ -205,10 +216,13 @@ ui dimAttrs BrickState{ appSettings = as@BrickSettings{}, ..}
|
|||||||
printTool Stack = str "Stack"
|
printTool Stack = str "Stack"
|
||||||
|
|
||||||
printNotes ListResult {..} =
|
printNotes ListResult {..} =
|
||||||
(if hlsPowered then [withAttr "hls-powered" $ str "hls-powered"] else mempty
|
(if hlsPowered then [withAttr (attrName "hls-powered") $ str "hls-powered"] else mempty
|
||||||
)
|
)
|
||||||
++ (if fromSrc then [withAttr "compiled" $ str "compiled"] else mempty)
|
++ (if fromSrc then [withAttr (attrName "compiled") $ str "compiled"] else mempty)
|
||||||
++ (if lStray then [withAttr "stray" $ str "stray"] else mempty)
|
++ (if lStray then [withAttr (attrName "stray") $ str "stray"] else mempty)
|
||||||
|
++ (case lReleaseDay of
|
||||||
|
Nothing -> mempty
|
||||||
|
Just d -> [withAttr (attrName "day") $ str (show d)])
|
||||||
|
|
||||||
-- | Draws the list elements.
|
-- | Draws the list elements.
|
||||||
--
|
--
|
||||||
@@ -238,8 +252,8 @@ ui dimAttrs BrickState{ appSettings = as@BrickSettings{}, ..}
|
|||||||
selItemAttr = if foc
|
selItemAttr = if foc
|
||||||
then withDefAttr listSelectedFocusedAttr
|
then withDefAttr listSelectedFocusedAttr
|
||||||
else withDefAttr listSelectedAttr
|
else withDefAttr listSelectedAttr
|
||||||
makeVisible = if isSelected then visible . selItemAttr else id
|
makeVisible' = if isSelected then visible . selItemAttr else id
|
||||||
in addSeparator $ makeVisible elemWidget
|
in addSeparator $ makeVisible' elemWidget
|
||||||
|
|
||||||
in render
|
in render
|
||||||
$ viewport "GHCup" Vertical
|
$ viewport "GHCup" Vertical
|
||||||
@@ -254,8 +268,8 @@ minHSize s' = hLimit s' . vLimit 1 . (<+> fill ' ')
|
|||||||
app :: AttrMap -> AttrMap -> App BrickState e String
|
app :: AttrMap -> AttrMap -> App BrickState e String
|
||||||
app attrs dimAttrs =
|
app attrs dimAttrs =
|
||||||
App { appDraw = \st -> [ui dimAttrs st]
|
App { appDraw = \st -> [ui dimAttrs st]
|
||||||
, appHandleEvent = eventHandler
|
, appHandleEvent = \be -> get >>= \s -> eventHandler s be
|
||||||
, appStartEvent = return
|
, appStartEvent = return ()
|
||||||
, appAttrMap = const attrs
|
, appAttrMap = const attrs
|
||||||
, appChooseCursor = showFirstCursor
|
, appChooseCursor = showFirstCursor
|
||||||
}
|
}
|
||||||
@@ -263,18 +277,22 @@ app attrs dimAttrs =
|
|||||||
defaultAttributes :: Bool -> AttrMap
|
defaultAttributes :: Bool -> AttrMap
|
||||||
defaultAttributes no_color = attrMap
|
defaultAttributes no_color = attrMap
|
||||||
Vty.defAttr
|
Vty.defAttr
|
||||||
[ ("active" , Vty.defAttr `withBackColor` Vty.blue)
|
[ (attrName "active" , Vty.defAttr `withBackColor` Vty.blue)
|
||||||
, ("not-installed", Vty.defAttr `withForeColor` Vty.red)
|
, (attrName "not-installed" , Vty.defAttr `withForeColor` Vty.red)
|
||||||
, ("set" , Vty.defAttr `withForeColor` Vty.green)
|
, (attrName "set" , Vty.defAttr `withForeColor` Vty.green)
|
||||||
, ("installed" , Vty.defAttr `withForeColor` Vty.green)
|
, (attrName "installed" , Vty.defAttr `withForeColor` Vty.green)
|
||||||
, ("recommended" , Vty.defAttr `withForeColor` Vty.green)
|
, (attrName "recommended" , Vty.defAttr `withForeColor` Vty.green)
|
||||||
, ("hls-powered" , Vty.defAttr `withForeColor` Vty.green)
|
, (attrName "hls-powered" , Vty.defAttr `withForeColor` Vty.green)
|
||||||
, ("latest" , Vty.defAttr `withForeColor` Vty.yellow)
|
, (attrName "latest" , Vty.defAttr `withForeColor` Vty.yellow)
|
||||||
, ("prerelease" , Vty.defAttr `withForeColor` Vty.red)
|
, (attrName "latest-prerelease" , Vty.defAttr `withForeColor` Vty.red)
|
||||||
, ("compiled" , Vty.defAttr `withForeColor` Vty.blue)
|
, (attrName "latest-nightly" , Vty.defAttr `withForeColor` Vty.red)
|
||||||
, ("stray" , Vty.defAttr `withForeColor` Vty.blue)
|
, (attrName "prerelease" , Vty.defAttr `withForeColor` Vty.red)
|
||||||
, ("help" , Vty.defAttr `withStyle` Vty.italic)
|
, (attrName "nightly" , Vty.defAttr `withForeColor` Vty.red)
|
||||||
, ("hooray" , Vty.defAttr `withForeColor` Vty.brightWhite)
|
, (attrName "compiled" , Vty.defAttr `withForeColor` Vty.blue)
|
||||||
|
, (attrName "stray" , Vty.defAttr `withForeColor` Vty.blue)
|
||||||
|
, (attrName "day" , Vty.defAttr `withForeColor` Vty.blue)
|
||||||
|
, (attrName "help" , Vty.defAttr `withStyle` Vty.italic)
|
||||||
|
, (attrName "hooray" , Vty.defAttr `withForeColor` Vty.brightWhite)
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
withForeColor | no_color = const
|
withForeColor | no_color = const
|
||||||
@@ -288,31 +306,31 @@ defaultAttributes no_color = attrMap
|
|||||||
dimAttributes :: Bool -> AttrMap
|
dimAttributes :: Bool -> AttrMap
|
||||||
dimAttributes no_color = attrMap
|
dimAttributes no_color = attrMap
|
||||||
(Vty.defAttr `Vty.withStyle` Vty.dim)
|
(Vty.defAttr `Vty.withStyle` Vty.dim)
|
||||||
[ ("active" , Vty.defAttr `withBackColor` Vty.blue) -- has no effect ??
|
[ (attrName "active" , Vty.defAttr `withBackColor` Vty.blue) -- has no effect ??
|
||||||
, ("no-bindist", Vty.defAttr `Vty.withStyle` Vty.dim)
|
, (attrName "no-bindist", Vty.defAttr `Vty.withStyle` Vty.dim)
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
withBackColor | no_color = \attr _ -> attr `Vty.withStyle` Vty.reverseVideo
|
withBackColor | no_color = \attr _ -> attr `Vty.withStyle` Vty.reverseVideo
|
||||||
| otherwise = Vty.withBackColor
|
| otherwise = Vty.withBackColor
|
||||||
|
|
||||||
eventHandler :: BrickState -> BrickEvent n e -> EventM n (Next BrickState)
|
eventHandler :: BrickState -> BrickEvent String e -> EventM String BrickState ()
|
||||||
eventHandler st@BrickState{..} ev = do
|
eventHandler st@BrickState{..} ev = do
|
||||||
AppState { keyBindings = kb } <- liftIO $ readIORef settings'
|
AppState { keyBindings = kb } <- liftIO $ readIORef settings'
|
||||||
case ev of
|
case ev of
|
||||||
(MouseDown _ Vty.BScrollUp _ _) ->
|
(MouseDown _ Vty.BScrollUp _ _) ->
|
||||||
continue (BrickState { appState = moveCursor 1 appState Up, .. })
|
put (BrickState { appState = moveCursor 1 appState Up, .. })
|
||||||
(MouseDown _ Vty.BScrollDown _ _) ->
|
(MouseDown _ Vty.BScrollDown _ _) ->
|
||||||
continue (BrickState { appState = moveCursor 1 appState Down, .. })
|
put (BrickState { appState = moveCursor 1 appState Down, .. })
|
||||||
(VtyEvent (Vty.EvResize _ _)) -> continue st
|
(VtyEvent (Vty.EvResize _ _)) -> put st
|
||||||
(VtyEvent (Vty.EvKey Vty.KUp _)) ->
|
(VtyEvent (Vty.EvKey Vty.KUp _)) ->
|
||||||
continue BrickState{ appState = moveCursor 1 appState Up, .. }
|
put BrickState{ appState = moveCursor 1 appState Up, .. }
|
||||||
(VtyEvent (Vty.EvKey Vty.KDown _)) ->
|
(VtyEvent (Vty.EvKey Vty.KDown _)) ->
|
||||||
continue BrickState{ appState = moveCursor 1 appState Down, .. }
|
put BrickState{ appState = moveCursor 1 appState Down, .. }
|
||||||
(VtyEvent (Vty.EvKey key _)) ->
|
(VtyEvent (Vty.EvKey key _)) ->
|
||||||
case find (\(key', _, _) -> key' == key) (keyHandlers kb) of
|
case find (\(key', _, _) -> key' == key) (keyHandlers kb) of
|
||||||
Nothing -> continue st
|
Nothing -> put st
|
||||||
Just (_, _, handler) -> handler st
|
Just (_, _, handler) -> handler st
|
||||||
_ -> continue st
|
_ -> put st
|
||||||
|
|
||||||
|
|
||||||
moveCursor :: Int -> BrickInternalState -> Direction -> BrickInternalState
|
moveCursor :: Int -> BrickInternalState -> Direction -> BrickInternalState
|
||||||
@@ -325,13 +343,14 @@ moveCursor steps ais@BrickInternalState{..} direction =
|
|||||||
|
|
||||||
-- | Suspend the current UI and run an IO action in terminal. If the
|
-- | 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.
|
-- IO action returns a Left value, then it's thrown as userError.
|
||||||
withIOAction :: (BrickState
|
withIOAction :: Ord n
|
||||||
|
=> (BrickState
|
||||||
-> (Int, ListResult)
|
-> (Int, ListResult)
|
||||||
-> ReaderT AppState IO (Either String a))
|
-> ReaderT AppState IO (Either String a))
|
||||||
-> BrickState
|
-> BrickState
|
||||||
-> EventM n (Next BrickState)
|
-> EventM n BrickState ()
|
||||||
withIOAction action as = case listSelectedElement' (appState as) of
|
withIOAction action as = case listSelectedElement' (appState as) of
|
||||||
Nothing -> continue as
|
Nothing -> put as
|
||||||
Just (ix, e) -> do
|
Just (ix, e) -> do
|
||||||
suspendAndResume $ do
|
suspendAndResume $ do
|
||||||
settings <- readIORef settings'
|
settings <- readIORef settings'
|
||||||
@@ -373,10 +392,7 @@ listSelectedElement' BrickInternalState{..} = fmap (ix, ) $ clr !? ix
|
|||||||
|
|
||||||
|
|
||||||
selectLatest :: Vector ListResult -> Int
|
selectLatest :: Vector ListResult -> Int
|
||||||
selectLatest v =
|
selectLatest = fromMaybe 0 . V.findIndex (\ListResult {..} -> lTool == GHC && Latest `elem` lTag)
|
||||||
case V.findIndex (\ListResult {..} -> lTool == GHC && Latest `elem` lTag) v of
|
|
||||||
Just ix -> ix
|
|
||||||
Nothing -> 0
|
|
||||||
|
|
||||||
|
|
||||||
-- | Replace the @appState@ or construct it based on a filter function
|
-- | Replace the @appState@ or construct it based on a filter function
|
||||||
@@ -403,14 +419,18 @@ filterVisible :: Bool -> Bool -> ListResult -> Bool
|
|||||||
filterVisible v t e | lInstalled e = True
|
filterVisible v t e | lInstalled e = True
|
||||||
| v
|
| v
|
||||||
, not t
|
, not t
|
||||||
, not (elem (lTool e) hiddenTools) = True
|
, Nightly `notElem` lTag e
|
||||||
|
, lTool e `notElem` hiddenTools = True
|
||||||
| not v
|
| not v
|
||||||
, t
|
, t
|
||||||
, not (elem Old (lTag e)) = True
|
, Old `notElem` lTag e
|
||||||
|
, Nightly `notElem` lTag e = True
|
||||||
| v
|
| v
|
||||||
|
, Nightly `notElem` lTag e
|
||||||
, t = True
|
, t = True
|
||||||
| otherwise = not (elem Old (lTag e)) &&
|
| otherwise = (Old `notElem` lTag e) &&
|
||||||
not (elem (lTool e) hiddenTools)
|
(Nightly `notElem` lTag e) &&
|
||||||
|
(lTool e `notElem` hiddenTools)
|
||||||
|
|
||||||
|
|
||||||
install' :: (MonadReader AppState m, MonadIO m, MonadThrow m, MonadFail m, MonadMask m, MonadUnliftIO m)
|
install' :: (MonadReader AppState m, MonadIO m, MonadThrow m, MonadFail m, MonadMask m, MonadUnliftIO m)
|
||||||
@@ -420,17 +440,11 @@ install' :: (MonadReader AppState m, MonadIO m, MonadThrow m, MonadFail m, Monad
|
|||||||
install' _ (_, ListResult {..}) = do
|
install' _ (_, ListResult {..}) = do
|
||||||
AppState { ghcupInfo = GHCupInfo { _ghcupDownloads = dls }} <- ask
|
AppState { ghcupInfo = GHCupInfo { _ghcupDownloads = dls }} <- ask
|
||||||
|
|
||||||
l <- liftIO $ readIORef logger'
|
|
||||||
let runLogger = myLoggerT l
|
|
||||||
|
|
||||||
let run =
|
let run =
|
||||||
runLogger
|
runResourceT
|
||||||
. runResourceT
|
|
||||||
. runE
|
. runE
|
||||||
@'[ AlreadyInstalled
|
@'[ AlreadyInstalled
|
||||||
#if !defined(TAR)
|
|
||||||
, ArchiveResult
|
, ArchiveResult
|
||||||
#endif
|
|
||||||
, UnknownArchive
|
, UnknownArchive
|
||||||
, FileDoesNotExistError
|
, FileDoesNotExistError
|
||||||
, CopyError
|
, CopyError
|
||||||
@@ -439,62 +453,106 @@ install' _ (_, ListResult {..}) = do
|
|||||||
, BuildFailed
|
, BuildFailed
|
||||||
, TagNotFound
|
, TagNotFound
|
||||||
, DigestError
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
|
, GPGError
|
||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
|
, DirNotEmpty
|
||||||
, NoUpdate
|
, NoUpdate
|
||||||
, TarDirDoesNotExist
|
, TarDirDoesNotExist
|
||||||
|
, FileAlreadyExistsError
|
||||||
|
, ProcessError
|
||||||
|
, ToolShadowed
|
||||||
|
, UninstallFailed
|
||||||
|
, MergeFileTreeError
|
||||||
]
|
]
|
||||||
|
|
||||||
run (do
|
run (do
|
||||||
|
ce <- liftIO $ fmap (either (const Nothing) Just) $
|
||||||
|
try @_ @SomeException $ getExecutablePath >>= canonicalizePath
|
||||||
|
dirs <- lift getDirs
|
||||||
case lTool of
|
case lTool of
|
||||||
GHC -> do
|
GHC -> do
|
||||||
let vi = getVersionInfo lVer GHC dls
|
let vi = getVersionInfo (GHCTargetVersion lCross lVer) GHC dls
|
||||||
liftE $ installGHCBin lVer $> vi
|
liftE $ installGHCBin (GHCTargetVersion lCross lVer) GHCupInternal False [] $> (vi, dirs, ce)
|
||||||
Cabal -> do
|
Cabal -> do
|
||||||
let vi = getVersionInfo lVer Cabal dls
|
let vi = getVersionInfo (GHCTargetVersion lCross lVer) Cabal dls
|
||||||
liftE $ installCabalBin lVer $> vi
|
liftE $ installCabalBin lVer GHCupInternal False $> (vi, dirs, ce)
|
||||||
GHCup -> do
|
GHCup -> do
|
||||||
let vi = snd <$> getLatest dls GHCup
|
let vi = snd <$> getLatest dls GHCup
|
||||||
liftE $ upgradeGHCup Nothing False $> vi
|
liftE $ upgradeGHCup Nothing False False $> (vi, dirs, ce)
|
||||||
HLS -> do
|
HLS -> do
|
||||||
let vi = getVersionInfo lVer HLS dls
|
let vi = getVersionInfo (GHCTargetVersion lCross lVer) HLS dls
|
||||||
liftE $ installHLSBin lVer $> vi
|
liftE $ installHLSBin lVer GHCupInternal False $> (vi, dirs, ce)
|
||||||
Stack -> do
|
Stack -> do
|
||||||
let vi = getVersionInfo lVer Stack dls
|
let vi = getVersionInfo (GHCTargetVersion lCross lVer) Stack dls
|
||||||
liftE $ installStackBin lVer $> vi
|
liftE $ installStackBin lVer GHCupInternal False $> (vi, dirs, ce)
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
VRight vi -> do
|
VRight (vi, Dirs{..}, Just ce) -> do
|
||||||
forM_ (_viPostInstall =<< vi) $ \msg ->
|
forM_ (_viPostInstall =<< vi) $ \msg -> logInfo msg
|
||||||
myLoggerT l $ $(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 ()
|
pure $ Right ()
|
||||||
VLeft (V (AlreadyInstalled _ _)) -> pure $ Right ()
|
VLeft (V (AlreadyInstalled _ _)) -> pure $ Right ()
|
||||||
VLeft (V NoUpdate) -> pure $ Right ()
|
VLeft (V NoUpdate) -> pure $ Right ()
|
||||||
VLeft e -> pure $ Left [i|#{prettyShow e}
|
VLeft e -> pure $ Left $ prettyHFError e <> "\n"
|
||||||
Also check the logs in ~/.ghcup/logs|]
|
<> "Also check the logs in ~/.ghcup/logs"
|
||||||
|
|
||||||
|
|
||||||
set' :: BrickState -> (Int, ListResult) -> IO (Either String ())
|
set' :: (MonadReader AppState m, MonadIO m, MonadThrow m, MonadFail m, MonadMask m, MonadUnliftIO m)
|
||||||
set' _ (_, ListResult {..}) = do
|
=> BrickState
|
||||||
settings <- readIORef settings'
|
-> (Int, ListResult)
|
||||||
l <- readIORef logger'
|
-> m (Either String ())
|
||||||
let runLogger = myLoggerT l
|
set' bs input@(_, ListResult {..}) = do
|
||||||
|
settings <- liftIO $ readIORef settings'
|
||||||
|
|
||||||
let run =
|
let run =
|
||||||
runLogger
|
flip runReaderT settings
|
||||||
. flip runReaderT settings
|
|
||||||
. runE @'[FileDoesNotExistError , NotInstalled , TagNotFound]
|
. runE @'[FileDoesNotExistError , NotInstalled , TagNotFound]
|
||||||
|
|
||||||
run (do
|
run (do
|
||||||
case lTool of
|
case lTool of
|
||||||
GHC -> liftE $ setGHC (GHCTargetVersion lCross lVer) SetGHCOnly $> ()
|
GHC -> liftE $ setGHC (GHCTargetVersion lCross lVer) SetGHCOnly Nothing $> ()
|
||||||
Cabal -> liftE $ setCabal lVer $> ()
|
Cabal -> liftE $ setCabal lVer $> ()
|
||||||
HLS -> liftE $ setHLS lVer $> ()
|
HLS -> liftE $ setHLS lVer SetHLSOnly Nothing $> ()
|
||||||
Stack -> liftE $ setStack lVer $> ()
|
Stack -> liftE $ setStack lVer $> ()
|
||||||
GHCup -> pure ()
|
GHCup -> pure ()
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
VRight _ -> pure $ Right ()
|
VRight _ -> pure $ Right ()
|
||||||
VLeft e -> pure $ Left (prettyShow e)
|
VLeft e -> case e of
|
||||||
|
(V (NotInstalled tool _)) -> do
|
||||||
|
promptAnswer <- getUserPromptResponse userPrompt
|
||||||
|
case promptAnswer of
|
||||||
|
PromptYes -> do
|
||||||
|
res <- install' bs input
|
||||||
|
case res of
|
||||||
|
(Left err) -> pure $ Left err
|
||||||
|
(Right _) -> do
|
||||||
|
logInfo "Setting now..."
|
||||||
|
set' bs input
|
||||||
|
|
||||||
|
PromptNo -> pure $ Left (prettyHFError e)
|
||||||
|
where
|
||||||
|
userPrompt = L.toStrict . B.toLazyText . B.fromString $
|
||||||
|
"This Version of "
|
||||||
|
<> show tool
|
||||||
|
<> " you are trying to set is not installed.\n"
|
||||||
|
<> "Would you like to install it first? [Y/N]: "
|
||||||
|
|
||||||
|
_ -> pure $ Left (prettyHFError e)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
del' :: (MonadReader AppState m, MonadIO m, MonadFail m, MonadMask m, MonadUnliftIO m)
|
del' :: (MonadReader AppState m, MonadIO m, MonadFail m, MonadMask m, MonadUnliftIO m)
|
||||||
@@ -504,12 +562,10 @@ del' :: (MonadReader AppState m, MonadIO m, MonadFail m, MonadMask m, MonadUnlif
|
|||||||
del' _ (_, ListResult {..}) = do
|
del' _ (_, ListResult {..}) = do
|
||||||
AppState { ghcupInfo = GHCupInfo { _ghcupDownloads = dls }} <- ask
|
AppState { ghcupInfo = GHCupInfo { _ghcupDownloads = dls }} <- ask
|
||||||
|
|
||||||
l <- liftIO $ readIORef logger'
|
let run = runE @'[NotInstalled, UninstallFailed]
|
||||||
let runLogger = myLoggerT l
|
|
||||||
let run = myLoggerT l . runE @'[NotInstalled]
|
|
||||||
|
|
||||||
run (do
|
run (do
|
||||||
let vi = getVersionInfo lVer lTool dls
|
let vi = getVersionInfo (GHCTargetVersion lCross lVer) lTool dls
|
||||||
case lTool of
|
case lTool of
|
||||||
GHC -> liftE $ rmGHCVer (GHCTargetVersion lCross lVer) $> vi
|
GHC -> liftE $ rmGHCVer (GHCTargetVersion lCross lVer) $> vi
|
||||||
Cabal -> liftE $ rmCabalVer lVer $> vi
|
Cabal -> liftE $ rmCabalVer lVer $> vi
|
||||||
@@ -519,10 +575,11 @@ del' _ (_, ListResult {..}) = do
|
|||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
VRight vi -> do
|
VRight vi -> do
|
||||||
forM_ (join $ fmap _viPostRemove vi) $ \msg ->
|
when (lTool == GHC) $ logGHCPostRm (mkTVer lVer)
|
||||||
runLogger $ $(logInfo) msg
|
forM_ (_viPostRemove =<< vi) $ \msg ->
|
||||||
|
logInfo msg
|
||||||
pure $ Right ()
|
pure $ Right ()
|
||||||
VLeft e -> pure $ Left (prettyShow e)
|
VLeft e -> pure $ Left (prettyHFError e)
|
||||||
|
|
||||||
|
|
||||||
changelog' :: (MonadReader AppState m, MonadIO m)
|
changelog' :: (MonadReader AppState m, MonadIO m)
|
||||||
@@ -531,9 +588,9 @@ changelog' :: (MonadReader AppState m, MonadIO m)
|
|||||||
-> m (Either String ())
|
-> m (Either String ())
|
||||||
changelog' _ (_, ListResult {..}) = do
|
changelog' _ (_, ListResult {..}) = do
|
||||||
AppState { pfreq, ghcupInfo = GHCupInfo { _ghcupDownloads = dls }} <- ask
|
AppState { pfreq, ghcupInfo = GHCupInfo { _ghcupDownloads = dls }} <- ask
|
||||||
case getChangeLog dls lTool (Left lVer) of
|
case getChangeLog dls lTool (ToolVersion lVer) of
|
||||||
Nothing -> pure $ Left
|
Nothing -> pure $ Left $
|
||||||
[i|Could not find ChangeLog for #{lTool}, version #{prettyVer lVer}|]
|
"Could not find ChangeLog for " <> prettyShow lTool <> ", version " <> T.unpack (prettyVer lVer)
|
||||||
Just uri -> do
|
Just uri -> do
|
||||||
let cmd = case _rPlatform pfreq of
|
let cmd = case _rPlatform pfreq of
|
||||||
Darwin -> "open"
|
Darwin -> "open"
|
||||||
@@ -542,55 +599,37 @@ changelog' _ (_, ListResult {..}) = do
|
|||||||
Windows -> "start"
|
Windows -> "start"
|
||||||
exec cmd [T.unpack $ decUTF8Safe $ serializeURIRef' uri] Nothing Nothing >>= \case
|
exec cmd [T.unpack $ decUTF8Safe $ serializeURIRef' uri] Nothing Nothing >>= \case
|
||||||
Right _ -> pure $ Right ()
|
Right _ -> pure $ Right ()
|
||||||
Left e -> pure $ Left $ prettyShow e
|
Left e -> pure $ Left $ prettyHFError e
|
||||||
|
|
||||||
|
|
||||||
settings' :: IORef AppState
|
settings' :: IORef AppState
|
||||||
{-# NOINLINE settings' #-}
|
{-# NOINLINE settings' #-}
|
||||||
settings' = unsafePerformIO $ do
|
settings' = unsafePerformIO $ do
|
||||||
dirs <- getAllDirs
|
dirs <- getAllDirs
|
||||||
newIORef $ AppState (Settings { cache = True
|
let loggerConfig = LoggerConfig { lcPrintDebug = False
|
||||||
, noVerify = False
|
, consoleOutter = \_ -> pure ()
|
||||||
, keepDirs = Never
|
, fileOutter = \_ -> pure ()
|
||||||
, downloader = Curl
|
, fancyColors = True
|
||||||
, verbose = False
|
}
|
||||||
, urlSource = GHCupURL
|
newIORef $ AppState defaultSettings
|
||||||
, noNetwork = False
|
|
||||||
, ..
|
|
||||||
})
|
|
||||||
dirs
|
dirs
|
||||||
defaultKeyBindings
|
defaultKeyBindings
|
||||||
(GHCupInfo mempty mempty mempty)
|
(GHCupInfo mempty mempty mempty)
|
||||||
(PlatformRequest A_64 Darwin Nothing)
|
(PlatformRequest A_64 Darwin Nothing)
|
||||||
|
loggerConfig
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
logger' :: IORef LoggerConfig
|
|
||||||
{-# NOINLINE logger' #-}
|
|
||||||
logger' = unsafePerformIO
|
|
||||||
(newIORef $ LoggerConfig { lcPrintDebug = False
|
|
||||||
, colorOutter = \_ -> pure ()
|
|
||||||
, rawOutter = \_ -> pure ()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
brickMain :: AppState
|
brickMain :: AppState
|
||||||
-> LoggerConfig
|
|
||||||
-> IO ()
|
-> IO ()
|
||||||
brickMain s l = do
|
brickMain s = do
|
||||||
writeIORef settings' s
|
writeIORef settings' s
|
||||||
-- logger interpreter
|
|
||||||
writeIORef logger' l
|
|
||||||
let runLogger = myLoggerT l
|
|
||||||
|
|
||||||
no_color <- isJust <$> lookupEnv "NO_COLOR"
|
|
||||||
|
|
||||||
eAppData <- getAppData (Just $ ghcupInfo s)
|
eAppData <- getAppData (Just $ ghcupInfo s)
|
||||||
case eAppData of
|
case eAppData of
|
||||||
Right ad ->
|
Right ad ->
|
||||||
defaultMain
|
defaultMain
|
||||||
(app (defaultAttributes no_color) (dimAttributes no_color))
|
(app (defaultAttributes (noColor $ settings s)) (dimAttributes (noColor $ settings s)))
|
||||||
(BrickState ad
|
(BrickState ad
|
||||||
defaultAppSettings
|
defaultAppSettings
|
||||||
(constructList ad defaultAppSettings Nothing)
|
(constructList ad defaultAppSettings Nothing)
|
||||||
@@ -599,7 +638,7 @@ brickMain s l = do
|
|||||||
)
|
)
|
||||||
$> ()
|
$> ()
|
||||||
Left e -> do
|
Left e -> do
|
||||||
runLogger ($(logError) [i|Error building app state: #{show e}|])
|
flip runReaderT s $ logError $ "Error building app state: " <> T.pack (show e)
|
||||||
exitWith $ ExitFailure 2
|
exitWith $ ExitFailure 2
|
||||||
|
|
||||||
|
|
||||||
@@ -610,32 +649,24 @@ defaultAppSettings = BrickSettings { showAllVersions = False, showAllTools = Fal
|
|||||||
getGHCupInfo :: IO (Either String GHCupInfo)
|
getGHCupInfo :: IO (Either String GHCupInfo)
|
||||||
getGHCupInfo = do
|
getGHCupInfo = do
|
||||||
settings <- readIORef settings'
|
settings <- readIORef settings'
|
||||||
l <- readIORef logger'
|
|
||||||
let runLogger = myLoggerT l
|
|
||||||
|
|
||||||
r <-
|
r <-
|
||||||
runLogger
|
flip runReaderT settings
|
||||||
. flip runReaderT settings
|
. runE @'[DigestError, ContentLengthError, GPGError, JSONError , DownloadFailed , FileDoesNotExistError]
|
||||||
. runE @'[JSONError , DownloadFailed , FileDoesNotExistError]
|
$ liftE getDownloadsF
|
||||||
$ liftE
|
|
||||||
$ getDownloadsF
|
|
||||||
|
|
||||||
case r of
|
case r of
|
||||||
VRight a -> pure $ Right a
|
VRight a -> pure $ Right a
|
||||||
VLeft e -> pure $ Left (prettyShow e)
|
VLeft e -> pure $ Left (prettyHFError e)
|
||||||
|
|
||||||
|
|
||||||
getAppData :: Maybe GHCupInfo
|
getAppData :: Maybe GHCupInfo
|
||||||
-> IO (Either String BrickData)
|
-> IO (Either String BrickData)
|
||||||
getAppData mgi = runExceptT $ do
|
getAppData mgi = runExceptT $ do
|
||||||
l <- liftIO $ readIORef logger'
|
|
||||||
let runLogger = myLoggerT l
|
|
||||||
|
|
||||||
r <- ExceptT $ maybe getGHCupInfo (pure . Right) mgi
|
r <- ExceptT $ maybe getGHCupInfo (pure . Right) mgi
|
||||||
liftIO $ modifyIORef settings' (\s -> s { ghcupInfo = r })
|
liftIO $ modifyIORef settings' (\s -> s { ghcupInfo = r })
|
||||||
settings <- liftIO $ readIORef settings'
|
settings <- liftIO $ readIORef settings'
|
||||||
|
|
||||||
runLogger . flip runReaderT settings $ do
|
flip runReaderT settings $ do
|
||||||
lV <- listVersions Nothing Nothing
|
lV <- listVersions Nothing [] False True (Nothing, Nothing)
|
||||||
pure $ BrickData (reverse lV)
|
pure $ BrickData (reverse lV)
|
||||||
|
|
||||||
|
|||||||
363
app/ghcup/GHCup/OptParse.hs
Normal file
363
app/ghcup/GHCup/OptParse.hs
Normal file
@@ -0,0 +1,363 @@
|
|||||||
|
{-# LANGUAGE CPP #-}
|
||||||
|
{-# LANGUAGE DataKinds #-}
|
||||||
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE DuplicateRecordFields #-}
|
||||||
|
|
||||||
|
|
||||||
|
module GHCup.OptParse (
|
||||||
|
module GHCup.OptParse.Common
|
||||||
|
, module GHCup.OptParse.Install
|
||||||
|
, module GHCup.OptParse.Test
|
||||||
|
, 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.Test
|
||||||
|
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
|
||||||
|
, optMetaMode :: Maybe MetaMode
|
||||||
|
, optPlatform :: Maybe PlatformRequest
|
||||||
|
, 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)
|
||||||
|
| Test TestCommand
|
||||||
|
| 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
|
||||||
|
| PrintAppErrors
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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" <> metavar "SEC" <> help "How long the yaml metadata caching interval is (in seconds), 0 to disable"))
|
||||||
|
<*> optional (option auto (long "metadata-fetching-mode" <> metavar "<Strict|Lax>" <> help "Whether to fail on metadata download failure (Strict) or fall back to cached version (Lax (default))"))
|
||||||
|
<*> 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 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
|
||||||
|
"test"
|
||||||
|
(info
|
||||||
|
(Test <$> testParser <**> helper)
|
||||||
|
( progDesc "Run tests for a tool (if any) [EXPERIMENTAL!]"
|
||||||
|
<> footerDoc (Just $ text testFooter)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
<> 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"
|
||||||
|
<> footerDoc (Just $ text listToolFooter))
|
||||||
|
)
|
||||||
|
<> 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
|
||||||
|
)
|
||||||
|
<|> subparser
|
||||||
|
(command
|
||||||
|
"print-app-errors"
|
||||||
|
(info (pure PrintAppErrors <**> helper)
|
||||||
|
(progDesc ""))
|
||||||
|
<> internal
|
||||||
|
)
|
||||||
148
app/ghcup/GHCup/OptParse/ChangeLog.hs
Normal file
148
app/ghcup/GHCup/OptParse/ChangeLog.hs
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
{-# 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.Errors
|
||||||
|
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 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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--------------
|
||||||
|
--[ 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' = fromMaybe
|
||||||
|
(ToolTag Latest)
|
||||||
|
clToolVer
|
||||||
|
muri = getChangeLog dls tool ver'
|
||||||
|
case muri of
|
||||||
|
Nothing -> do
|
||||||
|
runLogger
|
||||||
|
(logWarn $
|
||||||
|
"Could not find ChangeLog for " <> T.pack (prettyShow tool) <> ", version " <> T.pack (prettyShow 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 $ prettyHFError e)
|
||||||
|
>> pure (ExitFailure 13)
|
||||||
|
else liftIO $ putStrLn uri' >> pure ExitSuccess
|
||||||
830
app/ghcup/GHCup/OptParse/Common.hs
Normal file
830
app/ghcup/GHCup/OptParse/Common.hs
Normal file
@@ -0,0 +1,830 @@
|
|||||||
|
{-# LANGUAGE CPP #-}
|
||||||
|
{-# LANGUAGE DataKinds #-}
|
||||||
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE DuplicateRecordFields #-}
|
||||||
|
{-# LANGUAGE TypeApplications #-}
|
||||||
|
{-# LANGUAGE NumericUnderscores #-}
|
||||||
|
{-# LANGUAGE ViewPatterns #-}
|
||||||
|
|
||||||
|
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
|
||||||
|
import Control.Monad.Identity (Identity(..))
|
||||||
|
#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.Time.Calendar ( Day )
|
||||||
|
import Data.Time.Format ( parseTimeM, defaultTimeLocale )
|
||||||
|
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)
|
||||||
|
import qualified Cabal.Config as CC
|
||||||
|
|
||||||
|
|
||||||
|
-------------
|
||||||
|
--[ Types ]--
|
||||||
|
-------------
|
||||||
|
|
||||||
|
|
||||||
|
-- a superset of ToolVersion
|
||||||
|
data SetToolVersion = SetGHCVersion GHCTargetVersion
|
||||||
|
| SetToolVersion Version
|
||||||
|
| SetToolTag Tag
|
||||||
|
| SetToolDay Day
|
||||||
|
| SetRecommended
|
||||||
|
| SetNext
|
||||||
|
|
||||||
|
prettyToolVer :: ToolVersion -> String
|
||||||
|
prettyToolVer (GHCVersion v') = T.unpack $ tVerToText v'
|
||||||
|
prettyToolVer (ToolVersion v') = T.unpack $ prettyVer v'
|
||||||
|
prettyToolVer (ToolTag t) = show t
|
||||||
|
prettyToolVer (ToolDay day) = show day
|
||||||
|
|
||||||
|
toSetToolVer :: Maybe ToolVersion -> SetToolVersion
|
||||||
|
toSetToolVer (Just (GHCVersion v')) = SetGHCVersion v'
|
||||||
|
toSetToolVer (Just (ToolVersion v')) = SetToolVersion v'
|
||||||
|
toSetToolVer (Just (ToolTag t')) = SetToolTag t'
|
||||||
|
toSetToolVer (Just (ToolDay d')) = SetToolDay d'
|
||||||
|
toSetToolVer Nothing = SetRecommended
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--------------
|
||||||
|
--[ Parser ]--
|
||||||
|
--------------
|
||||||
|
|
||||||
|
|
||||||
|
toolVersionTagArgument :: [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|RELEASE_DATE"
|
||||||
|
mv (Just HLS) = "HLS_VERSION|TAG|RELEASE_DATE"
|
||||||
|
mv _ = "VERSION|TAG|RELEASE_DATE"
|
||||||
|
|
||||||
|
parser (Just GHC) = ghcVersionTagEither
|
||||||
|
parser Nothing = ghcVersionTagEither
|
||||||
|
parser _ = toolVersionTagEither
|
||||||
|
|
||||||
|
|
||||||
|
versionParser' :: [ListCriteria] -> Maybe Tool -> Parser Version
|
||||||
|
versionParser' criteria tool = argument
|
||||||
|
(eitherReader (first show . version . T.pack))
|
||||||
|
(metavar "VERSION" <> foldMap (completer . versionCompleter criteria) tool)
|
||||||
|
|
||||||
|
ghcVersionArgument :: [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 ToolDay (dayParser s') <|> second ToolTag (tagEither s') <|> second GHCVersion (ghcVersionEither s')
|
||||||
|
|
||||||
|
-- this ignores cross prefix
|
||||||
|
toolVersionTagEither :: String -> Either String ToolVersion
|
||||||
|
toolVersionTagEither s' =
|
||||||
|
second ToolDay (dayParser 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
|
||||||
|
"latest-prerelease" -> Right LatestPrerelease
|
||||||
|
"latest-nightly" -> Right LatestNightly
|
||||||
|
('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' <* MP.eof) "" . 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')
|
||||||
|
|
||||||
|
dayParser :: String -> Either String Day
|
||||||
|
dayParser s = maybe (Left $ "Could not parse \"" <> s <> "\". Expected format is: YYYY-MM-DD") Right
|
||||||
|
$ parseTimeM True defaultTimeLocale "%Y-%-m-%-d" s
|
||||||
|
|
||||||
|
|
||||||
|
criteriaParser :: String -> Either String ListCriteria
|
||||||
|
criteriaParser s' | t == T.pack "installed" = Right $ ListInstalled True
|
||||||
|
| t == T.pack "set" = Right $ ListSet True
|
||||||
|
| t == T.pack "available" = Right $ ListAvailable True
|
||||||
|
| t == T.pack "+installed" = Right $ ListInstalled True
|
||||||
|
| t == T.pack "+set" = Right $ ListSet True
|
||||||
|
| t == T.pack "+available" = Right $ ListAvailable True
|
||||||
|
| t == T.pack "-installed" = Right $ ListInstalled False
|
||||||
|
| t == T.pack "-set" = Right $ ListSet False
|
||||||
|
| t == T.pack "-available" = Right $ ListAvailable False
|
||||||
|
| 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", "latest-prerelease"] ++ add)
|
||||||
|
|
||||||
|
versionCompleter :: [ListCriteria] -> Tool -> Completer
|
||||||
|
versionCompleter criteria tool = versionCompleter' criteria tool (const True)
|
||||||
|
|
||||||
|
versionCompleter' :: [ListCriteria] -> Tool -> (Version -> Bool) -> Completer
|
||||||
|
versionCompleter' criteria tool filter' = 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 False False (Nothing, Nothing)
|
||||||
|
return $ fmap (T.unpack . prettyVer) . filter filter' . fmap 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
|
||||||
|
, DayNotFound
|
||||||
|
, 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
|
||||||
|
, DayNotFound
|
||||||
|
, NextVerNotFound
|
||||||
|
, NoToolVersionSet
|
||||||
|
] m (GHCTargetVersion, Maybe VersionInfo)
|
||||||
|
fromVersion' SetRecommended tool = do
|
||||||
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
|
second Just <$> getRecommended dls tool
|
||||||
|
?? TagNotFound Recommended tool
|
||||||
|
fromVersion' (SetGHCVersion v) tool = do
|
||||||
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
|
let vi = getVersionInfo v tool dls
|
||||||
|
case pvp $ prettyVer (_tvVersion v) of -- need to be strict here
|
||||||
|
Left _ -> pure (v, vi)
|
||||||
|
Right pvpIn ->
|
||||||
|
lift (getLatestToolFor tool (_tvTarget v) pvpIn dls) >>= \case
|
||||||
|
Just (pvp_, vi', mt) -> do
|
||||||
|
v' <- lift $ pvpToVersion pvp_ ""
|
||||||
|
when (v' /= _tvVersion v) $ lift $ logWarn ("Assuming you meant version " <> prettyVer v')
|
||||||
|
pure (GHCTargetVersion mt v', Just vi')
|
||||||
|
Nothing -> pure (v, vi)
|
||||||
|
fromVersion' (SetToolVersion (mkTVer -> v)) tool = do
|
||||||
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
|
let vi = getVersionInfo v tool dls
|
||||||
|
case pvp $ prettyVer (_tvVersion v) of -- need to be strict here
|
||||||
|
Left _ -> pure (v, vi)
|
||||||
|
Right pvpIn ->
|
||||||
|
lift (getLatestToolFor tool (_tvTarget v) pvpIn dls) >>= \case
|
||||||
|
Just (pvp_, vi', mt) -> do
|
||||||
|
v' <- lift $ pvpToVersion pvp_ ""
|
||||||
|
when (v' /= _tvVersion v) $ lift $ logWarn ("Assuming you meant version " <> prettyVer v')
|
||||||
|
pure (GHCTargetVersion mt v', Just vi')
|
||||||
|
Nothing -> pure (v, vi)
|
||||||
|
fromVersion' (SetToolTag Latest) tool = do
|
||||||
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
|
bimap id Just <$> getLatest dls tool ?? TagNotFound Latest tool
|
||||||
|
fromVersion' (SetToolDay day) tool = do
|
||||||
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
|
bimap id Just <$> case getByReleaseDay dls tool day of
|
||||||
|
Left ad -> throwE $ DayNotFound day tool ad
|
||||||
|
Right v -> pure v
|
||||||
|
fromVersion' (SetToolTag LatestPrerelease) tool = do
|
||||||
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
|
bimap id Just <$> getLatestPrerelease dls tool ?? TagNotFound LatestPrerelease tool
|
||||||
|
fromVersion' (SetToolTag LatestNightly) tool = do
|
||||||
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
|
bimap id Just <$> getLatestNightly dls tool ?? TagNotFound LatestNightly tool
|
||||||
|
fromVersion' (SetToolTag Recommended) tool = do
|
||||||
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
|
bimap id Just <$> getRecommended dls tool ?? TagNotFound Recommended tool
|
||||||
|
fromVersion' (SetToolTag (Base pvp'')) GHC = do
|
||||||
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
|
bimap id 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 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, GHCTargetVersion)]
|
||||||
|
checkForUpdates = do
|
||||||
|
GHCupInfo { _ghcupDownloads = dls } <- getGHCupInfo
|
||||||
|
lInstalled <- listVersions Nothing [ListInstalled True] False False (Nothing, Nothing)
|
||||||
|
let latestInstalled tool = (fmap (\lr -> GHCTargetVersion (lCross lr) (lVer lr)) . lastMay . filter (\lr -> lTool lr == tool)) lInstalled
|
||||||
|
|
||||||
|
ghcup <- forMM (getLatest dls GHCup) $ \(GHCTargetVersion _ l, _) -> do
|
||||||
|
(Right ghcup_ver) <- pure $ version $ prettyPVP ghcUpVer
|
||||||
|
if (l > ghcup_ver) then pure $ Just (GHCup, mkTVer 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
|
||||||
|
|
||||||
|
|
||||||
|
logGHCPostRm :: (MonadReader env m, HasLog env, MonadIO m) => GHCTargetVersion -> m ()
|
||||||
|
logGHCPostRm ghcVer = do
|
||||||
|
cabalStore <- liftIO $ handleIO (\_ -> if isWindows then pure "C:\\cabal\\store" else pure "~/.cabal/store")
|
||||||
|
(runIdentity . CC.cfgStoreDir <$> CC.readConfig)
|
||||||
|
let storeGhcDir = cabalStore </> ("ghc-" <> T.unpack (prettyVer $ _tvVersion ghcVer))
|
||||||
|
logInfo $ T.pack $ "After removing GHC you might also want to clean up your cabal store at: " <> storeGhcDir
|
||||||
|
|
||||||
614
app/ghcup/GHCup/OptParse/Compile.hs
Normal file
614
app/ghcup/GHCup/OptParse/Compile.hs
Normal file
@@ -0,0 +1,614 @@
|
|||||||
|
{-# 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 qualified GHCup.GHC as GHC
|
||||||
|
import qualified GHCup.HLS as HLS
|
||||||
|
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, pvp )
|
||||||
|
import qualified Data.Versions as V
|
||||||
|
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 URI.ByteString hiding ( uriParser )
|
||||||
|
import qualified Data.Text as T
|
||||||
|
import Control.Exception.Safe (MonadMask, displayException)
|
||||||
|
import System.FilePath (isPathSeparator)
|
||||||
|
import Text.Read (readEither)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
----------------
|
||||||
|
--[ Commands ]--
|
||||||
|
----------------
|
||||||
|
|
||||||
|
|
||||||
|
data CompileCommand = CompileGHC GHCCompileOptions
|
||||||
|
| CompileHLS HLSCompileOptions
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------
|
||||||
|
--[ Options ]--
|
||||||
|
---------------
|
||||||
|
|
||||||
|
|
||||||
|
data GHCCompileOptions = GHCCompileOptions
|
||||||
|
{ targetGhc :: GHC.GHCVer
|
||||||
|
, 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 :: HLS.HLSVer
|
||||||
|
, jobs :: Maybe Int
|
||||||
|
, setCompile :: Bool
|
||||||
|
, updateCabal :: 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 from hackage for 8.10.7, running 'cabal update' before the build
|
||||||
|
ghcup compile hls --version 1.7.0.0 --ghc 8.10.7 --cabal-update
|
||||||
|
# compile from master for ghc 9.2.3 using 'git describe' to name the binary and ignore the pinned index state
|
||||||
|
ghcup compile hls -g master --git-describe-version --ghc 9.2.3 -- --index-state=@(date '+%s')
|
||||||
|
# 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
|
||||||
|
<$> ((GHC.SourceDist <$> 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 [] GHC)
|
||||||
|
)
|
||||||
|
) <|>
|
||||||
|
(GHC.GitDist <$> (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"])
|
||||||
|
))
|
||||||
|
))
|
||||||
|
<|>
|
||||||
|
(
|
||||||
|
GHC.RemoteDist <$> (option
|
||||||
|
(eitherReader uriParser)
|
||||||
|
(long "remote-source-dist" <> metavar "URI" <> help
|
||||||
|
"URI (https/http/file) to a GHC source distribution"
|
||||||
|
<> completer fileUri
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
<*> 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 [] 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 [] 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
|
||||||
|
<$> ((HLS.HackageDist <$> option
|
||||||
|
(eitherReader
|
||||||
|
((>>= first displayException . V.version . V.prettyPVP) . first (const "Not a valid PVP version") . pvp . T.pack)
|
||||||
|
)
|
||||||
|
(short 'v' <> long "version" <> metavar "VERSION" <> help
|
||||||
|
"The version to compile (pulled from hackage)"
|
||||||
|
<> (completer $ versionCompleter' [] HLS (either (const False) (const True) . V.pvp . V.prettyVer))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
<|>
|
||||||
|
(HLS.GitDist <$> (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"])
|
||||||
|
))
|
||||||
|
))
|
||||||
|
<|>
|
||||||
|
(HLS.SourceDist <$> (option
|
||||||
|
(eitherReader
|
||||||
|
(first (const "Not a valid version") . version . T.pack)
|
||||||
|
)
|
||||||
|
(long "source-dist" <> metavar "VERSION" <> help
|
||||||
|
"The version to compile (pulled from packaged git sources)"
|
||||||
|
<> (completer $ versionCompleter [] HLS)
|
||||||
|
)
|
||||||
|
))
|
||||||
|
<|>
|
||||||
|
(
|
||||||
|
HLS.RemoteDist <$> (option
|
||||||
|
(eitherReader uriParser)
|
||||||
|
(long "remote-source-dist" <> metavar "URI" <> help
|
||||||
|
"URI (https/http/file) to a HLS source distribution"
|
||||||
|
<> completer fileUri
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
<*> 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"))
|
||||||
|
<*> switch (long "cabal-update" <> help "Run 'cabal update' before the build")
|
||||||
|
<*>
|
||||||
|
(
|
||||||
|
(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 [] 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 [] GHC))
|
||||||
|
)
|
||||||
|
<*> many (argument str (metavar "CABAL_ARGS" <> help "Additional arguments to cabal install, prefix with '-- ' (longopts)"))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
--[ Effect interpreters ]--
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
|
||||||
|
type GHCEffects = '[ AlreadyInstalled
|
||||||
|
, BuildFailed
|
||||||
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
|
, GPGError
|
||||||
|
, DownloadFailed
|
||||||
|
, GHCupSetError
|
||||||
|
, NoDownload
|
||||||
|
, NotFoundInPATH
|
||||||
|
, PatchFailed
|
||||||
|
, UnknownArchive
|
||||||
|
, TarDirDoesNotExist
|
||||||
|
, NotInstalled
|
||||||
|
, DirNotEmpty
|
||||||
|
, ArchiveResult
|
||||||
|
, FileDoesNotExistError
|
||||||
|
, HadrianNotFound
|
||||||
|
, InvalidBuildConfig
|
||||||
|
, ProcessError
|
||||||
|
, CopyError
|
||||||
|
, BuildFailed
|
||||||
|
, UninstallFailed
|
||||||
|
, MergeFileTreeError
|
||||||
|
]
|
||||||
|
type HLSEffects = '[ AlreadyInstalled
|
||||||
|
, BuildFailed
|
||||||
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
|
, GPGError
|
||||||
|
, DownloadFailed
|
||||||
|
, GHCupSetError
|
||||||
|
, NoDownload
|
||||||
|
, NotFoundInPATH
|
||||||
|
, PatchFailed
|
||||||
|
, UnknownArchive
|
||||||
|
, TarDirDoesNotExist
|
||||||
|
, TagNotFound
|
||||||
|
, DayNotFound
|
||||||
|
, 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
|
||||||
|
HLS.SourceDist targetVer -> do
|
||||||
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
|
let vi = getVersionInfo (mkTVer 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
|
||||||
|
_ -> 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
|
||||||
|
updateCabal
|
||||||
|
patches
|
||||||
|
cabalArgs
|
||||||
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
|
let vi = getVersionInfo (mkTVer 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 $ prettyHFError err
|
||||||
|
_ -> runLogger (logError $ T.pack (prettyHFError 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 $ prettyHFError e
|
||||||
|
pure $ ExitFailure 9
|
||||||
|
(CompileGHC GHCCompileOptions {..}) ->
|
||||||
|
runCompileGHC runAppState (do
|
||||||
|
case targetGhc of
|
||||||
|
GHC.SourceDist targetVer -> do
|
||||||
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
|
let vi = getVersionInfo (mkTVer 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
|
||||||
|
_ -> pure ()
|
||||||
|
targetVer <- liftE $ compileGHC
|
||||||
|
targetGhc
|
||||||
|
crossTarget
|
||||||
|
ovewrwiteVer
|
||||||
|
bootstrapGhc
|
||||||
|
jobs
|
||||||
|
buildConfig
|
||||||
|
patches
|
||||||
|
addConfArgs
|
||||||
|
buildFlavour
|
||||||
|
hadrian
|
||||||
|
(maybe GHCupInternal IsolateDir isolateDir)
|
||||||
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
|
let vi = getVersionInfo 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 $ prettyHFError err
|
||||||
|
_ -> runLogger (logError $ T.pack (prettyHFError 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 $ prettyHFError e
|
||||||
|
pure $ ExitFailure 9
|
||||||
261
app/ghcup/GHCup/OptParse/Config.hs
Normal file
261
app/ghcup/GHCup/OptParse/Config.hs
Normal file
@@ -0,0 +1,261 @@
|
|||||||
|
{-# 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 Bool 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 <$> switch (long "force" <> help "Delete existing entry (if any) and append instead of failing") <*> 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 -> UserSettings -> UserSettings
|
||||||
|
updateSettings usl usr =
|
||||||
|
let cache' = uCache usl <|> uCache usr
|
||||||
|
metaCache' = uMetaCache usl <|> uMetaCache usr
|
||||||
|
metaMode' = uMetaMode usl <|> uMetaMode usr
|
||||||
|
noVerify' = uNoVerify usl <|> uNoVerify usr
|
||||||
|
verbose' = uVerbose usl <|> uVerbose usr
|
||||||
|
keepDirs' = uKeepDirs usl <|> uKeepDirs usr
|
||||||
|
downloader' = uDownloader usl <|> uDownloader usr
|
||||||
|
urlSource' = uUrlSource usl <|> uUrlSource usr
|
||||||
|
noNetwork' = uNoNetwork usl <|> uNoNetwork usr
|
||||||
|
gpgSetting' = uGPGSetting usl <|> uGPGSetting usr
|
||||||
|
platformOverride' = uPlatformOverride usl <|> uPlatformOverride usr
|
||||||
|
mirrors' = uMirrors usl <|> uMirrors usr
|
||||||
|
in UserSettings cache' metaCache' metaMode' noVerify' verbose' keepDirs' downloader' (updateKeyBindings (uKeyBindings usl) (uKeyBindings usr)) urlSource' noNetwork' gpgSetting' platformOverride' mirrors'
|
||||||
|
where
|
||||||
|
updateKeyBindings :: Maybe UserKeyBindings -> Maybe UserKeyBindings -> Maybe UserKeyBindings
|
||||||
|
updateKeyBindings Nothing Nothing = Nothing
|
||||||
|
updateKeyBindings (Just kbl) Nothing = Just kbl
|
||||||
|
updateKeyBindings Nothing (Just kbr) = Just kbr
|
||||||
|
updateKeyBindings (Just kbl) (Just kbr) =
|
||||||
|
Just $ UserKeyBindings {
|
||||||
|
kUp = kUp kbl <|> kUp kbr
|
||||||
|
, kDown = kDown kbl <|> kDown kbr
|
||||||
|
, kQuit = kQuit kbl <|> kQuit kbr
|
||||||
|
, kInstall = kInstall kbl <|> kInstall kbr
|
||||||
|
, kUninstall = kUninstall kbl <|> kUninstall kbr
|
||||||
|
, kSet = kSet kbl <|> kSet kbr
|
||||||
|
, kChangelog = kChangelog kbl <|> kChangelog kbr
|
||||||
|
, kShowAll = kShowAll kbl <|> kShowAll kbr
|
||||||
|
, kShowAllTools = kShowAllTools kbl <|> kShowAllTools kbr
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
------------------
|
||||||
|
--[ Entrypoint ]--
|
||||||
|
------------------
|
||||||
|
|
||||||
|
data Duplicate = Duplicate -- ^ there is a duplicate somewhere in the middle
|
||||||
|
| NoDuplicate -- ^ there is no duplicate
|
||||||
|
| DuplicateLast -- ^ there's a duplicate, but it's the last element
|
||||||
|
|
||||||
|
|
||||||
|
config :: forall m. ( Monad m
|
||||||
|
, MonadMask m
|
||||||
|
, MonadUnliftIO m
|
||||||
|
, MonadFail m
|
||||||
|
)
|
||||||
|
=> ConfigCommand
|
||||||
|
-> Settings
|
||||||
|
-> UserSettings
|
||||||
|
-> KeyBindings
|
||||||
|
-> (ReaderT LeanAppState m () -> m ())
|
||||||
|
-> m ExitCode
|
||||||
|
config configCommand settings userConf 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 force uri -> do
|
||||||
|
r <- runE @'[DuplicateReleaseChannel] $ do
|
||||||
|
case urlSource settings of
|
||||||
|
AddSource xs -> do
|
||||||
|
case checkDuplicate xs (Right uri) of
|
||||||
|
Duplicate
|
||||||
|
| not force -> throwE (DuplicateReleaseChannel uri)
|
||||||
|
DuplicateLast -> pure ()
|
||||||
|
_ -> lift $ doConfig (defaultUserSettings { uUrlSource = Just $ AddSource (appendUnique xs (Right uri)) })
|
||||||
|
GHCupURL -> do
|
||||||
|
lift $ doConfig (defaultUserSettings { uUrlSource = Just $ AddSource [Right uri] })
|
||||||
|
pure ()
|
||||||
|
OwnSource xs -> do
|
||||||
|
case checkDuplicate xs (Right uri) of
|
||||||
|
Duplicate
|
||||||
|
| not force -> throwE (DuplicateReleaseChannel uri)
|
||||||
|
DuplicateLast -> pure ()
|
||||||
|
_ -> lift $ doConfig (defaultUserSettings { uUrlSource = Just $ OwnSource (appendUnique xs (Right uri)) })
|
||||||
|
OwnSpec spec -> do
|
||||||
|
lift $ doConfig (defaultUserSettings { uUrlSource = Just $ OwnSource [Left spec, Right uri] })
|
||||||
|
pure ()
|
||||||
|
case r of
|
||||||
|
VRight _ -> do
|
||||||
|
pure ExitSuccess
|
||||||
|
VLeft e -> do
|
||||||
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
|
pure $ ExitFailure 15
|
||||||
|
|
||||||
|
where
|
||||||
|
checkDuplicate :: Eq a => [a] -> a -> Duplicate
|
||||||
|
checkDuplicate xs a
|
||||||
|
| last xs == a = DuplicateLast
|
||||||
|
| a `elem` xs = Duplicate
|
||||||
|
| otherwise = NoDuplicate
|
||||||
|
|
||||||
|
-- appends the element to the end of the list, but also removes it from the existing list
|
||||||
|
appendUnique :: Eq a => [a] -> a -> [a]
|
||||||
|
appendUnique xs' e = go xs'
|
||||||
|
where
|
||||||
|
go [] = [e]
|
||||||
|
go (x:xs)
|
||||||
|
| x == e = go xs -- skip
|
||||||
|
| otherwise = x : go xs
|
||||||
|
|
||||||
|
doConfig :: MonadIO m => UserSettings -> m ()
|
||||||
|
doConfig usersettings = do
|
||||||
|
let settings' = updateSettings usersettings userConf
|
||||||
|
path <- liftIO getConfigFilePath
|
||||||
|
liftIO $ writeFile path $ formatConfig $ settings'
|
||||||
|
runLogger $ logDebug $ T.pack $ show settings'
|
||||||
|
pure ()
|
||||||
|
|
||||||
|
decodeSettings = lE' (JSONDecodeError . displayException) . Y.decodeEither' . UTF8.fromString
|
||||||
119
app/ghcup/GHCup/OptParse/DInfo.hs
Normal file
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 $ prettyHFError e
|
||||||
|
pure $ ExitFailure 8
|
||||||
142
app/ghcup/GHCup/OptParse/GC.hs
Normal file
142
app/ghcup/GHCup/OptParse/GC.hs
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
{-# 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 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 $ prettyHFError e
|
||||||
|
pure $ ExitFailure 27
|
||||||
538
app/ghcup/GHCup/OptParse/Install.hs
Normal file
538
app/ghcup/GHCup/OptParse/Install.hs
Normal file
@@ -0,0 +1,538 @@
|
|||||||
|
{-# 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 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
|
||||||
|
, 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/ghc/ghc/-/jobs/artifacts/master/raw/ghc-x86_64-linux-fedora33-release.tar.xz?job=x86_64-linux-fedora33-release' head|]
|
||||||
|
|
||||||
|
|
||||||
|
installOpts :: Maybe Tool -> Parser InstallOptions
|
||||||
|
installOpts tool =
|
||||||
|
(\(u, v) b is f -> InstallOptions v u b is f)
|
||||||
|
<$> ( ( (,)
|
||||||
|
<$> 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 [] 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
|
||||||
|
, DayNotFound
|
||||||
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
|
, GPGError
|
||||||
|
, DownloadFailed
|
||||||
|
, TarDirDoesNotExist
|
||||||
|
, NextVerNotFound
|
||||||
|
, NoToolVersionSet
|
||||||
|
, FileAlreadyExistsError
|
||||||
|
, ProcessError
|
||||||
|
, UninstallFailed
|
||||||
|
, MergeFileTreeError
|
||||||
|
, InstallSetError
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
runInstTool :: AppState
|
||||||
|
-> Excepts InstallEffects (ResourceT (ReaderT AppState IO)) a
|
||||||
|
-> IO (VEither InstallEffects a)
|
||||||
|
runInstTool appstate' =
|
||||||
|
flip runReaderT appstate'
|
||||||
|
. runResourceT
|
||||||
|
. runE
|
||||||
|
@InstallEffects
|
||||||
|
|
||||||
|
|
||||||
|
type InstallGHCEffects = '[ AlreadyInstalled
|
||||||
|
, ArchiveResult
|
||||||
|
, BuildFailed
|
||||||
|
, CopyError
|
||||||
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
|
, DirNotEmpty
|
||||||
|
, DownloadFailed
|
||||||
|
, FileAlreadyExistsError
|
||||||
|
, FileDoesNotExistError
|
||||||
|
, GPGError
|
||||||
|
, MergeFileTreeError
|
||||||
|
, NextVerNotFound
|
||||||
|
, NoDownload
|
||||||
|
, NoToolVersionSet
|
||||||
|
, NotInstalled
|
||||||
|
, ProcessError
|
||||||
|
, TagNotFound
|
||||||
|
, DayNotFound
|
||||||
|
, TarDirDoesNotExist
|
||||||
|
, UninstallFailed
|
||||||
|
, UnknownArchive
|
||||||
|
, InstallSetError
|
||||||
|
]
|
||||||
|
|
||||||
|
runInstGHC :: AppState
|
||||||
|
-> Excepts InstallGHCEffects (ResourceT (ReaderT AppState IO)) a
|
||||||
|
-> IO (VEither InstallGHCEffects a)
|
||||||
|
runInstGHC appstate' =
|
||||||
|
flip runReaderT appstate'
|
||||||
|
. 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' $ do
|
||||||
|
(v, vi) <- liftE $ fromVersion instVer GHC
|
||||||
|
liftE $ runBothE' (installGHCBin
|
||||||
|
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}} $ do
|
||||||
|
(v, vi) <- liftE $ fromVersion instVer GHC
|
||||||
|
liftE $ runBothE' (installGHCBindist
|
||||||
|
(DownloadInfo uri (Just $ RegexDir "ghc-.*") "" Nothing Nothing)
|
||||||
|
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 $ prettyHFError e
|
||||||
|
pure ExitSuccess
|
||||||
|
VLeft e@(V (AlreadyInstalled _ _)) -> do
|
||||||
|
runLogger $ logWarn $ T.pack $ prettyHFError 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 $ prettyHFError err)
|
||||||
|
_ -> runLogger (logError $ T.pack (prettyHFError 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 $ prettyHFError err)
|
||||||
|
_ -> runLogger (logError $ T.pack (prettyHFError 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 $ prettyHFError 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' $ 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}} $ do
|
||||||
|
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Cabal
|
||||||
|
liftE $ runBothE' (installCabalBindist
|
||||||
|
(DownloadInfo uri Nothing "" Nothing 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 $ prettyHFError 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 $ prettyHFError 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 $ prettyHFError 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' $ 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}} $ do
|
||||||
|
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer HLS
|
||||||
|
-- TODO: support legacy
|
||||||
|
liftE $ runBothE' (installHLSBindist
|
||||||
|
(DownloadInfo uri (if isWindows then Nothing else Just (RegexDir "haskell-language-server-*")) "" Nothing Nothing)
|
||||||
|
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 $ prettyHFError 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 $ prettyHFError 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 $ prettyHFError 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' $ 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}} $ do
|
||||||
|
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Stack
|
||||||
|
liftE $ runBothE' (installStackBindist
|
||||||
|
(DownloadInfo uri Nothing "" Nothing 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 $ prettyHFError 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 $ prettyHFError 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 $ prettyHFError e
|
||||||
|
logError $ "Also check the logs in " <> T.pack (fromGHCupPath logsDir)
|
||||||
|
pure $ ExitFailure 4
|
||||||
315
app/ghcup/GHCup/OptParse/List.hs
Normal file
315
app/ghcup/GHCup/OptParse/List.hs
Normal file
@@ -0,0 +1,315 @@
|
|||||||
|
{-# LANGUAGE CPP #-}
|
||||||
|
{-# LANGUAGE DataKinds #-}
|
||||||
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
|
{-# LANGUAGE DuplicateRecordFields #-}
|
||||||
|
{-# LANGUAGE RankNTypes #-}
|
||||||
|
|
||||||
|
module GHCup.OptParse.List where
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import GHCup
|
||||||
|
import GHCup.Prelude
|
||||||
|
import GHCup.Types
|
||||||
|
import GHCup.OptParse.Common
|
||||||
|
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.Char
|
||||||
|
import Data.List ( intercalate, sort )
|
||||||
|
import Data.Functor
|
||||||
|
import Data.Maybe
|
||||||
|
import Data.Time.Calendar ( Day )
|
||||||
|
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
|
||||||
|
, lFrom :: Maybe Day
|
||||||
|
, lTo :: Maybe Day
|
||||||
|
, lHideOld :: Bool
|
||||||
|
, lShowNightly :: Bool
|
||||||
|
, 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 "Apply filtering criteria, prefix with + or -"
|
||||||
|
<> completer (listCompleter
|
||||||
|
[ "+installed", "+set", "+available", "-installed", "-set", "-available"])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
<*> optional
|
||||||
|
(option
|
||||||
|
(eitherReader dayParser)
|
||||||
|
(short 's' <> long "since" <> metavar "YYYY-MM-DD" <> help
|
||||||
|
"List only tools with release date starting at YYYY-MM-DD or later"
|
||||||
|
<> completer toolCompleter
|
||||||
|
)
|
||||||
|
)
|
||||||
|
<*> optional
|
||||||
|
(option
|
||||||
|
(eitherReader dayParser)
|
||||||
|
(short 'u' <> long "until" <> metavar "YYYY-MM-DD" <> help
|
||||||
|
"List only tools with release date earlier than YYYY-MM-DD"
|
||||||
|
<> completer toolCompleter
|
||||||
|
)
|
||||||
|
)
|
||||||
|
<*> switch
|
||||||
|
(short 'o' <> long "hide-old" <> help "Hide 'old' GHC versions (installed ones are always shown)"
|
||||||
|
)
|
||||||
|
<*> switch
|
||||||
|
(short 'n' <> long "show-nightly" <> help "Show nightlies (installed ones are always shown)"
|
||||||
|
)
|
||||||
|
<*> switch
|
||||||
|
(short 'r' <> long "raw-format" <> help "More machine-parsable format"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
--------------
|
||||||
|
--[ Footer ]--
|
||||||
|
--------------
|
||||||
|
|
||||||
|
|
||||||
|
listToolFooter :: String
|
||||||
|
listToolFooter = [s|Discussion:
|
||||||
|
Lists tool versions with optional criteria.
|
||||||
|
Nightlies are by default hidden.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
# query nightlies in a specific range
|
||||||
|
ghcup list --show-nightly --since 2022-12-07 --until 2022-12-31
|
||||||
|
# show all installed GHC versions
|
||||||
|
ghcup list -t ghc -c installed|]
|
||||||
|
|
||||||
|
|
||||||
|
-----------------
|
||||||
|
--[ 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 Nightly = color Red "nightly"
|
||||||
|
printTag (Base pvp'') = "base-" ++ T.unpack (prettyPVP pvp'')
|
||||||
|
printTag (UnknownTag t ) = t
|
||||||
|
printTag LatestPrerelease = color Red "latest-prerelease"
|
||||||
|
printTag LatestNightly = color Red "latest-nightly"
|
||||||
|
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)
|
||||||
|
++ (case lReleaseDay of
|
||||||
|
Nothing -> mempty
|
||||||
|
Just d -> [color Blue (show d)])
|
||||||
|
++ (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 (maybeToList lCriteria) lHideOld lShowNightly (lFrom, lTo)
|
||||||
|
liftIO $ printListResult no_color lRawFormat l
|
||||||
|
pure ExitSuccess
|
||||||
|
)
|
||||||
98
app/ghcup/GHCup/OptParse/Nuke.hs
Normal file
98
app/ghcup/GHCup/OptParse/Nuke.hs
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
{-# 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 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 [ListInstalled True] False True (Nothing, Nothing)
|
||||||
|
|
||||||
|
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 $ prettyHFError e
|
||||||
|
pure $ ExitFailure 15
|
||||||
220
app/ghcup/GHCup/OptParse/Prefetch.hs
Normal file
220
app/ghcup/GHCup/OptParse/Prefetch.hs
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
{-# 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 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 [] (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 [] (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 [] (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 [] (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
|
||||||
|
, DayNotFound
|
||||||
|
, NextVerNotFound
|
||||||
|
, NoToolVersionSet
|
||||||
|
, NoDownload
|
||||||
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
|
, 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 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 $ prettyHFError e
|
||||||
|
pure $ ExitFailure 15
|
||||||
231
app/ghcup/GHCup/OptParse/Rm.hs
Normal file
231
app/ghcup/GHCup/OptParse/Rm.hs
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
{-# 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 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' [ListInstalled True] (Just Cabal) <**> helper)
|
||||||
|
(progDesc "Remove Cabal version")
|
||||||
|
)
|
||||||
|
<> command
|
||||||
|
"hls"
|
||||||
|
( RmHLS
|
||||||
|
<$> info (versionParser' [ListInstalled True] (Just HLS) <**> helper)
|
||||||
|
(progDesc "Remove haskell-language-server version")
|
||||||
|
)
|
||||||
|
<> command
|
||||||
|
"stack"
|
||||||
|
( RmStack
|
||||||
|
<$> info (versionParser' [ListInstalled True] (Just Stack) <**> helper)
|
||||||
|
(progDesc "Remove stack version")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
<|> (Right <$> rmOpts Nothing)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
rmOpts :: Maybe Tool -> Parser RmOptions
|
||||||
|
rmOpts tool = RmOptions <$> ghcVersionArgument [ListInstalled True] 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 ghcVer GHC dls)
|
||||||
|
)
|
||||||
|
>>= \case
|
||||||
|
VRight vi -> do
|
||||||
|
runLogger $ logGHCPostRm ghcVer
|
||||||
|
postRmLog vi
|
||||||
|
pure ExitSuccess
|
||||||
|
VLeft e -> do
|
||||||
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
|
pure $ ExitFailure 7
|
||||||
|
|
||||||
|
rmCabal' tv =
|
||||||
|
runRm runAppState (do
|
||||||
|
liftE $
|
||||||
|
rmCabalVer tv
|
||||||
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
|
pure (getVersionInfo (mkTVer tv) Cabal dls)
|
||||||
|
)
|
||||||
|
>>= \case
|
||||||
|
VRight vi -> do
|
||||||
|
postRmLog vi
|
||||||
|
pure ExitSuccess
|
||||||
|
VLeft e -> do
|
||||||
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
|
pure $ ExitFailure 15
|
||||||
|
|
||||||
|
rmHLS' tv =
|
||||||
|
runRm runAppState (do
|
||||||
|
liftE $
|
||||||
|
rmHLSVer tv
|
||||||
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
|
pure (getVersionInfo (mkTVer tv) HLS dls)
|
||||||
|
)
|
||||||
|
>>= \case
|
||||||
|
VRight vi -> do
|
||||||
|
postRmLog vi
|
||||||
|
pure ExitSuccess
|
||||||
|
VLeft e -> do
|
||||||
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
|
pure $ ExitFailure 15
|
||||||
|
|
||||||
|
rmStack' tv =
|
||||||
|
runRm runAppState (do
|
||||||
|
liftE $
|
||||||
|
rmStackVer tv
|
||||||
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
|
pure (getVersionInfo (mkTVer tv) Stack dls)
|
||||||
|
)
|
||||||
|
>>= \case
|
||||||
|
VRight vi -> do
|
||||||
|
postRmLog vi
|
||||||
|
pure ExitSuccess
|
||||||
|
VLeft e -> do
|
||||||
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
|
pure $ ExitFailure 15
|
||||||
|
|
||||||
|
postRmLog vi =
|
||||||
|
forM_ (_viPostRemove =<< vi) $ \msg ->
|
||||||
|
runLogger $ logInfo msg
|
||||||
495
app/ghcup/GHCup/OptParse/Run.hs
Normal file
495
app/ghcup/GHCup/OptParse/Run.hs
Normal file
@@ -0,0 +1,495 @@
|
|||||||
|
{-# 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 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 [] GHC)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
<*> optional
|
||||||
|
(option
|
||||||
|
(eitherReader toolVersionTagEither)
|
||||||
|
(metavar "CABAL_VERSION" <> long "cabal" <> help "The cabal version"
|
||||||
|
<> completer (tagCompleter Cabal [])
|
||||||
|
<> (completer $ versionCompleter [] Cabal)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
<*> optional
|
||||||
|
(option
|
||||||
|
(eitherReader toolVersionTagEither)
|
||||||
|
(metavar "HLS_VERSION" <> long "hls" <> help "The HLS version"
|
||||||
|
<> completer (tagCompleter HLS [])
|
||||||
|
<> (completer $ versionCompleter [] HLS)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
<*> optional
|
||||||
|
(option
|
||||||
|
(eitherReader toolVersionTagEither)
|
||||||
|
(metavar "STACK_VERSION" <> long "stack" <> help "The stack version"
|
||||||
|
<> completer (tagCompleter Stack [])
|
||||||
|
<> (completer $ versionCompleter [] 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
|
||||||
|
, DayNotFound
|
||||||
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
|
, 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 runAppendPATH
|
||||||
|
#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 $ prettyHFError e
|
||||||
|
pure $ ExitFailure 28
|
||||||
|
#endif
|
||||||
|
VLeft e -> do
|
||||||
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
|
pure $ ExitFailure 27
|
||||||
|
|
||||||
|
where
|
||||||
|
|
||||||
|
-- TODO: doesn't work for cross
|
||||||
|
resolveToolchainFull :: ( MonadFail m
|
||||||
|
, MonadThrow m
|
||||||
|
, MonadIO m
|
||||||
|
, MonadCatch m
|
||||||
|
)
|
||||||
|
=> Excepts
|
||||||
|
'[ TagNotFound
|
||||||
|
, DayNotFound
|
||||||
|
, 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
|
||||||
|
, DayNotFound
|
||||||
|
, NextVerNotFound
|
||||||
|
, NoToolVersionSet
|
||||||
|
, UnknownArchive
|
||||||
|
, TarDirDoesNotExist
|
||||||
|
, ProcessError
|
||||||
|
, NotInstalled
|
||||||
|
, NoDownload
|
||||||
|
, GPGError
|
||||||
|
, DownloadFailed
|
||||||
|
, DirNotEmpty
|
||||||
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
|
, 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
|
||||||
|
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)
|
||||||
|
|
||||||
|
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
|
||||||
343
app/ghcup/GHCup/OptParse/Set.hs
Normal file
343
app/ghcup/GHCup/OptParse/Set.hs
Normal file
@@ -0,0 +1,343 @@
|
|||||||
|
{-# 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 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 [ListInstalled True] tool))
|
||||||
|
|
||||||
|
setVersionArgument :: [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
|
||||||
|
, DayNotFound
|
||||||
|
, 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
|
||||||
|
, DayNotFound
|
||||||
|
, 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
|
||||||
|
, DayNotFound
|
||||||
|
, 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
|
||||||
|
, DayNotFound
|
||||||
|
, 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 _ 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 } = 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 $ prettyHFError e
|
||||||
|
pure $ ExitFailure 5
|
||||||
|
|
||||||
|
|
||||||
|
setCabal' :: SetOptions
|
||||||
|
-> m ExitCode
|
||||||
|
setCabal' SetOptions{ sToolVer } = 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 $ prettyHFError e
|
||||||
|
pure $ ExitFailure 14
|
||||||
|
|
||||||
|
setHLS' :: SetOptions
|
||||||
|
-> m ExitCode
|
||||||
|
setHLS' SetOptions{ sToolVer } = 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 $ prettyHFError e
|
||||||
|
pure $ ExitFailure 14
|
||||||
|
|
||||||
|
|
||||||
|
setStack' :: SetOptions
|
||||||
|
-> m ExitCode
|
||||||
|
setStack' SetOptions{ sToolVer } = 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 $ prettyHFError e
|
||||||
|
pure $ ExitFailure 14
|
||||||
189
app/ghcup/GHCup/OptParse/Test.hs
Normal file
189
app/ghcup/GHCup/OptParse/Test.hs
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
{-# LANGUAGE CPP #-}
|
||||||
|
{-# LANGUAGE DataKinds #-}
|
||||||
|
{-# LANGUAGE TypeApplications #-}
|
||||||
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE DuplicateRecordFields #-}
|
||||||
|
{-# LANGUAGE ViewPatterns #-}
|
||||||
|
{-# LANGUAGE TypeOperators #-}
|
||||||
|
|
||||||
|
module GHCup.OptParse.Test where
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import GHCup.OptParse.Common
|
||||||
|
|
||||||
|
import GHCup
|
||||||
|
import GHCup.Errors
|
||||||
|
import GHCup.Types
|
||||||
|
import GHCup.Utils.Dirs
|
||||||
|
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.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 URI.ByteString hiding ( uriParser )
|
||||||
|
|
||||||
|
import qualified Data.Text as T
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
----------------
|
||||||
|
--[ Commands ]--
|
||||||
|
----------------
|
||||||
|
|
||||||
|
|
||||||
|
data TestCommand = TestGHC TestOptions
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------
|
||||||
|
--[ Options ]--
|
||||||
|
---------------
|
||||||
|
|
||||||
|
|
||||||
|
data TestOptions = TestOptions
|
||||||
|
{ testVer :: Maybe ToolVersion
|
||||||
|
, testBindist :: Maybe URI
|
||||||
|
, addMakeArgs :: [T.Text]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------
|
||||||
|
--[ Footers ]--
|
||||||
|
---------------
|
||||||
|
|
||||||
|
testFooter :: String
|
||||||
|
testFooter = [s|Discussion:
|
||||||
|
Runs test suites from the test bindist.|]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------
|
||||||
|
--[ Parsers ]--
|
||||||
|
---------------
|
||||||
|
|
||||||
|
testParser :: Parser TestCommand
|
||||||
|
testParser =
|
||||||
|
subparser
|
||||||
|
( command
|
||||||
|
"ghc"
|
||||||
|
( TestGHC
|
||||||
|
<$> info
|
||||||
|
(testOpts (Just GHC) <**> helper)
|
||||||
|
( progDesc "Test GHC"
|
||||||
|
<> footerDoc (Just $ text testGHCFooter)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
where
|
||||||
|
testGHCFooter :: String
|
||||||
|
testGHCFooter = [s|Discussion:
|
||||||
|
Runs the GHC test suite from the test bindist.|]
|
||||||
|
|
||||||
|
|
||||||
|
testOpts :: Maybe Tool -> Parser TestOptions
|
||||||
|
testOpts tool =
|
||||||
|
(\(u, v) args -> TestOptions v u args)
|
||||||
|
<$> ( ( (,)
|
||||||
|
<$> 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 [] tool)
|
||||||
|
)
|
||||||
|
<|> pure (Nothing, Nothing)
|
||||||
|
)
|
||||||
|
<*> many (argument str (metavar "MAKE_ARGS" <> help "Additional arguments to 'make', prefix with '-- ' (longopts)"))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
--[ Effect interpreters ]--
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
|
||||||
|
type TestGHCEffects = [ DigestError
|
||||||
|
, ContentLengthError
|
||||||
|
, GPGError
|
||||||
|
, DownloadFailed
|
||||||
|
, NoDownload
|
||||||
|
, ArchiveResult
|
||||||
|
, TarDirDoesNotExist
|
||||||
|
, UnknownArchive
|
||||||
|
, TestFailed
|
||||||
|
, NextVerNotFound
|
||||||
|
, TagNotFound
|
||||||
|
, DayNotFound
|
||||||
|
, NoToolVersionSet
|
||||||
|
]
|
||||||
|
|
||||||
|
runTestGHC :: AppState
|
||||||
|
-> Excepts TestGHCEffects (ResourceT (ReaderT AppState IO)) a
|
||||||
|
-> IO (VEither TestGHCEffects a)
|
||||||
|
runTestGHC appstate' =
|
||||||
|
flip runReaderT appstate'
|
||||||
|
. runResourceT
|
||||||
|
. runE
|
||||||
|
@TestGHCEffects
|
||||||
|
|
||||||
|
|
||||||
|
-------------------
|
||||||
|
--[ Entrypoints ]--
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
|
||||||
|
test :: TestCommand -> Settings -> IO AppState -> (ReaderT LeanAppState IO () -> IO ()) -> IO ExitCode
|
||||||
|
test testCommand settings getAppState' runLogger = case testCommand of
|
||||||
|
(TestGHC iopts) -> go iopts
|
||||||
|
where
|
||||||
|
go :: TestOptions -> IO ExitCode
|
||||||
|
go TestOptions{..} = do
|
||||||
|
s'@AppState{ dirs = Dirs{ .. } } <- liftIO getAppState'
|
||||||
|
(case testBindist of
|
||||||
|
Nothing -> runTestGHC s' $ do
|
||||||
|
(v, vi) <- liftE $ fromVersion testVer GHC
|
||||||
|
liftE $ testGHCVer v addMakeArgs
|
||||||
|
pure vi
|
||||||
|
Just uri -> do
|
||||||
|
runTestGHC s'{ settings = settings {noVerify = True}} $ do
|
||||||
|
(v, vi) <- liftE $ fromVersion testVer GHC
|
||||||
|
liftE $ testGHCBindist (DownloadInfo uri (Just $ RegexDir ".*/.*") "" Nothing Nothing) v addMakeArgs
|
||||||
|
pure vi
|
||||||
|
)
|
||||||
|
>>= \case
|
||||||
|
VRight _ -> do
|
||||||
|
runLogger $ logInfo "GHC test successful"
|
||||||
|
pure ExitSuccess
|
||||||
|
VLeft e -> do
|
||||||
|
runLogger $ do
|
||||||
|
logError $ T.pack $ prettyHFError e
|
||||||
|
logError $ "Also check the logs in " <> T.pack (fromGHCupPath logsDir)
|
||||||
|
pure $ ExitFailure 3
|
||||||
|
|
||||||
121
app/ghcup/GHCup/OptParse/ToolRequirements.hs
Normal file
121
app/ghcup/GHCup/OptParse/ToolRequirements.hs
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
{-# 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 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 $ prettyHFError e
|
||||||
|
pure $ ExitFailure 12
|
||||||
204
app/ghcup/GHCup/OptParse/UnSet.hs
Normal file
204
app/ghcup/GHCup/OptParse/UnSet.hs
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
{-# 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 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 $ prettyHFError 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
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 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
|
||||||
|
, ContentLengthError
|
||||||
|
, 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 $ prettyHFError e
|
||||||
|
pure $ ExitFailure 11
|
||||||
342
app/ghcup/GHCup/OptParse/Whereis.hs
Normal file
342
app/ghcup/GHCup/OptParse/Whereis.hs
Normal file
@@ -0,0 +1,342 @@
|
|||||||
|
{-# 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.Environment
|
||||||
|
import System.Exit
|
||||||
|
|
||||||
|
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 [] (Just GHC)) <**> helper )
|
||||||
|
( progDesc "Get GHC location"
|
||||||
|
<> footerDoc (Just $ text whereisGHCFooter ))
|
||||||
|
)
|
||||||
|
<>
|
||||||
|
command
|
||||||
|
"cabal"
|
||||||
|
(WhereisTool Cabal <$> info
|
||||||
|
( optional (toolVersionTagArgument [] (Just Cabal)) <**> helper )
|
||||||
|
( progDesc "Get cabal location"
|
||||||
|
<> footerDoc (Just $ text whereisCabalFooter ))
|
||||||
|
)
|
||||||
|
<>
|
||||||
|
command
|
||||||
|
"hls"
|
||||||
|
(WhereisTool HLS <$> info
|
||||||
|
( optional (toolVersionTagArgument [] (Just HLS)) <**> helper )
|
||||||
|
( progDesc "Get HLS location"
|
||||||
|
<> footerDoc (Just $ text whereisHLSFooter ))
|
||||||
|
)
|
||||||
|
<>
|
||||||
|
command
|
||||||
|
"stack"
|
||||||
|
(WhereisTool Stack <$> info
|
||||||
|
( optional (toolVersionTagArgument [] (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
|
||||||
|
, DayNotFound
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
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 GHCup _, WhereisOptions{..}) -> do
|
||||||
|
loc <- liftIO (getExecutablePath >>= canonicalizePath )
|
||||||
|
if directory
|
||||||
|
then liftIO $ putStr $ takeDirectory loc
|
||||||
|
else liftIO $ putStr loc
|
||||||
|
pure ExitSuccess
|
||||||
|
|
||||||
|
(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 $ prettyHFError 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 $ prettyHFError 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 $ prettyHFError 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
|
||||||
2570
app/ghcup/Main.hs
2570
app/ghcup/Main.hs
File diff suppressed because it is too large
Load Diff
@@ -1,653 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Main settings:
|
|
||||||
# * BOOTSTRAP_HASKELL_NONINTERACTIVE - any nonzero value for noninteractive installation
|
|
||||||
# * BOOTSTRAP_HASKELL_NO_UPGRADE - any nonzero value to not trigger the upgrade
|
|
||||||
# * GHCUP_USE_XDG_DIRS - any nonzero value to respect The XDG Base Directory Specification
|
|
||||||
# * BOOTSTRAP_HASKELL_VERBOSE - any nonzero value for more verbose installation
|
|
||||||
# * BOOTSTRAP_HASKELL_GHC_VERSION - the ghc version to install
|
|
||||||
# * BOOTSTRAP_HASKELL_CABAL_VERSION - the cabal version to install
|
|
||||||
# * BOOTSTRAP_HASKELL_INSTALL_STACK - whether to install latest stack
|
|
||||||
# * BOOTSTRAP_HASKELL_INSTALL_HLS - whether to install latest hls
|
|
||||||
# * BOOTSTRAP_HASKELL_ADJUST_BASHRC - whether to adjust PATH in bashrc (prepend)
|
|
||||||
# * BOOTSTRAP_HASKELL_ADJUST_CABAL_CONFIG - whether to adjust mingw paths in cabal.config on windows
|
|
||||||
|
|
||||||
# License: LGPL-3.0
|
|
||||||
|
|
||||||
|
|
||||||
# safety subshell to avoid executing anything in case this script is not downloaded properly
|
|
||||||
(
|
|
||||||
|
|
||||||
plat="$(uname -s)"
|
|
||||||
arch=$(uname -m)
|
|
||||||
ghver="0.1.16.1"
|
|
||||||
base_url="https://downloads.haskell.org/~ghcup"
|
|
||||||
|
|
||||||
export GHCUP_SKIP_UPDATE_CHECK=yes
|
|
||||||
|
|
||||||
case "${plat}" in
|
|
||||||
MSYS*|MINGW*)
|
|
||||||
: "${GHCUP_INSTALL_BASE_PREFIX:=/c}"
|
|
||||||
GHCUP_DIR=$(cygpath -u "${GHCUP_INSTALL_BASE_PREFIX}/ghcup")
|
|
||||||
GHCUP_BIN=$(cygpath -u "${GHCUP_INSTALL_BASE_PREFIX}/ghcup/bin")
|
|
||||||
: "${GHCUP_MSYS2:=${GHCUP_DIR}/msys64}"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
: "${GHCUP_INSTALL_BASE_PREFIX:=$HOME}"
|
|
||||||
export GHCUP_USE_XDG_DIRS
|
|
||||||
|
|
||||||
if [ -n "${GHCUP_USE_XDG_DIRS}" ] ; then
|
|
||||||
GHCUP_DIR=${XDG_DATA_HOME:=$HOME/.local/share}/ghcup
|
|
||||||
GHCUP_BIN=${XDG_BIN_HOME:=$HOME/.local/bin}
|
|
||||||
else
|
|
||||||
GHCUP_DIR=${GHCUP_INSTALL_BASE_PREFIX}/.ghcup
|
|
||||||
GHCUP_BIN=${GHCUP_INSTALL_BASE_PREFIX}/.ghcup/bin
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
: "${BOOTSTRAP_HASKELL_GHC_VERSION:=recommended}"
|
|
||||||
: "${BOOTSTRAP_HASKELL_CABAL_VERSION:=recommended}"
|
|
||||||
|
|
||||||
|
|
||||||
die() {
|
|
||||||
(>&2 printf "\\033[0;31m%s\\033[0m\\n" "$1")
|
|
||||||
exit 2
|
|
||||||
}
|
|
||||||
|
|
||||||
warn() {
|
|
||||||
case "${plat}" in
|
|
||||||
MSYS*|MINGW*)
|
|
||||||
echo -e "\\033[0;35m$1\\033[0m"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
printf "\\033[0;35m%s\\033[0m\\n" "$1"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
yellow() {
|
|
||||||
case "${plat}" in
|
|
||||||
MSYS*|MINGW*)
|
|
||||||
echo -e "\\033[0;33m$1\\033[0m"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
printf "\\033[0;33m%s\\033[0m\\n" "$1"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
green() {
|
|
||||||
case "${plat}" in
|
|
||||||
MSYS*|MINGW*)
|
|
||||||
echo -e "\\033[0;32m$1\\033[0m"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
printf "\\033[0;32m%s\\033[0m\\n" "$1"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
edo() {
|
|
||||||
"$@" || die "\"$*\" failed!"
|
|
||||||
}
|
|
||||||
|
|
||||||
eghcup() {
|
|
||||||
edo _eghcup "$@"
|
|
||||||
}
|
|
||||||
|
|
||||||
_eghcup() {
|
|
||||||
if [ -n "${BOOTSTRAP_HASKELL_YAML}" ] ; then
|
|
||||||
args="-s ${BOOTSTRAP_HASKELL_YAML}"
|
|
||||||
fi
|
|
||||||
if [ -z "${BOOTSTRAP_HASKELL_VERBOSE}" ] ; then
|
|
||||||
"${GHCUP_BIN}/ghcup" ${args} "$@"
|
|
||||||
else
|
|
||||||
"${GHCUP_BIN}/ghcup" ${args} --verbose "$@"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
_done() {
|
|
||||||
echo
|
|
||||||
echo "==============================================================================="
|
|
||||||
case "${plat}" in
|
|
||||||
MSYS*|MINGW*)
|
|
||||||
green
|
|
||||||
green "All done!"
|
|
||||||
green
|
|
||||||
green "In a new powershell or cmd.exe session, now you can..."
|
|
||||||
green
|
|
||||||
green "Start a simple repl via:"
|
|
||||||
green " ghci"
|
|
||||||
green
|
|
||||||
green "Start a new haskell project in the current directory via:"
|
|
||||||
green " cabal init --interactive"
|
|
||||||
green
|
|
||||||
green "Install other GHC versions and tools via:"
|
|
||||||
green " ghcup list"
|
|
||||||
green " ghcup install <tool> <version>"
|
|
||||||
green
|
|
||||||
green "To install system libraries and update msys2/mingw64,"
|
|
||||||
green "open the \"Mingw haskell shell\""
|
|
||||||
green "and the \"Mingw package management docs\""
|
|
||||||
green "desktop shortcuts."
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
green
|
|
||||||
green "All done!"
|
|
||||||
green
|
|
||||||
green "To start a simple repl, run:"
|
|
||||||
green " ghci"
|
|
||||||
green
|
|
||||||
green "To start a new haskell project in the current directory, run:"
|
|
||||||
green " cabal init --interactive"
|
|
||||||
green
|
|
||||||
green "To install other GHC versions and tools, run:"
|
|
||||||
green " ghcup tui"
|
|
||||||
;;
|
|
||||||
|
|
||||||
esac
|
|
||||||
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
}
|
|
||||||
|
|
||||||
download_ghcup() {
|
|
||||||
|
|
||||||
case "${plat}" in
|
|
||||||
"linux"|"Linux")
|
|
||||||
case "${arch}" in
|
|
||||||
x86_64|amd64)
|
|
||||||
# we could be in a 32bit docker container, in which
|
|
||||||
# case uname doesn't give us what we want
|
|
||||||
if [ "$(getconf LONG_BIT)" = "32" ] ; then
|
|
||||||
_url=${base_url}/${ghver}/i386-linux-ghcup-${ghver}
|
|
||||||
elif [ "$(getconf LONG_BIT)" = "64" ] ; then
|
|
||||||
_url=${base_url}/${ghver}/x86_64-linux-ghcup-${ghver}
|
|
||||||
else
|
|
||||||
die "Unknown long bit size: $(getconf LONG_BIT)"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
i*86)
|
|
||||||
_url=${base_url}/${ghver}/i386-linux-ghcup-${ghver}
|
|
||||||
;;
|
|
||||||
armv7*)
|
|
||||||
_url=${base_url}/${ghver}/armv7-linux-ghcup-${ghver}
|
|
||||||
;;
|
|
||||||
aarch64|arm64|armv8l)
|
|
||||||
_url=${base_url}/${ghver}/aarch64-linux-ghcup-${ghver}
|
|
||||||
;;
|
|
||||||
*) 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=${base_url}/${ghver}/x86_64-portbld-freebsd-ghcup-${ghver}
|
|
||||||
;;
|
|
||||||
"Darwin"|"darwin")
|
|
||||||
case "${arch}" in
|
|
||||||
x86_64|amd64)
|
|
||||||
_url=${base_url}/${ghver}/x86_64-apple-darwin-ghcup-${ghver}
|
|
||||||
;;
|
|
||||||
aarch64|arm64|armv8l)
|
|
||||||
_url=${base_url}/${ghver}/aarch64-apple-darwin-ghcup-${ghver}
|
|
||||||
;;
|
|
||||||
i*86)
|
|
||||||
die "i386 currently not supported!"
|
|
||||||
;;
|
|
||||||
*) die "Unknown architecture: ${arch}"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
MSYS*|MINGW*)
|
|
||||||
case "${arch}" in
|
|
||||||
x86_64|amd64)
|
|
||||||
_url=${base_url}/${ghver}/x86_64-mingw64-ghcup-${ghver}.exe
|
|
||||||
;;
|
|
||||||
*) die "Unknown architecture: ${arch}"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
*) die "Unknown platform: ${plat}"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
case "${plat}" in
|
|
||||||
MSYS*|MINGW*)
|
|
||||||
edo curl -Lf "${_url}" > "${GHCUP_BIN}"/ghcup.exe
|
|
||||||
edo chmod +x "${GHCUP_BIN}"/ghcup.exe
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
edo curl -Lf "${_url}" > "${GHCUP_BIN}"/ghcup
|
|
||||||
edo chmod +x "${GHCUP_BIN}"/ghcup
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
edo mkdir -p "${GHCUP_DIR}"
|
|
||||||
|
|
||||||
# we may overwrite this in adjust_bashrc
|
|
||||||
cat <<-EOF > "${GHCUP_DIR}"/env || die "Failed to create env file"
|
|
||||||
export PATH="\$HOME/.cabal/bin:${GHCUP_BIN}:\$PATH"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# shellcheck disable=SC1090
|
|
||||||
edo . "${GHCUP_DIR}"/env
|
|
||||||
eghcup upgrade
|
|
||||||
}
|
|
||||||
|
|
||||||
# Figures out the users login shell and sets
|
|
||||||
# GHCUP_PROFILE_FILE and MY_SHELL variables.
|
|
||||||
find_shell() {
|
|
||||||
case $SHELL in
|
|
||||||
*/zsh) # login shell is zsh
|
|
||||||
GHCUP_PROFILE_FILE="$HOME/.zshrc"
|
|
||||||
MY_SHELL="zsh" ;;
|
|
||||||
*/bash) # login shell is bash
|
|
||||||
GHCUP_PROFILE_FILE="$HOME/.bashrc"
|
|
||||||
MY_SHELL="bash" ;;
|
|
||||||
*/sh) # login shell is sh, but might be a symlink to bash or zsh
|
|
||||||
if [ -n "${BASH}" ] ; then
|
|
||||||
GHCUP_PROFILE_FILE="$HOME/.bashrc"
|
|
||||||
MY_SHELL="bash"
|
|
||||||
elif [ -n "${ZSH_VERSION}" ] ; then
|
|
||||||
GHCUP_PROFILE_FILE="$HOME/.zshrc"
|
|
||||||
MY_SHELL="zsh"
|
|
||||||
else
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
*/fish) # login shell is fish
|
|
||||||
GHCUP_PROFILE_FILE="$HOME/.config/fish/config.fish"
|
|
||||||
MY_SHELL="fish" ;;
|
|
||||||
*) return ;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
# Ask user if they want to adjust the bashrc.
|
|
||||||
ask_bashrc() {
|
|
||||||
if [ -n "${BOOTSTRAP_HASKELL_ADJUST_BASHRC}" ] ; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
while true; do
|
|
||||||
if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then
|
|
||||||
echo "-------------------------------------------------------------------------------"
|
|
||||||
|
|
||||||
warn ""
|
|
||||||
warn "Detected ${MY_SHELL} shell on your system..."
|
|
||||||
warn "Do you want ghcup to automatically add the required PATH variable to \"${GHCUP_PROFILE_FILE}\"?"
|
|
||||||
warn ""
|
|
||||||
warn "[P] Yes, prepend [A] Yes, append [N] No [?] Help (default is \"P\")."
|
|
||||||
warn ""
|
|
||||||
|
|
||||||
read -r bashrc_answer </dev/tty
|
|
||||||
else
|
|
||||||
# On windows .bashrc isn't an important user config, so we adjust it
|
|
||||||
# always. On other platforms, let's be a bit more conservative.
|
|
||||||
case "${plat}" in
|
|
||||||
MSYS*|MINGW*)
|
|
||||||
return 1
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
case $bashrc_answer in
|
|
||||||
[Pp]* | "")
|
|
||||||
return 1
|
|
||||||
;;
|
|
||||||
[Aa]*)
|
|
||||||
return 2
|
|
||||||
;;
|
|
||||||
[Nn]*)
|
|
||||||
return 0;;
|
|
||||||
*)
|
|
||||||
echo "Possible choices are:"
|
|
||||||
echo
|
|
||||||
echo "P - Yes, prepend to PATH, taking precedence (default)"
|
|
||||||
echo "A - Yes, append to PATH"
|
|
||||||
echo "N - No, don't mess with my configuration"
|
|
||||||
echo
|
|
||||||
echo "Please make your choice and press ENTER."
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
unset bashrc_answer
|
|
||||||
}
|
|
||||||
|
|
||||||
# Needs 'find_shell' to be called beforehand.
|
|
||||||
adjust_bashrc() {
|
|
||||||
case $1 in
|
|
||||||
1)
|
|
||||||
cat <<-EOF > "${GHCUP_DIR}"/env || die "Failed to create env file"
|
|
||||||
export PATH="\$HOME/.cabal/bin:${GHCUP_BIN}:\$PATH"
|
|
||||||
EOF
|
|
||||||
;;
|
|
||||||
2)
|
|
||||||
cat <<-EOF > "${GHCUP_DIR}"/env || die "Failed to create env file"
|
|
||||||
export PATH="\$PATH:\$HOME/.cabal/bin:${GHCUP_BIN}"
|
|
||||||
EOF
|
|
||||||
;;
|
|
||||||
*) ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
case $1 in
|
|
||||||
1 | 2)
|
|
||||||
case $MY_SHELL in
|
|
||||||
"")
|
|
||||||
warn_path "Couldn't figure out login shell!"
|
|
||||||
return
|
|
||||||
;;
|
|
||||||
fish)
|
|
||||||
mkdir -p "${GHCUP_PROFILE_FILE%/*}"
|
|
||||||
sed -i -e '/# ghcup-env$/ s/^#*/#/' "${GHCUP_PROFILE_FILE}"
|
|
||||||
case $1 in
|
|
||||||
1)
|
|
||||||
echo "set -q GHCUP_INSTALL_BASE_PREFIX[1]; or set GHCUP_INSTALL_BASE_PREFIX \$HOME ; set -gx PATH \$HOME/.cabal/bin $GHCUP_BIN \$PATH # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
|
||||||
;;
|
|
||||||
2)
|
|
||||||
echo "set -q GHCUP_INSTALL_BASE_PREFIX[1]; or set GHCUP_INSTALL_BASE_PREFIX \$HOME ; set -gx PATH \$HOME/.cabal/bin \$PATH $GHCUP_BIN # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
break ;;
|
|
||||||
bash)
|
|
||||||
sed -i -e '/# ghcup-env$/ s/^#*/#/' "${GHCUP_PROFILE_FILE}"
|
|
||||||
echo "[ -f \"${GHCUP_DIR}/env\" ] && source \"${GHCUP_DIR}/env\" # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
|
||||||
case "${plat}" in
|
|
||||||
"Darwin"|"darwin")
|
|
||||||
if ! grep -q "ghcup-env" "${HOME}/.bash_profile" ; then
|
|
||||||
echo "[[ -f ~/.bashrc ]] && source ~/.bashrc # ghcup-env" >> "${HOME}/.bash_profile"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
break ;;
|
|
||||||
|
|
||||||
zsh)
|
|
||||||
sed -i -e '/# ghcup-env$/ s/^#*/#/' "${GHCUP_PROFILE_FILE}"
|
|
||||||
echo "[ -f \"${GHCUP_DIR}/env\" ] && source \"${GHCUP_DIR}/env\" # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
|
||||||
break ;;
|
|
||||||
esac
|
|
||||||
echo
|
|
||||||
echo "==============================================================================="
|
|
||||||
echo
|
|
||||||
warn "OK! ${GHCUP_PROFILE_FILE} has been modified. Restart your terminal for the changes to take effect,"
|
|
||||||
warn "or type \"source ${GHCUP_DIR}/env\" to apply them in your current terminal session."
|
|
||||||
return
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
warn_path
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
warn_path() {
|
|
||||||
echo
|
|
||||||
echo "==============================================================================="
|
|
||||||
echo
|
|
||||||
[ -n "$1" ] && warn "$1"
|
|
||||||
yellow "In order to run ghc and cabal, you need to adjust your PATH variable."
|
|
||||||
yellow "To do so, you may want run 'source $GHCUP_DIR/env' in your current terminal"
|
|
||||||
yellow "session as well as your shell configuration (e.g. ~/.bashrc)."
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
adjust_cabal_config() {
|
|
||||||
edo cabal user-config -a "extra-prog-path: $(cygpath -w "$GHCUP_BIN"), $(cygpath -w "$HOME"/AppData/Roaming/cabal/bin), $(cygpath -w "$GHCUP_MSYS2"/usr/bin), $(cygpath -w "$GHCUP_MSYS2"/mingw64/bin)" -a "extra-include-dirs: $(cygpath -w "$GHCUP_MSYS2"/mingw64/include)" -a "extra-lib-dirs: $(cygpath -w "$GHCUP_MSYS2"/mingw64/lib)" -f init
|
|
||||||
}
|
|
||||||
|
|
||||||
ask_cabal_config_init() {
|
|
||||||
case "${plat}" in
|
|
||||||
MSYS*|MINGW*)
|
|
||||||
if [ -n "${BOOTSTRAP_HASKELL_ADJUST_CABAL_CONFIG}" ] ; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then
|
|
||||||
echo "-------------------------------------------------------------------------------"
|
|
||||||
warn "Create an initial cabal.config including relevant msys2 paths (recommended)?"
|
|
||||||
warn "[Y] Yes [N] No [?] Help (default is \"Y\")."
|
|
||||||
echo
|
|
||||||
while true; do
|
|
||||||
read -r mingw_answer </dev/tty
|
|
||||||
|
|
||||||
case $mingw_answer in
|
|
||||||
[Yy]* | "")
|
|
||||||
return 1 ;;
|
|
||||||
[Nn]*)
|
|
||||||
return 0 ;;
|
|
||||||
*)
|
|
||||||
echo "Possible choices are:"
|
|
||||||
echo
|
|
||||||
echo "Y - Yes, create a cabal.config with pre-set paths to msys2/mingw64 (default)"
|
|
||||||
echo "N - No, leave the current/default cabal config untouched"
|
|
||||||
echo
|
|
||||||
echo "Please make your choice and press ENTER."
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
else
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
unset mingw_answer
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
do_cabal_config_init() {
|
|
||||||
case "${plat}" in
|
|
||||||
MSYS*|MINGW*)
|
|
||||||
case $1 in
|
|
||||||
1)
|
|
||||||
adjust_cabal_config
|
|
||||||
;;
|
|
||||||
0)
|
|
||||||
echo "Make sure that your global cabal.config references the correct mingw64 paths (extra-prog-path, extra-include-dirs and extra-lib-dirs)."
|
|
||||||
echo "And set the environment variable GHCUP_MSYS2 to the root path of your msys2 installation."
|
|
||||||
sleep 5
|
|
||||||
return ;;
|
|
||||||
*) ;;
|
|
||||||
esac
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
ask_hls() {
|
|
||||||
if [ -n "${BOOTSTRAP_HASKELL_INSTALL_HLS}" ] ; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then
|
|
||||||
echo "-------------------------------------------------------------------------------"
|
|
||||||
|
|
||||||
warn "Do you want to install haskell-language-server (HLS)?"
|
|
||||||
warn "HLS is a language-server that provides IDE-like functionality"
|
|
||||||
warn "and can integrate with different editors, such as Vim, Emacs, VS Code, Atom, ..."
|
|
||||||
warn "Also see https://github.com/haskell/haskell-language-server/blob/master/README.md"
|
|
||||||
warn ""
|
|
||||||
warn "[Y] Yes [N] No [?] Help (default is \"N\")."
|
|
||||||
warn ""
|
|
||||||
|
|
||||||
while true; do
|
|
||||||
read -r hls_answer </dev/tty
|
|
||||||
|
|
||||||
case $hls_answer in
|
|
||||||
[Yy]*)
|
|
||||||
return 1
|
|
||||||
;;
|
|
||||||
[Nn]* | "")
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Possible choices are:"
|
|
||||||
echo
|
|
||||||
echo "Y - Yes, install the haskell-langauge-server"
|
|
||||||
echo "N - No, don't install anything more (default)"
|
|
||||||
echo
|
|
||||||
echo "Please make your choice and press ENTER."
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
else
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
unset hls_answer
|
|
||||||
}
|
|
||||||
|
|
||||||
ask_stack() {
|
|
||||||
if [ -n "${BOOTSTRAP_HASKELL_INSTALL_STACK}" ] ; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then
|
|
||||||
echo "-------------------------------------------------------------------------------"
|
|
||||||
|
|
||||||
warn "Do you want to install stack?"
|
|
||||||
warn "Stack is a haskell build tool similar to cabal that is used by some projects."
|
|
||||||
warn "Also see https://docs.haskellstack.org/"
|
|
||||||
warn ""
|
|
||||||
warn "[Y] Yes [N] No [?] Help (default is \"N\")."
|
|
||||||
warn ""
|
|
||||||
|
|
||||||
while true; do
|
|
||||||
read -r stack_answer </dev/tty
|
|
||||||
|
|
||||||
case $stack_answer in
|
|
||||||
[Yy]*)
|
|
||||||
return 1 ;;
|
|
||||||
[Nn]* | "")
|
|
||||||
return 0 ;;
|
|
||||||
*)
|
|
||||||
echo "Possible choices are:"
|
|
||||||
echo
|
|
||||||
echo "Y - Yes, install stack"
|
|
||||||
echo "N - No, don't install anything more (default)"
|
|
||||||
echo
|
|
||||||
echo "Please make your choice and press ENTER."
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
else
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
unset stack_answer
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
find_shell
|
|
||||||
|
|
||||||
|
|
||||||
echo
|
|
||||||
echo "Welcome to Haskell!"
|
|
||||||
echo
|
|
||||||
echo "This script will download and install the following binaries:"
|
|
||||||
echo " * ghcup - The Haskell toolchain installer"
|
|
||||||
echo " * ghc - The Glasgow Haskell Compiler"
|
|
||||||
echo " * cabal - The Cabal build tool for managing Haskell software"
|
|
||||||
echo " * stack - (optional) A cross-platform program for developing Haskell projects"
|
|
||||||
echo " * hls - (optional) A language server for developers to integrate with their editor/IDE"
|
|
||||||
echo
|
|
||||||
if [ -z "${GHCUP_USE_XDG_DIRS}" ] ; then
|
|
||||||
echo "ghcup installs only into the following directory,"
|
|
||||||
echo "which can be removed anytime:"
|
|
||||||
case "${plat}" in
|
|
||||||
MSYS*|MINGW*)
|
|
||||||
echo " $(cygpath -w "$GHCUP_DIR")"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo " $GHCUP_DIR"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
else
|
|
||||||
echo "ghcup installs into XDG directories as long as"
|
|
||||||
echo "'GHCUP_USE_XDG_DIRS' is set."
|
|
||||||
fi
|
|
||||||
echo
|
|
||||||
|
|
||||||
if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then
|
|
||||||
warn "Press ENTER to proceed or ctrl-c to abort."
|
|
||||||
warn "Note that this script can be re-run at any given time."
|
|
||||||
# Wait for user input to continue.
|
|
||||||
# shellcheck disable=SC2034
|
|
||||||
read -r answer </dev/tty
|
|
||||||
fi
|
|
||||||
|
|
||||||
ask_bashrc
|
|
||||||
ask_bashrc_answer=$?
|
|
||||||
ask_cabal_config_init
|
|
||||||
ask_cabal_config_init_answer=$?
|
|
||||||
ask_hls
|
|
||||||
ask_hls_answer=$?
|
|
||||||
ask_stack
|
|
||||||
ask_stack_answer=$?
|
|
||||||
|
|
||||||
edo mkdir -p "${GHCUP_BIN}"
|
|
||||||
|
|
||||||
if command -V "ghcup" >/dev/null 2>&1 ; then
|
|
||||||
if [ -z "${BOOTSTRAP_HASKELL_NO_UPGRADE}" ] ; then
|
|
||||||
_eghcup upgrade || download_ghcup
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
download_ghcup
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo
|
|
||||||
echo "$(if [ -n "${BOOTSTRAP_HASKELL_YAML}" ] ; then ghcup -s "${BOOTSTRAP_HASKELL_YAML}" tool-requirements ; else ghcup tool-requirements ; fi)"
|
|
||||||
echo
|
|
||||||
|
|
||||||
if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then
|
|
||||||
warn "Press ENTER to proceed or ctrl-c to abort."
|
|
||||||
warn "Installation may take a while."
|
|
||||||
echo
|
|
||||||
|
|
||||||
# Wait for user input to continue.
|
|
||||||
# shellcheck disable=SC2034
|
|
||||||
read -r answer </dev/tty
|
|
||||||
fi
|
|
||||||
|
|
||||||
eghcup --cache install ghc "${BOOTSTRAP_HASKELL_GHC_VERSION}"
|
|
||||||
|
|
||||||
eghcup set ghc "${BOOTSTRAP_HASKELL_GHC_VERSION}"
|
|
||||||
eghcup --cache install cabal "${BOOTSTRAP_HASKELL_CABAL_VERSION}"
|
|
||||||
|
|
||||||
do_cabal_config_init $ask_cabal_config_init_answer
|
|
||||||
|
|
||||||
edo cabal new-update
|
|
||||||
|
|
||||||
case $ask_hls_answer in
|
|
||||||
1)
|
|
||||||
_eghcup --cache install hls || warn "HLS installation failed, continuing anyway"
|
|
||||||
;;
|
|
||||||
*) ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
case $ask_stack_answer in
|
|
||||||
1)
|
|
||||||
_eghcup --cache install stack || warn "Stack installation failed, continuing anyway"
|
|
||||||
;;
|
|
||||||
*) ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
|
|
||||||
adjust_bashrc $ask_bashrc_answer
|
|
||||||
|
|
||||||
|
|
||||||
_done
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
# vim: tabstop=4 shiftwidth=4 expandtab
|
|
||||||
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
packages: ./ghcup.cabal
|
|
||||||
|
|
||||||
optional-packages: ./vendored/*/*.cabal
|
|
||||||
|
|
||||||
optimization: 2
|
|
||||||
|
|
||||||
package ghcup
|
|
||||||
tests: True
|
|
||||||
flags: +tui
|
|
||||||
|
|
||||||
source-repository-package
|
|
||||||
type: git
|
|
||||||
location: https://github.com/jtdaugherty/brick.git
|
|
||||||
tag: b3b96cfe66dfd398d338e3feb2b6855e66a35190
|
|
||||||
|
|
||||||
source-repository-package
|
|
||||||
type: git
|
|
||||||
location: https://github.com/Bodigrim/tar
|
|
||||||
tag: ac197ec7ea4838dc2b4e22b9b888b080cedf29cf
|
|
||||||
|
|
||||||
source-repository-package
|
|
||||||
type: git
|
|
||||||
location: https://github.com/bgamari/terminal-size
|
|
||||||
tag: 34ea816bd63f75f800eedac12c6908c6f3736036
|
|
||||||
|
|
||||||
constraints: http-io-streams -brotli
|
|
||||||
|
|
||||||
package libarchive
|
|
||||||
flags: -system-libarchive
|
|
||||||
|
|
||||||
allow-newer: base, ghc-prim, template-haskell, language-c
|
|
||||||
|
|
||||||
with-compiler: ghc-8.10.5
|
|
||||||
@@ -1,264 +0,0 @@
|
|||||||
active-repositories: hackage.haskell.org:merge
|
|
||||||
constraints: any.Cabal ==3.2.1.0,
|
|
||||||
any.HUnit ==1.6.2.0,
|
|
||||||
any.HsOpenSSL ==0.11.7,
|
|
||||||
HsOpenSSL -fast-bignum -homebrew-openssl -macports-openssl -use-pkg-config,
|
|
||||||
any.QuickCheck ==2.14.2,
|
|
||||||
QuickCheck -old-random +templatehaskell,
|
|
||||||
any.StateVar ==1.2.2,
|
|
||||||
any.aeson ==1.5.6.0,
|
|
||||||
aeson -bytestring-builder -cffi -developer -fast,
|
|
||||||
any.aeson-pretty ==0.8.8,
|
|
||||||
aeson-pretty -lib-only,
|
|
||||||
any.alex ==3.2.6,
|
|
||||||
alex +small_base,
|
|
||||||
any.ansi-terminal ==0.11,
|
|
||||||
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.3,
|
|
||||||
async -bench,
|
|
||||||
any.attoparsec ==0.13.2.5,
|
|
||||||
attoparsec -developer,
|
|
||||||
any.auto-update ==0.1.6,
|
|
||||||
any.base ==4.14.2.0,
|
|
||||||
any.base-compat ==0.11.2,
|
|
||||||
any.base-compat-batteries ==0.11.2,
|
|
||||||
any.base-orphans ==0.8.4,
|
|
||||||
any.base16-bytestring ==1.0.1.0,
|
|
||||||
any.base64-bytestring ==1.1.0.0,
|
|
||||||
any.bifunctors ==5.5.11,
|
|
||||||
bifunctors +semigroups +tagged,
|
|
||||||
any.binary ==0.8.8.0,
|
|
||||||
any.bindings-DSL ==1.0.25,
|
|
||||||
any.blaze-builder ==0.4.2.1,
|
|
||||||
any.brick ==0.63,
|
|
||||||
brick -demos,
|
|
||||||
any.bytestring ==0.10.12.0,
|
|
||||||
any.bz2 ==1.0.1.0,
|
|
||||||
bz2 -cross +with-bzlib,
|
|
||||||
any.bzlib-conduit ==0.3.0.2,
|
|
||||||
any.c2hs ==0.28.8,
|
|
||||||
c2hs +base3 -regression,
|
|
||||||
any.call-stack ==0.4.0,
|
|
||||||
any.case-insensitive ==1.2.1.0,
|
|
||||||
any.casing ==0.1.4.1,
|
|
||||||
any.cereal ==0.5.8.1,
|
|
||||||
cereal -bytestring-builder,
|
|
||||||
any.chs-cabal ==0.1.1.0,
|
|
||||||
any.chs-deps ==0.1.0.0,
|
|
||||||
chs-deps -cross,
|
|
||||||
any.clock ==0.8.2,
|
|
||||||
clock -llvm,
|
|
||||||
any.cmdargs ==0.10.21,
|
|
||||||
cmdargs +quotation -testprog,
|
|
||||||
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.concurrent-output ==1.10.12,
|
|
||||||
any.conduit ==1.3.4.1,
|
|
||||||
any.conduit-extra ==1.3.5,
|
|
||||||
any.conduit-zstd ==0.0.2.0,
|
|
||||||
any.config-ini ==0.2.4.0,
|
|
||||||
config-ini -enable-doctests,
|
|
||||||
any.containers ==0.6.4.1,
|
|
||||||
any.contravariant ==1.5.4,
|
|
||||||
contravariant +semigroups +statevar +tagged,
|
|
||||||
any.cpphs ==1.20.9.1,
|
|
||||||
cpphs -old-locale,
|
|
||||||
any.cryptohash-sha1 ==0.11.100.1,
|
|
||||||
any.cryptohash-sha256 ==0.11.102.0,
|
|
||||||
cryptohash-sha256 -exe +use-cbits,
|
|
||||||
any.data-clist ==0.1.2.3,
|
|
||||||
any.data-default-class ==0.1.2.0,
|
|
||||||
any.data-fix ==0.3.1,
|
|
||||||
any.deepseq ==1.4.4.0,
|
|
||||||
any.digest ==0.0.1.3,
|
|
||||||
digest -bytestring-in-base,
|
|
||||||
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.easy-file ==0.2.2,
|
|
||||||
any.errors ==2.3.0,
|
|
||||||
any.exceptions ==0.10.4,
|
|
||||||
any.extra ==1.7.9,
|
|
||||||
any.fast-logger ==3.0.5,
|
|
||||||
any.filepath ==1.4.2.1,
|
|
||||||
any.free ==5.1.7,
|
|
||||||
any.generic-arbitrary ==0.1.0,
|
|
||||||
any.generics-sop ==0.5.1.1,
|
|
||||||
any.ghc-boot-th ==8.10.5,
|
|
||||||
any.ghc-byteorder ==4.11.0.0.10,
|
|
||||||
any.ghc-prim ==0.6.1,
|
|
||||||
any.happy ==1.20.0,
|
|
||||||
any.hashable ==1.3.2.0,
|
|
||||||
hashable +integer-gmp -random-initial-seed,
|
|
||||||
any.haskell-src-exts ==1.23.1,
|
|
||||||
any.haskell-src-meta ==0.8.7,
|
|
||||||
any.haskus-utils-data ==1.4,
|
|
||||||
any.haskus-utils-types ==1.5.1,
|
|
||||||
any.haskus-utils-variant ==3.1,
|
|
||||||
any.hpath-filepath ==0.10.4,
|
|
||||||
any.hpath-posix ==0.13.3,
|
|
||||||
any.hsc2hs ==0.68.7,
|
|
||||||
hsc2hs -in-ghc-tree,
|
|
||||||
any.hspec ==2.7.10,
|
|
||||||
any.hspec-core ==2.7.10,
|
|
||||||
any.hspec-discover ==2.7.10 || ==2.8.2,
|
|
||||||
any.hspec-expectations ==0.8.2,
|
|
||||||
any.hspec-golden-aeson ==0.9.0.0,
|
|
||||||
any.http-io-streams ==0.1.6.0,
|
|
||||||
http-io-streams -brotli +fast-xor,
|
|
||||||
any.indexed-profunctors ==0.1.1,
|
|
||||||
any.indexed-traversable ==0.1.1,
|
|
||||||
any.indexed-traversable-instances ==0.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.0.1,
|
|
||||||
language-c -allwarnings +iecfpextension +usebytestrings,
|
|
||||||
any.libarchive ==3.0.2.2,
|
|
||||||
libarchive -cross -low-memory -system-libarchive,
|
|
||||||
any.libyaml ==0.1.2,
|
|
||||||
libyaml -no-unicode -system-libyaml,
|
|
||||||
any.lifted-base ==0.2.3.12,
|
|
||||||
any.lzma-static ==5.2.5.4,
|
|
||||||
any.megaparsec ==9.0.1,
|
|
||||||
megaparsec -dev,
|
|
||||||
any.microlens ==0.4.12.0,
|
|
||||||
any.microlens-mtl ==0.2.0.1,
|
|
||||||
any.microlens-th ==0.4.3.10,
|
|
||||||
any.monad-control ==1.0.3,
|
|
||||||
any.monad-logger ==0.3.36,
|
|
||||||
monad-logger +template_haskell,
|
|
||||||
any.monad-loops ==0.4.3,
|
|
||||||
monad-loops +base4,
|
|
||||||
any.mono-traversable ==1.0.15.1,
|
|
||||||
any.mtl ==2.2.2,
|
|
||||||
any.network ==3.1.2.2,
|
|
||||||
network -devel,
|
|
||||||
any.network-uri ==2.6.4.1,
|
|
||||||
any.old-locale ==1.0.0.7,
|
|
||||||
any.old-time ==1.1.0.3,
|
|
||||||
any.openssl-streams ==1.2.3.0,
|
|
||||||
any.optics ==0.4,
|
|
||||||
any.optics-core ==0.4,
|
|
||||||
optics-core -explicit-generic-labels,
|
|
||||||
any.optics-extra ==0.4,
|
|
||||||
any.optics-th ==0.4,
|
|
||||||
any.optics-vl ==0.2.1,
|
|
||||||
any.optparse-applicative ==0.16.1.0,
|
|
||||||
optparse-applicative +process,
|
|
||||||
any.os-release ==1.0.2,
|
|
||||||
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.1.0,
|
|
||||||
any.process ==1.6.9.0,
|
|
||||||
any.profunctors ==5.6.2,
|
|
||||||
any.quickcheck-arbitrary-adt ==0.3.1.0,
|
|
||||||
any.quickcheck-io ==0.2.0,
|
|
||||||
any.random ==1.2.0,
|
|
||||||
any.recursion-schemes ==5.2.2.1,
|
|
||||||
recursion-schemes +template-haskell,
|
|
||||||
any.regex-base ==0.94.0.1,
|
|
||||||
any.regex-posix ==0.96.0.1,
|
|
||||||
regex-posix -_regex-posix-clib,
|
|
||||||
any.resourcet ==1.2.4.2,
|
|
||||||
any.rts ==1.0.1,
|
|
||||||
any.safe ==0.3.19,
|
|
||||||
any.safe-exceptions ==0.1.7.2,
|
|
||||||
any.scientific ==0.3.7.0,
|
|
||||||
scientific -bytestring-builder -integer-simple,
|
|
||||||
any.semigroupoids ==5.3.5,
|
|
||||||
semigroupoids +comonad +containers +contravariant +distributive +tagged +unordered-containers,
|
|
||||||
any.setenv ==0.1.1.3,
|
|
||||||
any.sop-core ==0.5.0.1,
|
|
||||||
any.split ==0.2.3.4,
|
|
||||||
any.splitmix ==0.1.0.3,
|
|
||||||
splitmix -optimised-mixer,
|
|
||||||
any.stm ==2.5.0.1,
|
|
||||||
any.stm-chans ==3.0.0.4,
|
|
||||||
any.streaming-commons ==0.2.2.1,
|
|
||||||
streaming-commons -use-bytestring-builder,
|
|
||||||
any.strict ==0.4.0.1,
|
|
||||||
strict +assoc,
|
|
||||||
any.strict-base ==0.4.0.0,
|
|
||||||
any.string-interpolate ==0.3.1.1,
|
|
||||||
string-interpolate -bytestring-builder -extended-benchmarks -text-builder,
|
|
||||||
any.syb ==0.7.2.1,
|
|
||||||
any.tagged ==0.8.6.1,
|
|
||||||
tagged +deepseq +transformers,
|
|
||||||
any.tar ==0.6.0.0,
|
|
||||||
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-conversions ==0.3.1,
|
|
||||||
any.text-zipper ==0.11,
|
|
||||||
any.tf-random ==0.5,
|
|
||||||
any.th-abstraction ==0.4.2.0,
|
|
||||||
any.th-compat ==0.1.2,
|
|
||||||
any.th-expand-syns ==0.4.8.0,
|
|
||||||
any.th-lift ==0.8.2,
|
|
||||||
any.th-lift-instances ==0.1.18,
|
|
||||||
any.th-orphans ==0.13.11,
|
|
||||||
any.th-reify-many ==0.1.9,
|
|
||||||
any.these ==1.1.1.1,
|
|
||||||
these +assoc,
|
|
||||||
any.time ==1.9.3,
|
|
||||||
any.time-compat ==1.9.6,
|
|
||||||
time-compat -old-locale,
|
|
||||||
any.transformers ==0.5.6.2,
|
|
||||||
any.transformers-base ==0.4.5.2,
|
|
||||||
transformers-base +orphaninstances,
|
|
||||||
any.transformers-compat ==0.7,
|
|
||||||
transformers-compat -five +five-three -four +generic-deriving +mtl -three -two,
|
|
||||||
any.typed-process ==0.2.6.0,
|
|
||||||
any.unix ==2.7.2.2,
|
|
||||||
any.unix-bytestring ==0.3.7.3,
|
|
||||||
any.unix-compat ==0.5.3,
|
|
||||||
unix-compat -old-time,
|
|
||||||
any.unix-time ==0.4.7,
|
|
||||||
any.unliftio-core ==0.2.0.1,
|
|
||||||
any.unordered-containers ==0.2.14.0,
|
|
||||||
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.0,
|
|
||||||
vector +boundschecks -internalchecks -unsafechecks -wall,
|
|
||||||
any.vector-algorithms ==0.8.0.4,
|
|
||||||
vector-algorithms +bench +boundschecks -internalchecks -llvm +properties -unsafechecks,
|
|
||||||
any.versions ==5.0.0,
|
|
||||||
any.vty ==5.33,
|
|
||||||
any.word-wrap ==0.4.1,
|
|
||||||
any.word8 ==0.1.3,
|
|
||||||
any.xor ==0.0.1.0,
|
|
||||||
any.yaml ==0.11.5.0,
|
|
||||||
yaml +no-examples +no-exe,
|
|
||||||
any.zip ==1.7.1,
|
|
||||||
zip -dev -disable-bzip2 -disable-zstd,
|
|
||||||
any.zlib ==0.6.2.3,
|
|
||||||
zlib -bundled-c-zlib -non-blocking-ffi -pkg-config,
|
|
||||||
any.zlib-bindings ==0.1.1.5,
|
|
||||||
any.zstd ==0.1.2.0,
|
|
||||||
zstd +standalone
|
|
||||||
index-state: hackage.haskell.org 2021-07-27T07:59:57Z
|
|
||||||
29
cabal.ghc8107.project
Normal file
29
cabal.ghc8107.project
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
packages: ./ghcup.cabal
|
||||||
|
|
||||||
|
optional-packages: ./vendored/*/*.cabal
|
||||||
|
|
||||||
|
optimization: 2
|
||||||
|
|
||||||
|
package ghcup
|
||||||
|
flags: +tui
|
||||||
|
|
||||||
|
constraints: http-io-streams -brotli,
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
with-compiler: ghc-8.10.7
|
||||||
246
cabal.ghc8107.project.freeze
Normal file
246
cabal.ghc8107.project.freeze
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
active-repositories: hackage.haskell.org:merge
|
||||||
|
constraints: any.Cabal ==3.6.3.0,
|
||||||
|
Cabal -bundled-binary-generic,
|
||||||
|
any.Cabal-syntax ==3.8.1.0,
|
||||||
|
any.HUnit ==1.6.2.0,
|
||||||
|
any.HsOpenSSL ==0.11.7.4,
|
||||||
|
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.1.1.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.4,
|
||||||
|
ansi-terminal -example +win32-2-13-1,
|
||||||
|
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.2,
|
||||||
|
any.base-compat-batteries ==0.12.2,
|
||||||
|
any.base-orphans ==0.8.7,
|
||||||
|
any.base16-bytestring ==1.0.2.0,
|
||||||
|
any.base64-bytestring ==1.2.1.0,
|
||||||
|
any.bifunctors ==5.5.14,
|
||||||
|
bifunctors +semigroups +tagged,
|
||||||
|
any.bimap ==0.5.0,
|
||||||
|
any.binary ==0.8.8.0,
|
||||||
|
any.binary-instances ==1.0.3,
|
||||||
|
any.binary-orphans ==1.0.3,
|
||||||
|
any.blaze-builder ==0.4.2.2,
|
||||||
|
any.brick ==1.5,
|
||||||
|
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-install-parsers ==0.5,
|
||||||
|
any.cabal-plan ==0.7.2.3,
|
||||||
|
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.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.5.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-array-byte ==0.1.0.1,
|
||||||
|
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.10,
|
||||||
|
any.fusion-plugin-types ==0.1.0,
|
||||||
|
any.generic-arbitrary ==0.2.2,
|
||||||
|
any.generically ==0.1,
|
||||||
|
any.ghc-boot-th ==8.10.7,
|
||||||
|
any.ghc-byteorder ==4.11.0.0.10,
|
||||||
|
any.ghc-prim ==0.6.1,
|
||||||
|
any.happy ==1.20.0,
|
||||||
|
any.hashable ==1.4.2.0,
|
||||||
|
hashable +integer-gmp -random-initial-seed,
|
||||||
|
any.haskell-lexer ==1.1.1,
|
||||||
|
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.10.8,
|
||||||
|
any.hspec-core ==2.10.8,
|
||||||
|
any.hspec-discover ==2.10.8,
|
||||||
|
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.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.2,
|
||||||
|
io-streams +network -nointeractivetests +zlib,
|
||||||
|
any.language-c ==0.9.2,
|
||||||
|
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.4,
|
||||||
|
any.lukko ==0.1.1.3,
|
||||||
|
lukko +ofd-locking,
|
||||||
|
any.lzma-static ==5.2.5.5,
|
||||||
|
any.megaparsec ==9.2.1,
|
||||||
|
megaparsec -dev,
|
||||||
|
any.microlens ==0.4.13.1,
|
||||||
|
any.microlens-mtl ==0.2.0.3,
|
||||||
|
any.microlens-th ==0.4.3.11,
|
||||||
|
any.mtl ==2.2.2,
|
||||||
|
any.network ==3.1.2.7,
|
||||||
|
network -devel,
|
||||||
|
any.network-uri ==2.6.4.2,
|
||||||
|
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.16.1,
|
||||||
|
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.3,
|
||||||
|
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.6,
|
||||||
|
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.5,
|
||||||
|
any.splitmix ==0.1.0.4,
|
||||||
|
splitmix -optimised-mixer,
|
||||||
|
any.stm ==2.5.0.1,
|
||||||
|
any.streamly ==0.8.3,
|
||||||
|
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.tar ==0.5.1.1,
|
||||||
|
tar -old-bytestring -old-time,
|
||||||
|
any.template-haskell ==2.16.0.0,
|
||||||
|
any.temporary ==1.3,
|
||||||
|
any.terminal-progress-bar ==0.4.1,
|
||||||
|
any.terminal-size ==0.3.3,
|
||||||
|
any.terminfo ==0.4.1.4,
|
||||||
|
any.text ==2.0.1,
|
||||||
|
text -developer +simdutf,
|
||||||
|
any.text-binary ==0.2.1.1,
|
||||||
|
any.text-short ==0.1.5,
|
||||||
|
text-short -asserts,
|
||||||
|
any.text-zipper ==0.12,
|
||||||
|
any.tf-random ==0.5,
|
||||||
|
any.th-abstraction ==0.4.5.0,
|
||||||
|
any.th-compat ==0.1.4,
|
||||||
|
any.th-lift ==0.8.2,
|
||||||
|
any.th-lift-instances ==0.1.20,
|
||||||
|
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.2,
|
||||||
|
transformers-compat -five +five-three -four +generic-deriving +mtl -three -two,
|
||||||
|
any.unicode-data ==0.3.1,
|
||||||
|
unicode-data -ucd2haskell,
|
||||||
|
any.unix ==2.7.2.2,
|
||||||
|
any.unix-bytestring ==0.3.7.8,
|
||||||
|
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.vector-binary-instances ==0.2.5.2,
|
||||||
|
any.versions ==5.0.4,
|
||||||
|
any.vty ==5.37,
|
||||||
|
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 2023-01-12T04:22:48Z
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
packages: ./ghcup.cabal
|
|
||||||
|
|
||||||
optional-packages: ./vendored/*/*.cabal
|
|
||||||
|
|
||||||
optimization: 2
|
|
||||||
|
|
||||||
package ghcup
|
|
||||||
tests: True
|
|
||||||
flags: +tui
|
|
||||||
|
|
||||||
source-repository-package
|
|
||||||
type: git
|
|
||||||
location: https://github.com/jtdaugherty/brick.git
|
|
||||||
tag: b3b96cfe66dfd398d338e3feb2b6855e66a35190
|
|
||||||
|
|
||||||
source-repository-package
|
|
||||||
type: git
|
|
||||||
location: https://github.com/Bodigrim/tar
|
|
||||||
tag: ac197ec7ea4838dc2b4e22b9b888b080cedf29cf
|
|
||||||
|
|
||||||
source-repository-package
|
|
||||||
type: git
|
|
||||||
location: https://github.com/bgamari/terminal-size
|
|
||||||
tag: 34ea816bd63f75f800eedac12c6908c6f3736036
|
|
||||||
|
|
||||||
constraints: http-io-streams -brotli
|
|
||||||
|
|
||||||
package libarchive
|
|
||||||
flags: -system-libarchive
|
|
||||||
|
|
||||||
allow-newer: base, ghc-prim, template-haskell, language-c
|
|
||||||
|
|
||||||
with-compiler: ghc-9.0.1
|
|
||||||
@@ -1,264 +0,0 @@
|
|||||||
active-repositories: hackage.haskell.org:merge
|
|
||||||
constraints: any.Cabal ==3.4.0.0,
|
|
||||||
any.HUnit ==1.6.2.0,
|
|
||||||
any.HsOpenSSL ==0.11.7,
|
|
||||||
HsOpenSSL -fast-bignum -homebrew-openssl -macports-openssl -use-pkg-config,
|
|
||||||
any.QuickCheck ==2.14.2,
|
|
||||||
QuickCheck -old-random +templatehaskell,
|
|
||||||
any.StateVar ==1.2.2,
|
|
||||||
any.aeson ==1.5.6.0,
|
|
||||||
aeson -bytestring-builder -cffi -developer -fast,
|
|
||||||
any.aeson-pretty ==0.8.8,
|
|
||||||
aeson-pretty -lib-only,
|
|
||||||
any.alex ==3.2.6,
|
|
||||||
alex +small_base,
|
|
||||||
any.ansi-terminal ==0.11,
|
|
||||||
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.3,
|
|
||||||
async -bench,
|
|
||||||
any.attoparsec ==0.13.2.5,
|
|
||||||
attoparsec -developer,
|
|
||||||
any.auto-update ==0.1.6,
|
|
||||||
any.base ==4.15.0.0,
|
|
||||||
any.base-compat ==0.11.2,
|
|
||||||
any.base-compat-batteries ==0.11.2,
|
|
||||||
any.base-orphans ==0.8.4,
|
|
||||||
any.base16-bytestring ==1.0.1.0,
|
|
||||||
any.base64-bytestring ==1.1.0.0,
|
|
||||||
any.bifunctors ==5.5.11,
|
|
||||||
bifunctors +semigroups +tagged,
|
|
||||||
any.binary ==0.8.8.0,
|
|
||||||
any.bindings-DSL ==1.0.25,
|
|
||||||
any.blaze-builder ==0.4.2.1,
|
|
||||||
any.brick ==0.63,
|
|
||||||
brick -demos,
|
|
||||||
any.bytestring ==0.10.12.1,
|
|
||||||
any.bz2 ==1.0.1.0,
|
|
||||||
bz2 -cross +with-bzlib,
|
|
||||||
any.bzlib-conduit ==0.3.0.2,
|
|
||||||
any.c2hs ==0.28.8,
|
|
||||||
c2hs +base3 -regression,
|
|
||||||
any.call-stack ==0.4.0,
|
|
||||||
any.case-insensitive ==1.2.1.0,
|
|
||||||
any.casing ==0.1.4.1,
|
|
||||||
any.cereal ==0.5.8.1,
|
|
||||||
cereal -bytestring-builder,
|
|
||||||
any.chs-cabal ==0.1.1.0,
|
|
||||||
any.chs-deps ==0.1.0.0,
|
|
||||||
chs-deps -cross,
|
|
||||||
any.clock ==0.8.2,
|
|
||||||
clock -llvm,
|
|
||||||
any.cmdargs ==0.10.21,
|
|
||||||
cmdargs +quotation -testprog,
|
|
||||||
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.concurrent-output ==1.10.12,
|
|
||||||
any.conduit ==1.3.4.1,
|
|
||||||
any.conduit-extra ==1.3.5,
|
|
||||||
any.conduit-zstd ==0.0.2.0,
|
|
||||||
any.config-ini ==0.2.4.0,
|
|
||||||
config-ini -enable-doctests,
|
|
||||||
any.containers ==0.6.4.1,
|
|
||||||
any.contravariant ==1.5.4,
|
|
||||||
contravariant +semigroups +statevar +tagged,
|
|
||||||
any.cpphs ==1.20.9.1,
|
|
||||||
cpphs -old-locale,
|
|
||||||
any.cryptohash-sha1 ==0.11.100.1,
|
|
||||||
any.cryptohash-sha256 ==0.11.102.0,
|
|
||||||
cryptohash-sha256 -exe +use-cbits,
|
|
||||||
any.data-clist ==0.1.2.3,
|
|
||||||
any.data-default-class ==0.1.2.0,
|
|
||||||
any.data-fix ==0.3.1,
|
|
||||||
any.deepseq ==1.4.5.0,
|
|
||||||
any.digest ==0.0.1.3,
|
|
||||||
digest -bytestring-in-base,
|
|
||||||
any.directory ==1.3.6.1,
|
|
||||||
any.disk-free-space ==0.1.0.1,
|
|
||||||
any.distributive ==0.6.2.1,
|
|
||||||
distributive +semigroups +tagged,
|
|
||||||
any.dlist ==1.0,
|
|
||||||
dlist -werror,
|
|
||||||
any.easy-file ==0.2.2,
|
|
||||||
any.errors ==2.3.0,
|
|
||||||
any.exceptions ==0.10.4,
|
|
||||||
any.extra ==1.7.9,
|
|
||||||
any.fast-logger ==3.0.5,
|
|
||||||
any.filepath ==1.4.2.1,
|
|
||||||
any.free ==5.1.7,
|
|
||||||
any.generic-arbitrary ==0.1.0,
|
|
||||||
any.generics-sop ==0.5.1.1,
|
|
||||||
any.ghc-bignum ==1.0,
|
|
||||||
any.ghc-boot-th ==9.0.1,
|
|
||||||
any.ghc-byteorder ==4.11.0.0.10,
|
|
||||||
any.ghc-prim ==0.7.0,
|
|
||||||
any.happy ==1.20.0,
|
|
||||||
any.hashable ==1.3.2.0,
|
|
||||||
hashable +integer-gmp -random-initial-seed,
|
|
||||||
any.haskell-src-exts ==1.23.1,
|
|
||||||
any.haskell-src-meta ==0.8.7,
|
|
||||||
any.haskus-utils-data ==1.4,
|
|
||||||
any.haskus-utils-types ==1.5.1,
|
|
||||||
any.haskus-utils-variant ==3.1,
|
|
||||||
any.hpath-filepath ==0.10.4,
|
|
||||||
any.hpath-posix ==0.13.3,
|
|
||||||
any.hsc2hs ==0.68.7,
|
|
||||||
hsc2hs -in-ghc-tree,
|
|
||||||
any.hspec ==2.7.10,
|
|
||||||
any.hspec-core ==2.7.10,
|
|
||||||
any.hspec-discover ==2.7.10 || ==2.8.2,
|
|
||||||
any.hspec-expectations ==0.8.2,
|
|
||||||
any.hspec-golden-aeson ==0.9.0.0,
|
|
||||||
any.http-io-streams ==0.1.6.0,
|
|
||||||
http-io-streams -brotli +fast-xor,
|
|
||||||
any.indexed-profunctors ==0.1.1,
|
|
||||||
any.indexed-traversable ==0.1.1,
|
|
||||||
any.indexed-traversable-instances ==0.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.0.1,
|
|
||||||
language-c -allwarnings +iecfpextension +usebytestrings,
|
|
||||||
any.libarchive ==3.0.2.2,
|
|
||||||
libarchive -cross -low-memory -system-libarchive,
|
|
||||||
any.libyaml ==0.1.2,
|
|
||||||
libyaml -no-unicode -system-libyaml,
|
|
||||||
any.lifted-base ==0.2.3.12,
|
|
||||||
any.lzma-static ==5.2.5.4,
|
|
||||||
any.megaparsec ==9.0.1,
|
|
||||||
megaparsec -dev,
|
|
||||||
any.microlens ==0.4.12.0,
|
|
||||||
any.microlens-mtl ==0.2.0.1,
|
|
||||||
any.microlens-th ==0.4.3.10,
|
|
||||||
any.monad-control ==1.0.3,
|
|
||||||
any.monad-logger ==0.3.36,
|
|
||||||
monad-logger +template_haskell,
|
|
||||||
any.monad-loops ==0.4.3,
|
|
||||||
monad-loops +base4,
|
|
||||||
any.mono-traversable ==1.0.15.1,
|
|
||||||
any.mtl ==2.2.2,
|
|
||||||
any.network ==3.1.2.2,
|
|
||||||
network -devel,
|
|
||||||
any.network-uri ==2.6.4.1,
|
|
||||||
any.old-locale ==1.0.0.7,
|
|
||||||
any.old-time ==1.1.0.3,
|
|
||||||
any.openssl-streams ==1.2.3.0,
|
|
||||||
any.optics ==0.4,
|
|
||||||
any.optics-core ==0.4,
|
|
||||||
optics-core -explicit-generic-labels,
|
|
||||||
any.optics-extra ==0.4,
|
|
||||||
any.optics-th ==0.4,
|
|
||||||
any.optics-vl ==0.2.1,
|
|
||||||
any.optparse-applicative ==0.16.1.0,
|
|
||||||
optparse-applicative +process,
|
|
||||||
any.os-release ==1.0.2,
|
|
||||||
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.1.0,
|
|
||||||
any.process ==1.6.11.0,
|
|
||||||
any.profunctors ==5.6.2,
|
|
||||||
any.quickcheck-arbitrary-adt ==0.3.1.0,
|
|
||||||
any.quickcheck-io ==0.2.0,
|
|
||||||
any.random ==1.2.0,
|
|
||||||
any.recursion-schemes ==5.2.2.1,
|
|
||||||
recursion-schemes +template-haskell,
|
|
||||||
any.regex-base ==0.94.0.1,
|
|
||||||
any.regex-posix ==0.96.0.1,
|
|
||||||
regex-posix -_regex-posix-clib,
|
|
||||||
any.resourcet ==1.2.4.2,
|
|
||||||
any.rts ==1.0,
|
|
||||||
any.safe ==0.3.19,
|
|
||||||
any.safe-exceptions ==0.1.7.2,
|
|
||||||
any.scientific ==0.3.7.0,
|
|
||||||
scientific -bytestring-builder -integer-simple,
|
|
||||||
any.semigroupoids ==5.3.5,
|
|
||||||
semigroupoids +comonad +containers +contravariant +distributive +tagged +unordered-containers,
|
|
||||||
any.setenv ==0.1.1.3,
|
|
||||||
any.sop-core ==0.5.0.1,
|
|
||||||
any.split ==0.2.3.4,
|
|
||||||
any.splitmix ==0.1.0.3,
|
|
||||||
splitmix -optimised-mixer,
|
|
||||||
any.stm ==2.5.0.0,
|
|
||||||
any.stm-chans ==3.0.0.4,
|
|
||||||
any.streaming-commons ==0.2.2.1,
|
|
||||||
streaming-commons -use-bytestring-builder,
|
|
||||||
any.strict ==0.4.0.1,
|
|
||||||
strict +assoc,
|
|
||||||
any.strict-base ==0.4.0.0,
|
|
||||||
any.string-interpolate ==0.3.1.1,
|
|
||||||
string-interpolate -bytestring-builder -extended-benchmarks -text-builder,
|
|
||||||
any.syb ==0.7.2.1,
|
|
||||||
any.tagged ==0.8.6.1,
|
|
||||||
tagged +deepseq +transformers,
|
|
||||||
any.tar ==0.6.0.0,
|
|
||||||
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.4,
|
|
||||||
any.text ==1.2.4.1,
|
|
||||||
any.text-conversions ==0.3.1,
|
|
||||||
any.text-zipper ==0.11,
|
|
||||||
any.tf-random ==0.5,
|
|
||||||
any.th-abstraction ==0.4.2.0,
|
|
||||||
any.th-compat ==0.1.2,
|
|
||||||
any.th-expand-syns ==0.4.8.0,
|
|
||||||
any.th-lift ==0.8.2,
|
|
||||||
any.th-lift-instances ==0.1.18,
|
|
||||||
any.th-orphans ==0.13.11,
|
|
||||||
any.th-reify-many ==0.1.9,
|
|
||||||
any.these ==1.1.1.1,
|
|
||||||
these +assoc,
|
|
||||||
any.time ==1.9.3,
|
|
||||||
any.time-compat ==1.9.6,
|
|
||||||
time-compat -old-locale,
|
|
||||||
any.transformers ==0.5.6.2,
|
|
||||||
any.transformers-base ==0.4.5.2,
|
|
||||||
transformers-base +orphaninstances,
|
|
||||||
any.transformers-compat ==0.7,
|
|
||||||
transformers-compat -five +five-three -four +generic-deriving +mtl -three -two,
|
|
||||||
any.typed-process ==0.2.6.0,
|
|
||||||
any.unix ==2.7.2.2,
|
|
||||||
any.unix-bytestring ==0.3.7.3,
|
|
||||||
any.unix-compat ==0.5.3,
|
|
||||||
unix-compat -old-time,
|
|
||||||
any.unix-time ==0.4.7,
|
|
||||||
any.unliftio-core ==0.2.0.1,
|
|
||||||
any.unordered-containers ==0.2.14.0,
|
|
||||||
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.0,
|
|
||||||
vector +boundschecks -internalchecks -unsafechecks -wall,
|
|
||||||
any.vector-algorithms ==0.8.0.4,
|
|
||||||
vector-algorithms +bench +boundschecks -internalchecks -llvm +properties -unsafechecks,
|
|
||||||
any.versions ==5.0.0,
|
|
||||||
any.vty ==5.33,
|
|
||||||
any.word-wrap ==0.4.1,
|
|
||||||
any.word8 ==0.1.3,
|
|
||||||
any.xor ==0.0.1.0,
|
|
||||||
any.yaml ==0.11.5.0,
|
|
||||||
yaml +no-examples +no-exe,
|
|
||||||
any.zip ==1.7.1,
|
|
||||||
zip -dev -disable-bzip2 -disable-zstd,
|
|
||||||
any.zlib ==0.6.2.3,
|
|
||||||
zlib -bundled-c-zlib -non-blocking-ffi -pkg-config,
|
|
||||||
any.zlib-bindings ==0.1.1.5,
|
|
||||||
any.zstd ==0.1.2.0,
|
|
||||||
zstd +standalone
|
|
||||||
index-state: hackage.haskell.org 2021-07-27T07:59:57Z
|
|
||||||
@@ -2,30 +2,24 @@ packages: ./ghcup.cabal
|
|||||||
|
|
||||||
optional-packages: ./vendored/*/*.cabal
|
optional-packages: ./vendored/*/*.cabal
|
||||||
|
|
||||||
optimization: 2
|
|
||||||
|
|
||||||
package ghcup
|
package ghcup
|
||||||
tests: True
|
|
||||||
flags: +tui
|
flags: +tui
|
||||||
|
|
||||||
source-repository-package
|
constraints: http-io-streams -brotli,
|
||||||
type: git
|
any.aeson >= 2.0.1.0
|
||||||
location: https://github.com/jtdaugherty/brick.git
|
|
||||||
tag: b3b96cfe66dfd398d338e3feb2b6855e66a35190
|
|
||||||
|
|
||||||
source-repository-package
|
|
||||||
type: git
|
|
||||||
location: https://github.com/Bodigrim/tar
|
|
||||||
tag: ac197ec7ea4838dc2b4e22b9b888b080cedf29cf
|
|
||||||
|
|
||||||
source-repository-package
|
|
||||||
type: git
|
|
||||||
location: https://github.com/bgamari/terminal-size
|
|
||||||
tag: 34ea816bd63f75f800eedac12c6908c6f3736036
|
|
||||||
|
|
||||||
constraints: http-io-streams -brotli
|
|
||||||
|
|
||||||
package libarchive
|
package libarchive
|
||||||
flags: -system-libarchive
|
flags: -system-libarchive
|
||||||
|
|
||||||
allow-newer: base, ghc-prim, template-haskell, language-c
|
package aeson-pretty
|
||||||
|
flags: +lib-only
|
||||||
|
|
||||||
|
package cabal-plan
|
||||||
|
flags: -exe
|
||||||
|
|
||||||
|
package aeson
|
||||||
|
flags: +ordered-keymap
|
||||||
|
|
||||||
|
package streamly
|
||||||
|
flags: +use-unliftio
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
-- windows picks weird version
|
-- windows picks weird version
|
||||||
constraints: any.hsc2hs ==0.68.7
|
constraints: any.hsc2hs ==0.68.8
|
||||||
|
|||||||
50
cabal.project.release
Normal file
50
cabal.project.release
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
packages: ./ghcup.cabal
|
||||||
|
|
||||||
|
optional-packages: ./vendored/*/*.cabal
|
||||||
|
|
||||||
|
optimization: 2
|
||||||
|
|
||||||
|
if os(linux)
|
||||||
|
package ghcup
|
||||||
|
flags: +tui
|
||||||
|
if arch(x86_64) || arch(i386)
|
||||||
|
package *
|
||||||
|
ghc-options: -split-sections -optl-static
|
||||||
|
elif os(darwin)
|
||||||
|
constraints: zlib +bundled-c-zlib,
|
||||||
|
lzma +static
|
||||||
|
package ghcup
|
||||||
|
flags: +tui
|
||||||
|
elif os(mingw32)
|
||||||
|
constraints: zlib +bundled-c-zlib,
|
||||||
|
lzma +static,
|
||||||
|
text -simdutf
|
||||||
|
package ghcup
|
||||||
|
flags: -tui
|
||||||
|
elif os(freebsd)
|
||||||
|
constraints: zlib +bundled-c-zlib,
|
||||||
|
zip +disable-zstd
|
||||||
|
package *
|
||||||
|
ghc-options: -split-sections -pgmc clang++14
|
||||||
|
package ghcup
|
||||||
|
flags: +tui
|
||||||
|
|
||||||
|
constraints: http-io-streams -brotli,
|
||||||
|
any.aeson >= 2.0.1.0,
|
||||||
|
any.hsc2hs ==0.68.8
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
7
cbits/dirutils.c
Normal file
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);
|
||||||
|
}
|
||||||
16
cbits/dirutils.h
Normal file
16
cbits/dirutils.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef POSIXPATHS_CBITS_DIRUTILS_H
|
||||||
|
#define POSIXPATHS_CBITS_DIRUTILS_H
|
||||||
|
|
||||||
|
#include <HsFFI.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
|
||||||
63
config.yaml
63
config.yaml
@@ -1,63 +0,0 @@
|
|||||||
# 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
|
|
||||||
|
|
||||||
# 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'
|
|
||||||
|
|
||||||
# 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
|
|
||||||
# OwnSource: "file:///home/jule/git/ghcup-hs/ghcup-0.0.3.yaml"
|
|
||||||
|
|
||||||
## Example 2: Add custom tarballs to the default downloads, overwriting duplicate versions
|
|
||||||
# AddSource:
|
|
||||||
# Left:
|
|
||||||
# toolRequirements: {} # this is ignored
|
|
||||||
# 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 a custom download file to the default downloads, overwriting duplicate versions
|
|
||||||
# AddSource:
|
|
||||||
# Right: "file:///home/jule/git/ghcup-hs/ghcup-custom.yaml"
|
|
||||||
9
data/build_mk/cross
Normal file
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
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
|
||||||
121
data/config.yaml
Normal file
121
data/config.yaml
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
# When trying to download ghcup metadata, this option decides what to do
|
||||||
|
# when the download fails:
|
||||||
|
# 1. Lax: use existing ~/.ghcup/cache/ghcup-<ver>.yaml as fallback (default)
|
||||||
|
# 2. Strict: fail hard
|
||||||
|
meta-mode: Lax # Strict | Lax
|
||||||
|
|
||||||
|
# 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"
|
||||||
|
|
||||||
|
# This is a way to override platform detection, e.g. when you're running
|
||||||
|
# a Ubuntu derivate based on 18.04, you could do:
|
||||||
|
#
|
||||||
|
# platform-override:
|
||||||
|
# arch: A_64
|
||||||
|
# platform:
|
||||||
|
# contents: Ubuntu
|
||||||
|
# tag: Linux
|
||||||
|
# version: '18.04'
|
||||||
|
platform-override: null
|
||||||
|
|
||||||
|
# Support for mirrors. Currently there are 3 hosts you can mirror:
|
||||||
|
# - github.com (for stack and some older HLS versions)
|
||||||
|
# - raw.githubusercontent.com (for the yaml metadata)
|
||||||
|
# - downloads.haskell.org (for everything else)
|
||||||
|
#
|
||||||
|
# E.g. when we have 'https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-0.0.7.yaml'
|
||||||
|
# and the following mirror config
|
||||||
|
#
|
||||||
|
# "raw.githubusercontent.com":
|
||||||
|
# authority:
|
||||||
|
# host: "mirror.sjtu.edu.cn"
|
||||||
|
# pathPrefix: "ghcup/yaml"
|
||||||
|
#
|
||||||
|
# Then the resulting url will be 'https://mirror.sjtu.edu.cn/ghcup/yaml/haskell/ghcup-metadata/master/ghcup-0.0.7.yaml'
|
||||||
|
mirrors:
|
||||||
|
"github.com":
|
||||||
|
authority:
|
||||||
|
host: "mirror.sjtu.edu.cn"
|
||||||
|
"raw.githubusercontent.com":
|
||||||
|
authority:
|
||||||
|
host: "mirror.sjtu.edu.cn"
|
||||||
|
pathPrefix: "ghcup/yaml"
|
||||||
|
"downloads.haskell.org":
|
||||||
|
authority:
|
||||||
|
host: "mirror.sjtu.edu.cn"
|
||||||
|
|
||||||
1
data/metadata
Submodule
1
data/metadata
Submodule
Submodule data/metadata added at c88802ea8c
71
docker/alpine32/Dockerfile
Normal file
71
docker/alpine32/Dockerfile
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
FROM --platform=linux/i386 i386/alpine:3.12
|
||||||
|
|
||||||
|
ENV LANG C.UTF-8
|
||||||
|
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
curl \
|
||||||
|
gcc \
|
||||||
|
g++ \
|
||||||
|
binutils \
|
||||||
|
binutils-gold \
|
||||||
|
coreutils \
|
||||||
|
bsd-compat-headers \
|
||||||
|
gmp-dev \
|
||||||
|
ncurses-dev \
|
||||||
|
libffi-dev \
|
||||||
|
make \
|
||||||
|
xz \
|
||||||
|
tar \
|
||||||
|
perl \
|
||||||
|
bash \
|
||||||
|
diffutils \
|
||||||
|
git \
|
||||||
|
gzip \
|
||||||
|
gnupg && \
|
||||||
|
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
|
||||||
|
|
||||||
|
ARG GHCUP_VERSION=0.1.19.4
|
||||||
|
ARG GPG_KEY=7D1E8AFD1D4A16D71FADA2F2CCC85C0E40C06A8C
|
||||||
|
|
||||||
|
# install ghcup
|
||||||
|
RUN gpg --batch --keyserver keys.openpgp.org --recv-keys $GPG_KEY && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/i386-linux-ghcup-$GHCUP_VERSION && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/SHA256SUMS && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/SHA256SUMS.sig && \
|
||||||
|
gpg --verify SHA256SUMS.sig SHA256SUMS && \
|
||||||
|
sha256sum -c --ignore-missing SHA256SUMS && \
|
||||||
|
mv i386-linux-ghcup-$GHCUP_VERSION /usr/bin/ghcup && \
|
||||||
|
chmod +x /usr/bin/ghcup && \
|
||||||
|
rm -rf SHA256SUMS SHA256SUMS.sig
|
||||||
|
|
||||||
|
ARG GHC=8.10.7
|
||||||
|
ARG CABAL_INSTALL=3.6.2.0
|
||||||
|
ARG STACK=2.9.1
|
||||||
|
|
||||||
|
ENV GHCUP_CURL_OPTS="--silent"
|
||||||
|
ENV NO_COLOR=1
|
||||||
|
|
||||||
|
# install haskell toolchain
|
||||||
|
RUN ghcup config set gpg-setting GPGStrict && \
|
||||||
|
ghcup --verbose install ghc --isolate=/usr --force ${GHC} && \
|
||||||
|
ghcup --verbose install cabal --isolate=/usr/bin --force ${CABAL_INSTALL} && \
|
||||||
|
find "/usr/lib/ghc-${GHC}/" \( -name "*_p.a" -o -name "*.p_hi" \) -type f -delete && \
|
||||||
|
rm -r "/usr/share/doc/ghc-${GHC}" && \
|
||||||
|
rm -rf /tmp/ghcup* && \
|
||||||
|
ghcup gc -p -s -c -t
|
||||||
|
|
||||||
|
ENV PATH /root/.cabal/bin:/root/.ghcup:/root/.local/bin:$PATH
|
||||||
|
|
||||||
72
docker/alpine64/Dockerfile
Normal file
72
docker/alpine64/Dockerfile
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
FROM alpine:3.12
|
||||||
|
|
||||||
|
ENV LANG C.UTF-8
|
||||||
|
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
curl \
|
||||||
|
gcc \
|
||||||
|
g++ \
|
||||||
|
binutils \
|
||||||
|
binutils-gold \
|
||||||
|
coreutils \
|
||||||
|
bsd-compat-headers \
|
||||||
|
gmp-dev \
|
||||||
|
ncurses-dev \
|
||||||
|
libffi-dev \
|
||||||
|
make \
|
||||||
|
xz \
|
||||||
|
tar \
|
||||||
|
perl \
|
||||||
|
bash \
|
||||||
|
diffutils \
|
||||||
|
git \
|
||||||
|
gzip \
|
||||||
|
gnupg && \
|
||||||
|
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
|
||||||
|
|
||||||
|
ARG GHCUP_VERSION=0.1.19.4
|
||||||
|
ARG GPG_KEY=7D1E8AFD1D4A16D71FADA2F2CCC85C0E40C06A8C
|
||||||
|
|
||||||
|
|
||||||
|
# install ghcup
|
||||||
|
RUN gpg --batch --keyserver keys.openpgp.org --recv-keys $GPG_KEY && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/x86_64-linux-ghcup-$GHCUP_VERSION && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/SHA256SUMS && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/SHA256SUMS.sig && \
|
||||||
|
gpg --verify SHA256SUMS.sig SHA256SUMS && \
|
||||||
|
sha256sum -c --ignore-missing SHA256SUMS && \
|
||||||
|
mv x86_64-linux-ghcup-$GHCUP_VERSION /usr/bin/ghcup && \
|
||||||
|
chmod +x /usr/bin/ghcup && \
|
||||||
|
rm -rf SHA256SUMS SHA256SUMS.sig
|
||||||
|
|
||||||
|
ARG GHC=8.10.7
|
||||||
|
ARG CABAL_INSTALL=3.6.2.0
|
||||||
|
ARG STACK=2.9.1
|
||||||
|
|
||||||
|
ENV GHCUP_CURL_OPTS="--silent"
|
||||||
|
ENV NO_COLOR=1
|
||||||
|
|
||||||
|
# install haskell toolchain
|
||||||
|
RUN ghcup config set gpg-setting GPGStrict && \
|
||||||
|
ghcup --verbose install ghc --isolate=/usr --force ${GHC} && \
|
||||||
|
ghcup --verbose install cabal --isolate=/usr/bin --force ${CABAL_INSTALL} && \
|
||||||
|
find "/usr/lib/ghc-${GHC}/" \( -name "*_p.a" -o -name "*.p_hi" \) -type f -delete && \
|
||||||
|
rm -r "/usr/share/doc/ghc-${GHC}" && \
|
||||||
|
rm -rf /tmp/ghcup* && \
|
||||||
|
ghcup gc -p -s -c -t
|
||||||
|
|
||||||
|
ENV PATH /root/.cabal/bin:/root/.ghcup:/root/.local/bin:$PATH
|
||||||
|
|
||||||
61
docker/arm32v7/buster/Dockerfile
Normal file
61
docker/arm32v7/buster/Dockerfile
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
FROM arm32v7/debian:10
|
||||||
|
|
||||||
|
ENV LANG C.UTF-8
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
ENV TZ=Asia/Singapore
|
||||||
|
|
||||||
|
COPY update_opt.sh /usr/bin/update_opt.sh
|
||||||
|
RUN chmod +x /usr/bin/update_opt.sh
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends \
|
||||||
|
ca-certificates \
|
||||||
|
curl \
|
||||||
|
dirmngr \
|
||||||
|
g++ \
|
||||||
|
git \
|
||||||
|
gnupg \
|
||||||
|
libsqlite3-dev \
|
||||||
|
libtinfo-dev \
|
||||||
|
libgmp-dev \
|
||||||
|
make \
|
||||||
|
netbase \
|
||||||
|
openssh-client \
|
||||||
|
xz-utils \
|
||||||
|
zlib1g-dev \
|
||||||
|
libnuma-dev libgmp10 libssl-dev liblzma-dev libbz2-dev wget lsb-release software-properties-common apt-transport-https gcc autoconf automake build-essential gzip patchelf tree \
|
||||||
|
llvm-11 clang-11 && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN update_opt.sh 11 1
|
||||||
|
|
||||||
|
ARG GHCUP_VERSION=0.1.19.4
|
||||||
|
ARG GPG_KEY=7D1E8AFD1D4A16D71FADA2F2CCC85C0E40C06A8C
|
||||||
|
|
||||||
|
# install ghcup
|
||||||
|
RUN gpg --batch --keyserver keys.openpgp.org --recv-keys $GPG_KEY && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/armv7-linux-ghcup-$GHCUP_VERSION && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/SHA256SUMS && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/SHA256SUMS.sig && \
|
||||||
|
gpg --verify SHA256SUMS.sig SHA256SUMS && \
|
||||||
|
sha256sum -c --ignore-missing SHA256SUMS && \
|
||||||
|
mv armv7-linux-ghcup-$GHCUP_VERSION /usr/bin/ghcup && \
|
||||||
|
chmod +x /usr/bin/ghcup && \
|
||||||
|
rm -rf SHA256SUMS SHA256SUMS.sig
|
||||||
|
|
||||||
|
ARG GHC=8.10.7
|
||||||
|
ARG CABAL_INSTALL=3.6.2.0
|
||||||
|
ARG STACK=2.9.1
|
||||||
|
|
||||||
|
ENV GHCUP_CURL_OPTS="--silent"
|
||||||
|
ENV NO_COLOR=1
|
||||||
|
|
||||||
|
# install haskell toolchain
|
||||||
|
RUN ghcup config set gpg-setting GPGStrict && \
|
||||||
|
ghcup --verbose install ghc --isolate=/usr --force ${GHC} && \
|
||||||
|
ghcup --verbose install cabal --isolate=/usr/bin --force ${CABAL_INSTALL} && \
|
||||||
|
ghcup gc -s -c -t
|
||||||
|
|
||||||
|
ENV PATH /root/.cabal/bin:/root/.ghcup/bin:/root/.local/bin:$PATH
|
||||||
|
|
||||||
|
CMD ["ghci"]
|
||||||
36
docker/arm32v7/buster/update_opt.sh
Executable file
36
docker/arm32v7/buster/update_opt.sh
Executable file
@@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# update_alternatives.sh
|
||||||
|
|
||||||
|
update_alternatives() {
|
||||||
|
local version=${1}
|
||||||
|
local priority=${2}
|
||||||
|
local master=${3}
|
||||||
|
local slaves=${4}
|
||||||
|
local path=${5}
|
||||||
|
local cmdln
|
||||||
|
|
||||||
|
cmdln="--verbose --install ${path}${master} ${master} ${path}${master}-${version} ${priority}"
|
||||||
|
for slave in ${slaves}; do
|
||||||
|
cmdln="${cmdln} --slave ${path}${slave} ${slave} ${path}${slave}-${version}"
|
||||||
|
done
|
||||||
|
update-alternatives ${cmdln}
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ ${#} -ne 2 ]]; then
|
||||||
|
echo usage: "${0}" clang_version priority
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
version=${1}
|
||||||
|
priority=${2}
|
||||||
|
path="/usr/bin/"
|
||||||
|
|
||||||
|
master="llvm-config"
|
||||||
|
slaves="llvm-addr2line llvm-ar llvm-as llvm-bcanalyzer llvm-bitcode-strip llvm-cat llvm-cfi-verify llvm-cov llvm-c-test llvm-cvtres llvm-cxxdump llvm-cxxfilt llvm-cxxmap llvm-debuginfod llvm-debuginfod-find llvm-diff llvm-dis llvm-dlltool llvm-dwarfdump llvm-dwarfutil llvm-dwp llvm-exegesis llvm-extract llvm-gsymutil llvm-ifs llvm-install-name-tool llvm-jitlink llvm-jitlink-executor llvm-lib llvm-libtool-darwin llvm-link llvm-lipo llvm-lto llvm-lto2 llvm-mc llvm-mca llvm-ml llvm-modextract llvm-mt llvm-nm llvm-objcopy llvm-objdump llvm-omp-device-info llvm-opt-report llvm-otool llvm-pdbutil llvm-PerfectShuffle llvm-profdata llvm-profgen llvm-ranlib llvm-rc llvm-readelf llvm-readobj llvm-reduce llvm-remark-size-diff llvm-rtdyld llvm-sim llvm-size llvm-split llvm-stress llvm-strings llvm-strip llvm-symbolizer llvm-tapi-diff llvm-tblgen llvm-tli-checker llvm-undname llvm-windres llvm-xray"
|
||||||
|
|
||||||
|
update_alternatives "${version}" "${priority}" "${master}" "${slaves}" "${path}"
|
||||||
|
|
||||||
|
master="clang"
|
||||||
|
slaves="analyze-build asan_symbolize bugpoint c-index-test clang++ clang-apply-replacements clang-change-namespace clang-check clang-cl clang-cpp clangd clang-doc clang-extdef-mapping clang-format clang-format-diff clang-include-fixer clang-linker-wrapper clang-move clang-nvlink-wrapper clang-offload-bundler clang-offload-packager clang-offload-wrapper clang-pseudo clang-query clang-refactor clang-rename clang-reorder-fields clang-repl clang-scan-deps clang-tidy count diagtool dsymutil FileCheck find-all-symbols git-clang-format hmaptool hwasan_symbolize intercept-build ld64.lld ld.lld llc lld lldb lldb-argdumper lldb-instr lldb-server lldb-vscode lld-link lli lli-child-target modularize not obj2yaml opt pp-trace run-clang-tidy sancov sanstats scan-build scan-build-py scan-view split-file UnicodeNameMappingGenerator verify-uselistorder wasm-ld yaml2obj yaml-bench"
|
||||||
|
|
||||||
|
update_alternatives "${version}" "${priority}" "${master}" "${slaves}" "${path}"
|
||||||
61
docker/arm32v7/focal/Dockerfile
Normal file
61
docker/arm32v7/focal/Dockerfile
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
FROM arm32v7/ubuntu:focal
|
||||||
|
|
||||||
|
ENV LANG C.UTF-8
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
ENV TZ=Asia/Singapore
|
||||||
|
|
||||||
|
COPY update_opt.sh /usr/bin/update_opt.sh
|
||||||
|
RUN chmod +x /usr/bin/update_opt.sh
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends \
|
||||||
|
ca-certificates \
|
||||||
|
curl \
|
||||||
|
dirmngr \
|
||||||
|
g++ \
|
||||||
|
git \
|
||||||
|
gnupg \
|
||||||
|
libsqlite3-dev \
|
||||||
|
libtinfo-dev \
|
||||||
|
libgmp-dev \
|
||||||
|
make \
|
||||||
|
netbase \
|
||||||
|
openssh-client \
|
||||||
|
xz-utils \
|
||||||
|
zlib1g-dev \
|
||||||
|
libnuma-dev libgmp10 libssl-dev liblzma-dev libbz2-dev wget lsb-release software-properties-common apt-transport-https gcc autoconf automake build-essential gzip patchelf tree \
|
||||||
|
llvm-9 clang-9 && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN update_opt.sh 9 1
|
||||||
|
|
||||||
|
ARG GHCUP_VERSION=0.1.19.4
|
||||||
|
ARG GPG_KEY=7D1E8AFD1D4A16D71FADA2F2CCC85C0E40C06A8C
|
||||||
|
|
||||||
|
# install ghcup
|
||||||
|
RUN gpg --batch --keyserver keys.openpgp.org --recv-keys $GPG_KEY && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/armv7-linux-ghcup-$GHCUP_VERSION && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/SHA256SUMS && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/SHA256SUMS.sig && \
|
||||||
|
gpg --verify SHA256SUMS.sig SHA256SUMS && \
|
||||||
|
sha256sum -c --ignore-missing SHA256SUMS && \
|
||||||
|
mv armv7-linux-ghcup-$GHCUP_VERSION /usr/bin/ghcup && \
|
||||||
|
chmod +x /usr/bin/ghcup && \
|
||||||
|
rm -rf SHA256SUMS SHA256SUMS.sig
|
||||||
|
|
||||||
|
ARG GHC=8.10.7
|
||||||
|
ARG CABAL_INSTALL=3.6.2.0
|
||||||
|
ARG STACK=2.9.1
|
||||||
|
|
||||||
|
ENV GHCUP_CURL_OPTS="--silent"
|
||||||
|
ENV NO_COLOR=1
|
||||||
|
|
||||||
|
# install haskell toolchain
|
||||||
|
RUN ghcup config set gpg-setting GPGStrict && \
|
||||||
|
ghcup --verbose install ghc --isolate=/usr --force ${GHC} && \
|
||||||
|
ghcup --verbose install cabal --isolate=/usr/bin --force ${CABAL_INSTALL} && \
|
||||||
|
ghcup gc -s -c -t
|
||||||
|
|
||||||
|
ENV PATH /root/.cabal/bin:/root/.ghcup/bin:/root/.local/bin:$PATH
|
||||||
|
|
||||||
|
CMD ["ghci"]
|
||||||
36
docker/arm32v7/focal/update_opt.sh
Executable file
36
docker/arm32v7/focal/update_opt.sh
Executable file
@@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# update_alternatives.sh
|
||||||
|
|
||||||
|
update_alternatives() {
|
||||||
|
local version=${1}
|
||||||
|
local priority=${2}
|
||||||
|
local master=${3}
|
||||||
|
local slaves=${4}
|
||||||
|
local path=${5}
|
||||||
|
local cmdln
|
||||||
|
|
||||||
|
cmdln="--verbose --install ${path}${master} ${master} ${path}${master}-${version} ${priority}"
|
||||||
|
for slave in ${slaves}; do
|
||||||
|
cmdln="${cmdln} --slave ${path}${slave} ${slave} ${path}${slave}-${version}"
|
||||||
|
done
|
||||||
|
update-alternatives ${cmdln}
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ ${#} -ne 2 ]]; then
|
||||||
|
echo usage: "${0}" clang_version priority
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
version=${1}
|
||||||
|
priority=${2}
|
||||||
|
path="/usr/bin/"
|
||||||
|
|
||||||
|
master="llvm-config"
|
||||||
|
slaves="llvm-addr2line llvm-ar llvm-as llvm-bcanalyzer llvm-bitcode-strip llvm-cat llvm-cfi-verify llvm-cov llvm-c-test llvm-cvtres llvm-cxxdump llvm-cxxfilt llvm-cxxmap llvm-debuginfod llvm-debuginfod-find llvm-diff llvm-dis llvm-dlltool llvm-dwarfdump llvm-dwarfutil llvm-dwp llvm-exegesis llvm-extract llvm-gsymutil llvm-ifs llvm-install-name-tool llvm-jitlink llvm-jitlink-executor llvm-lib llvm-libtool-darwin llvm-link llvm-lipo llvm-lto llvm-lto2 llvm-mc llvm-mca llvm-ml llvm-modextract llvm-mt llvm-nm llvm-objcopy llvm-objdump llvm-omp-device-info llvm-opt-report llvm-otool llvm-pdbutil llvm-PerfectShuffle llvm-profdata llvm-profgen llvm-ranlib llvm-rc llvm-readelf llvm-readobj llvm-reduce llvm-remark-size-diff llvm-rtdyld llvm-sim llvm-size llvm-split llvm-stress llvm-strings llvm-strip llvm-symbolizer llvm-tapi-diff llvm-tblgen llvm-tli-checker llvm-undname llvm-windres llvm-xray"
|
||||||
|
|
||||||
|
update_alternatives "${version}" "${priority}" "${master}" "${slaves}" "${path}"
|
||||||
|
|
||||||
|
master="clang"
|
||||||
|
slaves="analyze-build asan_symbolize bugpoint c-index-test clang++ clang-apply-replacements clang-change-namespace clang-check clang-cl clang-cpp clangd clang-doc clang-extdef-mapping clang-format clang-format-diff clang-include-fixer clang-linker-wrapper clang-move clang-nvlink-wrapper clang-offload-bundler clang-offload-packager clang-offload-wrapper clang-pseudo clang-query clang-refactor clang-rename clang-reorder-fields clang-repl clang-scan-deps clang-tidy count diagtool dsymutil FileCheck find-all-symbols git-clang-format hmaptool hwasan_symbolize intercept-build ld64.lld ld.lld llc lld lldb lldb-argdumper lldb-instr lldb-server lldb-vscode lld-link lli lli-child-target modularize not obj2yaml opt pp-trace run-clang-tidy sancov sanstats scan-build scan-build-py scan-view split-file UnicodeNameMappingGenerator verify-uselistorder wasm-ld yaml2obj yaml-bench"
|
||||||
|
|
||||||
|
update_alternatives "${version}" "${priority}" "${master}" "${slaves}" "${path}"
|
||||||
61
docker/arm64v8/buster/Dockerfile
Normal file
61
docker/arm64v8/buster/Dockerfile
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
FROM arm64v8/debian:10
|
||||||
|
|
||||||
|
ENV LANG C.UTF-8
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
ENV TZ=Asia/Singapore
|
||||||
|
|
||||||
|
COPY update_opt.sh /usr/bin/update_opt.sh
|
||||||
|
RUN chmod +x /usr/bin/update_opt.sh
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends \
|
||||||
|
ca-certificates \
|
||||||
|
curl \
|
||||||
|
dirmngr \
|
||||||
|
g++ \
|
||||||
|
git \
|
||||||
|
gnupg \
|
||||||
|
libsqlite3-dev \
|
||||||
|
libtinfo-dev \
|
||||||
|
libgmp-dev \
|
||||||
|
make \
|
||||||
|
netbase \
|
||||||
|
openssh-client \
|
||||||
|
xz-utils \
|
||||||
|
zlib1g-dev \
|
||||||
|
libnuma-dev libgmp10 libssl-dev liblzma-dev libbz2-dev wget lsb-release software-properties-common apt-transport-https gcc autoconf automake build-essential gzip patchelf tree \
|
||||||
|
llvm-11 clang-11 && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN update_opt.sh 11 1
|
||||||
|
|
||||||
|
ARG GHCUP_VERSION=0.1.19.4
|
||||||
|
ARG GPG_KEY=7D1E8AFD1D4A16D71FADA2F2CCC85C0E40C06A8C
|
||||||
|
|
||||||
|
# install ghcup
|
||||||
|
RUN gpg --batch --keyserver keys.openpgp.org --recv-keys $GPG_KEY && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/aarch64-linux-ghcup-$GHCUP_VERSION && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/SHA256SUMS && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/SHA256SUMS.sig && \
|
||||||
|
gpg --verify SHA256SUMS.sig SHA256SUMS && \
|
||||||
|
sha256sum -c --ignore-missing SHA256SUMS && \
|
||||||
|
mv aarch64-linux-ghcup-$GHCUP_VERSION /usr/bin/ghcup && \
|
||||||
|
chmod +x /usr/bin/ghcup && \
|
||||||
|
rm -rf SHA256SUMS SHA256SUMS.sig
|
||||||
|
|
||||||
|
ARG GHC=8.10.7
|
||||||
|
ARG CABAL_INSTALL=3.6.2.0
|
||||||
|
ARG STACK=2.9.1
|
||||||
|
|
||||||
|
ENV GHCUP_CURL_OPTS="--silent"
|
||||||
|
ENV NO_COLOR=1
|
||||||
|
|
||||||
|
# install haskell toolchain
|
||||||
|
RUN ghcup config set gpg-setting GPGStrict && \
|
||||||
|
ghcup --verbose install ghc --isolate=/usr --force ${GHC} && \
|
||||||
|
ghcup --verbose install cabal --isolate=/usr/bin --force ${CABAL_INSTALL} && \
|
||||||
|
ghcup gc -s -c -t
|
||||||
|
|
||||||
|
ENV PATH /root/.cabal/bin:/root/.ghcup/bin:/root/.local/bin:$PATH
|
||||||
|
|
||||||
|
CMD ["ghci"]
|
||||||
36
docker/arm64v8/buster/update_opt.sh
Executable file
36
docker/arm64v8/buster/update_opt.sh
Executable file
@@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# update_alternatives.sh
|
||||||
|
|
||||||
|
update_alternatives() {
|
||||||
|
local version=${1}
|
||||||
|
local priority=${2}
|
||||||
|
local master=${3}
|
||||||
|
local slaves=${4}
|
||||||
|
local path=${5}
|
||||||
|
local cmdln
|
||||||
|
|
||||||
|
cmdln="--verbose --install ${path}${master} ${master} ${path}${master}-${version} ${priority}"
|
||||||
|
for slave in ${slaves}; do
|
||||||
|
cmdln="${cmdln} --slave ${path}${slave} ${slave} ${path}${slave}-${version}"
|
||||||
|
done
|
||||||
|
update-alternatives ${cmdln}
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ ${#} -ne 2 ]]; then
|
||||||
|
echo usage: "${0}" clang_version priority
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
version=${1}
|
||||||
|
priority=${2}
|
||||||
|
path="/usr/bin/"
|
||||||
|
|
||||||
|
master="llvm-config"
|
||||||
|
slaves="llvm-addr2line llvm-ar llvm-as llvm-bcanalyzer llvm-bitcode-strip llvm-cat llvm-cfi-verify llvm-cov llvm-c-test llvm-cvtres llvm-cxxdump llvm-cxxfilt llvm-cxxmap llvm-debuginfod llvm-debuginfod-find llvm-diff llvm-dis llvm-dlltool llvm-dwarfdump llvm-dwarfutil llvm-dwp llvm-exegesis llvm-extract llvm-gsymutil llvm-ifs llvm-install-name-tool llvm-jitlink llvm-jitlink-executor llvm-lib llvm-libtool-darwin llvm-link llvm-lipo llvm-lto llvm-lto2 llvm-mc llvm-mca llvm-ml llvm-modextract llvm-mt llvm-nm llvm-objcopy llvm-objdump llvm-omp-device-info llvm-opt-report llvm-otool llvm-pdbutil llvm-PerfectShuffle llvm-profdata llvm-profgen llvm-ranlib llvm-rc llvm-readelf llvm-readobj llvm-reduce llvm-remark-size-diff llvm-rtdyld llvm-sim llvm-size llvm-split llvm-stress llvm-strings llvm-strip llvm-symbolizer llvm-tapi-diff llvm-tblgen llvm-tli-checker llvm-undname llvm-windres llvm-xray"
|
||||||
|
|
||||||
|
update_alternatives "${version}" "${priority}" "${master}" "${slaves}" "${path}"
|
||||||
|
|
||||||
|
master="clang"
|
||||||
|
slaves="analyze-build asan_symbolize bugpoint c-index-test clang++ clang-apply-replacements clang-change-namespace clang-check clang-cl clang-cpp clangd clang-doc clang-extdef-mapping clang-format clang-format-diff clang-include-fixer clang-linker-wrapper clang-move clang-nvlink-wrapper clang-offload-bundler clang-offload-packager clang-offload-wrapper clang-pseudo clang-query clang-refactor clang-rename clang-reorder-fields clang-repl clang-scan-deps clang-tidy count diagtool dsymutil FileCheck find-all-symbols git-clang-format hmaptool hwasan_symbolize intercept-build ld64.lld ld.lld llc lld lldb lldb-argdumper lldb-instr lldb-server lldb-vscode lld-link lli lli-child-target modularize not obj2yaml opt pp-trace run-clang-tidy sancov sanstats scan-build scan-build-py scan-view split-file UnicodeNameMappingGenerator verify-uselistorder wasm-ld yaml2obj yaml-bench"
|
||||||
|
|
||||||
|
update_alternatives "${version}" "${priority}" "${master}" "${slaves}" "${path}"
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user