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
This commit is contained in:
commit
91b3c7ce8e
@ -9,6 +9,7 @@
|
|||||||
#include "fetch-pack.h"
|
#include "fetch-pack.h"
|
||||||
#include "remote.h"
|
#include "remote.h"
|
||||||
#include "run-command.h"
|
#include "run-command.h"
|
||||||
|
#include "transport.h"
|
||||||
|
|
||||||
static int transfer_unpack_limit = -1;
|
static int transfer_unpack_limit = -1;
|
||||||
static int fetch_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);
|
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,
|
static int find_common(int fd[2], unsigned char *result_sha1,
|
||||||
struct ref *refs)
|
struct ref *refs)
|
||||||
{
|
{
|
||||||
@ -235,6 +246,7 @@ static int find_common(int fd[2], unsigned char *result_sha1,
|
|||||||
marked = 1;
|
marked = 1;
|
||||||
|
|
||||||
for_each_ref(rev_list_insert_ref, NULL);
|
for_each_ref(rev_list_insert_ref, NULL);
|
||||||
|
insert_alternate_refs();
|
||||||
|
|
||||||
fetching = 0;
|
fetching = 0;
|
||||||
for ( ; refs ; refs = refs->next) {
|
for ( ; refs ; refs = refs->next) {
|
||||||
|
@ -731,43 +731,14 @@ static int delete_only(struct command *commands)
|
|||||||
return 1;
|
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;
|
add_extra_ref(".have", ref->old_sha1, 0);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_alternate_refs(void)
|
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)
|
int cmd_receive_pack(int argc, const char **argv, const char *prefix)
|
||||||
|
66
t/t5501-fetch-push-alternates.sh
Executable file
66
t/t5501-fetch-push-alternates.sh
Executable file
@ -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
|
34
transport.c
34
transport.c
@ -1189,3 +1189,37 @@ char *transport_anonymize_url(const char *url)
|
|||||||
literal_copy:
|
literal_copy:
|
||||||
return xstrdup(url);
|
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;
|
||||||
|
}
|
||||||
|
@ -166,4 +166,7 @@ int transport_refs_pushed(struct ref *ref);
|
|||||||
void transport_print_push_status(const char *dest, struct ref *refs,
|
void transport_print_push_status(const char *dest, struct ref *refs,
|
||||||
int verbose, int porcelain, int *nonfastforward);
|
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
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user