{"thread":{"id":"23901","subject":"[WIP PATCH] Plug SVN exporter into remote helper","startedAt":"2010-05-25T17:00:17Z","lastAt":"2010-05-25T17:00:18Z","messageCount":2,"participants":["Ramkumar Ramachandra"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"142285","messageId":"1274806818-10904-1-git-send-email-artagnon@gmail.com","threadId":"23901","inReplyTo":null,"subject":"[WIP PATCH] Plug SVN exporter into remote helper","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2010-05-25T17:00:17Z","receivedAt":"2010-05-25T17:00:17Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"Hi,\n\nThis is a work-in-progress based on master, and is not intended for\ninclusion anytime in the near future. The remote helper should now\nhave a valid import capability. To use it, you must:\n\n0. Checkout the `git-merge` branch of my svn-dump-fast-export fork\n   into a fresh vcs-svn/ subdirectory on git.git `master`, and then\n   build it with the Makefile rule provided.\n1. Call the remote with a valid file (relative path is alright) passed\n   in as an argv[1].\n2. Give it the command \"import foo\" following by two newlines where\n   \"foo\" is any arbitrary string that isn't blank.\n\n[1]: http://github.com/artagnon/svn-dump-fast-export\n\nRamkumar Ramachandra (1):\n  Add remote SVN helper\n\n .gitignore   |    1 +\n Makefile     |   14 ++++-\n remote-svn.c |  191 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 205 insertions(+), 1 deletions(-)\n create mode 100644 remote-svn.c\n"},{"id":"142286","messageId":"1274806818-10904-2-git-send-email-artagnon@gmail.com","threadId":"23901","inReplyTo":"1274806818-10904-1-git-send-email-artagnon@gmail.com","subject":"[WIP PATCH] Add remote SVN helper","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2010-05-25T17:00:18Z","receivedAt":"2010-05-25T17:00:18Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"Add a remote helper for SVN that uses the exporter in vcs-svn/ with an\nappropriate Makefile rule. For this to work, you must check out the\ngit-merge branch of svn-dump-fast-export [1] into vcs-svn/ and then\nbuild git-remote-svn.\n\nSigned-off-by: Ramkumar Ramachandra <artagnon@gmail.com>\n---\n .gitignore   |    1 +\n Makefile     |   14 ++++-\n remote-svn.c |  191 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 205 insertions(+), 1 deletions(-)\n create mode 100644 remote-svn.c\n\ndiff --git a/.gitignore b/.gitignore\nindex dbf1b90..6ac8a7c 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -112,6 +112,7 @@\n /git-remote-https\n /git-remote-ftp\n /git-remote-ftps\n+/git-remote-svn\n /git-repack\n /git-replace\n /git-repo-config\ndiff --git a/Makefile b/Makefile\nindex 4f7224a..fde0cdb 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1746,6 +1746,14 @@ endif\n %.s: %.c GIT-CFLAGS FORCE\n \t$(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<\n \n+vcs-svn/%.o: vcs-svn/%.c GIT-CFLAGS FORCE\n+\t$(QUIET_CC)$(CC) -o $@ -c $(dep_args) $(ALL_CFLAGS)\t\\\n+\t-I./vcs-svn $(EXTRA_CPPFLAGS) $<\n+\n+remote-svn.o: remote-svn.c $(GITLIBS) GIT-CFLAGS FORCE\n+\t$(QUIET_CC)$(CC) -o $@ -c $(dep_args) $(ALL_CFLAGS)\t\\\n+\t-I./vcs-svn $(EXTRA_CPPFLAGS) $<\n+\n ifdef USE_COMPUTED_HEADER_DEPENDENCIES\n # Take advantage of gcc's on-the-fly dependency generation\n # See <http://gcc.gnu.org/gcc-3.0/features.html>.\n@@ -1824,6 +1832,10 @@ $(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o $(GITLIBS)\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \\\n \t\t$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)\n \n+git-remote-svn$X: remote-svn.o $(patsubst %.c,%.o,$(wildcard vcs-svn/*.c))\n+\t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \\\n+\t\t$(LIBS)\n+\n $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)\n \n@@ -2087,7 +2099,7 @@ distclean: clean\n \n clean:\n \t$(RM) *.o block-sha1/*.o ppc/*.o compat/*.o compat/*/*.o xdiff/*.o \\\n-\t\tbuiltin/*.o $(LIB_FILE) $(XDIFF_LIB)\n+\t\tbuiltin/*.o vcs-svn/*.o $(LIB_FILE) $(XDIFF_LIB)\n \t$(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git$X\n \t$(RM) $(TEST_PROGRAMS)\n \t$(RM) -r bin-wrappers\ndiff --git a/remote-svn.c b/remote-svn.c\nnew file mode 100644\nindex 0000000..def5b20\n--- /dev/null\n+++ b/remote-svn.c\n@@ -0,0 +1,191 @@\n+#include \"cache.h\"\n+#include \"strbuf.h\"\n+#include \"remote.h\"\n+#include \"strbuf.h\"\n+#include \"exec_cmd.h\"\n+\n+#include \"svnclient.h\"\n+\n+static struct remote *remote;\n+\n+struct options {\n+\tint verbosity;\n+\tunsigned long depth;\n+\tunsigned progress : 1,\n+\t\tdry_run : 1;\n+};\n+static struct options options;\n+\n+static int set_option(const char *name, const char *value)\n+{\n+\tif (!strcmp(name, \"verbosity\")) {\n+\t\tchar *end;\n+\t\tint v = strtol(value, &end, 10);\n+\t\tif (value == end || *end)\n+\t\t\treturn -1;\n+\t\toptions.verbosity = v;\n+\t\treturn 0;\n+\t} else if (!strcmp(name, \"progress\")) {\n+\t\tif (!strcmp(value, \"true\"))\n+\t\t\toptions.progress = 1;\n+\t\telse if (!strcmp(value, \"false\"))\n+\t\t\toptions.progress = 0;\n+\t\telse\n+\t\t\treturn -1;\n+\t\treturn 0;\n+\t} else if (!strcmp(name, \"dry-run\")) {\n+\t\tif (!strcmp(value, \"true\"))\n+\t\t\toptions.dry_run = 1;\n+\t\telse if (!strcmp(value, \"false\"))\n+\t\t\toptions.dry_run = 0;\n+\t\telse\n+\t\t\treturn -1;\n+\t\treturn 0;\n+\t} else {\n+\t\treturn 1;\n+\t}\n+}\n+\n+static int export_handler(int nr_spec, char **specs)\n+{\n+\tint err = 0;\n+\n+\t/* TODO: The real exporting */\n+        /* TODO: Write an importer for SVN */\n+\t\n+\treturn err;\n+}\n+\n+static int import_handler(int nr_spec, char **specs)\n+{\n+\tint err = 0, i;\n+\tfor (i = 0; i < nr_spec; i++)\n+\t\tFI_svn(specs[i]);\n+\treturn err;\n+}\n+\n+static void parse_import(struct strbuf *buf)\n+{\n+\tchar **specs = NULL;\n+\tint alloc_spec = 0, nr_spec = 0, i;\n+\n+\tdo {\n+\t\tif (!prefixcmp(buf->buf, \"import \")) {\n+\t\t\tALLOC_GROW(specs, nr_spec + 1, alloc_spec);\n+\t\t\tspecs[nr_spec++] = xstrdup(buf->buf + 5);\n+\t\t}\n+\t\telse\n+\t\t\tdie(\"remote helper does not support %s\", buf->buf);\n+\n+\t\tstrbuf_reset(buf);\n+\t\tif (strbuf_getline(buf, stdin, '\\n') == EOF)\n+\t\t\treturn;\n+\t\tif (!*buf->buf)\n+\t\t\tbreak;\n+\t} while (1);\n+\n+\tif (import_handler(nr_spec, specs))\n+\t\texit(128); /* error already reported */\n+\tfor (i = 0; i < nr_spec; i++)\n+\t\tfree(specs[i]);\n+\tfree(specs);\n+\n+\tprintf(\"\\n\");\n+\tfflush(stdout);\n+}\n+\n+static void parse_export(struct strbuf *buf)\n+{\n+\tchar **specs = NULL;\n+\tint alloc_spec = 0, nr_spec = 0, i;\n+\n+\tdo {\n+\t\tif (!prefixcmp(buf->buf, \"export \")) {\n+\t\t\tALLOC_GROW(specs, nr_spec + 1, alloc_spec);\n+\t\t\tspecs[nr_spec++] = xstrdup(buf->buf + 5);\n+\t\t} else\n+\t\t\tdie(\"remote helper does not support %s\", buf->buf);\n+\n+\t\tstrbuf_reset(buf);\n+\t\tif (strbuf_getline(buf, stdin, '\\n') == EOF)\n+\t\t\treturn;\n+\t\tif (!*buf->buf)\n+\t\t\tbreak;\n+\t} while (1);\n+\n+\tif (export_handler(nr_spec, specs))\n+\t\texit(128); /* error already reported */\n+\tfor (i = 0; i < nr_spec; i++)\n+\t\tfree(specs[i]);\n+\tfree(specs);\n+\n+\tprintf(\"\\n\");\n+\tfflush(stdout);\n+}\n+\n+int main(int argc, const char **argv)\n+{\n+\tstruct strbuf buf = STRBUF_INIT;\n+\tint nongit;\n+\n+\tgit_extract_argv0_path(argv[0]);\n+\tsetup_git_directory_gently(&nongit);\n+\tif (argc < 2) {\n+\t\tfprintf(stderr, \"Remote needed\\n\");\n+\t\treturn 1;\n+\t}\n+\n+\toptions.verbosity = 1;\n+\toptions.progress = !!isatty(2);\n+\n+\tremote = remote_get(argv[1]);\n+\n+\topen_svn_connection(remote->url[0]);\n+\tdo {\n+\t\tif (strbuf_getline(&buf, stdin, '\\n') == EOF)\n+\t\t\tbreak;\n+\n+\t\telse if (!strcmp(buf.buf, \"list\")) {\n+\t\t\t/* TODO: Code to list refs */\n+\t\t\tbreak;\n+\n+\t\t} else if (!prefixcmp(buf.buf, \"import \")) {\n+\t\t\tif (nongit)\n+\t\t\t\tdie(\"Import attempted without a local repo\");\n+\t\t\tparse_import(&buf);\n+\n+\t\t} else if (!prefixcmp(buf.buf, \"export \")) {\n+\t\t\tparse_export(&buf);\n+\n+\t\t} else if (!prefixcmp(buf.buf, \"option \")) {\n+\t\t\tchar *name = buf.buf + strlen(\"option \");\n+\t\t\tchar *value = strchr(name, ' ');\n+\t\t\tint result;\n+\t\t\tif (value)\n+\t\t\t\t*value++ = '\\0';\n+\t\t\telse\n+\t\t\t\tvalue = \"true\";\n+\t\t\tresult = set_option(name, value);\n+\t\t\tif (!result)\n+\t\t\t\tprintf(\"ok\\n\");\n+\t\t\telse if (result < 0)\n+\t\t\t\tprintf(\"error invalid value\\n\");\n+\t\t\telse\n+\t\t\t\tprintf(\"unsupported\\n\");\n+\t\t\tfflush(stdout);\n+\n+\t\t} else if (!strcmp(buf.buf, \"capabilities\")) {\n+\t\t\tprintf(\"option\\n\");\n+\t\t\tprintf(\"import\\n\");\n+\t\t\tprintf(\"export\\n\");\n+\t\t\tprintf(\"\\n\");\n+\t\t\tfflush(stdout);\n+\t\t} else\n+\t\t\treturn 1;\n+\n+\t\tstrbuf_reset(&buf);\n+\t} while (1);\n+\n+\tclose_svn_connection();\n+\treturn 0;\n+}\n-- \n1.7.1\n"}]}