[PATCH v7 01/16] Implement a remote helper for svn in C
Enable basic fetching from subversion repositories. When processing remote URLs starting with testsvn::, git invokes this remote-helper. It starts svnrdump to extract revisions from the subversion repository in the 'dump file format', and converts them to a git-fast-import stream using the functions of vcs-svn/. Imported refs are created in a private namespace at refs/svn/remote-name/master. The revision history is imported linearly (no branch detection) and completely, i.e. from revision 0 to HEAD. The 'bidi-import' capability is used. The remote-helper expects data from fast-import on its stdin. It buffers a batch of 'import' command lines in a string_list before starting to process them. Signed-off-by: Florian Achleitner florian.achleitner.2.6...@gmail.com Signed-off-by: Junio C Hamano gits...@pobox.com --- remote-testsvn.c | 174 ++ 1 file changed, 174 insertions(+) create mode 100644 remote-testsvn.c diff --git a/remote-testsvn.c b/remote-testsvn.c new file mode 100644 index 000..ebe803b --- /dev/null +++ b/remote-testsvn.c @@ -0,0 +1,174 @@ +#include cache.h +#include remote.h +#include strbuf.h +#include url.h +#include exec_cmd.h +#include run-command.h +#include vcs-svn/svndump.h +#include notes.h +#include argv-array.h + +static const char *url; +static const char *private_ref; +static const char *remote_ref = refs/heads/master; + +static int cmd_capabilities(const char *line); +static int cmd_import(const char *line); +static int cmd_list(const char *line); + +typedef int (*input_command_handler)(const char *); +struct input_command_entry { + const char *name; + input_command_handler fn; + unsigned char batchable;/* whether the command starts or is part of a batch */ +}; + +static const struct input_command_entry input_command_list[] = { + { capabilities, cmd_capabilities, 0 }, + { import, cmd_import, 1 }, + { list, cmd_list, 0 }, + { NULL, NULL } +}; + +static int cmd_capabilities(const char *line) { + printf(import\n); + printf(bidi-import\n); + printf(refspec %s:%s\n\n, remote_ref, private_ref); + fflush(stdout); + return 0; +} + +static void terminate_batch(void) +{ + /* terminate a current batch's fast-import stream */ + printf(done\n); + fflush(stdout); +} + +static int cmd_import(const char *line) +{ + int code; + int dumpin_fd; + unsigned int startrev = 0; + struct argv_array svndump_argv = ARGV_ARRAY_INIT; + struct child_process svndump_proc; + + memset(svndump_proc, 0, sizeof(struct child_process)); + svndump_proc.out = -1; + argv_array_push(svndump_argv, svnrdump); + argv_array_push(svndump_argv, dump); + argv_array_push(svndump_argv, url); + argv_array_pushf(svndump_argv, -r%u:HEAD, startrev); + svndump_proc.argv = svndump_argv.argv; + + code = start_command(svndump_proc); + if (code) + die(Unable to start %s, code %d, svndump_proc.argv[0], code); + dumpin_fd = svndump_proc.out; + + svndump_init_fd(dumpin_fd, STDIN_FILENO); + svndump_read(url, private_ref); + svndump_deinit(); + svndump_reset(); + + close(dumpin_fd); + code = finish_command(svndump_proc); + if (code) + warning(%s, returned %d, svndump_proc.argv[0], code); + argv_array_clear(svndump_argv); + + return 0; +} + +static int cmd_list(const char *line) +{ + printf(? %s\n\n, remote_ref); + fflush(stdout); + return 0; +} + +static int do_command(struct strbuf *line) +{ + const struct input_command_entry *p = input_command_list; + static struct string_list batchlines = STRING_LIST_INIT_DUP; + static const struct input_command_entry *batch_cmd; + /* +* commands can be grouped together in a batch. +* Batches are ended by \n. If no batch is active the program ends. +* During a batch all lines are buffered and passed to the handler function +* when the batch is terminated. +*/ + if (line-len == 0) { + if (batch_cmd) { + struct string_list_item *item; + for_each_string_list_item(item, batchlines) + batch_cmd-fn(item-string); + terminate_batch(); + batch_cmd = NULL; + string_list_clear(batchlines, 0); + return 0; /* end of the batch, continue reading other commands. */ + } + return 1; /* end of command stream, quit */ + } + if (batch_cmd) { + if (prefixcmp(batch_cmd-name, line-buf)) + die(Active %s batch interrupted by %s, batch_cmd-name, line-buf); + /* buffer batch lines */ + string_list_append(batchlines, line-buf); +
Re: [PATCH v7 01/16] Implement a remote helper for svn in C
Florian Achleitner florian.achleitner.2.6...@gmail.com writes: Enable basic fetching from subversion repositories. When processing remote URLs starting with testsvn::, git invokes this remote-helper. It starts svnrdump to extract revisions from the subversion repository in the 'dump file format', and converts them to a git-fast-import stream using the functions of vcs-svn/. Imported refs are created in a private namespace at refs/svn/remote-name/master. The revision history is imported linearly (no branch detection) and completely, i.e. from revision 0 to HEAD. The 'bidi-import' capability is used. The remote-helper expects data from fast-import on its stdin. It buffers a batch of 'import' command lines in a string_list before starting to process them. Signed-off-by: Florian Achleitner florian.achleitner.2.6...@gmail.com Signed-off-by: Junio C Hamano gits...@pobox.com --- remote-testsvn.c | 174 ++ 1 file changed, 174 insertions(+) create mode 100644 remote-testsvn.c diff --git a/remote-testsvn.c b/remote-testsvn.c new file mode 100644 index 000..ebe803b --- /dev/null +++ b/remote-testsvn.c @@ -0,0 +1,174 @@ +#include cache.h +#include remote.h +#include strbuf.h +#include url.h +#include exec_cmd.h +#include run-command.h +#include vcs-svn/svndump.h +#include notes.h +#include argv-array.h + +static const char *url; +static const char *private_ref; +static const char *remote_ref = refs/heads/master; + +static int cmd_capabilities(const char *line); +static int cmd_import(const char *line); +static int cmd_list(const char *line); + +typedef int (*input_command_handler)(const char *); +struct input_command_entry { + const char *name; + input_command_handler fn; + unsigned char batchable;/* whether the command starts or is part of a batch */ +}; + +static const struct input_command_entry input_command_list[] = { + { capabilities, cmd_capabilities, 0 }, + { import, cmd_import, 1 }, + { list, cmd_list, 0 }, + { NULL, NULL } +}; + +static int cmd_capabilities(const char *line) { Style: static int cmd_capabilities(const char *line) { + printf(import\n); + printf(bidi-import\n); + printf(refspec %s:%s\n\n, remote_ref, private_ref); + fflush(stdout); + return 0; +} + +static void terminate_batch(void) +{ + /* terminate a current batch's fast-import stream */ + printf(done\n); + fflush(stdout); +} + +static int cmd_import(const char *line) +{ + int code; + int dumpin_fd; + unsigned int startrev = 0; + struct argv_array svndump_argv = ARGV_ARRAY_INIT; + struct child_process svndump_proc; + + memset(svndump_proc, 0, sizeof(struct child_process)); + svndump_proc.out = -1; + argv_array_push(svndump_argv, svnrdump); + argv_array_push(svndump_argv, dump); + argv_array_push(svndump_argv, url); + argv_array_pushf(svndump_argv, -r%u:HEAD, startrev); + svndump_proc.argv = svndump_argv.argv; + + code = start_command(svndump_proc); + if (code) + die(Unable to start %s, code %d, svndump_proc.argv[0], code); + dumpin_fd = svndump_proc.out; + + svndump_init_fd(dumpin_fd, STDIN_FILENO); + svndump_read(url, private_ref); + svndump_deinit(); + svndump_reset(); + + close(dumpin_fd); + code = finish_command(svndump_proc); + if (code) + warning(%s, returned %d, svndump_proc.argv[0], code); + argv_array_clear(svndump_argv); + + return 0; +} + +static int cmd_list(const char *line) +{ + printf(? %s\n\n, remote_ref); + fflush(stdout); + return 0; +} + +static int do_command(struct strbuf *line) +{ + const struct input_command_entry *p = input_command_list; + static struct string_list batchlines = STRING_LIST_INIT_DUP; + static const struct input_command_entry *batch_cmd; + /* + * commands can be grouped together in a batch. + * Batches are ended by \n. If no batch is active the program ends. + * During a batch all lines are buffered and passed to the handler function + * when the batch is terminated. + */ + if (line-len == 0) { + if (batch_cmd) { + struct string_list_item *item; + for_each_string_list_item(item, batchlines) + batch_cmd-fn(item-string); + terminate_batch(); + batch_cmd = NULL; + string_list_clear(batchlines, 0); + return 0; /* end of the batch, continue reading other commands. */ + } + return 1; /* end of command stream, quit */ + } + if (batch_cmd) { + if (prefixcmp(batch_cmd-name, line-buf)) + die(Active %s batch