diff options
author | Daniel Silverstone <dsilvers@digital-scurf.org> | 2012-11-10 16:36:08 +0000 |
---|---|---|
committer | Daniel Silverstone <dsilvers@digital-scurf.org> | 2012-11-10 16:36:08 +0000 |
commit | 75ba310751a7f53b1ea3eb979b89f18ec18216d5 (patch) | |
tree | 894ebf2a63d4de1d330a73077b65d9d6058ee3e0 | |
parent | 6ce44b14c739e7da79c8504ae799032e67793d55 (diff) | |
download | gitano-75ba310751a7f53b1ea3eb979b89f18ec18216d5.tar.gz |
ADMINCOMMAND: Add a graveyard command
-rw-r--r-- | lib/gitano/admincommand.lua | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/lib/gitano/admincommand.lua b/lib/gitano/admincommand.lua index 5d67eba..d70f93e 100644 --- a/lib/gitano/admincommand.lua +++ b/lib/gitano/admincommand.lua @@ -9,6 +9,7 @@ local util = require 'gitano.util' local repository = require 'gitano.repository' local config = require 'gitano.config' local clod = require 'clod' +local luxio = require 'luxio' local function cmdmod() return require 'gitano.command' @@ -512,6 +513,166 @@ local function builtin_group_run(conf, _, cmdline, env) return "exit", 0 end +local builtin_graveyard_short = "Manage the graveyard" +local builtin_graveyard_helptext = [[ +usage: graveyard [list] + graveyard restore <entry> <name> + graveyard purge [<entry>] + +With no subcommand, or the subcommand 'list', the graveyard command will list +all the entries in the graveyard. + +With the restore subcommand, a graveyard entry will be restored to the location +provided. The caller will need create permissions in the given location, as +well as the rights to read the graveyard. + +With the purge subcommand, a graveyard entry will be purged entirely. Note +that once a graveyard entry is purged, it cannot be restored except if you have +made an out-of-band backup. +]] + +local function builtin_graveyard_validate(conf, _, cmdline) + if #cmdline == 1 then + cmdline[2] = "list" + end + if cmdline[2] == "list" then + if #cmdline == 2 then + return true + end + log.error("usage: graveyard list") + end + if cmdline[2] == "restore" then + if #cmdline == 4 then + cmdline[3] = cmdline[3]:gsub("/", "") + return true + end + log.error("usage: graveyard restore <entry> <name>") + end + if cmdline[2] == "purge" then + if #cmdline < 4 then + if cmdline[3] then + cmdline[3] = cmdline[3]:gsub("/", "") + end + return true + end + log.error("usage: graveyard purge [<entry>]") + end + log.error("Unable to parse graveyard commandline properly") + return false +end +local function builtin_graveyard_prep(conf, _, cmdline, context) + local context_copy = util.deep_copy(context) + context.operation = "graveyard" .. cmdline[2] + if cmdline[2] == "restore" then + context.target = cmdline[4] + end + if cmdline[2] == "purge" then + context.target = cmdline[3] or "all" + end + local action, reason = conf.repo:run_lace(context) + if action == "allow" and cmdline[2] == "restore" then + context_copy.operation = "createrepo" + local repo = repository.find(conf, cmdline[4]) + return repo:run_lace(context_copy) + end + return action, reason +end + +local function builtin_graveyard_run(conf, _, cmdline, env) + local graveyard_base = config.repo_path() .. "/.graveyard/" + if cmdline[2] == "list" then + -- List the contents of the graveyard. + local dirp, err = luxio.opendir(graveyard_base) + if not dirp then + if err == luxio.ENOTDIR then + log.error("Graveyard is not present, or empty") + return "exit", 1 + end + log.error("Error opening graveyard: " .. luxio.strerror(err)) + return "exit", 1 + end + local e, i + repeat + e, i = luxio.readdir(dirp) + if e == 0 then + if not i.d_name:find("^%.") then + log.state(i.d_name) + end + end + until not e + dirp = nil -- Allow GC of DIR handle + elseif cmdline[2] == "restore" then + -- Restoring a repository needs the prefix dirs to be made + local temp_repo, msg = repository.find(conf, cmdline[4]) + if not temp_repo then + log.error("Unable to proceed: " .. msg) + return "exit", 1 + end + local repo_path = temp_repo:fs_path() + local restore_src = graveyard_base .. cmdline[3] + -- Prepare the path towards the repo... + local ok, msg = util.mkdir_p(util.dirname(repo_path)) + if not ok then + log.error("Unable to proceed: " .. msg) + return "exit", 1 + end + -- Restore the repository + log.info("Trying to restore", cmdline[3], "as", cmdline[4]) + log.ddebug(restore_src, "=>", repo_path) + local e, errno = luxio.rename(restore_src, repo_path) + if e ~= 0 then + log.error("Restore failed. Could not rename: " .. luxio.strerror(errno)) + return "exit", 1 + end + -- Re-find the repository + local repo, msg = repository.find(conf, cmdline[4]) + if not repo then + log.error("Restore failed. Could not find restored repo: " .. msg) + return "exit", 1 + end + elseif cmdline[2] == "purge" then + local match = cmdline[3] + local to_remove = {} + local dirp, err = luxio.opendir(graveyard_base) + if not dirp then + if err == luxio.ENOTDIR then + log.error("Graveyard is not present, or empty") + return "exit", 1 + end + log.error("Error opening graveyard: " .. luxio.strerror(err)) + return "exit", 1 + end + local e, i + repeat + e, i = luxio.readdir(dirp) + if e == 0 then + if not i.d_name:find("^%.") then + if not match or (match == i.d_name) then + to_remove[#to_remove+1] = i.d_name + end + end + end + until not e + dirp = nil -- Allow GC of DIR handle + if #to_remove == 0 then + if match then + log.error("Unable to find", match, "to remove") + else + log.error("Nothing in the graveyard to purge") + end + return "exit", 1 + end + for i = 1, #to_remove do + log.info("Purging", to_remove[i], "from graveyard...") + local ok, msg = util.rm_rf(graveyard_base .. to_remove[i]) + if not ok then + log.error("Unable to remove:", msg) + end + end + end + return "exit", 0 +end + local function register_commands(reg) assert(reg("as", builtin_as_short, builtin_as_helptext, builtin_as_validate, builtin_as_prep, builtin_as_run, @@ -525,6 +686,10 @@ local function register_commands(reg) builtin_group_validate, builtin_group_prep, builtin_group_run, false, false, true)) + assert(reg("graveyard", builtin_graveyard_short, builtin_graveyard_helptext, + builtin_graveyard_validate, builtin_graveyard_prep, + builtin_graveyard_run, false, false, true)) + end return { |