remote-testsvn.con commit Create a note for every imported commit containing svn metadata (a9a5561)
   1#include "cache.h"
   2#include "remote.h"
   3#include "strbuf.h"
   4#include "url.h"
   5#include "exec_cmd.h"
   6#include "run-command.h"
   7#include "vcs-svn/svndump.h"
   8#include "notes.h"
   9#include "argv-array.h"
  10
  11static const char *url;
  12static int dump_from_file;
  13static const char *private_ref;
  14static const char *remote_ref = "refs/heads/master";
  15
  16static int cmd_capabilities(const char *line);
  17static int cmd_import(const char *line);
  18static int cmd_list(const char *line);
  19
  20typedef int (*input_command_handler)(const char *);
  21struct input_command_entry {
  22        const char *name;
  23        input_command_handler fn;
  24        unsigned char batchable;        /* whether the command starts or is part of a batch */
  25};
  26
  27static const struct input_command_entry input_command_list[] = {
  28        { "capabilities", cmd_capabilities, 0 },
  29        { "import", cmd_import, 1 },
  30        { "list", cmd_list, 0 },
  31        { NULL, NULL }
  32};
  33
  34static int cmd_capabilities(const char *line)
  35{
  36        printf("import\n");
  37        printf("bidi-import\n");
  38        printf("refspec %s:%s\n\n", remote_ref, private_ref);
  39        fflush(stdout);
  40        return 0;
  41}
  42
  43static void terminate_batch(void)
  44{
  45        /* terminate a current batch's fast-import stream */
  46        printf("done\n");
  47        fflush(stdout);
  48}
  49
  50static int cmd_import(const char *line)
  51{
  52        int code;
  53        int dumpin_fd;
  54        unsigned int startrev = 0;
  55        struct argv_array svndump_argv = ARGV_ARRAY_INIT;
  56        struct child_process svndump_proc;
  57
  58        if (dump_from_file) {
  59                dumpin_fd = open(url, O_RDONLY);
  60                if(dumpin_fd < 0)
  61                        die_errno("Couldn't open svn dump file %s.", url);
  62        } else {
  63                memset(&svndump_proc, 0, sizeof(struct child_process));
  64                svndump_proc.out = -1;
  65                argv_array_push(&svndump_argv, "svnrdump");
  66                argv_array_push(&svndump_argv, "dump");
  67                argv_array_push(&svndump_argv, url);
  68                argv_array_pushf(&svndump_argv, "-r%u:HEAD", startrev);
  69                svndump_proc.argv = svndump_argv.argv;
  70
  71                code = start_command(&svndump_proc);
  72                if (code)
  73                        die("Unable to start %s, code %d", svndump_proc.argv[0], code);
  74                dumpin_fd = svndump_proc.out;
  75        }
  76        svndump_init_fd(dumpin_fd, STDIN_FILENO);
  77        svndump_read(url, private_ref);
  78        svndump_deinit();
  79        svndump_reset();
  80
  81        close(dumpin_fd);
  82        if (!dump_from_file) {
  83                code = finish_command(&svndump_proc);
  84                if (code)
  85                        warning("%s, returned %d", svndump_proc.argv[0], code);
  86                argv_array_clear(&svndump_argv);
  87        }
  88
  89        return 0;
  90}
  91
  92static int cmd_list(const char *line)
  93{
  94        printf("? %s\n\n", remote_ref);
  95        fflush(stdout);
  96        return 0;
  97}
  98
  99static int do_command(struct strbuf *line)
 100{
 101        const struct input_command_entry *p = input_command_list;
 102        static struct string_list batchlines = STRING_LIST_INIT_DUP;
 103        static const struct input_command_entry *batch_cmd;
 104        /*
 105         * commands can be grouped together in a batch.
 106         * Batches are ended by \n. If no batch is active the program ends.
 107         * During a batch all lines are buffered and passed to the handler function
 108         * when the batch is terminated.
 109         */
 110        if (line->len == 0) {
 111                if (batch_cmd) {
 112                        struct string_list_item *item;
 113                        for_each_string_list_item(item, &batchlines)
 114                                batch_cmd->fn(item->string);
 115                        terminate_batch();
 116                        batch_cmd = NULL;
 117                        string_list_clear(&batchlines, 0);
 118                        return 0;       /* end of the batch, continue reading other commands. */
 119                }
 120                return 1;       /* end of command stream, quit */
 121        }
 122        if (batch_cmd) {
 123                if (prefixcmp(batch_cmd->name, line->buf))
 124                        die("Active %s batch interrupted by %s", batch_cmd->name, line->buf);
 125                /* buffer batch lines */
 126                string_list_append(&batchlines, line->buf);
 127                return 0;
 128        }
 129
 130        for (p = input_command_list; p->name; p++) {
 131                if (!prefixcmp(line->buf, p->name) && (strlen(p->name) == line->len ||
 132                                line->buf[strlen(p->name)] == ' ')) {
 133                        if (p->batchable) {
 134                                batch_cmd = p;
 135                                string_list_append(&batchlines, line->buf);
 136                                return 0;
 137                        }
 138                        return p->fn(line->buf);
 139                }
 140        }
 141        die("Unknown command '%s'\n", line->buf);
 142        return 0;
 143}
 144
 145int main(int argc, const char **argv)
 146{
 147        struct strbuf buf = STRBUF_INIT, url_sb = STRBUF_INIT,
 148                        private_ref_sb = STRBUF_INIT;
 149        static struct remote *remote;
 150        const char *url_in;
 151
 152        git_extract_argv0_path(argv[0]);
 153        setup_git_directory();
 154        if (argc < 2 || argc > 3) {
 155                usage("git-remote-svn <remote-name> [<url>]");
 156                return 1;
 157        }
 158
 159        remote = remote_get(argv[1]);
 160        url_in = (argc == 3) ? argv[2] : remote->url[0];
 161
 162        if (!prefixcmp(url_in, "file://")) {
 163                dump_from_file = 1;
 164                url = url_decode(url_in + sizeof("file://")-1);
 165        } else {
 166                dump_from_file = 0;
 167                end_url_with_slash(&url_sb, url_in);
 168                url = url_sb.buf;
 169        }
 170
 171        strbuf_addf(&private_ref_sb, "refs/svn/%s/master", remote->name);
 172        private_ref = private_ref_sb.buf;
 173
 174        while (1) {
 175                if (strbuf_getline(&buf, stdin, '\n') == EOF) {
 176                        if (ferror(stdin))
 177                                die("Error reading command stream");
 178                        else
 179                                die("Unexpected end of command stream");
 180                }
 181                if (do_command(&buf))
 182                        break;
 183                strbuf_reset(&buf);
 184        }
 185
 186        strbuf_release(&buf);
 187        strbuf_release(&url_sb);
 188        strbuf_release(&private_ref_sb);
 189        return 0;
 190}