-- gitano.actions -- -- Special hook actions -- -- Copyright 2012 Daniel Silverstone local util = require "gitano.util" local log = require "gitano.log" local gall = require "gall" local config = require "gitano.config" local sio = require 'luxio.simple' local supple = require 'gitano.supple' local function update_actions(conf, repo, tags) log.ddebug("Repo", repo.name, "ref", tags["ref"]) if repo.name == "gitano-admin" and tags["ref"] == "refs/heads/master" then -- Update to the master branch of the gitano-admin repo, perform a conf -- check based on the target sha log.chat("Verifying new gitano-admin master") local conf, msg = config.parse(repo.git:get(tags["newsha"])) if not conf then return false, msg end log.chat("Looks okay") end if tags["ref"] == "refs/gitano/admin" then -- Update to the admin branch, see if we can cause the repo to -- parse the new admin branch safely. log.chat("Verifying new admin sha:", tags["newsha"]) local ok, msg = repo:validate_admin_sha(tags["newsha"]) if not ok then return false, msg end log.chat("Looks okay") end -- No reason to reject, so let it through return true end local function http_txn(method, host, path, headers, body) log.ddebug("Attempting to fetch",host,":", path) log.ddebug("Connect...") local port = "http" if host:match(":") then host, port = host:match("^(.-):([^:]+)$") end local sock, err = sio.connect(host, port) if not sock then return "500", err, {}, "" end local req_lines = { method .. " " .. path .. " HTTP/1.0", "Host: " .. host, } for k, v in pairs(headers) do req_lines[#req_lines+1] = ("%s: %s"):format(k,v) end req_lines[#req_lines+1] = "Connection: Close" req_lines[#req_lines+1] = "" req_lines[#req_lines+1] = "" local req = table.concat(req_lines, "\r\n") log.ddebug("Write request") log.ddebug(req) local ok, msg = sock:write(req) if not ok then sock:close() return "500", msg, {}, "" end if body and body ~= "" then log.ddebug("Writing body of request:") log.ddebug(body) ok, msg = sock:write(body) if not ok then sock:close() return "500", msg, {}, "" end end log.ddebug("Read response") ok, msg = sock:read "*a" if not ok then sock:close() return "500", msg, {}, "" end local response = ok 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 http_get(host, path) return http_txn("GET", host, path, {}, "") end local function http_post(host, path, content_type, body) return http_txn("POST", host, path, { ["Content-Type"] = content_type, ["Content-Length"] = tostring(#body), }, body) end local function set_supple_globals(action) local globs = {} local logcopy = {} for _, k in pairs({ "state", "crit", "critical", "err", "error", "warn", "warning", "chat", "info", "debug", "ddebug", "deepdebug" }) do logcopy[k] = log[k] end globs["log"] = logcopy if action == "post-receive" then globs["http_get"] = http_get -- Legacy name for this, use http.get globs["http"] = { get = http_get, post = http_post } end supple.set_globals(globs) end return { update_actions = update_actions, set_supple_globals = set_supple_globals, }