aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2011-03-22 21:37:53 -0700
committerJunio C Hamano <gitster@pobox.com>2011-03-22 21:37:53 -0700
commit91b3c7ce8e189b90d3203265c9625806a15045e1 (patch)
tree2287f84dbd07706e74db16896e8e7f3a7d6dd7ed
parent1c92e394468c927f129c8f2a138b760f884e3bed (diff)
parente52d719266a06a8553043cb5616d9b4ce4abd27a (diff)
downloadgit-91b3c7ce8e189b90d3203265c9625806a15045e1.tar.gz
git-91b3c7ce8e189b90d3203265c9625806a15045e1.tar.xz
Merge branch 'jc/maint-fetch-alt'
* jc/maint-fetch-alt: fetch-pack: objects in our alternates are available to us refs_from_alternate: helper to use refs from alternates Conflicts: builtin/receive-pack.c
-rw-r--r--builtin/fetch-pack.c12
-rw-r--r--builtin/receive-pack.c35
-rwxr-xr-xt/t5501-fetch-push-alternates.sh66
-rw-r--r--transport.c34
-rw-r--r--transport.h3
5 files changed, 118 insertions, 32 deletions
diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index ef398620a..28d6900bb 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -9,6 +9,7 @@
#include "fetch-pack.h"
#include "remote.h"
#include "run-command.h"
+#include "transport.h"
static int transfer_unpack_limit = -1;
static int fetch_unpack_limit = -1;
@@ -217,6 +218,16 @@ static void send_request(int fd, struct strbuf *buf)
safe_write(fd, buf->buf, buf->len);
}
+static void insert_one_alternate_ref(const struct ref *ref, void *unused)
+{
+ rev_list_insert_ref(NULL, ref->old_sha1, 0, NULL);
+}
+
+static void insert_alternate_refs(void)
+{
+ foreach_alt_odb(refs_from_alternate_cb, insert_one_alternate_ref);
+}
+
static int find_common(int fd[2], unsigned char *result_sha1,
struct ref *refs)
{
@@ -235,6 +246,7 @@ static int find_common(int fd[2], unsigned char *result_sha1,
marked = 1;
for_each_ref(rev_list_insert_ref, NULL);
+ insert_alternate_refs();
fetching = 0;
for ( ; refs ; refs = refs->next) {
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index d8e2c5fca..27050e7c1 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -731,43 +731,14 @@ static int delete_only(struct command *commands)
return 1;
}
-static int add_refs_from_alternate(struct alternate_object_database *e, void *unused)
+static void add_one_alternate_ref(const struct ref *ref, void *unused)
{
- char *other;
- size_t len;
- struct remote *remote;
- struct transport *transport;
- const struct ref *extra;
-
- e->name[-1] = '\0';
- other = xstrdup(real_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) {
- add_extra_ref(".have", extra->old_sha1, 0);
- }
- transport_disconnect(transport);
- free(other);
- return 0;
+ add_extra_ref(".have", ref->old_sha1, 0);
}
static void add_alternate_refs(void)
{
- foreach_alt_odb(add_refs_from_alternate, NULL);
+ foreach_alt_odb(refs_from_alternate_cb, add_one_alternate_ref);
}
int cmd_receive_pack(int argc, const char **argv, const char *prefix)
diff --git a/t/t5501-fetch-push-alternates.sh b/t/t5501-fetch-push-alternates.sh
new file mode 100755
index 000000000..b5ced8483
--- /dev/null
+++ b/t/t5501-fetch-push-alternates.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+test_description='fetch/push involving alternates'
+. ./test-lib.sh
+
+count_objects () {
+ loose=0 inpack=0
+ eval "$(
+ git count-objects -v |
+ sed -n -e 's/^count: \(.*\)/loose=\1/p' \
+ -e 's/^in-pack: \(.*\)/inpack=\1/p'
+ )" &&
+ echo $(( $loose + $inpack ))
+}
+
+
+test_expect_success setup '
+ (
+ git init original &&
+ cd original &&
+ i=0 &&
+ while test $i -le 100
+ do
+ echo "$i" >count &&
+ git add count &&
+ git commit -m "$i" || exit
+ i=$(($i + 1))
+ done
+ ) &&
+ (
+ git clone --reference=original "file:///$(pwd)/original" one &&
+ cd one &&
+ echo Z >count &&
+ git add count &&
+ git commit -m Z &&
+ count_objects >../one.count
+ ) &&
+ A=$(pwd)/original/.git/objects &&
+ git init receiver &&
+ echo "$A" >receiver/.git/objects/info/alternates &&
+ git init fetcher &&
+ echo "$A" >fetcher/.git/objects/info/alternates
+'
+
+test_expect_success 'pushing into a repository with the same alternate' '
+ (
+ cd one &&
+ git push ../receiver master:refs/heads/it
+ ) &&
+ (
+ cd receiver &&
+ count_objects >../receiver.count
+ ) &&
+ test_cmp one.count receiver.count
+'
+
+test_expect_success 'fetching from a repository with the same alternate' '
+ (
+ cd fetcher &&
+ git fetch ../one master:refs/heads/it &&
+ count_objects >../fetcher.count
+ ) &&
+ test_cmp one.count fetcher.count
+'
+
+test_done
diff --git a/transport.c b/transport.c
index f1c07816e..a02f79aae 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(real_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;
+}
diff --git a/transport.h b/transport.h
index e803c0e7b..efb196886 100644
--- a/transport.h
+++ b/transport.h
@@ -166,4 +166,7 @@ int transport_refs_pushed(struct ref *ref);
void transport_print_push_status(const char *dest, struct ref *refs,
int verbose, int porcelain, int *nonfastforward);
+typedef void alternate_ref_fn(const struct ref *, void *);
+extern int refs_from_alternate_cb(struct alternate_object_database *e, void *cb);
+
#endif