[PATCH v7 01/16] Implement a remote helper for svn in C

2012-08-28 Thread Florian Achleitner
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

2012-08-28 Thread Junio C Hamano
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