{"thread":{"id":"1492","subject":"[PATCH] Alternate object pool mechanism updates.","startedAt":"2005-08-13T09:09:13Z","lastAt":"2005-08-17T05:48:39Z","messageCount":12,"participants":["Junio C Hamano","Petr Baudis","Linus Torvalds","Daniel Barkalow"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"7180","messageId":"7vmznmp5ja.fsf@assigned-by-dhcp.cox.net","threadId":"1492","inReplyTo":null,"subject":"[PATCH] Alternate object pool mechanism updates.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-13T09:09:13Z","receivedAt":"2005-08-13T09:09:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"It was a mistake to use GIT_ALTERNATE_OBJECT_DIRECTORIES\nenvironment variable to specify what alternate object pools to\nlook for missing objects when working with an object database.\nIt is not a property of the process running the git commands,\nbut a property of the object database that is partial and needs\nother object pools to complete the set of objects it lacks.\n\nThis patch allows you to have $GIT_OBJECT_DIRECTORY/info/alt\nfile whose contents is in exactly the same format as the\nenvironment variable, to let an object database name alternate\nobject pools it depends on.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\n cache.h      |    5 +-\n fsck-cache.c |    8 ++-\n sha1_file.c  |  146 ++++++++++++++++++++++++++++++++--------------------------\n 3 files changed, 88 insertions(+), 71 deletions(-)\n\n8150a422f79cc461316052b52263289b851d4820\ndiff --git a/cache.h b/cache.h\n--- a/cache.h\n+++ b/cache.h\n@@ -278,9 +278,10 @@ struct checkout {\n extern int checkout_entry(struct cache_entry *ce, struct checkout *state);\n \n extern struct alternate_object_database {\n-\tchar *base;\n+\tstruct alternate_object_database *next;\n \tchar *name;\n-} *alt_odb;\n+\tchar base[0]; /* more */\n+} *alt_odb_list;\n extern void prepare_alt_odb(void);\n \n extern struct packed_git {\ndiff --git a/fsck-cache.c b/fsck-cache.c\n--- a/fsck-cache.c\n+++ b/fsck-cache.c\n@@ -456,13 +456,13 @@ int main(int argc, char **argv)\n \tfsck_head_link();\n \tfsck_object_dir(get_object_directory());\n \tif (check_full) {\n-\t\tint j;\n+\t\tstruct alternate_object_database *alt;\n \t\tstruct packed_git *p;\n \t\tprepare_alt_odb();\n-\t\tfor (j = 0; alt_odb[j].base; j++) {\n+\t\tfor (alt = alt_odb_list; alt; alt = alt->next) {\n \t\t\tchar namebuf[PATH_MAX];\n-\t\t\tint namelen = alt_odb[j].name - alt_odb[j].base;\n-\t\t\tmemcpy(namebuf, alt_odb[j].base, namelen);\n+\t\t\tint namelen = alt->name - alt->base;\n+\t\t\tmemcpy(namebuf, alt->base, namelen);\n \t\t\tnamebuf[namelen - 1] = 0;\n \t\t\tfsck_object_dir(namebuf);\n \t\t}\ndiff --git a/sha1_file.c b/sha1_file.c\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -222,84 +222,100 @@ char *sha1_pack_index_name(const unsigne\n \treturn base;\n }\n \n-struct alternate_object_database *alt_odb;\n+struct alternate_object_database *alt_odb_list;\n+static struct alternate_object_database **alt_odb_tail;\n \n /*\n  * Prepare alternate object database registry.\n- * alt_odb points at an array of struct alternate_object_database.\n- * This array is terminated with an element that has both its base\n- * and name set to NULL.  alt_odb[n] comes from n'th non-empty\n- * element from colon separated ALTERNATE_DB_ENVIRONMENT environment\n- * variable, and its base points at a statically allocated buffer\n- * that contains \"/the/directory/corresponding/to/.git/objects/...\",\n- * while its name points just after the slash at the end of\n- * \".git/objects/\" in the example above, and has enough space to hold\n- * 40-byte hex SHA1, an extra slash for the first level indirection,\n- * and the terminating NUL.\n- * This function allocates the alt_odb array and all the strings\n- * pointed by base fields of the array elements with one xmalloc();\n- * the string pool immediately follows the array.\n+ *\n+ * The variable alt_odb_list points at the list of struct\n+ * alternate_object_database.  The elements on this list come from\n+ * non-empty elements from colon separated ALTERNATE_DB_ENVIRONMENT\n+ * environment variable, and $GIT_OBJECT_DIRECTORY/info/alt file,\n+ * whose contents is exactly in the same format as that environment\n+ * variable.  Its base points at a statically allocated buffer that\n+ * contains \"/the/directory/corresponding/to/.git/objects/...\", while\n+ * its name points just after the slash at the end of \".git/objects/\"\n+ * in the example above, and has enough space to hold 40-byte hex\n+ * SHA1, an extra slash for the first level indirection, and the\n+ * terminating NUL.\n  */\n-void prepare_alt_odb(void)\n+static void link_alt_odb_entries(const char *alt, const char *ep)\n {\n-\tint pass, totlen, i;\n \tconst char *cp, *last;\n-\tchar *op = NULL;\n-\tconst char *alt = gitenv(ALTERNATE_DB_ENVIRONMENT) ? : \"\";\n+\tstruct alternate_object_database *ent;\n+\n+\tlast = alt;\n+\tdo {\n+\t\tfor (cp = last; cp < ep && *cp != ':'; cp++)\n+\t\t\t;\n+\t\tif (last != cp) {\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\tent = xmalloc(sizeof(*ent) + entlen);\n+\t\t\t*alt_odb_tail = ent;\n+\t\t\talt_odb_tail = &(ent->next);\n+\t\t\tent->next = NULL;\n+\n+\t\t\tmemcpy(ent->base, last, pfxlen);\n+\t\t\tent->name = ent->base + pfxlen + 1;\n+\t\t\tent->base[pfxlen] = ent->base[pfxlen + 3] = '/';\n+\t\t\tent->base[entlen-1] = 0;\n+\t\t}\n+\t\twhile (cp < ep && *cp == ':')\n+\t\t\tcp++;\n+\t\tlast = cp;\n+\t} while (cp < ep);\n+}\n+\n+void prepare_alt_odb(void)\n+{\n+\tchar path[PATH_MAX];\n+\tchar *map, *ep;\n+\tint fd;\n+\tstruct stat st;\n+\tchar *alt = gitenv(ALTERNATE_DB_ENVIRONMENT) ? : \"\";\n \n-\tif (alt_odb)\n+\tsprintf(path, \"%s/info/alt\", get_object_directory());\n+\tif (alt_odb_tail)\n+\t\treturn;\n+\talt_odb_tail = &alt_odb_list;\n+\tlink_alt_odb_entries(alt, alt + strlen(alt));\n+\n+\tfd = open(path, O_RDONLY);\n+\tif (fd < 0)\n+\t\treturn;\n+\tif (fstat(fd, &st) || (st.st_size == 0)) {\n+\t\tclose(fd);\n \t\treturn;\n-\t/* The first pass counts how large an area to allocate to\n-\t * hold the entire alt_odb structure, including array of\n-\t * structs and path buffers for them.  The second pass fills\n-\t * the structure and prepares the path buffers for use by\n-\t * fill_sha1_path().\n-\t */\n-\tfor (totlen = pass = 0; pass < 2; pass++) {\n-\t\tlast = alt;\n-\t\ti = 0;\n-\t\tdo {\n-\t\t\tcp = strchr(last, ':') ? : last + strlen(last);\n-\t\t\tif (last != cp) {\n-\t\t\t\t/* 43 = 40-byte + 2 '/' + terminating NUL */\n-\t\t\t\tint pfxlen = cp - last;\n-\t\t\t\tint entlen = pfxlen + 43;\n-\t\t\t\tif (pass == 0)\n-\t\t\t\t\ttotlen += entlen;\n-\t\t\t\telse {\n-\t\t\t\t\talt_odb[i].base = op;\n-\t\t\t\t\talt_odb[i].name = op + pfxlen + 1;\n-\t\t\t\t\tmemcpy(op, last, pfxlen);\n-\t\t\t\t\top[pfxlen] = op[pfxlen + 3] = '/';\n-\t\t\t\t\top[entlen-1] = 0;\n-\t\t\t\t\top += entlen;\n-\t\t\t\t}\n-\t\t\t\ti++;\n-\t\t\t}\n-\t\t\twhile (*cp && *cp == ':')\n-\t\t\t\tcp++;\n-\t\t\tlast = cp;\n-\t\t} while (*cp);\n-\t\tif (pass)\n-\t\t\tbreak;\n-\t\talt_odb = xmalloc(sizeof(*alt_odb) * (i + 1) + totlen);\n-\t\talt_odb[i].base = alt_odb[i].name = NULL;\n-\t\top = (char*)(&alt_odb[i+1]);\n \t}\n+\tmap = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);\n+\tclose(fd);\n+\tif (map == MAP_FAILED)\n+\t\treturn;\n+\n+\t/* Remove the trailing newline */\n+\tfor (ep = map + st.st_size - 1; map < ep && ep[-1] == '\\n'; ep--)\n+\t\t;\n+\tlink_alt_odb_entries(map, ep);\n+\tmunmap(map, st.st_size);\n }\n \n static char *find_sha1_file(const unsigned char *sha1, struct stat *st)\n {\n-\tint i;\n \tchar *name = sha1_file_name(sha1);\n+\tstruct alternate_object_database *alt;\n \n \tif (!stat(name, st))\n \t\treturn name;\n \tprepare_alt_odb();\n-\tfor (i = 0; (name = alt_odb[i].name) != NULL; i++) {\n+\tfor (alt = alt_odb_list; alt; alt = alt->next) {\n+\t\tname = alt->name;\n \t\tfill_sha1_path(name, sha1);\n-\t\tif (!stat(alt_odb[i].base, st))\n-\t\t\treturn alt_odb[i].base;\n+\t\tif (!stat(alt->base, st))\n+\t\t\treturn alt->base;\n \t}\n \treturn NULL;\n }\n@@ -522,18 +538,18 @@ static void prepare_packed_git_one(char \n \n void prepare_packed_git(void)\n {\n-\tint i;\n \tstatic int run_once = 0;\n+\tstruct alternate_object_database *alt;\n \n-\tif (run_once++)\n+\tif (run_once)\n \t\treturn;\n-\n \tprepare_packed_git_one(get_object_directory());\n \tprepare_alt_odb();\n-\tfor (i = 0; alt_odb[i].base != NULL; i++) {\n-\t\talt_odb[i].name[0] = 0;\n-\t\tprepare_packed_git_one(alt_odb[i].base);\n+\tfor (alt = alt_odb_list; alt; alt = alt->next) {\n+\t\talt->name[0] = 0;\n+\t\tprepare_packed_git_one(alt->base);\n \t}\n+\trun_once = 1;\n }\n \n int check_sha1_signature(const unsigned char *sha1, void *map, unsigned long size, const char *type)\n"},{"id":"7187","messageId":"20050813120815.GC5608@pasky.ji.cz","threadId":"1492","inReplyTo":"7vmznmp5ja.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Alternate object pool mechanism updates.","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2005-08-13T12:08:16Z","receivedAt":"2005-08-13T12:08:16Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Sat, Aug 13, 2005 at 11:09:13AM CEST, I got a letter\nwhere Junio C Hamano <junkio@cox.net> told me that...\n> It was a mistake to use GIT_ALTERNATE_OBJECT_DIRECTORIES\n> environment variable to specify what alternate object pools to\n> look for missing objects when working with an object database.\n> It is not a property of the process running the git commands,\n> but a property of the object database that is partial and needs\n> other object pools to complete the set of objects it lacks.\n> \n> This patch allows you to have $GIT_OBJECT_DIRECTORY/info/alt\n> file whose contents is in exactly the same format as the\n> environment variable, to let an object database name alternate\n> object pools it depends on.\n> \n> Signed-off-by: Junio C Hamano <junkio@cox.net>\n\nWhat about calling it rather info/alternates (or info/alternate)? It\nlooks better, sounds better, is more namespace-ecological tab-completes\nfine and you don't type it that often anyway. :-)\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nIf you want the holes in your knowledge showing up try teaching\nsomeone.  -- Alan Cox\n"},{"id":"7208","messageId":"7v8xz5offn.fsf@assigned-by-dhcp.cox.net","threadId":"1492","inReplyTo":"20050813120815.GC5608@pasky.ji.cz","subject":"Re: [PATCH] Alternate object pool mechanism updates.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-13T18:33:00Z","receivedAt":"2005-08-13T18:33:00Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Petr Baudis <pasky@suse.cz> writes:\n\n> What about calling it rather info/alternates (or info/alternate)? It\n> looks better, sounds better, is more namespace-ecological tab-completes\n> fine and you don't type it that often anyway. :-)\n\nThanks for the suggestion.  Will fix and keep it in the pu\nbranch for now just in case somebody else suggests a name even\nbetter.\n"},{"id":"7249","messageId":"7v1x4wcca0.fsf@assigned-by-dhcp.cox.net","threadId":"1492","inReplyTo":"20050813120815.GC5608@pasky.ji.cz","subject":"Re: [PATCH] Alternate object pool mechanism updates.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-14T23:46:31Z","receivedAt":"2005-08-14T23:46:31Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Petr Baudis <pasky@suse.cz> writes:\n\n> What about calling it rather info/alternates (or info/alternate)? It\n> looks better, sounds better, is more namespace-ecological tab-completes\n> fine and you don't type it that often anyway. :-)\n\nOk, so the one in the proposed updates branch says\ninfo/alternates.\n\nWith this, your recent cg-clone -l can be made to still use\nindividual .git/object/??/ hierarchy to keep objects newly\ncreated in each repository while sharing the inherited objects\nfrom the parent repository, which would probably alleviate the\nmulti-user environment worries you express in the comments for\nthe option.  The git-clone-script in the proposed updates branch\nhas such a change.\n"},{"id":"7251","messageId":"Pine.LNX.4.58.0508141726390.3553@g5.osdl.org","threadId":"1492","inReplyTo":"7v1x4wcca0.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Alternate object pool mechanism updates.","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-08-15T00:29:05Z","receivedAt":"2005-08-15T00:29:05Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 14 Aug 2005, Junio C Hamano wrote:\n> \n> Ok, so the one in the proposed updates branch says\n> info/alternates.\n> \n> With this, your recent cg-clone -l can be made to still use\n> individual .git/object/??/ hierarchy to keep objects newly\n> created in each repository while sharing the inherited objects\n> from the parent repository, which would probably alleviate the\n> multi-user environment worries you express in the comments for\n> the option.  The git-clone-script in the proposed updates branch\n> has such a change.\n\nI think this is great - especially for places like kernel.org, where a lot \nof repos end up being related to each other, yet independent.\n\nHowever, exactly for places like kernel.org it would _also_ be nice if\nthere was some way to prune objects that have been merged back into the\nparent. In other words, imagine that people start using my kernel tree as\ntheir source of \"alternate\" objects, which works wonderfully well, but\nthen as I pull from them, nothing ever removes the objects that are now\nduplicate.\n\nWe've got a \"git prune-packed\", it would be good to have a \"git\nprune-alternate\" or something equivalent.\n\n\t\t\tLinus\n"},{"id":"7255","messageId":"7vr7cw7ypt.fsf@assigned-by-dhcp.cox.net","threadId":"1492","inReplyTo":"Pine.LNX.4.58.0508141726390.3553@g5.osdl.org","subject":"Re: [PATCH] Alternate object pool mechanism updates.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-15T01:53:02Z","receivedAt":"2005-08-15T01:53:02Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> I think this is great - especially for places like kernel.org, where a lot \n> of repos end up being related to each other, yet independent.\n\nYes.  There is one shortcoming in the current git-clone -s in\nthe proposed updates branch.  If the parent repository has\nalternates on its own, that information should be copied to the\ncloned one as well (e.g. Jeff has alternates pointing at you,\nand I clone from Jeff with -s flag --- I should list not just\nJeff but also you to borrow from in my alternates file).\n\n> However, exactly for places like kernel.org it would _also_ be nice if\n> there was some way to prune objects that have been merged back into the\n> parent.\n\nYes.  Another possibility is to use git-relink which was written\nexactly to solve this in a different way.\n"},{"id":"7373","messageId":"Pine.LNX.4.58.0508161156430.3553@g5.osdl.org","threadId":"1492","inReplyTo":"7vr7cw7ypt.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Alternate object pool mechanism updates.","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-08-16T19:07:42Z","receivedAt":"2005-08-16T19:07:42Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 14 Aug 2005, Junio C Hamano wrote:\n\n> Linus Torvalds <torvalds@osdl.org> writes:\n> \n> > I think this is great - especially for places like kernel.org, where a lot \n> > of repos end up being related to each other, yet independent.\n> \n> Yes.  There is one shortcoming in the current git-clone -s in\n> the proposed updates branch.  If the parent repository has\n> alternates on its own, that information should be copied to the\n> cloned one as well (e.g. Jeff has alternates pointing at you,\n> and I clone from Jeff with -s flag --- I should list not just\n> Jeff but also you to borrow from in my alternates file).\n\nBtw, looking at the code, it strikes me that using \":\" to separate the \nalternate object directories in the file is rather strange.\n\nMaybe allow a different format for the file? Or at least allow '\\n' as an \nalternate separator (but it would be nice to allow comments too).\n\nFinally, I have to say that that \"info\" directory is confusing. Namely,\nthere's two of them - the \"git info\" and the \"object info\" directories are\ntotally different directories - maybe logical, but to me it smells like\n\"info\" is here a code-name for \"misc files that don't make sense anywhere\nelse\".\n\nAnyway, I don't think \"alternates\" is necessarily sensible as a \"object\"  \ninformation. Sure, it's about alternate objects, but the thing is, object \ndirectories can be shared across many projects, but \"alternates\" to me \nmakes more sense as a per-project thing.\n\nWhat this all is leading up to is that I think we'd be better off with a \ntotally new \"git config\" file, in \".git/config\", and we'd have all the \nstartup configuration there. Including things like alternate object \ndirectories, perhaps standard preferences for that particular repo, and \nthings like the \"grafts\" thing.\n\nWouldn't that be nice?\n\n\t\tLinus\n"},{"id":"7374","messageId":"Pine.LNX.4.63.0508161519090.23242@iabervon.org","threadId":"1492","inReplyTo":"Pine.LNX.4.58.0508161156430.3553@g5.osdl.org","subject":"Re: [PATCH] Alternate object pool mechanism updates.","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-08-16T19:45:20Z","receivedAt":"2005-08-16T19:45:20Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Tue, 16 Aug 2005, Linus Torvalds wrote:\n\n> Finally, I have to say that that \"info\" directory is confusing. Namely,\n> there's two of them - the \"git info\" and the \"object info\" directories are\n> totally different directories - maybe logical, but to me it smells like\n> \"info\" is here a code-name for \"misc files that don't make sense anywhere\n> else\".\n>\n> What this all is leading up to is that I think we'd be better off with a\n> totally new \"git config\" file, in \".git/config\", and we'd have all the\n> startup configuration there. Including things like alternate object\n> directories, perhaps standard preferences for that particular repo, and\n> things like the \"grafts\" thing.\n>\n> Wouldn't that be nice?\n\nI'd originally proposed the .git/info directory because I keep multiple\nworking trees for the same repository, by having symlinks for .git/objects\nand .git/refs, and I could also get other per-repository things to be\nshared properly without knowing exactly what they are if they're in a\nsubdirectory of .git that could be a symlink. This would mean that a\n\".git/config\" would be per-working-tree, like .git/index or .git/HEAD, not\npre-repository like \".git/info/config\". Of course, the core didn't have\nany thing to go in .git/info at the time, so it didn't really get tacked\ndown.\n\n(I find it convenient to have mainline and my latest work both checked out\nfor reference while I'm generating a series of commits for a patch set,\nand I don't want three different repositories which could be out of sync;\nthis also keeps the repository safely out of pwd, since I have the actual\nrepositories as ~/git/{project}.git/)\n\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"7377","messageId":"7vacjhaa7y.fsf@assigned-by-dhcp.cox.net","threadId":"1492","inReplyTo":"Pine.LNX.4.58.0508161156430.3553@g5.osdl.org","subject":"Re: [PATCH] Alternate object pool mechanism updates.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-16T20:38:25Z","receivedAt":"2005-08-16T20:38:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> Btw, looking at the code, it strikes me that using \":\" to separate the \n> alternate object directories in the file is rather strange.\n\nYes, I admit it one was done in a quick and dirty way.  Patches\nwelcome [*1*] ;-)\n\n> Anyway, I don't think \"alternates\" is necessarily sensible as a \"object\"  \n> information. Sure, it's about alternate objects, but the thing is, object \n> directories can be shared across many projects, but \"alternates\" to me \n> makes more sense as a per-project thing.\n\nWell, I have to think about this a bit more, but I have to say\nthere were some thinking behind the way things are right now.\n\n$GIT_DIR/info describes properties of the repository.  That's\nwhy refs, graft and rev-cache go there.\n\n$GIT_OBJECT_DIRECTORY/info describes the properties of the\nobject pool (I am inventing words as I speak, but an object pool\nis a directory that can be combined with other object pools to\nmake an object database).  So object/info/packs talks about the\npacks in it, but not about packs it borrows from its alternates.\nThe alternates file in question talks about what other object\npools you need to consult to obtain the objects it refers to but\nit lacks itself.  If two repositories share a particular object\npool as its .git/objects directory, by symlinking .git/objects\nor by using GIT_OBJECT_DIRECTORY environment, it does not matter\nfrom which repository you look at this object pool.  The set of\nobjects it refers to but lacks itself, and from which other\npools these objects can be obtained, do not depend on from which\nrepository you are looking at it.  While I agree with everything\nyou said about \"maybe logical but confusing\", I have to disagree\nwith you about this one.\n\n> What this all is leading up to is that I think we'd be better off with a \n> totally new \"git config\" file, in \".git/config\", and we'd have all the \n> startup configuration there.\n\nI think what _is_ lacking is an easy way to have per repository\nconfiguration that can be shared among \"opt-in\" developers.  The\ngraft file naturally falls into this category, and probably the\nPorcelain standard .git/info/exclude file as well.  Although we\nended up doing .git/hooks, it is a per repository thing and\nlogically it _could_ be moved to .git/info/hooks [*2*].  And\nthat might also be a nice thing to share among \"opt-in\"\ndevelopers.\n\n[Footnote]\n\n*1* Sorry I could not resist --- I always wanted to say this.\n\n*2* I do not think we _should_ move it under .git/info, though.\n"},{"id":"7388","messageId":"7vek8t8sgi.fsf@assigned-by-dhcp.cox.net","threadId":"1492","inReplyTo":"Pine.LNX.4.58.0508141726390.3553@g5.osdl.org","subject":"Re: [PATCH] Alternate object pool mechanism updates.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-16T21:47:25Z","receivedAt":"2005-08-16T21:47:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> We've got a \"git prune-packed\", it would be good to have a \"git\n> prune-alternate\" or something equivalent.\n\nIf you have GIT_ALTERNATE_DIRECTORIES environment variable, git\nprune-packed will remove objects from your repository if it is\nfound in somebody else's pack.  I am not sure if this is the\nbehaviour we would want.\n"},{"id":"7390","messageId":"Pine.LNX.4.58.0508161451510.3553@g5.osdl.org","threadId":"1492","inReplyTo":"7vek8t8sgi.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Alternate object pool mechanism updates.","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-08-16T21:52:46Z","receivedAt":"2005-08-16T21:52:46Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 16 Aug 2005, Junio C Hamano wrote:\n> Linus Torvalds <torvalds@osdl.org> writes:\n> \n> > We've got a \"git prune-packed\", it would be good to have a \"git\n> > prune-alternate\" or something equivalent.\n> \n> If you have GIT_ALTERNATE_DIRECTORIES environment variable, git\n> prune-packed will remove objects from your repository if it is\n> found in somebody else's pack.  I am not sure if this is the\n> behaviour we would want.\n\nWell, it may be good enough if the \"master\" repository is regularly \npacked..\n\n\t\tLinus\n"},{"id":"7423","messageId":"7vbr3x2jwo.fsf_-_@assigned-by-dhcp.cox.net","threadId":"1492","inReplyTo":"7vacjhaa7y.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH] Use LF and allow comments in objects/info/alternates file.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-17T05:48:39Z","receivedAt":"2005-08-17T05:48:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Yes, using the same format for the file and the environment variable\nwas a big mistake.  This uses LF as the path separator, and allows\nlines that begin with '#' to be comments.  ':' is no longer a separator\nin objects/info/alternates file.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\n sha1_file.c |   26 +++++++++++++++-----------\n 1 files changed, 15 insertions(+), 11 deletions(-)\n\n9577e7e3db2299febdc17539478bba38874d4120\ndiff --git a/sha1_file.c b/sha1_file.c\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -240,14 +240,21 @@ static struct alternate_object_database \n  * SHA1, an extra slash for the first level indirection, and the\n  * terminating NUL.\n  */\n-static void link_alt_odb_entries(const char *alt, const char *ep)\n+static void link_alt_odb_entries(const char *alt, const char *ep, int sep)\n {\n \tconst char *cp, *last;\n \tstruct alternate_object_database *ent;\n \n \tlast = alt;\n-\tdo {\n-\t\tfor (cp = last; cp < ep && *cp != ':'; cp++)\n+\twhile (last < ep) {\n+\t\tcp = last;\n+\t\tif (cp < ep && *cp == '#') {\n+\t\t\twhile (cp < ep && *cp != sep)\n+\t\t\t\tcp++;\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\tif (last != cp) {\n \t\t\t/* 43 = 40-byte + 2 '/' + terminating NUL */\n@@ -264,16 +271,16 @@ static void link_alt_odb_entries(const c\n \t\t\tent->base[pfxlen] = ent->base[pfxlen + 3] = '/';\n \t\t\tent->base[entlen-1] = 0;\n \t\t}\n-\t\twhile (cp < ep && *cp == ':')\n+\t\twhile (cp < ep && *cp == sep)\n \t\t\tcp++;\n \t\tlast = cp;\n-\t} while (cp < ep);\n+\t}\n }\n \n void prepare_alt_odb(void)\n {\n \tchar path[PATH_MAX];\n-\tchar *map, *ep;\n+\tchar *map;\n \tint fd;\n \tstruct stat st;\n \tchar *alt = gitenv(ALTERNATE_DB_ENVIRONMENT) ? : \"\";\n@@ -282,7 +289,7 @@ void prepare_alt_odb(void)\n \tif (alt_odb_tail)\n \t\treturn;\n \talt_odb_tail = &alt_odb_list;\n-\tlink_alt_odb_entries(alt, alt + strlen(alt));\n+\tlink_alt_odb_entries(alt, alt + strlen(alt), ':');\n \n \tfd = open(path, O_RDONLY);\n \tif (fd < 0)\n@@ -296,10 +303,7 @@ void prepare_alt_odb(void)\n \tif (map == MAP_FAILED)\n \t\treturn;\n \n-\t/* Remove the trailing newline */\n-\tfor (ep = map + st.st_size - 1; map < ep && ep[-1] == '\\n'; ep--)\n-\t\t;\n-\tlink_alt_odb_entries(map, ep);\n+\tlink_alt_odb_entries(map, map + st.st_size, '\\n');\n \tmunmap(map, st.st_size);\n }\n \n"}]}