summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers@digital-scurf.org>2012-11-10 16:36:08 +0000
committerDaniel Silverstone <dsilvers@digital-scurf.org>2012-11-10 16:36:08 +0000
commit75ba310751a7f53b1ea3eb979b89f18ec18216d5 (patch)
tree894ebf2a63d4de1d330a73077b65d9d6058ee3e0
parent6ce44b14c739e7da79c8504ae799032e67793d55 (diff)
downloadgitano-75ba310751a7f53b1ea3eb979b89f18ec18216d5.tar.gz
ADMINCOMMAND: Add a graveyard command
-rw-r--r--lib/gitano/admincommand.lua165
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 {