APasz

Untitled

Dec 16th, 2025 (edited)
28
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.21 KB | None | 0 0
  1. -- Downloads StargateControl files from GitHub into disk/*.lua (or disk2/..., per file_list)
  2.  
  3. if not http then
  4. error("HTTP API is disabled")
  5. end
  6.  
  7. local BASE_URL = "https://raw.githubusercontent.com/APasz/StargateControl/main/"
  8. local COMMITS_API_URL = "https://api.github.com/repos/APasz/StargateControl/commits/main"
  9. local DEFAULT_TARGET_DIR = "disk"
  10. local FILE_LIST_PATH = "sync/file_list.lua"
  11. local UPDATER_PATH = "sync/updater.lua"
  12.  
  13. local args = { ... }
  14. local self_only = args[1] == "self" or args[1] == "manifest"
  15.  
  16. local function download(url, headers)
  17. local res, err = http.get(url, headers)
  18. if not res then
  19. return nil, err
  20. end
  21.  
  22. local content = res.readAll()
  23. res.close()
  24. return content, nil
  25. end
  26.  
  27. local function fetch_latest_commit_name()
  28. local parse_json = textutils.unserialiseJSON
  29. if not parse_json then
  30. return nil, "JSON parser unavailable"
  31. end
  32.  
  33. local headers = {
  34. ["User-Agent"] = "StargateControlUpdater",
  35. Accept = "application/vnd.github+json",
  36. }
  37.  
  38. local content, err = download(COMMITS_API_URL, headers)
  39. if not content then
  40. return nil, err
  41. end
  42.  
  43. local ok, data = pcall(parse_json, content)
  44. if not ok or type(data) ~= "table" then
  45. return nil, "Unexpected API response"
  46. end
  47.  
  48. local message = data.commit and data.commit.message
  49. if type(message) ~= "string" then
  50. return nil, "Commit message unavailable"
  51. end
  52.  
  53. local subject = message:match("([^\r\n]+)") or message
  54. return subject
  55. end
  56.  
  57. local function load_file_list()
  58. local content, err = download(BASE_URL .. FILE_LIST_PATH)
  59. if not content then
  60. error("Failed to download file list: " .. tostring(err), 0)
  61. end
  62.  
  63. local chunk, load_err = load(content, FILE_LIST_PATH, "t", {})
  64. if not chunk then
  65. error("Unable to parse file list: " .. tostring(load_err), 0)
  66. end
  67.  
  68. local ok, result = pcall(chunk)
  69. if not ok then
  70. error("Failed to load file list: " .. tostring(result), 0)
  71. end
  72.  
  73. if type(result) ~= "table" then
  74. error("Invalid file list contents", 0)
  75. end
  76.  
  77. return result
  78. end
  79.  
  80. local function download_file(path, destination, target_dir)
  81. local url = BASE_URL .. path
  82. local content, err = download(url)
  83. if not content then
  84. print("Failed; " .. path .. ": " .. tostring(err))
  85. return false
  86. end
  87.  
  88. local base_dir = target_dir or DEFAULT_TARGET_DIR
  89. local target_path = destination or fs.combine(base_dir, path)
  90. local dir = fs.getDir(target_path)
  91. if dir and dir ~= "" then
  92. fs.makeDir(dir)
  93. end
  94.  
  95. local f = fs.open(target_path, "w")
  96. if not f then
  97. print("Failed to open " .. target_path .. " for writing.")
  98. return false
  99. end
  100. f.write(content)
  101. f.close()
  102.  
  103. print("Saved: " .. target_path)
  104. return true
  105. end
  106.  
  107. local function collect_files(file_list)
  108. local files = {}
  109. local seen = {}
  110.  
  111. for _, scope_files in pairs(file_list) do
  112. for _, file in ipairs(scope_files) do
  113. local path = file.git
  114. if path ~= FILE_LIST_PATH then
  115. local disk = file.disk
  116. local key = ("%s:%s"):format(disk or "", path)
  117. if not seen[key] then
  118. files[#files + 1] = { path = path, disk = disk }
  119. seen[key] = true
  120. end
  121. end
  122. end
  123. end
  124.  
  125. return files
  126. end
  127.  
  128. local function validate_target_dirs(files)
  129. local missing = {}
  130.  
  131. if not fs.exists(DEFAULT_TARGET_DIR) or not fs.isDir(DEFAULT_TARGET_DIR) then
  132. missing[DEFAULT_TARGET_DIR] = true
  133. end
  134.  
  135. for _, file in ipairs(files) do
  136. local base_dir = file.disk or DEFAULT_TARGET_DIR
  137. if not fs.exists(base_dir) or not fs.isDir(base_dir) then
  138. missing[base_dir] = true
  139. end
  140. end
  141.  
  142. if next(missing) then
  143. local dirs = {}
  144. for dir in pairs(missing) do
  145. dirs[#dirs + 1] = dir
  146. end
  147. error("Missing target disk directories: " .. table.concat(dirs, ", "), 0)
  148. end
  149. end
  150.  
  151. local function resolve_disk_for_file(file)
  152. return file.disk or DEFAULT_TARGET_DIR
  153. end
  154.  
  155. local function download_files(files)
  156. local ok = true
  157. for _, file in ipairs(files) do
  158. local disk = resolve_disk_for_file(file)
  159. ok = download_file(file.path, nil, disk) and ok
  160. end
  161. return ok
  162. end
  163.  
  164. local commit_name, commit_err = fetch_latest_commit_name()
  165.  
  166. local success = true
  167. if self_only then
  168. validate_target_dirs({})
  169. success = download_file(FILE_LIST_PATH, nil, DEFAULT_TARGET_DIR) and success
  170. else
  171. local file_list = load_file_list()
  172. local files = collect_files(file_list)
  173. validate_target_dirs(files)
  174. success = download_file(FILE_LIST_PATH, nil, DEFAULT_TARGET_DIR) and success
  175. success = download_files(files) and success
  176. end
  177.  
  178. success = download_file(UPDATER_PATH, "updater.lua") and success
  179.  
  180. if success then
  181. print("Done!")
  182. else
  183. print("Done (with errors; see above)")
  184. end
  185. if commit_name then
  186. print(commit_name)
  187. elseif commit_err then
  188. print("Latest commit unavailable: " .. tostring(commit_err))
  189. end
Advertisement
Add Comment
Please, Sign In to add comment