-
Notifications
You must be signed in to change notification settings - Fork 12
/
configure.sml
163 lines (148 loc) · 5.6 KB
/
configure.sml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
(** Stateful configuration, hopefully with sensible defaults *)
structure Configure =
struct
fun // (dir, file) = OS.Path.joinDirFile { dir = dir, file = file }
infix 5 //
val smackHome = ref "<dummy>"
val smackSources: string list ref = ref []
val platform : string ref = ref ""
val compilers : string list ref = ref []
(** Attempt to ascertain the smackage home directory.
Resolved in this order:
SMACKAGE_HOME environment variable
/usr/local/smackage/
/opt/smackage/
~/.smackage/
*)
fun initSmackHome () =
let
val getEnv = OS.Process.getEnv
fun tryDir (SOME s) = ((OS.FileSys.openDir s; true) handle _ => false)
| tryDir NONE = false
fun useThisDir dir =
if tryDir (SOME dir) then smackHome := dir
else ( print ( "NOTICE: dir `"
^ dir ^ "' doesn't exist, trying to create it.\n")
; OS.FileSys.mkDir dir
handle _ => raise Fail "Couldn't create home directory"
; smackHome := dir)
in
if Option.isSome (getEnv "SMACKAGE_HOME")
then (* $SMACKAGE_HOME is set, definitely go with that. *)
useThisDir (valOf (getEnv "SMACKAGE_HOME"))
else if tryDir (SOME "/usr/local/smackage")
then smackHome := "/usr/local/smackage"
else if tryDir (SOME "/opt/smackage")
then smackHome := "/opt/smackage"
else if Option.isSome (OS.Process.getEnv "HOME")
then (* $HOME set, we're out of other options. Try ~/.smackage *)
useThisDir (valOf (getEnv "HOME") // ".smackage")
else raise Fail "Cannot find smackage home. Try setting SMACKAGE_HOME"
end
fun initFile fileName contents =
let
val filePath =
OS.Path.joinDirFile { dir = !smackHome, file = fileName }
fun create () =
let
val () =
print ("NOTICE: file `" ^ fileName ^ "' doesn't exist,\
\ trying to create it.\n")
val file = TextIO.openOut filePath
in
( TextIO.output (file, contents)
; TextIO.closeOut file)
end
in
if not (OS.FileSys.access (filePath, []))
then create () else
if not (OS.FileSys.access (filePath, [ OS.FileSys.A_READ
, OS.FileSys.A_WRITE ]))
then raise Fail ("Can't read/write to `" ^ fileName
^ "' (run as sudo?)")
else ()
end handle exn =>
( print ("Error with `" ^ fileName ^ "' file.\n")
; raise exn)
fun initDir dirName =
let
val dirPath =
OS.Path.joinDirFile { dir = !smackHome, file = dirName }
fun create () =
let
val () =
print ("NOTICE: dir `" ^ dirName ^ "' doesn't exist,\
\ trying to create it.\n")
in
OS.FileSys.mkDir dirPath
end
in
if not (OS.FileSys.access (dirPath, []))
then create () else
if not (OS.FileSys.isDir dirPath)
then raise Fail ("File `" ^ dirName
^ "' exists and is not a directory")
else ()
end
fun readConfigFile () =
let
val config = OS.Path.joinDirFile { dir = !smackHome, file = "config" }
fun loop file =
case Option.map
(String.tokens Char.isSpace)
(TextIO.inputLine file) of
NONE => TextIO.closeIn file
| SOME [] => loop file
| SOME [ "source", f ] =>
( smackSources := !smackSources @ [ f ] ; loop file)
| SOME [ "platform", p ] =>
( platform := p ; loop file)
| SOME [ "compiler", cmp ] =>
( compilers := !compilers @ [ cmp ] ; loop file)
| SOME s =>
raise Fail ( "Bad configuration line: "
^ String.concatWith " " s )
in
if not (OS.FileSys.access (config, [])) then () else
if not (OS.FileSys.access (config, [ OS.FileSys.A_READ ]))
then raise Fail "Config file exists but can't be read"
else loop (TextIO.openIn config)
end
(** Attempt to guess an appropriate default 'platform' config value.
Based on the output of 'uname -s'. Defaults to 'linux' if we can't
guess, because that's probably safe for most POSIX-compliant systems. *)
fun guessPlatform () =
let
val s = FSUtil.systemCleanLines "uname -s"
in
if null s then "win" else
if String.isPrefix "Darwin" (hd s) then "osx" else
if String.isPrefix "CYGWIN" (hd s) then "win" else "linux"
end
fun init () =
( initSmackHome ()
; initFile "sources.local"
"smackage git git://github.com/standardml/smackage.git\n"
; initFile "config"
("source " ^ ("lib" // "smackage" // "v1" // "sources") ^ "\n\
\compiler mlton\n\
\compiler smlnj\n\
\platform " ^ guessPlatform () ^ "\n")
; initFile "packages.installed" "smackage v1\n"
; initFile "versions.smackspec" "\n"
; initDir "lib"
; initDir "bin"
; readConfigFile ()
; VersionIndex.init (!smackHome))
(*
fun readConfig () =
let
val config =
OS.FileSys.joinDirPath { dir = smackHome, file = "config" }
in
if OS.FileSys.access (config, [ OS.FileSys.A_READ ])
then
else ()
end
*)
end