local pretty = require("cc.pretty") local args = { ... } local instance, user, repo = args[1]:match("https?://([^/]+)/([^/]+)/([^/]+)") local function getContents(path) local url = "https://" .. instance .. "/api/v1/repos/" .. user .. "/" .. repo .. "/contents" .. (path and ("/" .. path) or "") local res, err = http.get(url) if not res then printError(err) return nil, err end return textutils.unserializeJSON(res:readAll()) end local function walkRepository(basedir, callback) local res, err = getContents(basedir) if not res then return nil, err end for _, elem in ipairs(res) do if elem.type == "file" then callback(elem.path, elem) elseif elem.type == "dir" then walkRepository(elem.path, callback) else printError("unknown type: " .. elem.type) end end end local function downloadFile(url, path) local fp, err = io.open(path, "wb") if not fp then return nil, err end local rq rq, err = http.get(url, nil, true) if not rq then return nil, err end local headers = rq.getResponseHeaders() local length = tonumber(headers["Content-Length"]) or 1 local written = 0 local i = 0 local _, y = term.getCursorPos() while true do local chunk = rq.read(100) if not chunk then break end fp:write(chunk) written = written + #chunk term.setCursorPos(1, y) term.clearLine() local w = math.min(25, math.floor(written * 25 / length)) term.write("["..string.rep("=", w)..string.rep(" ", 25-w).."] ") term.write(string.format("%7.3f%% %s", 100 * written / length, path)) i = i + 1 if (i % 20) == 0 then sleep(0.1) end end fp:close() print() end walkRepository(nil, function(path, file) downloadFile(file.download_url, repo.."-clone/"..path) end)