summaryrefslogtreecommitdiff
path: root/transport.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2011-03-11 19:32:53 (GMT)
committerJunio C Hamano <gitster@pobox.com>2011-03-17 23:18:47 (GMT)
commit36cfda15527d4eb50c84256307e3cb46578f975e (patch)
tree636ad34656122b3c22046010b315d3581bca84f8 /transport.c
parentea2c69ed4728070be1d2ee953a6948398b859150 (diff)
downloadgit-36cfda15527d4eb50c84256307e3cb46578f975e.zip
git-36cfda15527d4eb50c84256307e3cb46578f975e.tar.gz
git-36cfda15527d4eb50c84256307e3cb46578f975e.tar.bz2
refs_from_alternate: helper to use refs from alternates
The receiving end of "git push" advertises the objects that the repository itself does not use, but are at the tips of refs in other repositories whose object databases are used as alternates for it. This helps it avoid having to receive (and the pusher having to send) objects that are already available to the receiving repository via the alternates mechanism. Tweak the helper function that implements this feature, and move it to transport.[ch] for future reuse by other programs. The additional test demonstrates how this optimization is helping "git push", and "git fetch" is ignorant about it. Signed-off-by: Junio C Hamano <gitster@pobox.com> Acked-by: Shawn O. Pearce <spearce@spearce.org>
Diffstat (limited to 'transport.c')
-rw-r--r--transport.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/transport.c b/transport.c
index 0078660..3dfbc6a 100644
--- a/transport.c
+++ b/transport.c
@@ -1189,3 +1189,37 @@ char *transport_anonymize_url(const char *url)
literal_copy:
return xstrdup(url);
}
+
+int refs_from_alternate_cb(struct alternate_object_database *e, void *cb)
+{
+ char *other;
+ size_t len;
+ struct remote *remote;
+ struct transport *transport;
+ const struct ref *extra;
+ alternate_ref_fn *ref_fn = cb;
+
+ e->name[-1] = '\0';
+ other = xstrdup(make_absolute_path(e->base));
+ e->name[-1] = '/';
+ len = strlen(other);
+
+ while (other[len-1] == '/')
+ other[--len] = '\0';
+ if (len < 8 || memcmp(other + len - 8, "/objects", 8))
+ return 0;
+ /* Is this a git repository with refs? */
+ memcpy(other + len - 8, "/refs", 6);
+ if (!is_directory(other))
+ return 0;
+ other[len - 8] = '\0';
+ remote = remote_get(other);
+ transport = transport_get(remote, other);
+ for (extra = transport_get_remote_refs(transport);
+ extra;
+ extra = extra->next)
+ ref_fn(extra, NULL);
+ transport_disconnect(transport);
+ free(other);
+ return 0;
+}