76 lines
1.9 KiB
Lua
76 lines
1.9 KiB
Lua
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)
|