[PATCH] Define relative .git/objects/info/alternates semantics.
Linus Torvalds <torvalds@osdl.org> writes:
Show 9 quoted lines
> Yes. We should probably have some well-defined meaning for relative paths
> in there regardless (eg just define that they are always relative to the
> main GIT_OBJECT_DIRECTORY or something).
>
> That would also allow mirrors to mirror the git archives in different
> places, without upsetting the result (as long as they are mirrored
> together).
>
> Linus
This patch is request-for-comments. I have experimented it and have a feeling that it may be more intuitive to make it relative to $project.git/ directory, instead of $project.git/objects as you originally suggested, in which case a maintainer tree would have "../../torvalds/linux-2.6.git/objects" instead (one less dotdot), and if nobody objects that is probably what I'll end up doing.
------------ An entry in the alternates file can name a directory relative to the object store it describes. A typical linux-2.6 maintainer repository would have "../../../torvalds/linux-2.6.git/objects" there, because the subsystem maintainer object store would live in
/pub/scm/linux/kernel/git/$u/$system.git/objects/
and the object store of Linus tree is in
/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/
This unfortunately is different from GIT_ALTERNATE_OBJECT_DIRECTORIES which is relative to the cwd of the running process, but there is no way to make it consistent with the behaviour of the environment variable. The process typically is run in $system.git/ directory for a naked repository, or one level up for a repository with a working tree, so we just define it to be relative to the objects/ directory to be different from either ;-).
Later, the dumb transport could be updated to read from info/alternates and make requests for the repository the repository borrows from.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
sha1_file.c | 28 ++++++++++++++++++++++------
1 files changed, 22 insertions(+), 6 deletions(-)
e2e8a0ba5fc80368bf46c615276e406dd373729c
diff --git a/sha1_file.c b/sha1_file.c
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -240,10 +240,12 @@ static struct alternate_object_database
* SHA1, an extra slash for the first level indirection, and the
* terminating NUL.
*/
-static void link_alt_odb_entries(const char *alt, const char *ep, int sep)
+static void link_alt_odb_entries(const char *alt, const char *ep, int sep,
+ const char *relative_base)
{
const char *cp, *last;
struct alternate_object_database *ent;
+ int base_len = -1;
last = alt;
while (last < ep) {
@@ -261,12 +263,25 @@ static void link_alt_odb_entries(const c
int pfxlen = cp - last;
int entlen = pfxlen + 43;
+ if (*last != '/' && relative_base) {
+ /* Relative alt-odb */
+ if (base_len < 0)
+ base_len = strlen(relative_base) + 1;
+ entlen += base_len;
+ pfxlen += base_len;
+ }
ent = xmalloc(sizeof(*ent) + entlen);
*alt_odb_tail = ent;
alt_odb_tail = &(ent->next);
ent->next = NULL;
-
- memcpy(ent->base, last, pfxlen);
+ if (*last != '/' && relative_base) {
+ memcpy(ent->base, relative_base, base_len - 1);
+ ent->base[base_len - 1] = '/';
+ memcpy(ent->base + base_len,
+ last, cp - last);
+ }
+ else
+ memcpy(ent->base, last, pfxlen);
ent->name = ent->base + pfxlen + 1;
ent->base[pfxlen] = ent->base[pfxlen + 3] = '/';
ent->base[entlen-1] = 0;
@@ -288,12 +303,12 @@ void prepare_alt_odb(void)
alt = getenv(ALTERNATE_DB_ENVIRONMENT);
if (!alt) alt = "";
- sprintf(path, "%s/info/alternates", get_object_directory());
if (alt_odb_tail)
return;
alt_odb_tail = &alt_odb_list;
- link_alt_odb_entries(alt, alt + strlen(alt), ':');
+ link_alt_odb_entries(alt, alt + strlen(alt), ':', NULL);
+ sprintf(path, "%s/info/alternates", get_object_directory());
fd = open(path, O_RDONLY);
if (fd < 0)
return;
@@ -306,7 +321,8 @@ void prepare_alt_odb(void)
if (map == MAP_FAILED)
return;
- link_alt_odb_entries(map, map + st.st_size, '\n');
+ link_alt_odb_entries(map, map + st.st_size, '\n',
+ get_object_directory());
munmap(map, st.st_size);
}