summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Silverstone <daniel.silverstone@codethink.co.uk>2014-03-10 16:35:58 +0000
committerDaniel Silverstone <daniel.silverstone@codethink.co.uk>2014-03-11 14:13:08 +0000
commit115c62b1d3e0b98020ec4493ce1d9de512a4995a (patch)
tree2a378e12c2ce83d03d393cc11734c7c8f3b258b0
parentc101d7d310b908ad88a61efb499b8ee14f94fdb5 (diff)
downloadgitano-115c62b1d3e0b98020ec4493ce1d9de512a4995a.tar.bz2
Support for rsync in Troves
In order to support ingesting of binary artifacts, we are proposing the use of `git-fat` which is a content filter which uses rsync to store the binary artifacts. That requires an access controlled binary artifact repository, so we take advantage of Gitano's ACLs and associate an optional rsync repository with every git repository on the server. By placing it inside the git repository, all of gitano's destroy and graveyard behaviour automatically works with the new rsync content. Signed-off-by: Daniel Silverstone <daniel.silverstone@codethink.co.uk>
-rw-r--r--Makefile3
-rw-r--r--plugins/rsync.lua105
2 files changed, 107 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index 4a94015..cab0162 100644
--- a/Makefile
+++ b/Makefile
@@ -61,7 +61,8 @@ SKEL_FILES := gitano-admin/rules/selfchecks.lace \
MAN1S := gitano-setup.1
-PLUGINS :=
+
+PLUGINS := rsync.lua
MOD_DIRS := gitano
MOD_FILES := $(patsubst %,%.lua,$(subst .,/,$(MODS)))
diff --git a/plugins/rsync.lua b/plugins/rsync.lua
new file mode 100644
index 0000000..4c07233
--- /dev/null
+++ b/plugins/rsync.lua
@@ -0,0 +1,105 @@
+-- rsync Plugin
+--
+-- This plugin is part of Trove. Trove is Codethink's Baserock central server
+-- and uses Gitano as the Git service. This plugin adds support to Trove for
+-- supporting 'rsync' as a command in Gitano. This means that every repository
+-- has an rsync tree attached to it which can be used by remote ends sshing
+-- into the Trove.
+--
+-- Copyright 2014 Daniel Silverstone <daniel.silverstone@codethink.co.uk>
+
+local gitano = require "gitano"
+
+local sp = require "luxio.subprocess"
+
+local rsync_short_help = "An rsync endpoint within Gitano"
+local rsync_helptext = [[
+Users are not expected to use this command directly, but instead to
+instruct their local rsync to use a remote of user@gitanohost:reponame
+when pushing or pulling rsync content.
+]]
+
+local function rsync_detect_repo(config, cmdline)
+ local repo, msg
+ local repopath = cmdline[#cmdline]
+
+ if #cmdline < 4 then
+ -- Validate will fail with a nice error, give up now
+ return nil, cmdline
+ end
+
+ if repopath:match("^/") then
+ repopath = repopath:sub(2)
+ end
+
+ local origpath = repopath
+
+ -- Basically, while there's still something to the repopath
+ -- and we've not yet found a repo, strip an element and try again...
+ while not repo and repopath ~= ""do
+ repo, msg = gitano.repository.find(config, repopath)
+ if not repo then
+ repopath = repopath:match("^(.*)/[^/]*$") or ""
+ end
+ end
+
+ if not repo then
+ gitano.log.error("Unable to find a repository for " .. cmdline[#cmdline])
+ return nil, nil
+ end
+
+ if repo.is_nascent then
+ gitano.log.error("Repository " .. repo.name .. " is nascent")
+ gitano.log.error("Cannot use rsync command with nascent repositories")
+ return nil, nil
+ end
+
+ -- Okay, so repopath represented a repository, let's convert the path
+ -- into something which we can work with...
+ cmdline[#cmdline] = repo:fs_path() .. "/rsync" .. origpath:sub(#repopath+1)
+ if origpath:match("/$") and not (cmdline[#cmdline]):match("/$") then
+ cmdline[#cmdline] = cmdline[#cmdline] .. "/"
+ end
+
+ gitano.util.mkdir_p(repo:fs_path() .. "/rsync")
+
+ -- And give back the repo for ruleset running and the cmdline for the rsync
+
+ gitano.log.error(cmdline[#cmdline])
+
+ return repo, cmdline
+end
+
+local function rsync_validate(config, repo, cmdline)
+ if #cmdline < 4 then
+ gitano.log.error("usage: rsync --server <rsync arguments> . <server-side-path>")
+ return false
+ end
+ if cmdline[2] ~= "--server" then
+ gitano.log.error("Second cmdline element must always be --server")
+ return false
+ end
+ return true
+end
+
+local function rsync_prep(config, repo, cmdline, context)
+ if cmdline[3] == "--sender" then
+ context.operation = "read"
+ else
+ context.operation = "write"
+ end
+ return config.repo:run_lace(context)
+end
+
+local function rsync_run(config, repo, cmdline, env)
+ local cmdcopy = {env=env}
+ for i = 1, #cmdline do cmdcopy[i] = cmdline[i] end
+ local proc = sp.spawn(cmdcopy)
+ return proc:wait()
+end
+
+assert(gitano.command.register("rsync",
+ rsync_short_help, rsync_helptext,
+ rsync_validate, rsync_prep, rsync_run,
+ true, false, false,
+ rsync_detect_repo))