Skip to content

Commit

Permalink
eric-wieser#26: Fetch tree and blob contents lazily.
Browse files Browse the repository at this point in the history
  • Loading branch information
danports committed Apr 13, 2020
1 parent 081b4d2 commit a122966
Showing 1 changed file with 53 additions and 27 deletions.
80 changes: 53 additions & 27 deletions apis/github
Original file line number Diff line number Diff line change
Expand Up @@ -76,51 +76,84 @@ Blob.fullPath = function(self)
return self.path
end
end
Blob.getContents = function(self)
local data = http.get(
('https://raw.github.com/%s/%s/%s/%s'):format(
self.repo.user, self.repo.name, self.sha,
encodeURI(self:fullPath())
)
)
return data.readAll()
end

-- A class for a tree (aka a folder)
local Tree = {}
Tree.__index = Tree
Tree.new = function(repo, sha, path)
local url = ('repos/%s/%s/git/trees/%s'):format(repo.user, repo.name, sha)
local status, data = getAPI(url, repo.auth)
return setmetatable({
repo = repo,
sha = sha,
path = path or ''
}, Tree)
end
Tree.getContents = function(self)
if self.contents then
return self.contents
end

local url = ('repos/%s/%s/git/trees/%s'):format(self.repo.user, self.repo.name, self.sha)
local status, data = getAPI(url, self.repo.auth)
if not status then
error('Could not get github API from ' ..url)
end
if data.tree then
local tree = setmetatable({
repo=repo, sha=data.sha,
path=path or '', size=0,
contents={}
}, Tree)
self.sha = data.sha
self.size = 0
self.contents = {}
for _, childdata in ipairs(data.tree) do
childdata.fullPath = fs.combine(tree:fullPath(), childdata.path)
childdata.fullPath = fs.combine(self:fullPath(), childdata.path)
local child
if childdata.type == 'blob' then
child = Blob.new(repo, childdata.sha, childdata.path)
child = Blob.new(self.repo, childdata.sha, childdata.path)
child.size = childdata.size
elseif childdata.type == 'tree' then
child = Tree.new(repo, childdata.sha, childdata.path)
child = Tree.new(self.repo, childdata.sha, childdata.path)
else
error("uh oh", JSON.encode(childdata))
child = childdata
error("Unknown tree node type", JSON.encode(childdata))
end
tree.size = tree.size + child.size
child.parent = tree
table.insert(tree.contents, child)
self.size = self.size + (child.size or 0)
child.parent = self
table.insert(self.contents, child)
end
return tree
return self.contents
else
error("uh oh", JSON.encode(data))
error("No tree data returned", JSON.encode(data))
end
end
local function walkTree(t, level)
for _, item in ipairs(t.contents) do
for _, item in ipairs(t:getContents()) do
coroutine.yield(item, level)
if getmetatable(item) == Tree then
walkTree(item, level + 1)
end
end
end
Tree.getFullSize = function(self)
local size = 0
for item in self:iter() do
if getmetatable(item) == Blob then
size = size + item.size
end
end
return size
end
Tree.getChild = function(self, path)
for _, item in ipairs(self:getContents()) do
if item.path == path then
return item
end
end
end
Tree.iter = function(self)
return coroutine.wrap(function()
walkTree(self, 0)
Expand All @@ -134,19 +167,12 @@ Tree.cloneTo = function(self, dest, onProgress)
end

for item in self:iter() do
local gitpath = item:fullPath()
local path = fs.combine(dest, gitpath)
local path = fs.combine(dest, item:fullPath())
if getmetatable(item) == Tree then
fs.makeDir(path)
elseif getmetatable(item) == Blob then
local data = http.get(
('https://raw.github.com/%s/%s/%s/%s'):format(
self.repo.user, self.repo.name, self.sha,
encodeURI(gitpath)
)
)
local text = item:getContents()
local h = fs.open(path, 'w')
local text = data.readAll()
h.write(text)
h.close()
end
Expand Down

0 comments on commit a122966

Please sign in to comment.