{"thread":{"id":"20308","subject":"[PATCH 2/3 v3] Use an external program to implement fetching with curl","startedAt":"2009-07-31T05:26:40Z","lastAt":"2009-08-05T20:10:10Z","messageCount":6,"participants":["Daniel Barkalow","Johannes Schindelin","Junio C Hamano","Sverre Rabbelier"],"isPatch":true,"patchVersion":3,"patchTotal":3},"messages":[{"id":"119212","messageId":"alpine.LNX.2.00.0907310112400.2147@iabervon.org","threadId":"20308","inReplyTo":null,"subject":"[PATCH 2/3 v3] Use an external program to implement fetching with curl","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2009-07-31T05:26:40Z","receivedAt":"2009-07-31T05:26:40Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"Use the transport native helper mechanism to fetch by http (and ftp, etc).\n\nSigned-off-by: Daniel Barkalow <barkalow@iabervon.org>\n---\nNote that the bulk of remote-curl is code moved verbatim from transport.c; \ncleaning it up is a separate topic.\n\n Makefile      |    5 ++\n remote-curl.c |  139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n transport.c   |  136 +-------------------------------------------------------\n 3 files changed, 145 insertions(+), 135 deletions(-)\n create mode 100644 remote-curl.c\n\ndiff --git a/Makefile b/Makefile\nindex 504646a..35117fc 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -981,6 +981,7 @@ else\n \t\tCURL_LIBCURL = -lcurl\n \tendif\n \tBUILTIN_OBJS += builtin-http-fetch.o\n+\tPROGRAMS += git-remote-http$X git-remote-https$X git-remote-ftp$X git-http-fetch$X\n \tEXTLIBS += $(CURL_LIBCURL)\n \tLIB_OBJS += http.o http-walker.o\n \tcurl_check := $(shell (echo 070908; curl-config --vernum) | sort -r | sed -ne 2p)\n@@ -1491,6 +1492,10 @@ git-http-push$X: revision.o http.o http-push.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-http$X git-remote-https$X git-remote-ftp$X: 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 $(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)\n $(patsubst git-%$X,%.o,$(PROGRAMS)) git.o: $(LIB_H) $(wildcard */*.h)\n builtin-revert.o wt-status.o: wt-status.h\ndiff --git a/remote-curl.c b/remote-curl.c\nnew file mode 100644\nindex 0000000..ad6a163\n--- /dev/null\n+++ b/remote-curl.c\n@@ -0,0 +1,139 @@\n+#include \"cache.h\"\n+#include \"remote.h\"\n+#include \"strbuf.h\"\n+#include \"walker.h\"\n+#include \"http.h\"\n+\n+static struct ref *get_refs(struct walker *walker, const char *url)\n+{\n+\tstruct strbuf buffer = STRBUF_INIT;\n+\tchar *data, *start, *mid;\n+\tchar *ref_name;\n+\tchar *refs_url;\n+\tint i = 0;\n+\tint http_ret;\n+\n+\tstruct ref *refs = NULL;\n+\tstruct ref *ref = NULL;\n+\tstruct ref *last_ref = NULL;\n+\n+\trefs_url = xmalloc(strlen(url) + 11);\n+\tsprintf(refs_url, \"%s/info/refs\", url);\n+\n+\thttp_ret = http_get_strbuf(refs_url, &buffer, HTTP_NO_CACHE);\n+\tswitch (http_ret) {\n+\tcase HTTP_OK:\n+\t\tbreak;\n+\tcase HTTP_MISSING_TARGET:\n+\t\tdie(\"%s not found: did you run git update-server-info on the\"\n+\t\t    \" server?\", refs_url);\n+\tdefault:\n+\t\thttp_error(refs_url, http_ret);\n+\t\tdie(\"HTTP request failed\");\n+\t}\n+\n+\tdata = buffer.buf;\n+\tstart = NULL;\n+\tmid = data;\n+\twhile (i < buffer.len) {\n+\t\tif (!start) {\n+\t\t\tstart = &data[i];\n+\t\t}\n+\t\tif (data[i] == '\\t')\n+\t\t\tmid = &data[i];\n+\t\tif (data[i] == '\\n') {\n+\t\t\tdata[i] = 0;\n+\t\t\tref_name = mid + 1;\n+\t\t\tref = xmalloc(sizeof(struct ref) +\n+\t\t\t\t      strlen(ref_name) + 1);\n+\t\t\tmemset(ref, 0, sizeof(struct ref));\n+\t\t\tstrcpy(ref->name, ref_name);\n+\t\t\tget_sha1_hex(start, ref->old_sha1);\n+\t\t\tif (!refs)\n+\t\t\t\trefs = ref;\n+\t\t\tif (last_ref)\n+\t\t\t\tlast_ref->next = ref;\n+\t\t\tlast_ref = ref;\n+\t\t\tstart = NULL;\n+\t\t}\n+\t\ti++;\n+\t}\n+\n+\tstrbuf_release(&buffer);\n+\n+\tref = alloc_ref(\"HEAD\");\n+\tif (!walker->fetch_ref(walker, ref) &&\n+\t    !resolve_remote_symref(ref, refs)) {\n+\t\tref->next = refs;\n+\t\trefs = ref;\n+\t} else {\n+\t\tfree(ref);\n+\t}\n+\n+\tstrbuf_release(&buffer);\n+\tfree(refs_url);\n+\treturn refs;\n+}\n+\n+int main(int argc, const char **argv)\n+{\n+\tstruct remote *remote;\n+\tstruct strbuf buf = STRBUF_INIT;\n+\tconst char *url;\n+\tstruct walker *walker = NULL;\n+\n+\tsetup_git_directory();\n+\tif (argc < 2) {\n+\t\tfprintf(stderr, \"Remote needed\\n\");\n+\t\treturn 1;\n+\t}\n+\n+\tremote = remote_get(argv[1]);\n+\n+\tif (argc > 2) {\n+\t\turl = argv[2];\n+\t} else {\n+\t\turl = remote->url[0];\n+\t}\n+\n+\tdo {\n+\t\tif (strbuf_getline(&buf, stdin, '\\n') == EOF)\n+\t\t\tbreak;\n+\t\tif (!prefixcmp(buf.buf, \"fetch \")) {\n+\t\t\tchar *obj = buf.buf + strlen(\"fetch \");\n+\t\t\tif (!walker)\n+\t\t\t\twalker = get_http_walker(url, remote);\n+\t\t\twalker->get_all = 1;\n+\t\t\twalker->get_tree = 1;\n+\t\t\twalker->get_history = 1;\n+\t\t\twalker->get_verbosely = 0;\n+\t\t\twalker->get_recover = 0;\n+\t\t\tif (walker_fetch(walker, 1, &obj, NULL, NULL))\n+\t\t\t\tdie(\"Fetch failed.\");\n+\t\t\tprintf(\"\\n\");\n+\t\t\tfflush(stdout);\n+\t\t} else if (!strcmp(buf.buf, \"list\")) {\n+\t\t\tstruct ref *refs;\n+\t\t\tstruct ref *posn;\n+\t\t\tif (!walker)\n+\t\t\t\twalker = get_http_walker(url, remote);\n+\t\t\trefs = get_refs(walker, url);\n+\t\t\tfor (posn = refs; posn; posn = posn->next) {\n+\t\t\t\tif (posn->symref)\n+\t\t\t\t\tprintf(\"@%s %s\\n\", posn->symref, posn->name);\n+\t\t\t\telse\n+\t\t\t\t\tprintf(\"%s %s\\n\", sha1_to_hex(posn->old_sha1), posn->name);\n+\t\t\t}\n+\t\t\tprintf(\"\\n\");\n+\t\t\tfflush(stdout);\n+\t\t} else if (!strcmp(buf.buf, \"capabilities\")) {\n+\t\t\tprintf(\"fetch\\n\");\n+\t\t\tprintf(\"\\n\");\n+\t\t\tfflush(stdout);\n+\t\t} else {\n+\t\t\treturn 1;\n+\t\t}\n+\t\tstrbuf_reset(&buf);\n+\t} while (1);\n+\treturn 0;\n+}\ndiff --git a/transport.c b/transport.c\nindex de0d587..d986126 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -1,9 +1,6 @@\n #include \"cache.h\"\n #include \"transport.h\"\n #include \"run-command.h\"\n-#ifndef NO_CURL\n-#include \"http.h\"\n-#endif\n #include \"pkt-line.h\"\n #include \"fetch-pack.h\"\n #include \"send-pack.h\"\n@@ -352,45 +349,6 @@ static int rsync_transport_push(struct transport *transport,\n \treturn result;\n }\n \n-/* Generic functions for using commit walkers */\n-\n-#ifndef NO_CURL /* http fetch is the only user */\n-static int fetch_objs_via_walker(struct transport *transport,\n-\t\t\t\t int nr_objs, const struct ref **to_fetch)\n-{\n-\tchar *dest = xstrdup(transport->url);\n-\tstruct walker *walker = transport->data;\n-\tchar **objs = xmalloc(nr_objs * sizeof(*objs));\n-\tint i;\n-\n-\twalker->get_all = 1;\n-\twalker->get_tree = 1;\n-\twalker->get_history = 1;\n-\twalker->get_verbosely = transport->verbose >= 0;\n-\twalker->get_recover = 0;\n-\n-\tfor (i = 0; i < nr_objs; i++)\n-\t\tobjs[i] = xstrdup(sha1_to_hex(to_fetch[i]->old_sha1));\n-\n-\tif (walker_fetch(walker, nr_objs, objs, NULL, NULL))\n-\t\tdie(\"Fetch failed.\");\n-\n-\tfor (i = 0; i < nr_objs; i++)\n-\t\tfree(objs[i]);\n-\tfree(objs);\n-\tfree(dest);\n-\treturn 0;\n-}\n-#endif /* NO_CURL */\n-\n-static int disconnect_walker(struct transport *transport)\n-{\n-\tstruct walker *walker = transport->data;\n-\tif (walker)\n-\t\twalker_free(walker);\n-\treturn 0;\n-}\n-\n #ifndef NO_CURL\n static int curl_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags)\n {\n@@ -432,96 +390,6 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons\n \treturn !!err;\n }\n \n-static struct ref *get_refs_via_curl(struct transport *transport, int for_push)\n-{\n-\tstruct strbuf buffer = STRBUF_INIT;\n-\tchar *data, *start, *mid;\n-\tchar *ref_name;\n-\tchar *refs_url;\n-\tint i = 0;\n-\tint http_ret;\n-\n-\tstruct ref *refs = NULL;\n-\tstruct ref *ref = NULL;\n-\tstruct ref *last_ref = NULL;\n-\n-\tstruct walker *walker;\n-\n-\tif (for_push)\n-\t\treturn NULL;\n-\n-\tif (!transport->data)\n-\t\ttransport->data = get_http_walker(transport->url,\n-\t\t\t\t\t\ttransport->remote);\n-\n-\twalker = transport->data;\n-\n-\trefs_url = xmalloc(strlen(transport->url) + 11);\n-\tsprintf(refs_url, \"%s/info/refs\", transport->url);\n-\n-\thttp_ret = http_get_strbuf(refs_url, &buffer, HTTP_NO_CACHE);\n-\tswitch (http_ret) {\n-\tcase HTTP_OK:\n-\t\tbreak;\n-\tcase HTTP_MISSING_TARGET:\n-\t\tdie(\"%s not found: did you run git update-server-info on the\"\n-\t\t    \" server?\", refs_url);\n-\tdefault:\n-\t\thttp_error(refs_url, http_ret);\n-\t\tdie(\"HTTP request failed\");\n-\t}\n-\n-\tdata = buffer.buf;\n-\tstart = NULL;\n-\tmid = data;\n-\twhile (i < buffer.len) {\n-\t\tif (!start)\n-\t\t\tstart = &data[i];\n-\t\tif (data[i] == '\\t')\n-\t\t\tmid = &data[i];\n-\t\tif (data[i] == '\\n') {\n-\t\t\tdata[i] = 0;\n-\t\t\tref_name = mid + 1;\n-\t\t\tref = xmalloc(sizeof(struct ref) +\n-\t\t\t\t      strlen(ref_name) + 1);\n-\t\t\tmemset(ref, 0, sizeof(struct ref));\n-\t\t\tstrcpy(ref->name, ref_name);\n-\t\t\tget_sha1_hex(start, ref->old_sha1);\n-\t\t\tif (!refs)\n-\t\t\t\trefs = ref;\n-\t\t\tif (last_ref)\n-\t\t\t\tlast_ref->next = ref;\n-\t\t\tlast_ref = ref;\n-\t\t\tstart = NULL;\n-\t\t}\n-\t\ti++;\n-\t}\n-\n-\tstrbuf_release(&buffer);\n-\n-\tref = alloc_ref(\"HEAD\");\n-\tif (!walker->fetch_ref(walker, ref) &&\n-\t    !resolve_remote_symref(ref, refs)) {\n-\t\tref->next = refs;\n-\t\trefs = ref;\n-\t} else {\n-\t\tfree(ref);\n-\t}\n-\n-\tstrbuf_release(&buffer);\n-\tfree(refs_url);\n-\treturn refs;\n-}\n-\n-static int fetch_objs_via_curl(struct transport *transport,\n-\t\t\t\t int nr_objs, const struct ref **to_fetch)\n-{\n-\tif (!transport->data)\n-\t\ttransport->data = get_http_walker(transport->url,\n-\t\t\t\t\t\ttransport->remote);\n-\treturn fetch_objs_via_walker(transport, nr_objs, to_fetch);\n-}\n-\n #endif\n \n struct bundle_transport_data {\n@@ -950,14 +818,12 @@ struct transport *transport_get(struct remote *remote, const char *url)\n \t} else if (!prefixcmp(url, \"http://\")\n \t        || !prefixcmp(url, \"https://\")\n \t        || !prefixcmp(url, \"ftp://\")) {\n+\t\ttransport_native_helper_init(ret);\n #ifdef NO_CURL\n \t\terror(\"git was compiled without libcurl support.\");\n #else\n-\t\tret->get_refs_list = get_refs_via_curl;\n-\t\tret->fetch = fetch_objs_via_curl;\n \t\tret->push = curl_transport_push;\n #endif\n-\t\tret->disconnect = disconnect_walker;\n \n \t} else if (is_local(url) && is_file(url)) {\n \t\tstruct bundle_transport_data *data = xcalloc(1, sizeof(*data));\n-- \n1.6.4.rc3.25.gd5eff.dirty\n"},{"id":"119603","messageId":"alpine.DEB.1.00.0908051203550.8306@pacific.mpi-cbg.de","threadId":"20308","inReplyTo":"alpine.LNX.2.00.0907310112400.2147@iabervon.org","subject":"Re: [PATCH 2/3 v3] Use an external program to implement fetching with curl","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-08-05T10:05:09Z","receivedAt":"2009-08-05T10:05:09Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 31 Jul 2009, Daniel Barkalow wrote:\n\n> Use the transport native helper mechanism to fetch by http (and ftp, etc).\n> \n> Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>\n> ---\n> Note that the bulk of remote-curl is code moved verbatim from transport.c; \n> cleaning it up is a separate topic.\n> \n>  Makefile      |    5 ++\n>  remote-curl.c |  139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n>  transport.c   |  136 +-------------------------------------------------------\n>  3 files changed, 145 insertions(+), 135 deletions(-)\n>  create mode 100644 remote-curl.c\n\nI wanted to suggest using the -C option so that the patch would consist of \nmostly deleted lines (easier to verify then that it was a code move), but \ntransport.c is over 1000 lines, so that would not have worked!\n\nSo I do like the patch, and you're obviously correct about the clean up.\n\nCiao,\nDscho\n"},{"id":"119627","messageId":"alpine.LNX.2.00.0908051135080.2147@iabervon.org","threadId":"20308","inReplyTo":"alpine.DEB.1.00.0908051203550.8306@pacific.mpi-cbg.de","subject":"Re: [PATCH 2/3 v3] Use an external program to implement fetching with curl","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2009-08-05T15:45:12Z","receivedAt":"2009-08-05T15:45:12Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Wed, 5 Aug 2009, Johannes Schindelin wrote:\n\n> Hi,\n> \n> On Fri, 31 Jul 2009, Daniel Barkalow wrote:\n> \n> > Use the transport native helper mechanism to fetch by http (and ftp, etc).\n> > \n> > Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>\n> > ---\n> > Note that the bulk of remote-curl is code moved verbatim from transport.c; \n> > cleaning it up is a separate topic.\n> > \n> >  Makefile      |    5 ++\n> >  remote-curl.c |  139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n> >  transport.c   |  136 +-------------------------------------------------------\n> >  3 files changed, 145 insertions(+), 135 deletions(-)\n> >  create mode 100644 remote-curl.c\n> \n> I wanted to suggest using the -C option so that the patch would consist of \n> mostly deleted lines (easier to verify then that it was a code move), but \n> transport.c is over 1000 lines, so that would not have worked!\n\nYeah; I did use -C (so patch 3 was an obvious move), but git was wiser \nthan to produce a copy-and-delete-85% version anyway. Someday, I want to \nhave a diff output format that makes these things clear somehow. I think \nit would be not-too-hard to get the diff code to determine that an \naddition matches or almost matches a deletion (or some unchanged code), \nand provide library access to this information, but representing it to \nhumans (and getting patch to still work) is hard.\n\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"119642","messageId":"7vk51i9mse.fsf@alter.siamese.dyndns.org","threadId":"20308","inReplyTo":"alpine.DEB.1.00.0908051203550.8306@pacific.mpi-cbg.de","subject":"Re: [PATCH 2/3 v3] Use an external program to implement fetching with curl","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-08-05T17:46:09Z","receivedAt":"2009-08-05T17:46:09Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n>>  Makefile      |    5 ++\n>>  remote-curl.c |  139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n>>  transport.c   |  136 +-------------------------------------------------------\n>>  3 files changed, 145 insertions(+), 135 deletions(-)\n>>  create mode 100644 remote-curl.c\n>\n> I wanted to suggest using the -C option so that the patch would consist of \n> mostly deleted lines (easier to verify then that it was a code move), but \n> transport.c is over 1000 lines, so that would not have worked!\n\nNot that matters, but ;-)\n\n$ git show --oneline -B1/1 -C --stat a2d725b\na2d725b Use an external program to implement fetching with curl\n Makefile      |    5 +\n remote-curl.c |  139 ++++\n transport.c   | 2132 +++++++++++++++++++++++++++------------------------------\n 3 files changed, 1143 insertions(+), 1133 deletions(-)\n"},{"id":"119648","messageId":"fabb9a1e0908051115u145b2b0bi2973bcf41d5ef68f@mail.gmail.com","threadId":"20308","inReplyTo":"alpine.LNX.2.00.0908051135080.2147@iabervon.org","subject":"Re: [PATCH 2/3 v3] Use an external program to implement fetching with curl","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-08-05T18:15:40Z","receivedAt":"2009-08-05T18:15:40Z","isPatch":true,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Heya,\n\nOn Wed, Aug 5, 2009 at 08:45, Daniel Barkalow<barkalow@iabervon.org> wrote:\n> Someday, I want to\n> have a diff output format that makes these things clear somehow. I think\n> it would be not-too-hard to get the diff code to determine that an\n> addition matches or almost matches a deletion (or some unchanged code),\n> and provide library access to this information, but representing it to\n> humans (and getting patch to still work) is hard.\n\nI started on this a while ago (as part of some post-GSoC git-stats\nwork), but I had a hard time finding a good rule to determine whether\nan added hunk is similar enough to a deleted hunk elsewhere. Perhaps a\nvariant of Levenshtein can be used to determine how different two\nhunks are; I tried diffing the two hunks and then looking at the\nration between the size of the diff and the size of the original hunk,\nbut as said that didn't really work out.\n\n-- \nCheers,\n\nSverre Rabbelier\n"},{"id":"119670","messageId":"alpine.DEB.1.00.0908052156360.8306@pacific.mpi-cbg.de","threadId":"20308","inReplyTo":"fabb9a1e0908051115u145b2b0bi2973bcf41d5ef68f@mail.gmail.com","subject":"Re: [PATCH 2/3 v3] Use an external program to implement fetching with curl","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-08-05T20:10:10Z","receivedAt":"2009-08-05T20:10:10Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 5 Aug 2009, Sverre Rabbelier wrote:\n\n> On Wed, Aug 5, 2009 at 08:45, Daniel Barkalow<barkalow@iabervon.org> \n> wrote:\n> > Someday, I want to have a diff output format that makes these things \n> > clear somehow. I think it would be not-too-hard to get the diff code \n> > to determine that an addition matches or almost matches a deletion (or \n> > some unchanged code), and provide library access to this information, \n> > but representing it to humans (and getting patch to still work) is \n> > hard.\n> \n> I started on this a while ago (as part of some post-GSoC git-stats \n> work), but I had a hard time finding a good rule to determine whether an \n> added hunk is similar enough to a deleted hunk elsewhere. Perhaps a \n> variant of Levenshtein can be used to determine how different two hunks \n> are; I tried diffing the two hunks and then looking at the ration \n> between the size of the diff and the size of the original hunk, but as \n> said that didn't really work out.\n\nI think that there are two complications:\n\n- how to present it in a format that helps the human to understand, yet is \n  well-defined enough to be used as a machine-readable edit script (I \n  really do not think that it can be well-designed if it only fulfills one \n  of the two purposes).  I could imagine something like this:\n\n\tdiff --git a/remote-curl.c b/remote-curl.c\n\tpartial copy from transport.c +394,130\n\t\t#ifndef NO_CURL\n\t\tstatic int curl_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags)\n\t\t{\n\t\t[...]\n\t\t}\n\n\t\t#endif\n\t@@ -1,4 +1,6\n\t+#include \"cache.h\"\n\t+#include \"transport.h\"\n\t+#include \"refs.h\"\n\t+\n\t #ifndef NO_CURL\n\t static int curl_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags)\n\n- how to determine efficiently where to spend a lot of time to determine \n  what could be similar enough.\n\nFor example, the diff would still look pretty unreadable if you determined \nthat there was a code move which involved a reindentation, so I am not at \nall sure if it is worth to try hard to detect that that was a move after \nall.\n\nCiao,\nDscho\n"}]}