{"thread":{"id":"4018","subject":"[PATCH] Transitively read alternatives","startedAt":"2006-05-01T20:36:33Z","lastAt":"2006-05-03T07:51:33Z","messageCount":6,"participants":["Martin Waitz","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"19333","messageId":"20060501203631.GH20847@admingilde.org","threadId":"4018","inReplyTo":null,"subject":"[PATCH] Transitively read alternatives","fromName":"Martin Waitz","fromEmail":"tali@admingilde.org","sentAt":"2006-05-01T20:36:33Z","receivedAt":"2006-05-01T20:36:33Z","isPatch":true,"sender":{"key":"tali@admingilde.org","avatar":"https://gravatar.com/avatar/3f89b03eee362187effabe257898735b475673a12265c398ea9161259ae91553?d=mp&s=160"},"body":"When adding an alternate object store then add entries from its\ninfo/alternates files, too.\n\nSigned-off-by: Martin Waitz <tali@admingilde.org>\n\n---\n\n sha1_file.c |  165 +++++++++++++++++++++++++++++++++--------------------------\n 1 files changed, 93 insertions(+), 72 deletions(-)\n\n7fabfb214a971b8b45ec36dcf47929f4bf0917eb\ndiff --git a/sha1_file.c b/sha1_file.c\nindex f2d33af..ff9c989 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -216,6 +216,8 @@ char *sha1_pack_index_name(const unsigne\n struct alternate_object_database *alt_odb_list;\n static struct alternate_object_database **alt_odb_tail;\n \n+static void read_info_alternates(const char * alternates);\n+\n /*\n  * Prepare alternate object database registry.\n  *\n@@ -231,13 +233,77 @@ static struct alternate_object_database \n  * SHA1, an extra slash for the first level indirection, and the\n  * terminating NUL.\n  */\n+static int link_alt_odb_entry(const char * entry, int len, const char * relative_base)\n+{\n+\tstruct stat st;\n+\tconst char *objdir = get_object_directory();\n+\tstruct alternate_object_database *ent;\n+\tstruct alternate_object_database *alt;\n+\t/* 43 = 40-byte + 2 '/' + terminating NUL */\n+\tint pfxlen = len;\n+\tint entlen = pfxlen + 43;\n+\tint base_len = -1;\n+\n+\tif (*entry != '/' && relative_base) {\n+\t\t/* Relative alt-odb */\n+\t\tif (base_len < 0)\n+\t\t\tbase_len = strlen(relative_base) + 1;\n+\t\tentlen += base_len;\n+\t\tpfxlen += base_len;\n+\t}\n+\tent = xmalloc(sizeof(*ent) + entlen);\n+\n+\tif (*entry != '/' && relative_base) {\n+\t\tmemcpy(ent->base, relative_base, base_len - 1);\n+\t\tent->base[base_len - 1] = '/';\n+\t\tmemcpy(ent->base + base_len, entry, len);\n+\t}\n+\telse\n+\t\tmemcpy(ent->base, entry, pfxlen);\n+\n+\tent->name = ent->base + pfxlen + 1;\n+\tent->base[pfxlen + 3] = '/';\n+\tent->base[pfxlen] = ent->base[entlen-1] = 0;\n+\n+\t/* Detect cases where alternate disappeared */\n+\tif (stat(ent->base, &st) || !S_ISDIR(st.st_mode)) {\n+\t\terror(\"object directory %s does not exist; \"\n+\t\t      \"check .git/objects/info/alternates.\",\n+\t\t      ent->base);\n+\t\tfree(ent);\n+\t\treturn -1;\n+\t}\n+\n+\t/* Prevent the common mistake of listing the same\n+\t * thing twice, or object directory itself.\n+\t */\n+\tfor (alt = alt_odb_list; alt; alt = alt->next)\n+\t\tif (!memcmp(ent->base, alt->base, pfxlen)) {\n+\t\t\tfree(ent);\n+\t\t\treturn -1;\n+\t\t}\n+\tif (!memcmp(ent->base, objdir, pfxlen)) {\n+\t\tfree(ent);\n+\t\treturn -1;\n+\t}\n+\n+\t/* recursively add alternates */\n+\tread_info_alternates(ent->base);\n+\n+\tent->base[pfxlen] = '/';\n+\n+\t/* add the alternate entry */\n+\t*alt_odb_tail = ent;\n+\talt_odb_tail = &(ent->next);\n+\tent->next = NULL;\n+\n+\treturn 0;\n+}\n+\n static void link_alt_odb_entries(const char *alt, const char *ep, int sep,\n \t\t\t\t const char *relative_base)\n {\n \tconst char *cp, *last;\n-\tstruct alternate_object_database *ent;\n-\tconst char *objdir = get_object_directory();\n-\tint base_len = -1;\n \n \tlast = alt;\n \twhile (last < ep) {\n@@ -248,61 +314,10 @@ static void link_alt_odb_entries(const c\n \t\t\tlast = cp + 1;\n \t\t\tcontinue;\n \t\t}\n-\t\tfor ( ; cp < ep && *cp != sep; cp++)\n-\t\t\t;\n+\t\twhile (cp < ep && *cp != sep)\n+\t\t\tcp++;\n \t\tif (last != cp) {\n-\t\t\tstruct stat st;\n-\t\t\tstruct alternate_object_database *alt;\n-\t\t\t/* 43 = 40-byte + 2 '/' + terminating NUL */\n-\t\t\tint pfxlen = cp - last;\n-\t\t\tint entlen = pfxlen + 43;\n-\n-\t\t\tif (*last != '/' && relative_base) {\n-\t\t\t\t/* Relative alt-odb */\n-\t\t\t\tif (base_len < 0)\n-\t\t\t\t\tbase_len = strlen(relative_base) + 1;\n-\t\t\t\tentlen += base_len;\n-\t\t\t\tpfxlen += base_len;\n-\t\t\t}\n-\t\t\tent = xmalloc(sizeof(*ent) + entlen);\n-\n-\t\t\tif (*last != '/' && relative_base) {\n-\t\t\t\tmemcpy(ent->base, relative_base, base_len - 1);\n-\t\t\t\tent->base[base_len - 1] = '/';\n-\t\t\t\tmemcpy(ent->base + base_len,\n-\t\t\t\t       last, cp - last);\n-\t\t\t}\n-\t\t\telse\n-\t\t\t\tmemcpy(ent->base, last, pfxlen);\n-\n-\t\t\tent->name = ent->base + pfxlen + 1;\n-\t\t\tent->base[pfxlen + 3] = '/';\n-\t\t\tent->base[pfxlen] = ent->base[entlen-1] = 0;\n-\n-\t\t\t/* Detect cases where alternate disappeared */\n-\t\t\tif (stat(ent->base, &st) || !S_ISDIR(st.st_mode)) {\n-\t\t\t\terror(\"object directory %s does not exist; \"\n-\t\t\t\t      \"check .git/objects/info/alternates.\",\n-\t\t\t\t      ent->base);\n-\t\t\t\tgoto bad;\n-\t\t\t}\n-\t\t\tent->base[pfxlen] = '/';\n-\n-\t\t\t/* Prevent the common mistake of listing the same\n-\t\t\t * thing twice, or object directory itself.\n-\t\t\t */\n-\t\t\tfor (alt = alt_odb_list; alt; alt = alt->next)\n-\t\t\t\tif (!memcmp(ent->base, alt->base, pfxlen))\n-\t\t\t\t\tgoto bad;\n-\t\t\tif (!memcmp(ent->base, objdir, pfxlen)) {\n-\t\t\tbad:\n-\t\t\t\tfree(ent);\n-\t\t\t}\n-\t\t\telse {\n-\t\t\t\t*alt_odb_tail = ent;\n-\t\t\t\talt_odb_tail = &(ent->next);\n-\t\t\t\tent->next = NULL;\n-\t\t\t}\n+\t\t\tlink_alt_odb_entry(last, cp - last, relative_base);\n \t\t}\n \t\twhile (cp < ep && *cp == sep)\n \t\t\tcp++;\n@@ -310,23 +325,14 @@ static void link_alt_odb_entries(const c\n \t}\n }\n \n-void prepare_alt_odb(void)\n+static void read_info_alternates(const char * relative_base)\n {\n-\tchar path[PATH_MAX];\n \tchar *map;\n-\tint fd;\n \tstruct stat st;\n-\tchar *alt;\n-\n-\talt = getenv(ALTERNATE_DB_ENVIRONMENT);\n-\tif (!alt) alt = \"\";\n-\n-\tif (alt_odb_tail)\n-\t\treturn;\n-\talt_odb_tail = &alt_odb_list;\n-\tlink_alt_odb_entries(alt, alt + strlen(alt), ':', NULL);\n+\tchar path[PATH_MAX];\n+\tint fd;\n \n-\tsprintf(path, \"%s/info/alternates\", get_object_directory());\n+\tsprintf(path, \"%s/info/alternates\", relative_base);\n \tfd = open(path, O_RDONLY);\n \tif (fd < 0)\n \t\treturn;\n@@ -339,11 +345,26 @@ void prepare_alt_odb(void)\n \tif (map == MAP_FAILED)\n \t\treturn;\n \n-\tlink_alt_odb_entries(map, map + st.st_size, '\\n',\n-\t\t\t     get_object_directory());\n+\tlink_alt_odb_entries(map, map + st.st_size, '\\n', relative_base);\n+\n \tmunmap(map, st.st_size);\n }\n \n+void prepare_alt_odb(void)\n+{\n+\tchar *alt;\n+\n+\talt = getenv(ALTERNATE_DB_ENVIRONMENT);\n+\tif (!alt) alt = \"\";\n+\n+\tif (alt_odb_tail)\n+\t\treturn;\n+\talt_odb_tail = &alt_odb_list;\n+\tlink_alt_odb_entries(alt, alt + strlen(alt), ':', NULL);\n+\n+\tread_info_alternates(get_object_directory());\n+}\n+\n static char *find_sha1_file(const unsigned char *sha1, struct stat *st)\n {\n \tchar *name = sha1_file_name(sha1);\n-- \n1.3.1.gc585-dirty\n\n-- \nMartin Waitz\n"},{"id":"19336","messageId":"7v1wvdsbuj.fsf@assigned-by-dhcp.cox.net","threadId":"4018","inReplyTo":"20060501203631.GH20847@admingilde.org","subject":"Re: [PATCH] Transitively read alternatives","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-05-01T20:56:36Z","receivedAt":"2006-05-01T20:56:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Martin Waitz <tali@admingilde.org> writes:\n\n> When adding an alternate object store then add entries from its\n> info/alternates files, too.\n>\n> Signed-off-by: Martin Waitz <tali@admingilde.org>\n\nHappy.  Sometimes it pays off to leave things that can be\nimproved as they are, mention just \"we might want to do this\ninstead\", and forget about it myself.  Somebody else comes in\nand fixes it for me ;-).\n\nIf you have a local copy of Linus, Jeff and David trees, you\ncould arrange Jeff tree to borrow from Linus and David, and\nDavid tree to borrow from Linus and Jeff.  I wonder what the new\ncode does when you add a new repository that borrows from Jeff\nand David.  Does it borrow from Linus twice?  Four times?  Does\nit stop without falling into endless recursion?  I did not do\nthis myself because I was lazy and did not want to address these\nissues.\n"},{"id":"19339","messageId":"20060501225335.GI20847@admingilde.org","threadId":"4018","inReplyTo":"7v1wvdsbuj.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Transitively read alternatives","fromName":"Martin Waitz","fromEmail":"tali@admingilde.org","sentAt":"2006-05-01T22:53:35Z","receivedAt":"2006-05-01T22:53:35Z","isPatch":true,"sender":{"key":"tali@admingilde.org","avatar":"https://gravatar.com/avatar/3f89b03eee362187effabe257898735b475673a12265c398ea9161259ae91553?d=mp&s=160"},"body":"hoi :)\n\nOn Mon, May 01, 2006 at 01:56:36PM -0700, Junio C Hamano wrote:\n> If you have a local copy of Linus, Jeff and David trees, you\n> could arrange Jeff tree to borrow from Linus and David, and\n> David tree to borrow from Linus and Jeff.  I wonder what the new\n> code does when you add a new repository that borrows from Jeff\n> and David.  Does it borrow from Linus twice?  Four times?  Does\n> it stop without falling into endless recursion?  I did not do\n> this myself because I was lazy and did not want to address these\n> issues.\n\nI haven't tested these corner cases extensively yet, but from reading\nthe code it should behave like this:\n\nIf you have loops or multiple references to the same repository then\nonly the first occurance is used.  When reading a reference to an alternate\nobject store for the second time it is simply ignored.\n\nBut of course you should be careful when you set up alternate files.\nHaving two repositories reference each other and then simultanously\nrunning git-prune in both is obviously not a good idea ;-).\n\n... more testing ...\n\nWell of course practice and reality always differ... I'll send an\nupdated patch shortly ;-)\n\n-- \nMartin Waitz\n"},{"id":"19351","messageId":"20060502073847.GK20847@admingilde.org","threadId":"4018","inReplyTo":"20060501225335.GI20847@admingilde.org","subject":"[PATCH] Transitively read alternatives","fromName":"Martin Waitz","fromEmail":"tali@admingilde.org","sentAt":"2006-05-02T07:38:47Z","receivedAt":"2006-05-02T07:38:47Z","isPatch":true,"sender":{"key":"tali@admingilde.org","avatar":"https://gravatar.com/avatar/3f89b03eee362187effabe257898735b475673a12265c398ea9161259ae91553?d=mp&s=160"},"body":"When adding an alternate object store then add entries from its\ninfo/alternates files, too.\n\nSigned-off-by: Martin Waitz <tali@admingilde.org>\n\n---\n\n sha1_file.c |  166 +++++++++++++++++++++++++++++++++--------------------------\n 1 files changed, 94 insertions(+), 72 deletions(-)\n\n6ef777610f4e314fd93ecf672b9898fb95a7d5af\ndiff --git a/sha1_file.c b/sha1_file.c\nindex f2d33af..fb5778c 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -216,6 +216,8 @@ char *sha1_pack_index_name(const unsigne\n struct alternate_object_database *alt_odb_list;\n static struct alternate_object_database **alt_odb_tail;\n \n+static void read_info_alternates(const char * alternates);\n+\n /*\n  * Prepare alternate object database registry.\n  *\n@@ -231,13 +233,78 @@ static struct alternate_object_database \n  * SHA1, an extra slash for the first level indirection, and the\n  * terminating NUL.\n  */\n+static int link_alt_odb_entry(const char * entry, int len, const char * relative_base)\n+{\n+\tstruct stat st;\n+\tconst char *objdir = get_object_directory();\n+\tstruct alternate_object_database *ent;\n+\tstruct alternate_object_database *alt;\n+\t/* 43 = 40-byte + 2 '/' + terminating NUL */\n+\tint pfxlen = len;\n+\tint entlen = pfxlen + 43;\n+\tint base_len = -1;\n+\n+\tif (*entry != '/' && relative_base) {\n+\t\t/* Relative alt-odb */\n+\t\tif (base_len < 0)\n+\t\t\tbase_len = strlen(relative_base) + 1;\n+\t\tentlen += base_len;\n+\t\tpfxlen += base_len;\n+\t}\n+\tent = xmalloc(sizeof(*ent) + entlen);\n+\n+\tif (*entry != '/' && relative_base) {\n+\t\tmemcpy(ent->base, relative_base, base_len - 1);\n+\t\tent->base[base_len - 1] = '/';\n+\t\tmemcpy(ent->base + base_len, entry, len);\n+\t}\n+\telse\n+\t\tmemcpy(ent->base, entry, pfxlen);\n+\n+\tent->name = ent->base + pfxlen + 1;\n+\tent->base[pfxlen + 3] = '/';\n+\tent->base[pfxlen] = ent->base[entlen-1] = 0;\n+\n+\t/* Detect cases where alternate disappeared */\n+\tif (stat(ent->base, &st) || !S_ISDIR(st.st_mode)) {\n+\t\terror(\"object directory %s does not exist; \"\n+\t\t      \"check .git/objects/info/alternates.\",\n+\t\t      ent->base);\n+\t\tfree(ent);\n+\t\treturn -1;\n+\t}\n+\n+\t/* Prevent the common mistake of listing the same\n+\t * thing twice, or object directory itself.\n+\t */\n+\tfor (alt = alt_odb_list; alt; alt = alt->next) {\n+\t\tif (!memcmp(ent->base, alt->base, pfxlen)) {\n+\t\t\tfree(ent);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\tif (!memcmp(ent->base, objdir, pfxlen)) {\n+\t\tfree(ent);\n+\t\treturn -1;\n+\t}\n+\n+\t/* add the alternate entry */\n+\t*alt_odb_tail = ent;\n+\talt_odb_tail = &(ent->next);\n+\tent->next = NULL;\n+\n+\t/* recursively add alternates */\n+\tread_info_alternates(ent->base);\n+\n+\tent->base[pfxlen] = '/';\n+\n+\treturn 0;\n+}\n+\n static void link_alt_odb_entries(const char *alt, const char *ep, int sep,\n \t\t\t\t const char *relative_base)\n {\n \tconst char *cp, *last;\n-\tstruct alternate_object_database *ent;\n-\tconst char *objdir = get_object_directory();\n-\tint base_len = -1;\n \n \tlast = alt;\n \twhile (last < ep) {\n@@ -248,61 +315,10 @@ static void link_alt_odb_entries(const c\n \t\t\tlast = cp + 1;\n \t\t\tcontinue;\n \t\t}\n-\t\tfor ( ; cp < ep && *cp != sep; cp++)\n-\t\t\t;\n+\t\twhile (cp < ep && *cp != sep)\n+\t\t\tcp++;\n \t\tif (last != cp) {\n-\t\t\tstruct stat st;\n-\t\t\tstruct alternate_object_database *alt;\n-\t\t\t/* 43 = 40-byte + 2 '/' + terminating NUL */\n-\t\t\tint pfxlen = cp - last;\n-\t\t\tint entlen = pfxlen + 43;\n-\n-\t\t\tif (*last != '/' && relative_base) {\n-\t\t\t\t/* Relative alt-odb */\n-\t\t\t\tif (base_len < 0)\n-\t\t\t\t\tbase_len = strlen(relative_base) + 1;\n-\t\t\t\tentlen += base_len;\n-\t\t\t\tpfxlen += base_len;\n-\t\t\t}\n-\t\t\tent = xmalloc(sizeof(*ent) + entlen);\n-\n-\t\t\tif (*last != '/' && relative_base) {\n-\t\t\t\tmemcpy(ent->base, relative_base, base_len - 1);\n-\t\t\t\tent->base[base_len - 1] = '/';\n-\t\t\t\tmemcpy(ent->base + base_len,\n-\t\t\t\t       last, cp - last);\n-\t\t\t}\n-\t\t\telse\n-\t\t\t\tmemcpy(ent->base, last, pfxlen);\n-\n-\t\t\tent->name = ent->base + pfxlen + 1;\n-\t\t\tent->base[pfxlen + 3] = '/';\n-\t\t\tent->base[pfxlen] = ent->base[entlen-1] = 0;\n-\n-\t\t\t/* Detect cases where alternate disappeared */\n-\t\t\tif (stat(ent->base, &st) || !S_ISDIR(st.st_mode)) {\n-\t\t\t\terror(\"object directory %s does not exist; \"\n-\t\t\t\t      \"check .git/objects/info/alternates.\",\n-\t\t\t\t      ent->base);\n-\t\t\t\tgoto bad;\n-\t\t\t}\n-\t\t\tent->base[pfxlen] = '/';\n-\n-\t\t\t/* Prevent the common mistake of listing the same\n-\t\t\t * thing twice, or object directory itself.\n-\t\t\t */\n-\t\t\tfor (alt = alt_odb_list; alt; alt = alt->next)\n-\t\t\t\tif (!memcmp(ent->base, alt->base, pfxlen))\n-\t\t\t\t\tgoto bad;\n-\t\t\tif (!memcmp(ent->base, objdir, pfxlen)) {\n-\t\t\tbad:\n-\t\t\t\tfree(ent);\n-\t\t\t}\n-\t\t\telse {\n-\t\t\t\t*alt_odb_tail = ent;\n-\t\t\t\talt_odb_tail = &(ent->next);\n-\t\t\t\tent->next = NULL;\n-\t\t\t}\n+\t\t\tlink_alt_odb_entry(last, cp - last, relative_base);\n \t\t}\n \t\twhile (cp < ep && *cp == sep)\n \t\t\tcp++;\n@@ -310,23 +326,14 @@ static void link_alt_odb_entries(const c\n \t}\n }\n \n-void prepare_alt_odb(void)\n+static void read_info_alternates(const char * relative_base)\n {\n-\tchar path[PATH_MAX];\n \tchar *map;\n-\tint fd;\n \tstruct stat st;\n-\tchar *alt;\n-\n-\talt = getenv(ALTERNATE_DB_ENVIRONMENT);\n-\tif (!alt) alt = \"\";\n-\n-\tif (alt_odb_tail)\n-\t\treturn;\n-\talt_odb_tail = &alt_odb_list;\n-\tlink_alt_odb_entries(alt, alt + strlen(alt), ':', NULL);\n+\tchar path[PATH_MAX];\n+\tint fd;\n \n-\tsprintf(path, \"%s/info/alternates\", get_object_directory());\n+\tsprintf(path, \"%s/info/alternates\", relative_base);\n \tfd = open(path, O_RDONLY);\n \tif (fd < 0)\n \t\treturn;\n@@ -339,11 +346,26 @@ void prepare_alt_odb(void)\n \tif (map == MAP_FAILED)\n \t\treturn;\n \n-\tlink_alt_odb_entries(map, map + st.st_size, '\\n',\n-\t\t\t     get_object_directory());\n+\tlink_alt_odb_entries(map, map + st.st_size, '\\n', relative_base);\n+\n \tmunmap(map, st.st_size);\n }\n \n+void prepare_alt_odb(void)\n+{\n+\tchar *alt;\n+\n+\talt = getenv(ALTERNATE_DB_ENVIRONMENT);\n+\tif (!alt) alt = \"\";\n+\n+\tif (alt_odb_tail)\n+\t\treturn;\n+\talt_odb_tail = &alt_odb_list;\n+\tlink_alt_odb_entries(alt, alt + strlen(alt), ':', NULL);\n+\n+\tread_info_alternates(get_object_directory());\n+}\n+\n static char *find_sha1_file(const unsigned char *sha1, struct stat *st)\n {\n \tchar *name = sha1_file_name(sha1);\n-- \n1.3.1.g6ef7\n\n-- \nMartin Waitz\n"},{"id":"19402","messageId":"7v8xpjhguu.fsf@assigned-by-dhcp.cox.net","threadId":"4018","inReplyTo":"20060502073847.GK20847@admingilde.org","subject":"Re: [PATCH] Transitively read alternatives","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-05-03T04:28:25Z","receivedAt":"2006-05-03T04:28:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Martin Waitz <tali@admingilde.org> writes:\n\n> When adding an alternate object store then add entries from its\n> info/alternates files, too.\n\nNot quite, I'm afraid...\n\n> +static int link_alt_odb_entry(const char * entry, int len, const char * relative_base)\n> +{\n> +\tstruct stat st;\n> +\tconst char *objdir = get_object_directory();\n> +\tstruct alternate_object_database *ent;\n> +\tstruct alternate_object_database *alt;\n> +\t/* 43 = 40-byte + 2 '/' + terminating NUL */\n> +\tint pfxlen = len;\n> +\tint entlen = pfxlen + 43;\n> +\tint base_len = -1;\n> +\n> +\tif (*entry != '/' && relative_base) {\n> +\t\t/* Relative alt-odb */\n> +\t\tif (base_len < 0)\n> +\t\t\tbase_len = strlen(relative_base) + 1;\n\nWouldn't base_len be always -1 here?\n\n> +\tif (*entry != '/' && relative_base) {\n> +\t\tmemcpy(ent->base, relative_base, base_len - 1);\n> +\t\tent->base[base_len - 1] = '/';\n> +\t\tmemcpy(ent->base + base_len, entry, len);\n> +\t}\n> +\telse\n> +\t\tmemcpy(ent->base, entry, pfxlen);\n\nHandling of full path sounds sensible; with relative_base case,\nthe referred-to object directory is relative to our object/\ndirectory, so \"A/.git/objects/info/alternates\" would typically\nhave \"../../../B/.git/objects/\" if A borrows from B that lives\nin the same subdirectory as A itself.\n\n> +\t/* recursively add alternates */\n> +\tread_info_alternates(ent->base);\n\nBut using that \"../../../B/.git/objects/\", we would read its\nalternates.  If it points at a neighbor we already borrow from,\nsay C (we would refer to it as \"../../../C/.git/objects/\"),\nprefixing with relative_base would yield\n\n\t../../../B/.git/objects/../../../C/.git/objects/\n\nand we would end up getting the same thing twice, which sounds a\nbit unfortunate.  Maybe it is easier not to do the recursive\nthing unless the alternate is absolute path, and also as a\npurely safety measure, limit the maximum recursion depth to\nsomething low like 5, similar to recursive symlink resolution.\n\nHmm?\n"},{"id":"19403","messageId":"20060503075133.GO20847@admingilde.org","threadId":"4018","inReplyTo":"7v8xpjhguu.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Transitively read alternatives","fromName":"Martin Waitz","fromEmail":"tali@admingilde.org","sentAt":"2006-05-03T07:51:33Z","receivedAt":"2006-05-03T07:51:33Z","isPatch":true,"sender":{"key":"tali@admingilde.org","avatar":"https://gravatar.com/avatar/3f89b03eee362187effabe257898735b475673a12265c398ea9161259ae91553?d=mp&s=160"},"body":"hoi :)\n\nOn Tue, May 02, 2006 at 09:28:25PM -0700, Junio C Hamano wrote:\n> > +\tif (*entry != '/' && relative_base) {\n> > +\t\t/* Relative alt-odb */\n> > +\t\tif (base_len < 0)\n> > +\t\t\tbase_len = strlen(relative_base) + 1;\n> \n> Wouldn't base_len be always -1 here?\n\nhmm, I just moved that part around.\n\n> Maybe it is easier not to do the recursive thing unless the alternate\n> is absolute path, and also as a purely safety measure, limit the\n> maximum recursion depth to something low like 5, similar to recursive\n> symlink resolution.\n\nAgreed.\nLets see if I have some free time in the evening ;-)\n\n-- \nMartin Waitz\n"}]}