login

local git = require "git"
local scan = require "scan"

local lud = require "ludweb"

git.init()

local path = "/tmp/cogit"
local limit = 20
local groups = scan.scanrepos(path)

local function time_fmt(sig)
    local s = os.date("%Y-%m-%d %H:%M:%S", sig.time_)
    local offset = sig.offset
    local sign
    if offset < 0 then
        offset = -offset
        sign = "-"
    else
        sign = "+"
    end
    local hours = math.floor(offset / 60)
    local mins = offset % 60
    s = s .. (" (UTC%s%02d:%02d)"):format(sign, hours, mins)
    return s
end

local function diff_cb(line_type, line)
    line = lud.template.escape(line:sub(1, #line-1))
    if line_type == " " then
        line = ' <span class="diff_ctx">' .. line .. '</span>'
    elseif line_type == "+" then
        line = '+<span class="diff_add">' .. line .. '</span>'
    elseif line_type == "-" then
        line = '-<span class="diff_del">' .. line .. '</span>'
    elseif line_type == "=" then
        line = ' <span class="diff_nonl diff_ctx_nonl">' .. line .. '</span>'
    elseif line_type == ">" then
        line = ' <span class="diff_nonl diff_old_nonl">' .. line .. '</span>'
    elseif line_type == "<" then
        line = ' <span class="diff_nonl diff_new_nonl">' .. line .. '</span>'
    elseif line_type == "F" then
        line = '\n<span class="diff_file_hdr">' .. line .. '</span>'
    elseif line_type == "H" then
        line = '<span class="diff_hunk_hdr">' .. line .. '</span>'
    elseif line_type == "B" then
        line = '<span class="diff_bin">' .. line .. '</span>'
    else
        line = line_type .. line
    end
    return line .. "\n"
end

local routes = {
    {"GET", "/?",
    function (req)
        local gnames = {}
        for gname in pairs(groups) do
            table.insert(gnames, gname)
        end
        return lud.template.render_file("view/home.html", {gnames=gnames})
    end},
    {"GET", "/group/([%w_-]+)",
    function (req, gname)
        local rnames = {}
        for rname in pairs(groups[gname]) do
            table.insert(rnames, rname)
        end
        return lud.template.render_file("view/group.html", {gname=gname, rnames=rnames})
    end},
    {"GET", "/group/([%w_-]+)/repo/([%w_-]+)",
    function (req, gname, rname)
        local repo = groups[gname][rname]
        local bnames = repo:branches()
        local tnames = repo:tags()
        local env = {repo=repo, gname=gname, rname=rname, bnames=bnames, tnames=tnames}
        return lud.template.render_file("view/repo.html", env)
    end},
    {"GET", "/group/([%w_-]+)/repo/([%w_-]+)/history/([%w_-]+)",
    function (req, gname, rname, first)
        local repo = groups[gname][rname]
        local commit = repo:commit(first)
        local prev = repo:find_prev(commit:id(), limit)
        local env = {
            gname=gname, rname=rname, bname=bname, commit=commit,
            limit=limit, prev=prev, first=first,
        }
        return lud.template.render_file("view/history.html", env)
    end},
    {"GET", "/group/([%w_-]+)/repo/([%w_-]+)/commit/([%w_-]+)",
    function (req, gname, rname, cid)
        local repo = groups[gname][rname]
        local commit = repo:commit(cid)
        local prev = repo:find_prev(commit:id(), 1)
        local sig = commit:signature()
        local time_str = time_fmt(sig)
        local diff = repo:diff(commit, diff_cb)
        local env = {
            gname=gname, rname=rname, bname=bname, commit=commit,
            time_str=time_str, sig=sig, cid=cid, prev=prev, diff=diff,
        }
        return lud.template.render_file("view/commit.html", env)
    end},
    {"GET", "/group/([%w_-]+)/repo/([%w_-]+)/commit/([%w_-]+)/tree/(.*)",
    function (req, gname, rname, cid, path)
        local repo = groups[gname][rname]
        local commit = repo:commit(cid)
        local node = commit:tree_entry(path)
        if node == nil then
            return "File not found", 404, "Not found"
        end
        local parts = {}
        for part in path:gmatch("[^/]+") do
            table.insert(parts, part)
        end
        local env = {
            gname=gname, rname=rname, cid=cid, path=path,
            base=req.path, parts=parts, node=node,
        }
        if node.type_ == "dir" then
            return lud.template.render_file("view/dir.html", env)
        elseif node.type_ == "file" then
            return lud.template.render_file("view/file.html", env)
        end
    end},
}

local app = lud.app.new_app(routes)
app:run(8080)

git.shutdown()