summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers@digital-scurf.org>2012-08-10 11:01:29 +0100
committerDaniel Silverstone <dsilvers@digital-scurf.org>2012-08-10 11:01:38 +0100
commitd0c22665a7a4ddbe2af447a5daf28d51c734ae6a (patch)
treec20198f58a0cea1a710a5116b06896a3f44af270
parent07cb69c35349fddcc4645754f28adc3218080de0 (diff)
downloadgitano-d0c22665a7a4ddbe2af447a5daf28d51c734ae6a.tar.gz
GITANO: Switch all current hooks (update, post-receive) to use Supple
-rw-r--r--bin/gitano-post-receive-hook16
-rw-r--r--bin/gitano-update-hook15
-rw-r--r--lib/gitano.lua2
-rw-r--r--lib/gitano/actions.lua20
-rw-r--r--lib/gitano/config.lua25
-rw-r--r--lib/gitano/repository.lua37
-rw-r--r--lib/gitano/sandbox.lua1
-rw-r--r--lib/gitano/supple.lua122
8 files changed, 204 insertions, 34 deletions
diff --git a/bin/gitano-post-receive-hook b/bin/gitano-post-receive-hook
index 01d23d6..9ac4df8 100644
--- a/bin/gitano-post-receive-hook
+++ b/bin/gitano-post-receive-hook
@@ -115,18 +115,12 @@ if repo.name == "gitano-admin" and updates[admin_repo.HEAD] then
end
end
-local fn, globs = repo:load_hook("post-receive")
-if not fn then
- gitano.log.crit(globs)
-elseif fn ~= true then
- gitano.log.info("Running project-repository post-receive hook")
-
- globs["_G"] = globs
- gitano.actions.set_hook_globals(config, repo, globs)
-
- local ok, msg = pcall(fn, repo, updates)
+if repo:uses_hook("post-receive") then
+ gitano.log.info("Running repository post-receive hook")
+ gitano.actions.set_supple_globals("post-receive")
+ local ok, msg = gitano.supple.run_hook(repo, "post-receive", updates)
if not ok then
- gitano.log.crit(msg)
+ gitano.log.crit(msg or "No reason given, but errored somehow.")
end
gitano.log.info("Finished")
end
diff --git a/bin/gitano-update-hook b/bin/gitano-update-hook
index 42588c5..12ac4ac 100644
--- a/bin/gitano-update-hook
+++ b/bin/gitano-update-hook
@@ -246,16 +246,11 @@ if not allow then
gitano.log.fatal("Actions denied action. Sorry")
end
-local fn, globs = repo:load_hook("update-hook")
-if not fn then
- gitano.log.crit(globs)
-elseif fn ~= true then
- gitano.log.info("Running project-repository update hook")
-
- globs["_G"] = globs
- gitano.actions.set_hook_globals(config, repo, globs)
-
- local ok, msg = pcall(fn, repo, refname, oldsha, newsha)
+if repo:uses_hook("update") then
+ gitano.log.info("Running repository update hook")
+ gitano.actions.set_supple_globals("update")
+ local ok, msg = gitano.supple.run_hook(repo, "update",
+ refname, oldsha, newsha)
if not ok then
gitano.log.fatal(msg or "No reason given to refuse action.")
end
diff --git a/lib/gitano.lua b/lib/gitano.lua
index aa40dbe..d1a0cca 100644
--- a/lib/gitano.lua
+++ b/lib/gitano.lua
@@ -15,6 +15,7 @@ local command = require 'gitano.command'
local actions = require 'gitano.actions'
local lace = require 'gitano.lace'
local markdown = require 'gitano.markdown'
+local supple = require 'gitano.supple'
return {
util = util,
@@ -27,4 +28,5 @@ return {
actions = actions,
lace = lace,
markdown = markdown,
+ supple = supple,
}
diff --git a/lib/gitano/actions.lua b/lib/gitano/actions.lua
index 3de1001..f565305 100644
--- a/lib/gitano/actions.lua
+++ b/lib/gitano/actions.lua
@@ -10,6 +10,7 @@ local log = require "gitano.log"
local git = require "gitano.git"
local config = require "gitano.config"
local sio = require 'luxio.simple'
+local supple = require 'gitano.supple'
local function update_actions(conf, repo, tags)
@@ -226,6 +227,7 @@ local function send_to_cia(msg)
end
local function cia_inform_commits(project, branch, repo, previoustip, newtip)
+ repo = supple.unproxy_repo(repo)
log.ddebug("Attempting CIA report for", branch, "in", project)
log.ddebug("Previous tip was", previoustip, "new tip is", newtip)
log.ddebug("Generating messages...")
@@ -266,7 +268,25 @@ local function set_hook_globals(config, repo, globs)
globs["cia"] = { inform_commits = cia_inform_commits }
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
+ globs["cia"] = { inform_commits = cia_inform_commits }
+ end
+ supple.set_globals(globs)
+end
+
return {
update_actions = update_actions,
set_hook_globals = set_hook_globals,
+ set_supple_globals = set_supple_globals,
}
diff --git a/lib/gitano/config.lua b/lib/gitano/config.lua
index 4ff8868..f49d4cb 100644
--- a/lib/gitano/config.lua
+++ b/lib/gitano/config.lua
@@ -239,6 +239,28 @@ local function parse_admin_config(commit)
return config
end
+local function load_file_content(conf, filename)
+ local entry = conf.content[filename]
+ if not entry then
+ return nil, "Not found: " .. conf.commit.sha .. "::" .. filename
+ end
+ if entry.type ~= "blob" then
+ return nil, conf.commit.sha .. "::" .. filename .. ": Not a blob"
+ end
+ return entry.obj.content, conf.commit.sha .. "::" .. filename
+end
+
+local function has_global_hook(conf, hook)
+ return (conf.content["global-hooks/" .. hook .. ".lua"] ~= nil and
+ conf.content["global-hooks/" .. hook .. ".lua"].type == "blob")
+end
+
+local function get_default_hook_content(conf, filename)
+ return [[
+(function(hookf, ...) return hookf(...) end)(...)
+]], conf.commit.sha .. "::[[" .. filename .. "]]"
+end
+
local function generate_ssh_config(conf)
local ret = {"","### Gitano Keys ###"}
for u, t in pairs(conf.users) do
@@ -417,4 +439,7 @@ return {
parse = parse_admin_config,
populate_context = populate_context,
commit = commit_config_changes,
+ load_file_content = load_file_content,
+ get_default_hook_content = get_default_hook_content,
+ has_global_hook = has_global_hook,
}
diff --git a/lib/gitano/repository.lua b/lib/gitano/repository.lua
index b443763..15136a9 100644
--- a/lib/gitano/repository.lua
+++ b/lib/gitano/repository.lua
@@ -35,24 +35,37 @@ local adminrefname = "refs/gitano/admin"
local repo_method = {}
-function repo_method:load_hook(hookname)
- -- Load the given hook from our admin branch.
- -- If there's no such hook, return true
- -- Otherwise sandbox it and return the function and global table
+function repo_method:load_from_admin_ref(filename)
local admincommit = self.git:get(adminrefname)
local admintree = admincommit.content.tree.content
local flat_tree = git.tree.flatten(admintree)
- local hook = flat_tree["hooks/" .. hookname .. ".lua"]
- if not hook then
+ local entry = flat_tree[filename]
+ if not entry then
+ return nil, "Not found: " .. admincommit.sha .. "::" .. filename
+ end
+ if entry.obj.type ~= "blob" then
+ return nil, admincommit.sha .. "::" .. filename .. ": Not a blob"
+ end
+ return entry.obj.content, admincommit.sha .. "::" .. filename
+end
+
+function repo_method:uses_hook(hookname)
+ -- If the hook is global, then we use it
+ if config.has_global_hook(self.config, hookname) then
return true
end
- if hook.obj.type ~= "blob" then
- return false, "Hook entry is not a blob?!"
+ local admincommit = self.git:get(adminrefname)
+ local admintree = admincommit.content.tree.content
+ local flat_tree = git.tree.flatten(admintree)
+ local entry = flat_tree["hooks/" .. hookname .. ".lua"]
+ if not entry then
+ return false
end
- local hook_src = hook.obj.content
- local hook_name = (self.name .. ":" .. admincommit.sha ..
- ":hooks/" .. hookname .. ".lua")
- return sandbox.wrap(hook_src, hook_name)
+ if entry.type ~= "blob" then
+ return false
+ end
+ -- Got a hook, it's a blob, sounds good
+ return true
end
function repo_method:fs_path()
diff --git a/lib/gitano/sandbox.lua b/lib/gitano/sandbox.lua
index f2c865a..d1ffe21 100644
--- a/lib/gitano/sandbox.lua
+++ b/lib/gitano/sandbox.lua
@@ -74,6 +74,5 @@ local function safe_load(str, name)
end
return {
- wrap = _wrap,
safe_load = safe_load,
}
diff --git a/lib/gitano/supple.lua b/lib/gitano/supple.lua
new file mode 100644
index 0000000..b836f61
--- /dev/null
+++ b/lib/gitano/supple.lua
@@ -0,0 +1,122 @@
+-- gitano.supple
+--
+-- Supple interface code for Gitano
+--
+-- Copyright 2012 Daniel Silverstone <dsilvers@digital-scurf.org>
+--
+--
+
+local supple = require 'supple'
+local log = require 'gitano.log'
+local config = require 'gitano.config'
+
+local repo_proxies = {}
+local proxied_repo = {}
+
+local proxy_repo_methods = {}
+local function proxy_repo_tostring(proxy)
+ return ("<ProxyRepository [%s]>"):format((proxied_repo[proxy] or {}).name or "Unknown")
+end
+
+local proxy_repo_meta = {
+ __index = proxy_repo_methods,
+ __tostring = proxy_repo_tostring,
+}
+
+local function get_repo_proxy(repo)
+ local proxy = repo_proxies[repo]
+ if proxy then
+ return proxy
+ end
+
+ proxy = setmetatable({}, proxy_repo_meta)
+ proxied_repo[proxy] = repo
+ repo_proxies[repo] = proxy
+
+ proxy.name = repo.name
+
+ return proxy
+end
+
+local function unproxy_repo(proxy)
+ return proxied_repo[proxy] or proxy
+end
+
+local repo, loadedhooks
+
+local function load_repo_module(fromrepo, prefix, module)
+ local modfile = prefix .. "/" .. module:gsub("%.", "/") .. ".lua"
+ local content, err
+ if fromrepo then
+ -- Load from the repository's admin reference
+ content, err = repo:load_from_admin_ref(modfile)
+ else
+ -- Load from the config repo
+ content, err = config.load_file_content(repo.config, modfile)
+ if not content then
+ if err:match("^Not found: ") then
+ content, err = config.get_default_hook_content(repo.config,
+ modfile)
+ end
+ end
+ end
+ return content, err
+end
+
+local function load_module_src(modname)
+ local pfx, mod = modname:match("^([^%.]+)%.(.+)$")
+ if not (pfx and mod) then
+ error("Unable to load " .. modname .. " (Not the right name format)")
+ end
+ if pfx == "lib" then
+ return load_repo_module(repo, pfx, mod)
+ elseif pfx == "hooks" and not loadedhooks then
+ return load_repo_module(repo, pfx, mod)
+ elseif pfx == "globalhooks" and not loadedhooks then
+ local mod, err = load_repo_module(nil, "global-hooks", mod)
+ loadedhooks = true
+ return mod, err
+ elseif pfx == "global" then
+ return load_repo_module(nil, "hooklib", mod)
+ end
+ error("Unable to load " .. modname)
+end
+
+local function load_module(modname)
+ local src, name = load_module_src(modname)
+ if not src then
+ error(name)
+ end
+ return supple.host.loadstring(src, "@" .. name)
+end
+
+local function set_globals(globs)
+ globs.load_module = load_module
+ supple.host.set_globals(globs)
+end
+
+local supple_runtime_code = [[
+local loadmodule = load_module
+load_module = nil
+function require(modname)
+ return loadmodule(modname)()
+end
+return (function(hookname, repo, ...)
+ local hookf = loadmodule("hooks." .. hookname)
+ local ghookf = loadmodule("globalhooks." .. hookname)
+ return ghookf(hookf, repo, ...)
+end)(...)
+]]
+
+local function run_hook(_repo, hook, ...)
+ repo = _repo
+ local proxy = get_repo_proxy(_repo)
+ return supple.host.run(supple_runtime_code, "@gitano.supple.runtime",
+ hook, proxy, ...)
+end
+
+return {
+ unproxy_repo = unproxy_repo,
+ set_globals = set_globals,
+ run_hook = run_hook,
+}