ikiwiki hosting internals/ todo/ git-annex support

It would be great to support git-annex in ikiwiki-hosting. One of the things that would need to change would be the `iki-git-shell` command, which currently doesn't allow `git-annex-shell` to run, which breaks `git-annex`. I tried setting the `annex-shell` variable on the client side to `git annex-shell` to try to workaround the issue, but it still fails with:

    fatal: unrecognized command 'git-annex-shell '/home/w-...''
    ...

The client then sets the `annex-ignore` variable and ignores that remote. And of course we'd also need ikiwiki itself to support git-annex but that's another story - at least allowing uploads would be a nice start.

The workaround, of course, is to set `git-annex-shell` as the command in the `authorized_keys` file instead of `iki-git-shell`... but that doesn't quite work because the remote URLs change completely.

So one solution is to exploit the `git-shell-commands` extension of `git-shell`, which allows running arbitrary commands from `git-shell`. Since `git-annex` starts with `git`, it will clear the `iki-git-shell` checks - but it fails in `git-shell` because it's not a recognized git command. To fix this, we need to add the following script in `$HOME/git-shell-commands/git-annex-shell`:

    #!/usr/bin/python

    import os
    import re
    import shlex
    import sys

    try:
        # original command is like:
        # "git-annex-shell 'configlist' '/'"
        # argv is expected to be:
        # ['git-shell-commands/git-annex-shell', '/home/.../source.git/']
        # the last argument is the sanitized repo path from iki-git-shell
        # so parse the original command string into an array safely
        orig_argv = shlex.split(os.environ['SSH_ORIGINAL_COMMAND'])
        # construct the command with the original command and the safe repo path
        cmd = ['git-annex-shell', '-c', orig_argv[1], sys.argv[1]]
        # if we have more arguments, shove them in (skipping unsafe path)
        cmd += orig_argv[3:]
        # restrict git-shell to known commands
        os.environ['GIT_ANNEX_SHELL_LIMITED'] = 'true'
        # restrict git-annex to the sanitized repository
        os.environ['GIT_ANNEX_SHELL_DIRECTORY'] = sys.argv[1]
        # keep all commands as readonly, disabled
        #os.environ['GIT_ANNEX_SHELL_READONLY'] = 'true'
        # split into that new command
        os.execlp('git-annex-shell', *cmd)
    except Exception as e:
        print "git-annex-shell wrapper improperly called: %s" % e

This will not work out of the box with `iki-git-shell` because the C code garbles the `SSH_ORIG_COMMAND` with `strtok`. The following patch is also necessary to carry the command down below:

    diff --git a/iki-git-shell.c b/iki-git-shell.c
    index 70250ad..37639a2 100644
    --- a/iki-git-shell.c
    +++ b/iki-git-shell.c
    @@ -74,6 +74,10 @@ int main (int argc, char **argv) {
                    fprintf(stderr, "error: SSH_ORIGINAL_COMMAND not set\n");
                    exit(1);
            }
    +       if (asprintf(&command, command) == -1) {
    +               perror("asprintf");
    +               exit(1);
    +       }

            s=strtok(command, " -"); /* handle "git-" and "git " */
            if (! s) {

That way the tokenizer operates on a copy of the string instead of garbling the environment directly.

Now, I know that:

1. this is clunky
2. it's python (heretic! burn! burn!)
3. there's more comments than code (but I took a while to figure that stuff out, so better to share)
4. it doesn't solve git-annex support in ikiwiki (ie. the objects won't get pushed to the source repo)
5. it's 1h30AM on a friday

But:

1. it's a start!
2. it works (ie. it will drop keys, share configs, etc)
3. it should be fairly secure

Your feedback would be greatly appreciated here. At the very least I think the patch on iki-git-shell can't hurt, unless hiding the original git command was deliberate.

Thanks! -- anarcat