Experimental implementation. Inspired by the existing shell script at divanorama/remote-svn-alpha. It doesn't use marks or notes yet, always imports the full history. svnrdump is started as a subprocess while svn-fe's functions are called directly. Signed-off-by: Florian Achleitner <florian.achleitner.2.6.31@xxxxxxxxx> --- contrib/svn-fe/remote-svn.c | 188 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 contrib/svn-fe/remote-svn.c diff --git a/contrib/svn-fe/remote-svn.c b/contrib/svn-fe/remote-svn.c new file mode 100644 index 0000000..ac09cc5 --- /dev/null +++ b/contrib/svn-fe/remote-svn.c @@ -0,0 +1,188 @@ + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include "cache.h" +#include "remote.h" +#include "strbuf.h" +#include "url.h" +#include "exec_cmd.h" +#include "run-command.h" +#include "svndump.h" + +static int debug = 0; + +static inline void printd(const char* fmt, ...) +{ + if(debug) { + va_list vargs; + va_start(vargs, fmt); + fprintf(stderr, "rhsvn debug: "); + vfprintf(stderr, fmt, vargs); + fprintf(stderr, "\n"); + va_end(vargs); + } +} + +static struct remote* remote; +static const char* url; +const char* private_refs = "refs/remote-svn/"; /* + remote->name. */ +const char* remote_ref = "refs/heads/master"; + +enum cmd_result cmd_capabilities(struct strbuf* line); +enum cmd_result cmd_import(struct strbuf* line); +enum cmd_result cmd_list(struct strbuf* line); + +enum cmd_result { SUCCESS, NOT_HANDLED, ERROR }; +typedef enum cmd_result (*command)(struct strbuf*); + +const command command_list[] = { + cmd_capabilities, cmd_import, cmd_list, NULL +}; + +enum cmd_result cmd_capabilities(struct strbuf* line) +{ + if(strcmp(line->buf, "capabilities")) + return NOT_HANDLED; + + printf("import\n"); + printf("\n"); + fflush(stdout); + return SUCCESS; +} + +enum cmd_result cmd_import(struct strbuf* line) +{ + const char* revs = "-r0:HEAD"; + int code; + struct child_process svndump_proc = { + .argv = NULL, /* comes later .. */ + /* we want a pipe to the child's stdout, but stdin, stderr inherited. + The user can be asked for e.g. a password */ + .in = 0, .out = -1, .err = 0, + .no_stdin = 0, .no_stdout = 0, .no_stderr = 0, + .git_cmd = 0, + .silent_exec_failure = 0, + .stdout_to_stderr = 0, + .use_shell = 0, + .clean_on_exit = 0, + .preexec_cb = NULL, + .env = NULL, + .dir = NULL + }; + + if(prefixcmp(line->buf, "import")) + return NOT_HANDLED; + + svndump_proc.argv = xcalloc(5, sizeof(char*)); + svndump_proc.argv[0] = "svnrdump"; + svndump_proc.argv[1] = "dump"; + svndump_proc.argv[2] = url; + svndump_proc.argv[3] = revs; + + code = start_command(&svndump_proc); + if(code) + die("Unable to start %s, code %d", svndump_proc.argv[0], code); + + svndump_init_fd(svndump_proc.out); + svndump_read(url); + svndump_deinit(); + svndump_reset(); + + close(svndump_proc.out); + + code = finish_command(&svndump_proc); + if(code) + warning("Something went wrong with termination of %s, code %d", svndump_proc.argv[0], code); + free(svndump_proc.argv); + + printf("done\n"); + return SUCCESS; + + + +} + +enum cmd_result cmd_list(struct strbuf* line) +{ + if(strcmp(line->buf, "list")) + return NOT_HANDLED; + + printf("? HEAD\n"); + printf("? %s\n", remote_ref); + printf("\n"); + fflush(stdout); + return SUCCESS; +} + +enum cmd_result do_command(struct strbuf* line) +{ + const command* p = command_list; + enum cmd_result ret; + printd("command line '%s'", line->buf); + while(*p) { + ret = (*p)(line); + if(ret != NOT_HANDLED) + return ret; + p++; + } + warning("Unknown command '%s'\n", line->buf); + return ret; +} + +int main(int argc, const char **argv) +{ + struct strbuf buf = STRBUF_INIT; + int nongit; + + if (getenv("GIT_TRANSPORT_HELPER_DEBUG")) + debug = 1; + + git_extract_argv0_path(argv[0]); + setup_git_directory_gently(&nongit); + if (argc < 2) { + fprintf(stderr, "Remote needed\n"); + return 1; + } + + remote = remote_get(argv[1]); + if (argc == 3) { + end_url_with_slash(&buf, argv[2]); + } else if (argc == 2) { + end_url_with_slash(&buf, remote->url[0]); + } else { + warning("Excess arguments!"); + } + + url = strbuf_detach(&buf, NULL); + + printd("remote-svn starting with url %s", url); + + /* build private ref namespace path for this svn remote. */ + strbuf_init(&buf, 0); + strbuf_addstr(&buf, private_refs); + strbuf_addstr(&buf, remote->name); + strbuf_addch(&buf, '/'); + private_refs = strbuf_detach(&buf, NULL); + + while(1) { + if (strbuf_getline(&buf, stdin, '\n') == EOF) { + if (ferror(stdin)) + fprintf(stderr, "Error reading command stream\n"); + else + fprintf(stderr, "Unexpected end of command stream\n"); + return 1; + } + /* an empty line terminates the command stream */ + if(buf.len == 0) + break; + + do_command(&buf); + strbuf_reset(&buf); + } + + strbuf_release(&buf); + free((void*)url); + free((void*)private_refs); + return 0; +} -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html