Skip to content

Commit 91b3c7c

Browse files
committed
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
2 parents 1c92e39 + e52d719 commit 91b3c7c

File tree

5 files changed

+118
-32
lines changed

5 files changed

+118
-32
lines changed

builtin/fetch-pack.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "fetch-pack.h"
1010
#include "remote.h"
1111
#include "run-command.h"
12+
#include "transport.h"
1213

1314
static int transfer_unpack_limit = -1;
1415
static int fetch_unpack_limit = -1;
@@ -217,6 +218,16 @@ static void send_request(int fd, struct strbuf *buf)
217218
safe_write(fd, buf->buf, buf->len);
218219
}
219220

221+
static void insert_one_alternate_ref(const struct ref *ref, void *unused)
222+
{
223+
rev_list_insert_ref(NULL, ref->old_sha1, 0, NULL);
224+
}
225+
226+
static void insert_alternate_refs(void)
227+
{
228+
foreach_alt_odb(refs_from_alternate_cb, insert_one_alternate_ref);
229+
}
230+
220231
static int find_common(int fd[2], unsigned char *result_sha1,
221232
struct ref *refs)
222233
{
@@ -235,6 +246,7 @@ static int find_common(int fd[2], unsigned char *result_sha1,
235246
marked = 1;
236247

237248
for_each_ref(rev_list_insert_ref, NULL);
249+
insert_alternate_refs();
238250

239251
fetching = 0;
240252
for ( ; refs ; refs = refs->next) {

builtin/receive-pack.c

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -731,43 +731,14 @@ static int delete_only(struct command *commands)
731731
return 1;
732732
}
733733

734-
static int add_refs_from_alternate(struct alternate_object_database *e, void *unused)
734+
static void add_one_alternate_ref(const struct ref *ref, void *unused)
735735
{
736-
char *other;
737-
size_t len;
738-
struct remote *remote;
739-
struct transport *transport;
740-
const struct ref *extra;
741-
742-
e->name[-1] = '\0';
743-
other = xstrdup(real_path(e->base));
744-
e->name[-1] = '/';
745-
len = strlen(other);
746-
747-
while (other[len-1] == '/')
748-
other[--len] = '\0';
749-
if (len < 8 || memcmp(other + len - 8, "/objects", 8))
750-
return 0;
751-
/* Is this a git repository with refs? */
752-
memcpy(other + len - 8, "/refs", 6);
753-
if (!is_directory(other))
754-
return 0;
755-
other[len - 8] = '\0';
756-
remote = remote_get(other);
757-
transport = transport_get(remote, other);
758-
for (extra = transport_get_remote_refs(transport);
759-
extra;
760-
extra = extra->next) {
761-
add_extra_ref(".have", extra->old_sha1, 0);
762-
}
763-
transport_disconnect(transport);
764-
free(other);
765-
return 0;
736+
add_extra_ref(".have", ref->old_sha1, 0);
766737
}
767738

768739
static void add_alternate_refs(void)
769740
{
770-
foreach_alt_odb(add_refs_from_alternate, NULL);
741+
foreach_alt_odb(refs_from_alternate_cb, add_one_alternate_ref);
771742
}
772743

773744
int cmd_receive_pack(int argc, const char **argv, const char *prefix)

t/t5501-fetch-push-alternates.sh

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#!/bin/sh
2+
3+
test_description='fetch/push involving alternates'
4+
. ./test-lib.sh
5+
6+
count_objects () {
7+
loose=0 inpack=0
8+
eval "$(
9+
git count-objects -v |
10+
sed -n -e 's/^count: \(.*\)/loose=\1/p' \
11+
-e 's/^in-pack: \(.*\)/inpack=\1/p'
12+
)" &&
13+
echo $(( $loose + $inpack ))
14+
}
15+
16+
17+
test_expect_success setup '
18+
(
19+
git init original &&
20+
cd original &&
21+
i=0 &&
22+
while test $i -le 100
23+
do
24+
echo "$i" >count &&
25+
git add count &&
26+
git commit -m "$i" || exit
27+
i=$(($i + 1))
28+
done
29+
) &&
30+
(
31+
git clone --reference=original "file:///$(pwd)/original" one &&
32+
cd one &&
33+
echo Z >count &&
34+
git add count &&
35+
git commit -m Z &&
36+
count_objects >../one.count
37+
) &&
38+
A=$(pwd)/original/.git/objects &&
39+
git init receiver &&
40+
echo "$A" >receiver/.git/objects/info/alternates &&
41+
git init fetcher &&
42+
echo "$A" >fetcher/.git/objects/info/alternates
43+
'
44+
45+
test_expect_success 'pushing into a repository with the same alternate' '
46+
(
47+
cd one &&
48+
git push ../receiver master:refs/heads/it
49+
) &&
50+
(
51+
cd receiver &&
52+
count_objects >../receiver.count
53+
) &&
54+
test_cmp one.count receiver.count
55+
'
56+
57+
test_expect_success 'fetching from a repository with the same alternate' '
58+
(
59+
cd fetcher &&
60+
git fetch ../one master:refs/heads/it &&
61+
count_objects >../fetcher.count
62+
) &&
63+
test_cmp one.count fetcher.count
64+
'
65+
66+
test_done

transport.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,3 +1189,37 @@ char *transport_anonymize_url(const char *url)
11891189
literal_copy:
11901190
return xstrdup(url);
11911191
}
1192+
1193+
int refs_from_alternate_cb(struct alternate_object_database *e, void *cb)
1194+
{
1195+
char *other;
1196+
size_t len;
1197+
struct remote *remote;
1198+
struct transport *transport;
1199+
const struct ref *extra;
1200+
alternate_ref_fn *ref_fn = cb;
1201+
1202+
e->name[-1] = '\0';
1203+
other = xstrdup(real_path(e->base));
1204+
e->name[-1] = '/';
1205+
len = strlen(other);
1206+
1207+
while (other[len-1] == '/')
1208+
other[--len] = '\0';
1209+
if (len < 8 || memcmp(other + len - 8, "/objects", 8))
1210+
return 0;
1211+
/* Is this a git repository with refs? */
1212+
memcpy(other + len - 8, "/refs", 6);
1213+
if (!is_directory(other))
1214+
return 0;
1215+
other[len - 8] = '\0';
1216+
remote = remote_get(other);
1217+
transport = transport_get(remote, other);
1218+
for (extra = transport_get_remote_refs(transport);
1219+
extra;
1220+
extra = extra->next)
1221+
ref_fn(extra, NULL);
1222+
transport_disconnect(transport);
1223+
free(other);
1224+
return 0;
1225+
}

transport.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,4 +166,7 @@ int transport_refs_pushed(struct ref *ref);
166166
void transport_print_push_status(const char *dest, struct ref *refs,
167167
int verbose, int porcelain, int *nonfastforward);
168168

169+
typedef void alternate_ref_fn(const struct ref *, void *);
170+
extern int refs_from_alternate_cb(struct alternate_object_database *e, void *cb);
171+
169172
#endif

0 commit comments

Comments
 (0)