{"thread":{"id":"19536","subject":"[PATCH 6/7] Add a transport implementation using git-vcs-* helpers","startedAt":"2009-05-27T18:15:50Z","lastAt":"2009-05-27T18:15:50Z","messageCount":1,"participants":["Daniel Barkalow"],"isPatch":true,"patchVersion":1,"patchTotal":7},"messages":[{"id":"114823","messageId":"alpine.LNX.2.00.0905271409220.2147@iabervon.org","threadId":"19536","inReplyTo":null,"subject":"[PATCH 6/7] Add a transport implementation using git-vcs-* helpers","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2009-05-27T18:15:50Z","receivedAt":"2009-05-27T18:15:50Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"This is somewhat careless about pushes (that is, it attempts to make \npushes that the helper can't necessarily handle), but actually works for \nfetches and simple pushes.\n\nSigned-off-by: Daniel Barkalow <barkalow@iabervon.org>\n---\n Makefile            |    1 +\n transport-foreign.c |  200 +++++++++++++++++++++++++++++++++++++++++++++++++++\n transport.c         |    1 +\n transport.h         |    3 +\n 4 files changed, 205 insertions(+), 0 deletions(-)\n create mode 100644 transport-foreign.c\n\ndiff --git a/Makefile b/Makefile\nindex fdb39fa..e6e926e 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -529,6 +529,7 @@ LIB_OBJS += symlinks.o\n LIB_OBJS += tag.o\n LIB_OBJS += trace.o\n LIB_OBJS += transport.o\n+LIB_OBJS += transport-foreign.o\n LIB_OBJS += tree-diff.o\n LIB_OBJS += tree.o\n LIB_OBJS += tree-walk.o\ndiff --git a/transport-foreign.c b/transport-foreign.c\nnew file mode 100644\nindex 0000000..29aad77\n--- /dev/null\n+++ b/transport-foreign.c\n@@ -0,0 +1,200 @@\n+#include \"cache.h\"\n+#include \"transport.h\"\n+\n+#include \"run-command.h\"\n+#include \"commit.h\"\n+#include \"diff.h\"\n+#include \"revision.h\"\n+\n+struct foreign_data\n+{\n+\tstruct child_process *importer;\n+};\n+\n+static struct child_process *get_importer(struct transport *transport)\n+{\n+\tstruct child_process *importer = transport->data;\n+\tif (!importer) {\n+\t\tstruct strbuf buf;\n+\t\timporter = xcalloc(1, sizeof(*importer));\n+\t\timporter->in = -1;\n+\t\timporter->out = -1;\n+\t\timporter->err = 0;\n+\t\timporter->argv = xcalloc(3, sizeof(*importer->argv));\n+\t\tstrbuf_init(&buf, 80);\n+\t\tstrbuf_addf(&buf, \"vcs-%s\", transport->remote->foreign_vcs);\n+\t\timporter->argv[0] = buf.buf;\n+\t\timporter->argv[1] = transport->remote->name;\n+\t\timporter->git_cmd = 1;\n+\t\tstart_command(importer);\n+\t\ttransport->data = importer;\n+\t}\n+\treturn importer;\n+}\n+\n+static int disconnect_foreign(struct transport *transport)\n+{\n+\tstruct child_process *importer = transport->data;\n+\tif (importer) {\n+\t\twrite(importer->in, \"\\n\", 1);\n+\t\tclose(importer->in);\n+\t\tfinish_command(importer);\n+\t\tfree(importer);\n+\t\ttransport->data = NULL;\n+\t}\n+\treturn 0;\n+}\n+\n+static int fetch_refs_via_foreign(struct transport *transport,\n+\t\t\t\t  int nr_heads, struct ref **to_fetch)\n+{\n+\tstruct child_process *importer;\n+\tstruct child_process fastimport;\n+\tstruct ref *posn;\n+\tint i, count;\n+\n+\tcount = 0;\n+\tfor (i = 0; i < nr_heads; i++) {\n+\t\tposn = to_fetch[i];\n+\t\tif (posn->status & REF_STATUS_UPTODATE)\n+\t\t\tcontinue;\n+\t\tcount++;\n+\t}\n+\tif (count) {\n+\t\timporter = get_importer(transport);\n+\n+\t\tmemset(&fastimport, 0, sizeof(fastimport));\n+\t\tfastimport.in = importer->out;\n+\t\tfastimport.argv = xcalloc(3, sizeof(*fastimport.argv));\n+\t\tfastimport.argv[0] = \"fast-import\";\n+\t\tfastimport.argv[1] = \"--quiet\";\n+\t\tfastimport.git_cmd = 1;\n+\t\tstart_command(&fastimport);\n+\n+\t\tfor (i = 0; i < nr_heads; i++) {\n+\t\t\tposn = to_fetch[i];\n+\t\t\tif (posn->status & REF_STATUS_UPTODATE)\n+\t\t\t\tcontinue;\n+\t\t\twrite(importer->in, \"import \", 7);\n+\t\t\twrite(importer->in, posn->name, strlen(posn->name));\n+\t\t\twrite(importer->in, \"\\n\", 1);\n+\t\t}\n+\t\tdisconnect_foreign(transport);\n+\t\tfinish_command(&fastimport);\n+\t}\n+\tfor (i = 0; i < nr_heads; i++) {\n+\t\tposn = to_fetch[i];\n+\t\tif (posn->status & REF_STATUS_UPTODATE)\n+\t\t\tcontinue;\n+\t\tread_ref(posn->name, posn->old_sha1);\n+\t}\n+\treturn 0;\n+}\n+\n+static struct ref *get_refs_via_foreign(struct transport *transport, int for_push)\n+{\n+\tstruct child_process *importer;\n+\tstruct ref *ret = NULL;\n+\tstruct ref **end = &ret;\n+\tstruct strbuf buf;\n+\tFILE *file;\n+\n+\timporter = get_importer(transport);\n+\twrite(importer->in, \"list\\n\", 5);\n+\n+\tstrbuf_init(&buf, 0);\n+\tfile = fdopen(importer->out, \"r\");\n+\twhile (1) {\n+\t\tchar *eon;\n+\t\tif (strbuf_getline(&buf, file, '\\n') == EOF)\n+\t\t\tbreak;\n+\n+\t\tif (!*buf.buf)\n+\t\t\tbreak;\n+\n+\t\teon = strchr(buf.buf, ' ');\n+\t\tif (eon)\n+\t\t\t*eon = '\\0';\n+\t\t*end = alloc_ref(buf.buf);\n+\t\tif (eon) {\n+\t\t\tif (strstr(eon + 1, \"unchanged\")) {\n+\t\t\t\t(*end)->status |= REF_STATUS_UPTODATE;\n+\t\t\t\tif (read_ref((*end)->name, (*end)->old_sha1))\n+\t\t\t\t\tdie(\"Unchanged?\");\n+\t\t\t\tfprintf(stderr, \"Old: %p %s\\n\", *end, sha1_to_hex((*end)->old_sha1));\n+\t\t\t}\n+\t\t}\n+\t\tend = &((*end)->next);\n+\t\tstrbuf_reset(&buf);\n+\t}\n+\n+\tstrbuf_release(&buf);\n+\treturn ret;\n+}\n+\n+static int foreign_push(struct transport *transport, struct ref *remote_refs, int flags) {\n+\tstruct ref *ref, *has;\n+\tstruct child_process *importer;\n+\tstruct rev_info revs;\n+\tstruct commit *commit;\n+\tstruct child_process fastimport;\n+\n+\timporter = get_importer(transport);\n+\n+\tmemset(&fastimport, 0, sizeof(fastimport));\n+\tfastimport.in = importer->out;\n+\tfastimport.argv = xcalloc(3, sizeof(*fastimport.argv));\n+\tfastimport.argv[0] = \"fast-import\";\n+\tfastimport.argv[1] = \"--quiet\";\n+\tfastimport.git_cmd = 1;\n+\tstart_command(&fastimport);\n+\tfor (ref = remote_refs; ref; ref = ref->next) {\n+\t\tif (!ref->peer_ref) {\n+\t\t\tref->status = REF_STATUS_NONE;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tinit_revisions(&revs, NULL);\n+\t\trevs.reverse = 1;\n+\t\tfor (has = remote_refs; has; has = has->next) {\n+\t\t\tcommit = lookup_commit(has->old_sha1);\n+\t\t\tcommit->object.flags |= UNINTERESTING;\n+\t\t\tadd_pending_object(&revs, &commit->object, has->name);\n+\t\t}\n+\t\tcommit = lookup_commit(ref->peer_ref->new_sha1);\n+\t\tadd_pending_object(&revs, &commit->object, ref->name);\n+\n+\t\tif (prepare_revision_walk(&revs))\n+\t\t\tdie(\"Something wrong\");\n+\n+\t\tref->status = REF_STATUS_UPTODATE;\n+\t\twhile ((commit = get_revision(&revs))) {\n+\t\t\tref->status = REF_STATUS_EXPECTING_REPORT;\n+\t\t\tfprintf(stderr, \"export %s %s\\n\", sha1_to_hex(commit->object.sha1), ref->name);\n+\t\t\twrite(importer->in, \"export \", 7);\n+\t\t\twrite(importer->in, sha1_to_hex(commit->object.sha1), 40);\n+\t\t\twrite(importer->in, \" \", 1);\n+\t\t\twrite(importer->in, ref->name, strlen(ref->name));\n+\t\t\twrite(importer->in, \"\\n\", 1);\n+\t\t}\n+\t}\n+\n+\tdisconnect_foreign(transport);\n+\tfinish_command(&fastimport);\n+\n+\tfor (ref = remote_refs; ref; ref = ref->next) {\n+\t\tread_ref(ref->name, ref->new_sha1);\n+\t\tif (ref->status == REF_STATUS_EXPECTING_REPORT)\n+\t\t\tref->status = REF_STATUS_OK;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+void transport_foreign_init(struct transport *transport)\n+{\n+\ttransport->get_refs_list = get_refs_via_foreign;\n+\ttransport->fetch = fetch_refs_via_foreign;\n+\ttransport->push_refs = foreign_push;\n+\ttransport->disconnect = disconnect_foreign;\n+\ttransport->url = transport->remote->foreign_vcs;\n+}\ndiff --git a/transport.c b/transport.c\nindex 011a8dc..457b74d 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -939,6 +939,7 @@ struct transport *transport_get(struct remote *remote, const char *url)\n \tret->remote = remote;\n \n \tif (remote && remote->foreign_vcs) {\n+\t\ttransport_foreign_init(ret);\n \t\treturn ret;\n \t}\n \ndiff --git a/transport.h b/transport.h\nindex f3db2e1..db40d23 100644\n--- a/transport.h\n+++ b/transport.h\n@@ -113,4 +113,7 @@ void transport_unlock_pack(struct transport *transport);\n int transport_disconnect(struct transport *transport);\n char *transport_anonymize_url(const char *url);\n \n+/* Transport methods defined outside transport.c */\n+void transport_foreign_init(struct transport *transport);\n+\n #endif\n-- \n1.6.0.6\n"}]}