summaryrefslogtreecommitdiff
path: root/lib/gitano/actions.lua
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers@digital-scurf.org>2012-05-07 09:37:18 +0100
committerDaniel Silverstone <dsilvers@digital-scurf.org>2012-05-07 09:37:18 +0100
commit19653ebf8604885e771c88ec95e7e92f6ea976fa (patch)
treecaca1c93fe33b6c784d59d0181325710ecd8890a /lib/gitano/actions.lua
parentdade4fcf8f98ae45301cf51c52e8f189d39b758e (diff)
downloadgitano-19653ebf8604885e771c88ec95e7e92f6ea976fa.tar.gz
ACTIONS: Initial CIA.vc report commit-notifications
Diffstat (limited to 'lib/gitano/actions.lua')
-rw-r--r--lib/gitano/actions.lua152
1 files changed, 152 insertions, 0 deletions
diff --git a/lib/gitano/actions.lua b/lib/gitano/actions.lua
index 8a02373..604b886 100644
--- a/lib/gitano/actions.lua
+++ b/lib/gitano/actions.lua
@@ -70,6 +70,157 @@ local function http_get(host, path)
return code, msg, headers, content
end
+local cia_pattern = [[
+<message>
+ <generator>
+ <name>gitano</name>
+ <version>1</version>
+ <url>http://www.gitano.org.uk/</url>
+ </generator>
+ <source>
+ <project>%s</project>
+ <branch>%s</branch>
+ </source>
+ <body>
+%s
+ </body>
+</message>
+]]
+
+local cia_commit_pattern = [[
+ <commit>
+ <version>%s</version>
+ <files>
+ %s
+ </files>
+ <author>%s</author>
+ <log>%s</log>
+ </commit>]]
+
+local function cia_branch_update_gen(project, branch, repo,
+ previoustip, newtip)
+ local revs = repo.git:rev_list(previoustip, newtip)
+ local commits = {}
+ for i = #revs, 1, -1 do
+ local commit = repo.git:get(revs[i])
+ local author = commit.content.author
+ author = ("%s <%s>"):format(author.realname, author.email)
+ author = util.html_escape(author)
+ local logline = commit.content.message:match("^([^\r\n]+)")
+ logline = util.html_escape(logline)
+ local mytree = commit.content.tree.content
+ local parent = commit.content.parents[1]
+ if parent then
+ parent = parent.content.tree.content
+ else
+ parent = repo.git:get(git.tree.empty_sha).content
+ end
+ local treedelta = parent:diff_to(mytree)
+ local filelist = {}
+ for i, v in ipairs(treedelta) do
+ local fmts = { "UNKNOWN_ACTION", "", util.html_escape(v.filename) }
+ if v.action == "A" then
+ fmts[1] = "add"
+ elseif v.action == "D" then
+ fmts[1] = "remove"
+ elseif v.action == "R" then
+ fmts[1] = "rename"
+ fmts[2] = ([[ to=%q]]):format(fmts[3])
+ fmts[3] = util.html_escape(v.src_name)
+ elseif v.action == "C" then
+ -- for copy we treat the new file as an add
+ fmts[1] = "add"
+ elseif v.action == "M" then
+ fmts[1] = "modify"
+ else
+ log.ddebug("Unknown action", v.action,
+ "in CIA commit formatter, assuming modify")
+ fmts[1] = "modify"
+ end
+ filelist[#filelist+1] =
+ ([[<file action="%s"%s>%s</file>]]):format(unpack(fmts))
+ end
+ filelist = table.concat(filelist, "\n ")
+ local com_msg = cia_commit_pattern:format(commit.sha:sub(1,7),
+ filelist,
+ author,
+ logline)
+ commits[#commits+1] = cia_pattern:format(project, branch,
+ com_msg)
+ end
+ return commits
+end
+
+
+local cia_xmlrpc_pattern = [[
+<?xml version="1.0"?>
+<methodCall>
+ <methodName>hub.deliver</methodName>
+ <params>
+ <value><string>%s</string></value>
+ </params>
+</methodCall>
+]]
+
+local function send_to_cia(msg)
+ if 1 == 0 then
+ print(msg)
+ return "200"
+ end
+ msg = cia_xmlrpc_pattern:format(util.html_escape(msg))
+ log.ddebug("Connect...")
+ sock = assert(sio.connect("cia.vc", "http"))
+
+ local req = table.concat({
+ "POST /RPC2 HTTP/1.0",
+ "Host: cia.vc",
+ "Content-Length: " .. tostring(#msg),
+ "Connection: Close",
+ "", ""
+ }, "\r\n")
+ log.ddebug("Write request")
+ assert(sock:write(req))
+ log.ddebug("Write body")
+ assert(sock:write(msg))
+ log.ddebug("Read response")
+ local response = assert(sock:read "*a")
+
+ assert(sock:close())
+
+ local code, msg, _headers, content = response:match("^HTTP/1.[01] (...) ?([^\r\n]+)\r?\n(.-)\r?\n\r?\n(.*)$")
+ local headers = {}
+ for k, v in _headers:gmatch("([^:\r\n]+): *([^\r\n]+)") do
+ local r = headers[k] or {}
+ r[#r+1] = v
+ headers[k] = r
+ end
+
+ return code, msg, headers, content
+end
+
+local function cia_inform_commits(project, branch, repo, previoustip, newtip)
+ log.ddebug("Attempting CIA report for", branch, "in", project)
+ log.ddebug("Previous tip was", previoustip, "new tip is", newtip)
+ log.ddebug("Generating messages...")
+ local msgs = cia_branch_update_gen(project, branch, repo,
+ previoustip, newtip)
+ log.ddebug("Generated", tostring(#msgs), "messages for CIA")
+ local ok = 0
+ for i = 1, #msgs do
+ local msg = msgs[i]
+ local code, msg, headers, content = send_to_cia(msg)
+ if code == "200" then
+ ok = ok + 1
+ else
+ log.warn("CIA returned", code,
+ "processing message", tostring(i), "of", tostring(#msgs))
+ print(content)
+ break
+ end
+ end
+ return ok == #msgs
+end
+
local function set_hook_globals(config, repo, globs)
for _, k in ipairs({ "table", "string", "pairs", "ipairs", "pcall",
"xpcall", "unpack", "tostring", "tonumber", "math",
@@ -85,6 +236,7 @@ local function set_hook_globals(config, repo, globs)
end
globs["log"] = logcopy
globs["http_get"] = http_get
+ globs["cia"] = { inform_commits = cia_inform_commits }
end
return {