Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d8b615ccb | ||
|
|
712cfab946 |
+13
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"runtime.version": "Lua 5.1",
|
||||||
|
"workspace.library": [
|
||||||
|
"/home/eejebring/code/external/cc-tweaked-documentation"
|
||||||
|
],
|
||||||
|
"diagnostics.globals": [
|
||||||
|
"os", "fs", "computer", "peripheral", "turtle", "term",
|
||||||
|
"redstone", "colors", "colours", "keys", "http", "gps",
|
||||||
|
"disk", "commands", "vector", "paintutils", "parallel",
|
||||||
|
"rs", "settings", "shell", "window", "io", "textutils",
|
||||||
|
"native", "periphemu", "read"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,107 +1,109 @@
|
|||||||
-- Save as /home/git.lua
|
local GIT_TOKEN = "" -- Leave empty for public repos, or add "your-token-here"
|
||||||
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
|
-- Parse a Gitea URL like: https://gitea.example.com/owner/repo or /owner/repo/branch/filename
|
||||||
local function parseGiteaURL(url)
|
local function parseGiteaURL(url)
|
||||||
local protocol, domain, path = url:match("^(https?://([^/]+))(/[^?]*)")
|
local protocol, domain, path = url:match("^(https?://([^/]+))(/[^?]*)")
|
||||||
if not protocol then
|
if not protocol then
|
||||||
protocol, domain, path = "https://gitea.local", "gitea.local", url
|
protocol, domain, path = "https://gitea.local", "gitea.local", url
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Remove trailing slashes and clean path
|
-- Remove trailing slashes and clean path
|
||||||
path = path:gsub("/+$", "")
|
path = path:gsub("/+$", "")
|
||||||
|
|
||||||
-- Extract components from path (format: /owner/repo or /owner/repo/branch)
|
-- Extract components from path (format: /owner/repo or /owner/repo/branch)
|
||||||
local parts = {}
|
local parts = {}
|
||||||
for segment in path:gmatch("[^/]+") do
|
for segment in path:gmatch("[^/]+") do
|
||||||
if segment ~= "" then table.insert(parts, segment) end
|
if segment ~= "" then table.insert(parts, segment) end
|
||||||
end
|
end
|
||||||
|
|
||||||
if #parts < 2 then
|
if #parts < 2 then
|
||||||
return nil, "Invalid URL format. Expected: https://domain.com/owner/repo"
|
return nil, "Invalid URL format. Expected: https://domain.com/owner/repo"
|
||||||
end
|
end
|
||||||
|
|
||||||
local owner = parts[1]
|
local owner = parts[1]
|
||||||
local repo = parts[2]
|
local repo = parts[2]
|
||||||
local branch = parts[3] or "master"
|
local branch = parts[3] or "master"
|
||||||
|
|
||||||
return {
|
return {
|
||||||
base = protocol .. "/" .. domain,
|
base = protocol .. "/" .. domain,
|
||||||
owner = owner,
|
owner = owner,
|
||||||
repo = repo,
|
repo = repo,
|
||||||
branch = branch
|
branch = branch
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
local function downloadFile(base, owner, repo, branch, path, target)
|
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 url = ("%s/api/v1/repos/%s/%s/raw/%s/%s"):format(base, owner, repo, branch, path)
|
||||||
|
|
||||||
local req = {url = url}
|
local req = { url = url }
|
||||||
if GIT_TOKEN ~= "" then
|
if GIT_TOKEN ~= "" then
|
||||||
req.headers = {Authorization = "token " .. GIT_TOKEN}
|
req.headers = { Authorization = "token " .. GIT_TOKEN }
|
||||||
end
|
end
|
||||||
|
|
||||||
local response = http.get(req)
|
local response = http.get(req)
|
||||||
if not response then error("Failed to download: "..path) end
|
if not response then error("Failed to download: " .. path) end
|
||||||
|
|
||||||
local data = response.readAll()
|
local data = response.readAll()
|
||||||
response.close()
|
response.close()
|
||||||
|
|
||||||
local file = fs.open(target, "w")
|
local file, fileError = fs.open(target, "w")
|
||||||
file.write(data)
|
if file then
|
||||||
file.close()
|
file.write(data)
|
||||||
|
file.close()
|
||||||
|
else
|
||||||
|
error("Could not download file '" .. target "' due to: " .. fileError)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function cloneRepo(url)
|
local function cloneRepo(url)
|
||||||
local info, err = parseGiteaURL(url)
|
local info, err = parseGiteaURL(url)
|
||||||
if not info then error(err) end
|
if not info then error(err) end
|
||||||
|
|
||||||
print("Cloning: " .. info.owner .. "/" .. info.repo .. "@" .. info.branch)
|
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 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
|
local req = { url = treeUrl }
|
||||||
req.headers = {Authorization = "token " .. GIT_TOKEN}
|
if GIT_TOKEN ~= "" then
|
||||||
end
|
req.headers = { Authorization = "token " .. GIT_TOKEN }
|
||||||
|
|
||||||
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
|
||||||
end
|
|
||||||
|
local resp = http.get(req)
|
||||||
print(("Cloned %d files to /home/git/%s/%s"):format(count, info.owner, info.repo))
|
if not resp then error("Cannot access repository. Check URL or token.") end
|
||||||
|
local responseJSON = resp.readAll()
|
||||||
|
resp.close()
|
||||||
|
if not responseJSON then error("Response returned empty.") end
|
||||||
|
|
||||||
|
local tree = textutils.unserializeJSON(responseJSON)
|
||||||
|
if not tree then error("Response could not be unserialized") end
|
||||||
|
|
||||||
|
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
|
end
|
||||||
|
|
||||||
local args = {...}
|
local args = { ... }
|
||||||
if args[1] == "pull" and args[2] then
|
if args[1] == "clone" and args[2] then
|
||||||
cloneRepo(args[2])
|
cloneRepo(args[2])
|
||||||
else
|
else
|
||||||
print("Usage:")
|
print("Usage:")
|
||||||
print(" git pull <full-gitea-url>")
|
print(" git pull <full-gitea-url>")
|
||||||
print("")
|
print("")
|
||||||
print("Examples:")
|
print("Examples:")
|
||||||
print(' git pull "https://gitea.example.com/user/myrepo"')
|
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(' git pull "https://gitea.example.com/user/myrepo/tree/main/path/to/file.lua"')
|
||||||
print("")
|
print("")
|
||||||
print("Set GIT_TOKEN variable above for private repos.")
|
print("Set GIT_TOKEN variable above for private repos.")
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user