commit 0bc0c325643a15cff357132d774e6f3c991d658e Author: eejebring Date: Wed Aug 19 20:13:05 2026 +0200 Add git.lua diff --git a/git.lua b/git.lua new file mode 100644 index 0000000..09faebd --- /dev/null +++ b/git.lua @@ -0,0 +1,107 @@ +-- Save as /home/git.lua +local http = require("http") +local fs = require("fs") +local json = textutils.unserializeJSON + +-- Configuration +local GIT_TOKEN = "" -- Leave empty for public repos, or add "your-token-here" + +-- Parse a Gitea URL like: https://gitea.example.com/owner/repo or /owner/repo/branch/filename +local function parseGiteaURL(url) + local protocol, domain, path = url:match("^(https?://([^/]+))(/[^?]*)") + if not protocol then + protocol, domain, path = "https://gitea.local", "gitea.local", url + end + + -- Remove trailing slashes and clean path + path = path:gsub("/+$", "") + + -- Extract components from path (format: /owner/repo or /owner/repo/branch) + local parts = {} + for segment in path:gmatch("[^/]+") do + if segment ~= "" then table.insert(parts, segment) end + end + + if #parts < 2 then + return nil, "Invalid URL format. Expected: https://domain.com/owner/repo" + end + + local owner = parts[1] + local repo = parts[2] + local branch = parts[3] or "master" + + return { + base = protocol .. "/" .. domain, + owner = owner, + repo = repo, + branch = branch + } +end + +local function downloadFile(base, owner, repo, branch, path, target) + local url = ("%s/api/v1/repos/%s/%s/raw/%s/%s"):format(base, owner, repo, branch, path) + + local req = {url = url} + if GIT_TOKEN ~= "" then + req.headers = {Authorization = "token " .. GIT_TOKEN} + end + + local response = http.get(req) + if not response then error("Failed to download: "..path) end + + local data = response.readAll() + response.close() + + local file = fs.open(target, "w") + file.write(data) + file.close() +end + +local function cloneRepo(url) + local info, err = parseGiteaURL(url) + if not info then error(err) end + + print("Cloning: " .. info.owner .. "/" .. info.repo .. "@" .. info.branch) + + local treeUrl = ("%s/api/v1/repos/%s/%s/git/trees/%s?recursive=1"):format(info.base, info.owner, info.repo, info.branch) + + local req = {url = treeUrl} + if GIT_TOKEN ~= "" then + req.headers = {Authorization = "token " .. GIT_TOKEN} + end + + local resp = http.get(req) + if not resp then error("Cannot access repository. Check URL or token.") end + + local tree = json(resp.readAll()) + resp.close() + + local count = 0 + for _, node in ipairs(tree.tree) do + if node.type == "blob" then + local localPath = ("git/%s/%s/%s"):format(info.owner, info.repo, node.path) + local dir = fs.getDir(localPath) + + if not fs.isDir(dir) then fs.makeDir(dir) end + + downloadFile(info.base, info.owner, info.repo, info.branch, node.path, localPath) + count = count + 1 + end + end + + print(("Cloned %d files to /home/git/%s/%s"):format(count, info.owner, info.repo)) +end + +local args = {...} +if args[1] == "pull" and args[2] then + cloneRepo(args[2]) +else + print("Usage:") + print(" git pull ") + print("") + print("Examples:") + print(' git pull "https://gitea.example.com/user/myrepo"') + print(' git pull "https://gitea.example.com/user/myrepo/tree/main/path/to/file.lua"') + print("") + print("Set GIT_TOKEN variable above for private repos.") +end \ No newline at end of file