diff --git a/gitea-clone.lua b/gitea-clone.lua new file mode 100644 index 0000000..34a0ebb --- /dev/null +++ b/gitea-clone.lua @@ -0,0 +1,70 @@ +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 _, y = term.getCursorPos() + while true do + local chunk = rq.read(1) + 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)) + end + fp:close() + print() +end + + +walkRepository(nil, function(path, file) + downloadFile(file.download_url, repo.."-clone/"..path) +end)