-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.lua
More file actions
213 lines (177 loc) · 5.71 KB
/
Copy pathinstall.lua
File metadata and controls
213 lines (177 loc) · 5.71 KB
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
-- Turtle Toolbox command-line installer for a fresh turtle.
-- Usage: wget run <installer-url>
local args = { ... }
local REPOSITORY_URL =
"https://raw.githubusercontent.com/Pyroxenium/turtle-toolbox/refs/heads/main/"
local TOOLBOX_ROOT = "/turtle-toolbox"
local STARTUP_PATH = "/startup.lua"
local TEMPORARY_ROOT = "/.turtle-toolbox-install"
local function printHelp()
print("Turtle Toolbox installer")
print("")
print("Usage:")
print(" installer")
print("")
print("Installs:")
print(" " .. STARTUP_PATH)
print(" " .. TOOLBOX_ROOT .. "/")
end
local function ensureParent(path)
local parent = fs.getDir(path)
if parent ~= "" and not fs.exists(parent) then
fs.makeDir(parent)
end
end
local function removeIfPresent(path)
if fs.exists(path) then
fs.delete(path)
end
end
local function fetch(url)
if not http then
error(
"installer: the HTTP API is disabled. Enable it in the CC:Tweaked configuration.",
0
)
end
local response, requestError = http.get(url)
if not response then
error(
"installer: download failed: " .. url .. " (" .. tostring(requestError) .. ")",
0
)
end
if response.getResponseCode then
local code, message = response.getResponseCode()
if code < 200 or code >= 300 then
response.close()
error(
("installer: HTTP %d %s: %s"):format(
code,
tostring(message or ""),
url
),
0
)
end
end
local content = response.readAll()
response.close()
return content
end
local function writeFile(path, content)
ensureParent(path)
local handle = fs.open(path, "w")
if not handle then
error("installer: cannot write " .. path, 0)
end
handle.write(content)
handle.close()
end
local function validatePath(path)
if path == "" or path:sub(1, 1) == "/" or path:sub(-1) == "/"
or path:find("\\", 1, true) or path:find("//", 1, true) then
return false
end
for part in path:gmatch("[^/]+") do
if part == "." or part == ".." then
return false
end
end
return true
end
local function parseManifest(content)
local files = {}
local seen = {}
for line in (content .. "\n"):gmatch("(.-)\n") do
local path = line:gsub("\r", ""):match("^%s*(.-)%s*$")
if path ~= "" and path:sub(1, 1) ~= "#" then
if not validatePath(path) then
error("installer: invalid manifest path: " .. path, 0)
end
if seen[path] then
error("installer: duplicate manifest path: " .. path, 0)
end
seen[path] = true
files[#files + 1] = path
end
end
if #files == 0 then
error("installer: the manifest is empty", 0)
end
return files
end
local function checkDestination()
if fs.exists(STARTUP_PATH) then
error(
"installer: " .. STARTUP_PATH .. " already exists; refusing to overwrite it.",
0
)
end
if fs.exists(TOOLBOX_ROOT) then
error(
"installer: " .. TOOLBOX_ROOT .. " already exists; refusing to overwrite it.",
0
)
end
end
local function install()
checkDestination()
removeIfPresent(TEMPORARY_ROOT)
fs.makeDir(TEMPORARY_ROOT)
local stagedToolbox = fs.combine(TEMPORARY_ROOT, "turtle-toolbox")
local stagedStartup = fs.combine(TEMPORARY_ROOT, "startup.lua")
local ok, result = pcall(function()
print("Downloading manifest...")
local files = parseManifest(fetch(REPOSITORY_URL .. "manifest.txt"))
local startupFound = false
local runtimeFiles = 0
for index, path in ipairs(files) do
print(("[%d/%d] %s"):format(index, #files, path))
local destination
if path == "startup.lua" then
destination = stagedStartup
startupFound = true
else
destination = fs.combine(stagedToolbox, path)
runtimeFiles = runtimeFiles + 1
end
writeFile(destination, fetch(REPOSITORY_URL .. path))
end
if not startupFound then
error("installer: startup.lua is missing from the manifest", 0)
end
if runtimeFiles == 0 then
error("installer: no toolbox runtime files were found", 0)
end
return { total = #files, runtime = runtimeFiles }
end)
if not ok then
removeIfPresent(TEMPORARY_ROOT)
error(result, 0)
end
local runtimeMoved, runtimeError = pcall(fs.move, stagedToolbox, TOOLBOX_ROOT)
if not runtimeMoved then
removeIfPresent(TEMPORARY_ROOT)
error("installer: unable to install the toolbox: " .. tostring(runtimeError), 0)
end
local startupMoved, startupError = pcall(fs.move, stagedStartup, STARTUP_PATH)
if not startupMoved then
removeIfPresent(TOOLBOX_ROOT)
removeIfPresent(TEMPORARY_ROOT)
error("installer: unable to install startup.lua: " .. tostring(startupError), 0)
end
removeIfPresent(TEMPORARY_ROOT)
print(("Installed %d runtime files to %s/"):format(result.runtime, TOOLBOX_ROOT))
print("Installed startup program to " .. STARTUP_PATH)
print("Turtle setup complete.")
print("Run now with: startup")
print("The toolbox will start automatically after reboot.")
end
if #args > 0 then
if #args == 1 and (args[1] == "-h" or args[1] == "--help") then
return printHelp()
end
error("installer: this installer does not accept a target argument", 0)
end
install()