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:
Junio C Hamano 2011-03-22 21:37:53 -07:00
Родитель 1c92e39446 e52d719266
Коммит 91b3c7ce8e
5 изменённых файлов: 118 добавлений и 32 удалений

Просмотреть файл

@ -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) {

Просмотреть файл

@ -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)

Просмотреть файл

@ -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

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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