Revision adc446fe5d5f6dc1fb5edeaa9aa016ef94e70da1 authored by Junio C Hamano on 08 October 2006, 19:56:19 UTC, committed by Junio C Hamano on 09 October 2006, 00:13:15 UTC
Sean <seanlkml@sympatico.ca> writes:

> On Sat, 07 Oct 2006 21:52:02 -0700
> Junio C Hamano <junkio@cox.net> wrote:
>
>> Using DAV, if it works with the server, has the advantage of not
>> having to keep objects/info/packs up-to-date from repository
>> owner's point of view.  But the repository owner ends up keeping
>> up-to-date as a side effect of keeping info/refs up-to-date
>> anyway (as I do not see a code to read that information over
>> DAV), so there is no point doing this over DAV in practice.
>>
>> Perhaps we should remove call to remote_ls() from
>> fetch_indices() unconditionally, not just protected with
>> NO_EXPAT and be done with it?
>
> That makes a lot of sense.  A server really has to always provide
> a objects/info/packs anyway, just to be fetchable today by clients
> that are compiled with NO_EXPAT.

And even for an isolated group where everybody knows that
everybody else runs DAV-enabled clients, they need info/refs
prepared for ls-remote and git-fetch script, which means you
will run update-server-info to keep objects/info/packs up to
date.

Nick, do you see holes in my logic?

-- >8 --
http-fetch.c: drop remote_ls()

While doing remote_ls() over DAV potentially allows the server
side not to keep objects/info/pack up-to-date, misconfigured or
buggy servers can silently ignore or not to respond to DAV
requests and makes the client hang.

The server side (unfortunately) needs to run git-update-server-info
even if remote_ls() removes the need to keep objects/info/pack file
up-to-date, because the caller of git-http-fetch (git-fetch) and other
clients that interact with the repository (e.g. git-ls-remote) need to
read from info/refs file (there is no code to make that unnecessary by
using DAV yet).

Perhaps the right solution in the longer-term is to make info/refs
also unnecessary by using DAV, and we would want to resurrect the
code this patch removes when we do so, but let's drop remote_ls()
implementation for now.  It is causing problems without really
helping anything yet.

git will keep it for us until we need it next time.

Signed-off-by: Junio C Hamano <junkio@cox.net>
1 parent 9a7a62f
Raw File
object-refs.c
#include "cache.h"
#include "object.h"

int track_object_refs = 0;

static unsigned int refs_hash_size, nr_object_refs;
static struct object_refs **refs_hash;

static unsigned int hash_obj(struct object *obj, unsigned int n)
{
	unsigned int hash = *(unsigned int *)obj->sha1;
	return hash % n;
}

static void insert_ref_hash(struct object_refs *ref, struct object_refs **hash, unsigned int size)
{
	int j = hash_obj(ref->base, size);

	while (hash[j]) {
		j++;
		if (j >= size)
			j = 0;
	}
	hash[j] = ref;
}

static void grow_refs_hash(void)
{
	int i;
	int new_hash_size = (refs_hash_size + 1000) * 3 / 2;
	struct object_refs **new_hash;

	new_hash = xcalloc(new_hash_size, sizeof(struct object_refs *));
	for (i = 0; i < refs_hash_size; i++) {
		struct object_refs *ref = refs_hash[i];
		if (!ref)
			continue;
		insert_ref_hash(ref, new_hash, new_hash_size);
	}
	free(refs_hash);
	refs_hash = new_hash;
	refs_hash_size = new_hash_size;
}

static void add_object_refs(struct object *obj, struct object_refs *ref)
{
	int nr = nr_object_refs + 1;

	if (nr > refs_hash_size * 2 / 3)
		grow_refs_hash();
	ref->base = obj;
	insert_ref_hash(ref, refs_hash, refs_hash_size);
	nr_object_refs = nr;
}

struct object_refs *lookup_object_refs(struct object *obj)
{
	struct object_refs *ref;
	int j;

	/* nothing to lookup */
	if (!refs_hash_size)
		return NULL;
	j = hash_obj(obj, refs_hash_size);
	while ((ref = refs_hash[j]) != NULL) {
		if (ref->base == obj)
			break;
		j++;
		if (j >= refs_hash_size)
			j = 0;
	}
	return ref;
}

struct object_refs *alloc_object_refs(unsigned count)
{
	struct object_refs *refs;
	size_t size = sizeof(*refs) + count*sizeof(struct object *);

	refs = xcalloc(1, size);
	refs->count = count;
	return refs;
}

static int compare_object_pointers(const void *a, const void *b)
{
	const struct object * const *pa = a;
	const struct object * const *pb = b;
	if (*pa == *pb)
		return 0;
	else if (*pa < *pb)
		return -1;
	else
		return 1;
}

void set_object_refs(struct object *obj, struct object_refs *refs)
{
	unsigned int i, j;

	/* Do not install empty list of references */
	if (refs->count < 1) {
		free(refs);
		return;
	}

	/* Sort the list and filter out duplicates */
	qsort(refs->ref, refs->count, sizeof(refs->ref[0]),
	      compare_object_pointers);
	for (i = j = 1; i < refs->count; i++) {
		if (refs->ref[i] != refs->ref[i - 1])
			refs->ref[j++] = refs->ref[i];
	}
	if (j < refs->count) {
		/* Duplicates were found - reallocate list */
		size_t size = sizeof(*refs) + j*sizeof(struct object *);
		refs->count = j;
		refs = xrealloc(refs, size);
	}

	for (i = 0; i < refs->count; i++)
		refs->ref[i]->used = 1;
	add_object_refs(obj, refs);
}

void mark_reachable(struct object *obj, unsigned int mask)
{
	const struct object_refs *refs;

	if (!track_object_refs)
		die("cannot do reachability with object refs turned off");
	/* If we've been here already, don't bother */
	if (obj->flags & mask)
		return;
	obj->flags |= mask;
	refs = lookup_object_refs(obj);
	if (refs) {
		unsigned i;
		for (i = 0; i < refs->count; i++)
			mark_reachable(refs->ref[i], mask);
	}
}


back to top