diff options
author | Daniel Silverstone <dsilvers@digital-scurf.org> | 2012-08-10 11:01:29 +0100 |
---|---|---|
committer | Daniel Silverstone <dsilvers@digital-scurf.org> | 2012-08-10 11:01:38 +0100 |
commit | d0c22665a7a4ddbe2af447a5daf28d51c734ae6a (patch) | |
tree | c20198f58a0cea1a710a5116b06896a3f44af270 | |
parent | 07cb69c35349fddcc4645754f28adc3218080de0 (diff) | |
download | gitano-d0c22665a7a4ddbe2af447a5daf28d51c734ae6a.tar.gz |
GITANO: Switch all current hooks (update, post-receive) to use Supple
-rw-r--r-- | bin/gitano-post-receive-hook | 16 | ||||
-rw-r--r-- | bin/gitano-update-hook | 15 | ||||
-rw-r--r-- | lib/gitano.lua | 2 | ||||
-rw-r--r-- | lib/gitano/actions.lua | 20 | ||||
-rw-r--r-- | lib/gitano/config.lua | 25 | ||||
-rw-r--r-- | lib/gitano/repository.lua | 37 | ||||
-rw-r--r-- | lib/gitano/sandbox.lua | 1 | ||||
-rw-r--r-- | lib/gitano/supple.lua | 122 |
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, +} |